@crosslink/sdk-browser 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1123 @@
1
+ "use strict";var CrosslinkSDK=(()=>{var ar=Object.defineProperty;var aa=Object.getOwnPropertyDescriptor;var ca=Object.getOwnPropertyNames;var la=Object.prototype.hasOwnProperty;var cr=(t,e,n)=>()=>{if(n)throw n[0];try{return t&&(e=t(t=0)),e}catch(r){throw n=[r],r}};var lr=(t,e)=>{for(var n in e)ar(t,n,{get:e[n],enumerable:!0})},da=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of ca(e))!la.call(t,o)&&o!==n&&ar(t,o,{get:()=>e[o],enumerable:!(r=aa(e,o))||r.enumerable});return t};var pa=t=>da(ar({},"__esModule",{value:!0}),t);var Ks={};lr(Ks,{JsonStore:()=>Fe,LocalStorageSecureStorage:()=>Re,MemorySecureStorage:()=>lt});var lt,Re,Fe,St=cr(()=>{"use strict";lt=class{map=new Map;get(e){return this.map.get(e)??null}set(e,n){this.map.set(e,n)}delete(e){this.map.delete(e)}},Re=class{constructor(e){this.ls=e}ls;get(e){return this.ls.getItem(e)}set(e,n){this.ls.setItem(e,n)}delete(e){this.ls.removeItem(e)}},Fe=class{constructor(e,n){this.storage=e;this.key=n}storage;key;load(e){let n=this.storage.get(this.key);if(!n)return e;try{return{...e,...JSON.parse(n)}}catch{return e}}save(e){this.storage.set(this.key,JSON.stringify(e))}}});function Zl(){return new Promise((t,e)=>{let n=indexedDB.open(Xl,1);n.onupgradeneeded=()=>{let r=n.result;r.objectStoreNames.contains(qe)||r.createObjectStore(qe),r.objectStoreNames.contains(le)||r.createObjectStore(le)},n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error??new Error("indexedDB open failed")),n.onblocked=()=>e(new Error("indexedDB open blocked by another tab"))})}function Wn(t){return new Promise((e,n)=>{t.oncomplete=()=>e(),t.onerror=()=>n(t.error??new Error("indexedDB transaction failed")),t.onabort=()=>n(t.error??new Error("indexedDB transaction aborted"))})}function fo(t){return new Promise((e,n)=>{t.onsuccess=()=>e(t.result),t.onerror=()=>n(t.error??new Error("indexedDB request failed"))})}async function At(t={}){try{let r=await on.open();return{storage:await sn.hydrate(r,{...t.onWriteError?{onWriteError:t.onWriteError}:{}}),kind:r.kind,encrypted:!0}}catch(r){if(t.allowPlaintextFallback===!1)throw r}let{LocalStorageSecureStorage:e,MemorySecureStorage:n}=await Promise.resolve().then(()=>(St(),Ks));return typeof localStorage<"u"?{storage:new e(localStorage),kind:"localstorage",encrypted:!1}:{storage:new n,kind:"memory",encrypted:!1}}var Xl,qe,le,Vs,on,Xn,sn,Zn=cr(()=>{"use strict";Xl="crosslink-secure",qe="keys",le="values",Vs="master";on=class t{constructor(e,n){this.db=e;this.key=n}db;key;kind="indexeddb-aes-gcm";encrypted=!0;static async open(){if(typeof indexedDB>"u")throw new Error("IndexedDB is not available in this environment");let e=globalThis.crypto?.subtle;if(!e)throw new Error("WebCrypto subtle is not available (requires a secure origin)");let n=await Zl(),r=await fo(n.transaction(qe,"readonly").objectStore(qe).get(Vs));if(!r){r=await e.generateKey({name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);let o=n.transaction(qe,"readwrite");o.objectStore(qe).put(r,Vs),await Wn(o)}return new t(n,r)}async get(e){let n=await fo(this.db.transaction(le,"readonly").objectStore(le).get(e));if(!n)return null;try{let r=await crypto.subtle.decrypt({name:"AES-GCM",iv:new Uint8Array(n.iv)},this.key,n.data);return new TextDecoder().decode(r)}catch{return null}}async set(e,n){let r=crypto.getRandomValues(new Uint8Array(12)),o=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},this.key,new TextEncoder().encode(n)),i=this.db.transaction(le,"readwrite");i.objectStore(le).put({iv:r.buffer,data:o},e),await Wn(i)}async delete(e){let n=this.db.transaction(le,"readwrite");n.objectStore(le).delete(e),await Wn(n)}async keys(){return(await fo(this.db.transaction(le,"readonly").objectStore(le).getAllKeys())).map(String)}async wipe(){let e=this.db.transaction([le,qe],"readwrite");e.objectStore(le).clear(),e.objectStore(qe).clear(),await Wn(e)}},Xn=class{constructor(e,n="sync-adapter",r=new Set){this.inner=e;this.knownKeys=r;this.kind=n}inner;knownKeys;kind;encrypted=!1;async get(e){return this.inner.get(e)}async set(e,n){this.knownKeys.add(e),this.inner.set(e,n)}async delete(e){this.knownKeys.delete(e),this.inner.delete(e)}async keys(){return[...this.knownKeys]}},sn=class t{constructor(e,n){this.backend=e;this.onWriteError=n}backend;onWriteError;cache=new Map;flushChain=Promise.resolve();pendingWrites=0;static async hydrate(e,n={}){let r=new t(e,n.onWriteError);for(let o of await e.keys()){let i=await e.get(o);i!==null&&r.cache.set(o,i)}return r}get kind(){return this.backend.kind}get encrypted(){return this.backend.encrypted}get(e){return this.cache.get(e)??null}set(e,n){this.cache.set(e,n),this.enqueue(e,()=>this.backend.set(e,n))}delete(e){this.cache.delete(e),this.enqueue(e,()=>this.backend.delete(e))}flushed(){return this.flushChain}get pending(){return this.pendingWrites}enqueue(e,n){this.pendingWrites+=1,this.flushChain=this.flushChain.then(n).catch(r=>{this.onWriteError?.(r,e)}).finally(()=>{this.pendingWrites-=1})}}});var Gs={};lr(Gs,{SecureDeviceCryptoStorage:()=>ho});var ho,zs=cr(()=>{"use strict";Zn();ho=class t{storage;constructor(e){this.storage=e}static async open(){let{storage:e}=await At({allowPlaintextFallback:!1});return new t(e)}storageKey(e){return`crosslink.device-crypto.${e}`}async load(e){let n=this.storageKey(e??"default"),r=this.storage.get(n);if(!r)return null;try{let o=JSON.parse(r);if(o&&typeof o.deviceId=="string"&&typeof o.edPrivateSeedB64=="string")return{deviceId:o.deviceId,edPrivateSeedB64:o.edPrivateSeedB64}}catch{}return null}async save(e,n){let r=this.storageKey(n??"default");this.storage.set(r,JSON.stringify(e))}async clear(e){let n=this.storageKey(e??"default");this.storage.delete(n)}}});var hd={};lr(hd,{ATTRIBUTION_MIN_CONTRAST:()=>Qs,AsyncStorageAdapter:()=>Xn,BrokeredPairingChannel:()=>Ot,CONTROL_ROUTES:()=>dt,CROSSLINK_ATTRIBUTION_LINK_TEXT:()=>ft,CROSSLINK_ATTRIBUTION_TEXT:()=>Bt,CROSSLINK_LOGO_PATH:()=>yo,CROSSLINK_LOGO_VIEWBOX:()=>mo,CROSSLINK_REPOSITORY:()=>Nt,CrosslinkClient:()=>me,CrosslinkMobileBootstrap:()=>un,CrosslinkOfflineShell:()=>dn,DEFAULT_OFFLINE_CONFIG:()=>Ve,DEFAULT_SERVICE_WORKER:()=>Co,DEFAULT_SERVICE_WORKER_CONFIG:()=>Ut,DirectPairingChannel:()=>_t,HydratedSecureStorage:()=>sn,INSTALL_HANDOFF_CONTEXT_COOKIE:()=>Mt,INSTALL_HANDOFF_COOKIE:()=>Rt,INSTALL_HANDOFF_QUERY_KEY:()=>gt,IndexedDbSecureStorage:()=>on,JsonStore:()=>Fe,LOGO_MIN_CONTRAST:()=>Ys,LocalStorageSecureStorage:()=>Re,MemoryLogSink:()=>_s,MemorySecureStorage:()=>lt,MockSocket:()=>Qn,NotificationHandler:()=>Jn,PairingCard:()=>ln,PoweredByCrosslink:()=>ht,SignalingPeer:()=>It,consoleLogger:()=>Is,contrastRatio:()=>rr,createCrosslinkClient:()=>fd,createCrosslinkLogo:()=>Js,createHttpPairingSource:()=>er,createLogger:()=>Vn,createOfflineUI:()=>Lt,createPairingCard:()=>ta,createPoweredByCrosslink:()=>na,createSecureCrosslinkClient:()=>ud,createSecureStorage:()=>At,createServiceWorkerConfig:()=>So,crosslinkLogoSvg:()=>ae,describeBootstrapEnvironment:()=>pn,generateServiceWorker:()=>sr,injectBootstrapStyles:()=>ir,injectPairingCardStyles:()=>wo,isStandalone:()=>Pt,noopLogger:()=>st,normalizeNetworkMode:()=>ut,parseColor:()=>pt,removeOfflineUI:()=>Eo,resetDeviceStorage:()=>fn,resolveCrosslinkTheme:()=>Ke,updateOfflineStatus:()=>vo,wsTransport:()=>an});function No(t){return t instanceof Uint8Array||ArrayBuffer.isView(t)&&t.constructor.name==="Uint8Array"}function hn(t){if(typeof t!="boolean")throw new Error(`boolean expected, not ${t}`)}function gn(t){if(!Number.isSafeInteger(t)||t<0)throw new Error("positive integer expected, got "+t)}function Y(t,...e){if(!No(t))throw new Error("Uint8Array expected");if(e.length>0&&!e.includes(t.length))throw new Error("Uint8Array expected of length "+e+", got length="+t.length)}function dr(t,e=!0){if(t.destroyed)throw new Error("Hash instance has been destroyed");if(e&&t.finished)throw new Error("Hash#digest() has already been called")}function Bo(t,e){Y(t);let n=e.outputLen;if(t.length<n)throw new Error("digestInto() expects output buffer of length at least "+n)}function Se(t){return new Uint32Array(t.buffer,t.byteOffset,Math.floor(t.byteLength/4))}function Ae(...t){for(let e=0;e<t.length;e++)t[e].fill(0)}function fa(t){return new DataView(t.buffer,t.byteOffset,t.byteLength)}var ua=new Uint8Array(new Uint32Array([287454020]).buffer)[0]===68;function ha(t){if(typeof t!="string")throw new Error("string expected");return new Uint8Array(new TextEncoder().encode(t))}function mn(t){if(typeof t=="string")t=ha(t);else if(No(t))t=yn(t);else throw new Error("Uint8Array expected, got "+typeof t);return t}function Lo(t,e){if(e==null||typeof e!="object")throw new Error("options must be defined");return Object.assign(t,e)}function Po(t,e){if(t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t[r]^e[r];return n===0}var pr=(t,e)=>{function n(r,...o){if(Y(r),!ua)throw new Error("Non little-endian hardware is not yet supported");if(t.nonceLength!==void 0){let d=o[0];if(!d)throw new Error("nonce / iv required");t.varSizeNonce?Y(d):Y(d,t.nonceLength)}let i=t.tagLength;i&&o[1]!==void 0&&Y(o[1]);let s=e(r,...o),a=(d,f)=>{if(f!==void 0){if(d!==2)throw new Error("cipher output not supported");Y(f)}},c=!1;return{encrypt(d,f){if(c)throw new Error("cannot encrypt() twice with same key + nonce");return c=!0,Y(d),a(s.encrypt.length,f),s.encrypt(d,f)},decrypt(d,f){if(Y(d),i&&d.length<i)throw new Error("invalid ciphertext length: smaller than tagLength="+i);return a(s.decrypt.length,f),s.decrypt(d,f)}}}return Object.assign(n,t),n};function fr(t,e,n=!0){if(e===void 0)return new Uint8Array(t);if(e.length!==t)throw new Error("invalid output length, expected "+t+", got: "+e.length);if(n&&!ga(e))throw new Error("invalid output, must be aligned");return e}function Oo(t,e,n,r){if(typeof t.setBigUint64=="function")return t.setBigUint64(e,n,r);let o=BigInt(32),i=BigInt(4294967295),s=Number(n>>o&i),a=Number(n&i),c=r?4:0,l=r?0:4;t.setUint32(e+c,s,r),t.setUint32(e+l,a,r)}function Ro(t,e,n){hn(n);let r=new Uint8Array(16),o=fa(r);return Oo(o,0,BigInt(e),n),Oo(o,8,BigInt(t),n),r}function ga(t){return t.byteOffset%4===0}function yn(t){return Uint8Array.from(t)}var Uo=t=>Uint8Array.from(t.split("").map(e=>e.charCodeAt(0))),ma=Uo("expand 16-byte k"),ya=Uo("expand 32-byte k"),ba=Se(ma),wa=Se(ya);function B(t,e){return t<<e|t>>>32-e}function ur(t){return t.byteOffset%4===0}var bn=64,xa=16,Do=2**32-1,Mo=new Uint32Array;function va(t,e,n,r,o,i,s,a){let c=o.length,l=new Uint8Array(bn),d=Se(l),f=ur(o)&&ur(i),p=f?Se(o):Mo,h=f?Se(i):Mo;for(let g=0;g<c;s++){if(t(e,n,r,d,s,a),s>=Do)throw new Error("arx: counter overflow");let b=Math.min(bn,c-g);if(f&&b===bn){let y=g/4;if(g%4!==0)throw new Error("arx: invalid block position");for(let m=0,v;m<xa;m++)v=y+m,h[v]=p[v]^d[m];g+=bn;continue}for(let y=0,m;y<b;y++)m=g+y,i[m]=o[m]^l[y];g+=b}}function hr(t,e){let{allowShortKeys:n,extendNonceFn:r,counterLength:o,counterRight:i,rounds:s}=Lo({allowShortKeys:!1,counterLength:8,counterRight:!1,rounds:20},e);if(typeof t!="function")throw new Error("core must be a function");return gn(o),gn(s),hn(i),hn(n),(a,c,l,d,f=0)=>{Y(a),Y(c),Y(l);let p=l.length;if(d===void 0&&(d=new Uint8Array(p)),Y(d),gn(f),f<0||f>=Do)throw new Error("arx: counter overflow");if(d.length<p)throw new Error(`arx: output (${d.length}) is shorter than data (${p})`);let h=[],g=a.length,b,y;if(g===32)h.push(b=yn(a)),y=wa;else if(g===16&&n)b=new Uint8Array(32),b.set(a),b.set(a,16),y=ba,h.push(b);else throw new Error(`arx: invalid 32-byte key, got length=${g}`);ur(c)||h.push(c=yn(c));let m=Se(b);if(r){if(c.length!==24)throw new Error("arx: extended nonce must be 24 bytes");r(y,m,Se(c.subarray(0,16)),m),c=c.subarray(16)}let v=16-o;if(v!==c.length)throw new Error(`arx: nonce must be ${v} or 16 bytes`);if(v!==12){let x=new Uint8Array(12);x.set(c,i?0:12-c.length),c=x,h.push(c)}let u=Se(c);return va(t,y,m,u,l,d,f,s),Ae(...h),d}}var W=(t,e)=>t[e++]&255|(t[e++]&255)<<8,gr=class{constructor(e){this.blockLen=16,this.outputLen=16,this.buffer=new Uint8Array(16),this.r=new Uint16Array(10),this.h=new Uint16Array(10),this.pad=new Uint16Array(8),this.pos=0,this.finished=!1,e=mn(e),Y(e,32);let n=W(e,0),r=W(e,2),o=W(e,4),i=W(e,6),s=W(e,8),a=W(e,10),c=W(e,12),l=W(e,14);this.r[0]=n&8191,this.r[1]=(n>>>13|r<<3)&8191,this.r[2]=(r>>>10|o<<6)&7939,this.r[3]=(o>>>7|i<<9)&8191,this.r[4]=(i>>>4|s<<12)&255,this.r[5]=s>>>1&8190,this.r[6]=(s>>>14|a<<2)&8191,this.r[7]=(a>>>11|c<<5)&8065,this.r[8]=(c>>>8|l<<8)&8191,this.r[9]=l>>>5&127;for(let d=0;d<8;d++)this.pad[d]=W(e,16+2*d)}process(e,n,r=!1){let o=r?0:2048,{h:i,r:s}=this,a=s[0],c=s[1],l=s[2],d=s[3],f=s[4],p=s[5],h=s[6],g=s[7],b=s[8],y=s[9],m=W(e,n+0),v=W(e,n+2),u=W(e,n+4),x=W(e,n+6),T=W(e,n+8),I=W(e,n+10),C=W(e,n+12),S=W(e,n+14),w=i[0]+(m&8191),E=i[1]+((m>>>13|v<<3)&8191),k=i[2]+((v>>>10|u<<6)&8191),O=i[3]+((u>>>7|x<<9)&8191),A=i[4]+((x>>>4|T<<12)&8191),_=i[5]+(T>>>1&8191),P=i[6]+((T>>>14|I<<2)&8191),M=i[7]+((I>>>11|C<<5)&8191),U=i[8]+((C>>>8|S<<8)&8191),D=i[9]+(S>>>5|o),N=0,H=N+w*a+E*(5*y)+k*(5*b)+O*(5*g)+A*(5*h);N=H>>>13,H&=8191,H+=_*(5*p)+P*(5*f)+M*(5*d)+U*(5*l)+D*(5*c),N+=H>>>13,H&=8191;let $=N+w*c+E*a+k*(5*y)+O*(5*b)+A*(5*g);N=$>>>13,$&=8191,$+=_*(5*h)+P*(5*p)+M*(5*f)+U*(5*d)+D*(5*l),N+=$>>>13,$&=8191;let F=N+w*l+E*c+k*a+O*(5*y)+A*(5*b);N=F>>>13,F&=8191,F+=_*(5*g)+P*(5*h)+M*(5*p)+U*(5*f)+D*(5*d),N+=F>>>13,F&=8191;let Z=N+w*d+E*l+k*c+O*a+A*(5*y);N=Z>>>13,Z&=8191,Z+=_*(5*b)+P*(5*g)+M*(5*h)+U*(5*p)+D*(5*f),N+=Z>>>13,Z&=8191;let ye=N+w*f+E*d+k*l+O*c+A*a;N=ye>>>13,ye&=8191,ye+=_*(5*y)+P*(5*b)+M*(5*g)+U*(5*h)+D*(5*p),N+=ye>>>13,ye&=8191;let be=N+w*p+E*f+k*d+O*l+A*c;N=be>>>13,be&=8191,be+=_*a+P*(5*y)+M*(5*b)+U*(5*g)+D*(5*h),N+=be>>>13,be&=8191;let we=N+w*h+E*p+k*f+O*d+A*l;N=we>>>13,we&=8191,we+=_*c+P*a+M*(5*y)+U*(5*b)+D*(5*g),N+=we>>>13,we&=8191;let xe=N+w*g+E*h+k*p+O*f+A*d;N=xe>>>13,xe&=8191,xe+=_*l+P*c+M*a+U*(5*y)+D*(5*b),N+=xe>>>13,xe&=8191;let ke=N+w*b+E*g+k*h+O*p+A*f;N=ke>>>13,ke&=8191,ke+=_*d+P*l+M*c+U*a+D*(5*y),N+=ke>>>13,ke&=8191;let Ce=N+w*y+E*b+k*g+O*h+A*p;N=Ce>>>13,Ce&=8191,Ce+=_*f+P*d+M*l+U*c+D*a,N+=Ce>>>13,Ce&=8191,N=(N<<2)+N|0,N=N+H|0,H=N&8191,N=N>>>13,$+=N,i[0]=H,i[1]=$,i[2]=F,i[3]=Z,i[4]=ye,i[5]=be,i[6]=we,i[7]=xe,i[8]=ke,i[9]=Ce}finalize(){let{h:e,pad:n}=this,r=new Uint16Array(10),o=e[1]>>>13;e[1]&=8191;for(let a=2;a<10;a++)e[a]+=o,o=e[a]>>>13,e[a]&=8191;e[0]+=o*5,o=e[0]>>>13,e[0]&=8191,e[1]+=o,o=e[1]>>>13,e[1]&=8191,e[2]+=o,r[0]=e[0]+5,o=r[0]>>>13,r[0]&=8191;for(let a=1;a<10;a++)r[a]=e[a]+o,o=r[a]>>>13,r[a]&=8191;r[9]-=8192;let i=(o^1)-1;for(let a=0;a<10;a++)r[a]&=i;i=~i;for(let a=0;a<10;a++)e[a]=e[a]&i|r[a];e[0]=(e[0]|e[1]<<13)&65535,e[1]=(e[1]>>>3|e[2]<<10)&65535,e[2]=(e[2]>>>6|e[3]<<7)&65535,e[3]=(e[3]>>>9|e[4]<<4)&65535,e[4]=(e[4]>>>12|e[5]<<1|e[6]<<14)&65535,e[5]=(e[6]>>>2|e[7]<<11)&65535,e[6]=(e[7]>>>5|e[8]<<8)&65535,e[7]=(e[8]>>>8|e[9]<<5)&65535;let s=e[0]+n[0];e[0]=s&65535;for(let a=1;a<8;a++)s=(e[a]+n[a]|0)+(s>>>16)|0,e[a]=s&65535;Ae(r)}update(e){dr(this),e=mn(e),Y(e);let{buffer:n,blockLen:r}=this,o=e.length;for(let i=0;i<o;){let s=Math.min(r-this.pos,o-i);if(s===r){for(;r<=o-i;i+=r)this.process(e,i);continue}n.set(e.subarray(i,i+s),this.pos),this.pos+=s,i+=s,this.pos===r&&(this.process(n,0,!1),this.pos=0)}return this}destroy(){Ae(this.h,this.r,this.buffer,this.pad)}digestInto(e){dr(this),Bo(e,this),this.finished=!0;let{buffer:n,h:r}=this,{pos:o}=this;if(o){for(n[o++]=1;o<16;o++)n[o]=0;this.process(n,0,!0)}this.finalize();let i=0;for(let s=0;s<8;s++)e[i++]=r[s]>>>0,e[i++]=r[s]>>>8;return e}digest(){let{buffer:e,outputLen:n}=this;this.digestInto(e);let r=e.slice(0,n);return this.destroy(),r}};function Ea(t){let e=(r,o)=>t(o).update(mn(r)).digest(),n=t(new Uint8Array(32));return e.outputLen=n.outputLen,e.blockLen=n.blockLen,e.create=r=>t(r),e}var Ho=Ea(t=>new gr(t));function qo(t,e,n,r,o,i=20){let s=t[0],a=t[1],c=t[2],l=t[3],d=e[0],f=e[1],p=e[2],h=e[3],g=e[4],b=e[5],y=e[6],m=e[7],v=o,u=n[0],x=n[1],T=n[2],I=s,C=a,S=c,w=l,E=d,k=f,O=p,A=h,_=g,P=b,M=y,U=m,D=v,N=u,H=x,$=T;for(let Z=0;Z<i;Z+=2)I=I+E|0,D=B(D^I,16),_=_+D|0,E=B(E^_,12),I=I+E|0,D=B(D^I,8),_=_+D|0,E=B(E^_,7),C=C+k|0,N=B(N^C,16),P=P+N|0,k=B(k^P,12),C=C+k|0,N=B(N^C,8),P=P+N|0,k=B(k^P,7),S=S+O|0,H=B(H^S,16),M=M+H|0,O=B(O^M,12),S=S+O|0,H=B(H^S,8),M=M+H|0,O=B(O^M,7),w=w+A|0,$=B($^w,16),U=U+$|0,A=B(A^U,12),w=w+A|0,$=B($^w,8),U=U+$|0,A=B(A^U,7),I=I+k|0,$=B($^I,16),M=M+$|0,k=B(k^M,12),I=I+k|0,$=B($^I,8),M=M+$|0,k=B(k^M,7),C=C+O|0,D=B(D^C,16),U=U+D|0,O=B(O^U,12),C=C+O|0,D=B(D^C,8),U=U+D|0,O=B(O^U,7),S=S+A|0,N=B(N^S,16),_=_+N|0,A=B(A^_,12),S=S+A|0,N=B(N^S,8),_=_+N|0,A=B(A^_,7),w=w+E|0,H=B(H^w,16),P=P+H|0,E=B(E^P,12),w=w+E|0,H=B(H^w,8),P=P+H|0,E=B(E^P,7);let F=0;r[F++]=s+I|0,r[F++]=a+C|0,r[F++]=c+S|0,r[F++]=l+w|0,r[F++]=d+E|0,r[F++]=f+k|0,r[F++]=p+O|0,r[F++]=h+A|0,r[F++]=g+_|0,r[F++]=b+P|0,r[F++]=y+M|0,r[F++]=m+U|0,r[F++]=v+D|0,r[F++]=u+N|0,r[F++]=x+H|0,r[F++]=T+$|0}function ka(t,e,n,r){let o=t[0],i=t[1],s=t[2],a=t[3],c=e[0],l=e[1],d=e[2],f=e[3],p=e[4],h=e[5],g=e[6],b=e[7],y=n[0],m=n[1],v=n[2],u=n[3];for(let T=0;T<20;T+=2)o=o+c|0,y=B(y^o,16),p=p+y|0,c=B(c^p,12),o=o+c|0,y=B(y^o,8),p=p+y|0,c=B(c^p,7),i=i+l|0,m=B(m^i,16),h=h+m|0,l=B(l^h,12),i=i+l|0,m=B(m^i,8),h=h+m|0,l=B(l^h,7),s=s+d|0,v=B(v^s,16),g=g+v|0,d=B(d^g,12),s=s+d|0,v=B(v^s,8),g=g+v|0,d=B(d^g,7),a=a+f|0,u=B(u^a,16),b=b+u|0,f=B(f^b,12),a=a+f|0,u=B(u^a,8),b=b+u|0,f=B(f^b,7),o=o+l|0,u=B(u^o,16),g=g+u|0,l=B(l^g,12),o=o+l|0,u=B(u^o,8),g=g+u|0,l=B(l^g,7),i=i+d|0,y=B(y^i,16),b=b+y|0,d=B(d^b,12),i=i+d|0,y=B(y^i,8),b=b+y|0,d=B(d^b,7),s=s+f|0,m=B(m^s,16),p=p+m|0,f=B(f^p,12),s=s+f|0,m=B(m^s,8),p=p+m|0,f=B(f^p,7),a=a+c|0,v=B(v^a,16),h=h+v|0,c=B(c^h,12),a=a+c|0,v=B(v^a,8),h=h+v|0,c=B(c^h,7);let x=0;r[x++]=o,r[x++]=i,r[x++]=s,r[x++]=a,r[x++]=y,r[x++]=m,r[x++]=v,r[x++]=u}var Ca=hr(qo,{counterRight:!1,counterLength:4,allowShortKeys:!1}),Sa=hr(qo,{counterRight:!1,counterLength:8,extendNonceFn:ka,allowShortKeys:!1});var Aa=new Uint8Array(16),$o=(t,e)=>{t.update(e);let n=e.length%16;n&&t.update(Aa.subarray(n))},Ta=new Uint8Array(32);function Fo(t,e,n,r,o){let i=t(e,n,Ta),s=Ho.create(i);o&&$o(s,o),$o(s,r);let a=Ro(r.length,o?o.length:0,!0);s.update(a);let c=s.digest();return Ae(i,a),c}var jo=t=>(e,n,r)=>({encrypt(i,s){let a=i.length;s=fr(a+16,s,!1),s.set(i);let c=s.subarray(0,-16);t(e,n,c,c,1);let l=Fo(t,e,n,c,r);return s.set(l,a),Ae(l),s},decrypt(i,s){s=fr(i.length-16,s,!1);let a=i.subarray(0,-16),c=i.subarray(-16),l=Fo(t,e,n,a,r);if(!Po(c,l))throw new Error("invalid tag");return s.set(i.subarray(0,-16)),t(e,n,s,s,1),Ae(l),s}}),Sd=pr({blockSize:64,nonceLength:12,tagLength:16},jo(Ca)),mr=pr({blockSize:64,nonceLength:24,tagLength:16},jo(Sa));var Ge=typeof globalThis=="object"&&"crypto"in globalThis?globalThis.crypto:void 0;function We(t){return t instanceof Uint8Array||ArrayBuffer.isView(t)&&t.constructor.name==="Uint8Array"}function ze(t){if(!Number.isSafeInteger(t)||t<0)throw new Error("positive integer expected, got "+t)}function Q(t,...e){if(!We(t))throw new Error("Uint8Array expected");if(e.length>0&&!e.includes(t.length))throw new Error("Uint8Array expected of length "+e+", got length="+t.length)}function Dt(t){if(typeof t!="function"||typeof t.create!="function")throw new Error("Hash should be wrapped by utils.createHasher");ze(t.outputLen),ze(t.blockLen)}function yt(t,e=!0){if(t.destroyed)throw new Error("Hash instance has been destroyed");if(e&&t.finished)throw new Error("Hash#digest() has already been called")}function Vo(t,e){Q(t);let n=e.outputLen;if(t.length<n)throw new Error("digestInto() expects output buffer of length at least "+n)}function de(...t){for(let e=0;e<t.length;e++)t[e].fill(0)}function wn(t){return new DataView(t.buffer,t.byteOffset,t.byteLength)}function pe(t,e){return t<<32-e|t>>>e}var Go=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",Ia=Array.from({length:256},(t,e)=>e.toString(16).padStart(2,"0"));function Xe(t){if(Q(t),Go)return t.toHex();let e="";for(let n=0;n<t.length;n++)e+=Ia[t[n]];return e}var Te={_0:48,_9:57,A:65,F:70,a:97,f:102};function Ko(t){if(t>=Te._0&&t<=Te._9)return t-Te._0;if(t>=Te.A&&t<=Te.F)return t-(Te.A-10);if(t>=Te.a&&t<=Te.f)return t-(Te.a-10)}function xn(t){if(typeof t!="string")throw new Error("hex string expected, got "+typeof t);if(Go)return Uint8Array.fromHex(t);let e=t.length,n=e/2;if(e%2)throw new Error("hex string expected, got unpadded hex of length "+e);let r=new Uint8Array(n);for(let o=0,i=0;o<n;o++,i+=2){let s=Ko(t.charCodeAt(i)),a=Ko(t.charCodeAt(i+1));if(s===void 0||a===void 0){let c=t[i]+t[i+1];throw new Error('hex string expected, got non-hex character "'+c+'" at index '+i)}r[o]=s*16+a}return r}function yr(t){if(typeof t!="string")throw new Error("string expected");return new Uint8Array(new TextEncoder().encode(t))}function Me(t){return typeof t=="string"&&(t=yr(t)),Q(t),t}function bt(...t){let e=0;for(let r=0;r<t.length;r++){let o=t[r];Q(o),e+=o.length}let n=new Uint8Array(e);for(let r=0,o=0;r<t.length;r++){let i=t[r];n.set(i,o),o+=i.length}return n}var mt=class{};function br(t){let e=r=>t().update(Me(r)).digest(),n=t();return e.outputLen=n.outputLen,e.blockLen=n.blockLen,e.create=()=>t(),e}function Ze(t=32){if(Ge&&typeof Ge.getRandomValues=="function")return Ge.getRandomValues(new Uint8Array(t));if(Ge&&typeof Ge.randomBytes=="function")return Uint8Array.from(Ge.randomBytes(t));throw new Error("crypto.getRandomValues must be defined")}function _a(t,e,n,r){if(typeof t.setBigUint64=="function")return t.setBigUint64(e,n,r);let o=BigInt(32),i=BigInt(4294967295),s=Number(n>>o&i),a=Number(n&i),c=r?4:0,l=r?0:4;t.setUint32(e+c,s,r),t.setUint32(e+l,a,r)}function zo(t,e,n){return t&e^~t&n}function Wo(t,e,n){return t&e^t&n^e&n}var Ht=class extends mt{constructor(e,n,r,o){super(),this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.blockLen=e,this.outputLen=n,this.padOffset=r,this.isLE=o,this.buffer=new Uint8Array(e),this.view=wn(this.buffer)}update(e){yt(this),e=Me(e),Q(e);let{view:n,buffer:r,blockLen:o}=this,i=e.length;for(let s=0;s<i;){let a=Math.min(o-this.pos,i-s);if(a===o){let c=wn(e);for(;o<=i-s;s+=o)this.process(c,s);continue}r.set(e.subarray(s,s+a),this.pos),this.pos+=a,s+=a,this.pos===o&&(this.process(n,0),this.pos=0)}return this.length+=e.length,this.roundClean(),this}digestInto(e){yt(this),Vo(e,this),this.finished=!0;let{buffer:n,view:r,blockLen:o,isLE:i}=this,{pos:s}=this;n[s++]=128,de(this.buffer.subarray(s)),this.padOffset>o-s&&(this.process(r,0),s=0);for(let f=s;f<o;f++)n[f]=0;_a(r,o-8,BigInt(this.length*8),i),this.process(r,0);let a=wn(e),c=this.outputLen;if(c%4)throw new Error("_sha2: outputLen should be aligned to 32bit");let l=c/4,d=this.get();if(l>d.length)throw new Error("_sha2: outputLen bigger than state");for(let f=0;f<l;f++)a.setUint32(4*f,d[f],i)}digest(){let{buffer:e,outputLen:n}=this;this.digestInto(e);let r=e.slice(0,n);return this.destroy(),r}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());let{blockLen:n,buffer:r,length:o,finished:i,destroyed:s,pos:a}=this;return e.destroyed=s,e.finished=i,e.length=o,e.pos=a,o%n&&e.buffer.set(r),e}clone(){return this._cloneInto()}},Ie=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]);var X=Uint32Array.from([1779033703,4089235720,3144134277,2227873595,1013904242,4271175723,2773480762,1595750129,1359893119,2917565137,2600822924,725511199,528734635,4215389547,1541459225,327033209]);var vn=BigInt(4294967295),Xo=BigInt(32);function Oa(t,e=!1){return e?{h:Number(t&vn),l:Number(t>>Xo&vn)}:{h:Number(t>>Xo&vn)|0,l:Number(t&vn)|0}}function Zo(t,e=!1){let n=t.length,r=new Uint32Array(n),o=new Uint32Array(n);for(let i=0;i<n;i++){let{h:s,l:a}=Oa(t[i],e);[r[i],o[i]]=[s,a]}return[r,o]}var wr=(t,e,n)=>t>>>n,xr=(t,e,n)=>t<<32-n|e>>>n,Ye=(t,e,n)=>t>>>n|e<<32-n,Qe=(t,e,n)=>t<<32-n|e>>>n,$t=(t,e,n)=>t<<64-n|e>>>n-32,Ft=(t,e,n)=>t>>>n-32|e<<64-n;function ve(t,e,n,r){let o=(e>>>0)+(r>>>0);return{h:t+n+(o/2**32|0)|0,l:o|0}}var Yo=(t,e,n)=>(t>>>0)+(e>>>0)+(n>>>0),Qo=(t,e,n,r)=>e+n+r+(t/2**32|0)|0,Jo=(t,e,n,r)=>(t>>>0)+(e>>>0)+(n>>>0)+(r>>>0),ei=(t,e,n,r,o)=>e+n+r+o+(t/2**32|0)|0,ti=(t,e,n,r,o)=>(t>>>0)+(e>>>0)+(n>>>0)+(r>>>0)+(o>>>0),ni=(t,e,n,r,o,i)=>e+n+r+o+i+(t/2**32|0)|0;var Ba=Uint32Array.from([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]),Ue=new Uint32Array(64),En=class extends Ht{constructor(e=32){super(64,e,8,!1),this.A=Ie[0]|0,this.B=Ie[1]|0,this.C=Ie[2]|0,this.D=Ie[3]|0,this.E=Ie[4]|0,this.F=Ie[5]|0,this.G=Ie[6]|0,this.H=Ie[7]|0}get(){let{A:e,B:n,C:r,D:o,E:i,F:s,G:a,H:c}=this;return[e,n,r,o,i,s,a,c]}set(e,n,r,o,i,s,a,c){this.A=e|0,this.B=n|0,this.C=r|0,this.D=o|0,this.E=i|0,this.F=s|0,this.G=a|0,this.H=c|0}process(e,n){for(let f=0;f<16;f++,n+=4)Ue[f]=e.getUint32(n,!1);for(let f=16;f<64;f++){let p=Ue[f-15],h=Ue[f-2],g=pe(p,7)^pe(p,18)^p>>>3,b=pe(h,17)^pe(h,19)^h>>>10;Ue[f]=b+Ue[f-7]+g+Ue[f-16]|0}let{A:r,B:o,C:i,D:s,E:a,F:c,G:l,H:d}=this;for(let f=0;f<64;f++){let p=pe(a,6)^pe(a,11)^pe(a,25),h=d+p+zo(a,c,l)+Ba[f]+Ue[f]|0,b=(pe(r,2)^pe(r,13)^pe(r,22))+Wo(r,o,i)|0;d=l,l=c,c=a,a=s+h|0,s=i,i=o,o=r,r=h+b|0}r=r+this.A|0,o=o+this.B|0,i=i+this.C|0,s=s+this.D|0,a=a+this.E|0,c=c+this.F|0,l=l+this.G|0,d=d+this.H|0,this.set(r,o,i,s,a,c,l,d)}roundClean(){de(Ue)}destroy(){this.set(0,0,0,0,0,0,0,0),de(this.buffer)}};var ri=Zo(["0x428a2f98d728ae22","0x7137449123ef65cd","0xb5c0fbcfec4d3b2f","0xe9b5dba58189dbbc","0x3956c25bf348b538","0x59f111f1b605d019","0x923f82a4af194f9b","0xab1c5ed5da6d8118","0xd807aa98a3030242","0x12835b0145706fbe","0x243185be4ee4b28c","0x550c7dc3d5ffb4e2","0x72be5d74f27b896f","0x80deb1fe3b1696b1","0x9bdc06a725c71235","0xc19bf174cf692694","0xe49b69c19ef14ad2","0xefbe4786384f25e3","0x0fc19dc68b8cd5b5","0x240ca1cc77ac9c65","0x2de92c6f592b0275","0x4a7484aa6ea6e483","0x5cb0a9dcbd41fbd4","0x76f988da831153b5","0x983e5152ee66dfab","0xa831c66d2db43210","0xb00327c898fb213f","0xbf597fc7beef0ee4","0xc6e00bf33da88fc2","0xd5a79147930aa725","0x06ca6351e003826f","0x142929670a0e6e70","0x27b70a8546d22ffc","0x2e1b21385c26c926","0x4d2c6dfc5ac42aed","0x53380d139d95b3df","0x650a73548baf63de","0x766a0abb3c77b2a8","0x81c2c92e47edaee6","0x92722c851482353b","0xa2bfe8a14cf10364","0xa81a664bbc423001","0xc24b8b70d0f89791","0xc76c51a30654be30","0xd192e819d6ef5218","0xd69906245565a910","0xf40e35855771202a","0x106aa07032bbd1b8","0x19a4c116b8d2d0c8","0x1e376c085141ab53","0x2748774cdf8eeb99","0x34b0bcb5e19b48a8","0x391c0cb3c5c95a63","0x4ed8aa4ae3418acb","0x5b9cca4f7763e373","0x682e6ff3d6b2b8a3","0x748f82ee5defb2fc","0x78a5636f43172f60","0x84c87814a1f0ab72","0x8cc702081a6439ec","0x90befffa23631e28","0xa4506cebde82bde9","0xbef9a3f7b2c67915","0xc67178f2e372532b","0xca273eceea26619c","0xd186b8c721c0c207","0xeada7dd6cde0eb1e","0xf57d4f7fee6ed178","0x06f067aa72176fba","0x0a637dc5a2c898a6","0x113f9804bef90dae","0x1b710b35131c471b","0x28db77f523047d84","0x32caab7b40c72493","0x3c9ebe0a15c9bebc","0x431d67c49c100d4c","0x4cc5d4becb3e42b6","0x597f299cfc657e2a","0x5fcb6fab3ad6faec","0x6c44198c4a475817"].map(t=>BigInt(t))),La=ri[0],Pa=ri[1],De=new Uint32Array(80),He=new Uint32Array(80),vr=class extends Ht{constructor(e=64){super(128,e,16,!1),this.Ah=X[0]|0,this.Al=X[1]|0,this.Bh=X[2]|0,this.Bl=X[3]|0,this.Ch=X[4]|0,this.Cl=X[5]|0,this.Dh=X[6]|0,this.Dl=X[7]|0,this.Eh=X[8]|0,this.El=X[9]|0,this.Fh=X[10]|0,this.Fl=X[11]|0,this.Gh=X[12]|0,this.Gl=X[13]|0,this.Hh=X[14]|0,this.Hl=X[15]|0}get(){let{Ah:e,Al:n,Bh:r,Bl:o,Ch:i,Cl:s,Dh:a,Dl:c,Eh:l,El:d,Fh:f,Fl:p,Gh:h,Gl:g,Hh:b,Hl:y}=this;return[e,n,r,o,i,s,a,c,l,d,f,p,h,g,b,y]}set(e,n,r,o,i,s,a,c,l,d,f,p,h,g,b,y){this.Ah=e|0,this.Al=n|0,this.Bh=r|0,this.Bl=o|0,this.Ch=i|0,this.Cl=s|0,this.Dh=a|0,this.Dl=c|0,this.Eh=l|0,this.El=d|0,this.Fh=f|0,this.Fl=p|0,this.Gh=h|0,this.Gl=g|0,this.Hh=b|0,this.Hl=y|0}process(e,n){for(let u=0;u<16;u++,n+=4)De[u]=e.getUint32(n),He[u]=e.getUint32(n+=4);for(let u=16;u<80;u++){let x=De[u-15]|0,T=He[u-15]|0,I=Ye(x,T,1)^Ye(x,T,8)^wr(x,T,7),C=Qe(x,T,1)^Qe(x,T,8)^xr(x,T,7),S=De[u-2]|0,w=He[u-2]|0,E=Ye(S,w,19)^$t(S,w,61)^wr(S,w,6),k=Qe(S,w,19)^Ft(S,w,61)^xr(S,w,6),O=Jo(C,k,He[u-7],He[u-16]),A=ei(O,I,E,De[u-7],De[u-16]);De[u]=A|0,He[u]=O|0}let{Ah:r,Al:o,Bh:i,Bl:s,Ch:a,Cl:c,Dh:l,Dl:d,Eh:f,El:p,Fh:h,Fl:g,Gh:b,Gl:y,Hh:m,Hl:v}=this;for(let u=0;u<80;u++){let x=Ye(f,p,14)^Ye(f,p,18)^$t(f,p,41),T=Qe(f,p,14)^Qe(f,p,18)^Ft(f,p,41),I=f&h^~f&b,C=p&g^~p&y,S=ti(v,T,C,Pa[u],He[u]),w=ni(S,m,x,I,La[u],De[u]),E=S|0,k=Ye(r,o,28)^$t(r,o,34)^$t(r,o,39),O=Qe(r,o,28)^Ft(r,o,34)^Ft(r,o,39),A=r&i^r&a^i&a,_=o&s^o&c^s&c;m=b|0,v=y|0,b=h|0,y=g|0,h=f|0,g=p|0,{h:f,l:p}=ve(l|0,d|0,w|0,E|0),l=a|0,d=c|0,a=i|0,c=s|0,i=r|0,s=o|0;let P=Yo(E,O,_);r=Qo(P,w,k,A),o=P|0}({h:r,l:o}=ve(this.Ah|0,this.Al|0,r|0,o|0)),{h:i,l:s}=ve(this.Bh|0,this.Bl|0,i|0,s|0),{h:a,l:c}=ve(this.Ch|0,this.Cl|0,a|0,c|0),{h:l,l:d}=ve(this.Dh|0,this.Dl|0,l|0,d|0),{h:f,l:p}=ve(this.Eh|0,this.El|0,f|0,p|0),{h,l:g}=ve(this.Fh|0,this.Fl|0,h|0,g|0),{h:b,l:y}=ve(this.Gh|0,this.Gl|0,b|0,y|0),{h:m,l:v}=ve(this.Hh|0,this.Hl|0,m|0,v|0),this.set(r,o,i,s,a,c,l,d,f,p,h,g,b,y,m,v)}roundClean(){de(De,He)}destroy(){de(this.buffer),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}};var oi=br(()=>new En);var ii=br(()=>new vr);var Cr=BigInt(0),kr=BigInt(1);function kn(t,e=""){if(typeof t!="boolean"){let n=e&&`"${e}"`;throw new Error(n+"expected boolean, got type="+typeof t)}return t}function qt(t,e,n=""){let r=We(t),o=t?.length,i=e!==void 0;if(!r||i&&o!==e){let s=n&&`"${n}" `,a=i?` of length ${e}`:"",c=r?`length=${o}`:`type=${typeof t}`;throw new Error(s+"expected Uint8Array"+a+", got "+c)}return t}function si(t){if(typeof t!="string")throw new Error("hex string expected, got "+typeof t);return t===""?Cr:BigInt("0x"+t)}function ai(t){return si(Xe(t))}function fe(t){return Q(t),si(Xe(Uint8Array.from(t).reverse()))}function Sr(t,e){return xn(t.toString(16).padStart(e*2,"0"))}function Cn(t,e){return Sr(t,e).reverse()}function J(t,e,n){let r;if(typeof e=="string")try{r=xn(e)}catch(i){throw new Error(t+" must be hex string or Uint8Array, cause: "+i)}else if(We(e))r=Uint8Array.from(e);else throw new Error(t+" must be hex string or Uint8Array");let o=r.length;if(typeof n=="number"&&o!==n)throw new Error(t+" of length "+n+" expected, got "+o);return r}function ci(t,e){if(t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t[r]^e[r];return n===0}function Ar(t){return Uint8Array.from(t)}var Er=t=>typeof t=="bigint"&&Cr<=t;function Ra(t,e,n){return Er(t)&&Er(e)&&Er(n)&&e<=t&&t<n}function wt(t,e,n,r){if(!Ra(e,n,r))throw new Error("expected valid "+t+": "+n+" <= n < "+r+", got "+e)}function li(t){let e;for(e=0;t>Cr;t>>=kr,e+=1);return e}var jt=t=>(kr<<BigInt(t))-kr;function Je(t,e,n={}){if(!t||typeof t!="object")throw new Error("expected valid options object");function r(o,i,s){let a=t[o];if(s&&a===void 0)return;let c=typeof a;if(c!==i||a===null)throw new Error(`param "${o}" is invalid: expected ${i}, got ${c}`)}Object.entries(e).forEach(([o,i])=>r(o,i,!1)),Object.entries(n).forEach(([o,i])=>r(o,i,!0))}var Tr=()=>{throw new Error("not implemented")};function Ir(t){let e=new WeakMap;return(n,...r)=>{let o=e.get(n);if(o!==void 0)return o;let i=t(n,...r);return e.set(n,i),i}}var re=BigInt(0),ee=BigInt(1),et=BigInt(2),fi=BigInt(3),ui=BigInt(4),hi=BigInt(5),Ma=BigInt(7),gi=BigInt(8),Ua=BigInt(9),mi=BigInt(16);function K(t,e){let n=t%e;return n>=re?n:e+n}function ce(t,e,n){let r=t;for(;e-- >re;)r*=r,r%=n;return r}function di(t,e){if(t===re)throw new Error("invert: expected non-zero number");if(e<=re)throw new Error("invert: expected positive modulus, got "+e);let n=K(t,e),r=e,o=re,i=ee,s=ee,a=re;for(;n!==re;){let l=r/n,d=r%n,f=o-s*l,p=i-a*l;r=n,n=d,o=s,i=a,s=f,a=p}if(r!==ee)throw new Error("invert: does not exist");return K(o,e)}function _r(t,e,n){if(!t.eql(t.sqr(e),n))throw new Error("Cannot find square root")}function yi(t,e){let n=(t.ORDER+ee)/ui,r=t.pow(e,n);return _r(t,r,e),r}function Da(t,e){let n=(t.ORDER-hi)/gi,r=t.mul(e,et),o=t.pow(r,n),i=t.mul(e,o),s=t.mul(t.mul(i,et),o),a=t.mul(i,t.sub(s,t.ONE));return _r(t,a,e),a}function Ha(t){let e=Oe(t),n=bi(t),r=n(e,e.neg(e.ONE)),o=n(e,r),i=n(e,e.neg(r)),s=(t+Ma)/mi;return(a,c)=>{let l=a.pow(c,s),d=a.mul(l,r),f=a.mul(l,o),p=a.mul(l,i),h=a.eql(a.sqr(d),c),g=a.eql(a.sqr(f),c);l=a.cmov(l,d,h),d=a.cmov(p,f,g);let b=a.eql(a.sqr(d),c),y=a.cmov(l,d,b);return _r(a,y,c),y}}function bi(t){if(t<fi)throw new Error("sqrt is not defined for small field");let e=t-ee,n=0;for(;e%et===re;)e/=et,n++;let r=et,o=Oe(t);for(;pi(o,r)===1;)if(r++>1e3)throw new Error("Cannot find square root: probably non-prime P");if(n===1)return yi;let i=o.pow(r,e),s=(e+ee)/et;return function(c,l){if(c.is0(l))return l;if(pi(c,l)!==1)throw new Error("Cannot find square root");let d=n,f=c.mul(c.ONE,i),p=c.pow(l,e),h=c.pow(l,s);for(;!c.eql(p,c.ONE);){if(c.is0(p))return c.ZERO;let g=1,b=c.sqr(p);for(;!c.eql(b,c.ONE);)if(g++,b=c.sqr(b),g===d)throw new Error("Cannot find square root");let y=ee<<BigInt(d-g-1),m=c.pow(f,y);d=g,f=c.sqr(m),p=c.mul(p,f),h=c.mul(h,m)}return h}}function $a(t){return t%ui===fi?yi:t%gi===hi?Da:t%mi===Ua?Ha(t):bi(t)}var _e=(t,e)=>(K(t,e)&ee)===ee,Fa=["create","isValid","is0","neg","inv","sqrt","sqr","eql","add","sub","mul","pow","div","addN","subN","mulN","sqrN"];function wi(t){let e={ORDER:"bigint",MASK:"bigint",BYTES:"number",BITS:"number"},n=Fa.reduce((r,o)=>(r[o]="function",r),e);return Je(t,n),t}function qa(t,e,n){if(n<re)throw new Error("invalid exponent, negatives unsupported");if(n===re)return t.ONE;if(n===ee)return e;let r=t.ONE,o=e;for(;n>re;)n&ee&&(r=t.mul(r,o)),o=t.sqr(o),n>>=ee;return r}function Sn(t,e,n=!1){let r=new Array(e.length).fill(n?t.ZERO:void 0),o=e.reduce((s,a,c)=>t.is0(a)?s:(r[c]=s,t.mul(s,a)),t.ONE),i=t.inv(o);return e.reduceRight((s,a,c)=>t.is0(a)?s:(r[c]=t.mul(s,r[c]),t.mul(s,a)),i),r}function pi(t,e){let n=(t.ORDER-ee)/et,r=t.pow(e,n),o=t.eql(r,t.ONE),i=t.eql(r,t.ZERO),s=t.eql(r,t.neg(t.ONE));if(!o&&!i&&!s)throw new Error("invalid Legendre symbol result");return o?1:i?0:-1}function xi(t,e){e!==void 0&&ze(e);let n=e!==void 0?e:t.toString(2).length,r=Math.ceil(n/8);return{nBitLength:n,nByteLength:r}}function Oe(t,e,n=!1,r={}){if(t<=re)throw new Error("invalid field: expected ORDER > 0, got "+t);let o,i,s=!1,a;if(typeof e=="object"&&e!=null){if(r.sqrt||n)throw new Error("cannot specify opts in two arguments");let p=e;p.BITS&&(o=p.BITS),p.sqrt&&(i=p.sqrt),typeof p.isLE=="boolean"&&(n=p.isLE),typeof p.modFromBytes=="boolean"&&(s=p.modFromBytes),a=p.allowedLengths}else typeof e=="number"&&(o=e),r.sqrt&&(i=r.sqrt);let{nBitLength:c,nByteLength:l}=xi(t,o);if(l>2048)throw new Error("invalid field: expected ORDER of <= 2048 bytes");let d,f=Object.freeze({ORDER:t,isLE:n,BITS:c,BYTES:l,MASK:jt(c),ZERO:re,ONE:ee,allowedLengths:a,create:p=>K(p,t),isValid:p=>{if(typeof p!="bigint")throw new Error("invalid field element: expected bigint, got "+typeof p);return re<=p&&p<t},is0:p=>p===re,isValidNot0:p=>!f.is0(p)&&f.isValid(p),isOdd:p=>(p&ee)===ee,neg:p=>K(-p,t),eql:(p,h)=>p===h,sqr:p=>K(p*p,t),add:(p,h)=>K(p+h,t),sub:(p,h)=>K(p-h,t),mul:(p,h)=>K(p*h,t),pow:(p,h)=>qa(f,p,h),div:(p,h)=>K(p*di(h,t),t),sqrN:p=>p*p,addN:(p,h)=>p+h,subN:(p,h)=>p-h,mulN:(p,h)=>p*h,inv:p=>di(p,t),sqrt:i||(p=>(d||(d=$a(t)),d(f,p))),toBytes:p=>n?Cn(p,l):Sr(p,l),fromBytes:(p,h=!0)=>{if(a){if(!a.includes(p.length)||p.length>l)throw new Error("Field.fromBytes: expected "+a+" bytes, got "+p.length);let b=new Uint8Array(l);b.set(p,n?0:b.length-p.length),p=b}if(p.length!==l)throw new Error("Field.fromBytes: expected "+l+" bytes, got "+p.length);let g=n?fe(p):ai(p);if(s&&(g=K(g,t)),!h&&!f.isValid(g))throw new Error("invalid field element: outside of range 0..ORDER");return g},invertBatch:p=>Sn(f,p),cmov:(p,h,g)=>g?h:p});return Object.freeze(f)}var An=BigInt(0),Lr=BigInt(1);function vi(t,e){let n=e.negate();return t?n:e}function Kt(t,e){let n=Sn(t.Fp,e.map(r=>r.Z));return e.map((r,o)=>t.fromAffine(r.toAffine(n[o])))}function Si(t,e){if(!Number.isSafeInteger(t)||t<=0||t>e)throw new Error("invalid window size, expected [1.."+e+"], got W="+t)}function Or(t,e){Si(t,e);let n=Math.ceil(e/t)+1,r=2**(t-1),o=2**t,i=jt(t),s=BigInt(t);return{windows:n,windowSize:r,mask:i,maxNumber:o,shiftBy:s}}function Ei(t,e,n){let{windowSize:r,mask:o,maxNumber:i,shiftBy:s}=n,a=Number(t&o),c=t>>s;a>r&&(a-=i,c+=Lr);let l=e*r,d=l+Math.abs(a)-1,f=a===0,p=a<0,h=e%2!==0;return{nextN:c,offset:d,isZero:f,isNeg:p,isNegF:h,offsetF:l}}function ja(t,e){if(!Array.isArray(t))throw new Error("array expected");t.forEach((n,r)=>{if(!(n instanceof e))throw new Error("invalid point at index "+r)})}function Ka(t,e){if(!Array.isArray(t))throw new Error("array of scalars expected");t.forEach((n,r)=>{if(!e.isValid(n))throw new Error("invalid scalar at index "+r)})}var Nr=new WeakMap,Ai=new WeakMap;function Br(t){return Ai.get(t)||1}function ki(t){if(t!==An)throw new Error("invalid wNAF")}var Tn=class{constructor(e,n){this.BASE=e.BASE,this.ZERO=e.ZERO,this.Fn=e.Fn,this.bits=n}_unsafeLadder(e,n,r=this.ZERO){let o=e;for(;n>An;)n&Lr&&(r=r.add(o)),o=o.double(),n>>=Lr;return r}precomputeWindow(e,n){let{windows:r,windowSize:o}=Or(n,this.bits),i=[],s=e,a=s;for(let c=0;c<r;c++){a=s,i.push(a);for(let l=1;l<o;l++)a=a.add(s),i.push(a);s=a.double()}return i}wNAF(e,n,r){if(!this.Fn.isValid(r))throw new Error("invalid scalar");let o=this.ZERO,i=this.BASE,s=Or(e,this.bits);for(let a=0;a<s.windows;a++){let{nextN:c,offset:l,isZero:d,isNeg:f,isNegF:p,offsetF:h}=Ei(r,a,s);r=c,d?i=i.add(vi(p,n[h])):o=o.add(vi(f,n[l]))}return ki(r),{p:o,f:i}}wNAFUnsafe(e,n,r,o=this.ZERO){let i=Or(e,this.bits);for(let s=0;s<i.windows&&r!==An;s++){let{nextN:a,offset:c,isZero:l,isNeg:d}=Ei(r,s,i);if(r=a,!l){let f=n[c];o=o.add(d?f.negate():f)}}return ki(r),o}getPrecomputes(e,n,r){let o=Nr.get(n);return o||(o=this.precomputeWindow(n,e),e!==1&&(typeof r=="function"&&(o=r(o)),Nr.set(n,o))),o}cached(e,n,r){let o=Br(e);return this.wNAF(o,this.getPrecomputes(o,e,r),n)}unsafe(e,n,r,o){let i=Br(e);return i===1?this._unsafeLadder(e,n,o):this.wNAFUnsafe(i,this.getPrecomputes(i,e,r),n,o)}createCache(e,n){Si(n,this.bits),Ai.set(e,n),Nr.delete(e)}hasCache(e){return Br(e)!==1}};function In(t,e,n,r){ja(n,t),Ka(r,e);let o=n.length,i=r.length;if(o!==i)throw new Error("arrays of points and scalars must have equal length");let s=t.ZERO,a=li(BigInt(o)),c=1;a>12?c=a-3:a>4?c=a-2:a>0&&(c=2);let l=jt(c),d=new Array(Number(l)+1).fill(s),f=Math.floor((e.BITS-1)/c)*c,p=s;for(let h=f;h>=0;h-=c){d.fill(s);for(let b=0;b<i;b++){let y=r[b],m=Number(y>>BigInt(h)&l);d[m]=d[m].add(n[b])}let g=s;for(let b=d.length-1,y=s;b>0;b--)y=y.add(d[b]),g=g.add(y);if(p=p.add(g),h!==0)for(let b=0;b<c;b++)p=p.double()}return p}function Ci(t,e,n){if(e){if(e.ORDER!==t)throw new Error("Field.ORDER must match order: Fp == p, Fn == n");return wi(e),e}else return Oe(t,{isLE:n})}function Ti(t,e,n={},r){if(r===void 0&&(r=t==="edwards"),!e||typeof e!="object")throw new Error(`expected valid ${t} CURVE object`);for(let c of["p","n","h"]){let l=e[c];if(!(typeof l=="bigint"&&l>An))throw new Error(`CURVE.${c} must be positive bigint`)}let o=Ci(e.p,n.Fp,r),i=Ci(e.n,n.Fn,r),a=["Gx","Gy","a",t==="weierstrass"?"b":"d"];for(let c of a)if(!o.isValid(e[c]))throw new Error(`CURVE.${c} must be valid field element of CURVE.Fp`);return e=Object.freeze(Object.assign({},e)),{CURVE:e,Fp:o,Fn:i}}var $e=BigInt(0),G=BigInt(1),Pr=BigInt(2),Va=BigInt(8);function Ga(t,e,n,r){let o=t.sqr(n),i=t.sqr(r),s=t.add(t.mul(e.a,o),i),a=t.add(t.ONE,t.mul(e.d,t.mul(o,i)));return t.eql(s,a)}function za(t,e={}){let n=Ti("edwards",t,e,e.FpFnLE),{Fp:r,Fn:o}=n,i=n.CURVE,{h:s}=i;Je(e,{},{uvRatio:"function"});let a=Pr<<BigInt(o.BYTES*8)-G,c=y=>r.create(y),l=e.uvRatio||((y,m)=>{try{return{isValid:!0,value:r.sqrt(r.div(y,m))}}catch{return{isValid:!1,value:$e}}});if(!Ga(r,i,i.Gx,i.Gy))throw new Error("bad curve params: generator point");function d(y,m,v=!1){let u=v?G:$e;return wt("coordinate "+y,m,u,a),m}function f(y){if(!(y instanceof g))throw new Error("ExtendedPoint expected")}let p=Ir((y,m)=>{let{X:v,Y:u,Z:x}=y,T=y.is0();m==null&&(m=T?Va:r.inv(x));let I=c(v*m),C=c(u*m),S=r.mul(x,m);if(T)return{x:$e,y:G};if(S!==G)throw new Error("invZ was invalid");return{x:I,y:C}}),h=Ir(y=>{let{a:m,d:v}=i;if(y.is0())throw new Error("bad point: ZERO");let{X:u,Y:x,Z:T,T:I}=y,C=c(u*u),S=c(x*x),w=c(T*T),E=c(w*w),k=c(C*m),O=c(w*c(k+S)),A=c(E+c(v*c(C*S)));if(O!==A)throw new Error("bad point: equation left != right (1)");let _=c(u*x),P=c(T*I);if(_!==P)throw new Error("bad point: equation left != right (2)");return!0});class g{constructor(m,v,u,x){this.X=d("x",m),this.Y=d("y",v),this.Z=d("z",u,!0),this.T=d("t",x),Object.freeze(this)}static CURVE(){return i}static fromAffine(m){if(m instanceof g)throw new Error("extended point not allowed");let{x:v,y:u}=m||{};return d("x",v),d("y",u),new g(v,u,G,c(v*u))}static fromBytes(m,v=!1){let u=r.BYTES,{a:x,d:T}=i;m=Ar(qt(m,u,"point")),kn(v,"zip215");let I=Ar(m),C=m[u-1];I[u-1]=C&-129;let S=fe(I),w=v?a:r.ORDER;wt("point.y",S,$e,w);let E=c(S*S),k=c(E-G),O=c(T*E-x),{isValid:A,value:_}=l(k,O);if(!A)throw new Error("bad point: invalid y coordinate");let P=(_&G)===G,M=(C&128)!==0;if(!v&&_===$e&&M)throw new Error("bad point: x=0 and x_0=1");return M!==P&&(_=c(-_)),g.fromAffine({x:_,y:S})}static fromHex(m,v=!1){return g.fromBytes(J("point",m),v)}get x(){return this.toAffine().x}get y(){return this.toAffine().y}precompute(m=8,v=!0){return b.createCache(this,m),v||this.multiply(Pr),this}assertValidity(){h(this)}equals(m){f(m);let{X:v,Y:u,Z:x}=this,{X:T,Y:I,Z:C}=m,S=c(v*C),w=c(T*x),E=c(u*C),k=c(I*x);return S===w&&E===k}is0(){return this.equals(g.ZERO)}negate(){return new g(c(-this.X),this.Y,this.Z,c(-this.T))}double(){let{a:m}=i,{X:v,Y:u,Z:x}=this,T=c(v*v),I=c(u*u),C=c(Pr*c(x*x)),S=c(m*T),w=v+u,E=c(c(w*w)-T-I),k=S+I,O=k-C,A=S-I,_=c(E*O),P=c(k*A),M=c(E*A),U=c(O*k);return new g(_,P,U,M)}add(m){f(m);let{a:v,d:u}=i,{X:x,Y:T,Z:I,T:C}=this,{X:S,Y:w,Z:E,T:k}=m,O=c(x*S),A=c(T*w),_=c(C*u*k),P=c(I*E),M=c((x+T)*(S+w)-O-A),U=P-_,D=P+_,N=c(A-v*O),H=c(M*U),$=c(D*N),F=c(M*N),Z=c(U*D);return new g(H,$,Z,F)}subtract(m){return this.add(m.negate())}multiply(m){if(!o.isValidNot0(m))throw new Error("invalid scalar: expected 1 <= sc < curve.n");let{p:v,f:u}=b.cached(this,m,x=>Kt(g,x));return Kt(g,[v,u])[0]}multiplyUnsafe(m,v=g.ZERO){if(!o.isValid(m))throw new Error("invalid scalar: expected 0 <= sc < curve.n");return m===$e?g.ZERO:this.is0()||m===G?this:b.unsafe(this,m,u=>Kt(g,u),v)}isSmallOrder(){return this.multiplyUnsafe(s).is0()}isTorsionFree(){return b.unsafe(this,i.n).is0()}toAffine(m){return p(this,m)}clearCofactor(){return s===G?this:this.multiplyUnsafe(s)}toBytes(){let{x:m,y:v}=this.toAffine(),u=r.toBytes(v);return u[u.length-1]|=m&G?128:0,u}toHex(){return Xe(this.toBytes())}toString(){return`<Point ${this.is0()?"ZERO":this.toHex()}>`}get ex(){return this.X}get ey(){return this.Y}get ez(){return this.Z}get et(){return this.T}static normalizeZ(m){return Kt(g,m)}static msm(m,v){return In(g,o,m,v)}_setWindowSize(m){this.precompute(m)}toRawBytes(){return this.toBytes()}}g.BASE=new g(i.Gx,i.Gy,G,c(i.Gx*i.Gy)),g.ZERO=new g($e,G,G,$e),g.Fp=r,g.Fn=o;let b=new Tn(g,o.BITS);return g.BASE.precompute(8),g}var _n=class{constructor(e){this.ep=e}static fromBytes(e){Tr()}static fromHex(e){Tr()}get x(){return this.toAffine().x}get y(){return this.toAffine().y}clearCofactor(){return this}assertValidity(){this.ep.assertValidity()}toAffine(e){return this.ep.toAffine(e)}toHex(){return Xe(this.toBytes())}toString(){return this.toHex()}isTorsionFree(){return!0}isSmallOrder(){return!1}add(e){return this.assertSame(e),this.init(this.ep.add(e.ep))}subtract(e){return this.assertSame(e),this.init(this.ep.subtract(e.ep))}multiply(e){return this.init(this.ep.multiply(e))}multiplyUnsafe(e){return this.init(this.ep.multiplyUnsafe(e))}double(){return this.init(this.ep.double())}negate(){return this.init(this.ep.negate())}precompute(e,n){return this.init(this.ep.precompute(e,n))}toRawBytes(){return this.toBytes()}};function Wa(t,e,n={}){if(typeof e!="function")throw new Error('"hash" function param is required');Je(n,{},{adjustScalarBytes:"function",randomBytes:"function",domain:"function",prehash:"function",mapToCurve:"function"});let{prehash:r}=n,{BASE:o,Fp:i,Fn:s}=t,a=n.randomBytes||Ze,c=n.adjustScalarBytes||(w=>w),l=n.domain||((w,E,k)=>{if(kn(k,"phflag"),E.length||k)throw new Error("Contexts/pre-hash are not supported");return w});function d(w){return s.create(fe(w))}function f(w){let E=u.secretKey;w=J("private key",w,E);let k=J("hashed private key",e(w),2*E),O=c(k.slice(0,E)),A=k.slice(E,2*E),_=d(O);return{head:O,prefix:A,scalar:_}}function p(w){let{head:E,prefix:k,scalar:O}=f(w),A=o.multiply(O),_=A.toBytes();return{head:E,prefix:k,scalar:O,point:A,pointBytes:_}}function h(w){return p(w).pointBytes}function g(w=Uint8Array.of(),...E){let k=bt(...E);return d(e(l(k,J("context",w),!!r)))}function b(w,E,k={}){w=J("message",w),r&&(w=r(w));let{prefix:O,scalar:A,pointBytes:_}=p(E),P=g(k.context,O,w),M=o.multiply(P).toBytes(),U=g(k.context,M,_,w),D=s.create(P+U*A);if(!s.isValid(D))throw new Error("sign failed: invalid s");let N=bt(M,s.toBytes(D));return qt(N,u.signature,"result")}let y={zip215:!0};function m(w,E,k,O=y){let{context:A,zip215:_}=O,P=u.signature;w=J("signature",w,P),E=J("message",E),k=J("publicKey",k,u.publicKey),_!==void 0&&kn(_,"zip215"),r&&(E=r(E));let M=P/2,U=w.subarray(0,M),D=fe(w.subarray(M,P)),N,H,$;try{N=t.fromBytes(k,_),H=t.fromBytes(U,_),$=o.multiplyUnsafe(D)}catch{return!1}if(!_&&N.isSmallOrder())return!1;let F=g(A,H.toBytes(),N.toBytes(),E);return H.add(N.multiplyUnsafe(F)).subtract($).clearCofactor().is0()}let v=i.BYTES,u={secretKey:v,publicKey:v,signature:2*v,seed:v};function x(w=a(u.seed)){return qt(w,u.seed,"seed")}function T(w){let E=S.randomSecretKey(w);return{secretKey:E,publicKey:h(E)}}function I(w){return We(w)&&w.length===s.BYTES}function C(w,E){try{return!!t.fromBytes(w,E)}catch{return!1}}let S={getExtendedPublicKey:p,randomSecretKey:x,isValidSecretKey:I,isValidPublicKey:C,toMontgomery(w){let{y:E}=t.fromBytes(w),k=u.publicKey,O=k===32;if(!O&&k!==57)throw new Error("only defined for 25519 and 448");let A=O?i.div(G+E,G-E):i.div(E-G,E+G);return i.toBytes(A)},toMontgomerySecret(w){let E=u.secretKey;qt(w,E);let k=e(w.subarray(0,E));return c(k).subarray(0,E)},randomPrivateKey:x,precompute(w=8,E=t.BASE){return E.precompute(w,!1)}};return Object.freeze({keygen:T,getPublicKey:h,sign:b,verify:m,utils:S,Point:t,lengths:u})}function Xa(t){let e={a:t.a,d:t.d,p:t.Fp.ORDER,n:t.n,h:t.h,Gx:t.Gx,Gy:t.Gy},n=t.Fp,r=Oe(e.n,t.nBitLength,!0),o={Fp:n,Fn:r,uvRatio:t.uvRatio},i={randomBytes:t.randomBytes,adjustScalarBytes:t.adjustScalarBytes,domain:t.domain,prehash:t.prehash,mapToCurve:t.mapToCurve};return{CURVE:e,curveOpts:o,hash:t.hash,eddsaOpts:i}}function Za(t,e){let n=e.Point;return Object.assign({},e,{ExtendedPoint:n,CURVE:t,nBitLength:n.Fn.BITS,nByteLength:n.Fn.BYTES})}function Ii(t){let{CURVE:e,curveOpts:n,hash:r,eddsaOpts:o}=Xa(t),i=za(e,n),s=Wa(i,r,o);return Za(t,s)}var Vt=BigInt(0),xt=BigInt(1),On=BigInt(2);function Ya(t){return Je(t,{adjustScalarBytes:"function",powPminus2:"function"}),Object.freeze({...t})}function _i(t){let e=Ya(t),{P:n,type:r,adjustScalarBytes:o,powPminus2:i,randomBytes:s}=e,a=r==="x25519";if(!a&&r!=="x448")throw new Error("invalid type");let c=s||Ze,l=a?255:448,d=a?32:56,f=BigInt(a?9:5),p=BigInt(a?121665:39081),h=a?On**BigInt(254):On**BigInt(447),g=a?BigInt(8)*On**BigInt(251)-xt:BigInt(4)*On**BigInt(445)-xt,b=h+g+xt,y=A=>K(A,n),m=v(f);function v(A){return Cn(y(A),d)}function u(A){let _=J("u coordinate",A,d);return a&&(_[31]&=127),y(fe(_))}function x(A){return fe(o(J("scalar",A,d)))}function T(A,_){let P=S(u(_),x(A));if(P===Vt)throw new Error("invalid private or public key received");return v(P)}function I(A){return T(A,m)}function C(A,_,P){let M=y(A*(_-P));return _=y(_-M),P=y(P+M),{x_2:_,x_3:P}}function S(A,_){wt("u",A,Vt,n),wt("scalar",_,h,b);let P=_,M=A,U=xt,D=Vt,N=A,H=xt,$=Vt;for(let Z=BigInt(l-1);Z>=Vt;Z--){let ye=P>>Z&xt;$^=ye,{x_2:U,x_3:N}=C($,U,N),{x_2:D,x_3:H}=C($,D,H),$=ye;let be=U+D,we=y(be*be),xe=U-D,ke=y(xe*xe),Ce=we-ke,ia=N+H,sa=N-H,Ao=y(sa*be),To=y(ia*xe),Io=Ao+To,_o=Ao-To;N=y(Io*Io),H=y(M*y(_o*_o)),U=y(we*ke),D=y(Ce*(we+y(p*Ce)))}({x_2:U,x_3:N}=C($,U,N)),{x_2:D,x_3:H}=C($,D,H);let F=i(D);return y(U*F)}let w={secretKey:d,publicKey:d,seed:d},E=(A=c(d))=>(Q(A,w.seed),A);function k(A){let _=E(A);return{secretKey:_,publicKey:I(_)}}return{keygen:k,getSharedSecret:(A,_)=>T(A,_),getPublicKey:A=>I(A),scalarMult:T,scalarMultBase:I,utils:{randomSecretKey:E,randomPrivateKey:E},GuBytes:m.slice(),lengths:w}}var Qa=BigInt(0),Be=BigInt(1),Oi=BigInt(2),Ja=BigInt(3),ec=BigInt(5),tc=BigInt(8),vt=BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed"),Gt={p:vt,n:BigInt("0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"),h:tc,a:BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec"),d:BigInt("0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3"),Gx:BigInt("0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a"),Gy:BigInt("0x6666666666666666666666666666666666666666666666666666666666666658")};function Li(t){let e=BigInt(10),n=BigInt(20),r=BigInt(40),o=BigInt(80),i=vt,a=t*t%i*t%i,c=ce(a,Oi,i)*a%i,l=ce(c,Be,i)*t%i,d=ce(l,ec,i)*l%i,f=ce(d,e,i)*d%i,p=ce(f,n,i)*f%i,h=ce(p,r,i)*p%i,g=ce(h,o,i)*h%i,b=ce(g,o,i)*h%i,y=ce(b,e,i)*d%i;return{pow_p_5_8:ce(y,Oi,i)*t%i,b2:a}}function Pi(t){return t[0]&=248,t[31]&=127,t[31]|=64,t}var Rr=BigInt("19681161376707505956807079304988542015446066515923890162744021073123829784752");function Dr(t,e){let n=vt,r=K(e*e*e,n),o=K(r*r*e,n),i=Li(t*o).pow_p_5_8,s=K(t*r*i,n),a=K(e*s*s,n),c=s,l=K(s*Rr,n),d=a===t,f=a===K(-t,n),p=a===K(-t*Rr,n);return d&&(s=c),(f||p)&&(s=l),_e(s,n)&&(s=K(-s,n)),{isValid:d||f,value:s}}var Ne=Oe(Gt.p,{isLE:!0}),nc=Oe(Gt.n,{isLE:!0}),rc={...Gt,Fp:Ne,hash:ii,adjustScalarBytes:Pi,uvRatio:Dr},ue=Ii(rc);var Hr=(()=>{let t=Ne.ORDER;return _i({P:t,type:"x25519",powPminus2:e=>{let{pow_p_5_8:n,b2:r}=Li(e);return K(ce(n,Ja,t)*r,t)},adjustScalarBytes:Pi})})();var Mr=Rr,oc=BigInt("25063068953384623474111414158702152701244531502492656460079210482610430750235"),ic=BigInt("54469307008909316920995813868745141605393597292927456921205312896311721017578"),sc=BigInt("1159843021668779879193775521855586647937357759715417654439879720876111806838"),ac=BigInt("40440834346308536858101042469323190826248399146238708352240133220865137265952"),Ni=t=>Dr(Be,t),cc=BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),Ur=t=>ue.Point.Fp.create(fe(t)&cc);function Bi(t){let{d:e}=Gt,n=vt,r=m=>Ne.create(m),o=r(Mr*t*t),i=r((o+Be)*sc),s=BigInt(-1),a=r((s-e*o)*r(o+e)),{isValid:c,value:l}=Dr(i,a),d=r(l*t);_e(d,n)||(d=r(-d)),c||(l=d),c||(s=o);let f=r(s*(o-Be)*ac-a),p=l*l,h=r((l+l)*a),g=r(f*oc),b=r(Be-p),y=r(Be+p);return new ue.Point(r(h*y),r(b*g),r(g*y),r(h*b))}function lc(t){Q(t,64);let e=Ur(t.subarray(0,32)),n=Bi(e),r=Ur(t.subarray(32,64)),o=Bi(r);return new Le(n.add(o))}var Le=class t extends _n{constructor(e){super(e)}static fromAffine(e){return new t(ue.Point.fromAffine(e))}assertSame(e){if(!(e instanceof t))throw new Error("RistrettoPoint expected")}init(e){return new t(e)}static hashToCurve(e){return lc(J("ristrettoHash",e,64))}static fromBytes(e){Q(e,32);let{a:n,d:r}=Gt,o=vt,i=x=>Ne.create(x),s=Ur(e);if(!ci(Ne.toBytes(s),e)||_e(s,o))throw new Error("invalid ristretto255 encoding 1");let a=i(s*s),c=i(Be+n*a),l=i(Be-n*a),d=i(c*c),f=i(l*l),p=i(n*r*d-f),{isValid:h,value:g}=Ni(i(p*f)),b=i(g*l),y=i(g*b*p),m=i((s+s)*b);_e(m,o)&&(m=i(-m));let v=i(c*y),u=i(m*v);if(!h||_e(u,o)||v===Qa)throw new Error("invalid ristretto255 encoding 2");return new t(new ue.Point(m,v,Be,u))}static fromHex(e){return t.fromBytes(J("ristrettoHex",e,32))}static msm(e,n){return In(t,ue.Point.Fn,e,n)}toBytes(){let{X:e,Y:n,Z:r,T:o}=this.ep,i=vt,s=y=>Ne.create(y),a=s(s(r+n)*s(r-n)),c=s(e*n),l=s(c*c),{value:d}=Ni(s(a*l)),f=s(d*a),p=s(d*c),h=s(f*p*o),g;if(_e(o*h,i)){let y=s(n*Mr),m=s(e*Mr);e=y,n=m,g=s(f*ic)}else g=p;_e(e*h,i)&&(n=s(-n));let b=s((r-n)*g);return _e(b,i)&&(b=s(-b)),Ne.toBytes(b)}equals(e){this.assertSame(e);let{X:n,Y:r}=this.ep,{X:o,Y:i}=e.ep,s=l=>Ne.create(l),a=s(n*i)===s(r*o),c=s(r*i)===s(n*o);return a||c}is0(){return this.equals(t.ZERO)}};Le.BASE=new Le(ue.Point.BASE);Le.ZERO=new Le(ue.Point.ZERO);Le.Fp=Ne;Le.Fn=nc;var Nn=class extends mt{constructor(e,n){super(),this.finished=!1,this.destroyed=!1,Dt(e);let r=Me(n);if(this.iHash=e.create(),typeof this.iHash.update!="function")throw new Error("Expected instance of class which extends utils.Hash");this.blockLen=this.iHash.blockLen,this.outputLen=this.iHash.outputLen;let o=this.blockLen,i=new Uint8Array(o);i.set(r.length>o?e.create().update(r).digest():r);for(let s=0;s<i.length;s++)i[s]^=54;this.iHash.update(i),this.oHash=e.create();for(let s=0;s<i.length;s++)i[s]^=106;this.oHash.update(i),de(i)}update(e){return yt(this),this.iHash.update(e),this}digestInto(e){yt(this),Q(e,this.outputLen),this.finished=!0,this.iHash.digestInto(e),this.oHash.update(e),this.oHash.digestInto(e),this.destroy()}digest(){let e=new Uint8Array(this.oHash.outputLen);return this.digestInto(e),e}_cloneInto(e){e||(e=Object.create(Object.getPrototypeOf(this),{}));let{oHash:n,iHash:r,finished:o,destroyed:i,blockLen:s,outputLen:a}=this;return e=e,e.finished=o,e.destroyed=i,e.blockLen=s,e.outputLen=a,e.oHash=n._cloneInto(e.oHash),e.iHash=r._cloneInto(e.iHash),e}clone(){return this._cloneInto()}destroy(){this.destroyed=!0,this.oHash.destroy(),this.iHash.destroy()}},Bn=(t,e,n)=>new Nn(t,e).update(n).digest();Bn.create=(t,e)=>new Nn(t,e);function dc(t,e,n){return Dt(t),n===void 0&&(n=new Uint8Array(t.outputLen)),Bn(t,Me(n),Me(e))}var $r=Uint8Array.from([0]),Ri=Uint8Array.of();function pc(t,e,n,r=32){Dt(t),ze(r);let o=t.outputLen;if(r>255*o)throw new Error("Length should be <= 255*HashLen");let i=Math.ceil(r/o);n===void 0&&(n=Ri);let s=new Uint8Array(i*o),a=Bn.create(t,e),c=a._cloneInto(),l=new Uint8Array(a.outputLen);for(let d=0;d<i;d++)$r[0]=d+1,c.update(d===0?Ri:l).update(n).update($r).digestInto(l),s.set(l,o*d),a._cloneInto(c);return a.destroy(),c.destroy(),de(l,$r),s.slice(0,r)}var Mi=(t,e,n,r,o)=>pc(t,dc(t,e,n),r,o);var Ln=oi;var fc="1.0";var Hi=[fc];var L={PARSE_ERROR:"parse_error",INVALID_MESSAGE:"invalid_message",VERSION_UNSUPPORTED:"version_unsupported",UNAUTHORIZED:"unauthorized",CAPABILITY_DENIED:"capability_denied",METHOD_NOT_FOUND:"method_not_found",VALIDATION_FAILED:"validation_failed",PAYLOAD_TOO_LARGE:"payload_too_large",RATE_LIMITED:"rate_limited",DEVICE_REVOKED:"device_revoked",SESSION_EXPIRED:"session_expired",PAIRING_EXPIRED:"pairing_expired",PAIRING_INVALID:"pairing_invalid",HOST_OFFLINE:"host_offline",TIMEOUT:"timeout",CANCELLED:"cancelled",INTERNAL:"internal",NOT_CONNECTED:"not_connected",PEER_LOST:"peer_lost",GRANT_EXPIRED:"grant_expired",CONSENT_DENIED:"consent_denied",CONSENT_TIMEOUT:"consent_timeout",POLICY_DENIED:"policy_denied"},uc=Object.values(L),R=class qr extends Error{code;data;constructor(e,n,r){super(n),this.name="CrosslinkError",this.code=e,this.data=r}toWire(){return{code:this.code,message:this.message,data:this.data}}static from(e){if(e instanceof qr)return e;let n=e instanceof Error?e.message:String(e);return new qr(L.INTERNAL,n)}static isInternal(e){return e===L.INTERNAL||e===L.PARSE_ERROR||e===L.INVALID_MESSAGE}};function zt(t){return jr(t)}function jr(t){if(t===null)return"null";let e=typeof t;if(e==="boolean")return t?"true":"false";if(e==="number"){if(!Number.isFinite(t))throw new TypeError("canonicalJson: non-finite number");return String(t)}if(e==="bigint")throw new TypeError("canonicalJson: bigint not allowed");if(e==="string")return JSON.stringify(t);if(Array.isArray(t)){let n="[";for(let r=0;r<t.length;r++)r>0&&(n+=","),n+=jr(t[r]);return n+"]"}if(e==="object"){let n=t,r=Object.keys(n).filter(i=>n[i]!==void 0).sort(),o="{";for(let i=0;i<r.length;i++)i>0&&(o+=","),o+=`${JSON.stringify(r[i])}:${jr(n[r[i]])}`;return o+"}"}throw new TypeError(`canonicalJson: unsupported type ${e}`)}var $i=typeof Buffer<"u";function j(t){if($i)return Buffer.from(t).toString("base64");let e="";for(let n=0;n<t.length;n++)e+=String.fromCharCode(t[n]);return btoa(e)}function V(t){if($i){let r=Buffer.from(t,"base64");return new Uint8Array(r)}let e=atob(t),n=new Uint8Array(e.length);for(let r=0;r<e.length;r++)n[r]=e.charCodeAt(r);return n}var Ui="0123456789abcdef";function Vr(t){let e="";for(let n=0;n<t.length;n++)e+=Ui[t[n]>>4]+Ui[t[n]&15];return e}function Fi(t){if(t.length%2!==0||/[^0-9a-f]/i.test(t))throw new TypeError("invalid hex string");let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.slice(n*2,n*2+2),16);return e}var hc=new TextEncoder,gc=new TextDecoder,Ee=t=>hc.encode(t),mc=t=>gc.decode(t);var q={HELLO:"hello",HELLO_OK:"hello_ok",REQ:"req",RES:"res",ERR:"err",CHUNK:"chunk",END:"end",EVT:"evt",SUB:"sub",UNSUB:"unsub",CANCEL:"cancel",PING:"ping",PONG:"pong",BYE:"bye"},Et=/^[A-Za-z0-9_-]{1,64}$/,yc=/^[A-Za-z0-9][A-Za-z0-9_.:@/-]{0,127}$/,Di=/^[A-Za-z0-9][A-Za-z0-9_.:@/-]{0,127}$/,bc=/^cd1_[0-9a-f]{32}$/,Fr=/^\d+\.\d+$/;function Gr(t){return wc(t(12))}function wc(t){let e="";for(let r=0;r<t.length;r++)e+=String.fromCharCode(t[r]);return(globalThis.btoa!==void 0?btoa(e):xc(e)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function xc(t){return Buffer.from(t).toString("base64")}function vc(t){if(typeof t!="object"||t===null)return"not-an-object";let e=t;if(typeof e.v!="string"||!Fr.test(e.v))return"bad-version";if(!Ec(e.t))return"bad-type";switch(e.t){case q.HELLO:{if(!Array.isArray(e.versions)||e.versions.length===0)return"hello-versions";if(!e.versions.every(n=>typeof n=="string"&&Fr.test(n)))return"hello-version-format";if(typeof e.deviceId!="string"||!bc.test(e.deviceId))return"hello-device-id";if(typeof e.appId!="string"||e.appId.length===0||e.appId.length>256)return"hello-app-id";break}case q.HELLO_OK:if(typeof e.version!="string"||!Fr.test(e.version))return"hello-ok-version";break;case q.REQ:if(typeof e.i!="string"||!Et.test(e.i))return"req-id";if(typeof e.m!="string"||!yc.test(e.m))return"req-method";if(e.idem!==void 0&&e.idem!==!0)return"req-idem-flag";break;case q.RES:case q.END:case q.CANCEL:if(typeof e.i!="string"||!Et.test(e.i))return`${e.t}-id`;break;case q.ERR:if(typeof e.i!="string"||!Et.test(e.i))return"err-id";if(typeof e.e!="object"||e.e===null||typeof e.e.code!="string"||!uc.includes(e.e.code)||typeof e.e.message!="string")return"err-body";break;case q.CHUNK:if(typeof e.i!="string"||!Et.test(e.i))return"chunk-id";if(typeof e.n!="number"||!Number.isInteger(e.n)||e.n<0)return"chunk-n";if(e.d===void 0)return"chunk-data-missing";break;case q.EVT:if(typeof e.s!="string"||!Et.test(e.s))return"evt-sub";if(typeof e.e!="string"||!Di.test(e.e))return"evt-name";break;case q.SUB:case q.UNSUB:if(typeof e.s!="string"||!Et.test(e.s))return`${e.t}-sub`;if(e.t===q.SUB&&(typeof e.e!="string"||!Di.test(e.e)))return"sub-event";break;case q.PING:case q.PONG:if(typeof e.ts!="number"||!Number.isFinite(e.ts))return"ts";break;case q.BYE:break}return null}function Ec(t){return typeof t=="string"&&Object.values(q).includes(t)}var ie={DEFAULT_MAX_FRAME_BYTES:4*1024*1024,MAX_FRAME_BYTES_HARD:16*1024*1024,DEFAULT_CHUNK_BYTES:256*1024,DEFAULT_REQUEST_TIMEOUT_MS:3e4,DEFAULT_MAX_INFLIGHT:32,DEFAULT_RATE_PER_SEC:50,PAIRING_CODE_TTL_MS:12e4,HEARTBEAT_INTERVAL_MS:15e3,HEARTBEAT_TIMEOUT_MS:45e3,CLOCK_SKEW_MS:12e4};function tt(t){return Ee(zt(t))}function qi(t){let e;try{e=typeof t=="string"?t:mc(t)}catch{throw new R(L.PARSE_ERROR,"payload is not valid UTF-8")}let n;try{n=JSON.parse(e)}catch{throw new R(L.PARSE_ERROR,"payload is not valid JSON")}if(Kr(n,0),n!==null&&typeof n=="object"&&typeof n.v=="string"&&!Hi.includes(n.v))throw new R(L.VERSION_UNSUPPORTED,"protocol version is not supported");let r=vc(n);if(r)throw new R(L.INVALID_MESSAGE,`invalid message: ${r}`);return n}function Kr(t,e){if(e>64)throw new R(L.INVALID_MESSAGE,"payload nesting exceeds 64");if(Array.isArray(t))for(let n of t)Kr(n,e+1);else if(t!==null&&typeof t=="object")for(let n of Object.values(t))Kr(n,e+1)}function ji(t){return t==="sinit"||t==="sack"||t==="srej"||t==="enc"||t==="oping"||t==="opong"||t==="bye"}var Pn=BigInt(4294967295),Ki=BigInt(32);function kc(t,e=!1){return e?{h:Number(t&Pn),l:Number(t>>Ki&Pn)}:{h:Number(t>>Ki&Pn)|0,l:Number(t&Pn)|0}}function Vi(t,e=!1){let n=t.length,r=new Uint32Array(n),o=new Uint32Array(n);for(let i=0;i<n;i++){let{h:s,l:a}=kc(t[i],e);[r[i],o[i]]=[s,a]}return[r,o]}function zr(t){return t instanceof Uint8Array||ArrayBuffer.isView(t)&&t.constructor.name==="Uint8Array"&&"BYTES_PER_ELEMENT"in t&&t.BYTES_PER_ELEMENT===1}var Rn=t=>t?`"${t}" `:"";function he(t,e=""){if(typeof t!="number")throw new TypeError(Rn(e)+"expected number, got "+typeof t);if(!Number.isSafeInteger(t)||t<0)throw new RangeError(Rn(e)+"expected integer >= 0, got "+t);return t}function zi(t,e=""){if(typeof t!="boolean")throw new TypeError(Rn(e)+"expected boolean, got type="+typeof t);return t}function se(t,e,n=""){if(zr(t)&&(e===void 0||t.length===e))return t;e!==void 0&&he(e,"length");let r=zr(t),o=e!==void 0?` of length ${e}`:"",i=r?`length=${t.length}`:`type=${typeof t}`,s=Rn(n)+"expected Uint8Array"+o+", got "+i;throw r?new RangeError(s):new TypeError(s)}var Cc=(t,e)=>{if(t===null||typeof t!="object"||Array.isArray(t))throw new TypeError((e==="object"?"":`"${e}" `)+"expected object, got type="+typeof t)},Gi=(t,e)=>{Cc(t,e);let n=Object.getPrototypeOf(t);if(n!==Object.prototype&&n!==null)throw new TypeError(`"${e}" expected plain object`);if(Object.hasOwn(t,"__proto__"))throw new TypeError(`"${e}.__proto__" is not allowed`)};function Wr(t,e=!0){if(t.destroyed)throw new Error("hash was destroyed");if(e&&t.finished)throw new Error("digest() was already called")}function Wi(t,e){se(t,void 0,"output");let n=e.outputLen;if(!(t.length>=n))throw new RangeError('"output" expected length >= '+n)}function Wt(t){return new Uint32Array(t.buffer,t.byteOffset,Math.floor(t.byteLength/4))}function Xr(...t){for(let e=0;e<t.length;e++)t[e].fill(0)}var Xi=new Uint8Array(new Uint32Array([287454020]).buffer)[0]===68;function Sc(t){return t<<24&4278190080|t<<8&16711680|t>>>8&65280|t>>>24&255}function Ac(t){for(let e=0;e<t.length;e++)t[e]=Sc(t[e]);return t}var kt=Xi?t=>t:Ac;function Zr(t,e,n="opts"){return Gi(t,"defaults"),e!==void 0&&Gi(e,n),Object.assign(Object.create(null),t,e)}function Yr(t,e={}){if(typeof t!="function")throw new TypeError('"hashCons" expected function, got type='+typeof t);e=Zr({},e,"info");let n=(o,i)=>t(i).update(o).digest(),r=t(void 0);return n.outputLen=r.outputLen,n.blockLen=r.blockLen,n.canXOF=r.canXOF,n.create=o=>t(o),Object.assign(n,e),Object.freeze(n)}function Zi(t=32){he(t,"bytesLength");let e=typeof globalThis=="object"?globalThis.crypto:null;if(typeof e?.getRandomValues!="function")throw new Error("crypto.getRandomValues must be defined");if(t>65536)throw new RangeError(`"bytesLength" expected <= 65536, got ${t}`);return e.getRandomValues(new Uint8Array(t))}var Xt=t=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,t])});var Tc=BigInt(0),Zt=BigInt(1),Ic=BigInt(2),_c=BigInt(7),Oc=BigInt(256),Nc=BigInt(113),Ji=[],es=[],ts=[];for(let t=0,e=Zt,n=1,r=0;t<24;t++){[n,r]=[r,(2*n+3*r)%5],Ji.push(2*(5*r+n)),es.push((t+1)*(t+2)/2%64);let o=Tc;for(let i=0;i<7;i++)e=(e<<Zt^(e>>_c)*Nc)%Oc,e&Ic&&(o^=Zt<<(Zt<<BigInt(i))-Zt);ts.push(o)}var ns=Vi(ts,!0),Bc=ns[0],Lc=ns[1],Pc=(t,e,n)=>t<<n|e>>>32-n,Rc=(t,e,n)=>e<<n|t>>>32-n,Mc=(t,e,n)=>e<<n-32|t>>>64-n,Uc=(t,e,n)=>t<<n-32|e>>>64-n,Yi=(t,e,n)=>n>32?Mc(t,e,n):Pc(t,e,n),Qi=(t,e,n)=>n>32?Uc(t,e,n):Rc(t,e,n),Ct=new Uint32Array(10);function Dc(t,e=24){if(!(t instanceof Uint32Array))throw new TypeError('"s" expected Uint32Array(50), got type='+typeof t);if(t.length!==50)throw new RangeError('"s" expected Uint32Array(50), got length='+t.length);if(he(e,"rounds"),e<1||e>24)throw new Error('"rounds" expected integer 1..24');for(let n=24-e;n<24;n++){for(let i=0;i<10;i++)Ct[i]=t[i]^t[i+10]^t[i+20]^t[i+30]^t[i+40];for(let i=0;i<10;i+=2){let s=(i+8)%10,a=(i+2)%10,c=Ct[a],l=Ct[a+1],d=Yi(c,l,1)^Ct[s],f=Qi(c,l,1)^Ct[s+1];for(let p=0;p<50;p+=10)t[i+p]^=d,t[i+p+1]^=f}let r=t[2],o=t[3];for(let i=0;i<24;i++){let s=es[i],a=Yi(r,o,s),c=Qi(r,o,s),l=Ji[i];r=t[l],o=t[l+1],t[l]=a,t[l+1]=c}for(let i=0;i<50;i+=10){let s=t[i],a=t[i+1],c=t[i+2],l=t[i+3];t[i]^=~t[i+2]&t[i+4],t[i+1]^=~t[i+3]&t[i+5],t[i+2]^=~t[i+4]&t[i+6],t[i+3]^=~t[i+5]&t[i+7],t[i+4]^=~t[i+6]&t[i+8],t[i+5]^=~t[i+7]&t[i+9],t[i+6]^=~t[i+8]&s,t[i+7]^=~t[i+9]&a,t[i+8]^=~s&c,t[i+9]^=~a&l}t[0]^=Bc[n],t[1]^=Lc[n]}Xr(Ct)}var Mn=class t{state;pos=0;posOut=0;finished=!1;state32;destroyed=!1;blockLen;suffix;outputLen;canXOF;enableXOF=!1;rounds;constructor(e,n,r,o=!1,i=24){if(he(e,"blockLen"),he(n,"suffix"),he(i,"rounds"),zi(o,"enableXOF"),this.blockLen=e,this.suffix=n,this.outputLen=r,this.enableXOF=o,this.canXOF=o,this.rounds=i,he(r,"outputLen"),!(0<e&&e<200))throw new Error('"blockLen" must be 1..199');this.state=new Uint8Array(200),this.state32=Wt(this.state)}clone(){return this._cloneInto()}keccak(){kt(this.state32),Dc(this.state32,this.rounds),kt(this.state32),this.posOut=0,this.pos=0}update(e){Wr(this),se(e);let{blockLen:n,state:r,state32:o}=this,i=e.length,s=n%4===0&&e.byteOffset%4===0,a=n/4,c=s&&i>=n?Wt(e):void 0;for(let l=0;l<i;){if(c!==void 0&&this.pos===0&&l%4===0&&i-l>=n){for(let f=0,p=l/4;f<a;f++)o[f]^=c[p+f];l+=n,this.pos=n,this.keccak();continue}let d=Math.min(n-this.pos,i-l);for(let f=0;f<d;f++)r[this.pos++]^=e[l++];this.pos===n&&this.keccak()}return this}finish(){if(this.finished)return;this.finished=!0;let{state:e,suffix:n,pos:r,blockLen:o}=this;e[r]^=n,(n&128)!==0&&r===o-1&&this.keccak(),e[o-1]^=128,this.keccak()}writeInto(e){Wr(this,!1),se(e),this.finish();let n=this.state,{blockLen:r}=this;for(let o=0,i=e.length;o<i;){this.posOut>=r&&this.keccak();let s=Math.min(r-this.posOut,i-o);e.set(n.subarray(this.posOut,this.posOut+s),o),this.posOut+=s,o+=s}return e}xofInto(e){if(!this.enableXOF)throw new Error("XOF is not enabled");return this.writeInto(e)}xof(e){return he(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(Wi(e,this),this.finished)throw new Error("digest() was already called");this.writeInto(e.length===this.outputLen?e:e.subarray(0,this.outputLen)),this.destroy()}digest(){let e=new Uint8Array(this.outputLen);return this.digestInto(e),e}destroy(){this.destroyed=!0,Xr(this.state)}_cloneInto(e){let{blockLen:n,suffix:r,outputLen:o,rounds:i,enableXOF:s}=this;return e||=new t(n,r,o,s,i),e.blockLen=n,e.state32.set(this.state32),e.pos=this.pos,e.posOut=this.posOut,e.finished=this.finished,e.rounds=i,e.suffix=r,e.outputLen=o,e.enableXOF=s,e.canXOF=this.canXOF,e.destroyed=this.destroyed,e}},rs=(t,e,n,r={})=>Yr(()=>new Mn(e,t,n),r);var os=rs(6,136,32,Xt(8));var is=rs(6,72,64,Xt(10));var ss=(t,e,n,r={})=>Yr((o={})=>(o=Zr({},o),new Mn(e,t,o.dkLen===void 0?n:o.dkLen,!0)),r),as=ss(31,168,16,Xt(11)),Un=ss(31,136,32,Xt(12));function Qr(t,e="object"){if(t===null||typeof t!="object"||Array.isArray(t))throw new TypeError(e==="object"?"expected valid options object":`"${e}" expected object, got type=${typeof t}`);return t}function cs(t,e={},n={},r="object"){Qr(t,r),Qr(e,"fields"),Qr(n,"optFields");function o(s,a,c){let l=r==="object"?`param "${String(s)}"`:`"${r}.${String(s)}"`,d=t[s];if(!Object.hasOwn(t,s)&&(c?d!==void 0:a!=="function"))throw new TypeError(`${l} is invalid: expected own property`);if(c&&d===void 0)return;let f=typeof d;if(f!==a||d===null)throw new TypeError(`${l} is invalid: expected ${a}, got ${f}`)}let i=(s,a)=>Object.entries(s).forEach(([c,l])=>o(c,l,a));i(e,!1),i(n,!0)}function Yt(t,e="n"){if(typeof t!="number")throw new TypeError(`wrong u32 integer "${e}": expected number, got type=${typeof t}`);if(!Number.isSafeInteger(t)||t<0||t>4294967295)throw new RangeError(`wrong u32 integer "${e}": expected 0..4294967295, got ${t}`);return t}function ds(t){return Yt(t,"x"),(t&t-1)===0&&t!==0}function Jr(t,e){if(Yt(t),typeof e!="number")throw new TypeError('"bits" expected number, got type='+typeof e);if(!Number.isSafeInteger(e)||e<0||e>32)throw new Error(`expected integer 0 <= bits <= 32, got ${e}`);let n=0;for(let r=0;r<e;r++,t>>>=1)n=n<<1|t&1;return n>>>0}function ps(t){return Yt(t),31-Math.clz32(t)}function ls(t){if(!t||typeof t!="object"||typeof t.length!="number")throw new TypeError('"values" expected array-like, got type='+typeof t);let e=t.length;if(!ds(e))throw new Error("expected positive power-of-two length, got "+e);let n=ps(e);for(let r=0;r<e;r++){let o=Jr(r,n);if(r<o){let i=t[r];t[r]=t[o],t[o]=i}}return t}var eo=(t,e)=>{cs(e,{N:"number",roots:"object",dit:"boolean"},{invertButterflies:"boolean",skipStages:"number",brp:"boolean"},"coreOpts");let{N:n,roots:r,dit:o,invertButterflies:i=!1,skipStages:s=0,brp:a=!0}=e;Yt(n,"coreOpts.N");let c=ps(n);if(!ds(n))throw new Error("FFT: Polynomial size should be power of two");Yt(s,"coreOpts.skipStages");let l=c===0?0:c-1;if(s>l)throw new Error(`FFT: wrong skipStages: expected 0 <= skipStages <= ${l}`);if(r.length!==n)throw new Error(`FFT: wrong roots length: expected ${n}, got ${r.length}`);let d=o!==i;return f=>{if(f.length!==n)throw new Error("FFT: wrong Polynomial length");o&&a&&ls(f);for(let p=0,h=1;p<c-s;p++){let g=o?p+1+s:c-p,b=1<<g,y=b>>1,m=n>>g;for(let v=0;v<n;v+=b)for(let u=0,x=h++;u<y;u++){let T=i?o?n-x:x:u*m,I=v+u,C=v+u+y,S=r[T],w=f[C],E=f[I];if(d){let k=t.mul(w,S);f[I]=t.add(E,k),f[C]=t.sub(E,k)}else i?(f[I]=t.add(w,E),f[C]=t.mul(t.sub(w,E),S)):(f[I]=t.add(E,w),f[C]=t.mul(t.sub(E,w),S))}}return!o&&a&&ls(f),f}};var ge=se;var Dn=Zi;function Hc(t,e,n=()=>{}){if(!Array.isArray(t))throw new TypeError(`"${e}" expected array, got type=${typeof t}`);for(let r=0;r<t.length;r++)n(t[r],`${e}[${r}]`);return t}function nt(t,e){if(t=se(t),e=se(e),t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t[r]^e[r];return n===0}function to(t){return new Uint8Array(se(t))}function Qt(t,...e){let n=o=>typeof o=="number"?o:o.bytesLen,r=e.reduce((o,i)=>o+n(i),0);return{bytesLen:r,encode:o=>{let i=new Uint8Array(r);for(let s=0,a=0;s<e.length;s++){let c=e[s],l=n(c),d=typeof c=="number"?o[s]:c.encode(o[s]);se(d,l,t),i.set(d,a),typeof c!="number"&&d.fill(0),a+=l}return i},decode:o=>{se(o,r,t);let i=[];for(let s of e){let a=n(s),c=o.subarray(0,a);i.push(typeof s=="number"?c:s.decode(c)),o=o.subarray(a)}return i}}}function Hn(t,e){let n=t,r=e*n.bytesLen;return{bytesLen:r,encode:o=>{let i=Hc(o,"u");if(i.length!==e)throw new RangeError(`vecCoder.encode: wrong length=${i.length}. Expected: ${e}`);let s=new Uint8Array(r);for(let a=0,c=0;a<i.length;a++){let l=n.encode(i[a]);s.set(l,c),l.fill(0),c+=l.length}return s},decode:o=>{se(o,r);let i=[];for(let s=0;s<o.length;s+=n.bytesLen)i.push(n.decode(o.subarray(s,s+n.bytesLen)));return i}}}function z(...t){for(let e of t)if(Array.isArray(e))for(let n of e)n.fill(0);else e.fill(0)}function $n(t){if(he(t,"bits"),t>32)throw new RangeError('"bits" expected <= 32, got '+t);return t===32?4294967295:~(-1<<t)>>>0}var fs=t=>{let{newPoly:e,N:n,Q:r,F:o,ROOT_OF_UNITY:i,brvBits:s,isKyber:a}=t,c=(u,x=r)=>{let T=u%x|0;return(T>=0?T|0:x+T|0)|0},l=(u,x=r)=>{let T=c(u,x)|0;return(T>x>>1?T-x|0:T)|0};function d(){let u=e(n);for(let x=0;x<n;x++){let T=Jr(x,s),I=BigInt(i)**BigInt(T)%BigInt(r);u[x]=Number(I)|0}return u}let f=d(),p=u=>{throw new Error("not implemented")},h=a?{add:(u,x)=>{let T=u+x|0;return T>=r?T-r|0:T},sub:(u,x)=>{let T=u-x|0;return T<0?T+r|0:T},mul:(u,x)=>c((u|0)*(x|0))|0,inv:p}:{add:(u,x)=>c((u|0)+(x|0))|0,sub:(u,x)=>c((u|0)-(x|0))|0,mul:(u,x)=>c((u|0)*(x|0))|0,inv:p},g={N:n,roots:f,invertButterflies:!0,skipStages:a?1:0,brp:!1},b=eo(h,{dit:!1,...g}),y=eo(h,{dit:!0,...g}),m={encode:u=>b(u),decode:u=>{y(u);for(let x=0;x<u.length;x++)u[x]=c(o*u[x]);return u}};return{mod:c,smod:l,nttZetas:f,NTT:{encode:u=>m.encode(u),decode:u=>m.decode(u)},bitsCoder:(u,x)=>{for(let C=0,S=0;C<n;C++)S+=u,S>32&&$n(S),S%=8;let T=$n(u),I=u*(n/8);return{bytesLen:I,encode:C=>{let S=C,w=new Uint8Array(I);for(let E=0,k=0,O=0,A=0;E<S.length;E++)for(k|=(x.encode(S[E])&T)<<O,O+=u;O>=8;O-=8,k>>=8)w[A++]=k&255;return w},decode:C=>{let S=e(n);for(let w=0,E=0,k=0,O=0;w<C.length;w++)for(E|=C[w]<<k,k+=8;k>=u;k-=u,E>>=u)S[O++]=x.decode(E&T);return S}}}}},$c=t=>(e,n)=>{n||(n=t.blockLen);let r=new Uint8Array(e.length+2);r.set(e);let o=e.length,i=new Uint8Array(n),s=t.create({}),a=0,c=0;return{stats:()=>({calls:a,xofs:c}),get:(l,d)=>(r[o+0]=l,r[o+1]=d,s.destroy(),s=t.create({}).update(r),a++,()=>(c++,s.xofInto(i))),clean:()=>{s.destroy(),z(i,r)}}},us=$c(as);var ne=256,te=3329,Fc=3303,qc=17,oe=fs({N:ne,Q:te,F:Fc,ROOT_OF_UNITY:qc,newPoly:t=>new Uint16Array(t),brvBits:7,isKyber:!0}),jc=Object.freeze({512:Object.freeze({N:ne,Q:te,K:2,ETA1:3,ETA2:2,du:10,dv:4,RBGstrength:128}),768:Object.freeze({N:ne,Q:te,K:3,ETA1:2,ETA2:2,du:10,dv:4,RBGstrength:192}),1024:Object.freeze({N:ne,Q:te,K:4,ETA1:2,ETA2:2,du:11,dv:5,RBGstrength:256})}),Kc=t=>{if(t>=12)return{encode:n=>n,decode:n=>n>=te?n-te:n};let e=2**(t-1);return{encode:n=>((n<<t)+te/2)/te,decode:n=>n*te+e>>>t}},Vc=t=>oe.bitsCoder(t,t===12?{encode:e=>e,decode:e=>e>=te?e-te:e}:{encode:e=>e,decode:e=>e}),Jt=t=>t===12?Vc(12):oe.bitsCoder(t,Kc(t));function rt(t,e){let n=t,r=e;for(let o=0;o<ne;o++){let i=n[o]+r[o];n[o]=i>=te?i-te:i}}function Gc(t,e){let n=t,r=e;for(let o=0;o<ne;o++){let i=n[o]-r[o];n[o]=i<0?i+te:i}}function zc(t,e,n,r,o){let i=oe.mod(oe.mod(e*r)*o+t*n),s=oe.mod(t*r+e*n);return{c0:i,c1:s}}function Fn(t,e){let n=t,r=e;for(let o=0;o<ne/2;o++){let i=oe.nttZetas[64+(o>>1)];o&1&&(i=-i);let{c0:s,c1:a}=zc(n[2*o+0],n[2*o+1],r[2*o+0],r[2*o+1],i);n[2*o+0]=s,n[2*o+1]=a}return n}function no(t){let e=t,n=new Uint16Array(ne);for(let r=0;r<ne;){let o=e();if(o.length%3)throw new Error("SampleNTT: unaligned block");for(let i=0;r<ne&&i+3<=o.length;i+=3){let s=(o[i+0]>>0|o[i+1]<<8)&4095,a=(o[i+1]>>4|o[i+2]<<4)&4095;s<te&&(n[r++]=s),r<ne&&a<te&&(n[r++]=a)}}return n}var Wc=(t,e)=>{let n=new Uint16Array(ne),r=Wt(t);kt(r);let o=0;for(let i=0,s=0,a=0,c=0;i<r.length;i++){let l=r[i];for(let d=0;d<32;d++)a+=l&1,l>>=1,o+=1,o===e?(c=a,a=0):o===2*e&&(n[s++]=oe.mod(c-a),a=0,o=0)}if(kt(r),o)throw new Error(`sampleCBD: leftover bits: ${o}`);return n};function en(t,e,n,r){return Wc(t(r*ne/4,e,n),r)}var Xc=t=>{let e=t,{K:n,PRF:r,XOF:o,HASH512:i,ETA1:s,ETA2:a,du:c,dv:l}=e,d=Jt(1),f=Jt(l),p=Jt(c),h=Qt("publicKey",Hn(Jt(12),n),32),g=Hn(Jt(12),n),b=Qt("ciphertext",Hn(p,n),f),y=Qt("seed",32,32),m=(v,u,x,T)=>{let I=[];for(let k=0;k<n;k++)I.push(oe.NTT.encode(en(r,T,k,s)));let C=new Uint16Array(ne),S=[];for(let k=0;k<n;k++){let O=en(r,T,n+k,a),A=new Uint16Array(ne);for(let _=0;_<n;_++){let P=u(k,_);rt(A,Fn(P,I[_]))}rt(O,oe.NTT.decode(A)),S.push(O),rt(C,Fn(v[k],I[k])),z(A)}let w=en(r,T,2*n,a);rt(w,oe.NTT.decode(C));let E=d.decode(x);return rt(E,w),z(v,I,C,w),b.encode([S,E])};return{secretCoder:g,lengths:{secretKey:g.bytesLen,publicKey:h.bytesLen,cipherText:b.bytesLen},keygen:v=>{ge(v,32,"seed");let u=new Uint8Array(33);u.set(v),u[32]=n;let x=i(u),[T,I]=y.decode(x),C=[],S=[];for(let k=0;k<n;k++)C.push(oe.NTT.encode(en(r,I,k,s)));let w=o(T);for(let k=0;k<n;k++){let O=oe.NTT.encode(en(r,I,n+k,s));for(let A=0;A<n;A++){let _=no(w.get(A,k));rt(O,Fn(_,C[A]))}S.push(O)}w.clean();let E={publicKey:h.encode([S,T]),secretKey:g.encode(C)};return z(T,I,C,S,u,x),E},encrypt:(v,u,x)=>{let[T,I]=h.decode(v),C=o(I),S=m(T,(w,E)=>no(C.get(w,E)),u,x);return C.clean(),S},prepare:v=>{let[u,x]=h.decode(v),T=o(x),I=[];for(let C=0;C<n;C++)for(let S=0;S<n;S++)I.push(no(T.get(C,S)));return T.clean(),{encrypt:(C,S)=>m(u.map(w=>w.slice()),(w,E)=>I[w*n+E].slice(),C,S),clean:()=>z(u,I)}},decrypt:(v,u)=>{let[x,T]=b.decode(v),I=g.decode(u),C=new Uint16Array(ne);for(let w=0;w<n;w++)rt(C,Fn(I[w],oe.NTT.encode(x[w])));Gc(T,oe.NTT.decode(C));let S=d.encode(T);return z(C,I,x,T),S}}};function Zc(t){let e=t,n=Xc(e),{HASH256:r,HASH512:o,KDF:i}=e,{secretCoder:s,lengths:a}=n,c=Qt("secretKey",a.secretKey,a.publicKey,32,32),l=32,d=64,f=(h,g)=>{let b=h.subarray(0,384*e.K),y=s.encode(s.decode(to(b))),m=nt(y,b);if(z(y),!m)throw new Error(`ML-KEM.${g}: wrong publicKey modulus`)},p=Object.freeze({...a,seed:64,msg:l,msgRand:l,secretKey:c.bytesLen});return Object.freeze({info:Object.freeze({type:"ml-kem"}),lengths:p,keygen:h=>{let g=h===void 0,b=g?Dn(d):h,y,m;try{ge(b,d,"seed");let v=n.keygen(b.subarray(0,32)),u=v.publicKey;y=v.secretKey,m=r(u);let x=c.encode([y,u,m,b.subarray(32)]);return{publicKey:u,secretKey:x}}finally{y!==void 0&&z(y),m!==void 0&&z(m),g&&z(b)}},getPublicKey:h=>{let[g,b,y,m]=c.decode(h);return Uint8Array.from(b)},encapsulate:(h,g)=>{let b=g===void 0,y=b?Dn(l):g,m;try{return ge(h,a.publicKey,"publicKey"),ge(y,l,"message"),f(h,"encapsulate"),m=o.create().update(y).update(r(h)).digest(),{cipherText:n.encrypt(h,y,m.subarray(32,64)),sharedSecret:m.subarray(0,32)}}finally{m!==void 0&&z(m.subarray(32)),b&&z(y)}},decapsulate:(h,g)=>{ge(g,c.bytesLen,"secretKey"),ge(h,a.cipherText,"cipherText");let b=c.bytesLen-96,y=b+32,m=r(g.subarray(b/2,y));if(!nt(m,g.subarray(y,y+32)))throw new Error("invalid secretKey: hash check failed");let[v,u,x,T]=c.decode(g),I=n.decrypt(h,v),C=o.create().update(I).update(x).digest(),S=C.subarray(0,32),w=n.encrypt(u,I,C.subarray(32,64)),E=nt(h,w),k=i.create({dkLen:32}).update(T).update(h).digest();return z(I,w,C.subarray(32),E?k:S),E?S:k},prepare:h=>{ge(h,a.publicKey,"publicKey"),f(h,"prepare");let g=to(h),b=r(g),y=n.prepare(g);return Object.freeze({publicKey:g,encapsulate:m=>{let v=m===void 0,u=v?Dn(l):m,x;try{return ge(u,l,"message"),x=o.create().update(u).update(b).digest(),{cipherText:y.encrypt(u,x.subarray(32,64)),sharedSecret:x.subarray(0,32)}}finally{x!==void 0&&z(x.subarray(32)),v&&z(u)}},decapsulate:(m,v)=>{ge(v,c.bytesLen,"secretKey"),ge(m,a.cipherText,"cipherText");let[u,x,T,I]=c.decode(v);if(!nt(x,g)||!nt(T,b))throw new Error("ML-KEM.decapsulate: secretKey does not match prepared publicKey");let C=n.decrypt(m,u),S=o.create().update(C).update(b).digest(),w=S.subarray(0,32),E=y.encrypt(C,S.subarray(32,64)),k=nt(m,E),O=i.create({dkLen:32}).update(I).update(m).digest();return z(C,E,S.subarray(32),k?O:w),k?w:O},clean:y.clean})}})}function Yc(t,e,n){return Un.create({dkLen:t}).update(e).update(new Uint8Array([n])).digest()}var Qc={HASH256:os,HASH512:is,KDF:Un,XOF:us,PRF:Yc},Jc=t=>Zc({...Qc,...t});var qn=Jc(jc[768]);function ot(t){return Ze(t)}function Kn(...t){let e=0;for(let o of t)e+=o.length;let n=new Uint8Array(e),r=0;for(let o of t)n.set(o,r),r+=o.length;return Ln(n)}function so(t,e,n,r){return Mi(Ln,t,e,Ee(n),r)}function Es(t,e){return ue.sign(t,e)}function ao(t,e,n){try{return ue.verify(t,e,n)}catch{return!1}}function ks(t){return Hr.getPublicKey(t)}function hs(t,e){let n=Hr.getSharedSecret(t,e),r=new Uint8Array(32),o=0;for(let i=0;i<32;i++)o|=n[i]^r[i];if(o===0)throw new Error("x25519: all-zero shared secret rejected");return n}function el(t,e,n,r){return mr(t,e,r).encrypt(n)}function tl(t,e,n,r){return mr(t,e,r).decrypt(n)}var nl="cd1_",gs=t=>new TextEncoder().encode(t),co=class tn{constructor(e){if(this.seed=e,e.length!==32)throw new TypeError("identity seed must be 32 bytes")}seed;_xPriv;_edPub;_xPub;static create(){return new tn(ot(32))}static fromSeed(e){return new tn(e)}get edPrivateKey(){return this.seed}get edPublicKey(){return this._edPub||(this._edPub=ue.getPublicKey(this.seed)),this._edPub}get xPrivateKey(){return this._xPriv||(this._xPriv=so(this.seed,new Uint8Array(0),"crosslink-x25519-v1",32)),this._xPriv}get xPublicKey(){return this._xPub||(this._xPub=ks(this.xPrivateKey)),this._xPub}get deviceId(){let e=Kn(gs("deviceId"),this.edPublicKey);return nl+Vr(e).slice(0,32)}get fingerprint(){return Vr(Kn(gs("fingerprint"),this.edPublicKey))}sign(e){return Es(e,this.edPrivateKey)}verifyOwn(e,n){return ao(e,n,this.edPublicKey)}toJson(){return{v:1,seed_b64:j(this.seed)}}static fromJson(e){if(!e||e.v!==1||typeof e.seed_b64!="string")throw new TypeError("invalid identity json");return tn.fromSeed(V(e.seed_b64))}static import(e){return tn.fromSeed(Fi(e))}};function rl(t,e,n){let[r,o]=ol(e,n)<=0?[e,n]:[n,e],i=so(il(r,o),Ee("crosslink-sas-v1"),t,6),s=[];for(let a=0;a<3;a++){let c=(i[a*2]<<8|i[a*2+1])%1e3;s.push(String(c).padStart(3,"0"))}return s.join(" ")}function ol(t,e){let n=Math.min(t.length,e.length);for(let r=0;r<n;r++)if(t[r]!==e[r])return t[r]-e[r];return t.length-e.length}function il(t,e){let n=new Uint8Array(t.length+e.length);return n.set(t),n.set(e,t.length),n}var ms={client:"c2h",host:"h2c"},ys={client:"h2c",host:"c2h"},sl=class{constructor(t,e,n){this.keys=t,this.role=e,this.maxFrameBytes=n}keys;role;maxFrameBytes;sendCounter=0;recvExpected=1;get role_(){return this.role}seal(t){this.sendCounter+=1;let e=this.sendCounter,n=ot(24),r=Ee(`${ms[this.role]}:${e}`),o=tt(t);if(o.length>this.maxFrameBytes)throw new R(L.PAYLOAD_TOO_LARGE,`message ${o.length}B exceeds session limit ${this.maxFrameBytes}B`);let i=this.keys[ms[this.role]],s=el(i,n,o,r);return{kind:"enc",n:e,iv:j(n),ct:j(s)}}open(t){if(typeof t.n!="number"||!Number.isInteger(t.n)||t.n!==this.recvExpected)throw new R(L.INVALID_MESSAGE,`replay/out-of-order frame: expected n=${this.recvExpected}, got ${String(t.n)}`);let e=t.n;this.recvExpected+=1;let n=V(t.iv);if(n.length!==24)throw new R(L.INVALID_MESSAGE,"bad nonce length");let r=Ee(`${ys[this.role]}:${e}`),o;try{o=tl(this.keys[ys[this.role]],n,V(t.ct),r)}catch{throw new R(L.INVALID_MESSAGE,"frame failed authentication")}return qi(o)}};var al="CLX1",cl="crosslink-session-keys-v1",ll="crosslink-session-keys-v1+ml-kem-768",Cs="ML-KEM-768";function Ss(t,e,n,r,o,i,s,a,c,l,d){let f=[al,t,e,n,r,o,i,s];return l&&f.push("pq",l.suite,l.ek),a!==void 0&&c!==void 0&&f.push(a,c),d&&f.push(d.suite,d.ct),Kn(new TextEncoder().encode(zt(f)))}function jn(t,e){let n=new Uint8Array(t.length+e.length);return n.set(t),n.set(e,t.length),n}function dl(t,e,n={}){let r=ot(32),o=ks(r),i=ot(32),s=n.hybridPq??"disabled",a=s==="disabled"?void 0:qn.keygen(),c=a?{suite:Cs,ek:j(a.publicKey)}:void 0,l=Es(Ss(e.appId,t.deviceId,j(t.xPublicKey),j(o),j(i),e.pubEdB64,e.pubXB64,void 0,void 0,c),t.edPrivateKey);return{init:{kind:"sinit",v:"1.0",app:e.appId,dev:t.deviceId,sx:j(t.xPublicKey),epk:j(o),nc:j(i),ts:n.nowMs??Date.now(),sig:j(l),...c?{pq:c}:{}},state:{ephPrivate:r,nonceClient:i,pqMode:s,...a?{pqSecretKey:a.secretKey}:{}}}}function pl(t,e,n,r,o){let i=V(r.epk),s=V(r.nh);if(i.length!==32||s.length!==32)throw new R(L.INVALID_MESSAGE,"bad accept key material lengths");if(e.pqMode==="required"&&!r.pq)throw new R(L.VERSION_UNSUPPORTED,"peer did not complete required hybrid PQ exchange");if(!!e.pqSecretKey!=!!r.pq)throw new R(L.INVALID_MESSAGE,"hybrid PQ negotiation does not match the offer");if(r.pq&&r.pq.suite!==Cs)throw new R(L.VERSION_UNSUPPORTED,"unsupported hybrid PQ suite");let a=Ss(n.app,n.dev,n.sx,n.epk,n.nc,j(o.pubEd),j(o.pubX),r.epk,r.nh,n.pq,r.pq);if(!ao(V(r.sig),a,o.pubEd))throw new R(L.UNAUTHORIZED,"host handshake signature invalid");let c=hs(e.ephPrivate,i),l=hs(t.xPrivateKey,o.pubX),d;try{if(r.pq&&e.pqSecretKey){let h=V(r.pq.ct);if(h.length!==qn.lengths.cipherText)throw new R(L.INVALID_MESSAGE,"bad ML-KEM ciphertext length");d=qn.decapsulate(h,e.pqSecretKey)}let f=d?jn(jn(c,l),d):jn(c,l),p=so(f,jn(e.nonceClient,s),d?ll:cl,64);return{c2h:p.slice(0,32),h2c:p.slice(32,64)}}finally{e.pqSecretKey?.fill(0),d?.fill(0)}}var bs={trace:10,debug:20,info:30,warn:40,error:50},fl=/(^|[._-])(secret|token|password|passphrase|seed|privkey|private_?key|auth|authorization|cookie|api_?key|credential)s?([._-]|$)/i,ro=512,ul=4;function hl(t){return oo(t,0)}function oo(t,e){if(e>ul)return"[depth]";if(t==null)return t;if(typeof t=="string")return t.length>ro?`${t.slice(0,ro)}\u2026[+${t.length-ro}]`:t;if(typeof t=="number"||typeof t=="boolean"||typeof t=="bigint")return typeof t=="bigint"?t.toString():t;if(t instanceof Error)return{name:t.name,message:t.message,code:t.code};if(t instanceof Uint8Array)return`[bytes ${t.length}]`;if(Array.isArray(t))return t.slice(0,32).map(n=>oo(n,e+1));if(typeof t=="object"){let n={};for(let[r,o]of Object.entries(t))n[r]=fl.test(r)?gl(o):oo(o,e+1);return n}return String(t)}function gl(t){return typeof t=="string"?`[redacted ${t.length}]`:t instanceof Uint8Array?`[redacted ${t.length}]`:"[redacted]"}var ml=class As{constructor(e,n,r){this.sink=e,this.minLevel=n,this.bindings=r}sink;minLevel;bindings;isEnabled(e){return bs[e]>=bs[this.minLevel]}child(e){return new As(this.sink,this.minLevel,{...this.bindings,...e})}trace(e,n){this.emit("trace",e,n)}debug(e,n){this.emit("debug",e,n)}info(e,n){this.emit("info",e,n)}warn(e,n){this.emit("warn",e,n)}error(e,n){this.emit("error",e,n)}emit(e,n,r){if(!this.isEnabled(e))return;let o;try{o={level:e,time:Date.now(),event:n,fields:hl({...this.bindings,...r??{}})}}catch{o={level:e,time:Date.now(),event:n,fields:{_logError:"field-serialization-failed"}}}try{this.sink(o)}catch{}}},Ts={trace(){},debug(){},info(){},warn(){},error(){},isEnabled:()=>!1,child:()=>Ts},st=Ts;function Vn(t,e={}){return new ml(t,e.level??"info",e.bindings??{})}function Is(t={}){let e=t.console??console;return Vn(r=>{let o=r.level==="error"?e.error:r.level==="warn"?e.warn:r.level==="info"?e.info:e.debug;if(t.json){o.call(e,JSON.stringify(r));return}let i=new Date(r.time).toISOString().slice(11,23),s=Object.entries(r.fields).map(([a,c])=>`${a}=${yl(c)}`).join(" ");o.call(e,`${i} ${r.level.toUpperCase().padEnd(5)} ${r.event}${s?` ${s}`:""}`)},t)}function yl(t){return typeof t=="string"?/\s/.test(t)?JSON.stringify(t):t:t==null?String(t):typeof t=="object"?JSON.stringify(t):String(t)}var _s=class{constructor(t=1e3){this.limit=t}limit;records=[];sink=t=>{this.records.push(t),this.records.length>this.limit&&this.records.shift()};logger(t={}){return Vn(this.sink,{level:"trace",...t})}matching(t){return this.records.filter(e=>e.event===t||e.event.startsWith(`${t}.`))}clear(){this.records.length=0}};var bl=class{constructor(t,e,n,r,o={}){if(this.transport=t,this.meta=n,this.handlers=r,this.maxFrameBytes=o.maxFrameBytes??ie.DEFAULT_MAX_FRAME_BYTES,this.cipher=new sl(e,n.role,this.maxFrameBytes),this.log=(o.logger??st).child({role:n.role,appId:n.appId,peer:n.peerDeviceId,transport:n.transportKind}),this.log.info("session.opened"),t.onData(i=>this.handleData(i)),t.onClose(i=>this.handleClosed(i)),o.heartbeat!==!1){let i=o.heartbeatIntervalMs??ie.HEARTBEAT_INTERVAL_MS,s=o.heartbeatTimeoutMs??ie.HEARTBEAT_TIMEOUT_MS;this.hbTimer=setInterval(()=>{let a=Date.now()-this.lastRecvAt;if(a>s){this.log.warn("session.heartbeat-timeout",{silentForMs:a,timeoutMs:s}),this.close("heartbeat-timeout");return}try{this.sendOuter({kind:"oping",ts:Date.now()})}catch{}},i)}}transport;meta;handlers;cipher;log;closed=!1;lastRecvAt=Date.now();hbTimer;maxFrameBytes;get isOpen(){return!this.closed}send(t){this.sendOuter(this.cipher.seal(t))}sendOuter(t){if(this.closed)throw Object.assign(new Error("session closed"),{code:"not_connected"});this.transport.send(tt(t))}handleData(t){this.lastRecvAt=Date.now();let e;try{let n=new TextDecoder().decode(t);e=JSON.parse(n)}catch{this.log.warn("session.malformed-frame",{bytes:t.length}),this.close("malformed-outer-frame");return}if(!ji(e.kind)){this.log.warn("session.unknown-frame-kind",{kind:String(e.kind).slice(0,32)}),this.close("unknown-outer-kind");return}switch(e.kind){case"enc":try{let n=this.cipher.open(e);this.handlers.onMessage(n,this)}catch(n){this.log.error("session.decrypt-failed",{error:n}),this.close(n)}break;case"oping":try{this.sendOuter({kind:"opong",ts:e.ts})}catch{}break;case"opong":break;case"bye":case"srej":this.handleClosed(e.reason??e.code??"bye");break;default:break}}close(t){if(!this.closed){this.closed=!0,this.log.info("session.closed",{reason:ws(t),initiator:"local"}),this.hbTimer&&clearInterval(this.hbTimer);try{let e={kind:"bye",reason:typeof t=="string"?t.slice(0,128):void 0};this.transport.send(tt(e))}catch{}try{this.transport.close(t)}catch{}this.handlers.onClose(t)}}handleClosed(t){this.closed||(this.closed=!0,this.log.info("session.closed",{reason:ws(t),initiator:"peer"}),this.hbTimer&&clearInterval(this.hbTimer),this.handlers.onClose(t))}};function ws(t){return t===void 0?"unspecified":typeof t=="string"?t.slice(0,128):t instanceof Error?`${t.name}: ${t.message.slice(0,96)}`:String(t).slice(0,128)}var wl=class{constructor(t,e=ie.DEFAULT_REQUEST_TIMEOUT_MS){this.session=t,this.defaultTimeoutMs=e}session;defaultTimeoutMs;pending=new Map;nextSeq=0;subs=new Map;get activeRequests(){return this.pending.size}async call(t,e,n={}){return await this.execute(t,e,void 0,n)}async stream(t,e,n,r={}){return await this.execute(t,e,n,r)}subscribe(t,e){let n=this.subs.get(t);if(!n){let r=`sub_${this.nextSeq++}_${xl(ot(6))}`;n={subId:r,cbs:new Set},this.subs.set(t,n),this.session.send({v:"1.0",t:q.SUB,s:r,e:t})}return n.cbs.add(e),()=>{let r=this.subs.get(t);if(r&&(r.cbs.delete(e),r.cbs.size===0)){this.subs.delete(t);try{this.session.send({v:"1.0",t:q.UNSUB,s:r.subId})}catch{}}}}subscribedEvents(){return[...this.subs.keys()]}cancel(t){try{this.session.send({v:"1.0",t:q.CANCEL,i:t})}catch{}}handleMessage(t){switch(t.t){case q.RES:{let e=this.pending.get(t.i);e&&(this.clearPending(t.i,e),e.resolve(t.p));break}case q.END:{let e=this.pending.get(t.i);e&&(this.clearPending(t.i,e),e.resolve(t.p));break}case q.ERR:{let e=this.pending.get(t.i);e&&(this.clearPending(t.i,e),e.reject(new R(t.e.code,t.e.message,t.e.data)));break}case q.CHUNK:{this.pending.get(t.i)?.onChunk?.(t.d,t.n);break}case q.EVT:{let e=this.subs.get(t.e);if(e&&t.s===e.subId)for(let n of[...e.cbs])try{n(t.p)}catch{}break}default:break}}failAll(t=L.PEER_LOST,e="connection lost"){for(let[n,r]of[...this.pending])this.clearPending(n,r),r.reject(new R(t,e))}execute(t,e,n,r){let o=Gr(()=>ot(12)),i=r.timeoutMs??this.defaultTimeoutMs;return new Promise((s,a)=>{let c={resolve:s,reject:a,onChunk:n};c.timer=setTimeout(()=>{this.pending.delete(o),c.reject(new R(L.TIMEOUT,`${t} timed out after ${i}ms`)),this.cancel(o)},i),this.pending.set(o,c);try{this.session.send({v:"1.0",t:q.REQ,i:o,m:t,...e!==void 0?{p:e}:{},ts:Date.now()})}catch{this.clearPending(o,c),c.reject(new R(L.NOT_CONNECTED,"session closed"))}})}clearPending(t,e){e.timer&&clearTimeout(e.timer),this.pending.delete(t)}};function xl(t){let e="";for(let n=0;n<t.length;n++)e+=String.fromCharCode(t[n]);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var xs={memory:"direct",lan:"direct","webrtc-direct":"direct","turn-relayed":"turn-relayed","crosslink-relayed":"crosslink-relayed"},Os=class{constructor(t){this.options=t,this.log=(t.logger??st).child({component:"client-link",appId:t.appId,device:t.identity.deviceId})}options;session;rpcClient;state="offline";attempts=0;reconnectTimer;stopped=!1;queue=[];desiredSubscriptions=new Map;activeSubscriptions=new Map;log;get currentState(){return this.state}get connected(){return this.session?.isOpen??!1}get rpc(){if(!this.rpcClient||!this.connected)throw new R(L.NOT_CONNECTED,"not connected");return this.rpcClient}async connect(){if(this.stopped&&(this.state==="revoked"||this.state==="unauthorized"||this.state==="protocol-incompatible"))throw new R(this.state==="revoked"?L.DEVICE_REVOKED:this.state==="unauthorized"?L.UNAUTHORIZED:L.VERSION_UNSUPPORTED,`cannot connect: ${this.state}`);this.stopped=!1,clearTimeout(this.reconnectTimer),this.setState("connecting");let t=[];for(let e of this.options.candidates){let n;this.log.debug("link.candidate-dial",{candidate:e.kind});try{n=await e.connect()}catch(o){this.log.debug("link.candidate-failed",{candidate:e.kind,error:o}),t.push(o);continue}if(await this.handshakeOver(n)){this.attempts=0,this.log.info("link.connected",{candidate:e.kind,queued:this.queue.length}),this.setState(xs[e.kind],{transport:e.kind}),this.flushQueue();return}if(this.stopped)break}if(this.stopped){let e=this.state==="revoked"?L.DEVICE_REVOKED:this.state==="unauthorized"?L.UNAUTHORIZED:this.state==="protocol-incompatible"?L.VERSION_UNSUPPORTED:L.HOST_OFFLINE;throw new R(e,`cannot connect: ${this.state}`)}throw this.log.warn("link.all-candidates-failed",{candidates:this.options.candidates.map(e=>e.kind),failures:t.length}),new R(L.HOST_OFFLINE,"no transport candidate succeeded")}close(){this.log.info("link.close-requested",{state:this.state}),this.stopped=!0,clearTimeout(this.reconnectTimer),this.rpcClient?.failAll(L.NOT_CONNECTED,"client closed"),this.session?.close("client-close"),this.session=void 0,this.rpcClient=void 0,this.setState("offline")}async upgrade(t){if(!this.connected)return this.log.debug("link.upgrade-skipped",{reason:"not-connected"}),!1;let e=this.session?.meta.transportKind;this.log.info("link.upgrade-attempt",{from:e,to:t.kind});let n;try{n=await t.connect()}catch(s){return this.log.warn("link.upgrade-dial-failed",{to:t.kind,error:s}),!1}let r=this.session,o=this.rpcClient;if(!await this.handshakeOver(n))return this.log.warn("link.upgrade-handshake-failed",{to:t.kind}),!1;o?.failAll(L.NOT_CONNECTED,"connection upgraded; retry this request");try{r?.close("upgraded")}catch{}return this.attempts=0,this.log.info("link.upgraded",{from:e,to:t.kind}),this.setState(xs[t.kind],{transport:t.kind,upgraded:!0}),!0}get transportKind(){return this.session?.meta.transportKind}markRevoked(){this.log.warn("link.revoked"),this.stopped=!0,clearTimeout(this.reconnectTimer),this.rpcClient?.failAll(L.DEVICE_REVOKED,"device revoked"),this.session?.close("revoked"),this.session=void 0,this.rpcClient=void 0,this.setState("revoked")}async call(t,e,n={}){if(!this.rpcClient||!this.connected)throw new R(L.NOT_CONNECTED,"not connected");return this.rpcClient.call(t,e,n)}stream(t,e,n,r={}){return!this.rpcClient||!this.connected?Promise.reject(new R(L.NOT_CONNECTED,"not connected")):this.rpcClient.stream(t,e,n,r)}subscribe(t,e){let n=this.desiredSubscriptions.get(t);n||(n=new Set,this.desiredSubscriptions.set(t,n)),n.add(e);let r=this.rpcClient&&this.connected?this.rpcClient.subscribe(t,e):void 0;return this.activeSubscriptions.set(e,()=>r?.()),()=>{let o=this.desiredSubscriptions.get(t);o?.delete(e),o&&o.size===0&&this.desiredSubscriptions.delete(t),this.activeSubscriptions.get(e)?.(),this.activeSubscriptions.delete(e),r=void 0}}queueIdempotent(t,e){return new Promise((n,r)=>{this.queue.push({method:t,input:e,resolve:n,reject:r})})}get queuedCount(){return this.queue.length}async handshakeOver(t){let e=this.options.hostRecord(),{init:n,state:r}=dl(this.options.identity,{appId:this.options.appId,pubEdB64:e.pubEdB64,pubXB64:e.pubXB64},{hybridPq:this.options.hybridPq??"disabled"}),o;try{o=await this.requestFrame(t,tt(n),this.options.handshakeTimeoutMs??1e4)}catch(i){this.log.warn("link.handshake-failed",{transport:t.kind,error:i});try{t.close("handshake-error")}catch{}return!1}if(o.kind==="sack"){let i=pl(this.options.identity,r,n,o,{pubEd:V(e.pubEdB64),pubX:V(e.pubXB64)});return this.attachSession(t,i),!0}if(o.kind==="srej"){let i=String(o.code??"");return this.log.warn("link.handshake-rejected",{code:i,message:String(o.message??"").slice(0,200)}),t.close(i),i===L.DEVICE_REVOKED?(this.markRevoked(),!1):i===L.VERSION_UNSUPPORTED?(this.setState("protocol-incompatible",{version:n.v}),this.stopped=!0,!1):(i===L.UNAUTHORIZED&&(this.setState("unauthorized"),this.stopped=!0),!1)}return this.log.warn("link.unexpected-handshake-frame",{kind:String(o.kind).slice(0,32)}),t.close("unexpected-handshake-frame"),!1}attachSession(t,e){let n=new bl(t,e,{role:"client",appId:this.options.appId,peerDeviceId:"host",transportKind:t.kind},{onMessage:r=>{this.rpcClient&&this.rpcClient.handleMessage(r),this.options.onMessage?.(r)},onClose:r=>{try{t.close("session-ended")}catch{}if(this.session!==n){this.log.debug("link.stale-session-closed",{reason:String(r??"")});return}if(r==="device-revoked"){this.markRevoked();return}this.handleDisconnect()}},{maxFrameBytes:this.options.maxFrameBytes??ie.DEFAULT_MAX_FRAME_BYTES,logger:this.options.logger});this.session=n,this.rpcClient=new wl(n,this.options.requestTimeoutMs);for(let[r,o]of this.desiredSubscriptions)for(let i of o){let s=this.rpcClient.subscribe(r,i);this.activeSubscriptions.set(i,s)}this.desiredSubscriptions.size>0&&this.log.debug("link.subscriptions-restored",{events:[...this.desiredSubscriptions.keys()]})}handleDisconnect(){if(this.log.info("link.disconnected",{state:this.state,stopped:this.stopped}),this.activeSubscriptions.clear(),this.rpcClient?.failAll(),this.session=void 0,this.rpcClient=void 0,this.stopped){this.state!=="revoked"&&this.state!=="unauthorized"&&this.state!=="protocol-incompatible"&&this.setState("offline");return}this.scheduleReconnect()}scheduleReconnect(){if(this.stopped)return;let t=++this.attempts,n=Math.min(3e4,500*2**Math.min(t,6))*(.7+Math.random()*.6);this.log.info("link.reconnect-scheduled",{attempt:t,delayMs:Math.round(n)}),this.setState("reconnecting",{attempt:t,delayMs:Math.round(n)}),this.reconnectTimer=setTimeout(()=>{this.stopped||this.connect().catch(()=>{this.stopped||this.scheduleReconnect()})},n)}async flushQueue(){for(;this.queue.length>0&&this.connected;){let t=this.queue.shift();try{let e=await this.rpcClient.call(t.method,t.input);t.resolve(e)}catch(e){this.log.warn("link.queued-call-failed",{method:t.method,error:e}),t.reject(R.from(e))}}}setState(t,e){(this.state!==t||e)&&(this.log.debug("link.state",{from:this.state,to:t,...e??{}}),this.state=t,this.options.onStateChange?.(t,e))}isFatal(t){return t.some(e=>e instanceof R&&[L.DEVICE_REVOKED,L.UNAUTHORIZED,L.VERSION_UNSUPPORTED].includes(e.code))}requestFrame(t,e,n){return new Promise((r,o)=>{let i=!1,s=setTimeout(()=>a(o,new Error("handshake timed out")),n);function a(c,l){i||(i=!0,clearTimeout(s),c===r&&l!==void 0?r(l):o(l instanceof Error?l:new Error(String(l??"handshake failed"))))}t.onData(c=>{try{let l=JSON.parse(new TextDecoder().decode(c));a(r,l)}catch(l){a(o,l instanceof Error?l:new Error("bad handshake frame"))}}),t.onClose(()=>a(o,new Error("transport closed during handshake"))),Promise.resolve().then(()=>t.send(e)).catch(c=>a(o,c instanceof Error?c:new Error(String(c))))})}},Ns="crosslink.system.deviceLink.create";var vl={claim:"crosslink-pair-claim-v1",challenge:"crosslink-pair-challenge-v1",complete:"crosslink-pair-complete-v1"};function io(t,e){return Ee(zt([vl[t],...e]))}var El=t=>new TextEncoder().encode(t);function kl(t){return Sl(Ln(Cl(El("fingerprint"),t)))}function Cl(t,e){let n=new Uint8Array(t.length+e.length);return n.set(t),n.set(e,t.length),n}function Sl(t){let e="";for(let n=0;n<t.length;n++)e+=(t[n]>>4).toString(16)+(t[n]&15).toString(16);return e}var Al=t=>new TextEncoder().encode(t);function Bs(t,e,n,r){let o=j(ot(32));return{claim:{kind:"pair_claim",ps:"",dev:t.deviceId,name:n.slice(0,64),pub_ed:j(t.edPublicKey),pub_x:j(t.xPublicKey),nonce:o,...r&&r.length>0?{caps_req:r}:{}},state:{claimNonce:o}}}function Ls(t,e,n){let r=io("claim",[n,String(e.dev),String(e.name),String(e.pub_ed),String(e.pub_x),String(e.nonce),Array.isArray(e.caps_req)?e.caps_req:null]);e.ps=n,e.sig=j(t.sign(r))}async function Ps(t,e,n,r,o){if(r.kind!=="pair_challenge")throw new R(L.INVALID_MESSAGE,"expected pair_challenge frame");let i=String(r.host_pub_ed??""),s=String(r.host_pub_x??""),a=String(r.nonce??""),c=Array.isArray(r.granted_caps)?r.granted_caps.map(String):[],l=r.link===!0;if(l!==(e.link===!0))throw new R(L.PAIRING_INVALID,"pairing URI mode does not match the host session");if(!kl(V(i)).startsWith(e.fp16))throw new R(L.UNAUTHORIZED,"host identity does not match the scanned QR fingerprint");let f=[String(r.ps??""),n.claimNonce,i,s,a,c];l&&f.push(!0);let p=io("challenge",f);if(!ao(V(String(r.sig??"")),p,V(i)))throw new R(L.UNAUTHORIZED,"host challenge signature invalid");if(String(r.claim_nonce??"")!==n.claimNonce)throw new R(L.PAIRING_INVALID,"challenge does not match our claim");let g=rl(e.appId,t.edPublicKey,V(i));if(!await o({sas:g,hostName:e.appName,hostFp16:e.fp16,grantedCaps:c,link:l}))throw new R(L.PAIRING_INVALID,"pairing cancelled by client user");let y=j(t.sign(io("complete",[String(r.ps),n.claimNonce,a]))),m={appId:e.appId,appName:e.appName,fingerprint:Tl(i),pubEdB64:i,pubXB64:s,grantedCaps:c,pairedAt:Date.now()};return{complete:{kind:"pair_complete",ps:String(r.ps),claim_nonce:n.claimNonce,challenge_nonce:a,sig:y},record:m}}function Tl(t){return Il(Kn(Al("fingerprint"),V(t)))}function Il(t){let e="";for(let n=0;n<t.length;n++)e+=(t[n]>>4).toString(16)+(t[n]&15).toString(16);return e}var _l=["lan","wan","sig","relay","tunnel"],vs=["lan","wan","sig","relay","tunnel"],Ol=["lan","wan"];function Nl(t){return Ol.includes(t)}var lo="~",Rs=",",Ms=8,Bl=512;function Us(t){return[...t].sort((e,n)=>vs.indexOf(e.kind)-vs.indexOf(n.kind))}function rn(t,e){return t.filter(n=>e.includes(n.kind))}function po(t,e){if(!e)return{usable:[...t],blocked:[]};let n;try{n=new URL(e).protocol==="https:"}catch{return{usable:[...t],blocked:[]}}if(!n)return{usable:[...t],blocked:[]};let r=[],o=[];for(let i of t){let s;try{s=new URL(i.url)}catch{o.push({endpoint:i,reason:"the endpoint URL could not be parsed"});continue}if(s.protocol==="wss:"||s.protocol==="https:"||Hs(s.hostname)){r.push(i);continue}o.push({endpoint:i,reason:`this page is served over https, and browsers block an insecure ${s.protocol} connection to ${s.hostname} as mixed content`})}return{usable:r,blocked:o}}function Ll(t){return Us($s(t)).slice(0,Ms).map(e=>`${e.kind}${lo}${e.url}`).join(Rs)}function Pl(t){let e=[];for(let n of t.split(Rs)){let r=n.trim();if(!r)continue;let o=r.indexOf(lo);if(o<=0)continue;let i=r.slice(0,o),s=r.slice(o+1);if(_l.includes(i)&&Ds(s,i)&&(e.push({kind:i,url:s}),e.length>=Ms))break}return Us($s(e))}function Ds(t,e){if(!t||t.length>Bl||!/^(wss?|https?):\/\//i.test(t))return!1;try{let n=new URL(t);return!(!n.hostname||e&&Nl(e)&&Hs(n.hostname))}catch{return!1}}function Hs(t){let e=t.replace(/^\[|\]$/g,"").toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="::1"||e==="0:0:0:0:0:0:0:1"||e==="0.0.0.0"?!0:/^127\./.test(e)}function Gn(t){return t.replace(/^http(s?):\/\//i,"ws$1://")}function zn(t){return t.replace(/^ws(s?):\/\//i,"http$1://")}function $s(t){let e=new Set,n=[];for(let r of t){let o=`${r.kind}${lo}${r.url}`;e.has(o)||(e.add(o),n.push(r))}return n}var nn="crosslink://pair",Rl=2;function Pe(t){let e=at(ct(t)),n=new URLSearchParams({v:String(Rl),e:Ll(e.endpoints),a:e.appId,n:e.appName,f:e.fp16,...e.transport?{t:e.transport}:{}});return`${nn}?${n.toString()}`}function Fs(t,e){let n=Pe(t),r=new URLSearchParams(n.slice(nn.length).replace(/^\?/,""));return r.set("c",e),r.set("l","1"),`${nn}?${r.toString()}`}function at(t){let e=Ml(t.trim()),n=Number(e.get("v"));if(n!==1&&n!==2)throw new Error(`unsupported pairing uri version: ${String(e.get("v"))}`);let r=Ul(e,n),o=e.get("c"),i=e.get("l")==="1",s=o?i?o.trim():Dl(o):"",a=e.get("a"),c=e.get("n")??a??"",l=(e.get("f")??"").toLowerCase(),d=e.get("t")??void 0;if(r.length===0)throw new Error("pairing uri advertises no usable endpoint (expected e=lan~ws://\u2026 / wan~ws://\u2026 / sig~wss://\u2026)");if(!a||a.length>256||!/^[\w.@:/-]+$/.test(a))throw new Error("pairing uri missing valid app id");if(!/^[0-9a-f]{16}$/.test(l))throw new Error("pairing uri missing fingerprint");let f=rn(r,["sig","relay","tunnel"]);return{version:n,endpoints:r,code:s,appId:a,appName:c,fp16:l,transport:d,signalingUrl:f[0]?.url,link:i}}function Ml(t){if(t.startsWith(nn))return new URLSearchParams(t.slice(nn.length).replace(/^\?/,""));if(!/^https?:\/\//i.test(t))throw new Error("not a crosslink pairing URI");let e=new URL(t);return["c","e","s","a"].some(r=>e.searchParams.get(r)!==null)?e.searchParams:new URLSearchParams(e.hash.replace(/^#/,""))}function Ul(t,e){if(e===2)return Pl(t.get("e")??"");let n=t.get("s")??"";return Ds(n,"sig")?[{kind:"sig",url:n}]:[]}function Dl(t){let e=t.replace(/\D/g,"");return e.length===9?e:t.trim()}var it="pair";function ct(t){let e=t.trim();if(!/^https?:\/\//i.test(e))return e;try{let n=new URL(e),r=new URLSearchParams(n.hash.replace(/^#/,"")),o=r.get(it);if(o||(r=n.searchParams,o=r.get(it)),o)return Hl(o)}catch{}return e}function Hl(t){try{return decodeURIComponent(t)}catch{return t}}var qs="crosslink.notification";var $l="crosslink.webrtc.offer",Fl=65536,ql=15e3,jl="crosslink";function Kl(t,e){let n=e.timeoutMs??ql;return{kind:"webrtc-direct",connect:async()=>{let r=e.createPeer();try{let o=r.createDataChannel(e.label??jl,{ordered:!0}),i=Gl(o,n);await r.setLocalDescription(await r.createOffer()),await zl(r,n);let s=r.localDescription?.sdp;if(!s)throw new Error("no local description after createOffer");let a=await t.call(e.method??$l,{type:"offer",sdp:s},{timeoutMs:n});return await r.setRemoteDescription(Vl(a,"answer")),await i,Wl(o)}catch(o){throw r.close(),o}}}}async function js(t,e){if(t.transportKind==="webrtc-direct")return!0;try{return await t.upgrade(Kl(t,e))}catch{return!1}}function Vl(t,e){let n=t;if(!n||typeof n.sdp!="string"||n.type!==e)throw Object.assign(new Error(`expected an SDP ${e}`),{code:"validation_failed"});if(n.sdp.length>Fl)throw Object.assign(new Error("SDP too large"),{code:"payload_too_large"});return{type:e,sdp:n.sdp}}function Gl(t,e){return t.readyState==="open"?Promise.resolve():new Promise((n,r)=>{let o=setTimeout(()=>r(new Error("datachannel open timeout")),e);t.onopen=()=>{clearTimeout(o),n()},t.onerror=()=>{clearTimeout(o),r(new Error("datachannel error"))}})}function zl(t,e){return t.iceGatheringState==="complete"?Promise.resolve():new Promise(n=>{let r=()=>{t.onicegatheringstatechange=null,n()};t.onicegatheringstatechange=()=>{t.iceGatheringState==="complete"&&r()},setTimeout(r,Math.min(2e3,e))})}function Wl(t,e="webrtc-direct"){let n,r,o=!1;t.binaryType="arraybuffer",t.onmessage=async s=>{if(o)return;let a=s.data,c=a instanceof ArrayBuffer?new Uint8Array(a):new Uint8Array(a.buffer,a.byteOffset,a.byteLength);n?.(c)};let i=()=>{o||(o=!0,r?.("dc-closed"))};return t.onclose=i,t.onerror=i,{kind:e,onData(s){n=s},onClose(s){r=s},async send(s){if(o||t.readyState!=="open")throw new Error("datachannel closed");t.send(s)},close(s){if(!o){try{t.close()}catch{}o=!0,r?.(typeof s=="string"?s:"closed")}}}}St();Zn();function Yl(t){if(t instanceof ArrayBuffer)return new Uint8Array(t);if(ArrayBuffer.isView(t)){let e=t;return new Uint8Array(e.buffer,e.byteOffset,e.byteLength)}if(typeof t=="string")throw new Error("unexpected text frame");if(typeof Blob<"u"&&t instanceof Blob)return t.arrayBuffer().then(e=>new Uint8Array(e));throw new Error("unsupported websocket message type")}function Tt(t,e){return new Promise((n,r)=>{let o=!1,i=setTimeout(()=>{if(!o){o=!0;try{t.close()}catch{}r(new Error(`connection timed out after ${e}ms`))}},e),s=()=>{o||(o=!0,clearTimeout(i),t.removeEventListener?.("error",a),n())},a=c=>{if(o)return;o=!0,clearTimeout(i);let l=c;r(new Error(`connection failed: ${l?.error?.message??l?.message??"unknown"}`))};t.addEventListener("open",s),t.addEventListener("error",a)})}function an(t,e){try{t.binaryType="arraybuffer"}catch{}let n,r,o=!1;t.addEventListener("message",s=>{if(o)return;let a;try{a=Yl(s.data)}catch{return}if(a instanceof Uint8Array){n?.(a);return}a.then(c=>{o||n?.(c)})});let i=()=>{o||(o=!0,r?.("ws-closed"))};return t.addEventListener("close",i),t.addEventListener("error",()=>{try{t.close()}catch{}i()}),{kind:e,onData(s){n=s},onClose(s){r=s},async send(s){if(o||t.readyState!==1)throw new Error("transport closed");t.send(s)},close(s){if(!o)try{t.close(1e3,typeof s=="string"?s.slice(0,100):void 0)}catch{}}}}var It=class t{constructor(e){this.ws=e;e.addEventListener("message",n=>{let r;try{r=JSON.parse(String(n.data))}catch{return}if(r.op==="pair_deliver"&&typeof r.blob=="string"){let o={from:String(r.from),blob:r.blob},i=this.resolvers.shift();i?i(o):this.queue.push(o);return}r.op==="error"&&this.fail(new Error(`signaling error: ${JSON.stringify(r.error??{})}`)),r.op==="pair_not_found"&&this.fail(new Error("PAIRING_EXPIRED: code not found or expired"))}),e.addEventListener("close",()=>this.fail(new Error("signaling connection closed"))),e.addEventListener("error",()=>this.fail(new Error("signaling connection failed")))}ws;queue=[];resolvers=[];failure;failureWaiters=[];static async open(e,n=1e4){let r=e(),o=new t(r);try{await Tt(r,n)}catch(i){throw new Error(`cannot reach signaling: ${String(i?.message??i)}`,{cause:i})}return o}async resolve(e){return this.send({op:"pair_resolve",code:e}),new Promise((n,r)=>{let o=i=>{let s;try{s=JSON.parse(String(i.data))}catch{return}s.op==="pair_found"?(this.ws.removeEventListener?.("message",o),n({psid:String(s.psid),hostConn:String(s.host_conn),app:s.app})):s.op==="pair_not_found"?(this.ws.removeEventListener?.("message",o),r(new Error("PAIRING_EXPIRED"))):s.op==="error"&&(this.ws.removeEventListener?.("message",o),r(new Error(String(s.error?.code??"error"))))};this.ws.addEventListener("message",o)})}sendTo(e,n){this.send({op:"pair_payload",to:e,blob:n})}nextBlob(e,n=15e3){let r=this.queue.findIndex(o=>o.from===e);return r>=0?Promise.resolve(this.queue.splice(r,1)[0].blob):new Promise((o,i)=>{let s=setTimeout(()=>{this.failureWaiters=this.failureWaiters.filter(c=>c!==a),i(new Error("timeout awaiting pairing reply"))},n),a=c=>{clearTimeout(s),i(c||new Error("peer closed"))};this.resolvers.push(c=>{clearTimeout(s),this.failureWaiters=this.failureWaiters.filter(l=>l!==a),c.from===e?o(c.blob):(this.queue.push(c),this.resolvers.push(l=>o(l.blob)),i(new Error("blob from unexpected sender")))}),this.failureWaiters.push(a),this.failure&&a(this.failure)})}close(){try{this.ws.close(1e3,"done")}catch{}}send(e){this.ws.send(JSON.stringify(e))}fail(e){this.failure=e;let n=this.failureWaiters.splice(0);for(let r of n)r(e)}};var _t=class t{constructor(e){this.ws=e;try{e.binaryType="arraybuffer"}catch{}e.addEventListener("message",n=>{let r=Ql(n.data);if(r){if(r instanceof Promise){r.then(o=>{o&&this.deliver(o)});return}this.deliver(r)}}),e.addEventListener("close",()=>this.fail(new Error("host closed the pairing connection"))),e.addEventListener("error",()=>this.fail(new Error("pairing connection failed")))}ws;kind="direct";queue=[];waiters=[];failure;static async open(e,n,r){let o=n(e),i=new t(o);try{await Tt(o,r)}catch(s){throw new Error(`cannot reach ${e}: ${String(s?.message??s)}`,{cause:s})}return i}async resolve(e){this.send({kind:"pair_hello",code:e});let n=await this.next();if(n.kind==="pair_error")throw new Error(Yn(n));if(n.kind!=="pair_ready"||typeof n.ps!="string")throw new Error(`unexpected reply to pair_hello: ${String(n.kind)}`);return{psid:n.ps,app:n.app}}send(e){this.ws.send(new TextEncoder().encode(JSON.stringify(e)))}next(){let e=this.queue.shift();return e?Promise.resolve(e):this.failure?Promise.reject(this.failure):new Promise((n,r)=>this.waiters.push({resolve:n,reject:r}))}close(){try{this.ws.close()}catch{}}deliver(e){let n=this.waiters.shift();n?n.resolve(e):this.queue.push(e)}fail(e){if(!this.failure){this.failure=e;for(let n of this.waiters.splice(0))n.reject(e)}}},Ot=class{constructor(e){this.peer=e}peer;kind="brokered";hostConn="";async resolve(e){let n=await this.peer.resolve(e);return this.hostConn=n.hostConn,{psid:n.psid,app:n.app}}send(e){this.peer.sendTo(this.hostConn,JSON.stringify(e))}async next(){let e=await this.peer.nextBlob(this.hostConn);return JSON.parse(e)}close(){this.peer.close()}};function Yn(t){let e=t.error;return`PAIRING_FAILED${e?.code?` (${e.code})`:""}: ${e?.message??"the host rejected the pairing attempt"}`}function Ql(t){if(typeof Blob<"u"&&t instanceof Blob)return t.text().then(uo);if(typeof t=="string")return uo(t);try{let e=t instanceof ArrayBuffer?new Uint8Array(t):ArrayBuffer.isView(t)?new Uint8Array(t.buffer,t.byteOffset,t.byteLength):null;return e?uo(new TextDecoder().decode(e)):null}catch{return null}}function uo(t){try{let e=JSON.parse(t);return e&&typeof e=="object"?e:null}catch{return null}}var go=class{file;constructor(e){this.file=new Fe(e,"crosslink.apps")}all(){return this.file.load({apps:{}}).apps}list(){return Object.values(this.all())}get(e){return this.all()[e]}upsert(e){let n=this.file.load({apps:{}});n.apps[e.appId]=e,this.file.save(n)}remove(e){let n=this.file.load({apps:{}});delete n.apps[e],this.file.save(n)}},me=class t{constructor(e={}){this.options=e;let n=e.storage??new lt;this.storage=n,this.appStore=new go(n),this.hints=new Fe(n,"crosslink.hints"),this.log=(e.logger??st).child({component:"crosslink-client"});let r="crosslink.identity.seed",o=n.get(r);o?this.identity=co.fromSeed(ed(o)):(this.identity=co.create(),n.set(r,j(this.identity.seed)),this.log.info("client.identity-created",{deviceId:this.identity.deviceId}))}options;log;identity;appStore;hints;link;storage;deviceCryptoStorage;stateListeners=new Set;static async create(e={}){if(e.storage)return new t(e);let n=e.logger??st,{storage:r,kind:o,encrypted:i}=await At({...e.allowPlaintextFallback!==void 0?{allowPlaintextFallback:e.allowPlaintextFallback}:{},onWriteError:(s,a)=>n.error("client.storage-write-failed",{key:a,error:s})});return i?n.info("client.storage",{kind:o}):n.warn("client.storage-not-encrypted",{kind:o,detail:"identity seed is stored in the clear; WebCrypto/IndexedDB unavailable"}),new t({...e,storage:r})}get deviceId(){return this.identity.deviceId}listApps(){return this.appStore.list()}forget(e){this.appStore.remove(e),this.link?.close(),this.link=void 0}async pairFromQr(e,n,r){if(!this.deviceCryptoStorage)try{let l=await Promise.resolve().then(()=>(zs(),Gs));this.deviceCryptoStorage=await l.SecureDeviceCryptoStorage.open()}catch(l){this.log.warn("client.device-crypto-init-failed",{error:String(l)})}let o=ct(e),i=at(o),s=r??i.code,a=i.link?s:s.replace(/\D/g,"");if(!i.link&&a.length!==9)throw new Error("A valid 9-digit pairing code is required");let c=await this.openPairingChannel(i);try{let l=await c.resolve(a);if(!l.app.fingerprint.startsWith(i.fp16))throw this.log.error("client.fingerprint-mismatch",{expected:i.fp16,got:l.app.fingerprint.slice(0,16)}),new Error("SECURITY: host fingerprint does not match the scanned code");let{claim:d,state:f}=Bs(this.identity,i,this.options.deviceName??"browser",n);Ls(this.identity,d,l.psid),c.send(d);let p=await c.next();if(p.kind==="pair_error")throw new Error(Yn(p));let h=x=>typeof window<"u"&&typeof window.confirm=="function"?window.confirm(`Confirm pairing with "${x.hostName}"?
2
+
3
+ SAS: ${x.sas}
4
+ Capabilities: ${x.grantedCaps.join(", ")||"(none)"}`):!0,g=this.options.onConfirmPairing??h,b=x=>x.link?!0:g(x),{complete:y,record:m}=await Ps(this.identity,i,f,p,b);c.send(y);let v=await c.next();if(v.kind==="pair_error")throw new Error(Yn(v));m.lastConnected=Date.now(),this.appStore.upsert(m),this.log.info("client.paired",{appId:m.appId,appName:m.appName,grantedCaps:m.grantedCaps,requestedCaps:n??null});let u=this.hints.load({});return u[m.appId]={endpoints:i.endpoints,relay:l.app.relay,lan:l.app.lan,signalingUrl:i.signalingUrl},this.hints.save(u),m}finally{c.close()}}async openPairingChannel(e){let n=this.options.dialTimeoutMs??1e4,r=[],{usable:o,blocked:i}=po(e.endpoints,this.pageOrigin());for(let s of i)r.push(`${s.endpoint.kind} ${s.endpoint.url}: ${s.reason}`),this.log.warn("client.endpoint-blocked",{endpoint:s.endpoint.kind,reason:s.reason});for(let s of rn(o,["lan","wan","tunnel"]))try{let a=await _t.open(Gn(s.url),c=>this.ws(c),n);return this.log.info("client.pairing-channel",{kind:"direct",endpoint:s.kind}),a}catch(a){r.push(`${s.kind} ${s.url}: ${String(a?.message??a)}`),this.log.debug("client.pairing-endpoint-failed",{endpoint:s.kind,error:String(a)})}for(let s of rn(o,["sig"])){let a=`${Gn(s.url).replace(/\/$/,"")}/ws`;try{let c=await It.open(()=>this.ws(a),n);return this.log.info("client.pairing-channel",{kind:"brokered",endpoint:s.kind}),new Ot(c)}catch(c){r.push(`sig ${a}: ${String(c?.message??c)}`)}}throw new Error(`cannot reach the host on any route from this QR code.
5
+ Tried:
6
+ ${r.join(`
7
+ `)}
8
+ `+(i.length>0&&o.length===0?"Every route this host advertises is insecure, and this page is served over https, so the browser refuses all of them. The host needs a wss:// route \u2014 a relay or a tunnel \u2014 to be reachable from an installable Crosslink origin.":'If the phone is not on the same Wi-Fi, the host needs remote access (networkMode: "remote") or a signaling service.'))}pageOrigin(){if(typeof location>"u")return null;let e=location.origin;return e&&e!=="null"?e:null}async connect(e){let n=e?this.appStore.get(e):this.appStore.list()[0];if(!n)throw new Error("no paired app"+(e?` for ${e}`:""));if(this.link&&this.link.currentState!=="offline"&&this.link.currentState!=="connecting"&&this.link.currentState!=="reconnecting")return this.rpc();let r=this.hints.load({}),o=r[n.appId]??{},i=null;if(o.signalingUrl){let p=this.options.fetch??globalThis.fetch;try{let h=await p(`${zn(o.signalingUrl).replace(/\/$/,"")}/apps/${encodeURIComponent(n.appId)}`);h.ok&&(i=await h.json(),r[n.appId]={...o,...i},this.hints.save(r))}catch(h){this.log.debug("client.presence-lookup-failed",{appId:n.appId,error:h})}}let s=i?.relay??o.relay,a=i?.lan??o.lan,c=[],l=new Set,d=(p,h)=>{if(!l.has(p)){if(l.add(p),po([{kind:"lan",url:p}],this.pageOrigin()).usable.length===0){this.log.warn("client.candidate-blocked",{kind:h,url:p});return}c.push({kind:"lan",connect:async()=>{let{ws:g,ready:b}=Ws(p,y=>this.ws(y),this.options.dialTimeoutMs??1e4);return await b,an(g,"lan")}}),this.log.debug("client.candidate",{kind:h,url:p})}};a&&a.host&&d(`ws://${a.host}:${a.port}`,"lan");for(let p of rn(o.endpoints??[],["lan","wan","tunnel"]))d(Gn(p.url),p.kind==="wan"?"wan":"lan");if(s&&this.options.networkMode!=="local-only"&&c.push({kind:"crosslink-relayed",connect:async()=>{let h=`${`${s.url.replace(/^http/,"ws").replace(/\/$/,"")}/ws`}?channel=${encodeURIComponent(s.channel)}&role=c`+(this.options.relayToken?`&auth=${encodeURIComponent(this.options.relayToken)}`:""),{ws:g,ready:b}=Ws(h,y=>this.ws(y),this.options.dialTimeoutMs??1e4);return await b,an(g,"crosslink-relayed")}}),c.length===0)throw this.log.warn("client.no-candidates",{appId:n.appId}),new Error("no known transport for this app; re-pair or check host is online");this.log.debug("client.connecting",{appId:n.appId,candidates:c.map(p=>p.kind)}),this.link?.close();let f=new Os({identity:this.identity,appId:n.appId,hostRecord:()=>{let p=this.appStore.get(n.appId);return p.lastConnected=Date.now(),p},candidates:c,autoReconnect:!0,requestTimeoutMs:this.options.requestTimeoutMs,onStateChange:(p,h)=>this.publishState(p,h),logger:this.options.logger,hybridPq:this.options.hybridPq??"disabled"});return this.link=f,await f.connect(),this.options.webrtc&&this.tryWebrtcUpgrade(f),f.rpc}async tryWebrtcUpgrade(e){if(this.options.webrtc?.createPeer)try{await js(e,{createPeer:this.options.webrtc.createPeer,timeoutMs:this.options.webrtc.timeoutMs})&&this.log.info("client.webrtc-upgraded")}catch(n){this.log.debug("client.webrtc-upgrade-failed",{error:n})}}rpc(){if(!this.link||!this.link.connected)throw new Error("not connected");return this.link.rpc}async createDeviceLink(){return this.rpc().call(Ns)}get connection(){return this.link}async pairFromBootstrap(e,n,r){return this.pairFromQr(e,n,r)}async pairWithCode(e,n,r){return this.pairFromQr(Pe(e),r,n)}get storageEncrypted(){return this.storage.encrypted===!0}ws(e){return(this.options.webSocket??Jl)(e)}get state(){return this.link?.currentState??"offline"}onStateChange(e){return this.stateListeners.add(e),()=>{this.stateListeners.delete(e)}}publishState(e,n){this.options.onStateChange?.(e,n);for(let r of[...this.stateListeners])try{r(e,n)}catch(o){this.log.warn("client.state-listener-failed",{error:String(o)})}}close(){this.link?.close(),this.link=void 0}};function Jl(t){let e=globalThis.WebSocket;if(typeof e!="function")throw new Error("WebSocket not available in this environment");return new e(t)}function Ws(t,e,n){let r=e(t);return{ws:r,ready:Tt(r,n)}}function ed(t){let e=td(t),n=new Uint8Array(e.length);for(let r=0;r<e.length;r++)n[r]=e.charCodeAt(r);return n}function td(t){return typeof atob=="function"?atob(t):Buffer.from(t,"base64").toString("binary")}var Qn=class t{constructor(e,n={}){this.url=e;let r=()=>{if(this.readyState===0){if(n.failToOpen){this.readyState=3,this.emit("error",{type:"error"}),this.emit("close",{code:1006,reason:"failed to open"});return}this.readyState=1,this.emit("open",{type:"open"})}};n.openDelayMs&&n.openDelayMs>0?setTimeout(r,n.openDelayMs):queueMicrotask(r)}url;readyState=0;binaryType="arraybuffer";sent=[];listeners=new Map;peer;static pair(e="ws://a",n="ws://b"){let r=new t(e),o=new t(n);return r.attach(o),o.attach(r),[r,o]}attach(e){this.peer=e}addEventListener(e,n){let r=this.listeners.get(e);r||(r=new Set,this.listeners.set(e,r)),r.add(n)}removeEventListener(e,n){this.listeners.get(e)?.delete(n)}send(e){if(this.readyState!==1)throw new Error("mock socket is not open");this.sent.push(e),queueMicrotask(()=>this.peer?.deliver(e))}close(e=1e3,n=""){if(this.readyState===3||this.readyState===2)return;this.readyState=3,this.emit("close",{code:e,reason:n});let r=this.peer;queueMicrotask(()=>r?.remoteClosed(e,n))}fail(e="mock failure"){if(this.readyState===3)return;this.emit("error",{type:"error",reason:e}),this.readyState=3,this.emit("close",{code:1006,reason:e});let n=this.peer;queueMicrotask(()=>n?.remoteClosed(1006,e))}deliver(e){this.readyState===1&&this.emit("message",{data:e})}remoteClosed(e,n){this.readyState!==3&&(this.readyState=3,this.emit("close",{code:e,reason:n}))}emit(e,n){for(let r of[...this.listeners.get(e)??[]])try{r(n)}catch{}}};St();Zn();var Jn=class{constructor(e={}){this.options=e}options;unsub;seen=new Set;start(e){return this.options.autoRequestPermission&&typeof Notification<"u"&&Notification.requestPermission(),this.unsub=e.subscribe(qs,(n=>{!n.id||this.seen.has(n.id)||(this.seen.add(n.id),this.deliver(n))})),()=>this.stop()}stop(){this.unsub?.(),this.unsub=void 0}deliver(e){if(this.options.onNotification){this.options.onNotification(e);return}if(typeof Notification>"u"||Notification.permission!=="granted")return;let n=new Notification(e.title,{body:e.body,tag:e.id,icon:e.url});n.onclick=()=>{this.options.onClick?.(e),e.url&&window.open(e.url,"_blank"),n.close()}}};var nd="/__crosslink",dt={pairing:"/pairing",networkMode:"/network-mode",devices:"/devices",revoke:"/revoke",events:"/events"};function cn(t,e){return`${t.replace(/\/+$/,"")}${e}`}async function Xs(t){let e=await t.text().catch(()=>""),n=e.trim();try{let o=JSON.parse(e);o?.error&&(n=o.error)}catch{}let r=new Error(n||`Request failed with status ${t.status}`);return r.code=`CL-P${t.status}`,r}function er(t=nd){let e=t.replace(/\/+$/,"");return{devicesEndpoint:cn(e,dt.devices),revokeEndpoint:cn(e,dt.revoke),async getSession(n){let r=new URL(cn(e,dt.pairing),location.href);n&&r.searchParams.set("mode",n);let o=await fetch(r.toString(),{headers:{accept:"application/json"}});if(!o.ok)throw await Xs(o);return await o.json()},async setNetworkMode(n){let r=await fetch(cn(e,dt.networkMode),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({mode:n})});if(!r.ok)throw await Xs(r)},subscribe(n){if(typeof EventSource>"u")return()=>{};let r=new EventSource(cn(e,dt.events)),o=()=>n({type:"invalidate"}),i=a=>{let c;try{c=JSON.parse(a.data).deviceId}catch{}n({type:"connected",deviceId:c})},s=a=>{let c;try{c=JSON.parse(a.data).deviceId}catch{}n({type:"disconnected",deviceId:c})};return r.addEventListener("crosslink.pairing-invalidated",o),r.addEventListener("crosslink.device-connected",i),r.addEventListener("crosslink.device-disconnected",s),()=>r.close()}}}var mo="105 363 1060 222",yo="M233.73 383.42C254.47 380.94 275.68 386.3 293.3 397.22C298.36 400.36 310.34 407.06 306.92 414.39C305.05 418.41 299.18 424.66 294.5 424.16C290.7 423.75 283.6 416.8 279.92 414.57C271.58 409.53 262.05 406.61 252.45 405.27C210.49 399.39 171.23 433.96 172.83 476.5C174.51 521.08 215.67 550.01 258.38 541.73C267.91 539.88 276.87 535.81 284.85 530.38C288.81 527.68 292.08 522.77 297.47 523.95C299.49 524.39 307.14 531.68 307.85 533.67C308.39 535.19 308.34 536.9 307.92 538.44C307.04 541.58 302.8 544.02 300.34 545.88C285.61 557.02 267.9 563.4 249.5 564.79C194.73 568.93 147.61 523.68 151.02 468.5C152.07 451.5 158.16 436.04 167.48 421.97C173.81 412.42 182.42 403.72 192.26 397.74C205.14 389.9 218.77 385.21 233.73 383.42ZM791.59 387.27C795.36 386.55 802.6 386.03 805.44 389.07C807.56 391.34 807.21 394.63 807.24 397.5C807.3 404.17 807.27 410.83 807.25 417.5C807.15 451.5 807.23 485.5 807.25 519.5C807.26 529.5 807.29 539.5 807.27 549.5C807.26 554.33 807.43 559.18 801.47 559.66C797.97 559.94 791 560.91 788.25 558.23C786.05 556.09 786.66 552.28 786.64 549.5C786.6 542.17 786.66 534.83 786.64 527.5C786.54 494.5 786.59 461.5 786.65 428.5C786.67 418.17 786.7 407.83 786.62 397.5C786.59 393.48 786.61 388.22 791.59 387.27ZM1047.5 490.33C1049.96 490.3 1052.92 490.63 1055.26 489.73C1058.8 488.37 1065.75 479.23 1068.61 476.12C1077.64 466.3 1086.84 456.19 1096.5 447C1100.43 443.26 1119.54 442.69 1123.5 445.8C1123.66 451.35 1115.32 457.13 1111.53 461.04C1099.51 473.43 1087.04 485.6 1075.57 498.5C1077.87 503.34 1082.73 507.17 1086.35 511.17C1095.38 521.13 1104.32 531.19 1113.52 541C1115.75 543.37 1125.96 553.61 1126.66 555.81C1127.01 556.89 1126.75 557.43 1126.8 558.5C1123.25 560.55 1118.53 559.73 1114.5 559.69C1110.76 559.66 1106.1 560.51 1102.63 558.88C1098.64 557 1095.59 552.04 1092.65 548.84C1085.62 541.2 1078.7 533.45 1071.74 525.76C1063.43 516.58 1060.8 509.28 1046.79 512.5C1044.96 522.02 1046.59 534.66 1046.57 544.5C1046.57 548.23 1047.48 553.75 1045.59 557.14C1043.49 560.88 1026.82 562.35 1025.95 554.5C1024.58 542.11 1025.96 527.16 1025.95 514.5C1025.94 486.17 1025.87 457.83 1025.93 429.5C1025.95 418.83 1025.94 408.17 1025.9 397.5C1025.89 393.57 1025.68 388.29 1030.61 387.24C1032.49 386.84 1034.59 387.09 1036.5 387.09C1038.56 387.1 1040.88 386.81 1042.81 387.66C1048.5 390.17 1046.49 406.98 1046.51 412.56C1046.56 430.21 1046.47 447.85 1046.53 465.5C1046.56 473.31 1045.12 482.95 1047.5 490.33ZM844.74 395.34C862.3 390.41 870.21 415.48 853.62 421.22C835.59 427.47 827.09 400.31 844.74 395.34ZM463.67 441.41C471.92 440.68 480.11 442.01 487.94 444.53C494.65 446.69 500.51 450.23 506.18 454.35C510.98 457.84 514.79 462.48 518.32 467.22C546.74 505.4 518.83 560.06 472.5 563.08C464.08 563.63 455.77 562.3 447.8 559.63C440.61 557.23 433.85 553.39 428.12 548.4C387.12 512.7 410.35 446.13 463.67 441.41ZM938.73 441.43C964.07 438.8 988.77 454.5 996.81 478.63C1001.03 491.31 999.84 505.34 999.82 518.5C999.8 528.5 999.67 538.5 999.8 548.5C999.85 552.1 1000.71 557.37 996.66 559.21C994.79 560.06 992.49 559.69 990.5 559.67C987.56 559.65 983.54 560.44 981.08 558.44C978.66 556.48 979.13 553.29 979.15 550.5C979.17 544.5 979.16 538.5 979.16 532.5C979.15 506.82 985.32 474.05 954.7 463.73C950.67 462.38 946.75 461.96 942.5 462.04C938.21 462.13 934.22 463.12 930.27 464.75C909.54 473.31 908.83 490.84 908.83 510.5C908.83 519.5 908.79 528.5 908.78 537.5C908.78 543.14 909.77 549.73 908.6 555.26C907.36 561.17 892.64 561.43 889.51 557.98C887.34 555.6 888.08 551.45 888.05 548.5C887.98 539.83 888.06 531.17 888.07 522.5C888.08 510.07 886.92 496.94 889.34 484.69C894.17 460.27 914.52 443.93 938.73 441.43ZM370.81 444.44C378.29 443.39 385.96 443.92 393.5 443.91C396.8 443.91 400.83 443.49 403.26 446.23C405.44 448.69 404.78 452.49 404.76 455.5C404.75 457.24 404.95 459.11 404.32 460.76C401.95 466.94 387.89 464.88 382.5 464.89C368.82 464.9 356.04 469.36 350.54 483.06C345.38 495.93 347.67 523.81 347.69 538.5C347.7 543.73 349 550.79 347.34 555.78C345.69 560.75 334.22 560.97 330.2 559.33C326.24 557.72 327 552.92 327 549.5C327 540.5 326.98 531.5 327 522.5C327.02 510.28 326.04 497.62 328.16 485.54C331.95 463.92 349.33 447.47 370.81 444.44ZM632.82 448.5C630.99 452.96 625.86 456.37 622.98 460.46C622.01 461.84 620.99 464.11 619.29 464.68C614.01 466.44 601.31 464.28 594.65 465.33C578.59 467.86 566.31 480.49 563.75 496.48C562.92 501.66 563.12 506.77 564.57 511.83C566.29 517.82 569.39 523.27 573.67 527.82C584.18 538.98 597.17 538.99 611.5 539.08C626.5 539.17 640.93 539.33 651.61 527.14C656.22 521.88 659.71 515.44 660.73 508.46C661.28 504.62 660.22 499.75 661.65 496.17C663.77 490.82 677.12 490.22 680.29 494.22C682.78 497.37 681.9 502.8 681.67 506.5C680.91 518.95 675.64 530.73 667.69 540.21C651.84 559.1 633.43 559.88 610.5 559.75C595.85 559.66 582.93 559.16 570.01 551.47C529.05 527.1 536.59 463.2 580.88 447.43C593.12 443.07 605.72 444 618.5 443.95C623.82 443.92 630.4 442.77 632.82 448.5ZM672.17 556.5C672.3 555.53 672.1 554.9 672.51 553.96C673.37 551.95 676.41 550 677.9 548.38C680.43 545.62 682.15 542.33 684.5 539.46C697.35 538.01 711.53 541.69 723.35 534.86C748.05 520.57 750.19 485.59 725.32 470.15C716.44 464.64 706.56 464.92 696.5 464.91C681.72 464.89 667.28 463.66 655.36 473.89C648.93 479.41 644.84 487.35 643.27 495.62C642.39 500.25 644.05 506.55 640.99 510.49C636.17 516.71 623.36 514.7 622.14 506.47C618.6 482.48 637.65 455.23 659.96 447.48C671.89 443.34 684.08 443.97 696.5 443.96C712.53 443.94 727.02 445.31 740.35 455.09C776.51 481.63 768.28 540.25 726.62 556.17C714.11 560.95 700.63 559.64 687.5 559.74C682.23 559.78 675.73 561.11 672.17 556.5ZM843.71 444.37C848.02 443.53 856.53 442.92 858.52 447.96C860.51 453 859.14 467.45 859.13 473.5C859.09 492.83 859.08 512.17 859.13 531.5C859.15 538.17 859.16 544.83 859.1 551.5C859.07 555.16 858.76 558.98 854.37 559.61C850.62 560.16 841.54 561.12 839.26 557.25C836.93 553.29 838.56 539.46 838.55 534.5C838.47 514.17 838.44 493.83 838.52 473.5C838.55 467.55 837.15 452.54 839.22 447.7C839.97 445.93 841.87 444.73 843.71 444.37ZM461.77 462.42C418.77 469.25 416.23 530.16 458.13 541.44C464.19 543.07 470.34 543.03 476.49 541.92C517.97 534.45 519.66 475.76 479.83 463.58C474.06 461.82 467.74 461.46 461.77 462.42Z",Nt="https://github.com/jacobpowaza/crosslink",Bt="Powered by",ft="Crosslink",rd="#38bdf8",od="#0b1120",id="#ffffff",Ys=3,Qs=4.5;function pt(t){if(!t)return null;let e=t.trim().toLowerCase(),n=e.match(/^#([0-9a-f]{3,8})$/);if(n){let o=n[1];return(o.length===3||o.length===4)&&(o=o.slice(0,3).split("").map(i=>i+i).join("")),o.length<6?null:{r:parseInt(o.slice(0,2),16),g:parseInt(o.slice(2,4),16),b:parseInt(o.slice(4,6),16)}}let r=e.match(/^rgba?\(\s*([\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)/);return r?{r:Math.min(255,Math.max(0,Number(r[1]))),g:Math.min(255,Math.max(0,Number(r[2]))),b:Math.min(255,Math.max(0,Number(r[3])))}:null}function je({r:t,g:e,b:n}){let r=o=>Math.round(Math.min(255,Math.max(0,o))).toString(16).padStart(2,"0");return`#${r(t)}${r(e)}${r(n)}`}function nr({r:t,g:e,b:n}){let r=o=>{let i=o/255;return i<=.03928?i/12.92:((i+.055)/1.055)**2.4};return .2126*r(t)+.7152*r(e)+.0722*r(n)}function rr(t,e){let n=nr(t),r=nr(e),[o,i]=n>=r?[n,r]:[r,n];return(o+.05)/(i+.05)}function tr(t,e,n){return{r:t.r+(e.r-t.r)*n,g:t.g+(e.g-t.g)*n,b:t.b+(e.b-t.b)*n}}function Zs(t,e,n){if(rr(t,e)>=n)return t;let r=nr(e)>.4?{r:0,g:0,b:0}:{r:255,g:255,b:255},o=t;for(let i=1;i<=20;i+=1){let s=tr(t,r,i/20);if(o=s,rr(s,e)>=n)return s}return o}function Ke(t={}){let e=pt(t.backgroundColor),n=t.appearance==="light"||t.appearance==="dark"?t.appearance:e&&nr(e)>.4?"light":"dark",r=e??pt(n==="light"?id:od),o=pt(t.accentColor)??pt(rd),i=pt(t.textColor)??(n==="light"?{r:15,g:23,b:42}:{r:226,g:232,b:240}),s=tr(r,n==="light"?{r:0,g:0,b:0}:{r:255,g:255,b:255},.06),a=tr(i,r,.42),c=tr(r,i,.18);return{appName:t.appName?.trim()||"This app",appIcon:t.appIcon?.trim()||null,accentColor:je(o),backgroundColor:je(r),surfaceColor:je(s),textColor:je(i),mutedColor:je(a),dividerColor:je(c),logoColor:je(Zs(o,r,3)),attributionColor:je(Zs(a,r,4.5)),appearance:n}}function sd(t,e){return typeof t=="number"?`${t}px`:t||e}function ae(t={}){let n=`width:${sd(t.width,"140px")};height:auto;display:block;${t.color?`color:${t.color};`:""}${t.style??""}`,r=t.className?` class="${t.className}"`:"",o=t.title??"Crosslink";return[`<svg viewBox="${mo}" fill="none" xmlns="http://www.w3.org/2000/svg"`,` role="img" aria-label="${o}"${r} style="${n}">`,`<title>${o}</title>`,`<path d="${yo}" fill="currentColor" fill-rule="evenodd"/>`,"</svg>"].join("")}function Js(t={}){let e=document.createElement("span");return e.className="cl-logo-holder",e.style.cssText="display:inline-flex;align-items:center",e.innerHTML=ae(t),e}function bo(t){return Ke({...t,backgroundColor:t.backgroundColor??(t.appearance==="light"?"#ffffff":"#000000")})}var ad=`
9
+ .cl-pair-card {
10
+ --cl-bg: #000000;
11
+ --cl-fg: #ffffff;
12
+ --cl-muted: #9a9a9a;
13
+ --cl-divider: #2a2a2a;
14
+ --cl-pill: #e7e7ea;
15
+ --cl-pill-text: #0a0a0a;
16
+ --cl-border: 1px solid #000000;
17
+ --cl-radius: 28px;
18
+ --cl-accent: #38bdf8;
19
+ position: relative;
20
+ width: 100%;
21
+ max-width: 100%;
22
+ min-width: 0;
23
+ background: var(--cl-bg);
24
+ color: var(--cl-fg);
25
+ border: var(--cl-border);
26
+ border-radius: var(--cl-radius);
27
+ padding: 28px 32px;
28
+ margin: 20px 0;
29
+ flex-shrink: 0;
30
+ display: grid;
31
+ grid-template-columns: 1.1fr auto 1fr auto 1fr;
32
+ align-items: center;
33
+ gap: 28px 28px;
34
+ box-sizing: border-box;
35
+ font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
36
+ text-align: left;
37
+ }
38
+ .cl-pair-card * {
39
+ box-sizing: border-box;
40
+ }
41
+
42
+ /* \u2500\u2500 Route summary in the settings popover \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
43
+ .cl-route-summary {
44
+ border-top: 1px solid var(--cl-divider);
45
+ margin-top: 6px;
46
+ padding: 8px 12px 4px;
47
+ color: var(--cl-muted);
48
+ font-size: 12px;
49
+ line-height: 1.45;
50
+ }
51
+ .cl-route-summary p {
52
+ margin: 0 0 4px;
53
+ }
54
+
55
+ /* \u2500\u2500 Cog Button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
56
+ .cl-cog-btn {
57
+ position: absolute;
58
+ top: 14px;
59
+ right: 16px;
60
+ background: transparent;
61
+ border: none;
62
+ color: var(--cl-muted);
63
+ cursor: pointer;
64
+ padding: 6px;
65
+ border-radius: 8px;
66
+ display: flex;
67
+ align-items: center;
68
+ justify-content: center;
69
+ transition: color 0.15s, background 0.15s;
70
+ z-index: 20;
71
+ }
72
+ .cl-cog-btn:hover {
73
+ color: var(--cl-fg);
74
+ background: rgba(255, 255, 255, 0.1);
75
+ }
76
+ .cl-cog-btn svg {
77
+ width: 17px;
78
+ height: 17px;
79
+ display: block;
80
+ }
81
+
82
+ /* \u2500\u2500 Small Dropdown Menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
83
+ /* \u2500\u2500 Pending state while a setting is applied \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
84
+ /* A mode change is a round trip to the host \u2014 it asks a router for a mapping,
85
+ or re-derives which routes to advertise \u2014 so the popover says it is working
86
+ rather than looking like the click did nothing. */
87
+ .cl-spinner {
88
+ width: 12px;
89
+ height: 12px;
90
+ border-radius: 50%;
91
+ border: 2px solid currentColor;
92
+ border-right-color: transparent;
93
+ display: inline-block;
94
+ flex-shrink: 0;
95
+ animation: clSpin 0.7s linear infinite;
96
+ }
97
+ @keyframes clSpin {
98
+ to { transform: rotate(360deg); }
99
+ }
100
+ @media (prefers-reduced-motion: reduce) {
101
+ .cl-spinner { animation-duration: 2.4s; }
102
+ .cl-pair-refresh[data-busy="true"]::before { animation-duration: 2.4s; }
103
+ }
104
+ .cl-mode-pending {
105
+ display: flex;
106
+ align-items: center;
107
+ gap: 8px;
108
+ padding: 8px 12px;
109
+ font-size: 12px;
110
+ color: var(--cl-muted);
111
+ }
112
+ .cl-mode-pending[hidden] {
113
+ display: none;
114
+ }
115
+ /* Inputs stay in the DOM and keep their checked state; they simply refuse a
116
+ second change until the first one has an answer. */
117
+ .cl-settings-dropdown[data-pending="true"] .cl-dropdown-item {
118
+ opacity: 0.55;
119
+ pointer-events: none;
120
+ }
121
+ .cl-pair-refresh[data-busy="true"]::before {
122
+ content: "";
123
+ width: 12px;
124
+ height: 12px;
125
+ margin-right: 8px;
126
+ border: 2px solid currentColor;
127
+ border-right-color: transparent;
128
+ border-radius: 50%;
129
+ display: inline-block;
130
+ vertical-align: -2px;
131
+ animation: clSpin 0.7s linear infinite;
132
+ }
133
+
134
+ .cl-settings-dropdown {
135
+ position: absolute;
136
+ top: 44px;
137
+ right: 14px;
138
+ width: 300px;
139
+ background: var(--cl-bg);
140
+ border: 1px solid var(--cl-divider);
141
+ border-radius: 12px;
142
+ padding: 8px;
143
+ z-index: 30;
144
+ box-shadow: 0 16px 36px rgba(0, 0, 0, 0.75), 0 0 0 1px rgba(255, 255, 255, 0.08);
145
+ animation: clDropdownFade 0.12s ease-out;
146
+ display: flex;
147
+ flex-direction: column;
148
+ gap: 2px;
149
+ }
150
+ .cl-settings-dropdown[hidden] {
151
+ display: none;
152
+ }
153
+ @keyframes clDropdownFade {
154
+ from { opacity: 0; transform: translateY(-4px) scale(0.98); }
155
+ to { opacity: 1; transform: translateY(0) scale(1); }
156
+ }
157
+ .cl-dropdown-header {
158
+ font-size: 11px;
159
+ font-weight: 700;
160
+ text-transform: uppercase;
161
+ letter-spacing: 0.05em;
162
+ color: var(--cl-muted);
163
+ padding: 6px 8px 4px 8px;
164
+ }
165
+ .cl-dropdown-item {
166
+ display: flex;
167
+ align-items: center;
168
+ justify-content: space-between;
169
+ padding: 8px 10px;
170
+ border-radius: 8px;
171
+ cursor: pointer;
172
+ font-size: 13px;
173
+ color: var(--cl-fg);
174
+ transition: background 0.12s;
175
+ position: relative;
176
+ user-select: none;
177
+ }
178
+ .cl-dropdown-item:hover {
179
+ background: rgba(255, 255, 255, 0.08);
180
+ }
181
+ .cl-dropdown-label {
182
+ display: flex;
183
+ align-items: center;
184
+ gap: 8px;
185
+ flex: 1;
186
+ }
187
+ .cl-dropdown-label input[type="radio"] {
188
+ accent-color: var(--cl-accent);
189
+ cursor: pointer;
190
+ margin: 0;
191
+ }
192
+ .cl-info-knob-wrap {
193
+ position: relative;
194
+ display: flex;
195
+ align-items: center;
196
+ justify-content: center;
197
+ }
198
+ .cl-info-knob {
199
+ width: 18px;
200
+ height: 18px;
201
+ border-radius: 50%;
202
+ background: rgba(255, 255, 255, 0.12);
203
+ color: var(--cl-muted);
204
+ font-size: 11px;
205
+ font-weight: 700;
206
+ font-family: inherit;
207
+ display: inline-flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+ border: none;
211
+ cursor: pointer;
212
+ padding: 0;
213
+ transition: background 0.15s, color 0.15s;
214
+ }
215
+ .cl-info-knob:hover,
216
+ .cl-info-knob:focus {
217
+ background: var(--cl-accent);
218
+ color: #082f49;
219
+ }
220
+ /* Tooltip on hover / focus */
221
+ .cl-dropdown-tooltip {
222
+ position: absolute;
223
+ right: 0;
224
+ top: calc(100% + 6px);
225
+ width: 250px;
226
+ background: #020617;
227
+ border: 1px solid var(--cl-divider);
228
+ border-radius: 8px;
229
+ padding: 10px 12px;
230
+ font-size: 11px;
231
+ line-height: 1.45;
232
+ color: #cbd5e1;
233
+ box-shadow: 0 8px 24px rgba(0,0,0,0.6);
234
+ pointer-events: none;
235
+ opacity: 0;
236
+ visibility: hidden;
237
+ transform: translateY(-2px);
238
+ transition: opacity 0.15s, transform 0.15s, visibility 0.15s;
239
+ z-index: 50;
240
+ }
241
+ .cl-info-knob-wrap:hover .cl-dropdown-tooltip,
242
+ .cl-info-knob-wrap:focus-within .cl-dropdown-tooltip {
243
+ opacity: 1;
244
+ visibility: visible;
245
+ pointer-events: auto;
246
+ transform: translateY(0);
247
+ }
248
+ .cl-dropdown-tooltip a {
249
+ color: var(--cl-accent);
250
+ text-decoration: underline;
251
+ text-underline-offset: 2px;
252
+ display: inline-block;
253
+ margin-top: 6px;
254
+ }
255
+
256
+ /* \u2500\u2500 Columns \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
257
+ .cl-pair-left {
258
+ display: flex;
259
+ flex-direction: column;
260
+ align-items: flex-start;
261
+ }
262
+ .cl-pair-logo {
263
+ height: 24px;
264
+ width: auto;
265
+ max-width: 140px;
266
+ display: block;
267
+ /* Contrast-corrected in resolveCrosslinkTheme; currentColor carries it
268
+ into the SVG path so one variable tints the whole mark. */
269
+ color: var(--cl-logo, var(--cl-fg));
270
+ }
271
+ .cl-pair-logo-wrap {
272
+ margin-bottom: 10px;
273
+ }
274
+ .cl-pair-app {
275
+ display: flex;
276
+ align-items: center;
277
+ justify-content: center;
278
+ gap: 8px;
279
+ margin-bottom: 10px;
280
+ }
281
+ .cl-pair-app[hidden] {
282
+ display: none;
283
+ }
284
+ .cl-pair-app-icon {
285
+ width: 20px;
286
+ height: 20px;
287
+ border-radius: 5px;
288
+ object-fit: cover;
289
+ display: block;
290
+ flex-shrink: 0;
291
+ }
292
+ .cl-pair-app-icon svg {
293
+ width: 20px;
294
+ height: 20px;
295
+ display: block;
296
+ }
297
+ .cl-pair-app-name {
298
+ font-size: 14px;
299
+ font-weight: 600;
300
+ color: var(--cl-fg);
301
+ letter-spacing: -0.01em;
302
+ }
303
+ .cl-pair-status {
304
+ font-size: 11px;
305
+ color: var(--cl-muted);
306
+ margin: 8px 0 0 0;
307
+ text-align: center;
308
+ min-height: 14px;
309
+ }
310
+ .cl-pair-status[hidden] {
311
+ display: none;
312
+ }
313
+ .cl-pair-status-on {
314
+ color: #4ade80;
315
+ font-weight: 600;
316
+ }
317
+ .cl-pair-blurb {
318
+ font-size: 13px;
319
+ line-height: 1.55;
320
+ color: var(--cl-muted);
321
+ max-width: 32ch;
322
+ margin: 0;
323
+ }
324
+ .cl-pair-blurb strong {
325
+ color: var(--cl-fg);
326
+ font-weight: 600;
327
+ }
328
+ .cl-pair-refresh {
329
+ appearance: none;
330
+ background: none;
331
+ border: none;
332
+ color: var(--cl-muted);
333
+ font: inherit;
334
+ font-size: 12px;
335
+ text-decoration: underline;
336
+ text-underline-offset: 2px;
337
+ cursor: pointer;
338
+ padding: 0;
339
+ margin-top: 14px;
340
+ transition: color 0.15s;
341
+ }
342
+ .cl-pair-refresh:hover {
343
+ color: var(--cl-fg);
344
+ }
345
+ .cl-pair-refresh:disabled {
346
+ opacity: 0.5;
347
+ cursor: default;
348
+ }
349
+ .cl-pair-divider {
350
+ width: 1px;
351
+ align-self: stretch;
352
+ background: var(--cl-divider);
353
+ }
354
+ .cl-pair-label {
355
+ font-size: 12px;
356
+ font-weight: 700;
357
+ text-transform: none;
358
+ color: var(--cl-fg);
359
+ margin: 0 0 14px 0;
360
+ text-align: center;
361
+ }
362
+ .cl-pair-center,
363
+ .cl-pair-right {
364
+ display: flex;
365
+ flex-direction: column;
366
+ align-items: center;
367
+ }
368
+ .cl-qr-wrap {
369
+ background: #ffffff;
370
+ border-radius: 16px;
371
+ padding: 12px;
372
+ min-width: 176px;
373
+ min-height: 176px;
374
+ width: 176px;
375
+ height: 176px;
376
+ display: flex;
377
+ align-items: center;
378
+ justify-content: center;
379
+ overflow: hidden;
380
+ }
381
+ .cl-qr-wrap svg {
382
+ width: 152px;
383
+ height: 152px;
384
+ display: block;
385
+ }
386
+ .cl-qr-wrap img {
387
+ width: 152px;
388
+ height: 152px;
389
+ display: block;
390
+ border-radius: 8px;
391
+ }
392
+ .cl-qr-placeholder {
393
+ color: #6b6b6b;
394
+ font-size: 12px;
395
+ text-align: center;
396
+ max-width: 140px;
397
+ line-height: 1.4;
398
+ }
399
+ .cl-qr-placeholder.cl-error {
400
+ color: #f87171;
401
+ }
402
+ .cl-error-code {
403
+ color: #991b1b;
404
+ font: 700 18px/1.2 "SF Mono", "Fira Code", monospace;
405
+ letter-spacing: 0.04em;
406
+ }
407
+ .cl-error-details-btn {
408
+ appearance: none;
409
+ border: 0;
410
+ background: transparent;
411
+ color: #334155;
412
+ cursor: pointer;
413
+ font: 600 11px/1.2 inherit;
414
+ padding: 6px;
415
+ text-decoration: underline;
416
+ text-underline-offset: 2px;
417
+ }
418
+ .cl-skeleton {
419
+ position: relative;
420
+ overflow: hidden;
421
+ background: #e2e8f0;
422
+ }
423
+ .cl-skeleton::after {
424
+ content: "";
425
+ position: absolute;
426
+ inset: 0;
427
+ transform: translateX(-100%);
428
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,.8), transparent);
429
+ animation: clSkeletonSweep 1.35s ease-in-out infinite;
430
+ }
431
+ .cl-qr-skeleton {
432
+ width: 132px;
433
+ height: 132px;
434
+ border-radius: 10px;
435
+ }
436
+ .cl-pill.cl-pill-skeleton {
437
+ min-width: 44px;
438
+ height: 52px;
439
+ padding: 0;
440
+ }
441
+ @keyframes clSkeletonSweep {
442
+ 100% { transform: translateX(100%); }
443
+ }
444
+ @media (prefers-reduced-motion: reduce) {
445
+ .cl-skeleton::after { animation: none; }
446
+ }
447
+ .cl-pair-code-pills {
448
+ display: grid;
449
+ grid-template-columns: repeat(3, 1fr);
450
+ gap: 8px;
451
+ max-width: 200px;
452
+ justify-content: center;
453
+ min-height: 44px;
454
+ align-items: center;
455
+ }
456
+ .cl-pair-code-pills .cl-pill {
457
+ background: var(--cl-pill);
458
+ color: var(--cl-pill-text);
459
+ font-family: "SF Mono", "Fira Code", monospace;
460
+ font-size: 24px;
461
+ font-weight: 700;
462
+ line-height: 1;
463
+ border-radius: 12px;
464
+ padding: 14px 8px;
465
+ min-width: 44px;
466
+ text-align: center;
467
+ display: block;
468
+ }
469
+ .cl-pair-hint {
470
+ font-size: 11px;
471
+ color: var(--cl-muted);
472
+ margin: 12px 0 0 0;
473
+ text-align: center;
474
+ }
475
+ @media (max-width: 860px) {
476
+ .cl-pair-card {
477
+ grid-template-columns: 1fr;
478
+ text-align: center;
479
+ padding: 20px 24px;
480
+ gap: 20px;
481
+ }
482
+ .cl-pair-left,
483
+ .cl-pair-center,
484
+ .cl-pair-right {
485
+ min-width: 0;
486
+ }
487
+ .cl-pair-left {
488
+ align-items: center;
489
+ }
490
+ .cl-pair-card .cl-pair-divider {
491
+ width: 100%;
492
+ height: 1px;
493
+ }
494
+ .cl-pair-logo {
495
+ margin-left: auto;
496
+ margin-right: auto;
497
+ }
498
+ .cl-pair-blurb {
499
+ max-width: none;
500
+ overflow-wrap: anywhere;
501
+ }
502
+ }
503
+
504
+ /* \u2500\u2500 Connected Devices Modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
505
+ .cl-connected-modal-backdrop {
506
+ position: fixed;
507
+ top: 0;
508
+ left: 0;
509
+ width: 100vw;
510
+ height: 100vh;
511
+ background: rgba(0, 0, 0, 0.75);
512
+ z-index: 100;
513
+ display: flex;
514
+ align-items: center;
515
+ justify-content: center;
516
+ animation: clDropdownFade 0.15s ease-out;
517
+ }
518
+ .cl-error-modal {
519
+ max-width: 480px;
520
+ }
521
+ .cl-error-modal code {
522
+ color: #fca5a5;
523
+ font-size: 12px;
524
+ }
525
+ .cl-error-modal p {
526
+ color: #cbd5e1;
527
+ font-size: 13px;
528
+ line-height: 1.55;
529
+ margin: 0;
530
+ overflow-wrap: anywhere;
531
+ }
532
+ .cl-connected-modal {
533
+ background: #0a0a0a;
534
+ border: 1px solid var(--cl-divider);
535
+ border-radius: 20px;
536
+ width: 92vw;
537
+ max-width: 640px;
538
+ max-height: 85vh;
539
+ padding: 24px 28px;
540
+ box-shadow: 0 24px 60px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(255, 255, 255, 0.06);
541
+ overflow-y: auto;
542
+ font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
543
+ color: var(--cl-fg);
544
+ }
545
+ .cl-modal-header {
546
+ display: flex;
547
+ align-items: center;
548
+ justify-content: space-between;
549
+ margin-bottom: 16px;
550
+ gap: 16px;
551
+ }
552
+ .cl-modal-header h3 {
553
+ margin: 0;
554
+ font-size: 18px;
555
+ font-weight: 700;
556
+ letter-spacing: -0.02em;
557
+ }
558
+ .cl-modal-header button {
559
+ background: rgba(255, 255, 255, 0.08);
560
+ border: 1px solid var(--cl-divider);
561
+ border-radius: 10px;
562
+ color: var(--cl-fg);
563
+ font-size: 20px;
564
+ line-height: 1;
565
+ padding: 4px 10px;
566
+ cursor: pointer;
567
+ transition: background 0.15s;
568
+ }
569
+ .cl-modal-header button:hover {
570
+ background: rgba(255, 255, 255, 0.15);
571
+ }
572
+ .cl-modal-body {
573
+ display: flex;
574
+ flex-direction: column;
575
+ gap: 10px;
576
+ }
577
+ .cl-modal-error {
578
+ color: #f87171;
579
+ font-size: 12px;
580
+ padding: 8px 0;
581
+ }
582
+ .cl-device-card {
583
+ background: #121212;
584
+ border: 1px solid var(--cl-divider);
585
+ border-radius: 14px;
586
+ padding: 16px 18px;
587
+ display: flex;
588
+ align-items: flex-start;
589
+ justify-content: space-between;
590
+ gap: 16px;
591
+ }
592
+ .cl-device-info {
593
+ flex: 1;
594
+ min-width: 0;
595
+ }
596
+ .cl-device-name {
597
+ font-weight: 600;
598
+ font-size: 15px;
599
+ margin-bottom: 4px;
600
+ letter-spacing: -0.01em;
601
+ }
602
+ .cl-device-meta {
603
+ font-size: 11px;
604
+ color: var(--cl-muted);
605
+ margin-bottom: 8px;
606
+ text-transform: capitalize;
607
+ }
608
+ .cl-device-detail {
609
+ font-size: 11px;
610
+ line-height: 1.5;
611
+ color: #c4c4c4;
612
+ }
613
+ .cl-device-detail strong {
614
+ color: var(--cl-muted);
615
+ font-weight: 600;
616
+ }
617
+ .cl-device-actions {
618
+ flex-shrink: 0;
619
+ }
620
+ .cl-revoke-btn {
621
+ background: #1a1a2e;
622
+ border: 1px solid #2a2a3a;
623
+ color: #e7e7ea;
624
+ border-radius: 8px;
625
+ padding: 7px 14px;
626
+ font-size: 12px;
627
+ font-weight: 600;
628
+ cursor: pointer;
629
+ transition: background 0.15s, border-color 0.15s, color 0.15s;
630
+ }
631
+ .cl-revoke-btn:hover {
632
+ background: #7f1d1d;
633
+ border-color: #f87171;
634
+ color: #f87171;
635
+ }
636
+ `.trim(),ea=!1;function wo(){if(ea||typeof document>"u")return;let t=document.createElement("style");t.id="crosslink-pairing-card-styles",t.textContent=ad,document.head.appendChild(t),ea=!0}var ln=class{element;options;logoEl;blurbEl;refreshBtn;qrWrapEl;codePillsEl;hintEl;settingsPopover;routeSummaryEl;modePendingEl;appRowEl;statusEl;brand;currentMode;expiryTimer=null;source=null;refreshTimer=null;unsubscribeSource=null;destroyed=!1;inFlight=null;refreshQueued=!1;connectedDevices=new Set;constructor(e={}){this.options=e,this.brand=bo({appName:e.appName,appIcon:e.appIcon,...e.brand}),this.currentMode=ut(e.networkMode),e.injectStyles!==!1&&wo(),this.element=document.createElement("div"),this.element.className="cl-pair-card",this.applyBrand(),this.applyTheme(e.theme);let n=document.createElement("button");n.className="cl-cog-btn",n.title="Connection Settings",n.setAttribute("aria-label","Connection Settings"),n.innerHTML=`
637
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
638
+ <circle cx="12" cy="12" r="3"/>
639
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/>
640
+ </svg>
641
+ `,n.addEventListener("click",()=>this.toggleSettings()),this.settingsPopover=this.createSettingsPopover();let r=document.createElement("div");r.className="cl-pair-left",this.logoEl=document.createElement("div"),this.logoEl.className="cl-pair-logo-wrap",this.renderBrandMark(),this.appRowEl=document.createElement("div"),this.appRowEl.className="cl-pair-app",this.renderAppRow(),this.blurbEl=document.createElement("p"),this.blurbEl.className="cl-pair-blurb",this.blurbEl.innerHTML=e.blurb??"<strong>Connect another device</strong> with Crosslink. The framework authenticates trusted devices and protects application data end to end across supported transports.",this.refreshBtn=document.createElement("button"),this.refreshBtn.className="cl-pair-refresh",this.refreshBtn.textContent="Refresh code",this.refreshBtn.addEventListener("click",()=>{this.refresh()}),r.appendChild(this.logoEl),r.appendChild(this.blurbEl),r.appendChild(this.refreshBtn);let o=document.createElement("div");o.className="cl-pair-divider";let i=document.createElement("div");i.className="cl-pair-center";let s=document.createElement("h3");s.className="cl-pair-label",s.textContent="Scan this on your device",this.qrWrapEl=document.createElement("div"),this.qrWrapEl.className="cl-qr-wrap",this.renderQr(e.qr),i.appendChild(this.appRowEl),i.appendChild(s),i.appendChild(this.qrWrapEl);let a=document.createElement("div");a.className="cl-pair-divider";let c=document.createElement("div");c.className="cl-pair-right";let l=document.createElement("h3");l.className="cl-pair-label",l.textContent="Pairing Code",this.codePillsEl=document.createElement("div"),this.codePillsEl.className="cl-pair-code-pills",this.renderCode(e.code),this.hintEl=document.createElement("p"),this.hintEl.className="cl-pair-hint",this.renderExpiry(e.expiresAt),this.statusEl=document.createElement("p"),this.statusEl.className="cl-pair-status",this.statusEl.setAttribute("role","status"),this.statusEl.setAttribute("aria-live","polite"),this.renderStatus(e.status??null,!1),c.appendChild(l),c.appendChild(this.codePillsEl),c.appendChild(this.hintEl),c.appendChild(this.statusEl),this.element.appendChild(n),this.element.appendChild(this.settingsPopover),this.element.appendChild(r),this.element.appendChild(o),this.element.appendChild(i),this.element.appendChild(a),this.element.appendChild(c),e.target&&this.mount(e.target),typeof document<"u"&&typeof document.addEventListener=="function"&&document.addEventListener("click",d=>{this.element.contains(d.target)||this.toggleSettings(!1)}),e.source!==!1&&this.attachSource(e.source??!0)}attachSource(e){this.source=typeof e=="object"?e:er(e===!0?void 0:e),this.options.devicesEndpoint??=this.source.devicesEndpoint,this.options.revokeEndpoint??=this.source.revokeEndpoint,this.unsubscribeSource=this.source.subscribe?.(n=>this.handleSourceEvent(n))??null,this.refresh()}async refresh(){if(!this.source){await this.handleRefresh();return}if(!this.destroyed)return this.inFlight?(this.refreshQueued=!0,this.inFlight):(this.inFlight=this.mintSession().finally(()=>{this.inFlight=null,this.refreshQueued&&!this.destroyed&&(this.refreshQueued=!1,this.refresh())}),this.inFlight)}async mintSession(){let e=this.source;if(e){this.clearRefreshTimer(),this.update({loading:!0,error:null});try{let n=await e.getSession(this.currentMode);if(this.destroyed)return;n.application&&this.adoptHostApplication(n.application),n.networkMode&&(this.currentMode=ut(n.networkMode)),this.update({loading:!1,error:null,qr:n.qrSvg??null,code:n.code,expiresAt:n.expiresAt,networkMode:this.currentMode,endpoints:n.endpoints??null,remoteNote:n.remoteNote??null,status:this.sessionStatusText(),connected:this.connectedDevices.size>0}),this.scheduleSessionRefresh(n.expiresAt),this.options.onSession?.(n)}catch(n){if(this.destroyed)return;let r=n instanceof Error?n:new Error(String(n));this.update({loading:!1,error:r.message||"Crosslink could not create a pairing code.",errorCode:r.code??"CL-P001"}),this.options.onError?.(r),this.refreshTimer=setTimeout(()=>{this.refresh()},5e3)}}}adoptHostApplication(e){let n={appName:this.options.appName,appIcon:this.options.appIcon,...this.options.brand},r={appName:n.appName??e.name,appIcon:n.appIcon??e.icon??void 0,accentColor:n.accentColor??e.accentColor,backgroundColor:n.backgroundColor??e.backgroundColor,textColor:n.textColor??e.textColor,appearance:n.appearance??e.appearance},o=bo(r);JSON.stringify(o)!==JSON.stringify(this.brand)&&(this.brand=o,this.applyBrand(),this.renderAppRow())}sessionStatusText(){let e=this.connectedDevices.size;return e===0?"Waiting for a device to scan":e===1?"Device connected":`${e} devices connected`}scheduleSessionRefresh(e){this.clearRefreshTimer();let n=(this.options.refreshLeadSeconds??15)*1e3,r=Math.max(1e3,e-Date.now()-n);this.refreshTimer=setTimeout(()=>{this.refresh()},r)}clearRefreshTimer(){this.refreshTimer!==null&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}handleSourceEvent(e){if(!this.destroyed)switch(e.type){case"invalidate":this.refresh();break;case"connected":this.connectedDevices.add(e.deviceId??"device"),this.update({status:this.sessionStatusText(),connected:!0}),this.options.onDeviceConnected?.(e.deviceId);break;case"disconnected":this.connectedDevices.delete(e.deviceId??"device"),this.update({status:this.sessionStatusText(),connected:this.connectedDevices.size>0});break}}normalizeMode(e){return ut(e)}createSettingsPopover(){let e=document.createElement("div");e.className="cl-settings-dropdown",e.hidden=!0;let n=this.options.remoteGuideUrl||"https://crosslink.mintlify.site/guides/remote-access",r=this.options.securityGuideUrl||"https://crosslink.mintlify.site/security/overview",o=this.options.lanGuideUrl||"https://crosslink.mintlify.site/guides/connection-modes",i=this.normalizeMode(this.currentMode);e.innerHTML=`
642
+ <div class="cl-dropdown-header">Connection Mode</div>
643
+
644
+ <!-- Automatic (default) -->
645
+ <label class="cl-dropdown-item">
646
+ <div class="cl-dropdown-label">
647
+ <input type="radio" name="cl-net-mode" value="auto" ${i==="auto"?"checked":""}>
648
+ <span>Automatic</span>
649
+ </div>
650
+ <div class="cl-info-knob-wrap">
651
+ <button type="button" class="cl-info-knob" aria-label="Info">&#8505;</button>
652
+ <div class="cl-dropdown-tooltip">
653
+ <strong>How it works:</strong> The pairing payload carries every available route, and the connecting device picks the first one that answers &mdash; local first, then other confirmed routes.<br>
654
+ <strong>Security:</strong> Crosslink authenticates devices and encrypts application data end to end whichever route wins.
655
+ <a href="${o}" target="_blank" rel="noopener noreferrer">Mintlify docs &rarr;</a>
656
+ </div>
657
+ </div>
658
+ </label>
659
+
660
+ <!-- Same network only -->
661
+ <label class="cl-dropdown-item">
662
+ <div class="cl-dropdown-label">
663
+ <input type="radio" name="cl-net-mode" value="local-only" ${i==="local-only"?"checked":""}>
664
+ <span>Same network only</span>
665
+ </div>
666
+ <div class="cl-info-knob-wrap">
667
+ <button type="button" class="cl-info-knob" aria-label="Info">&#8505;</button>
668
+ <div class="cl-dropdown-tooltip">
669
+ <strong>How it works:</strong> Direct connection on the current Wi-Fi or LAN. No remote transport is advertised.<br>
670
+ <strong>Security:</strong> The same Crosslink authentication and end-to-end encryption apply on the local link.
671
+ <a href="${o}" target="_blank" rel="noopener noreferrer">Mintlify docs &rarr;</a>
672
+ </div>
673
+ </div>
674
+ </label>
675
+
676
+ <!-- LAN + relay -->
677
+ <label class="cl-dropdown-item">
678
+ <div class="cl-dropdown-label">
679
+ <input type="radio" name="cl-net-mode" value="lan-and-relay" ${i==="lan-and-relay"?"checked":""}>
680
+ <span>Same network + relay</span>
681
+ </div>
682
+ <div class="cl-info-knob-wrap">
683
+ <button type="button" class="cl-info-knob" aria-label="Info">&#8505;</button>
684
+ <div class="cl-dropdown-tooltip">
685
+ <strong>How it works:</strong> Adds a configured relay so another device can reach the host when a direct local route is unavailable.<br>
686
+ <strong>Security:</strong> Crosslink encrypts application data before it reaches the relay and authenticates it at the destination.
687
+ <a href="${r}" target="_blank" rel="noopener noreferrer">Mintlify docs &rarr;</a>
688
+ </div>
689
+ </div>
690
+ </label>
691
+
692
+ <!-- Remote -->
693
+ <label class="cl-dropdown-item">
694
+ <div class="cl-dropdown-label">
695
+ <input type="radio" name="cl-net-mode" value="remote" ${i==="remote"?"checked":""}>
696
+ <span>Reachable from anywhere</span>
697
+ </div>
698
+ <div class="cl-info-knob-wrap">
699
+ <button type="button" class="cl-info-knob" aria-label="Info">&#8505;</button>
700
+ <div class="cl-dropdown-tooltip">
701
+ <strong>How it works:</strong> Advertises a confirmed internet route, such as a router mapping or configured tunnel. If none is available, Crosslink reports that instead of claiming remote reachability.<br>
702
+ <strong>Security:</strong> The framework keeps device authentication and end-to-end encryption in place on the public route.
703
+ <a href="${n}" target="_blank" rel="noopener noreferrer">Mintlify docs &rarr;</a>
704
+ </div>
705
+ </div>
706
+ </label>
707
+ `,this.modePendingEl=document.createElement("div"),this.modePendingEl.className="cl-mode-pending",this.modePendingEl.setAttribute("role","status"),this.modePendingEl.setAttribute("aria-live","polite"),this.modePendingEl.hidden=!0;let s=document.createElement("span");s.className="cl-spinner";let a=document.createElement("span");a.textContent="Applying\u2026",this.modePendingEl.append(s,a),e.appendChild(this.modePendingEl),this.routeSummaryEl=document.createElement("div"),this.routeSummaryEl.className="cl-route-summary",this.routeSummaryEl.hidden=!0,e.appendChild(this.routeSummaryEl),e.querySelectorAll('input[name="cl-net-mode"]').forEach(f=>{f.addEventListener("change",p=>{this.setNetworkMode(ut(p.target.value))})});let l=document.createElement("div");l.className="cl-dropdown-header",l.style.marginTop="4px",l.textContent="Devices",e.appendChild(l);let d=document.createElement("label");return d.className="cl-dropdown-item",d.innerHTML=`
708
+ <div class="cl-dropdown-label">
709
+ <span>Connected Devices</span>
710
+ </div>
711
+ `,d.addEventListener("click",()=>this.openConnectedDevicesModal()),e.appendChild(d),e}toggleSettings(e){let n=this.settingsPopover.hidden,r=e!==void 0?e:n;this.settingsPopover.hidden=!r}setNetworkMode(e){let n=this.normalizeMode(e);this.currentMode=n;try{typeof localStorage<"u"&&localStorage.setItem("crosslink.networkMode",n)}catch{}let r=this.settingsPopover.querySelector(`input[value="${n}"]`);if(r&&(r.checked=!0),this.source){this.applyNetworkMode(n);return}this.options.onNetworkModeChange&&this.options.onNetworkModeChange(n)}async applyNetworkMode(e){this.setSettingsPending(!0);try{await this.source?.setNetworkMode?.(e),await this.options.onNetworkModeChange?.(e)}catch(n){let r=n instanceof Error?n:new Error(String(n));this.update({loading:!1,error:r.message,errorCode:r.code??"CL-P001"}),this.options.onError?.(r),this.setSettingsPending(!1);return}try{await this.refresh()}finally{this.setSettingsPending(!1)}}setSettingsPending(e){this.modePendingEl.hidden=!e,e?this.settingsPopover.setAttribute("data-pending","true"):this.settingsPopover.removeAttribute("data-pending"),this.settingsPopover.querySelectorAll('input[name="cl-net-mode"]').forEach(n=>{n.disabled=e})}getNetworkMode(){return this.currentMode}mount(e){let n=typeof e=="string"?document.querySelector(e):e;if(!n)throw new Error(`PairingCard target element not found: ${String(e)}`);return n.appendChild(this.element),this}update(e){return e.loading?(this.renderLoading(),this.refreshBtn.disabled=!0,this.refreshBtn.setAttribute("data-busy","true")):(this.refreshBtn.disabled=!1,this.refreshBtn.removeAttribute("data-busy")),e.networkMode&&this.syncNetworkMode(ut(e.networkMode)),(e.status!==void 0||e.connected!==void 0)&&this.renderStatus(e.status??null,e.connected===!0),(e.endpoints!==void 0||e.remoteNote!==void 0)&&this.renderRoutes(e.endpoints??null,e.remoteNote??null),e.error?(this.renderError(e.errorCode||"CL-P001",e.error),this.hintEl.textContent="",this):(e.qr!==void 0&&this.renderQr(e.qr),e.code!==void 0&&this.renderCode(e.code),e.expiresAt!==void 0&&this.renderExpiry(e.expiresAt),this)}applyTheme(e){if(!e)return this;let n=this.element.style;return e.bg&&n.setProperty("--cl-bg",e.bg),e.fg&&n.setProperty("--cl-fg",e.fg),e.muted&&n.setProperty("--cl-muted",e.muted),e.divider&&n.setProperty("--cl-divider",e.divider),e.pill&&n.setProperty("--cl-pill",e.pill),e.pillText&&n.setProperty("--cl-pill-text",e.pillText),e.border&&n.setProperty("--cl-border",e.border),e.radius&&n.setProperty("--cl-radius",e.radius),this}setBlurb(e){return this.blurbEl.innerHTML=e,this}syncNetworkMode(e){this.currentMode=e;let n=this.settingsPopover.querySelector(`input[value="${e}"]`);n&&(n.checked=!0)}renderBrandMark(){this.logoEl.replaceChildren(),this.logoEl.innerHTML=ae({className:"cl-pair-logo",width:"140px"})}renderAppRow(){this.appRowEl.replaceChildren();let e=this.brand.appIcon;if(e)if(e.trim().startsWith("<svg")){let r=document.createElement("span");r.className="cl-pair-app-icon",r.innerHTML=e,this.appRowEl.appendChild(r)}else{let r=document.createElement("img");r.className="cl-pair-app-icon",r.src=e,r.alt="",this.appRowEl.appendChild(r)}let n=document.createElement("span");n.className="cl-pair-app-name",n.textContent=this.brand.appName,this.appRowEl.appendChild(n),this.appRowEl.hidden=!e&&this.brand.appName==="This app"}renderStatus(e,n){this.statusEl.textContent=e??"",this.statusEl.hidden=!e,this.statusEl.classList.toggle("cl-pair-status-on",n)}applyBrand(){let e=this.element.style;e.setProperty("--cl-bg",this.brand.backgroundColor),e.setProperty("--cl-fg",this.brand.textColor),e.setProperty("--cl-muted",this.brand.mutedColor),e.setProperty("--cl-divider",this.brand.dividerColor),e.setProperty("--cl-accent",this.brand.accentColor),e.setProperty("--cl-logo",this.brand.textColor),e.setProperty("--cl-attribution",this.brand.attributionColor),this.applyTheme(this.options.theme)}setBrand(e){return this.brand=bo({...this.options.brand,...e}),this.applyBrand(),this.renderAppRow(),this}getBrand(){return this.brand}renderQr(e){if(this.qrWrapEl.replaceChildren(),!e){this.renderQrSkeleton();return}if(e.trim().startsWith("<svg"))this.qrWrapEl.innerHTML=e;else{let n=document.createElement("img");n.src=e,n.alt="Scan to pair",this.qrWrapEl.appendChild(n)}}renderCode(e){if(this.codePillsEl.replaceChildren(),!e){this.renderCodeSkeleton();return}let n=String(e).replace(/\D/g,"");for(let r of n){let o=document.createElement("span");o.className="cl-pill",o.textContent=r,this.codePillsEl.appendChild(o)}}renderLoading(){this.renderQrSkeleton(),this.renderCodeSkeleton(),this.hintEl.textContent="Generating a secure pairing code\u2026"}renderQrSkeleton(){this.qrWrapEl.replaceChildren();let e=document.createElement("span");e.className="cl-skeleton cl-qr-skeleton",e.setAttribute("aria-label","Generating QR code"),this.qrWrapEl.appendChild(e)}renderCodeSkeleton(){this.codePillsEl.replaceChildren();for(let e=0;e<9;e++){let n=document.createElement("span");n.className="cl-pill cl-pill-skeleton cl-skeleton",n.setAttribute("aria-hidden","true"),this.codePillsEl.appendChild(n)}}renderError(e,n){this.qrWrapEl.replaceChildren(),this.codePillsEl.replaceChildren();let r=String(e).toUpperCase().replace(/[^A-Z0-9-]/g,"").slice(0,12)||"CL-P001",o=document.createElement("div");o.className="cl-qr-placeholder cl-error";let i=document.createElement("div");i.className="cl-error-code",i.textContent=r;let s=document.createElement("button");s.type="button",s.className="cl-error-details-btn",s.textContent="View details",s.addEventListener("click",()=>this.openErrorModal(r,n)),o.append(i,s),this.qrWrapEl.appendChild(o)}openErrorModal(e,n){let r=document.createElement("div");r.className="cl-connected-modal-backdrop";let o=document.createElement("div");o.className="cl-connected-modal cl-error-modal",o.setAttribute("role","dialog"),o.setAttribute("aria-modal","true");let i=document.createElement("div");i.className="cl-modal-header";let s=document.createElement("h3");s.textContent="Pairing error";let a=document.createElement("button");a.type="button",a.setAttribute("aria-label","Close error details"),a.innerHTML="&times;",a.addEventListener("click",()=>r.remove()),i.append(s,a);let c=document.createElement("div");c.className="cl-modal-body";let l=document.createElement("code");l.textContent=e;let d=document.createElement("p");d.textContent=n,c.append(l,d),o.append(i,c),r.appendChild(o),r.addEventListener("click",f=>{f.target===r&&r.remove()}),document.body.appendChild(r),a.focus()}renderExpiry(e){if(clearInterval(this.expiryTimer),!e){this.hintEl.textContent="";return}if(typeof e=="string"){this.hintEl.textContent=e;return}let n=()=>{let r=Math.max(0,Math.round((e-Date.now())/1e3));if(r<=0)this.hintEl.textContent="code expired \u2014 click refresh",clearInterval(this.expiryTimer);else{let o=Math.floor(r/60),i=r%60;this.hintEl.textContent=o>0?`expires in ${o}m ${i}s`:`expires in ${i}s`}};n(),this.expiryTimer=setInterval(n,1e3)}renderRoutes(e,n){let r=this.routeSummaryEl,o={lan:"this network",wan:"the internet, directly",sig:"a signaling service",relay:"a relay service",tunnel:"a provider tunnel"};r.replaceChildren();let i=[];e&&e.length>0?i.push(`Reachable over: ${e.map(s=>o[s.kind]??s.kind).join(", ")}.`):e&&i.push("This host currently advertises no route."),n&&i.push(n),r.hidden=i.length===0;for(let s of i){let a=document.createElement("p");a.textContent=s,r.appendChild(a)}}async handleRefresh(){if(this.options.onRefresh){this.refreshBtn.disabled=!0;try{await this.options.onRefresh()}finally{this.refreshBtn.disabled=!1}}}async openConnectedDevicesModal(){let e=this.options.devicesEndpoint||"/api/devices";try{let n=await fetch(e);if(!n.ok)throw new Error(`Failed to fetch devices: ${n.status}`);let r=await n.json(),o=(r.devices||r||[]).filter(i=>typeof i.revokedAt!="number");this.renderConnectedDevicesModal(o)}catch(n){this.renderConnectedDevicesModal([],String(n?.message||n))}}renderConnectedDevicesModal(e,n){let r=document.querySelector(".cl-connected-modal-backdrop");r&&r.remove();let o=document.createElement("div");o.className="cl-connected-modal-backdrop",o.style.cssText="position:fixed;top:0;left:0;width:100vw;height:100vh;background:rgba(0,0,0,0.75);z-index:100;display:flex;align-items:center;justify-content:center;animation:clDropdownFade 0.15s ease-out;";let i=document.createElement("div");i.className="cl-connected-modal";let s=document.createElement("div");s.className="cl-modal-header";let a=document.createElement("h3");a.textContent="Connected Devices";let c=document.createElement("button");c.type="button",c.setAttribute("aria-label","Close"),c.innerHTML="&times;",c.addEventListener("click",()=>o.remove()),s.appendChild(a),s.appendChild(c);let l=document.createElement("div");if(l.className="cl-modal-body",n){let d=document.createElement("div");d.className="cl-modal-error",d.textContent=n,l.appendChild(d)}if(e.length===0&&!n){let d=document.createElement("p");d.style.cssText="color:var(--cl-muted);text-align:center;padding:20px 0;",d.textContent="No paired devices found.",l.appendChild(d)}else for(let d of e){let f=document.createElement("div");f.className="cl-device-card";let p=d.status||(d.revokedAt?"Revoked":d.lastConnected?Date.now()-d.lastConnected<3e5?"Online":"Offline":"Unknown"),h=p==="Online"?"#4ade80":p==="Revoked"?"#f87171":"#9a9a9a",g=d.revokedAt?"Not trusted":"Trusted",b=d.firstPaired?new Date(d.firstPaired).toLocaleString():"Unknown",y=d.lastConnected?new Date(d.lastConnected).toLocaleString():"Never",m=document.createElement("div");m.className="cl-device-info";let v=document.createElement("div");v.className="cl-device-name",v.textContent=d.name||"Unnamed Device";let u=document.createElement("div");u.className="cl-device-meta",u.textContent=[d.deviceType,d.location].filter(Boolean).join(" \u2022 ");let x=document.createElement("div");x.className="cl-device-detail";let T=[["Device ID",String(d.deviceId??"")],["IP",d.ipAddress||"Not available"],["First paired",b],["Last connected",y],["Status",p,h],["Trusted",g]];for(let[S,w,E]of T){let k=document.createElement("div"),O=document.createElement("strong");O.textContent=`${S}: `;let A=document.createElement("span");A.textContent=w,E&&(A.style.cssText=`color:${E};font-weight:600;`),k.append(O,A),x.appendChild(k)}m.appendChild(v),m.appendChild(u),m.appendChild(x);let I=document.createElement("div");I.className="cl-device-actions";let C=document.createElement("button");C.className="cl-revoke-btn",C.textContent="Revoke Access",C.addEventListener("click",async()=>{C.disabled=!0,C.textContent="Revoking...";try{let S=this.options.revokeEndpoint||"/api/revoke",w=await fetch(S,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceId:d.deviceId})}),E=await w.json().catch(()=>null);if(!w.ok||E?.ok!==!0)throw new Error("Revoke failed");f.remove()}catch{C.textContent="Failed",C.style.background="#7f1d1d"}}),I.appendChild(C),f.appendChild(m),f.appendChild(I),l.appendChild(f)}i.appendChild(s),i.appendChild(l),o.appendChild(i),document.body.appendChild(o),o.addEventListener("click",d=>{d.target===o&&o.remove()})}destroy(){this.destroyed=!0,this.refreshQueued=!1,clearInterval(this.expiryTimer),this.clearRefreshTimer(),this.unsubscribeSource?.(),this.unsubscribeSource=null,this.element.remove()}};function ut(t){switch(t){case"local":case"local-only":return"local-only";case"lan-and-relay":case"relay":return"lan-and-relay";case"remote":case"open-lan":case"open-lan-remote":return"remote";case"ngrok":case"cloudflare":case"cloudflared":case"open-lan-cloudflared":return"auto";default:return"auto"}}function ta(t={}){return new ln(t)}function xo(t,e){return typeof t=="number"?`${t}px`:t||e}var ht=class{element;options;constructor(e={}){this.options=e,this.element=document.createElement("div"),this.render(),e.target&&this.mount(e.target)}mount(e=document.body){let n=typeof e=="string"?document.querySelector(e):e;if(!n)throw new Error(`PoweredByCrosslink target not found: ${String(e)}`);return this.element.parentElement!==n&&n.appendChild(this.element),this}update(e){return this.options={...this.options,...e},this.render(),this}destroy(){this.element.remove()}render(){let e=this.options.placement??"bottom-center",n=xo(this.options.offset,"8px"),r=xo(this.options.size,"11px"),o=[];e!=="inline"&&(o.push("position:fixed",`z-index:${this.options.zIndex??100002}`),e.startsWith("top")?o.push(`top:calc(${n} + env(safe-area-inset-top))`):o.push(`bottom:calc(${n} + env(safe-area-inset-bottom))`),e.endsWith("left")?o.push(`left:${n}`):e.endsWith("right")?o.push(`right:${n}`):o.push("left:50%","transform:translateX(-50%)")),this.element.className=`cl-powered-by-crosslink${this.options.className?` ${this.options.className}`:""}`,this.element.style.cssText=[...o,"display:inline-flex","align-items:center","gap:.32em","max-width:calc(100vw - 24px)","padding:4px 7px","border-radius:999px",`background:${this.options.background??"rgba(0,0,0,.58)"}`,`color:${this.options.color??"#94a3b8"}`,`font:${r}/1.2 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif`,"white-space:nowrap","box-sizing:border-box"].join(";"),this.element.textContent="";let i=Ke({accentColor:this.options.accentColor,backgroundColor:this.options.backgroundColor??this.options.background}),s=document.createElement("span");s.textContent=this.options.text??Bt;let a=document.createElement("a");if(a.href=Nt,a.target="_blank",a.rel="noopener noreferrer",a.setAttribute("aria-label",ft),a.style.cssText="color:inherit;display:inline-flex;align-items:center;text-decoration:none",a.innerHTML=ae({width:xo(this.options.logoWidth,"58px"),color:this.options.accentColor?i.logoColor:void 0,title:ft}),this.element.append(s,a),this.options.suffix){let c=document.createElement("span");c.textContent=this.options.suffix,this.element.appendChild(c)}}};function na(t={}){return new ht(t)}var Ve={title:"Trying to reconnect",message:"Crosslink can't reach the app on your computer yet. We'll keep trying automatically.",icon:"",appName:"Crosslink",themeColor:"#000000",bgColor:"#000000",accentColor:"",textColor:"",appearance:"auto",debuggingUrl:"https://crosslink.mintlify.site/resources/debugging-mobile-reconnect"},dn=class{client;options;currentState="connecting";reachabilityTimer=null;reconnectTimer=null;visibilityHandler=null;onlineHandler=null;isPageVisible=!0;attemptCount=0;isAttempting=!1;offlineElement=null;constructor(e){if(this.options={clientOptions:e.clientOptions,offline:{...Ve,...e.offline},onConnected:e.onConnected,onAuthRequired:e.onAuthRequired,onStateChange:e.onStateChange??(()=>{}),minRetryDelay:e.minRetryDelay??1e3,maxRetryDelay:e.maxRetryDelay??3e4,reachabilityCheckInterval:e.reachabilityCheckInterval??1e4,serviceWorkerUrl:e.serviceWorkerUrl??"/sw.js",autoRegisterServiceWorker:e.autoRegisterServiceWorker??!0,autoMountOfflineUI:e.autoMountOfflineUI??!0,container:e.container},e.client)this.client=e.client;else{let n=e.clientOptions?.onStateChange,r={...e.clientOptions,onStateChange:(o,i)=>{n?.(o,i),this.handleClientStateChange(o,i)}};this.client=new me(r)}this.setupVisibilityHandlers(),this.setupOnlineHandler()}async start(){if(this.options.autoRegisterServiceWorker&&typeof navigator<"u"&&"serviceWorker"in navigator)try{await navigator.serviceWorker.register(this.options.serviceWorkerUrl)}catch(n){console.warn("[OfflineShell] Service worker registration notice:",n)}let e=this.client.listApps();if(e.length===0){this.setState("authentication-required"),await this.options.onAuthRequired();return}await this.attemptSilentAuth(e[0])}async attemptSilentAuth(e){if(!this.isAttempting){this.isAttempting=!0,this.currentState!=="reconnecting"&&this.setState("connecting");try{let n=await this.client.connect(e.appId);this.isAttempting=!1,this.cancelTimers(),this.unmountOfflineUI(),this.setState("connected"),await this.options.onConnected(n,this.client)}catch(n){this.isAttempting=!1,await this.handleConnectionError(n,e)}}}handleClientStateChange(e,n){e==="revoked"||e==="unauthorized"?(this.unmountOfflineUI(),this.cancelTimers(),this.setState("authentication-required",n),this.options.onAuthRequired()):e==="offline"&&this.currentState==="connected"&&this.showHostOffline()}async handleConnectionError(e,n){let r=String(e?.message??e??"").toLowerCase(),o=this.client.state;if(r.includes("revoked")||r.includes("device_revoked")||r.includes("device-revoked")||r.includes("unauthorized")||r.includes("not paired")||r.includes("fingerprint")||r.includes("signature invalid")||r.includes("challenge nonce")||o==="revoked"||o==="unauthorized"){this.unmountOfflineUI(),this.cancelTimers(),this.setState("authentication-failed"),await this.options.onAuthRequired();return}this.showHostOffline()}showHostOffline(){this.setState("host-offline"),this.options.autoMountOfflineUI&&this.mountOfflineUI(),this.scheduleReconnect(),this.startReachabilityChecks()}scheduleReconnect(){if(this.reconnectTimer)return;let n=Math.min(this.options.maxRetryDelay,this.options.minRetryDelay*Math.pow(1.5,Math.min(this.attemptCount,8)))*(.8+Math.random()*.4),r=Math.max(1,Math.round(n/1e3));this.updateOfflineStatus(`Reconnecting in ${r}s\u2026`),this.reconnectTimer=setTimeout(async()=>{this.reconnectTimer=null,this.attemptCount++,await this.reconnectNow()},n)}async reconnectNow(){if(this.currentState==="connected"||this.isAttempting)return;let e=this.client.listApps();if(e.length===0){this.setState("authentication-required"),await this.options.onAuthRequired();return}this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.setState("reconnecting",{attempt:this.attemptCount}),this.updateOfflineStatus("Trying to reconnect\u2026"),await this.attemptSilentAuth(e[0])}startReachabilityChecks(){if(this.reachabilityTimer)return;let e=async()=>{if(this.currentState!=="host-offline"&&this.currentState!=="reconnecting"){this.cancelReachabilityChecks();return}let n=this.client.listApps();if(n.length===0)return;(await this.checkHostReachability(n[0].appId)).reachable&&(this.cancelReachabilityChecks(),await this.reconnectNow())};this.reachabilityTimer=setInterval(e,this.options.reachabilityCheckInterval)}cancelReachabilityChecks(){this.reachabilityTimer&&(clearInterval(this.reachabilityTimer),this.reachabilityTimer=null)}async checkHostReachability(e){let n=this.getHints(e);if(!n)return{reachable:!1};if(n.signalingUrl)try{let r=new AbortController,o=setTimeout(()=>r.abort(),4e3),s=await(this.options.clientOptions?.fetch??globalThis.fetch)(`${zn(n.signalingUrl).replace(/\/$/,"")}/apps/${encodeURIComponent(e)}`,{signal:r.signal,cache:"no-store"});if(clearTimeout(o),s.ok){let a=await s.json().catch(()=>({}));return{reachable:!0,hostInfo:{relay:a.relay,lan:a.lan,fingerprint:a.fingerprint}}}}catch{}return{reachable:!1}}cancelTimers(){this.cancelReachabilityChecks(),this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.attemptCount=0}setState(e,n){this.currentState!==e&&(this.currentState=e,this.options.onStateChange(e,n))}getHints(e){try{return this.client.hints?.load?.({})?.[e]??null}catch{return null}}setupVisibilityHandlers(){typeof document>"u"||(this.visibilityHandler=()=>{this.isPageVisible=!document.hidden,this.isPageVisible&&(this.currentState==="host-offline"||this.currentState==="reconnecting")&&this.reconnectNow().catch(()=>{})},document.addEventListener("visibilitychange",this.visibilityHandler))}setupOnlineHandler(){typeof window>"u"||(this.onlineHandler=()=>{(this.currentState==="host-offline"||this.currentState==="reconnecting")&&this.reconnectNow().catch(()=>{})},window.addEventListener("online",this.onlineHandler))}mountOfflineUI(){if(typeof document>"u")return;if(!this.offlineElement){let n={...Ve,...this.options.offline};this.offlineElement=Lt(n,()=>this.forceReconnect())}let e=this.options.container??document.body;e&&!e.contains(this.offlineElement)&&e.appendChild(this.offlineElement)}unmountOfflineUI(){this.offlineElement&&this.offlineElement.parentElement&&this.offlineElement.remove(),this.offlineElement=null}updateOfflineStatus(e){if(typeof document>"u")return;let n=document.getElementById("crosslink-offline-status");n&&(n.textContent=e)}getState(){return this.currentState}async forceReconnect(){this.attemptCount=0,await this.reconnectNow()}destroy(){this.cancelTimers(),this.unmountOfflineUI(),typeof document<"u"&&this.visibilityHandler&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null),typeof window<"u"&&this.onlineHandler&&(window.removeEventListener("online",this.onlineHandler),this.onlineHandler=null)}getClient(){return this.client}};function Lt(t,e){let n={...Ve,...t},r=Ke({appName:n.appName,appIcon:n.icon,accentColor:n.accentColor||void 0,backgroundColor:n.bgColor||void 0,textColor:n.textColor||void 0,appearance:n.appearance==="auto"?void 0:n.appearance}),o=document.createElement("div");if(o.id="crosslink-offline-shell",o.style.cssText=`
712
+ position: fixed;
713
+ inset: 0;
714
+ z-index: 99999;
715
+ background: ${r.backgroundColor};
716
+ color: ${r.textColor};
717
+ display: flex;
718
+ flex-direction: column;
719
+ align-items: center;
720
+ justify-content: center;
721
+ padding: 32px 24px;
722
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
723
+ text-align: center;
724
+ box-sizing: border-box;
725
+ overflow: hidden;
726
+ `,r.appIcon){let y=document.createElement("img");y.src=r.appIcon,y.alt="",y.style.cssText="width:56px;height:56px;border-radius:14px;margin-bottom:18px;object-fit:cover",o.appendChild(y)}let i=document.createElement("div");i.id="crosslink-offline-appname",i.textContent=r.appName,i.style.cssText=`font-size:13px;font-weight:600;letter-spacing:.02em;color:${r.mutedColor};margin-bottom:16px`,o.appendChild(i);let s=document.createElement("h1");s.textContent=n.title||`${r.appName} is unavailable`,s.style.cssText=`
727
+ font-size: 21px;
728
+ font-weight: 700;
729
+ margin: 0 0 10px 0;
730
+ color: ${r.textColor};
731
+ letter-spacing: -0.02em;
732
+ `,o.appendChild(s);let a=document.createElement("p");a.style.cssText=`
733
+ color: ${r.mutedColor};
734
+ font-size: 14px;
735
+ line-height: 1.55;
736
+ max-width: 300px;
737
+ margin: 0 0 28px 0;
738
+ white-space: pre-line;
739
+ `,a.textContent=n.message||`Crosslink isn't currently able to reach the computer running ${r.appName}.`,o.appendChild(a);let c=document.createElement("div");c.style.cssText="margin-bottom: 24px;";let l=document.createElement("span");if(l.id="crosslink-offline-status",l.style.cssText=`color:${r.mutedColor};font-size:13px;font-weight:400`,l.textContent="Trying to reconnect\u2026",c.appendChild(l),o.appendChild(c),e){let y=document.createElement("button");y.textContent="Attempt reopening the app",y.style.cssText=`
740
+ background: ${r.surfaceColor};
741
+ border: 1px solid ${r.dividerColor};
742
+ color: ${r.textColor};
743
+ padding: 8px 20px;
744
+ border-radius: 999px;
745
+ font-size: 13px;
746
+ font-weight: 500;
747
+ cursor: pointer;
748
+ transition: background 0.15s ease;
749
+ `,y.onclick=()=>{e()},o.appendChild(y)}let d=document.createElement("a");d.href=n.debuggingUrl,d.target="_blank",d.rel="noopener noreferrer",d.textContent="Still not working? Open the debugging guide",d.style.cssText=`color:${r.mutedColor};font-size:12px;margin-top:18px;text-underline-offset:3px`,o.appendChild(d);let f=document.createElement("div");f.id="crosslink-offline-brand",f.style.cssText="position:absolute;left:0;right:0;bottom:calc(24px + env(safe-area-inset-bottom));display:flex;flex-direction:column;align-items:center;gap:8px";let p=document.createElement("div");p.style.cssText="display:flex;justify-content:center;opacity:.95",p.innerHTML=ae({width:"132px",color:r.logoColor});let h=document.createElement("div");h.style.cssText=`font-size:11px;color:${r.attributionColor}`;let g=document.createElement("span");g.textContent=`${Bt} `;let b=document.createElement("a");return b.href=Nt,b.target="_blank",b.rel="noopener noreferrer",b.textContent=ft,b.style.cssText="color:inherit;font-weight:700;text-underline-offset:2px",h.append(g,b),f.append(p,h),o.appendChild(f),o}function vo(t){if(typeof document>"u")return;let e=document.getElementById("crosslink-offline-status");e&&(e.textContent=t)}function Eo(){if(typeof document>"u")return;document.getElementById("crosslink-offline-shell")?.remove()}St();function cd(){if(typeof window>"u")return!1;let t=window.navigator.standalone===!0,e=typeof window.matchMedia=="function"&&window.matchMedia("(display-mode: standalone)").matches;return t||e}function pn(){if(typeof window>"u"||typeof location>"u")return{origin:null,secureContext:!1,serviceWorkerAvailable:!1,webCryptoAvailable:typeof crypto<"u"&&!!crypto.subtle,standalone:!1,installable:!1,insecureTransportBlocked:!1,limitations:[]};let t=location.origin&&location.origin!=="null"?location.origin:null,e=window.isSecureContext===!0,n=e&&typeof navigator<"u"&&"serviceWorker"in navigator,r=typeof crypto<"u"&&!!crypto.subtle,o=location.protocol==="https:",i=[];return e||i.push(`${t??"This origin"} is not a secure context, so the browser will not register a service worker: this device can pair and use the app, but it cannot cache Crosslink's offline screen and an installed launch will show the browser's own error page when the host is unreachable.`),r||i.push("Web Crypto is unavailable on this origin, so this device's Crosslink identity is stored without encryption at rest. Anything with access to this browser profile can read it."),o&&i.push("This page is served over https, so the browser blocks insecure ws:// routes as mixed content. The host must advertise a wss:// route \u2014 a relay or a tunnel \u2014 for this install to reach it."),{origin:t,secureContext:e,serviceWorkerAvailable:n,webCryptoAvailable:r,standalone:cd(),installable:e&&n,insecureTransportBlocked:o,limitations:i}}var gt="crosslink_install",Rt="crosslink_install",Mt="crosslink_install_context";function ra(t){if(typeof document>"u")return null;let e=`${t}=`;for(let n of String(document.cookie??"").split(";")){let r=n.trim();if(r.startsWith(e))return ko(r.slice(e.length))}return null}function or(t){let e=typeof location<"u"&&location.protocol==="https:"?"; Secure":"";return`; Path=/; Max-Age=${Math.max(0,Math.floor(t))}; SameSite=Strict${e}`}function ld(t,e,n){if(typeof document>"u")return;let r=Math.max(1,Math.ceil((n-Date.now())/1e3));document.cookie=`${Rt}=${encodeURIComponent(t)}${or(r)}`,document.cookie=`${Mt}=${encodeURIComponent(JSON.stringify({targetUri:e,expiresAt:n}))}${or(r)}`}function dd(){typeof document>"u"||(document.cookie=`${Rt}=${or(0)}`,document.cookie=`${Mt}=${or(0)}`)}function ko(t){try{return decodeURIComponent(t)}catch{return t}}function Pt(){return typeof window>"u"?!1:window.matchMedia?.("(display-mode: standalone)")?.matches===!0||window.navigator?.standalone===!0}async function fn(){if(!(typeof window>"u"))try{if(localStorage.clear(),sessionStorage.clear(),window.indexedDB?.databases){let t=await window.indexedDB.databases();for(let e of t)e.name&&window.indexedDB.deleteDatabase(e.name)}else window.indexedDB?.deleteDatabase("crosslink-secure-storage");if("caches"in window){let t=await caches.keys();for(let e of t)await caches.delete(e)}}catch(t){console.warn("[Crosslink] Storage reset warning:",t)}}var pd=`
750
+ /* \u2500\u2500 Crosslink Mobile Framework Styles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
751
+ .cl-screen-overlay {
752
+ position: fixed;
753
+ inset: 0;
754
+ z-index: 99999;
755
+ background: #000000;
756
+ color: #ffffff;
757
+ display: flex;
758
+ flex-direction: column;
759
+ align-items: center;
760
+ justify-content: center;
761
+ padding: 32px 20px;
762
+ box-sizing: border-box;
763
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
764
+ text-align: center;
765
+ overflow-y: auto;
766
+ -webkit-tap-highlight-color: transparent;
767
+ }
768
+ .cl-screen-overlay * {
769
+ box-sizing: border-box;
770
+ }
771
+
772
+ /* \u2500\u2500 Crosslink Logo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
773
+ .cl-crosslink-logo {
774
+ width: 150px;
775
+ height: auto;
776
+ margin-bottom: 20px;
777
+ display: block;
778
+ opacity: 0.95;
779
+ }
780
+
781
+ /* \u2500\u2500 Screen A: Pairing Screen \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
782
+ .cl-pair-screen {
783
+ background: #000000;
784
+ gap: 20px;
785
+ }
786
+ .cl-pair-title {
787
+ font-size: 22px;
788
+ font-weight: 700;
789
+ letter-spacing: -0.02em;
790
+ margin: 0;
791
+ color: #ffffff;
792
+ }
793
+ .cl-pair-desc {
794
+ font-size: 14px;
795
+ color: #a1a1aa;
796
+ max-width: 290px;
797
+ line-height: 1.5;
798
+ margin: 0;
799
+ }
800
+ .cl-pair-grid {
801
+ display: grid;
802
+ grid-template-columns: repeat(3, 1fr);
803
+ gap: 10px;
804
+ max-width: 260px;
805
+ margin: 8px 0;
806
+ }
807
+ .cl-pair-digit {
808
+ width: 72px;
809
+ height: 64px;
810
+ font-size: 26px;
811
+ text-align: center;
812
+ border-radius: 14px;
813
+ border: 1px solid #27272a;
814
+ background: #111111;
815
+ color: #ffffff;
816
+ font-weight: 700;
817
+ outline: none;
818
+ font-family: inherit;
819
+ transition: border-color 0.15s, box-shadow 0.15s;
820
+ }
821
+ .cl-pair-digit:focus {
822
+ border-color: #ffffff;
823
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.2);
824
+ }
825
+ .cl-pair-err {
826
+ font-size: 13px;
827
+ color: #f87171;
828
+ min-height: 20px;
829
+ margin: 0;
830
+ line-height: 1.4;
831
+ max-width: 280px;
832
+ }
833
+ .cl-pair-reset {
834
+ margin-top: 12px;
835
+ background: transparent;
836
+ border: none;
837
+ color: #71717a;
838
+ font-size: 12px;
839
+ cursor: pointer;
840
+ padding: 6px 12px;
841
+ border-radius: 6px;
842
+ text-decoration: underline;
843
+ transition: color 0.15s;
844
+ }
845
+ .cl-pair-reset:hover {
846
+ color: #a1a1aa;
847
+ }
848
+
849
+ /* \u2500\u2500 Screen B: Add to Home Screen (Screen B) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
850
+ .cl-bootstrap-screen {
851
+ background: #000000;
852
+ justify-content: center;
853
+ position: fixed;
854
+ inset: 0;
855
+ z-index: 100000;
856
+ height: 100dvh;
857
+ }
858
+ .cl-bootstrap-appname {
859
+ font-size: 21px;
860
+ font-weight: 600;
861
+ color: #ffffff;
862
+ margin-top: 12px;
863
+ letter-spacing: -0.01em;
864
+ }
865
+ .cl-continue-btn {
866
+ margin-top: 20px;
867
+ background: rgba(255, 255, 255, 0.15);
868
+ border: 1px solid rgba(255, 255, 255, 0.25);
869
+ color: #ffffff;
870
+ padding: 11px 24px;
871
+ border-radius: 999px;
872
+ font-size: 14px;
873
+ font-weight: 600;
874
+ cursor: pointer;
875
+ transition: background 0.15s;
876
+ }
877
+ .cl-continue-btn:hover {
878
+ background: rgba(255, 255, 255, 0.25);
879
+ }
880
+ .cl-bootstrap-nudge {
881
+ position: absolute;
882
+ left: 0;
883
+ right: 0;
884
+ bottom: calc(4px + env(safe-area-inset-bottom));
885
+ display: flex;
886
+ flex-direction: column;
887
+ align-items: center;
888
+ gap: 2px;
889
+ pointer-events: none;
890
+ }
891
+ .cl-bootstrap-nudge span {
892
+ font-family: "Caveat", "Segoe Script", "Bradley Hand", cursive, sans-serif;
893
+ font-size: 21px;
894
+ color: #ffffff;
895
+ opacity: 0.92;
896
+ text-align: center;
897
+ max-width: 280px;
898
+ line-height: 1.2;
899
+ }
900
+ .cl-bootstrap-nudge svg {
901
+ width: 34px;
902
+ height: 52px;
903
+ color: #ffffff;
904
+ opacity: 0.92;
905
+ }
906
+
907
+ /* \u2500\u2500 SAS Modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
908
+ .cl-sas-modal {
909
+ position: fixed;
910
+ inset: 0;
911
+ z-index: 100001;
912
+ background: #000000;
913
+ display: flex;
914
+ flex-direction: column;
915
+ align-items: center;
916
+ justify-content: center;
917
+ padding: 32px 20px;
918
+ gap: 14px;
919
+ text-align: center;
920
+ box-sizing: border-box;
921
+ font-family: system-ui, -apple-system, sans-serif;
922
+ }
923
+ .cl-sas-modal h2 { font-size: 18px; color: #fff; margin: 0; }
924
+ .cl-sas-modal p { color: #a1a1aa; font-size: 13px; margin: 0; }
925
+ .cl-sas-grid {
926
+ display: grid;
927
+ grid-template-columns: repeat(3, 1fr);
928
+ gap: 8px;
929
+ width: 100%;
930
+ max-width: 240px;
931
+ margin: 10px 0;
932
+ }
933
+ .cl-sas-grid span {
934
+ display: grid;
935
+ place-items: center;
936
+ aspect-ratio: 1.5;
937
+ background: #111111;
938
+ border: 1px solid #27272a;
939
+ border-radius: 10px;
940
+ font-size: 24px;
941
+ font-weight: 700;
942
+ color: #ffffff;
943
+ font-variant-numeric: tabular-nums;
944
+ }
945
+ .cl-sas-caps { color: #a1a1aa; font-size: 12px; }
946
+ .cl-sas-actions { display: flex; gap: 12px; margin-top: 10px; }
947
+ .cl-sas-actions button {
948
+ padding: 10px 22px;
949
+ border-radius: 999px;
950
+ border: none;
951
+ font: inherit;
952
+ font-size: 14px;
953
+ font-weight: 600;
954
+ cursor: pointer;
955
+ }
956
+ .cl-sas-ok { background: #ffffff; color: #000000; }
957
+ .cl-sas-no { background: #111111; color: #ffffff; border: 1px solid #27272a !important; }
958
+ `.trim(),oa=!1;function ir(){if(oa||typeof document>"u")return;let t=document.createElement("style");t.id="crosslink-bootstrap-styles",t.textContent=pd,document.head.appendChild(t),oa=!0}var un=class{client;options;state="initializing";currentScreenElement=null;reconnectTimer=null;reachabilityTimer=null;visibilityHandler=null;onlineHandler=null;isAttempting=!1;attemptCount=0;activeRpc=null;targetPairingUri=null;poweredBy=null;environment=null;constructor(e){if(this.options=e,ir(),e.client)this.client=e.client;else{let n={...e.clientOptions,...e.clientOptions?.storage?{}:typeof localStorage<"u"?{storage:new Re(localStorage)}:{},deviceName:e.clientOptions?.deviceName??"mobile",onConfirmPairing:r=>this.showSasConfirmation(r),onStateChange:(r,o)=>this.handleClientStateChange(r,o)};this.client=new me(n)}this.setupListeners()}async start(){this.ensurePoweredBy(),this.environment=pn();for(let r of this.environment.limitations)console.warn(`[crosslink] ${r}`);if(this.options.onEnvironment?.(this.environment),this.options.autoRegisterServiceWorker!==!1&&this.environment.serviceWorkerAvailable)try{await navigator.serviceWorker.register(this.options.serviceWorkerUrl??"/sw.js")}catch(r){console.warn("[crosslink] service worker registration failed",r)}if(this.extractPairingUriFromLocation(),typeof location<"u"&&(new URLSearchParams(location.search).has("reset")||location.hash.includes("reset"))){if(await fn(),this.targetPairingUri)try{localStorage.setItem("crosslink.pendingPair",this.targetPairingUri)}catch{}location.href=location.pathname;return}let e=await this.discoverInstallHandoff();if(this.client.listApps().length===0&&e)try{console.info("[crosslink/install] redeeming handoff",{standalone:Pt(),source:e.source});let r=Fs(e.targetUri,e.handoffId);await this.client.pairFromQr(r,this.options.capabilities),this.targetPairingUri=e.targetUri,this.clearInstallState(),console.info("[crosslink/install] linked device created; credentials persisted")}catch(r){console.warn("[crosslink/install] handoff unavailable/expired; falling back to normal pairing",{error:String(r?.message??r)}),this.targetPairingUri=e.targetUri,this.clearInstallState()}let n=this.client.listApps();if(n.length===0){this.transitionTo("pairing-required");return}await this.attemptSilentAuth(n[0])}extractPairingUriFromLocation(){if(this.options.pairingUri){this.targetPairingUri=this.options.pairingUri;return}if(typeof location>"u")return;let e=new URLSearchParams(location.hash.replace(/^#/,"")).get(it),n=new URLSearchParams(location.search).get(it),r=e||n||"";if(r){this.targetPairingUri=ct(ko(r));try{localStorage.setItem("crosslink.pendingPair",this.targetPairingUri)}catch{}}else try{this.targetPairingUri=localStorage.getItem("crosslink.pendingPair")}catch{}}async discoverInstallHandoff(){let e="";typeof location<"u"&&(e=new URLSearchParams(location.search).get(gt)??"");let n=ra(Rt)??"",r=ra(Mt),o="",i=0;if(r)try{let a=JSON.parse(r);o=typeof a.targetUri=="string"?Pe(a.targetUri):"",i=typeof a.expiresAt=="number"?a.expiresAt:0}catch{}let s=n||e;if(s&&o&&i>Date.now())return{handoffId:s,targetUri:o,expiresAt:i,source:n?"cookie":"url"};if(e&&typeof fetch=="function")try{let a=await fetch(`/__crosslink/install/${encodeURIComponent(e)}`,{credentials:"same-origin",cache:"no-store"});if(a.ok){let c=await a.json();if(typeof c.uri=="string"&&typeof c.expiresAt=="number")return{handoffId:e,targetUri:Pe(c.uri),expiresAt:c.expiresAt,source:"url"}}}catch{}if((s||r)&&(o&&(this.targetPairingUri=o),this.clearInstallState()),this.targetPairingUri)try{let a=at(ct(this.targetPairingUri));if(a.link&&a.code)return{handoffId:a.code,targetUri:Pe(this.targetPairingUri),expiresAt:Number.MAX_SAFE_INTEGER,source:"legacy-link"}}catch{}return null}clearInstallState(){if(dd(),typeof localStorage<"u"&&localStorage.removeItem("crosslink.pendingPair"),!(typeof location>"u"||typeof history>"u"))try{let e=new URL(location.href);e.searchParams.delete(gt);let n=new URLSearchParams(e.hash.replace(/^#/,"")),r=n.get(it);if(r)try{at(ct(ko(r))).link&&n.delete(it)}catch{}e.hash=n.toString()?`#${n.toString()}`:"",history.replaceState(history.state,"",`${e.pathname}${e.search}${e.hash}`)}catch{}}getEffectiveAppId(){if(this.options.appId)return this.options.appId;let e=this.client.listApps();if(e.length>0)return e[0].appId;if(this.targetPairingUri)try{let n=at(this.targetPairingUri);if(n.appId)return n.appId}catch{}return"default"}completedOnboardingApps=new Set;isOnboardingCompleted(e){return Pt()||this.completedOnboardingApps.has(e)?!0:typeof localStorage<"u"?localStorage.getItem(`crosslink.onboarding.${e}`)==="true":!1}markOnboardingCompleted(e){this.completedOnboardingApps.add(e),typeof localStorage<"u"&&localStorage.setItem(`crosslink.onboarding.${e}`,"true")}clearOnboarding(e){this.completedOnboardingApps.delete(e),typeof localStorage<"u"&&localStorage.removeItem(`crosslink.onboarding.${e}`)}async prepareDeviceLinkHandoff(){if(!(Pt()||typeof location>"u"))try{let{handoffId:e,uri:n,expiresAt:r}=await this.client.createDeviceLink(),o=Pe(n);this.targetPairingUri=o,ld(e,o,r);let i=document.querySelector?.('link[rel="manifest"]');if(i?.href){let s=new URL(i.href,location.href);s.searchParams.set(gt,e),s.searchParams.set("v",String(r)),i.href=s.toString()}if(typeof history<"u"){let s=new URL(location.href);s.searchParams.set(gt,e),s.hash="",history.replaceState(history.state,"",`${s.pathname}${s.search}`)}console.info("[crosslink/install] handoff prepared",{currentPath:location.pathname,manifestPath:i?.href?new URL(i.href).pathname:null,launchHasHandoff:!0,expiresAt:r})}catch(e){console.warn("[crosslink/install] could not prepare handoff",{error:String(e?.message??e)})}}async attemptSilentAuth(e){if(!this.isAttempting){this.isAttempting=!0;try{let n=await this.client.connect(e.appId);this.activeRpc=n,this.isAttempting=!1,this.cancelTimers(),this.isOnboardingCompleted(e.appId)?this.transitionTo("authorized"):(await this.prepareDeviceLinkHandoff(),this.transitionTo("add-to-home-screen"))}catch(n){this.isAttempting=!1,await this.handleAuthError(n,e)}}}async handleAuthError(e,n){let r=String(e?.message??e??"").toLowerCase(),o=this.client.state;if(r.includes("revoked")||r.includes("device_revoked")||r.includes("device-revoked")||r.includes("unauthorized")||r.includes("not paired")||r.includes("signature invalid")||r.includes("challenge nonce")||o==="revoked"||o==="unauthorized"){this.client.forget(n.appId),this.clearOnboarding(n.appId),this.transitionTo("pairing-required",{reason:"revoked"});return}this.transitionTo("offline"),this.scheduleReconnect()}handleClientStateChange(e,n){if(e==="revoked"||e==="unauthorized"){let r=this.getEffectiveAppId();this.client.forget(r),this.clearOnboarding(r),this.transitionTo("pairing-required",{reason:"revoked",...n})}else e==="offline"&&this.state==="authorized"&&(this.transitionTo("offline"),this.scheduleReconnect())}transitionTo(e,n){if(this.ensurePoweredBy(),this.state=e,this.options.onStateChange?.(e,n),this.unmountCurrentScreen(),e==="authorized"){let o=this.activeRpc;if(!o)try{o=this.client.rpc()}catch{}o&&this.options.onAuthorized(o,this.client);return}this.options.onUnauthorized?.();let r=this.options.container??(typeof document<"u"?document.body:null);if(r)switch(e){case"pairing-required":case"pairing":{let o=this.createPairingScreen(i=>this.handlePairingSubmit(i));this.currentScreenElement=o,r.appendChild(o);break}case"add-to-home-screen":{let o=this.getEffectiveAppId(),i=this.createAddToHomeScreen(()=>{this.markOnboardingCompleted(o),this.transitionTo("authorized")});this.currentScreenElement=i,r.appendChild(i);break}case"offline":{let o={...Ve,...this.options.offline,appName:this.options.appName||this.options.offline?.appName||"Crosslink"},i=Lt(o,()=>this.forceReconnect());this.currentScreenElement=i,r.appendChild(i);break}}}unmountCurrentScreen(){this.currentScreenElement&&this.currentScreenElement.parentElement&&this.currentScreenElement.remove(),this.currentScreenElement=null}ensurePoweredBy(){if(typeof document>"u")return;this.poweredBy||(this.poweredBy=new ht(this.options.poweredBy));let e=this.options.poweredBy?.target??document.body;this.poweredBy.mount(e)}async handlePairingSubmit(e){let n=document.getElementById("cl-pair-err");n&&(n.textContent="Verifying pairing code\u2026",n.style.color="#38bdf8");try{let r=this.targetPairingUri??(typeof localStorage<"u"?localStorage.getItem("crosslink.pendingPair"):null);if(!r)throw new Error("scan the QR code on your computer to start pairing");let o=Pe(r);this.targetPairingUri=o,this.clearInstallState(),console.info("[crosslink/pairing] falling back to NORMAL pairing"),await this.client.pairWithCode(o,e,this.options.capabilities??[]),typeof localStorage<"u"&&localStorage.removeItem("crosslink.pendingPair");let i=this.client.listApps();i.length>0&&await this.attemptSilentAuth(i[0])}catch(r){n&&(n.textContent=`Pairing failed: ${r.message||String(r)}`,n.style.color="#f87171")}}createPairingScreen(e){let n=document.createElement("div");n.id="crosslink-pairing-screen",n.className="cl-screen-overlay cl-pair-screen";let r=document.createElement("div");r.style.cssText="display:flex;justify-content:center",r.innerHTML=ae({width:"140px",className:"cl-crosslink-logo"}),n.appendChild(r);let o=document.createElement("h2");o.className="cl-pair-title",o.textContent="Pairing Required",n.appendChild(o);let i=document.createElement("p");i.className="cl-pair-desc",i.textContent="Type the 9-digit pairing code shown on your computer to connect.",n.appendChild(i);let s=document.createElement("div");s.className="cl-pair-grid";let a=[];for(let d=0;d<9;d++){let f=document.createElement("input");f.type="text",f.inputMode="numeric",f.maxLength=1,f.className="cl-pair-digit",f.setAttribute("aria-label",`Digit ${d+1}`),f.addEventListener("input",p=>{let h=f.value.replace(/\D/g,"");f.value=h?h[0]:"",h&&d<8&&a[d+1].focus();let g=a.map(b=>b.value.replace(/\D/g,"")).join("");g.length===9&&e(g)}),f.addEventListener("keydown",p=>{p.key==="Backspace"&&!f.value&&d>0&&a[d-1].focus()}),f.addEventListener("paste",p=>{p.preventDefault();let g=(p.clipboardData?.getData("text")||"").replace(/\D/g,"").slice(0,9);for(let b=0;b<g.length;b++)a[b]&&(a[b].value=g[b]);g.length===9?e(g):g.length>0&&a[g.length]&&a[g.length].focus()}),s.appendChild(f),a.push(f)}n.appendChild(s);let c=document.createElement("p");c.id="cl-pair-err",c.className="cl-pair-err",n.appendChild(c);let l=document.createElement("button");return l.className="cl-pair-reset",l.textContent="Reset connection data",l.onclick=async()=>{await fn(),location.reload()},n.appendChild(l),setTimeout(()=>a[0]?.focus(),100),n}createAddToHomeScreen(e){let n=document.createElement("div");n.id="crosslink-bootstrap-screen",n.className="cl-screen-overlay cl-bootstrap-screen";let r=document.createElement("div");r.style.cssText="display:flex;justify-content:center",r.innerHTML=ae({width:"170px",className:"cl-crosslink-logo"}),n.appendChild(r);let o=document.createElement("h2");o.className="cl-bootstrap-appname",o.textContent=this.options.onboarding?.appName||this.options.appName||"Crosslink",n.appendChild(o);let i=document.createElement("button");i.className="cl-continue-btn",i.innerHTML="Continue in browser &rarr;",i.onclick=()=>e(),n.appendChild(i);let s=document.createElement("div");return s.className="cl-bootstrap-nudge",s.innerHTML=`
959
+ <span>Add to home screen</span>
960
+ <svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
961
+ <path d="M24 5 C 24 16, 24 27, 24 39" stroke="currentColor" stroke-width="3" stroke-linecap="round" fill="none"/>
962
+ <path d="M16 31 L 24 40 L 32 31" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
963
+ </svg>
964
+ `,n.appendChild(s),n}showSasConfirmation(e){return new Promise(n=>{let r=document.createElement("div");r.id="crosslink-sas-modal",r.className="cl-sas-modal";let o=document.createElement("div");o.style.cssText="display:flex;justify-content:center;margin-bottom:8px",o.innerHTML=ae({width:"120px",className:"cl-crosslink-logo"}),r.appendChild(o);let i=document.createElement("h2");i.textContent="Verify Security Code",r.appendChild(i);let s=document.createElement("p");s.textContent="Confirm the numbers match on your computer:",r.appendChild(s);let a=document.createElement("div");a.className="cl-sas-grid";for(let p of e.sas.replace(/\s/g,"")){let h=document.createElement("span");h.textContent=p,a.appendChild(h)}r.appendChild(a);let c=document.createElement("p");c.className="cl-sas-caps",c.textContent="Capabilities: "+(e.grantedCaps.join(", ")||"(none)"),r.appendChild(c);let l=document.createElement("div");l.className="cl-sas-actions";let d=document.createElement("button");d.className="cl-sas-ok",d.textContent="They match",d.onclick=()=>{r.remove(),n(!0)};let f=document.createElement("button");f.className="cl-sas-no",f.textContent="Cancel",f.onclick=()=>{r.remove(),n(!1)},l.append(d,f),r.appendChild(l),document.body.appendChild(r)})}scheduleReconnect(){if(this.reconnectTimer)return;let n=Math.min(3e4,1e3*Math.pow(1.5,Math.min(this.attemptCount,8)))*(.8+Math.random()*.4);this.reconnectTimer=setTimeout(async()=>{this.reconnectTimer=null,this.attemptCount++,await this.forceReconnect()},n)}async forceReconnect(){let e=this.client.listApps();if(e.length===0){this.transitionTo("pairing-required");return}this.client.close(),await this.attemptSilentAuth(e[0])}cancelTimers(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.reachabilityTimer&&(clearInterval(this.reachabilityTimer),this.reachabilityTimer=null),this.attemptCount=0}setupListeners(){typeof document>"u"||typeof window>"u"||(this.visibilityHandler=()=>{!document.hidden&&this.state==="offline"&&this.forceReconnect().catch(()=>{})},document.addEventListener("visibilitychange",this.visibilityHandler),this.onlineHandler=()=>{this.state==="offline"&&this.forceReconnect().catch(()=>{})},window.addEventListener("online",this.onlineHandler))}getEnvironment(){return this.environment}getState(){return this.state}getClient(){return this.client}destroy(){this.cancelTimers(),this.unmountCurrentScreen(),this.poweredBy?.destroy(),this.poweredBy=null,typeof document<"u"&&this.visibilityHandler&&document.removeEventListener("visibilitychange",this.visibilityHandler),typeof window<"u"&&this.onlineHandler&&window.removeEventListener("online",this.onlineHandler)}};var Ut={version:"2.0.0",precacheAssets:["./mobile.html","./bundle.js","./manifest.webmanifest","./crosslink-mark.svg","./icon-192.png","./icon-512.png"],navigationTimeoutMs:4e3};function sr(t={}){let e=t.version||Ut.version,n=t.precacheAssets||Ut.precacheAssets,r=t.navigationTimeoutMs??Ut.navigationTimeoutMs??4e3,o=`crosslink-shell-v${e}`,i=JSON.stringify(n,null,2);return`/* Crosslink PWA Service Worker \u2014 Generated by Crosslink Framework */
965
+ const CACHE_NAME = "${o}";
966
+ const PRECACHE_ASSETS = ${i};
967
+ const NAVIGATION_TIMEOUT_MS = ${r};
968
+
969
+ // Endpoints and patterns that must NEVER be cached (security, credentials, active RPC/presence)
970
+ const NEVER_CACHE_PATTERNS = [
971
+ "/api/",
972
+ "/rpc/",
973
+ "/ws",
974
+ "/pair",
975
+ "/verify-pair",
976
+ "/challenge",
977
+ "/session",
978
+ "/__crosslink/install/",
979
+ "/revoke",
980
+ "/events"
981
+ ];
982
+
983
+ function isSecuritySensitive(url) {
984
+ const path = url.pathname;
985
+ return NEVER_CACHE_PATTERNS.some((pattern) => path.includes(pattern));
986
+ }
987
+
988
+ async function fetchNavigation(request) {
989
+ const controller = new AbortController();
990
+ const timeout = setTimeout(() => controller.abort(), NAVIGATION_TIMEOUT_MS);
991
+ try {
992
+ const response = await fetch(request, { signal: controller.signal });
993
+ if (!response || !response.ok) throw new Error("host navigation unavailable");
994
+ return response;
995
+ } finally {
996
+ clearTimeout(timeout);
997
+ }
998
+ }
999
+
1000
+ self.addEventListener("install", (event) => {
1001
+ event.waitUntil(
1002
+ caches.open(CACHE_NAME).then(async (cache) => {
1003
+ // Robust asset caching: fetch individually so one missing asset doesn't abort entire install
1004
+ for (const asset of PRECACHE_ASSETS) {
1005
+ try {
1006
+ const res = await fetch(asset, { cache: "no-cache" });
1007
+ if (res.ok) {
1008
+ await cache.put(asset, res);
1009
+ }
1010
+ } catch (err) {
1011
+ console.warn("[Crosslink SW] Precache missed:", asset);
1012
+ }
1013
+ }
1014
+ })
1015
+ );
1016
+ self.skipWaiting();
1017
+ });
1018
+
1019
+ self.addEventListener("activate", (event) => {
1020
+ event.waitUntil(
1021
+ caches.keys().then((keys) =>
1022
+ Promise.all(
1023
+ keys
1024
+ .filter((key) => key.startsWith("crosslink-") && key !== CACHE_NAME)
1025
+ .map((key) => caches.delete(key))
1026
+ )
1027
+ ).then(() => self.clients.claim())
1028
+ );
1029
+ });
1030
+
1031
+ self.addEventListener("fetch", (event) => {
1032
+ const { request } = event;
1033
+ if (request.method !== "GET") return;
1034
+
1035
+ const url = new URL(request.url);
1036
+ // Ignore cross-origin requests
1037
+ if (url.origin !== self.location.origin) return;
1038
+
1039
+ // Never cache auth or API calls
1040
+ if (isSecuritySensitive(url)) {
1041
+ return;
1042
+ }
1043
+
1044
+ // Install-specific manifests and bootstrap navigations carry only an opaque
1045
+ // handoff id, but serving a cached response for another install would still
1046
+ // lose or cross-wire the handoff. Always go to the network for them.
1047
+ if (url.searchParams.has("crosslink_install")) {
1048
+ event.respondWith(fetch(request, { cache: "no-store" }));
1049
+ return;
1050
+ }
1051
+
1052
+ // 1. Navigation requests: network-first with offline fallback to cached shell
1053
+ if (request.mode === "navigate") {
1054
+ event.respondWith(
1055
+ fetchNavigation(request)
1056
+ .then((response) => {
1057
+ if (response && response.ok) {
1058
+ const copy = response.clone();
1059
+ caches.open(CACHE_NAME).then((cache) => cache.put(request, copy));
1060
+ }
1061
+ return response;
1062
+ })
1063
+ .catch(async () => {
1064
+ // Host is offline: return cached shell
1065
+ const cached =
1066
+ (await caches.match(request, { ignoreSearch: true })) ||
1067
+ (await caches.match("./mobile.html", { ignoreSearch: true })) ||
1068
+ (await caches.match("/mobile.html", { ignoreSearch: true })) ||
1069
+ (await caches.match("/", { ignoreSearch: true }));
1070
+ if (cached) return cached;
1071
+ return new Response("Application is offline", {
1072
+ status: 503,
1073
+ statusText: "Offline",
1074
+ headers: { "Content-Type": "text/plain" }
1075
+ });
1076
+ })
1077
+ );
1078
+ return;
1079
+ }
1080
+
1081
+ // 2. Static shell assets: cache-first with network fallback
1082
+ event.respondWith(
1083
+ caches.match(request, { ignoreSearch: true }).then((hit) => {
1084
+ if (hit) return hit;
1085
+ return fetch(request).then((response) => {
1086
+ if (response && response.ok) {
1087
+ const copy = response.clone();
1088
+ caches.open(CACHE_NAME).then((cache) => cache.put(request, copy));
1089
+ }
1090
+ return response;
1091
+ });
1092
+ })
1093
+ );
1094
+ });
1095
+
1096
+ self.addEventListener("message", (event) => {
1097
+ if (event.data === "skipWaiting") {
1098
+ self.skipWaiting();
1099
+ }
1100
+ });
1101
+ `}var Co=sr();function So(t){let e=[t.startUrl||"./mobile.html","./bundle.js",t.manifestPath||"./manifest.webmanifest","./crosslink-mark.svg"];if(t.icons)for(let n of t.icons)n.src&&!e.includes(n.src)&&e.push(n.src);return{version:t.version||"1.0.0",precacheAssets:e}}St();function fd(t={}){let e=t.storage??(typeof localStorage<"u"?new Re(localStorage):void 0);return new me({...t,storage:e})}function ud(t={}){return me.create(t)}return pa(hd);})();
1102
+ /*! Bundled license information:
1103
+
1104
+ @noble/ciphers/esm/utils.js:
1105
+ (*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) *)
1106
+
1107
+ @noble/hashes/esm/utils.js:
1108
+ (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
1109
+
1110
+ @noble/curves/esm/utils.js:
1111
+ @noble/curves/esm/abstract/modular.js:
1112
+ @noble/curves/esm/abstract/curve.js:
1113
+ @noble/curves/esm/abstract/edwards.js:
1114
+ @noble/curves/esm/abstract/montgomery.js:
1115
+ @noble/curves/esm/ed25519.js:
1116
+ @noble/curves/utils.js:
1117
+ (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
1118
+
1119
+ @noble/post-quantum/utils.js:
1120
+ @noble/post-quantum/_crystals.js:
1121
+ @noble/post-quantum/ml-kem.js:
1122
+ (*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) *)
1123
+ */