@cross-deck/web 1.12.1 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- "use strict";var Crossdeck=(()=>{var ge=Object.defineProperty;var bt=Object.getOwnPropertyDescriptor;var vt=Object.getOwnPropertyNames;var wt=Object.prototype.hasOwnProperty;var _t=(r,e)=>{for(var t in e)ge(r,t,{get:e[t],enumerable:!0})},St=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of vt(e))!wt.call(r,n)&&n!==t&&ge(r,n,{get:()=>e[n],enumerable:!(s=bt(e,n))||s.enumerable});return r};var Et=r=>St(ge({},"__esModule",{value:!0}),r);var Mr={};_t(Mr,{CROSSDECK_ERROR_CODES:()=>xe,Crossdeck:()=>pt,CrossdeckClient:()=>G,CrossdeckContracts:()=>gt,CrossdeckError:()=>_,DEFAULT_BASE_URL:()=>Q,MemoryStorage:()=>O,SDK_NAME:()=>A,SDK_VERSION:()=>R,getErrorCode:()=>pe});var _=class r extends Error{constructor(e){super(e.message),this.name="CrossdeckError",this.type=e.type,this.code=e.code,this.requestId=e.requestId,this.status=e.status,this.retryAfterMs=e.retryAfterMs,this.minVersion=e.minVersion,this.surface=e.surface,Object.setPrototypeOf(this,r.prototype)}};async function Fe(r){let e=r.headers.get("x-request-id")??void 0,t=xt(r.headers.get("retry-after")),s;try{s=await r.json()}catch{s=null}let n=s?.error;return n&&typeof n.type=="string"&&typeof n.code=="string"?new _({type:n.type,code:n.code,message:n.message??`HTTP ${r.status}`,requestId:n.request_id??e,status:r.status,retryAfterMs:t,minVersion:typeof n.minVersion=="string"?n.minVersion:void 0,surface:typeof n.surface=="string"?n.surface:void 0}):new _({type:Ct(r.status),code:`http_${r.status}`,message:`HTTP ${r.status} ${r.statusText||""}`.trim(),requestId:e,status:r.status,retryAfterMs:t})}function xt(r){if(!r)return;let e=r.trim();if(!e)return;if(/^\d+(\.\d+)?$/.test(e)){let n=Number(e);return!Number.isFinite(n)||n<0?void 0:Math.round(n*1e3)}if(!/[a-zA-Z,/:]/.test(e))return;let t=Date.parse(e);if(!Number.isFinite(t))return;let s=t-Date.now();return s>0?s:0}function Ct(r){return r===401?"authentication_error":r===403?"permission_error":r===429?"rate_limit_error":r>=400&&r<500?"invalid_request_error":"internal_error"}var R="1.12.1",A="@cross-deck/web";var Q="https://api.cross-deck.com/v1",Tt=15e3,Y=class{constructor(e){this.config=e}async request(e,t,s={}){if(this.config.localDevMode)return It(t);let n=this.buildUrl(t,s.query),i={Authorization:`Bearer ${this.config.publicKey}`,"Crossdeck-Sdk-Version":`${A}@${this.config.sdkVersion}`,Accept:"application/json"};s.idempotencyKey&&(i["Idempotency-Key"]=s.idempotencyKey);let o;s.body!==void 0&&(i["Content-Type"]="application/json",o=JSON.stringify(s.body));let a=s.timeoutMs??this.config.timeoutMs??Tt,c=typeof AbortController<"u"&&a>0?new AbortController:null,l=null;c&&a>0&&(l=setTimeout(()=>c.abort(),a));let d;try{d=await fetch(n,{method:e,headers:i,body:o,keepalive:s.keepalive===!0,signal:c?.signal})}catch(u){let m=c?.signal?.aborted===!0;throw new _({type:"network_error",code:m?"request_timeout":"fetch_failed",message:m?`Request to ${t} aborted after ${a}ms`:u instanceof Error?u.message:"fetch failed"})}finally{l!==null&&clearTimeout(l)}if(!d.ok){let u=await Fe(d);if(this.config.onErrorParsed)try{this.config.onErrorParsed(u)}catch{}throw u}if(d.status!==204)try{return await d.json()}catch{throw new _({type:"internal_error",code:"invalid_json_response",message:"Server returned a 2xx with an unparseable body.",requestId:d.headers.get("x-request-id")??void 0,status:d.status})}}get isLocalDevMode(){return this.config.localDevMode===!0}buildUrl(e,t){let s=this.config.baseUrl.replace(/\/+$/,""),n=e.startsWith("/")?e:`/${e}`,i=s+n;if(t){let o=new URLSearchParams;for(let[c,l]of Object.entries(t))typeof l=="string"&&l.length>0&&o.append(c,l);let a=o.toString();a&&(i+=(i.includes("?")?"&":"?")+a)}return i}},X=null;function It(r){return r.startsWith("/sdk/heartbeat")?{object:"heartbeat",ok:!0,projectId:"proj_local_dev",appId:"app_local_dev",platform:"web",env:"sandbox",serverTime:Date.now()}:r.startsWith("/identity/alias")?(X||(X=`cdcust_local_${typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID().replace(/-/g,"").slice(0,16):Math.random().toString(36).slice(2,18)}`),{object:"alias_result",crossdeckCustomerId:X,linked:[],mergePending:!1,env:"sandbox"}):r.startsWith("/entitlements")?{object:"list",data:[],crossdeckCustomerId:X??"",env:"sandbox"}:r.startsWith("/events")?{object:"list",received:0,env:"sandbox"}:{}}var M="anon_id",B="cdcust_id",Z=class{constructor(e,t,s){this.primary=e;this.prefix=t;this.secondary=s??null;let n=e.getItem(t+M),i=e.getItem(t+B),o=this.secondary?.getItem(t+M)??null,a=this.secondary?.getItem(t+B)??null,c=n??o,l=i??a;this.state={anonymousId:c??this.mintAnonymousId(),crossdeckCustomerId:l},(!n||!o)&&this.writeBoth(t+M,this.state.anonymousId),l&&(!i||!a)&&this.writeBoth(t+B,l)}get anonymousId(){return this.state.anonymousId}get crossdeckCustomerId(){return this.state.crossdeckCustomerId}setCrossdeckCustomerId(e){this.state.crossdeckCustomerId=e,this.writeBoth(this.prefix+B,e)}reset(){this.deleteBoth(this.prefix+M),this.deleteBoth(this.prefix+B),this.state={anonymousId:this.mintAnonymousId(),crossdeckCustomerId:null},this.writeBoth(this.prefix+M,this.state.anonymousId)}mintAnonymousId(){let e=Date.now().toString(36),t=V(10);return`anon_${e}${t}`}writeBoth(e,t){try{this.primary.setItem(e,t)}catch{}if(this.secondary)try{this.secondary.setItem(e,t)}catch{}}deleteBoth(e){try{this.primary.removeItem(e)}catch{}if(this.secondary)try{this.secondary.removeItem(e)}catch{}}};function V(r){let e="0123456789abcdefghijklmnopqrstuvwxyz",t=[],s=globalThis.crypto;if(s?.getRandomValues){let n=new Uint8Array(r);s.getRandomValues(n);for(let i=0;i<r;i++)t.push(e[n[i]%e.length]??"0")}else for(let n=0;n<r;n++)t.push(e[Math.floor(Math.random()*e.length)]??"0");return t.join("")}var Rt=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]);function At(r){if(typeof TextEncoder<"u")return new TextEncoder().encode(r);let e=[];for(let t=0;t<r.length;t++){let s=r.charCodeAt(t);if(s>=55296&&s<=56319&&t+1<r.length){let n=r.charCodeAt(t+1);n>=56320&&n<=57343&&(s=65536+(s-55296<<10)+(n-56320),t++)}s<128?e.push(s):s<2048?(e.push(192|s>>6),e.push(128|s&63)):s<65536?(e.push(224|s>>12),e.push(128|s>>6&63),e.push(128|s&63)):(e.push(240|s>>18),e.push(128|s>>12&63),e.push(128|s>>6&63),e.push(128|s&63))}return new Uint8Array(e)}function $(r){let e=At(r),t=e.length*8,s=Math.floor((e.length+9+63)/64),n=new Uint8Array(s*64);n.set(e),n[e.length]=128;let i=Math.floor(t/4294967296),o=t>>>0,a=n.length-8;n[a+0]=i>>>24&255,n[a+1]=i>>>16&255,n[a+2]=i>>>8&255,n[a+3]=i&255,n[a+4]=o>>>24&255,n[a+5]=o>>>16&255,n[a+6]=o>>>8&255,n[a+7]=o&255;let c=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),l=new Uint32Array(64);for(let u=0;u<s;u++){let m=u*64;for(let f=0;f<16;f++)l[f]=(n[m+f*4]<<24|n[m+f*4+1]<<16|n[m+f*4+2]<<8|n[m+f*4+3])>>>0;for(let f=16;f<64;f++){let w=l[f-15],E=l[f-2],I=(w>>>7|w<<25)^(w>>>18|w<<14)^w>>>3,D=(E>>>17|E<<15)^(E>>>19|E<<13)^E>>>10;l[f]=l[f-16]+I+l[f-7]+D>>>0}let p=c[0],y=c[1],b=c[2],g=c[3],v=c[4],S=c[5],T=c[6],C=c[7];for(let f=0;f<64;f++){let w=(v>>>6|v<<26)^(v>>>11|v<<21)^(v>>>25|v<<7),E=v&S^~v&T,I=C+w+E+Rt[f]+l[f]>>>0,D=(p>>>2|p<<30)^(p>>>13|p<<19)^(p>>>22|p<<10),yt=p&y^p&b^y&b,kt=D+yt>>>0;C=T,T=S,S=v,v=g+I>>>0,g=b,b=y,y=p,p=I+kt>>>0}c[0]=c[0]+p>>>0,c[1]=c[1]+y>>>0,c[2]=c[2]+b>>>0,c[3]=c[3]+g>>>0,c[4]=c[4]+v>>>0,c[5]=c[5]+S>>>0,c[6]=c[6]+T>>>0,c[7]=c[7]+C>>>0}let d="";for(let u=0;u<8;u++)d+=c[u].toString(16).padStart(8,"0");return d}var Pt=1440*60*1e3,ee="_anon",Dt="_index",P=class r{constructor(e,t="crossdeck:entitlements",s=Pt){this.all=[];this.lastUpdated=0;this.lastRefreshFailedAt=0;this.listeners=new Set;this.listenerErrorCount=0;this.currentSuffix=ee;this.storage=e,this.storageKeyPrefix=t,this.staleAfterMs=s,this.hydrate()}get storageKey(){return`${this.storageKeyPrefix}:${this.currentSuffix}`}get indexKey(){return`${this.storageKeyPrefix}:${Dt}`}static suffixForUserId(e){return e==null||e===""?ee:$(e)}setUserKey(e){let t=r.suffixForUserId(e);if(t===this.currentSuffix){this.all=[],this.lastUpdated=0,this.lastRefreshFailedAt=0,this.notify(),this.hydrate();return}this.currentSuffix=t,this.all=[],this.lastUpdated=0,this.lastRefreshFailedAt=0,this.hydrate(),this.notify()}isEntitled(e){let t=Date.now()/1e3;return this.all.some(s=>s.key===e&&s.isActive&&(s.validUntil==null||s.validUntil>t))}list(){return this.all.slice()}get freshness(){return this.lastUpdated}get isStale(){return this.lastRefreshFailedAt>this.lastUpdated?!0:this.lastUpdated>0&&Date.now()-this.lastUpdated>this.staleAfterMs}get refreshFailedAt(){return this.lastRefreshFailedAt}get listenerErrors(){return this.listenerErrorCount}markRefreshFailed(){this.lastRefreshFailedAt=Date.now()}setFromList(e){this.all=e.slice(),this.lastUpdated=Date.now(),this.lastRefreshFailedAt=0,this.persist(),this.recordSuffixInIndex(this.currentSuffix),this.notify()}clear(){if(this.all=[],this.lastUpdated=0,this.lastRefreshFailedAt=0,this.storage)try{this.storage.removeItem(this.storageKey)}catch{}this.removeSuffixFromIndex(this.currentSuffix),this.notify()}clearAll(){if(this.all=[],this.lastUpdated=0,this.lastRefreshFailedAt=0,this.currentSuffix=ee,this.storage){let e=this.readIndex();for(let t of e)try{this.storage.removeItem(`${this.storageKeyPrefix}:${t}`)}catch{}try{this.storage.removeItem(`${this.storageKeyPrefix}:${ee}`)}catch{}try{this.storage.removeItem(this.indexKey)}catch{}}this.notify()}subscribe(e){this.listeners.add(e);let t=!1;return()=>{t||(t=!0,this.listeners.delete(e))}}hydrate(){if(this.storage)try{let e=this.storage.getItem(this.storageKey);if(!e)return;let t=JSON.parse(e);t&&t.v===1&&Array.isArray(t.entitlements)&&(this.all=t.entitlements,this.lastUpdated=typeof t.lastUpdated=="number"?t.lastUpdated:0)}catch{}}persist(){if(this.storage)try{let e={v:1,entitlements:this.all,lastUpdated:this.lastUpdated};this.storage.setItem(this.storageKey,JSON.stringify(e))}catch{}}readIndex(){if(!this.storage)return[];try{let e=this.storage.getItem(this.indexKey);if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t.filter(s=>typeof s=="string"):[]}catch{return[]}}recordSuffixInIndex(e){if(!this.storage)return;let t=this.readIndex();if(!t.includes(e)){t.push(e);try{this.storage.setItem(this.indexKey,JSON.stringify(t))}catch{}}}removeSuffixFromIndex(e){if(!this.storage)return;let t=this.readIndex(),s=t.filter(n=>n!==e);if(s.length!==t.length)try{s.length===0?this.storage.removeItem(this.indexKey):this.storage.setItem(this.indexKey,JSON.stringify(s))}catch{}}notify(){if(this.listeners.size===0)return;let e=this.all.slice(),t=[...this.listeners];for(let s of t)try{s(e)}catch{this.listenerErrorCount+=1}}};function Vt(r){return[r.slice(0,8),r.slice(8,12),r.slice(12,16),r.slice(16,20),r.slice(20,32)].join("-")}function L(r){let e;if(r.rail==="apple"?e=r.signedTransactionInfo??"":r.rail==="google"?e=r.purchaseToken??"":e="",!e)throw new Error(`deriveIdempotencyKeyForPurchase: no stable identifier in body (rail=${r.rail}). Apple needs signedTransactionInfo; Google needs purchaseToken.`);let t=`crossdeck:purchases/sync:${r.rail}:${e}`;return Vt($(t))}function Ot(r,e,t={},s=Math.random){let n=t.baseMs??1e3,i=t.maxMs??6e4,o=t.factor??2,a=Math.min(r,30),l=Math.min(i,n*Math.pow(o,a))*s();if(e!==void 0){let u=Math.min(864e5,e);if(u>l)return u}return Math.max(0,Math.round(l))}var te=class{constructor(e={}){this.options=e;this.attempts=0}get consecutiveFailures(){return this.attempts}get isWarning(){return this.attempts>=(this.options.failuresBeforeWarn??8)}nextDelay(e,t=Math.random){let s=Ot(this.attempts,e,this.options,t);return this.attempts+=1,s}recordSuccess(){this.attempts=0}};var N=1e3,re=class{constructor(e){this.cfg=e;this.buffer=[];this.pendingBatch=null;this.pendingBatchId=null;this.dropped=0;this.inFlight=0;this.lastFlushAt=0;this.lastError=null;this.cancelTimer=null;this.firstFlushFired=!1;this.nextRetryAt=null;this.parked=!1;this.parkWarned=!1;if(this.retry=new te(e.retry??{}),this.persistent=e.persistentStore??null,this.persistent){let t=this.persistent.load();t.length>0&&(t.length>N?(this.dropped+=t.length-N,this.buffer=t.slice(t.length-N)):this.buffer=t,this.cfg.onBufferChange?.(this.buffer.length),this.scheduleIdleFlush())}}enqueue(e){if(this.buffer.push(e),this.buffer.length>N){let t=this.buffer.length-N;this.buffer.splice(0,t),this.dropped+=t,this.cfg.onDrop?.(t)}this.cfg.onBufferChange?.(this.buffer.length),this.persistAll(),this.buffer.length>=this.cfg.batchSize?this.flush():this.scheduleIdleFlush()}async flush(e={}){if(this.parked)return null;let t,s;if(this.pendingBatch!==null&&this.pendingBatchId!==null)t=this.pendingBatch,s=this.pendingBatchId;else{if(this.buffer.length===0)return null;t=this.buffer.splice(0),s=this.mintBatchId(),this.pendingBatch=t,this.pendingBatchId=s,this.inFlight+=t.length,this.cfg.onBufferChange?.(this.buffer.length),this.persistAll()}this.cancelTimerIfSet(),this.nextRetryAt=null;try{let n=this.cfg.envelope(),i=await this.cfg.http.request("POST","/events",{body:{envelopeVersion:1,appId:n.appId,environment:n.environment,sdk:n.sdk,events:t},keepalive:e.keepalive===!0,idempotencyKey:s});return this.lastFlushAt=Date.now(),this.lastError=null,this.inFlight-=t.length,this.pendingBatch=null,this.pendingBatchId=null,this.retry.recordSuccess(),this.persistAll(),this.firstFlushFired||(this.firstFlushFired=!0,this.cfg.onFirstFlushSuccess?.()),i}catch(n){let i=n instanceof Error?n.message:String(n);if(this.lastError=i,Nt(n)){if(this.parked=!0,this.buffer=[...t,...this.buffer],this.buffer.length>N){let l=this.buffer.length-N;this.buffer.splice(0,l),this.dropped+=l}this.pendingBatch=null,this.pendingBatchId=null,this.inFlight-=t.length,this.persistAll(),this.cfg.onBufferChange?.(this.buffer.length);let c=Ut(n);return this.parkWarned||(this.parkWarned=!0,console.warn(`[Crossdeck] SDK outdated \u2014 the server is no longer accepting this version's event format. Your events are PARKED on-device (held, not lost) and will deliver automatically once you update @cross-deck/web${c?` to >= ${c}`:""} and redeploy.`)),this.cfg.onParked?.({minVersion:c,surface:$t(n)}),null}if(Lt(n)){let c=t.length;return this.pendingBatch=null,this.pendingBatchId=null,this.inFlight-=c,this.dropped+=c,this.persistAll(),this.cfg.onDrop?.(c),this.cfg.onPermanentFailure?.({status:n.status??0,droppedCount:c,lastError:i}),null}let o=Ft(n),a=this.retry.nextDelay(o);return this.scheduleRetry(a),this.cfg.onRetryScheduled?.({delayMs:a,consecutiveFailures:this.retry.consecutiveFailures,retryAfterMs:o,lastError:i}),null}}reset(){this.cancelTimerIfSet(),this.nextRetryAt=null,this.buffer=[],this.pendingBatch=null,this.pendingBatchId=null,this.dropped=0,this.inFlight=0,this.lastError=null,this.retry.recordSuccess(),this.persistent?.clear(),this.cfg.onBufferChange?.(0)}getStats(){return{buffered:this.buffer.length,dropped:this.dropped,inFlight:this.inFlight,lastFlushAt:this.lastFlushAt,lastError:this.lastError,consecutiveFailures:this.retry.consecutiveFailures,nextRetryAt:this.nextRetryAt}}get pendingIdempotencyKey(){return this.pendingBatchId}persistAll(){if(this.persistent){if(this.pendingBatch===null){this.persistent.save(this.buffer);return}this.persistent.save([...this.pendingBatch,...this.buffer])}}scheduleIdleFlush(){this.cancelTimerIfSet();let e=this.cfg.scheduler??Le;this.cancelTimer=e(()=>{this.flush()},this.cfg.intervalMs)}scheduleRetry(e){this.cancelTimerIfSet(),this.nextRetryAt=Date.now()+e;let t=this.cfg.scheduler??Le;this.cancelTimer=t(()=>{this.flush()},e)}cancelTimerIfSet(){this.cancelTimer&&(this.cancelTimer(),this.cancelTimer=null)}mintBatchId(){return`batch_${Date.now().toString(36)}${V(10)}`}};function Ft(r){if(r&&typeof r=="object"&&"retryAfterMs"in r){let e=r.retryAfterMs;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}}function Lt(r){if(!r||typeof r!="object")return!1;let e=r.status;return!(typeof e!="number"||!Number.isFinite(e)||e<400||e>=500||e===408||e===429||e===426)}function Nt(r){return!r||typeof r!="object"?!1:r.status===426?!0:r.code==="sdk_version_unsupported"}function Ut(r){let e=r?.minVersion;return typeof e=="string"&&e.length>0?e:void 0}function $t(r){let e=r?.surface;return typeof e=="string"&&e.length>0?e:void 0}function Le(r,e){let t=setTimeout(r,e);if(typeof t.unref=="function")try{t.unref()}catch{}return()=>clearTimeout(t)}var se=class{constructor(e){this.options=e;this.writeScheduled=!1;this.pendingSnapshot=null;this.key=`${e.prefix}queue.v1`}load(){let e;try{e=this.options.storage.getItem(this.key)}catch{return[]}if(!e)return[];try{let t=JSON.parse(e);return!t||t.version!==1||!Array.isArray(t.events)?[]:t.events}catch{return[]}}save(e){this.pendingSnapshot=e.slice(),!this.writeScheduled&&(this.writeScheduled=!0,queueMicrotask(()=>this.flushWrite()))}saveSync(e){this.pendingSnapshot=e.slice(),this.flushWrite()}clear(){this.pendingSnapshot=null,this.writeScheduled=!1;try{this.options.storage.removeItem(this.key)}catch{}}flushWrite(){this.writeScheduled=!1;let e=this.pendingSnapshot;if(this.pendingSnapshot=null,e===null)return;if(e.length===0){try{this.options.storage.removeItem(this.key)}catch{}return}let t={version:1,events:e};try{this.options.storage.setItem(this.key,JSON.stringify(t))}catch{}}};var O=class{constructor(){this.store=new Map}getItem(e){return this.store.get(e)??null}setItem(e,t){this.store.set(e,t)}removeItem(e){this.store.delete(e)}},ie=class{constructor(e){this.maxAgeSec=e?.maxAgeSec??63072e3,this.secure=e?.secure??qt(),this.sameSite=e?.sameSite??"Lax",this.domain=e?.domain||void 0}getItem(e){if(!ne())return null;let t=globalThis.document,s=t.cookie?t.cookie.split(/;\s*/):[],n=encodeURIComponent(e)+"=";for(let i of s)if(i.startsWith(n))try{return decodeURIComponent(i.slice(n.length))}catch{return null}return null}setItem(e,t){if(!ne())return;let s=globalThis.document,n=[`${encodeURIComponent(e)}=${encodeURIComponent(t)}`,"Path=/",`Max-Age=${this.maxAgeSec}`,`SameSite=${this.sameSite}`];this.domain&&n.push(`Domain=${this.domain}`),this.secure&&n.push("Secure");try{s.cookie=n.join("; ")}catch{}}removeItem(e){if(!ne())return;let t=globalThis.document,s=[`${encodeURIComponent(e)}=`,"Path=/","Max-Age=0",`SameSite=${this.sameSite}`];this.domain&&s.push(`Domain=${this.domain}`),this.secure&&s.push("Secure");try{t.cookie=s.join("; ")}catch{}}};function Ne(r){if(r===void 0||r==="none"||r==="")return;if(r!=="auto"){let i=r.trim().toLowerCase();return i.startsWith(".")?i:`.${i}`}if(!ne())return;let e=globalThis.document,s=(globalThis.location?.hostname??"").toLowerCase();if(!s||s==="localhost"||/^\d{1,3}(\.\d{1,3}){3}$/.test(s)||s.indexOf(".")===-1)return;let n=s.split(".");for(let i=n.length-2;i>=0;i--){let o="."+n.slice(i).join("."),a="__cd_domain_probe";try{e.cookie=`${a}=1; Domain=${o}; Path=/; SameSite=Lax`;let c=e.cookie.indexOf(`${a}=1`)!==-1;if(e.cookie=`${a}=; Domain=${o}; Path=/; Max-Age=0; SameSite=Lax`,c)return o}catch{return}}}function Ue(){try{let r=globalThis.localStorage;if(r){let e="__crossdeck_probe__";return r.setItem(e,"1"),r.removeItem(e),r}}catch{}return new O}function qt(){try{return globalThis.location?.protocol==="https:"}catch{return!1}}function ne(){return typeof globalThis.document<"u"}var Kt="__crossdeckBucketsBridge__";function ye(r){try{let e=globalThis[Kt];typeof e=="function"&&e(r)}catch{}}function Mt(){return typeof globalThis.window<"u"&&typeof globalThis.document<"u"&&typeof globalThis.navigator<"u"}function $e(r){let e={};if(r?.appVersion&&(e.appVersion=r.appVersion),!Mt())return e;let t=globalThis.window,s=globalThis.navigator,n=globalThis.document;try{typeof s.language=="string"&&(e.locale=s.language)}catch{}try{e.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{}try{t.screen&&(e.screenWidth=t.screen.width,e.screenHeight=t.screen.height),e.viewportWidth=t.innerWidth,e.viewportHeight=t.innerHeight,e.devicePixelRatio=t.devicePixelRatio}catch{}try{let i=s.userAgent??"",o=Bt(i);Object.assign(e,o)}catch{}try{let i=s.userAgentData;if(i?.platform&&!e.os&&(e.os=i.platform),i?.brands&&!e.browser){let o=i.brands.find(a=>!/Not[ .;A]*Brand/i.test(a.brand)&&!/Chromium/i.test(a.brand));o&&(e.browser=o.brand,e.browserVersion=o.version)}}catch{}return e}function Bt(r){let e={};if(/iPad|iPhone|iPod/.test(r)){e.os="iOS";let t=r.match(/OS (\d+[._]\d+(?:[._]\d+)?)/);t?.[1]&&(e.osVersion=t[1].replace(/_/g,"."))}else if(/Android/.test(r)){e.os="Android";let t=r.match(/Android (\d+(?:\.\d+)*)/);t?.[1]&&(e.osVersion=t[1])}else if(/Windows/.test(r)){e.os="Windows";let t=r.match(/Windows NT (\d+\.\d+)/);t?.[1]&&(e.osVersion=t[1])}else if(/Mac OS X|Macintosh/.test(r)){e.os="macOS";let t=r.match(/Mac OS X (\d+[._]\d+(?:[._]\d+)?)/);t?.[1]&&(e.osVersion=t[1].replace(/_/g,"."))}else/Linux/.test(r)&&(e.os="Linux");return/Edg\/(\d+(?:\.\d+)*)/.test(r)?(e.browser="Edge",e.browserVersion=r.match(/Edg\/(\d+(?:\.\d+)*)/)?.[1]):/Firefox\/(\d+(?:\.\d+)*)/.test(r)?(e.browser="Firefox",e.browserVersion=r.match(/Firefox\/(\d+(?:\.\d+)*)/)?.[1]):/OPR\/(\d+(?:\.\d+)*)/.test(r)?(e.browser="Opera",e.browserVersion=r.match(/OPR\/(\d+(?:\.\d+)*)/)?.[1]):/Chrome\/(\d+(?:\.\d+)*)/.test(r)?(e.browser="Chrome",e.browserVersion=r.match(/Chrome\/(\d+(?:\.\d+)*)/)?.[1]):/Version\/(\d+(?:\.\d+)*).*Safari/.test(r)&&(e.browser="Safari",e.browserVersion=r.match(/Version\/(\d+(?:\.\d+)*)/)?.[1]),e}var F={sessions:!0,pageViews:!0,deviceInfo:!0,clicks:!0,webVitals:!0,errors:!0},ke=1800*1e3,jt="crossdeck:session",Wt=5e3,j={utm_source:"",utm_medium:"",utm_campaign:"",utm_content:"",utm_term:"",referrer:"",gclid:"",fbclid:"",msclkid:"",ttclid:"",li_fat_id:"",twclid:""},W=class{constructor(e,t,s){this.cfg=e;this.track=t;this.session=null;this.cleanups=[];this.lastPersistAt=0;this._sessionSeq=0;this.pageviewId=null;this.storage=s?.storage??null,this.sessionKey=s?.storageKey??jt,this.cookieStorage=s?.cookieStorage??null}install(){Ke()&&(this.cfg.sessions&&this.installSessionTracking(),this.cfg.pageViews&&this.installPageViewTracking(),this.cfg.clicks&&this.installClickTracking())}uninstall(){for(;this.cleanups.length;){let e=this.cleanups.pop();try{e?.()}catch{}}this.session&&!this.session.endedSent&&this.emitSessionEnd(),this.clearStoredSession(),this.session=null}resetSession(){this.session&&!this.session.endedSent&&this.emitSessionEnd(),this.pageviewId=null,this.session=this.startNewSession(),this.persistSession(),this.emitSessionStart()}markActivity(){if(!this.session)return;let e=Date.now();if(e-this.session.lastActivityAt>=ke){this.pageviewId=null,this.session=this.startNewSession(),this.persistSession(),this.emitSessionStart();return}this.session.lastActivityAt=e,e-this.lastPersistAt>=Wt&&this.persistSession()}get currentSessionId(){return this.session?.sessionId??null}get currentPageviewId(){return this.pageviewId}get currentAcquisition(){return this.session?.acquisition??j}nextSeq(){let e=this._sessionSeq;return this._sessionSeq+=1,e}installSessionTracking(){let e=Date.now(),t=this.readStoredSession();t&&e-t.lastActivityAt<ke?(this.session={sessionId:t.id,startedAt:t.startedAt,lastActivityAt:e,hiddenAt:null,endedSent:!1,acquisition:t.acquisition},this.persistSession()):(this.session=this.startNewSession(),this.persistSession(),this.emitSessionStart());let s=()=>{try{if(!this.session)return;let a=globalThis.document;a.visibilityState==="hidden"?(this.session.hiddenAt=Date.now(),this.persistSession()):a.visibilityState==="visible"&&(Date.now()-this.session.lastActivityAt>=ke?(this.pageviewId=null,this.session=this.startNewSession(),this.persistSession(),this.emitSessionStart()):this.session.hiddenAt=null)}catch{}},n=()=>{try{this.persistSession()}catch{}},i=globalThis.window,o=globalThis.document;o.addEventListener("visibilitychange",s),i.addEventListener("pagehide",n),i.addEventListener("beforeunload",n),this.cleanups.push(()=>{o.removeEventListener("visibilitychange",s),i.removeEventListener("pagehide",n),i.removeEventListener("beforeunload",n)})}startNewSession(){let e=Date.now();return this._sessionSeq=0,{sessionId:or(),startedAt:e,lastActivityAt:e,hiddenAt:null,endedSent:!1,acquisition:this.resolveAcquisition()}}resolveAcquisition(){let e=ar();if(!this.storage&&!this.cookieStorage)return e;let t=`${this.sessionKey}_origin_first`,s=()=>{try{let o=this.storage?.getItem(t);if(o)return o}catch{}try{return this.cookieStorage?.getItem(t)??null}catch{return null}},n=o=>{try{this.storage?.setItem(t,o)}catch{}try{this.cookieStorage?.setItem(t,o)}catch{}},i=o=>!!(o.utm_source||o.utm_medium||o.utm_campaign||o.utm_content||o.utm_term||o.gclid||o.fbclid||o.msclkid||o.ttclid||o.li_fat_id||o.twclid);try{if(i(e))return s()===null&&n(JSON.stringify(e)),e;let o=s();if(o){let a=JSON.parse(o);return{...j,...a,referrer:e.referrer}}}catch{}return e}readStoredSession(){if(!this.storage)return null;try{let e=this.storage.getItem(this.sessionKey);if(!e)return null;let t=JSON.parse(e);return!t||typeof t.id!="string"||typeof t.startedAt!="number"||typeof t.lastActivityAt!="number"?null:{id:t.id,startedAt:t.startedAt,lastActivityAt:t.lastActivityAt,acquisition:t.acquisition&&typeof t.acquisition=="object"?t.acquisition:j}}catch{return null}}persistSession(){if(!(!this.storage||!this.session)){this.lastPersistAt=Date.now();try{let e={id:this.session.sessionId,startedAt:this.session.startedAt,lastActivityAt:this.session.lastActivityAt,acquisition:this.session.acquisition};this.storage.setItem(this.sessionKey,JSON.stringify(e))}catch{}}}clearStoredSession(){if(this.storage)try{this.storage.removeItem(this.sessionKey)}catch{}}emitSessionStart(){this.session&&this.track("session.started",{sessionId:this.session.sessionId})}emitSessionEnd(){if(!this.session||this.session.endedSent)return;let e=Date.now()-this.session.startedAt;this.track("session.ended",{sessionId:this.session.sessionId,durationMs:e}),this.session.endedSent=!0}installPageViewTracking(){let e=globalThis.window,t=globalThis.document,s=0,n="",i=250,o=(m=!1)=>{let p=e.location,y=p.href,b=Date.now();!m&&y===n&&b-s<i||(s=b,n=y,this.pageviewId=`pv_${Date.now().toString(36)}${V(10)}`,this.track("page.viewed",{pageviewId:this.pageviewId,path:p.pathname,url:y,search:p.search||void 0,hash:p.hash||void 0,title:t.title,referrer:t.referrer||void 0}))};o();let a=e.history.pushState,c=e.history.replaceState;function l(m,p,y){a.apply(this,[m,p,y]),queueMicrotask(o)}function d(m,p,y){c.apply(this,[m,p,y]),queueMicrotask(o)}e.history.pushState=l,e.history.replaceState=d;let u=()=>o(!0);e.addEventListener("popstate",u),this.cleanups.push(()=>{e.history.pushState===l&&(e.history.pushState=a),e.history.replaceState===d&&(e.history.replaceState=c),e.removeEventListener("popstate",u)})}installClickTracking(){let e=globalThis.window,t=globalThis.document,s=0,n=null,i=100,o=64,a=c=>{let l=c.target;if(!l||!(l instanceof Element))return;let d=Date.now();if(l===n&&d-s<i)return;s=d,n=l;let m=Ht(l)||l;if(zt(m)||Jt(m)||Gt(m))return;let p=m.tagName.toLowerCase(),y=sr(rr(m),o),b=m.href||void 0,g=m.target||void 0,v=m.id||void 0,S=m.getAttribute("role")||void 0,T=m.getAttribute("aria-label")||void 0,C=nr(m),f=ir(m),w=p==="a"&&!!b,E=m.getAttribute("data-cd-event"),I={selector:C,tag:p,text:y,elementId:v,role:S,ariaLabel:T,href:b,isLink:w,linkTarget:g,viewportX:c.clientX,viewportY:c.clientY,pageX:c.pageX,pageY:c.pageY,...f};for(let D of Object.keys(I))(I[D]===void 0||I[D]===null||I[D]==="")&&delete I[D];this.track(E||"element.clicked",I)};t.addEventListener("click",a,{capture:!0,passive:!0}),this.cleanups.push(()=>{t.removeEventListener("click",a,{capture:!0})})}};function Ht(r){return r.closest("[data-cd-event]")||r.closest("[data-cd-noTrack]")||r.closest("button, a, [role='button'], [role='link'], input[type='button'], input[type='submit']")||null}function zt(r){if(!(r instanceof HTMLElement))return!1;let e=r.tagName.toLowerCase();if(e==="textarea"||e==="select")return!0;if(e==="input"){let t=(r.type||"").toLowerCase();return t!=="button"&&t!=="submit"&&t!=="image"&&t!=="reset"}return!1}function Jt(r){return!!r.closest("[data-cd-noTrack], [data-cd-no-track], .cd-noTrack, .cd-no-track")}function Gt(r){return!!r.closest('input[type="password"]')}var Xt=new Set(["span","b","strong","em","i","small","mark","u","label","abbr","time","bdi","cite","code","kbd","q","sub","sup"]),Yt=new Set(["svg","style","script","noscript"]),Qt="a[href], button, input, select, textarea, [role='button'], [role='link'], h1, h2, h3, h4, h5, h6",Zt="h1, h2, h3, h4, h5, h6";function qe(r){return r.replace(/\s+/g," ").trim()}function be(r){let e="",t=s=>{let n=s.childNodes;for(let i=0;i<n.length;i++){let o=n[i];if(o){if(o.nodeType===3)e+=o.textContent||"";else if(o.nodeType===1){if(Yt.has(o.tagName.toLowerCase()))continue;e+=" ",t(o),e+=" "}}}};return t(r),qe(e)}function er(r){let e="",t=r.childNodes;for(let s=0;s<t.length;s++){let n=t[s];n&&(n.nodeType===3?e+=" "+(n.textContent||""):n.nodeType===1&&Xt.has(n.tagName.toLowerCase())&&(e+=" "+be(n)))}return qe(e)}function tr(r){if(!(r.querySelector(Qt)!==null))return be(r);let t=er(r);if(t)return t;let s=r.querySelector(Zt);if(s){let n=be(s);if(n)return n}return""}function rr(r){let e=l=>l.replace(/\s+/g," ").trim(),t=r.getAttribute("data-cd-track")||r.getAttribute("data-track")||r.getAttribute("data-testid");if(t){let l=e(t);if(l)return l}let s=r.getAttribute("aria-label");if(s){let l=e(s);if(l)return l}let n=r.getAttribute("aria-labelledby");if(n&&typeof r.ownerDocument?.getElementById=="function"){let l=[];for(let d of n.split(/\s+/)){let u=r.ownerDocument.getElementById(d),m=u?.textContent?e(u.textContent):"";m&&l.push(m)}if(l.length>0)return l.join(" ")}if(r instanceof HTMLInputElement&&r.value){let l=e(r.value);if(l)return l}let i=tr(r);if(i)return i;let o=r.getAttribute("title");if(o){let l=e(o);if(l)return l}let a=r.querySelector("img[alt]");if(a){let l=a.getAttribute("alt")??"",d=e(l);if(d)return d}let c=r.querySelector("svg title");if(c?.textContent){let l=e(c.textContent);if(l)return l}return""}function sr(r,e){return r.length<=e?r:r.slice(0,e-1)+"\u2026"}function nr(r){let e=[],t=r,s=0;for(;t&&t.nodeName.toLowerCase()!=="body"&&s<5;){let n=t.nodeName.toLowerCase();if(t.id){e.unshift(`${n}#${t.id}`);break}if(t.classList.length>0){let i=Array.from(t.classList).filter(o=>!o.startsWith("cd-")).slice(0,2).join(".");i&&(n+=`.${i}`)}e.unshift(n),t=t.parentElement,s++}return e.join(" > ")}function ir(r){let e={};if(!(r instanceof HTMLElement))return e;for(let t of r.getAttributeNames()){if(!t.startsWith("data-")||t==="data-cd-noTrack"||t==="data-cd-no-track"||t==="data-cd-event")continue;let s=r.getAttribute(t)||"",n=t.replace(/^data-cd-prop-/,"").replace(/^data-/,"");e[n]=s}return e}function Ke(){return typeof globalThis.window<"u"&&typeof globalThis.document<"u"}function or(){return`sess_${Date.now().toString(36)}${V(10)}`}function ar(){if(!Ke())return{...j};let r={...j};try{let e=globalThis.window,t=new URLSearchParams(e.location.search??"");r.utm_source=t.get("utm_source")??"",r.utm_medium=t.get("utm_medium")??"",r.utm_campaign=t.get("utm_campaign")??"",r.utm_content=t.get("utm_content")??"",r.utm_term=t.get("utm_term")??"",r.gclid=t.get("gclid")??"",r.fbclid=t.get("fbclid")??"",r.msclkid=t.get("msclkid")??"",r.ttclid=t.get("ttclid")??"",r.li_fat_id=t.get("li_fat_id")??"",r.twclid=t.get("twclid")??""}catch{}try{let e=globalThis.document;typeof e.referrer=="string"&&(r.referrer=e.referrer)}catch{}return r}var cr=[/^email$/i,/^password$/i,/^token$/i,/^secret$/i,/^card$/i,/^phone$/i,/password/i,/credit_?card/i];function Me(r){if(!r)return[];let e=[];for(let t of Object.keys(r))cr.some(s=>s.test(t))&&e.push(t);return e}var oe=class{constructor(){this.enabled=!1;this.seen=new Set}emit(e,t,s){if(!this.enabled)return;if(dr.has(e)){if(this.seen.has(e))return;this.seen.add(e)}let n=s?` ${lr(s)}`:"";console.info(`[crossdeck:${e}] ${t}${n}`)}},dr=new Set(["sdk.configured","sdk.first_event_sent","sdk.environment_mismatch"]);function lr(r){try{return JSON.stringify(r)}catch{return"[unserialisable context]"}}function H(r,e={}){let t=[];if(!r)return{properties:{},warnings:t};let s=e.maxStringLength??1024,n=e.maxBatchPropertyBytes??8192,i=e.maxDepth??5,o=new Set,a=(d,u,m)=>{if(m>i)return t.push({kind:"depth_exceeded",key:u}),{keep:!0,value:"[depth-exceeded]"};if(d===null)return{keep:!0,value:null};let p=typeof d;if(p==="string"){let y=d;return y.length>s?(t.push({kind:"truncated_string",key:u}),{keep:!0,value:y.slice(0,s-1)+"\u2026"}):{keep:!0,value:y}}if(p==="number")return Number.isFinite(d)?{keep:!0,value:d}:(t.push({kind:"non_serialisable",key:u}),{keep:!0,value:null});if(p==="boolean")return{keep:!0,value:d};if(p==="bigint")return t.push({kind:"coerced_bigint",key:u}),{keep:!0,value:d.toString()};if(p==="function")return t.push({kind:"dropped_function",key:u}),{keep:!1,value:void 0};if(p==="symbol")return t.push({kind:"dropped_symbol",key:u}),{keep:!1,value:void 0};if(p==="undefined")return t.push({kind:"dropped_undefined",key:u}),{keep:!1,value:void 0};if(d instanceof Date)return t.push({kind:"coerced_date",key:u}),{keep:!0,value:Number.isFinite(d.getTime())?d.toISOString():null};if(d instanceof Error)return t.push({kind:"coerced_error",key:u}),{keep:!0,value:{name:d.name,message:d.message,stack:typeof d.stack=="string"?d.stack.slice(0,s):void 0}};if(d instanceof Map){t.push({kind:"coerced_map",key:u});let y={};for(let[b,g]of d.entries()){let v=typeof b=="string"?b:String(b),S=a(g,`${u}.${v}`,m+1);S.keep&&(y[v]=S.value)}return{keep:!0,value:y}}if(d instanceof Set){t.push({kind:"coerced_set",key:u});let y=[],b=0;for(let g of d.values()){let v=a(g,`${u}[${b}]`,m+1);v.keep&&y.push(v.value),b++}return{keep:!0,value:y}}if(Array.isArray(d)){if(o.has(d))return t.push({kind:"circular_reference",key:u}),{keep:!0,value:"[circular]"};o.add(d);let y=[];for(let b=0;b<d.length;b++){let g=a(d[b],`${u}[${b}]`,m+1);g.keep&&y.push(g.value)}return o.delete(d),{keep:!0,value:y}}if(p==="object"){let y=d;if(o.has(y))return t.push({kind:"circular_reference",key:u}),{keep:!0,value:"[circular]"};o.add(y);let b={};for(let g of Object.keys(y)){let v=a(y[g],`${u}.${g}`,m+1);v.keep&&(b[g]=v.value)}return o.delete(y),{keep:!0,value:b}}t.push({kind:"non_serialisable",key:u});try{return{keep:!0,value:String(d)}}catch{return{keep:!1,value:void 0}}},c={};for(let d of Object.keys(r)){let u=a(r[d],d,0);u.keep&&(c[d]=u.value)}let l=Be(c);if(l&&ve(l)>n){t.push({kind:"size_cap_exceeded",key:"*"});let d=Object.keys(c).map(m=>({k:m,size:ve(Be(c[m])??"")})).sort((m,p)=>p.size-m.size),u=ve(l);for(let{k:m}of d){if(u<=n)break;u-=d.find(p=>p.k===m).size,delete c[m]}c.__truncated=!0}return{properties:c,warnings:t}}function Be(r){try{return JSON.stringify(r)??null}catch{return null}}function ve(r){return typeof TextEncoder<"u"?new TextEncoder().encode(r).length:r.length*4}var ae="super_props",we="groups",ce=class{constructor(e,t){this.storage=e;this.prefix=t;this.superProps={};this.groups={};this.superProps=je(e,t+ae)??{},this.groups=je(e,t+we)??{}}register(e){for(let[t,s]of Object.entries(e))s===null?delete this.superProps[t]:s!==void 0&&(this.superProps[t]=s);return _e(this.storage,this.prefix+ae,this.superProps),{...this.superProps}}unregister(e){e in this.superProps&&(delete this.superProps[e],_e(this.storage,this.prefix+ae,this.superProps))}getSuperProperties(){return{...this.superProps}}setGroup(e,t,s){t===null?delete this.groups[e]:this.groups[e]=s!==void 0?{id:t,traits:s}:{id:t},_e(this.storage,this.prefix+we,this.groups)}getGroups(){return JSON.parse(JSON.stringify(this.groups))}getGroupIds(){let e={};for(let[t,s]of Object.entries(this.groups))e[t]=s.id;return e}clear(){this.superProps={},this.groups={};try{this.storage.removeItem(this.prefix+ae)}catch{}try{this.storage.removeItem(this.prefix+we)}catch{}}};function je(r,e){let t;try{t=r.getItem(e)}catch{return null}if(!t)return null;try{return JSON.parse(t)}catch{return null}}function _e(r,e,t){try{r.setItem(e,JSON.stringify(t))}catch{}}var We="$crossdeck_internal",Se="crossdeck.internalOptOut";function He(){try{return typeof localStorage<"u"?localStorage:null}catch{return null}}function ze(){try{let r=typeof location<"u"?location.search:"",e=new URLSearchParams(r||"");if(!e.has("crossdeck_internal"))return;let t=He();if(!t)return;let s=e.get("crossdeck_internal");s==="1"||s==="true"?t.setItem(Se,"1"):(s==="0"||s==="false")&&t.removeItem(Se)}catch{}}function Je(){try{return He()?.getItem(Se)==="1"}catch{return!1}}var de=class{constructor(e,t){this.cfg=e;this.report=t;this.observers=[];this.flushed=new Set;this.cls=0;this.clsEntries=[];this.inp=0;this.cleanups=[]}install(){if(!this.cfg.enabled||typeof PerformanceObserver>"u"||typeof globalThis>"u"||!("document"in globalThis))return;let e=globalThis.document;try{let i=new PerformanceObserver(o=>{for(let a of o.getEntries()){let c=a;c.responseStart>0&&!this.flushed.has("ttfb")&&(this.flushed.add("ttfb"),this.report("webvitals.ttfb",{valueMs:Math.round(c.responseStart-c.startTime)}))}});i.observe({type:"navigation",buffered:!0}),this.observers.push(i)}catch{}try{let i=new PerformanceObserver(o=>{for(let a of o.getEntries())a.name==="first-contentful-paint"&&!this.flushed.has("fcp")&&(this.flushed.add("fcp"),this.report("webvitals.fcp",{valueMs:Math.round(a.startTime)}))});i.observe({type:"paint",buffered:!0}),this.observers.push(i)}catch{}let t=0;try{let i=new PerformanceObserver(o=>{let a=o.getEntries(),c=a[a.length-1];c&&(t=c.startTime)});i.observe({type:"largest-contentful-paint",buffered:!0}),this.observers.push(i)}catch{}try{let i=new PerformanceObserver(o=>{for(let a of o.getEntries()){let c=a;typeof c.value=="number"&&!c.hadRecentInput&&(this.cls+=c.value,this.clsEntries.push(a))}});i.observe({type:"layout-shift",buffered:!0}),this.observers.push(i)}catch{}try{let i=new PerformanceObserver(o=>{for(let a of o.getEntries()){let c=a;c.interactionId&&c.duration>this.inp&&(this.inp=c.duration)}});try{i.observe({type:"event",buffered:!0,durationThreshold:16})}catch{i.observe({type:"first-input",buffered:!0})}this.observers.push(i)}catch{}let s=()=>{try{t>0&&!this.flushed.has("lcp")&&(this.flushed.add("lcp"),this.report("webvitals.lcp",{valueMs:Math.round(t)})),this.cls>0&&!this.flushed.has("cls")&&(this.flushed.add("cls"),this.report("webvitals.cls",{value:Math.round(this.cls*1e3)/1e3})),this.inp>0&&!this.flushed.has("inp")&&(this.flushed.add("inp"),this.report("webvitals.inp",{valueMs:Math.round(this.inp)}))}catch{}},n=()=>{e.visibilityState==="hidden"&&s()};e.addEventListener("visibilitychange",n),globalThis.window.addEventListener("pagehide",s),this.cleanups.push(()=>{e.removeEventListener("visibilitychange",n),globalThis.window.removeEventListener("pagehide",s)})}uninstall(){for(let e of this.observers)try{e.disconnect()}catch{}this.observers=[];for(let e of this.cleanups.splice(0))try{e()}catch{}}};var ur={analytics:!0,marketing:!0,errors:!0},le=class{constructor(e){this.state={...ur};this.dntDenied=!1;e?.respectDnt&&this.detectDnt()&&(this.dntDenied=!0,this.state={analytics:!1,marketing:!1,errors:!1})}set(e){if(this.dntDenied)return{...this.state};for(let t of Object.keys(e)){let s=e[t];typeof s=="boolean"&&(this.state[t]=s)}return{...this.state}}get(){return{...this.state}}get analytics(){return this.state.analytics}get marketing(){return this.state.marketing}get errors(){return this.state.errors}get isDntDenied(){return this.dntDenied}detectDnt(){try{let e=globalThis.navigator;return e?[e.doNotTrack,e.msDoNotTrack,globalThis.doNotTrack].some(s=>s==="1"||s==="yes"):!1}catch{return!1}}},fr=/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,pr=/\b\d(?:[ -]?\d){12,18}\b/g,hr="<email>",mr="<card>";function gr(r){return r&&r.replace(fr,hr).replace(pr,mr)}function Ee(r){let e={};for(let t of Object.keys(r))e[t]=Ge(r[t]);return e}function Ge(r){return typeof r=="string"?gr(r):Array.isArray(r)?r.map(Ge):r&&typeof r=="object"&&r.constructor===Object?Ee(r):r}var ue=class{constructor(e=50){this.maxSize=e;this.items=[]}add(e){this.items.push(e),this.items.length>this.maxSize&&this.items.shift()}snapshot(){return this.items.slice()}clear(){this.items=[]}get size(){return this.items.length}};var yr="https://api.cross-deck.com/v1/events",Xe="cd_pub_live_eea2f84dbb834a45b7";function kr(){return!Xe.startsWith("cd_pub_RELIABILITY_PLACEHOLDER")}var br=new Set(["contract_id","sdk_version","sdk_platform","failure_reason","run_context","run_id","test_file","test_name","device_class","verification_phase"]);function vr(r){let e={};for(let[t,s]of Object.entries(r))br.has(t)&&typeof s=="string"&&(e[t]=s);return e}function fe(r){if(!kr())return;let e=vr(r);if(Object.keys(e).length===0)return;let t=JSON.stringify({events:[{name:"crossdeck.contract_failed",timestamp:Date.now(),properties:e}]}),s=globalThis.fetch;if(typeof s=="function")try{s(yr,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Xe}`,"Crossdeck-Sdk-Version":`${A}@${R}`},body:t,keepalive:!0,credentials:"omit",cache:"no-store",referrerPolicy:"no-referrer"}).catch(()=>{})}catch{}}var xe=Object.freeze([{code:"invalid_public_key",type:"configuration_error",description:"The publishable key passed to Crossdeck.init() doesn't start with cd_pub_.",resolution:"Copy the key from your Crossdeck dashboard \u2192 API keys page.",retryable:!1},{code:"missing_app_id",type:"configuration_error",description:"Crossdeck.init() was called without an appId.",resolution:"Add appId to your init options \u2014 find it in the dashboard's Apps page.",retryable:!1},{code:"invalid_environment",type:"configuration_error",description:"Crossdeck.init() requires environment: 'production' | 'sandbox'.",resolution:'Pass the literal string "production" or "sandbox" \u2014 no other values are accepted.',retryable:!1},{code:"environment_mismatch",type:"configuration_error",description:"The publishable key's env prefix doesn't match the declared environment option.",resolution:"Either change `environment` to match the key prefix (cd_pub_test_ \u2194 sandbox, cd_pub_live_ \u2194 production), or swap the key for one minted in the right env.",retryable:!1},{code:"not_initialized",type:"configuration_error",description:"An SDK method was called before Crossdeck.init().",resolution:"Call Crossdeck.init({ appId, publicKey, environment }) once at app startup before any other method.",retryable:!1},{code:"missing_user_id",type:"invalid_request_error",description:"identify() was called with an empty userId.",resolution:"Pass a stable, non-empty user identifier from your auth layer \u2014 never a hardcoded placeholder.",retryable:!1},{code:"missing_event_name",type:"invalid_request_error",description:"track() was called without an event name.",resolution:"Pass a non-empty string as the first argument.",retryable:!1},{code:"missing_group_type",type:"invalid_request_error",description:"group() was called without a group type.",resolution:'Pass a non-empty type (e.g. "org", "team") as the first argument.',retryable:!1},{code:"missing_signed_transaction_info",type:"invalid_request_error",description:"syncPurchases() was called without StoreKit 2 signed transaction info.",resolution:"Pass the JWS string from Transaction.currentEntitlements / Transaction.updates.",retryable:!1},{code:"fetch_failed",type:"network_error",description:"The underlying fetch() call failed (typically a network outage or DNS issue).",resolution:"Check the user's network. The SDK will retry automatically with exponential backoff.",retryable:!0},{code:"request_timeout",type:"network_error",description:"A request was aborted after the configured timeoutMs (default 15s).",resolution:"Check the user's connection. Increase timeoutMs in init options if the user is on a known-slow network.",retryable:!0},{code:"invalid_json_response",type:"internal_error",description:"The server returned a 2xx with an unparseable body.",resolution:"Likely a transient backend bug. Retry; if it persists, contact support with the requestId.",retryable:!0},{code:"missing_api_key",type:"authentication_error",description:"No Authorization header (or Crossdeck-Api-Key header) on the request.",resolution:"Make sure Crossdeck.init({ publicKey }) was called with a cd_pub_\u2026 key before the request fired. Re-check your env-vars in CI / Docker if the key is empty at runtime.",retryable:!1},{code:"invalid_api_key",type:"authentication_error",description:"The API key is malformed, unknown, or doesn't resolve to a project.",resolution:"Copy the key from your Crossdeck dashboard \u2192 API keys. Confirm prefix is cd_pub_test_ / cd_pub_live_ for client SDKs and cd_sk_test_ / cd_sk_live_ for the Node server SDK.",retryable:!1},{code:"key_revoked",type:"authentication_error",description:"The API key was revoked in the Crossdeck dashboard.",resolution:"Mint a fresh key in the dashboard \u2192 API keys \u2192 Create new, swap it in, and redeploy. The revoked key cannot be reactivated.",retryable:!1},{code:"identity_token_invalid",type:"authentication_error",description:"The Firebase / Apple / Google ID token supplied with the request didn't verify against the dashboard's configured signers.",resolution:"Refresh the token client-side (Firebase auth.currentUser.getIdToken(true)) and retry. If the failure persists, confirm the signer is registered under dashboard \u2192 Authentication \u2192 Identity sources.",retryable:!0},{code:"origin_not_allowed",type:"permission_error",description:"The Origin header isn't in the project's Allowed origins list.",resolution:"Add the origin (e.g. https://app.example.com) under dashboard \u2192 Settings \u2192 Allowed origins. Wildcards like https://*.example.com are supported.",retryable:!1},{code:"bundle_id_not_allowed",type:"permission_error",description:"The iOS bundle ID sent via X-Crossdeck-Bundle-Id isn't registered under this app's Apple identity lock.",resolution:"Add the bundle ID under dashboard \u2192 Apps \u2192 <your app> \u2192 iOS bundle IDs.",retryable:!1},{code:"package_name_not_allowed",type:"permission_error",description:"The Android package name sent via X-Crossdeck-Package-Name isn't registered under this app's Android identity lock.",resolution:"Add the package name under dashboard \u2192 Apps \u2192 <your app> \u2192 Android package names.",retryable:!1},{code:"env_mismatch",type:"permission_error",description:"The request env (inferred from key prefix) doesn't match the resolved app's configured env.",resolution:"Use a cd_pub_live_ / cd_sk_live_ key with a production app, cd_pub_test_ / cd_sk_test_ with a sandbox app. The two cannot cross.",retryable:!1},{code:"idempotency_key_in_use",type:"invalid_request_error",description:"An Idempotency-Key was reused for a request with a different body (Stripe-grade contract).",resolution:"Generate a fresh key for a different transaction, or reuse the key only with the EXACT same body. The v1.4.0 SDKs derive keys deterministically from the body so this should never fire on SDK-managed calls.",retryable:!1},{code:"rate_limited",type:"rate_limit_error",description:"Request rate exceeded the project's per-second cap.",resolution:"Honour the Retry-After header \u2014 the SDK does this automatically on managed retries. If you're hitting it from a custom code path, throttle to <100 req/s/key.",retryable:!0},{code:"internal_error",type:"internal_error",description:"Server-side issue. Safe to retry with backoff.",resolution:"The SDK retries automatically. If your code paths through to this error, contact support with the requestId from the response envelope.",retryable:!0},{code:"google_not_supported",type:"invalid_request_error",description:"POST /purchases/sync with rail=google is gated until the Play Developer API reconciliation worker ships.",resolution:"Until v1.5+, Google Play purchases verify via Real-time Developer Notifications. The SDK auto-track path handles this transparently for Android consumers.",retryable:!1},{code:"stripe_not_supported",type:"invalid_request_error",description:"POST /purchases/sync with rail=stripe is unsupported \u2014 Stripe Checkout's redirect flow uses platform webhooks instead.",resolution:"Wire Stripe via the standard Checkout / Customer Portal flow; Crossdeck reconciles via the platform webhook automatically. No SDK call needed.",retryable:!1},{code:"missing_required_param",type:"invalid_request_error",description:"A required field is absent from the request body.",resolution:"Inspect the error.message \u2014 the missing field name is included verbatim. Refer to the SDK's TypeScript types for the canonical request shape.",retryable:!1},{code:"invalid_param_value",type:"invalid_request_error",description:"A field is present but the value failed validation (wrong shape, wrong length, wrong enum value).",resolution:"Read error.message for the specific field + reason. SDK-managed call sites should never emit this \u2014 file a bug if you do.",retryable:!1},{code:"sdk_version_unsupported",type:"version_error",description:"HTTP 426 \u2014 your installed SDK sends an event format the server no longer accepts. The data is good; only the wire dialect is too old. The SDK PARKS automatically: events are held on-device (paused, not lost) and deliver on the next launch after you upgrade.",resolution:"Update @cross-deck/web to at least the version in error.minVersion and redeploy \u2014 the parked queue backfills automatically. See https://cross-deck.com/docs/sdk-event-durability/.",retryable:!1}]);function pe(r){return xe.find(e=>e.code===r)}function tt(r){return{sdkVersion:`${A}@${R}`,runId:`cd_verify_${Pr(8)}`,runContext:r.runContext??"customer-app",logVerifierResults:r.logVerifierResults,disableContractAssertions:r.disableContractAssertions,console,emitTelemetry:fe}}var J=class{constructor(e){this.ctx=e;this.reentrancyDepth=0}report(e,t,s){this.ctx.disableContractAssertions||(e.ok?this.reportPass(e,t,s):this.reportFail(e,t,s))}reportPass(e,t,s){if(!this.ctx.logVerifierResults)return;let n=wr(e,s);t==="boot"?this.ctx.console.info(n):this.ctx.console.debug(n)}reportFail(e,t,s){if(this.ctx.console.warn(_r(e,s)),!(this.reentrancyDepth>0)){this.reentrancyDepth+=1;try{this.ctx.emitTelemetry({contract_id:e.contractId,sdk_version:this.ctx.sdkVersion,sdk_platform:"web",failure_reason:Ar(e.failureReason,128),run_context:this.ctx.runContext,run_id:this.ctx.runId,verification_phase:t})}finally{this.reentrancyDepth-=1}}}};function wr(r,e){return`${e?`[crossdeck.${e}]`:"[crossdeck]"} \u2713 ${r.contractId} \u2014 ${r.evidence} (${r.durationMs}ms)`}function _r(r,e){return`${e?`[crossdeck.${e}]`:"[crossdeck]"} \u2717 ${r.contractId} \u2014 ${r.failureReason} (${r.durationMs}ms)`}var Sr={contractId:"per-user-cache-isolation",bootTest(){let r=h();try{let e=new he,t=new P(e,"_verifier");if(t.setUserKey("user_A"),t.setFromList([{object:"entitlement",key:"pro",isActive:!0,validUntil:null,source:{rail:"stripe",productId:"p_verifier",subscriptionId:"s_verifier"},updatedAt:Date.now()}]),t.setUserKey("user_B"),t.list().length!==0)return k("per-user-cache-isolation","in-memory snapshot still carried user_A's entitlements after rotation",h()-r);let n=P.suffixForUserId("user_A"),i=P.suffixForUserId("user_B");if(n===i)return k("per-user-cache-isolation","suffixes for user_A and user_B collided",h()-r);let o=e.getItem(`_verifier:${n}`),a=e.getItem(`_verifier:${i}`);return o?a?k("per-user-cache-isolation","user_B's storage slot already contained data before any write",h()-r):x("per-user-cache-isolation",`slot rotated A:${z(n)} \u2192 B:${z(i)} (isolated, physically separate)`,h()-r):k("per-user-cache-isolation","user_A's storage slot was wiped on rotation (expected isolation, not erasure)",h()-r)}catch(e){return k("per-user-cache-isolation",`boot test threw: ${e.message?.slice(0,80)??"unknown error"}`,h()-r)}},hooks:{onIdentify(r){let e=h(),t=P.suffixForUserId(r.priorUserId),s=P.suffixForUserId(r.nextUserId);return t!==s?r.cache.list().length!==0?k("per-user-cache-isolation","in-memory snapshot still held entitlements after slot rotation",h()-e):x("per-user-cache-isolation",`slot rotated ${z(t)} \u2192 ${z(s)}`,h()-e):x("per-user-cache-isolation",`same-id re-identify (suffix ${z(s)}); cleared + rehydrated per contract`,h()-e)}}},Ce="eyJ.jws.sig",Ye="a66b1640-efaf-bb4d-1261-6650033bf111",Er={contractId:"idempotency-key-deterministic",bootTest(){let r=h();try{let e=L({rail:"apple",signedTransactionInfo:Ce});if(e!==Ye)return k("idempotency-key-deterministic",`canonical apple JWS derived ${e} (expected ${Ye})`,h()-r);if(L({rail:"apple",signedTransactionInfo:Ce})!==e)return k("idempotency-key-deterministic","same JWS produced different keys on two derivations",h()-r);let s=e,n=L({rail:"google",purchaseToken:Ce});return s===n?k("idempotency-key-deterministic","rail namespacing failed \u2014 apple/google identical key",h()-r):x("idempotency-key-deterministic",`apple JWS \u2192 ${e} (canonical vector + determinism + rail isolation)`,h()-r)}catch(e){return k("idempotency-key-deterministic",`boot test threw: ${e.message?.slice(0,80)??"unknown error"}`,h()-r)}},hooks:{onSyncPurchases(r){let e=h();try{return L(r.rail==="apple"?{rail:"apple",signedTransactionInfo:r.stableIdentifier}:{rail:r.rail,purchaseToken:r.stableIdentifier})!==r.derivedKey?k("idempotency-key-deterministic","derived key drifted from canonical algorithm",h()-e):x("idempotency-key-deterministic",`${r.rail} \u2192 ${r.derivedKey}`,h()-e)}catch(t){return k("idempotency-key-deterministic",`hot-path derivation threw: ${t.message?.slice(0,80)??"unknown error"}`,h()-e)}}}},xr={contractId:"error-envelope-shape",bootTest(){let r=h(),e={error:{type:"invalid_request_error",code:"missing_customer",message:"Customer identifier is required.",request_id:"req_test1234"}},t=new Set(["authentication_error","permission_error","invalid_request_error","rate_limit_error","internal_error"]),s=e.error,n=["type","code","message","request_id"].filter(i=>!(i in s)||typeof s[i]!="string");return n.length>0?k("error-envelope-shape",`envelope missing required fields: ${n.join(", ")}`,h()-r):t.has(s.type)?x("error-envelope-shape","{ type, code, message, request_id } parsed and type \u2208 ApiErrorType",h()-r):k("error-envelope-shape",`error.type "${s.type}" not in canonical ApiErrorType set`,h()-r)},hooks:{onErrorParse(r){let e=h();return new Set(["authentication_error","permission_error","invalid_request_error","rate_limit_error","internal_error"]).has(r.errorType)?!r.errorCode||r.errorCode.length===0?k("error-envelope-shape","wire error.code was empty",h()-e):x("error-envelope-shape",`${r.errorType}/${r.errorCode} on ${r.httpStatus}${r.requestId?` (${r.requestId.slice(0,12)}\u2026)`:""}`,h()-e):k("error-envelope-shape",`wire error.type "${r.errorType}" outside canonical ApiErrorType`,h()-e)}}},Cr={contractId:"flush-interval-parity",bootTest(){let r=h();return 2e3!==2e3?k("flush-interval-parity","canonical default drifted from 2000ms",h()-r):x("flush-interval-parity","eventFlushIntervalMs default = 2000ms (Web/Node/RN/Swift/Android parity)",h()-r)}};function rt(r){return{contractId:"flush-interval-parity",bootTest(){let e=h(),t=2e3;return r<100||r>6e4?k("flush-interval-parity",`configured eventFlushIntervalMs=${r} outside reasonable bounds [100, 60000]`,h()-e):r!==t?x("flush-interval-parity",`eventFlushIntervalMs = ${r}ms (override; canonical default is 2000ms)`,h()-e):x("flush-interval-parity","eventFlushIntervalMs = 2000ms (canonical default)",h()-e)}}}var Tr={contractId:"super-property-merge-precedence",bootTest(){let r=h(),n={...{plan:"device_plan",os:"macos"},...{plan:"super_plan",appVersion:"1.0.0"},...{plan:"caller_plan",eventSpecific:!0}};return n.plan!=="caller_plan"?k("super-property-merge-precedence",`merged.plan = "${n.plan}" (expected "caller_plan"; caller must override super and device)`,h()-r):n.appVersion!=="1.0.0"?k("super-property-merge-precedence","super-property appVersion was clobbered by device or caller",h()-r):n.os!=="macos"?k("super-property-merge-precedence","device property os was dropped from merged result",h()-r):x("super-property-merge-precedence","caller > super > device verified (synthetic merge)",h()-r)},hooks:{onTrack(r){let e=h();for(let[t,s]of Object.entries(r.callerProperties))if(r.mergedProperties[t]!==s)return k("super-property-merge-precedence",`caller key "${t}" did not win in merged output`,h()-e);for(let[t,s]of Object.entries(r.superProperties))if(!(t in r.callerProperties)&&r.mergedProperties[t]!==s)return k("super-property-merge-precedence",`super key "${t}" did not win over device in merged output`,h()-e);return x("super-property-merge-precedence",`caller(${Object.keys(r.callerProperties).length}) > super(${Object.keys(r.superProperties).length}) > device verified`,h()-e)}}},Te=["contract_id","sdk_version","sdk_platform","failure_reason","run_context","run_id"],Qe=["test_file","test_name","device_class","verification_phase"],Ze=["anonymousId","developerUserId","crossdeckCustomerId","email","userId","ip","ipAddress","userAgent","stack","stackTrace","url","referrer","deviceId"],Ir={contractId:"contract-failed-payload-schema-lock",bootTest(){let r=h(),t=Object.keys({contract_id:"synthetic",sdk_version:R,sdk_platform:"web",failure_reason:"synthetic",run_context:"customer-app",run_id:"synthetic-run-id",verification_phase:"boot"}),s=new Set([...Te,...Qe]),n=new Set(Ze);for(let i of Te)if(!t.includes(i))return k("contract-failed-payload-schema-lock",`missing required field: ${i}`,h()-r);for(let i of t)if(n.has(i))return k("contract-failed-payload-schema-lock",`forbidden field on wire: ${i}`,h()-r);for(let i of t)if(!s.has(i))return k("contract-failed-payload-schema-lock",`unrecognised field on wire: ${i} (not in required \u222A optional)`,h()-r);return x("contract-failed-payload-schema-lock",`${t.length} fields \u2286 required(${Te.length}) \u222A optional(${Qe.length}); ${Ze.length} forbidden absent`,h()-r)}},et=Object.freeze(["missing_api_key","invalid_api_key","key_revoked","identity_token_invalid","origin_not_allowed","bundle_id_not_allowed","package_name_not_allowed","env_mismatch","idempotency_key_in_use","rate_limited","internal_error","google_not_supported","stripe_not_supported","missing_required_param","invalid_param_value","sdk_version_unsupported"]),Rr={contractId:"sdk-error-codes-catalogue",bootTest(){let r=h();try{let e=[];for(let t of et){let s=pe(t);(!s||!s.description||s.description.trim().length===0||!s.resolution||s.resolution.trim().length===0)&&e.push(t)}return e.length>0?k("sdk-error-codes-catalogue",`catalogue missing description+resolution for backend code(s): ${e.join(", ")}`,h()-r):x("sdk-error-codes-catalogue",`all ${et.length} backend wire codes carry description + resolution`,h()-r)}catch(e){return k("sdk-error-codes-catalogue",`boot test threw: ${e.message?.slice(0,80)??"unknown error"}`,h()-r)}}},st=Object.freeze([Sr,Er,xr,Cr,Tr,Ir,Rr]);async function Ie(r,e,t){if(t.disableContractAssertions)return{passed:0,failed:0,totalMs:0};let s=h(),n=0,i=0;if(t.logVerifierResults){let a=r.filter(d=>d.bootTest).length,c=r.filter(d=>d.hooks).length,l=r.map(d=>d.contractId).join(", ");t.console.info(`[crossdeck] Contract self-verification \u2014 ${r.length} verifiers (${a} boot-tests, ${c} hot-path hooks): ${l}`)}for(let a of r){if(!a.bootTest)continue;let c;try{c=await a.bootTest()}catch(l){c=k(a.contractId,`bootTest threw: ${l.message?.slice(0,80)??"unknown"}`,0)}e.report(c,"boot"),c.ok?n+=1:i+=1}let o=h()-s;if(t.logVerifierResults){let a=i===0?"passed":"complete";t.console.info(`[crossdeck] Self-verification ${a} \u2014 ${n} passed, ${i} failed (${o}ms)`)}return{passed:n,failed:i,totalMs:o}}function nt(r,e,t,s){if(!t.disableContractAssertions)for(let n of r){let i=n.hooks?.onIdentify;if(!i)continue;let o;try{o=i(s)}catch(a){o=k(n.contractId,`hook threw: ${a.message?.slice(0,80)??"unknown"}`,0)}e.report(o,"hot_path","identify")}}function it(r,e,t,s){if(!t.disableContractAssertions)for(let n of r){let i=n.hooks?.onTrack;if(!i)continue;let o;try{o=i(s)}catch(a){o=k(n.contractId,`hook threw: ${a.message?.slice(0,80)??"unknown"}`,0)}e.report(o,"hot_path","track")}}function ot(r,e,t,s){if(!t.disableContractAssertions)for(let n of r){let i=n.hooks?.onSyncPurchases;if(!i)continue;let o;try{o=i(s)}catch(a){o=k(n.contractId,`hook threw: ${a.message?.slice(0,80)??"unknown"}`,0)}e.report(o,"hot_path","syncPurchases")}}function at(r,e,t,s){if(!t.disableContractAssertions)for(let n of r){let i=n.hooks?.onErrorParse;if(!i)continue;let o;try{o=i(s)}catch(a){o=k(n.contractId,`hook threw: ${a.message?.slice(0,80)??"unknown"}`,0)}e.report(o,"hot_path","errorParse")}}function ct(){try{if(typeof process<"u"&&process.env){let e=process.env.NODE_ENV;if(typeof e=="string")return e!=="production"}}catch{}let r=globalThis.__DEV__;return typeof r=="boolean"?r:!1}function x(r,e,t){return{ok:!0,contractId:r,evidence:e,durationMs:t}}function k(r,e,t){return{ok:!1,contractId:r,failureReason:e,durationMs:t}}function h(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Ar(r,e){return r.length>e?r.slice(0,e-1)+"\u2026":r}function z(r){let e=r.startsWith("_")?r.slice(1):r;return e.length<=12?e:`${e.slice(0,4)}\u2026${e.slice(-4)}`}function Pr(r){let e=new Uint8Array(Math.ceil(r/2));if(typeof globalThis<"u"&&globalThis.crypto?.getRandomValues)globalThis.crypto.getRandomValues(e);else for(let s=0;s<e.length;s+=1)e[s]=Math.floor(Math.random()*256);let t="";for(let s=0;s<e.length;s+=1)t+=e[s].toString(16).padStart(2,"0");return t.slice(0,r)}var he=class{constructor(){this.map=new Map}getItem(e){return this.map.get(e)??null}setItem(e,t){this.map.set(e,t)}removeItem(e){this.map.delete(e)}keys(){return Array.from(this.map.keys())}};he._=$;function Ae(r){if(!r||typeof r!="string")return[];let e=r.split(`
2
- `),t=[];for(let s of e){let n=s.trim();if(!n)continue;let i=Dr(n);i&&t.push(i)}return t}function Dr(r){let e=/^at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)$/.exec(r);return e?Re({function:e[1],filename:e[2],lineno:parseInt(e[3],10),colno:parseInt(e[4],10),raw:r}):(e=/^at\s+(.+?):(\d+):(\d+)$/.exec(r),e?Re({function:"?",filename:e[1],lineno:parseInt(e[2],10),colno:parseInt(e[3],10),raw:r}):(e=/^(.*?)@(.+?):(\d+):(\d+)$/.exec(r),e?Re({function:e[1]||"?",filename:e[2],lineno:parseInt(e[3],10),colno:parseInt(e[4],10),raw:r}):/^\w*Error/.test(r)||!r.includes(":")?null:{function:"?",filename:"",lineno:0,colno:0,in_app:!0,raw:r}))}function Re(r){return{function:r.function||"?",filename:r.filename,lineno:Number.isFinite(r.lineno)?r.lineno:0,colno:Number.isFinite(r.colno)?r.colno:0,in_app:Vr(r.filename),raw:r.raw}}function Vr(r){return r?!(/^(?:chrome|moz|safari|webkit)-extension:\/\//.test(r)||/^iabjs:\/\//.test(r)||/^(?:webview|inappbrowser):\/\//i.test(r)||/\bcdn\.jsdelivr\.net\b/.test(r)||/\bunpkg\.com\b/.test(r)||/\bgoogletagmanager\.com\b/.test(r)||/\bgoogle-analytics\.com\b/.test(r)||/\b@cross-deck\/web\b/.test(r)||/\/crossdeck\.umd\.min\.js$/.test(r)):!0}var Or=/(__firefox__|__gCrWeb|zaloJSV2)/;function lt(r){let e=Or.exec(r??"");return e?e[1]:null}function Pe(r,e){return lt(e)?r.map(t=>t.in_app?{...t,in_app:!1}:t):r}function q(r,e,t){let s=lt(r);if(s)return dt(`injected-global:${s}`);let n=e.filter(o=>o.in_app).slice(0,3),i=[(r||"").slice(0,200),...n.map(o=>`${o.function}@${o.filename}:${o.lineno}`)];if(n.length===0&&t){let o=[t.errorType??"",t.filename??"",t.lineno??"",t.colno??""].join(":");o!==":::"&&i.push(o)}return dt(i.join("|"))}function dt(r){let e=5381;for(let t=0;t<r.length;t++)e=(e<<5)+e+r.charCodeAt(t)|0;return(e>>>0).toString(16).padStart(8,"0")}var ut={enabled:!0,onError:!0,onUnhandledRejection:!0,wrapFetch:!0,wrapXhr:!0,captureConsole:!1,ignoreErrors:["ResizeObserver loop limit exceeded","ResizeObserver loop completed with undelivered notifications","Non-Error promise rejection captured"],allowUrls:[],denyUrls:[/^chrome-extension:\/\//,/^moz-extension:\/\//,/^safari-extension:\/\//,/^webkit-extension:\/\//,/^safari-web-extension:\/\//],sampleRate:1,maxPerFingerprintPerMinute:5,maxPerSession:100},me=class{constructor(e){this.opts=e;this.installed=!1;this.cleanups=[];this._reporting=!1;this.sessionCount=0;this.fingerprintWindow=new Map}install(){if(this.installed||!this.opts.config.enabled||typeof globalThis>"u"||!("window"in globalThis))return;let e=globalThis.window;this.opts.config.onError&&this.installOnErrorListener(e),this.opts.config.onUnhandledRejection&&this.installRejectionListener(e),this.opts.config.wrapFetch&&this.installFetchWrap(e),this.opts.config.wrapXhr&&this.installXhrWrap(e),this.opts.config.captureConsole&&this.installConsoleWrap(),this.installed=!0}uninstall(){for(let e of this.cleanups.splice(0))try{e()}catch{}this.installed=!1}captureError(e,t){if(this.opts.isConsented())try{let s=this.buildFromUnknown(e,"error.handled",t?.level??"error");t?.context&&(s.context={...s.context,...t.context}),t?.tags&&(s.tags={...s.tags,...t.tags}),this.maybeReport(s)}catch{}}captureMessage(e,t="info"){if(this.opts.isConsented())try{let s={timestamp:Date.now(),kind:"error.message",level:t,message:e,errorType:null,frames:[],rawStack:null,filename:null,lineno:null,colno:null,fingerprint:q(e,[]),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:this.opts.getContext(),tags:this.opts.getTags()};this.maybeReport(s)}catch{}}installOnErrorListener(e){let t=s=>{if(!this._reporting&&this.opts.isConsented())try{this._reporting=!0;let n=this.buildFromErrorEvent(s);this.maybeReport(n)}catch{}finally{this._reporting=!1}};e.addEventListener("error",t,!0),this.cleanups.push(()=>e.removeEventListener("error",t,!0))}installRejectionListener(e){let t=s=>{if(!this._reporting&&this.opts.isConsented())try{this._reporting=!0;let n=this.buildFromUnknown(s.reason,"error.unhandledrejection","error");this.maybeReport(n)}catch{}finally{this._reporting=!1}};e.addEventListener("unhandledrejection",t),this.cleanups.push(()=>e.removeEventListener("unhandledrejection",t))}installFetchWrap(e){let t=e.fetch?.bind(e);if(!t)return;let s=async(...n)=>{let i=n[0],o=n[1]??{},a=typeof i=="string"?i:i?.url??"",c=(o.method||"GET").toUpperCase(),l=Date.now();Ve(a,this.opts.selfHostname)||this.opts.breadcrumbs.add({timestamp:l,category:"http",message:`${c} ${a}`,data:{url:a,method:c}});try{let d=await t(...n);return d.status>=500&&this.opts.isConsented()&&(Ve(a,this.opts.selfHostname)||this.captureHttp({url:a,method:c,status:d.status,statusText:d.statusText})),d}catch(d){throw this.opts.isConsented()&&!a.includes("api.cross-deck.com")&&!Nr(a,d,e)&&this.captureHttp({url:a,method:c,status:0,statusText:d instanceof Error?d.message:"network error"}),d}};e.fetch=s,this.cleanups.push(()=>{e.fetch===s&&(e.fetch=t)})}installXhrWrap(e){let s=e.XMLHttpRequest?.prototype;if(!s)return;let n=s.open,i=s.send,o=this;s.open=function(a,c,...l){return this._cdMethod=a,this._cdUrl=c,n.apply(this,[a,c,...l])},s.send=function(a){let c=this,l=()=>{try{if(c.status>=500&&o.opts.isConsented()){let d=c._cdUrl??"";Ve(d,o.opts.selfHostname)||o.captureHttp({url:d,method:(c._cdMethod??"GET").toUpperCase(),status:c.status,statusText:c.statusText})}}catch{}};return c.addEventListener("loadend",l),i.apply(this,[a??null])},this.cleanups.push(()=>{s.open=n,s.send=i})}installConsoleWrap(){let e=globalThis.console;if(!e)return;let t=e.error.bind(e);e.error=(...s)=>{try{this.opts.isConsented()&&this.captureMessage(s.map(n=>Lr(n)).join(" "),"error")}catch{}return t(...s)},this.cleanups.push(()=>{e.error=t})}buildFromErrorEvent(e){let t=e.error,s=e.filename||null,n=typeof e.lineno=="number"&&e.lineno>0?e.lineno:null,i=typeof e.colno=="number"&&e.colno>0?e.colno:null;if(t==null&&!s&&n==null&&(e.message==="Script error."||e.message==="Script error"||!e.message)){let p="Cross-origin script error (browser hid details \u2014 script needs crossorigin attribute + CORS headers)";return{timestamp:Date.now(),kind:"error.unhandled",level:"error",message:p,errorType:"ScriptError",frames:[],rawStack:null,filename:null,lineno:null,colno:null,fingerprint:q(p,[]),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:this.opts.getContext(),tags:{...this.opts.getTags(),cross_origin:"true"}}}let a=Oe(t),c=(a.message||e.message||"Unknown error").slice(0,1024),l=t instanceof Error?t.stack??null:null,d=Pe(Ae(l),c),u=a.errorType??null,m=a.extras?{...this.opts.getContext(),__error_extras:a.extras}:this.opts.getContext();return{timestamp:Date.now(),kind:"error.unhandled",level:"error",message:c,errorType:u,frames:d,rawStack:l,filename:s,lineno:n,colno:i,fingerprint:q(c,d,{filename:s,lineno:n,colno:i,errorType:u}),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:m,tags:this.opts.getTags()}}buildFromUnknown(e,t,s){let n=Oe(e),i=(n.message||"Unknown error").slice(0,1024),o=e instanceof Error?e.stack??null:null,a=Pe(Ae(o),i),c=n.errorType??null,l=n.extras?{...this.opts.getContext(),__error_extras:n.extras}:this.opts.getContext();return{timestamp:Date.now(),kind:t,level:s,message:i,errorType:c,frames:a,rawStack:o,filename:null,lineno:null,colno:null,fingerprint:q(i,a,{errorType:c}),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:l,tags:this.opts.getTags()}}captureHttp(e){try{let t=`HTTP ${e.status} ${e.method} ${e.url}`,s={timestamp:Date.now(),kind:"error.http",level:"error",message:t,errorType:"HTTPError",frames:[],rawStack:null,filename:e.url,lineno:null,colno:null,fingerprint:q(`HTTP ${e.status} ${e.method}`,[],{filename:e.url,errorType:"HTTPError"}),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:this.opts.getContext(),tags:this.opts.getTags(),http:e};this.maybeReport(s)}catch{}}maybeReport(e){if(this.sessionCount>=this.opts.config.maxPerSession||this.shouldIgnore(e)||!this.passesUrlGate(e)||!this.passesSample(e)||!this.passesRateLimit(e))return;let t=e,s=this.opts.beforeSend?.();if(s){try{t=s(e)}catch{t=e}if(!t)return}this.sessionCount+=1;try{this.opts.report(t)}catch{}}shouldIgnore(e){for(let t of this.opts.config.ignoreErrors)if(typeof t=="string"&&e.message.includes(t)||t instanceof RegExp&&t.test(e.message))return!0;return!1}passesUrlGate(e){let s=(e.frames.find(n=>n.filename)??null)?.filename??e.filename??"";if(!s)return!0;for(let n of this.opts.config.denyUrls)if(typeof n=="string"&&s.includes(n)||n instanceof RegExp&&n.test(s))return!1;if(this.opts.config.allowUrls.length>0){for(let n of this.opts.config.allowUrls)if(typeof n=="string"&&s.includes(n)||n instanceof RegExp&&n.test(s))return!0;return!1}return!0}passesSample(e){return this.opts.config.sampleRate>=1?!0:this.opts.config.sampleRate<=0?!1:parseInt(e.fingerprint.slice(0,2),16)/255<this.opts.config.sampleRate}passesRateLimit(e){let s=Date.now(),n=this.opts.config.maxPerFingerprintPerMinute,o=(this.fingerprintWindow.get(e.fingerprint)??[]).filter(a=>s-a<6e4);return o.length>=n?(this.fingerprintWindow.set(e.fingerprint,o),!1):(o.push(s),this.fingerprintWindow.set(e.fingerprint,o),!0)}};function Oe(r){if(r===null)return{message:"(thrown: null)",errorType:null,extras:null};if(r===void 0)return{message:"(thrown: undefined)",errorType:null,extras:null};if(typeof r=="string")return{message:r,errorType:null,extras:null};if(typeof r=="number"||typeof r=="boolean"||typeof r=="bigint")return{message:String(r),errorType:typeof r,extras:null};if(typeof r=="symbol")return{message:r.toString(),errorType:"symbol",extras:null};if(typeof r=="function")return{message:`(thrown function: ${r.name||"anonymous"})`,errorType:"function",extras:null};if(r instanceof Error){let e=r.name||r.constructor?.name||"Error",t=typeof r.message=="string"&&r.message.length>0?r.message:K(r)||e,s={},n=Fr(r);n.length>0&&(s.cause=n);for(let i of["code","status","statusCode","errno","response","data","detail","details"]){let o=r[i];o!==void 0&&typeof o!="function"&&(s[i]=De(o))}for(let i of Object.keys(r)){if(i==="message"||i==="stack"||i==="name"||i==="cause"||i in s)continue;let o=r[i];typeof o!="function"&&(s[i]=De(o))}return{message:t,errorType:e,extras:Object.keys(s).length>0?s:null}}if(typeof Response<"u"&&r instanceof Response)return{message:`HTTP ${r.status} ${r.statusText||""}${r.url?` ${r.url}`:""}`.trim(),errorType:"Response",extras:{status:r.status,statusText:r.statusText,url:r.url,type:r.type}};if(typeof r=="object"){let e=r,t=e.constructor&&typeof e.constructor=="function"&&e.constructor.name||null,s=typeof e.message=="string"&&e.message?e.message:null,n=typeof e.name=="string"&&e.name?e.name:null,i=null;try{let u=JSON.stringify(e);i=u==="{}"?null:u}catch{i=null}let o=K(e),a=s??i??(o&&o!=="[object Object]"?o:null)??(t?`(thrown ${t} with no message)`:"(thrown object with no message)"),c=n??t??null,l={},d=0;for(let u of Object.keys(e)){if(d>=20)break;if(u==="message"||u==="name")continue;let m=e[u];typeof m!="function"&&(l[u]=De(m),d++)}return{message:a,errorType:c,extras:Object.keys(l).length>0?l:null}}return{message:K(r)||"(unstringifiable thrown value)",errorType:null,extras:null}}function Fr(r){let e=[],t=r.cause,s=0;for(;t!=null&&s<5;)t instanceof Error?(e.push({name:t.name||"Error",message:t.message||""}),t=t.cause):(e.push({name:"non-Error",message:K(t)}),t=null),s++;return e}function K(r){try{let e=Object.prototype.toString.call(r);if(e!=="[object Object]")return e;let t=r?.toString;if(typeof t=="function"&&t!==Object.prototype.toString){let s=t.call(r);if(typeof s=="string")return s}return e}catch{return"(throwing toString)"}}function De(r){if(r==null)return r;let e=typeof r;if(e==="string"||e==="number"||e==="boolean")return r;if(e==="bigint")return String(r);try{let t=JSON.stringify(r);return t===void 0?K(r):JSON.parse(t)}catch{return K(r)}}function Lr(r){return Oe(r).message}function ft(r){if(!r||typeof r!="string")return null;try{return new URL(r).hostname.toLowerCase()}catch{return null}}function Ve(r,e){if(!e||!r)return!1;try{return new URL(r).hostname.toLowerCase()===e}catch{return!1}}function Nr(r,e,t){if(e instanceof Error&&e.name==="AbortError")return!0;let s=t.navigator;if(s&&s.onLine===!1)return!0;let n=t.location?.href,i=t.location?.origin;if(!i)return!1;try{return new URL(r,n??i).origin===i}catch{return!1}}var G=class{constructor(){this.state=null;this.verifiers=null;this.verifierReporter=null;this.verifierCtx=null}init(e){if(this.state){try{this.state.uninstallUnloadFlush?.()}catch{}try{this.state.autoTracker?.uninstall()}catch{}try{this.state.webVitals?.uninstall()}catch{}try{this.state.errors?.uninstall()}catch{}try{this.state.events.flush({keepalive:!0})}catch{}}if(!e.publicKey||!e.publicKey.startsWith("cd_pub_"))throw new _({type:"configuration_error",code:"invalid_public_key",message:"Crossdeck.init requires a publishable key starting with cd_pub_."});if(!e.appId)throw new _({type:"configuration_error",code:"missing_app_id",message:"Crossdeck.init requires an appId. Find yours in the Crossdeck dashboard."});if(e.environment!=="production"&&e.environment!=="sandbox")throw new _({type:"configuration_error",code:"invalid_environment",message:'Crossdeck.init requires environment: "production" | "sandbox".'});let t=Ur(e.publicKey);if(t&&t!==e.environment)throw new _({type:"configuration_error",code:"environment_mismatch",message:`Crossdeck.init: environment "${e.environment}" disagrees with key prefix (${t}). Reconcile the publishable key with the environment declaration.`});let s=$r(),n=e.storage??Ue(),i=e.persistIdentity??!0,o=qr(e.autoTrack),a={appId:e.appId,publicKey:e.publicKey,environment:e.environment,baseUrl:e.baseUrl??Q,persistIdentity:i,storagePrefix:e.storagePrefix??"crossdeck:",autoHeartbeat:e.autoHeartbeat??!0,eventFlushBatchSize:e.eventFlushBatchSize??20,eventFlushIntervalMs:e.eventFlushIntervalMs??2e3,sdkVersion:e.sdkVersion??R,autoTrack:o,appVersion:e.appVersion??null},c=new oe;c.enabled=e.debug===!0;let l=new Y({publicKey:a.publicKey,baseUrl:a.baseUrl,sdkVersion:a.sdkVersion,localDevMode:s,onErrorParsed:f=>{this.verifiers&&this.verifierReporter&&this.verifierCtx&&at(this.verifiers,this.verifierReporter,this.verifierCtx,{errorType:f.type,errorCode:f.code,requestId:f.requestId??null,httpStatus:typeof f.status=="number"?f.status:0})}});s&&console.log("[crossdeck] Localhost detected \u2014 running in dev mode (no network calls). Set publicKey: 'cd_pub_test_\u2026' and deploy to a real domain to test against the Crossdeck Sandbox.");let d=i?n:new O,m=i&&!e.storage&&typeof globalThis.document<"u"?new ie({domain:Ne(e.cookieDomain??"auto")}):void 0,p=new Z(d,a.storagePrefix,m),y=new P(d,a.storagePrefix+"entitlements"),b=i?new se({storage:d,prefix:a.storagePrefix}):null;b&&c.emit("sdk.queue_restored","Restored persisted event queue from a prior session.");let g=new re({http:l,batchSize:a.eventFlushBatchSize,intervalMs:a.eventFlushIntervalMs,envelope:()=>({appId:a.appId,environment:a.environment,sdk:{name:A,version:a.sdkVersion}}),persistentStore:b??void 0,onFirstFlushSuccess:()=>{c.emit("sdk.first_event_sent","First telemetry event received. View it in Live Events.",{appId:a.appId,environment:a.environment})},onRetryScheduled:f=>{c.emit("sdk.flush_retry_scheduled",`Event flush failed (${f.lastError}). Retrying in ${f.delayMs}ms (attempt ${f.consecutiveFailures}).`,{...f})},onPermanentFailure:f=>{let w=`[crossdeck] Event batch DROPPED (status ${f.status}): ${f.lastError}. ${f.droppedCount} event(s) lost \u2014 check your publishable key + app config.`;console.error(w),c.emit("sdk.flush_permanent_failure",w,{...f})},onParked:f=>{c.emit("sdk.parked",`[crossdeck] SDK parked \u2014 server no longer accepts this version's event format. Events held on-device (paused, not lost); update @cross-deck/web${f.minVersion?` to >= ${f.minVersion}`:""} to resume.`,{...f})}}),v=o.deviceInfo?$e({appVersion:a.appVersion??void 0}):a.appVersion?{appVersion:a.appVersion}:{},S=new ce(i?d:new O,a.storagePrefix);ze();let T=new le({respectDnt:e.respectDnt===!0});T.isDntDenied&&c.emit("sdk.consent_dnt_applied","Do Not Track detected \u2014 all tracking dimensions denied at init.");let C=new ue(50);if(this.state={http:l,identity:p,entitlements:y,events:g,autoTracker:null,webVitals:null,errors:null,breadcrumbs:C,errorContext:{},errorTags:{},errorBeforeSend:null,superProps:S,consent:T,scrubPii:e.scrubPii!==!1,deviceInfo:v,options:a,debug:c,developerUserId:null,uninstallUnloadFlush:null,lastServerTime:null,lastClientTime:null},c.emit("sdk.configured",`Crossdeck connected to ${a.appId} in ${a.environment} mode.`,{appId:a.appId,environment:a.environment,sdkVersion:a.sdkVersion}),o.sessions||o.pageViews){let f=new W(o,(w,E)=>this.track(w,E),{storage:d,storageKey:a.storagePrefix+"session",cookieStorage:m??void 0});this.state.autoTracker=f,f.install()}if(o.webVitals){let f=new de({enabled:!0},(w,E)=>this.track(w,E));this.state.webVitals=f,f.install()}if(o.errors){let f=new me({config:{...ut,enabled:!0},breadcrumbs:C,report:w=>this.reportError(w),getContext:()=>({...this.state.errorContext}),getTags:()=>({...this.state.errorTags}),beforeSend:()=>this.state.errorBeforeSend,isConsented:()=>this.state.consent.errors,selfHostname:ft(a.baseUrl)});this.state.errors=f,f.install()}if(this.state.uninstallUnloadFlush=Kr(()=>{this.flush({keepalive:!0}).catch(()=>{})}),a.autoHeartbeat&&!s&&this.heartbeat().catch(()=>{}),s||this.captureCampaignArrival().catch(()=>{}),e.disableContractAssertions!==!0){let f=ct();this.verifierCtx=tt({logVerifierResults:e.logVerifierResults??f,disableContractAssertions:!1,runContext:typeof process<"u"&&process.env&&process.env.CI?"ci":"customer-app"}),this.verifierReporter=new J(this.verifierCtx);let w=rt(a.eventFlushIntervalMs);this.verifiers=Object.freeze([...st,w]),s?(e.verifyContractsAtBoot??f)&&this.verifierReporter&&Ie(this.verifiers,this.verifierReporter,this.verifierCtx).catch(()=>{}):this.bootstrapVerifierLayerRemote(e,f).catch(()=>{})}}async bootstrapVerifierLayerRemote(e,t){if(!this.state||!this.verifiers||!this.verifierCtx)return;let s={logVerifierResults:null,verifyContractsAtBoot:null};try{let o=await this.state.http.request("GET","/config");if(o&&o.verifierConfig){let a=o.verifierConfig;s={logVerifierResults:typeof a.logVerifierResults=="boolean"?a.logVerifierResults:null,verifyContractsAtBoot:typeof a.verifyContractsAtBoot=="boolean"?a.verifyContractsAtBoot:null}}}catch{}let n=e.logVerifierResults??s.logVerifierResults??t,i=e.verifyContractsAtBoot??s.verifyContractsAtBoot??t;n!==this.verifierCtx.logVerifierResults&&(this.verifierCtx={...this.verifierCtx,logVerifierResults:n},this.verifierReporter=new J(this.verifierCtx)),i&&this.verifierReporter&&await Ie(this.verifiers,this.verifierReporter,this.verifierCtx)}start(e){typeof console<"u"&&console.warn("[crossdeck] Crossdeck.start() is deprecated \u2014 use Crossdeck.init() instead. The signature is the same."),this.init(e)}async captureCampaignArrival(){let e=this.state;if(!e)return;let t=globalThis.location;if(!t||typeof t.search!="string"||t.search.length===0)return;let s=null;try{s=new URLSearchParams(t.search).get("cd_ref")}catch{return}if(s)try{await e.http.request("POST","/integrations/hubspot/arrival",{body:{anonymousId:e.identity.anonymousId,ref:s}})}catch{}}async identify(e,t){let s=this.requireStarted();if(!e)throw new _({type:"invalid_request_error",code:"missing_user_id",message:"identify(userId) requires a non-empty userId."});if(ye({actor:e}),!s.consent.analytics)return s.debug.emit("sdk.consent_denied","identify() skipped \u2014 consent denied for analytics."),{object:"alias_result",crossdeckCustomerId:s.identity.crossdeckCustomerId??"",linked:[],mergePending:!1,env:s.options.environment};let n=t?.traits!==void 0?H(t.traits):null,i=n&&Object.keys(n.properties).length>0?n.properties:void 0;if(s.debug.enabled&&n&&n.warnings.length>0)for(let l of n.warnings)s.debug.emit("sdk.property_coerced",`identify() traits key ${JSON.stringify(l.key)} was ${l.kind.replace(/_/g," ")} during validation.`,{key:l.key,kind:l.kind});let o={userId:e,anonymousId:s.identity.anonymousId};t?.email&&(o.email=t.email),i&&(o.traits=i);let a=s.developerUserId;s.entitlements.setUserKey(e),this.verifiers&&this.verifierReporter&&this.verifierCtx&&nt(this.verifiers,this.verifierReporter,this.verifierCtx,{priorUserId:a,nextUserId:e,cache:s.entitlements});let c=await s.http.request("POST","/identity/alias",{body:o});return s.identity.setCrossdeckCustomerId(c.crossdeckCustomerId),s.developerUserId=e,c}register(e){let t=this.requireStarted(),s=H(e);return t.superProps.register(s.properties)}unregister(e){this.requireStarted().superProps.unregister(e)}getSuperProperties(){return this.state?this.state.superProps.getSuperProperties():{}}group(e,t,s){let n=this.requireStarted();if(!e)throw new _({type:"invalid_request_error",code:"missing_group_type",message:"group(type, id) requires a non-empty type."});let i=s?H(s).properties:void 0;n.superProps.setGroup(e,t,i)}getGroups(){return this.state?this.state.superProps.getGroups():{}}consent(e){let t=this.requireStarted(),s=t.consent.set(e);return t.debug.emit("sdk.consent_changed","Consent state updated.",{...s}),s}consentStatus(){return this.state?this.state.consent.get():{analytics:!0,marketing:!0,errors:!0}}captureError(e,t){this.state?.errors&&this.state.errors.captureError(e,t)}captureMessage(e,t="info"){this.state?.errors&&this.state.errors.captureMessage(e,t)}setTag(e,t){this.state&&(this.state.errorTags[e]=t)}setTags(e){this.state&&Object.assign(this.state.errorTags,e)}setContext(e,t){this.state&&(this.state.errorContext[e]=t)}addBreadcrumb(e){this.state&&this.state.breadcrumbs.add(e)}setErrorBeforeSend(e){this.state&&(this.state.errorBeforeSend=e)}reportError(e){let t={fingerprint:e.fingerprint,level:e.level,errorType:e.errorType,message:e.message,stack:e.rawStack??void 0,frames:e.frames,filename:e.filename??void 0,lineno:e.lineno??void 0,colno:e.colno??void 0,tags:e.tags,context:e.context,breadcrumbs:e.breadcrumbs,http:e.http};for(let s of Object.keys(t))t[s]===void 0&&delete t[s];this.track(e.kind,t)}async forget(){let e=this.requireStarted(),t=this.identityQueryParams();try{await e.http.request("POST","/identity/forget",{body:{...t}})}catch(s){e.debug.emit("sdk.consent_denied",`forget() server call failed (${s instanceof Error?s.message:String(s)}). Local state wiped anyway.`)}this.reset()}async getEntitlements(){let e=this.requireStarted(),t=this.identityQueryParams(),s;try{s=await e.http.request("GET","/entitlements",{query:t})}catch(n){throw e.entitlements.markRefreshFailed(),n}return s.crossdeckCustomerId&&e.identity.setCrossdeckCustomerId(s.crossdeckCustomerId),e.entitlements.setFromList(s.data),s.data}isEntitled(e){return this.requireStarted().entitlements.isEntitled(e)}listEntitlements(){return this.requireStarted().entitlements.list()}onEntitlementsChange(e){return this.requireStarted().entitlements.subscribe(e)}reportContractFailure(e){let t={contract_id:e.contractId,sdk_version:R,sdk_platform:"web",failure_reason:e.failureReason,run_context:e.runContext,run_id:e.runId};e.testRef&&(t.test_file=e.testRef.file,t.test_name=e.testRef.name),e.deviceClass&&(t.device_class=e.deviceClass),fe(t)}track(e,t){let s=this.requireStarted();if(!e)throw new _({type:"invalid_request_error",code:"missing_event_name",message:"track(name) requires a non-empty name."});let n=e.startsWith("error."),i=e.startsWith("webvitals.");if(!(n||i?s.consent.errors:s.consent.analytics)){s.debug.enabled&&s.debug.emit("sdk.consent_denied",`Dropped event "${e}" \u2014 consent denied for ${i?"errors":"analytics"}.`);return}if(s.debug.enabled&&t){let f=Me(t);f.length>0&&s.debug.emit("sdk.sensitive_property_warning",`Event "${e}" has potentially sensitive property names: ${f.join(", ")}. Crossdeck is privacy-first \u2014 avoid sending PII unless intentional.`,{eventName:e,flagged:f})}s.debug.enabled&&!s.developerUserId&&!s.identity.crossdeckCustomerId&&s.debug.emit("sdk.no_identity","Using anonymous user until identify(userId) is called.");let a=H(t);if(s.debug.enabled&&a.warnings.length>0)for(let f of a.warnings)s.debug.emit("sdk.property_coerced",`Event "${e}" property ${JSON.stringify(f.key)} was ${f.kind.replace(/_/g," ")} during validation.`,{eventName:e,key:f.key,kind:f.kind});let c=s.autoTracker?.nextSeq()??0,l=Date.now();s.autoTracker?.markActivity();let d={},u=s.deviceInfo;u.os&&(d.os=u.os),u.osVersion&&(d.osVersion=u.osVersion);let m=s.options.appVersion;m&&(d.appVersion=m),d.sdkName=A,d.sdkVersion=s.options.sdkVersion,u.locale&&(d.locale=u.locale),u.timezone&&(d.timezone=u.timezone),u.browser&&(d.browser=u.browser),u.browserVersion&&(d.browserVersion=u.browserVersion);let p={};u.screenWidth!==void 0&&(p.screenWidth=u.screenWidth),u.screenHeight!==void 0&&(p.screenHeight=u.screenHeight),u.viewportWidth!==void 0&&(p.viewportWidth=u.viewportWidth),u.viewportHeight!==void 0&&(p.viewportHeight=u.viewportHeight),u.devicePixelRatio!==void 0&&(p.devicePixelRatio=u.devicePixelRatio);let y=s.autoTracker?.currentSessionId;y&&(p.sessionId=y);let b=s.autoTracker?.currentPageviewId;b&&(p.pageviewId=b);let g=s.autoTracker?.currentAcquisition;g&&(g.utm_source&&(p.utm_source=g.utm_source),g.utm_medium&&(p.utm_medium=g.utm_medium),g.utm_campaign&&(p.utm_campaign=g.utm_campaign),g.utm_content&&(p.utm_content=g.utm_content),g.utm_term&&(p.utm_term=g.utm_term),g.referrer&&s.consent.marketing&&(p.referrer=g.referrer),s.consent.marketing&&(g.gclid&&(p.gclid=g.gclid),g.fbclid&&(p.fbclid=g.fbclid),g.msclkid&&(p.msclkid=g.msclkid),g.ttclid&&(p.ttclid=g.ttclid),g.li_fat_id&&(p.li_fat_id=g.li_fat_id),g.twclid&&(p.twclid=g.twclid)));let v=s.superProps.getSuperProperties();for(let f of Object.keys(v))f in p||(p[f]=v[f]);let S=s.superProps.getGroupIds();Object.keys(S).length>0&&(p.$groups=S),Object.assign(p,a.properties),Je()&&(p[We]=!0);let T=s.scrubPii?Ee(p):p,C={eventId:this.mintEventId(),name:e,timestamp:l,seq:c,context:d,properties:T};if(Object.assign(C,this.identityHintForEvent()),s.events.enqueue(C),this.verifiers&&this.verifierReporter&&this.verifierCtx&&it(this.verifiers,this.verifierReporter,this.verifierCtx,{callerProperties:a.properties,superProperties:v,deviceProperties:s.deviceInfo,mergedProperties:p}),!n&&!i){let f=e.startsWith("page.")?"navigation":e.startsWith("element.")||e==="session.started"?"ui.click":"custom";s.breadcrumbs.add({timestamp:C.timestamp,category:f,message:e,data:t?{...t}:void 0})}}async flush(e={}){await this.requireStarted().events.flush(e)}async flushEvents(){return this.flush()}async syncPurchases(e){let t=this.requireStarted();if(!e.signedTransactionInfo)throw new _({type:"invalid_request_error",code:"missing_signed_transaction_info",message:"syncPurchases requires a signedTransactionInfo string from StoreKit 2."});let s=e.rail??"apple",n={...e,rail:s},i=L(n);if(this.verifiers&&this.verifierReporter&&this.verifierCtx){let a=s==="apple"?n.signedTransactionInfo??"":n.purchaseToken??"";ot(this.verifiers,this.verifierReporter,this.verifierCtx,{rail:s,stableIdentifier:a,derivedKey:i})}let o=await t.http.request("POST","/purchases/sync",{body:n,idempotencyKey:i});t.identity.setCrossdeckCustomerId(o.crossdeckCustomerId),t.entitlements.setFromList(o.entitlements);try{let a=o.entitlements[0]?.source.productId,c=o.entitlements[0]?.source.subscriptionId,l={rail:s};a&&(l.productId=a),c&&(l.subscriptionId=c),o.idempotent_replay&&(l.idempotent_replay=!0),this.track("purchase.completed",l)}catch{}return t.debug.emit("sdk.purchase_evidence_sent","StoreKit transaction forwarded. Waiting for backend verification.",{rail:e.rail??"apple"}),o}async purchaseApple(e){return this.syncPurchases({rail:"apple",...e})}setDebugMode(e){let t=this.requireStarted();t.debug.enabled=e,e&&t.debug.emit("sdk.configured",`Debug mode enabled for ${t.options.appId} in ${t.options.environment} mode.`,{appId:t.options.appId,environment:t.options.environment})}async heartbeat(){let e=this.requireStarted(),t=await e.http.request("GET","/sdk/heartbeat");return typeof t?.serverTime=="number"&&Number.isFinite(t.serverTime)&&(e.lastServerTime=t.serverTime,e.lastClientTime=Date.now()),t}reset(){if(this.state){if(this.state.developerUserId)try{this.track("user.signed_out",{auto:!0})}catch{}if(this.state.autoTracker?.uninstall(),this.state.developerUserId&&this.state.identity.reset(),ye({actor:void 0}),this.state.entitlements.clearAll(),this.state.events.reset(),this.state.superProps.clear(),this.state.breadcrumbs.clear(),this.state.errorContext={},this.state.errorTags={},this.state.developerUserId=null,this.state.lastServerTime=null,this.state.lastClientTime=null,this.state.autoTracker){let e=new W(this.state.options.autoTrack,(t,s)=>this.track(t,s));this.state.autoTracker=e,e.install()}}}diagnostics(){if(!this.state)return{started:!1,anonymousId:null,crossdeckCustomerId:null,developerUserId:null,sdkVersion:null,baseUrl:null,clock:{lastServerTime:null,lastClientTime:null,skewMs:null},entitlements:{count:0,lastUpdated:0,stale:!1,listenerErrors:0},events:{buffered:0,dropped:0,inFlight:0,lastFlushAt:0,lastError:null,consecutiveFailures:0,nextRetryAt:null}};let e=this.state,t=e.lastServerTime!==null&&e.lastClientTime!==null?e.lastClientTime-e.lastServerTime:null;return{started:!0,anonymousId:e.identity.anonymousId,crossdeckCustomerId:e.identity.crossdeckCustomerId,developerUserId:e.developerUserId,sdkVersion:e.options.sdkVersion,baseUrl:e.options.baseUrl,clock:{lastServerTime:e.lastServerTime,lastClientTime:e.lastClientTime,skewMs:t},entitlements:{count:e.entitlements.list().length,lastUpdated:e.entitlements.freshness,stale:e.entitlements.isStale,listenerErrors:e.entitlements.listenerErrors},events:e.events.getStats()}}getCheckoutReference(){let e=this.requireStarted();return e.identity.crossdeckCustomerId??e.developerUserId??e.identity.anonymousId}getAnonymousId(){return this.state?this.state.identity.anonymousId:null}requireStarted(){if(!this.state)throw new _({type:"configuration_error",code:"not_initialized",message:"Call Crossdeck.init({ appId, publicKey, environment }) before any other method."});return this.state}identityQueryParams(){let e=this.requireStarted();return e.identity.crossdeckCustomerId?{customerId:e.identity.crossdeckCustomerId}:e.developerUserId?{userId:e.developerUserId}:{anonymousId:e.identity.anonymousId}}identityHintForEvent(){let e=this.requireStarted(),t={anonymousId:e.identity.anonymousId};return e.developerUserId&&(t.developerUserId=e.developerUserId),e.identity.crossdeckCustomerId&&(t.crossdeckCustomerId=e.identity.crossdeckCustomerId),t}mintEventId(){return`evt_${Date.now().toString(36)}${V(8)}`}},pt=new G;function Ur(r){return r.startsWith("cd_pub_test_")?"sandbox":r.startsWith("cd_pub_live_")?"production":null}function $r(){let r=globalThis.window;if(r?.__CROSSDECK_FORCE_LIVE__===!0)return!1;let e=r?.location?.hostname;return e?!!(e==="localhost"||e==="127.0.0.1"||e==="0.0.0.0"||e==="::1"||e==="[::1]"||/^\[?fe80::/i.test(e)||e.endsWith(".local")||/^10\./.test(e)||/^192\.168\./.test(e)||/^172\.(1[6-9]|2\d|3[0-1])\./.test(e)):!1}function qr(r){return r===!1?{sessions:!1,pageViews:!1,deviceInfo:!1,clicks:!1,webVitals:!1,errors:!1}:r===void 0||r===!0?{...F}:{sessions:r.sessions??F.sessions,pageViews:r.pageViews??F.pageViews,deviceInfo:r.deviceInfo??F.deviceInfo,clicks:r.clicks??F.clicks,webVitals:r.webVitals??F.webVitals,errors:r.errors??F.errors}}function Kr(r){let e=globalThis.window,t=globalThis.document;if(!e||!t)return()=>{};let s=()=>{try{t.visibilityState==="hidden"&&r()}catch{}},n=()=>{try{r()}catch{}};return t.addEventListener("visibilitychange",s),e.addEventListener("pagehide",n),e.addEventListener("beforeunload",n),()=>{t.removeEventListener("visibilitychange",s),e.removeEventListener("pagehide",n),e.removeEventListener("beforeunload",n)}}var ht="@cross-deck/web@1.12.0",mt="1.12.0",U=Object.freeze([{id:"contract-failed-payload-schema-lock",pillar:"diagnostics",status:"enforced",claim:"The `crossdeck.contract_failed` event payload contains ONLY the named diagnostic fields and never any end-user personal data. The wire shape is fixed \u2014 adding a new field requires (1) a pull request that updates this contract's `allowedFields` set, (2) a Privacy Policy \xA76 amendment, and (3) the Customer Disclosure Template / SDK Data Collection Reference \xA7B updates. Per-SDK assertion tests enforce the field set on every release. The `verification_phase` field is a categorical bucket \u2014 values are restricted to `boot` (the SDK self-test ran on Crossdeck.start) or `hot_path` (a verifier observed a real customer-triggered operation). The categorical nature is what preserves the diagnostic-only-not-personal classification. This is the structural guarantee that backs the independent-controller lawful basis in the Privacy Policy: the payload remains diagnostic-only, not personal, so the legitimate-interest analysis stays valid as the SDK evolves.",appliesTo:["web","node","swift","android","react-native"],allowedFields:{required:["contract_id","sdk_version","sdk_platform","failure_reason","run_context","run_id"],optional:["test_file","test_name","device_class","verification_phase"],forbidden:["anonymousId","developerUserId","crossdeckCustomerId","email","ip","user_agent","message","stack","stack_trace","frames","exception_message","url","path","screen","title","label","text","ariaLabel","accessibilityLabel","contentDescription","session_id","sessionId"]},transport:"Telemetry is single-fire to the Crossdeck reliability endpoint only \u2014 NOT the customer's appId. The customer's track() pipeline never carries `crossdeck.*` events; the customer's dashboard never shows individual contract failures. Operational telemetry flows one-way to the Crossdeck operations team for SDK reliability purposes (legitimate interest, independent-controller flow per Privacy Policy \xA76). The reliability endpoint is hardcoded at SDK build time; the publishable key for the reliability project is embedded as a constant and rejects writes that don't match the schema.",codeRef:["sdks/web/src/crossdeck.ts","sdks/node/src/crossdeck-server.ts","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/swift/Sources/Crossdeck/_DiagnosticTelemetry.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Crossdeck.kt","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/_DiagnosticTelemetry.kt","sdks/react-native/src/crossdeck.ts","backend/src/api/v1-sdk-diagnostic.ts","sdks/web/src/_diagnostic-telemetry.ts","sdks/node/src/_diagnostic-telemetry.ts","sdks/react-native/src/_diagnostic-telemetry.ts"],testRef:[{file:"sdks/web/tests/contract-failed-schema-lock.test.ts",name:"reportContractFailure payload conforms to schema-lock"},{file:"sdks/node/tests/contract-failed-schema-lock.test.ts",name:"reportContractFailure payload conforms to schema-lock"},{file:"sdks/swift/Tests/CrossdeckTests/ContractFailedSchemaLockTests.swift",name:"test_reportContractFailure_payloadFieldsAreInAllowList"},{file:"sdks/swift/Tests/CrossdeckTests/ContractFailedSchemaLockTests.swift",name:"test_reportContractFailure_doesNotEnterCustomerTrackPipeline"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/ContractFailedSchemaLockTest.kt",name:"reportContractFailure payload conforms to schema-lock"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/ContractFailedSchemaLockTest.kt",name:"reportContractFailure does not enter customer track pipeline"},{file:"sdks/react-native/tests/contract-failed-schema-lock.test.ts",name:"reportContractFailure payload conforms to schema-lock"},{file:"backend/tests/unit/v1-sdk-diagnostic.test.ts",name:"forbidden fields are enumerated in the schema-lock contract"},{file:"backend/tests/unit/v1-sdk-diagnostic.test.ts",name:"required fields are enumerated in the schema-lock contract"},{file:"backend/tests/unit/v1-sdk-diagnostic.test.ts",name:"regression guard: never returns a raw IP"},{file:"backend/tests/unit/v1-sdk-diagnostic.test.ts",name:"verification_phase is in the optional field set"}],registeredAt:"2026-05-27",firstRegisteredIn:"Diagnostic telemetry single-fire + schema-lock \u2014 independent-controller flow",privacyReferences:["legal/privacy/index.html#sdk-diagnostic","legal/customer-disclosure/index.html#flow-b","legal/security/index.html#diagnostic","legal/sdk-data/index.html#b-diagnostic"],bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"error-envelope-shape",pillar:"errors",status:"enforced",claim:"Every v1 REST endpoint returns errors in a Stripe-shape envelope: `{ error: { type, code, message, request_id } }` where `type` is one of authentication_error / permission_error / invalid_request_error / rate_limit_error / internal_error (the wire vocabulary in backend/src/api/v1-errors.ts ApiErrorType). HTTP status parity: invalid_request_error \u2192 400, authentication_error \u2192 401, permission_error \u2192 403, rate_limit_error \u2192 429, internal_error \u2192 500. SDK-side clients parse this shape via `crossdeckErrorFromResponse` (Web/Node/RN) / `crossdeckErrorFrom(response:)` (Swift) / `crossdeckErrorFromResponse` (Android) and surface the request_id verbatim so support traces are end-to-end joinable. Firebase callable endpoints (managed-keys / dashboard auth) use the Firebase HttpsError envelope instead \u2014 this contract applies to REST /v1/* only.",appliesTo:["web","node","react-native","swift","android","backend"],codeRef:["backend/src/api/v1-errors.ts","sdks/web/src/errors.ts","sdks/node/src/errors.ts","sdks/react-native/src/errors.ts","sdks/swift/Sources/Crossdeck/Errors.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Errors.kt"],testRef:[{file:"sdks/swift/Tests/CrossdeckTests/ErrorsTests.swift",name:"test_errorEnvelope_fallsBackOnGarbageBody"},{file:"sdks/swift/Tests/CrossdeckTests/ErrorsTests.swift",name:"test_errorEnvelope_reads_XRequestId_fallback"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/ErrorTypeWireVocabTest.kt",name:"backend 500 response parses to INTERNAL_ERROR"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 8 (codifies existing contract)",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"flush-interval-parity",pillar:"analytics",status:"enforced",claim:"Every Crossdeck SDK defaults its event-queue flush interval to 2000ms \u2014 the Stripe-adjacent industry norm. Pre-v1.4.0 the defaults disagreed (Web/Node 1500ms; RN/Swift/Android 5000ms), so cross-platform funnels saw events landing at different cadences. Per-instance override stays \u2014 call sites can still tune it freely.",appliesTo:["web","node","react-native","swift","android"],codeRef:["sdks/web/src/crossdeck.ts","sdks/node/src/crossdeck-server.ts","sdks/react-native/src/crossdeck.ts","sdks/swift/Sources/Crossdeck/EventQueue.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/EventQueue.kt"],testRef:[{file:"sdks/swift/Sources/Crossdeck/EventQueue.swift",name:"flushIntervalMs: Int = 2_000"},{file:"sdks/android/crossdeck/src/main/kotlin/com/crossdeck/EventQueue.kt",name:"flushIntervalMs: Long = 2_000L"},{file:"sdks/web/src/crossdeck.ts",name:"options.eventFlushIntervalMs ?? 2000"},{file:"sdks/node/src/crossdeck-server.ts",name:"options.eventFlushIntervalMs ?? 2000"},{file:"sdks/react-native/src/crossdeck.ts",name:"options.eventFlushIntervalMs ?? 2000"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 3.3",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"idempotency-key-deterministic",pillar:"revenue",status:"enforced",claim:"syncPurchases() on every SDK derives a deterministic Idempotency-Key from the request body (UUID-shaped SHA-256 of `crossdeck:purchases/sync:<rail>:<jws|token>`). Same input -> same key. Backend short-circuits same-key-same-body retries by returning the cached response (status + body) with `idempotent_replay: true` flag in the body AND `Idempotent-Replayed: true` response header. Same-key-different-body returns 400 `idempotency_key_in_use`. 24-hour TTL matches Stripe. Cache only stores 2xx responses \u2014 4xx/5xx pass through so callers can fix bugs and retry. Helper returns nil/throws on missing identifier (no silent random fallback). Cross-SDK parity is CI-pinned: deriveForPurchase('apple', 'eyJ.jws.sig') MUST equal 'a66b1640-efaf-bb4d-1261-6650033bf111' on every SDK.",appliesTo:["web","node","react-native","swift","android","backend"],codeRef:["sdks/web/src/idempotency-key.ts","sdks/web/src/crossdeck.ts","sdks/react-native/src/idempotency-key.ts","sdks/react-native/src/crossdeck.ts","sdks/node/src/idempotency-key.ts","sdks/node/src/crossdeck-server.ts","sdks/swift/Sources/Crossdeck/IdempotencyKey.swift","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/IdempotencyKey.kt","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Crossdeck.kt","backend/src/lib/idempotency-response-cache.ts","backend/src/api/v1-purchases.ts"],testRef:[{file:"sdks/web/tests/idempotency-key.test.ts",name:"cross-SDK oracle \u2014 apple JWS pins canonical vector"},{file:"sdks/web/tests/idempotency-key.test.ts",name:"is deterministic: same body twice -> identical key"},{file:"sdks/web/tests/idempotency-key.test.ts",name:"same identifier under different rails -> different keys"},{file:"sdks/web/tests/idempotency-key.test.ts",name:"never silently falls back to a random key on missing identifier"},{file:"sdks/react-native/tests/idempotency-key.test.ts",name:"is deterministic"},{file:"sdks/react-native/tests/idempotency-key.test.ts",name:"cross-SDK oracle \u2014 apple JWS pins canonical vector"},{file:"sdks/node/tests/idempotency-key.test.ts",name:"is deterministic"},{file:"sdks/node/tests/idempotency-key.test.ts",name:"rail namespacing prevents cross-rail collisions"},{file:"sdks/node/tests/idempotency-key.test.ts",name:"apple JWS produces the canonical pinned UUID across all 5 SDKs"},{file:"backend/tests/unit/idempotency-response-cache.test.ts",name:"is deterministic for the same input"},{file:"backend/tests/unit/idempotency-response-cache.test.ts",name:"injects idempotent_replay: true into a JSON object body"},{file:"backend/tests/unit/idempotency-response-cache.test.ts",name:"matches Stripe's 24-hour idempotency window"},{file:"sdks/swift/Tests/CrossdeckTests/IdempotencyKeyTests.swift",name:"test_crossSdkOracle_appleJWS"},{file:"sdks/swift/Tests/CrossdeckTests/IdempotencyKeyTests.swift",name:"test_railNamespacing_preventsCrossRailCollisions"},{file:"sdks/swift/Tests/CrossdeckTests/IdempotencyKeyTests.swift",name:"test_missingIdentifier_returnsNil"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/IdempotencyKeyTest.kt",name:"cross-SDK oracle for apple JWS"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/IdempotencyKeyTest.kt",name:"rail namespacing prevents cross-rail collisions"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/IdempotencyKeyTest.kt",name:"missing identifier returns null - never silent random fallback"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 2.2.a + 2.2.b + 2.2.c",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"init-reentry-drains-prior-queue",pillar:"lifecycle",status:"enforced",claim:"Web + RN init() re-entry drains the prior EventQueue's pending setTimeout BEFORE replacing this.state. Pre-v1.4.0 the teardown handled autoTracker/webVitals/errors/unloadFlush but NOT events, so the prior queue's timer would fire AFTER the state swap \u2014 sending old-init events against new-init http + identity references (cross-identity leak during HMR / config swap / multi-tenant SDK shells). The teardown CANNOT call persistent.clear() \u2014 the durable queue belongs to the SDK lifetime, not the init() lifetime, and a survived crash mid-flush re-hydrates on the next init.",appliesTo:["web","react-native"],codeRef:["sdks/web/src/crossdeck.ts","sdks/react-native/src/crossdeck.ts"],testRef:[{file:"sdks/web/tests/init-reentry.test.ts",name:"re-init drains the prior queue's pending timer before swapping state"},{file:"sdks/web/tests/init-reentry.test.ts",name:"re-init does NOT wipe the durable event store"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 5.5",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!1},{id:"invalid-input-rejected-natively",pillar:"errors",status:"enforced",claim:"No public SDK API ever crashes the host app, and invalid input never reaches the wire. Invalid input (empty event name, empty userId, out-of-range config such as a non-positive breadcrumb capacity, NaN/Infinity/oversize/cyclic property values) is rejected at the call site WITHOUT a fatal trap. The signalling IDIOM is per-language and intentionally NOT uniform: Web, Node, and React Native THROW a typed CrossdeckError synchronously (code missing_event_name / missing_user_id / invalid_request_error) \u2014 a normal, catchable JavaScript convention where an uncaught throw logs and the app continues; Swift DROPS with a debug-log signal (track_dropped / identify_dropped) to match its non-throwing fire-and-forget surface, and exposes the throwing equivalent only via identifyAndWait(userId:). What is UNIFORM is the invariant, not the mechanism: every SDK rejects the same inputs, no public fire-and-forget API contains a fatalError / assertionFailure / precondition reachable from customer input, and no rejected input is enqueued or transmitted. Swift additionally proves this in BOTH debug and release configuration, because precondition fires under -O while assertionFailure does not. The bug class this contract closes was never the per-language difference \u2014 it was the UNDECLARED difference: each SDK's public API documentation must state its own semantics explicitly (TS docs: 'throws on empty name'; Swift docs: 'drops and logs').",appliesTo:["web","node","react-native","swift"],codeRef:["sdks/web/src/crossdeck.ts","sdks/node/src/crossdeck-server.ts","sdks/react-native/src/crossdeck.ts","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/swift/Sources/Crossdeck/Breadcrumbs.swift"],testRef:[{file:"sdks/web/tests/crossdeck.test.ts",name:"track with empty name throws synchronously"},{file:"sdks/web/tests/crossdeck.test.ts",name:"rejects empty userId"},{file:"sdks/node/tests/crossdeck-server.test.ts",name:"track() throws CrossdeckError with code 'missing_event_name' when event name is empty"},{file:"sdks/react-native/tests/crossdeck.test.ts",name:"track('') throws CrossdeckError(missing_event_name) synchronously"},{file:"sdks/react-native/tests/crossdeck.test.ts",name:"identify('') rejects with CrossdeckError(missing_user_id)"},{file:"sdks/swift/Tests/CrossdeckTests/CrossdeckPublicAPITests.swift",name:"test_track_dropsEmptyName"},{file:"sdks/swift/Tests/CrossdeckTests/CrossdeckPublicAPITests.swift",name:"test_identifyAndWait_rejectsEmptyId"},{file:"sdks/swift/Tests/CrossdeckTests/PublicAPIInputSafetyTests.swift",name:"test_start_withZeroBreadcrumbCapacity_doesNotTrap"}],registeredAt:"2026-06-11",firstRegisteredIn:"swift trap-on-input class fix \u2014 first machine-tested Swift release",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!1},{id:"per-user-cache-isolation",pillar:"entitlements",status:"enforced",claim:"Every identify(userId) switches the entitlement cache to a physically separate per-user storage slot \u2014 `crossdeck:entitlements:<sha256(userId)>` \u2014 and unconditionally wipes the in-memory snapshot. A user-switch on a shared device CANNOT cross-read a prior user's cached entitlements, even if the in-memory clear is somehow skipped, because the storage keys are physically separate. reset() wipes every per-user slot via the persisted index.",appliesTo:["web","react-native","swift","android"],codeRef:["sdks/web/src/entitlement-cache.ts","sdks/web/src/hash.ts","sdks/web/src/crossdeck.ts","sdks/react-native/src/entitlement-cache.ts","sdks/react-native/src/hash.ts","sdks/react-native/src/crossdeck.ts","sdks/swift/Sources/Crossdeck/EntitlementCache.swift","sdks/swift/Sources/Crossdeck/IdempotencyKey.swift","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/EntitlementCache.kt","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/IdempotencyKey.kt","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Crossdeck.kt"],testRef:[{file:"sdks/web/tests/entitlement-cache-isolation.test.ts",name:"identify(B) makes A's entitlements unreachable from in-memory"},{file:"sdks/web/tests/entitlement-cache-isolation.test.ts",name:"clearAll() removes every per-user storage key plus the index"},{file:"sdks/web/tests/entitlement-cache-isolation.test.ts",name:"a second cache instance reading A's storage suffix CANNOT see B's data"},{file:"sdks/react-native/tests/entitlement-cache-isolation.test.ts",name:"identify(B) makes A's entitlements unreachable from in-memory"},{file:"sdks/react-native/tests/entitlement-cache-isolation.test.ts",name:"removes every per-user storage key plus the index"},{file:"sdks/swift/Tests/CrossdeckTests/EntitlementCacheIsolationTests.swift",name:"test_identifyB_makesAEntitlementsUnreachable"},{file:"sdks/swift/Tests/CrossdeckTests/EntitlementCacheIsolationTests.swift",name:"test_identifiedWritesLandUnderPerUserSha256Key"},{file:"sdks/swift/Tests/CrossdeckTests/EntitlementCacheIsolationTests.swift",name:"test_clearAll_removesEveryPerUserStorageKeyPlusIndex"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/EntitlementCacheIsolationTest.kt",name:"identified writes land under per-user sha256 key"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/EntitlementCacheIsolationTest.kt",name:"identify B makes A entitlements unreachable from in-memory"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/EntitlementCacheIsolationTest.kt",name:"clearAll removes every per-user storage key plus the index"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/EntitlementCacheIsolationTest.kt",name:"a fresh cache bound to A's key CANNOT read B's blob"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 1.3 (web/RN) + dogfood-gap fix (swift + android)",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"sdk-error-codes-catalogue",pillar:"errors",status:"enforced",claim:"Web + Node SDK error-codes catalogues include EVERY backend-emitted ApiErrorCode with a description + resolution. Pre-v1.4.0 the catalogues documented codes the SDK threw ITSELF but ZERO backend codes \u2014 a developer hitting `invalid_api_key` / `origin_not_allowed` / `bundle_id_not_allowed` / `env_mismatch` / `idempotency_key_in_use` etc. got `undefined` from getErrorCode() and had to hunt for guidance. v1.4.0 backfills the catalogue from backend/src/api/v1-errors.ts so every wire code has a canonical 'what does this mean / what should I do' answer Stripe-style.",appliesTo:["web","node"],codeRef:["sdks/web/src/error-codes.ts","sdks/node/src/error-codes.ts","sdks/web/src/_contract-verifiers.ts","backend/src/api/v1-errors.ts"],testRef:[{file:"sdks/web/tests/contract-verifiers.test.ts",name:"sdk-error-codes-catalogue covers every backend wire code with remediation"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"includes backend code"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"invalid_api_key resolution points at the dashboard"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"idempotency_key_in_use resolution mentions Stripe-grade contract"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"identity-lock codes carry permission_error type"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"no entry has an empty description or resolution"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 6.2",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"super-property-merge-precedence",pillar:"analytics",status:"enforced",claim:"Every Crossdeck SDK merges event properties with the precedence device < super < caller (caller-supplied values win over registered super-properties, which win over auto-attached device info). Pre-v1.4.0 Swift had it INVERTED (super < device < caller \u2014 device clobbered super), so a `register('plan', 'pro')` super-property was silently overridden by auto-attached device fields whenever keys collided. Cross-SDK funnel queries on super-property keys returned different answers per platform.",appliesTo:["web","swift"],codeRef:["sdks/web/src/super-properties.ts","sdks/web/src/_contract-verifiers.ts","sdks/swift/Sources/Crossdeck/EventPropertyMerge.swift","sdks/swift/Sources/Crossdeck/Crossdeck.swift"],testRef:[{file:"sdks/web/tests/contract-verifiers.test.ts",name:"super-property-merge-precedence verifies caller > super > device"},{file:"sdks/swift/Tests/CrossdeckTests/EventPropertyMergeTests.swift",name:"test_super_overrides_device"},{file:"sdks/swift/Tests/CrossdeckTests/EventPropertyMergeTests.swift",name:"test_caller_overrides_super"},{file:"sdks/swift/Tests/CrossdeckTests/EventPropertyMergeTests.swift",name:"test_full_precedence_chain"},{file:"sdks/swift/Tests/CrossdeckTests/EventPropertyMergeTests.swift",name:"test_matchesWebNodeRNPrecedence"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 3.2",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"sync-purchases-funnel-parity",pillar:"analytics",status:"enforced",claim:"Manual syncPurchases() emits a `purchase.completed` analytics event on success across ALL SDKs (Web / Node / RN / Swift / Android). Pre-v1.4.0 only Swift/Android auto-track emitted it \u2014 Web/Node/RN manual calls + Swift/Android manual calls fired ZERO analytics. Schema mirrors the auto-track event name + rail/productId/subscriptionId so cross-platform funnels reconcile on every payment path. When the backend short-circuits via the v1.4.0 idempotency cache, the event also carries `idempotent_replay: true`.",appliesTo:["web","node","react-native","swift","android"],codeRef:["sdks/web/src/crossdeck.ts","sdks/node/src/crossdeck-server.ts","sdks/react-native/src/crossdeck.ts","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Crossdeck.kt"],testRef:[{file:"sdks/web/tests/sync-purchases-funnel.test.ts",name:"emits purchase.completed after a successful sync"},{file:"sdks/web/tests/sync-purchases-funnel.test.ts",name:"carries idempotent_replay=true when backend replied from cache"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 3.5",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!1}]);var gt={all(){return U.filter(r=>r.status==="enforced")},allIncludingHistorical(){return U},byId(r){return U.find(e=>e.id===r)},byPillar(r){return U.filter(e=>e.pillar===r&&e.status==="enforced")},withStatus(r){return U.filter(e=>e.status===r)},sdkVersion:mt,bundledIn:ht,findByTestName(r){return U.find(e=>e.testRef.some(t=>t.name===r))}};return Et(Mr);})();
1
+ "use strict";var Crossdeck=(()=>{var ke=Object.defineProperty;var St=Object.getOwnPropertyDescriptor;var Tt=Object.getOwnPropertyNames;var Et=Object.prototype.hasOwnProperty;var xt=(r,e)=>{for(var t in e)ke(r,t,{get:e[t],enumerable:!0})},It=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Tt(e))!Et.call(r,n)&&n!==t&&ke(r,n,{get:()=>e[n],enumerable:!(s=St(e,n))||s.enumerable});return r};var Ct=r=>It(ke({},"__esModule",{value:!0}),r);var Jr={};xt(Jr,{CROSSDECK_ERROR_CODES:()=>Ce,Crossdeck:()=>yt,CrossdeckClient:()=>J,CrossdeckContracts:()=>vt,CrossdeckError:()=>_,DEFAULT_BASE_URL:()=>Z,MemoryStorage:()=>F,SDK_NAME:()=>A,SDK_VERSION:()=>R,TRUST_PANEL_ORIGIN:()=>be,getErrorCode:()=>me,mountTrustPanel:()=>te});var _=class r extends Error{constructor(e){super(e.message),this.name="CrossdeckError",this.type=e.type,this.code=e.code,this.requestId=e.requestId,this.status=e.status,this.retryAfterMs=e.retryAfterMs,this.minVersion=e.minVersion,this.surface=e.surface,Object.setPrototypeOf(this,r.prototype)}};async function Me(r){let e=r.headers.get("x-request-id")??void 0,t=Rt(r.headers.get("retry-after")),s;try{s=await r.json()}catch{s=null}let n=s?.error;return n&&typeof n.type=="string"&&typeof n.code=="string"?new _({type:n.type,code:n.code,message:n.message??`HTTP ${r.status}`,requestId:n.request_id??e,status:r.status,retryAfterMs:t,minVersion:typeof n.minVersion=="string"?n.minVersion:void 0,surface:typeof n.surface=="string"?n.surface:void 0}):new _({type:At(r.status),code:`http_${r.status}`,message:`HTTP ${r.status} ${r.statusText||""}`.trim(),requestId:e,status:r.status,retryAfterMs:t})}function Rt(r){if(!r)return;let e=r.trim();if(!e)return;if(/^\d+(\.\d+)?$/.test(e)){let n=Number(e);return!Number.isFinite(n)||n<0?void 0:Math.round(n*1e3)}if(!/[a-zA-Z,/:]/.test(e))return;let t=Date.parse(e);if(!Number.isFinite(t))return;let s=t-Date.now();return s>0?s:0}function At(r){return r===401?"authentication_error":r===403?"permission_error":r===429?"rate_limit_error":r>=400&&r<500?"invalid_request_error":"internal_error"}var R="1.13.0",A="@cross-deck/web";var Z="https://api.cross-deck.com/v1",Pt=15e3,Q=class{constructor(e){this.config=e}async request(e,t,s={}){if(this.config.localDevMode)return Dt(t);let n=this.buildUrl(t,s.query),i={Authorization:`Bearer ${this.config.publicKey}`,"Crossdeck-Sdk-Version":`${A}@${this.config.sdkVersion}`,Accept:"application/json"};s.idempotencyKey&&(i["Idempotency-Key"]=s.idempotencyKey);let o;s.body!==void 0&&(i["Content-Type"]="application/json",o=JSON.stringify(s.body));let a=s.timeoutMs??this.config.timeoutMs??Pt,c=typeof AbortController<"u"&&a>0?new AbortController:null,d=null;c&&a>0&&(d=setTimeout(()=>c.abort(),a));let l;try{l=await fetch(n,{method:e,headers:i,body:o,keepalive:s.keepalive===!0,signal:c?.signal})}catch(u){let h=c?.signal?.aborted===!0;throw new _({type:"network_error",code:h?"request_timeout":"fetch_failed",message:h?`Request to ${t} aborted after ${a}ms`:u instanceof Error?u.message:"fetch failed"})}finally{d!==null&&clearTimeout(d)}if(!l.ok){let u=await Me(l);if(this.config.onErrorParsed)try{this.config.onErrorParsed(u)}catch{}throw u}if(l.status!==204)try{return await l.json()}catch{throw new _({type:"internal_error",code:"invalid_json_response",message:"Server returned a 2xx with an unparseable body.",requestId:l.headers.get("x-request-id")??void 0,status:l.status})}}get isLocalDevMode(){return this.config.localDevMode===!0}buildUrl(e,t){let s=this.config.baseUrl.replace(/\/+$/,""),n=e.startsWith("/")?e:`/${e}`,i=s+n;if(t){let o=new URLSearchParams;for(let[c,d]of Object.entries(t))typeof d=="string"&&d.length>0&&o.append(c,d);let a=o.toString();a&&(i+=(i.includes("?")?"&":"?")+a)}return i}},Y=null;function Dt(r){return r.startsWith("/sdk/heartbeat")?{object:"heartbeat",ok:!0,projectId:"proj_local_dev",appId:"app_local_dev",platform:"web",env:"sandbox",serverTime:Date.now()}:r.startsWith("/identity/alias")?(Y||(Y=`cdcust_local_${typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID().replace(/-/g,"").slice(0,16):Math.random().toString(36).slice(2,18)}`),{object:"alias_result",crossdeckCustomerId:Y,linked:[],mergePending:!1,env:"sandbox"}):r.startsWith("/entitlements")?{object:"list",data:[],crossdeckCustomerId:Y??"",env:"sandbox"}:r.startsWith("/events")?{object:"list",received:0,env:"sandbox"}:{}}var B="anon_id",H="cdcust_id",ee=class{constructor(e,t,s){this.primary=e;this.prefix=t;this.secondary=s??null;let n=e.getItem(t+B),i=e.getItem(t+H),o=this.secondary?.getItem(t+B)??null,a=this.secondary?.getItem(t+H)??null,c=n??o,d=i??a;this.state={anonymousId:c??this.mintAnonymousId(),crossdeckCustomerId:d},(!n||!o)&&this.writeBoth(t+B,this.state.anonymousId),d&&(!i||!a)&&this.writeBoth(t+H,d)}get anonymousId(){return this.state.anonymousId}get crossdeckCustomerId(){return this.state.crossdeckCustomerId}setCrossdeckCustomerId(e){this.state.crossdeckCustomerId=e,this.writeBoth(this.prefix+H,e)}reset(){this.deleteBoth(this.prefix+B),this.deleteBoth(this.prefix+H),this.state={anonymousId:this.mintAnonymousId(),crossdeckCustomerId:null},this.writeBoth(this.prefix+B,this.state.anonymousId)}mintAnonymousId(){let e=Date.now().toString(36),t=O(10);return`anon_${e}${t}`}writeBoth(e,t){try{this.primary.setItem(e,t)}catch{}if(this.secondary)try{this.secondary.setItem(e,t)}catch{}}deleteBoth(e){try{this.primary.removeItem(e)}catch{}if(this.secondary)try{this.secondary.removeItem(e)}catch{}}};function O(r){let e="0123456789abcdefghijklmnopqrstuvwxyz",t=[],s=globalThis.crypto;if(s?.getRandomValues){let n=new Uint8Array(r);s.getRandomValues(n);for(let i=0;i<r;i++)t.push(e[n[i]%e.length]??"0")}else for(let n=0;n<r;n++)t.push(e[Math.floor(Math.random()*e.length)]??"0");return t.join("")}var be="https://trust.cross-deck.com";function te(r){let e=Ft(r.origin)||be,t=Ue(r.timeoutMs,15e3,1e3,12e4),s=!1,n=null,i=null,o=null,a,c=new Promise(u=>{a=u});function d(u,h){if(!s)if(s=!0,i&&V(()=>clearTimeout(i)),n&&V(()=>window.removeEventListener("message",n)),u)V(()=>r.onToken?.(u)),a(u);else{let f=h||"unavailable";V(()=>r.onUnavailable?.(f)),a({token:null,expiresAt:null,reason:f})}}try{if(typeof window>"u"||typeof document>"u")return queueMicrotask(()=>d(null,"no_dom")),l();let u=Vt(r.target);if(o=Ot(e,r.publicKey),!u)return queueMicrotask(()=>d(null,"no_mount_target")),l();n=h=>{if(h.origin!==e||!h.data||!o||h.source!==o.contentWindow)return;let f=h.data;f.type==="cd-trust-size"&&typeof f.height=="number"?V(()=>{o&&(o.style.height=Ue(f.height,132,96,220)+"px")}):f.type==="cd-trust-token"&&typeof f.token=="string"&&d({token:f.token,expiresAt:typeof f.expMs=="number"?f.expMs:null})},window.addEventListener("message",n),u.appendChild(o),i=setTimeout(()=>d(null,"timeout"),t)}catch(u){queueMicrotask(()=>d(null,"mount_error:"+Lt(u)))}return l();function l(){return{frame:o,ready:c,destroy(){n&&V(()=>window.removeEventListener("message",n)),i&&V(()=>clearTimeout(i)),V(()=>o?.parentNode?.removeChild(o)),d(null,"destroyed")}}}}function Ot(r,e){let t=document.createElement("iframe");return t.title="Protected by Crossdeck Trust",t.setAttribute("aria-label","Protected by Crossdeck Trust"),t.setAttribute("scrolling","no"),t.setAttribute("allowtransparency","true"),t.style.cssText="border:0;display:block;width:100%;max-width:360px;height:132px;margin:0;background:transparent;color-scheme:light;",t.src=r+"/panel?k="+encodeURIComponent(e||""),t}function Vt(r){try{return typeof r=="string"?document.querySelector(r):r||null}catch{return null}}function Ft(r){if(!r||typeof r!="string")return null;try{return new URL(r).origin}catch{return null}}function Ue(r,e,t,s){let n=typeof r=="number"&&isFinite(r)?r:e;return Math.min(Math.max(n,t),s)}function V(r){try{r()}catch{}}function Lt(r){try{return r instanceof Error?r.message:String(r)}catch{return"unknown"}}var Nt=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]);function Mt(r){if(typeof TextEncoder<"u")return new TextEncoder().encode(r);let e=[];for(let t=0;t<r.length;t++){let s=r.charCodeAt(t);if(s>=55296&&s<=56319&&t+1<r.length){let n=r.charCodeAt(t+1);n>=56320&&n<=57343&&(s=65536+(s-55296<<10)+(n-56320),t++)}s<128?e.push(s):s<2048?(e.push(192|s>>6),e.push(128|s&63)):s<65536?(e.push(224|s>>12),e.push(128|s>>6&63),e.push(128|s&63)):(e.push(240|s>>18),e.push(128|s>>12&63),e.push(128|s>>6&63),e.push(128|s&63))}return new Uint8Array(e)}function q(r){let e=Mt(r),t=e.length*8,s=Math.floor((e.length+9+63)/64),n=new Uint8Array(s*64);n.set(e),n[e.length]=128;let i=Math.floor(t/4294967296),o=t>>>0,a=n.length-8;n[a+0]=i>>>24&255,n[a+1]=i>>>16&255,n[a+2]=i>>>8&255,n[a+3]=i&255,n[a+4]=o>>>24&255,n[a+5]=o>>>16&255,n[a+6]=o>>>8&255,n[a+7]=o&255;let c=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),d=new Uint32Array(64);for(let u=0;u<s;u++){let h=u*64;for(let p=0;p<16;p++)d[p]=(n[h+p*4]<<24|n[h+p*4+1]<<16|n[h+p*4+2]<<8|n[h+p*4+3])>>>0;for(let p=16;p<64;p++){let w=d[p-15],T=d[p-2],C=(w>>>7|w<<25)^(w>>>18|w<<14)^w>>>3,D=(T>>>17|T<<15)^(T>>>19|T<<13)^T>>>10;d[p]=d[p-16]+C+d[p-7]+D>>>0}let f=c[0],y=c[1],b=c[2],g=c[3],v=c[4],S=c[5],I=c[6],x=c[7];for(let p=0;p<64;p++){let w=(v>>>6|v<<26)^(v>>>11|v<<21)^(v>>>25|v<<7),T=v&S^~v&I,C=x+w+T+Nt[p]+d[p]>>>0,D=(f>>>2|f<<30)^(f>>>13|f<<19)^(f>>>22|f<<10),wt=f&y^f&b^y&b,_t=D+wt>>>0;x=I,I=S,S=v,v=g+C>>>0,g=b,b=y,y=f,f=C+_t>>>0}c[0]=c[0]+f>>>0,c[1]=c[1]+y>>>0,c[2]=c[2]+b>>>0,c[3]=c[3]+g>>>0,c[4]=c[4]+v>>>0,c[5]=c[5]+S>>>0,c[6]=c[6]+I>>>0,c[7]=c[7]+x>>>0}let l="";for(let u=0;u<8;u++)l+=c[u].toString(16).padStart(8,"0");return l}var Ut=1440*60*1e3,re="_anon",qt="_index",P=class r{constructor(e,t="crossdeck:entitlements",s=Ut){this.all=[];this.lastUpdated=0;this.lastRefreshFailedAt=0;this.listeners=new Set;this.listenerErrorCount=0;this.currentSuffix=re;this.storage=e,this.storageKeyPrefix=t,this.staleAfterMs=s,this.hydrate()}get storageKey(){return`${this.storageKeyPrefix}:${this.currentSuffix}`}get indexKey(){return`${this.storageKeyPrefix}:${qt}`}static suffixForUserId(e){return e==null||e===""?re:q(e)}setUserKey(e){let t=r.suffixForUserId(e);if(t===this.currentSuffix){this.all=[],this.lastUpdated=0,this.lastRefreshFailedAt=0,this.notify(),this.hydrate();return}this.currentSuffix=t,this.all=[],this.lastUpdated=0,this.lastRefreshFailedAt=0,this.hydrate(),this.notify()}isEntitled(e){let t=Date.now()/1e3;return this.all.some(s=>s.key===e&&s.isActive&&(s.validUntil==null||s.validUntil>t))}list(){return this.all.slice()}get freshness(){return this.lastUpdated}get isStale(){return this.lastRefreshFailedAt>this.lastUpdated?!0:this.lastUpdated>0&&Date.now()-this.lastUpdated>this.staleAfterMs}get refreshFailedAt(){return this.lastRefreshFailedAt}get listenerErrors(){return this.listenerErrorCount}markRefreshFailed(){this.lastRefreshFailedAt=Date.now()}setFromList(e){this.all=e.slice(),this.lastUpdated=Date.now(),this.lastRefreshFailedAt=0,this.persist(),this.recordSuffixInIndex(this.currentSuffix),this.notify()}clear(){if(this.all=[],this.lastUpdated=0,this.lastRefreshFailedAt=0,this.storage)try{this.storage.removeItem(this.storageKey)}catch{}this.removeSuffixFromIndex(this.currentSuffix),this.notify()}clearAll(){if(this.all=[],this.lastUpdated=0,this.lastRefreshFailedAt=0,this.currentSuffix=re,this.storage){let e=this.readIndex();for(let t of e)try{this.storage.removeItem(`${this.storageKeyPrefix}:${t}`)}catch{}try{this.storage.removeItem(`${this.storageKeyPrefix}:${re}`)}catch{}try{this.storage.removeItem(this.indexKey)}catch{}}this.notify()}subscribe(e){this.listeners.add(e);let t=!1;return()=>{t||(t=!0,this.listeners.delete(e))}}hydrate(){if(this.storage)try{let e=this.storage.getItem(this.storageKey);if(!e)return;let t=JSON.parse(e);t&&t.v===1&&Array.isArray(t.entitlements)&&(this.all=t.entitlements,this.lastUpdated=typeof t.lastUpdated=="number"?t.lastUpdated:0)}catch{}}persist(){if(this.storage)try{let e={v:1,entitlements:this.all,lastUpdated:this.lastUpdated};this.storage.setItem(this.storageKey,JSON.stringify(e))}catch{}}readIndex(){if(!this.storage)return[];try{let e=this.storage.getItem(this.indexKey);if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t.filter(s=>typeof s=="string"):[]}catch{return[]}}recordSuffixInIndex(e){if(!this.storage)return;let t=this.readIndex();if(!t.includes(e)){t.push(e);try{this.storage.setItem(this.indexKey,JSON.stringify(t))}catch{}}}removeSuffixFromIndex(e){if(!this.storage)return;let t=this.readIndex(),s=t.filter(n=>n!==e);if(s.length!==t.length)try{s.length===0?this.storage.removeItem(this.indexKey):this.storage.setItem(this.indexKey,JSON.stringify(s))}catch{}}notify(){if(this.listeners.size===0)return;let e=this.all.slice(),t=[...this.listeners];for(let s of t)try{s(e)}catch{this.listenerErrorCount+=1}}};function $t(r){return[r.slice(0,8),r.slice(8,12),r.slice(12,16),r.slice(16,20),r.slice(20,32)].join("-")}function N(r){let e;if(r.rail==="apple"?e=r.signedTransactionInfo??"":r.rail==="google"?e=r.purchaseToken??"":e="",!e)throw new Error(`deriveIdempotencyKeyForPurchase: no stable identifier in body (rail=${r.rail}). Apple needs signedTransactionInfo; Google needs purchaseToken.`);let t=`crossdeck:purchases/sync:${r.rail}:${e}`;return $t(q(t))}function Kt(r,e,t={},s=Math.random){let n=t.baseMs??1e3,i=t.maxMs??6e4,o=t.factor??2,a=Math.min(r,30),d=Math.min(i,n*Math.pow(o,a))*s();if(e!==void 0){let u=Math.min(864e5,e);if(u>d)return u}return Math.max(0,Math.round(d))}var se=class{constructor(e={}){this.options=e;this.attempts=0}get consecutiveFailures(){return this.attempts}get isWarning(){return this.attempts>=(this.options.failuresBeforeWarn??8)}nextDelay(e,t=Math.random){let s=Kt(this.attempts,e,this.options,t);return this.attempts+=1,s}recordSuccess(){this.attempts=0}};var M=1e3,ne=class{constructor(e){this.cfg=e;this.buffer=[];this.pendingBatch=null;this.pendingBatchId=null;this.dropped=0;this.inFlight=0;this.lastFlushAt=0;this.lastError=null;this.cancelTimer=null;this.firstFlushFired=!1;this.nextRetryAt=null;this.parked=!1;this.parkWarned=!1;if(this.retry=new se(e.retry??{}),this.persistent=e.persistentStore??null,this.persistent){let t=this.persistent.load();t.length>0&&(t.length>M?(this.dropped+=t.length-M,this.buffer=t.slice(t.length-M)):this.buffer=t,this.cfg.onBufferChange?.(this.buffer.length),this.scheduleIdleFlush())}}enqueue(e){if(this.buffer.push(e),this.buffer.length>M){let t=this.buffer.length-M;this.buffer.splice(0,t),this.dropped+=t,this.cfg.onDrop?.(t)}this.cfg.onBufferChange?.(this.buffer.length),this.persistAll(),this.buffer.length>=this.cfg.batchSize?this.flush():this.scheduleIdleFlush()}async flush(e={}){if(this.parked)return null;let t,s;if(this.pendingBatch!==null&&this.pendingBatchId!==null)t=this.pendingBatch,s=this.pendingBatchId;else{if(this.buffer.length===0)return null;t=this.buffer.splice(0),s=this.mintBatchId(),this.pendingBatch=t,this.pendingBatchId=s,this.inFlight+=t.length,this.cfg.onBufferChange?.(this.buffer.length),this.persistAll()}this.cancelTimerIfSet(),this.nextRetryAt=null;try{let n=this.cfg.envelope(),i=await this.cfg.http.request("POST","/events",{body:{envelopeVersion:1,appId:n.appId,environment:n.environment,sdk:n.sdk,events:t},keepalive:e.keepalive===!0,idempotencyKey:s});return this.lastFlushAt=Date.now(),this.lastError=null,this.inFlight-=t.length,this.pendingBatch=null,this.pendingBatchId=null,this.retry.recordSuccess(),this.persistAll(),this.firstFlushFired||(this.firstFlushFired=!0,this.cfg.onFirstFlushSuccess?.()),i}catch(n){let i=n instanceof Error?n.message:String(n);if(this.lastError=i,jt(n)){if(this.parked=!0,this.buffer=[...t,...this.buffer],this.buffer.length>M){let d=this.buffer.length-M;this.buffer.splice(0,d),this.dropped+=d}this.pendingBatch=null,this.pendingBatchId=null,this.inFlight-=t.length,this.persistAll(),this.cfg.onBufferChange?.(this.buffer.length);let c=Wt(n);return this.parkWarned||(this.parkWarned=!0,console.warn(`[Crossdeck] SDK outdated \u2014 the server is no longer accepting this version's event format. Your events are PARKED on-device (held, not lost) and will deliver automatically once you update @cross-deck/web${c?` to >= ${c}`:""} and redeploy.`)),this.cfg.onParked?.({minVersion:c,surface:Gt(n)}),null}if(Ht(n)){let c=t.length;return this.pendingBatch=null,this.pendingBatchId=null,this.inFlight-=c,this.dropped+=c,this.persistAll(),this.cfg.onDrop?.(c),this.cfg.onPermanentFailure?.({status:n.status??0,droppedCount:c,lastError:i}),null}let o=Bt(n),a=this.retry.nextDelay(o);return this.scheduleRetry(a),this.cfg.onRetryScheduled?.({delayMs:a,consecutiveFailures:this.retry.consecutiveFailures,retryAfterMs:o,lastError:i}),null}}reset(){this.cancelTimerIfSet(),this.nextRetryAt=null,this.buffer=[],this.pendingBatch=null,this.pendingBatchId=null,this.dropped=0,this.inFlight=0,this.lastError=null,this.retry.recordSuccess(),this.persistent?.clear(),this.cfg.onBufferChange?.(0)}getStats(){return{buffered:this.buffer.length,dropped:this.dropped,inFlight:this.inFlight,lastFlushAt:this.lastFlushAt,lastError:this.lastError,consecutiveFailures:this.retry.consecutiveFailures,nextRetryAt:this.nextRetryAt}}get pendingIdempotencyKey(){return this.pendingBatchId}persistAll(){if(this.persistent){if(this.pendingBatch===null){this.persistent.save(this.buffer);return}this.persistent.save([...this.pendingBatch,...this.buffer])}}scheduleIdleFlush(){this.cancelTimerIfSet();let e=this.cfg.scheduler??qe;this.cancelTimer=e(()=>{this.flush()},this.cfg.intervalMs)}scheduleRetry(e){this.cancelTimerIfSet(),this.nextRetryAt=Date.now()+e;let t=this.cfg.scheduler??qe;this.cancelTimer=t(()=>{this.flush()},e)}cancelTimerIfSet(){this.cancelTimer&&(this.cancelTimer(),this.cancelTimer=null)}mintBatchId(){return`batch_${Date.now().toString(36)}${O(10)}`}};function Bt(r){if(r&&typeof r=="object"&&"retryAfterMs"in r){let e=r.retryAfterMs;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}}function Ht(r){if(!r||typeof r!="object")return!1;let e=r.status;return!(typeof e!="number"||!Number.isFinite(e)||e<400||e>=500||e===408||e===429||e===426)}function jt(r){return!r||typeof r!="object"?!1:r.status===426?!0:r.code==="sdk_version_unsupported"}function Wt(r){let e=r?.minVersion;return typeof e=="string"&&e.length>0?e:void 0}function Gt(r){let e=r?.surface;return typeof e=="string"&&e.length>0?e:void 0}function qe(r,e){let t=setTimeout(r,e);if(typeof t.unref=="function")try{t.unref()}catch{}return()=>clearTimeout(t)}var ie=class{constructor(e){this.options=e;this.writeScheduled=!1;this.pendingSnapshot=null;this.key=`${e.prefix}queue.v1`}load(){let e;try{e=this.options.storage.getItem(this.key)}catch{return[]}if(!e)return[];try{let t=JSON.parse(e);return!t||t.version!==1||!Array.isArray(t.events)?[]:t.events}catch{return[]}}save(e){this.pendingSnapshot=e.slice(),!this.writeScheduled&&(this.writeScheduled=!0,queueMicrotask(()=>this.flushWrite()))}saveSync(e){this.pendingSnapshot=e.slice(),this.flushWrite()}clear(){this.pendingSnapshot=null,this.writeScheduled=!1;try{this.options.storage.removeItem(this.key)}catch{}}flushWrite(){this.writeScheduled=!1;let e=this.pendingSnapshot;if(this.pendingSnapshot=null,e===null)return;if(e.length===0){try{this.options.storage.removeItem(this.key)}catch{}return}let t={version:1,events:e};try{this.options.storage.setItem(this.key,JSON.stringify(t))}catch{}}};var F=class{constructor(){this.store=new Map}getItem(e){return this.store.get(e)??null}setItem(e,t){this.store.set(e,t)}removeItem(e){this.store.delete(e)}},ae=class{constructor(e){this.maxAgeSec=e?.maxAgeSec??63072e3,this.secure=e?.secure??Xt(),this.sameSite=e?.sameSite??"Lax",this.domain=e?.domain||void 0}getItem(e){if(!oe())return null;let t=globalThis.document,s=t.cookie?t.cookie.split(/;\s*/):[],n=encodeURIComponent(e)+"=";for(let i of s)if(i.startsWith(n))try{return decodeURIComponent(i.slice(n.length))}catch{return null}return null}setItem(e,t){if(!oe())return;let s=globalThis.document,n=[`${encodeURIComponent(e)}=${encodeURIComponent(t)}`,"Path=/",`Max-Age=${this.maxAgeSec}`,`SameSite=${this.sameSite}`];this.domain&&n.push(`Domain=${this.domain}`),this.secure&&n.push("Secure");try{s.cookie=n.join("; ")}catch{}}removeItem(e){if(!oe())return;let t=globalThis.document,s=[`${encodeURIComponent(e)}=`,"Path=/","Max-Age=0",`SameSite=${this.sameSite}`];this.domain&&s.push(`Domain=${this.domain}`),this.secure&&s.push("Secure");try{t.cookie=s.join("; ")}catch{}}};function $e(r){if(r===void 0||r==="none"||r==="")return;if(r!=="auto"){let i=r.trim().toLowerCase();return i.startsWith(".")?i:`.${i}`}if(!oe())return;let e=globalThis.document,s=(globalThis.location?.hostname??"").toLowerCase();if(!s||s==="localhost"||/^\d{1,3}(\.\d{1,3}){3}$/.test(s)||s.indexOf(".")===-1)return;let n=s.split(".");for(let i=n.length-2;i>=0;i--){let o="."+n.slice(i).join("."),a="__cd_domain_probe";try{e.cookie=`${a}=1; Domain=${o}; Path=/; SameSite=Lax`;let c=e.cookie.indexOf(`${a}=1`)!==-1;if(e.cookie=`${a}=; Domain=${o}; Path=/; Max-Age=0; SameSite=Lax`,c)return o}catch{return}}}function Ke(){try{let r=globalThis.localStorage;if(r){let e="__crossdeck_probe__";return r.setItem(e,"1"),r.removeItem(e),r}}catch{}return new F}function Xt(){try{return globalThis.location?.protocol==="https:"}catch{return!1}}function oe(){return typeof globalThis.document<"u"}var zt="__crossdeckBucketsBridge__";function ve(r){try{let e=globalThis[zt];typeof e=="function"&&e(r)}catch{}}function Jt(){return typeof globalThis.window<"u"&&typeof globalThis.document<"u"&&typeof globalThis.navigator<"u"}function Be(r){let e={};if(r?.appVersion&&(e.appVersion=r.appVersion),!Jt())return e;let t=globalThis.window,s=globalThis.navigator,n=globalThis.document;try{typeof s.language=="string"&&(e.locale=s.language)}catch{}try{e.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{}try{t.screen&&(e.screenWidth=t.screen.width,e.screenHeight=t.screen.height),e.viewportWidth=t.innerWidth,e.viewportHeight=t.innerHeight,e.devicePixelRatio=t.devicePixelRatio}catch{}try{let i=s.userAgent??"",o=Yt(i);Object.assign(e,o)}catch{}try{let i=s.userAgentData;if(i?.platform&&!e.os&&(e.os=i.platform),i?.brands&&!e.browser){let o=i.brands.find(a=>!/Not[ .;A]*Brand/i.test(a.brand)&&!/Chromium/i.test(a.brand));o&&(e.browser=o.brand,e.browserVersion=o.version)}}catch{}return e}function Yt(r){let e={};if(/iPad|iPhone|iPod/.test(r)){e.os="iOS";let t=r.match(/OS (\d+[._]\d+(?:[._]\d+)?)/);t?.[1]&&(e.osVersion=t[1].replace(/_/g,"."))}else if(/Android/.test(r)){e.os="Android";let t=r.match(/Android (\d+(?:\.\d+)*)/);t?.[1]&&(e.osVersion=t[1])}else if(/Windows/.test(r)){e.os="Windows";let t=r.match(/Windows NT (\d+\.\d+)/);t?.[1]&&(e.osVersion=t[1])}else if(/Mac OS X|Macintosh/.test(r)){e.os="macOS";let t=r.match(/Mac OS X (\d+[._]\d+(?:[._]\d+)?)/);t?.[1]&&(e.osVersion=t[1].replace(/_/g,"."))}else/Linux/.test(r)&&(e.os="Linux");return/Edg\/(\d+(?:\.\d+)*)/.test(r)?(e.browser="Edge",e.browserVersion=r.match(/Edg\/(\d+(?:\.\d+)*)/)?.[1]):/Firefox\/(\d+(?:\.\d+)*)/.test(r)?(e.browser="Firefox",e.browserVersion=r.match(/Firefox\/(\d+(?:\.\d+)*)/)?.[1]):/OPR\/(\d+(?:\.\d+)*)/.test(r)?(e.browser="Opera",e.browserVersion=r.match(/OPR\/(\d+(?:\.\d+)*)/)?.[1]):/Chrome\/(\d+(?:\.\d+)*)/.test(r)?(e.browser="Chrome",e.browserVersion=r.match(/Chrome\/(\d+(?:\.\d+)*)/)?.[1]):/Version\/(\d+(?:\.\d+)*).*Safari/.test(r)&&(e.browser="Safari",e.browserVersion=r.match(/Version\/(\d+(?:\.\d+)*)/)?.[1]),e}var L={sessions:!0,pageViews:!0,deviceInfo:!0,clicks:!0,webVitals:!0,errors:!0},we=1800*1e3,Qt="crossdeck:session",Zt=5e3,j={utm_source:"",utm_medium:"",utm_campaign:"",utm_content:"",utm_term:"",referrer:"",gclid:"",fbclid:"",msclkid:"",ttclid:"",li_fat_id:"",twclid:""},W=class{constructor(e,t,s){this.cfg=e;this.track=t;this.session=null;this.cleanups=[];this.lastPersistAt=0;this._sessionSeq=0;this.pageviewId=null;this.storage=s?.storage??null,this.sessionKey=s?.storageKey??Qt,this.cookieStorage=s?.cookieStorage??null}install(){je()&&(this.cfg.sessions&&this.installSessionTracking(),this.cfg.pageViews&&this.installPageViewTracking(),this.cfg.clicks&&this.installClickTracking())}uninstall(){for(;this.cleanups.length;){let e=this.cleanups.pop();try{e?.()}catch{}}this.session&&!this.session.endedSent&&this.emitSessionEnd(),this.clearStoredSession(),this.session=null}resetSession(){this.session&&!this.session.endedSent&&this.emitSessionEnd(),this.pageviewId=null,this.session=this.startNewSession(),this.persistSession(),this.emitSessionStart()}markActivity(){if(!this.session)return;let e=Date.now();if(e-this.session.lastActivityAt>=we){this.pageviewId=null,this.session=this.startNewSession(),this.persistSession(),this.emitSessionStart();return}this.session.lastActivityAt=e,e-this.lastPersistAt>=Zt&&this.persistSession()}get currentSessionId(){return this.session?.sessionId??null}get currentPageviewId(){return this.pageviewId}get currentAcquisition(){return this.session?.acquisition??j}nextSeq(){let e=this._sessionSeq;return this._sessionSeq+=1,e}installSessionTracking(){let e=Date.now(),t=this.readStoredSession();t&&e-t.lastActivityAt<we?(this.session={sessionId:t.id,startedAt:t.startedAt,lastActivityAt:e,hiddenAt:null,endedSent:!1,acquisition:t.acquisition},this.persistSession()):(this.session=this.startNewSession(),this.persistSession(),this.emitSessionStart());let s=()=>{try{if(!this.session)return;let a=globalThis.document;a.visibilityState==="hidden"?(this.session.hiddenAt=Date.now(),this.persistSession()):a.visibilityState==="visible"&&(Date.now()-this.session.lastActivityAt>=we?(this.pageviewId=null,this.session=this.startNewSession(),this.persistSession(),this.emitSessionStart()):this.session.hiddenAt=null)}catch{}},n=()=>{try{this.persistSession()}catch{}},i=globalThis.window,o=globalThis.document;o.addEventListener("visibilitychange",s),i.addEventListener("pagehide",n),i.addEventListener("beforeunload",n),this.cleanups.push(()=>{o.removeEventListener("visibilitychange",s),i.removeEventListener("pagehide",n),i.removeEventListener("beforeunload",n)})}startNewSession(){let e=Date.now();return this._sessionSeq=0,{sessionId:hr(),startedAt:e,lastActivityAt:e,hiddenAt:null,endedSent:!1,acquisition:this.resolveAcquisition()}}resolveAcquisition(){let e=mr();if(!this.storage&&!this.cookieStorage)return e;let t=`${this.sessionKey}_origin_first`,s=()=>{try{let o=this.storage?.getItem(t);if(o)return o}catch{}try{return this.cookieStorage?.getItem(t)??null}catch{return null}},n=o=>{try{this.storage?.setItem(t,o)}catch{}try{this.cookieStorage?.setItem(t,o)}catch{}},i=o=>!!(o.utm_source||o.utm_medium||o.utm_campaign||o.utm_content||o.utm_term||o.gclid||o.fbclid||o.msclkid||o.ttclid||o.li_fat_id||o.twclid);try{if(i(e))return s()===null&&n(JSON.stringify(e)),e;let o=s();if(o){let a=JSON.parse(o);return{...j,...a,referrer:e.referrer}}}catch{}return e}readStoredSession(){if(!this.storage)return null;try{let e=this.storage.getItem(this.sessionKey);if(!e)return null;let t=JSON.parse(e);return!t||typeof t.id!="string"||typeof t.startedAt!="number"||typeof t.lastActivityAt!="number"?null:{id:t.id,startedAt:t.startedAt,lastActivityAt:t.lastActivityAt,acquisition:t.acquisition&&typeof t.acquisition=="object"?t.acquisition:j}}catch{return null}}persistSession(){if(!(!this.storage||!this.session)){this.lastPersistAt=Date.now();try{let e={id:this.session.sessionId,startedAt:this.session.startedAt,lastActivityAt:this.session.lastActivityAt,acquisition:this.session.acquisition};this.storage.setItem(this.sessionKey,JSON.stringify(e))}catch{}}}clearStoredSession(){if(this.storage)try{this.storage.removeItem(this.sessionKey)}catch{}}emitSessionStart(){this.session&&this.track("session.started",{sessionId:this.session.sessionId})}emitSessionEnd(){if(!this.session||this.session.endedSent)return;let e=Date.now()-this.session.startedAt;this.track("session.ended",{sessionId:this.session.sessionId,durationMs:e}),this.session.endedSent=!0}installPageViewTracking(){let e=globalThis.window,t=globalThis.document,s=0,n="",i=250,o=(h=!1)=>{let f=e.location,y=f.href,b=Date.now();!h&&y===n&&b-s<i||(s=b,n=y,this.pageviewId=`pv_${Date.now().toString(36)}${O(10)}`,this.track("page.viewed",{pageviewId:this.pageviewId,path:f.pathname,url:y,search:f.search||void 0,hash:f.hash||void 0,title:t.title,referrer:t.referrer||void 0}))};o();let a=e.history.pushState,c=e.history.replaceState;function d(h,f,y){a.apply(this,[h,f,y]),queueMicrotask(o)}function l(h,f,y){c.apply(this,[h,f,y]),queueMicrotask(o)}e.history.pushState=d,e.history.replaceState=l;let u=()=>o(!0);e.addEventListener("popstate",u),this.cleanups.push(()=>{e.history.pushState===d&&(e.history.pushState=a),e.history.replaceState===l&&(e.history.replaceState=c),e.removeEventListener("popstate",u)})}installClickTracking(){let e=globalThis.window,t=globalThis.document,s=0,n=null,i=100,o=64,a=c=>{let d=c.target;if(!d||!(d instanceof Element))return;let l=Date.now();if(d===n&&l-s<i)return;s=l,n=d;let h=er(d)||d;if(tr(h)||rr(h)||sr(h))return;let f=h.tagName.toLowerCase(),y=ur(lr(h),o),b=h.href||void 0,g=h.target||void 0,v=h.id||void 0,S=h.getAttribute("role")||void 0,I=h.getAttribute("aria-label")||void 0,x=fr(h),p=pr(h),w=f==="a"&&!!b,T=h.getAttribute("data-cd-event"),C={selector:x,tag:f,text:y,elementId:v,role:S,ariaLabel:I,href:b,isLink:w,linkTarget:g,viewportX:c.clientX,viewportY:c.clientY,pageX:c.pageX,pageY:c.pageY,...p};for(let D of Object.keys(C))(C[D]===void 0||C[D]===null||C[D]==="")&&delete C[D];this.track(T||"element.clicked",C)};t.addEventListener("click",a,{capture:!0,passive:!0}),this.cleanups.push(()=>{t.removeEventListener("click",a,{capture:!0})})}};function er(r){return r.closest("[data-cd-event]")||r.closest("[data-cd-noTrack]")||r.closest("button, a, [role='button'], [role='link'], input[type='button'], input[type='submit']")||null}function tr(r){if(!(r instanceof HTMLElement))return!1;let e=r.tagName.toLowerCase();if(e==="textarea"||e==="select")return!0;if(e==="input"){let t=(r.type||"").toLowerCase();return t!=="button"&&t!=="submit"&&t!=="image"&&t!=="reset"}return!1}function rr(r){return!!r.closest("[data-cd-noTrack], [data-cd-no-track], .cd-noTrack, .cd-no-track")}function sr(r){return!!r.closest('input[type="password"]')}var nr=new Set(["span","b","strong","em","i","small","mark","u","label","abbr","time","bdi","cite","code","kbd","q","sub","sup"]),ir=new Set(["svg","style","script","noscript"]),or="a[href], button, input, select, textarea, [role='button'], [role='link'], h1, h2, h3, h4, h5, h6",ar="h1, h2, h3, h4, h5, h6";function He(r){return r.replace(/\s+/g," ").trim()}function _e(r){let e="",t=s=>{let n=s.childNodes;for(let i=0;i<n.length;i++){let o=n[i];if(o){if(o.nodeType===3)e+=o.textContent||"";else if(o.nodeType===1){if(ir.has(o.tagName.toLowerCase()))continue;e+=" ",t(o),e+=" "}}}};return t(r),He(e)}function cr(r){let e="",t=r.childNodes;for(let s=0;s<t.length;s++){let n=t[s];n&&(n.nodeType===3?e+=" "+(n.textContent||""):n.nodeType===1&&nr.has(n.tagName.toLowerCase())&&(e+=" "+_e(n)))}return He(e)}function dr(r){if(!(r.querySelector(or)!==null))return _e(r);let t=cr(r);if(t)return t;let s=r.querySelector(ar);if(s){let n=_e(s);if(n)return n}return""}function lr(r){let e=d=>d.replace(/\s+/g," ").trim(),t=r.getAttribute("data-cd-track")||r.getAttribute("data-track")||r.getAttribute("data-testid");if(t){let d=e(t);if(d)return d}let s=r.getAttribute("aria-label");if(s){let d=e(s);if(d)return d}let n=r.getAttribute("aria-labelledby");if(n&&typeof r.ownerDocument?.getElementById=="function"){let d=[];for(let l of n.split(/\s+/)){let u=r.ownerDocument.getElementById(l),h=u?.textContent?e(u.textContent):"";h&&d.push(h)}if(d.length>0)return d.join(" ")}if(r instanceof HTMLInputElement&&r.value){let d=e(r.value);if(d)return d}let i=dr(r);if(i)return i;let o=r.getAttribute("title");if(o){let d=e(o);if(d)return d}let a=r.querySelector("img[alt]");if(a){let d=a.getAttribute("alt")??"",l=e(d);if(l)return l}let c=r.querySelector("svg title");if(c?.textContent){let d=e(c.textContent);if(d)return d}return""}function ur(r,e){return r.length<=e?r:r.slice(0,e-1)+"\u2026"}function fr(r){let e=[],t=r,s=0;for(;t&&t.nodeName.toLowerCase()!=="body"&&s<5;){let n=t.nodeName.toLowerCase();if(t.id){e.unshift(`${n}#${t.id}`);break}if(t.classList.length>0){let i=Array.from(t.classList).filter(o=>!o.startsWith("cd-")).slice(0,2).join(".");i&&(n+=`.${i}`)}e.unshift(n),t=t.parentElement,s++}return e.join(" > ")}function pr(r){let e={};if(!(r instanceof HTMLElement))return e;for(let t of r.getAttributeNames()){if(!t.startsWith("data-")||t==="data-cd-noTrack"||t==="data-cd-no-track"||t==="data-cd-event")continue;let s=r.getAttribute(t)||"",n=t.replace(/^data-cd-prop-/,"").replace(/^data-/,"");e[n]=s}return e}function je(){return typeof globalThis.window<"u"&&typeof globalThis.document<"u"}function hr(){return`sess_${Date.now().toString(36)}${O(10)}`}function mr(){if(!je())return{...j};let r={...j};try{let e=globalThis.window,t=new URLSearchParams(e.location.search??"");r.utm_source=t.get("utm_source")??"",r.utm_medium=t.get("utm_medium")??"",r.utm_campaign=t.get("utm_campaign")??"",r.utm_content=t.get("utm_content")??"",r.utm_term=t.get("utm_term")??"",r.gclid=t.get("gclid")??"",r.fbclid=t.get("fbclid")??"",r.msclkid=t.get("msclkid")??"",r.ttclid=t.get("ttclid")??"",r.li_fat_id=t.get("li_fat_id")??"",r.twclid=t.get("twclid")??""}catch{}try{let e=globalThis.document;typeof e.referrer=="string"&&(r.referrer=e.referrer)}catch{}return r}var gr=[/^email$/i,/^password$/i,/^token$/i,/^secret$/i,/^card$/i,/^phone$/i,/password/i,/credit_?card/i];function We(r){if(!r)return[];let e=[];for(let t of Object.keys(r))gr.some(s=>s.test(t))&&e.push(t);return e}var ce=class{constructor(){this.enabled=!1;this.seen=new Set}emit(e,t,s){if(!this.enabled)return;if(yr.has(e)){if(this.seen.has(e))return;this.seen.add(e)}let n=s?` ${kr(s)}`:"";console.info(`[crossdeck:${e}] ${t}${n}`)}},yr=new Set(["sdk.configured","sdk.first_event_sent","sdk.environment_mismatch"]);function kr(r){try{return JSON.stringify(r)}catch{return"[unserialisable context]"}}function G(r,e={}){let t=[];if(!r)return{properties:{},warnings:t};let s=e.maxStringLength??1024,n=e.maxBatchPropertyBytes??8192,i=e.maxDepth??5,o=new Set,a=(l,u,h)=>{if(h>i)return t.push({kind:"depth_exceeded",key:u}),{keep:!0,value:"[depth-exceeded]"};if(l===null)return{keep:!0,value:null};let f=typeof l;if(f==="string"){let y=l;return y.length>s?(t.push({kind:"truncated_string",key:u}),{keep:!0,value:y.slice(0,s-1)+"\u2026"}):{keep:!0,value:y}}if(f==="number")return Number.isFinite(l)?{keep:!0,value:l}:(t.push({kind:"non_serialisable",key:u}),{keep:!0,value:null});if(f==="boolean")return{keep:!0,value:l};if(f==="bigint")return t.push({kind:"coerced_bigint",key:u}),{keep:!0,value:l.toString()};if(f==="function")return t.push({kind:"dropped_function",key:u}),{keep:!1,value:void 0};if(f==="symbol")return t.push({kind:"dropped_symbol",key:u}),{keep:!1,value:void 0};if(f==="undefined")return t.push({kind:"dropped_undefined",key:u}),{keep:!1,value:void 0};if(l instanceof Date)return t.push({kind:"coerced_date",key:u}),{keep:!0,value:Number.isFinite(l.getTime())?l.toISOString():null};if(l instanceof Error)return t.push({kind:"coerced_error",key:u}),{keep:!0,value:{name:l.name,message:l.message,stack:typeof l.stack=="string"?l.stack.slice(0,s):void 0}};if(l instanceof Map){t.push({kind:"coerced_map",key:u});let y={};for(let[b,g]of l.entries()){let v=typeof b=="string"?b:String(b),S=a(g,`${u}.${v}`,h+1);S.keep&&(y[v]=S.value)}return{keep:!0,value:y}}if(l instanceof Set){t.push({kind:"coerced_set",key:u});let y=[],b=0;for(let g of l.values()){let v=a(g,`${u}[${b}]`,h+1);v.keep&&y.push(v.value),b++}return{keep:!0,value:y}}if(Array.isArray(l)){if(o.has(l))return t.push({kind:"circular_reference",key:u}),{keep:!0,value:"[circular]"};o.add(l);let y=[];for(let b=0;b<l.length;b++){let g=a(l[b],`${u}[${b}]`,h+1);g.keep&&y.push(g.value)}return o.delete(l),{keep:!0,value:y}}if(f==="object"){let y=l;if(o.has(y))return t.push({kind:"circular_reference",key:u}),{keep:!0,value:"[circular]"};o.add(y);let b={};for(let g of Object.keys(y)){let v=a(y[g],`${u}.${g}`,h+1);v.keep&&(b[g]=v.value)}return o.delete(y),{keep:!0,value:b}}t.push({kind:"non_serialisable",key:u});try{return{keep:!0,value:String(l)}}catch{return{keep:!1,value:void 0}}},c={};for(let l of Object.keys(r)){let u=a(r[l],l,0);u.keep&&(c[l]=u.value)}let d=Ge(c);if(d&&Se(d)>n){t.push({kind:"size_cap_exceeded",key:"*"});let l=Object.keys(c).map(h=>({k:h,size:Se(Ge(c[h])??"")})).sort((h,f)=>f.size-h.size),u=Se(d);for(let{k:h}of l){if(u<=n)break;u-=l.find(f=>f.k===h).size,delete c[h]}c.__truncated=!0}return{properties:c,warnings:t}}function Ge(r){try{return JSON.stringify(r)??null}catch{return null}}function Se(r){return typeof TextEncoder<"u"?new TextEncoder().encode(r).length:r.length*4}var de="super_props",Te="groups",le=class{constructor(e,t){this.storage=e;this.prefix=t;this.superProps={};this.groups={};this.superProps=Xe(e,t+de)??{},this.groups=Xe(e,t+Te)??{}}register(e){for(let[t,s]of Object.entries(e))s===null?delete this.superProps[t]:s!==void 0&&(this.superProps[t]=s);return Ee(this.storage,this.prefix+de,this.superProps),{...this.superProps}}unregister(e){e in this.superProps&&(delete this.superProps[e],Ee(this.storage,this.prefix+de,this.superProps))}getSuperProperties(){return{...this.superProps}}setGroup(e,t,s){t===null?delete this.groups[e]:this.groups[e]=s!==void 0?{id:t,traits:s}:{id:t},Ee(this.storage,this.prefix+Te,this.groups)}getGroups(){return JSON.parse(JSON.stringify(this.groups))}getGroupIds(){let e={};for(let[t,s]of Object.entries(this.groups))e[t]=s.id;return e}clear(){this.superProps={},this.groups={};try{this.storage.removeItem(this.prefix+de)}catch{}try{this.storage.removeItem(this.prefix+Te)}catch{}}};function Xe(r,e){let t;try{t=r.getItem(e)}catch{return null}if(!t)return null;try{return JSON.parse(t)}catch{return null}}function Ee(r,e,t){try{r.setItem(e,JSON.stringify(t))}catch{}}var ze="$crossdeck_internal",xe="crossdeck.internalOptOut";function Je(){try{return typeof localStorage<"u"?localStorage:null}catch{return null}}function Ye(){try{let r=typeof location<"u"?location.search:"",e=new URLSearchParams(r||"");if(!e.has("crossdeck_internal"))return;let t=Je();if(!t)return;let s=e.get("crossdeck_internal");s==="1"||s==="true"?t.setItem(xe,"1"):(s==="0"||s==="false")&&t.removeItem(xe)}catch{}}function Qe(){try{return Je()?.getItem(xe)==="1"}catch{return!1}}var ue=class{constructor(e,t){this.cfg=e;this.report=t;this.observers=[];this.flushed=new Set;this.cls=0;this.clsEntries=[];this.inp=0;this.cleanups=[]}install(){if(!this.cfg.enabled||typeof PerformanceObserver>"u"||typeof globalThis>"u"||!("document"in globalThis))return;let e=globalThis.document;try{let i=new PerformanceObserver(o=>{for(let a of o.getEntries()){let c=a;c.responseStart>0&&!this.flushed.has("ttfb")&&(this.flushed.add("ttfb"),this.report("webvitals.ttfb",{valueMs:Math.round(c.responseStart-c.startTime)}))}});i.observe({type:"navigation",buffered:!0}),this.observers.push(i)}catch{}try{let i=new PerformanceObserver(o=>{for(let a of o.getEntries())a.name==="first-contentful-paint"&&!this.flushed.has("fcp")&&(this.flushed.add("fcp"),this.report("webvitals.fcp",{valueMs:Math.round(a.startTime)}))});i.observe({type:"paint",buffered:!0}),this.observers.push(i)}catch{}let t=0;try{let i=new PerformanceObserver(o=>{let a=o.getEntries(),c=a[a.length-1];c&&(t=c.startTime)});i.observe({type:"largest-contentful-paint",buffered:!0}),this.observers.push(i)}catch{}try{let i=new PerformanceObserver(o=>{for(let a of o.getEntries()){let c=a;typeof c.value=="number"&&!c.hadRecentInput&&(this.cls+=c.value,this.clsEntries.push(a))}});i.observe({type:"layout-shift",buffered:!0}),this.observers.push(i)}catch{}try{let i=new PerformanceObserver(o=>{for(let a of o.getEntries()){let c=a;c.interactionId&&c.duration>this.inp&&(this.inp=c.duration)}});try{i.observe({type:"event",buffered:!0,durationThreshold:16})}catch{i.observe({type:"first-input",buffered:!0})}this.observers.push(i)}catch{}let s=()=>{try{t>0&&!this.flushed.has("lcp")&&(this.flushed.add("lcp"),this.report("webvitals.lcp",{valueMs:Math.round(t)})),this.cls>0&&!this.flushed.has("cls")&&(this.flushed.add("cls"),this.report("webvitals.cls",{value:Math.round(this.cls*1e3)/1e3})),this.inp>0&&!this.flushed.has("inp")&&(this.flushed.add("inp"),this.report("webvitals.inp",{valueMs:Math.round(this.inp)}))}catch{}},n=()=>{e.visibilityState==="hidden"&&s()};e.addEventListener("visibilitychange",n),globalThis.window.addEventListener("pagehide",s),this.cleanups.push(()=>{e.removeEventListener("visibilitychange",n),globalThis.window.removeEventListener("pagehide",s)})}uninstall(){for(let e of this.observers)try{e.disconnect()}catch{}this.observers=[];for(let e of this.cleanups.splice(0))try{e()}catch{}}};var br={analytics:!0,marketing:!0,errors:!0},fe=class{constructor(e){this.state={...br};this.dntDenied=!1;e?.respectDnt&&this.detectDnt()&&(this.dntDenied=!0,this.state={analytics:!1,marketing:!1,errors:!1})}set(e){if(this.dntDenied)return{...this.state};for(let t of Object.keys(e)){let s=e[t];typeof s=="boolean"&&(this.state[t]=s)}return{...this.state}}get(){return{...this.state}}get analytics(){return this.state.analytics}get marketing(){return this.state.marketing}get errors(){return this.state.errors}get isDntDenied(){return this.dntDenied}detectDnt(){try{let e=globalThis.navigator;return e?[e.doNotTrack,e.msDoNotTrack,globalThis.doNotTrack].some(s=>s==="1"||s==="yes"):!1}catch{return!1}}},vr=/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,wr=/\b\d(?:[ -]?\d){12,18}\b/g,_r="<email>",Sr="<card>";function Tr(r){return r&&r.replace(vr,_r).replace(wr,Sr)}function Ie(r){let e={};for(let t of Object.keys(r))e[t]=Ze(r[t]);return e}function Ze(r){return typeof r=="string"?Tr(r):Array.isArray(r)?r.map(Ze):r&&typeof r=="object"&&r.constructor===Object?Ie(r):r}var pe=class{constructor(e=50){this.maxSize=e;this.items=[]}add(e){this.items.push(e),this.items.length>this.maxSize&&this.items.shift()}snapshot(){return this.items.slice()}clear(){this.items=[]}get size(){return this.items.length}};var Er="https://api.cross-deck.com/v1/events",et="cd_pub_live_eea2f84dbb834a45b7";function xr(){return!et.startsWith("cd_pub_RELIABILITY_PLACEHOLDER")}var Ir=new Set(["contract_id","sdk_version","sdk_platform","failure_reason","run_context","run_id","test_file","test_name","device_class","verification_phase"]);function Cr(r){let e={};for(let[t,s]of Object.entries(r))Ir.has(t)&&typeof s=="string"&&(e[t]=s);return e}function he(r){if(!xr())return;let e=Cr(r);if(Object.keys(e).length===0)return;let t=JSON.stringify({events:[{name:"crossdeck.contract_failed",timestamp:Date.now(),properties:e}]}),s=globalThis.fetch;if(typeof s=="function")try{s(Er,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${et}`,"Crossdeck-Sdk-Version":`${A}@${R}`},body:t,keepalive:!0,credentials:"omit",cache:"no-store",referrerPolicy:"no-referrer"}).catch(()=>{})}catch{}}var Ce=Object.freeze([{code:"invalid_public_key",type:"configuration_error",description:"The publishable key passed to Crossdeck.init() doesn't start with cd_pub_.",resolution:"Copy the key from your Crossdeck dashboard \u2192 API keys page.",retryable:!1},{code:"missing_app_id",type:"configuration_error",description:"Crossdeck.init() was called without an appId.",resolution:"Add appId to your init options \u2014 find it in the dashboard's Apps page.",retryable:!1},{code:"invalid_environment",type:"configuration_error",description:"Crossdeck.init() requires environment: 'production' | 'sandbox'.",resolution:'Pass the literal string "production" or "sandbox" \u2014 no other values are accepted.',retryable:!1},{code:"environment_mismatch",type:"configuration_error",description:"The publishable key's env prefix doesn't match the declared environment option.",resolution:"Either change `environment` to match the key prefix (cd_pub_test_ \u2194 sandbox, cd_pub_live_ \u2194 production), or swap the key for one minted in the right env.",retryable:!1},{code:"not_initialized",type:"configuration_error",description:"An SDK method was called before Crossdeck.init().",resolution:"Call Crossdeck.init({ appId, publicKey, environment }) once at app startup before any other method.",retryable:!1},{code:"missing_user_id",type:"invalid_request_error",description:"identify() was called with an empty userId.",resolution:"Pass a stable, non-empty user identifier from your auth layer \u2014 never a hardcoded placeholder.",retryable:!1},{code:"missing_event_name",type:"invalid_request_error",description:"track() was called without an event name.",resolution:"Pass a non-empty string as the first argument.",retryable:!1},{code:"missing_group_type",type:"invalid_request_error",description:"group() was called without a group type.",resolution:'Pass a non-empty type (e.g. "org", "team") as the first argument.',retryable:!1},{code:"missing_signed_transaction_info",type:"invalid_request_error",description:"syncPurchases() was called without StoreKit 2 signed transaction info.",resolution:"Pass the JWS string from Transaction.currentEntitlements / Transaction.updates.",retryable:!1},{code:"fetch_failed",type:"network_error",description:"The underlying fetch() call failed (typically a network outage or DNS issue).",resolution:"Check the user's network. The SDK will retry automatically with exponential backoff.",retryable:!0},{code:"request_timeout",type:"network_error",description:"A request was aborted after the configured timeoutMs (default 15s).",resolution:"Check the user's connection. Increase timeoutMs in init options if the user is on a known-slow network.",retryable:!0},{code:"invalid_json_response",type:"internal_error",description:"The server returned a 2xx with an unparseable body.",resolution:"Likely a transient backend bug. Retry; if it persists, contact support with the requestId.",retryable:!0},{code:"missing_api_key",type:"authentication_error",description:"No Authorization header (or Crossdeck-Api-Key header) on the request.",resolution:"Make sure Crossdeck.init({ publicKey }) was called with a cd_pub_\u2026 key before the request fired. Re-check your env-vars in CI / Docker if the key is empty at runtime.",retryable:!1},{code:"invalid_api_key",type:"authentication_error",description:"The API key is malformed, unknown, or doesn't resolve to a project.",resolution:"Copy the key from your Crossdeck dashboard \u2192 API keys. Confirm prefix is cd_pub_test_ / cd_pub_live_ for client SDKs and cd_sk_test_ / cd_sk_live_ for the Node server SDK.",retryable:!1},{code:"key_revoked",type:"authentication_error",description:"The API key was revoked in the Crossdeck dashboard.",resolution:"Mint a fresh key in the dashboard \u2192 API keys \u2192 Create new, swap it in, and redeploy. The revoked key cannot be reactivated.",retryable:!1},{code:"identity_token_invalid",type:"authentication_error",description:"The Firebase / Apple / Google ID token supplied with the request didn't verify against the dashboard's configured signers.",resolution:"Refresh the token client-side (Firebase auth.currentUser.getIdToken(true)) and retry. If the failure persists, confirm the signer is registered under dashboard \u2192 Authentication \u2192 Identity sources.",retryable:!0},{code:"origin_not_allowed",type:"permission_error",description:"The Origin header isn't in the project's Allowed origins list.",resolution:"Add the origin (e.g. https://app.example.com) under dashboard \u2192 Settings \u2192 Allowed origins. Wildcards like https://*.example.com are supported.",retryable:!1},{code:"bundle_id_not_allowed",type:"permission_error",description:"The iOS bundle ID sent via X-Crossdeck-Bundle-Id isn't registered under this app's Apple identity lock.",resolution:"Add the bundle ID under dashboard \u2192 Apps \u2192 <your app> \u2192 iOS bundle IDs.",retryable:!1},{code:"package_name_not_allowed",type:"permission_error",description:"The Android package name sent via X-Crossdeck-Package-Name isn't registered under this app's Android identity lock.",resolution:"Add the package name under dashboard \u2192 Apps \u2192 <your app> \u2192 Android package names.",retryable:!1},{code:"env_mismatch",type:"permission_error",description:"The request env (inferred from key prefix) doesn't match the resolved app's configured env.",resolution:"Use a cd_pub_live_ / cd_sk_live_ key with a production app, cd_pub_test_ / cd_sk_test_ with a sandbox app. The two cannot cross.",retryable:!1},{code:"idempotency_key_in_use",type:"invalid_request_error",description:"An Idempotency-Key was reused for a request with a different body (Stripe-grade contract).",resolution:"Generate a fresh key for a different transaction, or reuse the key only with the EXACT same body. The v1.4.0 SDKs derive keys deterministically from the body so this should never fire on SDK-managed calls.",retryable:!1},{code:"rate_limited",type:"rate_limit_error",description:"Request rate exceeded the project's per-second cap.",resolution:"Honour the Retry-After header \u2014 the SDK does this automatically on managed retries. If you're hitting it from a custom code path, throttle to <100 req/s/key.",retryable:!0},{code:"internal_error",type:"internal_error",description:"Server-side issue. Safe to retry with backoff.",resolution:"The SDK retries automatically. If your code paths through to this error, contact support with the requestId from the response envelope.",retryable:!0},{code:"google_not_supported",type:"invalid_request_error",description:"POST /purchases/sync with rail=google is gated until the Play Developer API reconciliation worker ships.",resolution:"Until v1.5+, Google Play purchases verify via Real-time Developer Notifications. The SDK auto-track path handles this transparently for Android consumers.",retryable:!1},{code:"stripe_not_supported",type:"invalid_request_error",description:"POST /purchases/sync with rail=stripe is unsupported \u2014 Stripe Checkout's redirect flow uses platform webhooks instead.",resolution:"Wire Stripe via the standard Checkout / Customer Portal flow; Crossdeck reconciles via the platform webhook automatically. No SDK call needed.",retryable:!1},{code:"missing_required_param",type:"invalid_request_error",description:"A required field is absent from the request body.",resolution:"Inspect the error.message \u2014 the missing field name is included verbatim. Refer to the SDK's TypeScript types for the canonical request shape.",retryable:!1},{code:"invalid_param_value",type:"invalid_request_error",description:"A field is present but the value failed validation (wrong shape, wrong length, wrong enum value).",resolution:"Read error.message for the specific field + reason. SDK-managed call sites should never emit this \u2014 file a bug if you do.",retryable:!1},{code:"sdk_version_unsupported",type:"version_error",description:"HTTP 426 \u2014 your installed SDK sends an event format the server no longer accepts. The data is good; only the wire dialect is too old. The SDK PARKS automatically: events are held on-device (paused, not lost) and deliver on the next launch after you upgrade.",resolution:"Update @cross-deck/web to at least the version in error.minVersion and redeploy \u2014 the parked queue backfills automatically. See https://cross-deck.com/docs/sdk-event-durability/.",retryable:!1}]);function me(r){return Ce.find(e=>e.code===r)}function it(r){return{sdkVersion:`${A}@${R}`,runId:`cd_verify_${Ur(8)}`,runContext:r.runContext??"customer-app",logVerifierResults:r.logVerifierResults,disableContractAssertions:r.disableContractAssertions,console,emitTelemetry:he}}var z=class{constructor(e){this.ctx=e;this.reentrancyDepth=0}report(e,t,s){this.ctx.disableContractAssertions||(e.ok?this.reportPass(e,t,s):this.reportFail(e,t,s))}reportPass(e,t,s){if(!this.ctx.logVerifierResults)return;let n=Rr(e,s);t==="boot"?this.ctx.console.info(n):this.ctx.console.debug(n)}reportFail(e,t,s){if(this.ctx.console.warn(Ar(e,s)),!(this.reentrancyDepth>0)){this.reentrancyDepth+=1;try{this.ctx.emitTelemetry({contract_id:e.contractId,sdk_version:this.ctx.sdkVersion,sdk_platform:"web",failure_reason:Mr(e.failureReason,128),run_context:this.ctx.runContext,run_id:this.ctx.runId,verification_phase:t})}finally{this.reentrancyDepth-=1}}}};function Rr(r,e){return`${e?`[crossdeck.${e}]`:"[crossdeck]"} \u2713 ${r.contractId} \u2014 ${r.evidence} (${r.durationMs}ms)`}function Ar(r,e){return`${e?`[crossdeck.${e}]`:"[crossdeck]"} \u2717 ${r.contractId} \u2014 ${r.failureReason} (${r.durationMs}ms)`}var Pr={contractId:"per-user-cache-isolation",bootTest(){let r=m();try{let e=new ge,t=new P(e,"_verifier");if(t.setUserKey("user_A"),t.setFromList([{object:"entitlement",key:"pro",isActive:!0,validUntil:null,source:{rail:"stripe",productId:"p_verifier",subscriptionId:"s_verifier"},updatedAt:Date.now()}]),t.setUserKey("user_B"),t.list().length!==0)return k("per-user-cache-isolation","in-memory snapshot still carried user_A's entitlements after rotation",m()-r);let n=P.suffixForUserId("user_A"),i=P.suffixForUserId("user_B");if(n===i)return k("per-user-cache-isolation","suffixes for user_A and user_B collided",m()-r);let o=e.getItem(`_verifier:${n}`),a=e.getItem(`_verifier:${i}`);return o?a?k("per-user-cache-isolation","user_B's storage slot already contained data before any write",m()-r):E("per-user-cache-isolation",`slot rotated A:${X(n)} \u2192 B:${X(i)} (isolated, physically separate)`,m()-r):k("per-user-cache-isolation","user_A's storage slot was wiped on rotation (expected isolation, not erasure)",m()-r)}catch(e){return k("per-user-cache-isolation",`boot test threw: ${e.message?.slice(0,80)??"unknown error"}`,m()-r)}},hooks:{onIdentify(r){let e=m(),t=P.suffixForUserId(r.priorUserId),s=P.suffixForUserId(r.nextUserId);return t!==s?r.cache.list().length!==0?k("per-user-cache-isolation","in-memory snapshot still held entitlements after slot rotation",m()-e):E("per-user-cache-isolation",`slot rotated ${X(t)} \u2192 ${X(s)}`,m()-e):E("per-user-cache-isolation",`same-id re-identify (suffix ${X(s)}); cleared + rehydrated per contract`,m()-e)}}},Re="eyJ.jws.sig",tt="a66b1640-efaf-bb4d-1261-6650033bf111",Dr={contractId:"idempotency-key-deterministic",bootTest(){let r=m();try{let e=N({rail:"apple",signedTransactionInfo:Re});if(e!==tt)return k("idempotency-key-deterministic",`canonical apple JWS derived ${e} (expected ${tt})`,m()-r);if(N({rail:"apple",signedTransactionInfo:Re})!==e)return k("idempotency-key-deterministic","same JWS produced different keys on two derivations",m()-r);let s=e,n=N({rail:"google",purchaseToken:Re});return s===n?k("idempotency-key-deterministic","rail namespacing failed \u2014 apple/google identical key",m()-r):E("idempotency-key-deterministic",`apple JWS \u2192 ${e} (canonical vector + determinism + rail isolation)`,m()-r)}catch(e){return k("idempotency-key-deterministic",`boot test threw: ${e.message?.slice(0,80)??"unknown error"}`,m()-r)}},hooks:{onSyncPurchases(r){let e=m();try{return N(r.rail==="apple"?{rail:"apple",signedTransactionInfo:r.stableIdentifier}:{rail:r.rail,purchaseToken:r.stableIdentifier})!==r.derivedKey?k("idempotency-key-deterministic","derived key drifted from canonical algorithm",m()-e):E("idempotency-key-deterministic",`${r.rail} \u2192 ${r.derivedKey}`,m()-e)}catch(t){return k("idempotency-key-deterministic",`hot-path derivation threw: ${t.message?.slice(0,80)??"unknown error"}`,m()-e)}}}},Or={contractId:"error-envelope-shape",bootTest(){let r=m(),e={error:{type:"invalid_request_error",code:"missing_customer",message:"Customer identifier is required.",request_id:"req_test1234"}},t=new Set(["authentication_error","permission_error","invalid_request_error","rate_limit_error","internal_error"]),s=e.error,n=["type","code","message","request_id"].filter(i=>!(i in s)||typeof s[i]!="string");return n.length>0?k("error-envelope-shape",`envelope missing required fields: ${n.join(", ")}`,m()-r):t.has(s.type)?E("error-envelope-shape","{ type, code, message, request_id } parsed and type \u2208 ApiErrorType",m()-r):k("error-envelope-shape",`error.type "${s.type}" not in canonical ApiErrorType set`,m()-r)},hooks:{onErrorParse(r){let e=m();return new Set(["authentication_error","permission_error","invalid_request_error","rate_limit_error","internal_error"]).has(r.errorType)?!r.errorCode||r.errorCode.length===0?k("error-envelope-shape","wire error.code was empty",m()-e):E("error-envelope-shape",`${r.errorType}/${r.errorCode} on ${r.httpStatus}${r.requestId?` (${r.requestId.slice(0,12)}\u2026)`:""}`,m()-e):k("error-envelope-shape",`wire error.type "${r.errorType}" outside canonical ApiErrorType`,m()-e)}}},Vr={contractId:"flush-interval-parity",bootTest(){let r=m();return 2e3!==2e3?k("flush-interval-parity","canonical default drifted from 2000ms",m()-r):E("flush-interval-parity","eventFlushIntervalMs default = 2000ms (Web/Node/RN/Swift/Android parity)",m()-r)}};function ot(r){return{contractId:"flush-interval-parity",bootTest(){let e=m(),t=2e3;return r<100||r>6e4?k("flush-interval-parity",`configured eventFlushIntervalMs=${r} outside reasonable bounds [100, 60000]`,m()-e):r!==t?E("flush-interval-parity",`eventFlushIntervalMs = ${r}ms (override; canonical default is 2000ms)`,m()-e):E("flush-interval-parity","eventFlushIntervalMs = 2000ms (canonical default)",m()-e)}}}var Fr={contractId:"super-property-merge-precedence",bootTest(){let r=m(),n={...{plan:"device_plan",os:"macos"},...{plan:"super_plan",appVersion:"1.0.0"},...{plan:"caller_plan",eventSpecific:!0}};return n.plan!=="caller_plan"?k("super-property-merge-precedence",`merged.plan = "${n.plan}" (expected "caller_plan"; caller must override super and device)`,m()-r):n.appVersion!=="1.0.0"?k("super-property-merge-precedence","super-property appVersion was clobbered by device or caller",m()-r):n.os!=="macos"?k("super-property-merge-precedence","device property os was dropped from merged result",m()-r):E("super-property-merge-precedence","caller > super > device verified (synthetic merge)",m()-r)},hooks:{onTrack(r){let e=m();for(let[t,s]of Object.entries(r.callerProperties))if(r.mergedProperties[t]!==s)return k("super-property-merge-precedence",`caller key "${t}" did not win in merged output`,m()-e);for(let[t,s]of Object.entries(r.superProperties))if(!(t in r.callerProperties)&&r.mergedProperties[t]!==s)return k("super-property-merge-precedence",`super key "${t}" did not win over device in merged output`,m()-e);return E("super-property-merge-precedence",`caller(${Object.keys(r.callerProperties).length}) > super(${Object.keys(r.superProperties).length}) > device verified`,m()-e)}}},Ae=["contract_id","sdk_version","sdk_platform","failure_reason","run_context","run_id"],rt=["test_file","test_name","device_class","verification_phase"],st=["anonymousId","developerUserId","crossdeckCustomerId","email","userId","ip","ipAddress","userAgent","stack","stackTrace","url","referrer","deviceId"],Lr={contractId:"contract-failed-payload-schema-lock",bootTest(){let r=m(),t=Object.keys({contract_id:"synthetic",sdk_version:R,sdk_platform:"web",failure_reason:"synthetic",run_context:"customer-app",run_id:"synthetic-run-id",verification_phase:"boot"}),s=new Set([...Ae,...rt]),n=new Set(st);for(let i of Ae)if(!t.includes(i))return k("contract-failed-payload-schema-lock",`missing required field: ${i}`,m()-r);for(let i of t)if(n.has(i))return k("contract-failed-payload-schema-lock",`forbidden field on wire: ${i}`,m()-r);for(let i of t)if(!s.has(i))return k("contract-failed-payload-schema-lock",`unrecognised field on wire: ${i} (not in required \u222A optional)`,m()-r);return E("contract-failed-payload-schema-lock",`${t.length} fields \u2286 required(${Ae.length}) \u222A optional(${rt.length}); ${st.length} forbidden absent`,m()-r)}},nt=Object.freeze(["missing_api_key","invalid_api_key","key_revoked","identity_token_invalid","origin_not_allowed","bundle_id_not_allowed","package_name_not_allowed","env_mismatch","idempotency_key_in_use","rate_limited","internal_error","google_not_supported","stripe_not_supported","missing_required_param","invalid_param_value","sdk_version_unsupported"]),Nr={contractId:"sdk-error-codes-catalogue",bootTest(){let r=m();try{let e=[];for(let t of nt){let s=me(t);(!s||!s.description||s.description.trim().length===0||!s.resolution||s.resolution.trim().length===0)&&e.push(t)}return e.length>0?k("sdk-error-codes-catalogue",`catalogue missing description+resolution for backend code(s): ${e.join(", ")}`,m()-r):E("sdk-error-codes-catalogue",`all ${nt.length} backend wire codes carry description + resolution`,m()-r)}catch(e){return k("sdk-error-codes-catalogue",`boot test threw: ${e.message?.slice(0,80)??"unknown error"}`,m()-r)}}},at=Object.freeze([Pr,Dr,Or,Vr,Fr,Lr,Nr]);async function Pe(r,e,t){if(t.disableContractAssertions)return{passed:0,failed:0,totalMs:0};let s=m(),n=0,i=0;if(t.logVerifierResults){let a=r.filter(l=>l.bootTest).length,c=r.filter(l=>l.hooks).length,d=r.map(l=>l.contractId).join(", ");t.console.info(`[crossdeck] Contract self-verification \u2014 ${r.length} verifiers (${a} boot-tests, ${c} hot-path hooks): ${d}`)}for(let a of r){if(!a.bootTest)continue;let c;try{c=await a.bootTest()}catch(d){c=k(a.contractId,`bootTest threw: ${d.message?.slice(0,80)??"unknown"}`,0)}e.report(c,"boot"),c.ok?n+=1:i+=1}let o=m()-s;if(t.logVerifierResults){let a=i===0?"passed":"complete";t.console.info(`[crossdeck] Self-verification ${a} \u2014 ${n} passed, ${i} failed (${o}ms)`)}return{passed:n,failed:i,totalMs:o}}function ct(r,e,t,s){if(!t.disableContractAssertions)for(let n of r){let i=n.hooks?.onIdentify;if(!i)continue;let o;try{o=i(s)}catch(a){o=k(n.contractId,`hook threw: ${a.message?.slice(0,80)??"unknown"}`,0)}e.report(o,"hot_path","identify")}}function dt(r,e,t,s){if(!t.disableContractAssertions)for(let n of r){let i=n.hooks?.onTrack;if(!i)continue;let o;try{o=i(s)}catch(a){o=k(n.contractId,`hook threw: ${a.message?.slice(0,80)??"unknown"}`,0)}e.report(o,"hot_path","track")}}function lt(r,e,t,s){if(!t.disableContractAssertions)for(let n of r){let i=n.hooks?.onSyncPurchases;if(!i)continue;let o;try{o=i(s)}catch(a){o=k(n.contractId,`hook threw: ${a.message?.slice(0,80)??"unknown"}`,0)}e.report(o,"hot_path","syncPurchases")}}function ut(r,e,t,s){if(!t.disableContractAssertions)for(let n of r){let i=n.hooks?.onErrorParse;if(!i)continue;let o;try{o=i(s)}catch(a){o=k(n.contractId,`hook threw: ${a.message?.slice(0,80)??"unknown"}`,0)}e.report(o,"hot_path","errorParse")}}function ft(){try{if(typeof process<"u"&&process.env){let e=process.env.NODE_ENV;if(typeof e=="string")return e!=="production"}}catch{}let r=globalThis.__DEV__;return typeof r=="boolean"?r:!1}function E(r,e,t){return{ok:!0,contractId:r,evidence:e,durationMs:t}}function k(r,e,t){return{ok:!1,contractId:r,failureReason:e,durationMs:t}}function m(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}function Mr(r,e){return r.length>e?r.slice(0,e-1)+"\u2026":r}function X(r){let e=r.startsWith("_")?r.slice(1):r;return e.length<=12?e:`${e.slice(0,4)}\u2026${e.slice(-4)}`}function Ur(r){let e=new Uint8Array(Math.ceil(r/2));if(typeof globalThis<"u"&&globalThis.crypto?.getRandomValues)globalThis.crypto.getRandomValues(e);else for(let s=0;s<e.length;s+=1)e[s]=Math.floor(Math.random()*256);let t="";for(let s=0;s<e.length;s+=1)t+=e[s].toString(16).padStart(2,"0");return t.slice(0,r)}var ge=class{constructor(){this.map=new Map}getItem(e){return this.map.get(e)??null}setItem(e,t){this.map.set(e,t)}removeItem(e){this.map.delete(e)}keys(){return Array.from(this.map.keys())}};ge._=q;function Oe(r){if(!r||typeof r!="string")return[];let e=r.split(`
2
+ `),t=[];for(let s of e){let n=s.trim();if(!n)continue;let i=qr(n);i&&t.push(i)}return t}function qr(r){let e=/^at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)$/.exec(r);return e?De({function:e[1],filename:e[2],lineno:parseInt(e[3],10),colno:parseInt(e[4],10),raw:r}):(e=/^at\s+(.+?):(\d+):(\d+)$/.exec(r),e?De({function:"?",filename:e[1],lineno:parseInt(e[2],10),colno:parseInt(e[3],10),raw:r}):(e=/^(.*?)@(.+?):(\d+):(\d+)$/.exec(r),e?De({function:e[1]||"?",filename:e[2],lineno:parseInt(e[3],10),colno:parseInt(e[4],10),raw:r}):/^\w*Error/.test(r)||!r.includes(":")?null:{function:"?",filename:"",lineno:0,colno:0,in_app:!0,raw:r}))}function De(r){return{function:r.function||"?",filename:r.filename,lineno:Number.isFinite(r.lineno)?r.lineno:0,colno:Number.isFinite(r.colno)?r.colno:0,in_app:$r(r.filename),raw:r.raw}}function $r(r){return r?!(/^(?:chrome|moz|safari|webkit)-extension:\/\//.test(r)||/^iabjs:\/\//.test(r)||/^(?:webview|inappbrowser):\/\//i.test(r)||/\bcdn\.jsdelivr\.net\b/.test(r)||/\bunpkg\.com\b/.test(r)||/\bgoogletagmanager\.com\b/.test(r)||/\bgoogle-analytics\.com\b/.test(r)||/\b@cross-deck\/web\b/.test(r)||/\/crossdeck\.umd\.min\.js$/.test(r)):!0}var Kr=/(__firefox__|__gCrWeb|zaloJSV2)/;function ht(r){let e=Kr.exec(r??"");return e?e[1]:null}function Ve(r,e){return ht(e)?r.map(t=>t.in_app?{...t,in_app:!1}:t):r}function $(r,e,t){let s=ht(r);if(s)return pt(`injected-global:${s}`);let n=e.filter(o=>o.in_app).slice(0,3),i=[(r||"").slice(0,200),...n.map(o=>`${o.function}@${o.filename}:${o.lineno}`)];if(n.length===0&&t){let o=[t.errorType??"",t.filename??"",t.lineno??"",t.colno??""].join(":");o!==":::"&&i.push(o)}return pt(i.join("|"))}function pt(r){let e=5381;for(let t=0;t<r.length;t++)e=(e<<5)+e+r.charCodeAt(t)|0;return(e>>>0).toString(16).padStart(8,"0")}var mt={enabled:!0,onError:!0,onUnhandledRejection:!0,wrapFetch:!0,wrapXhr:!0,captureConsole:!1,ignoreErrors:["ResizeObserver loop limit exceeded","ResizeObserver loop completed with undelivered notifications","Non-Error promise rejection captured"],allowUrls:[],denyUrls:[/^chrome-extension:\/\//,/^moz-extension:\/\//,/^safari-extension:\/\//,/^webkit-extension:\/\//,/^safari-web-extension:\/\//],sampleRate:1,maxPerFingerprintPerMinute:5,maxPerSession:100},ye=class{constructor(e){this.opts=e;this.installed=!1;this.cleanups=[];this._reporting=!1;this.sessionCount=0;this.fingerprintWindow=new Map}install(){if(this.installed||!this.opts.config.enabled||typeof globalThis>"u"||!("window"in globalThis))return;let e=globalThis.window;this.opts.config.onError&&this.installOnErrorListener(e),this.opts.config.onUnhandledRejection&&this.installRejectionListener(e),this.opts.config.wrapFetch&&this.installFetchWrap(e),this.opts.config.wrapXhr&&this.installXhrWrap(e),this.opts.config.captureConsole&&this.installConsoleWrap(),this.installed=!0}uninstall(){for(let e of this.cleanups.splice(0))try{e()}catch{}this.installed=!1}captureError(e,t){if(this.opts.isConsented())try{let s=this.buildFromUnknown(e,"error.handled",t?.level??"error");t?.context&&(s.context={...s.context,...t.context}),t?.tags&&(s.tags={...s.tags,...t.tags}),this.maybeReport(s)}catch{}}captureMessage(e,t="info"){if(this.opts.isConsented())try{let s={timestamp:Date.now(),kind:"error.message",level:t,message:e,errorType:null,frames:[],rawStack:null,filename:null,lineno:null,colno:null,fingerprint:$(e,[]),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:this.opts.getContext(),tags:this.opts.getTags()};this.maybeReport(s)}catch{}}installOnErrorListener(e){let t=s=>{if(!this._reporting&&this.opts.isConsented())try{this._reporting=!0;let n=this.buildFromErrorEvent(s);this.maybeReport(n)}catch{}finally{this._reporting=!1}};e.addEventListener("error",t,!0),this.cleanups.push(()=>e.removeEventListener("error",t,!0))}installRejectionListener(e){let t=s=>{if(!this._reporting&&this.opts.isConsented())try{this._reporting=!0;let n=this.buildFromUnknown(s.reason,"error.unhandledrejection","error");this.maybeReport(n)}catch{}finally{this._reporting=!1}};e.addEventListener("unhandledrejection",t),this.cleanups.push(()=>e.removeEventListener("unhandledrejection",t))}installFetchWrap(e){let t=e.fetch?.bind(e);if(!t)return;let s=async(...n)=>{let i=n[0],o=n[1]??{},a=typeof i=="string"?i:i?.url??"",c=(o.method||"GET").toUpperCase(),d=Date.now();Le(a,this.opts.selfHostname)||this.opts.breadcrumbs.add({timestamp:d,category:"http",message:`${c} ${a}`,data:{url:a,method:c}});try{let l=await t(...n);return l.status>=500&&this.opts.isConsented()&&(Le(a,this.opts.selfHostname)||this.captureHttp({url:a,method:c,status:l.status,statusText:l.statusText})),l}catch(l){throw this.opts.isConsented()&&!a.includes("api.cross-deck.com")&&!jr(a,l,e)&&this.captureHttp({url:a,method:c,status:0,statusText:l instanceof Error?l.message:"network error"}),l}};e.fetch=s,this.cleanups.push(()=>{e.fetch===s&&(e.fetch=t)})}installXhrWrap(e){let s=e.XMLHttpRequest?.prototype;if(!s)return;let n=s.open,i=s.send,o=this;s.open=function(a,c,...d){return this._cdMethod=a,this._cdUrl=c,n.apply(this,[a,c,...d])},s.send=function(a){let c=this,d=()=>{try{if(c.status>=500&&o.opts.isConsented()){let l=c._cdUrl??"";Le(l,o.opts.selfHostname)||o.captureHttp({url:l,method:(c._cdMethod??"GET").toUpperCase(),status:c.status,statusText:c.statusText})}}catch{}};return c.addEventListener("loadend",d),i.apply(this,[a??null])},this.cleanups.push(()=>{s.open=n,s.send=i})}installConsoleWrap(){let e=globalThis.console;if(!e)return;let t=e.error.bind(e);e.error=(...s)=>{try{this.opts.isConsented()&&this.captureMessage(s.map(n=>Hr(n)).join(" "),"error")}catch{}return t(...s)},this.cleanups.push(()=>{e.error=t})}buildFromErrorEvent(e){let t=e.error,s=e.filename||null,n=typeof e.lineno=="number"&&e.lineno>0?e.lineno:null,i=typeof e.colno=="number"&&e.colno>0?e.colno:null;if(t==null&&!s&&n==null&&(e.message==="Script error."||e.message==="Script error"||!e.message)){let f="Cross-origin script error (browser hid details \u2014 script needs crossorigin attribute + CORS headers)";return{timestamp:Date.now(),kind:"error.unhandled",level:"error",message:f,errorType:"ScriptError",frames:[],rawStack:null,filename:null,lineno:null,colno:null,fingerprint:$(f,[]),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:this.opts.getContext(),tags:{...this.opts.getTags(),cross_origin:"true"}}}let a=Ne(t),c=(a.message||e.message||"Unknown error").slice(0,1024),d=t instanceof Error?t.stack??null:null,l=Ve(Oe(d),c),u=a.errorType??null,h=a.extras?{...this.opts.getContext(),__error_extras:a.extras}:this.opts.getContext();return{timestamp:Date.now(),kind:"error.unhandled",level:"error",message:c,errorType:u,frames:l,rawStack:d,filename:s,lineno:n,colno:i,fingerprint:$(c,l,{filename:s,lineno:n,colno:i,errorType:u}),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:h,tags:this.opts.getTags()}}buildFromUnknown(e,t,s){let n=Ne(e),i=(n.message||"Unknown error").slice(0,1024),o=e instanceof Error?e.stack??null:null,a=Ve(Oe(o),i),c=n.errorType??null,d=n.extras?{...this.opts.getContext(),__error_extras:n.extras}:this.opts.getContext();return{timestamp:Date.now(),kind:t,level:s,message:i,errorType:c,frames:a,rawStack:o,filename:null,lineno:null,colno:null,fingerprint:$(i,a,{errorType:c}),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:d,tags:this.opts.getTags()}}captureHttp(e){try{let t=`HTTP ${e.status} ${e.method} ${e.url}`,s={timestamp:Date.now(),kind:"error.http",level:"error",message:t,errorType:"HTTPError",frames:[],rawStack:null,filename:e.url,lineno:null,colno:null,fingerprint:$(`HTTP ${e.status} ${e.method}`,[],{filename:e.url,errorType:"HTTPError"}),breadcrumbs:this.opts.breadcrumbs.snapshot(),context:this.opts.getContext(),tags:this.opts.getTags(),http:e};this.maybeReport(s)}catch{}}maybeReport(e){if(this.sessionCount>=this.opts.config.maxPerSession||this.shouldIgnore(e)||!this.passesUrlGate(e)||!this.passesSample(e)||!this.passesRateLimit(e))return;let t=e,s=this.opts.beforeSend?.();if(s){try{t=s(e)}catch{t=e}if(!t)return}this.sessionCount+=1;try{this.opts.report(t)}catch{}}shouldIgnore(e){for(let t of this.opts.config.ignoreErrors)if(typeof t=="string"&&e.message.includes(t)||t instanceof RegExp&&t.test(e.message))return!0;return!1}passesUrlGate(e){let s=(e.frames.find(n=>n.filename)??null)?.filename??e.filename??"";if(!s)return!0;for(let n of this.opts.config.denyUrls)if(typeof n=="string"&&s.includes(n)||n instanceof RegExp&&n.test(s))return!1;if(this.opts.config.allowUrls.length>0){for(let n of this.opts.config.allowUrls)if(typeof n=="string"&&s.includes(n)||n instanceof RegExp&&n.test(s))return!0;return!1}return!0}passesSample(e){return this.opts.config.sampleRate>=1?!0:this.opts.config.sampleRate<=0?!1:parseInt(e.fingerprint.slice(0,2),16)/255<this.opts.config.sampleRate}passesRateLimit(e){let s=Date.now(),n=this.opts.config.maxPerFingerprintPerMinute,o=(this.fingerprintWindow.get(e.fingerprint)??[]).filter(a=>s-a<6e4);return o.length>=n?(this.fingerprintWindow.set(e.fingerprint,o),!1):(o.push(s),this.fingerprintWindow.set(e.fingerprint,o),!0)}};function Ne(r){if(r===null)return{message:"(thrown: null)",errorType:null,extras:null};if(r===void 0)return{message:"(thrown: undefined)",errorType:null,extras:null};if(typeof r=="string")return{message:r,errorType:null,extras:null};if(typeof r=="number"||typeof r=="boolean"||typeof r=="bigint")return{message:String(r),errorType:typeof r,extras:null};if(typeof r=="symbol")return{message:r.toString(),errorType:"symbol",extras:null};if(typeof r=="function")return{message:`(thrown function: ${r.name||"anonymous"})`,errorType:"function",extras:null};if(r instanceof Error){let e=r.name||r.constructor?.name||"Error",t=typeof r.message=="string"&&r.message.length>0?r.message:K(r)||e,s={},n=Br(r);n.length>0&&(s.cause=n);for(let i of["code","status","statusCode","errno","response","data","detail","details"]){let o=r[i];o!==void 0&&typeof o!="function"&&(s[i]=Fe(o))}for(let i of Object.keys(r)){if(i==="message"||i==="stack"||i==="name"||i==="cause"||i in s)continue;let o=r[i];typeof o!="function"&&(s[i]=Fe(o))}return{message:t,errorType:e,extras:Object.keys(s).length>0?s:null}}if(typeof Response<"u"&&r instanceof Response)return{message:`HTTP ${r.status} ${r.statusText||""}${r.url?` ${r.url}`:""}`.trim(),errorType:"Response",extras:{status:r.status,statusText:r.statusText,url:r.url,type:r.type}};if(typeof r=="object"){let e=r,t=e.constructor&&typeof e.constructor=="function"&&e.constructor.name||null,s=typeof e.message=="string"&&e.message?e.message:null,n=typeof e.name=="string"&&e.name?e.name:null,i=null;try{let u=JSON.stringify(e);i=u==="{}"?null:u}catch{i=null}let o=K(e),a=s??i??(o&&o!=="[object Object]"?o:null)??(t?`(thrown ${t} with no message)`:"(thrown object with no message)"),c=n??t??null,d={},l=0;for(let u of Object.keys(e)){if(l>=20)break;if(u==="message"||u==="name")continue;let h=e[u];typeof h!="function"&&(d[u]=Fe(h),l++)}return{message:a,errorType:c,extras:Object.keys(d).length>0?d:null}}return{message:K(r)||"(unstringifiable thrown value)",errorType:null,extras:null}}function Br(r){let e=[],t=r.cause,s=0;for(;t!=null&&s<5;)t instanceof Error?(e.push({name:t.name||"Error",message:t.message||""}),t=t.cause):(e.push({name:"non-Error",message:K(t)}),t=null),s++;return e}function K(r){try{let e=Object.prototype.toString.call(r);if(e!=="[object Object]")return e;let t=r?.toString;if(typeof t=="function"&&t!==Object.prototype.toString){let s=t.call(r);if(typeof s=="string")return s}return e}catch{return"(throwing toString)"}}function Fe(r){if(r==null)return r;let e=typeof r;if(e==="string"||e==="number"||e==="boolean")return r;if(e==="bigint")return String(r);try{let t=JSON.stringify(r);return t===void 0?K(r):JSON.parse(t)}catch{return K(r)}}function Hr(r){return Ne(r).message}function gt(r){if(!r||typeof r!="string")return null;try{return new URL(r).hostname.toLowerCase()}catch{return null}}function Le(r,e){if(!e||!r)return!1;try{return new URL(r).hostname.toLowerCase()===e}catch{return!1}}function jr(r,e,t){if(e instanceof Error&&e.name==="AbortError")return!0;let s=t.navigator;if(s&&s.onLine===!1)return!0;let n=t.location?.href,i=t.location?.origin;if(!i)return!1;try{return new URL(r,n??i).origin===i}catch{return!1}}var J=class{constructor(){this.state=null;this.verifiers=null;this.verifierReporter=null;this.verifierCtx=null}init(e){if(this.state){try{this.state.uninstallUnloadFlush?.()}catch{}try{this.state.autoTracker?.uninstall()}catch{}try{this.state.webVitals?.uninstall()}catch{}try{this.state.errors?.uninstall()}catch{}try{this.state.events.flush({keepalive:!0})}catch{}}if(!e.publicKey||!e.publicKey.startsWith("cd_pub_"))throw new _({type:"configuration_error",code:"invalid_public_key",message:"Crossdeck.init requires a publishable key starting with cd_pub_."});if(!e.appId)throw new _({type:"configuration_error",code:"missing_app_id",message:"Crossdeck.init requires an appId. Find yours in the Crossdeck dashboard."});if(e.environment!=="production"&&e.environment!=="sandbox")throw new _({type:"configuration_error",code:"invalid_environment",message:'Crossdeck.init requires environment: "production" | "sandbox".'});let t=Wr(e.publicKey);if(t&&t!==e.environment)throw new _({type:"configuration_error",code:"environment_mismatch",message:`Crossdeck.init: environment "${e.environment}" disagrees with key prefix (${t}). Reconcile the publishable key with the environment declaration.`});let s=Gr(),n=e.storage??Ke(),i=e.persistIdentity??!0,o=Xr(e.autoTrack),a={appId:e.appId,publicKey:e.publicKey,environment:e.environment,baseUrl:e.baseUrl??Z,persistIdentity:i,storagePrefix:e.storagePrefix??"crossdeck:",autoHeartbeat:e.autoHeartbeat??!0,eventFlushBatchSize:e.eventFlushBatchSize??20,eventFlushIntervalMs:e.eventFlushIntervalMs??2e3,sdkVersion:e.sdkVersion??R,autoTrack:o,appVersion:e.appVersion??null},c=new ce;c.enabled=e.debug===!0;let d=new Q({publicKey:a.publicKey,baseUrl:a.baseUrl,sdkVersion:a.sdkVersion,localDevMode:s,onErrorParsed:p=>{this.verifiers&&this.verifierReporter&&this.verifierCtx&&ut(this.verifiers,this.verifierReporter,this.verifierCtx,{errorType:p.type,errorCode:p.code,requestId:p.requestId??null,httpStatus:typeof p.status=="number"?p.status:0})}});s&&console.log("[crossdeck] Localhost detected \u2014 running in dev mode (no network calls). Set publicKey: 'cd_pub_test_\u2026' and deploy to a real domain to test against the Crossdeck Sandbox.");let l=i?n:new F,h=i&&!e.storage&&typeof globalThis.document<"u"?new ae({domain:$e(e.cookieDomain??"auto")}):void 0,f=new ee(l,a.storagePrefix,h),y=new P(l,a.storagePrefix+"entitlements"),b=i?new ie({storage:l,prefix:a.storagePrefix}):null;b&&c.emit("sdk.queue_restored","Restored persisted event queue from a prior session.");let g=new ne({http:d,batchSize:a.eventFlushBatchSize,intervalMs:a.eventFlushIntervalMs,envelope:()=>({appId:a.appId,environment:a.environment,sdk:{name:A,version:a.sdkVersion}}),persistentStore:b??void 0,onFirstFlushSuccess:()=>{c.emit("sdk.first_event_sent","First telemetry event received. View it in Live Events.",{appId:a.appId,environment:a.environment})},onRetryScheduled:p=>{c.emit("sdk.flush_retry_scheduled",`Event flush failed (${p.lastError}). Retrying in ${p.delayMs}ms (attempt ${p.consecutiveFailures}).`,{...p})},onPermanentFailure:p=>{let w=`[crossdeck] Event batch DROPPED (status ${p.status}): ${p.lastError}. ${p.droppedCount} event(s) lost \u2014 check your publishable key + app config.`;console.error(w),c.emit("sdk.flush_permanent_failure",w,{...p})},onParked:p=>{c.emit("sdk.parked",`[crossdeck] SDK parked \u2014 server no longer accepts this version's event format. Events held on-device (paused, not lost); update @cross-deck/web${p.minVersion?` to >= ${p.minVersion}`:""} to resume.`,{...p})}}),v=o.deviceInfo?Be({appVersion:a.appVersion??void 0}):a.appVersion?{appVersion:a.appVersion}:{},S=new le(i?l:new F,a.storagePrefix);Ye();let I=new fe({respectDnt:e.respectDnt===!0});I.isDntDenied&&c.emit("sdk.consent_dnt_applied","Do Not Track detected \u2014 all tracking dimensions denied at init.");let x=new pe(50);if(this.state={http:d,identity:f,entitlements:y,events:g,autoTracker:null,webVitals:null,errors:null,breadcrumbs:x,errorContext:{},errorTags:{},errorBeforeSend:null,superProps:S,consent:I,scrubPii:e.scrubPii!==!1,deviceInfo:v,options:a,debug:c,developerUserId:null,uninstallUnloadFlush:null,lastServerTime:null,lastClientTime:null},c.emit("sdk.configured",`Crossdeck connected to ${a.appId} in ${a.environment} mode.`,{appId:a.appId,environment:a.environment,sdkVersion:a.sdkVersion}),o.sessions||o.pageViews){let p=new W(o,(w,T)=>this.track(w,T),{storage:l,storageKey:a.storagePrefix+"session",cookieStorage:h??void 0});this.state.autoTracker=p,p.install()}if(o.webVitals){let p=new ue({enabled:!0},(w,T)=>this.track(w,T));this.state.webVitals=p,p.install()}if(o.errors){let p=new ye({config:{...mt,enabled:!0},breadcrumbs:x,report:w=>this.reportError(w),getContext:()=>({...this.state.errorContext}),getTags:()=>({...this.state.errorTags}),beforeSend:()=>this.state.errorBeforeSend,isConsented:()=>this.state.consent.errors,selfHostname:gt(a.baseUrl)});this.state.errors=p,p.install()}if(this.state.uninstallUnloadFlush=zr(()=>{this.flush({keepalive:!0}).catch(()=>{})}),a.autoHeartbeat&&!s&&this.heartbeat().catch(()=>{}),s||this.captureCampaignArrival().catch(()=>{}),e.disableContractAssertions!==!0){let p=ft();this.verifierCtx=it({logVerifierResults:e.logVerifierResults??p,disableContractAssertions:!1,runContext:typeof process<"u"&&process.env&&process.env.CI?"ci":"customer-app"}),this.verifierReporter=new z(this.verifierCtx);let w=ot(a.eventFlushIntervalMs);this.verifiers=Object.freeze([...at,w]),s?(e.verifyContractsAtBoot??p)&&this.verifierReporter&&Pe(this.verifiers,this.verifierReporter,this.verifierCtx).catch(()=>{}):this.bootstrapVerifierLayerRemote(e,p).catch(()=>{})}}async bootstrapVerifierLayerRemote(e,t){if(!this.state||!this.verifiers||!this.verifierCtx)return;let s={logVerifierResults:null,verifyContractsAtBoot:null};try{let o=await this.state.http.request("GET","/config");if(o&&o.verifierConfig){let a=o.verifierConfig;s={logVerifierResults:typeof a.logVerifierResults=="boolean"?a.logVerifierResults:null,verifyContractsAtBoot:typeof a.verifyContractsAtBoot=="boolean"?a.verifyContractsAtBoot:null}}}catch{}let n=e.logVerifierResults??s.logVerifierResults??t,i=e.verifyContractsAtBoot??s.verifyContractsAtBoot??t;n!==this.verifierCtx.logVerifierResults&&(this.verifierCtx={...this.verifierCtx,logVerifierResults:n},this.verifierReporter=new z(this.verifierCtx)),i&&this.verifierReporter&&await Pe(this.verifiers,this.verifierReporter,this.verifierCtx)}start(e){typeof console<"u"&&console.warn("[crossdeck] Crossdeck.start() is deprecated \u2014 use Crossdeck.init() instead. The signature is the same."),this.init(e)}async captureCampaignArrival(){let e=this.state;if(!e)return;let t=globalThis.location;if(!t||typeof t.search!="string"||t.search.length===0)return;let s=null;try{s=new URLSearchParams(t.search).get("cd_ref")}catch{return}if(s)try{await e.http.request("POST","/integrations/hubspot/arrival",{body:{anonymousId:e.identity.anonymousId,ref:s}})}catch{}}async identify(e,t){let s=this.requireStarted();if(!e)throw new _({type:"invalid_request_error",code:"missing_user_id",message:"identify(userId) requires a non-empty userId."});if(ve({actor:e}),!s.consent.analytics)return s.debug.emit("sdk.consent_denied","identify() skipped \u2014 consent denied for analytics."),{object:"alias_result",crossdeckCustomerId:s.identity.crossdeckCustomerId??"",linked:[],mergePending:!1,env:s.options.environment};let n=t?.traits!==void 0?G(t.traits):null,i=n&&Object.keys(n.properties).length>0?n.properties:void 0;if(s.debug.enabled&&n&&n.warnings.length>0)for(let d of n.warnings)s.debug.emit("sdk.property_coerced",`identify() traits key ${JSON.stringify(d.key)} was ${d.kind.replace(/_/g," ")} during validation.`,{key:d.key,kind:d.kind});let o={userId:e,anonymousId:s.identity.anonymousId};t?.email&&(o.email=t.email),i&&(o.traits=i);let a=s.developerUserId;s.entitlements.setUserKey(e),this.verifiers&&this.verifierReporter&&this.verifierCtx&&ct(this.verifiers,this.verifierReporter,this.verifierCtx,{priorUserId:a,nextUserId:e,cache:s.entitlements});let c=await s.http.request("POST","/identity/alias",{body:o});return s.identity.setCrossdeckCustomerId(c.crossdeckCustomerId),s.developerUserId=e,c}register(e){let t=this.requireStarted(),s=G(e);return t.superProps.register(s.properties)}unregister(e){this.requireStarted().superProps.unregister(e)}getSuperProperties(){return this.state?this.state.superProps.getSuperProperties():{}}group(e,t,s){let n=this.requireStarted();if(!e)throw new _({type:"invalid_request_error",code:"missing_group_type",message:"group(type, id) requires a non-empty type."});let i=s?G(s).properties:void 0;n.superProps.setGroup(e,t,i)}getGroups(){return this.state?this.state.superProps.getGroups():{}}consent(e){let t=this.requireStarted(),s=t.consent.set(e);return t.debug.emit("sdk.consent_changed","Consent state updated.",{...s}),s}consentStatus(){return this.state?this.state.consent.get():{analytics:!0,marketing:!0,errors:!0}}captureError(e,t){this.state?.errors&&this.state.errors.captureError(e,t)}captureMessage(e,t="info"){this.state?.errors&&this.state.errors.captureMessage(e,t)}setTag(e,t){this.state&&(this.state.errorTags[e]=t)}setTags(e){this.state&&Object.assign(this.state.errorTags,e)}setContext(e,t){this.state&&(this.state.errorContext[e]=t)}addBreadcrumb(e){this.state&&this.state.breadcrumbs.add(e)}setErrorBeforeSend(e){this.state&&(this.state.errorBeforeSend=e)}reportError(e){let t={fingerprint:e.fingerprint,level:e.level,errorType:e.errorType,message:e.message,stack:e.rawStack??void 0,frames:e.frames,filename:e.filename??void 0,lineno:e.lineno??void 0,colno:e.colno??void 0,tags:e.tags,context:e.context,breadcrumbs:e.breadcrumbs,http:e.http};for(let s of Object.keys(t))t[s]===void 0&&delete t[s];this.track(e.kind,t)}async forget(){let e=this.requireStarted(),t=this.identityQueryParams();try{await e.http.request("POST","/identity/forget",{body:{...t}})}catch(s){e.debug.emit("sdk.consent_denied",`forget() server call failed (${s instanceof Error?s.message:String(s)}). Local state wiped anyway.`)}this.reset()}async getEntitlements(){let e=this.requireStarted(),t=this.identityQueryParams(),s;try{s=await e.http.request("GET","/entitlements",{query:t})}catch(n){throw e.entitlements.markRefreshFailed(),n}return s.crossdeckCustomerId&&e.identity.setCrossdeckCustomerId(s.crossdeckCustomerId),e.entitlements.setFromList(s.data),s.data}isEntitled(e){return this.requireStarted().entitlements.isEntitled(e)}listEntitlements(){return this.requireStarted().entitlements.list()}onEntitlementsChange(e){return this.requireStarted().entitlements.subscribe(e)}reportContractFailure(e){let t={contract_id:e.contractId,sdk_version:R,sdk_platform:"web",failure_reason:e.failureReason,run_context:e.runContext,run_id:e.runId};e.testRef&&(t.test_file=e.testRef.file,t.test_name=e.testRef.name),e.deviceClass&&(t.device_class=e.deviceClass),he(t)}track(e,t){let s=this.requireStarted();if(!e)throw new _({type:"invalid_request_error",code:"missing_event_name",message:"track(name) requires a non-empty name."});let n=e.startsWith("error."),i=e.startsWith("webvitals.");if(!(n||i?s.consent.errors:s.consent.analytics)){s.debug.enabled&&s.debug.emit("sdk.consent_denied",`Dropped event "${e}" \u2014 consent denied for ${i?"errors":"analytics"}.`);return}if(s.debug.enabled&&t){let p=We(t);p.length>0&&s.debug.emit("sdk.sensitive_property_warning",`Event "${e}" has potentially sensitive property names: ${p.join(", ")}. Crossdeck is privacy-first \u2014 avoid sending PII unless intentional.`,{eventName:e,flagged:p})}s.debug.enabled&&!s.developerUserId&&!s.identity.crossdeckCustomerId&&s.debug.emit("sdk.no_identity","Using anonymous user until identify(userId) is called.");let a=G(t);if(s.debug.enabled&&a.warnings.length>0)for(let p of a.warnings)s.debug.emit("sdk.property_coerced",`Event "${e}" property ${JSON.stringify(p.key)} was ${p.kind.replace(/_/g," ")} during validation.`,{eventName:e,key:p.key,kind:p.kind});let c=s.autoTracker?.nextSeq()??0,d=Date.now();s.autoTracker?.markActivity();let l={},u=s.deviceInfo;u.os&&(l.os=u.os),u.osVersion&&(l.osVersion=u.osVersion);let h=s.options.appVersion;h&&(l.appVersion=h),l.sdkName=A,l.sdkVersion=s.options.sdkVersion,u.locale&&(l.locale=u.locale),u.timezone&&(l.timezone=u.timezone),u.browser&&(l.browser=u.browser),u.browserVersion&&(l.browserVersion=u.browserVersion);let f={};u.screenWidth!==void 0&&(f.screenWidth=u.screenWidth),u.screenHeight!==void 0&&(f.screenHeight=u.screenHeight),u.viewportWidth!==void 0&&(f.viewportWidth=u.viewportWidth),u.viewportHeight!==void 0&&(f.viewportHeight=u.viewportHeight),u.devicePixelRatio!==void 0&&(f.devicePixelRatio=u.devicePixelRatio);let y=s.autoTracker?.currentSessionId;y&&(f.sessionId=y);let b=s.autoTracker?.currentPageviewId;b&&(f.pageviewId=b);let g=s.autoTracker?.currentAcquisition;g&&(g.utm_source&&(f.utm_source=g.utm_source),g.utm_medium&&(f.utm_medium=g.utm_medium),g.utm_campaign&&(f.utm_campaign=g.utm_campaign),g.utm_content&&(f.utm_content=g.utm_content),g.utm_term&&(f.utm_term=g.utm_term),g.referrer&&s.consent.marketing&&(f.referrer=g.referrer),s.consent.marketing&&(g.gclid&&(f.gclid=g.gclid),g.fbclid&&(f.fbclid=g.fbclid),g.msclkid&&(f.msclkid=g.msclkid),g.ttclid&&(f.ttclid=g.ttclid),g.li_fat_id&&(f.li_fat_id=g.li_fat_id),g.twclid&&(f.twclid=g.twclid)));let v=s.superProps.getSuperProperties();for(let p of Object.keys(v))p in f||(f[p]=v[p]);let S=s.superProps.getGroupIds();Object.keys(S).length>0&&(f.$groups=S),Object.assign(f,a.properties),Qe()&&(f[ze]=!0);let I=s.scrubPii?Ie(f):f,x={eventId:this.mintEventId(),name:e,timestamp:d,seq:c,context:l,properties:I};if(Object.assign(x,this.identityHintForEvent()),s.events.enqueue(x),this.verifiers&&this.verifierReporter&&this.verifierCtx&&dt(this.verifiers,this.verifierReporter,this.verifierCtx,{callerProperties:a.properties,superProperties:v,deviceProperties:s.deviceInfo,mergedProperties:f}),!n&&!i){let p=e.startsWith("page.")?"navigation":e.startsWith("element.")||e==="session.started"?"ui.click":"custom";s.breadcrumbs.add({timestamp:x.timestamp,category:p,message:e,data:t?{...t}:void 0})}}async flush(e={}){await this.requireStarted().events.flush(e)}async flushEvents(){return this.flush()}async syncPurchases(e){let t=this.requireStarted();if(!e.signedTransactionInfo)throw new _({type:"invalid_request_error",code:"missing_signed_transaction_info",message:"syncPurchases requires a signedTransactionInfo string from StoreKit 2."});let s=e.rail??"apple",n={...e,rail:s},i=N(n);if(this.verifiers&&this.verifierReporter&&this.verifierCtx){let a=s==="apple"?n.signedTransactionInfo??"":n.purchaseToken??"";lt(this.verifiers,this.verifierReporter,this.verifierCtx,{rail:s,stableIdentifier:a,derivedKey:i})}let o=await t.http.request("POST","/purchases/sync",{body:n,idempotencyKey:i});t.identity.setCrossdeckCustomerId(o.crossdeckCustomerId),t.entitlements.setFromList(o.entitlements);try{let a=o.entitlements[0]?.source.productId,c=o.entitlements[0]?.source.subscriptionId,d={rail:s};a&&(d.productId=a),c&&(d.subscriptionId=c),o.idempotent_replay&&(d.idempotent_replay=!0),this.track("purchase.completed",d)}catch{}return t.debug.emit("sdk.purchase_evidence_sent","StoreKit transaction forwarded. Waiting for backend verification.",{rail:e.rail??"apple"}),o}async purchaseApple(e){return this.syncPurchases({rail:"apple",...e})}setDebugMode(e){let t=this.requireStarted();t.debug.enabled=e,e&&t.debug.emit("sdk.configured",`Debug mode enabled for ${t.options.appId} in ${t.options.environment} mode.`,{appId:t.options.appId,environment:t.options.environment})}async heartbeat(){let e=this.requireStarted(),t=await e.http.request("GET","/sdk/heartbeat");return typeof t?.serverTime=="number"&&Number.isFinite(t.serverTime)&&(e.lastServerTime=t.serverTime,e.lastClientTime=Date.now()),t}reset(){if(this.state){if(this.state.developerUserId)try{this.track("user.signed_out",{auto:!0})}catch{}if(this.state.autoTracker?.uninstall(),this.state.developerUserId&&this.state.identity.reset(),ve({actor:void 0}),this.state.entitlements.clearAll(),this.state.events.reset(),this.state.superProps.clear(),this.state.breadcrumbs.clear(),this.state.errorContext={},this.state.errorTags={},this.state.developerUserId=null,this.state.lastServerTime=null,this.state.lastClientTime=null,this.state.autoTracker){let e=new W(this.state.options.autoTrack,(t,s)=>this.track(t,s));this.state.autoTracker=e,e.install()}}}diagnostics(){if(!this.state)return{started:!1,anonymousId:null,crossdeckCustomerId:null,developerUserId:null,sdkVersion:null,baseUrl:null,clock:{lastServerTime:null,lastClientTime:null,skewMs:null},entitlements:{count:0,lastUpdated:0,stale:!1,listenerErrors:0},events:{buffered:0,dropped:0,inFlight:0,lastFlushAt:0,lastError:null,consecutiveFailures:0,nextRetryAt:null}};let e=this.state,t=e.lastServerTime!==null&&e.lastClientTime!==null?e.lastClientTime-e.lastServerTime:null;return{started:!0,anonymousId:e.identity.anonymousId,crossdeckCustomerId:e.identity.crossdeckCustomerId,developerUserId:e.developerUserId,sdkVersion:e.options.sdkVersion,baseUrl:e.options.baseUrl,clock:{lastServerTime:e.lastServerTime,lastClientTime:e.lastClientTime,skewMs:t},entitlements:{count:e.entitlements.list().length,lastUpdated:e.entitlements.freshness,stale:e.entitlements.isStale,listenerErrors:e.entitlements.listenerErrors},events:e.events.getStats()}}getCheckoutReference(){let e=this.requireStarted();return e.identity.crossdeckCustomerId??e.developerUserId??e.identity.anonymousId}getAnonymousId(){return this.state?this.state.identity.anonymousId:null}get trust(){let e=this.state?this.state.options.publicKey:"";return{panel:t=>te({...t,publicKey:e})}}requireStarted(){if(!this.state)throw new _({type:"configuration_error",code:"not_initialized",message:"Call Crossdeck.init({ appId, publicKey, environment }) before any other method."});return this.state}identityQueryParams(){let e=this.requireStarted();return e.identity.crossdeckCustomerId?{customerId:e.identity.crossdeckCustomerId}:e.developerUserId?{userId:e.developerUserId}:{anonymousId:e.identity.anonymousId}}identityHintForEvent(){let e=this.requireStarted(),t={anonymousId:e.identity.anonymousId};return e.developerUserId&&(t.developerUserId=e.developerUserId),e.identity.crossdeckCustomerId&&(t.crossdeckCustomerId=e.identity.crossdeckCustomerId),t}mintEventId(){return`evt_${Date.now().toString(36)}${O(8)}`}},yt=new J;function Wr(r){return r.startsWith("cd_pub_test_")?"sandbox":r.startsWith("cd_pub_live_")?"production":null}function Gr(){let r=globalThis.window;if(r?.__CROSSDECK_FORCE_LIVE__===!0)return!1;let e=r?.location?.hostname;return e?!!(e==="localhost"||e==="127.0.0.1"||e==="0.0.0.0"||e==="::1"||e==="[::1]"||/^\[?fe80::/i.test(e)||e.endsWith(".local")||/^10\./.test(e)||/^192\.168\./.test(e)||/^172\.(1[6-9]|2\d|3[0-1])\./.test(e)):!1}function Xr(r){return r===!1?{sessions:!1,pageViews:!1,deviceInfo:!1,clicks:!1,webVitals:!1,errors:!1}:r===void 0||r===!0?{...L}:{sessions:r.sessions??L.sessions,pageViews:r.pageViews??L.pageViews,deviceInfo:r.deviceInfo??L.deviceInfo,clicks:r.clicks??L.clicks,webVitals:r.webVitals??L.webVitals,errors:r.errors??L.errors}}function zr(r){let e=globalThis.window,t=globalThis.document;if(!e||!t)return()=>{};let s=()=>{try{t.visibilityState==="hidden"&&r()}catch{}},n=()=>{try{r()}catch{}};return t.addEventListener("visibilitychange",s),e.addEventListener("pagehide",n),e.addEventListener("beforeunload",n),()=>{t.removeEventListener("visibilitychange",s),e.removeEventListener("pagehide",n),e.removeEventListener("beforeunload",n)}}var kt="@cross-deck/web@1.12.0",bt="1.12.0",U=Object.freeze([{id:"contract-failed-payload-schema-lock",pillar:"diagnostics",status:"enforced",claim:"The `crossdeck.contract_failed` event payload contains ONLY the named diagnostic fields and never any end-user personal data. The wire shape is fixed \u2014 adding a new field requires (1) a pull request that updates this contract's `allowedFields` set, (2) a Privacy Policy \xA76 amendment, and (3) the Customer Disclosure Template / SDK Data Collection Reference \xA7B updates. Per-SDK assertion tests enforce the field set on every release. The `verification_phase` field is a categorical bucket \u2014 values are restricted to `boot` (the SDK self-test ran on Crossdeck.start) or `hot_path` (a verifier observed a real customer-triggered operation). The categorical nature is what preserves the diagnostic-only-not-personal classification. This is the structural guarantee that backs the independent-controller lawful basis in the Privacy Policy: the payload remains diagnostic-only, not personal, so the legitimate-interest analysis stays valid as the SDK evolves.",appliesTo:["web","node","swift","android","react-native"],allowedFields:{required:["contract_id","sdk_version","sdk_platform","failure_reason","run_context","run_id"],optional:["test_file","test_name","device_class","verification_phase"],forbidden:["anonymousId","developerUserId","crossdeckCustomerId","email","ip","user_agent","message","stack","stack_trace","frames","exception_message","url","path","screen","title","label","text","ariaLabel","accessibilityLabel","contentDescription","session_id","sessionId"]},transport:"Telemetry is single-fire to the Crossdeck reliability endpoint only \u2014 NOT the customer's appId. The customer's track() pipeline never carries `crossdeck.*` events; the customer's dashboard never shows individual contract failures. Operational telemetry flows one-way to the Crossdeck operations team for SDK reliability purposes (legitimate interest, independent-controller flow per Privacy Policy \xA76). The reliability endpoint is hardcoded at SDK build time; the publishable key for the reliability project is embedded as a constant and rejects writes that don't match the schema.",codeRef:["sdks/web/src/crossdeck.ts","sdks/node/src/crossdeck-server.ts","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/swift/Sources/Crossdeck/_DiagnosticTelemetry.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Crossdeck.kt","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/_DiagnosticTelemetry.kt","sdks/react-native/src/crossdeck.ts","backend/src/api/v1-sdk-diagnostic.ts","sdks/web/src/_diagnostic-telemetry.ts","sdks/node/src/_diagnostic-telemetry.ts","sdks/react-native/src/_diagnostic-telemetry.ts"],testRef:[{file:"sdks/web/tests/contract-failed-schema-lock.test.ts",name:"reportContractFailure payload conforms to schema-lock"},{file:"sdks/node/tests/contract-failed-schema-lock.test.ts",name:"reportContractFailure payload conforms to schema-lock"},{file:"sdks/swift/Tests/CrossdeckTests/ContractFailedSchemaLockTests.swift",name:"test_reportContractFailure_payloadFieldsAreInAllowList"},{file:"sdks/swift/Tests/CrossdeckTests/ContractFailedSchemaLockTests.swift",name:"test_reportContractFailure_doesNotEnterCustomerTrackPipeline"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/ContractFailedSchemaLockTest.kt",name:"reportContractFailure payload conforms to schema-lock"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/ContractFailedSchemaLockTest.kt",name:"reportContractFailure does not enter customer track pipeline"},{file:"sdks/react-native/tests/contract-failed-schema-lock.test.ts",name:"reportContractFailure payload conforms to schema-lock"},{file:"backend/tests/unit/v1-sdk-diagnostic.test.ts",name:"forbidden fields are enumerated in the schema-lock contract"},{file:"backend/tests/unit/v1-sdk-diagnostic.test.ts",name:"required fields are enumerated in the schema-lock contract"},{file:"backend/tests/unit/v1-sdk-diagnostic.test.ts",name:"regression guard: never returns a raw IP"},{file:"backend/tests/unit/v1-sdk-diagnostic.test.ts",name:"verification_phase is in the optional field set"}],registeredAt:"2026-05-27",firstRegisteredIn:"Diagnostic telemetry single-fire + schema-lock \u2014 independent-controller flow",privacyReferences:["legal/privacy/index.html#sdk-diagnostic","legal/customer-disclosure/index.html#flow-b","legal/security/index.html#diagnostic","legal/sdk-data/index.html#b-diagnostic"],bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"error-envelope-shape",pillar:"errors",status:"enforced",claim:"Every v1 REST endpoint returns errors in a Stripe-shape envelope: `{ error: { type, code, message, request_id } }` where `type` is one of authentication_error / permission_error / invalid_request_error / rate_limit_error / internal_error (the wire vocabulary in backend/src/api/v1-errors.ts ApiErrorType). HTTP status parity: invalid_request_error \u2192 400, authentication_error \u2192 401, permission_error \u2192 403, rate_limit_error \u2192 429, internal_error \u2192 500. SDK-side clients parse this shape via `crossdeckErrorFromResponse` (Web/Node/RN) / `crossdeckErrorFrom(response:)` (Swift) / `crossdeckErrorFromResponse` (Android) and surface the request_id verbatim so support traces are end-to-end joinable. Firebase callable endpoints (managed-keys / dashboard auth) use the Firebase HttpsError envelope instead \u2014 this contract applies to REST /v1/* only.",appliesTo:["web","node","react-native","swift","android","backend"],codeRef:["backend/src/api/v1-errors.ts","sdks/web/src/errors.ts","sdks/node/src/errors.ts","sdks/react-native/src/errors.ts","sdks/swift/Sources/Crossdeck/Errors.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Errors.kt"],testRef:[{file:"sdks/swift/Tests/CrossdeckTests/ErrorsTests.swift",name:"test_errorEnvelope_fallsBackOnGarbageBody"},{file:"sdks/swift/Tests/CrossdeckTests/ErrorsTests.swift",name:"test_errorEnvelope_reads_XRequestId_fallback"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/ErrorTypeWireVocabTest.kt",name:"backend 500 response parses to INTERNAL_ERROR"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 8 (codifies existing contract)",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"flush-interval-parity",pillar:"analytics",status:"enforced",claim:"Every Crossdeck SDK defaults its event-queue flush interval to 2000ms \u2014 the Stripe-adjacent industry norm. Pre-v1.4.0 the defaults disagreed (Web/Node 1500ms; RN/Swift/Android 5000ms), so cross-platform funnels saw events landing at different cadences. Per-instance override stays \u2014 call sites can still tune it freely.",appliesTo:["web","node","react-native","swift","android"],codeRef:["sdks/web/src/crossdeck.ts","sdks/node/src/crossdeck-server.ts","sdks/react-native/src/crossdeck.ts","sdks/swift/Sources/Crossdeck/EventQueue.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/EventQueue.kt"],testRef:[{file:"sdks/swift/Sources/Crossdeck/EventQueue.swift",name:"flushIntervalMs: Int = 2_000"},{file:"sdks/android/crossdeck/src/main/kotlin/com/crossdeck/EventQueue.kt",name:"flushIntervalMs: Long = 2_000L"},{file:"sdks/web/src/crossdeck.ts",name:"options.eventFlushIntervalMs ?? 2000"},{file:"sdks/node/src/crossdeck-server.ts",name:"options.eventFlushIntervalMs ?? 2000"},{file:"sdks/react-native/src/crossdeck.ts",name:"options.eventFlushIntervalMs ?? 2000"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 3.3",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"idempotency-key-deterministic",pillar:"revenue",status:"enforced",claim:"syncPurchases() on every SDK derives a deterministic Idempotency-Key from the request body (UUID-shaped SHA-256 of `crossdeck:purchases/sync:<rail>:<jws|token>`). Same input -> same key. Backend short-circuits same-key-same-body retries by returning the cached response (status + body) with `idempotent_replay: true` flag in the body AND `Idempotent-Replayed: true` response header. Same-key-different-body returns 400 `idempotency_key_in_use`. 24-hour TTL matches Stripe. Cache only stores 2xx responses \u2014 4xx/5xx pass through so callers can fix bugs and retry. Helper returns nil/throws on missing identifier (no silent random fallback). Cross-SDK parity is CI-pinned: deriveForPurchase('apple', 'eyJ.jws.sig') MUST equal 'a66b1640-efaf-bb4d-1261-6650033bf111' on every SDK.",appliesTo:["web","node","react-native","swift","android","backend"],codeRef:["sdks/web/src/idempotency-key.ts","sdks/web/src/crossdeck.ts","sdks/react-native/src/idempotency-key.ts","sdks/react-native/src/crossdeck.ts","sdks/node/src/idempotency-key.ts","sdks/node/src/crossdeck-server.ts","sdks/swift/Sources/Crossdeck/IdempotencyKey.swift","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/IdempotencyKey.kt","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Crossdeck.kt","backend/src/lib/idempotency-response-cache.ts","backend/src/api/v1-purchases.ts"],testRef:[{file:"sdks/web/tests/idempotency-key.test.ts",name:"cross-SDK oracle \u2014 apple JWS pins canonical vector"},{file:"sdks/web/tests/idempotency-key.test.ts",name:"is deterministic: same body twice -> identical key"},{file:"sdks/web/tests/idempotency-key.test.ts",name:"same identifier under different rails -> different keys"},{file:"sdks/web/tests/idempotency-key.test.ts",name:"never silently falls back to a random key on missing identifier"},{file:"sdks/react-native/tests/idempotency-key.test.ts",name:"is deterministic"},{file:"sdks/react-native/tests/idempotency-key.test.ts",name:"cross-SDK oracle \u2014 apple JWS pins canonical vector"},{file:"sdks/node/tests/idempotency-key.test.ts",name:"is deterministic"},{file:"sdks/node/tests/idempotency-key.test.ts",name:"rail namespacing prevents cross-rail collisions"},{file:"sdks/node/tests/idempotency-key.test.ts",name:"apple JWS produces the canonical pinned UUID across all 5 SDKs"},{file:"backend/tests/unit/idempotency-response-cache.test.ts",name:"is deterministic for the same input"},{file:"backend/tests/unit/idempotency-response-cache.test.ts",name:"injects idempotent_replay: true into a JSON object body"},{file:"backend/tests/unit/idempotency-response-cache.test.ts",name:"matches Stripe's 24-hour idempotency window"},{file:"sdks/swift/Tests/CrossdeckTests/IdempotencyKeyTests.swift",name:"test_crossSdkOracle_appleJWS"},{file:"sdks/swift/Tests/CrossdeckTests/IdempotencyKeyTests.swift",name:"test_railNamespacing_preventsCrossRailCollisions"},{file:"sdks/swift/Tests/CrossdeckTests/IdempotencyKeyTests.swift",name:"test_missingIdentifier_returnsNil"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/IdempotencyKeyTest.kt",name:"cross-SDK oracle for apple JWS"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/IdempotencyKeyTest.kt",name:"rail namespacing prevents cross-rail collisions"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/IdempotencyKeyTest.kt",name:"missing identifier returns null - never silent random fallback"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 2.2.a + 2.2.b + 2.2.c",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"init-reentry-drains-prior-queue",pillar:"lifecycle",status:"enforced",claim:"Web + RN init() re-entry drains the prior EventQueue's pending setTimeout BEFORE replacing this.state. Pre-v1.4.0 the teardown handled autoTracker/webVitals/errors/unloadFlush but NOT events, so the prior queue's timer would fire AFTER the state swap \u2014 sending old-init events against new-init http + identity references (cross-identity leak during HMR / config swap / multi-tenant SDK shells). The teardown CANNOT call persistent.clear() \u2014 the durable queue belongs to the SDK lifetime, not the init() lifetime, and a survived crash mid-flush re-hydrates on the next init.",appliesTo:["web","react-native"],codeRef:["sdks/web/src/crossdeck.ts","sdks/react-native/src/crossdeck.ts"],testRef:[{file:"sdks/web/tests/init-reentry.test.ts",name:"re-init drains the prior queue's pending timer before swapping state"},{file:"sdks/web/tests/init-reentry.test.ts",name:"re-init does NOT wipe the durable event store"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 5.5",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!1},{id:"invalid-input-rejected-natively",pillar:"errors",status:"enforced",claim:"No public SDK API ever crashes the host app, and invalid input never reaches the wire. Invalid input (empty event name, empty userId, out-of-range config such as a non-positive breadcrumb capacity, NaN/Infinity/oversize/cyclic property values) is rejected at the call site WITHOUT a fatal trap. The signalling IDIOM is per-language and intentionally NOT uniform: Web, Node, and React Native THROW a typed CrossdeckError synchronously (code missing_event_name / missing_user_id / invalid_request_error) \u2014 a normal, catchable JavaScript convention where an uncaught throw logs and the app continues; Swift DROPS with a debug-log signal (track_dropped / identify_dropped) to match its non-throwing fire-and-forget surface, and exposes the throwing equivalent only via identifyAndWait(userId:). What is UNIFORM is the invariant, not the mechanism: every SDK rejects the same inputs, no public fire-and-forget API contains a fatalError / assertionFailure / precondition reachable from customer input, and no rejected input is enqueued or transmitted. Swift additionally proves this in BOTH debug and release configuration, because precondition fires under -O while assertionFailure does not. The bug class this contract closes was never the per-language difference \u2014 it was the UNDECLARED difference: each SDK's public API documentation must state its own semantics explicitly (TS docs: 'throws on empty name'; Swift docs: 'drops and logs').",appliesTo:["web","node","react-native","swift"],codeRef:["sdks/web/src/crossdeck.ts","sdks/node/src/crossdeck-server.ts","sdks/react-native/src/crossdeck.ts","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/swift/Sources/Crossdeck/Breadcrumbs.swift"],testRef:[{file:"sdks/web/tests/crossdeck.test.ts",name:"track with empty name throws synchronously"},{file:"sdks/web/tests/crossdeck.test.ts",name:"rejects empty userId"},{file:"sdks/node/tests/crossdeck-server.test.ts",name:"track() throws CrossdeckError with code 'missing_event_name' when event name is empty"},{file:"sdks/react-native/tests/crossdeck.test.ts",name:"track('') throws CrossdeckError(missing_event_name) synchronously"},{file:"sdks/react-native/tests/crossdeck.test.ts",name:"identify('') rejects with CrossdeckError(missing_user_id)"},{file:"sdks/swift/Tests/CrossdeckTests/CrossdeckPublicAPITests.swift",name:"test_track_dropsEmptyName"},{file:"sdks/swift/Tests/CrossdeckTests/CrossdeckPublicAPITests.swift",name:"test_identifyAndWait_rejectsEmptyId"},{file:"sdks/swift/Tests/CrossdeckTests/PublicAPIInputSafetyTests.swift",name:"test_start_withZeroBreadcrumbCapacity_doesNotTrap"}],registeredAt:"2026-06-11",firstRegisteredIn:"swift trap-on-input class fix \u2014 first machine-tested Swift release",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!1},{id:"per-user-cache-isolation",pillar:"entitlements",status:"enforced",claim:"Every identify(userId) switches the entitlement cache to a physically separate per-user storage slot \u2014 `crossdeck:entitlements:<sha256(userId)>` \u2014 and unconditionally wipes the in-memory snapshot. A user-switch on a shared device CANNOT cross-read a prior user's cached entitlements, even if the in-memory clear is somehow skipped, because the storage keys are physically separate. reset() wipes every per-user slot via the persisted index.",appliesTo:["web","react-native","swift","android"],codeRef:["sdks/web/src/entitlement-cache.ts","sdks/web/src/hash.ts","sdks/web/src/crossdeck.ts","sdks/react-native/src/entitlement-cache.ts","sdks/react-native/src/hash.ts","sdks/react-native/src/crossdeck.ts","sdks/swift/Sources/Crossdeck/EntitlementCache.swift","sdks/swift/Sources/Crossdeck/IdempotencyKey.swift","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/EntitlementCache.kt","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/IdempotencyKey.kt","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Crossdeck.kt"],testRef:[{file:"sdks/web/tests/entitlement-cache-isolation.test.ts",name:"identify(B) makes A's entitlements unreachable from in-memory"},{file:"sdks/web/tests/entitlement-cache-isolation.test.ts",name:"clearAll() removes every per-user storage key plus the index"},{file:"sdks/web/tests/entitlement-cache-isolation.test.ts",name:"a second cache instance reading A's storage suffix CANNOT see B's data"},{file:"sdks/react-native/tests/entitlement-cache-isolation.test.ts",name:"identify(B) makes A's entitlements unreachable from in-memory"},{file:"sdks/react-native/tests/entitlement-cache-isolation.test.ts",name:"removes every per-user storage key plus the index"},{file:"sdks/swift/Tests/CrossdeckTests/EntitlementCacheIsolationTests.swift",name:"test_identifyB_makesAEntitlementsUnreachable"},{file:"sdks/swift/Tests/CrossdeckTests/EntitlementCacheIsolationTests.swift",name:"test_identifiedWritesLandUnderPerUserSha256Key"},{file:"sdks/swift/Tests/CrossdeckTests/EntitlementCacheIsolationTests.swift",name:"test_clearAll_removesEveryPerUserStorageKeyPlusIndex"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/EntitlementCacheIsolationTest.kt",name:"identified writes land under per-user sha256 key"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/EntitlementCacheIsolationTest.kt",name:"identify B makes A entitlements unreachable from in-memory"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/EntitlementCacheIsolationTest.kt",name:"clearAll removes every per-user storage key plus the index"},{file:"sdks/android/crossdeck/src/test/kotlin/com/crossdeck/EntitlementCacheIsolationTest.kt",name:"a fresh cache bound to A's key CANNOT read B's blob"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 1.3 (web/RN) + dogfood-gap fix (swift + android)",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"sdk-error-codes-catalogue",pillar:"errors",status:"enforced",claim:"Web + Node SDK error-codes catalogues include EVERY backend-emitted ApiErrorCode with a description + resolution. Pre-v1.4.0 the catalogues documented codes the SDK threw ITSELF but ZERO backend codes \u2014 a developer hitting `invalid_api_key` / `origin_not_allowed` / `bundle_id_not_allowed` / `env_mismatch` / `idempotency_key_in_use` etc. got `undefined` from getErrorCode() and had to hunt for guidance. v1.4.0 backfills the catalogue from backend/src/api/v1-errors.ts so every wire code has a canonical 'what does this mean / what should I do' answer Stripe-style.",appliesTo:["web","node"],codeRef:["sdks/web/src/error-codes.ts","sdks/node/src/error-codes.ts","sdks/web/src/_contract-verifiers.ts","backend/src/api/v1-errors.ts"],testRef:[{file:"sdks/web/tests/contract-verifiers.test.ts",name:"sdk-error-codes-catalogue covers every backend wire code with remediation"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"includes backend code"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"invalid_api_key resolution points at the dashboard"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"idempotency_key_in_use resolution mentions Stripe-grade contract"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"identity-lock codes carry permission_error type"},{file:"sdks/web/tests/error-codes-backfill.test.ts",name:"no entry has an empty description or resolution"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 6.2",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"super-property-merge-precedence",pillar:"analytics",status:"enforced",claim:"Every Crossdeck SDK merges event properties with the precedence device < super < caller (caller-supplied values win over registered super-properties, which win over auto-attached device info). Pre-v1.4.0 Swift had it INVERTED (super < device < caller \u2014 device clobbered super), so a `register('plan', 'pro')` super-property was silently overridden by auto-attached device fields whenever keys collided. Cross-SDK funnel queries on super-property keys returned different answers per platform.",appliesTo:["web","swift"],codeRef:["sdks/web/src/super-properties.ts","sdks/web/src/_contract-verifiers.ts","sdks/swift/Sources/Crossdeck/EventPropertyMerge.swift","sdks/swift/Sources/Crossdeck/Crossdeck.swift"],testRef:[{file:"sdks/web/tests/contract-verifiers.test.ts",name:"super-property-merge-precedence verifies caller > super > device"},{file:"sdks/swift/Tests/CrossdeckTests/EventPropertyMergeTests.swift",name:"test_super_overrides_device"},{file:"sdks/swift/Tests/CrossdeckTests/EventPropertyMergeTests.swift",name:"test_caller_overrides_super"},{file:"sdks/swift/Tests/CrossdeckTests/EventPropertyMergeTests.swift",name:"test_full_precedence_chain"},{file:"sdks/swift/Tests/CrossdeckTests/EventPropertyMergeTests.swift",name:"test_matchesWebNodeRNPrecedence"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 3.2",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!0},{id:"sync-purchases-funnel-parity",pillar:"analytics",status:"enforced",claim:"Manual syncPurchases() emits a `purchase.completed` analytics event on success across ALL SDKs (Web / Node / RN / Swift / Android). Pre-v1.4.0 only Swift/Android auto-track emitted it \u2014 Web/Node/RN manual calls + Swift/Android manual calls fired ZERO analytics. Schema mirrors the auto-track event name + rail/productId/subscriptionId so cross-platform funnels reconcile on every payment path. When the backend short-circuits via the v1.4.0 idempotency cache, the event also carries `idempotent_replay: true`.",appliesTo:["web","node","react-native","swift","android"],codeRef:["sdks/web/src/crossdeck.ts","sdks/node/src/crossdeck-server.ts","sdks/react-native/src/crossdeck.ts","sdks/swift/Sources/Crossdeck/Crossdeck.swift","sdks/android/crossdeck/src/main/kotlin/com/crossdeck/Crossdeck.kt"],testRef:[{file:"sdks/web/tests/sync-purchases-funnel.test.ts",name:"emits purchase.completed after a successful sync"},{file:"sdks/web/tests/sync-purchases-funnel.test.ts",name:"carries idempotent_replay=true when backend replied from cache"}],registeredAt:"2026-05-26",firstRegisteredIn:"bank-grade reconciliation v1.4.0 \u2014 phase 3.5",bundledIn:"@cross-deck/web@1.12.0",runtimeVerified:!1}]);var vt={all(){return U.filter(r=>r.status==="enforced")},allIncludingHistorical(){return U},byId(r){return U.find(e=>e.id===r)},byPillar(r){return U.filter(e=>e.pillar===r&&e.status==="enforced")},withStatus(r){return U.filter(e=>e.status===r)},sdkVersion:bt,bundledIn:kt,findByTestName(r){return U.find(e=>e.testRef.some(t=>t.name===r))}};return Ct(Jr);})();
3
3
  //# sourceMappingURL=crossdeck.umd.min.js.map