var Jn=Object.create;var dr=Object.defineProperty;var Zn=Object.getOwnPropertyDescriptor;var es=Object.getOwnPropertyNames;var ts=Object.getPrototypeOf,is=Object.prototype.hasOwnProperty;var ur=(s,e)=>()=>{try{return e||s((e={exports:{}}).exports,e),e.exports}catch(t){throw e=0,t}};var rs=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of es(e))!is.call(s,r)&&r!==t&&dr(s,r,{get:()=>e[r],enumerable:!(i=Zn(e,r))||i.enumerable});return s};var hr=(s,e,t)=>(t=s!=null?Jn(ts(s)):{},rs(e||!s||!s.__esModule?dr(t,"default",{value:s,enumerable:!0}):t,s));var Tn=ur((vo,Gt)=>{var wt=class{constructor(e={}){this.permission=typeof Notification<"u"&&Notification&&typeof Notification.permission=="string"?Notification.permission:"denied",this.isTabActive=this.checkTabActive(),this.unreadCount=0,this.originalTitle=document.title,this.notificationQueue=[],this.maxQueueSize=e.maxQueueSize||5,this.rateLimitMs=e.rateLimitMs||2e3,this.lastNotificationTime=0,this.trustedOrigins=e.trustedOrigins||[],this.isSecureContext=window.isSecureContext,this.hidden=this.getHiddenProperty(),this.visibilityChange=this.getVisibilityChangeEvent(),this.initVisibilityTracking(),this.initSecurityChecks()}initSecurityChecks(){}getHiddenProperty(){return typeof document.hidden<"u"?"hidden":typeof document.msHidden<"u"?"msHidden":typeof document.webkitHidden<"u"?"webkitHidden":"hidden"}getVisibilityChangeEvent(){return typeof document.hidden<"u"?"visibilitychange":typeof document.msHidden<"u"?"msvisibilitychange":typeof document.webkitHidden<"u"?"webkitvisibilitychange":"visibilitychange"}checkTabActive(){return this.hidden&&typeof document[this.hidden]<"u"?!document[this.hidden]:typeof document.hasFocus=="function"?document.hasFocus():!0}initVisibilityTracking(){typeof document.addEventListener<"u"&&typeof document[this.hidden]<"u"&&document.addEventListener(this.visibilityChange,()=>{this.isTabActive=this.checkTabActive(),this.isTabActive&&(this.resetUnreadCount(),this.clearNotificationQueue())}),window.addEventListener("focus",()=>{this.isTabActive=this.checkTabActive(),this.isTabActive&&this.resetUnreadCount()}),window.addEventListener("blur",()=>{this.isTabActive=this.checkTabActive()}),window.addEventListener("beforeunload",()=>{this.clearNotificationQueue()})}async requestPermission(){if(!this.isSecureContext||!("Notification"in window))return!1;if(this.permission==="granted")return!0;if(this.permission==="denied")return!1;try{return this.permission=await Notification.requestPermission(),this.permission==="granted"}catch{return!1}}updateTitle(){this.unreadCount>0?document.title=`(${this.unreadCount}) ${this.originalTitle}`:document.title=this.originalTitle}sanitizeText(e){if(typeof e!="string")return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML.replace(//g,">").replace(/"/g,""").replace(/'/g,"'").substring(0,500)}validateIconUrl(e){if(!e)return null;try{let t=new URL(e,window.location.origin);return t.protocol==="https:"||t.protocol==="data:"?this.trustedOrigins.length>0?this.trustedOrigins.some(r=>t.origin===r)?t.href:null:t.href:null}catch{return null}}checkRateLimit(){let e=Date.now();return e-this.lastNotificationTime"u"||(this.isTabActive=this.checkTabActive(),this.isTabActive)||this.permission!=="granted"||!this.checkRateLimit())return null;let r=this.sanitizeText(e||"Unknown"),n=this.sanitizeText(t||""),a=this.validateIconUrl(i.icon)||"/logo/icon-192x192.png";this.notificationQueue.length>=this.maxQueueSize&&this.clearNotificationQueue();try{let o=new Notification(`${r}`,{body:n.substring(0,200),icon:a,badge:a,tag:`chat-${i.senderId||"unknown"}`,requireInteraction:!1,silent:i.silent||!1,vibrate:navigator.vibrate?[200,100,200]:void 0,data:{senderId:this.sanitizeText(i.senderId),timestamp:Date.now()}});this.unreadCount++,this.updateTitle(),this.notificationQueue.push(o),o.onclick=l=>{if(l.preventDefault(),window.focus(),o.close(),typeof i.onClick=="function")try{i.onClick(i.senderId)}catch(h){console.error("[Notifications] Error in onClick handler:",h)}},o.onerror=l=>{console.error("[Notifications] Error showing notification:",l)};let c=Math.min(i.autoClose||5e3,1e4);return setTimeout(()=>{o.close(),this.removeFromQueue(o)},c),o}catch(o){return console.error("[Notifications] Failed to create notification:",o),null}}removeFromQueue(e){let t=this.notificationQueue.indexOf(e);t>-1&&this.notificationQueue.splice(t,1)}clearNotificationQueue(){this.notificationQueue.forEach(e=>{try{e.close()}catch{}}),this.notificationQueue=[]}resetUnreadCount(){this.unreadCount=0,this.updateTitle()}getStatus(){return{permission:this.permission,isTabActive:this.isTabActive,unreadCount:this.unreadCount,isSecureContext:this.isSecureContext,queueSize:this.notificationQueue.length}}},qt=class{constructor(){this.notificationManager=new wt({maxQueueSize:5,rateLimitMs:2e3,trustedOrigins:[window.location.origin]}),this.dataChannel=null,this.peerConnection=null,this.remotePeerName="Peer",this.messageHistory=[],this.maxHistorySize=100}async init(){}async enableNotifications(){return await this.notificationManager.requestPermission()}setupDataChannel(e){if(!e){console.error("[Chat] Invalid DataChannel");return}this.dataChannel=e,this.dataChannel.onmessage=t=>{this.handleIncomingMessage(t.data)},this.dataChannel.onerror=t=>{}}validateMessage(e){try{let t=typeof e=="string"?JSON.parse(e):e;if(!t||typeof t!="object")throw new Error("Invalid message structure");if(!t.text||typeof t.text!="string")throw new Error("Invalid message text");if(t.text.length>1e4)throw new Error("Message too long");return{text:t.text,senderName:t.senderName||"Unknown",senderId:t.senderId||"unknown",timestamp:t.timestamp||Date.now(),senderAvatar:t.senderAvatar||null}}catch(t){return console.error("[Chat] Message validation failed:",t),null}}handleIncomingMessage(e){let t=this.validateMessage(e);t&&(this.messageHistory.push(t),this.messageHistory.length>this.maxHistorySize&&this.messageHistory.shift(),this.displayMessage(t),this.notificationManager.notify(t.senderName,t.text,{icon:t.senderAvatar,senderId:t.senderId,onClick:i=>{this.scrollToLatestMessage()}}),this.notificationManager.isTabActive||this.playNotificationSound())}displayMessage(e){let t=document.getElementById("messages");if(!t)return;let i=document.createElement("div");i.className="message";let r=document.createElement("strong");r.textContent=e.senderName+": ";let n=document.createElement("span");n.textContent=e.text,n.style.wordWrap="break-word",n.style.overflowWrap="break-word",n.style.whiteSpace="normal";let a=document.createElement("small");a.textContent=new Date(e.timestamp).toLocaleTimeString(),i.appendChild(r),i.appendChild(n),i.appendChild(document.createElement("br")),i.appendChild(a),t.appendChild(i),this.scrollToLatestMessage()}playNotificationSound(){try{let e=new Audio("/assets/audio/notification.mp3");e.volume=.3,e.play().catch(t=>{})}catch{}}scrollToLatestMessage(){let e=document.getElementById("messages");e&&(e.scrollTop=e.scrollHeight)}getStatus(){return{notifications:this.notificationManager.getStatus(),messageCount:this.messageHistory.length,connected:this.dataChannel?.readyState==="open"}}};typeof Gt<"u"&&Gt.exports&&(Gt.exports={SecureChatNotificationManager:wt,SecureP2PChat:qt});typeof window<"u"&&(window.SecureChatNotificationManager=wt,window.SecureP2PChat=qt)});var vn=ur((ko,jt)=>{var Cn=hr(Tn());var Wt=class{constructor(e){this.webrtcManager=e,this.notificationManager=new Cn.SecureChatNotificationManager({maxQueueSize:10,rateLimitMs:1e3,trustedOrigins:[window.location.origin]}),this.isInitialized=!1,this.originalOnMessage=null,this.originalOnStatusChange=null,this.processedMessages=new Set}async init(){try{return this.isInitialized||(this.originalOnMessage=this.webrtcManager.onMessage,this.originalOnStatusChange=this.webrtcManager.onStatusChange,this.webrtcManager.onMessage=(e,t,...i)=>{this.handleIncomingMessage(e,t,i[0]),this.originalOnMessage&&this.originalOnMessage(e,t,...i)},this.webrtcManager.onStatusChange=e=>{this.handleStatusChange(e),this.originalOnStatusChange&&this.originalOnStatusChange(e)},this.webrtcManager.deliverMessageToUI&&(this.originalDeliverMessageToUI=this.webrtcManager.deliverMessageToUI.bind(this.webrtcManager),this.webrtcManager.deliverMessageToUI=(e,t,...i)=>{this.handleIncomingMessage(e,t,i[0]),this.originalDeliverMessageToUI(e,t,...i)}),this.isInitialized=!0),!0}catch{return!1}}handleIncomingMessage(e,t,i){try{let r=`${t}:${typeof e=="string"?e:JSON.stringify(e)}`;if(this.processedMessages.has(r))return;if(this.processedMessages.add(r),this.processedMessages.size>100){let l=Array.from(this.processedMessages);this.processedMessages.clear(),l.slice(-50).forEach(h=>this.processedMessages.add(h))}if(t==="system"||t==="file-transfer"||t==="heartbeat")return;let n=this.extractMessageInfo(e,t);if(!n)return;let o=!!i&&typeof i=="object"&&(i.once===!0||Number.isFinite(i.ttl)&&i.ttl>0)?"Sent you a private message":n.text,c=this.notificationManager.notify(n.senderName,o,{icon:n.senderAvatar,senderId:n.senderId,onClick:l=>{this.focusChatWindow()}})}catch{}}handleStatusChange(e){try{(e==="disconnected"||e==="failed")&&(this.notificationManager.clearNotificationQueue(),this.notificationManager.resetUnreadCount())}catch{}}extractMessageInfo(e,t){try{let i=e;if(typeof e=="string")try{i=JSON.parse(e)}catch{return{senderName:"Peer",text:e,senderId:"peer",senderAvatar:null}}return typeof i=="object"&&i!==null?{senderName:i.senderName||i.name||"Peer",text:i.text||i.message||i.content||"",senderId:i.senderId||i.id||"peer",senderAvatar:i.senderAvatar||i.avatar||null}:null}catch{return null}}focusChatWindow(){try{window.focus();let e=document.getElementById("messages");e&&(e.scrollTop=e.scrollHeight)}catch{}}async requestPermission(){try{return await this.notificationManager.requestPermission()}catch{return!1}}getStatus(){return this.notificationManager.getStatus()}clearNotifications(){this.notificationManager.clearNotificationQueue(),this.notificationManager.resetUnreadCount()}cleanup(){try{this.isInitialized&&(this.originalOnMessage&&(this.webrtcManager.onMessage=this.originalOnMessage),this.originalOnStatusChange&&(this.webrtcManager.onStatusChange=this.originalOnStatusChange),this.originalDeliverMessageToUI&&(this.webrtcManager.deliverMessageToUI=this.originalDeliverMessageToUI),this.clearNotifications(),this.isInitialized=!1)}catch{}}};typeof jt<"u"&&jt.exports&&(jt.exports={NotificationIntegration:Wt});typeof window<"u"&&(window.NotificationIntegration=Wt)});function fr(s,e){(e==null||e>s.length)&&(e=s.length);for(var t=0,i=Array(e);t2?i-2:0),n=2;n1?t-1:0),r=1;r"u"?null:re(BigInt.prototype.toString),_r=typeof Symbol>"u"?null:re(Symbol.prototype.toString),pe=re(Object.prototype.hasOwnProperty),ft=re(Object.prototype.toString),ae=re(RegExp.prototype.test),$e=ms(TypeError);function re(s){return function(e){e instanceof RegExp&&(e.lastIndex=0);for(var t=arguments.length,i=new Array(t>1?t-1:0),r=1;r2&&arguments[2]!==void 0?arguments[2]:pt;if(pr&&pr(s,null),!Fe(e))return s;let i=e.length;for(;i--;){let r=e[i];if(typeof r=="string"){let n=t(r);n!==r&&(ls(e)||(e[i]=n),r=n)}s[r]=!0}return s}function Ss(s){for(let e=0;e/g),vs=ce(/\${[\w\W]*/g),ks=ce(/^data-[\-\w.\u00B7-\uFFFF]+$/),As=ce(/^aria-[\-\w]+$/),Cr=ce(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Is=ce(/^(?:\w+script|data):/i),xs=ce(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),Rs=ce(/^html$/i),Ms=ce(/^[a-z][.\w]*(-[.\w]+)+$/i),vr=ce(/<[/\w!]/g),Ls=ce(/<[/\w]/g),Ds=ce(/<\/no(script|embed|frames)/i),Ps=ce(/\/>/i),ve={element:1,attribute:2,text:3,cdataSection:4,entityReference:5,entityNode:6,processingInstruction:7,comment:8,document:9,documentType:10,documentFragment:11,notation:12},Fs=function(){return typeof window>"u"?null:window},Ks=function(e,t){if(typeof e!="object"||typeof e.createPolicy!="function")return null;let i=null,r="data-tt-policy-suffix";t&&t.hasAttribute(r)&&(i=t.getAttribute(r));let n="dompurify"+(i?"#"+i:"");try{return e.createPolicy(n,{createHTML(a){return a},createScriptURL(a){return a}})}catch{return console.warn("TrustedTypes policy "+n+" could not be created."),null}},kr=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},Pe=function(e,t,i,r){return pe(e,t)&&Fe(e[t])?V(r.base?fe(r.base):{},e[t],r.transform):i};function xr(){let s=arguments.length>0&&arguments[0]!==void 0?arguments[0]:Fs(),e=k=>xr(k);if(e.version="3.4.10",e.removed=[],!s||!s.document||s.document.nodeType!==ve.document||!s.Element)return e.isSupported=!1,e;let t=s.document,i=t,r=i.currentScript;s.DocumentFragment;let n=s.HTMLTemplateElement,a=s.Node,o=s.Element,c=s.NodeFilter,l=s.NamedNodeMap;l===void 0&&(s.NamedNodeMap||s.MozNamedAttrMap),s.HTMLFormElement;let h=s.DOMParser,u=s.trustedTypes,p=o.prototype,S=ke(p,"cloneNode"),w=ke(p,"remove"),g=ke(p,"nextSibling"),m=ke(p,"childNodes"),I=ke(p,"parentNode"),b=ke(p,"shadowRoot"),D=ke(p,"attributes"),_=a&&a.prototype?ke(a.prototype,"nodeType"):null,R=a&&a.prototype?ke(a.prototype,"nodeName"):null;if(typeof n=="function"){let k=t.createElement("template");k.content&&k.content.ownerDocument&&(t=k.content.ownerDocument)}let E,C="",M,v=!1,q=0,O=function(){if(q>0)throw $e('A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.')},x=function(d){O(),q++;try{return E.createHTML(d)}finally{q--}},ue=function(d){O(),q++;try{return E.createScriptURL(d)}finally{q--}},ne=function(){return v||(M=Ks(u,r),v=!0),M},te=t,ye=te.implementation,Re=te.createNodeIterator,j=te.createDocumentFragment,U=te.getElementsByTagName,H=i.importNode,A=kr();e.isSupported=typeof Ar=="function"&&typeof I=="function"&&ye&&ye.createHTMLDocument!==void 0;let F=Ts,K=Cs,z=vs,W=ks,X=As,Se=Is,_e=xs,ge=Ms,Ye=Cr,Y=null,Xt=V({},[...wr,...pi,...yi,...gi,...Er]),ee=null,Qt=V({},[...br,...mi,...Tr,...It]),J=Object.seal(it(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),ot=null,Bi=null,Me=Object.seal(it(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}})),Hi=!0,Jt=!0,$i=!1,Gi=!0,Le=!1,ct=!0,Be=!1,Zt=!1,ei=!1,Xe=!1,Et=!1,bt=!1,qi=!0,ji=!1,Wi="user-content-",ti=!0,ii=!1,Qe={},Te=null,ri=V({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","selectedcontent","style","svg","template","thead","title","video","xmp"]),Yi=null,Xi=V({},["audio","video","img","source","image","track"]),ni=null,Qi=V({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Tt="http://www.w3.org/1998/Math/MathML",Ct="http://www.w3.org/2000/svg",Ce="http://www.w3.org/1999/xhtml",Je=Ce,si=!1,ai=null,Kn=V({},[Tt,Ct,Ce],fi),Ji=oe(["mi","mo","mn","ms","mtext"]),oi=V({},Ji),Zi=oe(["annotation-xml"]),ci=V({},Zi),Nn=V({},["title","style","font","a","script"]),lt=null,On=["application/xhtml+xml","text/html"],Un="text/html",Z=null,Ze=null,zn=t.createElement("form"),er=function(d){return d instanceof RegExp||d instanceof Function},li=function(){let d=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(Ze&&Ze===d)return;(!d||typeof d!="object")&&(d={}),d=fe(d),lt=On.indexOf(d.PARSER_MEDIA_TYPE)===-1?Un:d.PARSER_MEDIA_TYPE,Z=lt==="application/xhtml+xml"?fi:pt,Y=Pe(d,"ALLOWED_TAGS",Xt,{transform:Z}),ee=Pe(d,"ALLOWED_ATTR",Qt,{transform:Z}),ai=Pe(d,"ALLOWED_NAMESPACES",Kn,{transform:fi}),ni=Pe(d,"ADD_URI_SAFE_ATTR",Qi,{transform:Z,base:Qi}),Yi=Pe(d,"ADD_DATA_URI_TAGS",Xi,{transform:Z,base:Xi}),Te=Pe(d,"FORBID_CONTENTS",ri,{transform:Z}),ot=Pe(d,"FORBID_TAGS",fe({}),{transform:Z}),Bi=Pe(d,"FORBID_ATTR",fe({}),{transform:Z}),Qe=pe(d,"USE_PROFILES")?d.USE_PROFILES&&typeof d.USE_PROFILES=="object"?fe(d.USE_PROFILES):d.USE_PROFILES:!1,Hi=d.ALLOW_ARIA_ATTR!==!1,Jt=d.ALLOW_DATA_ATTR!==!1,$i=d.ALLOW_UNKNOWN_PROTOCOLS||!1,Gi=d.ALLOW_SELF_CLOSE_IN_ATTR!==!1,Le=d.SAFE_FOR_TEMPLATES||!1,ct=d.SAFE_FOR_XML!==!1,Be=d.WHOLE_DOCUMENT||!1,Xe=d.RETURN_DOM||!1,Et=d.RETURN_DOM_FRAGMENT||!1,bt=d.RETURN_TRUSTED_TYPE||!1,ei=d.FORCE_BODY||!1,qi=d.SANITIZE_DOM!==!1,ji=d.SANITIZE_NAMED_PROPS||!1,ti=d.KEEP_CONTENT!==!1,ii=d.IN_PLACE||!1,Ye=ws(d.ALLOWED_URI_REGEXP)?d.ALLOWED_URI_REGEXP:Cr,Je=typeof d.NAMESPACE=="string"?d.NAMESPACE:Ce,oi=pe(d,"MATHML_TEXT_INTEGRATION_POINTS")&&d.MATHML_TEXT_INTEGRATION_POINTS&&typeof d.MATHML_TEXT_INTEGRATION_POINTS=="object"?fe(d.MATHML_TEXT_INTEGRATION_POINTS):V({},Ji),ci=pe(d,"HTML_INTEGRATION_POINTS")&&d.HTML_INTEGRATION_POINTS&&typeof d.HTML_INTEGRATION_POINTS=="object"?fe(d.HTML_INTEGRATION_POINTS):V({},Zi);let y=pe(d,"CUSTOM_ELEMENT_HANDLING")&&d.CUSTOM_ELEMENT_HANDLING&&typeof d.CUSTOM_ELEMENT_HANDLING=="object"?fe(d.CUSTOM_ELEMENT_HANDLING):it(null);if(J=it(null),pe(y,"tagNameCheck")&&er(y.tagNameCheck)&&(J.tagNameCheck=y.tagNameCheck),pe(y,"attributeNameCheck")&&er(y.attributeNameCheck)&&(J.attributeNameCheck=y.attributeNameCheck),pe(y,"allowCustomizedBuiltInElements")&&typeof y.allowCustomizedBuiltInElements=="boolean"&&(J.allowCustomizedBuiltInElements=y.allowCustomizedBuiltInElements),ce(J),Le&&(Jt=!1),Et&&(Xe=!0),Qe&&(Y=V({},Er),ee=it(null),Qe.html===!0&&(V(Y,wr),V(ee,br)),Qe.svg===!0&&(V(Y,pi),V(ee,mi),V(ee,It)),Qe.svgFilters===!0&&(V(Y,yi),V(ee,mi),V(ee,It)),Qe.mathMl===!0&&(V(Y,gi),V(ee,Tr),V(ee,It))),Me.tagCheck=null,Me.attributeCheck=null,pe(d,"ADD_TAGS")&&(typeof d.ADD_TAGS=="function"?Me.tagCheck=d.ADD_TAGS:Fe(d.ADD_TAGS)&&(Y===Xt&&(Y=fe(Y)),V(Y,d.ADD_TAGS,Z))),pe(d,"ADD_ATTR")&&(typeof d.ADD_ATTR=="function"?Me.attributeCheck=d.ADD_ATTR:Fe(d.ADD_ATTR)&&(ee===Qt&&(ee=fe(ee)),V(ee,d.ADD_ATTR,Z))),pe(d,"ADD_URI_SAFE_ATTR")&&Fe(d.ADD_URI_SAFE_ATTR)&&V(ni,d.ADD_URI_SAFE_ATTR,Z),pe(d,"FORBID_CONTENTS")&&Fe(d.FORBID_CONTENTS)&&(Te===ri&&(Te=fe(Te)),V(Te,d.FORBID_CONTENTS,Z)),pe(d,"ADD_FORBID_CONTENTS")&&Fe(d.ADD_FORBID_CONTENTS)&&(Te===ri&&(Te=fe(Te)),V(Te,d.ADD_FORBID_CONTENTS,Z)),ti&&(Y["#text"]=!0),Be&&V(Y,["html","head","body"]),Y.table&&(V(Y,["tbody"]),delete ot.tbody),d.TRUSTED_TYPES_POLICY){if(typeof d.TRUSTED_TYPES_POLICY.createHTML!="function")throw $e('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if(typeof d.TRUSTED_TYPES_POLICY.createScriptURL!="function")throw $e('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');let T=E;E=d.TRUSTED_TYPES_POLICY;try{C=x("")}catch(L){throw E=T,L}}else d.TRUSTED_TYPES_POLICY===null?(E=void 0,C=""):(E===void 0&&(E=ne()),E&&typeof C=="string"&&(C=x("")));(A.uponSanitizeElement.length>0||A.uponSanitizeAttribute.length>0)&&Y===Xt&&(Y=fe(Y)),A.uponSanitizeAttribute.length>0&&ee===Qt&&(ee=fe(ee)),oe&&oe(d),Ze=d},tr=V({},[...pi,...yi,...Es]),ir=V({},[...gi,...bs]),Vn=function(d,y,T){return y.namespaceURI===Ce?d==="svg":y.namespaceURI===Tt?d==="svg"&&(T==="annotation-xml"||oi[T]):!!tr[d]},Bn=function(d,y,T){return y.namespaceURI===Ce?d==="math":y.namespaceURI===Ct?d==="math"&&ci[T]:!!ir[d]},Hn=function(d,y,T){return y.namespaceURI===Ct&&!ci[T]||y.namespaceURI===Tt&&!oi[T]?!1:!ir[d]&&(Nn[d]||!tr[d])},$n=function(d){let y=I(d);(!y||!y.tagName)&&(y={namespaceURI:Je,tagName:"template"});let T=pt(d.tagName),L=pt(y.tagName);return ai[d.namespaceURI]?d.namespaceURI===Ct?Vn(T,y,L):d.namespaceURI===Tt?Bn(T,y,L):d.namespaceURI===Ce?Hn(T,y,L):!!(lt==="application/xhtml+xml"&&ai[d.namespaceURI]):!1},De=function(d){tt(e.removed,{element:d});try{I(d).removeChild(d)}catch{if(w(d),!I(d))throw $e("a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place")}},rr=function(d){let y=m(d);if(y){let L=[];ut(y,N=>{tt(L,N)}),ut(L,N=>{try{w(N)}catch{}})}let T=D(d);if(T)for(let L=T.length-1;L>=0;--L){let N=T[L],B=N&&N.name;if(typeof B=="string")try{d.removeAttribute(B)}catch{}}},He=function(d,y){try{tt(e.removed,{attribute:y.getAttributeNode(d),from:y})}catch{tt(e.removed,{attribute:null,from:y})}if(y.removeAttribute(d),d==="is")if(Xe||Et)try{De(y)}catch{}else try{y.setAttribute(d,"")}catch{}},Gn=function(d){let y=D(d);if(y)for(let T=y.length-1;T>=0;--T){let L=y[T],N=L&&L.name;if(!(typeof N!="string"||ee[Z(N)]))try{d.removeAttribute(N)}catch{}}},qn=function(d){let y=[d];for(;y.length>0;){let T=y.pop();(_?_(T):T.nodeType)===ve.element&&Gn(T);let N=m(T);if(N)for(let B=N.length-1;B>=0;--B)y.push(N[B])}},nr=function(d){let y=null,T=null;if(ei)d=""+d;else{let B=gr(d,/^[\r\n\t ]+/);T=B&&B[0]}lt==="application/xhtml+xml"&&Je===Ce&&(d=''+d+"");let L=E?x(d):d;if(Je===Ce)try{y=new h().parseFromString(L,lt)}catch{}if(!y||!y.documentElement){y=ye.createDocument(Je,"template",null);try{y.documentElement.innerHTML=si?C:L}catch{}}let N=y.body||y.documentElement;return d&&T&&N.insertBefore(t.createTextNode(T),N.childNodes[0]||null),Je===Ce?U.call(y,Be?"html":"body")[0]:Be?y.documentElement:N},sr=function(d){return Re.call(d.ownerDocument||d,d,c.SHOW_ELEMENT|c.SHOW_COMMENT|c.SHOW_TEXT|c.SHOW_PROCESSING_INSTRUCTION|c.SHOW_CDATA_SECTION,null)},vt=function(d){return d=ht(d,F," "),d=ht(d,K," "),d=ht(d,z," "),d},di=function(d){var y;d.normalize();let T=Re.call(d.ownerDocument||d,d,c.SHOW_TEXT|c.SHOW_COMMENT|c.SHOW_CDATA_SECTION|c.SHOW_PROCESSING_INSTRUCTION,null),L=T.nextNode();for(;L;)L.data=vt(L.data),L=T.nextNode();let N=(y=d.querySelectorAll)===null||y===void 0?void 0:y.call(d,"template");N&&ut(N,B=>{et(B.content)&&di(B.content)})},kt=function(d){let y=R?R(d):null;return typeof y!="string"||Z(y)!=="form"?!1:typeof d.nodeName!="string"||typeof d.textContent!="string"||typeof d.removeChild!="function"||d.attributes!==D(d)||typeof d.removeAttribute!="function"||typeof d.setAttribute!="function"||typeof d.namespaceURI!="string"||typeof d.insertBefore!="function"||typeof d.hasChildNodes!="function"||d.nodeType!==_(d)||d.childNodes!==m(d)},et=function(d){if(!_||typeof d!="object"||d===null)return!1;try{return _(d)===ve.documentFragment}catch{return!1}},dt=function(d){if(!_||typeof d!="object"||d===null)return!1;try{return typeof _(d)=="number"}catch{return!1}};function Ae(k,d,y){k.length!==0&&ut(k,T=>{T.call(e,d,y,Ze)})}let jn=function(d,y){return!!(ct&&d.hasChildNodes()&&!dt(d.firstElementChild)&&ae(vr,d.textContent)&&ae(vr,d.innerHTML)||ct&&d.namespaceURI===Ce&&y==="style"&&dt(d.firstElementChild)||d.nodeType===ve.processingInstruction||ct&&d.nodeType===ve.comment&&ae(Ls,d.data))},Wn=function(d,y){if(!ot[y]&&cr(y)&&(J.tagNameCheck instanceof RegExp&&ae(J.tagNameCheck,y)||J.tagNameCheck instanceof Function&&J.tagNameCheck(y)))return!1;if(ti&&!Te[y]){let T=I(d),L=m(d);if(L&&T){let N=L.length;for(let B=N-1;B>=0;--B){let se=ii?L[B]:S(L[B],!0);T.insertBefore(se,g(d))}}}return De(d),!0},ar=function(d){if(Ae(A.beforeSanitizeElements,d,null),kt(d))return De(d),!0;let y=Z(R?R(d):d.nodeName);if(Ae(A.uponSanitizeElement,d,{tagName:y,allowedTags:Y}),jn(d,y))return De(d),!0;if(ot[y]||!(Me.tagCheck instanceof Function&&Me.tagCheck(y))&&!Y[y])return Wn(d,y);if((_?_(d):d.nodeType)===ve.element&&!$n(d)||(y==="noscript"||y==="noembed"||y==="noframes")&&ae(Ds,d.innerHTML))return De(d),!0;if(Le&&d.nodeType===ve.text){let L=vt(d.textContent);d.textContent!==L&&(tt(e.removed,{element:d.cloneNode()}),d.textContent=L)}return Ae(A.afterSanitizeElements,d,null),!1},or=function(d,y,T){if(Bi[y]||qi&&(y==="id"||y==="name")&&(T in t||T in zn))return!1;let L=ee[y]||Me.attributeCheck instanceof Function&&Me.attributeCheck(y,d);if(!(Jt&&ae(W,y))){if(!(Hi&&ae(X,y))){if(L){if(!ni[y]){if(!ae(Ye,ht(T,_e,""))){if(!((y==="src"||y==="xlink:href"||y==="href")&&d!=="script"&&mr(T,"data:")===0&&Yi[d])){if(!($i&&!ae(Se,ht(T,_e,"")))){if(T)return!1}}}}}else if(!(cr(d)&&(J.tagNameCheck instanceof RegExp&&ae(J.tagNameCheck,d)||J.tagNameCheck instanceof Function&&J.tagNameCheck(d))&&(J.attributeNameCheck instanceof RegExp&&ae(J.attributeNameCheck,y)||J.attributeNameCheck instanceof Function&&J.attributeNameCheck(y,d))||y==="is"&&J.allowCustomizedBuiltInElements&&(J.tagNameCheck instanceof RegExp&&ae(J.tagNameCheck,T)||J.tagNameCheck instanceof Function&&J.tagNameCheck(T))))return!1}}return!0},Yn=V({},["annotation-xml","color-profile","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","missing-glyph"]),cr=function(d){return!Yn[pt(d)]&&ae(ge,d)},Xn=function(d,y,T,L){if(E&&typeof u=="object"&&typeof u.getAttributeType=="function"&&!T)switch(u.getAttributeType(d,y)){case"TrustedHTML":return x(L);case"TrustedScriptURL":return ue(L)}return L},Qn=function(d,y,T,L){try{T?d.setAttributeNS(T,y,L):d.setAttribute(y,L),kt(d)?De(d):yr(e.removed)}catch{He(y,d)}},lr=function(d){Ae(A.beforeSanitizeAttributes,d,null);let y=d.attributes;if(!y||kt(d))return;let T={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:ee,forceKeepAttr:void 0},L=y.length,N=Z(d.nodeName);for(;L--;){let B=y[L],se=B.name,ie=B.namespaceURI,we=B.value,Ee=Z(se),hi=we,he=se==="value"?hi:ps(hi);if(T.attrName=Ee,T.attrValue=he,T.keepAttr=!0,T.forceKeepAttr=void 0,Ae(A.uponSanitizeAttribute,d,T),he=T.attrValue,ji&&(Ee==="id"||Ee==="name")&&mr(he,Wi)!==0&&(He(se,d),he=Wi+he),ct&&ae(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i,he)){He(se,d);continue}if(Ee==="attributename"&&gr(he,"href")){He(se,d);continue}if(!T.forceKeepAttr){if(!T.keepAttr){He(se,d);continue}if(!Gi&&ae(Ps,he)){He(se,d);continue}if(Le&&(he=vt(he)),!or(N,Ee,he)){He(se,d);continue}he=Xn(N,Ee,ie,he),he!==hi&&Qn(d,se,ie,he)}}Ae(A.afterSanitizeAttributes,d,null)},At=function(d){let y=null,T=sr(d);for(Ae(A.beforeSanitizeShadowDOM,d,null);y=T.nextNode();)if(Ae(A.uponSanitizeShadowNode,y,null),ar(y),lr(y),et(y.content)&&At(y.content),(_?_(y):y.nodeType)===ve.element){let N=b(y);et(N)&&(ui(N),At(N))}Ae(A.afterSanitizeShadowDOM,d,null)},ui=function(d){let y=[{node:d,shadow:null}];for(;y.length>0;){let T=y.pop();if(T.shadow){At(T.shadow);continue}let L=T.node,B=(_?_(L):L.nodeType)===ve.element,se=m(L);if(se)for(let ie=se.length-1;ie>=0;--ie)y.push({node:se[ie],shadow:null});if(B){let ie=R?R(L):null;if(typeof ie=="string"&&Z(ie)==="template"){let we=L.content;et(we)&&y.push({node:we,shadow:null})}}if(B){let ie=b(L);et(ie)&&y.push({node:null,shadow:ie},{node:ie,shadow:null})}}};return e.sanitize=function(k){let d=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},y=null,T=null,L=null,N=null;if(si=!k,si&&(k=""),typeof k!="string"&&!dt(k)&&(k=_s(k),typeof k!="string"))throw $e("dirty is not a string, aborting");if(!e.isSupported)return k;Zt||li(d),e.removed=[];let B=ii&&typeof k!="string"&&dt(k);if(B){let we=R?R(k):k.nodeName;if(typeof we=="string"){let Ee=Z(we);if(!Y[Ee]||ot[Ee])throw $e("root node is forbidden and cannot be sanitized in-place")}if(kt(k))throw $e("root node is clobbered and cannot be sanitized in-place");try{ui(k)}catch(Ee){throw rr(k),Ee}}else if(dt(k))y=nr(""),T=y.ownerDocument.importNode(k,!0),T.nodeType===ve.element&&T.nodeName==="BODY"||T.nodeName==="HTML"?y=T:y.appendChild(T),ui(T);else{if(!Xe&&!Le&&!Be&&k.indexOf("<")===-1)return E&&bt?x(k):k;if(y=nr(k),!y)return Xe?null:bt?C:""}y&&ei&&De(y.firstChild);let se=sr(B?k:y);try{for(;L=se.nextNode();)ar(L),lr(L),et(L.content)&&At(L.content)}catch(we){throw B&&rr(k),we}if(B)return ut(e.removed,we=>{we.element&&qn(we.element)}),Le&&di(k),k;if(Xe){if(Le&&di(y),Et)for(N=j.call(y.ownerDocument);y.firstChild;)N.appendChild(y.firstChild);else N=y;return(ee.shadowroot||ee.shadowrootmode)&&(N=H.call(i,N,!0)),N}let ie=Be?y.outerHTML:y.innerHTML;return Be&&Y["!doctype"]&&y.ownerDocument&&y.ownerDocument.doctype&&y.ownerDocument.doctype.name&&ae(Rs,y.ownerDocument.doctype.name)&&(ie=" `+ie),Le&&(ie=vt(ie)),E&&bt?x(ie):ie},e.setConfig=function(){let k=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};li(k),Zt=!0},e.clearConfig=function(){Ze=null,Zt=!1,E=M,C=""},e.isValidAttribute=function(k,d,y){Ze||li({});let T=Z(k),L=Z(d);return or(T,L,y)},e.addHook=function(k,d){typeof d=="function"&&tt(A[k],d)},e.removeHook=function(k,d){if(d!==void 0){let y=hs(A[k],d);return y===-1?void 0:fs(A[k],y,1)[0]}return yr(A[k])},e.removeHooks=function(k){A[k]=[]},e.removeAllHooks=function(){A=kr()},e}var Rr=xr();var xt=class s{static _keyMetadata=new WeakMap;static _messageSanitizer=null;static sortObjectKeys(e){if(typeof e!="object"||e===null)return e;if(Array.isArray(e))return e.map(s.sortObjectKeys);let t={};return Object.keys(e).sort().forEach(i=>{t[i]=s.sortObjectKeys(e[i])}),t}static assertCryptoKey(e,t=null,i=[]){if(!(e instanceof CryptoKey))throw new Error("Expected CryptoKey");if(t&&e.algorithm?.name!==t)throw new Error(`Expected algorithm ${t}, got ${e.algorithm?.name}`);for(let r of i)if(!e.usages||!e.usages.includes(r))throw new Error(`Missing required key usage: ${r}`)}static arrayBufferToBase64(e){let t="",i=new Uint8Array(e),r=i.byteLength;for(let n=0;n=4294967296-4294967296%t);r+=e[a%t]}return r}static async calculateSecurityLevel(e){let t=0,i=100,r={};try{if(!e||!e.securityFeatures)return console.warn("Security manager not fully initialized, using fallback calculation"),{level:"INITIALIZING",score:0,color:"gray",verificationResults:{},timestamp:Date.now(),details:"Security system initializing...",isRealData:!1};let n="full",a=!1;try{let u=await s.verifyEncryption(e);u.passed?(t+=20,r.verifyEncryption={passed:!0,details:u.details,points:20}):r.verifyEncryption={passed:!1,details:u.details,points:0}}catch(u){r.verifyEncryption={passed:!1,details:`Encryption check failed: ${u.message}`,points:0}}try{let u=await s.verifyECDHKeyExchange(e);u.passed?(t+=15,r.verifyECDHKeyExchange={passed:!0,details:u.details,points:15}):r.verifyECDHKeyExchange={passed:!1,details:u.details,points:0}}catch(u){r.verifyECDHKeyExchange={passed:!1,details:`Key exchange check failed: ${u.message}`,points:0}}try{let u=await s.verifyMessageIntegrity(e);u.passed?(t+=10,r.verifyMessageIntegrity={passed:!0,details:u.details,points:10}):r.verifyMessageIntegrity={passed:!1,details:u.details,points:0}}catch(u){r.verifyMessageIntegrity={passed:!1,details:`Message integrity check failed: ${u.message}`,points:0}}try{let u=await s.verifyECDSASignatures(e);u.passed?(t+=15,r.verifyECDSASignatures={passed:!0,details:u.details,points:15}):r.verifyECDSASignatures={passed:!1,details:u.details,points:0}}catch(u){r.verifyECDSASignatures={passed:!1,details:`Digital signatures check failed: ${u.message}`,points:0}}try{let u=await s.verifyRateLimiting(e);u.passed?(t+=5,r.verifyRateLimiting={passed:!0,details:u.details,points:5}):r.verifyRateLimiting={passed:!1,details:u.details,points:0}}catch(u){r.verifyRateLimiting={passed:!1,details:`Rate limiting check failed: ${u.message}`,points:0}}try{let u=await s.verifyMetadataProtection(e);u.passed?(t+=10,r.verifyMetadataProtection={passed:!0,details:u.details,points:10}):r.verifyMetadataProtection={passed:!1,details:u.details,points:0}}catch(u){r.verifyMetadataProtection={passed:!1,details:`Metadata protection check failed: ${u.message}`,points:0}}try{let u=await s.verifyPerfectForwardSecrecy(e);u.passed?(t+=10,r.verifyPerfectForwardSecrecy={passed:!0,details:u.details,points:10}):r.verifyPerfectForwardSecrecy={passed:!1,details:u.details,points:0}}catch(u){r.verifyPerfectForwardSecrecy={passed:!1,details:`PFS check failed: ${u.message}`,points:0}}await s.verifyNestedEncryption(e)?(t+=5,r.nestedEncryption={passed:!0,details:"Nested encryption active",points:5}):r.nestedEncryption={passed:!1,details:"Nested encryption failed",points:0},await s.verifyPacketPadding(e)?(t+=5,r.packetPadding={passed:!0,details:"Packet padding active",points:5}):r.packetPadding={passed:!1,details:"Packet padding failed",points:0},await s.verifyAdvancedFeatures(e)?(t+=10,r.advancedFeatures={passed:!0,details:"Advanced features active",points:10}):r.advancedFeatures={passed:!1,details:"Advanced features failed",points:0};let o=Math.round(t/i*100),c=10,l=Object.values(r).filter(u=>u.passed).length;return{level:o>=85?"HIGH":o>=65?"MEDIUM":o>=35?"LOW":"CRITICAL",score:o,color:o>=85?"green":o>=65?"orange":o>=35?"yellow":"red",verificationResults:r,timestamp:Date.now(),details:`Real verification: ${t}/${i} security checks passed (${l}/${c} available)`,isRealData:!0,passedChecks:l,totalChecks:c,sessionType:n,maxPossibleScore:100}}catch(n){return console.error("Security level calculation failed:",n.message),{level:"UNKNOWN",score:0,color:"red",verificationResults:{},timestamp:Date.now(),details:`Verification failed: ${n.message}`,isRealData:!1}}}static async verifyEncryption(e){try{if(!e.encryptionKey)return{passed:!1,details:"No encryption key available"};let t=["Test encryption verification","\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438","Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?","Large data: "+"A".repeat(1e3)];for(let i of t){let n=new TextEncoder().encode(i),a=crypto.getRandomValues(new Uint8Array(12)),o=await crypto.subtle.encrypt({name:"AES-GCM",iv:a},e.encryptionKey,n),c=await crypto.subtle.decrypt({name:"AES-GCM",iv:a},e.encryptionKey,o);if(new TextDecoder().decode(c)!==i)return{passed:!1,details:`Decryption mismatch for: ${i.substring(0,20)}...`}}return{passed:!0,details:"AES-GCM encryption/decryption working correctly"}}catch(t){return console.error("Encryption verification failed:",t.message),{passed:!1,details:`Encryption test failed: ${t.message}`}}}static async verifyECDHKeyExchange(e){try{if(!e.ecdhKeyPair||!e.ecdhKeyPair.privateKey||!e.ecdhKeyPair.publicKey)return{passed:!1,details:"No ECDH key pair available"};let t=e.ecdhKeyPair.privateKey.algorithm.name,i=e.ecdhKeyPair.privateKey.algorithm.namedCurve;if(t!=="ECDH")return{passed:!1,details:`Invalid key type: ${t}, expected ECDH`};if(i!=="P-384"&&i!=="P-256")return{passed:!1,details:`Unsupported curve: ${i}, expected P-384 or P-256`};try{if(!await crypto.subtle.deriveKey({name:"ECDH",public:e.ecdhKeyPair.publicKey},e.ecdhKeyPair.privateKey,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]))return{passed:!1,details:"Key derivation failed"}}catch(r){return{passed:!1,details:`Key derivation test failed: ${r.message}`}}return{passed:!0,details:`ECDH key exchange working with ${i} curve`}}catch(t){return console.error("ECDH verification failed:",t.message),{passed:!1,details:`ECDH test failed: ${t.message}`}}}static async verifyECDSASignatures(e){try{if(!e.ecdsaKeyPair||!e.ecdsaKeyPair.privateKey||!e.ecdsaKeyPair.publicKey)return{passed:!1,details:"No ECDSA key pair available"};let t=["Test ECDSA signature verification","\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u043E\u0434\u043F\u0438\u0441\u0438","Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?","Large data: "+"B".repeat(2e3)];for(let i of t){let n=new TextEncoder().encode(i),a=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},e.ecdsaKeyPair.privateKey,n);if(!await crypto.subtle.verify({name:"ECDSA",hash:"SHA-256"},e.ecdsaKeyPair.publicKey,a,n))return{passed:!1,details:`Signature verification failed for: ${i.substring(0,20)}...`}}return{passed:!0,details:"ECDSA digital signatures working correctly"}}catch(t){return console.error("ECDSA verification failed:",t.message),{passed:!1,details:`ECDSA test failed: ${t.message}`}}}static async verifyMessageIntegrity(e){try{if(!e.macKey||!(e.macKey instanceof CryptoKey))return{passed:!1,details:"MAC key not available or invalid"};let t=["Test message integrity verification","\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u0446\u0435\u043B\u043E\u0441\u0442\u043D\u043E\u0441\u0442\u0438","Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?","Large data: "+"C".repeat(3e3)];for(let i of t){let n=new TextEncoder().encode(i),a=await crypto.subtle.sign({name:"HMAC",hash:"SHA-256"},e.macKey,n);if(!await crypto.subtle.verify({name:"HMAC",hash:"SHA-256"},e.macKey,a,n))return{passed:!1,details:`HMAC verification failed for: ${i.substring(0,20)}...`}}return{passed:!0,details:"Message integrity (HMAC) working correctly"}}catch(t){return console.error("Message integrity verification failed:",t.message),{passed:!1,details:`Message integrity test failed: ${t.message}`}}}static async verifyRateLimiting(e){try{let t=s.rateLimiter;if(!t||typeof t.checkMessageRate!="function")return{passed:!1,details:"Rate limiter is not available"};let i=`selftest_${crypto.getRandomValues(new Uint32Array(1))[0]}`,r=3;for(let a=0;a0}catch(t){return console.error("Nested encryption verification failed:",t.message),!1}}static async verifyPacketPadding(e){try{if(!e.paddingConfig||!e.paddingConfig.enabled)return!1;let r=new TextEncoder().encode("Test packet padding verification"),n=Math.floor(Math.random()*(e.paddingConfig.maxPadding-e.paddingConfig.minPadding))+e.paddingConfig.minPadding,a=new Uint8Array(r.byteLength+n);return a.set(new Uint8Array(r),0),a.byteLength>=r.byteLength+e.paddingConfig.minPadding}catch(t){return s.secureLog.log("error","Packet padding verification failed",{error:t.message}),!1}}static async verifyAdvancedFeatures(e){try{let t=e.fakeTrafficConfig&&e.fakeTrafficConfig.enabled,i=e.decoyChannelsConfig&&e.decoyChannelsConfig.enabled,r=e.antiFingerprintingConfig&&e.antiFingerprintingConfig.enabled;return t||i||r}catch(t){return s.secureLog.log("error","Advanced features verification failed",{error:t.message}),!1}}static async verifyMutualAuth(e){try{return!e.isVerified||!e.verificationCode?!1:e.isVerified&&e.verificationCode.length>0}catch(t){return s.secureLog.log("error","Mutual auth verification failed",{error:t.message}),!1}}static async verifyNonExtractableKeys(e){let t=[["encryptionKey",e?.encryptionKey],["macKey",e?.macKey],["metadataKey",e?.metadataKey]];for(let[i,r]of t){if(!r||!(r instanceof CryptoKey))return!1;if(r.extractable!==!1)return s.secureLog.log("error","Session key is extractable",{keyName:i}),!1}return!0}static async verifyEnhancedValidation(e){try{return e.securityFeatures?e.securityFeatures.hasEnhancedValidation||e.securityFeatures.hasEnhancedReplayProtection:!1}catch(t){return s.secureLog.log("error","Enhanced validation verification failed",{error:t.message}),!1}}static async verifyPFS(e){try{return e.securityFeatures&&e.securityFeatures.hasPFS===!0&&e.keyRotationInterval&&e.currentKeyVersion!==void 0&&e.keyVersions&&e.keyVersions instanceof Map}catch(t){return s.secureLog.log("error","PFS verification failed",{error:t.message}),!1}}static rateLimiter={messages:new Map,connections:new Map,locks:new Map,async checkMessageRate(e,t=60,i=6e4){if(typeof e!="string"||e.length>256)return!1;let r=`msg_${e}`;if(this.locks.has(r))return await new Promise(n=>setTimeout(n,Math.floor(Math.random()*10)+5)),this.checkMessageRate(e,t,i);this.locks.set(r,!0);try{let n=Date.now();this.messages.has(r)||this.messages.set(r,[]);let o=this.messages.get(r).filter(c=>n-c=t?!1:(o.push(n),this.messages.set(r,o),!0)}finally{this.locks.delete(r)}},async checkConnectionRate(e,t=5,i=3e5){if(typeof e!="string"||e.length>256)return!1;let r=`conn_${e}`;if(this.locks.has(r))return await new Promise(n=>setTimeout(n,Math.floor(Math.random()*10)+5)),this.checkConnectionRate(e,t,i);this.locks.set(r,!0);try{let n=Date.now();this.connections.has(r)||this.connections.set(r,[]);let o=this.connections.get(r).filter(c=>n-c=t?!1:(o.push(n),this.connections.set(r,o),!0)}finally{this.locks.delete(r)}},cleanup(){let e=Date.now(),t=36e5;for(let[i,r]of this.messages.entries()){if(this.locks.has(i))continue;let n=r.filter(a=>e-ae-a3e4&&this.locks.delete(i)}}};static validateSalt(e){if(!e||e.length!==64)throw new Error("Salt must be exactly 64 bytes");if(new Set(e).size<16)throw new Error("Salt has insufficient entropy");return!0}static secureLog={logs:[],maxLogs:100,isProductionMode:!1,init(){this.isProductionMode=this._detectProductionMode(),this.isProductionMode&&console.log("[SecureChat] Production mode detected - sensitive logging disabled")},_detectProductionMode(){return typeof process<"u"&&!0||!window.DEBUG_MODE&&!window.DEVELOPMENT_MODE||window.location.hostname&&!window.location.hostname.includes("localhost")&&!window.location.hostname.includes("127.0.0.1")&&!window.location.hostname.includes(".local")||typeof window.webpackHotUpdate>"u"&&!window.location.search.includes("debug")},log(e,t,i={}){let r=this.sanitizeContext(i),n={timestamp:Date.now(),level:e,message:t,context:r,id:crypto.getRandomValues(new Uint32Array(1))[0]};if(this.logs.push(n),this.logs.length>this.maxLogs&&(this.logs=this.logs.slice(-this.maxLogs)),this.isProductionMode)if(e==="error")console.error(`\u274C [SecureChat] ${t} [ERROR_CODE: ${this._generateErrorCode(t)}]`);else if(e==="warn")console.warn(`\u26A0\uFE0F [SecureChat] ${t}`);else return;else e==="error"?console.error(`\u274C [SecureChat] ${t}`,{errorType:r?.constructor?.name||"Unknown"}):e==="warn"?console.warn(`\u26A0\uFE0F [SecureChat] ${t}`,{details:r}):console.log(`[SecureChat] ${t}`,r)},_generateErrorCode(e){let t=e.split("").reduce((i,r)=>(i=(i<<5)-i+r.charCodeAt(0),i&i),0);return Math.abs(t).toString(36).substring(0,6).toUpperCase()},sanitizeContext(e){if(!e||typeof e!="object")return e;let t=[/key/i,/secret/i,/password/i,/token/i,/signature/i,/challenge/i,/proof/i,/salt/i,/iv/i,/nonce/i,/hash/i,/fingerprint/i,/mac/i,/private/i,/encryption/i,/decryption/i],i={};for(let[r,n]of Object.entries(e))t.some(o=>o.test(r)||typeof n=="string"&&o.test(n))?i[r]="[REDACTED]":typeof n=="string"&&n.length>100?i[r]=n.substring(0,100)+"...[TRUNCATED]":n instanceof ArrayBuffer||n instanceof Uint8Array?i[r]=`[${n.constructor.name}(${n.byteLength||n.length} bytes)]`:n&&typeof n=="object"&&!Array.isArray(n)?i[r]=this.sanitizeContext(n):i[r]=n;return i},getLogs(e=null){return e?this.logs.filter(t=>t.level===e):[...this.logs]},clearLogs(){this.logs=[]},async sendErrorToServer(e,t,i={}){if(this.isProductionMode)try{let r={errorCode:e,timestamp:Date.now(),userAgent:navigator.userAgent.substring(0,100),url:window.location.href.substring(0,100)};window.DEBUG_MODE&&console.log("[SecureChat] Error logged to server:",r)}catch{}}};static async generateECDHKeyPair(){try{try{return await crypto.subtle.generateKey({name:"ECDH",namedCurve:"P-384"},!1,["deriveKey","deriveBits"])}catch(e){return s.secureLog.log("warn","Elliptic curve P-384 generation failed, switching curve",{error:e.message}),await crypto.subtle.generateKey({name:"ECDH",namedCurve:"P-256"},!1,["deriveKey","deriveBits"])}}catch(e){throw s.secureLog.log("error","ECDH key generation failed",{error:e.message}),new Error("Failed to create keys for secure exchange")}}static async generateECDSAKeyPair(){try{try{return await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-384"},!1,["sign","verify"])}catch(e){return s.secureLog.log("warn","Elliptic curve P-384 generation failed, switching curve",{error:e.message}),await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!1,["sign","verify"])}}catch(e){throw s.secureLog.log("error","ECDSA key generation failed",{error:e.message}),new Error("Failed to generate keys for digital signatures")}}static async signData(e,t){try{let i=new TextEncoder,r=typeof t=="string"?i.encode(t):t;try{let n=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-384"},e,r);return Array.from(new Uint8Array(n))}catch(n){s.secureLog.log("warn","SHA-384 signing failed, trying SHA-256",{error:n.message});let a=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},e,r);return Array.from(new Uint8Array(a))}}catch(i){throw s.secureLog.log("error","Data signing failed",{error:i.message}),new Error("Failed to sign data")}}static async verifySignature(e,t,i){try{let r=new TextEncoder,n=typeof i=="string"?r.encode(i):i,a=new Uint8Array(t);try{return await crypto.subtle.verify({name:"ECDSA",hash:"SHA-384"},e,a,n)}catch{return await crypto.subtle.verify({name:"ECDSA",hash:"SHA-256"},e,a,n)}}catch(r){throw s.secureLog.log("error","Signature verification failed",{error:r.message}),new Error("Failed to verify digital signature")}}static async validateKeyStructure(e,t="ECDH"){try{if(!Array.isArray(e)||e.length===0)throw new Error("Invalid key data format");let i=new Uint8Array(e);if(i.length<50)throw new Error("Key data too short - invalid SPKI structure");if(i.length>2e3)throw new Error("Key data too long - possible attack");let r=s.parseASN1(i);if(!r||r.tag!==48)throw new Error("Invalid SPKI structure - missing SEQUENCE tag");if(r.children.length!==2)throw new Error(`Invalid SPKI structure - expected 2 elements, got ${r.children.length}`);let n=r.children[0];if(n.tag!==48)throw new Error("Invalid AlgorithmIdentifier - not a SEQUENCE");let a=n.children[0];if(a.tag!==6)throw new Error("Invalid algorithm OID - not an OBJECT IDENTIFIER");let o=a.value,c=s.oidToString(o),h={ECDH:["1.2.840.10045.2.1"],ECDSA:["1.2.840.10045.2.1"],RSA:["1.2.840.113549.1.1.1"],"AES-GCM":["2.16.840.1.101.3.4.1.6","2.16.840.1.101.3.4.1.46"]}[t];if(!h)throw new Error(`Unknown algorithm: ${t}`);if(!h.includes(c))throw new Error(`Invalid algorithm OID: expected ${h.join(" or ")}, got ${c}`);if(t==="ECDH"||t==="ECDSA"){if(n.children.length<2)throw new Error("Missing curve parameters for EC key");let p=n.children[1];if(p.tag!==6)throw new Error("Invalid curve OID - not an OBJECT IDENTIFIER");let S=s.oidToString(p.value);if(!{"1.2.840.10045.3.1.7":"P-256","1.3.132.0.34":"P-384"}[S])throw new Error(`Invalid or unsupported curve OID: ${S}`)}let u=r.children[1];if(u.tag!==3)throw new Error("Invalid public key - not a BIT STRING");if(u.value[0]!==0)throw new Error(`Invalid BIT STRING - unexpected unused bits: ${u.value[0]}`);if(t==="ECDH"||t==="ECDSA"){let p=u.value.slice(1);if(p[0]!==4)throw new Error(`Invalid EC point format: expected uncompressed (0x04), got 0x${p[0].toString(16)}`);let S={"P-256":65,"P-384":97},g=s.oidToString(n.children[1].value)==="1.2.840.10045.3.1.7"?"P-256":"P-384",m=S[g];if(p.length!==m)throw new Error(`Invalid EC point size for ${g}: expected ${m}, got ${p.length}`)}try{let p=t==="ECDSA"||t==="ECDH"?{name:t,namedCurve:"P-384"}:{name:t},S=t==="ECDSA"?["verify"]:[];await crypto.subtle.importKey("spki",i.buffer,p,!1,S)}catch(p){if(t==="ECDSA"||t==="ECDH")try{let S={name:t,namedCurve:"P-256"},w=t==="ECDSA"?["verify"]:[];await crypto.subtle.importKey("spki",i.buffer,S,!1,w)}catch(S){throw new Error(`Key import validation failed: ${S.message}`)}else throw new Error(`Key import validation failed: ${p.message}`)}return!0}catch(i){throw s.secureLog.log("error","Key structure validation failed",{error:i.message,algorithm:t}),new Error(`Invalid key structure: ${i.message}`)}}static parseASN1(e,t=0){if(t>=e.length)return null;let i=e[t],r=t+1;if(r>=e.length)throw new Error("Truncated ASN.1 structure");let n=e[r],a=r+1;if(n&128){let l=n&127;if(l>4)throw new Error("ASN.1 length too large");n=0;for(let h=0;h=e.length)throw new Error("Truncated ASN.1 length");n=n<<8|e[a+h]}a+=l}if(a+n>e.length)throw new Error("ASN.1 structure extends beyond data");let o=e.slice(a,a+n),c={tag:i,length:n,value:o,children:[]};if(i===48||i===49){let l=0;for(;l2)throw new Error(`Invalid OID first component: ${i[0]}`);if((i[0]===0||i[0]===1)&&i[1]>39)throw new Error(`Invalid OID second component: ${i[1]} (must be <= 39 for first component ${i[0]})`);return!0}static async exportPublicKeyWithSignature(e,t,i="ECDH"){try{if(!["ECDH","ECDSA"].includes(i))throw new Error("Invalid key type");let r=await crypto.subtle.exportKey("spki",e),n=Array.from(new Uint8Array(r));await s.validateKeyStructure(n,i);let a={keyType:i,keyData:n,timestamp:Date.now(),version:"4.0"},o=JSON.stringify(a),c=await s.signData(t,o);return{...a,signature:c}}catch(r){throw s.secureLog.log("error","Public key export failed",{error:r.message,keyType:i}),new Error(`Failed to export ${i} key: ${r.message}`)}}static async importSignedPublicKey(e,t,i="ECDH"){try{if(!e||typeof e!="object")throw new Error("Invalid signed package format");let{keyType:r,keyData:n,timestamp:a,version:o,signature:c}=e;if(!r||!n||!a||!c)throw new Error("Missing required fields in signed package");if(!s.constantTimeCompare(r,i))throw new Error(`Key type mismatch: expected ${i}, got ${r}`);if(Date.now()-a>36e5)throw new Error("Signed key package is too old");await s.validateKeyStructure(n,r);let u=JSON.stringify({keyType:r,keyData:n,timestamp:a,version:o});if(!await s.verifySignature(t,c,u))throw new Error("Invalid signature on key package - possible MITM attack");let S=new Uint8Array(n);try{let w=r==="ECDH"?{name:"ECDH",namedCurve:"P-384"}:{name:"ECDSA",namedCurve:"P-384"},g=r==="ECDH"?[]:["verify"];return await crypto.subtle.importKey("spki",S,w,!1,g)}catch(w){s.secureLog.log("warn","Elliptic curve P-384 import failed, switching curve",{error:w.message});let g=r==="ECDH"?{name:"ECDH",namedCurve:"P-256"}:{name:"ECDSA",namedCurve:"P-256"},m=r==="ECDH"?[]:["verify"];return await crypto.subtle.importKey("spki",S,g,!1,m)}}catch(r){throw s.secureLog.log("error","Signed public key import failed",{error:r.message,expectedKeyType:i}),new Error(`Failed to import the signed key: ${r.message}`)}}static async exportPublicKey(e){try{let t=await crypto.subtle.exportKey("spki",e),i=Array.from(new Uint8Array(t));return await s.validateKeyStructure(i,"ECDH"),i}catch(t){throw s.secureLog.log("error","Legacy public key export failed",{error:t.message}),new Error("Failed to export the public key")}}static async importPublicKey(e){try{await s.validateKeyStructure(e,"ECDH");let t=new Uint8Array(e);try{return await crypto.subtle.importKey("spki",t,{name:"ECDH",namedCurve:"P-384"},!1,[])}catch(i){return s.secureLog.log("warn","P-384 import failed, trying P-256",{error:i.message}),await crypto.subtle.importKey("spki",t,{name:"ECDH",namedCurve:"P-256"},!1,[])}}catch(t){throw s.secureLog.log("error","Legacy public key import failed",{error:t.message}),new Error("Failed to import the public key")}}static isKeyTrusted(e){if(e instanceof CryptoKey){let t=s._keyMetadata.get(e);return t?t.trusted===!0:!1}else if(e&&e._securityMetadata)return e._securityMetadata.trusted===!0;return!1}static async importPublicKeyFromSignedPackage(e,t=null,i={}){try{if(!e||!e.keyData||!e.signature)throw new Error("Invalid signed key package format");let n=["keyData","signature","keyType","timestamp","version"].filter(p=>!e[p]);if(n.length>0)throw s.secureLog.log("error","Missing required fields in signed package",{missingFields:n,availableFields:Object.keys(e)}),new Error(`Required fields are missing in the signed package: ${n.join(", ")}`);if(!t)throw s.secureLog.log("error","SECURITY VIOLATION: Signed package received without verifying key",{keyType:e.keyType,keySize:e.keyData.length,timestamp:e.timestamp,version:e.version,securityRisk:"HIGH - Potential MITM attack vector"}),new Error("CRITICAL SECURITY ERROR: Signed key package received without a verification key. This may indicate a possible MITM attack attempt. Import rejected for security reasons.");await s.validateKeyStructure(e.keyData,e.keyType||"ECDH");let a={...e};delete a.signature;let o=JSON.stringify(a);if(!await s.verifySignature(t,e.signature,o))throw s.secureLog.log("error","SECURITY BREACH: Invalid signature detected - MITM attack prevented",{keyType:e.keyType,keySize:e.keyData.length,timestamp:e.timestamp,version:e.version,attackPrevented:!0}),new Error("CRITICAL SECURITY ERROR: Invalid key signature detected. This indicates a possible MITM attack attempt. Key import rejected.");let l=await s.calculateKeyFingerprint(e.keyData),h=new Uint8Array(e.keyData),u=e.keyType||"ECDH";try{let p=await crypto.subtle.importKey("spki",h,{name:u,namedCurve:"P-384"},!1,u==="ECDSA"?["verify"]:[]);return s._keyMetadata.set(p,{trusted:!0,verificationStatus:"VERIFIED_SECURE",verificationTimestamp:Date.now()}),p}catch(p){s.secureLog.log("warn","P-384 import failed, trying P-256",{error:p.message});let S=await crypto.subtle.importKey("spki",h,{name:u,namedCurve:"P-256"},!1,u==="ECDSA"?["verify"]:[]);return s._keyMetadata.set(S,{trusted:!0,verificationStatus:"VERIFIED_SECURE",verificationTimestamp:Date.now()}),S}}catch(r){throw s.secureLog.log("error","Signed package key import failed",{error:r.message,securityImplications:"Potential security breach prevented"}),new Error(`Failed to import the public key from the signed package: ${r.message}`)}}static async deriveSharedKeys(e,t,i){try{if(!(e instanceof CryptoKey))throw s.secureLog.log("error","Private key is not a CryptoKey",{privateKeyType:typeof e,privateKeyAlgorithm:e?.algorithm?.name}),new Error("The private key is not a valid CryptoKey.");if(!(t instanceof CryptoKey))throw s.secureLog.log("error","Public key is not a CryptoKey",{publicKeyType:typeof t,publicKeyAlgorithm:t?.algorithm?.name}),new Error("The public key is not a valid CryptoKey.");if(!i||i.length!==64)throw new Error("Salt must be exactly 64 bytes for enhanced security");let r=new Uint8Array(i),n=new TextEncoder,a,o=null;try{o=await crypto.subtle.deriveBits({name:"ECDH",public:t},e,256),a=await crypto.subtle.importKey("raw",o,{name:"HKDF",hash:"SHA-256"},!1,["deriveKey","deriveBits"])}catch(m){throw s.secureLog.log("error","ECDH derivation failed",{error:m.message}),m}finally{o&&(s.zeroizeBuffer(o),o=null)}let c;c=await crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:r,info:n.encode("message-encryption-v4")},a,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);let l;l=await crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:r,info:n.encode("message-authentication-v4")},a,{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"]);let h;h=await crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:r,info:n.encode("perfect-forward-secrecy-v4")},a,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);let u;u=await crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:r,info:n.encode("metadata-protection-v4")},a,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"]);let p=await crypto.subtle.deriveBits({name:"HKDF",hash:"SHA-256",salt:r,info:n.encode("double-ratchet-root-v1")},a,256),S=new Uint8Array(p),w=null,g;try{w=await crypto.subtle.deriveBits({name:"HKDF",hash:"SHA-256",salt:r,info:n.encode("fingerprint-generation-v4")},a,256),g=await s.generateKeyFingerprint(new Uint8Array(w))}finally{w&&(s.zeroizeBuffer(w),w=null)}if(!(c instanceof CryptoKey))throw s.secureLog.log("error","Derived message key is not a CryptoKey",{messageKeyType:typeof c,messageKeyAlgorithm:c?.algorithm?.name}),new Error("The derived message key is not a valid CryptoKey.");if(!(l instanceof CryptoKey))throw s.secureLog.log("error","Derived MAC key is not a CryptoKey",{macKeyType:typeof l,macKeyAlgorithm:l?.algorithm?.name}),new Error("The derived MAC key is not a valid CryptoKey.");if(!(h instanceof CryptoKey))throw s.secureLog.log("error","Derived PFS key is not a CryptoKey",{pfsKeyType:typeof h,pfsKeyAlgorithm:h?.algorithm?.name}),new Error("The derived PFS key is not a valid CryptoKey.");if(!(u instanceof CryptoKey))throw s.secureLog.log("error","Derived metadata key is not a CryptoKey",{metadataKeyType:typeof u,metadataKeyAlgorithm:u?.algorithm?.name}),new Error("The derived metadata key is not a valid CryptoKey.");return{messageKey:c,macKey:l,pfsKey:h,metadataKey:u,ratchetRoot:S,fingerprint:g,timestamp:Date.now(),version:"4.0"}}catch(r){throw s.secureLog.log("error","Enhanced key derivation failed",{error:r.message,errorStack:r.stack,privateKeyType:typeof e,publicKeyType:typeof t,saltLength:i?.length,privateKeyAlgorithm:e?.algorithm?.name,publicKeyAlgorithm:t?.algorithm?.name}),new Error(`Failed to create shared encryption keys: ${r.message}`)}}static async generateKeyFingerprint(e){let t=new Uint8Array(e),i=await crypto.subtle.digest("SHA-384",t);return Array.from(new Uint8Array(i)).slice(0,12).map(n=>n.toString(16).padStart(2,"0")).join(":")}static generateMutualAuthChallenge(){let e=crypto.getRandomValues(new Uint8Array(48)),t=Date.now(),i=crypto.getRandomValues(new Uint8Array(16));return{challenge:Array.from(e),timestamp:t,nonce:Array.from(i),version:"4.0"}}static async createAuthProof(e,t,i){try{if(!e||!e.challenge||!e.timestamp||!e.nonce)throw new Error("Invalid challenge structure");let r=Date.now()-e.timestamp;if(r>12e4)throw new Error("Challenge expired");let n={challenge:e.challenge,timestamp:e.timestamp,nonce:e.nonce,responseTimestamp:Date.now(),publicKeyHash:await s.hashPublicKey(i)},a=JSON.stringify(n),o=await s.signData(t,a),c={...n,signature:o,version:"4.0"};return s.secureLog.log("info","Authentication proof created",{challengeAge:Math.round(r/1e3)+"s"}),c}catch(r){throw s.secureLog.log("error","Authentication proof creation failed",{error:r.message}),new Error(`Failed to create cryptographic proof: ${r.message}`)}}static async verifyAuthProof(e,t,i){try{if(await new Promise(h=>setTimeout(h,Math.floor(Math.random()*20)+5)),s.assertCryptoKey(i,"ECDSA",["verify"]),!e||!t||!i)throw new Error("Missing required parameters for proof verification");let r=["challenge","timestamp","nonce","responseTimestamp","publicKeyHash","signature"];for(let h of r)if(!e[h])throw new Error(`Missing required field: ${h}`);if(!s.constantTimeCompareArrays(e.challenge,t.challenge)||e.timestamp!==t.timestamp||!s.constantTimeCompareArrays(e.nonce,t.nonce))throw new Error("Challenge mismatch - possible replay attack");let n=Date.now()-e.responseTimestamp;if(n>18e5)throw new Error("Proof response expired");let a=await s.hashPublicKey(i);if(!s.constantTimeCompare(e.publicKeyHash,a))throw new Error("Public key hash mismatch");let o={...e};delete o.signature;let c=JSON.stringify(o);if(!await s.verifySignature(i,e.signature,c))throw new Error("Invalid proof signature");return s.secureLog.log("info","Authentication proof verified successfully",{responseAge:Math.round(n/1e3)+"s"}),!0}catch(r){throw s.secureLog.log("error","Authentication proof verification failed",{error:r.message}),new Error(`Failed to verify cryptographic proof: ${r.message}`)}}static async hashPublicKey(e){try{let t=await crypto.subtle.exportKey("spki",e),i=await crypto.subtle.digest("SHA-384",t);return Array.from(new Uint8Array(i)).map(n=>n.toString(16).padStart(2,"0")).join("")}catch(t){throw s.secureLog.log("error","Public key hashing failed",{error:t.message}),new Error("Failed to create hash of the public key")}}static generateAuthChallenge(){let e=crypto.getRandomValues(new Uint8Array(32));return Array.from(e)}static generateVerificationCode(){let e="0123456789ABCDEF",t=e.length,i="";for(let r=0;r<6;r++){let n;do n=crypto.getRandomValues(new Uint8Array(1))[0];while(n>=256-256%t);i+=e[n%t]}return i.match(/.{1,2}/g).join("-")}static async encryptMessage(e,t,i,r,n,a=0){try{if(!e||typeof e!="string")throw new Error("Invalid message format");s.assertCryptoKey(t,"AES-GCM",["encrypt"]),s.assertCryptoKey(i,"HMAC",["sign"]),s.assertCryptoKey(r,"AES-GCM",["encrypt"]);let o=new TextEncoder,c=o.encode(e),l=crypto.getRandomValues(new Uint8Array(12)),h=crypto.getRandomValues(new Uint8Array(12)),u=Date.now(),p=16-c.length%16,S=new Uint8Array(c.length+p);S.set(c);let w=crypto.getRandomValues(new Uint8Array(p));S.set(w,c.length);let g=await crypto.subtle.encrypt({name:"AES-GCM",iv:l},t,S),m={id:n,timestamp:u,sequenceNumber:a,originalLength:c.length,version:"4.0"},I=JSON.stringify(s.sortObjectKeys(m)),b=await crypto.subtle.encrypt({name:"AES-GCM",iv:h},r,o.encode(I)),D={messageIv:Array.from(l),messageData:Array.from(new Uint8Array(g)),metadataIv:Array.from(h),metadataData:Array.from(new Uint8Array(b)),version:"4.0"},_=s.sortObjectKeys(D),R=JSON.stringify(_),E=await crypto.subtle.sign("HMAC",i,o.encode(R));return D.mac=Array.from(new Uint8Array(E)),D}catch(o){throw s.secureLog.log("error","Message encryption failed",{error:o.message,messageId:n}),new Error(`Failed to encrypt the message: ${o.message}`)}}static async decryptMessage(e,t,i,r,n=null){try{s.assertCryptoKey(t,"AES-GCM",["decrypt"]),s.assertCryptoKey(i,"HMAC",["verify"]),s.assertCryptoKey(r,"AES-GCM",["decrypt"]);let a=["messageIv","messageData","metadataIv","metadataData","mac","version"];for(let M of a)if(!e[M])throw new Error(`Missing required field: ${M}`);let o={...e};delete o.mac;let c=s.sortObjectKeys(o),l=JSON.stringify(c);if(!await crypto.subtle.verify("HMAC",i,new Uint8Array(e.mac),new TextEncoder().encode(l)))throw s.secureLog.log("error","MAC verification failed",{payloadFields:Object.keys(e),macLength:e.mac?.length}),new Error("Message authentication failed - possible tampering");let u=new Uint8Array(e.metadataIv),p=new Uint8Array(e.metadataData),S=await crypto.subtle.decrypt({name:"AES-GCM",iv:u},r,p),w=new TextDecoder().decode(S),g=JSON.parse(w);if(!g.id||!g.timestamp||g.sequenceNumber===void 0||!g.originalLength)throw new Error("Invalid metadata structure");let m=Date.now()-g.timestamp;if(m>18e5)throw new Error("Message expired (older than 30 minutes)");if(n!==null){if(g.sequenceNumbern+10)throw new Error(`Sequence number gap too large: expected around ${n}, got ${g.sequenceNumber}`)}let I=new Uint8Array(e.messageIv),b=new Uint8Array(e.messageData),D=await crypto.subtle.decrypt({name:"AES-GCM",iv:I},t,b),R=new Uint8Array(D).slice(0,g.originalLength),C=new TextDecoder().decode(R);return s.secureLog.log("info","Message decrypted successfully",{messageId:g.id,sequenceNumber:g.sequenceNumber,messageAge:Math.round(m/1e3)+"s"}),{message:C,messageId:g.id,timestamp:g.timestamp,sequenceNumber:g.sequenceNumber}}catch(a){throw s.secureLog.log("error","Message decryption failed",{error:a.message}),new Error(`Failed to decrypt the message: ${a.message}`)}}static _getMessageSanitizer(){if(s._messageSanitizer)return s._messageSanitizer;if(typeof window>"u"||!window?.document)throw new Error("DOMPurify requires a browser-like window for message sanitization");return s._messageSanitizer=Rr(window),s._messageSanitizer}static sanitizeMessage(e){if(typeof e!="string")throw new Error("Message must be a string");let t=s._getMessageSanitizer().sanitize(e,{ALLOWED_TAGS:[],ALLOWED_ATTR:[],ALLOW_UNKNOWN_PROTOCOLS:!1,FORBID_TAGS:["script","style","svg","math","template"],FORBID_ATTR:["style"],KEEP_CONTENT:!0,RETURN_TRUSTED_TYPE:!1,USE_PROFILES:{html:!1,svg:!1,svgFilters:!1,mathMl:!1}});return String(t).trim().substring(0,2e3)}static generateSalt(){return Array.from(crypto.getRandomValues(new Uint8Array(64)))}static async calculateKeyFingerprint(e){try{let t=new TextEncoder,i=new Uint8Array(e),r=await crypto.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(r)).map(o=>o.toString(16).padStart(2,"0")).join("")}catch(t){throw s.secureLog.log("error","Key fingerprint calculation failed",{error:t.message}),new Error("Failed to compute the key fingerprint")}}static constantTimeCompare(e,t){let i=typeof e=="string"?e:JSON.stringify(e),r=typeof t=="string"?t:JSON.stringify(t);if(i.length!==r.length){let a=0;for(let o=0;oa.toLowerCase()===t);if(i)return i;let r=t.split("-")[0],n=Ke.find(a=>a.toLowerCase().split("-")[0]===r);if(n)return n}return null}function Vs({pathname:s="/",stored:e=null,languages:t=[]}={}){let i=Dr(s);return i||(Bs(s)?"en":e&&Ke.includes(e)?e:zs(t)||"en")}function Bs(s){return s==="/"||s==="/index.html"}function Hs(s,e="/"){let t=Dr(e),r=(t?String(e).slice(t.length+1):String(e)).replace(/^\/+/,"");return s==="en"?`/${r}`:`/${s}/${r}`}function Pr(s){try{localStorage.setItem(Lr,s)}catch{}}function $s(){try{return localStorage.getItem(Lr)}catch{return null}}var Rt=null;function Ge(){if(Rt)return Rt;let s=typeof window>"u"?null:window;return!s||!s.location?"en":(Rt=Vs({pathname:s.location.pathname||"/",stored:$s(),languages:s.navigator?.languages||[]}),Rt)}function Gs(s=Ge()){return rt[s]?.dir==="rtl"?"rtl":"ltr"}function qs(s=Ge()){return Gs(s)==="rtl"}function Fr(s=Ge()){return qs(s)?-1:1}function Oe(s,e=Ge()){let t=Mt(e)?.[s]??Mt("en")?.[s];return Array.isArray(t)?t:[]}function Kr({pathname:s="/",active:e="en"}={}){return Ke.map(t=>({code:t,href:Hs(t,s),hrefLang:rt[t]?.htmlLang||t,label:rt[t]?.nativeName||t,abbr:rt[t]?.abbr||t.toUpperCase(),dir:rt[t]?.dir||"ltr",isCurrent:t===e}))}function f(s,e,t=Ge()){let i=Mt(t)?.[s]??Mr[t]?.[s]??Mt("en")?.[s]??s;return e?String(i).replace(/\{(\w+)\}/g,(r,n)=>Object.prototype.hasOwnProperty.call(e,n)?String(e[n]):r):i}var Ie=class s{static#e=null;static#n=Symbol("SecureFileTransferContext");static getInstance(){return this.#e||(this.#e=new s),this.#e}#t=null;#i=!1;#r="high";setFileTransferSystem(e){if(!(e instanceof je))throw new Error("Invalid file transfer system instance");this.#t=e,this.#i=!0}getFileTransferSystem(){return this.#t}isActive(){return this.#i&&this.#t!==null}deactivate(){this.#i=!1,this.#t=null}getSecurityLevel(){return this.#r}setSecurityLevel(e){["low","medium","high"].includes(e)&&(this.#r=e)}},Q=class{static#e=new Set(["File size exceeds maximum limit","Unsupported file type","Transfer timeout","Connection lost","Invalid file data","File transfer failed","Transfer cancelled","Network error","File not found","Permission denied"]);static sanitizeError(e){let t=e.message||e;for(let i of this.#e)if(t.includes(i))return i;return console.error("\u{1F512} Internal file transfer error:",{message:e.message,stack:e.stack,timestamp:new Date().toISOString()}),"File transfer failed"}static logSecurityEvent(e,t={}){console.warn("\u{1F512} Security event:",{event:e,timestamp:new Date().toISOString(),...t})}},Lt=class{static async signFileMetadata(e,t){try{let r=new TextEncoder().encode(JSON.stringify({fileId:e.fileId,fileName:e.fileName,fileSize:e.fileSize,fileHash:e.fileHash,timestamp:e.timestamp,version:e.version||"2.0"})),n=await crypto.subtle.sign("RSASSA-PKCS1-v1_5",t,r);return Array.from(new Uint8Array(n))}catch(i){throw Q.logSecurityEvent("signature_failed",{error:i.message}),new Error("Failed to sign file metadata")}}static async verifyFileMetadata(e,t,i){try{let n=new TextEncoder().encode(JSON.stringify({fileId:e.fileId,fileName:e.fileName,fileSize:e.fileSize,fileHash:e.fileHash,timestamp:e.timestamp,version:e.version||"2.0"})),a=new Uint8Array(t),o=await crypto.subtle.verify("RSASSA-PKCS1-v1_5",i,a,n);return o||Q.logSecurityEvent("invalid_signature",{fileId:e.fileId}),o}catch(r){return Q.logSecurityEvent("verification_failed",{error:r.message}),!1}}},Dt=class{static MAX_MESSAGE_SIZE=1024*1024;static isMessageSizeValid(e){let t=JSON.stringify(e),i=new Blob([t]).size;if(i>this.MAX_MESSAGE_SIZE)throw Q.logSecurityEvent("message_too_large",{size:i,limit:this.MAX_MESSAGE_SIZE}),new Error("Message too large");return!0}},wi=class{constructor(){this.locks=new Map}async withLock(e,t){for(;this.locks.has(e);)await this.locks.get(e);let i,r=new Promise(n=>{i=n});this.locks.set(e,r);try{return await t()}finally{this.locks.delete(e),i()}}},nt=class{constructor(e,t){this.maxRequests=e,this.windowMs=t,this.requests=new Map}isAllowed(e){let t=Date.now(),i=t-this.windowMs;this.requests.has(e)||this.requests.set(e,[]);let n=this.requests.get(e).filter(a=>a>i);return this.requests.set(e,n),n.length>=this.maxRequests?(Q.logSecurityEvent("rate_limit_exceeded",{identifier:e,requestCount:n.length,limit:this.maxRequests}),!1):(n.push(t),!0)}},qe=class{static secureWipe(e){if(e instanceof ArrayBuffer){let t=new Uint8Array(e);crypto.getRandomValues(t)}else e instanceof Uint8Array&&crypto.getRandomValues(e)}static secureDelete(e,t){e[t]&&(this.secureWipe(e[t]),delete e[t])}},je=class{constructor(e,t,i,r,n,a){if(this.webrtcManager=e,this.onProgress=t,this.onComplete=i,this.onError=r,this.onFileReceived=n,this.onIncomingFileRequest=a,!e)throw new Error("webrtcManager is required for EnhancedSecureFileTransfer");Ie.getInstance().setFileTransferSystem(this),this.atomicOps=new wi,this.rateLimiter=new nt(10,6e4),this.signingKey=null,this.verificationKey=null,this.CHUNK_SIZE=16*1024,this.MAX_RECEIVE_CHUNK_SIZE=64*1024,this.MAX_FILE_SIZE=100*1024*1024,this.MAX_CONCURRENT_TRANSFERS=3,this.CHUNK_TIMEOUT=3e4,this.RETRY_ATTEMPTS=3,this.FILE_TYPE_RESTRICTIONS={pdf:{extensions:[".pdf"],mimeTypes:["application/pdf","application/x-pdf","application/acrobat"],maxSize:50*1024*1024,category:"PDF",description:"PDF"},text:{extensions:[".txt"],mimeTypes:["text/plain","application/txt"],maxSize:10*1024*1024,category:f("fileType.text"),description:"TXT"},images:{extensions:[".jpg",".jpeg",".png",".gif",".webp",".bmp",".ico"],mimeTypes:["image/jpeg","image/jpg","image/pjpeg","image/png","image/gif","image/webp","image/bmp","image/x-windows-bmp","image/x-icon","image/vnd.microsoft.icon"],maxSize:25*1024*1024,category:f("fileType.images"),description:"JPG, JPEG, PNG, GIF, WEBP, BMP, ICO"},archives:{extensions:[".zip"],mimeTypes:["application/zip","application/x-zip","application/x-zip-compressed","multipart/x-zip"],maxSize:100*1024*1024,category:f("fileType.archives"),description:"ZIP"},voice:{extensions:[".webm",".ogg",".oga",".opus",".m4a",".mp4",".mp3",".wav"],mimeTypes:["audio/webm","audio/ogg","audio/opus","audio/mp4","audio/mpeg","audio/mp3","audio/wav","audio/x-m4a","audio/aac"],maxSize:20*1024*1024,category:"Voice",description:f("fileType.voice")}},this.BLOCKED_EXTENSIONS=new Set([".exe",".bat",".cmd",".sh",".js",".msi",".dmg",".app",".jar",".scr",".ps1",".vbs",".html",".svg"]),this._genericMimeTypes=new Set(["application/octet-stream","application/binary"]),this._allowedMimeTypes=new Set;for(let o of Object.values(this.FILE_TYPE_RESTRICTIONS))for(let c of o.mimeTypes)this._allowedMimeTypes.add(c);this.activeTransfers=new Map,this.receivingTransfers=new Map,this.pendingIncomingTransfers=new Map,this.transferQueue=[],this.pendingChunks=new Map,this.incomingOfferLimiter=new nt(5,6e4),this.incomingChunkLimiter=new nt(6e4,6e4),this.incomingTransferChunkLimiters=new Map,this.MAX_INCOMING_CHUNKS_PER_TRANSFER_PER_MINUTE=3e4,this.MAX_PENDING_INCOMING_TRANSFERS=3,this.MAX_AUTO_ACCEPT_VOICE_SIZE=4*1024*1024,this.MAX_AUTO_ACCEPT_VOICE_SESSION_BYTES=64*1024*1024,this.autoAcceptedVoiceBytes=0,this.sessionKeys=new Map,this.processedChunks=new Set,this.transferNonces=new Map,this.receivedFileBuffers=new Map,this.MAX_RETAINED_RECEIVED_FILE_BUFFERS=3,this.setupFileMessageHandlers(),this.webrtcManager&&(this.webrtcManager.fileTransferSystem=this)}getFileType(e){let t=String(e?.name||"").toLowerCase(),i=t.lastIndexOf("."),r=i>=0?t.substring(i):"",n=String(e?.type||"").toLowerCase();for(let[a,o]of Object.entries(this.FILE_TYPE_RESTRICTIONS)){if(!o.extensions.includes(r))continue;if(!n||this._genericMimeTypes.has(n)||this._allowedMimeTypes.has(n))return{type:a,category:o.category,description:o.description,maxSize:o.maxSize,allowed:!0,extension:r,mimeType:n}}return{type:"blocked",category:f("fileType.unsupported"),description:"Allowed: JPG, JPEG, PNG, GIF, WEBP, BMP, ICO, PDF, TXT, ZIP",maxSize:this.MAX_FILE_SIZE,allowed:!1,extension:r,mimeType:n}}validateFile(e){let t=this.getFileType(e),i=[],n=String(e?.name||"").toLowerCase(),a=n.lastIndexOf("."),o=a>=0?n.substring(a):"";return this.BLOCKED_EXTENSIONS.has(o)&&i.push(`File rejected: ${o} files are not allowed for security reasons.`),e.size>t.maxSize&&i.push(`File size (${this.formatFileSize(e.size)}) exceeds maximum allowed for ${t.category} (${this.formatFileSize(t.maxSize)})`),!t.allowed&&!this.BLOCKED_EXTENSIONS.has(o)&&i.push(`File rejected: unsupported file type. Supported types: ${t.description}`),e.size>this.MAX_FILE_SIZE&&i.push(`File size (${this.formatFileSize(e.size)}) exceeds general limit (${this.formatFileSize(this.MAX_FILE_SIZE)})`),{isValid:i.length===0,errors:i,fileType:t,fileSize:e.size,formattedSize:this.formatFileSize(e.size)}}normalizeDisplayFileName(e){return String(e||"").normalize("NFKC").replace(/[\u0000-\u001F\u007F]/g,"").replace(/[\\/]+/g,"_").trim().slice(0,255)}validateIncomingMetadata(e){let t=[];(!e||typeof e!="object")&&t.push("Invalid file transfer metadata"),(!e?.fileId||typeof e.fileId!="string")&&t.push("Invalid file id"),(!Number.isSafeInteger(e?.fileSize)||e.fileSize<=0)&&t.push("Invalid file size"),(!Number.isSafeInteger(e?.totalChunks)||e.totalChunks<=0)&&t.push("Invalid chunk count"),(!Number.isSafeInteger(e?.chunkSize)||e.chunkSize<=0||e.chunkSize>this.MAX_RECEIVE_CHUNK_SIZE)&&t.push("Invalid chunk size"),(!Array.isArray(e?.salt)||e.salt.length!==32)&&t.push("Invalid salt");let i=typeof e?.fileName=="string"?e.fileName:"",r=this.normalizeDisplayFileName(i);if((!i||i!==i.trim()||/[\u0000-\u001F\u007F]/.test(i)||/[\\/]/.test(i)||i==="."||i===".."||r.length===0)&&t.push("Dangerous file name"),t.length===0){let c=this.validateFile({name:r,size:e.fileSize,type:e.fileType||"application/octet-stream"});c.isValid||t.push(...c.errors)}let a=!!e?.isVoice,o=a?this.rejectVoiceAutoAcceptReason(e):null;return{isValid:t.length===0,errors:t,displayName:r,isVoice:a&&!o,voiceRejection:o}}rejectVoiceAutoAcceptReason(e){let t=String(e?.fileType||"").toLowerCase(),i=e?.fileSize;return t.startsWith("audio/")?this.FILE_TYPE_RESTRICTIONS.voice.mimeTypes.includes(t)?!Number.isSafeInteger(i)||i<=0||i>this.MAX_AUTO_ACCEPT_VOICE_SIZE?`too large to auto-accept (${this.formatFileSize(i||0)} > ${this.formatFileSize(this.MAX_AUTO_ACCEPT_VOICE_SIZE)})`:this.autoAcceptedVoiceBytes+i>this.MAX_AUTO_ACCEPT_VOICE_SESSION_BYTES?"session auto-accept budget for voice notes is exhausted":null:`unsupported audio MIME type (${t})`:`not an audio MIME type (${t||"absent"})`}formatFileSize(e){if(e===0)return"0 B";let t=1024,i=["B","KB","MB","GB"],r=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,r)).toFixed(2))+" "+i[r]}getSupportedFileTypes(){let e={};for(let[t,i]of Object.entries(this.FILE_TYPE_RESTRICTIONS))e[t]={category:i.category,description:i.description,extensions:i.extensions,maxSize:this.formatFileSize(i.maxSize),maxSizeBytes:i.maxSize};return e}getFileTypeInfo(){return{supportedTypes:this.getSupportedFileTypes(),generalMaxSize:this.formatFileSize(this.MAX_FILE_SIZE),generalMaxSizeBytes:this.MAX_FILE_SIZE,restrictions:this.FILE_TYPE_RESTRICTIONS}}arrayBufferToBase64(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),i="",r=t.byteLength;for(let n=0;n{this.webrtcManager.dataChannel&&(clearInterval(e),this.setupMessageInterception())},100);setTimeout(()=>{clearInterval(e)},5e3);return}this.setupMessageInterception()}setupMessageInterception(){try{if(!this.webrtcManager.dataChannel)return;this.webrtcManager&&(this.webrtcManager.fileTransferSystem=this),this.webrtcManager.dataChannel.onmessage&&(this.originalOnMessage=this.webrtcManager.dataChannel.onmessage),this.webrtcManager.dataChannel.onmessage=async e=>{try{if(e.data.length>Dt.MAX_MESSAGE_SIZE){console.warn("\u{1F512} Message too large, ignoring"),Q.logSecurityEvent("oversized_message_blocked");return}if(typeof e.data=="string")try{let t=JSON.parse(e.data);if(Dt.isMessageSizeValid(t),this.isFileTransferMessage(t)){await this.handleFileMessage(t);return}}catch(t){if(t.message==="Message too large")return}if(this.originalOnMessage)return this.originalOnMessage.call(this.webrtcManager.dataChannel,e)}catch(t){if(console.error("\u274C Error in file system message interception:",t),this.originalOnMessage)return this.originalOnMessage.call(this.webrtcManager.dataChannel,e)}}}catch(e){console.error("\u274C Failed to set up message interception:",e)}}isFileTransferMessage(e){return!e||typeof e!="object"||!e.type?!1:["file_transfer_start","file_transfer_response","file_chunk","chunk_confirmation","file_chunk_request","file_transfer_complete","file_transfer_error"].includes(e.type)}async handleFileMessage(e){try{if(!this.webrtcManager.fileTransferSystem)try{if(typeof this.webrtcManager.initializeFileTransfer=="function"){this.webrtcManager.initializeFileTransfer();let t=0,i=50;for(;!this.webrtcManager.fileTransferSystem&&tsetTimeout(r,100)),t++;if(!this.webrtcManager.fileTransferSystem)throw new Error("File transfer system initialization timeout")}else throw new Error("initializeFileTransfer method not available")}catch(t){if(console.error("\u274C Failed to initialize file transfer system:",t),e.fileId){let i={type:"file_transfer_error",fileId:e.fileId,error:"File transfer system not available",timestamp:Date.now()};await this.sendSecureMessage(i)}return}switch(e.type){case"file_transfer_start":await this.handleFileTransferStart(e);break;case"file_transfer_response":this.handleTransferResponse(e);break;case"file_chunk":await this.handleFileChunk(e);break;case"chunk_confirmation":this.handleChunkConfirmation(e);break;case"file_chunk_request":await this.handleChunkRequest(e);break;case"file_transfer_complete":this.handleTransferComplete(e);break;case"file_transfer_error":this.handleTransferError(e);break;default:console.warn("\u26A0\uFE0F Unknown file message type:",e.type)}}catch(t){if(console.error("\u274C Error handling file message:",t),e.fileId){let i={type:"file_transfer_error",fileId:e.fileId,error:t.message,timestamp:Date.now()};await this.sendSecureMessage(i)}}}async deriveFileSessionKey(e){try{if(!this.webrtcManager.keyFingerprint||!this.webrtcManager.sessionSalt)throw new Error("WebRTC session data not available");let t=crypto.getRandomValues(new Uint8Array(32)),i=new TextEncoder,r=i.encode(this.webrtcManager.keyFingerprint),n=i.encode(e),a=new Uint8Array(this.webrtcManager.sessionSalt),o=new Uint8Array(r.length+a.length+t.length+n.length),c=0;o.set(r,c),c+=r.length,o.set(a,c),c+=a.length,o.set(t,c),c+=t.length,o.set(n,c);let l=await crypto.subtle.digest("SHA-256",o),h=await crypto.subtle.importKey("raw",l,{name:"AES-GCM"},!1,["encrypt","decrypt"]);return this.sessionKeys.set(e,{key:h,salt:Array.from(t),created:Date.now()}),{key:h,salt:Array.from(t)}}catch(t){throw console.error("\u274C Failed to derive file session key:",t),t}}async deriveFileSessionKeyFromSalt(e,t){try{if(!t||!Array.isArray(t)||t.length!==32)throw new Error(`Invalid salt: ${t?.length||0} bytes`);if(!this.webrtcManager.keyFingerprint||!this.webrtcManager.sessionSalt)throw new Error("WebRTC session data not available");let i=new TextEncoder,r=i.encode(this.webrtcManager.keyFingerprint),n=i.encode(e),a=new Uint8Array(t),o=new Uint8Array(this.webrtcManager.sessionSalt),c=new Uint8Array(r.length+o.length+a.length+n.length),l=0;c.set(r,l),l+=r.length,c.set(o,l),l+=o.length,c.set(a,l),l+=a.length,c.set(n,l);let h=await crypto.subtle.digest("SHA-256",c),u=await crypto.subtle.importKey("raw",h,{name:"AES-GCM"},!1,["encrypt","decrypt"]);return this.sessionKeys.set(e,{key:u,salt:t,created:Date.now()}),u}catch(i){throw console.error("\u274C Failed to derive session key from salt:",i),i}}_emitTransferProgress(e,t){if(typeof this.onProgress!="function"||!e)return;let i=e.totalChunks||0,r=t==="up"?e.sentChunks||0:e.receivedCount||0,n=i>0?Math.min(100,Math.round(r/i*100)):0;try{this.onProgress({fileId:e.fileId,uiId:e.uiId||null,direction:t,progress:n,transferredChunks:r,totalChunks:i,isVoice:!!e.isVoice,voice:e.voice||null})}catch{}}async sendFile(e,t={}){try{if(!this.webrtcManager)throw new Error("WebRTC Manager not initialized");let i=this.getClientIdentifier();if(!this.rateLimiter.isAllowed(i))throw Q.logSecurityEvent("rate_limit_exceeded",{clientId:i}),new Error("Rate limit exceeded. Please wait before sending another file.");if(!e||!e.size)throw new Error("Invalid file object");let r=this.validateFile(e);if(!r.isValid){let p=r.errors.join(". ");throw new Error(p)}if(this.activeTransfers.size>=this.MAX_CONCURRENT_TRANSFERS)throw new Error("Maximum concurrent transfers reached");let n=`file_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,a=await this.calculateFileHash(e),o=await this.deriveFileSessionKey(n),c=o.key,l=o.salt,h={fileId:n,file:e,fileHash:a,sessionKey:c,salt:l,totalChunks:Math.ceil(e.size/this.CHUNK_SIZE),sentChunks:0,confirmedChunks:0,startTime:Date.now(),status:"preparing",retryCount:0,lastChunkTime:Date.now(),isVoice:!!(t&&t.voice),voice:t&&t.voice?t.voice:null,uiId:t&&t.uiId?t.uiId:null};this.activeTransfers.set(n,h),this.transferNonces.set(n,0);let u=new Promise((p,S)=>{h.resolveConsent=p,h.rejectConsent=S,h.consentTimeout=setTimeout(()=>{h.consentTimeout=null,S(new Error("Transfer timeout"))},3e4)});return await this.sendFileMetadata(h),await u,await this.startChunkTransmission(h),n}catch(i){let r=Q.sanitizeError(i);throw console.error("\u274C File sending failed:",r),this.onError&&this.onError(r),new Error(r)}}async sendFileMetadata(e){try{let t={type:"file_transfer_start",fileId:e.fileId,fileName:e.file.name,fileSize:e.file.size,fileType:e.file.type||"application/octet-stream",fileHash:e.fileHash,totalChunks:e.totalChunks,chunkSize:this.CHUNK_SIZE,salt:e.salt,timestamp:Date.now(),version:"2.0"};if(e.isVoice&&(t.isVoice=!0,e.voice&&(t.voice=e.voice)),this.signingKey)try{t.signature=await Lt.signFileMetadata(t,this.signingKey),console.log("\u{1F512} File metadata signed successfully")}catch(i){Q.logSecurityEvent("signature_failed",{fileId:e.fileId,error:i.message})}await this.sendSecureMessage(t),e.status="metadata_sent"}catch(t){let i=Q.sanitizeError(t);throw console.error("\u274C Failed to send file metadata:",i),e.status="failed",new Error(i)}}async startChunkTransmission(e){try{e.status="transmitting";let t=e.file,i=e.totalChunks;for(let r=0;r{let i=this.activeTransfers.get(e.fileId);i&&i.status!=="completed"&&this.cleanupTransfer(e.fileId)},18e4)}async handleChunkRequest(e){let t=this.activeTransfers.get(e?.fileId);if(!t||!t.file)return;let i=Array.isArray(e.missing)?e.missing:[];if(i.length===0)return;this._armSenderIdleTimeout(t),t.status="transmitting";let n=i.slice(0,512);for(let a of n)if(!(!Number.isInteger(a)||a<0||a>=t.totalChunks))try{let o=a*this.CHUNK_SIZE,c=Math.min(o+this.CHUNK_SIZE,t.file.size),l=await this.readFileChunk(t.file,o,c);await this.sendFileChunk(t,a,l),await this.waitForBackpressure()}catch(o){console.warn("\u26A0\uFE0F Failed to retransmit chunk",a,Q.sanitizeError(o))}t.status==="transmitting"&&(t.status="waiting_confirmation"),this._armSenderIdleTimeout(t)}async readFileChunk(e,t,i){try{return await e.slice(t,i).arrayBuffer()}catch(r){let n=Q.sanitizeError(r);throw console.error("\u274C Failed to read file chunk:",n),new Error(n)}}async sendFileChunk(e,t,i){try{let r=e.sessionKey,n=crypto.getRandomValues(new Uint8Array(12)),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:n},r,i),o=this.arrayBufferToBase64(new Uint8Array(a)),c={type:"file_chunk",fileId:e.fileId,chunkIndex:t,totalChunks:e.totalChunks,nonce:Array.from(n),encryptedDataB64:o,chunkSize:i.byteLength,timestamp:Date.now()};await this.waitForBackpressure(),await this.sendSecureMessage(c)}catch(r){let n=Q.sanitizeError(r);throw console.error("\u274C Failed to send file chunk:",n),new Error(n)}}async sendSecureMessage(e){let t=JSON.stringify(e),i=this.webrtcManager?.dataChannel,r=10,n=0,a=o=>new Promise(c=>setTimeout(c,o));for(;;)try{if(!i||i.readyState!=="open")throw new Error("Data channel not ready");await this.waitForBackpressure(),i.send(t);return}catch(o){let c=String(o?.message||""),l=c.includes("send queue is full")||c.includes("bufferedAmount"),h=o?.name==="OperationError";if((l||h)&&ne.bufferedAmountLowThreshold&&await new Promise(i=>{let r=()=>{e.removeEventListener("bufferedamountlow",r),i()};e.addEventListener("bufferedamountlow",r,{once:!0})});return}let t=4*1024*1024;for(;e.bufferedAmount>t;)await new Promise(i=>setTimeout(i,20))}catch{}}async calculateFileHash(e){try{let t=await e.arrayBuffer(),i=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(i)).map(n=>n.toString(16).padStart(2,"0")).join("")}catch(t){throw console.error("\u274C File hash calculation failed:",t),t}}async handleFileTransferStart(e){try{let t=this.getClientIdentifier();if(!this.incomingOfferLimiter.isAllowed(t))throw new Error("Incoming file request rate limit exceeded");let i=this.validateIncomingMetadata(e);if(!i.isValid)throw new Error(i.errors.join(". "));if(e.signature&&this.verificationKey)try{if(!await Lt.verifyFileMetadata(e,e.signature,this.verificationKey))throw Q.logSecurityEvent("invalid_metadata_signature",{fileId:e.fileId}),new Error("Invalid file metadata signature");console.log("\u{1F512} File metadata signature verified successfully")}catch(n){throw Q.logSecurityEvent("verification_failed",{fileId:e.fileId,error:n.message}),new Error("File metadata verification failed")}if(this.receivingTransfers.has(e.fileId)||this.pendingIncomingTransfers.has(e.fileId))return;if(this.pendingIncomingTransfers.size>=this.MAX_PENDING_INCOMING_TRANSFERS)throw new Error("Too many pending incoming file requests");i.voiceRejection&&console.warn(`Voice auto-accept declined, falling back to consent: ${i.voiceRejection}`);let r={...e,isVoice:i.isVoice,fileName:i.displayName,receivedAt:Date.now()};this.pendingIncomingTransfers.set(e.fileId,r),i.isVoice&&(this.autoAcceptedVoiceBytes+=e.fileSize),typeof this.onIncomingFileRequest=="function"?this.onIncomingFileRequest({fileId:r.fileId,fileName:r.fileName,fileSize:r.fileSize,mimeType:r.fileType||"application/octet-stream",isVoice:i.isVoice,voice:r.voice||null}):await this.rejectIncomingFile(e.fileId,f("file.consentUnavailable"))}catch(t){let i=Q.sanitizeError(t);console.error("\u274C Failed to handle file transfer start:",i);let r={type:"file_transfer_response",fileId:e.fileId,accepted:!1,error:i,timestamp:Date.now()};await this.sendSecureMessage(r)}}async handleFileChunk(e){return this.atomicOps.withLock(`chunk-${e.fileId}`,async()=>{try{let t=this.receivingTransfers.get(e.fileId);if(!t||t._assembled||t.status==="completed")return;if(!this._isIncomingChunkAllowed(e.fileId)){console.warn("\u26A0\uFE0F Incoming file chunk rate limit exceeded; cleaning up transfer:",e.fileId),this.cleanupReceivingTransfer(e.fileId);return}if(t.lastChunkTime=Date.now(),t.receivedChunks.has(e.chunkIndex))return;if(e.chunkIndex<0||e.chunkIndex>=t.totalChunks)throw new Error(`Invalid chunk index: ${e.chunkIndex}`);let i=new Uint8Array(e.nonce),r;if(e.encryptedDataB64)r=this.base64ToUint8Array(e.encryptedDataB64);else if(e.encryptedData)r=new Uint8Array(e.encryptedData);else throw new Error("Missing encrypted data");let n=await crypto.subtle.decrypt({name:"AES-GCM",iv:i},t.sessionKey,r);if(n.byteLength!==e.chunkSize)throw new Error(`Chunk size mismatch: expected ${e.chunkSize}, got ${n.byteLength}`);t.receivedChunks.set(e.chunkIndex,n),t.receivedCount++,this._emitTransferProgress(t,"down");let a={type:"chunk_confirmation",fileId:e.fileId,chunkIndex:e.chunkIndex,timestamp:Date.now()};await this.sendSecureMessage(a),t.receivedCount===t.totalChunks&&await this.assembleFile(t)}catch(t){let i=Q.sanitizeError(t);console.warn("\u26A0\uFE0F Dropping unprocessable file chunk (will be re-requested):",e.chunkIndex,i)}})}_isIncomingChunkAllowed(e){let t=this.getClientIdentifier();return this.incomingChunkLimiter.isAllowed(t)?(this.incomingTransferChunkLimiters.has(e)||this.incomingTransferChunkLimiters.set(e,new nt(this.MAX_INCOMING_CHUNKS_PER_TRANSFER_PER_MINUTE,6e4)),this.incomingTransferChunkLimiters.get(e).isAllowed(e)?!0:(Q.logSecurityEvent("incoming_chunk_transfer_rate_limit_exceeded",{clientId:t,fileId:e}),!1)):(Q.logSecurityEvent("incoming_chunk_aggregate_rate_limit_exceeded",{clientId:t,fileId:e}),!1)}async assembleFile(e){if(!e._assembled){e._assembled=!0;try{e.status="assembling";for(let h=0;hh+u.length,0);if(i!==e.fileSize)throw new Error(`File size mismatch: expected ${e.fileSize}, got ${i}`);let r=new Uint8Array(i),n=0;for(let h of t)r.set(h,n),n+=h.length;if(await this.calculateFileHashFromData(r)!==e.fileHash)throw new Error("File integrity check failed - hash mismatch");let o=r.buffer,c=new Blob([o],{type:e.fileType});if(e.endTime=Date.now(),e.status="completed",this._storeReceivedFileBuffer(e.fileId,{buffer:o,type:e.fileType,name:e.fileName,size:e.fileSize}),this.onFileReceived){let h=async()=>{let S=await this.getBlob(e.fileId);if(!S)throw new Error("This file is no longer available for download.");return S},u=async()=>{let S=await h();return URL.createObjectURL(S)},p=S=>{try{URL.revokeObjectURL(S)}catch{}};this.onFileReceived({fileId:e.fileId,fileName:e.fileName,fileSize:e.fileSize,mimeType:e.fileType,transferTime:e.endTime-e.startTime,isVoice:!!e.isVoice,voice:e.voice||null,fileBlob:c,getBlob:h,getObjectURL:u,revokeObjectURL:p})}let l={type:"file_transfer_complete",fileId:e.fileId,success:!0,timestamp:Date.now()};await this.sendSecureMessage(l),e._stallTimer&&(clearInterval(e._stallTimer),e._stallTimer=null),e.receivedChunks&&e.receivedChunks.clear(),e.sessionKey=null}catch(t){console.error("\u274C File assembly failed:",t),e.status="failed",this.onError&&this.onError(`File assembly failed: ${t.message}`);let i={type:"file_transfer_complete",fileId:e.fileId,success:!1,error:t.message,timestamp:Date.now()};await this.sendSecureMessage(i),this.cleanupReceivingTransfer(e.fileId)}}}async calculateFileHashFromData(e){try{let t=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(t)).map(r=>r.toString(16).padStart(2,"0")).join("")}catch(t){throw console.error("\u274C Hash calculation failed:",t),t}}handleTransferResponse(e){try{let t=this.activeTransfers.get(e.fileId);if(!t)return;e.accepted?(t.status="accepted",t.consentTimeout&&clearTimeout(t.consentTimeout),t.consentTimeout=null,t.resolveConsent?.(),t.resolveConsent=null,t.rejectConsent=null):(t.status="rejected",t.consentTimeout&&clearTimeout(t.consentTimeout),t.consentTimeout=null,t.rejectConsent?.(new Error(e.error||"Transfer rejected")),t.rejectConsent=null,t.resolveConsent=null,this.onError&&this.onError(`Transfer rejected: ${e.error||"Unknown reason"}`),this.cleanupTransfer(e.fileId))}catch(t){console.error("\u274C Failed to handle transfer response:",t)}}handleChunkConfirmation(e){try{let t=this.activeTransfers.get(e.fileId);if(!t)return;t.confirmedChunks++,t.lastChunkTime=Date.now(),t.status==="waiting_confirmation"&&this._armSenderIdleTimeout(t)}catch(t){console.error("\u274C Failed to handle chunk confirmation:",t)}}handleTransferComplete(e){try{let t=this.activeTransfers.get(e.fileId);if(!t)return;e.success?(t.status="completed",t.endTime=Date.now(),this.onComplete&&this.onComplete({fileId:t.fileId,fileName:t.file.name,fileSize:t.file.size,transferTime:t.endTime-t.startTime,status:"completed"})):(t.status="failed",this.onError&&this.onError(`Transfer failed: ${e.error||"Unknown error"}`)),this.cleanupTransfer(e.fileId)}catch(t){console.error("\u274C Failed to handle transfer completion:",t)}}handleTransferError(e){try{let t=this.activeTransfers.get(e.fileId);t&&(t.status="failed",this.cleanupTransfer(e.fileId));let i=this.receivingTransfers.get(e.fileId);i&&(i.status="failed",this.cleanupReceivingTransfer(e.fileId)),this.onError&&this.onError(`Transfer error: ${e.error||"Unknown error"}`)}catch(t){console.error("\u274C Failed to handle transfer error:",t)}}getActiveTransfers(){return Array.from(this.activeTransfers.values()).map(e=>({fileId:e.fileId,fileName:e.file?.name||"Unknown",fileSize:e.file?.size||0,progress:Math.round(e.sentChunks/e.totalChunks*100),totalChunks:e.totalChunks||0,transferredChunks:e.sentChunks||0,status:e.status,startTime:e.startTime}))}getReceivingTransfers(){return Array.from(this.receivingTransfers.values()).map(e=>({fileId:e.fileId,fileName:e.fileName||"Unknown",fileSize:e.fileSize||0,progress:Math.round(e.receivedCount/e.totalChunks*100),totalChunks:e.totalChunks||0,transferredChunks:e.receivedCount||0,status:e.status,startTime:e.startTime}))}getPendingIncomingTransfers(){return Array.from(this.pendingIncomingTransfers.values()).map(e=>({fileId:e.fileId,fileName:e.fileName,fileSize:e.fileSize,mimeType:e.fileType||"application/octet-stream",receivedAt:e.receivedAt}))}async acceptIncomingFile(e){let t=this.pendingIncomingTransfers.get(e);if(!t)return!1;let i=await this.deriveFileSessionKeyFromSalt(e,t.salt);return this.receivingTransfers.set(e,{fileId:e,fileName:t.fileName,fileSize:t.fileSize,fileType:t.fileType||"application/octet-stream",fileHash:t.fileHash,totalChunks:t.totalChunks,chunkSize:t.chunkSize||this.CHUNK_SIZE,sessionKey:i,salt:t.salt,receivedChunks:new Map,receivedCount:0,startTime:Date.now(),lastChunkTime:Date.now(),status:"receiving",isVoice:!!t.isVoice,voice:t.voice||null}),this.pendingIncomingTransfers.delete(e),await this.sendSecureMessage({type:"file_transfer_response",fileId:e,accepted:!0,timestamp:Date.now()}),this._startReceiverStallDetector(e),!0}_startReceiverStallDetector(e){let n=this.receivingTransfers.get(e);n&&(n._stallTimer&&clearInterval(n._stallTimer),n._lastProgressCount=n.receivedCount||0,n._lastProgressTime=Date.now(),n._stallTimer=setInterval(async()=>{let a=this.receivingTransfers.get(e);if(!a||a._stallTimer!==n._stallTimer){clearInterval(n._stallTimer);return}if(a.status==="completed"||a._assembled){clearInterval(a._stallTimer),a._stallTimer=null;return}if(a.receivedCount!==a._lastProgressCount&&(a._lastProgressCount=a.receivedCount,a._lastProgressTime=Date.now()),!(a.receivedCount>=a.totalChunks)&&!(Date.now()-(a.lastChunkTime||0)<5e3)){if(Date.now()-a._lastProgressTime>18e4){clearInterval(a._stallTimer),a._stallTimer=null,a.status="failed",this.onError&&this.onError("File transfer stalled \u2014 no data received. Please try again."),this.cleanupReceivingTransfer(e);return}await this._requestMissingChunks(e)}},2500))}async _requestMissingChunks(e){let t=this.receivingTransfers.get(e);if(!t||!t.receivedChunks)return;let i=256,r=[];for(let n=0;nthis.MAX_RETAINED_RECEIVED_FILE_BUFFERS;){let i=this.receivedFileBuffers.keys().next().value;this._discardReceivedFileBuffer(i)}}_discardReceivedFileBuffer(e){let t=this.receivedFileBuffers.get(e);if(!t)return;try{t.buffer&&(qe.secureWipe(t.buffer),new Uint8Array(t.buffer).fill(0))}catch{}this.receivedFileBuffers.delete(e);let i=this.receivingTransfers.get(e);i&&(i.status==="completed"||i._assembled)&&(i._stallTimer&&(clearInterval(i._stallTimer),i._stallTimer=null),this.receivingTransfers.delete(e))}cleanupReceivingTransfer(e){try{this.pendingChunks.delete(e);let t=this.receivingTransfers.get(e);if(t){if(t._stallTimer&&(clearInterval(t._stallTimer),t._stallTimer=null),t.receivedChunks&&t.receivedChunks.size>0){for(let[n,a]of t.receivedChunks)try{a&&(a instanceof ArrayBuffer||a instanceof Uint8Array)&&(qe.secureWipe(a),a instanceof ArrayBuffer?new Uint8Array(a).fill(0):a instanceof Uint8Array&&a.fill(0))}catch(o){console.warn("\u26A0\uFE0F Failed to securely wipe chunk:",o)}t.receivedChunks.clear()}if(t.sessionKey)try{t.sessionKey=null}catch(n){console.warn("\u26A0\uFE0F Failed to clear session key:",n)}if(t.salt)try{Array.isArray(t.salt)&&t.salt.fill(0),t.salt=null}catch(n){console.warn("\u26A0\uFE0F Failed to clear salt:",n)}for(let[n,a]of Object.entries(t))a&&typeof a=="object"&&(a instanceof ArrayBuffer||a instanceof Uint8Array?qe.secureWipe(a):Array.isArray(a)&&a.fill(0),t[n]=null)}this.receivingTransfers.delete(e),this.sessionKeys.delete(e),this.incomingTransferChunkLimiters.delete(e);let i=this.receivedFileBuffers.get(e);if(i)try{i.buffer&&(qe.secureWipe(i.buffer),new Uint8Array(i.buffer).fill(0));for(let[n,a]of Object.entries(i))a&&typeof a=="object"&&((a instanceof ArrayBuffer||a instanceof Uint8Array)&&qe.secureWipe(a),i[n]=null);this.receivedFileBuffers.delete(e)}catch(n){console.warn("\u26A0\uFE0F Failed to securely clear file buffer:",n),this.receivedFileBuffers.delete(e)}let r=[];for(let n of this.processedChunks)n.startsWith(e)&&r.push(n);for(let n of r)this.processedChunks.delete(n);if(typeof global<"u"&&global.gc)try{global.gc()}catch{}console.log(`\u{1F512} Memory safely cleaned for file transfer: ${e}`)}catch(t){throw console.error("\u274C Error during secure memory cleanup:",t),this.receivingTransfers.delete(e),this.sessionKeys.delete(e),this.receivedFileBuffers.delete(e),this.pendingChunks.delete(e),new Error(`Memory cleanup failed: ${t.message}`)}}getTransferStatus(e){if(this.activeTransfers.has(e)){let t=this.activeTransfers.get(e);return{type:"sending",fileId:t.fileId,fileName:t.file.name,progress:Math.round(t.sentChunks/t.totalChunks*100),status:t.status,startTime:t.startTime}}if(this.receivingTransfers.has(e)){let t=this.receivingTransfers.get(e);return{type:"receiving",fileId:t.fileId,fileName:t.fileName,progress:Math.round(t.receivedCount/t.totalChunks*100),status:t.status,startTime:t.startTime}}return null}getSystemStatus(){return{initialized:!0,activeTransfers:this.activeTransfers.size,receivingTransfers:this.receivingTransfers.size,totalTransfers:this.activeTransfers.size+this.receivingTransfers.size,maxConcurrentTransfers:this.MAX_CONCURRENT_TRANSFERS,maxFileSize:this.MAX_FILE_SIZE,chunkSize:this.CHUNK_SIZE,hasWebrtcManager:!!this.webrtcManager,isConnected:this.webrtcManager?.isConnected?.()||!1,hasDataChannel:!!this.webrtcManager?.dataChannel,dataChannelState:this.webrtcManager?.dataChannel?.readyState,isVerified:this.webrtcManager?.isVerified,hasEncryptionKey:!!this.webrtcManager?.encryptionKey,hasMacKey:!!this.webrtcManager?.macKey,linkedToWebRTCManager:this.webrtcManager?.fileTransferSystem===this,supportedFileTypes:this.getSupportedFileTypes(),fileTypeInfo:this.getFileTypeInfo()}}cleanup(){Ie.getInstance().deactivate(),this.webrtcManager&&this.webrtcManager.dataChannel&&this.originalOnMessage&&(this.webrtcManager.dataChannel.onmessage=this.originalOnMessage,this.originalOnMessage=null),this.webrtcManager&&this.originalProcessMessage&&(this.webrtcManager.processMessage=this.originalProcessMessage,this.originalProcessMessage=null),this.webrtcManager&&this.originalRemoveSecurityLayers&&(this.webrtcManager.removeSecurityLayers=this.originalRemoveSecurityLayers,this.originalRemoveSecurityLayers=null);for(let e of this.activeTransfers.keys())this.cleanupTransfer(e);for(let e of this.receivingTransfers.keys())this.cleanupReceivingTransfer(e);this.atomicOps&&this.atomicOps.locks.clear(),this.rateLimiter&&this.rateLimiter.requests.clear(),this.incomingChunkLimiter&&this.incomingChunkLimiter.requests.clear(),this.incomingTransferChunkLimiters.clear(),this.pendingChunks.clear(),this.pendingIncomingTransfers.clear(),this.activeTransfers.clear(),this.receivingTransfers.clear(),this.transferQueue.length=0,this.sessionKeys.clear(),this.transferNonces.clear(),this.processedChunks.clear();for(let e of Array.from(this.receivedFileBuffers.keys()))this._discardReceivedFileBuffer(e);this.clearKeys()}onSessionUpdate(e){this.sessionKeys.clear()}diagnoseFileTransferIssue(){return{timestamp:new Date().toISOString(),fileTransferSystem:{initialized:!!this,hasWebrtcManager:!!this.webrtcManager,webrtcManagerType:this.webrtcManager?.constructor?.name,linkedToWebRTCManager:this.webrtcManager?.fileTransferSystem===this},webrtcManager:{hasDataChannel:!!this.webrtcManager?.dataChannel,dataChannelState:this.webrtcManager?.dataChannel?.readyState,isConnected:this.webrtcManager?.isConnected?.()||!1,isVerified:this.webrtcManager?.isVerified,hasEncryptionKey:!!this.webrtcManager?.encryptionKey,hasMacKey:!!this.webrtcManager?.macKey,hasKeyFingerprint:!!this.webrtcManager?.keyFingerprint,hasSessionSalt:!!this.webrtcManager?.sessionSalt},securityContext:{contextActive:Ie.getInstance().isActive(),securityLevel:Ie.getInstance().getSecurityLevel(),hasAtomicOps:!!this.atomicOps,hasRateLimiter:!!this.rateLimiter},transfers:{activeTransfers:this.activeTransfers.size,receivingTransfers:this.receivingTransfers.size,pendingChunks:this.pendingChunks.size,sessionKeys:this.sessionKeys.size},fileTypeSupport:{supportedTypes:this.getSupportedFileTypes(),generalMaxSize:this.formatFileSize(this.MAX_FILE_SIZE),restrictions:Object.keys(this.FILE_TYPE_RESTRICTIONS)}}}async debugKeyDerivation(e){try{if(!this.webrtcManager.keyFingerprint||!this.webrtcManager.sessionSalt)throw new Error("Session data not available");let t=await this.deriveFileSessionKey(e),i=await this.deriveFileSessionKeyFromSalt(e,t.salt),r=new TextEncoder().encode("test data"),n=crypto.getRandomValues(new Uint8Array(12)),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:n},t.key,r),o=await crypto.subtle.decrypt({name:"AES-GCM",iv:n},i,a);if(new TextDecoder().decode(o)==="test data")return{success:!0,message:"All tests passed"};throw new Error("Decryption verification failed")}catch(t){return console.error("\u274C Key derivation test failed:",t),{success:!1,error:t.message}}}registerWithWebRTCManager(){if(!this.webrtcManager)throw new Error("WebRTC manager not available");this.webrtcManager.fileTransferSystem=this,this.webrtcManager.setFileMessageHandler=e=>{this.webrtcManager._fileMessageHandler=e},this.webrtcManager.setFileMessageHandler(e=>this.handleFileMessage(e))}static createFileMessageFilter(e){return async t=>{try{if(typeof t.data=="string"){let i=JSON.parse(t.data);if(e.isFileTransferMessage(i))return await e.handleFileMessage(i),!0}}catch{}return!1}}setSigningKey(e){if(!e||!(e instanceof CryptoKey))throw new Error("Invalid private key for signing");this.signingKey=e,console.log("\u{1F512} Signing key set successfully")}setVerificationKey(e){if(!e||!(e instanceof CryptoKey))throw new Error("Invalid public key for verification");this.verificationKey=e,console.log("\u{1F512} Verification key set successfully")}async generateSigningKeyPair(){try{let e=await crypto.subtle.generateKey({name:"RSASSA-PKCS1-v1_5",modulusLength:2048,publicExponent:new Uint8Array([1,0,1]),hash:"SHA-256"},!0,["sign","verify"]);return this.signingKey=e.privateKey,this.verificationKey=e.publicKey,console.log("\u{1F512} RSA key pair generated successfully"),e}catch(e){let t=Q.sanitizeError(e);throw console.error("\u274C Failed to generate signing key pair:",t),new Error(t)}}clearKeys(){this.signingKey=null,this.verificationKey=null,console.log("\u{1F512} Security keys cleared")}getSecurityStatus(){return{signingEnabled:this.signingKey!==null,verificationEnabled:this.verificationKey!==null,contextActive:Ie.getInstance().isActive(),securityLevel:Ie.getInstance().getSecurityLevel()}}getClientIdentifier(){return this.webrtcManager?.connectionId||this.webrtcManager?.keyFingerprint?.substring(0,16)||"default-client"}destroy(){Ie.getInstance().deactivate(),this.clearKeys(),console.log("\u{1F512} File transfer system destroyed safely")}};var Ue=typeof navigator<"u"&&/AppleWebKit/.test(navigator.userAgent)&&!/Chrome|Chromium|Edg\//.test(navigator.userAgent),st={opusFmtp:{minptime:10,useinbandfec:1,usedtx:1,stereo:0,maxaveragebitrate:32e3,cbr:0},preferRed:!0,sender:{maxBitrate:4e4,priority:"high",networkPriority:"high"}},xe={codecPreferenceOrder:["VP9","AV1","H264","VP8"],vp9:{preferredScalabilityMode:"L3T3_KEY",simulcast:[{rid:"low",scaleResolutionDownBy:4,maxBitrate:15e4,scalabilityMode:"L1T3"},{rid:"mid",scaleResolutionDownBy:2,maxBitrate:5e5,scalabilityMode:"L1T3"},{rid:"high",scaleResolutionDownBy:1,maxBitrate:15e5,scalabilityMode:"L1T3"}],degradationPreference:"balanced"},av1:{scalabilityMode:"L1T3",maxBitrate:12e5,degradationPreference:"maintain-framerate"},simulcast:[{rid:"low",scaleResolutionDownBy:4,maxBitrate:15e4},{rid:"mid",scaleResolutionDownBy:2,maxBitrate:5e5},{rid:"high",scaleResolutionDownBy:1,maxBitrate:15e5}],networkPriority:"medium"},Nr={twccUri:"http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",video:{rtcpFb:["transport-cc","nack","nack pli","ccm fir","goog-remb"],twcc:!0},audio:{rtcpFb:["transport-cc","nack"],twcc:!0}},Ei={intervalMs:1e3,loss:{highPct:.1,recoverPct:.03,audioProtectPct:.25},rtt:{highMs:300,recoverMs:150},stepDownPct:.2,stepUpPct:.1,minVideoBitrate:1e5,recoverStableTicks:5,cpuScaleStep:1.5};function js(s){return s.indexOf(`\r `)!==-1?`\r `:` `}function Ur(s){let e=js(s),t=s.split(/\r\n|\n/),i=[],r=[],n=null;for(let a of t)a.startsWith("m=")?(n={lines:[a]},r.push(n)):n?n.lines.push(a):i.push(a);return{eol:e,session:i,media:r}}function zr(s){let e=[...s.session];for(let t of s.media)e.push(...t.lines);return e.join(s.eol)}function Vr(s){let e=s.lines[0].match(/^m=(\w+)/);return e?e[1]:null}function Ws(s,e){let t=new RegExp("^a=rtpmap:(\\d+)\\s+"+e+"\\/","i"),i=[];for(let r of s.lines){let n=r.match(t);n&&i.push(n[1])}return i}function Ys(s){let e=new Map;for(let t of s.split(";")){let i=t.trim();if(!i)continue;let r=i.indexOf("=");r===-1?e.set(i,void 0):e.set(i.slice(0,r).trim(),i.slice(r+1).trim())}return e}function Or(s){let e=[];for(let[t,i]of s)e.push(i===void 0?t:`${t}=${i}`);return e.join(";")}function Xs(s,e,t){let i=s.lines.findIndex(o=>o.startsWith(`a=fmtp:${e} `)||o===`a=fmtp:${e}`);if(i!==-1){let o=s.lines[i].slice(`a=fmtp:${e} `.length),c=Ys(o);for(let[l,h]of Object.entries(t))c.set(l,String(h));s.lines[i]=`a=fmtp:${e} ${Or(c)}`;return}let r=new Map;for(let[o,c]of Object.entries(t))r.set(o,String(c));let n=`a=fmtp:${e} ${Or(r)}`,a=s.lines.findIndex(o=>o.startsWith(`a=rtpmap:${e} `));a!==-1?s.lines.splice(a+1,0,n):s.lines.push(n)}function bi(s,e){if(!s||typeof s!="string")return s;let t=Ur(s),i=!1;for(let r of t.media)if(Vr(r)==="audio")for(let n of Ws(r,"opus"))Xs(r,n,e),i=!0;return i?zr(t):s}var Qs=/^(rtx|red|ulpfec|flexfec-03|telephone-event|CN)$/i;function Js(s){let e=[];for(let t of s.lines){let i=t.match(/^a=rtpmap:(\d+)\s+([^/]+)\//);i&&!Qs.test(i[2])&&e.push(i[1])}return e}function Zs(s,e){for(let t of Js(s))for(let i of e){let r=`a=rtcp-fb:${t} ${i}`;if(s.lines.includes(r))continue;let n=-1;for(let a=0;ar.startsWith("a=extmap:")&&r.includes(e)))return;let t=0,i=-1;for(let r=0;rr.startsWith("a=mid:")),i===-1&&(i=s.lines.length-1)),s.lines.splice(i+1,0,`a=extmap:${t+1} ${e}`)}function Br(s,e){if(!s||typeof s!="string"||!e)return s;let t=Ur(s),i=!1;for(let r of t.media){let n=Vr(r),a=n==="video"?e.video:n==="audio"?e.audio:null;a&&(Array.isArray(a.rtcpFb)&&(Zs(r,a.rtcpFb),i=!0),a.twcc&&e.twccUri&&(ea(r,e.twccUri),i=!0))}return i?zr(t):s}function Hr(s){try{if(Ue||!s||typeof s.setCodecPreferences!="function"||!st.preferRed)return!1;let e=typeof RTCRtpSender<"u"&&RTCRtpSender.getCapabilities?RTCRtpSender.getCapabilities("audio"):null;if(!e||!Array.isArray(e.codecs))return!1;let t=o=>/red$/i.test(o.mimeType),i=o=>/opus$/i.test(o.mimeType);if(!e.codecs.some(t))return!1;let r=e.codecs.filter(t),n=e.codecs.filter(i),a=e.codecs.filter(o=>!t(o)&&!i(o));return s.setCodecPreferences([...r,...n,...a]),!0}catch{return!1}}async function $r(s,e={}){try{if(Ue||!s||typeof s.getParameters!="function")return!1;let t={...st.sender,...e},i=s.getParameters();(!i.encodings||i.encodings.length===0)&&(i.encodings=[{}]);for(let r of i.encodings)r.maxBitrate=t.maxBitrate,r.priority=t.priority,r.networkPriority=t.networkPriority;return await s.setParameters(i),!0}catch{return!1}}var Gr={VP9:0,AV1:1,H264:2,VP8:3};function qr(s){return(String(s||"").split("/")[1]||"").toUpperCase()}function ta(s){let e=t=>{let i=qr(t.mimeType);return Object.prototype.hasOwnProperty.call(Gr,i)?Gr[i]:99};return s.map((t,i)=>({c:t,i})).sort((t,i)=>e(t.c)-e(i.c)||t.i-i.i).map(t=>t.c)}function jr(s){if(!s||!Array.isArray(s.codecs))return null;let e=new Set(s.codecs.map(t=>qr(t.mimeType)));for(let t of xe.codecPreferenceOrder)if(e.has(t))return t;return null}function Wr(){return typeof RTCRtpSender<"u"&&RTCRtpSender.getCapabilities?RTCRtpSender.getCapabilities("video"):null}function Yr(s){try{if(Ue||!s||typeof s.setCodecPreferences!="function")return!1;let e=Wr();return!e||!Array.isArray(e.codecs)?!1:(s.setCodecPreferences(ta(e.codecs)),jr(e))}catch{return!1}}function ia(s){return s==="VP9"?{scalabilityMode:xe.vp9.preferredScalabilityMode,maxBitrate:15e5,degradationPreference:xe.vp9.degradationPreference}:s==="AV1"?{scalabilityMode:xe.av1.scalabilityMode,maxBitrate:xe.av1.maxBitrate,degradationPreference:xe.av1.degradationPreference}:{scalabilityMode:void 0,maxBitrate:15e5,degradationPreference:"balanced"}}async function Xr(s,e={}){try{if(Ue||!s||typeof s.getParameters!="function")return!1;let t=jr(Wr())||"VP8",i={...ia(t),...e},r=s.getParameters();(!r.encodings||r.encodings.length===0)&&(r.encodings=[{}]);let n=r.encodings.length>1;if(n)for(let a of r.encodings)a.networkPriority=xe.networkPriority;else{let a=r.encodings[0];a.maxBitrate=i.maxBitrate,a.networkPriority=xe.networkPriority,i.scalabilityMode&&(a.scalabilityMode=i.scalabilityMode)}i.degradationPreference&&(r.degradationPreference=i.degradationPreference);try{return await s.setParameters(r),!0}catch{if(!n&&i.scalabilityMode){delete r.encodings[0].scalabilityMode;try{return await s.setParameters(r),!0}catch{return!1}}return!1}}catch{return!1}}function Qr(s,e={}){let t=null,i=null,r=null;for(let m of s)!m||typeof m.type!="string"||(m.type==="outbound-rtp"&&!m.isRemote?(!t||m.kind==="video")&&(t=m):m.type==="remote-inbound-rtp"?(!i||m.kind==="video")&&(i=m):m.type==="candidate-pair"&&(m.nominated||m.selected||m.state==="succeeded")&&(!r||m.nominated)&&(r=m));let n=Number(t?.packetsSent??0),a=Number(i?.packetsLost??0),o=n-(e.packetsSent??n),c=a-(e.packetsLost??a),l=o+c,h=l>0?Math.min(1,Math.max(0,c/l)):0,u=r?.currentRoundTripTime??i?.roundTripTime??0,p=Number(u)*1e3,S=Number(i?.jitter??0)*1e3,w=r?.availableOutgoingBitrate!=null?Number(r.availableOutgoingBitrate):null,g=t?.qualityLimitationReason??"none";return{lossPct:h,rttMs:p,jitterMs:S,availableOutgoingBitrate:w,qualityLimitationReason:g,counters:{packetsSent:n,packetsLost:a},hasData:!!(t&&(i||r))}}function Jr(s){if(!s||!s.hasData)return null;let e=s.lossPct,t=s.rttMs;return e<.03&&t<150?"excellent":e<.07&&t<250?"good":e<.15&&t<400?"fair":"poor"}function ra(s,e,t=Ei){let{targetBitrate:i,ceilingBitrate:r,scaleResolutionDownBy:n,goodTicks:a}=e,o=!1,c="steady";if(s.qualityLimitationReason==="cpu"){let l=Math.min(4,+(n*t.cpuScaleStep).toFixed(3));l!==n&&(n=l,o=!0),a=0,c="cpu"}else if(s.lossPct>t.loss.highPct||s.rttMs>t.rtt.highMs){let l=Math.max(t.minVideoBitrate,Math.round(i*(1-t.stepDownPct)));l!==i&&(i=l,o=!0),a=0,c="backoff"}else if(s.lossPct=t.recoverStableTicks){let l=Math.min(r,Math.round(i*(1+t.stepUpPct)));l!==i&&(i=l,o=!0,c="rampup"),a=0}}else a=0;return{targetBitrate:i,scaleResolutionDownBy:n,goodTicks:a,changed:o,reason:c}}var Pt=class{constructor(e,t={}){this.pc=e,this.getVideoSender=t.getVideoSender||(()=>null),this.onQuality=t.onQuality||(()=>{}),this.cfg=t.cfg||Ei,this._timer=null,this._prevCounters={},this._lastQuality=void 0,this.state={targetBitrate:t.ceilingBitrate||15e5,ceilingBitrate:t.ceilingBitrate||15e5,scaleResolutionDownBy:1,goodTicks:0}}start(){this._timer||(this._timer=setInterval(()=>{this._tick().catch(()=>{})},this.cfg.intervalMs))}stop(){this._timer&&(clearInterval(this._timer),this._timer=null)}async _tick(){if(!this.pc||typeof this.pc.getStats!="function")return;let e=await this.pc.getStats(),t=typeof e.values=="function"?Array.from(e.values()):e,i=Qr(t,this._prevCounters);this._prevCounters=i.counters;let r=Jr(i);if(r&&r!==this._lastQuality){this._lastQuality=r;try{this.onQuality(r,i)}catch{}}if(!i.hasData)return;let n=ra(i,this.state,this.cfg);this.state={targetBitrate:n.targetBitrate,ceilingBitrate:this.state.ceilingBitrate,scaleResolutionDownBy:n.scaleResolutionDownBy,goodTicks:n.goodTicks},n.changed&&await this._applyToVideoSender()}async _applyToVideoSender(){if(Ue)return;let e=this.getVideoSender();if(!(!e||typeof e.getParameters!="function"))try{let t=e.getParameters();if((!t.encodings||t.encodings.length===0)&&(t.encodings=[{}]),t.encodings.length===1)t.encodings[0].maxBitrate=this.state.targetBitrate,t.encodings[0].scaleResolutionDownBy=this.state.scaleResolutionDownBy;else{let i=t.encodings[t.encodings.length-1];i.maxBitrate=this.state.targetBitrate}await e.setParameters(t)}catch{}}};var na="SecureBit-DR-Root-v1",sa="SecureBit-DR-Message-v1",aa="SecureBit-DR-Init-v1",oa=Uint8Array.of(1),ca=Uint8Array.of(2),Kt=new TextEncoder,la=new TextDecoder,Ft=Object.freeze({MAX_SKIP_PER_CHAIN:512,MAX_SKIPPED_KEYS:1024,SKIPPED_KEY_TTL_MS:300*1e3});function Zr(s){let e="",t=new Uint8Array(s);for(let i=0;i{o&&o.apply(),this._receivingChainKey&&this._receivingChainKey!==S&&$(this._receivingChainKey);for(let w of a)$(w);this._receivingChainKey=S,this._receiveCount=i+1,this._remotePublicKeyB64=h;for(let{id:w,key:g}of n)this._rememberSkipped(w,g);$(p)},discard:()=>{o&&o.discard();for(let{key:w}of n)$(w);for(let w of a)$(w);$(S),$(p)}}}async _collectSkipped(e,t,i,r){if(iFt.MAX_SKIP_PER_CHAIN)throw new Error(`DoubleRatchet: refusing to skip ${i-t} messages (limit ${Ft.MAX_SKIP_PER_CHAIN})`);let n=[],a=e;for(let o=t;o=Ft.MAX_SKIPPED_KEYS;){let i=this._skipped.keys().next().value,r=this._skipped.get(i);this._skipped.delete(i),r&&$(r.key)}this._skipped.set(e,{key:t,storedAt:Date.now()})}_pruneSkipped(){let e=Date.now()-Ft.SKIPPED_KEY_TTL_MS;for(let[t,i]of this._skipped)i.storedAt{$(this._rootKey),$(r.nextRoot),this._sendingChainKey&&$(this._sendingChainKey),this._rootKey=o.nextRoot,this._sendingChainKey=o.chainKey,this._selfKeyPair=n,this._remotePublicKey=t,this._remotePublicKeyB64=e,this._previousSendCount=this._sendCount,this._sendCount=0},discard:()=>{$(r.nextRoot),$(r.chainKey),$(o.nextRoot),$(o.chainKey)}}}destroy(){$(this._rootKey),$(this._sendingChainKey),$(this._receivingChainKey);for(let e of this._skipped.values())$(e.key);this._skipped.clear(),this._rootKey=null,this._sendingChainKey=null,this._receivingChainKey=null,this._selfKeyPair=null,this._remotePublicKey=null,this._remotePublicKeyB64=null,this._initialised=!1}};var G=Object.freeze({MAX_PAYLOAD_BYTES:512,MAX_CANDIDATES:8,MIN_UFRAG:4,MAX_UFRAG:64,MIN_PWD:22,MAX_PWD:64,FINGERPRINT_BYTES:32,COMMITMENT_BYTES:16,BINDING_BYTES:8,MAX_LIFETIME_MINUTES:60,MAX_EXT_BYTES:255,SURPLUS_CANDIDATE_BYTES:48,CLOCK_SKEW_MS:12e4}),sn=Date.UTC(2024,0,1),da=16777215,le=Object.freeze({OFFER:0,ANSWER:1}),an=Object.freeze(["actpass","active","passive"]),xi=Object.freeze([262144,1073741823,65536,null]),on=3,mt=Object.freeze({MAX_MESSAGE_SIZE:1}),me=Object.freeze({HOST_V4:0,HOST_MDNS:1,SRFLX_V4:2,RELAY_V4:3,HOST_V6:4,SRFLX_V6:5,RELAY_V6:6}),cn=Object.freeze({0:4,1:16,2:4,3:4,4:16,5:16,6:16}),at=Object.freeze({0:"host",1:"host",2:"srflx",3:"relay",4:"host",5:"srflx",6:"relay"}),ki=Object.freeze({0:"v4",1:"mdns",2:"v4",3:"v4",4:"v6",5:"v6",6:"v6"}),Ri=Object.freeze([null,"passive","active","so"]),ua=Object.freeze({host:126,srflx:100,relay:0}),Ot=/^[A-Za-z0-9+/]+$/,Ai=class extends Error{constructor(e,t="malformed"){super(e),this.name="DescriptorError",this.code=t}},P=(s,e)=>{throw new Ai(s,e)},ha=/^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})\.local$/i,fa=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;function ln(s){let e=fa.exec(s);if(!e)return null;let t=new Uint8Array(4);for(let i=0;i<4;i++){let r=Number(e[i+1]);if(!Number.isInteger(r)||r<0||r>255)return null;t[i]=r}return t}function pa(s){if(!/^[0-9a-fA-F:.]+$/.test(s)||s.length>45)return null;let e=s,t=null,i=e.lastIndexOf(":");if(e.includes(".")){if(t=ln(e.slice(i+1)),!t)return null;e=e.slice(0,i+1)+"0:0"}let r=e.split("::");if(r.length>2)return null;let n=h=>h===""?[]:h.split(":").map(u=>u.length===0||u.length>4?NaN:parseInt(u,16)),a=n(r[0]),o=r.length===2?n(r[1]):[];if([...a,...o].some(h=>!Number.isInteger(h)||h<0||h>65535))return null;let c;if(r.length===2){let h=8-a.length-o.length;if(h<1)return null;c=[...a,...new Array(h).fill(0),...o]}else c=a;if(c.length!==8)return null;let l=new Uint8Array(16);return c.forEach((h,u)=>{l[u*2]=h>>8,l[u*2+1]=h&255}),t&&l.set(t,12),l}function ya(s){let e=ha.exec(s);if(!e)return null;let t=(e[1]+e[2]+e[3]+e[4]+e[5]).toLowerCase(),i=new Uint8Array(16);for(let r=0;r<16;r++)i[r]=parseInt(t.substr(r*2,2),16);return i}function ga(s){return typeof s!="string"&&P("SDP must be a string"),s.length>64*1024&&P("SDP is too large"),s.split(/\r\n|\n/).filter(e=>e.length>0)}function yt(s,e){let t=`a=${e}:`;for(let i of s)if(i.startsWith(t))return i.slice(t.length).trim();return null}function dn(s){let e=ga(s),t=yt(e,"ice-ufrag"),i=yt(e,"ice-pwd");(!t||!i)&&P("SDP is missing ICE credentials");let r=yt(e,"fingerprint");r||P("SDP is missing a DTLS fingerprint");let[n,a]=r.split(/\s+/);(!n||n.toLowerCase()!=="sha-256")&&P(`unsupported DTLS fingerprint algorithm: ${String(n).slice(0,16)}`);let o=String(a).split(":");o.length!==G.FINGERPRINT_BYTES&&P("DTLS fingerprint has the wrong length");let c=new Uint8Array(G.FINGERPRINT_BYTES);o.forEach((w,g)=>{/^[0-9a-fA-F]{2}$/.test(w)||P("DTLS fingerprint is not hex"),c[g]=parseInt(w,16)});let l=yt(e,"setup")||"actpass",h=an.indexOf(l);h<0&&P(`unsupported DTLS setup role: ${l.slice(0,16)}`);let u=yt(e,"max-message-size"),p=u===null?65536:Number(u);(!Number.isInteger(p)||p<0)&&P("invalid a=max-message-size");let S=[];for(let w of e){if(!w.startsWith("a=candidate:"))continue;let g=w.slice(12).split(/\s+/);if(g.length<8||g[6]!=="typ"||g[1]!=="1")continue;let m=g[2].toLowerCase(),I=Number(g[3]),b=g[4],D=Number(g[5]),_=g[7];if(!Number.isInteger(D)||D<1||D>65535)continue;let R=0;if(m==="tcp"){let v=g.indexOf("tcptype"),q=v>=0?Ri.indexOf(g[v+1]):-1;if(q<=0)continue;R=q}else if(m!=="udp")continue;let E=null,C=null,M=ya(b);if(M&&_==="host")E=me.HOST_MDNS,C=M;else{let v=ln(b),q=v?null:pa(b),O=v||q;if(!O)continue;if(_==="host")E=v?me.HOST_V4:me.HOST_V6;else if(_==="srflx"||_==="prflx")E=v?me.SRFLX_V4:me.SRFLX_V6;else if(_==="relay")E=v?me.RELAY_V4:me.RELAY_V6;else continue;C=O}S.push({kind:E,tcptype:R,addr:C,port:D,priority:Number.isFinite(I)?I:0})}return{ufrag:t,pwd:i,fingerprint:c,setup:h,maxMessageSize:p,candidates:S}}function rn(s){return 1+cn[s.kind]+2}var ma=s=>s.tcptype!==2&&s.tcptype!==3;function Mi(s,{maxCandidates:e=G.MAX_CANDIDATES,maxBytes:t=G.SURPLUS_CANDIDATE_BYTES,keepMdns:i=!0,maxRelays:r=2}={}){let n=s.filter(m=>i||m.kind!==me.HOST_MDNS),a=[],o=new Set;for(let m of n){let I=`${m.kind}:${m.tcptype}:${Array.from(m.addr).join(".")}:${m.port}`;o.has(I)||(o.add(I),a.push(m))}let c=(m,I)=>(I.priority||0)-(m.priority||0),l=m=>`${ki[m.kind]}/${at[m.kind]}/${m.tcptype===0?"udp":"tcp"}`,h=new Map;for(let m of[...a].sort(c)){if(!ma(m))continue;let I=l(m);h.has(I)||h.set(I,[]),h.get(I).push(m)}let u=[],p=new Set,S=0,w=0,g=m=>{u.push(m),p.add(m),S+=rn(m),at[m.kind]==="relay"&&w++};for(let m of h.values())g(m[0]);for(let m of[...a].sort(c))if(!p.has(m)){if(u.length>=e)break;S+rn(m)>t||at[m.kind]==="relay"&&w>=r||g(m)}return u.sort(c)}var St=class{constructor(){this.b=[]}u8(e){this.b.push(e&255)}u16(e){this.b.push(e>>8&255,e&255)}u24(e){this.b.push(e>>16&255,e>>8&255,e&255)}u32(e){this.b.push(e>>>24&255,e>>>16&255,e>>>8&255,e&255)}bytes(e){for(let t of e)this.b.push(t&255)}ascii(e){for(let t=0;t2147483647)&&P("max-message-size must be an integer between 1024 and 2^31-1");let e=[],t=xi.indexOf(s);if(t<0){t=on;let i=new St;i.u32(s),e.push({type:mt.MAX_MESSAGE_SIZE,value:i.done()})}return{mmsIndex:t,records:e}}function un(s){let{type:e,bindingTag:t=null,expiresAtMs:i,sdpFields:r,commitment:n=null}=s;e!==le.OFFER&&e!==le.ANSWER&&P("invalid descriptor type"),e===le.ANSWER?(!(t instanceof Uint8Array)||t.length!==G.BINDING_BYTES)&&P("answer needs an 8-byte binding tag"):t!==null&&P("offers do not carry a binding tag"),n!==null&&(!(n instanceof Uint8Array)||n.length!==G.COMMITMENT_BYTES)&&P("commitment must be 16 bytes");let{ufrag:a,pwd:o,fingerprint:c,setup:l,maxMessageSize:h,candidates:u}=r;(a.lengthG.MAX_UFRAG||!Ot.test(a))&&P("invalid ice-ufrag"),(o.lengthG.MAX_PWD||!Ot.test(o))&&P("invalid ice-pwd"),u.length>G.MAX_CANDIDATES&&P("too many candidates");let p=Math.ceil((i-sn)/6e4);(!Number.isInteger(p)||p<0||p>da)&&P("expiry out of range");let{mmsIndex:S,records:w}=Sa(h),g=new St;for(let _ of w)_.value.length>255&&P("extension value is too long"),g.u8(_.type),g.u8(_.value.length),g.bytes(_.value);let m=g.done();m.length>G.MAX_EXT_BYTES&&P("extension area is too long");let I=e&3|(l&3)<<2|(S&3)<<4|(n?64:0)|(m.length?128:0),b=new St;b.u8(2),b.u8(I),b.u24(p),e===le.ANSWER&&b.bytes(t),b.bytes(c),b.u8(a.length),b.ascii(a),b.u8(o.length),b.ascii(o),b.u8(u.length);for(let _ of u)b.u8((_.kind&15)<<4|_.tcptype&15),b.bytes(_.addr),b.u16(_.port);n&&b.bytes(n),m.length&&(b.u8(m.length),b.bytes(m));let D=b.done();return D.length>G.MAX_PAYLOAD_BYTES&&P("descriptor exceeds the payload limit"),D}var _t=class{constructor(e){this.buf=e,this.i=0}need(e){this.i+e>this.buf.length&&P("descriptor is truncated")}u8(){return this.need(1),this.buf[this.i++]}u16(){this.need(2);let e=this.buf[this.i]<<8|this.buf[this.i+1];return this.i+=2,e}u24(){this.need(3);let e=this.buf[this.i]<<16|this.buf[this.i+1]<<8|this.buf[this.i+2];return this.i+=3,e}u32(){this.need(4);let e=(this.buf[this.i]<<24>>>0)+(this.buf[this.i+1]<<16)+(this.buf[this.i+2]<<8)+this.buf[this.i+3];return this.i+=4,e>>>0}bytes(e){return this.need(e),this.buf.slice(this.i,this.i+=e)}ascii(e){this.need(e);let t="";for(let i=0;i126)&&P("non-printable byte in a text field"),t+=String.fromCharCode(r)}return this.i+=e,t}get rest(){return this.buf.length-this.i}};function _a(s){let e=new _t(s),t=new Map,i=-1;for(;e.rest>0;){let r=e.u8(),n=e.u8(),a=e.bytes(n);if(r<=i&&P("extension records must be in ascending type order without duplicates"),i=r,r===mt.MAX_MESSAGE_SIZE){n!==4&&P("extension 0x01 must be 4 bytes");let o=new _t(a).u32();(o<1024||o>2147483647)&&P("extension 0x01 value is out of range"),xi.includes(o)&&P("extension 0x01 duplicates a value the flags already encode"),t.set(r,o)}else P(`unknown extension type 0x${r.toString(16).padStart(2,"0")}`,"unknown_extension")}return t}function Li(s,{nowMs:e=Date.now()}={}){s instanceof Uint8Array||P("descriptor must be a Uint8Array"),s.length===0&&P("descriptor is empty"),s.length>G.MAX_PAYLOAD_BYTES&&P("descriptor exceeds the payload limit");let t=new _t(s),i=t.u8();i!==2&&P(`unsupported descriptor version 0x${i.toString(16)}`,"version");let r=t.u8(),n=r&3;n!==le.OFFER&&n!==le.ANSWER&&P("reserved descriptor type");let a=r>>2&3;a>2&&P("reserved DTLS setup role");let o=r>>4&3,c=(r&64)!==0,l=(r&128)!==0,h=t.u24(),u=sn+h*6e4;if(e-G.CLOCK_SKEW_MS>u){let C=Math.round((e-u)/6e4);P(`this code expired ${C} minute(s) ago. If it was just created, this device's clock or time zone is probably wrong \u2014 check the date and time settings.`,"expired")}u-e>G.MAX_LIFETIME_MINUTES*6e4+G.CLOCK_SKEW_MS&&P("descriptor lifetime is implausibly long","lifetime");let p=n===le.ANSWER?t.bytes(G.BINDING_BYTES):null,S=t.bytes(G.FINGERPRINT_BYTES),w=t.u8();(wG.MAX_UFRAG)&&P("ice-ufrag length out of range");let g=t.ascii(w);Ot.test(g)||P("ice-ufrag contains characters outside the ICE alphabet");let m=t.u8();(mG.MAX_PWD)&&P("ice-pwd length out of range");let I=t.ascii(m);Ot.test(I)||P("ice-pwd contains characters outside the ICE alphabet");let b=t.u8();b>G.MAX_CANDIDATES&&P("too many candidates");let D=[];for(let C=0;C>4&15,q=M&15,O=cn[v];O===void 0&&P(`reserved candidate kind ${v}`),q>=Ri.length&&P("reserved TCP candidate type");let x=t.bytes(O),ue=t.u16();ue<1&&P("candidate port must be non-zero"),D.push({kind:v,tcptype:q,addr:x,port:ue})}let _=null;c&&(_=t.bytes(G.COMMITMENT_BYTES));let R=new Map;if(l){let C=t.u8();C===0&&P("extension area is flagged but empty"),R=_a(t.bytes(C))}t.rest!==0&&P(`${t.rest} trailing byte(s) after the descriptor`);let E;return o===on?(R.has(mt.MAX_MESSAGE_SIZE)||P("flags promise an explicit max-message-size but no extension carries it"),E=R.get(mt.MAX_MESSAGE_SIZE)):(R.has(mt.MAX_MESSAGE_SIZE)&&P("extension 0x01 present but the flags do not select it"),E=xi[o]),{version:i,type:n,setup:a,maxMessageSize:E,expiresAtMs:u,bindingTag:p,fingerprint:S,ufrag:g,pwd:I,candidates:D,commitment:_,extensions:R}}var hn=s=>s.toString(16).padStart(2,"0");function nn(s,e){switch(s){case me.HOST_MDNS:{let t=Array.from(e,hn).join("");return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}.local`}case me.HOST_V4:case me.SRFLX_V4:case me.RELAY_V4:return`${e[0]}.${e[1]}.${e[2]}.${e[3]}`;default:{let t=[];for(let i=0;i<16;i+=2)t.push((e[i]<<8|e[i+1]).toString(16));return t.join(":")}}}function Di(s,{sessionId:e="1"}={}){let t=s.type===le.OFFER,i={relay:0,srflx:1,host:2},r=s.candidates.filter(u=>u.kind!==me.HOST_MDNS&&u.tcptype===0).sort((u,p)=>i[at[u.kind]]-i[at[p.kind]])[0],n=r&&ki[r.kind]==="v6",a=r?r.port:9,o=r?`c=IN IP${n?"6":"4"} ${nn(r.kind,r.addr)}`:"c=IN IP4 0.0.0.0",c=["v=0",`o=- ${e} 2 IN IP4 127.0.0.1`,"s=-","t=0 0","a=group:BUNDLE 0","a=msid-semantic: WMS",`m=application ${a} UDP/DTLS/SCTP webrtc-datachannel`,o,"a=ice-ufrag:"+s.ufrag,"a=ice-pwd:"+s.pwd,"a=fingerprint:sha-256 "+Array.from(s.fingerprint,u=>hn(u).toUpperCase()).join(":"),"a=setup:"+an[s.setup],"a=mid:0","a=sctp-port:5000","a=max-message-size:"+s.maxMessageSize],l=s.candidates.map((u,p)=>{let S=at[u.kind],w=u.tcptype===0?"udp":"tcp",g=Math.max(0,65535-p),m=ua[S]*16777216+g*256+255,b=`a=candidate:${String(u.kind*4+u.tcptype+1)} 1 ${w} ${m} ${nn(u.kind,u.addr)} ${u.port} typ ${S}`;return S!=="host"&&(b+=ki[u.kind]==="v6"?" raddr :: rport 0":" raddr 0.0.0.0 rport 0"),w==="tcp"&&(b+=` tcptype ${Ri[u.tcptype]}`),b});l.push("a=end-of-candidates");let h=c.indexOf(o)+1;return c.splice(h,0,...l),{type:t?"offer":"answer",sdp:c.join(`\r `)+`\r `}}var Pi=new TextEncoder;function Ut(...s){let e=s.reduce((r,n)=>r+n.length,0),t=new Uint8Array(e),i=0;for(let r of s)t.set(r,i),i+=r.length;return t}async function Fi(s,e){return(await s(Ut(Pi.encode("sbq2/bind\0"),e))).slice(0,G.BINDING_BYTES)}async function zt(s,e){return(await s(Ut(Pi.encode("sbq2/blob\0"),e))).slice(0,G.COMMITMENT_BYTES)}function fn(s,e,t,i){let r=n=>{let a=new Uint8Array(4);return new DataView(a.buffer).setUint32(0,n.length),Ut(a,n)};return Ut(Pi.encode("sbq2/sas/v1\0"),r(s),r(e),r(t),r(i))}var gt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function wa(s){let e="";for(let t=0;t>2],e+=gt[(i&3)<<4|(r??0)>>4],r===void 0||(e+=gt[(r&15)<<2|(n??0)>>6],n===void 0))break;e+=gt[n&63]}return e}function Ea(s){typeof s!="string"&&P("payload must be a string");let e=s.replace(/\s+/g,"");e.length>Math.ceil(G.MAX_PAYLOAD_BYTES*4/3)+4&&P("payload is too long"),/^[A-Za-z0-9_-]*$/.test(e)||P("payload contains characters outside base64url"),e.length%4===1&&P("payload has an impossible length");let t=new Uint8Array(Math.floor(e.length*3/4)),i=0,r=0,n=0;for(let a of e)r=r<<6|gt.indexOf(a),n+=6,n>=8&&(n-=8,t[i++]=r>>n&255);return r&(1<{throw new Ni(s,e)};function gn({role:s,ecdhSpki:e,ecdsaSpki:t}){s!==be.OFFER&&s!==be.ANSWER&&de("invalid role");for(let[a,o]of[["ecdh",e],["ecdsa",t]])o instanceof Uint8Array||de(`${a} SPKI must be a Uint8Array`),(o.lengthWe.MAX_SPKI)&&de(`${a} SPKI length out of range`);let i=new Uint8Array(4+e.length+2+t.length),r=new DataView(i.buffer),n=0;return i[n++]=yn,i[n++]=s,r.setUint16(n,e.length),n+=2,i.set(e,n),n+=e.length,r.setUint16(n,t.length),n+=2,i.set(t,n),i}function mn(s){s instanceof Uint8Array||de("key blob must be a Uint8Array"),s.length===0&&de("key blob is empty"),s.length>We.MAX_BLOB_BYTES&&de("key blob exceeds the size limit");let e=new DataView(s.buffer,s.byteOffset,s.byteLength),t=0,i=h=>{t+h>s.length&&de("key blob is truncated")};i(1);let r=s[t++];r!==yn&&de(`unsupported key blob version 0x${r.toString(16)}`,"version"),i(1);let n=s[t++];n!==be.OFFER&&n!==be.ANSWER&&de("reserved key blob role"),i(2);let a=e.getUint16(t);t+=2,(aWe.MAX_SPKI)&&de("ECDH SPKI length out of range"),i(a);let o=s.slice(t,t+a);t+=a,i(2);let c=e.getUint16(t);t+=2,(cWe.MAX_SPKI)&&de("ECDSA SPKI length out of range"),i(c);let l=s.slice(t,t+c);return t+=c,t!==s.length&&de(`${s.length-t} trailing byte(s) after the key blob`),{version:r,role:n,ecdhSpki:o,ecdsaSpki:l}}function Sn({offerDescriptor:s,answerDescriptor:e,offerBlob:t,answerBlob:i}){for(let[r,n]of Object.entries({offerDescriptor:s,answerDescriptor:e,offerBlob:t,answerBlob:i}))(!(n instanceof Uint8Array)||n.length===0)&&de(`transcript component ${r} is missing`);return fn(s,e,t,i)}async function _n(s,e){let t=await s.digest("SHA-512",e);return Array.from(new Uint8Array(t))}var wn=new TextEncoder;function Oi(s){let e=wn.encode("sbq2/proof/v1\0"),t=new Uint8Array(e.length+s.length);return t.set(e,0),t.set(s,e.length),t}async function En(s,{ecdhPrivateKey:e,peerEcdhPublicKey:t,transcript:i,digits:r=7}){let n=await s.deriveBits({name:"ECDH",public:t},e,256),a=null;try{a=await s.importKey("raw",n,"HKDF",!1,["deriveBits"]);let o=new Uint8Array(await s.digest("SHA-256",i)),c=await s.deriveBits({name:"HKDF",hash:"SHA-256",salt:o,info:wn.encode("sbq2-sas-v1")},a,64),l=new DataView(c),h=(l.getUint32(0)^l.getUint32(4))>>>0,u=10**r;return String(h%u).padStart(r,"0")}finally{try{new Uint8Array(n).fill(0)}catch{}}}async function bn(s,e,t){(!(t instanceof Uint8Array)||t.length!==G.COMMITMENT_BYTES)&&de("descriptor carried no usable commitment","commitment_missing");let r=await zt(async a=>new Uint8Array(await s.digest("SHA-256",a)),e);r.length!==t.length&&de("commitment length mismatch","commitment_mismatch");let n=0;for(let a=0;a({...c}))}},this._emitGlobalEvents=o.emitGlobalEvents!==!1,this._ipLeakWarningShown=!1,this._initializeSecureLogging(),this._setupOwnLogger(),this._setupProductionLogging(),this._storeImportantMethods(),this._setupSecureGlobalAPI(),!window.EnhancedSecureCryptoUtils)throw new Error("EnhancedSecureCryptoUtils is not loaded. Please ensure the module is loaded first.");this.getSecurityData=()=>this.lastSecurityCalculation?{level:this.lastSecurityCalculation.level,score:this.lastSecurityCalculation.score,timestamp:this.lastSecurityCalculation.timestamp}:null,this._secureLog("info","\u{1F512} Enhanced WebRTC Manager initialized with secure API"),this.sessionConstraints=null,this.peerConnection=null,this.dataChannel=null,this.onMessage=e,this.onStatusChange=t,this.onKeyExchange=i,this.onVerificationStateChange=a,this.onVerificationRequired=r,this.onAnswerError=n,this.isInitiator=!1,this.connectionAttempts=0,this.maxConnectionAttempts=s.LIMITS.MAX_CONNECTION_ATTEMPTS;try{this._initializeMutexSystem()}catch(c){throw this._secureLog("error","\u274C Failed to initialize mutex system",{errorType:c.constructor.name}),new Error("Critical: Mutex system initialization failed")}if(!this._validateMutexSystem())throw this._secureLog("error","\u274C Mutex system validation failed after initialization"),new Error("Critical: Mutex system validation failed");if(typeof window<"u"&&this._secureLog("info","\u{1F512} Emergency mutex handlers will be available through secure API"),this._secureLog("info","\u{1F512} Enhanced Mutex system fully initialized and validated"),this.heartbeatInterval=null,this.messageQueue=[],this._reconnect={phase:"idle",attempts:0,startedAt:0,graceTimer:null,retryTimer:null,restartTimer:null,inFlightAt:0,barrenFailures:0,pendingRole:null},this._lastInboundAt=0,this._livenessProbeAt=0,this._livenessTimer=null,this._heartbeatTimer=null,this.ecdhKeyPair=null,this.ecdsaKeyPair=null,this.fileTransferSystem&&(this.fileTransferSystem.cleanup(),this.fileTransferSystem=null),this.verificationCode=null,this.pendingSASCode=null,this.isVerified=!1,this.sasValidationAttempts=0,this.processedMessageIds=new Set,this.localVerificationConfirmed=!1,this.remoteVerificationConfirmed=!1,this.bothVerificationsConfirmed=!1,this.expectedDTLSFingerprint=null,this._peerDTLSFingerprint=null,this.strictDTLSValidation=!0,this.ephemeralKeyPairs=new Map,this.sessionStartTime=Date.now(),this.messageCounter=0,this.sequenceNumber=0,this.expectedSequenceNumber=0,this.sessionSalt=null,this._pendingOfferContext=null,this.replayWindowSize=64,this.replayWindow=new Set,this.maxSequenceGap=100,this.replayProtectionEnabled=!0,this.sessionId=null,this._handshakeMode=null,this._sbq2=null,this.connectionId=Array.from(crypto.getRandomValues(new Uint8Array(8))).map(c=>c.toString(16).padStart(2,"0")).join(""),this.peerPublicKey=null,this._ratchet=null,this._peerSupportsRatchet=!1,this.rateLimiterId=null,this.intentionalDisconnect=!1,this._sessionAlive=!0,this._fileTransferInitRetryTimers=new Set,this._peerDisconnectCleanupTimer=null,this._logCleanupInterval=null,this.lastCleanupTime=Date.now(),this._resetNotificationFlags(),this.verificationInitiationSent=!1,this.disconnectNotificationSent=!1,this.reconnectionFailedNotificationSent=!1,this.peerDisconnectNotificationSent=!1,this.connectionClosedNotificationSent=!1,this.fakeTrafficDisabledNotificationSent=!1,this.advancedFeaturesDisabledNotificationSent=!1,this.securityUpgradeNotificationSent=!1,this.lastSecurityUpgradeStage=null,this.securityCalculationNotificationSent=!1,this.lastSecurityCalculationLevel=null,this.fileTransferSystem=null,this.onFileProgress=null,this._ivTrackingSystem={usedIVs:new Set,ivHistory:new Map,collisionCount:0,maxIVHistorySize:1e4,maxSessionIVs:1e3,entropyValidation:{minEntropy:3,entropyTests:0,entropyFailures:0},rngValidation:{testsPerformed:0,weakRngDetected:!1,lastValidation:0},sessionIVs:new Map,emergencyMode:!1},this._lastIVCleanupTime=null,this._secureErrorHandler={errorCategories:{CRYPTOGRAPHIC:"cryptographic",NETWORK:"network",VALIDATION:"validation",SYSTEM:"system",UNKNOWN:"unknown"},errorMappings:new Map,errorCounts:new Map,lastErrorTime:0,errorThreshold:10,isInErrorMode:!1},this._secureMemoryManager={sensitiveData:new WeakMap,cleanupQueue:[],isCleaning:!1,cleanupInterval:null,memoryStats:{totalCleanups:0,failedCleanups:0,lastCleanup:0}},this.onFileReceived=null,this.onFileError=null,this.onCallStateChanged=null,this.callState={active:!1,phase:"idle",withVideo:!1,micEnabled:!0,cameraEnabled:!1,remoteHasVideo:!1,callId:null,quality:null,groupCallId:null,error:null},this.localMediaStream=null,this.remoteMediaStream=null,this._pendingCallOffer=null,this._callMakingOffer=!1,this._callAudioSender=null,this._callVideoSender=null,this._callFacingMode="user",this._adaptationController=null,this._callGroupContext=null,this._externalMediaStream=null,this._callStateListeners=new Set,this.keyRotationInterval=null,this.lastKeyRotation=Date.now(),this.currentKeyVersion=0,this.keyVersions=new Map,this.oldKeys=new Map,this.maxOldKeys=s.LIMITS.MAX_OLD_KEYS,this.peerConnection=null,this.dataChannel=null,this.securityFeatures={hasEncryption:!0,hasECDH:!0,hasECDSA:!0,hasMutualAuth:!0,hasMetadataProtection:!0,hasEnhancedReplayProtection:!0,hasNonExtractableKeys:!0,hasRateLimiting:!0,hasEnhancedValidation:!0,hasPFS:!0,hasNestedEncryption:!0,hasPacketPadding:!0,hasPacketReordering:!0,hasAntiFingerprinting:!0,hasFakeTraffic:!0,hasDecoyChannels:!0,hasMessageChunking:!0},this._secureLog("info","\u{1F512} Enhanced WebRTC Manager initialized with tiered security"),this._secureLog("info","\u{1F512} Configuration loaded from constructor parameters",{fakeTraffic:this._config.fakeTraffic.enabled,decoyChannels:this._config.decoyChannels.enabled,packetPadding:this._config.packetPadding.enabled,antiFingerprinting:this._config.antiFingerprinting.enabled}),this.sessionMode="ratchet",this._hardenDebugModeReferences(),this._initializeUnifiedScheduler(),this._syncSecurityFeaturesWithTariff(),!this._validateCryptographicSecurity())throw this._secureLog("error","\u{1F6A8} CRITICAL: Cryptographic security validation failed after tariff sync"),new Error("Critical cryptographic features are missing after tariff synchronization");this.nestedEncryptionKey=null,this.paddingConfig={enabled:this._config.packetPadding.enabled,minPadding:this._config.packetPadding.minPadding,maxPadding:this._config.packetPadding.maxPadding,useRandomPadding:this._config.packetPadding.useRandomPadding,preserveMessageSize:this._config.packetPadding.preserveMessageSize},this.fakeTrafficConfig={enabled:this._config.fakeTraffic?.enabled||!1,minInterval:this._config.fakeTraffic?.minInterval||15e3,maxInterval:this._config.fakeTraffic?.maxInterval||3e4,minSize:this._config.fakeTraffic?.minSize||64,maxSize:this._config.fakeTraffic?.maxSize||1024,patterns:this._config.fakeTraffic?.patterns||["heartbeat","status","ping"],randomDecoyIntervals:this._config.fakeTraffic?.randomDecoyIntervals||!0},this.fakeTrafficTimer=null,this.lastFakeTraffic=0,this.chunkingConfig={enabled:!1,maxChunkSize:s.SIZES.CHUNK_SIZE_MAX,minDelay:s.SIZES.CHUNK_DELAY_MIN,maxDelay:s.SIZES.CHUNK_DELAY_MAX,useRandomDelays:!0,addChunkHeaders:!0},this.chunkQueue=[],this.chunkingInProgress=!1,this.decoyChannels=new Map,this.decoyChannelConfig={enabled:this._config.decoyChannels.enabled,maxDecoyChannels:this._config.decoyChannels.maxDecoyChannels,decoyChannelNames:this._config.decoyChannels.decoyChannelNames,sendDecoyData:this._config.decoyChannels.sendDecoyData,randomDecoyIntervals:this._config.decoyChannels.randomDecoyIntervals},this.decoyTimers=new Map,this.reorderingConfig={enabled:!1,maxOutOfOrder:s.LIMITS.MAX_OUT_OF_ORDER_PACKETS,reorderTimeout:s.TIMEOUTS.REORDER_TIMEOUT,useSequenceNumbers:!0,useTimestamps:!0},this.packetBuffer=new Map,this.lastProcessedSequence=-1,this.antiFingerprintingConfig={enabled:this._config.antiFingerprinting.enabled,randomizeTiming:this._config.antiFingerprinting.randomizeTiming,randomizeSizes:this._config.antiFingerprinting.randomizeSizes,addNoise:this._config.antiFingerprinting.addNoise,maskPatterns:this._config.antiFingerprinting.maskPatterns,useRandomHeaders:this._config.antiFingerprinting.useRandomHeaders},this.fingerprintMask=this.generateFingerprintMask(),this.rateLimiterId=`webrtc_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,this.startPeriodicCleanup(),this.initializeEnhancedSecurity(),this._keyOperationMutex={locked:!1,queue:[],lockId:null,lockTimeout:null},this._cryptoOperationMutex={locked:!1,queue:[],lockId:null,lockTimeout:null},this._connectionOperationMutex={locked:!1,queue:[],lockId:null,lockTimeout:null},this._keySystemState={isInitializing:!1,isRotating:!1,isDestroying:!1,lastOperation:null,lastOperationTime:Date.now()},this._operationCounters={keyOperations:0,cryptoOperations:0,connectionOperations:0}}_createMessageAAD(e,t=null,i=!1){try{let r={sessionId:this.currentSession?.sessionId||this.sessionId||"unknown",keyFingerprint:this.keyFingerprint||"unknown",sequenceNumber:this._generateNextSequenceNumber(),messageType:e,timestamp:Date.now(),connectionId:this.connectionId||"unknown",isFileMessage:i};return t&&typeof t=="object"&&(t.fileId&&(r.fileId=t.fileId),t.chunkIndex!==void 0&&(r.chunkIndex=t.chunkIndex),t.totalChunks!==void 0&&(r.totalChunks=t.totalChunks)),JSON.stringify(r)}catch(r){return this._secureLog("error","\u274C Failed to create message AAD",{errorType:r.constructor.name,message:r.message,messageType:e}),JSON.stringify({sessionId:"unknown",keyFingerprint:"unknown",sequenceNumber:Date.now(),messageType:e,timestamp:Date.now(),connectionId:"unknown",isFileMessage:i})}}_generateNextSequenceNumber(){let e=this.sequenceNumber++;return this.sequenceNumber>Number.MAX_SAFE_INTEGER-1e3&&(this.sequenceNumber=0,this.expectedSequenceNumber=0,this.replayWindow.clear(),this._secureLog("warn","\u26A0\uFE0F Sequence number reset due to overflow",{timestamp:Date.now()})),e}async _createSafeLogHash(e,t="unknown"){try{let i;if(e instanceof ArrayBuffer)i=new Uint8Array(e);else if(e instanceof Uint8Array)i=e;else if(e instanceof CryptoKey){let a=`${e.type}_${e.algorithm?.name||"unknown"}_${e.extractable}`;i=new TextEncoder().encode(a)}else if(typeof e=="string")i=new TextEncoder().encode(e);else if(typeof e=="object"&&e!==null){let a={type:e.kty||"unknown",use:e.use||"unknown"};i=new TextEncoder().encode(JSON.stringify(a))}else i=new TextEncoder().encode(String(e));let r=await crypto.subtle.digest("SHA-256",i),n=new Uint8Array(r);return Array.from(n.slice(0,4)).map(a=>a.toString(16).padStart(2,"0")).join("")}catch{return"hash_error"}}async _asyncSleep(e){return new Promise(t=>setTimeout(t,e))}async _scheduleAsyncCleanup(e,t=0){return new Promise(i=>{setTimeout(async()=>{try{await e(),i(!0)}catch(r){this._secureLog("error","Async cleanup failed",{errorType:r?.constructor?.name||"Unknown"}),i(!1)}},t)})}async _batchAsyncOperation(e,t=10,i=5){let r=[];for(let n=0;n{let r=` self.onmessage = function(e) { const { type, data } = e.data; try { switch (type) { case 'cleanup_arrays': // Simulate heavy array cleanup let processed = 0; for (let i = 0; i < data.count; i++) { // Simulate work processed++; if (processed % 1000 === 0) { // Yield control periodically setTimeout(() => {}, 0); } } self.postMessage({ success: true, processed }); break; case 'cleanup_objects': // Simulate object cleanup const cleaned = data.objects.map(() => null); self.postMessage({ success: true, cleaned: cleaned.length }); break; default: self.postMessage({ success: true, message: 'Unknown cleanup type' }); } } catch (error) { self.postMessage({ success: false, error: error.message }); } }; `,n=new Blob([r],{type:"application/javascript"}),a=new Worker(URL.createObjectURL(n)),o=setTimeout(()=>{a.terminate(),i(new Error("Worker cleanup timeout"))},5e3);a.onmessage=c=>{clearTimeout(o),a.terminate(),URL.revokeObjectURL(n),c.data.success?t(c.data):i(new Error(c.data.error))},a.onerror=c=>{clearTimeout(o),a.terminate(),URL.revokeObjectURL(n),i(c)},a.postMessage(e)})}async _cleanupInMainThread(e){let{type:t,data:i}=e;switch(t){case"cleanup_arrays":let r=0,n=100;for(;rc++),await this._asyncSleep(1);return{success:!0,cleaned:c};default:return{success:!0,message:"Unknown cleanup type"}}}_initializeMutexSystem(){this._keyOperationMutex={locked:!1,queue:[],lockId:null,lockTimeout:null,lockTime:null,operationCount:0},this._cryptoOperationMutex={locked:!1,queue:[],lockId:null,lockTimeout:null,lockTime:null,operationCount:0},this._connectionOperationMutex={locked:!1,queue:[],lockId:null,lockTimeout:null,lockTime:null,operationCount:0},this._keySystemState={isInitializing:!1,isRotating:!1,isDestroying:!1,lastOperation:null,lastOperationTime:Date.now(),operationId:null,concurrentOperations:0,maxConcurrentOperations:1},this._operationCounters={keyOperations:0,cryptoOperations:0,connectionOperations:0,totalOperations:0,failedOperations:0},this._secureLog("info","\u{1F512} Enhanced mutex system initialized with atomic protection",{mutexes:["keyOperation","cryptoOperation","connectionOperation"],timestamp:Date.now(),features:["atomic_operations","race_condition_protection","enhanced_state_tracking"]})}_hardenDebugModeReferences(){this._secureLog("info","\u{1F512} XSS Hardening: Debug mode references already replaced")}_initializeUnifiedScheduler(){this._maintenanceScheduler=setInterval(()=>{this._executeMaintenanceCycle()},3e5),this._secureLog("info","\u{1F527} Unified maintenance scheduler initialized (5-minute cycle)"),this._activeTimers=new Set([this._maintenanceScheduler])}_trackActiveTimer(e){return e&&(this._activeTimers||(this._activeTimers=new Set),this._activeTimers.add(e),e)}_untrackActiveTimer(e){e&&this._activeTimers&&this._activeTimers.delete(e)}_setSASMaterialReady(e,t){this._sasLocalFingerprint=e,this._sasRemoteFingerprint=t}_isVerificationReady(){let e=!!(this.peerConnection?.localDescription&&this.peerConnection?.remoteDescription),t=this.dataChannel?.readyState==="open",i=typeof this.verificationCode=="string"&&this.verificationCode.trim().length>0,r=typeof this._sasLocalFingerprint=="string"&&this._sasLocalFingerprint.trim().length>0&&typeof this._sasRemoteFingerprint=="string"&&this._sasRemoteFingerprint.trim().length>0;return e&&t&&i&&r}_notifyVerificationReadyIfPossible(){return this._isVerificationReady()?(this._verificationUiOpened||(this._verificationUiOpened=!0,this.onStatusChange?.("verifying"),this.onVerificationRequired?.(this.verificationCode)),!0):!1}_countIceCandidatesInSDP(e){return typeof e!="string"?0:(e.match(/^a=candidate:/gm)||[]).length}_summarizeIceCandidatesInSDP(e){let t={total:0,host:0,srflx:0,relay:0,prflx:0,unknown:0};if(typeof e!="string")return t;for(let i of e.match(/^a=candidate:.*$/gm)||[]){t.total+=1;let n=i.match(/\btyp\s+(host|srflx|relay|prflx)\b/i)?.[1]?.toLowerCase();n&&Object.prototype.hasOwnProperty.call(t,n)?t[n]+=1:t.unknown+=1}return t}_describeIceCandidatesInSDP(e){return typeof e!="string"?[]:(e.match(/^a=candidate:.*$/gm)||[]).map(t=>{let i=t.slice(12).trim().split(/\s+/),r=i.findIndex(h=>h.toLowerCase()==="typ"),n=i[4]||"",a=i[5]||"",o=r>=0&&i[r+1]||"unknown",c=(i[2]||"unknown").toLowerCase(),l="unknown";return/\.local$/i.test(n)?l="mdns":/^(10\.|192\.168\.|172\.(1[6-9]|2\d|3[0-1])\.)/.test(n)?l="private-ipv4":/^\d{1,3}(\.\d{1,3}){3}$/.test(n)?l="public-ipv4":n.includes(":")&&(l="ipv6"),{candidateType:o,protocol:c,addressKind:l,portPresent:!!a,tcpType:(()=>{let h=i.findIndex(u=>u.toLowerCase()==="tcptype");return h>=0&&i[h+1]||null})()}})}_logIceCandidateDiagnostics(e,t,i={}){let r=this._summarizeIceCandidatesInSDP(t),n=this._describeIceCandidatesInSDP(t);return console.info(`[SecureBit ICE] ${e}`,{candidateSummary:r,candidateDetails:n,candidateDetailsJson:JSON.stringify(n),...i}),{candidateSummary:r,candidateDetails:n}}_hasOnlyMdnsHostCandidates(e){let t=this._summarizeIceCandidatesInSDP(e),i=this._describeIceCandidatesInSDP(e);return t.total>0&&t.srflx===0&&t.relay===0&&t.prflx===0&&i.every(r=>r.candidateType==="host"&&r.addressKind==="mdns")}_warnIfRemoteCandidatesNeedRelay(e,t){if(!this._hasOnlyMdnsHostCandidates(t))return!1;let i=e==="answer"?"Connection warning: the response contains only browser-masked mDNS host candidates and no server-reflexive or TURN relay candidates. This network/browser combination may not connect until TURN is configured.":"Connection warning: the invitation contains only browser-masked mDNS host candidates and no server-reflexive or TURN relay candidates. This network/browser combination may not connect until TURN is configured.";return this._secureLog("warn","Remote ICE candidates require TURN or usable non-mDNS candidates",{context:e,candidateSummary:this._summarizeIceCandidatesInSDP(t),candidateDetails:this._describeIceCandidatesInSDP(t)}),this.deliverMessageToUI(i,"system"),!0}async _collectIceFailureDiagnostics(){if(!this.peerConnection?.getStats)return null;try{let e=await this.peerConnection.getStats(),t=new Map,i=[];return e.forEach(r=>{(r.type==="local-candidate"||r.type==="remote-candidate")&&t.set(r.id,{type:r.type,candidateType:r.candidateType,protocol:r.protocol,address:r.address||r.ip||null,port:r.port||null,networkType:r.networkType||null})}),e.forEach(r=>{r.type==="candidate-pair"&&i.push({state:r.state,nominated:!!r.nominated,writable:!!r.writable,bytesSent:r.bytesSent||0,bytesReceived:r.bytesReceived||0,currentRoundTripTime:r.currentRoundTripTime??null,local:t.get(r.localCandidateId)||null,remote:t.get(r.remoteCandidateId)||null})}),{pairCount:i.length,states:i.reduce((r,n)=>(r[n.state||"unknown"]=(r[n.state||"unknown"]||0)+1,r),{}),pairs:i}}catch(e){return{error:e?.message||"Failed to collect ICE diagnostics"}}}_storePendingOfferContext(){this._pendingOfferContext={sessionSalt:Array.isArray(this.sessionSalt)?[...this.sessionSalt]:null,sessionId:this.sessionId||null,connectionId:this.connectionId||null,keyFingerprint:this.keyFingerprint||null,createdAt:Date.now()}}_restorePendingOfferContextIfNeeded(){if(Array.isArray(this.sessionSalt)&&this.sessionSalt.length===64)return!0;let t=this._pendingOfferContext?.sessionSalt;return!Array.isArray(t)||t.length!==64?!1:(this.sessionSalt=[...t],!this.sessionId&&this._pendingOfferContext.sessionId&&(this.sessionId=this._pendingOfferContext.sessionId),!this.connectionId&&this._pendingOfferContext.connectionId&&(this.connectionId=this._pendingOfferContext.connectionId),!this.keyFingerprint&&this._pendingOfferContext.keyFingerprint&&(this.keyFingerprint=this._pendingOfferContext.keyFingerprint),this._secureLog("warn","Restored pending offer context before applying answer",{pendingContextAgeMs:Date.now()-(this._pendingOfferContext.createdAt||Date.now())}),!0)}_clearPendingOfferContext(){this._pendingOfferContext?.sessionSalt&&this._secureWipeMemory(this._pendingOfferContext.sessionSalt,"pendingOfferContext.sessionSalt"),this._pendingOfferContext=null}_executeMaintenanceCycle(){try{this._secureLog("info","\u{1F527} Starting maintenance cycle"),this._cleanupLogs(),this._auditLoggingSystemSecurity(),this._verifyAPIIntegrity(),this._validateCryptographicSecurity(),this._syncSecurityFeaturesWithTariff(),this._cleanupResources(),this._enforceResourceLimits(),this.isConnected&&this.isVerified&&this._monitorKeySecurity(),this._debugMode&&this._monitorGlobalExposure(),this._secureLog("info","\u{1F527} Maintenance cycle completed successfully")}catch(e){this._secureLog("error","\u274C Maintenance cycle failed",{errorType:e?.constructor?.name||"Unknown",message:e?.message||"Unknown error"}),this._emergencyCleanup().catch(t=>{this._secureLog("error","Emergency cleanup failed",{errorType:t?.constructor?.name||"Unknown"})})}}_enforceResourceLimits(){let e=[];this._logCounts.size>this._resourceLimits.maxLogEntries&&e.push("log_entries"),this.messageQueue.length>this._resourceLimits.maxMessageQueue&&e.push("message_queue"),this._ivTrackingSystem&&this._ivTrackingSystem.ivHistory.size>this._resourceLimits.maxIVHistory&&e.push("iv_history"),this.processedMessageIds.size>this._resourceLimits.maxProcessedMessageIds&&e.push("processed_message_ids"),this.decoyChannels.size>this._resourceLimits.maxDecoyChannels&&e.push("decoy_channels"),this._fakeTrafficMessages&&this._fakeTrafficMessages.length>this._resourceLimits.maxFakeTrafficMessages&&e.push("fake_traffic_messages"),this.chunkQueue.length>this._resourceLimits.maxChunkQueue&&e.push("chunk_queue"),this.packetBuffer&&this.packetBuffer.size>this._resourceLimits.maxPacketBuffer&&e.push("packet_buffer"),e.length>0&&(this._secureLog("warn","\u26A0\uFE0F Resource limit violations detected",{violations:e}),this._emergencyCleanup().catch(t=>{this._secureLog("error","Emergency cleanup failed",{errorType:t?.constructor?.name||"Unknown"})}))}async _emergencyCleanup(){this._secureLog("warn","\u{1F6A8} EMERGENCY: Resource limits exceeded, performing emergency cleanup");try{if(this._logCounts.clear(),this._secureLog("info","\u{1F9F9} Emergency: All logs cleared"),this.messageQueue.length=0,this._secureLog("info","\u{1F9F9} Emergency: Message queue cleared"),this._ivTrackingSystem&&(this._ivTrackingSystem.usedIVs.clear(),this._ivTrackingSystem.ivHistory.clear(),this._ivTrackingSystem.sessionIVs.clear(),this._ivTrackingSystem.collisionCount=0,this._ivTrackingSystem.emergencyMode=!1,this._secureLog("info","\u{1F9F9} Enhanced Emergency: IV tracking system cleared")),this.processedMessageIds.clear(),this._secureLog("info","\u{1F9F9} Emergency: Processed message IDs cleared"),this.decoyChannels){for(let[e,t]of this.decoyTimers)t&&clearTimeout(t);this.decoyChannels.clear(),this.decoyTimers.clear(),this._secureLog("info","\u{1F9F9} Enhanced Emergency: Decoy channels cleared")}this.fakeTrafficTimer&&(clearTimeout(this.fakeTrafficTimer),this.fakeTrafficTimer=null),this._fakeTrafficMessages&&(this._fakeTrafficMessages.length=0,this._secureLog("info","\u{1F9F9} Enhanced Emergency: Fake traffic messages cleared")),this.chunkQueue.length=0,this._secureLog("info","\u{1F9F9} Emergency: Chunk queue cleared"),this.packetBuffer&&(this.packetBuffer.clear(),this._secureLog("info","\u{1F9F9} Emergency: Packet buffer cleared")),this._secureMemoryManager.isCleaning=!0,this._secureMemoryManager.cleanupQueue.length=0,this._secureMemoryManager.memoryStats.lastCleanup=Date.now(),await this._scheduleAsyncCleanup(async()=>{this._secureLog("info","\u{1F9F9} Enhanced Emergency: Starting natural memory cleanup");for(let e=0;e<3;e++)this._secureLog("info",`\u{1F9F9} Enhanced Emergency: Cleanup cycle ${e+1}/3`),await this._performNaturalCleanup();this._secureLog("info","\u{1F9F9} Enhanced Emergency: Natural cleanup completed")},0),this._secureMemoryManager.isCleaning=!1,this._secureLog("info","\u2705 Enhanced emergency cleanup completed successfully")}catch(e){this._secureLog("error","\u274C Enhanced emergency cleanup failed",{errorType:e?.constructor?.name||"Unknown",message:e?.message||"Unknown error"}),this._secureMemoryManager.isCleaning=!1}}_validateEmergencyCleanup(e){let t={messageQueueSize:this.messageQueue.length,processedIdsSize:this.processedMessageIds.size,packetBufferSize:this.packetBuffer?this.packetBuffer.size:0,ivTrackingSize:this._ivTrackingSystem?this._ivTrackingSystem.usedIVs.size:0,decoyChannelsSize:this.decoyChannels?this.decoyChannels.size:0};return{messageQueueCleared:t.messageQueueSize===0,processedIdsCleared:t.processedIdsSize===0,packetBufferCleared:t.packetBufferSize===0,ivTrackingCleared:t.ivTrackingSize===0,decoyChannelsCleared:t.decoyChannelsSize===0,allCleared:t.messageQueueSize===0&&t.processedIdsSize===0&&t.packetBufferSize===0&&t.ivTrackingSize===0&&t.decoyChannelsSize===0}}_cleanupResources(){let e=Date.now();this.processedMessageIds.size>this._emergencyThresholds.processedMessageIds&&(this.processedMessageIds.clear(),this._secureLog("info","\u{1F9F9} Old processed message IDs cleared")),this._ivTrackingSystem&&this._cleanupOldIVs(),this.cleanupOldKeys(),window.EnhancedSecureCryptoUtils&&window.EnhancedSecureCryptoUtils.rateLimiter&&window.EnhancedSecureCryptoUtils.rateLimiter.cleanup(),this._secureLog("info","\u{1F9F9} Resource cleanup completed")}_monitorKeySecurity(){this._keyStorageStats.activeKeys>10&&this._secureLog("warn","\u26A0\uFE0F High number of active keys detected. Consider rotation.")}_sendHeartbeat(e=!1){try{return this.dataChannel&&this.dataChannel.readyState==="open"?(this.dataChannel.send(JSON.stringify({type:s.MESSAGE_TYPES.HEARTBEAT,ack:e,timestamp:Date.now()})),this._heartbeatConfig.lastHeartbeat=Date.now(),this._secureLog("debug",e?"\u{1F493} Heartbeat ack sent":"\u{1F493} Heartbeat sent"),!0):!1}catch(t){return this._secureLog("error","\u274C Heartbeat failed:",{errorType:t?.constructor?.name||"Unknown",message:t?.message||"Unknown error"}),!1}}_validateInputData(e,t="unknown"){let i={isValid:!1,sanitizedData:null,errors:[],warnings:[]};try{if(e==null)return i.errors.push("Data cannot be null or undefined"),i;if(typeof e=="string")return e.length>this._inputValidationLimits.maxStringLength?(i.errors.push(`String too long: ${e.length} > ${this._inputValidationLimits.maxStringLength}`),i):(i.sanitizedData=this._sanitizeInputString(e),i.isValid=!0,i);if(typeof e=="object"){let r=new WeakSet,n=(o,c="")=>{if(!(o===null||typeof o!="object")){if(r.has(o)){i.errors.push(`Circular reference detected at path: ${c}`);return}if(r.add(o),c.split(".").length>this._inputValidationLimits.maxObjectDepth){i.errors.push(`Object too deep: ${c.split(".").length} > ${this._inputValidationLimits.maxObjectDepth}`);return}if(Array.isArray(o)&&o.length>this._inputValidationLimits.maxArrayLength){i.errors.push(`Array too long: ${o.length} > ${this._inputValidationLimits.maxArrayLength}`);return}for(let l in o)o.hasOwnProperty(l)&&n(o[l],c?`${c}.${l}`:l)}};if(n(e),i.errors.length>0)return i;let a=this._calculateObjectSize(e);return a>this._inputValidationLimits.maxMessageSize?(i.errors.push(`Object too large: ${a} bytes > ${this._inputValidationLimits.maxMessageSize} bytes`),i):(i.sanitizedData=this._sanitizeInputObject(e),i.isValid=!0,i)}return e instanceof ArrayBuffer?e.byteLength>this._inputValidationLimits.maxMessageSize?(i.errors.push(`ArrayBuffer too large: ${e.byteLength} bytes > ${this._inputValidationLimits.maxMessageSize} bytes`),i):(i.sanitizedData=e,i.isValid=!0,i):(i.errors.push(`Unsupported data type: ${typeof e}`),i)}catch(r){return i.errors.push(`Validation error: ${r.message}`),this._secureLog("error","\u274C Input validation failed",{context:t,errorType:r?.constructor?.name||"Unknown",message:r?.message||"Unknown error"}),i}}_calculateObjectSize(e){try{let t=JSON.stringify(e);return new TextEncoder().encode(t).length}catch{return 1024*1024}}_sanitizeInputString(e){return typeof e!="string"||(e=e.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g,""),e=e.replace(/\r\n?/g,` `),e=e.replace(/\n{3,}/g,` `),e=e.trim()),e}_sanitizeInputObject(e){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(i=>this._sanitizeInputObject(i));let t={};for(let i in e)if(e.hasOwnProperty(i)){let r=e[i];typeof r=="string"?t[i]=this._sanitizeInputString(r):typeof r=="object"?t[i]=this._sanitizeInputObject(r):t[i]=r}return t}_checkRateLimit(e="message"){let t=Date.now();return this._rateLimiter||(this._rateLimiter={messageCount:0,lastReset:t,burstCount:0,lastBurstReset:t}),t-this._rateLimiter.lastReset>6e4&&(this._rateLimiter.messageCount=0,this._rateLimiter.lastReset=t),t-this._rateLimiter.lastBurstReset>1e3&&(this._rateLimiter.burstCount=0,this._rateLimiter.lastBurstReset=t),this._rateLimiter.burstCount>=this._inputValidationLimits.rateLimitBurstSize?(this._secureLog("warn","\u26A0\uFE0F Rate limit burst exceeded",{context:e}),!1):this._rateLimiter.messageCount>=this._inputValidationLimits.rateLimitMessagesPerMinute?(this._secureLog("warn","\u26A0\uFE0F Rate limit exceeded",{context:e}),!1):(this._rateLimiter.messageCount++,this._rateLimiter.burstCount++,!0)}_checkInboundRateLimit(e="incoming_message"){let t=Date.now();return this._inboundRateLimiter||(this._inboundRateLimiter={messageCount:0,lastReset:t,burstCount:0,lastBurstReset:t}),t-this._inboundRateLimiter.lastReset>6e4&&(this._inboundRateLimiter.messageCount=0,this._inboundRateLimiter.lastReset=t),t-this._inboundRateLimiter.lastBurstReset>1e3&&(this._inboundRateLimiter.burstCount=0,this._inboundRateLimiter.lastBurstReset=t),this._inboundRateLimiter.burstCount>=this._inputValidationLimits.rateLimitBurstSize?(this._secureLog("warn","\u26A0\uFE0F Inbound message burst limit exceeded; dropping message",{context:e}),!1):this._inboundRateLimiter.messageCount>=this._inputValidationLimits.rateLimitMessagesPerMinute?(this._secureLog("warn","\u26A0\uFE0F Inbound message rate limit exceeded; dropping message",{context:e}),!1):(this._inboundRateLimiter.messageCount++,this._inboundRateLimiter.burstCount++,!0)}_initializeSecureKeyStorage(){this._masterKeyManager=new $t,this._secureKeyStorage=new Bt(this._masterKeyManager),this._keyStorageStats={totalKeys:0,activeKeys:0,lastAccess:null,lastRotation:null},this._secureLog("info","\u{1F510} Enhanced secure key storage initialized")}setMasterKeyPasswordCallback(e){this._masterKeyManager&&this._masterKeyManager.setPasswordRequiredCallback(e)}setMasterKeySessionExpiredCallback(e){this._masterKeyManager&&this._masterKeyManager.setSessionExpiredCallback(e)}lockMasterKey(){this._masterKeyManager&&this._masterKeyManager.lock()}isMasterKeyUnlocked(){return this._masterKeyManager?this._masterKeyManager.isUnlocked():!1}getMasterKeySessionStatus(){return this._masterKeyManager?this._masterKeyManager.getSessionStatus():null}async _ensureFileTransferReady(){try{if(this.fileTransferSystem)return!0;if(!this.dataChannel||this.dataChannel.readyState!=="open")throw new Error("Data channel not open");if(!this.isVerified)throw new Error("Connection not verified");this.initializeFileTransfer();let e=0,t=50;for(;!this.fileTransferSystem&&esetTimeout(i,100)),e++;if(!this.fileTransferSystem)throw new Error("File transfer system initialization timeout");return!0}catch(e){return this._secureLog("error","\u274C _ensureFileTransferReady failed",{errorType:e?.constructor?.name||"Unknown",hasMessage:!!e?.message}),!1}}_getSecureKey(e){return this._secureKeyStorage.retrieveKey(e)}async _setSecureKey(e,t){if(!(t instanceof CryptoKey))return this._secureLog("error","\u274C Attempt to store non-CryptoKey"),!1;let i=await this._secureKeyStorage.storeKey(e,t,{version:this.currentKeyVersion,type:t.algorithm.name});return i&&this._secureLog("info",`\u{1F511} Key ${e} stored securely with encryption`),i}_validateKeyValue(e){return e instanceof CryptoKey&&e.algorithm&&e.usages&&e.usages.length>0}_secureWipeKeys(){this._secureKeyStorage.secureWipeAll(),this._masterKeyManager&&this._masterKeyManager.lock(),this._secureLog("info","\u{1F9F9} All keys securely wiped and encrypted storage cleared")}_validateKeyStorage(){return this._secureKeyStorage instanceof Bt}_getKeyStorageStats(){let e=this._secureKeyStorage.getStorageStats();return{totalKeysCount:e.totalKeys,activeKeysCount:e.totalKeys,hasLastAccess:e.metadata.some(t=>t.lastAccessed),hasLastRotation:!!this._keyStorageStats.lastRotation,storageType:"SecureKeyStorage",timestamp:Date.now()}}_rotateKeys(){let e=Array.from(this._secureKeyStorage.keys());this._secureKeyStorage.clear(),this._keyStorageStats.lastRotation=Date.now(),this._keyStorageStats.activeKeys=0,this._secureLog("info",`\u{1F504} Key rotation completed. ${e.length} keys rotated`)}_emergencyKeyWipe(){this._secureWipeKeys(),this._secureLog("error","\u{1F6A8} EMERGENCY: All keys wiped due to security threat")}_startKeySecurityMonitoring(){this._secureLog("info","\u{1F527} Key security monitoring moved to unified scheduler")}_validateKeyConstantTime(e){let t=0;try{let i=e instanceof CryptoKey;t+=i?1:0}catch{t+=0}try{let i=!!(e&&e.algorithm);t+=i?1:0}catch{t+=0}try{let i=!!(e&&e.type);t+=i?1:0}catch{t+=0}try{let i=e&&e.extractable!==void 0;t+=i?1:0}catch{t+=0}return t===4}_validateKeyPairConstantTime(e){if(!e||typeof e!="object")return!1;let t=this._validateKeyConstantTime(e.privateKey),i=this._validateKeyConstantTime(e.publicKey);return t&&i}_initializeSecureLogging(){this._logLevels={error:0,warn:1,info:2,debug:3,trace:4},this._currentLogLevel=this._isProductionMode?this._logLevels.error:this._logLevels.info,this._logCounts=new Map,this._maxLogCount=this._isProductionMode?5:50,this._resourceLimits={maxLogEntries:this._isProductionMode?100:1e3,maxMessageQueue:1e3,maxIVHistory:1e4,maxProcessedMessageIds:5e3,maxDecoyChannels:100,maxFakeTrafficMessages:500,maxChunkQueue:200,maxPacketBuffer:1e3},this._emergencyThresholds={logEntries:this._resourceLimits.maxLogEntries*.8,messageQueue:this._resourceLimits.maxMessageQueue*.8,ivHistory:this._resourceLimits.maxIVHistory*.8,processedMessageIds:this._resourceLimits.maxProcessedMessageIds*.8},this._inputValidationLimits={maxStringLength:1e5,maxObjectDepth:10,maxArrayLength:1e3,maxMessageSize:1024*1024,maxConcurrentMessages:10,rateLimitMessagesPerMinute:60,rateLimitBurstSize:10},this._absoluteBlacklist=new Set(["encryptionKey","macKey","metadataKey","privateKey","publicKey","ecdhKeyPair","ecdsaKeyPair","peerPublicKey","nestedEncryptionKey","verificationCode","sessionSalt","keyFingerprint","sessionId","authChallenge","authProof","authToken","sessionToken","password","token","secret","credential","signature","apiKey","accessKey","secretKey","privateKey","hash","digest","nonce","iv","cipher","seed","entropy","random","salt","fingerprint","jwt","bearer","refreshToken","accessToken","fileHash","fileSignature","transferKey","chunkKey"]),this._safeFieldsWhitelist=new Set(["timestamp","type","status","state","level","isConnected","isVerified","isInitiator","version","count","total","active","inactive","success","failure","readyState","connectionState","iceConnectionState","activeFeaturesCount","totalFeatures","stage","errorType","errorCode","phase","attempt"]),this._initializeLogSecurityMonitoring(),this._secureLog("info",`\u{1F527} Enhanced secure logging initialized (Production: ${this._isProductionMode})`)}_initializeLogSecurityMonitoring(){this._logSecurityViolations=0,this._maxLogSecurityViolations=3}_auditLoggingSystemSecurity(){let e=0;for(let[i,r]of this._logCounts.entries())r>this._maxLogCount*2&&(e++,this._originalConsole?.error?.(`\u{1F6A8} LOG SECURITY: Excessive log count detected: ${i}`));let t=Array.from(this._logCounts.keys());for(let i of t)this._containsSensitiveContent(i)&&(e++,this._originalConsole?.error?.(`\u{1F6A8} LOG SECURITY: Sensitive content in log key: ${i}`));this._logSecurityViolations+=e,this._logSecurityViolations>=this._maxLogSecurityViolations&&(this._emergencyDisableLogging(),this._originalConsole?.error?.("\u{1F6A8} CRITICAL: Logging system disabled due to security violations"))}_secureLogShim(...e){try{if(!Array.isArray(e)||e.length===0)return;let t=e[0],i=e.slice(1);if(i.length===0){this._secureLog("info",String(t||""));return}if(i.length===1){this._secureLog("info",String(t||""),i[0]);return}this._secureLog("info",String(t||""),{additionalArgs:i,argCount:i.length})}catch{try{this._originalConsole?.log&&this._originalConsole.log(...e)}catch{}}}_setupOwnLogger(){this.logger={log:(e,t)=>this._secureLog("info",e,t),info:(e,t)=>this._secureLog("info",e,t),warn:(e,t)=>this._secureLog("warn",e,t),error:(e,t)=>this._secureLog("error",e,t),debug:(e,t)=>this._secureLog("debug",e,t)},s.DEBUG_MODE?this._secureLog("info","\u{1F512} Own logger created - development mode"):this._secureLog("info","\u{1F512} Own logger created - production mode")}_setupProductionLogging(){this._isProductionMode&&(this.logger={log:()=>{},info:()=>{},warn:(e,t)=>this._secureLog("warn",e,t),error:(e,t)=>this._secureLog("error",e,t),debug:()=>{}},this._secureLog("info","Production logging mode activated"))}_secureLog(e,t,i=null){if(i&&!this._auditLogMessage(t,i)){this._originalConsole?.error?.("SECURITY: Logging blocked due to potential data leakage");return}if(this._logLevels[e]>this._currentLogLevel)return;let r=`${e}:${t.substring(0,50)}`,n=this._logCounts.get(r)||0;if(n>=this._maxLogCount)return;this._logCounts.set(r,n+1);let a=null;if(i&&(a=this._sanitizeLogData(i),this._containsSensitiveContent(JSON.stringify(a)))){this._originalConsole?.error?.("ECURITY: Sanitized data still contains sensitive content - blocking log");return}if(this._isProductionMode){if(e==="error"){let c=this._sanitizeString(t);this._originalConsole?.error?.(c)}return}let o=this._originalConsole?.[e]||this._originalConsole?.log;a?o(t,a):o(t)}_sanitizeLogData(e){if(typeof e=="string")return this._sanitizeString(e);if(!e||typeof e!="object")return e;let t={};for(let[r,n]of Object.entries(e)){let a=r.toLowerCase(),o=["key","secret","token","password","credential","auth","fingerprint","salt","signature","private","encryption","mac","metadata","session","jwt","bearer","hash","digest","nonce","iv","cipher","seed","entropy"];if(this._absoluteBlacklist.has(r)||o.some(l=>a.includes(l))){t[r]="[SENSITIVE_DATA_BLOCKED]";continue}if(this._safeFieldsWhitelist.has(r)){typeof n=="string"?t[r]=this._sanitizeString(n):t[r]=n;continue}if(typeof n=="boolean"||typeof n=="number")t[r]=n;else if(typeof n=="string")t[r]=this._sanitizeString(n);else if(n instanceof ArrayBuffer||n instanceof Uint8Array)t[r]=`[${n.constructor.name}( bytes)]`;else if(n&&typeof n=="object")try{t[r]=this._sanitizeLogData(n)}catch{t[r]="[RECURSIVE_SANITIZATION_FAILED]"}else t[r]=`[${typeof n}]`}let i=JSON.stringify(t);return this._containsSensitiveContent(i)?{error:"SANITIZATION_FAILED_SENSITIVE_CONTENT_DETECTED"}:t}_sanitizeString(e){if(typeof e!="string"||e.length===0)return e;let t=[/[a-f0-9]{16,}/i,/[a-f0-9]{8,}/i,/[A-Za-z0-9+/]{16,}={0,2}/,/[A-Za-z0-9+/]{12,}/,/[A-Za-z0-9+/=]{10,}/,/[1-9A-HJ-NP-Za-km-z]{16,}/,/[A-Z2-7]{16,}={0,6}/,/[A-Z2-7]{12,}/,/[A-Za-z0-9\-_]{16,}/,/[A-Za-z0-9\.\-_]{16,}/,/\b[A-Za-z0-9]{12,}\b/,/\b[A-Za-z0-9]{8,}\b/,/BEGIN\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\s+KEY/i,/END\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\s+KEY/i,/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/,/(api[_-]?key|token|secret|password|credential)[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i,/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i,/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/,/\b\d{3}-\d{2}-\d{4}\b/,/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/,/(fingerprint|hash|digest|signature)[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i,/(encryption|mac|metadata)[\s]*key[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i,/(session|auth|jwt|bearer)[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i];for(let i of t)if(i.test(e))return"[SENSITIVE_DATA_REDACTED]";return this._hasHighEntropy(e)?"[HIGH_ENTROPY_DATA_REDACTED]":this._hasSuspiciousDistribution(e)?"[SUSPICIOUS_DATA_REDACTED]":e.length>50?e.substring(0,20)+"...[TRUNCATED]":e}_containsSensitiveContent(e){return typeof e!="string"?!1:[/[a-f0-9]{16,}/i,/[A-Za-z0-9+/]{16,}={0,2}/,/[1-9A-HJ-NP-Za-km-z]{16,}/,/[A-Z2-7]{16,}={0,6}/,/\b[A-Za-z0-9]{12,}\b/,/BEGIN\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\s+KEY/i,/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/,/(api[_-]?key|token|secret|password|credential)[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i].some(i=>i.test(e))||this._hasHighEntropy(e)||this._hasSuspiciousDistribution(e)}_hasHighEntropy(e){if(e.length<8)return!1;let t={};for(let n of e)t[n]=(t[n]||0)+1;let i=e.length,r=0;for(let n of Object.values(t)){let a=n/i;r-=a*Math.log2(a)}return r>4.5}_hasSuspiciousDistribution(e){return e.length<8?!1:(e.match(/[a-f0-9]/gi)||[]).length>=e.length*.8||(e.match(/[A-Za-z0-9+/=]/g)||[]).length>=e.length*.9||new Set(e).size/e.length>.8&&e.length>16}_detectProductionMode(){return typeof process<"u"&&!0||!this._debugMode||window.location.hostname&&!window.location.hostname.includes("localhost")&&!window.location.hostname.includes("127.0.0.1")&&!window.location.hostname.includes(".local")||typeof window.webpackHotUpdate>"u"&&!window.location.search.includes("debug")}_setupSecureGlobalAPI(){this._secureLog("info","Starting secure global API setup");let e={};typeof this.sendMessage=="function"&&(e.sendMessage=this.sendMessage.bind(this)),e.getConnectionStatus=()=>({isConnected:this.isConnected?this.isConnected():!1,isVerified:this.isVerified||!1,connectionState:this.peerConnection?.connectionState||"disconnected"}),e.getSecurityStatus=()=>({securityLevel:"maximum",stage:"initialized",activeFeaturesCount:Object.values(this.securityFeatures||{}).filter(Boolean).length}),typeof this.sendFile=="function"&&(e.sendFile=this.sendFile.bind(this)),e.getFileTransferStatus=()=>({initialized:!!this.fileTransferSystem,status:"ready",activeTransfers:0,receivingTransfers:0}),typeof this.disconnect=="function"&&(e.disconnect=this.disconnect.bind(this));let t={...e,getConfiguration:()=>({fakeTraffic:this._config.fakeTraffic.enabled,decoyChannels:this._config.decoyChannels.enabled,packetPadding:this._config.packetPadding.enabled,antiFingerprinting:this._config.antiFingerprinting.enabled}),emergency:{}};typeof this._emergencyUnlockAllMutexes=="function"&&(t.emergency.unlockAllMutexes=this._emergencyUnlockAllMutexes.bind(this)),typeof this._emergencyRecoverMutexSystem=="function"&&(t.emergency.recoverMutexSystem=this._emergencyRecoverMutexSystem.bind(this)),typeof this._emergencyDisableLogging=="function"&&(t.emergency.disableLogging=this._emergencyDisableLogging.bind(this)),typeof this._resetLoggingSystem=="function"&&(t.emergency.resetLogging=this._resetLoggingSystem.bind(this)),t.getFileTransferSystemStatus=()=>({initialized:!!this.fileTransferSystem,status:"ready",activeTransfers:0,receivingTransfers:0}),this._secureLog("info","API methods available",{sendMessage:!!e.sendMessage,getConnectionStatus:!!e.getConnectionStatus,getSecurityStatus:!!e.getSecurityStatus,sendFile:!!e.sendFile,getFileTransferStatus:!!e.getFileTransferStatus,disconnect:!!e.disconnect,getConfiguration:!!t.getConfiguration,emergencyMethods:Object.keys(t.emergency).length}),Object.freeze(t),Object.freeze(t.emergency),this._createProtectedGlobalAPI(t),this._setupMinimalGlobalProtection(),this._secureLog("info","Secure global API setup completed successfully")}_createProtectedGlobalAPI(e){this._secureLog("info","Creating protected global API"),window.secureBitChat?this._secureLog("warn","\u26A0\uFE0F Global API already exists, skipping setup"):this._exportAPI(e)}_exportAPI(e){this._secureLog("info","Exporting API to window.secureBitChat"),!this._importantMethods||!this._importantMethods.defineProperty?(this._secureLog("error","\u274C Important methods not available for API export, using fallback"),Object.defineProperty(window,"secureBitChat",{value:e,writable:!1,configurable:!1,enumerable:!0})):this._importantMethods.defineProperty(window,"secureBitChat",{value:e,writable:!1,configurable:!1,enumerable:!0}),this._secureLog("info","\u{1F512} Secure API exported to window.secureBitChat")}_setupMinimalGlobalProtection(){this._protectGlobalAPI(),this._secureLog("info","\u{1F512} Minimal global protection activated")}_storeImportantMethods(){this._importantMethods={defineProperty:Object.defineProperty,getOwnPropertyDescriptor:Object.getOwnPropertyDescriptor,freeze:Object.freeze,consoleLog:console.log,consoleError:console.error,consoleWarn:console.warn},this._secureLog("info","\u{1F512} Important methods stored locally",{defineProperty:!!this._importantMethods.defineProperty,getOwnPropertyDescriptor:!!this._importantMethods.getOwnPropertyDescriptor,freeze:!!this._importantMethods.freeze})}_setupSimpleProtection(){this._secureLog("info","\u{1F512} Simple protection activated - no monitoring")}_preventGlobalExposure(){this._secureLog("info","\u{1F512} No global exposure prevention - using secure API export only")}_verifyAPIIntegrity(){try{if(!window.secureBitChat)return this._secureLog("error","\u274C SECURITY ALERT: Secure API has been removed!"),!1;let t=["sendMessage","getConnectionStatus","disconnect"].filter(i=>typeof window.secureBitChat[i]!="function");return t.length>0?(this._secureLog("error","\u274C SECURITY ALERT: API tampering detected, missing methods:",{errorType:t?.constructor?.name||"Unknown"}),!1):!0}catch(e){return this._secureLog("error","\u274C SECURITY ALERT: API integrity check failed:",{errorType:e?.constructor?.name||"Unknown"}),!1}}_auditGlobalExposure(){return this._secureLog("info","\u{1F512} Global exposure check completed at initialization"),[]}_startSecurityAudit(){this._secureLog("info","\u{1F512} Security audit completed at initialization - no periodic monitoring")}_protectGlobalAPI(){if(!window.secureBitChat){this._secureLog("warn","\u26A0\uFE0F Global API not found during protection setup");return}try{this._validateAPIIntegrityOnce()&&this._secureLog("info","\u{1F512} Global API protection verified")}catch(e){this._secureLog("error","\u274C Failed to verify global API protection",{errorType:e.constructor.name,errorMessage:e.message})}}_validateAPIIntegrityOnce(){try{if(!this._importantMethods||!this._importantMethods.getOwnPropertyDescriptor){let e=Object.getOwnPropertyDescriptor(window,"secureBitChat");if(!e||e.configurable)throw new Error("secureBitChat must not be reconfigurable!")}else{let e=this._importantMethods.getOwnPropertyDescriptor(window,"secureBitChat");if(!e||e.configurable)throw new Error("secureBitChat must not be reconfigurable!")}return this._secureLog("info","\u2705 API integrity validated"),!0}catch(e){return this._secureLog("error","\u274C API integrity validation failed",{errorType:e.constructor.name,errorMessage:e.message}),!1}}_secureWipeMemory(e,t="unknown"){if(e)try{e instanceof ArrayBuffer?this._secureWipeArrayBuffer(e,t):e instanceof Uint8Array?this._secureWipeUint8Array(e,t):Array.isArray(e)?this._secureWipeArray(e,t):typeof e=="string"?this._secureWipeString(e,t):e instanceof CryptoKey?this._secureWipeCryptoKey(e,t):typeof e=="object"&&this._secureWipeObject(e,t),this._secureMemoryManager.memoryStats.totalCleanups++}catch(i){this._secureMemoryManager.memoryStats.failedCleanups++,this._secureLog("error","\u274C Secure memory wipe failed",{context:t,errorType:i.constructor.name,errorMessage:i.message})}}_secureWipeArrayBuffer(e,t){if(!(!e||e.byteLength===0))try{let i=new Uint8Array(e);crypto.getRandomValues(i),i.fill(0),i.fill(255),i.fill(0),this._secureLog("debug","\u{1F512} ArrayBuffer securely wiped",{context:t,size:e.byteLength})}catch(i){this._secureLog("error","\u274C Failed to wipe ArrayBuffer",{context:t,errorType:i.constructor.name})}}_secureWipeUint8Array(e,t){if(!(!e||e.length===0))try{crypto.getRandomValues(e),e.fill(0),e.fill(255),e.fill(0),this._secureLog("debug","\u{1F512} Uint8Array securely wiped",{context:t,size:e.length})}catch(i){this._secureLog("error","\u274C Failed to wipe Uint8Array",{context:t,errorType:i.constructor.name})}}_secureWipeArray(e,t){if(!(!Array.isArray(e)||e.length===0))try{e.forEach((i,r)=>{i!=null&&this._secureWipeMemory(i,`${t}[${r}]`)}),e.fill(null),this._secureLog("debug","\u{1F512} Array securely wiped",{context:t,size:e.length})}catch(i){this._secureLog("error","\u274C Failed to wipe array",{context:t,errorType:i.constructor.name})}}_secureWipeString(e,t){return this._secureLog("debug","String secret cannot be wiped in JS (immutable) \u2014 reference dropped only",{context:t,length:e?e.length:0}),!1}_secureWipeCryptoKey(e,t){return!e||!(e instanceof CryptoKey)||(this._secureLog("debug","CryptoKey cannot be wiped from JS \u2014 handle dropped, material is non-extractable",{context:t,type:e.type,extractable:e.extractable}),e.extractable&&this._secureLog("error","Extractable key reached the wipe path \u2014 material may persist in memory",{context:t})),!1}_secureWipeObject(e,t){if(!(!e||typeof e!="object"))try{for(let[i,r]of Object.entries(e))r!=null&&this._secureWipeMemory(r,`${t}.${i}`),e[i]=null;this._secureLog("debug","\u{1F512} Object securely wiped",{context:t,properties:Object.keys(e).length})}catch(i){this._secureLog("error","\u274C Failed to wipe object",{context:t,errorType:i.constructor.name})}}_secureCleanupCryptographicMaterials(){try{if(this.ecdhKeyPair&&(this._secureWipeMemory(this.ecdhKeyPair,"ecdhKeyPair"),this.ecdhKeyPair=null),this.ecdsaKeyPair&&(this._secureWipeMemory(this.ecdsaKeyPair,"ecdsaKeyPair"),this.ecdsaKeyPair=null),this.encryptionKey&&(this._secureWipeMemory(this.encryptionKey,"encryptionKey"),this.encryptionKey=null),this.macKey&&(this._secureWipeMemory(this.macKey,"macKey"),this.macKey=null),this.metadataKey&&(this._secureWipeMemory(this.metadataKey,"metadataKey"),this.metadataKey=null),this.nestedEncryptionKey&&(this._secureWipeMemory(this.nestedEncryptionKey,"nestedEncryptionKey"),this.nestedEncryptionKey=null),this.sessionSalt&&(this._secureWipeMemory(this.sessionSalt,"sessionSalt"),this.sessionSalt=null),this.sessionId&&(this._secureWipeMemory(this.sessionId,"sessionId"),this.sessionId=null),this.verificationCode&&(this._secureWipeMemory(this.verificationCode,"verificationCode"),this.verificationCode=null),this.peerPublicKey&&(this._secureWipeMemory(this.peerPublicKey,"peerPublicKey"),this.peerPublicKey=null),this.keyFingerprint&&(this._secureWipeMemory(this.keyFingerprint,"keyFingerprint"),this.keyFingerprint=null),this.connectionId&&(this._secureWipeMemory(this.connectionId,"connectionId"),this.connectionId=null),this._clearPendingOfferContext(),this._ratchet){try{this._ratchet.destroy()}catch{}this._ratchet=null}this._peerSupportsRatchet=!1,this._secureLog("info","\u{1F512} Cryptographic materials securely cleaned up")}catch(e){this._secureLog("error","\u274C Failed to cleanup cryptographic materials",{errorType:e.constructor.name,errorMessage:e.message})}}async _forceGarbageCollection(){try{await this._performNaturalCleanup(),this._secureLog("debug","\u{1F512} Natural memory cleanup performed")}catch(e){this._secureLog("error","\u274C Failed to perform natural cleanup",{errorType:e.constructor.name})}}async _performPeriodicMemoryCleanup(){try{this._secureMemoryManager.isCleaning=!0;let e=this.sessionMode==="ratchet"&&this.isConnected&&this.dataChannel&&this.dataChannel.readyState==="open",t=this._pendingOfferContext?Date.now()-(this._pendingOfferContext.createdAt||0):1/0,i=!!this._pendingOfferContext&&Array.isArray(this._pendingOfferContext.sessionSalt)&&this._pendingOfferContext.sessionSalt.length===64&&t100&&this.messageQueue.splice(0,this.messageQueue.length-50).forEach((a,o)=>{this._secureWipeMemory(a,`periodicCleanup[${o}]`)}),this.processedMessageIds&&this.processedMessageIds.size>1e3&&this.processedMessageIds.clear(),await this._forceGarbageCollection(),this._secureLog("debug","\u{1F512} Periodic memory cleanup completed")}catch(e){this._secureLog("error","\u274C Error during periodic memory cleanup",{errorType:e.constructor.name,errorMessage:e.message})}finally{this._secureMemoryManager.isCleaning=!1}}_createSecureErrorMessage(e,t="unknown"){try{let i=this._categorizeError(e),r=this._getSafeErrorMessage(i,t);return this._secureLog("error","Internal error occurred",{category:i,context:t,errorType:e?.constructor?.name||"Unknown",timestamp:Date.now()}),this._trackErrorFrequency(i),r}catch(i){return this._secureLog("error","Error handling failed",{originalError:e?.message||"Unknown",handlingError:i.message}),"An unexpected error occurred"}}_categorizeError(e){if(!e||!e.message)return this._secureErrorHandler.errorCategories.UNKNOWN;let t=e.message.toLowerCase();return t.includes("crypto")||t.includes("key")||t.includes("encrypt")||t.includes("decrypt")||t.includes("sign")||t.includes("verify")||t.includes("ecdh")||t.includes("ecdsa")?this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC:t.includes("network")||t.includes("connection")||t.includes("timeout")||t.includes("webrtc")||t.includes("peer")?this._secureErrorHandler.errorCategories.NETWORK:t.includes("invalid")||t.includes("validation")||t.includes("format")||t.includes("type")?this._secureErrorHandler.errorCategories.VALIDATION:t.includes("system")||t.includes("internal")||t.includes("memory")||t.includes("resource")?this._secureErrorHandler.errorCategories.SYSTEM:this._secureErrorHandler.errorCategories.UNKNOWN}_getSafeErrorMessage(e,t){let i={[this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC]:{key_generation:"Security initialization failed",key_import:"Security verification failed",key_derivation:"Security setup failed",encryption:"Message security failed",decryption:"Message verification failed",signature:"Authentication failed",default:"Security operation failed"},[this._secureErrorHandler.errorCategories.NETWORK]:{connection:"Connection failed",timeout:"Connection timeout",peer:"Peer connection failed",webrtc:"Communication failed",default:"Network operation failed"},[this._secureErrorHandler.errorCategories.VALIDATION]:{format:"Invalid data format",type:"Invalid data type",structure:"Invalid data structure",default:"Validation failed"},[this._secureErrorHandler.errorCategories.SYSTEM]:{memory:"System resource error",resource:"System resource unavailable",internal:"Internal system error",default:"System operation failed"},[this._secureErrorHandler.errorCategories.UNKNOWN]:{default:"An unexpected error occurred"}},r=i[e]||i[this._secureErrorHandler.errorCategories.UNKNOWN],n="default";return t.includes("key")||t.includes("crypto")?n=e===this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC?"key_generation":"default":t.includes("connection")||t.includes("peer")?n=e===this._secureErrorHandler.errorCategories.NETWORK?"connection":"default":(t.includes("validation")||t.includes("format"))&&(n=e===this._secureErrorHandler.errorCategories.VALIDATION?"format":"default"),r[n]||r.default}_trackErrorFrequency(e){let t=Date.now();t-this._secureErrorHandler.lastErrorTime>6e4&&this._secureErrorHandler.errorCounts.clear();let i=this._secureErrorHandler.errorCounts.get(e)||0;this._secureErrorHandler.errorCounts.set(e,i+1),this._secureErrorHandler.lastErrorTime=t;let r=Array.from(this._secureErrorHandler.errorCounts.values()).reduce((n,a)=>n+a,0);r>this._secureErrorHandler.errorThreshold&&(this._secureErrorHandler.isInErrorMode=!0,this._secureLog("warn","\u26A0\uFE0F High error frequency detected - entering error mode",{totalErrors:r,threshold:this._secureErrorHandler.errorThreshold}))}_throwSecureError(e,t="unknown"){let i=this._createSecureErrorMessage(e,t);throw new Error(i)}_getErrorHandlingStats(){return{errorCounts:Object.fromEntries(this._secureErrorHandler.errorCounts),isInErrorMode:this._secureErrorHandler.isInErrorMode,lastErrorTime:this._secureErrorHandler.lastErrorTime,errorThreshold:this._secureErrorHandler.errorThreshold}}_resetErrorHandlingSystem(){this._secureErrorHandler.errorCounts.clear(),this._secureErrorHandler.isInErrorMode=!1,this._secureErrorHandler.lastErrorTime=0,this._secureLog("info","\u{1F504} Error handling system reset")}_getMemoryManagementStats(){return{totalCleanups:this._secureMemoryManager.memoryStats.totalCleanups,failedCleanups:this._secureMemoryManager.memoryStats.failedCleanups,lastCleanup:this._secureMemoryManager.memoryStats.lastCleanup,isCleaning:this._secureMemoryManager.isCleaning,queueLength:this._secureMemoryManager.cleanupQueue.length}}_validateAPIIntegrity(){try{if(!window.secureBitChat)return this._secureLog("error","\u274C Global API not found during integrity validation"),!1;let e=["sendMessage","getConnectionStatus","getSecurityStatus","sendFile","disconnect"],t=e.filter(a=>!window.secureBitChat[a]||typeof window.secureBitChat[a]!="function");if(t.length>0)return this._secureLog("error","\u274C Global API integrity validation failed - missing methods",{missingMethods:t}),!1;let i={test:!0},n=e.map(a=>{try{return window.secureBitChat[a].bind(i)}catch{return null}}).filter(a=>a===null);if(n.length>0)return this._secureLog("error","\u274C Global API integrity validation failed - method binding issues",{unboundMethods:n.length}),!1;try{let a="_integrity_test_"+Date.now();return Object.defineProperty(window.secureBitChat,a,{value:"test",writable:!0,configurable:!0}),this._secureLog("error","\u274C Global API integrity validation failed - API is mutable"),delete window.secureBitChat[a],!1}catch{this._secureLog("debug","\u2705 Global API immutability verified")}return this._secureLog("info","\u2705 Global API integrity validation passed"),!0}catch(e){return this._secureLog("error","\u274C Global API integrity validation failed",{errorType:e.constructor.name,errorMessage:e.message}),!1}}_validateCryptographicSecurity(){let e=["hasRateLimiting"],t=e.filter(n=>!this.securityFeatures[n]);t.length>0&&(this._secureLog("error","\u{1F6A8} CRITICAL: Missing critical rate limiting feature",{missing:t,currentFeatures:this.securityFeatures,action:"Rate limiting will be forced enabled"}),t.forEach(n=>{this.securityFeatures[n]=!0,this._secureLog("warn",`\u26A0\uFE0F Forced enable critical: ${n} = true`)}));let i=Object.keys(this.securityFeatures).filter(n=>this.securityFeatures[n]),r=["hasEncryption","hasECDH","hasECDSA"].filter(n=>this.securityFeatures[n]);return this._secureLog("info","\u2705 Cryptographic security validation passed",{criticalFeatures:e.length,availableFeatures:i.length,encryptionFeatures:r.length,totalSecurityFeatures:i.length,note:"Encryption features will be enabled after key generation",currentState:{hasEncryption:this.securityFeatures.hasEncryption,hasECDH:this.securityFeatures.hasECDH,hasECDSA:this.securityFeatures.hasECDSA,hasRateLimiting:this.securityFeatures.hasRateLimiting}}),!0}_syncSecurityFeaturesWithTariff(){this._secureLog("info","\u2705 All security features enabled by default - no payment required"),["hasEncryption","hasECDH","hasECDSA","hasMutualAuth","hasMetadataProtection","hasEnhancedReplayProtection","hasNonExtractableKeys","hasRateLimiting","hasEnhancedValidation","hasPFS","hasNestedEncryption","hasPacketPadding","hasPacketReordering","hasAntiFingerprinting","hasFakeTraffic","hasDecoyChannels","hasMessageChunking"].forEach(t=>{this.securityFeatures[t]=!0}),this._secureLog("info","\u2705 All security features enabled by default",{enabledFeatures:Object.keys(this.securityFeatures).filter(t=>this.securityFeatures[t]).length,totalFeatures:Object.keys(this.securityFeatures).length})}_emergencyShutdown(e="Security breach"){this._secureLog("error","\u274C EMERGENCY SHUTDOWN: ${reason}");try{this.encryptionKey=null,this.macKey=null,this.metadataKey=null,this.verificationCode=null,this.keyFingerprint=null,this.connectionId=null,this.dataChannel&&(this.dataChannel.close(),this.dataChannel=null),this.peerConnection&&(this.peerConnection.close(),this.peerConnection=null),this.messageQueue=[],this.processedMessageIds.clear(),this.packetBuffer.clear(),this.onStatusChange&&this.onStatusChange("security_breach"),this._secureLog("info","\u{1F512} Emergency shutdown completed")}catch(t){this._secureLog("error","\u274C Error during emergency shutdown:",{errorType:t?.constructor?.name||"Unknown"})}}_finalizeSecureInitialization(){if(this._startKeySecurityMonitoring(),!this._verifyAPIIntegrity()){this._secureLog("error","\u274C Security initialization failed");return}this._startSecurityMonitoring(),this._logCleanupInterval=this._trackActiveTimer(setInterval(()=>{this._cleanupLogs()},3e5)),this._secureLog("info","\u2705 Secure WebRTC Manager initialization completed"),this._secureLog("info","\u{1F512} Global exposure protection: Monitoring only, no automatic removal")}_startSecurityMonitoring(){this._secureLog("info","\u{1F527} Security monitoring moved to unified scheduler")}_validateConnection(e=!0){let t=this.dataChannel&&this.dataChannel.readyState==="open",i=this.isVerified,r=t&&i;if(!r&&e){if(!t)throw new Error("Data channel not ready");if(!i)throw new Error("Connection not verified")}return r}_enforceVerificationGate(e="unknown",t=!0){if(!this.isVerified){let i=`SECURITY VIOLATION: ${e} blocked - connection not cryptographically verified`;if(this._secureLog("error",i,{operation:e,isVerified:this.isVerified,hasKeys:!!(this.encryptionKey&&this.macKey),timestamp:Date.now()}),t)throw new Error(i);return!1}return!0}_setVerifiedStatus(e,t="unknown",i=null){if(e){if(!this.encryptionKey||!this.macKey)throw new Error("Cannot set verified=true without encryption keys");if(!t||t==="unknown")throw new Error("Cannot set verified=true without specifying verification method");if(t.includes("SAS")&&!this.localVerificationConfirmed)throw this._secureLog("error","Blocked verified transition without local SAS confirmation",{verificationMethod:t,localConfirmed:this.localVerificationConfirmed,remoteConfirmed:this.remoteVerificationConfirmed}),new Error("Cannot set verified=true without local SAS confirmation");this._secureLog("info","Connection verified through cryptographic verification",{verificationMethod:t,hasEncryptionKey:!!this.encryptionKey,hasMacKey:!!this.macKey,keyFingerprint:this.keyFingerprint,timestamp:Date.now(),verificationData:i?"provided":"none"})}this.isVerified=e,e?this.onStatusChange("connected"):this.onStatusChange("disconnected")}markGroupLinkVerified(e="group_roster_signature"){let t=this._sbq2;if(!this._isSbq2()||!t||!t.completed||!t.proofVerified||!t.keysDerived)throw new Error("Group link cannot be released: the in-band handshake has not completed");if(!this.encryptionKey||!this.macKey)throw new Error("Group link cannot be released: session keys are missing");if(this.isVerified)return!0;this.localVerificationConfirmed=!0,this.remoteVerificationConfirmed=!0,this.bothVerificationsConfirmed=!0,this._setVerifiedStatus(!0,"GROUP_ROSTER_SIGNATURE",{reason:e,timestamp:Date.now()}),this._enforceVerificationGate("group_link_release",!1),this.onStatusChange?.("verified");try{this.processMessageQueue()}catch{}return!0}_createFileMessageAAD(e,t=null){if(typeof this._createMessageAAD!="function")throw new Error("_createMessageAAD method is not available in _createFileMessageAAD. Manager may not be fully initialized.");return this._createMessageAAD(e,t,!0)}_validateFileMessageAAD(e,t=null){try{let i=JSON.parse(e);if(i.sessionId!==(this.currentSession?.sessionId||"unknown"))throw new Error("AAD sessionId mismatch - possible replay attack");if(i.keyFingerprint!==(this.keyFingerprint||"unknown"))throw new Error("AAD keyFingerprint mismatch - possible key substitution attack");if(t&&i.messageType!==t)throw new Error(`AAD messageType mismatch - expected ${t}, got ${i.messageType}`);if(Date.now()-i.timestamp>18e5)throw new Error("AAD timestamp too old - possible replay attack");return i}catch(i){throw this._secureLog("error","AAD validation failed",{error:i.message,aadLength:typeof e=="string"?e.length:0}),new Error(`AAD validation failed: ${i.message}`)}}_validateIncomingSequenceNumber(e,t="unknown"){try{if(!this.replayProtectionEnabled)return!0;if(typeof e!="number"||!Number.isFinite(e))return this._secureLog("warn","Missing or non-numeric sequence number - rejecting",{receivedType:typeof e,context:t,timestamp:Date.now()}),!1;if(ethis.expectedSequenceNumber+this.maxSequenceGap)return this._secureLog("warn","Sequence number gap too large - possible DoS attack",{received:e,expected:this.expectedSequenceNumber,gap:e-this.expectedSequenceNumber,context:t,timestamp:Date.now()}),!1;if(this.replayWindow.has(e))return this._secureLog("warn","Duplicate sequence number detected - replay attack",{received:e,context:t,timestamp:Date.now()}),!1;if(this.replayWindow.add(e),this.replayWindow.size>this.replayWindowSize){let i=Math.min(...this.replayWindow);this.replayWindow.delete(i)}if(e===this.expectedSequenceNumber)for(this.expectedSequenceNumber++;this.replayWindow.has(this.expectedSequenceNumber-this.replayWindowSize-1);)this.replayWindow.delete(this.expectedSequenceNumber-this.replayWindowSize-1);return this._secureLog("debug","Sequence number validation successful",{received:e,expected:this.expectedSequenceNumber,context:t,timestamp:Date.now()}),!0}catch(i){return this._secureLog("error","Sequence number validation failed",{error:i.message,context:t,timestamp:Date.now()}),!1}}_validateMessageAAD(e,t=null){try{let i=JSON.parse(e);if(i.sessionId!==(this.currentSession?.sessionId||"unknown"))throw new Error("AAD sessionId mismatch - possible replay attack");if(i.keyFingerprint!==(this.keyFingerprint||"unknown"))throw new Error("AAD keyFingerprint mismatch - possible key substitution attack");if(!this._validateIncomingSequenceNumber(i.sequenceNumber,i.messageType))throw new Error("Sequence number validation failed - possible replay or DoS attack");if(t&&i.messageType!==t)throw new Error(`AAD messageType mismatch - expected ${t}, got ${i.messageType}`);return i}catch(i){throw this._secureLog("error","AAD validation failed",{error:i.message,aadLength:typeof e=="string"?e.length:0}),new Error(`AAD validation failed: ${i.message}`)}}getAntiReplayStatus(){let e={replayProtectionEnabled:this.replayProtectionEnabled,replayWindowSize:this.replayWindowSize,currentReplayWindowSize:this.replayWindow.size,sequenceNumber:this.sequenceNumber,expectedSequenceNumber:this.expectedSequenceNumber,maxSequenceGap:this.maxSequenceGap,replayWindowEntries:Array.from(this.replayWindow).sort((t,i)=>t-i)};return this._secureLog("info","Anti-replay status retrieved",e),e}configureAntiReplayProtection(e){try{if(e.windowSize!==void 0){if(e.windowSize<16||e.windowSize>1024)throw new Error("Replay window size must be between 16 and 1024");this.replayWindowSize=e.windowSize}if(e.maxGap!==void 0){if(e.maxGap<10||e.maxGap>1e3)throw new Error("Max sequence gap must be between 10 and 1000");this.maxSequenceGap=e.maxGap}return e.enabled!==void 0&&(this.replayProtectionEnabled=e.enabled),this._secureLog("info","Anti-replay protection configured",e),!0}catch(t){return this._secureLog("error","Failed to configure anti-replay protection",{error:t.message}),!1}}async getRealSecurityLevel(){try{let e={ecdhKeyExchange:!!this.ecdhKeyPair,ecdsaSignatures:!!this.ecdsaKeyPair,aesEncryption:!!this.encryptionKey,messageIntegrity:!!this.hmacKey,replayProtection:this.replayProtectionEnabled,dtlsFingerprint:!!(this.expectedDTLSFingerprint&&this._peerDTLSFingerprint),sasCode:!!this.verificationCode&&this.localVerificationConfirmed===!0,metadataProtection:!0,trafficObfuscation:!0,perfectForwardSecrecy:this.isRatchetActive?.()===!0,rateLimiter:!0,connectionId:this.connectionId,keyFingerprint:this.keyFingerprint,currentSecurityLevel:"maximum",timestamp:Date.now()},t=await this.calculateAndReportSecurityLevel();return t?{...t,...e}:{...e,level:"INITIALIZING",score:0,isRealData:!1}}catch(e){throw this._secureLog("error","Failed to calculate real security level",{error:e.message}),e}}_extractDTLSFingerprintFromSDP(e){try{if(!e||typeof e!="string")throw new Error("Invalid SDP provided");let t=/a=fingerprint:([a-zA-Z0-9-]+)\s+([A-Fa-f0-9:]+)/g,i=[],r;for(;(r=t.exec(e))!==null;)i.push({algorithm:r[1].toLowerCase(),fingerprint:r[2].trim()});if(i.length===0){let a=/fingerprint\s*=\s*([a-zA-Z0-9-]+)\s+([A-Fa-f0-9:]+)/gi;for(;(r=a.exec(e))!==null;)i.push({algorithm:r[1].toLowerCase(),fingerprint:r[2].trim()})}if(i.length===0)throw this._secureLog("warn","No DTLS fingerprints found in SDP - this may be normal for some WebRTC implementations",{sdpLength:e.length,sdpPreview:e.substring(0,200)+"..."}),new Error("No DTLS fingerprints found in SDP");return[...i].sort((a,o)=>{let c=a.algorithm==="sha-256",l=o.algorithm==="sha-256";if(c!==l)return c?-1:1;let h=a.algorithm.localeCompare(o.algorithm);return h!==0?h:a.fingerprint.localeCompare(o.fingerprint)})[0].fingerprint}catch(t){throw this._secureLog("error","Failed to extract DTLS fingerprint from SDP",{error:t.message,sdpLength:e?.length||0}),new Error(`DTLS fingerprint extraction failed: ${t.message}`)}}async _validateDTLSFingerprint(e,t,i="unknown"){try{if(!e||!t)throw new Error("Missing fingerprint for validation");let r=e.toLowerCase().replace(/:/g,""),n=t.toLowerCase().replace(/:/g,"");if(r!==n)throw this._secureLog("error","DTLS fingerprint mismatch - possible MITM attack",{context:i,timestamp:Date.now()}),new Error(`DTLS fingerprint mismatch - possible MITM attack in ${i}`);return this._secureLog("info","DTLS fingerprint validation successful",{context:i,timestamp:Date.now()}),!0}catch(r){throw this._secureLog("error","DTLS fingerprint validation failed",{error:r.message,context:i}),r}}async _computeSAS(e,t,i){try{if(!e){let m=[];throw e||m.push("keyMaterialRaw"),new Error(`Missing required parameters for SAS computation: ${m.join(", ")}`)}let r=new TextEncoder,n=(m,I)=>{if(typeof m!="string"||m.trim().length===0)throw new Error(`Security error: ${I} must be a non-empty DTLS fingerprint string for SAS computation`);return m.trim().toLowerCase()},a=n(t,"localFP"),o=n(i,"remoteFP"),c=r.encode("webrtc-sas|"+[a,o].sort().join("|")),l;if(e instanceof ArrayBuffer)l=e;else if(e instanceof Uint8Array)l=e.buffer;else if(typeof e=="string"){let m=e.replace(/:/g,"").replace(/\s/g,""),I=new Uint8Array(m.length/2);for(let b=0;b>>0,g=String(w%1e7).padStart(7,"0");return this._secureLog("info","SAS code computed successfully",{localFP:a.substring(0,16)+"...",remoteFP:o.substring(0,16)+"...",sasLength:g.length,timestamp:Date.now()}),g}catch(r){throw this._secureLog("error","SAS computation failed",{error:r.message,keyMaterialType:typeof e,hasLocalFP:!!t,hasRemoteFP:!!i,timestamp:Date.now()}),new Error(`SAS computation failed: ${r.message}`)}}_dispatchAppEvent(e){if(!this._emitGlobalEvents)return!1;try{return document.dispatchEvent(e)}catch{return!1}}_isSbq2(){return this._handshakeMode==="sbq2"}_latchHandshakeMode(e){if(this._handshakeMode&&this._handshakeMode!==e)throw new Error(`handshake format cannot change mid-session (${this._handshakeMode} -> ${e})`);this._handshakeMode=e}_sbq2State(){return this._sbq2||(this._sbq2={role:null,localDescriptor:null,remoteDescriptor:null,localBlob:null,remoteBlob:null,remoteCommitment:null,transcript:null,peerEcdhKey:null,peerEcdsaKey:null,blobSent:!1,proofSent:!1,proofVerified:!1,keysDerived:!1,pendingProof:null,completed:!1,timer:null,startedAt:0}),this._sbq2}_sbq2Abort(e,t){let i=this._sbq2;i?.timer&&(clearTimeout(i.timer),i.timer=null),this._secureLog("error","SBQ2 handshake aborted",{code:e});try{this.deliverMessageToUI(t,"system")}catch{}try{this.onStatusChange?.("failed")}catch{}try{this.disconnect()}catch{}}async _exportSpki(e){return new Uint8Array(await crypto.subtle.exportKey("spki",e))}async _sbq2BuildLocalBlob(e){if(!this.ecdhKeyPair?.publicKey||!this.ecdsaKeyPair?.publicKey)throw new Error("SBQ2: key pairs are not ready");let t=gn({role:e,ecdhSpki:await this._exportSpki(this.ecdhKeyPair.publicKey),ecdsaSpki:await this._exportSpki(this.ecdsaKeyPair.publicKey)}),r=await zt(async a=>new Uint8Array(await crypto.subtle.digest("SHA-256",a)),t),n=this._sbq2State();return n.role=e,n.localBlob=t,{blob:t,commitment:r}}async _sbq2BuildDescriptor(e,{bindingTag:t=null,lifetimeMs:i=600*1e3}={}){let r=this.peerConnection?.localDescription?.sdp;if(!r)throw new Error("SBQ2: no local description to encode");let n=e===le.OFFER?be.OFFER:be.ANSWER,{commitment:a}=await this._sbq2BuildLocalBlob(n),o=dn(r),c=un({type:e,expiresAtMs:Date.now()+i,sdpFields:{...o,candidates:Mi(o.candidates)},commitment:a,...e===le.ANSWER?{bindingTag:t}:{}}),l=this._sbq2State();return l.localDescriptor=c,this._secureLog("info","SBQ2 descriptor built",{type:e===le.OFFER?"offer":"answer",bytes:c.length,candidates:Mi(o.candidates).length}),{bytes:c,text:pn(c)}}_sbq2AdoptRemoteDescriptor(e,t){let i=Li(e);if(i.type!==t)throw new Error(`expected an ${t===le.OFFER?"invitation":"answer"}, got the other kind`);if(!i.commitment)throw new Error("the invitation carries no key commitment");let r=this._sbq2State();return r.remoteDescriptor=e,r.remoteCommitment=i.commitment,i}async _runSbq2KeyExchange(){let e=this._sbq2State();if(!(e.completed||e.blobSent)){if(e.startedAt=Date.now(),!e.localBlob||!e.localDescriptor||!e.remoteDescriptor||!e.remoteCommitment){this._sbq2Abort("incomplete_state","The secure handshake could not start because the connection setup is incomplete. Please start a new invitation.");return}e.timer=setTimeout(()=>{e.completed||this._sbq2Abort("timeout","The other side did not complete the secure handshake in time. Please try connecting again.")},s.SBQ2_KEY_EXCHANGE_TIMEOUT_MS);try{this.dataChannel.send(JSON.stringify({type:s.MESSAGE_TYPES.KEY_BLOB,v:2,blob:window.EnhancedSecureCryptoUtils.arrayBufferToBase64(e.localBlob.buffer.slice(e.localBlob.byteOffset,e.localBlob.byteOffset+e.localBlob.byteLength))})),e.blobSent=!0,this._secureLog("info","SBQ2 key blob sent",{bytes:e.localBlob.length})}catch{this._sbq2Abort("blob_send_failed","The secure handshake could not be sent. Please try connecting again.")}}}async _sbq2HandleHandshakeFrame(e){let t=s.MESSAGE_TYPES,i=this._sbq2State();if(!this._isSbq2()){this._secureLog("error","Rejected SBQ2 handshake frame on a non-SBQ2 session",{messageType:e?.type});return}try{if(e.type===t.KEY_BLOB){if(i.remoteBlob){this._sbq2Abort("duplicate_blob","The secure handshake was sent twice. The connection has been closed for safety.");return}let r=new Uint8Array(window.EnhancedSecureCryptoUtils.base64ToArrayBuffer(String(e.blob||"")));await bn(crypto.subtle,r,i.remoteCommitment);let n=mn(r),a=i.role===be.OFFER?be.ANSWER:be.OFFER;if(n.role!==a){this._sbq2Abort("role_mismatch","The other side sent the wrong kind of handshake. The connection has been closed for safety.");return}i.remoteBlob=r,i.peerEcdhKey=await crypto.subtle.importKey("spki",n.ecdhSpki,{name:"ECDH",namedCurve:"P-384"},!1,[]),i.peerEcdsaKey=await crypto.subtle.importKey("spki",n.ecdsaSpki,{name:"ECDSA",namedCurve:"P-384"},!1,["verify"]),await this._sbq2CompleteExchange();return}if(e.type===t.KEY_PROOF){let r=new Uint8Array(window.EnhancedSecureCryptoUtils.base64ToArrayBuffer(String(e.sig||"")));if(!i.transcript||!i.peerEcdsaKey){i.pendingProof=r;return}await this._sbq2VerifyProof(r);return}}catch(r){let n=r?.code||"handshake_failed",a=n==="commitment_mismatch"?"The key material does not match the invitation you scanned. This can mean someone tampered with the connection, so it has been closed.":"The secure handshake failed. The connection has been closed for safety.";this._sbq2Abort(n,a)}}async _sbq2CompleteExchange(){let e=this._sbq2State();if(e.keysDerived||!e.remoteBlob||!e.localBlob)return;this._peerSupportsRatchet=!0;let t=e.role===be.OFFER;e.transcript=Sn({offerDescriptor:t?e.localDescriptor:e.remoteDescriptor,answerDescriptor:t?e.remoteDescriptor:e.localDescriptor,offerBlob:t?e.localBlob:e.remoteBlob,answerBlob:t?e.remoteBlob:e.localBlob}),this.sessionSalt=await _n(crypto.subtle,e.transcript),this.peerPublicKey=e.peerEcdhKey,this.peerECDHPublicKey=e.peerEcdhKey;let i=await window.EnhancedSecureCryptoUtils.deriveSharedKeys(this.ecdhKeyPair.privateKey,e.peerEcdhKey,this.sessionSalt);await this._setEncryptionKeys(i.messageKey,i.macKey,i.metadataKey,i.fingerprint),await this._initializeRatchet(i,t),e.keysDerived=!0;let r=new Uint8Array(await crypto.subtle.sign({name:"ECDSA",hash:"SHA-384"},this.ecdsaKeyPair.privateKey,Oi(e.transcript)));if(this.dataChannel.send(JSON.stringify({type:s.MESSAGE_TYPES.KEY_PROOF,sig:window.EnhancedSecureCryptoUtils.arrayBufferToBase64(r.buffer)})),e.proofSent=!0,e.pendingProof){let n=e.pendingProof;e.pendingProof=null,await this._sbq2VerifyProof(n)}}async _sbq2VerifyProof(e){let t=this._sbq2State();if(t.proofVerified)return;if(!await crypto.subtle.verify({name:"ECDSA",hash:"SHA-384"},t.peerEcdsaKey,e,Oi(t.transcript))){this._sbq2Abort("bad_proof","The other side could not prove it owns its identity key. The connection has been closed for safety.");return}t.proofVerified=!0,this.verificationCode=await En(crypto.subtle,{ecdhPrivateKey:this.ecdhKeyPair.privateKey,peerEcdhPublicKey:t.peerEcdhKey,transcript:t.transcript});let r=this.expectedDTLSFingerprint,n=this._peerDTLSFingerprint;r&&n&&this._setSASMaterialReady(r,n),t.completed=!0,t.timer&&(clearTimeout(t.timer),t.timer=null),this.securityFeatures.hasMutualAuth=!0,this.securityFeatures.hasMetadataProtection=!0,this.securityFeatures.hasEnhancedReplayProtection=!0,this._secureLog("info","SBQ2 in-band key exchange complete",{elapsedMs:Date.now()-t.startedAt,ratchetActive:this.isRatchetActive?.()===!0});try{this.onKeyExchange?.(this.keyFingerprint)}catch{}this._notifyVerificationReadyIfPossible(),this.initiateVerification()}_decodeKeyFingerprint(e){try{if(!e||typeof e!="string")throw new Error("Invalid hex string provided");return window.EnhancedSecureCryptoUtils.hexToUint8Array(e)}catch(t){throw this._secureLog("error","Key fingerprint decoding failed",{error:t.message,inputType:typeof e,inputLength:e?.length||0}),new Error(`Key fingerprint decoding failed: ${t.message}`)}}_emergencyWipeOnFingerprintMismatch(e="DTLS fingerprint mismatch"){try{this._secureLog("error","\u{1F6A8} EMERGENCY: Initiating security wipe due to fingerprint mismatch",{reason:e,timestamp:Date.now()}),this._secureWipeKeys(),this._secureWipeMemory(this.encryptionKey,"emergency_wipe"),this._secureWipeMemory(this.macKey,"emergency_wipe"),this._secureWipeMemory(this.metadataKey,"emergency_wipe"),this._wipeEphemeralKeys(),this._hardWipeOldKeys(),this.isVerified=null,this.verificationCode=null,this.keyFingerprint=null,this.connectionId=null,this.expectedDTLSFingerprint=null,this._peerDTLSFingerprint=null,this.disconnect(),this.deliverMessageToUI("\u{1F6A8} SECURITY BREACH: Connection terminated due to fingerprint mismatch. Possible MITM attack detected!","system")}catch(t){this._secureLog("error","Failed to perform emergency wipe",{error:t.message})}}getCurrentDTLSFingerprint(){try{if(!this.expectedDTLSFingerprint)throw new Error("No DTLS fingerprint available - connection not established");return this.expectedDTLSFingerprint}catch(e){throw this._secureLog("error","Failed to get current DTLS fingerprint",{error:e.message}),e}}disableStrictDTLSValidation(){this.strictDTLSValidation=!1,this._secureLog("warn","\u26A0\uFE0F Strict DTLS validation disabled - security reduced",{timestamp:Date.now()}),this.deliverMessageToUI("\u26A0\uFE0F DTLS validation disabled for debugging","system")}enableStrictDTLSValidation(){this.strictDTLSValidation=!0,this._secureLog("info","\u2705 Strict DTLS validation re-enabled",{timestamp:Date.now()}),this.deliverMessageToUI("\u2705 DTLS validation re-enabled","system")}async _initializeRatchet(e,t){let i=e?.ratchetRoot;if(!i)return!1;if(!this._peerSupportsRatchet)return this._secureLog("warn","Peer did not advertise Double Ratchet \u2014 falling back to static session keys",{localVersion:s.RATCHET_VERSION}),window.EnhancedSecureCryptoUtils.zeroizeBuffer(i),!1;try{let r=this.peerPublicKey||this.peerECDHPublicKey;if(!r||!this.ecdhKeyPair?.privateKey)throw new Error("handshake ECDH keys unavailable");let n=new Nt;return await n.init({sharedSecret:i,sessionSalt:new Uint8Array(this.sessionSalt||[]),selfPrivateKey:this.ecdhKeyPair.privateKey,remotePublicKey:r,isInitiator:t}),this._ratchet=n,this.securityFeatures.hasPFS=!0,this._secureLog("info","\u{1F510} Double Ratchet active \u2014 per-message forward secrecy enabled",{role:t?"initiator":"responder"}),!0}catch(r){return this._ratchet=null,this.securityFeatures.hasPFS=!1,this._secureLog("error","Double Ratchet initialisation failed \u2014 continuing with static session keys",{errorType:r?.constructor?.name||"Unknown"}),!1}finally{window.EnhancedSecureCryptoUtils.zeroizeBuffer(i)}}isRatchetActive(){return!!this._ratchet?.isInitialised}async _generateEphemeralECDHKeys(){try{this._secureLog("info","\u{1F511} Generating ephemeral ECDH keys for PFS",{sessionStartTime:this.sessionStartTime,timestamp:Date.now()});let e=await window.EnhancedSecureCryptoUtils.generateECDHKeyPair();if(!e||!this._validateKeyPairConstantTime(e))throw new Error("Ephemeral ECDH key pair validation failed");let t=this.currentSession?.sessionId||`session_${Date.now()}`;return this.ephemeralKeyPairs.set(t,{keyPair:e,timestamp:Date.now(),sessionId:t}),this._secureLog("info","\u2705 Ephemeral ECDH keys generated for PFS",{timestamp:Date.now()}),e}catch(e){throw this._secureLog("error","\u274C Failed to generate ephemeral ECDH keys",{error:e.message}),new Error(`Ephemeral key generation failed: ${e.message}`)}}async _hardWipeOldKeys(){try{this._secureLog("info","\u{1F9F9} Performing hard wipe of old keys for PFS",{oldKeysCount:this.oldKeys.size,timestamp:Date.now()});for(let[e,t]of this.oldKeys.entries())t.encryptionKey&&this._secureWipeMemory(t.encryptionKey,"pfs_key_wipe"),t.macKey&&this._secureWipeMemory(t.macKey,"pfs_key_wipe"),t.metadataKey&&this._secureWipeMemory(t.metadataKey,"pfs_key_wipe"),t.encryptionKey=null,t.macKey=null,t.metadataKey=null,t.keyFingerprint=null;this.oldKeys.clear(),await this._performNaturalCleanup(),this._secureLog("info","\u2705 Hard wipe of old keys completed for PFS",{timestamp:Date.now()})}catch(e){this._secureLog("error","\u274C Failed to perform hard wipe of old keys",{error:e.message})}}async _wipeEphemeralKeys(){try{this._secureLog("info","\u{1F9F9} Wiping ephemeral keys for PFS",{ephemeralKeysCount:this.ephemeralKeyPairs.size,timestamp:Date.now()});for(let[e,t]of this.ephemeralKeyPairs.entries())t.keyPair?.privateKey&&this._secureWipeMemory(t.keyPair.privateKey,"ephemeral_key_wipe"),t.keyPair?.publicKey&&this._secureWipeMemory(t.keyPair.publicKey,"ephemeral_key_wipe"),t.keyPair=null,t.timestamp=null,t.sessionId=null;this.ephemeralKeyPairs.clear(),await this._performNaturalCleanup(),this._secureLog("info","\u2705 Ephemeral keys wiped for PFS",{timestamp:Date.now()})}catch(e){this._secureLog("error","\u274C Failed to wipe ephemeral keys",{error:e.message})}}async _encryptFileMessage(e,t){try{if(!this.encryptionKey)throw new Error("No encryption key available for file message");let i=typeof e=="string"?e:JSON.stringify(e),n={type:"encrypted_file_message",encryptedData:await window.EnhancedSecureCryptoUtils.encryptDataWithAAD(i,this.encryptionKey,t),aad:t,timestamp:Date.now(),keyFingerprint:this.keyFingerprint};return JSON.stringify(n)}catch(i){throw this._secureLog("error","Failed to encrypt file message",{error:i.message}),new Error(`File message encryption failed: ${i.message}`)}}async _decryptFileMessage(e){try{let t=JSON.parse(e);if(t.type!=="encrypted_file_message")throw new Error("Invalid encrypted file message type");if(t.keyFingerprint!==this.keyFingerprint)throw new Error("Key fingerprint mismatch in encrypted file message");let i=this._validateMessageAAD(t.aad,"file_message");if(!this.encryptionKey)throw new Error("No encryption key available for file message decryption");return{decryptedData:await window.EnhancedSecureCryptoUtils.decryptDataWithAAD(t.encryptedData,this.encryptionKey,t.aad),aad:i}}catch(t){throw this._secureLog("error","Failed to decrypt file message",{error:t.message}),new Error(`File message decryption failed: ${t.message}`)}}_validateEncryptionKeys(e=!0){let t=!!(this.encryptionKey&&this.macKey&&this.metadataKey);if(!t&&e)throw new Error("Encryption keys not initialized");return t}async _tryReinitializeEncryptionKeys(){try{if(this.encryptionKey&&this.macKey&&this.metadataKey)return!0;let e=!!(this.ecdhKeyPair?.privateKey&&(this.peerPublicKey||this.peerECDHPublicKey)),t=this.peerPublicKey||this.peerECDHPublicKey;if(!e||!t||!this.sessionSalt)return!1;let i=await window.EnhancedSecureCryptoUtils.deriveSharedKeys(this.ecdhKeyPair.privateKey,t,this.sessionSalt);return await this._setEncryptionKeys(i.messageKey,i.macKey,i.metadataKey,i.fingerprint),!!(this.encryptionKey&&this.macKey&&this.metadataKey)}catch(e){return this._secureLog("error","Failed to reinitialize encryption keys",{error:e.message}),!1}}_isFileMessage(e){if(typeof e=="string")try{let t=JSON.parse(e);return t.type&&t.type.startsWith("file_")}catch{return!1}return typeof e=="object"&&e.type?e.type.startsWith("file_"):!1}_isSystemMessage(e){let t=[s.MESSAGE_TYPES.HEARTBEAT,s.MESSAGE_TYPES.VERIFICATION,s.MESSAGE_TYPES.VERIFICATION_RESPONSE,s.MESSAGE_TYPES.VERIFICATION_CONFIRMED,s.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED,s.MESSAGE_TYPES.PEER_DISCONNECT,s.MESSAGE_TYPES.SECURITY_UPGRADE,s.MESSAGE_TYPES.KEY_ROTATION_SIGNAL,s.MESSAGE_TYPES.KEY_ROTATION_READY];if(typeof e=="string")try{let i=JSON.parse(e);return t.includes(i.type)}catch{return!1}return typeof e=="object"&&e.type?t.includes(e.type):!1}_isFakeMessage(e){if(typeof e=="string")try{let t=JSON.parse(e);return t.type===s.MESSAGE_TYPES.FAKE||t.isFakeTraffic===!0}catch{return!1}return typeof e=="object"&&e!==null?e.type===s.MESSAGE_TYPES.FAKE||e.isFakeTraffic===!0:!1}_withErrorHandling(e,t,i=null){try{return e()}catch(r){return this._debugMode&&this._secureLog("error","\u274C ${errorMessage}:",{errorType:r?.constructor?.name||"Unknown"}),i}}async _withAsyncErrorHandling(e,t,i=null){try{return await e()}catch(r){return this._debugMode&&this._secureLog("error","\u274C ${errorMessage}:",{errorType:r?.constructor?.name||"Unknown"}),i}}_getMessageType(e){if(typeof e=="string")try{return JSON.parse(e).type||null}catch{return null}return typeof e=="object"&&e!==null&&e.type||null}_resetNotificationFlags(){this.lastSecurityLevelNotification=null,this.verificationNotificationSent=!1,this.verificationInitiationSent=!1,this._verificationUiOpened=!1,this._sasLocalFingerprint=null,this._sasRemoteFingerprint=null,this.disconnectNotificationSent=!1,this.reconnectionFailedNotificationSent=!1,this.peerDisconnectNotificationSent=!1,this.connectionClosedNotificationSent=!1,this.fakeTrafficDisabledNotificationSent=!1,this.advancedFeaturesDisabledNotificationSent=!1,this.securityUpgradeNotificationSent=!1,this.lastSecurityUpgradeStage=null,this.securityCalculationNotificationSent=!1,this.lastSecurityCalculationLevel=null}_isFilteredMessage(e){return Object.values(s.FILTERED_RESULTS).includes(e)}_cleanupLogs(){this._logCounts.size>500&&(this._logCounts.clear(),this._secureLog("debug","\u{1F9F9} Log counts cleared due to size limit"));let e=Date.now(),t=3e5,i=0;for(let[r,n]of this._logCounts.entries())n>10&&i++;i>20&&(this._logCounts.clear(),this._secureLog("warn","\u{1F6A8} Emergency log cleanup due to suspicious patterns")),this._logSecurityViolations>0&&i<5&&(this._logSecurityViolations=Math.max(0,this._logSecurityViolations-1)),(!this._lastIVCleanupTime||Date.now()-this._lastIVCleanupTime>3e5)&&(this._cleanupOldIVs(),this._lastIVCleanupTime=Date.now()),(!this._secureMemoryManager.memoryStats.lastCleanup||Date.now()-this._secureMemoryManager.memoryStats.lastCleanup>6e5)&&(this._performPeriodicMemoryCleanup().catch(r=>{this._secureLog("error","Periodic cleanup failed",{errorType:r?.constructor?.name||"Unknown"})}),this._secureMemoryManager.memoryStats.lastCleanup=Date.now())}_getLoggingStats(){let e={isProductionMode:this._isProductionMode,debugMode:this._debugMode,currentLogLevel:this._currentLogLevel,logCountsSize:this._logCounts.size,maxLogCount:this._maxLogCount,securityViolations:this._logSecurityViolations||0,maxSecurityViolations:this._maxLogSecurityViolations||3,systemStatus:this._currentLogLevel===-1?"DISABLED":"ACTIVE"},t={};for(let[i,r]of Object.entries(e))typeof r=="string"&&this._containsSensitiveContent(r)?t[i]="[SENSITIVE_DATA_REDACTED]":t[i]=r;return t}async _emergencyDisableLogging(){this._currentLogLevel=-1,this._logCounts.clear(),this._logSecurityViolations&&(this._logSecurityViolations=0),this._secureLog=()=>{arguments[0]==="error"&&this._originalConsole?.error&&this._originalConsole.error("\u{1F6A8} SECURITY: Logging system disabled - potential data exposure prevented")},this._originalSanitizeString=this._sanitizeString,this._originalSanitizeLogData=this._sanitizeLogData,this._originalAuditLogMessage=this._auditLogMessage,this._originalContainsSensitiveContent=this._containsSensitiveContent,this._sanitizeString=()=>"[LOGGING_DISABLED]",this._sanitizeLogData=()=>({error:"LOGGING_DISABLED"}),this._auditLogMessage=()=>!1,this._containsSensitiveContent=()=>!0,await this._performNaturalCleanup(),this._originalConsole?.error?.("\u{1F6A8} CRITICAL: Secure logging system disabled due to potential data exposure")}_resetLoggingSystem(){this._secureLog("info","\u{1F527} Resetting logging system after emergency shutdown"),this._sanitizeString=this._originalSanitizeString||(e=>e),this._sanitizeLogData=this._originalSanitizeLogData||(e=>e),this._auditLogMessage=this._originalAuditLogMessage||(()=>!0),this._containsSensitiveContent=this._originalContainsSensitiveContent||(()=>!1),this._logSecurityViolations=0,this._secureLog("info","\u2705 Logging system reset successfully")}_auditLogMessage(e,t){if(!t||typeof t!="object")return!0;let i=JSON.stringify(t);if(this._containsSensitiveContent(e))return this._emergencyDisableLogging(),this._originalConsole?.error?.("\u{1F6A8} SECURITY BREACH: Sensitive content detected in log message"),!1;if(this._containsSensitiveContent(i))return this._emergencyDisableLogging(),this._originalConsole?.error?.("\u{1F6A8} SECURITY BREACH: Sensitive content detected in log data"),!1;let r=["secret","token","password","credential","auth","fingerprint","salt","signature","private_key","api_key","private","encryption","mac","metadata","session","jwt","bearer","key","hash","digest","nonce","iv","cipher"],n=i.toLowerCase();for(let a of r)if(n.includes(a)&&!this._safeFieldsWhitelist.has(a))return this._emergencyDisableLogging(),this._originalConsole?.error?.(`\u{1F6A8} SECURITY BREACH: Dangerous pattern detected in log: ${a}`),!1;for(let[a,o]of Object.entries(t))if(typeof o=="string"&&this._hasHighEntropy(o))return this._emergencyDisableLogging(),this._originalConsole?.error?.(`\u{1F6A8} SECURITY BREACH: High entropy value detected in log field: ${a}`),!1;return!0}initializeFileTransfer(){try{if(this._sessionAlive===!1)return;if(this._secureLog("info","\u{1F527} Initializing Enhanced Secure File Transfer system..."),this.fileTransferSystem){this._secureLog("info","\u2705 File transfer system already initialized");return}if(!!!(this.dataChannel&&this.dataChannel.readyState==="open")){if(this._secureLog("warn","\u26A0\uFE0F Data channel not open, deferring file transfer initialization"),this.dataChannel){let r=()=>{this._secureLog("info","\u{1F504} DataChannel opened, initializing file transfer..."),this.initializeFileTransfer()};this.dataChannel.addEventListener("open",r,{once:!0})}return}if(!this.isVerified){this._secureLog("warn","\u26A0\uFE0F Connection not verified yet, deferring file transfer initialization"),this._scheduleFileTransferInitRetry(500);return}if(this.fileTransferSystem&&(this._secureLog("info","\u{1F9F9} Cleaning up existing file transfer system"),this.fileTransferSystem.cleanup(),this.fileTransferSystem=null),!this.encryptionKey||!this.macKey){this._secureLog("warn","\u26A0\uFE0F Encryption keys not ready, deferring file transfer initialization"),this._scheduleFileTransferInitRetry(1e3);return}let t=r=>{try{this._secureLog("info","\u{1F3C1} Sender transfer summary",{summary:r}),this.onFileProgress&&this.onFileProgress({type:"complete",...r})}catch(n){this._secureLog("warn","\u26A0\uFE0F onComplete handler failed:",{details:n.message})}};this.fileTransferSystem=new je(this,this.onFileProgress||null,t,this.onFileError||null,this.onFileReceived||null,this.onIncomingFileRequest||null),this._fileTransferActive=!0,this._secureLog("info","\u2705 Enhanced Secure File Transfer system initialized successfully");let i=this.fileTransferSystem.getSystemStatus();this._secureLog("info","\u{1F50D} File transfer system status after init",{status:i})}catch(e){this._secureLog("error","\u274C Failed to initialize file transfer system",{errorType:e.constructor.name}),this.fileTransferSystem=null,this._fileTransferActive=!1}}_scheduleFileTransferInitRetry(e){if(this._sessionAlive===!1)return null;this._fileTransferInitRetryTimers||(this._fileTransferInitRetryTimers=new Set);let t=this._trackActiveTimer(setTimeout(()=>{this._fileTransferInitRetryTimers.delete(t),this._untrackActiveTimer(t),this._sessionAlive!==!1&&this.initializeFileTransfer()},e));return this._fileTransferInitRetryTimers.add(t),t}async initializeEnhancedSecurity(){try{await this.generateNestedEncryptionKey(),this.decoyChannelConfig.enabled&&this.initializeDecoyChannels(),this.fakeTrafficConfig.enabled&&this.startFakeTrafficGeneration()}catch(e){this._secureLog("error","\u274C Failed to initialize enhanced security",{errorType:e.constructor.name})}}getSafeRandomInt(e,t){if(!Number.isInteger(e)||!Number.isInteger(t))throw new Error("getSafeRandomInt requires integer min and max");if(e>=t)throw new Error("min must be less than max");let i=t-e+1,r=Math.ceil(Math.log2(i)),n=Math.ceil(r/8),a=(1<=i);return e+o}getSafeRandomFloat(e,t,i=1e3){if(typeof e!="number"||typeof t!="number")throw new Error("getSafeRandomFloat requires numeric min and max");if(e>=t)throw new Error("minFloat must be less than maxFloat");let r=this.getSafeRandomInt(0,i),n=(t-e)/i;return e+r*n}generateFingerprintMask(){return{timingOffset:this.getSafeRandomInt(0,1500),sizeVariation:this.getSafeRandomFloat(.75,1.25,1e3),noisePattern:Array.from(crypto.getRandomValues(new Uint8Array(64))),headerVariations:["X-Client-Version","X-Session-ID","X-Request-ID","X-Timestamp","X-Signature","X-Secure","X-Encrypted","X-Protected","X-Safe","X-Anonymous","X-Private"],noiseIntensity:this.getSafeRandomInt(50,150),sizeMultiplier:this.getSafeRandomFloat(.75,1.25,1e3),timingVariation:this.getSafeRandomInt(100,1100)}}configureSecurityForSession(){this._secureLog("info","\u{1F527} Configuring security - all features enabled by default"),this.sessionConstraints={},Object.keys(this.securityFeatures).forEach(e=>{this.sessionConstraints[e]=!0}),this.applySessionConstraints(),this._secureLog("info","\u2705 Security configured - all features enabled",{constraints:this.sessionConstraints}),this._validateCryptographicSecurity()||(this._secureLog("error","\u{1F6A8} CRITICAL: Cryptographic security validation failed after session configuration"),this.onStatusChange&&this.onStatusChange("security_breach",{type:"crypto_security_failure",message:"Cryptographic security validation failed after session configuration"})),this.notifySecurityLevel(),setTimeout(()=>{this.calculateAndReportSecurityLevel()},s.TIMEOUTS.SECURITY_CALC_DELAY)}applySessionConstraints(){this.sessionConstraints&&(Object.keys(this.sessionConstraints).forEach(e=>{switch(this.securityFeatures[e]=!0,e){case"hasFakeTraffic":this.fakeTrafficConfig.enabled=!0,this.isConnected()&&this.startFakeTrafficGeneration();break;case"hasDecoyChannels":this.decoyChannelConfig.enabled=!0,this.isConnected()&&this.initializeDecoyChannels();break;case"hasPacketReordering":this.reorderingConfig.enabled=!0;break;case"hasAntiFingerprinting":this.antiFingerprintingConfig.enabled=!0;break;case"hasMessageChunking":this.chunkingConfig.enabled=!0;break}}),this._secureLog("info","\u2705 All security features enabled by default",{constraints:this.sessionConstraints,currentFeatures:this.securityFeatures}))}_sanitizeIncomingChatMessage(e){return typeof e!="string"?e:window.EnhancedSecureCryptoUtils.sanitizeMessage(e)}deliverMessageToUI(e,t="received",i=null){try{if(this._secureLog("debug","\u{1F4E4} deliverMessageToUI called",{message:e,type:t,messageType:typeof e,hasOnMessage:!!this.onMessage}),typeof e=="object"&&e.type&&[s.MESSAGE_TYPES.FILE_TRANSFER_START,s.MESSAGE_TYPES.FILE_TRANSFER_RESPONSE,s.MESSAGE_TYPES.FILE_CHUNK,s.MESSAGE_TYPES.CHUNK_CONFIRMATION,s.MESSAGE_TYPES.FILE_TRANSFER_COMPLETE,s.MESSAGE_TYPES.FILE_TRANSFER_ERROR,s.MESSAGE_TYPES.HEARTBEAT,s.MESSAGE_TYPES.VERIFICATION,s.MESSAGE_TYPES.VERIFICATION_RESPONSE,s.MESSAGE_TYPES.VERIFICATION_CONFIRMED,s.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED,s.MESSAGE_TYPES.PEER_DISCONNECT,s.MESSAGE_TYPES.KEY_ROTATION_SIGNAL,s.MESSAGE_TYPES.KEY_ROTATION_READY,s.MESSAGE_TYPES.SECURITY_UPGRADE].includes(e.type)){this._debugMode&&this._secureLog("warn",`\u{1F6D1} Blocked system/file message from UI: ${e.type}`);return}if(typeof e=="string"&&e.trim().startsWith("{"))try{let n=JSON.parse(e);if(n.type&&[s.MESSAGE_TYPES.FILE_TRANSFER_START,s.MESSAGE_TYPES.FILE_TRANSFER_RESPONSE,s.MESSAGE_TYPES.FILE_CHUNK,s.MESSAGE_TYPES.CHUNK_CONFIRMATION,s.MESSAGE_TYPES.FILE_TRANSFER_COMPLETE,s.MESSAGE_TYPES.FILE_TRANSFER_ERROR,s.MESSAGE_TYPES.HEARTBEAT,s.MESSAGE_TYPES.VERIFICATION,s.MESSAGE_TYPES.VERIFICATION_RESPONSE,s.MESSAGE_TYPES.VERIFICATION_CONFIRMED,s.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED,s.MESSAGE_TYPES.PEER_DISCONNECT,s.MESSAGE_TYPES.KEY_ROTATION_SIGNAL,s.MESSAGE_TYPES.KEY_ROTATION_READY,s.MESSAGE_TYPES.SECURITY_UPGRADE].includes(n.type)){this._debugMode&&this._secureLog("warn",`\u{1F6D1} Blocked system/file message from UI (string): ${n.type}`);return}}catch{}let r=t==="received"?this._sanitizeIncomingChatMessage(e):e;if(this.onMessage){let n=i&&typeof this._sanitizeMessageMeta=="function"?this._sanitizeMessageMeta(i):null;this._secureLog("debug","\u{1F4E4} Calling this.onMessage callback",{message:r,type:t}),this.onMessage(r,t,n||void 0)}else this._secureLog("warn","\u26A0\uFE0F this.onMessage callback is null or undefined")}catch(r){this._secureLog("error","\u274C Failed to deliver message to UI:",{errorType:r?.constructor?.name||"Unknown"})}}notifySecurityLevel(){if(this.lastSecurityLevelNotification==="maximum")return;if(this.lastSecurityLevelNotification="maximum",this.onMessage&&this.deliverMessageToUI("\u{1F6E1}\uFE0F Maximum Security Active - All features enabled","system"),this.onMessage){let t=Object.entries(this.securityFeatures).filter(([i,r])=>r===!0).map(([i])=>i.replace("has","").replace(/([A-Z])/g," $1").trim().toLowerCase()).slice(0,5);this.deliverMessageToUI(`\u{1F527} Active: ${t.join(", ")}...`,"system")}}cleanupDecoyChannels(){for(let[e,t]of this.decoyTimers.entries())clearTimeout(t);this.decoyTimers.clear();for(let[e,t]of this.decoyChannels.entries())t.readyState==="open"&&t.close();this.decoyChannels.clear(),this._secureLog("info","\u{1F9F9} Decoy channels cleaned up")}async generateNestedEncryptionKey(){try{this.nestedEncryptionKey=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(e){throw this._secureLog("error","\u274C Failed to generate nested encryption key:",{errorType:e?.constructor?.name||"Unknown"}),e}}async applyNestedEncryption(e){if(!this.nestedEncryptionKey||!this.securityFeatures.hasNestedEncryption)return e;try{let t=this._generateSecureIV(s.SIZES.NESTED_ENCRYPTION_IV_SIZE,"nestedEncryption"),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:t},this.nestedEncryptionKey,e),r=new Uint8Array(s.SIZES.NESTED_ENCRYPTION_IV_SIZE+i.byteLength);return r.set(t,0),r.set(new Uint8Array(i),s.SIZES.NESTED_ENCRYPTION_IV_SIZE),this._secureLog("debug","\u2705 Nested encryption applied with secure IV",{ivSize:t.length,dataSize:e.byteLength,encryptedSize:i.byteLength}),r.buffer}catch(t){return this._secureLog("error","\u274C Nested encryption failed:",{errorType:t?.constructor?.name||"Unknown",errorMessage:t?.message||"Unknown error"}),t.message.includes("emergency mode")&&(this.securityFeatures.hasNestedEncryption=!1,this._secureLog("warn","\u26A0\uFE0F Nested encryption disabled due to IV emergency mode")),e}}async removeNestedEncryption(e){if(!this.nestedEncryptionKey||!this.securityFeatures.hasNestedEncryption)return e;if(!(e instanceof ArrayBuffer)||e.byteLengtht.length-4?(this._debugMode&&this._secureLog("warn","\u26A0\uFE0F Invalid packet padding size, skipping removal"),e):t.slice(4,4+r).buffer}catch(t){return this._debugMode&&this._secureLog("error","\u274C Packet padding removal failed:",{errorType:t?.constructor?.name||"Unknown"}),e}}startFakeTrafficGeneration(){if(!this.fakeTrafficConfig.enabled||!this.isConnected())return;if(this.fakeTrafficTimer){this._secureLog("warn","\u26A0\uFE0F Fake traffic generation already running");return}let e=async()=>{if(!this.isConnected()){this.stopFakeTrafficGeneration();return}try{let n=this.generateFakeMessage();await this.sendFakeMessage(n);let a=this.fakeTrafficConfig.randomDecoyIntervals?this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minInterval,Math.min(this.fakeTrafficConfig.maxInterval,6e4)):this.fakeTrafficConfig.minInterval,o=Math.max(a,s.TIMEOUTS.FAKE_TRAFFIC_MIN_INTERVAL);this.fakeTrafficTimer=setTimeout(e,o)}catch(n){this._debugMode&&this._secureLog("error","\u274C Fake traffic generation failed:",{errorType:n?.constructor?.name||"Unknown"}),this.stopFakeTrafficGeneration()}},t=s.TIMEOUTS.DECOY_INITIAL_DELAY,i=Math.min(this.fakeTrafficConfig.maxInterval,3e4),r=this.getUnbiasedRandomInRange(t,i);this.fakeTrafficTimer=setTimeout(e,r)}stopFakeTrafficGeneration(){this.fakeTrafficTimer&&(clearTimeout(this.fakeTrafficTimer),this.fakeTrafficTimer=null)}generateFakeMessage(){let e=this.getUnbiasedRandomInRange(0,this.fakeTrafficConfig.patterns.length-1),t=this.fakeTrafficConfig.patterns[e],i=this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minSize,this.fakeTrafficConfig.maxSize),r=crypto.getRandomValues(new Uint8Array(i));return{type:s.MESSAGE_TYPES.FAKE,pattern:t,data:Array.from(r).map(n=>n.toString(16).padStart(2,"0")).join(""),timestamp:Date.now(),size:i,isFakeTraffic:!0,source:"fake_traffic_generator",fakeId:crypto.getRandomValues(new Uint32Array(1))[0].toString(36)}}emergencyDisableAdvancedFeatures(){this._secureLog("error","\u{1F6A8} Emergency disabling advanced security features due to errors"),this.securityFeatures.hasNestedEncryption=!1,this.securityFeatures.hasPacketReordering=!1,this.securityFeatures.hasAntiFingerprinting=!1,this.reorderingConfig.enabled=!1,this.antiFingerprintingConfig.enabled=!1,this.packetBuffer.clear(),this.emergencyDisableFakeTraffic(),this._secureLog("info","\u2705 Advanced features disabled, keeping basic encryption"),this.advancedFeaturesDisabledNotificationSent||(this.advancedFeaturesDisabledNotificationSent=!0,this.onMessage&&this.deliverMessageToUI("\u{1F6A8} Advanced security features temporarily disabled due to compatibility issues","system"))}async sendFakeMessage(e){if(this._validateConnection(!1))try{this._secureLog("debug","\u{1F3AD} Sending fake message",{hasPattern:!!e.pattern,sizeRange:e.size>100?"large":"small"});let t=JSON.stringify({...e,type:s.MESSAGE_TYPES.FAKE,isFakeTraffic:!0,timestamp:Date.now()}),i=new TextEncoder().encode(t),r=await this.applySecurityLayers(i,!0);this.dataChannel.send(r),this._secureLog("debug","\u{1F3AD} Fake message sent successfully",{pattern:e.pattern})}catch(t){this._secureLog("error","\u274C Failed to send fake message",{error:t.message})}}checkFakeTrafficStatus(){let e={fakeTrafficEnabled:this.securityFeatures.hasFakeTraffic,fakeTrafficConfigEnabled:this.fakeTrafficConfig.enabled,timerActive:!!this.fakeTrafficTimer,patterns:this.fakeTrafficConfig.patterns,intervals:{min:this.fakeTrafficConfig.minInterval,max:this.fakeTrafficConfig.maxInterval}};return this._debugMode&&this._secureLog("info","\u{1F3AD} Fake Traffic Status",{status:e}),e}emergencyDisableFakeTraffic(){this._debugMode&&this._secureLog("error","\u{1F6A8} Emergency disabling fake traffic"),this.securityFeatures.hasFakeTraffic=!1,this.fakeTrafficConfig.enabled=!1,this.stopFakeTrafficGeneration(),this._debugMode&&this._secureLog("info","\u2705 Fake traffic disabled"),this.fakeTrafficDisabledNotificationSent||(this.fakeTrafficDisabledNotificationSent=!0,this.onMessage&&this.deliverMessageToUI("\u{1F6A8} Fake traffic emergency disabled","system"))}async _applySecurityLayersWithoutMutex(e,t=!1){try{let i=e;return t?(this.encryptionKey&&typeof i=="string"&&(i=await window.EnhancedSecureCryptoUtils.encryptData(i,this.encryptionKey)),i):(this.securityFeatures.hasNestedEncryption&&this.nestedEncryptionKey&&i instanceof ArrayBuffer&&(i=await this.applyNestedEncryption(i)),this.securityFeatures.hasPacketReordering&&this.reorderingConfig?.enabled&&i instanceof ArrayBuffer&&(i=this.applyPacketReordering(i)),this.securityFeatures.hasPacketPadding&&i instanceof ArrayBuffer&&(i=this.applyPacketPadding(i)),this.securityFeatures.hasAntiFingerprinting&&i instanceof ArrayBuffer&&(i=this.applyAntiFingerprinting(i)),this.encryptionKey&&typeof i=="string"&&(i=await window.EnhancedSecureCryptoUtils.encryptData(i,this.encryptionKey)),i)}catch(i){return this._secureLog("error","\u274C Error in applySecurityLayersWithoutMutex:",{errorType:i?.constructor?.name||"Unknown"}),e}}async processChunkedMessage(e){try{if(!this.chunkingConfig.addChunkHeaders)return this.processMessage(e);let t=new Uint8Array(e);if(t.length<16)return this.processMessage(e);let i=new DataView(t.buffer,0,16),r=i.getUint32(0,!1),n=i.getUint32(4,!1),a=i.getUint32(8,!1),o=i.getUint32(12,!1),c=t.slice(16,16+o);this.chunkQueue[r]||(this.chunkQueue[r]={chunks:new Array(a),received:0,timestamp:Date.now()});let l=this.chunkQueue[r];if(l.chunks[n]=c,l.received++,this._secureLog("debug",`\u{1F4E6} Received chunk ${n+1}/${a} for message ${r}`),l.received===a){let h=l.chunks.reduce((S,w)=>S+w.length,0),u=new Uint8Array(h),p=0;for(let S of l.chunks)u.set(S,p),p+=S.length;await this.processMessage(u.buffer),delete this.chunkQueue[r],this._secureLog("info",`\u{1F4E6} Chunked message ${r} reassembled and processed`)}}catch(t){this._secureLog("error","\u274C Chunked message processing failed:",{errorType:t?.constructor?.name||"Unknown"})}}initializeDecoyChannels(){if(!(!this.decoyChannelConfig.enabled||!this.peerConnection)){if(this.decoyChannels.size>0){this._secureLog("warn","\u26A0\uFE0F Decoy channels already initialized, skipping...");return}try{let e=Math.min(this.decoyChannelConfig.maxDecoyChannels,this.decoyChannelConfig.decoyChannelNames.length);for(let t=0;t.5,maxRetransmits:Math.floor(Math.random()*3)});this.setupDecoyChannel(r,i),this.decoyChannels.set(i,r)}this._debugMode&&this._secureLog("info",`\u{1F3AD} Initialized ${e} decoy channels`)}catch(e){this._debugMode&&this._secureLog("error","\u274C Failed to initialize decoy channels:",{errorType:e?.constructor?.name||"Unknown"})}}}setupDecoyChannel(e,t){e.onopen=()=>{this._debugMode&&this._secureLog("debug",`\u{1F3AD} Decoy channel "${t}" opened`),this.startDecoyTraffic(e,t)},e.onmessage=i=>{this._debugMode&&this._secureLog("debug",`\u{1F3AD} Received decoy message on "${t}": ${i.data?.length||"undefined"} bytes`)},e.onclose=()=>{this._debugMode&&this._secureLog("debug",`\u{1F3AD} Decoy channel "${t}" closed`),this.stopDecoyTraffic(t)},e.onerror=i=>{this._debugMode&&this._secureLog("error",`\u274C Decoy channel "${t}" error`,{error:i.message})}}startDecoyTraffic(e,t){let i=async()=>{if(e.readyState==="open")try{let n=this.generateDecoyData(t);e.send(n);let a=this.decoyChannelConfig.randomDecoyIntervals?Math.random()*15e3+1e4:2e4;this.decoyTimers.set(t,setTimeout(()=>i(),a))}catch(n){this._debugMode&&this._secureLog("error",`\u274C Failed to send decoy data on "${t}"`,{error:n.message})}},r=Math.random()*1e4+5e3;this.decoyTimers.set(t,setTimeout(()=>i(),r))}stopDecoyTraffic(e){let t=this.decoyTimers.get(e);t&&(clearTimeout(t),this.decoyTimers.delete(e))}generateDecoyData(e){let t={sync:()=>JSON.stringify({type:"sync",timestamp:Date.now(),sequence:Math.floor(Math.random()*1e3),data:Array.from(crypto.getRandomValues(new Uint8Array(32))).map(i=>i.toString(16).padStart(2,"0")).join("")}),status:()=>JSON.stringify({type:"status",status:["online","away","busy"][Math.floor(Math.random()*3)],uptime:Math.floor(Math.random()*3600),data:Array.from(crypto.getRandomValues(new Uint8Array(16))).map(i=>i.toString(16).padStart(2,"0")).join("")}),heartbeat:()=>JSON.stringify({type:"heartbeat",timestamp:Date.now(),data:Array.from(crypto.getRandomValues(new Uint8Array(24))).map(i=>i.toString(16).padStart(2,"0")).join("")}),metrics:()=>JSON.stringify({type:"metrics",cpu:Math.random()*100,memory:Math.random()*100,network:Math.random()*1e3,data:Array.from(crypto.getRandomValues(new Uint8Array(20))).map(i=>i.toString(16).padStart(2,"0")).join("")}),debug:()=>JSON.stringify({type:"debug",level:["info","warn","error"][Math.floor(Math.random()*3)],message:"Debug message",data:Array.from(crypto.getRandomValues(new Uint8Array(28))).map(i=>i.toString(16).padStart(2,"0")).join("")})};return t[e]?t[e]():Array.from(crypto.getRandomValues(new Uint8Array(64))).map(i=>i.toString(16).padStart(2,"0")).join("")}addReorderingHeaders(e){if(!this.reorderingConfig.enabled)return e;try{let t=new Uint8Array(e),i=this.reorderingConfig.useTimestamps?12:8,r=new ArrayBuffer(i),n=new DataView(r);this.reorderingConfig.useSequenceNumbers&&n.setUint32(0,this.sequenceNumber++,!1),this.reorderingConfig.useTimestamps&&n.setUint32(4,Date.now(),!1),n.setUint32(this.reorderingConfig.useTimestamps?8:4,t.length,!1);let a=new Uint8Array(i+t.length);return a.set(new Uint8Array(r),0),a.set(t,i),a.buffer}catch(t){return this._secureLog("error","\u274C Failed to add reordering headers:",{errorType:t?.constructor?.name||"Unknown"}),e}}async processReorderedPacket(e){if(!this.reorderingConfig.enabled)return this.processMessage(e);try{let t=new Uint8Array(e),i=this.reorderingConfig.useTimestamps?12:8;if(t.lengtht.length-i||o<=0)return this._debugMode&&this._secureLog("warn","\u26A0\uFE0F Invalid reordered packet data size, processing directly"),this.processMessage(e);let c=t.slice(i,i+o);try{let l=new TextDecoder().decode(c),h=JSON.parse(l);if(h.type==="fake"||h.isFakeTraffic===!0){this._debugMode&&this._secureLog("warn",`\u{1F3AD} BLOCKED: Reordered fake message: ${h.pattern||"unknown"}`);return}}catch{}this.packetBuffer.set(n,{data:c.buffer,timestamp:a||Date.now()}),await this.processOrderedPackets()}catch(t){return this._secureLog("error","\u274C Failed to process reordered packet:",{errorType:t?.constructor?.name||"Unknown"}),this.processMessage(e)}}async processOrderedPackets(){let e=Date.now(),t=this.reorderingConfig.reorderTimeout;for(;;){let i=this.lastProcessedSequence+1,r=this.packetBuffer.get(i);if(r){try{let n=new TextDecoder().decode(r.data),a=JSON.parse(n);if(a.type==="fake"||a.isFakeTraffic===!0){this._secureLog("warn",`\u{1F3AD} BLOCKED: Ordered fake message: ${a.pattern||"unknown"}`),this.packetBuffer.delete(i),this.lastProcessedSequence=i;continue}}catch{}await this.processMessage(r.data),this.packetBuffer.delete(i),this.lastProcessedSequence=i}else{let n=this.findOldestPacket();if(n&&e-n.timestamp>t){this._secureLog("warn","\u26A0\uFE0F Packet ${oldestPacket.sequence} timed out, processing out of order");try{let a=new TextDecoder().decode(n.data),o=JSON.parse(a);if(o.type==="fake"||o.isFakeTraffic===!0){this._secureLog("warn",`\u{1F3AD} BLOCKED: Timed out fake message: ${o.pattern||"unknown"}`),this.packetBuffer.delete(n.sequence),this.lastProcessedSequence=n.sequence;continue}}catch{}await this.processMessage(n.data),this.packetBuffer.delete(n.sequence),this.lastProcessedSequence=n.sequence}else break}}this.cleanupOldPackets(e,t)}findOldestPacket(){let e=null;for(let[t,i]of this.packetBuffer.entries())(!e||i.timestampt&&(this._secureLog("warn","\u26A0\uFE0F \u{1F5D1}\uFE0F Removing timed out packet ${sequence}"),this.packetBuffer.delete(i))}applyAntiFingerprinting(e){if(!this.antiFingerprintingConfig.enabled)return e;try{let t=e;return this.antiFingerprintingConfig.addNoise&&(t=this.addNoise(t)),this.antiFingerprintingConfig.randomizeSizes&&(t=this.randomizeSize(t)),this.antiFingerprintingConfig.maskPatterns&&(t=this.maskPatterns(t)),this.antiFingerprintingConfig.useRandomHeaders&&(t=this.addRandomHeaders(t)),t}catch(t){return this._secureLog("error","\u274C Anti-fingerprinting failed:",{errorType:t?.constructor?.name||"Unknown"}),e}}addNoise(e){let t=new Uint8Array(e),i=this.getUnbiasedRandomInRange(8,40),r=crypto.getRandomValues(new Uint8Array(i)),n=new Uint8Array(t.length+i);return n.set(t,0),n.set(r,t.length),n.buffer}randomizeSize(e){let t=new Uint8Array(e),i=this.fingerprintMask.sizeVariation,r=Math.floor(t.length*i);if(r>t.length){let n=crypto.getRandomValues(new Uint8Array(r-t.length)),a=new Uint8Array(r);return a.set(t,0),a.set(n,t.length),a.buffer}else if(r=256-256%this.fingerprintMask.headerVariations.length);let l=this.fingerprintMask.headerVariations[c%this.fingerprintMask.headerVariations.length],h;do h=crypto.getRandomValues(new Uint8Array(1))[0];while(h>=256-256%16);let u=crypto.getRandomValues(new Uint8Array(h%16+4)),p=new DataView(n.buffer,a);p.setUint32(0,u.length+8,!1),p.setUint32(4,this.hashString(l),!1),n.set(u,a+8);let S=this.calculateChecksum(n.slice(a,a+8+u.length));new DataView(n.buffer,a+8+u.length).setUint32(0,S,!1),a+=8+u.length+4}return n.set(t,a),n.buffer}hashString(e){let t=0;for(let i=0;i50)try{if(/^[A-Za-z0-9+/=]+$/.test(i.trim())&&(this._debugMode&&this._secureLog("debug","\u{1F513} Applying standard decryption..."),i=await window.EnhancedSecureCryptoUtils.decryptData(i,this.encryptionKey),this._debugMode&&this._secureLog("debug","\u2705 Standard decryption successful"),typeof i=="string")){try{let n=JSON.parse(i);if(n.type==="fake"||n.isFakeTraffic===!0)return this._debugMode&&this._secureLog("warn",`\u{1F3AD} BLOCKED: Legacy fake message: ${n.pattern||"unknown"}`),"FAKE_MESSAGE_FILTERED"}catch{}i=new TextEncoder().encode(i).buffer}}catch(r){return this._debugMode&&this._secureLog("warn","\u26A0\uFE0F Standard decryption failed:",{details:r.message}),e}if(this.securityFeatures.hasNestedEncryption&&this.nestedEncryptionKey&&i instanceof ArrayBuffer&&i.byteLength>12)try{if(i=await this.removeNestedEncryption(i),i instanceof ArrayBuffer)try{let r=new TextDecoder().decode(i),n=JSON.parse(r);if(n.type==="fake"||n.isFakeTraffic===!0)return this._debugMode&&this._secureLog("warn",`\u{1F3AD} BLOCKED: Nested fake message: ${n.pattern||"unknown"}`),"FAKE_MESSAGE_FILTERED"}catch{}}catch(r){this._debugMode&&this._secureLog("warn","\u26A0\uFE0F Nested decryption failed - skipping this layer:",{details:r.message})}if(this.securityFeatures.hasPacketReordering&&this.reorderingConfig.enabled&&i instanceof ArrayBuffer)try{let r=this.reorderingConfig.useTimestamps?12:8;if(i.byteLength>r)return await this.processReorderedPacket(i)}catch(r){this._debugMode&&this._secureLog("warn","\u26A0\uFE0F Reordering processing failed - using direct processing:",{details:r.message})}if(this.securityFeatures.hasPacketPadding&&i instanceof ArrayBuffer)try{i=this.removePacketPadding(i)}catch(r){this._debugMode&&this._secureLog("warn","\u26A0\uFE0F Padding removal failed:",{details:r.message})}if(this.securityFeatures.hasAntiFingerprinting&&i instanceof ArrayBuffer)try{i=this.removeAntiFingerprinting(i)}catch(r){this._debugMode&&this._secureLog("warn","\u26A0\uFE0F Anti-fingerprinting removal failed:",{details:r.message})}if(i instanceof ArrayBuffer&&(i=new TextDecoder().decode(i)),typeof i=="string")try{let r=JSON.parse(i);if(r.type==="fake"||r.isFakeTraffic===!0)return this._debugMode&&this._secureLog("warn",`\u{1F3AD} BLOCKED: Final check fake message: ${r.pattern||"unknown"}`),"FAKE_MESSAGE_FILTERED"}catch{}return i}catch(t){return this._secureLog("error","\u274C Critical error in removeSecurityLayers:",{errorType:t?.constructor?.name||"Unknown"}),e}}removeAntiFingerprinting(e){return e}async applySecurityLayers(e,t=!1){try{let i=e;return t?(this.encryptionKey&&typeof i=="string"&&(i=await window.EnhancedSecureCryptoUtils.encryptData(i,this.encryptionKey)),i):(this.securityFeatures.hasNestedEncryption&&this.nestedEncryptionKey&&i instanceof ArrayBuffer&&(i=await this.applyNestedEncryption(i)),this.securityFeatures.hasPacketReordering&&this.reorderingConfig?.enabled&&i instanceof ArrayBuffer&&(i=this.applyPacketReordering(i)),this.securityFeatures.hasPacketPadding&&i instanceof ArrayBuffer&&(i=this.applyPacketPadding(i)),this.securityFeatures.hasAntiFingerprinting&&i instanceof ArrayBuffer&&(i=this.applyAntiFingerprinting(i)),this.encryptionKey&&typeof i=="string"&&(i=await window.EnhancedSecureCryptoUtils.encryptData(i,this.encryptionKey)),i)}catch(i){return this._secureLog("error","\u274C Error in applySecurityLayers:",{errorType:i?.constructor?.name||"Unknown"}),e}}_sanitizeMessageMeta(e){if(!e||typeof e!="object")return null;let t={};if(typeof e.mid=="string"&&e.mid.length>0&&e.mid.length<=64&&(t.mid=e.mid.replace(/[^A-Za-z0-9_-]/g,"").slice(0,64)),e.code===!0&&(t.code=!0),e.once===!0&&(t.once=!0),Number.isFinite(e.onceTtl)){let i=Math.floor(e.onceTtl);i>=1&&i<=3600&&(t.onceTtl=i)}if(Number.isFinite(e.ttl)){let i=Math.floor(e.ttl);i>=5&&i<=86400&&(t.ttl=i)}return Object.keys(t).length?t:null}sendMessageDelete(e){return typeof e!="string"||!e?!1:this.sendSystemMessage({type:s.MESSAGE_TYPES.MESSAGE_DELETE,messageId:e.slice(0,64)})}sendDeliveryReceipt(e){return typeof e!="string"||!e?!1:this.sendSystemMessage({type:s.MESSAGE_TYPES.MESSAGE_RECEIPT,messageId:e.slice(0,64)})}async sendMessage(e,t=null){let i=this._validateInputData(e,"sendMessage");if(!i.isValid){let r=`Input validation failed: ${i.errors.join(", ")}`;throw this._secureLog("error","\u274C Input validation failed in sendMessage",{errors:i.errors,dataType:typeof e,dataLength:e?.length||e?.byteLength||0}),new Error(r)}if(!this._checkRateLimit("sendMessage"))throw new Error("Rate limit exceeded for message sending");if(this._enforceVerificationGate("sendMessage"),!this.dataChannel||this.dataChannel.readyState!=="open")throw new Error("Data channel not ready");try{if(this.encryptionKey&&this.macKey&&this.metadataKey||await this._tryReinitializeEncryptionKeys(),this._secureLog("debug","sendMessage called",{hasDataChannel:!!this.dataChannel,dataChannelReady:this.dataChannel?.readyState==="open",isInitiator:this.isInitiator,isVerified:this.isVerified,connectionReady:this.peerConnection?.connectionState==="connected"}),this._secureLog("debug","\u{1F50D} sendMessage DEBUG",{dataType:typeof i.sanitizedData,isString:typeof i.sanitizedData=="string",isArrayBuffer:i.sanitizedData instanceof ArrayBuffer,dataLength:i.sanitizedData?.length||i.sanitizedData?.byteLength||0}),typeof i.sanitizedData=="string")try{let n=JSON.parse(i.sanitizedData);if(n.type&&n.type.startsWith("file_")){this._secureLog("debug","\u{1F4C1} File message detected - applying full encryption with AAD",{type:n.type});let a=this._createFileMessageAAD(n.type,n.data),o=await this._encryptFileMessage(i.sanitizedData,a);return this.dataChannel.send(o),!0}}catch{}if(typeof i.sanitizedData=="string"){if(typeof this._createMessageAAD!="function")throw new Error("_createMessageAAD method is not available. Manager may not be fully initialized.");let n=this._createMessageAAD("message",{content:i.sanitizedData}),a={type:"message",data:i.sanitizedData,timestamp:Date.now(),aad:n};return t&&typeof t=="object"&&(a.meta=this._sanitizeMessageMeta(t)),await this.sendSecureMessage(a)}this._secureLog("debug","\u{1F510} Applying security layers to non-string data");let r=await this._applySecurityLayersWithLimitedMutex(i.sanitizedData,!1);return this.dataChannel.send(r),!0}catch(r){throw this._secureLog("error","\u274C Failed to send message",{error:r.message,errorType:r.constructor.name}),r}}async _applySecurityLayersWithLimitedMutex(e,t=!1){return this._withMutex("cryptoOperation",async i=>{try{let r=e;return t?(this.encryptionKey&&typeof r=="string"&&(r=await window.EnhancedSecureCryptoUtils.encryptData(r,this.encryptionKey)),r):(this.securityFeatures.hasNestedEncryption&&this.nestedEncryptionKey&&r instanceof ArrayBuffer&&(r=await this.applyNestedEncryption(r)),this.securityFeatures.hasPacketReordering&&this.reorderingConfig?.enabled&&r instanceof ArrayBuffer&&(r=this.applyPacketReordering(r)),this.securityFeatures.hasPacketPadding&&r instanceof ArrayBuffer&&(r=this.applyPacketPadding(r)),this.securityFeatures.hasAntiFingerprinting&&r instanceof ArrayBuffer&&(r=this.applyAntiFingerprinting(r)),this.encryptionKey&&typeof r=="string"&&(r=await window.EnhancedSecureCryptoUtils.encryptData(r,this.encryptionKey)),r)}catch(r){return this._secureLog("error","\u274C Error in applySecurityLayers:",{errorType:r?.constructor?.name||"Unknown"}),e}},3e3)}async sendSystemMessage(e){if(e.type==="verification_request"||e.type==="verification_response"||e.type==="verification_required"||this._enforceVerificationGate("sendSystemMessage",!1),!this.dataChannel||this.dataChannel.readyState!=="open")return this._secureLog("warn","\u26A0\uFE0F Cannot send system message - data channel not ready"),!1;try{let i=JSON.stringify({type:e.type,data:e,timestamp:Date.now()});return this._secureLog("debug","\u{1F527} Sending system message",{type:e.type}),this.dataChannel.send(i),!0}catch(i){return this._secureLog("error","\u274C Failed to send system message:",{errorType:i?.constructor?.name||"Unknown"}),!1}}async processMessage(e){try{if(this._noteInboundActivity?.(),this._secureLog("debug","\uFFFD\uFFFD Processing message",{dataType:typeof e,isArrayBuffer:e instanceof ArrayBuffer,hasData:!!(e?.length||e?.byteLength)}),typeof e=="string")try{let r=JSON.parse(e),n=["file_transfer_start","file_transfer_response","file_chunk","chunk_confirmation","file_transfer_complete","file_transfer_error"];if(r.type==="encrypted_file_message"){this._secureLog("debug","\u{1F4C1} Encrypted file message detected in processMessage");try{let{decryptedData:a,aad:o}=await this._decryptFileMessage(e),c=JSON.parse(a);if(this._secureLog("debug","\u{1F4C1} File message decrypted successfully",{type:c.type,aadMessageType:o.messageType}),this.fileTransferSystem&&typeof this.fileTransferSystem.handleFileMessage=="function"){await this.fileTransferSystem.handleFileMessage(c);return}}catch(a){this._secureLog("error","\u274C Failed to decrypt file message",{error:a.message});return}}if(r.type&&n.includes(r.type)){this._secureLog("warn","\u26A0\uFE0F Unencrypted file message detected - this should not happen in secure mode",{type:r.type}),this._secureLog("error","\u274C Dropping unencrypted file message for security",{type:r.type});return}if(r.type==="enhanced_message"){if(this._secureLog("debug","\u{1F510} Enhanced message detected in processMessage"),!this._checkInboundRateLimit("processMessage:enhanced_message"))return;try{let a=await window.EnhancedSecureCryptoUtils.decryptMessage(r.data,this.encryptionKey,this.macKey,this.metadataKey),o=JSON.parse(a.data);if(a.metadata&&a.metadata.sequenceNumber!==void 0&&!this._validateIncomingSequenceNumber(a.metadata.sequenceNumber,"enhanced_message")){this._secureLog("warn","\u26A0\uFE0F Enhanced message sequence number validation failed - possible replay attack",{received:a.metadata.sequenceNumber,expected:this.expectedSequenceNumber});return}o.type==="message"&&this.onMessage&&o.data&&this.deliverMessageToUI(o.data,"received",o.meta);return}catch(a){this._secureLog("error","\u274C Failed to decrypt enhanced message",{error:a.message});return}}if(r.type===s.MESSAGE_TYPES.MESSAGE){this._secureLog("error","Rejected unencrypted frame in processMessage",{messageType:"message"});return}if(r.type&&s.POST_VERIFICATION_CONTROL_TYPES.has(r.type)){if(!this._enforceVerificationGate("control_frame_receive",!1)){this._secureLog("error","Dropped control frame received before verification",{messageType:r.type});return}let a=s.MESSAGE_TYPES;if(r.type===a.MESSAGE_DELETE){let o=r?.data?.messageId??r?.messageId;if(typeof o=="string"&&o)try{this.onMessageDelete?.(o.slice(0,64))}catch{}return}if(r.type===a.MESSAGE_RECEIPT){let o=r?.data?.messageId??r?.messageId;if(typeof o=="string"&&o)try{this.onMessageDelivered?.(o.slice(0,64))}catch{}return}if([a.CALL_OFFER,a.CALL_ANSWER,a.CALL_ICE,a.CALL_DECLINE,a.CALL_END].includes(r.type)){try{await this._handleCallSignal(r.type,r.data||{})}catch(o){this._secureLog("error","\u274C Call signal handling failed",{errorType:o?.constructor?.name})}return}if([a.ICE_RESTART_OFFER,a.ICE_RESTART_ANSWER,a.ICE_RESTART_REQUEST].includes(r.type)){try{await this._handleIceRestartSignal(r.type,r.data||{})}catch(o){this._secureLog("error","\u274C ICE restart signal handling failed",{errorType:o?.constructor?.name})}return}return}if(r.type&&["heartbeat","verification","verification_response","verification_confirmed","verification_both_confirmed","peer_disconnect","security_upgrade"].includes(r.type)){this.handleSystemMessage(r);return}if(r.type==="fake"){this._secureLog("warn","\u{1F3AD} Fake message blocked in processMessage",{pattern:r.pattern});return}}catch{this._secureLog("error","Rejected malformed (non-JSON) frame in processMessage",{dataLength:typeof e=="string"?e.length:0});return}let t=await this._processEncryptedDataWithLimitedMutex(e);if(t==="FAKE_MESSAGE_FILTERED"||t==="FILE_MESSAGE_FILTERED"||t==="SYSTEM_MESSAGE_FILTERED")return;if(!t){this._secureLog("warn","\u26A0\uFE0F No data returned from removeSecurityLayers");return}let i;if(typeof t=="string")try{let r=JSON.parse(t);if(r.type&&fileMessageTypes.includes(r.type)){this._secureLog("debug","\u{1F4C1} File message detected after decryption",{type:r.type}),this.fileTransferSystem&&await this.fileTransferSystem.handleFileMessage(r);return}if(r.type&&["heartbeat","verification","verification_response","verification_confirmed","verification_both_confirmed","peer_disconnect","security_upgrade"].includes(r.type)){this.handleSystemMessage(r);return}if(r.type==="fake"){this._secureLog("warn",`\u{1F3AD} Post-decryption fake message blocked: ${r.pattern}`);return}r.type==="message"&&r.data?i=r.data:i=t}catch{i=t}else if(t instanceof ArrayBuffer)i=new TextDecoder().decode(t);else if(t&&typeof t=="object"&&t.message)i=t.message;else{this._secureLog("warn","\u26A0\uFE0F Unexpected data type after processing:",{details:typeof t});return}if(i&&i.trim().startsWith("{"))try{let r=JSON.parse(i);if(r.type==="fake"){this._secureLog("warn",`\u{1F3AD} Final fake message check blocked: ${r.pattern}`);return}let n=["file_transfer_start","file_transfer_response","file_chunk","chunk_confirmation","file_transfer_complete","file_transfer_error","heartbeat","verification","verification_response","peer_disconnect","key_rotation_signal","key_rotation_ready","security_upgrade","ice_restart_offer","ice_restart_answer","ice_restart_request"];if(r.type&&n.includes(r.type)){this._secureLog("warn",`\u{1F4C1} Final system/file message check blocked: ${r.type}`);return}}catch{}i&&this._secureLog("error","Rejected unauthenticated payload at the end of processMessage",{messageLength:typeof i=="string"?i.length:0})}catch(t){this._secureLog("error","\u274C Failed to process message:",{errorType:t?.constructor?.name||"Unknown"})}}async _processEncryptedDataWithLimitedMutex(e){return this._withMutex("cryptoOperation",async t=>{this._secureLog("debug","\u{1F510} Processing encrypted data with limited mutex",{operationId:t,dataType:typeof e});try{return await this.removeSecurityLayers(e)}catch(i){return this._secureLog("error","\u274C Error processing encrypted data",{operationId:t,errorType:i.constructor.name}),e}},2e3)}notifySecurityUpdate(){try{this._secureLog("debug","\u{1F512} Notifying about security level update",{isConnected:this.isConnected(),isVerified:this.isVerified,hasKeys:!!(this.encryptionKey&&this.macKey&&this.metadataKey),hasLastCalculation:!!this.lastSecurityCalculation}),this._dispatchAppEvent?.(new CustomEvent("security-level-updated",{detail:{timestamp:Date.now(),manager:"webrtc",webrtcManager:this,isConnected:this.isConnected(),isVerified:this.isVerified,hasKeys:!!(this.encryptionKey&&this.macKey&&this.metadataKey),lastCalculation:this.lastSecurityCalculation}})),setTimeout(()=>{},100),this.lastSecurityCalculation&&this._dispatchAppEvent?.(new CustomEvent("real-security-calculated",{detail:{securityData:this.lastSecurityCalculation,webrtcManager:this,timestamp:Date.now()}}))}catch(e){this._secureLog("error","\u274C Error in notifySecurityUpdate",{error:e.message})}}handleSystemMessage(e){switch(this._secureLog("debug","\u{1F527} Handling system message:",{type:e.type}),e.type){case"heartbeat":this.handleHeartbeat(e);break;case"verification":this.handleVerificationRequest(e.data);break;case"verification_response":this.handleVerificationResponse(e.data);break;case"sas_code":this.handleSASCode(e.data);break;case"verification_confirmed":this.handleVerificationConfirmed(e.data);break;case"verification_both_confirmed":this.handleVerificationBothConfirmed(e.data);break;case"peer_disconnect":this.handlePeerDisconnectNotification(e);break;case"key_rotation_signal":this._secureLog("debug","\u{1F504} Key rotation signal received (ignored for stability)");break;case"key_rotation_ready":this._secureLog("debug","\u{1F504} Key rotation ready signal received (ignored for stability)");break;case"security_upgrade":this._secureLog("debug","\u{1F512} Security upgrade notification received:",{type:e.type});break;default:this._secureLog("debug","\u{1F527} Unknown system message type:",{type:e.type})}}enableStage2Security(){this.sessionConstraints?.hasPacketReordering&&(this.securityFeatures.hasPacketReordering=!0,this.reorderingConfig.enabled=!0),this.sessionConstraints?.hasAntiFingerprinting&&(this.securityFeatures.hasAntiFingerprinting=!0,this.antiFingerprintingConfig.enabled=!0,this.antiFingerprintingConfig.randomizeSizes=!0,this.antiFingerprintingConfig.maskPatterns=!0,this.antiFingerprintingConfig.useRandomHeaders=!0),this.notifySecurityUpgrade(2),setTimeout(()=>{this.calculateAndReportSecurityLevel()},500)}enableStage3Security(){this._secureLog("info","\u{1F512} Enabling Stage 3 features (traffic obfuscation)"),this.sessionConstraints?.hasMessageChunking&&(this.securityFeatures.hasMessageChunking=!0,this.chunkingConfig.enabled=!0),this.sessionConstraints?.hasFakeTraffic&&(this.securityFeatures.hasFakeTraffic=!0,this.fakeTrafficConfig.enabled=!0,this.startFakeTrafficGeneration()),this.notifySecurityUpgrade(3),setTimeout(()=>{this.calculateAndReportSecurityLevel()},500)}enableStage4Security(){if(this._secureLog("info","\u{1F512} Enabling Stage 4 features (maximum safety)"),this.sessionConstraints?.hasDecoyChannels&&this.isConnected()&&this.isVerified){this.securityFeatures.hasDecoyChannels=!0,this.decoyChannelConfig.enabled=!0;try{this.initializeDecoyChannels()}catch(e){this._secureLog("warn","\u26A0\uFE0F Decoy channels initialization failed:",{details:e.message}),this.securityFeatures.hasDecoyChannels=!1,this.decoyChannelConfig.enabled=!1}}this.sessionConstraints?.hasAntiFingerprinting&&(this.antiFingerprintingConfig.randomizeSizes=!0,this.antiFingerprintingConfig.maskPatterns=!0,this.antiFingerprintingConfig.useRandomHeaders=!1),this.notifySecurityUpgrade(4),setTimeout(()=>{this.calculateAndReportSecurityLevel()},500)}forceSecurityUpdate(){setTimeout(()=>{this.calculateAndReportSecurityLevel(),this.notifySecurityUpdate()},100)}getSecurityStatus(){let e=Object.entries(this.securityFeatures).filter(([i,r])=>r===!0).map(([i])=>i);return{stage:4,securityLevel:"maximum",activeFeatures:e,totalFeatures:Object.keys(this.securityFeatures).length,activeFeaturesCount:e.length,activeFeaturesNames:e,sessionConstraints:this.sessionConstraints}}notifySecurityUpgrade(e){let t={1:"Basic Enhanced",2:"Medium Security",3:"High Security",4:"Maximum Security"},i=`\u{1F512} Security upgraded to Stage ${e}: ${t[e]}`;if((!this.securityUpgradeNotificationSent||this.lastSecurityUpgradeStage!==e)&&(this.securityUpgradeNotificationSent=!0,this.lastSecurityUpgradeStage=e,this.onMessage&&this.deliverMessageToUI(i,"system")),this.dataChannel&&this.dataChannel.readyState==="open")try{let n={type:"security_upgrade",stage:e,stageName:t[e],message:i,timestamp:Date.now()};this._secureLog("debug","\u{1F512} Sending security upgrade notification to peer:",{type:n.type,stage:n.stage}),this.dataChannel.send(JSON.stringify(n))}catch(n){this._secureLog("warn","\u26A0\uFE0F Failed to send security upgrade notification to peer:",{details:n.message})}let r=this.getSecurityStatus()}async calculateAndReportSecurityLevel(){try{if(!window.EnhancedSecureCryptoUtils)return this._secureLog("warn","\u26A0\uFE0F EnhancedSecureCryptoUtils not available for security calculation"),null;if(!this.isConnected()||!this.isVerified||!this.encryptionKey||!this.macKey)return this._secureLog("debug","\u26A0\uFE0F WebRTC not ready for security calculation",{connected:this.isConnected(),verified:this.isVerified,hasEncryptionKey:!!this.encryptionKey,hasMacKey:!!this.macKey}),null;this._secureLog("debug","\u{1F50D} Calculating real security level",{managerState:"ready",hasAllKeys:!!(this.encryptionKey&&this.macKey&&this.metadataKey)});let e=await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(this);if(this._secureLog("info","Real security level calculated",{hasSecurityLevel:!!e.level,scoreRange:e.score>80?"high":e.score>50?"medium":"low",checksRatio:`${e.passedChecks}/${e.totalChecks}`,isRealCalculation:e.isRealData}),this.lastSecurityCalculation=e,this._dispatchAppEvent?.(new CustomEvent("real-security-calculated",{detail:{securityData:e,webrtcManager:this,timestamp:Date.now(),source:"calculateAndReportSecurityLevel"}})),e.isRealData&&this.onMessage&&(!this.securityCalculationNotificationSent||this.lastSecurityCalculationLevel!==e.level)){this.securityCalculationNotificationSent=!0,this.lastSecurityCalculationLevel=e.level;let t=`Security Level: ${e.level} (${e.score}%) - ${e.passedChecks}/${e.totalChecks} checks passed`;this.deliverMessageToUI(t,"system")}return e}catch(e){return this._secureLog("error","Failed to calculate real security level",{errorType:e.constructor.name}),null}}async autoEnableSecurityFeatures(){this._secureLog("info","Starting graduated security activation - all features enabled");let e=()=>this.isConnected()&&this.isVerified&&this.connectionAttempts===0&&this.messageQueue.length===0&&this.peerConnection?.connectionState==="connected";await this.calculateAndReportSecurityLevel(),this.notifySecurityUpgrade(1),setTimeout(async()=>{e()&&(this.enableStage2Security(),await this.calculateAndReportSecurityLevel(),setTimeout(async()=>{e()&&(this.enableStage3Security(),await this.calculateAndReportSecurityLevel(),setTimeout(async()=>{e()&&(this.enableStage4Security(),await this.calculateAndReportSecurityLevel())},2e4))},15e3))},1e4)}async establishConnection(){try{await this.initializeEnhancedSecurity(),this.fakeTrafficConfig.enabled&&this.startFakeTrafficGeneration(),this.decoyChannelConfig.enabled&&this.initializeDecoyChannels()}catch(e){throw this._secureLog("error","\u274C Failed to establish enhanced connection:",{errorType:e?.constructor?.name||"Unknown"}),this.onStatusChange("disconnected"),e}}_clearVerificationStates(){try{this.localVerificationConfirmed=!1,this.remoteVerificationConfirmed=!1,this.bothVerificationsConfirmed=!1,this.isVerified=!1,this.verificationCode=null,this.pendingSASCode=null,this.sasValidationAttempts=0,this._verificationUiOpened=!1,this._sasLocalFingerprint=null,this._sasRemoteFingerprint=null,this.keyFingerprint=null,this.expectedDTLSFingerprint=null,this._peerDTLSFingerprint=null,this.connectionId=null,this.processedMessageIds.clear(),this.verificationNotificationSent=!1,this.verificationInitiationSent=!1}catch(e){this._secureLog("error","\u274C Error clearing verification states:",{errorType:e?.constructor?.name||"Unknown"})}}startPeriodicCleanup(){this._secureLog("info","\u{1F527} Periodic cleanup moved to unified scheduler")}async calculateSecurityLevel(){return await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(this)}shouldRotateKeys(){return!this.isConnected()||!this.isVerified?!1:Date.now()-this.lastKeyRotation>this.keyRotationInterval||this.messageCounter%100===0}async rotateKeys(){return this._withMutex("keyOperation",async e=>{if(this._secureLog("info","\u{1F504} Starting key rotation with mutex",{operationId:e}),!this.isConnected()||!this.isVerified)return this._secureLog("warn"," Key rotation aborted - connection not ready",{operationId:e,isConnected:this.isConnected(),isVerified:this.isVerified}),!1;if(this._keySystemState.isRotating)return this._secureLog("warn"," Key rotation already in progress",{operationId:e}),!1;try{this._keySystemState.isRotating=!0,this._keySystemState.lastOperation="rotation",this._keySystemState.lastOperationTime=Date.now();let t={type:"key_rotation_signal",newVersion:this.currentKeyVersion+1,timestamp:Date.now(),operationId:e};if(this.dataChannel&&this.dataChannel.readyState==="open")this.dataChannel.send(JSON.stringify(t));else throw new Error("Data channel not ready for key rotation");return this._hardWipeOldKeys(),new Promise(i=>{this.pendingRotation={newVersion:this.currentKeyVersion+1,operationId:e,resolve:i,timeout:setTimeout(()=>{this._secureLog("error"," Key rotation timeout",{operationId:e}),this._keySystemState.isRotating=!1,this.pendingRotation=null,i(!1)},1e4)}})}catch(t){return this._secureLog("error"," Key rotation failed in critical section",{operationId:e,errorType:t.constructor.name}),this._keySystemState.isRotating=!1,!1}},1e4)}cleanupOldKeys(){let e=Date.now(),t=s.LIMITS.MAX_KEY_AGE,i=0;for(let[r,n]of this.oldKeys.entries())e-n.timestamp>t&&(n.encryptionKey&&this._secureWipeMemory(n.encryptionKey,"pfs_cleanup_wipe"),n.macKey&&this._secureWipeMemory(n.macKey,"pfs_cleanup_wipe"),n.metadataKey&&this._secureWipeMemory(n.metadataKey,"pfs_cleanup_wipe"),n.encryptionKey=null,n.macKey=null,n.metadataKey=null,n.keyFingerprint=null,this.oldKeys.delete(r),i++,this._secureLog("info","\u{1F9F9} Old PFS keys hard wiped and cleaned up",{version:r,age:Math.round((e-n.timestamp)/1e3)+"s",timestamp:Date.now()}));i>0&&this._secureLog("info",`PFS cleanup completed: ${i} keys hard wiped`,{timestamp:Date.now()})}getKeysForVersion(e){let t=this.oldKeys.get(e);return t&&t.encryptionKey&&t.macKey&&t.metadataKey?{encryptionKey:t.encryptionKey,macKey:t.macKey,metadataKey:t.metadataKey}:e===this.currentKeyVersion&&this.encryptionKey&&this.macKey&&this.metadataKey?{encryptionKey:this.encryptionKey,macKey:this.macKey,metadataKey:this.metadataKey}:(window.EnhancedSecureCryptoUtils.secureLog.log("error","No valid keys found for version",{requestedVersion:e,currentVersion:this.currentKeyVersion,availableVersions:Array.from(this.oldKeys.keys())}),null)}_hasTurnServer(){return(this._config.webrtc.iceServers||[]).some(e=>(Array.isArray(e.urls)?e.urls:[e.urls]).some(i=>typeof i=="string"&&i.toLowerCase().startsWith("turn:")))}_buildPeerConnectionConfig(){let e=this._isRelayOnlyMode(),t={iceServers:this._config.webrtc.iceServers,iceCandidatePoolSize:10,bundlePolicy:"balanced"};return e&&(t.iceTransportPolicy="relay"),t}_summarizeIceServerConfig(e=[]){let t={serverCount:0,stun:0,turn:0,turns:0,hasCredentials:!1};for(let i of e||[]){t.serverCount+=1,(i?.username||i?.credential)&&(t.hasCredentials=!0);let r=Array.isArray(i?.urls)?i.urls:[i?.urls];for(let n of r){let a=String(n||"").toLowerCase();a.startsWith("stun:")&&(t.stun+=1),a.startsWith("turn:")&&(t.turn+=1),a.startsWith("turns:")&&(t.turns+=1)}}return t}_isRelayOnlyMode(){return this._config.webrtc.privacyMode==="relay-only"}_setRelayOnlyMode(e){let t=e===!0;this._config.webrtc.privacyMode=t?"relay-only":"standard",this._config.webrtc.relayOnly=t}_warnIfTurnMissing(){if(this._ipLeakWarningShown)return;this._ipLeakWarningShown=!0;let e=this._isRelayOnlyMode(),t=this._hasTurnServer(),i=null;e&&!t?i="Privacy mode is relay-only, but no TURN server is configured. Relay-only mode cannot connect until TURN is configured; STUN alone does not hide IP addresses.":!e&&!t?i="Privacy warning: relay-only mode is disabled and no TURN server is configured. Direct WebRTC connections may expose host or server-reflexive IP addresses; STUN alone does not provide IP protection.":e||(i="Privacy warning: relay-only mode is disabled. Direct WebRTC connectivity may expose host or server-reflexive IP addresses even when TURN is available."),i&&this.deliverMessageToUI(i,"system")}createPeerConnection(){this._sessionAlive=!0;let e=this._buildPeerConnectionConfig();this._warnIfTurnMissing(),console.info("[SecureBit ICE] peer connection config",this._summarizeIceServerConfig(e.iceServers)),this.peerConnection=new RTCPeerConnection(e),this._callAudioSender=null,this._callVideoSender=null,this.peerConnection.onconnectionstatechange=()=>{let t=this.peerConnection.connectionState;console.info("[SecureBit ICE] connection state changed",{connectionState:t,iceConnectionState:this.peerConnection.iceConnectionState,iceGatheringState:this.peerConnection.iceGatheringState}),t==="connected"&&!this.isVerified?this._notifyVerificationReadyIfPossible():t==="connected"&&this.isVerified?this._onPathRecovered()||this.onStatusChange("connected"):t==="disconnected"?this.intentionalDisconnect?(this.onStatusChange("disconnected"),setTimeout(()=>this.disconnect(),100)):this.isVerified?this._onPathDegraded("ice_disconnected"):console.warn(`[SecureBit ICE] State is ${t} but not verified yet. Keeping session open for manual exchange.`):t==="closed"?(this._resetReconnectState(),this.onStatusChange("disconnected"),this._clearVerificationStates(),this.intentionalDisconnect&&setTimeout(()=>this.disconnect(),100)):t==="failed"?(this._collectIceFailureDiagnostics().then(i=>{console.warn("[SecureBit ICE] failure diagnostics",i),this._noteIceFailureDiagnostics(i)}),this.isVerified?this._onPathLost("ice_failed"):console.warn("[SecureBit ICE] State is failed but not verified yet. Keeping session open for manual exchange.")):this.isReconnecting()&&(t==="connecting"||t==="new")||this.onStatusChange(t)},this.peerConnection.oniceconnectionstatechange=()=>{console.info("[SecureBit ICE] ICE connection state changed",{connectionState:this.peerConnection.connectionState,iceConnectionState:this.peerConnection.iceConnectionState,iceGatheringState:this.peerConnection.iceGatheringState})},this.peerConnection.onicecandidateerror=t=>{console.warn("[SecureBit ICE] ICE candidate error",{url:t.url,errorCode:t.errorCode,errorText:t.errorText})},this.peerConnection.ontrack=t=>{try{this._refreshRemoteStream()}catch(i){this._secureLog("warn","\u26A0\uFE0F ontrack handling failed",{errorType:i?.constructor?.name})}},this.peerConnection.ondatachannel=t=>{t.channel.label==="securechat"?(this.dataChannel=t.channel,this.setupDataChannel(t.channel)):t.channel.label==="heartbeat"&&(this.heartbeatChannel=t.channel)}}setupDataChannel(e){this.dataChannel=e;let t=!1,i=async()=>{if(!t){t=!0;try{this.dataChannel&&typeof this.dataChannel.bufferedAmountLowThreshold=="number"&&(this.dataChannel.bufferedAmountLowThreshold=1024*1024)}catch{}if(this._handshakeMode==="sbq2")try{await this._runSbq2KeyExchange()}catch(r){this._secureLog("error","SBQ2 key exchange failed to start",{errorType:r?.constructor?.name||"Unknown"}),this._sbq2Abort("start_failed","The secure handshake could not be started. Please try connecting again.");return}try{await this.establishConnection(),this.initializeFileTransfer()}catch(r){this._secureLog("error","Error in establishConnection:",{errorType:r?.constructor?.name||"Unknown"})}if(this.pendingSASCode&&this.dataChannel&&this.dataChannel.readyState==="open")try{let r={type:"sas_code",data:{code:this.pendingSASCode,timestamp:Date.now(),verificationMethod:"SAS",securityLevel:"MITM_PROTECTION_REQUIRED"}};this.dataChannel.send(JSON.stringify(r)),this.pendingSASCode=null}catch{}else this.pendingSASCode;this.isVerified?(this.onStatusChange("connected"),this.processMessageQueue(),setTimeout(async()=>{await this.calculateAndReportSecurityLevel(),this.autoEnableSecurityFeatures(),this.notifySecurityUpdate()},500)):(this._notifyVerificationReadyIfPossible(),this.initiateVerification()),this.startHeartbeat()}};this.dataChannel.onopen=i,this.dataChannel.readyState==="open"&&Promise.resolve().then(()=>i()).catch(r=>{this._secureLog("error","Deferred data channel open handling failed",{errorType:r?.constructor?.name||"Unknown"})}),this.dataChannel.onclose=()=>{this._resetReconnectState?.(),this._teardownRecoveryLifecycleListeners?.(),this.intentionalDisconnect?(this.onStatusChange("disconnected"),this._clearVerificationStates(),this.connectionClosedNotificationSent||(this.connectionClosedNotificationSent=!0,this.deliverMessageToUI("\u{1F50C} Enhanced secure connection closed","system"))):(this.onStatusChange("disconnected"),this._clearVerificationStates(),this.connectionClosedNotificationSent||(this.connectionClosedNotificationSent=!0,this.deliverMessageToUI("\u{1F50C} Enhanced secure connection closed. Check connection status.","system"))),this._wipeEphemeralKeys(),this.stopHeartbeat(),this.isVerified=!1},this.dataChannel.onmessage=async r=>{try{if(this._noteInboundActivity?.(),typeof r.data=="string")try{let n=JSON.parse(r.data),a=["file_transfer_start","file_transfer_response","file_chunk","chunk_confirmation","file_transfer_complete","file_transfer_error"];if(n.type&&a.includes(n.type)){if(!this._enforceVerificationGate("file_message_receive",!1)){this._secureLog("error","Dropped file message received before verification",{messageType:n.type});return}if(!this.fileTransferSystem)try{if(this.isVerified&&this.dataChannel&&this.dataChannel.readyState==="open"){this.initializeFileTransfer();let o=0,c=30;for(;!this.fileTransferSystem&&osetTimeout(l,100)),o++}}catch(o){this._secureLog("error","Failed to initialize file transfer system for receiver:",{errorType:o?.constructor?.name||"Unknown"})}if(this.fileTransferSystem){await this.fileTransferSystem.handleFileMessage(n);return}this._secureLog("warn","\u26A0\uFE0F File transfer system not ready, attempting lazy init...");try{if(await this._ensureFileTransferReady(),this.fileTransferSystem){await this.fileTransferSystem.handleFileMessage(n);return}}catch(o){this._secureLog("error","Lazy init of file transfer failed:",{errorType:o?.message||o?.constructor?.name||"Unknown"})}this._secureLog("error","No file transfer system available for:",{errorType:n.type?.constructor?.name||"Unknown"});return}if(n.type&&s.POST_VERIFICATION_CONTROL_TYPES.has(n.type)){if(!this._enforceVerificationGate("control_frame_receive",!1)){this._secureLog("error","Dropped control frame received before verification",{messageType:n.type});return}let o=s.MESSAGE_TYPES;if(n.type===o.MESSAGE_DELETE){let c=n?.data?.messageId??n?.messageId;if(typeof c=="string"&&c)try{this.onMessageDelete?.(c.slice(0,64))}catch{}return}if(n.type===o.MESSAGE_RECEIPT){let c=n?.data?.messageId??n?.messageId;if(typeof c=="string"&&c)try{this.onMessageDelivered?.(c.slice(0,64))}catch{}return}if([o.CALL_OFFER,o.CALL_ANSWER,o.CALL_ICE,o.CALL_DECLINE,o.CALL_END].includes(n.type)){try{await this._handleCallSignal(n.type,n.data||{})}catch{}return}if([o.ICE_RESTART_OFFER,o.ICE_RESTART_ANSWER,o.ICE_RESTART_REQUEST].includes(n.type)){try{await this._handleIceRestartSignal(n.type,n.data||{})}catch(c){this._secureLog("error","\u274C ICE restart signal handling failed",{errorType:c?.constructor?.name})}return}return}if(n.type===s.MESSAGE_TYPES.KEY_BLOB||n.type===s.MESSAGE_TYPES.KEY_PROOF){await this._sbq2HandleHandshakeFrame(n);return}if(n.type&&["heartbeat","verification","verification_response","verification_confirmed","verification_both_confirmed","sas_code","peer_disconnect","security_upgrade"].includes(n.type)){this.handleSystemMessage(n);return}if(n.type===s.MESSAGE_TYPES.RATCHET_MESSAGE){await this._processRatchetMessage(n);return}if(n.type==="enhanced_message"&&n.data){await this._processEnhancedMessageWithoutMutex(n);return}this._secureLog("error","Rejected unencrypted frame on the chat channel",{messageType:typeof n.type=="string"?n.type.slice(0,32):typeof n.type});return}catch{this._secureLog("error","Rejected malformed (non-JSON) frame on the chat channel",{dataLength:typeof r.data=="string"?r.data.length:0});return}else r.data instanceof ArrayBuffer&&await this._processBinaryDataWithoutMutex(r.data)}catch(n){this._secureLog("error","Failed to process message in onmessage:",{errorType:n?.constructor?.name||"Unknown"})}}}async _processBinaryDataWithoutMutex(e){try{if(!this._checkInboundRateLimit("binary_message"))return;let t=e;if(this.securityFeatures.hasNestedEncryption&&this.nestedEncryptionKey&&t instanceof ArrayBuffer&&t.byteLength>12)try{t=await this.removeNestedEncryption(t)}catch{this._secureLog("warn","Nested decryption failed, continuing with original data")}if(this.securityFeatures.hasPacketPadding&&t instanceof ArrayBuffer)try{t=this.removePacketPadding(t)}catch{this._secureLog("warn","Packet padding removal failed, continuing with original data")}if(this.securityFeatures.hasAntiFingerprinting&&t instanceof ArrayBuffer)try{t=this.removeAntiFingerprinting(t)}catch{this._secureLog("warn","Anti-fingerprinting removal failed, continuing with original data")}if(t instanceof ArrayBuffer){let i=new TextDecoder().decode(t);try{let r=JSON.parse(i);if(r.type==="fake"||r.isFakeTraffic===!0)return}catch{}this._secureLog("error","Rejected unauthenticated binary frame on the chat channel",{byteLength:e?.byteLength||0})}}catch(t){this._secureLog("error","Error processing binary data:",{errorType:t?.constructor?.name||"Unknown"})}}async _processRatchetMessage(e){try{if(!this._checkInboundRateLimit("ratchet_message"))return;if(!this.isRatchetActive()){this._secureLog("error","Received a ratchet message but no ratchet is active");return}if(typeof e?.h!="string"||typeof e?.c!="string"){this._secureLog("error","Malformed ratchet message frame");return}let t=await this._ratchet.decrypt(e.h,e.c);try{let i=JSON.parse(t);if(i.type==="fake"||i.isFakeTraffic===!0)return;if(i&&i.type==="message"&&typeof i.data=="string"){this.deliverMessageToUI(i.data,"received",i.meta);return}}catch{}this.deliverMessageToUI(t,"received")}catch(t){this._secureLog("error","Failed to decrypt ratchet message",{errorType:t?.constructor?.name||"Unknown"})}}async _processEnhancedMessageWithoutMutex(e){try{if(!this._checkInboundRateLimit("enhanced_message"))return;if(!this.encryptionKey||!this.macKey||!this.metadataKey){this._secureLog("error","Missing encryption keys for enhanced message");return}let t=await window.EnhancedSecureCryptoUtils.decryptMessage(e.data,this.encryptionKey,this.macKey,this.metadataKey);if(!this._validateIncomingSequenceNumber(t?.sequenceNumber,"enhanced_message")){this._secureLog("error","Rejected chat message failing anti-replay validation",{messageId:t?.messageId?"present":"absent"});return}if(t&&t.message){try{let i=JSON.parse(t.message);if(i.type==="fake"||i.isFakeTraffic===!0)return;if(i&&i.type==="message"&&typeof i.data=="string"){this.onMessage&&this.deliverMessageToUI(i.data,"received",i.meta);return}}catch{}this.onMessage&&this.deliverMessageToUI(t.message,"received")}else this._secureLog("warn","No message content in decrypted result")}catch(t){this._secureLog("error","Error processing enhanced message:",{errorType:t?.constructor?.name||"Unknown"})}}_generateOperationId(){return`op_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}async _acquireMutex(e,t,i=5e3){let r=`_${e}Mutex`,n=this[r];if(!n)throw this._secureLog("error",`Unknown mutex: ${e}`,{mutexPropertyName:r,availableMutexes:this._getAvailableMutexes(),operationId:t}),new Error(`Unknown mutex: ${e}. Available: ${this._getAvailableMutexes().join(", ")}`);if(!t||typeof t!="string")throw new Error("Invalid operation ID for mutex acquisition");return new Promise((a,o)=>{(()=>{if(n.lockId===t){this._secureLog("warn",`Mutex '${e}' already locked by same operation`,{operationId:t}),a();return}if(!n.locked)n.locked=!0,n.lockId=t,n.lockTime=Date.now(),this._secureLog("debug",`Mutex '${e}' acquired atomically`,{operationId:t,lockTime:n.lockTime}),n.lockTimeout=setTimeout(()=>{this._handleMutexTimeout(e,t,i)},i),a();else{let l={resolve:a,reject:o,operationId:t,timestamp:Date.now(),timeout:setTimeout(()=>{let h=n.queue.findIndex(u=>u.operationId===t);h!==-1&&(n.queue.splice(h,1),o(new Error(`Mutex acquisition timeout for '${e}'`)))},i)};n.queue.push(l),this._secureLog("debug",`Operation queued for mutex '${e}'`,{operationId:t,queueLength:n.queue.length,currentLockId:n.lockId})}})()})}_releaseMutex(e,t){if(!e||typeof e!="string")throw new Error("Invalid mutex name provided for release");if(!t||typeof t!="string")throw new Error("Invalid operation ID provided for mutex release");let i=`_${e}Mutex`,r=this[i];if(!r)throw this._secureLog("error",`Unknown mutex for release: ${e}`,{mutexPropertyName:i,availableMutexes:this._getAvailableMutexes(),operationId:t}),new Error(`Unknown mutex for release: ${e}`);if(r.lockId!==t)throw this._secureLog("error","CRITICAL: Invalid mutex release attempt - potential race condition",{mutexName:e,expectedLockId:r.lockId,providedOperationId:t,mutexState:{locked:r.locked,lockTime:r.lockTime,queueLength:r.queue.length}}),new Error(`Invalid mutex release attempt for '${e}': expected '${r.lockId}', got '${t}'`);if(!r.locked)throw this._secureLog("error","CRITICAL: Attempting to release unlocked mutex",{mutexName:e,operationId:t,mutexState:{locked:r.locked,lockId:r.lockId,lockTime:r.lockTime}}),new Error(`Attempting to release unlocked mutex: ${e}`);try{r.lockTimeout&&(clearTimeout(r.lockTimeout),r.lockTimeout=null);let n=r.lockTime?Date.now()-r.lockTime:0;r.locked=!1,r.lockId=null,r.lockTime=null,this._secureLog("debug",`Mutex released successfully: ${e}`,{operationId:t,lockDuration:n,queueLength:r.queue.length}),this._processNextInQueue(e)}catch(n){throw this._secureLog("error","Error during mutex release queue processing",{mutexName:e,operationId:t,errorType:n.constructor.name,errorMessage:n.message}),r.locked=!1,r.lockId=null,r.lockTime=null,r.lockTimeout=null,n}}_processNextInQueue(e){let t=this[`_${e}Mutex`];if(!t){this._secureLog("error",`Mutex not found for queue processing: ${e}`);return}if(t.queue.length===0)return;if(t.locked){this._secureLog("warn",`Mutex '${e}' is still locked, skipping queue processing`,{lockId:t.lockId,queueLength:t.queue.length});return}let i=t.queue.shift();if(!i){this._secureLog("warn",`Empty queue item for mutex '${e}'`);return}if(!i.operationId||!i.resolve||!i.reject){this._secureLog("error",`Invalid queue item structure for mutex '${e}'`,{hasOperationId:!!i.operationId,hasResolve:!!i.resolve,hasReject:!!i.reject});return}try{i.timeout&&clearTimeout(i.timeout),this._secureLog("debug",`Processing next operation in queue for mutex '${e}'`,{operationId:i.operationId,queueRemaining:t.queue.length,timestamp:Date.now()}),setTimeout(async()=>{try{await this._acquireMutex(e,i.operationId,5e3),this._secureLog("debug",`Queued operation acquired mutex '${e}'`,{operationId:i.operationId,acquisitionTime:Date.now()}),i.resolve()}catch(r){this._secureLog("error",`Queued operation failed to acquire mutex '${e}'`,{operationId:i.operationId,errorType:r.constructor.name,errorMessage:r.message,timestamp:Date.now()}),i.reject(new Error(`Queue processing failed for '${e}': ${r.message}`)),setTimeout(()=>{this._processNextInQueue(e)},50)}},10)}catch(r){this._secureLog("error",`Critical error during queue processing for mutex '${e}'`,{operationId:i.operationId,errorType:r.constructor.name,errorMessage:r.message});try{i.reject(new Error(`Queue processing critical error: ${r.message}`))}catch(n){this._secureLog("error","Failed to reject queue item",{originalError:r.message,rejectError:n.message})}setTimeout(()=>{this._processNextInQueue(e)},100)}}_getAvailableMutexes(){let e=[],t=Object.getOwnPropertyNames(this);for(let i of t)if(i.endsWith("Mutex")&&i.startsWith("_")){let r=i.slice(1,-5);e.push(r)}return e}async _withMutex(e,t,i=5e3){let r=this._generateOperationId();if(!this._validateMutexSystem())throw this._secureLog("error","Mutex system not properly initialized",{operationId:r,mutexName:e}),new Error("Mutex system not properly initialized. Call _initializeMutexSystem() first.");let n=this[`_${e}Mutex`];if(!n)throw new Error(`Mutex '${e}' not found`);let a=!1;try{await this._acquireMutex(e,r,i),a=!0;let o=`${e}Operations`;this._operationCounters&&this._operationCounters[o]!==void 0&&this._operationCounters[o]++;let c=await t(r);return c===void 0&&t.name!=="cleanup"&&this._secureLog("warn","Mutex operation returned undefined result",{operationId:r,mutexName:e,operationName:t.name}),c}catch(o){throw this._secureLog("error","Error in mutex operation",{operationId:r,mutexName:e,errorType:o.constructor.name,errorMessage:o.message,mutexAcquired:a,mutexState:n?{locked:n.locked,lockId:n.lockId,queueLength:n.queue.length}:"null"}),e==="keyOperation"&&this._handleKeyOperationError(o,r),(o.message.includes("timeout")||o.message.includes("race condition"))&&this._emergencyUnlockAllMutexes("errorHandler"),o}finally{if(a)try{await this._releaseMutex(e,r),n.locked&&n.lockId===r&&(this._secureLog("error","Mutex release verification failed",{operationId:r,mutexName:e}),n.locked=!1,n.lockId=null,n.lockTimeout=null)}catch(o){this._secureLog("error","Error releasing mutex in finally block",{operationId:r,mutexName:e,releaseErrorType:o.constructor.name,releaseErrorMessage:o.message}),n.locked=!1,n.lockId=null,n.lockTimeout=null}}}_validateMutexSystem(){let e=["keyOperation","cryptoOperation","connectionOperation"];for(let t of e){let i=`_${t}Mutex`,r=this[i];if(!r||typeof r!="object")return this._secureLog("error",`Missing or invalid mutex: ${t}`,{mutexPropertyName:i,mutexType:typeof r}),!1;let n=["locked","queue","lockId","lockTimeout"];for(let a of n)if(!(a in r))return this._secureLog("error",`Mutex ${t} missing property: ${a}`),!1}return!0}_emergencyRecoverMutexSystem(){this._secureLog("warn","Emergency mutex system recovery initiated");try{if(this._emergencyUnlockAllMutexes("emergencyRecovery"),this._initializeMutexSystem(),!this._validateMutexSystem())throw new Error("Mutex system validation failed after recovery");return this._secureLog("info","Mutex system recovered successfully with validation"),!0}catch(e){this._secureLog("error","Failed to recover mutex system",{errorType:e.constructor.name,errorMessage:e.message});try{return this._initializeMutexSystem(),this._secureLog("warn","Forced mutex system re-initialization completed"),!0}catch(t){return this._secureLog("error","CRITICAL: Forced re-initialization also failed",{originalError:e.message,reinitError:t.message}),!1}}}async _generateEncryptionKeys(){return this._withMutex("keyOperation",async e=>{this._secureLog("info","Generating encryption keys with atomic mutex",{operationId:e});let t=this._keySystemState;if(t.isInitializing){this._secureLog("warn","Key generation already in progress, waiting for completion",{operationId:e,lastOperation:t.lastOperation,lastOperationTime:t.lastOperationTime});let i=0,r=50;for(;t.isInitializing&&isetTimeout(n,100)),i++;if(t.isInitializing)throw new Error("Key generation timeout - operation still in progress after 5 seconds")}try{t.isInitializing=!0,t.lastOperation="generation",t.lastOperationTime=Date.now(),t.operationId=e,this._secureLog("debug","Atomic key generation state set",{operationId:e,timestamp:t.lastOperationTime});let i=null,r=null;try{if(i=await this._generateEphemeralECDHKeys(),!i||!i.privateKey||!i.publicKey)throw new Error("Ephemeral ECDH key pair validation failed");if(!this._validateKeyPairConstantTime(i))throw new Error("Ephemeral ECDH keys are not valid CryptoKey instances");this._secureLog("debug","Ephemeral ECDH keys generated and validated for PFS",{operationId:e,privateKeyType:i.privateKey.algorithm?.name,publicKeyType:i.publicKey.algorithm?.name,isEphemeral:!0})}catch(n){this._secureLog("error","Ephemeral ECDH key generation failed",{operationId:e,errorType:n.constructor.name}),this._throwSecureError(n,"ephemeral_ecdh_key_generation")}try{if(r=await window.EnhancedSecureCryptoUtils.generateECDSAKeyPair(),!r||!r.privateKey||!r.publicKey)throw new Error("ECDSA key pair validation failed");if(!this._validateKeyPairConstantTime(r))throw new Error("ECDSA keys are not valid CryptoKey instances");this._secureLog("debug","ECDSA keys generated and validated",{operationId:e,privateKeyType:r.privateKey.algorithm?.name,publicKeyType:r.publicKey.algorithm?.name})}catch(n){this._secureLog("error","ECDSA key generation failed",{operationId:e,errorType:n.constructor.name}),this._throwSecureError(n,"ecdsa_key_generation")}if(!i||!r)throw new Error("One or both key pairs failed to generate");return this._enableSecurityFeaturesAfterKeyGeneration(i,r),this._secureLog("info","Encryption keys generated successfully with atomic protection",{operationId:e,hasECDHKeys:!!(i?.privateKey&&i?.publicKey),hasECDSAKeys:!!(r?.privateKey&&r?.publicKey),generationTime:Date.now()-t.lastOperationTime}),{ecdhKeyPair:i,ecdsaKeyPair:r}}catch(i){throw this._secureLog("error","Key generation failed, resetting state",{operationId:e,errorType:i.constructor.name}),i}finally{t.isInitializing=!1,t.operationId=null,this._secureLog("debug","Key generation state reset",{operationId:e})}})}_enableSecurityFeaturesAfterKeyGeneration(e,t){try{e&&e.privateKey&&e.publicKey&&(this.securityFeatures.hasEncryption=!0,this.securityFeatures.hasECDH=!0,this._secureLog("info","ECDH encryption features enabled")),t&&t.privateKey&&t.publicKey&&(this.securityFeatures.hasECDSA=!0,this._secureLog("info","ECDSA signature features enabled")),this.securityFeatures.hasEncryption&&(this.securityFeatures.hasMetadataProtection=!0,this.securityFeatures.hasEnhancedReplayProtection=!0,this.securityFeatures.hasNonExtractableKeys=!0,this._secureLog("info","Additional encryption-dependent features enabled")),e&&this.ephemeralKeyPairs.size>0&&(this.securityFeatures.hasPFS=!0,this._secureLog("info","Perfect Forward Secrecy enabled with ephemeral keys")),this._secureLog("info","Security features updated after key generation",{hasEncryption:this.securityFeatures.hasEncryption,hasECDH:this.securityFeatures.hasECDH,hasECDSA:this.securityFeatures.hasECDSA,hasMetadataProtection:this.securityFeatures.hasMetadataProtection,hasEnhancedReplayProtection:this.securityFeatures.hasEnhancedReplayProtection,hasNonExtractableKeys:this.securityFeatures.hasNonExtractableKeys,hasPFS:this.securityFeatures.hasPFS})}catch(i){this._secureLog("error","Failed to enable security features after key generation",{errorType:i.constructor.name,errorMessage:i.message})}}_emergencyUnlockAllMutexes(e="unknown"){let t=["keyOperation","cryptoOperation","connectionOperation","emergencyRecovery","systemShutdown","errorHandler"];if(!t.includes(e))throw this._secureLog("error","UNAUTHORIZED emergency mutex unlock attempt",{callerContext:e,authorizedCallers:t,timestamp:Date.now()}),new Error(`Unauthorized emergency mutex unlock attempt by: ${e}`);let i=["keyOperation","cryptoOperation","connectionOperation"];this._secureLog("error","EMERGENCY: Unlocking all mutexes with authorization and state cleanup",{callerContext:e,timestamp:Date.now()});let r=0,n=0;if(i.forEach(a=>{let o=this[`_${a}Mutex`];if(o)try{o.lockTimeout&&clearTimeout(o.lockTimeout);let c={locked:o.locked,lockId:o.lockId,lockTime:o.lockTime,queueLength:o.queue.length};o.locked=!1,o.lockId=null,o.lockTimeout=null,o.lockTime=null;let l=0;o.queue.forEach(h=>{try{h.reject&&typeof h.reject=="function"&&(h.reject(new Error(`Emergency mutex unlock for ${a} by ${e}`)),l++)}catch(u){this._secureLog("warn","Failed to reject queue item during emergency unlock",{mutexName:a,errorType:u.constructor.name})}}),o.queue=[],r++,this._secureLog("debug",`Emergency unlocked mutex: ${a}`,{previousState:c,queueRejectCount:l,callerContext:e})}catch(c){n++,this._secureLog("error",`Error during emergency unlock of mutex: ${a}`,{errorType:c.constructor.name,errorMessage:c.message,callerContext:e})}}),this._keySystemState)try{let a={...this._keySystemState};this._keySystemState.isInitializing=!1,this._keySystemState.isRotating=!1,this._keySystemState.isDestroying=!1,this._keySystemState.operationId=null,this._keySystemState.concurrentOperations=0,this._secureLog("debug","Emergency reset key system state",{previousState:a,callerContext:e})}catch(a){this._secureLog("error","Error resetting key system state during emergency unlock",{errorType:a.constructor.name,errorMessage:a.message,callerContext:e})}this._secureLog("info","Emergency mutex unlock completed",{callerContext:e,unlockedCount:r,errorCount:n,totalMutexes:i.length,timestamp:Date.now()}),setTimeout(()=>{this._validateMutexSystemAfterEmergencyUnlock()},100)}_handleKeyOperationError(e,t){this._secureLog("error","Key operation error detected, initiating recovery",{operationId:t,errorType:e.constructor.name,errorMessage:e.message}),this._keySystemState&&(this._keySystemState.isInitializing=!1,this._keySystemState.isRotating=!1,this._keySystemState.isDestroying=!1,this._keySystemState.operationId=null),this.ecdhKeyPair=null,this.ecdsaKeyPair=null,this.encryptionKey=null,this.macKey=null,this.metadataKey=null,(e.message.includes("timeout")||e.message.includes("race condition"))&&(this._secureLog("warn","Race condition or timeout detected, triggering emergency recovery"),this._emergencyRecoverMutexSystem())}_generateSecureIV(e=12,t="general"){if(this._ivTrackingSystem.emergencyMode)throw this._secureLog("error","CRITICAL: IV generation blocked - emergency mode active due to IV reuse"),new Error("IV generation blocked - emergency mode active");let i=0,r=100;for(;io.toString(16).padStart(2,"0")).join("");if(this._ivTrackingSystem.usedIVs.has(a)){if(this._ivTrackingSystem.collisionCount++,this._secureLog("error","CRITICAL: IV reuse detected!",{context:t,attempt:i,collisionCount:this._ivTrackingSystem.collisionCount,ivString:a.substring(0,16)+"..."}),this._ivTrackingSystem.collisionCount>5)throw this._ivTrackingSystem.emergencyMode=!0,this._secureLog("error","CRITICAL: Emergency mode activated due to excessive IV reuse"),new Error("Emergency mode: Excessive IV reuse detected");continue}if(!this._validateIVEntropy(n)){if(this._ivTrackingSystem.entropyValidation.entropyFailures++,this._secureLog("warn","Low entropy IV detected",{context:t,attempt:i,entropyFailures:this._ivTrackingSystem.entropyValidation.entropyFailures}),this._ivTrackingSystem.entropyValidation.entropyFailures>10)throw this._ivTrackingSystem.emergencyMode=!0,this._secureLog("error","CRITICAL: Emergency mode activated due to low entropy IVs"),new Error("Emergency mode: Low entropy IVs detected");continue}return this._ivTrackingSystem.usedIVs.add(a),this._ivTrackingSystem.ivHistory.set(a,{timestamp:Date.now(),context:t,attempt:i}),this.sessionId&&(this._ivTrackingSystem.sessionIVs.has(this.sessionId)||this._ivTrackingSystem.sessionIVs.set(this.sessionId,new Set),this._ivTrackingSystem.sessionIVs.get(this.sessionId).add(a)),this._validateRNGQuality(),this._secureLog("debug","Secure IV generated",{context:t,attempt:i,ivSize:e,totalIVs:this._ivTrackingSystem.usedIVs.size}),n}throw this._secureLog("error",`Failed to generate unique IV after ${r} attempts`,{context:t,totalIVs:this._ivTrackingSystem.usedIVs.size}),new Error(`Failed to generate unique IV after ${r} attempts`)}_validateIVEntropy(e){this._ivTrackingSystem.entropyValidation.entropyTests++;let t=new Array(256).fill(0);for(let w=0;w0){let g=t[w]/n;r-=g*Math.log2(g)}i.shannon=r;let o=Math.max(...t)/n;i.min=-Math.log2(o);let c=0;for(let w=0;w<256;w++)if(t[w]>0){let g=t[w]/n;c+=g*g}i.collision=-Math.log2(c);let l=Array.from(e).map(w=>String.fromCharCode(w)).join(""),h=this._estimateCompressedLength(l);i.compression=(1-h/n)*8,i.quantum=this._calculateQuantumResistantEntropy(e);let u=this._detectAdvancedSuspiciousPatterns(e),p=this._ivTrackingSystem.entropyValidation.minEntropy,S=i.shannon>=p&&i.min>=p*.8&&i.collision>=p*.9&&i.compression>=p*.7&&i.quantum>=p*.6&&!u;return S||this._secureLog("warn","Enhanced IV entropy validation failed",{shannon:i.shannon.toFixed(2),min:i.min.toFixed(2),collision:i.collision.toFixed(2),compression:i.compression.toFixed(2),quantum:i.quantum.toFixed(2),minThreshold:p,hasSuspiciousPatterns:u}),S}_estimateCompressedLength(e){let t=0,i=0;for(;ir&&(r=o,n=i-a)}r>=3?(t+=3,i+=r):(t+=1,i+=1)}return t}_calculateQuantumResistantEntropy(e){let t=0;this._detectQuantumVulnerablePatterns(e)&&(t-=2);let r=this._analyzeBitDistribution(e);t+=r.score;let n=this._detectPeriodicity(e);return t-=n*.5,Math.max(0,Math.min(8,t))}_detectQuantumVulnerablePatterns(e){let t=[[0,0,0,0,0,0,0,0],[255,255,255,255,255,255,255,255],[0,1,0,1,0,1,0,1],[1,0,1,0,1,0,1,0]];for(let i of t)for(let r=0;r<=e.length-i.length;r++){let n=!0;for(let a=0;a>>0).toString(2).split("1").length-1;let r=(i-t)/i,n=t/i,a=Math.abs(.5-n);return{score:Math.max(0,8-a*16),zeroRatio:r,oneRatio:n,deviation:a}}_detectPeriodicity(e){if(e.length<16)return 0;let t=0;for(let i=2;i<=e.length/2;i++){let r=0,n=0;for(let a=0;a0){let a=r/n;t=Math.max(t,a)}}return t}_detectAdvancedSuspiciousPatterns(e){let t=[[0,1,2,3,4,5,6,7],[255,254,253,252,251,250,249,248],[0,0,0,0,0,0,0,0],[255,255,255,255,255,255,255,255],[0,255,0,255,0,255,0,255],[255,0,255,0,255,0,255,0]];for(let n of t)for(let a=0;a<=e.length-n.length;a++){let o=!0;for(let c=0;cn<3).length>e.length*.3}_calculateLocalEntropy(e){let i=[];for(let r=0;r<=e.length-8;r++){let n=e.slice(r,r+8),a={};for(let c of n)a[c]=(a[c]||0)+1;let o=0;for(let c of Object.values(a)){let l=c/8;o-=l*Math.log2(l)}i.push(o)}return i}_detectSuspiciousIVPatterns(e){let t=e.every(n=>n===0),i=e.every(n=>n===255);if(t||i)return!0;let r=0;for(let n=1;n=3)return!0;for(let n=2;n<=Math.floor(e.length/2);n++)for(let a=0;a<=e.length-n*2;a++){let o=e.slice(a,a+n),c=e.slice(a+n,a+n*2);if(o.every((l,h)=>l===c[h]))return!0}return!1}async _cleanupOldIVs(){let e=Date.now(),t=18e5,i=0,r=[];if(this._ivTrackingSystem.ivHistory.size>this._ivTrackingSystem.maxIVHistorySize){let n=Array.from(this._ivTrackingSystem.ivHistory.entries()),a=n.slice(0,n.length-this._ivTrackingSystem.maxIVHistorySize);for(let[o]of a)r.push(o),i++,r.length>=100&&(this._processCleanupBatch(r),r.length=0)}for(let[n,a]of this._ivTrackingSystem.ivHistory.entries())e-a.timestamp>t&&(r.push(n),i++,r.length>=100&&(this._processCleanupBatch(r),r.length=0));r.length>0&&this._processCleanupBatch(r);for(let[n,a]of this._ivTrackingSystem.sessionIVs.entries())if(a.size>this._ivTrackingSystem.maxSessionIVs){let o=Array.from(a),c=o.slice(0,o.length-this._ivTrackingSystem.maxSessionIVs);for(let l of c)a.delete(l),this._ivTrackingSystem.usedIVs.delete(l),this._ivTrackingSystem.ivHistory.delete(l),i++}i>50&&await this._performNaturalCleanup(),i>0&&this._secureLog("debug",`Enhanced cleanup: ${i} old IVs removed`,{cleanedCount:i,remainingIVs:this._ivTrackingSystem.usedIVs.size,remainingHistory:this._ivTrackingSystem.ivHistory.size,memoryPressure:this._calculateMemoryPressure()})}_processCleanupBatch(e){for(let t of e)this._ivTrackingSystem.usedIVs.delete(t),this._ivTrackingSystem.ivHistory.delete(t)}_calculateMemoryPressure(){let e=this._ivTrackingSystem.usedIVs.size,t=this._resourceLimits.maxIVHistory;return Math.min(100,Math.floor(e/t*100))}_getIVTrackingStats(){return{totalIVs:this._ivTrackingSystem.usedIVs.size,collisionCount:this._ivTrackingSystem.collisionCount,entropyTests:this._ivTrackingSystem.entropyValidation.entropyTests,entropyFailures:this._ivTrackingSystem.entropyValidation.entropyFailures,rngTests:this._ivTrackingSystem.rngValidation.testsPerformed,weakRngDetected:this._ivTrackingSystem.rngValidation.weakRngDetected,emergencyMode:this._ivTrackingSystem.emergencyMode,sessionCount:this._ivTrackingSystem.sessionIVs.size,lastCleanup:this._lastIVCleanupTime||0}}_resetIVTrackingSystem(){this._secureLog("warn","Resetting IV tracking system"),this._ivTrackingSystem.usedIVs.clear(),this._ivTrackingSystem.ivHistory.clear(),this._ivTrackingSystem.sessionIVs.clear(),this._ivTrackingSystem.collisionCount=0,this._ivTrackingSystem.entropyValidation.entropyTests=0,this._ivTrackingSystem.entropyValidation.entropyFailures=0,this._ivTrackingSystem.rngValidation.testsPerformed=0,this._ivTrackingSystem.rngValidation.weakRngDetected=!1,this._ivTrackingSystem.emergencyMode=!1,this._secureLog("info","IV tracking system reset completed")}_validateRNGQuality(){let e=Date.now();if(this._ivTrackingSystem.rngValidation.testsPerformed%1e3===0)try{let t=[];for(let n=0;n<100;n++)t.push(crypto.getRandomValues(new Uint8Array(12)));let i=t.map(n=>Array.from(n).map(a=>a.toString(16).padStart(2,"0")).join("")),r=new Set(i);r.size<95&&(this._ivTrackingSystem.rngValidation.weakRngDetected=!0,this._secureLog("error","CRITICAL: Weak RNG detected in validation test",{uniqueIVs:r.size,totalTests:t.length})),this._ivTrackingSystem.rngValidation.lastValidation=e}catch(t){this._secureLog("error","RNG validation failed",{errorType:t.constructor.name})}this._ivTrackingSystem.rngValidation.testsPerformed++}_handleMutexTimeout(e,t,i){let r=this[`_${e}Mutex`];if(!r){this._secureLog("error",`Mutex '${e}' not found during timeout handling`);return}if(r.lockId!==t){this._secureLog("warn",`Timeout for different operation ID on mutex '${e}'`,{expectedOperationId:t,actualLockId:r.lockId,locked:r.locked});return}if(!r.locked){this._secureLog("warn",`Timeout for already unlocked mutex '${e}'`,{operationId:t});return}try{let n=r.lockTime?Date.now()-r.lockTime:0;this._secureLog("warn",`Mutex '${e}' auto-released due to timeout`,{operationId:t,lockDuration:n,timeout:i,queueLength:r.queue.length}),r.locked=!1,r.lockId=null,r.lockTimeout=null,r.lockTime=null,setTimeout(()=>{try{this._processNextInQueue(e)}catch(a){this._secureLog("error",`Error processing queue after timeout for mutex '${e}'`,{errorType:a.constructor.name,errorMessage:a.message})}},10)}catch(n){this._secureLog("error",`Critical error during mutex timeout handling for '${e}'`,{operationId:t,errorType:n.constructor.name,errorMessage:n.message});try{this._emergencyUnlockAllMutexes("timeoutHandler")}catch(a){this._secureLog("error","Emergency unlock failed during timeout handling",{originalError:n.message,emergencyError:a.message})}}}_validateMutexSystemAfterEmergencyUnlock(){let e=["keyOperation","cryptoOperation","connectionOperation"],t=0;this._secureLog("info","Validating mutex system after emergency unlock"),e.forEach(i=>{let r=this[`_${i}Mutex`];if(!r){t++,this._secureLog("error",`Mutex '${i}' not found after emergency unlock`);return}r.locked&&(t++,this._secureLog("error",`Mutex '${i}' still locked after emergency unlock`,{lockId:r.lockId,lockTime:r.lockTime})),r.lockId!==null&&(t++,this._secureLog("error",`Mutex '${i}' still has lock ID after emergency unlock`,{lockId:r.lockId})),r.lockTimeout!==null&&(t++,this._secureLog("error",`Mutex '${i}' still has timeout after emergency unlock`)),r.queue.length>0&&(t++,this._secureLog("error",`Mutex '${i}' still has queue items after emergency unlock`,{queueLength:r.queue.length}))}),this._keySystemState&&(this._keySystemState.isInitializing||this._keySystemState.isRotating||this._keySystemState.isDestroying)&&(t++,this._secureLog("error","Key system state not properly reset after emergency unlock",{isInitializing:this._keySystemState.isInitializing,isRotating:this._keySystemState.isRotating,isDestroying:this._keySystemState.isDestroying})),t===0?this._secureLog("info","Mutex system validation passed after emergency unlock"):(this._secureLog("error","Mutex system validation failed after emergency unlock",{validationErrors:t}),setTimeout(()=>{this._emergencyRecoverMutexSystem()},1e3))}_getMutexSystemDiagnostics(){let e={timestamp:Date.now(),systemValid:this._validateMutexSystem(),mutexes:{},counters:{...this._operationCounters},keySystemState:{...this._keySystemState}};return["keyOperation","cryptoOperation","connectionOperation"].forEach(i=>{let r=`_${i}Mutex`,n=this[r];n?e.mutexes[i]={locked:n.locked,lockId:n.lockId,queueLength:n.queue.length,hasTimeout:!!n.lockTimeout}:e.mutexes[i]={error:"not_found"}}),e}async createSecureOffer(){return this._withMutex("connectionOperation",async e=>{this._secureLog("info","Creating secure offer with mutex",{operationId:e,connectionAttempts:this.connectionAttempts,currentState:this.peerConnection?.connectionState||"none"});try{if(this._resetNotificationFlags(),!this._checkRateLimit())throw new Error("Connection rate limit exceeded. Please wait before trying again.");this.connectionAttempts=0,this.sessionSalt=window.EnhancedSecureCryptoUtils.generateSalt(),this._secureLog("debug","Session salt generated",{operationId:e,saltLength:this.sessionSalt.length,isValidSalt:Array.isArray(this.sessionSalt)&&this.sessionSalt.length===64});let t=await this._generateEncryptionKeys();if(this.ecdhKeyPair=t.ecdhKeyPair,this.ecdsaKeyPair=t.ecdsaKeyPair,!this.ecdhKeyPair?.privateKey||!this.ecdhKeyPair?.publicKey)throw new Error("Failed to generate valid ECDH key pair");if(!this.ecdsaKeyPair?.privateKey||!this.ecdsaKeyPair?.publicKey)throw new Error("Failed to generate valid ECDSA key pair");let i=await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(await crypto.subtle.exportKey("spki",this.ecdhKeyPair.publicKey)),r=await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(await crypto.subtle.exportKey("spki",this.ecdsaKeyPair.publicKey));if(!i||!r)throw new Error("Failed to generate key fingerprints");this._secureLog("info","Generated unique key pairs for MITM protection",{operationId:e,hasECDHFingerprint:!!i,hasECDSAFingerprint:!!r,fingerprintLength:i.length,timestamp:Date.now()});let n=await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(this.ecdhKeyPair.publicKey,this.ecdsaKeyPair.privateKey,"ECDH"),a=await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(this.ecdsaKeyPair.publicKey,this.ecdsaKeyPair.privateKey,"ECDSA");if(!n||typeof n!="object")throw this._secureLog("error","CRITICAL: ECDH key export failed - invalid object structure",{operationId:e}),new Error("CRITICAL SECURITY FAILURE: ECDH key export validation failed - hard abort required");if(!n.keyData||!n.signature)throw this._secureLog("error","CRITICAL: ECDH key export incomplete - missing keyData or signature",{operationId:e,hasKeyData:!!n.keyData,hasSignature:!!n.signature}),new Error("CRITICAL SECURITY FAILURE: ECDH key export incomplete - hard abort required");if(!a||typeof a!="object")throw this._secureLog("error","CRITICAL: ECDSA key export failed - invalid object structure",{operationId:e}),new Error("CRITICAL SECURITY FAILURE: ECDSA key export validation failed - hard abort required");if(!a.keyData||!a.signature)throw this._secureLog("error","CRITICAL: ECDSA key export incomplete - missing keyData or signature",{operationId:e,hasKeyData:!!a.keyData,hasSignature:!!a.signature}),new Error("CRITICAL SECURITY FAILURE: ECDSA key export incomplete - hard abort required");this._updateSecurityFeatures({hasEncryption:!0,hasECDH:!0,hasECDSA:!0,hasMutualAuth:!0,hasMetadataProtection:!0,hasEnhancedReplayProtection:!0,hasNonExtractableKeys:!0,hasRateLimiting:!0,hasEnhancedValidation:!0,hasPFS:!0}),this.isInitiator=!0,this.onStatusChange("connecting"),this.createPeerConnection(),this.dataChannel=this.peerConnection.createDataChannel("securechat",{ordered:!0}),this.setupDataChannel(this.dataChannel),this._secureLog("debug","Data channel created",{operationId:e,channelLabel:this.dataChannel.label,channelOrdered:this.dataChannel.ordered});let o=await this.peerConnection.createOffer({offerToReceiveAudio:!1,offerToReceiveVideo:!1});await this.peerConnection.setLocalDescription(o);try{let m=this._extractDTLSFingerprintFromSDP(o.sdp);this.expectedDTLSFingerprint=m,this._secureLog("info","Generated DTLS fingerprint for out-of-band verification",{fingerprint:m,context:"offer_creation"}),this.deliverMessageToUI(`DTLS fingerprint ready for verification: ${m}`,"system")}catch(m){this._secureLog("error","Failed to extract DTLS fingerprint from offer",{error:m.message})}let c=Date.now(),l=await this.waitForIceGathering(),h=this._summarizeIceCandidatesInSDP(this.peerConnection.localDescription?.sdp),u=h.total;if(!l&&u===0)throw this.deliverMessageToUI("No network candidates could be gathered, so the invitation would not be usable. This usually means a VPN or firewall is blocking STUN/TURN. Try turning the VPN off, switching network, or adding your own TURN server in Advanced network settings.","system"),new Error("ICE gathering produced no candidates \u2014 check VPN/firewall or configure a TURN server");if(this._secureLog(u>0?"info":"warn","ICE candidates captured for offer export",{candidateSummary:h,iceGatheringState:this.peerConnection.iceGatheringState,iceGatheringDurationMs:Date.now()-c,iceGatheringCompleted:l}),this._logIceCandidateDiagnostics("offer export",this.peerConnection.localDescription?.sdp,{iceGatheringState:this.peerConnection.iceGatheringState,iceGatheringDurationMs:Date.now()-c,iceGatheringCompleted:l}),l||this.deliverMessageToUI("ICE gathering timed out before completion, but available candidates were included in the invitation. Connectivity may still fail on restrictive networks.","system"),u===0&&this.deliverMessageToUI("No ICE candidates were gathered for the invitation yet. The peer connection may fail unless network candidates become available.","system"),this._secureLog("debug","ICE gathering completed",{operationId:e,iceGatheringState:this.peerConnection.iceGatheringState,connectionState:this.peerConnection.connectionState}),this.verificationCode=window.EnhancedSecureCryptoUtils.generateVerificationCode(),!this.verificationCode||this.verificationCode.lengthm.toString(16).padStart(2,"0")).join(""),!this.sessionId||this.sessionId.length!==s.SIZES.SESSION_ID_LENGTH*2)throw new Error("Failed to generate valid session ID");this.connectionId=Array.from(crypto.getRandomValues(new Uint8Array(8))).map(m=>m.toString(16).padStart(2,"0")).join(""),this._storePendingOfferContext();let S={level:"MAXIMUM",score:100,color:"green",details:"All security features enabled by default",passedChecks:10,totalChecks:10,isRealData:!0},w=Date.now(),g={t:"offer",s:this.peerConnection.localDescription.sdp,v:s.PROTOCOL_VERSION,ts:w,e:n,d:a,sl:this.sessionSalt,si:this.sessionId,ci:this.connectionId,vc:this.verificationCode,ac:p,slv:"MAX",dr:s.RATCHET_VERSION,kf:{e:i.substring(0,12),d:r.substring(0,12)}};try{let m=this.validateEnhancedOfferData(g)}catch(m){throw new Error(`Offer package validation error: ${m.message}`)}if(this._secureLog("info","Enhanced secure offer created successfully",{operationId:e,version:g.version,hasECDSA:!0,hasMutualAuth:!0,hasSessionId:!!g.sessionId,securityLevel:S.level,timestamp:w,capabilitiesCount:10}),this._dispatchAppEvent?.(new CustomEvent("new-connection",{detail:{type:"offer",timestamp:w,securityLevel:S.level,operationId:e}})),s.SBQ2_SEND_ENABLED){this._latchHandshakeMode("sbq2");let{text:m}=await this._sbq2BuildDescriptor(le.OFFER);return{t:"offer",sbq2:m}}return this._latchHandshakeMode("sb1"),g}catch(t){throw this._secureLog("error","Enhanced secure offer creation failed in critical section",{operationId:e,errorType:t.constructor.name,errorMessage:t.message,phase:this._determineErrorPhase(t),connectionAttempts:this.connectionAttempts}),this._cleanupFailedOfferCreation(),this.onStatusChange("disconnected"),t}},6e4)}_determineErrorPhase(e){let t=e.message.toLowerCase();return t.includes("rate limit")?"rate_limiting":t.includes("key pair")||t.includes("generate")?"key_generation":t.includes("fingerprint")?"fingerprinting":t.includes("export")||t.includes("signature")?"key_export":t.includes("peer connection")?"webrtc_setup":t.includes("offer")||t.includes("sdp")?"sdp_creation":t.includes("verification")?"verification_setup":t.includes("session")?"session_setup":t.includes("validation")?"package_validation":"unknown"}_cleanupFailedOfferCreation(){try{this._secureCleanupCryptographicMaterials(),this.peerConnection&&(this.peerConnection.close(),this.peerConnection=null),this.dataChannel&&(this.dataChannel.close(),this.dataChannel=null),this.isInitiator=!1,this.isVerified=!1,this._updateSecurityFeatures({hasEncryption:!1,hasECDH:!1,hasECDSA:!1,hasMutualAuth:!1,hasMetadataProtection:!1,hasEnhancedReplayProtection:!1,hasNonExtractableKeys:!1,hasEnhancedValidation:!1,hasPFS:!1}),this._forceGarbageCollection().catch(e=>{this._secureLog("error","Cleanup failed during offer cleanup",{errorType:e?.constructor?.name||"Unknown"})}),this._secureLog("debug","Failed offer creation cleanup completed with secure memory wipe")}catch(e){this._secureLog("error","Error during offer creation cleanup",{errorType:e.constructor.name,errorMessage:e.message})}}_updateSecurityFeatures(e){let t={...this.securityFeatures};try{Object.assign(this.securityFeatures,e),this._secureLog("debug","Security features updated",{updatedCount:Object.keys(e).length,totalFeatures:Object.keys(this.securityFeatures).length})}catch(i){throw this.securityFeatures=t,this._secureLog("error","Security features update failed, rolled back",{errorType:i.constructor.name}),i}}async _createSbq2Answer(e){return this._withMutex("connectionOperation",async t=>{try{if(this._resetNotificationFlags(),!this._checkRateLimit())throw new Error("Connection rate limit exceeded. Please wait before trying again.");this._latchHandshakeMode("sbq2");let i=Ki(String(e.sbq2)),r=this._sbq2AdoptRemoteDescriptor(i,le.OFFER),{sdp:n}=Di(r);this.isInitiator=!1,this.onStatusChange("connecting");let a=await this._generateEncryptionKeys();if(this.ecdhKeyPair=a.ecdhKeyPair,this.ecdsaKeyPair=a.ecdsaKeyPair,!this.ecdhKeyPair?.privateKey||!this.ecdsaKeyPair?.privateKey)throw new Error("Failed to generate valid key pairs");this.createPeerConnection(),this._peerDTLSFingerprint=Array.from(r.fingerprint,l=>l.toString(16).padStart(2,"0").toUpperCase()).join(":"),await this.peerConnection.setRemoteDescription({type:"offer",sdp:n}),await this.peerConnection.setLocalDescription(await this.peerConnection.createAnswer({offerToReceiveAudio:!1,offerToReceiveVideo:!1})),this.expectedDTLSFingerprint=this._extractDTLSFingerprintFromSDP(this.peerConnection.localDescription.sdp),await this.waitForIceGathering();let o=async l=>new Uint8Array(await crypto.subtle.digest("SHA-256",l)),{text:c}=await this._sbq2BuildDescriptor(le.ANSWER,{bindingTag:await Fi(o,i)});return this._dispatchAppEvent?.(new CustomEvent("new-connection",{detail:{type:"answer",timestamp:Date.now(),operationId:t}})),{t:"answer",sbq2:c}}catch(i){throw this._secureLog("error","SBQ2 answer creation failed",{operationId:t,errorType:i?.constructor?.name||"Unknown"}),this.onStatusChange("disconnected"),i}},6e4)}async createSecureAnswer(e){return e&&typeof e.sbq2=="string"?this._createSbq2Answer(e):this._withMutex("connectionOperation",async t=>{this._secureLog("info","Creating secure answer with mutex",{operationId:t,hasOfferData:!!e,offerType:e?.type,offerVersion:e?.version,offerTimestamp:e?.timestamp});try{if(this._resetNotificationFlags(),this._secureLog("debug","Starting enhanced offer validation",{operationId:t,hasOfferData:!!e,offerType:e?.type,hasECDHKey:!!e?.ecdhPublicKey,hasECDSAKey:!!e?.ecdsaPublicKey,hasSalt:!!e?.salt}),!this.validateEnhancedOfferData(e))throw new Error("Invalid connection data format - failed enhanced validation");if(!window.EnhancedSecureCryptoUtils.rateLimiter.checkConnectionRate(this.rateLimiterId))throw new Error("Connection rate limit exceeded. Please wait before trying again.");let i=e.ts||e.timestamp,r=e.v||e.version;if(!i||!r)throw new Error("Missing required security fields in offer data \u2013 possible MITM attack");let n=Date.now()-i,a=18e5;if(n>a)throw this._secureLog("error","Offer data is too old - possible replay attack",{operationId:t,offerAge:Math.round(n/1e3),maxAllowedAge:Math.round(a/1e3),timestamp:e.timestamp}),this.onAnswerError&&this.onAnswerError("replay_attack","Offer data is too old \u2013 possible replay attack"),new Error("Offer data is too old \u2013 possible replay attack");let o=r;if(o!==s.PROTOCOL_VERSION)throw this._secureLog("warn","Protocol version mismatch detected",{operationId:t,expectedVersion:s.PROTOCOL_VERSION,receivedVersion:o}),new Error(`Version mismatch: expected protocol ${s.PROTOCOL_VERSION}, received ${o}`);if(this.sessionSalt=e.sl||e.salt,this._peerSupportsRatchet=e.dr===s.RATCHET_VERSION,!Array.isArray(this.sessionSalt))throw new Error("Invalid session salt format - must be array");let c=64;if(this.sessionSalt.length!==c)throw new Error(`Invalid session salt length: expected ${c}, got ${this.sessionSalt.length}`);let l=await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(this.sessionSalt);this._secureLog("info","Session salt validated successfully",{operationId:t,saltLength:this.sessionSalt.length,saltFingerprint:l.substring(0,8)});let h=await this._generateEncryptionKeys();if(this.ecdhKeyPair=h.ecdhKeyPair,this.ecdsaKeyPair=h.ecdsaKeyPair,!(this.ecdhKeyPair?.privateKey instanceof CryptoKey))throw this._secureLog("error","Local ECDH private key is not a CryptoKey",{operationId:t,hasKeyPair:!!this.ecdhKeyPair,privateKeyType:typeof this.ecdhKeyPair?.privateKey,privateKeyAlgorithm:this.ecdhKeyPair?.privateKey?.algorithm?.name}),new Error("Local ECDH private key is not a valid CryptoKey");let u;try{let x=e.d||e.ecdsaPublicKey;u=await crypto.subtle.importKey("spki",new Uint8Array(x.keyData),{name:"ECDSA",namedCurve:"P-384"},!1,["verify"])}catch(x){this._throwSecureError(x,"ecdsa_key_import")}let p;try{let x=e.e||e.ecdhPublicKey;p=await window.EnhancedSecureCryptoUtils.importSignedPublicKey(x,u,"ECDH")}catch(x){this._secureLog("error","Failed to import signed ECDH public key",{operationId:t,errorType:x.constructor.name}),this._throwSecureError(x,"ecdh_key_import")}if(!(p instanceof CryptoKey))throw this._secureLog("error","Peer ECDH public key is not a CryptoKey",{operationId:t,publicKeyType:typeof p,publicKeyAlgorithm:p?.algorithm?.name}),new Error("Peer ECDH public key is not a valid CryptoKey");this.peerPublicKey=p;let S;try{this._secureLog("debug","About to call deriveSharedKeys",{operationId:t,privateKeyType:typeof this.ecdhKeyPair.privateKey,publicKeyType:typeof p,saltLength:this.sessionSalt?.length,privateKeyAlgorithm:this.ecdhKeyPair.privateKey?.algorithm?.name,publicKeyAlgorithm:p?.algorithm?.name}),S=await window.EnhancedSecureCryptoUtils.deriveSharedKeys(this.ecdhKeyPair.privateKey,p,this.sessionSalt),this._secureLog("debug","deriveSharedKeys completed successfully",{operationId:t,hasMessageKey:!!S.messageKey,hasMacKey:!!S.macKey,hasPfsKey:!!S.pfsKey,hasMetadataKey:!!S.metadataKey,hasFingerprint:!!S.fingerprint})}catch(x){this._secureLog("error","Failed to derive shared keys",{operationId:t,errorType:x.constructor.name,errorMessage:x.message,errorStack:x.stack,privateKeyType:typeof this.ecdhKeyPair.privateKey,publicKeyType:typeof p,saltLength:this.sessionSalt?.length,privateKeyAlgorithm:this.ecdhKeyPair.privateKey?.algorithm?.name,publicKeyAlgorithm:p?.algorithm?.name}),this._throwSecureError(x,"key_derivation")}if(await this._setEncryptionKeys(S.messageKey,S.macKey,S.metadataKey,S.fingerprint),await this._initializeRatchet(S,!1),!(this.encryptionKey instanceof CryptoKey)||!(this.macKey instanceof CryptoKey)||!(this.metadataKey instanceof CryptoKey))throw this._secureLog("error","Invalid key types after derivation",{operationId:t,encryptionKeyType:typeof this.encryptionKey,macKeyType:typeof this.macKey,metadataKeyType:typeof this.metadataKey}),new Error("Invalid key types after derivation");this.verificationCode=e.vc||e.verificationCode||null,this._secureLog("info","Encryption keys derived and set successfully",{operationId:t,hasEncryptionKey:!!this.encryptionKey,hasMacKey:!!this.macKey,hasMetadataKey:!!this.metadataKey,hasKeyFingerprint:!!this.keyFingerprint,mitmProtection:"enabled",signatureVerified:!0}),this._updateSecurityFeatures({hasEncryption:!0,hasECDH:!0,hasECDSA:!0,hasMutualAuth:!0,hasMetadataProtection:!0,hasEnhancedReplayProtection:!0,hasNonExtractableKeys:!0,hasRateLimiting:!0,hasEnhancedValidation:!0,hasPFS:!0}),this.currentKeyVersion=0,this.lastKeyRotation=Date.now(),this.keyVersions.set(0,{salt:this.sessionSalt,timestamp:this.lastKeyRotation,messageCount:0});let w;if(e.authChallenge)try{w=await window.EnhancedSecureCryptoUtils.createAuthProof(e.authChallenge,this.ecdsaKeyPair.privateKey,this.ecdsaKeyPair.publicKey)}catch(x){this._secureLog("error","Failed to create authentication proof",{operationId:t,errorType:x.constructor.name}),this._throwSecureError(x,"authentication_proof_creation")}else this._secureLog("warn","No auth challenge in offer - mutual auth disabled",{operationId:t});if(this.isInitiator=!1,this.onStatusChange("connecting"),this.onKeyExchange(this.keyFingerprint),this.createPeerConnection(),this.strictDTLSValidation)try{this._peerDTLSFingerprint=this._extractDTLSFingerprintFromSDP(e.sdp)}catch(x){this._secureLog("warn","Could not extract peer DTLS fingerprint from offer",{error:x.message,context:"offer_validation"})}else this._secureLog("info","DTLS fingerprint validation disabled - proceeding without validation");try{this._secureLog("debug","Setting remote description from offer",{operationId:t,sdpLength:e.sdp?.length||0}),await this.peerConnection.setRemoteDescription(new RTCSessionDescription({type:"offer",sdp:e.s||e.sdp})),this._logIceCandidateDiagnostics("remote offer applied",this.peerConnection.remoteDescription?.sdp,{signalingState:this.peerConnection.signalingState}),this._warnIfRemoteCandidatesNeedRelay("offer",this.peerConnection.remoteDescription?.sdp),this._secureLog("debug","Remote description set successfully",{operationId:t,signalingState:this.peerConnection.signalingState})}catch(x){this._secureLog("error","Failed to set remote description",{error:x.message,operationId:t}),this._throwSecureError(x,"webrtc_remote_description")}this._secureLog("debug","Remote description set successfully",{operationId:t,connectionState:this.peerConnection.connectionState,signalingState:this.peerConnection.signalingState});let g;try{g=await this.peerConnection.createAnswer({offerToReceiveAudio:!1,offerToReceiveVideo:!1})}catch(x){this._throwSecureError(x,"webrtc_create_answer")}try{await this.peerConnection.setLocalDescription(g)}catch(x){this._throwSecureError(x,"webrtc_local_description")}try{let x=this._extractDTLSFingerprintFromSDP(g.sdp);this.expectedDTLSFingerprint=x,this._secureLog("info","Generated DTLS fingerprint for out-of-band verification",{fingerprint:x,context:"answer_creation"}),this.deliverMessageToUI(`DTLS fingerprint ready for verification: ${x}`,"system")}catch(x){this._secureLog("error","Failed to extract DTLS fingerprint from answer",{error:x.message})}try{let x=this._extractDTLSFingerprintFromSDP(e.s||e.sdp),ue=this.expectedDTLSFingerprint,ne=this._decodeKeyFingerprint(this.keyFingerprint);this.verificationCode=await this._computeSAS(ne,ue,x),this._setSASMaterialReady(ue,x)}catch(x){throw this._secureLog("error","SAS computation failed in createSecureAnswer (Answer side)",{errorType:x?.constructor?.name||"Unknown"}),new Error(`SAS computation failed: ${x.message}`)}let m=Date.now(),I=await this.waitForIceGathering(),b=this._summarizeIceCandidatesInSDP(this.peerConnection.localDescription?.sdp),D=b.total;if(!I&&D===0)throw this.deliverMessageToUI("No network candidates could be gathered, so the response would not be usable. This usually means a VPN or firewall is blocking STUN/TURN. Try turning the VPN off, switching network, or adding your own TURN server in Advanced network settings.","system"),new Error("ICE gathering produced no candidates \u2014 check VPN/firewall or configure a TURN server");this._secureLog(D>0?"info":"warn","ICE candidates captured for answer export",{candidateSummary:b,iceGatheringState:this.peerConnection.iceGatheringState,iceGatheringDurationMs:Date.now()-m,iceGatheringCompleted:I}),this._logIceCandidateDiagnostics("answer export",this.peerConnection.localDescription?.sdp,{iceGatheringState:this.peerConnection.iceGatheringState,iceGatheringDurationMs:Date.now()-m,iceGatheringCompleted:I}),I||this.deliverMessageToUI("ICE gathering timed out before completion, but available candidates were included in the response. Connectivity may still fail on restrictive networks.","system"),D===0&&this.deliverMessageToUI("No ICE candidates were gathered for the response yet. The peer connection may fail unless network candidates become available.","system"),this._secureLog("debug","ICE gathering completed for answer",{operationId:t,iceGatheringState:this.peerConnection.iceGatheringState,connectionState:this.peerConnection.connectionState});let _=await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(this.ecdhKeyPair.publicKey,this.ecdsaKeyPair.privateKey,"ECDH"),R=await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(this.ecdsaKeyPair.publicKey,this.ecdsaKeyPair.privateKey,"ECDSA");if(!_||typeof _!="object")throw this._secureLog("error","CRITICAL: ECDH key export failed - invalid object structure",{operationId:t}),new Error("CRITICAL SECURITY FAILURE: ECDH key export validation failed - hard abort required");if(!_.keyData||!_.signature)throw this._secureLog("error","CRITICAL: ECDH key export incomplete - missing keyData or signature",{operationId:t,hasKeyData:!!_.keyData,hasSignature:!!_.signature}),new Error("CRITICAL SECURITY FAILURE: ECDH key export incomplete - hard abort required");if(!R||typeof R!="object")throw this._secureLog("error","CRITICAL: ECDSA key export failed - invalid object structure",{operationId:t}),new Error("CRITICAL SECURITY FAILURE: ECDSA key export validation failed - hard abort required");if(!R.keyData||!R.signature)throw this._secureLog("error","CRITICAL: ECDSA key export incomplete - missing keyData or signature",{operationId:t,hasKeyData:!!R.keyData,hasSignature:!!R.signature}),new Error("CRITICAL SECURITY FAILURE: ECDSA key export incomplete - hard abort required");let E={level:"MAXIMUM",score:100,color:"green",details:"All security features enabled by default",passedChecks:10,totalChecks:10,isRealData:!0},C=Date.now(),M={t:"answer",s:this.peerConnection.localDescription.sdp,v:s.PROTOCOL_VERSION,ts:C,e:_,d:R,ap:w,slv:"MAX",dr:s.RATCHET_VERSION,sc:{sf:l.substring(0,12),kd:!0,ma:!0}},v=M.s||M.sdp,q=M.e||M.ecdhPublicKey,O=M.d||M.ecdsaPublicKey;if(!v||!q||!O)throw new Error("Generated answer package is incomplete");return this._secureLog("info","Enhanced secure answer created successfully",{operationId:t,version:M.version,hasECDSA:!0,hasMutualAuth:!!w,hasSessionConfirmation:!!M.sessionConfirmation,securityLevel:E.level,timestamp:C,processingTime:C-e.timestamp}),this._dispatchAppEvent?.(new CustomEvent("new-connection",{detail:{type:"answer",timestamp:C,securityLevel:E.level,operationId:t}})),setTimeout(async()=>{try{let x=await this.calculateAndReportSecurityLevel();x&&(this.notifySecurityUpdate(),this._secureLog("info","Post-connection security level calculated",{operationId:t,level:x.level}))}catch(x){this._secureLog("error","Error calculating post-connection security",{operationId:t,errorType:x.constructor.name})}},1e3),setTimeout(async()=>{(!this.lastSecurityCalculation||this.lastSecurityCalculation.score<50)&&(this._secureLog("info","Retrying security calculation",{operationId:t}),await this.calculateAndReportSecurityLevel(),this.notifySecurityUpdate())},3e3),this.notifySecurityUpdate(),M}catch(i){throw this._secureLog("error","Enhanced secure answer creation failed in critical section",{operationId:t,errorType:i.constructor.name,errorMessage:i.message,phase:this._determineAnswerErrorPhase(i),offerAge:e?.timestamp?Date.now()-e.timestamp:"unknown"}),this._cleanupFailedAnswerCreation(),this.onStatusChange("disconnected"),this.onAnswerError&&(i.message.includes("too old")||i.message.includes("replay")?this.onAnswerError("replay_attack",i.message):i.message.includes("MITM")||i.message.includes("signature")?this.onAnswerError("security_violation",i.message):i.message.includes("validation")||i.message.includes("format")?this.onAnswerError("invalid_format",i.message):this.onAnswerError("general_error",i.message)),i}},6e4)}_determineAnswerErrorPhase(e){let t=e.message.toLowerCase();return t.includes("validation")||t.includes("format")?"offer_validation":t.includes("rate limit")?"rate_limiting":t.includes("replay")||t.includes("too old")?"replay_protection":t.includes("salt")?"salt_validation":t.includes("key pair")||t.includes("generate")?"key_generation":t.includes("import")||t.includes("ecdsa")||t.includes("ecdh")?"key_import":t.includes("signature")||t.includes("mitm")?"signature_verification":t.includes("derive")||t.includes("shared")?"key_derivation":t.includes("auth")||t.includes("proof")?"authentication":t.includes("remote description")||t.includes("local description")?"webrtc_setup":t.includes("answer")||t.includes("sdp")?"sdp_creation":t.includes("export")?"key_export":t.includes("security level")?"security_calculation":"unknown"}_cleanupFailedAnswerCreation(){try{this._clearPendingOfferContext(),this._secureCleanupCryptographicMaterials(),this.currentKeyVersion=0,this.keyVersions.clear(),this.oldKeys.clear(),this.peerConnection&&(this.peerConnection.close(),this.peerConnection=null),this.dataChannel&&(this.dataChannel.close(),this.dataChannel=null),this.isInitiator=!1,this.isVerified=!1,this.sequenceNumber=0,this.expectedSequenceNumber=0,this.messageCounter=0,this.processedMessageIds.clear(),this.replayWindow.clear(),this._updateSecurityFeatures({hasEncryption:!1,hasECDH:!1,hasECDSA:!1,hasMutualAuth:!1,hasMetadataProtection:!1,hasEnhancedReplayProtection:!1,hasNonExtractableKeys:!1,hasEnhancedValidation:!1,hasPFS:!1}),this._forceGarbageCollection().catch(e=>{this._secureLog("error","Cleanup failed during answer cleanup",{errorType:e?.constructor?.name||"Unknown"})}),this._secureLog("debug","Failed answer creation cleanup completed with secure memory wipe")}catch(e){this._secureLog("error","Error during answer creation cleanup",{errorType:e.constructor.name,errorMessage:e.message})}}async _setEncryptionKeys(e,t,i,r){return this._withMutex("keyOperation",async n=>{if(this._secureLog("info","Setting encryption keys with mutex",{operationId:n}),!(e instanceof CryptoKey)||!(t instanceof CryptoKey)||!(i instanceof CryptoKey))throw new Error("Invalid key types provided");if(!r||typeof r!="string")throw new Error("Invalid key fingerprint provided");let a={encryptionKey:this.encryptionKey,macKey:this.macKey,metadataKey:this.metadataKey,keyFingerprint:this.keyFingerprint};try{return this.encryptionKey=e,this.macKey=t,this.metadataKey=i,this.keyFingerprint=r,this.sequenceNumber=0,this.expectedSequenceNumber=0,this.messageCounter=0,this.processedMessageIds.clear(),this.replayWindow.clear(),this._secureLog("info","Encryption keys set successfully",{operationId:n,hasAllKeys:!!(this.encryptionKey&&this.macKey&&this.metadataKey),hasFingerprint:!!this.keyFingerprint}),!0}catch(o){throw this.encryptionKey=a.encryptionKey,this.macKey=a.macKey,this.metadataKey=a.metadataKey,this.keyFingerprint=a.keyFingerprint,this._secureLog("error","Key setting failed, rolled back",{operationId:n,errorType:o.constructor.name}),o}})}async _handleSbq2Answer(e){if(!this._isSbq2())throw new Error("Received a new-format response to an old-format invitation. Please start a new invitation.");let t=this._sbq2State(),i=Ki(String(e.sbq2)),r=Li(i);if(r.type!==le.ANSWER)throw new Error("That code is an invitation, not a response to one.");if(!r.commitment)throw new Error("The response carries no key commitment");let a=await Fi(async l=>new Uint8Array(await crypto.subtle.digest("SHA-256",l)),t.localDescriptor),o=0;for(let l=0;ll.toString(16).padStart(2,"0").toUpperCase()).join(":");let{sdp:c}=Di(r);await this.peerConnection.setRemoteDescription({type:"answer",sdp:c}),this._secureLog("info","SBQ2 answer accepted; awaiting in-band key exchange",{bytes:i.length})}async handleSecureAnswer(e){if(e&&typeof e.sbq2=="string")return this._handleSbq2Answer(e);try{if(!e||typeof e!="object"||Array.isArray(e))throw this._secureLog("error","CRITICAL: Invalid answer data structure",{hasAnswerData:!!e,answerDataType:typeof e,isArray:Array.isArray(e)}),new Error("CRITICAL SECURITY FAILURE: Answer data must be a non-null object");let t=e.t==="answer"&&e.s,i=e.type==="enhanced_secure_answer"&&e.sdp;if(!t&&!i)throw this._secureLog("error","CRITICAL: Invalid answer format",{type:e.type||e.t,hasSdp:!!(e.sdp||e.s)}),new Error("CRITICAL SECURITY FAILURE: Invalid answer format - hard abort required");let r=e.v||e.version;if(r!==s.PROTOCOL_VERSION)throw new Error(`Version mismatch: expected protocol ${s.PROTOCOL_VERSION}, received ${r||"unknown"}`);let n=e.ecdhPublicKey||e.e,a=e.ecdsaPublicKey||e.d;if(!n||typeof n!="object"||Array.isArray(n))throw this._secureLog("error","CRITICAL: Invalid ECDH public key structure in answer",{hasEcdhKey:!!n,ecdhKeyType:typeof n,isArray:Array.isArray(n),availableKeys:Object.keys(e)}),new Error("CRITICAL SECURITY FAILURE: Missing or invalid ECDH public key structure");if(!n.keyData||!n.signature)throw this._secureLog("error","CRITICAL: ECDH key missing keyData or signature in answer",{hasKeyData:!!n.keyData,hasSignature:!!n.signature}),new Error("CRITICAL SECURITY FAILURE: ECDH key missing keyData or signature");if(!a||typeof a!="object"||Array.isArray(a))throw this._secureLog("error","CRITICAL: Invalid ECDSA public key structure in answer",{hasEcdsaKey:!!a,ecdsaKeyType:typeof a,isArray:Array.isArray(a)}),new Error("CRITICAL SECURITY FAILURE: Missing or invalid ECDSA public key structure");if(!a.keyData||!a.signature)throw this._secureLog("error","CRITICAL: ECDSA key missing keyData or signature in answer",{hasKeyData:!!a.keyData,hasSignature:!!a.signature}),new Error("CRITICAL SECURITY FAILURE: ECDSA key missing keyData or signature");let o=e.ts||e.timestamp,c=e.v||e.version;if(!o||!c)throw new Error("Missing required fields in response data \u2013 possible MITM attack");if(e.sessionId&&this.sessionId&&e.sessionId!==this.sessionId)throw window.EnhancedSecureCryptoUtils.secureLog.log("error","Session ID mismatch detected - possible MITM attack",{}),new Error("Session ID mismatch \u2013 possible MITM attack");let l=Date.now()-e.timestamp;if(l>36e5)throw window.EnhancedSecureCryptoUtils.secureLog.log("error","Answer data is too old - possible replay attack",{answerAge:l,timestamp:e.timestamp}),this.onAnswerError&&this.onAnswerError("replay_attack","Response data is too old \u2013 possible replay attack"),new Error("Response data is too old \u2013 possible replay attack");r!==s.PROTOCOL_VERSION&&window.EnhancedSecureCryptoUtils.secureLog.log("warn","Incompatible protocol version in answer",{expectedVersion:s.PROTOCOL_VERSION,receivedVersion:r});let h=await crypto.subtle.importKey("spki",new Uint8Array(a.keyData),{name:"ECDSA",namedCurve:"P-384"},!1,["verify"]),u=await window.EnhancedSecureCryptoUtils.importPublicKeyFromSignedPackage(n,h);if(this._restorePendingOfferContextIfNeeded(),!this.sessionSalt||this.sessionSalt.length!==64)throw window.EnhancedSecureCryptoUtils.secureLog.log("error","Invalid session salt detected - possible session hijacking",{saltLength:this.sessionSalt?this.sessionSalt.length:0}),new Error("Missing pending offer context. Apply the response in the original creator window that generated the invitation.");let p=await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(this.sessionSalt);if(window.EnhancedSecureCryptoUtils.secureLog.log("info","Session salt integrity verified",{saltFingerprint:p.substring(0,8)}),!(this.ecdhKeyPair?.privateKey instanceof CryptoKey))throw window.EnhancedSecureCryptoUtils.secureLog.log("error","Local ECDH private key is not a CryptoKey in handleSecureAnswer",{hasKeyPair:!!this.ecdhKeyPair,privateKeyType:typeof this.ecdhKeyPair?.privateKey,privateKeyAlgorithm:this.ecdhKeyPair?.privateKey?.algorithm?.name}),new Error("Local ECDH private key is not a CryptoKey");if(!(u instanceof CryptoKey))throw window.EnhancedSecureCryptoUtils.secureLog.log("error","Peer ECDH public key is not a CryptoKey in handleSecureAnswer",{publicKeyType:typeof u,publicKeyAlgorithm:u?.algorithm?.name}),new Error("Peer ECDH public key is not a CryptoKey");this.peerPublicKey=u,this._peerSupportsRatchet=e.dr===s.RATCHET_VERSION,this.connectionId||(this.connectionId=Array.from(crypto.getRandomValues(new Uint8Array(8))).map(g=>g.toString(16).padStart(2,"0")).join(""));let S=await window.EnhancedSecureCryptoUtils.deriveSharedKeys(this.ecdhKeyPair.privateKey,u,this.sessionSalt);if(this.encryptionKey=S.messageKey,this.macKey=S.macKey,this.metadataKey=S.metadataKey,this.keyFingerprint=S.fingerprint,await this._initializeRatchet(S,!0),this.sequenceNumber=0,this.expectedSequenceNumber=0,this.messageCounter=0,this.processedMessageIds.clear(),this.replayWindow.clear(),!(this.encryptionKey instanceof CryptoKey)||!(this.macKey instanceof CryptoKey)||!(this.metadataKey instanceof CryptoKey))throw window.EnhancedSecureCryptoUtils.secureLog.log("error","Invalid key types after derivation in handleSecureAnswer",{encryptionKeyType:typeof this.encryptionKey,macKeyType:typeof this.macKey,metadataKeyType:typeof this.metadataKey,encryptionKeyAlgorithm:this.encryptionKey?.algorithm?.name,macKeyAlgorithm:this.macKey?.algorithm?.name,metadataKeyAlgorithm:this.metadataKey?.algorithm?.name}),new Error("Invalid key types after export");this._secureLog("info","Encryption keys set in handleSecureAnswer",{hasEncryptionKey:!!this.encryptionKey,hasMacKey:!!this.macKey,hasMetadataKey:!!this.metadataKey,hasKeyFingerprint:!!this.keyFingerprint,mitmProtection:"enabled",signatureVerified:!0}),this.securityFeatures.hasMutualAuth=!0,this.securityFeatures.hasMetadataProtection=!0,this.securityFeatures.hasEnhancedReplayProtection=!0,this.securityFeatures.hasPFS=!0,this.currentKeyVersion=0,this.lastKeyRotation=Date.now(),this.keyVersions.set(0,{salt:this.sessionSalt,timestamp:this.lastKeyRotation,messageCount:0}),this.onKeyExchange(this.keyFingerprint);try{let g=this._extractDTLSFingerprintFromSDP(e.sdp||e.s),m=this.expectedDTLSFingerprint,I=this._decodeKeyFingerprint(this.keyFingerprint);this.verificationCode=await this._computeSAS(I,m,g),this._setSASMaterialReady(m,g),this.pendingSASCode=this.verificationCode,this._secureLog("info","SAS verification code generated for MITM protection (Offer side)",{sasCode:this.verificationCode,localFP:m.substring(0,16)+"...",remoteFP:g.substring(0,16)+"...",timestamp:Date.now()})}catch(g){this._secureLog("error","SAS computation failed in handleSecureAnswer (Offer side)",{errorType:g?.constructor?.name||"Unknown"}),this._secureLog("error","SAS computation failed in handleSecureAnswer (Offer side)",{error:g.message,stack:g.stack,timestamp:Date.now()})}if(this.strictDTLSValidation)try{this._peerDTLSFingerprint=this._extractDTLSFingerprintFromSDP(e.sdp||e.s)}catch(g){this._secureLog("warn","Could not extract peer DTLS fingerprint from answer",{error:g.message,context:"answer_validation"})}else this._secureLog("info","DTLS fingerprint validation disabled - proceeding without validation");let w=e.sdp||e.s;if(this.peerConnection?.signalingState!=="have-local-offer"){this._secureLog("warn","Ignoring answer outside have-local-offer state",{signalingState:this.peerConnection?.signalingState||"unknown"});return}this._secureLog("debug","Setting remote description from answer",{sdpLength:w?.length||0,usingCompactSDP:!e.sdp&&!!e.s}),await this.peerConnection.setRemoteDescription({type:"answer",sdp:w}),this._logIceCandidateDiagnostics("remote answer applied",this.peerConnection.remoteDescription?.sdp,{signalingState:this.peerConnection.signalingState}),this._warnIfRemoteCandidatesNeedRelay("answer",this.peerConnection.remoteDescription?.sdp),this._secureLog("debug","Remote description set successfully from answer",{signalingState:this.peerConnection.signalingState}),setTimeout(async()=>{try{await this.calculateAndReportSecurityLevel()&&this.notifySecurityUpdate()}catch(g){this._secureLog("error","Error calculating security after connection:",{errorType:g?.constructor?.name||"Unknown"})}},1e3),setTimeout(async()=>{(!this.lastSecurityCalculation||this.lastSecurityCalculation.score<50)&&(await this.calculateAndReportSecurityLevel(),this.notifySecurityUpdate())},3e3),this.notifySecurityUpdate()}catch(t){throw this._secureLog("error","Enhanced secure answer handling failed",{errorType:t.constructor.name}),this.onStatusChange("failed"),this.onAnswerError&&(t.message.includes("too old")||t.message.includes("\u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0441\u0442\u0430\u0440\u044B\u0435")?this.onAnswerError("replay_attack",t.message):t.message.includes("MITM")||t.message.includes("signature")||t.message.includes("\u043F\u043E\u0434\u043F\u0438\u0441\u044C")?this.onAnswerError("security_violation",t.message):this.onAnswerError("general_error",t.message)),t}}initiateVerification(){this.isInitiator?this.verificationInitiationSent||(this.verificationInitiationSent=!0,this.deliverMessageToUI("CRITICAL: Compare verification code with peer out-of-band (voice/video/in-person) to prevent MITM attack!","system"),this.deliverMessageToUI(`Your verification code: ${this.verificationCode}`,"system"),this.deliverMessageToUI("Ask peer to confirm this exact code before allowing traffic!","system")):this.deliverMessageToUI("Waiting for verification code from peer...","system")}_validateSASCode(e){if(!e||typeof e!="string"||!this.verificationCode||typeof this.verificationCode!="string")return!1;let t=e.replace(/[-\s]/g,"").toUpperCase(),i=this.verificationCode.replace(/[-\s]/g,"").toUpperCase();return t.length!==i.length?!1:window.EnhancedSecureCryptoUtils.constantTimeCompare(t,i)}confirmVerification(e){try{if(!this._validateSASCode(e))throw this.sasValidationAttempts=(this.sasValidationAttempts||0)+1,this._secureLog("warn","SAS validation failed: user entered incorrect code",{attempts:this.sasValidationAttempts,maxAttempts:s.MAX_SAS_ATTEMPTS}),this.sasValidationAttempts>=s.MAX_SAS_ATTEMPTS?(this.deliverMessageToUI("Verification failed 3 times. Session reset for safety.","system"),this.disconnect(),new Error("SAS_MAX_ATTEMPTS")):new Error("SAS_MISMATCH");this.localVerificationConfirmed=!0,this.sasValidationAttempts=0;let t={type:"verification_confirmed",data:{timestamp:Date.now(),verificationMethod:"MANUAL_SAS_ENTRY",securityLevel:"MITM_PROTECTION_REQUIRED"}};this.dataChannel.send(JSON.stringify(t)),this.onVerificationStateChange&&this.onVerificationStateChange({localConfirmed:this.localVerificationConfirmed,remoteConfirmed:this.remoteVerificationConfirmed,bothConfirmed:this.bothVerificationsConfirmed}),this._checkBothVerificationsConfirmed(),this.deliverMessageToUI("Code verified locally. Waiting for peer confirmation...","system"),this.processMessageQueue()}catch(t){throw t.message==="SAS_MISMATCH"?this.deliverMessageToUI("Verification failed: the code you entered is incorrect.","system"):t.message!=="SAS_MAX_ATTEMPTS"&&(this._secureLog("error","SAS verification failed:",{errorType:t?.constructor?.name||"Unknown"}),this.deliverMessageToUI("SAS verification failed","system")),t}}_checkBothVerificationsConfirmed(){if(this.localVerificationConfirmed&&this.remoteVerificationConfirmed&&!this.bothVerificationsConfirmed){this.bothVerificationsConfirmed=!0;let e={type:"verification_both_confirmed",data:{timestamp:Date.now(),verificationMethod:"SAS",securityLevel:"MITM_PROTECTION_COMPLETE"}};this.dataChannel.send(JSON.stringify(e)),this.onVerificationStateChange&&this.onVerificationStateChange({localConfirmed:this.localVerificationConfirmed,remoteConfirmed:this.remoteVerificationConfirmed,bothConfirmed:this.bothVerificationsConfirmed}),this.deliverMessageToUI("Both parties confirmed! Opening secure chat in 2 seconds...","system"),setTimeout(()=>{try{this._setVerifiedStatus(!0,"MUTUAL_SAS_CONFIRMED",{code:this.verificationCode,timestamp:Date.now()}),this._enforceVerificationGate("mutual_confirmed",!1),this.onStatusChange?.("verified")}catch(t){this._secureLog("error","Verified transition rejected - aborting session",{errorType:t?.constructor?.name||"Unknown"}),this.deliverMessageToUI("Verification could not be completed safely. Connection aborted.","system"),this.disconnect()}},2e3)}}handleVerificationConfirmed(e){this.remoteVerificationConfirmed=!0,this.deliverMessageToUI("Peer confirmed the verification code. Waiting for your confirmation...","system"),this.onVerificationStateChange&&this.onVerificationStateChange({localConfirmed:this.localVerificationConfirmed,remoteConfirmed:this.remoteVerificationConfirmed,bothConfirmed:this.bothVerificationsConfirmed}),this._checkBothVerificationsConfirmed()}handleVerificationBothConfirmed(e){if(!this.bothVerificationsConfirmed){if(!this.localVerificationConfirmed){this._secureLog("error","Peer claimed mutual SAS confirmation before local confirmation - possible MITM attack",{localConfirmed:this.localVerificationConfirmed,remoteConfirmed:this.remoteVerificationConfirmed,timestamp:Date.now()}),this.deliverMessageToUI("Verification protocol violation: peer claimed confirmation before you verified the code. Connection aborted for safety.","system"),this.disconnect();return}this.remoteVerificationConfirmed=!0,this.bothVerificationsConfirmed=!0,this.onVerificationStateChange&&this.onVerificationStateChange({localConfirmed:this.localVerificationConfirmed,remoteConfirmed:this.remoteVerificationConfirmed,bothConfirmed:this.bothVerificationsConfirmed}),this.deliverMessageToUI("Both parties confirmed! Opening secure chat in 2 seconds...","system"),setTimeout(()=>{this._setVerifiedStatus(!0,"MUTUAL_SAS_CONFIRMED",{code:this.verificationCode,timestamp:Date.now()}),this._enforceVerificationGate("mutual_confirmed",!1),this.onStatusChange?.("verified")},2e3)}}handleVerificationRequest(e){if(this._validateSASCode(e?.code)){let t={type:"verification_response",data:{ok:!0,timestamp:Date.now(),verificationMethod:"SAS",securityLevel:"MITM_PROTECTED"}};this.dataChannel.send(JSON.stringify(t)),this.verificationNotificationSent||(this.verificationNotificationSent=!0,this.deliverMessageToUI("SAS verification successful! MITM protection confirmed. Channel is now secure!","system")),this.processMessageQueue()}else{let t={type:"verification_response",data:{ok:!1,timestamp:Date.now(),reason:"code_mismatch"}};this.dataChannel.send(JSON.stringify(t)),this._secureLog("error","SAS verification failed - possible MITM attack",{receivedCodeLength:typeof e?.code=="string"?e.code.length:0,timestamp:Date.now()}),this.deliverMessageToUI("SAS verification failed! Possible MITM attack detected. Connection aborted for safety!","system"),this.disconnect()}}handleSASCode(e){if(!e?.code||typeof e.code!="string"){this._secureLog("warn","Invalid SAS announcement received from peer");return}if(!this.verificationCode){this._secureLog("error","Received peer SAS announcement before local SAS was derived - refusing to adopt it",{timestamp:Date.now()}),this.deliverMessageToUI("Verification failed: no locally derived code to compare against. Connection aborted for safety.","system"),this.disconnect();return}if(!this._validateSASCode(e.code)){this._secureLog("error","Peer-announced SAS does not match locally computed SAS"),this.deliverMessageToUI("Version or SAS mismatch detected. Connection aborted for safety.","system"),this.disconnect();return}this._notifyVerificationReadyIfPossible(),this._secureLog("info","Peer SAS announcement matched locally derived code",{timestamp:Date.now()})}handleVerificationResponse(e){e.ok===!0?(this._secureLog("info","Mutual SAS verification completed - MITM protection active",{verificationMethod:e.verificationMethod||"SAS",securityLevel:e.securityLevel||"MITM_PROTECTED",timestamp:Date.now()}),this.verificationNotificationSent||(this.verificationNotificationSent=!0,this.deliverMessageToUI(" Mutual SAS verification complete! MITM protection active. Channel is now secure!","system")),this.processMessageQueue()):(this._secureLog("error","Peer SAS verification failed - connection not secure",{responseData:e,timestamp:Date.now()}),this.deliverMessageToUI("Peer verification failed! Connection not secure!","system"),this.disconnect())}validateOfferData(e){return e&&e.type==="enhanced_secure_offer"&&e.sdp&&e.publicKey&&e.salt&&e.verificationCode&&Array.isArray(e.publicKey)&&Array.isArray(e.salt)&&e.salt.length===32}validateEnhancedOfferData(e){try{if(!e||typeof e!="object"||Array.isArray(e))throw this._secureLog("error","CRITICAL: Invalid offer data structure",{hasOfferData:!!e,offerDataType:typeof e,isArray:Array.isArray(e)}),new Error("CRITICAL SECURITY FAILURE: Offer data must be a non-null object");let t=e.v===s.PROTOCOL_VERSION&&e.e&&e.d,i=e.version===s.PROTOCOL_VERSION&&e.ecdhPublicKey&&e.ecdsaPublicKey;if(!(t?["offer"].includes(e.t):["enhanced_secure_offer","secure_offer"].includes(e.type)))throw new Error("Invalid offer type");if(t){let a=["e","d","sl","vc","si","ci","ac","slv"];for(let c of a)if(!e[c])throw new Error(`Missing required v4.1 compact field: ${c}`);if(!e.e||typeof e.e!="object"||Array.isArray(e.e))throw new Error("CRITICAL SECURITY FAILURE: Invalid ECDH public key structure");if(!e.d||typeof e.d!="object"||Array.isArray(e.d))throw new Error("CRITICAL SECURITY FAILURE: Invalid ECDSA public key structure");if(!Array.isArray(e.sl)||e.sl.length!==64)throw new Error("Salt must be exactly 64 bytes for v4.1");if(typeof e.vc!="string"||e.vc.length<6)throw new Error("Invalid verification code format");if(!["MAX","HIGH","MED","LOW"].includes(e.slv))throw new Error("Invalid security level");let o=Date.now()-e.ts;if(o>36e5)throw new Error("Offer is too old (older than 1 hour)");this._secureLog("info","v4.1 compact offer validation passed",{version:e.v,hasECDH:!!e.e,hasECDSA:!!e.d,hasSalt:!!e.sl,hasVerificationCode:!!e.vc,securityLevel:e.slv,offerAge:Math.round(o/1e3)+"s"})}else if(i){let a=["ecdhPublicKey","ecdsaPublicKey","salt","verificationCode","authChallenge","timestamp","version","securityLevel"];for(let c of a)if(!e[c])throw new Error(`Missing v4.1 field: ${c}`);if(!Array.isArray(e.salt)||e.salt.length!==64)throw new Error("Salt must be exactly 64 bytes for v4.1");let o=Date.now()-e.timestamp;if(o>36e5)throw new Error("Offer is too old (older than 1 hour)");if(!e.ecdhPublicKey||typeof e.ecdhPublicKey!="object"||Array.isArray(e.ecdhPublicKey))throw this._secureLog("error","CRITICAL: Invalid ECDH public key structure",{hasEcdhKey:!!e.ecdhPublicKey,ecdhKeyType:typeof e.ecdhPublicKey,isArray:Array.isArray(e.ecdhPublicKey)}),new Error("CRITICAL SECURITY FAILURE: Invalid ECDH public key structure - hard abort required");if(!e.ecdsaPublicKey||typeof e.ecdsaPublicKey!="object"||Array.isArray(e.ecdsaPublicKey))throw this._secureLog("error","CRITICAL: Invalid ECDSA public key structure",{hasEcdsaKey:!!e.ecdsaPublicKey,ecdsaKeyType:typeof e.ecdsaPublicKey,isArray:Array.isArray(e.ecdsaPublicKey)}),new Error("CRITICAL SECURITY FAILURE: Invalid ECDSA public key structure - hard abort required");if(!e.ecdhPublicKey.keyData||!e.ecdhPublicKey.signature)throw this._secureLog("error","CRITICAL: ECDH key missing keyData or signature",{hasKeyData:!!e.ecdhPublicKey.keyData,hasSignature:!!e.ecdhPublicKey.signature}),new Error("CRITICAL SECURITY FAILURE: ECDH key missing keyData or signature");if(!e.ecdsaPublicKey.keyData||!e.ecdsaPublicKey.signature)throw this._secureLog("error","CRITICAL: ECDSA key missing keyData or signature",{hasKeyData:!!e.ecdsaPublicKey.keyData,hasSignature:!!e.ecdsaPublicKey.signature}),new Error("CRITICAL SECURITY FAILURE: ECDSA key missing keyData or signature");if(typeof e.verificationCode!="string"||e.verificationCode.length<6)throw new Error("Invalid SAS verification code format - MITM protection required");this._secureLog("info","v4.1 offer validation passed",{version:e.version,hasSecurityLevel:!!e.securityLevel?.level,offerAge:Math.round(o/1e3)+"s"})}else{let a=e.v||e.version||"unknown";throw new Error(`Version mismatch: expected protocol ${s.PROTOCOL_VERSION}, received ${a}`)}let n=t?e.s:e.sdp;if(typeof n!="string"||!n.includes("v=0"))throw new Error("Invalid SDP structure");return!0}catch(t){throw this._secureLog("error","CRITICAL: Security validation failed - hard abort required",{error:t.message,errorType:t.constructor.name,timestamp:Date.now()}),new Error(`CRITICAL SECURITY VALIDATION FAILURE: ${t.message}`)}}async sendSecureMessage(e){let t=this._validateInputData(e,"sendSecureMessage");if(!t.isValid){let i=`Input validation failed: ${t.errors.join(", ")}`;throw this._secureLog("error","Input validation failed in sendSecureMessage",{errors:t.errors,messageType:typeof e}),new Error(i)}if(!this._checkRateLimit("sendSecureMessage"))throw new Error("Rate limit exceeded for secure message sending");if(this._enforceVerificationGate("sendSecureMessage"),!this.isConnected())throw t.sanitizedData&&typeof t.sanitizedData=="object"&&t.sanitizedData.type&&t.sanitizedData.type.startsWith("file_")?new Error("Connection not ready for file transfer. Please ensure the connection is established and verified."):(this.messageQueue.push(t.sanitizedData),new Error("Connection not ready. Message queued for sending."));return this._withMutex("cryptoOperation",async i=>{if(!this.isConnected()||!this.isVerified)throw new Error("Connection lost during message preparation");if(!this.encryptionKey||!this.macKey||!this.metadataKey)throw new Error("Encryption keys not initialized");if(!window.EnhancedSecureCryptoUtils.rateLimiter.checkMessageRate(this.rateLimiterId))throw new Error("Message rate limit exceeded (60 messages per minute)");try{let r=typeof t.sanitizedData=="string"?t.sanitizedData:JSON.stringify(t.sanitizedData),n=window.EnhancedSecureCryptoUtils.sanitizeMessage(r),a=`msg_${Date.now()}_${this.messageCounter++}`;if(typeof this._createMessageAAD!="function")throw new Error("_createMessageAAD method is not available in sendSecureMessage. Manager may not be fully initialized.");let o=e.aad||this._createMessageAAD("enhanced_message",{content:n}),c;if(this._ratchet?.canEncrypt){let{header:l,ciphertext:h}=await this._ratchet.encrypt(n);c={type:s.MESSAGE_TYPES.RATCHET_MESSAGE,h:l,c:h,version:"5.0"}}else c={type:"enhanced_message",data:await window.EnhancedSecureCryptoUtils.encryptMessage(n,this.encryptionKey,this.macKey,this.metadataKey,a,JSON.parse(o).sequenceNumber),keyVersion:this.currentKeyVersion,version:"4.0"};this.dataChannel.send(JSON.stringify(c)),typeof t.sanitizedData=="string"&&this.deliverMessageToUI(t.sanitizedData,"sent"),this._secureLog("debug","Secure message sent successfully",{operationId:i,messageLength:n.length,keyVersion:this.currentKeyVersion})}catch(r){throw this._secureLog("error","Secure message sending failed",{operationId:i,errorType:r.constructor.name}),r.message.includes("Session expired")?new Error("Session expired. Please enter your password to unlock."):r.message.includes("Encryption keys not initialized")?new Error("Session expired due to inactivity. Please reconnect to the chat."):r.message.includes("Connection lost")?new Error("Connection lost. Please check your Internet connection."):r.message.includes("Rate limit exceeded")?new Error("Message rate limit exceeded. Please wait before sending another message."):r}},2e3)}processMessageQueue(){for(;this.messageQueue.length>0&&this.isConnected()&&this.isVerified;){let e=this.messageQueue.shift();this.sendSecureMessage(e).catch(console.error)}}startHeartbeat(){this._heartbeatConfig={enabled:!0,interval:s.TIMEOUTS.HEARTBEAT_INTERVAL,lastHeartbeat:0},this.stopHeartbeat(!0),this._heartbeatTimer=setInterval(()=>{this._heartbeatConfig?.enabled&&this.dataChannel?.readyState==="open"&&this._sendHeartbeat()},s.TIMEOUTS.HEARTBEAT_INTERVAL),this._trackActiveTimer(this._heartbeatTimer),this._lastInboundAt=Date.now(),this._livenessProbeAt=0,this._livenessArmed=!1,this._startLivenessWatchdog(),this._setupRecoveryLifecycleListeners(),this._secureLog("info","\u{1F504} Liveness watchdog started",{heartbeatMs:s.TIMEOUTS.HEARTBEAT_INTERVAL,probeAfterMs:s.TIMEOUTS.LIVENESS_PROBE_AFTER,probeTimeoutMs:s.TIMEOUTS.LIVENESS_PROBE_TIMEOUT})}stopHeartbeat(e=!1){!e&&this._heartbeatConfig&&(this._heartbeatConfig.enabled=!1),this._heartbeatTimer&&(clearInterval(this._heartbeatTimer),this._activeTimers?.delete(this._heartbeatTimer),this._heartbeatTimer=null),e||this._stopLivenessWatchdog()}handleHeartbeat(e){this._lastInboundAt=Date.now(),this._livenessProbeAt=0;let t=e?.ack===!0||e?.data?.ack===!0;t||this._sendHeartbeat(!0),this._secureLog("debug",t?"\u{1F493} Heartbeat ack received":"\u{1F493} Heartbeat probe received")}_noteInboundActivity(){this._lastInboundAt=Date.now(),this._livenessProbeAt=0,this._livenessArmed=!0}_startLivenessWatchdog(){this._stopLivenessWatchdog(),this._livenessTimer=setInterval(()=>{try{this._checkLiveness()}catch(e){this._secureLog("error","\u274C Liveness check failed",{errorType:e?.constructor?.name||"Unknown"})}},s.TIMEOUTS.LIVENESS_CHECK_INTERVAL),this._trackActiveTimer(this._livenessTimer)}_stopLivenessWatchdog(){this._livenessTimer&&(clearInterval(this._livenessTimer),this._activeTimers?.delete(this._livenessTimer),this._livenessTimer=null)}_checkLiveness(){if(!this.isVerified||this._reconnect.phase!=="idle"||this.dataChannel?.readyState!=="open"||!this._lastInboundAt||!this._livenessArmed)return;let e=s.TIMEOUTS,t=Date.now();if(this.peerConnection?.connectionState==="connected"){this._livenessProbeAt=0;return}if(this._livenessProbeAt){if(t-this._livenessProbeAt"u"||this._recoveryLifecycleBound||(this._recoveryLifecycleBound=!0,this._onDeviceOnline=()=>{this.isVerified&&(this.isReconnecting()?(this._secureLog("info","\u{1F504} Device back online \u2014 retrying immediately"),this._attemptIceRestart()):this._checkLiveness())},this._onVisibilityRestored=()=>{typeof document>"u"||document.visibilityState!=="visible"||this.isVerified&&(this._lastInboundAt=Date.now(),this._livenessProbeAt=0,this._reconnect.phase==="idle"&&this.dataChannel?.readyState==="open"&&(this._livenessProbeAt=Date.now(),this._sendHeartbeat(!1),this._secureLog("info","\u{1F504} returned to foreground, probing peer")))},window.addEventListener("online",this._onDeviceOnline),typeof document<"u"&&document.addEventListener("visibilitychange",this._onVisibilityRestored))}_teardownRecoveryLifecycleListeners(){!this._recoveryLifecycleBound||typeof window>"u"||(this._recoveryLifecycleBound=!1,this._onDeviceOnline&&window.removeEventListener("online",this._onDeviceOnline),this._onVisibilityRestored&&typeof document<"u"&&document.removeEventListener("visibilitychange",this._onVisibilityRestored),this._onDeviceOnline=null,this._onVisibilityRestored=null)}_resetReconnectState(){let e=this._reconnect;e&&(e.graceTimer&&(clearTimeout(e.graceTimer),this._activeTimers?.delete(e.graceTimer)),e.retryTimer&&(clearTimeout(e.retryTimer),this._activeTimers?.delete(e.retryTimer)),e.restartTimer&&(clearTimeout(e.restartTimer),this._activeTimers?.delete(e.restartTimer)),e.graceTimer=null,e.retryTimer=null,e.restartTimer=null,e.phase="idle",e.attempts=0,e.startedAt=0,e.inFlightAt=0,e.barrenFailures=0,e.pendingRole=null)}_onPathDegraded(e="ice_disconnected"){this.isVerified&&this._reconnect.phase==="idle"&&(this._reconnect.phase="grace",this._reconnect.startedAt=Date.now(),this._secureLog("info","\u{1F504} path degraded, holding grace window",{reason:e}),this.onStatusChange("reconnecting"),this._reconnect.graceTimer=setTimeout(()=>{if(this._reconnect.graceTimer=null,this.peerConnection?.connectionState==="connected"){this._onPathRecovered();return}this._attemptIceRestart()},s.TIMEOUTS.ICE_DISCONNECT_GRACE),this._trackActiveTimer(this._reconnect.graceTimer))}_onPathLost(e="ice_failed"){this.isVerified&&(this._reconnect.phase==="restarting"||this._reconnect.phase==="exhausted"||(this._reconnect.phase==="idle"&&(this._reconnect.startedAt=Date.now(),this.onStatusChange("reconnecting")),this._reconnect.graceTimer&&(clearTimeout(this._reconnect.graceTimer),this._activeTimers?.delete(this._reconnect.graceTimer),this._reconnect.graceTimer=null),this._secureLog("info","\u{1F504} path lost, restarting ICE",{reason:e}),this._attemptIceRestart()))}_noteIceFailureDiagnostics(e){if(this.isReconnecting()&&e){if(e.pairCount>0){this._reconnect.barrenFailures=0;return}this._reconnect.barrenFailures=(this._reconnect.barrenFailures||0)+1,!(this._reconnect.barrenFailuress.TIMEOUTS.RECONNECT_MAX_DURATION){this._giveUpAutoReconnect("timeout");return}if(e.inFlightAt&&Date.now()-e.inFlightAt=2&&i>s.TIMEOUTS.RECOVERY_SILENCE_LIMIT){this._secureLog("warn","\u26A0\uFE0F nothing has reached us since the drop \u2014 the channel cannot carry a renegotiation",{silentForMs:i,attempts:e.attempts}),this._giveUpAutoReconnect("no_signalling_path");return}e.phase="restarting",e.attempts+=1,e.inFlightAt=Date.now(),this._secureLog("info","\u{1F504} ICE restart attempt",{attempt:e.attempts,role:this.isInitiator?"offerer":"answerer"});try{this.isInitiator?await this._sendIceRestartOffer():await this.sendSystemMessage({type:s.MESSAGE_TYPES.ICE_RESTART_REQUEST,timestamp:Date.now()})}catch(r){this._secureLog("warn","\u26A0\uFE0F ICE restart attempt failed to send",{errorType:r?.constructor?.name||"Unknown"})}this._scheduleReconnectRetry()}_scheduleReconnectRetry(){let e=this._reconnect;e.retryTimer&&(clearTimeout(e.retryTimer),this._activeTimers?.delete(e.retryTimer));let t=s.RECONNECT_BACKOFF,i=t[Math.min(Math.max(e.attempts-1,0),t.length-1)];e.retryTimer=setTimeout(()=>{if(e.retryTimer=null,this.peerConnection?.connectionState==="connected"){this._onPathRecovered();return}this._attemptIceRestart()},i),this._trackActiveTimer(e.retryTimer)}async _sendIceRestartOffer(){let e=this.peerConnection;if(!e)return;if(e.signalingState==="have-local-offer")try{await e.setLocalDescription({type:"rollback"})}catch{}let t=await e.createOffer({iceRestart:!0});await e.setLocalDescription(t),await this.waitForIceGathering(s.TIMEOUTS.ICE_RESTART_GATHERING,s.TIMEOUTS.ICE_RESTART_GATHERING),await this.sendSystemMessage({type:s.MESSAGE_TYPES.ICE_RESTART_OFFER,sdp:e.localDescription.sdp,timestamp:Date.now()}),this._secureLog("debug","\u{1F504} ICE restart offer sent")}_currentRemoteDtlsFingerprint(){let e=this.peerConnection?.currentRemoteDescription?.sdp||this.peerConnection?.remoteDescription?.sdp;if(!e)return null;try{return this._extractDTLSFingerprintFromSDP(e)}catch{return null}}async _assertSameRemoteIdentity(e,t){let i=this._currentRemoteDtlsFingerprint();if(!i)throw new Error(`Cannot verify peer identity for ${t}`);let r=this._extractDTLSFingerprintFromSDP(e);await this._validateDTLSFingerprint(r,i,t)}async _handleIceRestartSignal(e,t){let i=s.MESSAGE_TYPES,r=this.peerConnection;if(r)switch(this._noteInboundActivity(),e){case i.ICE_RESTART_REQUEST:{if(!this.isInitiator)return;this._reconnect.phase==="idle"&&(this._reconnect.startedAt=Date.now(),this._reconnect.phase="restarting",this.onStatusChange("reconnecting")),await this._sendIceRestartOffer();return}case i.ICE_RESTART_OFFER:{if(!t.sdp)return;await this._assertSameRemoteIdentity(t.sdp,"ice_restart_offer"),this._reconnect.phase==="idle"&&(this._reconnect.startedAt=Date.now(),this.onStatusChange("reconnecting")),this._reconnect.phase="restarting",await r.setRemoteDescription({type:"offer",sdp:t.sdp});let n=await r.createAnswer();await r.setLocalDescription(n),await this.waitForIceGathering(s.TIMEOUTS.ICE_RESTART_GATHERING,s.TIMEOUTS.ICE_RESTART_GATHERING),await this.sendSystemMessage({type:i.ICE_RESTART_ANSWER,sdp:r.localDescription.sdp,timestamp:Date.now()}),this._secureLog("debug","\u{1F504} ICE restart answer sent");return}case i.ICE_RESTART_ANSWER:{if(!t.sdp)return;if(r.signalingState!=="have-local-offer"){this._secureLog("warn","\u26A0\uFE0F Ignoring restart answer in unexpected state",{signalingState:r.signalingState});return}await this._assertSameRemoteIdentity(t.sdp,"ice_restart_answer"),await r.setRemoteDescription({type:"answer",sdp:t.sdp}),this._reconnect.inFlightAt=0,this._secureLog("debug","\u{1F504} ICE restart answer applied");return}default:}}_giveUpAutoReconnect(e){this._resetReconnectState(),this._reconnect.phase="exhausted",this._teardownRecoveryLifecycleListeners?.(),this._secureLog("warn","\u26A0\uFE0F automatic reconnection exhausted \u2014 ending session",{reason:e}),this.reconnectionFailedNotificationSent||(this.reconnectionFailedNotificationSent=!0,this.deliverMessageToUI("Could not restore the connection. This chat is being closed and its data wiped \u2014 start a new one to continue.","system")),this.onStatusChange("recovery_failed"),this._clearVerificationStates()}_stopAllTimers(){this._secureLog("info","Stopping all timers and cleanup scheduler"),this._maintenanceScheduler&&(clearInterval(this._maintenanceScheduler),this._maintenanceScheduler=null),this.stopHeartbeat?.(),this._resetReconnectState?.(),this._activeTimers&&(this._activeTimers.forEach(e=>{e&&(clearInterval(e),clearTimeout(e))}),this._activeTimers.clear()),this._fileTransferInitRetryTimers&&this._fileTransferInitRetryTimers.clear(),this._logCleanupInterval=null,this._secureLog("info","All timers stopped successfully")}waitForIceGathering(e=s.TIMEOUTS.ICE_GATHERING_TIMEOUT,t=s.TIMEOUTS.ICE_GATHERING_HARD_TIMEOUT){return new Promise(i=>{let r=this.peerConnection;if(!r){i(!1);return}if(r.iceGatheringState==="complete"){i(!0);return}let n=!1,a=null,o=null,c=()=>{try{let u=this.peerConnection?.localDescription?.sdp;return u?this._summarizeIceCandidatesInSDP(u).total>0:!1}catch{return!1}},l=u=>{if(!n){n=!0,a&&(clearTimeout(a),this._untrackActiveTimer?.(a)),o&&(clearTimeout(o),this._untrackActiveTimer?.(o));try{r.removeEventListener("icegatheringstatechange",h)}catch{}i(u)}},h=()=>{this.peerConnection?.iceGatheringState==="complete"&&l(!0)};r.addEventListener("icegatheringstatechange",h),a=setTimeout(()=>{c()&&l(!1)},e),this._trackActiveTimer?.(a),o=setTimeout(()=>l(!1),Math.max(t,e)),this._trackActiveTimer?.(o)})}retryConnection(){this._secureLog("info","Retrying connection",{attempt:this.connectionAttempts,maxAttempts:this.maxConnectionAttempts}),this.onStatusChange("retrying")}isConnected(){let e=!!this.dataChannel,i=this.dataChannel?.readyState==="open",r=this.isVerified,n=this.peerConnection?.connectionState;return this.dataChannel&&this.dataChannel.readyState==="open"&&this.isVerified}getConnectionInfo(){return{fingerprint:this.keyFingerprint,isConnected:this.isConnected(),isVerified:this.isVerified,connectionState:this.peerConnection?.connectionState,iceConnectionState:this.peerConnection?.iceConnectionState,verificationCode:this.verificationCode}}handleUnexpectedDisconnect(){this.sendDisconnectNotification(),this.isVerified=!1,this.disconnectNotificationSent||(this.disconnectNotificationSent=!0,this.deliverMessageToUI("\u{1F50C} Connection lost. Attempting to reconnect...","system")),this.fileTransferSystem&&(this.fileTransferSystem.cleanup(),this.fileTransferSystem=null),this._dispatchAppEvent?.(new CustomEvent("peer-disconnect",{detail:{reason:"connection_lost",timestamp:Date.now()}}))}sendDisconnectNotification(){try{if(this.dataChannel&&this.dataChannel.readyState==="open"){let e={type:"peer_disconnect",timestamp:Date.now(),reason:this.intentionalDisconnect?"user_disconnect":"connection_lost"};for(let t=0;t<3;t++)try{this.dataChannel.send(JSON.stringify(e)),window.EnhancedSecureCryptoUtils.secureLog.log("info","Disconnect notification sent",{reason:e.reason,attempt:t+1});break}catch(i){t===2&&window.EnhancedSecureCryptoUtils.secureLog.log("error","Failed to send disconnect notification",{error:i.message})}}}catch(e){window.EnhancedSecureCryptoUtils.secureLog.log("error","Could not send disconnect notification",{error:e.message})}}attemptReconnection(){return!this.isVerified||this.dataChannel?.readyState!=="open"?(this.reconnectionFailedNotificationSent||(this.reconnectionFailedNotificationSent=!0,this.deliverMessageToUI("Unable to reconnect. A new connection is required.","system")),!1):(this._resetReconnectState(),this.reconnectionFailedNotificationSent=!1,this._reconnect.startedAt=Date.now(),this.onStatusChange("reconnecting"),this._attemptIceRestart(),!0)}handlePeerDisconnectNotification(e){let t=e.reason||"unknown",i=t==="user_disconnect"?"manually disconnected.":"connection lost.";this.peerDisconnectNotificationSent||(this.peerDisconnectNotificationSent=!0,this.deliverMessageToUI(`Peer ${i}`,"system")),this.onStatusChange("peer_disconnected"),this.intentionalDisconnect=!1,this.isVerified=!1,this.stopHeartbeat(),this.onKeyExchange(""),this.onVerificationRequired(""),this._dispatchAppEvent?.(new CustomEvent("peer-disconnect",{detail:{reason:t,timestamp:Date.now()}})),this._peerDisconnectCleanupTimer||(this._peerDisconnectCleanupTimer=this._trackActiveTimer(setTimeout(()=>{let r=this._peerDisconnectCleanupTimer;this._peerDisconnectCleanupTimer=null,this._untrackActiveTimer(r),this._sessionAlive!==!1&&this.disconnect()},2e3))),window.EnhancedSecureCryptoUtils.secureLog.log("info","Peer disconnect notification processed",{reason:t})}disconnect(){try{this._sessionAlive=!1;try{this._stopAdaptation?.()}catch{}try{this._stopLocalMediaPermanently?.()}catch{}this._callAudioSender=null,this._callVideoSender=null,this._callGroupContext=null,this._externalMediaStream=null,this._callStateListeners?.clear?.(),this.intentionalDisconnect=!0,window.EnhancedSecureCryptoUtils.secureLog.log("info","Starting intentional disconnect"),this.sendDisconnectNotification(),this._teardownRecoveryLifecycleListeners?.(),this._stopAllTimers(),this._peerDisconnectCleanupTimer=null,this.stopHeartbeat(),this.stopFakeTrafficGeneration();for(let e of this.decoyTimers.entries())clearTimeout(e[1]);this.decoyTimers.clear(),this.fileTransferSystem&&(this.fileTransferSystem.cleanup(),this.fileTransferSystem=null);for(let e of this.decoyChannels.values())e.readyState==="open"&&e.close();this.decoyChannels.clear(),this.heartbeatChannel&&(this.heartbeatChannel.close(),this.heartbeatChannel=null),this.isVerified=!1,this.processedMessageIds.clear(),this.messageCounter=0,this.packetBuffer.clear(),this.chunkQueue=[],this._wipeEphemeralKeys(),this._hardWipeOldKeys(),this._secureCleanupCryptographicMaterials(),this.keyVersions.clear(),this.oldKeys.clear(),this.currentKeyVersion=0,this.lastKeyRotation=Date.now(),this.sequenceNumber=0,this.expectedSequenceNumber=0,this.replayWindow.clear(),this._clearVerificationStates(),this.securityFeatures={hasEncryption:!0,hasECDH:!0,hasECDSA:!0,hasMutualAuth:!0,hasMetadataProtection:!0,hasEnhancedReplayProtection:!0,hasNonExtractableKeys:!0,hasRateLimiting:!0,hasEnhancedValidation:!0,hasPFS:!0},this.dataChannel&&(this.dataChannel.close(),this.dataChannel.onopen=null,this.dataChannel.onclose=null,this.dataChannel.onmessage=null,this.dataChannel.onerror=null,this.dataChannel=null),this.peerConnection&&(this.peerConnection.close(),this.peerConnection.onconnectionstatechange=null,this.peerConnection.ondatachannel=null,this.peerConnection=null),this.messageQueue&&this.messageQueue.length>0&&(this.messageQueue.forEach((e,t)=>{this._secureWipeMemory(e,`messageQueue[${t}]`)}),this.messageQueue=[]),this._forceGarbageCollection().catch(e=>{this._secureLog("error","Cleanup failed during disconnect",{errorType:e?.constructor?.name||"Unknown"})}),this._dispatchAppEvent?.(new CustomEvent("peer-disconnect",{detail:{reason:"user_disconnect",timestamp:Date.now()}})),this._dispatchAppEvent?.(new CustomEvent("connection-cleaned",{detail:{timestamp:Date.now(),reason:"user_cleanup"}})),this.onStatusChange("disconnected"),this.onKeyExchange(""),this.onVerificationRequired(""),this._secureLog("info","Connection securely cleaned up with complete memory wipe")}catch(e){this._secureLog("error","\u274C Error during enhanced disconnect:",{errorType:e?.constructor?.name||"Unknown"})}finally{this.intentionalDisconnect=!1}}async sendFile(e,t={}){if(this._enforceVerificationGate("sendFile"),!this.isConnected())throw new Error("Connection not ready for file transfer. Please ensure the connection is established.");if(!this.fileTransferSystem&&(this.initializeFileTransfer(),await new Promise(i=>setTimeout(i,500)),!this.fileTransferSystem))throw new Error("File transfer system could not be initialized. Please try reconnecting.");if(!this.encryptionKey||!this.macKey)throw new Error("Encryption keys not ready. Please wait for connection to be fully established.");try{return await this.fileTransferSystem.sendFile(e,t)}catch(i){throw this._secureLog("error","File transfer error:",{errorType:i?.constructor?.name||"Unknown"}),i.message.includes("Connection not ready")?new Error("Connection not ready for file transfer. Check connection status."):i.message.includes("Encryption keys not initialized")?new Error("Session expired due to inactivity. Please reconnect to the chat."):i.message.includes("Transfer timeout")?new Error("File transfer timeout. Check connection and try again."):i}}getFileTransfers(){if(!this.fileTransferSystem)return{sending:[],receiving:[]};try{let e=[],t=[];return typeof this.fileTransferSystem.getActiveTransfers=="function"?e=this.fileTransferSystem.getActiveTransfers():this._secureLog("warn","getActiveTransfers method not available in file transfer system"),typeof this.fileTransferSystem.getReceivingTransfers=="function"?t=this.fileTransferSystem.getReceivingTransfers():this._secureLog("warn","getReceivingTransfers method not available in file transfer system"),{sending:e||[],receiving:t||[]}}catch(e){return this._secureLog("error","Error getting file transfers:",{errorType:e?.constructor?.name||"Unknown"}),{sending:[],receiving:[]}}}getFileTransferStatus(){if(!this.fileTransferSystem)return{initialized:!1,status:"not_initialized",message:"File transfer system not initialized"};let e=this.fileTransferSystem.getActiveTransfers(),t=this.fileTransferSystem.getReceivingTransfers();return{initialized:!0,status:"ready",activeTransfers:e.length,receivingTransfers:t.length,totalTransfers:e.length+t.length}}cancelFileTransfer(e){return this.fileTransferSystem?this.fileTransferSystem.cancelTransfer(e):!1}cleanupFileTransferSystem(){return this.fileTransferSystem?(this._secureLog("info","\u{1F9F9} Force cleaning up file transfer system"),this.fileTransferSystem.cleanup(),this.fileTransferSystem=null,!0):!1}reinitializeFileTransfer(){try{return this.fileTransferSystem&&this.fileTransferSystem.cleanup(),this.initializeFileTransfer(),!0}catch(e){return this._secureLog("error","Failed to reinitialize file transfer system:",{errorType:e?.constructor?.name||"Unknown"}),!1}}setFileTransferCallbacks(e,t,i,r=null){this.onFileProgress=e,this.onFileReceived=t,this.onFileError=i,this.onIncomingFileRequest=r,this.fileTransferSystem&&(this.fileTransferSystem.onProgress=e,this.fileTransferSystem.onFileReceived=t,this.fileTransferSystem.onError=i,this.fileTransferSystem.onIncomingFileRequest=r)}getPendingIncomingFiles(){return this.fileTransferSystem?this.fileTransferSystem.getPendingIncomingTransfers():[]}async acceptIncomingFile(e){return this.fileTransferSystem?this.fileTransferSystem.acceptIncomingFile(e):!1}async rejectIncomingFile(e){return this.fileTransferSystem?this.fileTransferSystem.rejectIncomingFile(e):!1}async getReceivedFileObjectURL(e){return this.fileTransferSystem?this.fileTransferSystem.getObjectURL(e):null}revokeReceivedFileObjectURL(e){this.fileTransferSystem&&this.fileTransferSystem.revokeObjectURL(e)}async handleSessionActivation(e){try{this.currentSession=e;let t=!!(this.encryptionKey&&this.macKey);e.sessionId&&this.onStatusChange("connected"),setTimeout(()=>{try{this.initializeFileTransfer()}catch(r){this._secureLog("warn","File transfer initialization failed during session activation:",{details:r.message})}},1e3),this.fileTransferSystem&&this.isConnected()&&typeof this.fileTransferSystem.onSessionUpdate=="function"&&this.fileTransferSystem.onSessionUpdate({keyFingerprint:this.keyFingerprint,sessionSalt:this.sessionSalt,hasMacKey:!!this.macKey})}catch(t){this._secureLog("error","Failed to handle session activation:",{errorType:t?.constructor?.name||"Unknown"})}}checkFileTransferReadiness(){let e={hasFileTransferSystem:!!this.fileTransferSystem,hasDataChannel:!!this.dataChannel,dataChannelState:this.dataChannel?.readyState,isConnected:this.isConnected(),isVerified:this.isVerified,hasEncryptionKey:!!this.encryptionKey,hasMacKey:!!this.macKey,ready:!1};return e.ready=e.hasFileTransferSystem&&e.hasDataChannel&&e.dataChannelState==="open"&&e.isConnected&&e.isVerified,e}forceReinitializeFileTransfer(){try{return this.fileTransferSystem&&(this.fileTransferSystem.cleanup(),this.fileTransferSystem=null),setTimeout(()=>{this.initializeFileTransfer()},500),!0}catch(e){return this._secureLog("error","Failed to force reinitialize file transfer:",{errorType:e?.constructor?.name||"Unknown"}),!1}}getFileTransferDiagnostics(){let e={timestamp:new Date().toISOString(),webrtcManager:{hasDataChannel:!!this.dataChannel,dataChannelState:this.dataChannel?.readyState,isConnected:this.isConnected(),isVerified:this.isVerified,isInitiator:this.isInitiator,hasEncryptionKey:!!this.encryptionKey,hasMacKey:!!this.macKey,hasMetadataKey:!!this.metadataKey,hasKeyFingerprint:!!this.keyFingerprint,hasSessionSalt:!!this.sessionSalt},fileTransferSystem:null,globalState:{fileTransferActive:this._fileTransferActive||!1,hasFileTransferSystem:!!this.fileTransferSystem,fileTransferSystemType:this.fileTransferSystem?"EnhancedSecureFileTransfer":"none"}};if(this.fileTransferSystem)try{e.fileTransferSystem=this.fileTransferSystem.getSystemStatus()}catch(t){e.fileTransferSystem={error:t.message}}return e}getSupportedFileTypes(){if(!this.fileTransferSystem)return{error:"File transfer system not initialized"};try{return this.fileTransferSystem.getSupportedFileTypes()}catch(e){return{error:e.message}}}validateFile(e){if(!this.fileTransferSystem)return{isValid:!1,errors:["File transfer system not initialized"],fileType:null,fileSize:e?.size||0,formattedSize:"0 B"};try{return this.fileTransferSystem.validateFile(e)}catch(t){return{isValid:!1,errors:[t.message],fileType:null,fileSize:e?.size||0,formattedSize:"0 B"}}}getFileTypeInfo(){if(!this.fileTransferSystem)return{error:"File transfer system not initialized"};try{return this.fileTransferSystem.getFileTypeInfo()}catch(e){return{error:e.message}}}async forceInitializeFileTransfer(e={}){let t=new AbortController,{signal:i=t.signal,timeout:r=6e3}=e;i&&i!==t.signal&&i.addEventListener("abort",()=>t.abort());try{if(!this.isVerified)throw new Error("Connection not verified");if(!this.dataChannel||this.dataChannel.readyState!=="open")throw new Error("Data channel not open");if(!this.encryptionKey||!this.macKey)throw new Error("Encryption keys not ready");this.fileTransferSystem&&(this.fileTransferSystem.cleanup(),this.fileTransferSystem=null),this.initializeFileTransfer();let n=0,a=50,o=100,c=a*o,l=new Promise((h,u)=>{let p=()=>{if(t.signal.aborted){u(new Error("Operation cancelled"));return}if(this.fileTransferSystem){h(!0);return}if(n>=a){u(new Error(`Initialization timeout after ${c}ms`));return}n++,setTimeout(p,o)};p()});if(await Promise.race([l,new Promise((h,u)=>setTimeout(()=>u(new Error(`Global timeout after ${r}ms`)),r))]),this.fileTransferSystem)return!0;throw new Error("Force initialization timeout")}catch(n){return n.name==="AbortError"||n.message.includes("cancelled")?(this._secureLog("info","File transfer initialization cancelled by user"),{cancelled:!0}):(this._secureLog("error","Force file transfer initialization failed:",{errorType:n?.constructor?.name||"Unknown",message:n.message,attempts}),{error:n.message,attempts})}}cancelFileTransferInitialization(){try{return this.fileTransferSystem?(this.fileTransferSystem.cleanup(),this.fileTransferSystem=null,this._fileTransferActive=!1,this._secureLog("info","File transfer initialization cancelled"),!0):!1}catch(e){return this._secureLog("error","Failed to cancel file transfer initialization:",{errorType:e?.constructor?.name||"Unknown"}),!1}}getFileTransferSystemStatus(){if(!this.fileTransferSystem)return{available:!1,status:"not_initialized"};try{let e=this.fileTransferSystem.getSystemStatus();return{available:!0,status:e.status||"unknown",activeTransfers:e.activeTransfers||0,receivingTransfers:e.receivingTransfers||0,systemType:"EnhancedSecureFileTransfer"}}catch(e){return this._secureLog("error","Failed to get file transfer system status:",{errorType:e?.constructor?.name||"Unknown"}),{available:!1,status:"error",error:e.message}}}_validateNestedEncryptionSecurity(){if(this.securityFeatures.hasNestedEncryption&&this.nestedEncryptionKey)try{let e=this._generateSecureIV(s.SIZES.NESTED_ENCRYPTION_IV_SIZE,"securityTest1"),t=this._generateSecureIV(s.SIZES.NESTED_ENCRYPTION_IV_SIZE,"securityTest2");return e.every((r,n)=>r===t[n])?(this._secureLog("error","CRITICAL: Nested encryption security validation failed - IVs are identical!"),!1):this._getIVTrackingStats().totalIVs<2?(this._secureLog("error","CRITICAL: IV tracking system not working properly"),!1):(this._secureLog("info","Nested encryption security validation passed - secure IV generation working"),!0)}catch(e){return this._secureLog("error","CRITICAL: Nested encryption security validation failed:",{errorType:e.constructor.name,errorMessage:e.message}),!1}return!0}getCallState(){return{...this.callState}}addCallStateListener(e){return typeof e!="function"?()=>{}:(this._callStateListeners.add(e),()=>this._callStateListeners.delete(e))}removeCallStateListener(e){this._callStateListeners.delete(e)}setCallGroupContext(e){this._callGroupContext=typeof e=="string"&&e?e:null,this._updateCallState({}),this._callGroupContext&&this._pendingCallOffer&&this.callState.phase==="incoming"&&this.acceptCall().catch(t=>{this._secureLog("warn","\u26A0\uFE0F Failed to answer a group call leg that was already ringing",{errorType:t?.constructor?.name})})}setExternalMediaStream(e){this._externalMediaStream=e||null}_usingExternalMedia(){return!!this._externalMediaStream&&this.localMediaStream===this._externalMediaStream}getRemoteMediaStream(){return this.remoteMediaStream}getLocalMediaStream(){return this.localMediaStream}_refreshRemoteStream(){let e=this.peerConnection;if(!e||typeof e.getReceivers!="function")return;let t=e.getReceivers().map(n=>n.track).filter(n=>n&&(n.kind==="audio"||n.kind==="video")&&n.readyState==="live"),i=this.remoteMediaStream?this.remoteMediaStream.getTracks():[];i.length===t.length&&i.every(n=>t.includes(n))||(this.remoteMediaStream=new MediaStream(t)),this._updateCallState({remoteHasVideo:t.some(n=>n.kind==="video")})}_scheduleRemoteRefresh(){this._refreshRemoteStream(),setTimeout(()=>{try{this._refreshRemoteStream()}catch{}},300),setTimeout(()=>{try{this._refreshRemoteStream()}catch{}},1200)}_updateCallState(e){this.callState={...this.callState,...e,groupCallId:this._callGroupContext};let t=this.getCallState();t.phase==="active"?this._startAdaptation():t.phase==="idle"&&this._stopAdaptation();try{this.onCallStateChanged?.(t)}catch{}for(let i of this._callStateListeners)try{i(t)}catch{}if(typeof document<"u")try{this._dispatchAppEvent?.(new CustomEvent("securebit-call-state",{detail:{managerId:this._managerId||null,state:t}}))}catch{}}_callCanStart(){let e=typeof this.isConnected=="function"?this.isConnected():!1,t=this.dataChannel&&this.dataChannel.readyState==="open";return!!(e&&t&&this.isVerified&&!this.isReconnecting())}async _sendCallSignal(e,t){return await this.sendSystemMessage({type:e,...t})}_audioConstraints(){return{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}}_videoConstraints(){return{facingMode:this._callFacingMode,width:{ideal:1280},height:{ideal:720}}}async _acquireLocalMedia(e){let t=this._externalMediaStream||await navigator.mediaDevices.getUserMedia({audio:this._audioConstraints(),video:e?this._videoConstraints():!1});this.localMediaStream=t;let i=this.peerConnection,r=t.getAudioTracks()[0]||null,n=t.getVideoTracks()[0]||null;return r&&(this._callAudioSender?await this._callAudioSender.replaceTrack(r):this._callAudioSender=i.addTrack(r,t)),n&&(this._callVideoSender?await this._callVideoSender.replaceTrack(n):this._callVideoSender=i.addTrack(n,t)),this._applyCallCodecPrefs(),t}_stopLocalMediaPermanently(){try{if(this.localMediaStream&&!this._usingExternalMedia())for(let e of this.localMediaStream.getTracks())try{e.stop()}catch{}}catch{}this.localMediaStream=null}_applyCallCodecPrefs(){try{let e=this.peerConnection?.getTransceivers?.()||[],t=e.find(r=>r.sender&&r.sender===this._callAudioSender);t&&Hr(t);let i=e.find(r=>r.sender&&r.sender===this._callVideoSender);i&&Yr(i)}catch{}}_mungeCallSdp(e){try{let t=bi(e,st.opusFmtp);return t=Br(t,Nr),t}catch{return e}}async _setLocalMunged(e){let t=this.peerConnection;try{await t.setLocalDescription({type:e.type,sdp:this._mungeCallSdp(e.sdp)});return}catch{try{await t.setLocalDescription({type:e.type,sdp:bi(e.sdp,st.opusFmtp)});return}catch{await t.setLocalDescription(e)}}}async _applyCallSenderParams(){try{this._callAudioSender&&await $r(this._callAudioSender,{}),this._callVideoSender&&await Xr(this._callVideoSender,{})}catch{}}_startAdaptation(){if(!(this._adaptationController||!this.peerConnection))try{this._adaptationController=new Pt(this.peerConnection,{getVideoSender:()=>this._callVideoSender,ceilingBitrate:15e5,onQuality:e=>{e!==this.callState.quality&&this._updateCallState({quality:e})}}),this._adaptationController.start()}catch{}}_stopAdaptation(){if(this._adaptationController){try{this._adaptationController.stop()}catch{}this._adaptationController=null}}_notifyCallMediaError(e,t){let i=e?.name||"",r=t?"camera/microphone":"microphone",n,a;i==="NotAllowedError"?(a="permission_denied",n=`\u26A0\uFE0F Call not started \u2014 ${r} access is blocked. Allow it for this site in the browser, and enable your browser under System Settings \u2192 Privacy & Security \u2192 ${t?"Camera/Microphone":"Microphone"}, then try again.`):i==="NotFoundError"||i==="OverconstrainedError"?(a="device_not_found",n=`\u26A0\uFE0F Call not started \u2014 no ${r} found on this device.`):i==="NotReadableError"||i==="AbortError"?(a="device_busy",n=`\u26A0\uFE0F Call not started \u2014 your ${r} is in use by another app. Close it and try again.`):(a="media_failed",n=`\u26A0\uFE0F Call not started \u2014 could not access ${r}${i?" ("+i+")":""}.`);try{this.deliverMessageToUI(n,"system")}catch{}return a}async startCall(e=!1){if(!this._callCanStart())throw this._updateCallState({error:"not_verified"}),new Error("Calls require a connected, SAS-verified session.");if(this.callState.active){this._secureLog("warn","\u26A0\uFE0F startCall ignored \u2014 a call is already active");return}let t=crypto?.randomUUID?.()||String(Date.now())+Math.random().toString(36).slice(2);this._updateCallState({active:!0,phase:"outgoing",withVideo:e,callId:t,micEnabled:!0,cameraEnabled:e,remoteHasVideo:!1,error:null});try{await this._acquireLocalMedia(e),this._callMakingOffer=!0;let i=await this.peerConnection.createOffer();await this._setLocalMunged(i),this._callMakingOffer=!1,await this._applyCallSenderParams(),await this._sendCallSignal(s.MESSAGE_TYPES.CALL_OFFER,{callId:t,withVideo:e,sdp:this.peerConnection.localDescription.sdp})}catch(i){this._callMakingOffer=!1,this._secureLog("error","\u274C startCall failed",{errorType:i?.constructor?.name});let r=this._notifyCallMediaError(i,e);throw await this._teardownCallMedia(),this._updateCallState({active:!1,phase:"idle",error:r}),i}}async _onIncomingCallOffer(e){if(this.callState.active&&(this.callState.phase==="active"||this.callState.phase==="connecting")){await this._answerCallOffer(e,!0),e.withVideo&&this._updateCallState({withVideo:!0});return}this._pendingCallOffer=e,this._updateCallState({active:!0,phase:"incoming",withVideo:!!e.withVideo,callId:e.callId,remoteHasVideo:!!e.withVideo,error:null}),this._callGroupContext&&await this.acceptCall()}async _answerCallOffer(e,t=!1){await this.peerConnection.setRemoteDescription({type:"offer",sdp:e.sdp}),t||await this._acquireLocalMedia(!!e.withVideo);let i=await this.peerConnection.createAnswer();await this._setLocalMunged(i),await this._applyCallSenderParams(),await this._sendCallSignal(s.MESSAGE_TYPES.CALL_ANSWER,{callId:e.callId,sdp:this.peerConnection.localDescription.sdp})}async acceptCall(){let e=this._pendingCallOffer;if(e){this._pendingCallOffer=null,this._updateCallState({phase:"connecting",cameraEnabled:!!e.withVideo});try{await this._answerCallOffer(e,!1),this._updateCallState({phase:"active"}),this._scheduleRemoteRefresh()}catch(t){this._secureLog("error","\u274C acceptCall failed",{errorType:t?.constructor?.name});let i=this._notifyCallMediaError(t,!!e.withVideo);try{await this._sendCallSignal(s.MESSAGE_TYPES.CALL_END,{callId:e.callId})}catch{}await this._teardownCallMedia(),this._updateCallState({active:!1,phase:"idle",error:i})}}}async declineCall(){let e=this.callState.callId;this._pendingCallOffer=null,await this._sendCallSignal(s.MESSAGE_TYPES.CALL_DECLINE,{callId:e}),this._updateCallState({active:!1,phase:"idle",withVideo:!1,remoteHasVideo:!1})}async endCall(e=!0){let t=this.callState.callId;if(e&&t)try{await this._sendCallSignal(s.MESSAGE_TYPES.CALL_END,{callId:t})}catch{}await this._teardownCallMedia(),this._updateCallState({active:!1,phase:"idle",withVideo:!1,micEnabled:!0,cameraEnabled:!1,remoteHasVideo:!1,callId:null,quality:null})}async _teardownCallMedia(){this._stopAdaptation();let e=this.peerConnection;try{if(this.localMediaStream&&!this._usingExternalMedia())for(let t of this.localMediaStream.getTracks())try{t.stop()}catch{}if(e)for(let t of[this._callAudioSender,this._callVideoSender].filter(Boolean))try{await t.replaceTrack(null)}catch{}}catch{}this.localMediaStream=null,this.remoteMediaStream=null,this._callMakingOffer=!1;try{this.peerConnection&&(this.peerConnection.signalingState==="have-local-offer"||this.peerConnection.signalingState==="have-local-pranswer")&&await this.peerConnection.setLocalDescription({type:"rollback"})}catch{}}setMicEnabled(e){this.localMediaStream&&this.localMediaStream.getAudioTracks().forEach(t=>{t.enabled=e}),this._updateCallState({micEnabled:e})}toggleMic(){this.setMicEnabled(!this.callState.micEnabled)}async setCameraEnabled(e){if(!e){this.localMediaStream&&this.localMediaStream.getVideoTracks().forEach(i=>{i.enabled=!1}),this._updateCallState({cameraEnabled:!1});return}let t=this.localMediaStream?.getVideoTracks?.()||[];if(t.length){t.forEach(i=>{i.enabled=!0}),this._updateCallState({cameraEnabled:!0,withVideo:!0});return}await this.upgradeToVideo()}async toggleCamera(){await this.setCameraEnabled(!this.callState.cameraEnabled)}async upgradeToVideo(){if(this.localMediaStream)try{let t=(await navigator.mediaDevices.getUserMedia({video:this._videoConstraints()})).getVideoTracks()[0];if(!t)return;await this.addVideoTrack(t)}catch(e){this._secureLog("error","\u274C upgradeToVideo failed",{errorType:e?.constructor?.name}),this._updateCallState({cameraEnabled:!1,error:"camera_failed"})}}async addVideoTrack(e){!e||!this.localMediaStream||!this.peerConnection||(this.localMediaStream.getVideoTracks().includes(e)||this.localMediaStream.addTrack(e),this._callVideoSender?await this._callVideoSender.replaceTrack(e):this._callVideoSender=this.peerConnection.addTrack(e,this.localMediaStream),this._applyCallCodecPrefs(),this._updateCallState({cameraEnabled:!0,withVideo:!0}),await this._renegotiateCall())}async replaceVideoTrack(e){!e||!this._callVideoSender||await this._callVideoSender.replaceTrack(e)}async switchCamera(){if(!(!this._callVideoSender||!this.localMediaStream)){this._callFacingMode=this._callFacingMode==="user"?"environment":"user";try{let t=(await navigator.mediaDevices.getUserMedia({video:{facingMode:this._callFacingMode}})).getVideoTracks()[0],i=this.localMediaStream.getVideoTracks()[0];if(i){this.localMediaStream.removeTrack(i);try{i.stop()}catch{}}this.localMediaStream.addTrack(t),await this._callVideoSender.replaceTrack(t)}catch(e){this._secureLog("warn","\u26A0\uFE0F switchCamera failed",{errorType:e?.constructor?.name})}}}async _renegotiateCall(){if(!this._callMakingOffer)try{this._callMakingOffer=!0;let e=await this.peerConnection.createOffer();await this._setLocalMunged(e),await this._applyCallSenderParams(),await this._sendCallSignal(s.MESSAGE_TYPES.CALL_OFFER,{callId:this.callState.callId,withVideo:this.callState.withVideo,sdp:this.peerConnection.localDescription.sdp})}finally{this._callMakingOffer=!1}}async _handleCallSignal(e,t){let i=s.MESSAGE_TYPES;switch(e){case i.CALL_OFFER:{await this._onIncomingCallOffer(t);return}case i.CALL_ANSWER:{try{this.peerConnection.signalingState==="have-local-offer"&&await this.peerConnection.setRemoteDescription({type:"answer",sdp:t.sdp}),this.callState.phase==="outgoing"&&this._updateCallState({phase:"active"}),this._scheduleRemoteRefresh()}catch(r){this._secureLog("warn","\u26A0\uFE0F Failed to apply call answer",{errorType:r?.constructor?.name})}return}case i.CALL_ICE:{try{t.candidate&&await this.peerConnection.addIceCandidate(t.candidate)}catch{}return}case i.CALL_DECLINE:{await this._teardownCallMedia(),this._updateCallState({active:!1,phase:"idle",withVideo:!1,remoteHasVideo:!1,error:"declined"});return}case i.CALL_END:{await this.endCall(!1);return}default:return}}},Bt=class{constructor(e=null){this._keyStore=new WeakMap,this._keyMetadata=new Map,this._keyReferences=new Map,this._masterKeyManager=e||new $t,this._persistentStorage=new Ui(this._masterKeyManager),this._setupMasterKeyCallbacks(),setTimeout(()=>{this.validateStorageIntegrity()||this._secureLog("error","CRITICAL: Key storage integrity check failed")},100)}_secureLog(e,t,i={}){try{let r=typeof window<"u"&&window.EnhancedSecureCryptoUtils?.secureLog||null;if(r&&typeof r.log=="function"){r.log(e,`[KeyStorage] ${t}`,i);return}}catch{}e==="error"?console.error(`[KeyStorage] ${t}`):e==="warn"&&console.warn(`[KeyStorage] ${t}`)}_setupMasterKeyCallbacks(){this._masterKeyManager.setPasswordRequiredCallback((e,t)=>{this._secureLog("error","Master key password requested but no password UI is installed",{isRetry:!!e}),t(null)}),this._masterKeyManager.setSessionExpiredCallback(e=>{console.warn(`Master key session expired: ${e}`)}),this._masterKeyManager.setUnlockedCallback(()=>{console.log("Master key unlocked successfully")})}setPasswordCallback(e){this._masterKeyManager.setPasswordRequiredCallback(e)}setSessionExpiredCallback(e){this._masterKeyManager.setSessionExpiredCallback(e)}async _ensureMasterKeyUnlocked(){this._masterKeyManager.isUnlocked()||await this._masterKeyManager.unlock()}async storeKey(e,t,i={}){if(!(t instanceof CryptoKey))throw new Error("Only CryptoKey objects can be stored");try{return t.extractable?(await this._persistentStorage.storeExtractableKey(e,t,i),this._keyReferences.set(e,t),this._keyMetadata.set(e,{...i,created:Date.now(),lastAccessed:Date.now(),extractable:!0,persistent:!0,encrypted:!0}),!0):(this._keyReferences.set(e,t),this._keyMetadata.set(e,{...i,created:Date.now(),lastAccessed:Date.now(),extractable:!1,persistent:!1,encrypted:!1}),!0)}catch(r){return this._secureLog("error","Failed to store key securely",{errorType:r?.constructor?.name||"Unknown"}),!1}}async retrieveKey(e){try{if(this._keyReferences.has(e)){let i=this._keyMetadata.get(e);return i&&(i.lastAccessed=Date.now()),this._keyReferences.get(e)}let t=await this._persistentStorage.retrieveKey(e);if(t){this._keyReferences.set(e,t);let i=this._keyMetadata.get(e);return this._keyMetadata.set(e,{...i,lastAccessed:Date.now(),restoredFromPersistent:!0}),t}return null}catch(t){return this._secureLog("error","Failed to retrieve key",{errorType:t?.constructor?.name||"Unknown"}),null}}async _encryptKeyData(e){let t=typeof e=="object"?JSON.stringify(e):e,r=new TextEncoder().encode(t);await this._ensureMasterKeyUnlocked();let{encryptedData:n,iv:a}=await this._masterKeyManager.encryptBytes(r),o=new Uint8Array(a.length+n.byteLength);return o.set(a,0),o.set(n,a.length),o}async _decryptKeyData(e){let t=e.slice(0,12),i=e.slice(12);await this._ensureMasterKeyUnlocked();let r=await this._masterKeyManager.decryptBytes(i,t),a=new TextDecoder().decode(r);try{return JSON.parse(a)}catch{return r}}async secureWipe(e){let t=this._keyReferences.get(e);t&&(this._keyStore.delete(t),this._keyReferences.delete(e),this._keyMetadata.delete(e)),await this._performNaturalCleanup()}async secureWipeAll(){try{await this._persistentStorage.clearAll()}catch(e){this._secureLog("error","Failed to clear persistent storage",{errorType:e?.constructor?.name||"Unknown"})}this._keyReferences.clear(),this._keyMetadata.clear(),this._keyStore=new WeakMap,await this._performNaturalCleanup()}validateStorageIntegrity(){let e=[];for(let[t,i]of this._keyMetadata.entries())i.extractable===!0&&i.encrypted!==!0&&e.push({keyId:t,type:"EXTRACTABLE_KEY_NOT_ENCRYPTED",metadata:i}),i.extractable===!1&&i.encrypted===!0&&e.push({keyId:t,type:"NON_EXTRACTABLE_KEY_ENCRYPTED",metadata:i});return e.length>0?(this._secureLog("error","Storage integrity violations detected",{violationCount:e.length}),!1):!0}async getStorageStats(){let e=await this._persistentStorage.getStorageStats();return{totalKeys:this._keyReferences.size,memoryKeys:this._keyReferences.size,persistentKeys:e.persistentKeys,metadata:Array.from(this._keyMetadata.entries()).map(([t,i])=>({id:t,created:i.created,lastAccessed:i.lastAccessed,age:Date.now()-i.created,persistent:i.persistent||!1})),persistent:e}}async listAllKeys(){try{let e=Array.from(this._keyMetadata.entries()).map(([r,n])=>({keyId:r,...n,location:"memory"})),i=(await this._persistentStorage.listStoredKeys()).map(r=>({...r,location:"persistent"}));return{memoryKeys:e,persistentKeys:i,totalCount:e.length+i.length}}catch(e){return this._secureLog("error","Failed to list keys",{errorType:e?.constructor?.name||"Unknown"}),{memoryKeys:[],persistentKeys:[],totalCount:0,error:e.message}}}async deleteKey(e){try{return this._keyReferences.delete(e),this._keyMetadata.delete(e),await this._persistentStorage.deleteKey(e),!0}catch(t){return this._secureLog("error","Failed to delete key",{errorType:t?.constructor?.name||"Unknown"}),!1}}},Ht=class{constructor(e="SecureKeyStorage",t=1){this.dbName=e,this.version=t,this.db=null,this.KEYS_STORE="encrypted_keys",this.METADATA_STORE="key_metadata",this.SALT_STORE="master_salt"}async initialize(){return new Promise((e,t)=>{let i=indexedDB.open(this.dbName,this.version);i.onerror=()=>{t(new Error(`Failed to open IndexedDB: ${i.error}`))},i.onsuccess=()=>{this.db=i.result,e()},i.onupgradeneeded=r=>{let n=r.target.result;if(!n.objectStoreNames.contains(this.KEYS_STORE)){let a=n.createObjectStore(this.KEYS_STORE,{keyPath:"keyId"});a.createIndex("timestamp","timestamp",{unique:!1}),a.createIndex("algorithm","algorithm",{unique:!1})}if(!n.objectStoreNames.contains(this.METADATA_STORE)){let a=n.createObjectStore(this.METADATA_STORE,{keyPath:"keyId"});a.createIndex("created","created",{unique:!1}),a.createIndex("lastAccessed","lastAccessed",{unique:!1})}n.objectStoreNames.contains(this.SALT_STORE)||n.createObjectStore(this.SALT_STORE,{keyPath:"id"})}})}async storeEncryptedKey(e,t,i,r,n,a,o={}){if(!this.db)throw new Error("Database not initialized");let c=this.db.transaction([this.KEYS_STORE,this.METADATA_STORE],"readwrite"),l={keyId:e,encryptedData:Array.from(new Uint8Array(t)),iv:Array.from(new Uint8Array(i)),algorithm:r,usages:n,type:a},h={keyId:e,...o};return new Promise((u,p)=>{let S=c.objectStore(this.KEYS_STORE).put(l),w=c.objectStore(this.METADATA_STORE).put(h);c.oncomplete=()=>u(),c.onerror=()=>p(new Error(`Failed to store key: ${c.error}`))})}async getEncryptedKey(e){if(!this.db)throw new Error("Database not initialized");let i=this.db.transaction([this.KEYS_STORE],"readonly").objectStore(this.KEYS_STORE);return new Promise((r,n)=>{let a=i.get(e);a.onsuccess=()=>{let o=a.result;o&&(o.encryptedData=new Uint8Array(o.encryptedData),o.iv=new Uint8Array(o.iv)),r(o)},a.onerror=()=>n(new Error(`Failed to retrieve key: ${a.error}`))})}async updateKeyMetadata(e,t){if(!this.db)throw new Error("Database not initialized");let r=this.db.transaction([this.METADATA_STORE],"readwrite").objectStore(this.METADATA_STORE);return new Promise((n,a)=>{let o=r.get(e);o.onsuccess=()=>{let c=o.result;if(c){Object.assign(c,t);let l=r.put(c);l.onsuccess=()=>n(),l.onerror=()=>a(new Error(`Failed to update metadata: ${l.error}`))}else a(new Error(`Key metadata not found: ${e}`))},o.onerror=()=>a(new Error(`Failed to get metadata: ${o.error}`))})}async getKeyMetadataRecord(e){if(!this.db)throw new Error("Database not initialized");let i=this.db.transaction([this.METADATA_STORE],"readonly").objectStore(this.METADATA_STORE);return new Promise((r,n)=>{let a=i.get(e);a.onsuccess=()=>r(a.result||null),a.onerror=()=>n(new Error(`Failed to get metadata: ${a.error}`))})}async putKeyMetadataRecord(e){if(!this.db)throw new Error("Database not initialized");let i=this.db.transaction([this.METADATA_STORE],"readwrite").objectStore(this.METADATA_STORE);return new Promise((r,n)=>{let a=i.put(e);a.onsuccess=()=>r(),a.onerror=()=>n(new Error(`Failed to store metadata: ${a.error}`))})}async deleteKey(e){if(!this.db)throw new Error("Database not initialized");let t=this.db.transaction([this.KEYS_STORE,this.METADATA_STORE],"readwrite");return new Promise((i,r)=>{let n=t.objectStore(this.KEYS_STORE).delete(e),a=t.objectStore(this.METADATA_STORE).delete(e);t.oncomplete=()=>i(),t.onerror=()=>r(new Error(`Failed to delete key: ${t.error}`))})}async listKeys(){if(!this.db)throw new Error("Database not initialized");let t=this.db.transaction([this.METADATA_STORE],"readonly").objectStore(this.METADATA_STORE);return new Promise((i,r)=>{let n=t.getAll();n.onsuccess=()=>i(n.result),n.onerror=()=>r(new Error(`Failed to list keys: ${n.error}`))})}async storeMasterSalt(e){if(!this.db)throw new Error("Database not initialized");let i=this.db.transaction([this.SALT_STORE],"readwrite").objectStore(this.SALT_STORE),r={id:"master_salt",salt:Array.from(new Uint8Array(e))};return new Promise((n,a)=>{let o=i.put(r);o.onsuccess=()=>n(),o.onerror=()=>a(new Error(`Failed to store salt: ${o.error}`))})}async getMasterSalt(){if(!this.db)throw new Error("Database not initialized");let t=this.db.transaction([this.SALT_STORE],"readonly").objectStore(this.SALT_STORE);return new Promise((i,r)=>{let n=t.get("master_salt");n.onsuccess=()=>{let a=n.result;i(a?new Uint8Array(a.salt):null)},n.onerror=()=>r(new Error(`Failed to retrieve salt: ${n.error}`))})}async clearAll(){if(!this.db)throw new Error("Database not initialized");let e=this.db.transaction([this.KEYS_STORE,this.METADATA_STORE,this.SALT_STORE],"readwrite");return new Promise((t,i)=>{let r=e.objectStore(this.KEYS_STORE).clear(),n=e.objectStore(this.METADATA_STORE).clear(),a=e.objectStore(this.SALT_STORE).clear();e.oncomplete=()=>t(),e.onerror=()=>i(new Error(`Failed to clear database: ${e.error}`))})}close(){this.db&&(this.db.close(),this.db=null)}},Ui=class{constructor(e,t=null){this._masterKeyManager=e,this._indexedDB=t||new Ht,this._dbInitialized=!1,this._keyCache=new WeakMap,this._keyReferences=new Map}async _ensureDBInitialized(){this._dbInitialized||(await this._indexedDB.initialize(),this._dbInitialized=!0)}async _ensureMasterKeyUnlocked(){typeof this._masterKeyManager.isUnlocked=="function"&&!this._masterKeyManager.isUnlocked()&&await this._masterKeyManager.unlock()}async storeExtractableKey(e,t,i={}){if(!(t instanceof CryptoKey))throw new Error("Only CryptoKey objects can be stored");if(!t.extractable)throw new Error("Key must be extractable for persistent storage");try{await this._ensureDBInitialized();let r=await crypto.subtle.exportKey("jwk",t),{encryptedData:n,iv:a}=await this._encryptKeyData(r),o=await this._encryptMetadata({...i,created:Date.now(),lastAccessed:Date.now(),extractable:!0,persistent:!0});await this._indexedDB.storeEncryptedKey(e,n,a,t.algorithm,t.usages,t.type,o);let c=await this._importAsNonExtractable(r,t.algorithm,t.usages);return this._keyReferences.set(e,c),!0}catch(r){throw new Error(`Failed to store extractable key: ${r.message}`)}}async retrieveKey(e){try{if(this._keyReferences.has(e))return this._keyReferences.get(e);await this._ensureDBInitialized();let t=await this._indexedDB.getEncryptedKey(e);if(!t)return null;let i=await this._decryptKeyData(t.encryptedData,t.iv),r=await this._importAsNonExtractable(i,t.algorithm,t.usages);return this._keyReferences.set(e,r),await this._updateEncryptedMetadata(e,{lastAccessed:Date.now()}),r}catch(t){throw new Error(`Failed to retrieve key: ${t.message}`)}}async deleteKey(e){try{return await this._ensureDBInitialized(),await this._indexedDB.deleteKey(e),this._keyReferences.delete(e),!0}catch(t){throw new Error(`Failed to delete key: ${t.message}`)}}async listStoredKeys(){try{await this._ensureDBInitialized();let e=await this._indexedDB.listKeys(),t=[];for(let i of e){let r=await this._readMetadataWithMigration(i);r&&t.push({keyId:i.keyId,...r})}return t}catch(e){throw new Error(`Failed to list keys: ${e.message}`)}}async clearAll(){try{return await this._ensureDBInitialized(),await this._indexedDB.clearAll(),this._keyReferences.clear(),!0}catch(e){throw new Error(`Failed to clear storage: ${e.message}`)}}async _encryptKeyData(e){let t=JSON.stringify(e),i=new TextEncoder().encode(t);return await this._ensureMasterKeyUnlocked(),await this._masterKeyManager.encryptBytes(i)}async _decryptKeyData(e,t){await this._ensureMasterKeyUnlocked();let i=await this._masterKeyManager.decryptBytes(e,t),r=new TextDecoder().decode(i);return JSON.parse(r)}async _encryptMetadata(e){let t=new TextEncoder().encode(JSON.stringify(e));await this._ensureMasterKeyUnlocked();let{encryptedData:i,iv:r}=await this._masterKeyManager.encryptBytes(t);return{metadataVersion:1,encryptedMetadata:Array.from(i),metadataIv:Array.from(r)}}async _decryptMetadataRecord(e){if(!e?.encryptedMetadata||!e?.metadataIv)throw new Error("Encrypted metadata missing");await this._ensureMasterKeyUnlocked();let t=await this._masterKeyManager.decryptBytes(new Uint8Array(e.encryptedMetadata),new Uint8Array(e.metadataIv));return JSON.parse(new TextDecoder().decode(t))}async _readMetadataWithMigration(e){if(!e)return null;if(e.encryptedMetadata)try{return await this._decryptMetadataRecord(e)}catch{return null}let{keyId:t,...i}=e,r={keyId:t,...await this._encryptMetadata(i)};return await this._indexedDB.putKeyMetadataRecord(r),i}async _updateEncryptedMetadata(e,t){let i=await this._indexedDB.getKeyMetadataRecord(e);if(!i)throw new Error(`Key metadata not found: ${e}`);let r=await this._readMetadataWithMigration(i);if(!r)throw new Error(`Key metadata corrupted: ${e}`);await this._indexedDB.putKeyMetadataRecord({keyId:e,...await this._encryptMetadata({...r,...t})})}async _importAsNonExtractable(e,t,i){return await crypto.subtle.importKey("jwk",e,t,!1,i)}async getStorageStats(){try{await this._ensureDBInitialized();let e=await this._indexedDB.listKeys();return{totalKeys:e.length,memoryKeys:this._keyReferences.size,persistentKeys:e.length,lastAccessed:e.reduce((t,i)=>Math.max(t,i.lastAccessed||0),0)}}catch(e){return{totalKeys:0,memoryKeys:this._keyReferences.size,persistentKeys:0,lastAccessed:0,error:e.message}}}},$t=class{constructor(e=null){this._keyHandle=null,this._isUnlocked=!1,this._sessionTimeout=null,this._lastActivity=null,this._sessionTimeoutMs=3600*1e3,this._inactivityTimeoutMs=1800*1e3,this._pbkdf2Iterations=31e4,this._saltSize=32,this._indexedDB=e||new Ht,this._dbInitialized=!1,this._onPasswordRequired=null,this._onSessionExpired=null,this._onUnlocked=null}setPasswordRequiredCallback(e){this._onPasswordRequired=e}setSessionExpiredCallback(e){this._onSessionExpired=e}setUnlockedCallback(e){this._onUnlocked=e}_setupEventListeners(){typeof document<"u"&&(document.addEventListener("visibilitychange",()=>{document.hidden?this._handleFocusOut():this._handleFocusIn()}),window.addEventListener("blur",()=>this._handleFocusOut()),window.addEventListener("focus",()=>this._handleFocusIn()),["mousedown","mousemove","keypress","scroll","touchstart"].forEach(e=>{document.addEventListener(e,()=>this._updateActivity(),{passive:!0})}))}_handleFocusOut(){this._isUnlocked&&this._startInactivityTimer(this._inactivityTimeoutMs)}_handleFocusIn(){this._isUnlocked&&this._resetSessionTimer()}_updateActivity(){this._lastActivity=Date.now(),this._isUnlocked&&this._resetSessionTimer()}_startSessionTimer(){this._clearTimers(),this._sessionTimeout=setTimeout(()=>{this._expireSession("timeout")},this._sessionTimeoutMs)}_startInactivityTimer(e){this._clearTimers(),this._sessionTimeout=setTimeout(()=>{this._expireSession("inactivity")},e)}_resetSessionTimer(){this._isUnlocked&&this._startSessionTimer()}_clearTimers(){this._sessionTimeout&&(clearTimeout(this._sessionTimeout),this._sessionTimeout=null)}_expireSession(e="unknown"){this._isUnlocked&&(this._secureWipeMasterKey(),this._isUnlocked=!1,this._onSessionExpired&&this._onSessionExpired(e))}async _ensureDBInitialized(){this._dbInitialized||(await this._indexedDB.initialize(),this._dbInitialized=!0)}_generateSalt(){return crypto.getRandomValues(new Uint8Array(this._saltSize))}async _getOrCreateSalt(){await this._ensureDBInitialized();let e=await this._indexedDB.getMasterSalt();return e||(e=this._generateSalt(),await this._indexedDB.storeMasterSalt(e)),e}async _deriveKeyFromPassword(e,t){try{let i=await crypto.subtle.importKey("raw",new TextEncoder().encode(e),"PBKDF2",!1,["deriveKey"]);return await crypto.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:this._pbkdf2Iterations,hash:"SHA-256"},i,{name:"AES-GCM",length:256},!1,["encrypt","decrypt","wrapKey","unwrapKey"])}catch(i){throw new Error(`Key derivation failed: ${i.message}`)}}async _requestPassword(e=!1){if(!this._onPasswordRequired)throw new Error("Password callback not set");return new Promise((t,i)=>{this._onPasswordRequired(e,r=>{r?t(r):i(new Error("Password not provided"))})})}async unlock(e=null){try{e||(e=await this._requestPassword(!1));let t=await this._getOrCreateSalt();return this._keyHandle=await this._deriveKeyFromPassword(e,t),this._isUnlocked=!0,this._lastActivity=Date.now(),this._startSessionTimer(),e=null,this._onUnlocked&&this._onUnlocked(),{success:!0}}catch(t){throw e=null,t}}lock(){this._expireSession("manual")}async encryptBytes(e){if(!this._isUnlocked||!this._keyHandle)throw new Error("Master key is locked");this._updateActivity();let t=crypto.getRandomValues(new Uint8Array(12)),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:t},this._keyHandle,e);return{encryptedData:new Uint8Array(i),iv:t}}async decryptBytes(e,t){if(!this._isUnlocked||!this._keyHandle)throw new Error("Master key is locked");this._updateActivity();let i=await crypto.subtle.decrypt({name:"AES-GCM",iv:t},this._keyHandle,e);return new Uint8Array(i)}isUnlocked(){return this._isUnlocked&&this._keyHandle!==null}getSessionStatus(){return{isUnlocked:this._isUnlocked,lastActivity:this._lastActivity,sessionTimeoutMs:this._sessionTimeoutMs,inactivityTimeoutMs:this._inactivityTimeoutMs}}_secureWipeMasterKey(){this._keyHandle&&(this._keyHandle=null),this._clearTimers()}destroy(){this._secureWipeMasterKey(),this._isUnlocked=!1,typeof document<"u"&&(document.removeEventListener("visibilitychange",this._handleFocusOut),window.removeEventListener("blur",this._handleFocusOut),window.removeEventListener("focus",this._handleFocusIn))}};var Fn=hr(vn());var kn="6.7.3";var zi=()=>{if(Ke.length<2)return null;let[s,e]=React.useState(!1),t=React.useRef(null),i=typeof window<"u"?window.location.pathname:"/",r=Kr({pathname:i,active:Ge()}),n=r.find(c=>c.isCurrent)||r[0];React.useEffect(()=>{if(!s)return;let c=h=>{t.current&&!t.current.contains(h.target)&&e(!1)},l=h=>{h.key==="Escape"&&e(!1)};return document.addEventListener("pointerdown",c),document.addEventListener("keydown",l),()=>{document.removeEventListener("pointerdown",c),document.removeEventListener("keydown",l)}},[s]);let a=React.createElement("button",{key:"trigger",type:"button",onClick:()=>e(c=>!c),"aria-haspopup":"menu","aria-expanded":s?"true":"false","aria-label":f("language.label"),style:{display:"flex",alignItems:"center",gap:"6px",padding:"7px 10px",borderRadius:"9px",border:"1px solid rgba(255,255,255,0.07)",background:s?"rgba(255,255,255,0.06)":"rgba(255,255,255,0.02)",color:"#cfcfd4",font:"inherit",fontSize:"12.5px",fontWeight:600,cursor:"pointer",transition:"background .15s, color .15s"}},[React.createElement("span",{key:"c"},n?n.abbr:""),React.createElement("svg",{key:"v",width:11,height:11,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.4,strokeLinecap:"round",strokeLinejoin:"round",style:{transform:s?"rotate(180deg)":"none",transition:"transform .18s"},dangerouslySetInnerHTML:{__html:''}})]),o=React.createElement("div",{key:"menu",role:"menu",className:"sb-scroll",style:{position:"absolute",top:"calc(100% + 6px)",insetInlineEnd:0,zIndex:60,display:s?"block":"none",minWidth:"170px",padding:"5px",borderRadius:"11px",border:"1px solid rgba(255,255,255,0.08)",background:"#161618",boxShadow:"0 14px 34px rgba(0,0,0,0.45)",maxHeight:"min(62vh, 420px)",overflowY:"auto",overscrollBehavior:"contain"}},r.map(c=>React.createElement("a",{key:c.code,href:c.href,hrefLang:c.hrefLang,lang:c.hrefLang,dir:c.dir,role:"menuitem","aria-current":c.isCurrent?"page":void 0,onClick:()=>Pr(c.code),style:{display:"flex",alignItems:"center",gap:"10px",padding:"8px 10px",borderRadius:"8px",fontSize:"13px",fontWeight:c.isCurrent?600:500,color:c.isCurrent?"#e8e8eb":"#9a9aa2",background:c.isCurrent?"rgba(255,255,255,0.06)":"transparent",textDecoration:"none",whiteSpace:"nowrap"}},[React.createElement("span",{key:"a",style:{fontSize:"11px",fontWeight:700,letterSpacing:"0.4px",color:"#6b6b73",width:"22px",flex:"none",textAlign:"start"}},c.abbr),React.createElement("span",{key:"n"},c.label)])));return React.createElement("nav",{ref:t,"aria-label":f("language.label"),style:{position:"relative",display:"inline-flex"}},[a,o])};window.LanguageSwitcher=zi;var Ta=`v${kn}`,Ca=({status:s,fingerprint:e,verificationCode:t,onDisconnect:i,isConnected:r,securityLevel:n,webrtcManager:a})=>{let[o,c]=React.useState(null),[l,h]=React.useState(0),[u,p]=React.useState(!1),[S,w]=React.useState(0),[g,m]=React.useState("unknown");React.useEffect(()=>{let U=!1,H=0,A=async()=>{let K=Date.now();if(!(K-H<1e4)&&!U){U=!0,H=K;try{if(!a||!r)return;let z=a,W=null;if(typeof z.getRealSecurityLevel=="function"?W=await z.getRealSecurityLevel():typeof z.calculateAndReportSecurityLevel=="function"?W=await z.calculateAndReportSecurityLevel():W=await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(z),W&&W.isRealData!==!1){let X=o?.score||0,Se=W.score||0;X!==Se||!o?(c(W),h(K)):window.DEBUG_MODE}}catch{}finally{U=!1}}};if(r&&(A(),!o||o.score<50)){let K=setInterval(()=>{!o||o.score<50?A():clearInterval(K)},5e3);setTimeout(()=>clearInterval(K),3e4)}let F=setInterval(A,3e4);return()=>clearInterval(F)},[a,r]),React.useEffect(()=>{let U=A=>{setTimeout(()=>{h(0)},100)},H=A=>{A.detail&&A.detail.securityData&&(c(A.detail.securityData),h(Date.now()))};return document.addEventListener("security-level-updated",U),document.addEventListener("real-security-calculated",H),window.forceHeaderSecurityUpdate=A=>{A&&window.EnhancedSecureCryptoUtils?window.EnhancedSecureCryptoUtils.calculateSecurityLevel(A).then(F=>{F&&F.isRealData!==!1&&(c(F),h(Date.now()))}).catch(F=>{}):h(0)},()=>{document.removeEventListener("security-level-updated",U),document.removeEventListener("real-security-calculated",H)}},[]),React.useEffect(()=>{p(!0),w(0),m("premium")},[]),React.useEffect(()=>{p(!0),w(0),m("premium")},[]),React.useEffect(()=>{let U=K=>{p(!0),w(0),m("premium")},H=()=>{c(null),h(0),p(!1),w(0),m("unknown")},A=()=>{c(null),h(0)},F=()=>{c(null),h(0),p(!1),w(0),m("unknown")};return document.addEventListener("force-header-update",U),document.addEventListener("peer-disconnect",A),document.addEventListener("connection-cleaned",H),document.addEventListener("disconnected",F),()=>{document.removeEventListener("force-header-update",U),document.removeEventListener("peer-disconnect",A),document.removeEventListener("connection-cleaned",H),document.removeEventListener("disconnected",F)}},[]);let I=async U=>{if(U&&(U.button===2||U.ctrlKey||U.metaKey)&&i&&typeof i=="function"){i();return}U.preventDefault(),U.stopPropagation();let H=null;if(a&&window.EnhancedSecureCryptoUtils)try{H=await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(a)}catch{}if(!H&&!o){alert(f("sec.verificationWait"));return}let A=H||o;A||(A={level:"UNKNOWN",score:0,color:"gray",verificationResults:{},timestamp:Date.now(),details:f("sec.verificationUnavailable"),isRealData:!1,passedChecks:0,totalChecks:0});let F=`REAL-TIME SECURITY VERIFICATION `;if(F+=`Security Level: ${A.level} (${A.score}%) `,F+=`Verification Time: ${new Date(A.timestamp).toLocaleTimeString()} `,F+=`Data Source: ${A.isRealData?f("sec.realTests"):f("sec.simulatedData")} `,A.verificationResults){F+=`DETAILED CRYPTOGRAPHIC TESTS: `,F+="="+"=".repeat(40)+` `;let X=Object.entries(A.verificationResults).filter(([_e,ge])=>ge.passed),Se=Object.entries(A.verificationResults).filter(([_e,ge])=>!ge.passed);X.length>0&&(F+=`PASSED TESTS: `,X.forEach(([_e,ge])=>{let Ye=_e.replace(/([A-Z])/g," $1").replace(/^./,Y=>Y.toUpperCase());F+=` ${Ye}: ${ge.details||f("sec.testPassed")} `}),F+=` `),Se.length>0&&(F+=`FAILED/UNAVAILABLE TESTS: `,Se.forEach(([_e,ge])=>{let Ye=_e.replace(/([A-Z])/g," $1").replace(/^./,Y=>Y.toUpperCase());F+=` ${Ye}: ${ge.details||f("sec.testFailed")} `}),F+=` `),F+=`SUMMARY: `,F+=`Passed: ${A.passedChecks}/${A.totalChecks} tests `,F+=`Score: ${A.score}/${A.maxPossibleScore||100} points `}if(F+=`SECURITY FEATURES STATUS: `,F+="="+"=".repeat(40)+` `,A.verificationResults){let X={"ECDSA Digital Signatures":A.verificationResults.verifyECDSASignatures?.passed||!1,"ECDH Key Exchange":A.verificationResults.verifyECDHKeyExchange?.passed||!1,"AES-GCM Encryption":A.verificationResults.verifyEncryption?.passed||!1,[f("sec.messageIntegrity")]:A.verificationResults.verifyMessageIntegrity?.passed||!1,[f("sec.forwardSecrecy")]:A.verificationResults.verifyPerfectForwardSecrecy?.passed||!1,[f("sec.replayProtection")]:A.verificationResults.verifyReplayProtection?.passed||!1,"DTLS Fingerprint":A.verificationResults.verifyDTLSFingerprint?.passed||!1,"SAS Verification":A.verificationResults.verifySASVerification?.passed||!1,[f("sec.metadataProtection")]:A.verificationResults.verifyMetadataProtection?.passed||!1,[f("sec.trafficObfuscation")]:A.verificationResults.verifyTrafficObfuscation?.passed||!1};Object.entries(X).forEach(([Se,_e])=>{F+=`${_e?"\u2705":"\u274C"} ${Se} `})}else F+=`\u2705 ECDSA Digital Signatures `,F+=`\u2705 ECDH Key Exchange `,F+=`\u2705 AES-GCM Encryption `,F+=`\u2705 Message Integrity (HMAC) `,F+=`\u2705 Perfect Forward Secrecy `,F+=`\u2705 Replay Protection `,F+=`\u2705 DTLS Fingerprint `,F+=`\u2705 SAS Verification `,F+=`\u2705 Metadata Protection `,F+=`\u2705 Traffic Obfuscation `;F+=` ${A.details||f("sec.verificationDone")}`,A.isRealData?F+=` \u2705 This is REAL-TIME verification using actual cryptographic functions.`:F+=` \u26A0\uFE0F Warning: This data may be simulated. Connection may not be fully established.`;let K=document.createElement("div");K.style.cssText=` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 10000; display: flex; align-items: center; justify-content: center; font-family: monospace; `;let z=document.createElement("div");z.style.cssText=` background: #1a1a1a; color: #fff; padding: 20px; border-radius: 8px; max-width: 80%; max-height: 80%; overflow-y: auto; white-space: pre-line; border: 1px solid #333; `,z.textContent=F,K.appendChild(z),K.addEventListener("click",X=>{X.target===K&&document.body.removeChild(K)});let W=X=>{X.key==="Escape"&&(document.body.removeChild(K),document.removeEventListener("keydown",W))};document.addEventListener("keydown",W),document.body.appendChild(K)},D=(()=>{switch(s){case"connected":return{text:f("status.connected"),className:"status-connected",badgeClass:"bg-green-500/10 text-green-400 border-green-500/20"};case"verifying":return{text:f("status.verifying"),className:"status-verifying",badgeClass:"bg-purple-500/10 text-purple-400 border-purple-500/20"};case"connecting":return{text:f("status.connecting"),className:"status-connecting",badgeClass:"bg-blue-500/10 text-blue-400 border-blue-500/20"};case"retrying":return{text:f("status.retrying"),className:"status-connecting",badgeClass:"bg-yellow-500/10 text-yellow-400 border-yellow-500/20"};case"failed":return{text:f("status.error"),className:"status-failed",badgeClass:"bg-red-500/10 text-red-400 border-red-500/20"};case"reconnecting":return{text:f("status.reconnecting"),className:"status-connecting",badgeClass:"bg-yellow-500/10 text-yellow-400 border-yellow-500/20"};case"peer_disconnected":return{text:f("status.peerDisconnected"),className:"status-failed",badgeClass:"bg-orange-500/10 text-orange-400 border-orange-500/20"};default:return{text:f("status.notConnected"),className:"status-disconnected",badgeClass:"bg-gray-500/10 text-gray-400 border-gray-500/20"}}})(),_=r?o||n:null,E=(()=>{if(!_)return{tooltip:f("sec.verificationInProgress"),isVerified:!1,dataSource:"loading"};let U=_.isRealData!==!1,H=`${_.level} (${_.score}%)`;return U?{tooltip:`${H} - Real-time verification \u2705 Right-click or Ctrl+click to disconnect`,isVerified:!0,dataSource:"real"}:{tooltip:`${H} - Estimated (connection establishing...) Right-click or Ctrl+click to disconnect`,isVerified:!1,dataSource:"estimated"}})();React.useEffect(()=>(window.debugHeaderSecurity=void 0,()=>{delete window.debugHeaderSecurity}),[o,l,r,a,_,E]);let C=_?_.color==="green"?"#3ecf8e":_.color==="orange"?"#f0892a":_.color==="yellow"?"#e3c84e":"#e5727a":"#3ecf8e",M=r?"#3ecf8e":["connecting","verifying","retrying","reconnecting"].includes(s)?"#e3c84e":s==="failed"?"#e5727a":"#6b6b73",v=M==="#3ecf8e"?"rgba(62,207,142,0.16)":M==="#e3c84e"?"rgba(227,200,78,0.16)":M==="#e5727a"?"rgba(229,114,122,0.16)":"rgba(107,107,115,0.16)",q="'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",O=!r,[x,ue]=React.useState(!1);React.useEffect(()=>{let U=()=>ue((window.scrollY||window.pageYOffset||0)>8);return U(),window.addEventListener("scroll",U,{passive:!0}),()=>window.removeEventListener("scroll",U)},[]);let ne="blur(20px) saturate(180%)",te="background .25s ease, backdrop-filter .25s ease, -webkit-backdrop-filter .25s ease, border-color .25s ease",ye={paddingTop:"var(--sb-safe-top, 0px)",paddingBottom:"var(--sb-bar-extra, 0px)"},Re={position:"fixed",top:0,left:0,right:0,...ye},j=O?x?{...Re,background:"rgba(15,15,17,0.72)",backdropFilter:ne,WebkitBackdropFilter:ne,borderBottom:"1px solid rgba(255,255,255,0.06)",transition:te}:{...Re,background:"transparent",backdropFilter:"blur(0px) saturate(100%)",WebkitBackdropFilter:"blur(0px) saturate(100%)",borderBottom:"1px solid transparent",transition:te}:{...ye,background:"rgba(18,18,20,0.72)",backdropFilter:ne,WebkitBackdropFilter:ne,borderBottom:"1px solid rgba(255,255,255,0.06)"};return React.createElement("header",{className:O?"header-minimal z-50":"header-minimal sticky top-0 z-50",style:j},[React.createElement("div",{key:"container",className:"max-w-7xl mx-auto",style:{padding:"0 20px"}},[React.createElement("div",{key:"content",className:"flex items-center justify-between",style:{height:"var(--sb-bar-h, 64px)",gap:"16px"}},[React.createElement("div",{key:"left",style:{display:"flex",alignItems:"center",gap:"12px",minWidth:0}},[React.createElement("div",{key:"logo",style:{width:"36px",height:"36px",flex:"none",display:"grid",placeItems:"center"}},React.createElement("img",{src:"/logo/securebit-mark.svg",alt:"SecureBit",style:{width:"100%",height:"100%",objectFit:"contain",display:"block"}})),React.createElement("div",{key:"txt",style:{lineHeight:1.2,minWidth:0}},[React.createElement("div",{key:"r1",style:{display:"flex",alignItems:"baseline",gap:"7px"}},[React.createElement("span",{key:"n",style:{fontSize:"16px",fontWeight:800,letterSpacing:"-0.3px",color:"#e8e8eb"}},"SecureBit"),React.createElement("span",{key:"v",style:{fontFamily:q,fontSize:"10px",fontWeight:500,color:"#56565e"}},Ta)]),React.createElement("div",{key:"r2",className:"hidden sm:block",style:{fontSize:"11px",color:"#6b6b73",fontWeight:500}},f("hdr.tagline"))])]),React.createElement("div",{key:"right",style:{display:"flex",alignItems:"center",gap:"9px"}},[O&&React.createElement(zi,{key:"lang"}),!O&&React.createElement("button",{key:"net",type:"button",onClick:()=>window.dispatchEvent(new CustomEvent("securebit:open-network-settings")),title:f("hdr.netSettingsTitle"),"aria-label":f("hdr.netSettings"),className:"sb-disconnect",style:{display:"grid",placeItems:"center",width:"38px",height:"38px",borderRadius:"9px",border:"1px solid rgba(255,255,255,0.07)",background:"rgba(255,255,255,0.02)",color:"#9a9aa2",cursor:"pointer",transition:"all .15s"}},React.createElement("i",{className:"fas fa-network-wired",style:{fontSize:"13px"}})),!O&&_&&React.createElement("div",{key:"sec",onClick:I,onContextMenu:U=>{U.preventDefault(),typeof i=="function"&&i()},title:E.tooltip,className:"sb-secpill",style:{display:"flex",alignItems:"center",gap:"8px",padding:"7px 12px",borderRadius:"9px",border:"1px solid rgba(255,255,255,0.07)",background:"rgba(255,255,255,0.02)",cursor:"pointer"}},[React.createElement("i",{key:"i",className:"fas fa-shield-halved",style:{fontSize:"13px",color:C}}),React.createElement("span",{key:"l",className:"hidden sm:inline",style:{fontSize:"12.5px",fontWeight:600,color:"#e8e8eb"}},f(`secLevel.${_.level}`)===`secLevel.${_.level}`?String(_.level):f(`secLevel.${_.level}`)),React.createElement("span",{key:"s",style:{fontFamily:q,fontSize:"11.5px",color:"#8a8a92"}},_.score+"%")]),!O&&React.createElement("div",{key:"status",style:{display:"flex",alignItems:"center",gap:"8px",padding:"8px 13px",borderRadius:"9px",border:"1px solid rgba(255,255,255,0.07)",background:"rgba(255,255,255,0.02)"}},[React.createElement("span",{key:"dot",style:{width:"7px",height:"7px",borderRadius:"50%",background:M,boxShadow:"0 0 0 3px "+v}}),React.createElement("span",{key:"t",className:"hidden sm:inline",style:{fontSize:"13px",fontWeight:600,color:"#cfcfd4"}},D.text)]),r&&React.createElement("button",{key:"dc",onClick:i,className:"sb-disconnect",style:{display:"flex",alignItems:"center",gap:"7px",padding:"8px 14px",borderRadius:"9px",border:"1px solid rgba(255,255,255,0.08)",background:"transparent",color:"#9a9aa2",fontFamily:"inherit",fontSize:"13px",fontWeight:600,cursor:"pointer",transition:"all .15s"}},[React.createElement("i",{key:"i",className:"fas fa-power-off",style:{fontSize:"12px"}}),React.createElement("span",{key:"t",className:"sb-hide-sm"},f("hdr.disconnect"))])])])])])};window.EnhancedMinimalHeader=Ca;var Yt="1.0.1",Vi=`https://github.com/SecureBitChat/securebit-desktop/releases/download/v${Yt}`,va=()=>{let s=[{id:"web",name:"Web App",subtitle:"Browser Version",icon:"fas fa-globe",platform:"Web",isActive:!0,url:"https://securebit.chat/",color:"green"},{id:"windows",name:"Windows",subtitle:"Desktop App",icon:"fab fa-windows",platform:"Desktop",isActive:!0,url:`${Vi}/SecureBit.Chat_${Yt}_x64-setup.exe`,color:"blue"},{id:"macos",name:"macOS",subtitle:"Desktop App",icon:"fab fa-safari",platform:"Desktop",isActive:!0,url:`${Vi}/SecureBit.Chat_${Yt}_x64.dmg`,color:"gray"},{id:"linux",name:"Linux",subtitle:"Desktop App",icon:"fab fa-linux",platform:"Desktop",isActive:!0,url:`${Vi}/SecureBit.Chat_${Yt}_amd64.AppImage`,color:"orange"},{id:"ios",name:"iOS",subtitle:"iPhone & iPad",icon:"fab fa-apple",platform:"Mobile",isActive:!1,url:"https://apps.apple.com/app/securebit-chat/",color:"white"},{id:"android",name:"Android",subtitle:"Google Play",icon:"fab fa-android",platform:"Mobile",isActive:!1,url:"https://play.google.com/store/apps/details?id=com.securebit.chat",color:"green"},{id:"chrome",name:"Chrome",subtitle:"Browser Extension",icon:"fab fa-chrome",platform:"Browser",isActive:!1,url:"#",color:"yellow"},{id:"edge",name:"Edge",subtitle:"Browser Extension",icon:"fab fa-edge",platform:"Browser",isActive:!1,url:"#",color:"blue"},{id:"opera",name:"Opera",subtitle:"Browser Extension",icon:"fab fa-opera",platform:"Browser",isActive:!1,url:"#",color:"red"},{id:"firefox",name:"Firefox",subtitle:"Browser Extension",icon:"fab fa-firefox-browser",platform:"Browser",isActive:!1,url:"#",color:"orange"}],e=c=>{c.isActive&&window.open(c.url,"_blank")},t=s.filter(c=>c.platform==="Desktop"||c.platform==="Web"),i=s.filter(c=>c.platform==="Mobile"),r=s.filter(c=>c.platform==="Browser"),n="w-28 h-28",a={green:"text-green-500",blue:"text-blue-500",gray:"text-gray-500",orange:"text-orange-500",red:"text-red-500",white:"text-white",yellow:"text-yellow-400"},o=c=>React.createElement("div",{key:c.id,className:`group relative ${n} rounded-2xl overflow-hidden card-minimal cursor-pointer`},[React.createElement("i",{key:"bg-icon",className:`${c.icon} absolute text-[3rem] ${c.isActive?a[c.color]:"text-white/10"} top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none transition-all duration-500 group-hover:scale-105`}),React.createElement("div",{key:"overlay",className:"absolute inset-0 bg-black/30 backdrop-blur-md flex flex-col items-center justify-center text-center opacity-0 transition-opacity duration-300 group-hover:opacity-100"},[React.createElement("h4",{key:"name",className:"text-sm font-semibold text-primary mb-1"},c.name),React.createElement("p",{key:"subtitle",className:"text-xs text-secondary mb-2"},c.subtitle),c.isActive?React.createElement("button",{key:"btn",onClick:()=>e(c),className:"px-2 py-1 rounded-xl bg-emerald-500 text-black font-medium hover:bg-emerald-600 transition-colors text-xs"},c.id==="web"?"Launch":"Download"):React.createElement("span",{key:"coming",className:"text-gray-400 font-medium text-xs"},"Coming Soon")])]);return React.createElement("div",{className:"mt-20 px-6"},[React.createElement("div",{key:"header",className:"text-center max-w-3xl mx-auto mb-12"},[React.createElement("h3",{key:"title",className:"text-3xl font-bold text-primary mb-3"},"Download SecureBit.chat"),React.createElement("p",{key:"subtitle",className:"text-secondary text-lg mb-5"},"Stay secure on every device. Choose your platform and start chatting privately.")]),React.createElement("div",{key:"desktop-row",className:"hidden sm:flex justify-center flex-wrap gap-6 mb-6"},t.map(o)),React.createElement("div",{key:"mobile-row",className:"flex justify-center gap-6 mb-6"},i.map(o)),React.createElement("div",{key:"browser-row",className:"flex justify-center gap-6"},r.map(o))])};window.DownloadApps=va;var ka=()=>{let[s,e]=React.useState(typeof window<"u"&&window.matchMedia("(max-width:767px)").matches);React.useEffect(()=>{let p=window.matchMedia("(max-width:767px)"),S=()=>e(p.matches);return p.addEventListener?p.addEventListener("change",S):p.addListener(S),()=>{p.removeEventListener?p.removeEventListener("change",S):p.removeListener(S)}},[]);let t="#f0892a",i="'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",r="'Manrope', system-ui, -apple-system, sans-serif",n="https://docs.google.com/forms/d/e/1FAIpQLSc9ijV9PCoyXkus6vEx1OWwvwAsLq8fKS6-H5BmX-c-bvia6w/viewform?usp=dialog",a=[{id:"aegis",name:"Aegis Investment",logo:"/logo/aegis.png",logoHeight:"42px",url:"https://aegis-investment.com/",desc:f("partners.aegis.desc"),role:f("partners.aegis.role"),delay:".5s"},{id:"furi",name:"FuriLabs",logo:"/logo/furi-160.png",logoHeight:"54px",url:"https://furilabs.com/",desc:f("partners.furilabs.desc"),role:f("partners.furilabs.role"),delay:".56s"}],o=(p,S,w,g,m)=>React.createElement("svg",{className:m,width:S,height:S,viewBox:"0 0 24 24",fill:"none",stroke:w,strokeWidth:g,strokeLinecap:"round",strokeLinejoin:"round",dangerouslySetInnerHTML:{__html:p}}),c=p=>React.createElement("span",{key:"role",style:{fontFamily:i,fontSize:"10.5px",fontWeight:600,color:"#6b6b73",textTransform:"uppercase",letterSpacing:"1.2px",padding:"6px 11px",borderRadius:"8px",border:"1px solid rgba(255,255,255,0.07)",background:"rgba(255,255,255,0.025)",whiteSpace:"nowrap"}},p),l=p=>React.createElement("a",{key:p.id,href:p.url,target:"_blank",rel:"noopener noreferrer",style:{flex:"1 1 320px",minWidth:s?"auto":"300px",borderRadius:"18px",background:"#141416",border:"1px solid rgba(255,255,255,0.06)",padding:"30px 30px 26px",display:"flex",flexDirection:"column",textDecoration:"none",color:"inherit",transition:"transform .28s cubic-bezier(.2,.7,.3,1), border-color .28s cubic-bezier(.2,.7,.3,1)",animation:`ptUp ${p.delay} cubic-bezier(.2,.7,.3,1)`},onMouseEnter:S=>{S.currentTarget.style.transform="translateY(-4px)",S.currentTarget.style.borderColor="rgba(255,255,255,0.13)"},onMouseLeave:S=>{S.currentTarget.style.transform="none",S.currentTarget.style.borderColor="rgba(255,255,255,0.06)"}},[React.createElement("div",{key:"logo",style:{display:"flex",alignItems:"center",marginBottom:"30px",height:"54px"}},React.createElement("img",{src:p.logo,alt:p.name,loading:"lazy",decoding:"async",style:{height:p.logoHeight,width:"auto",maxWidth:"190px",objectFit:"contain",display:"block"}})),React.createElement("h3",{key:"name",style:{margin:"0 0 9px",fontSize:"21px",fontWeight:800,letterSpacing:"-0.4px",color:"#f4f4f6"}},p.name),React.createElement("p",{key:"desc",style:{margin:"0 0 22px",fontSize:"14.5px",lineHeight:1.6,color:"#9a9aa2"}},p.desc),React.createElement("div",{key:"foot",style:{marginTop:"auto",paddingTop:"6px",display:"flex",alignItems:"center",gap:"12px"}},[c(p.role)])]),h=React.createElement("a",{key:"invite",href:n,target:"_blank",rel:"noopener noreferrer",style:{flex:"1 1 320px",minWidth:s?"auto":"300px",borderRadius:"18px",background:"#111113",border:"1px dashed rgba(255,255,255,0.12)",padding:"30px",display:"flex",flexDirection:"column",justifyContent:"space-between",textDecoration:"none",color:"inherit",transition:"border-color .28s cubic-bezier(.2,.7,.3,1)",animation:"ptUp .62s cubic-bezier(.2,.7,.3,1)"},onMouseEnter:p=>{p.currentTarget.style.borderColor="rgba(240,137,42,0.4)"},onMouseLeave:p=>{p.currentTarget.style.borderColor="rgba(255,255,255,0.12)"}},[React.createElement("div",{key:"top"},[React.createElement("div",{key:"icon",style:{width:"48px",height:"48px",borderRadius:"13px",display:"grid",placeItems:"center",background:"rgba(240,137,42,0.12)",border:"1px solid rgba(240,137,42,0.28)",marginBottom:"24px"}},o('',23,t,1.9)),React.createElement("h3",{key:"title",style:{margin:"0 0 8px",fontSize:"21px",fontWeight:800,letterSpacing:"-0.4px",color:"#f4f4f6"}},f("partners.inviteTitle")),React.createElement("p",{key:"desc",style:{margin:0,fontSize:"14.5px",lineHeight:1.6,color:"#8a8a92"}},f("partners.inviteDesc"))]),React.createElement("span",{key:"btn",style:{marginTop:"26px",width:"100%",display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"10px",padding:"15px 20px",borderRadius:"12px",border:"none",background:t,color:"#1a0f04",fontFamily:r,fontSize:"15px",fontWeight:700,cursor:"pointer",boxShadow:"0 8px 24px rgba(240,137,42,0.28)",boxSizing:"border-box",transition:"background .2s cubic-bezier(.2,.7,.3,1), transform .2s cubic-bezier(.2,.7,.3,1)"}},[f("partners.inviteCta"),o('',17,"currentColor",2.2,"sb-mirror-rtl")])]),u=React.createElement("div",{key:"inner",style:{maxWidth:"1240px",margin:"0 auto",padding:s?"0 18px":"0 40px"}},[React.createElement("div",{key:"head",style:{marginBottom:"44px"}},[React.createElement("div",{key:"eyebrow",style:{fontFamily:i,fontSize:"11px",fontWeight:600,color:"#6b6b73",textTransform:"uppercase",letterSpacing:"1.6px",marginBottom:"14px"}},f("partners.eyebrow")),React.createElement("h2",{key:"h2",style:{margin:0,fontSize:s?"30px":"40px",fontWeight:800,letterSpacing:"-1.1px",lineHeight:1.04,color:"#f4f4f6"}},f("partners.heading"))]),React.createElement("div",{key:"cards",style:{display:"flex",gap:"18px",alignItems:"stretch",flexWrap:"wrap"}},[...a.map(l),h])]);return React.createElement("section",{style:{width:"100%",color:"#e8e8eb",fontFamily:r,padding:s?"48px 0":"72px 0",background:"radial-gradient(1100px 640px at 50% -6%, rgba(240,137,42,0.055), transparent 62%), #0f0f11"}},[React.createElement("style",{key:"kf",dangerouslySetInnerHTML:{__html:"@keyframes ptUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}"}}),u])};window.BecomePartner=ka;var Aa=()=>{let[s,e]=React.useState(0),[t,i]=React.useState(typeof window<"u"&&window.matchMedia("(max-width:767px)").matches);React.useEffect(()=>{let _=window.matchMedia("(max-width:767px)"),R=()=>i(_.matches);return _.addEventListener?_.addEventListener("change",R):_.addListener(R),()=>{_.removeEventListener?_.removeEventListener("change",R):_.removeListener(R)}},[]);let r="#f0892a",n="radial-gradient(130% 90% at 28% 0%, rgba(240,137,42,0.11), transparent 60%), #141416",a="rgba(240,137,42,0.3)",o="#111113",c="rgba(255,255,255,0.06)",l="'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",h="'Manrope', system-ui, -apple-system, sans-serif",u=[{num:"01",title:[f("unique.s1.titleTop"),f("unique.s1.titleBottom")],collapsed:f("unique.s1.collapsed"),desc:f("unique.s1.desc"),tags:Oe("unique.s1.tags"),icon:''},{num:"02",title:[f("unique.s2.titleTop"),f("unique.s2.titleBottom")],collapsed:f("unique.s2.collapsed"),desc:f("unique.s2.desc"),tags:Oe("unique.s2.tags"),icon:''},{num:"03",title:[f("unique.s3.titleTop"),f("unique.s3.titleBottom")],collapsed:f("unique.s3.collapsed"),desc:f("unique.s3.desc"),tags:Oe("unique.s3.tags"),icon:''},{num:"04",title:[f("unique.s4.titleTop"),f("unique.s4.titleBottom")],collapsed:f("unique.s4.collapsed"),desc:f("unique.s4.desc"),tags:Oe("unique.s4.tags"),icon:''},{num:"05",title:[f("unique.s5.titleTop"),f("unique.s5.titleBottom")],collapsed:f("unique.s5.collapsed"),desc:f("unique.s5.desc"),tags:Oe("unique.s5.tags"),icon:''}],p=(_,R,E,C)=>React.createElement("svg",{width:R,height:R,viewBox:"0 0 24 24",fill:"none",stroke:E,strokeWidth:C,strokeLinecap:"round",strokeLinejoin:"round",dangerouslySetInnerHTML:{__html:_}}),S=_=>e(R=>(R+_+u.length)%u.length),w=(_,R,E)=>React.createElement("button",{key:_,onClick:R,"aria-label":_,className:"sb-mirror-rtl",style:{width:"46px",height:"46px",display:"grid",placeItems:"center",borderRadius:"50%",border:"1px solid rgba(255,255,255,0.1)",background:"rgba(255,255,255,0.025)",color:"#cfcfd4",cursor:"pointer",transition:"all .2s cubic-bezier(.2,.7,.3,1)"},onMouseEnter:C=>{C.currentTarget.style.borderColor=a,C.currentTarget.style.color=r},onMouseLeave:C=>{C.currentTarget.style.borderColor="rgba(255,255,255,0.1)",C.currentTarget.style.color="#cfcfd4"}},p(E,18,"currentColor",2.1)),g=_=>React.createElement("span",{key:_,style:{display:"inline-flex",alignItems:"center",gap:"7px",padding:"7px 12px",borderRadius:"9px",border:"1px solid rgba(255,255,255,0.07)",background:"rgba(255,255,255,0.025)",fontFamily:l,fontSize:"11.5px",fontWeight:500,color:"#9a9aa2"}},[React.createElement("span",{key:"dot",style:{width:"5px",height:"5px",borderRadius:"50%",background:"#3ecf8e"}}),_]),m=_=>React.createElement("div",{key:"exp",style:{height:"100%",display:"flex",flexDirection:"column",justifyContent:t?"flex-start":"space-between",gap:t?"18px":0,padding:t?"24px 22px":"32px 34px",minWidth:t?"auto":"320px",animation:"wuUp .42s cubic-bezier(.2,.7,.3,1)"}},[React.createElement("div",{key:"top",style:{display:"flex",alignItems:"center",justifyContent:"space-between"}},[React.createElement("div",{key:"ic",style:{width:"54px",height:"54px",borderRadius:"15px",display:"grid",placeItems:"center",background:"rgba(240,137,42,0.13)",border:"1px solid rgba(240,137,42,0.3)"}},p(_.icon,26,r,1.9)),React.createElement("span",{key:"n",style:{fontFamily:l,fontSize:"13px",fontWeight:600,color:"#6b6b73"}},_.num)]),React.createElement("div",{key:"mid"},[React.createElement("h3",{key:"h",style:{margin:"0 0 12px",fontSize:t?"24px":"30px",fontWeight:800,letterSpacing:"-0.7px",lineHeight:1.08,color:"#f4f4f6"}},[_.title[0],React.createElement("br",{key:"br"}),_.title[1]]),React.createElement("p",{key:"p",style:{margin:0,fontSize:"15px",lineHeight:1.6,color:"#9a9aa2",maxWidth:"380px"}},_.desc)]),React.createElement("div",{key:"tags",style:{display:"flex",flexWrap:"wrap",gap:"8px"}},_.tags.map(g))]),I=_=>t?React.createElement("div",{key:"col",style:{display:"flex",alignItems:"center",gap:"16px",padding:"20px 22px"}},[React.createElement("span",{key:"n",style:{fontFamily:l,fontSize:"12px",fontWeight:600,color:"#56565e"}},_.num),React.createElement("span",{key:"l",style:{fontSize:"16px",fontWeight:800,letterSpacing:"-0.2px",color:"#cfcfd4"}},_.collapsed)]):React.createElement("div",{key:"col",style:{position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"space-between",padding:"24px 0"}},[React.createElement("span",{key:"n",style:{fontFamily:l,fontSize:"12px",fontWeight:600,color:"#56565e"}},_.num),React.createElement("span",{key:"l",style:{writingMode:"vertical-rl",transform:"rotate(180deg)",fontSize:"17px",fontWeight:800,letterSpacing:"-0.2px",color:"#cfcfd4",whiteSpace:"nowrap"}},_.collapsed),p(_.icon,22,"#56565e",1.8)]),b=u.map((_,R)=>{let E=s===R;return React.createElement("div",{key:R,onClick:()=>e(R),onMouseEnter:C=>{E||(C.currentTarget.style.filter="brightness(1.18)")},onMouseLeave:C=>{C.currentTarget.style.filter="none"},style:{flex:t?"none":E?6.2:1,minWidth:t?"auto":"72px",position:"relative",borderRadius:"18px",overflow:"hidden",cursor:"pointer",background:E?n:o,border:"1px solid "+(E?a:c),color:"#8a8a92",transition:"flex .46s cubic-bezier(.2,.7,.3,1), background .3s ease, border-color .3s ease, filter .2s ease"}},E?m(_):I(_))}),D=React.createElement("div",{key:"inner",style:{maxWidth:"1180px",margin:"0 auto",padding:t?"0 18px":"0 40px"}},[React.createElement("div",{key:"head",style:{display:"flex",alignItems:"flex-end",justifyContent:"space-between",gap:"24px",marginBottom:"28px"}},[React.createElement("div",{key:"titles"},[React.createElement("div",{key:"eyebrow",style:{fontFamily:l,fontSize:"11px",fontWeight:600,color:"#6b6b73",textTransform:"uppercase",letterSpacing:"1.4px",marginBottom:"12px"}},f("unique.eyebrow")),React.createElement("h2",{key:"h2",style:{margin:0,fontSize:t?"28px":"38px",fontWeight:800,letterSpacing:"-1.1px",lineHeight:1.05,color:"#f4f4f6"}},f("unique.heading"))]),React.createElement("div",{key:"nav",style:{display:"flex",alignItems:"center",gap:"10px",flex:"none"}},[w("prev",()=>S(-1),''),w("next",()=>S(1),'')])]),React.createElement("div",{key:"accordion",style:{display:"flex",flexDirection:t?"column":"row",gap:t?"12px":"14px",height:t?"auto":"440px"}},b)]);return React.createElement("section",{style:{width:"100%",color:"#e8e8eb",fontFamily:h,padding:t?"44px 0":"64px 0",background:"radial-gradient(1100px 700px at 18% 8%, rgba(240,137,42,0.05), transparent 60%), #0f0f11"}},[React.createElement("style",{key:"kf",dangerouslySetInnerHTML:{__html:"@keyframes wuUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}"}}),D])};window.UniqueFeatureSlider=Aa;function Ia(){let[s,e]=React.useState(typeof window<"u"&&window.matchMedia("(max-width:767px)").matches);React.useEffect(()=>{let b=window.matchMedia("(max-width:767px)"),D=()=>e(b.matches);return b.addEventListener?b.addEventListener("change",D):b.addListener(D),()=>{b.removeEventListener?b.removeEventListener("change",D):b.removeListener(D)}},[]);let t="'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",i="'Manrope', system-ui, -apple-system, sans-serif",r=[{v:"v1.0",k:"r1",status:"released"},{v:"v1.5",k:"r2",status:"released"},{v:"v2.0",k:"r3",status:"released"},{v:"v3.0",k:"r4",status:"released"},{v:"v3.5",k:"r5",status:"released"},{v:"v4.5",k:"r6",status:"released"},{v:"v5.0",k:"r7",status:"released"},{v:"v5.5",k:"r8",status:"released"},{v:"v6.0",k:"r9",status:"current"},{v:"v6.5",k:"r10",status:"dev"},{v:"v7.0",k:"r11",status:"planned"},{v:"v7.5",k:"r12",status:"research"},{v:"v8.0",k:"r13",status:"research"}].map(b=>({...b,title:f(`roadmap.${b.k}.title`),sub:f(`roadmap.${b.k}.sub`),date:f(`roadmap.${b.k}.date`),features:Oe(`roadmap.${b.k}.features`)})),n={released:{word:f("roadmap.status.released"),color:"#3ecf8e",line:"rgba(62,207,142,0.32)"},current:{word:f("roadmap.status.current"),color:"#f0892a",line:"rgba(240,137,42,0.32)"},dev:{word:f("roadmap.status.dev"),color:"#e3b341",line:"rgba(255,255,255,0.08)"},planned:{word:f("roadmap.status.planned"),color:"#8a8a92",line:"rgba(255,255,255,0.08)"},research:{word:f("roadmap.status.research"),color:"#6b6b73",line:"rgba(255,255,255,0.08)"}},[a,o]=React.useState({}),c=b=>a[b]===void 0?r[b].status==="current":a[b],l=b=>o(D=>({...D,[b]:!c(b)})),h=(b,D)=>{let _=parseInt(b.slice(1),16);return`rgba(${_>>16&255},${_>>8&255},${_&255},${D})`},u=r.length,p=r.filter(b=>b.status==="released"||b.status==="current").length,S=u-p,w=(p/u*100).toFixed(1)+"%",[g,m]=f("roadmap.progress",{total:u}).split("{shipped}"),I=b=>b==="released"?React.createElement("div",{style:{position:"absolute",insetInlineStart:"13px",top:"16px",width:"28px",height:"28px",borderRadius:"50%",display:"grid",placeItems:"center",background:"linear-gradient(rgba(62,207,142,0.16),rgba(62,207,142,0.16)), #0f0f11",border:"1px solid rgba(62,207,142,0.4)",zIndex:2}},React.createElement("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"#3ecf8e",strokeWidth:"2.4",strokeLinecap:"round",strokeLinejoin:"round"},React.createElement("path",{d:"M5 13l4 4 10-11"}))):b==="current"?React.createElement("div",{style:{position:"absolute",insetInlineStart:"13px",top:"16px",width:"28px",height:"28px",borderRadius:"50%",display:"grid",placeItems:"center",background:"linear-gradient(rgba(240,137,42,0.2),rgba(240,137,42,0.2)), #0f0f11",border:"1px solid #f0892a",zIndex:2,animation:"rmPulse 2.4s ease-out infinite"}},React.createElement("span",{style:{width:"9px",height:"9px",borderRadius:"50%",background:"#f0892a"}})):b==="dev"?React.createElement("div",{style:{position:"absolute",insetInlineStart:"13px",top:"16px",width:"28px",height:"28px",borderRadius:"50%",display:"grid",placeItems:"center",background:"linear-gradient(rgba(227,179,65,0.15),rgba(227,179,65,0.15)), #0f0f11",border:"1px solid rgba(227,179,65,0.4)",zIndex:2}},React.createElement("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"#e3b341",strokeWidth:"2.2",strokeLinecap:"round",strokeLinejoin:"round"},React.createElement("path",{d:"M12 3a9 9 0 1 0 9 9"}))):React.createElement("div",{style:{position:"absolute",insetInlineStart:"13px",top:"16px",width:"28px",height:"28px",borderRadius:"50%",display:"grid",placeItems:"center",background:"#0f0f11",border:`1px ${b==="research"?"dashed":"solid"} rgba(255,255,255,0.18)`,zIndex:2}},React.createElement("span",{style:{width:"7px",height:"7px",borderRadius:"50%",background:n[b].color}}));return React.createElement("section",{style:{width:"100%",color:"#e8e8eb",fontFamily:i,padding:s?"48px 0":"64px 0",background:"radial-gradient(1200px 720px at 50% -8%, rgba(240,137,42,0.05), transparent 60%), #0f0f11"}},React.createElement("style",{dangerouslySetInnerHTML:{__html:"@keyframes rmExp{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}@keyframes rmPulse{0%,100%{box-shadow:0 0 0 0 rgba(240,137,42,0.18)}60%{box-shadow:0 0 0 9px rgba(240,137,42,0)}}"}}),React.createElement("div",{style:{maxWidth:"1040px",margin:"0 auto",padding:s?"0 18px":"0 40px"}},React.createElement("div",{style:{marginBottom:"30px"}},React.createElement("div",{style:{fontFamily:t,fontSize:"11px",fontWeight:600,color:"#6b6b73",textTransform:"uppercase",letterSpacing:"1.6px",marginBottom:"13px"}},f("roadmap.eyebrow")),React.createElement("h2",{style:{margin:"0 0 14px",fontSize:s?"27px":"34px",fontWeight:800,letterSpacing:"-1px",lineHeight:1.08,color:"#f4f4f6"}},f("roadmap.heading")),React.createElement("p",{style:{margin:0,fontSize:"15.5px",lineHeight:1.6,color:"#8a8a92",maxWidth:"660px"}},f("roadmap.subheading"))),React.createElement("div",{style:{display:"flex",alignItems:"center",gap:"18px",flexWrap:"wrap",padding:"18px 22px",borderRadius:"14px",background:"#141416",border:"1px solid rgba(255,255,255,0.06)",marginBottom:"36px"}},React.createElement("div",{style:{fontFamily:t,fontSize:"12px",fontWeight:600,color:"#e8e8eb",whiteSpace:"nowrap"}},g,React.createElement("span",{style:{color:"#3ecf8e"}},p),m),React.createElement("div",{style:{flex:"1 1 240px",minWidth:"200px",height:"8px",borderRadius:"99px",background:"#0c0c0e",border:"1px solid rgba(255,255,255,0.06)",overflow:"hidden"}},React.createElement("div",{style:{height:"100%",width:w,background:"linear-gradient(90deg, #3ecf8e, #f0892a)"}})),React.createElement("div",{style:{fontFamily:t,fontSize:"11px",fontWeight:600,color:"#6b6b73",textTransform:"uppercase",letterSpacing:"0.8px",whiteSpace:"nowrap"}},f("roadmap.upcoming",{upcoming:S}))),r.map((b,D)=>{let _=n[b.status],R=c(D),E=Dl(D),style:{display:"flex",alignItems:"center",gap:s?"11px":"16px",padding:s?"16px 16px":"18px 22px",cursor:"pointer",transition:"background .18s ease"},onMouseEnter:C=>{C.currentTarget.style.background="rgba(255,255,255,0.018)"},onMouseLeave:C=>{C.currentTarget.style.background="transparent"}},React.createElement("div",{style:{flex:"none",minWidth:"52px",textAlign:"center",padding:"7px 10px",borderRadius:"9px",background:"#0c0c0e",border:"1px solid rgba(255,255,255,0.07)",fontFamily:t,fontSize:"13px",fontWeight:700,color:b.status==="current"?"#f0892a":"#cfcfd4"}},b.v),React.createElement("div",{style:{flex:1,minWidth:0}},React.createElement("div",{style:{fontSize:s?"15.5px":"17px",fontWeight:800,letterSpacing:"-0.4px",color:"#f4f4f6"}},b.title),!s&&React.createElement("div",{style:{marginTop:"3px",fontSize:"13.5px",color:"#9a9aa2"}},b.sub)),React.createElement("div",{style:{flex:"none",display:"flex",alignItems:"center",gap:s?"8px":"14px"}},React.createElement("span",{style:{display:"inline-flex",alignItems:"center",gap:"7px",padding:"6px 11px",borderRadius:"8px",background:h(_.color,.1),border:`1px solid ${h(_.color,.22)}`,fontFamily:t,fontSize:"10.5px",fontWeight:600,color:_.color,textTransform:"uppercase",letterSpacing:"0.8px",whiteSpace:"nowrap"}},React.createElement("span",{style:{width:"6px",height:"6px",borderRadius:"50%",background:_.color}}),!s&&_.word),!s&&React.createElement("span",{style:{fontFamily:t,fontSize:"12px",fontWeight:500,color:"#8a8a92",whiteSpace:"nowrap",minWidth:"74px",textAlign:"end"}},b.date),React.createElement("span",{style:{color:"#6b6b73",display:"inline-flex",transition:"transform .22s cubic-bezier(.2,.7,.3,1)",transform:R?"rotate(180deg)":"rotate(0deg)"}},React.createElement("svg",{width:"17",height:"17",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.1",strokeLinecap:"round",strokeLinejoin:"round"},React.createElement("path",{d:"M6 9l6 6 6-6"}))))),R&&React.createElement("div",{style:{padding:"4px 22px 22px 22px",animation:"rmExp .24s cubic-bezier(.2,.7,.3,1)"}},React.createElement("div",{style:{fontFamily:t,fontSize:"10px",fontWeight:600,color:"#56565e",textTransform:"uppercase",letterSpacing:"1.2px",marginBottom:"14px",paddingTop:"14px",borderTop:"1px solid rgba(255,255,255,0.05)"}},f("roadmap.keyFeatures")),React.createElement("div",{style:{display:"grid",gridTemplateColumns:s?"1fr":"1fr 1fr",gap:"11px 28px"}},b.features.map((C,M)=>React.createElement("div",{key:M,style:{display:"flex",alignItems:"flex-start",gap:"10px"}},React.createElement("span",{style:{flex:"none",marginTop:"7px",width:"5px",height:"5px",borderRadius:"50%",background:_.color}}),React.createElement("span",{style:{fontSize:"13.5px",lineHeight:1.5,color:"#cfcfd4"}},C)))))))})))}window.Roadmap=Ia;var xa=()=>{let[s,e]=React.useState(typeof window<"u"&&window.matchMedia("(max-width:767px)").matches);React.useEffect(()=>{let l=window.matchMedia("(max-width:767px)"),h=()=>e(l.matches);return l.addEventListener?l.addEventListener("change",h):l.addListener(h),()=>{l.removeEventListener?l.removeEventListener("change",h):l.removeListener(h)}},[]);let t="#f0892a",i="'Manrope', system-ui, -apple-system, sans-serif",r="https://github.com/SecureBitChat/securebit-chat/",n="mailto:lockbitchat@tutanota.com",a=React.createElement("a",{key:"gh",href:r,target:"_blank",rel:"noopener noreferrer",style:{display:"inline-flex",alignItems:"center",gap:"11px",padding:"15px 26px",borderRadius:"13px",background:t,color:"#1a0f04",textDecoration:"none",fontSize:"15.5px",fontWeight:700,letterSpacing:"-0.2px",boxShadow:"0 8px 24px rgba(240,137,42,0.28)",whiteSpace:"nowrap",transition:"all .2s cubic-bezier(.2,.7,.3,1)"},onMouseEnter:l=>{l.currentTarget.style.background="#ff9637",l.currentTarget.style.transform="translateY(-2px)"},onMouseLeave:l=>{l.currentTarget.style.background=t,l.currentTarget.style.transform="none"}},[React.createElement("svg",{key:"i",width:20,height:20,viewBox:"0 0 24 24",fill:"currentColor",dangerouslySetInnerHTML:{__html:''}}),f("community.github")]),o=React.createElement("a",{key:"fb",href:n,rel:"noopener noreferrer",style:{display:"inline-flex",alignItems:"center",gap:"11px",padding:"15px 26px",borderRadius:"13px",background:"rgba(255,255,255,0.03)",color:"#e8e8eb",textDecoration:"none",fontSize:"15.5px",fontWeight:700,letterSpacing:"-0.2px",border:"1px solid rgba(255,255,255,0.1)",whiteSpace:"nowrap",transition:"all .2s cubic-bezier(.2,.7,.3,1)"},onMouseEnter:l=>{l.currentTarget.style.borderColor="rgba(255,255,255,0.24)",l.currentTarget.style.background="rgba(255,255,255,0.06)"},onMouseLeave:l=>{l.currentTarget.style.borderColor="rgba(255,255,255,0.1)",l.currentTarget.style.background="rgba(255,255,255,0.03)"}},[React.createElement("svg",{key:"i",width:20,height:20,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.9,strokeLinecap:"round",strokeLinejoin:"round",dangerouslySetInnerHTML:{__html:''}}),f("community.feedback")]),c=React.createElement("div",{key:"card",style:{position:"relative",overflow:"hidden",maxWidth:"860px",width:"100%",borderRadius:"24px",background:"radial-gradient(700px 360px at 50% 0%, rgba(240,137,42,0.1), transparent 65%), #121214",border:"1px solid rgba(255,255,255,0.07)",padding:s?"40px 24px 36px":"56px 56px 48px",textAlign:"center",boxShadow:"0 24px 60px rgba(0,0,0,0.4)"}},[React.createElement("div",{key:"hairline",style:{position:"absolute",top:0,left:"50%",transform:"translateX(-50%)",width:"180px",height:"1px",background:"linear-gradient(90deg, transparent, rgba(240,137,42,0.7), transparent)"}}),React.createElement("img",{key:"icon",src:"/logo/securebit-mark.svg",alt:"SecureBit",style:{display:"inline-block",width:"64px",height:"64px",objectFit:"contain",marginBottom:"22px",animation:"ccUp .4s cubic-bezier(.2,.7,.3,1)"}}),React.createElement("h2",{key:"title",style:{margin:"0 0 16px",fontSize:s?"28px":"36px",fontWeight:800,letterSpacing:"-1px",lineHeight:1.05,color:"#f4f4f6"}},f("community.title")),React.createElement("p",{key:"desc",style:{margin:"0 auto 32px",maxWidth:"560px",fontSize:"16px",lineHeight:1.65,color:"#9a9aa2"}},f("community.description")),React.createElement("div",{key:"btns",style:{display:"flex",gap:"14px",justifyContent:"center",flexWrap:"wrap"}},[a,o]),React.createElement("div",{key:"snap",style:{display:"flex",justifyContent:s?"center":"flex-end",marginTop:"28px"}},React.createElement("a",{href:"https://snapcraft.io/securebit-chat",target:"_blank",rel:"noopener noreferrer","aria-label":"Get it from the Snap Store",style:{display:"inline-flex",opacity:.9,transition:"opacity .2s"},onMouseEnter:l=>{l.currentTarget.style.opacity=1},onMouseLeave:l=>{l.currentTarget.style.opacity=.9}},React.createElement("img",{src:"/assets/badges/snap-store.svg",alt:"Get it from the Snap Store",width:182,height:56,loading:"lazy",style:{display:"block"}})))]);return React.createElement("section",{style:{width:"100%",display:"flex",alignItems:"center",justifyContent:"center",background:"#0f0f11",fontFamily:i,padding:s?"48px 18px":"64px 48px"}},[React.createElement("style",{key:"kf",dangerouslySetInnerHTML:{__html:"@keyframes ccUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}"}}),c])};window.CommunityCTA=xa;var Ra=({webrtcManager:s,isConnected:e,pendingIncomingFiles:t=[],onIncomingDecision:i,showDropzone:r=!0})=>{let[n,a]=React.useState(!1),[o,c]=React.useState({sending:[],receiving:[]}),l=React.useRef(null);React.useEffect(()=>{if(!e||!s)return;let C=setInterval(()=>{let M=s.getFileTransfers();c(M)},500);return()=>clearInterval(C)},[e,s]),React.useEffect(()=>{e||c({sending:[],receiving:[]})},[e]);let h=async E=>{if(!e||!s){alert("\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E. \u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435.");return}if(!s.isConnected()||!s.isVerified){alert("\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u043D\u0435 \u0433\u043E\u0442\u043E\u0432\u043E \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043B\u043E\u0432. \u0414\u043E\u0436\u0434\u0438\u0442\u0435\u0441\u044C \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F.");return}for(let C of E)try{let M=s.validateFile(C);if(!M.isValid){let v=M.errors.join(". ");alert(`\u0424\u0430\u0439\u043B ${C.name} \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D: ${v}`);continue}await s.sendFile(C)}catch(M){M.message.includes(f("file.notReady"))?alert(`\u0424\u0430\u0439\u043B ${C.name} \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D \u0441\u0435\u0439\u0447\u0430\u0441. \u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0438 \u043F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u0441\u043D\u043E\u0432\u0430.`):M.message.includes(f("file.tooLarge"))||M.message.includes("exceeds maximum")?alert(`\u0424\u0430\u0439\u043B ${C.name} \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0431\u043E\u043B\u044C\u0448\u043E\u0439: ${M.message}`):M.message.includes(f("file.maxConcurrent"))?alert("\u0414\u043E\u0441\u0442\u0438\u0433\u043D\u0443\u0442 \u043B\u0438\u043C\u0438\u0442 \u043E\u0434\u043D\u043E\u0432\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0445 \u043F\u0435\u0440\u0435\u0434\u0430\u0447. \u0414\u043E\u0436\u0434\u0438\u0442\u0435\u0441\u044C \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u0442\u0435\u043A\u0443\u0449\u0438\u0445 \u043F\u0435\u0440\u0435\u0434\u0430\u0447."):M.message.includes(f("file.typeNotAllowed"))?alert(`\u0422\u0438\u043F \u0444\u0430\u0439\u043B\u0430 ${C.name} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F: ${M.message}`):alert(`\u041E\u0448\u0438\u0431\u043A\u0430 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438 \u0444\u0430\u0439\u043B\u0430 ${C.name}: ${M.message}`)}},u=E=>{E.preventDefault(),a(!1);let C=Array.from(E.dataTransfer.files);h(C)},p=E=>{E.preventDefault(),a(!0)},S=E=>{E.preventDefault(),a(!1)},w=E=>{let C=Array.from(E.target.files);h(C),E.target.value=""},g=E=>{if(E===0)return"0 B";let C=1024,M=["B","KB","MB","GB"],v=Math.floor(Math.log(E)/Math.log(C));return parseFloat((E/Math.pow(C,v)).toFixed(2))+" "+M[v]},m=E=>{switch(E){case"metadata_sent":case"preparing":return"fas fa-cog fa-spin";case"transmitting":case"receiving":return"fas fa-exchange-alt fa-pulse";case"assembling":return"fas fa-puzzle-piece fa-pulse";case"completed":return"fas fa-check text-green-400";case"failed":return"fas fa-times text-red-400";default:return"fas fa-circle"}},I=E=>{switch(E){case"metadata_sent":return"\u041F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0430...";case"transmitting":return"\u041E\u0442\u043F\u0440\u0430\u0432\u043A\u0430...";case"receiving":return"\u041F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u0435...";case"assembling":return"\u0421\u0431\u043E\u0440\u043A\u0430 \u0444\u0430\u0439\u043B\u0430...";case"completed":return"\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E";case"failed":return"\u041E\u0448\u0438\u0431\u043A\u0430";default:return E}},b=(E,C)=>{let M=E.totalChunks||0,v=E.transferredChunks||0,q=E.status==="completed",O=M>0?Math.min(M,32):24,x;return q?x=O:M>0?x=Math.floor(v/M*O):x=Math.floor((E.progress||0)/100*O),x=Math.max(0,Math.min(O,x)),React.createElement("div",{key:"progress"},[React.createElement("div",{key:"squares",style:{display:"flex",flexWrap:"wrap",gap:"3px",marginBottom:"7px"}},Array.from({length:O},(ue,ne)=>React.createElement("div",{key:ne,style:{width:"11px",height:"11px",borderRadius:"2px",background:ne0?`${Math.min(v,M)} / ${M} chunks`:`${(E.progress||0).toFixed(0)}%`)])])},D=E=>E.status==="completed",_=async(E,C)=>{typeof i=="function"&&await i(E,C),c(s.getFileTransfers())};return e?s&&s.isConnected()&&s.isVerified?React.createElement("div",{className:"file-transfer-component"},[r&&React.createElement("div",{key:"drop-zone",onDrop:u,onDragOver:p,onDragLeave:S,style:{position:"relative",border:"1.5px dashed "+(n?"rgba(240,137,42,0.7)":"rgba(255,255,255,0.14)"),borderRadius:"14px",background:n?"rgba(240,137,42,0.07)":"#141416",padding:"24px 22px",textAlign:"center",transition:"all .15s"}},[React.createElement("div",{key:"icon-box",style:{width:"42px",height:"42px",margin:"0 auto 10px",borderRadius:"12px",display:"grid",placeItems:"center",background:"rgba(255,255,255,0.04)",border:"1px solid rgba(255,255,255,0.08)"}},React.createElement("i",{className:"fas fa-arrow-up-from-bracket",style:{color:"#9a9aa2",fontSize:"18px"}})),React.createElement("div",{key:"title",style:{fontSize:"14px",fontWeight:700,color:"#e8e8eb"}},f("file.drop")),React.createElement("div",{key:"sub",style:{fontSize:"12px",color:"#7b7b83",marginTop:"4px"}},f("file.dropHint")),React.createElement("button",{key:"browse",type:"button",onClick:()=>l.current?.click(),className:"sb-send",style:{marginTop:"14px",display:"inline-flex",alignItems:"center",gap:"7px",padding:"9px 16px",borderRadius:"9px",border:"none",background:"#f0892a",color:"#1a0f04",fontFamily:"inherit",fontSize:"13px",fontWeight:700,cursor:"pointer"}},[React.createElement("i",{key:"i",className:"fas fa-folder-open",style:{fontSize:"13px"}}),f("file.browse")])]),r&&React.createElement("input",{key:"file-input",ref:l,type:"file",multiple:!0,className:"hidden",onChange:w}),t.length>0&&React.createElement("div",{key:"incoming-consent",className:"mt-4 space-y-2"},t.map(E=>React.createElement("div",{key:E.fileId,style:{borderRadius:"12px",border:"1px solid rgba(255,255,255,0.08)",background:"#161618",padding:"12px 14px"}},[React.createElement("div",{key:"info",style:{marginBottom:"12px",display:"flex",alignItems:"center",gap:"11px"}},[React.createElement("div",{key:"ic",style:{flex:"none",width:"34px",height:"34px",borderRadius:"9px",display:"grid",placeItems:"center",background:"rgba(240,137,42,0.12)",border:"1px solid rgba(240,137,42,0.22)"}},React.createElement("i",{className:"fas fa-file-arrow-down",style:{color:"#f0892a",fontSize:"15px"}})),React.createElement("div",{key:"text",style:{minWidth:0}},[React.createElement("div",{key:"title",style:{fontSize:"13px",fontWeight:600,color:"#e8e8eb"}},f("file.incoming")),React.createElement("div",{key:"meta",style:{fontSize:"11.5px",color:"#7b7b83",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},`${E.fileName} \xB7 ${g(E.fileSize)} \xB7 ${E.mimeType}`)])]),React.createElement("div",{key:"actions",style:{display:"flex",gap:"8px"}},[React.createElement("button",{key:"accept",onClick:()=>_(E.fileId,!0),style:{display:"inline-flex",alignItems:"center",gap:"6px",borderRadius:"8px",border:"none",background:"#f0892a",color:"#1a0f04",padding:"8px 14px",fontSize:"13px",fontWeight:700,cursor:"pointer"}},[React.createElement("i",{key:"i",className:"fas fa-check",style:{fontSize:"12px"}}),f("file.accept")]),React.createElement("button",{key:"reject",onClick:()=>_(E.fileId,!1),style:{display:"inline-flex",alignItems:"center",gap:"6px",borderRadius:"8px",border:"1px solid rgba(229,114,122,0.3)",background:"rgba(229,114,122,0.08)",color:"#e5727a",padding:"8px 14px",fontSize:"13px",fontWeight:600,cursor:"pointer"}},[React.createElement("i",{key:"i",className:"fas fa-xmark",style:{fontSize:"12px"}}),f("file.reject")])])]))),(o.sending.length>0||o.receiving.length>0)&&React.createElement("div",{key:"transfers",className:"active-transfers mt-4"},[React.createElement("h4",{key:"title",style:{display:"flex",alignItems:"center",gap:"8px",fontSize:"12.5px",fontWeight:600,color:"#8a8a92",marginBottom:"10px"}},[React.createElement("i",{key:"icon",className:"fas fa-right-left",style:{fontSize:"12px"}}),f("file.title")]),...o.sending.map(E=>React.createElement("div",{key:`send-${E.fileId}`,style:{borderRadius:"11px",border:"1px solid rgba(255,255,255,0.07)",background:"#161618",padding:"12px",marginBottom:"8px"}},[React.createElement("div",{key:"header",className:"flex items-center justify-between mb-2"},[React.createElement("div",{key:"info",className:"flex items-center"},[React.createElement("i",{key:"icon",className:"fas fa-arrow-up",style:{color:"#f0892a",fontSize:"13px",marginInlineEnd:"8px"}}),React.createElement("span",{key:"name",className:"font-medium text-sm",style:{color:"#e8e8eb"}},E.fileName),React.createElement("span",{key:"size",className:"text-xs ms-2",style:{color:"#7b7b83"}},g(E.fileSize))]),React.createElement("button",{key:"cancel",onClick:()=>s.cancelFileTransfer(E.fileId),className:"text-red-400 hover:text-red-300 text-xs"},[React.createElement("i",{className:"fas fa-times"})])]),b(E,"#f0892a")])),...o.receiving.map(E=>React.createElement("div",{key:`recv-${E.fileId}`,style:{borderRadius:"11px",border:"1px solid rgba(255,255,255,0.07)",background:"#161618",padding:"12px",marginBottom:"8px"}},[React.createElement("div",{key:"header",className:"flex items-center justify-between mb-2"},[React.createElement("div",{key:"info",className:"flex items-center"},[React.createElement("i",{key:"icon",className:"fas fa-arrow-down",style:{color:"#3ecf8e",fontSize:"13px",marginInlineEnd:"8px"}}),React.createElement("span",{key:"name",className:"font-medium text-sm",style:{color:"#e8e8eb"}},E.fileName),React.createElement("span",{key:"size",className:"text-xs ms-2",style:{color:"#7b7b83"}},g(E.fileSize))]),React.createElement("div",{key:"actions",className:"flex items-center space-x-2"},[E.status==="completed"?React.createElement("button",{key:"download",className:"text-green-400 hover:text-green-300 text-xs flex items-center",onClick:async()=>{try{let C=await s.getReceivedFileObjectURL(E.fileId);if(!C){alert(f("file.gone"));return}let M=document.createElement("a");M.href=C,M.download=E.fileName||"file",M.click(),setTimeout(()=>s.revokeReceivedFileObjectURL(C),1e4)}catch(C){alert(C.message||f("file.gone"))}}},[React.createElement("i",{key:"i",className:"fas fa-download me-1"}),f("file.download")]):null,React.createElement("button",{key:"cancel",onClick:()=>s.cancelFileTransfer(E.fileId),className:"text-red-400 hover:text-red-300 text-xs"},[React.createElement("i",{className:"fas fa-times"})])])]),b(E,"#3ecf8e")]))])]):React.createElement("div",{className:"p-4 text-center text-yellow-600"},[React.createElement("i",{key:"icon",className:"fas fa-exclamation-triangle me-2"}),"\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0443\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u0435\u0442\u0441\u044F... \u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u043E\u0432 \u0431\u0443\u0434\u0435\u0442 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430 \u043F\u043E\u0441\u043B\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438."]):React.createElement("div",{className:"p-4 text-center text-muted"},f("file.needConnection"))};window.FileTransferComponent=Ra;var ze=Object.freeze({MAX_SERVERS:10,MAX_URLS_PER_SERVER:8,MAX_STRING_LENGTH:512}),Uo=Object.freeze(["stun","stuns","turn","turns"]),Ma=/^(stuns?|turns?):/i,La=/^(\[[0-9a-f:]+\]|[a-z0-9.-]+)(:\d{1,5})?$/i,Da=/^transport=(udp|tcp)$/i;function xn(s){for(let e=0;eze.MAX_STRING_LENGTH)return f("iceUrl.tooLong");if(xn(e))return f("iceUrl.badChars");let t=e.match(Ma);if(!t)return f("iceUrl.badScheme");let i=e.slice(t[0].length),[r,n,...a]=i.split("?");return a.length>0?f("iceUrl.badQuery"):r?La.test(r)?n!==void 0&&!Da.test(n)?f("iceUrl.badTransport"):null:f("iceUrl.badHost"):f("iceUrl.noHost")}function Rn(s){return typeof s=="string"&&/^turns?:/i.test(s.trim())}function An(s,e){return s==null||s===""?null:typeof s!="string"?`${e} must be a string`:s.length>ze.MAX_STRING_LENGTH?`${e} is too long`:xn(s)?`${e} contains invalid characters`:null}function In(s){let e=[],t=[],i=[];return Array.isArray(s)?s.length===0?{servers:[],errors:[],warnings:[]}:s.length>ze.MAX_SERVERS?(e.push(f("iceErr.tooMany",{max:ze.MAX_SERVERS})),{servers:[],errors:e,warnings:t}):(s.forEach((r,n)=>{let a=`Server #${n+1}`;if(!r||typeof r!="object"){e.push(f("iceErr.invalidEntry",{label:a}));return}let o=Array.isArray(r.urls)?r.urls:[r.urls];if(o.length===0||o.length>ze.MAX_URLS_PER_SERVER){e.push(f("iceErr.urlCount",{label:a,max:ze.MAX_URLS_PER_SERVER}));return}let c=[],l=!1;for(let S of o){let w=Pa(S);if(w){e.push(`${a}: ${w}`);continue}let g=S.trim();c.push(g),Rn(g)&&(l=!0)}if(c.length===0)return;let h=An(r.username,`${a} username`);h&&e.push(h);let u=An(r.credential,`${a} credential`);u&&e.push(u);let p={urls:c.length===1?c[0]:c};r.username&&(p.username=String(r.username)),r.credential&&(p.credential=String(r.credential)),l&&(!p.username||!p.credential)&&t.push(f("iceErr.turnCreds",{label:a})),i.push(p)}),{servers:i,errors:e,warnings:t}):{servers:[],errors:[f("iceErr.notArray")],warnings:[]}}function Mn(s){if(typeof s!="string"||!s.trim())return{servers:[],errors:[],warnings:[]};let e=s.trim();if(e.startsWith("[")||e.startsWith("{")){let i;try{i=JSON.parse(e)}catch{return{servers:[],errors:[f("iceErr.invalidJson")],warnings:[]}}let r=Array.isArray(i)?i:[i];return In(r)}let t=e.split(` `).map(i=>i.trim()).filter(Boolean).map(i=>({urls:i}));return In(t)}function Ln(s){return Array.isArray(s)?s.some(e=>(Array.isArray(e?.urls)?e.urls:[e?.urls]).some(Rn)):!1}var Ve=window.React,Fa=["# One URL per line, e.g.:","stun:stun.example.com:3478","turn:turn.example.com:3478?transport=udp","","# Or paste JSON for servers with credentials:",'[{"urls":"turns:turn.example.com:5349","username":"user","credential":"secret"}]'].join(` `);async function Ka(s,e=6e3){let t={host:0,srflx:0,relay:0};if(typeof RTCPeerConnection>"u")return{...t,error:f("ice.errUnavailable")};let i;try{i=new RTCPeerConnection({iceServers:s})}catch(r){return{...t,error:r.message||f("ice.errInvalid")}}return new Promise(r=>{let n=!1,a=()=>{if(!n){n=!0,clearTimeout(o);try{i.close()}catch{}r(t)}},o=setTimeout(a,e);i.onicecandidate=c=>{if(!c.candidate){a();return}let l=c.candidate.candidate||"";/ typ host/.test(l)?t.host++:/ typ srflx/.test(l)?t.srflx++:/ typ relay/.test(l)&&t.relay++};try{i.createDataChannel("securebit-ice-test"),i.createOffer().then(c=>i.setLocalDescription(c)).catch(()=>a())}catch{a()}})}var Na=({isOpen:s,onClose:e,initial:t,hasSaved:i,onApply:r,onForget:n,embedded:a})=>{if(!s)return null;let[o,c]=Ve.useState(t?.useCustom||!1),[l,h]=Ve.useState(t?.serversText||""),[u,p]=Ve.useState(t?.privacyMode==="relay-only"),[S,w]=Ve.useState(t?.persisted||!1),[g,m]=Ve.useState("idle"),[I,b]=Ve.useState(null),D=o?Mn(l):{servers:[],errors:[],warnings:[]},_=Ln(D.servers),R=!o||D.servers.length>0&&D.errors.length===0,E=async()=>{m("running"),b(null);let j=await Ka(D.servers);b(j),m("done")},C=()=>{R&&r({useCustom:o,servers:o?D.servers:[],privacyMode:u?"relay-only":"standard",serversText:l},S)},M=async()=>{n&&await n(),w(!1)},v=Ve.createElement,q="#f0892a",O="#3ecf8e",x="'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",ue=(j,U,H,A,F)=>v("button",{type:"button",onClick:U,style:Object.assign({width:"100%",textAlign:"start",display:"flex",alignItems:"flex-start",gap:"12px",padding:"14px 15px",borderRadius:"13px",border:`1px solid ${j?"rgba(240,137,42,0.45)":"rgba(255,255,255,0.07)"}`,background:j?"rgba(240,137,42,0.06)":"#141416",color:"inherit",fontFamily:"inherit",cursor:"pointer",transition:"all .15s",marginBottom:"10px"},F||{})},[v("span",{key:"ring",style:{flex:"none",width:"18px",height:"18px",marginTop:"1px",borderRadius:"50%",border:`1.5px solid ${j?q:"rgba(255,255,255,0.22)"}`,display:"grid",placeItems:"center"}},v("span",{style:{width:"8px",height:"8px",borderRadius:"50%",background:j?q:"transparent"}})),v("span",{key:"tx",style:{flex:1}},[v("span",{key:"t",style:{display:"block",fontSize:"14px",fontWeight:700,color:"#f4f4f6"}},H),v("span",{key:"d",style:{display:"block",fontSize:"12.5px",color:"#8a8a92",marginTop:"2px"}},A)])]),ne=(j,U,H,A,F,K)=>v("button",{type:"button",onClick:U,style:{width:"100%",textAlign:"start",display:"flex",alignItems:"flex-start",gap:"12px",padding:"14px 15px",borderRadius:"13px",border:`1px solid ${j?"rgba(62,207,142,0.3)":"rgba(255,255,255,0.07)"}`,background:j?"rgba(62,207,142,0.05)":"#141416",color:"inherit",fontFamily:"inherit",cursor:"pointer",transition:"all .15s",marginBottom:"10px"}},[v("span",{key:"tx",style:{flex:1}},[v("span",{key:"r1",style:{display:"flex",alignItems:"center",gap:"8px"}},[v("span",{key:"t",style:{fontSize:"14px",fontWeight:700,color:"#f4f4f6"}},H),K&&v("span",{key:"b",style:{fontSize:"10px",fontWeight:700,color:O,padding:"2px 7px",borderRadius:"5px",background:"rgba(62,207,142,0.1)",border:"1px solid rgba(62,207,142,0.22)"}},K)]),v("span",{key:"d",style:{display:"block",fontSize:"12.5px",lineHeight:1.5,color:"#8a8a92",marginTop:"3px"}},A)]),v("span",{key:"tr",style:{flex:"none",width:"42px",height:"24px",borderRadius:"99px",background:j?F||O:"rgba(255,255,255,0.08)",border:`1px solid ${j?F||O:"rgba(255,255,255,0.12)"}`,position:"relative",transition:"all .18s",marginTop:"1px"}},v("span",{style:{position:"absolute",top:"2px",insetInlineStart:"2px",width:"18px",height:"18px",borderRadius:"50%",background:"#fff",transform:j?`translateX(${18*Fr()}px)`:"translateX(0)",transition:"transform .18s"}}))]),te=[];if(te.push(v("p",{key:"intro",style:{margin:"0 0 18px",fontSize:"13.5px",lineHeight:1.6,color:"#9a9aa2"}},f("ice.intro"))),te.push(ue(!o,()=>c(!1),f("ice.publicTitle"),f("ice.publicDesc"))),te.push(ue(o,()=>c(!0),f("ice.customTitle"),f("ice.customDesc",{max:ze.MAX_SERVERS}),o?{marginBottom:"14px"}:null)),o){let j=[];j.push(v("div",{key:"ta",style:{borderRadius:"13px",border:"1px solid rgba(255,255,255,0.08)",background:"#0c0c0e",overflow:"hidden",marginBottom:"12px"}},v("textarea",{dir:"ltr",value:l,onChange:H=>h(H.target.value),rows:5,spellCheck:!1,autoComplete:"off",placeholder:Fa,style:{width:"100%",resize:"vertical",border:"none",outline:"none",background:"transparent",color:"#c9ccd8",fontFamily:x,fontSize:"12px",lineHeight:1.65,padding:"13px 14px",minHeight:"104px"}}))),D.errors.length>0&&j.push(v("ul",{key:"err",style:{margin:"0 0 10px",paddingInlineStart:"18px",color:"#e5727a",fontSize:"12.5px"}},D.errors.slice(0,6).map((H,A)=>v("li",{key:A},H)))),D.warnings.length>0&&j.push(v("ul",{key:"warn",style:{margin:"0 0 10px",paddingInlineStart:"18px",color:"#e3c84e",fontSize:"12.5px"}},D.warnings.slice(0,6).map((H,A)=>v("li",{key:A},H)))),D.servers.length>0&&D.errors.length===0&&j.push(v("p",{key:"ok",style:{margin:"0 0 10px",fontSize:"12.5px",color:O}},`${D.servers.length} server(s) parsed${_?" (TURN present)":" (STUN only \u2014 does not hide IP)"}.`)),j.push(v("div",{key:"note",style:{display:"flex",alignItems:"flex-start",gap:"9px",padding:"12px 13px",borderRadius:"11px",border:"1px solid rgba(62,207,142,0.18)",background:"rgba(62,207,142,0.05)",marginBottom:"12px"}},[v("i",{key:"i",className:"fas fa-info-circle",style:{color:O,fontSize:"13px",marginTop:"2px",flex:"none"}}),v("span",{key:"t",style:{fontSize:"12px",lineHeight:1.55,color:"#a8b8ae"}},[f("ice.turnNote"),v("span",{key:"m",style:{fontFamily:x,color:O}},"turns:"),f("ice.turnNoteTls")])]));let U=g==="done"&&I&&!I.error?O:"#cfcfd4";j.push(v("div",{key:"test",style:{display:"flex",alignItems:"center",gap:"12px",flexWrap:"wrap",marginBottom:"4px"}},[v("button",{key:"btn",type:"button",disabled:!R||g==="running",onClick:E,style:{display:"inline-flex",alignItems:"center",gap:"8px",padding:"10px 15px",borderRadius:"10px",border:`1px solid ${g==="done"&&I&&!I.error?"rgba(62,207,142,0.4)":"rgba(255,255,255,0.1)"}`,background:g==="done"&&I&&!I.error?"rgba(62,207,142,0.08)":"rgba(255,255,255,0.04)",color:U,fontFamily:"inherit",fontSize:"13px",fontWeight:600,cursor:!R||g==="running"?"not-allowed":"pointer",opacity:!R||g==="running"?.6:1}},[v("i",{key:"i",className:g==="running"?"fas fa-circle-notch":"fas fa-play-circle",style:g==="running"?{animation:"sbSpin 1s linear infinite"}:null}),g==="running"?f("ice.testing"):f("ice.test")]),g==="done"&&I?v("span",{key:"res",style:{fontSize:"12px",color:I.error?"#e5727a":"#8a8a92"}},I.error?`Test failed: ${I.error}`:I.srflx>0||I.relay>0?`STUN ${I.srflx>0?"OK":"none"} \xB7 TURN ${I.relay>0?"OK":"none"} \xB7 host ${I.host}`:`host ${I.host} \xB7 this browser hides STUN/TURN candidates from the test \u2014 your servers still apply to real connections`):null])),te.push(v("div",{key:"custom",style:{marginBottom:"16px"}},j))}te.push(ne(u,()=>p(!u),f("ice.relayTitle"),f("ice.relayDesc"),O,f("ice.relayBadge"))),u&&o&&!_&&te.push(v("p",{key:"relaywarn",style:{margin:"-4px 0 10px",fontSize:"12.5px",color:"#e3c84e"}},f("ice.relayWarning"))),te.push(ne(S,()=>w(!S),f("ice.persist"),f("ice.persistDesc"),q));let ye=[];return i&&ye.push(v("button",{key:"forget",type:"button",onClick:M,style:{marginInlineEnd:"auto",padding:"11px 18px",borderRadius:"11px",border:"1px solid rgba(229,114,122,0.3)",background:"transparent",color:"#e5727a",fontFamily:"inherit",fontSize:"13.5px",fontWeight:600,cursor:"pointer"}},f("ice.forget"))),ye.push(v("button",{key:"cancel",type:"button",onClick:e,style:{padding:"11px 18px",borderRadius:"11px",border:"1px solid rgba(255,255,255,0.1)",background:"transparent",color:"#b3b3ba",fontFamily:"inherit",fontSize:"13.5px",fontWeight:600,cursor:"pointer"}},f("ice.cancel"))),ye.push(v("button",{key:"apply",type:"button",onClick:C,disabled:!R,style:{display:"inline-flex",alignItems:"center",gap:"8px",padding:"11px 20px",borderRadius:"11px",border:"none",background:q,color:"#1a0f04",fontFamily:"inherit",fontSize:"13.5px",fontWeight:700,cursor:R?"pointer":"not-allowed",opacity:R?1:.5,boxShadow:"0 6px 18px rgba(240,137,42,0.28)"}},[v("i",{key:"i",className:"fas fa-check"}),f("ice.apply")])),v("div",{className:"sb-ice-overlay",style:a?{position:"absolute",inset:0,zIndex:60,display:"flex",flexDirection:"column",background:"#0f0f11",animation:"sbSlideUp .32s cubic-bezier(.2,.7,.3,1)"}:{position:"fixed",inset:0,zIndex:60,display:"flex",flexDirection:"column",alignItems:"stretch",background:"#0f0f11",animation:"sbSlideUp .32s cubic-bezier(.2,.7,.3,1)"}},[v(Ve.Fragment,{key:"panel"},[v("div",{key:"head",style:{display:"flex",alignItems:"center",gap:"12px",padding:"20px 24px",borderBottom:"1px solid rgba(255,255,255,0.06)"}},[v("div",{key:"ic",style:{width:"38px",height:"38px",flex:"none",display:"grid",placeItems:"center",borderRadius:"10px",background:"rgba(255,255,255,0.03)",border:"1px solid rgba(255,255,255,0.06)"}},v("i",{className:"fas fa-sliders-h",style:{color:"#cfcfd4",fontSize:"15px"}})),v("div",{key:"tx",style:{flex:1,lineHeight:1.25}},[v("div",{key:"t",style:{fontSize:"16.5px",fontWeight:800,letterSpacing:"-0.3px",color:"#f4f4f6"}},f("ice.title")),v("div",{key:"s",style:{fontSize:"12px",color:"#7b7b83"}},f("ice.subtitle"))]),v("button",{key:"x",type:"button",onClick:e,style:{width:"32px",height:"32px",flex:"none",display:"grid",placeItems:"center",borderRadius:"9px",border:"none",background:"rgba(255,255,255,0.04)",color:"#8a8a92",cursor:"pointer"}},v("i",{className:"fas fa-times"}))]),v("div",{key:"body",className:"custom-scrollbar",style:{flex:1,overflowY:"auto",padding:"20px 24px"}},te),v("div",{key:"foot",style:{display:"flex",alignItems:"center",justifyContent:"flex-end",gap:"10px",padding:"16px 24px",borderTop:"1px solid rgba(255,255,255,0.06)",background:"#0e0e10",borderRadius:"0"}},ye)])])};window.IceServerSettings=Na;var Oa=({webrtcManager:s,peerTitle:e})=>{let t=React.createElement,i="'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",r={lock:'',minimize:'',expand:'',user:'',micOn:'',micOff:'',camOn:'',camOff:'',flip:'',phone:'',phoneHangup:''},n=(K,z,W)=>t("span",{style:{display:"grid",placeItems:"center",width:z+"px",height:z+"px"},dangerouslySetInnerHTML:{__html:`${K}`}}),[a,o]=React.useState(()=>s?.getCallState?.()||{phase:"idle",active:!1}),[c,l]=React.useState(!1),[h,u]=React.useState(0),p=React.useRef(null),S=React.useRef(null),w=React.useRef(null);React.useEffect(()=>{if(!s)return;let K=W=>o(W),z=s.onCallStateChanged;return s.onCallStateChanged=K,o(s.getCallState?s.getCallState():{phase:"idle",active:!1}),()=>{s.onCallStateChanged===K&&(s.onCallStateChanged=z||null)}},[s]);let g=a.phase||"idle",m=!!a.active,I=!!a.withVideo||!!a.remoteHasVideo;if(React.useEffect(()=>{let K=s?.getRemoteMediaStream?.(),z=s?.getLocalMediaStream?.(),W=(X,Se,_e)=>{if(!X||!Se)return;X.srcObject!==Se&&(X.muted=_e,X.srcObject=Se);let ge=X.play&&X.play();ge&&ge.catch&&ge.catch(()=>{})};W(S.current,K,!1,"remoteAudio"),W(p.current,K,!0,"remoteVideo"),W(w.current,z,!0,"selfVideo")}),React.useEffect(()=>{if(g!=="active"){u(0);return}let K=Date.now(),z=setInterval(()=>u(Math.floor((Date.now()-K)/1e3)),1e3);return()=>clearInterval(z)},[g]),React.useEffect(()=>{g==="idle"&&l(!1)},[g]),!m||g==="idle"||g==="ended"||a.groupCallId)return null;let b=K=>`${String(Math.floor(K/60)).padStart(2,"0")}:${String(K%60).padStart(2,"0")}`,D=g==="outgoing"||g==="connecting",_=g==="outgoing"?f("call.ringing"):g==="connecting"?f("call.connecting"):g==="active"?b(h):f("call.ringing"),R=e||f("call.peer"),E={width:"56px",height:"56px",borderRadius:"50%",display:"grid",placeItems:"center",border:"1px solid rgba(255,255,255,0.1)",background:"rgba(255,255,255,0.05)",color:"#cfcfd4",cursor:"pointer",transition:"all .15s"},C={...E,background:"#e5484d",color:"#fff",border:"1px solid transparent"},M={width:"56px",height:"56px",borderRadius:"50%",display:"grid",placeItems:"center",border:"none",background:"#e5484d",color:"#fff",cursor:"pointer",boxShadow:"0 8px 24px rgba(229,72,77,0.35)",transition:"transform .15s"},v=K=>({width:"36px",height:"36px",borderRadius:"9px",display:"grid",placeItems:"center",border:"1px solid rgba(255,255,255,"+(K?"0.15":"0.1")+")",background:K?"rgba(0,0,0,0.35)":"rgba(255,255,255,0.04)",color:K?"#fff":"#cfcfd4",cursor:"pointer",transition:"all .15s"}),q=t("span",{key:"enc",style:{display:"inline-flex",alignItems:"center",gap:"4px",fontSize:"11px",fontWeight:600,color:"#3ecf8e"}},[n(r.lock,11,2),f("call.encryptedShort")]),O={excellent:{bars:4,color:"#3ecf8e",label:f("call.qualityExcellent")},good:{bars:3,color:"#3ecf8e",label:f("call.qualityGood")},fair:{bars:2,color:"#e3c84e",label:f("call.qualityFair")},poor:{bars:1,color:"#e5727a",label:f("call.qualityWeak")}},x=K=>{let z=O[a.quality];if(!z)return null;let W=t("span",{key:"bars",style:{display:"inline-flex",alignItems:"flex-end",gap:"2px",height:"14px"}},[0,1,2,3].map(X=>t("span",{key:X,style:{width:"3px",height:5+X*3+"px",borderRadius:"1px",background:Xs?.acceptCall?.(),ne=()=>s?.declineCall?.(),te=()=>{l(!1),s?.endCall?.()},ye=()=>s?.toggleMic?.(),Re=()=>s?.toggleCamera?.(),j=()=>s?.switchCamera?.(),U=()=>s?.upgradeToVideo?.(),H=t("audio",{key:"ra",ref:S,autoPlay:!0,playsInline:!0,style:{display:"none"}}),A=(K,z,W)=>t("div",{key:K,style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"8px"}},[z,t("span",{key:"l",style:{fontFamily:i,fontSize:"10.5px",color:"#8a8a92"}},W)]),F=(K,z)=>t("div",{key:"av",style:{position:"relative",width:"120px",height:"120px",marginBottom:"28px",display:"grid",placeItems:"center"}},[z&&t("span",{key:"p1",style:{position:"absolute",inset:0,borderRadius:"50%",border:"1.5px solid rgba(240,137,42,0.5)",animation:"sbCallPulse 2s ease-out infinite"}}),z&&t("span",{key:"p2",style:{position:"absolute",inset:0,borderRadius:"50%",border:"1.5px solid rgba(240,137,42,0.4)",animation:"sbCallPulse 2s ease-out infinite",animationDelay:"1s"}}),t("div",{key:"c",style:{width:"104px",height:"104px",borderRadius:"50%",display:"grid",placeItems:"center",background:"radial-gradient(circle at 35% 30%, #2a2a30, #161618)",border:"1px solid rgba(255,255,255,0.1)",boxShadow:"0 12px 30px rgba(0,0,0,0.4)",color:"#8a8a92"}},n(r.user,K,1.6))]);return g==="incoming"?t("div",{style:{position:"absolute",inset:0,zIndex:40,display:"flex",flexDirection:"column",background:"radial-gradient(680px 460px at 50% 36%, rgba(240,137,42,0.08), transparent 70%), #0d0d0f",animation:"sbExpand .2s ease"}},[H,t("div",{key:"top",style:{flex:"none",display:"flex",alignItems:"center",justifyContent:"flex-start",padding:"16px 18px"}},t("span",{style:{display:"inline-flex",alignItems:"center",gap:"7px",fontSize:"12px",fontWeight:600,color:"#3ecf8e"}},[n(r.lock,13,2),f("call.encrypted")])),t("div",{key:"mid",style:{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"}},[F(46,!0),t("div",{key:"nm",style:{fontSize:"24px",fontWeight:800,letterSpacing:"-0.5px",color:"#f4f4f6"}},R),t("div",{key:"st",style:{fontFamily:i,fontSize:"14px",fontWeight:500,color:"#9a9aa2",marginTop:"8px"}},a.withVideo?f("call.incomingVideo"):f("call.incoming"))]),t("div",{key:"ctrls",style:{flex:"none",display:"flex",alignItems:"flex-start",justifyContent:"center",gap:"48px",padding:"28px 24px 40px"}},[A("dec",t("button",{onClick:ne,title:f("call.decline"),style:{...M,width:"62px",height:"62px"}},n(r.phoneHangup,24,1.9)),f("call.decline")),A("acc",t("button",{onClick:ue,title:f("call.accept"),style:{width:"62px",height:"62px",borderRadius:"50%",display:"grid",placeItems:"center",border:"none",background:"#3ecf8e",color:"#06231a",cursor:"pointer",boxShadow:"0 8px 24px rgba(62,207,142,0.35)"}},n(r.phone,24,1.9)),f("call.accept"))])]):c?t("div",{style:{position:"absolute",bottom:"18px",insetInlineEnd:"18px",zIndex:40,width:"236px",borderRadius:"14px",overflow:"hidden",background:"#161618",border:"1px solid rgba(255,255,255,0.1)",boxShadow:"0 18px 44px rgba(0,0,0,0.55)",animation:"sbExpand .18s ease"}},[H,I&&t("div",{key:"v",style:{position:"relative",height:"132px",background:"#111"}},[t("video",{key:"rv",ref:p,autoPlay:!0,muted:!0,playsInline:!0,style:{width:"100%",height:"100%",objectFit:"cover",display:"block"}}),!a.remoteHasVideo&&t("div",{key:"off",style:{position:"absolute",inset:0,display:"grid",placeItems:"center",background:"linear-gradient(120deg,#15151b,#1d1a24)",color:"#6b6b73"}},n(r.camOff,22,1.8)),t("span",{key:"s",style:{position:"absolute",top:"8px",insetInlineStart:"9px",fontFamily:i,fontSize:"11px",fontWeight:600,color:"#fff",padding:"3px 7px",borderRadius:"6px",background:"rgba(0,0,0,0.5)"}},_)]),t("div",{key:"bar",style:{display:"flex",alignItems:"center",gap:"11px",padding:"11px 12px"}},[t("span",{key:"ic",style:{position:"relative",flex:"none",width:"34px",height:"34px",borderRadius:"9px",display:"grid",placeItems:"center",background:"rgba(62,207,142,0.1)",border:"1px solid rgba(62,207,142,0.25)",color:"#3ecf8e"}},n(r.user,16,1.9)),t("div",{key:"tx",style:{flex:1,minWidth:0}},[t("div",{key:"n",style:{fontSize:"13px",fontWeight:700,color:"#f4f4f6",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},R),t("div",{key:"s",style:{display:"flex",alignItems:"center",gap:"7px",fontFamily:i,fontSize:"11px",color:"#9a9aa2"}},[(I?f("call.videoPrefix"):f("call.voicePrefix"))+_,g==="active"&&x(!0)])]),t("button",{key:"exp",onClick:()=>l(!1),title:f("call.expand"),style:{flex:"none",width:"32px",height:"32px",borderRadius:"8px",display:"grid",placeItems:"center",border:"none",background:"rgba(255,255,255,0.05)",color:"#cfcfd4",cursor:"pointer",transition:"all .15s"}},n(r.expand,15,2)),t("button",{key:"end",onClick:te,title:f("call.end"),style:{flex:"none",width:"32px",height:"32px",borderRadius:"8px",display:"grid",placeItems:"center",border:"none",background:"#e5484d",color:"#fff",cursor:"pointer",transition:"transform .15s"}},n(r.phoneHangup,15,2))])]):I?t("div",{style:{position:"absolute",inset:0,zIndex:40,overflow:"hidden",background:"#0a0a0c",animation:"sbExpand .2s ease"}},[H,a.remoteHasVideo?t("video",{key:"rv",ref:p,autoPlay:!0,muted:!0,playsInline:!0,style:{position:"absolute",inset:0,width:"100%",height:"100%",objectFit:"cover",background:"#0a0a0c"}}):t("div",{key:"ph",style:{position:"absolute",inset:0,background:"linear-gradient(120deg, #15151b, #1d1a24, #161620)",backgroundSize:"200% 200%",animation:"sbLiveBg 9s ease-in-out infinite",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:"18px"}},[t("div",{key:"a",style:{width:"120px",height:"120px",borderRadius:"50%",display:"grid",placeItems:"center",background:"radial-gradient(circle at 35% 30%, #2a2a30, #161618)",border:"1px solid rgba(255,255,255,0.1)",color:"#9a9aa2"}},n(r.user,54,1.5)),t("div",{key:"t",style:{fontSize:"15px",fontWeight:600,color:"#8a8a92"}},f("call.peerCameraOff"))]),t("div",{key:"top",style:{position:"absolute",top:0,left:0,right:0,display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:"14px",padding:"18px 20px",background:"linear-gradient(180deg, rgba(0,0,0,0.55), transparent)"}},[t("div",{key:"l"},[t("div",{key:"n",style:{fontSize:"18px",fontWeight:800,letterSpacing:"-0.3px",color:"#fff"}},R),t("div",{key:"s",style:{display:"inline-flex",alignItems:"center",gap:"9px",marginTop:"4px"}},[t("span",{key:"st",style:{fontFamily:i,fontSize:"12.5px",fontWeight:500,color:"#e8e8eb"}},_),q,g==="active"&&x(!1)])]),t("button",{key:"min",onClick:()=>l(!0),title:f("call.minimize"),style:{flex:"none",...v(!0)}},n(r.minimize,16,2))]),t("div",{key:"self",style:{position:"absolute",bottom:"108px",insetInlineEnd:"18px",width:"132px",height:"176px",borderRadius:"14px",overflow:"hidden",border:"1px solid rgba(255,255,255,0.16)",boxShadow:"0 12px 30px rgba(0,0,0,0.5)",background:"#111"}},[t("video",{key:"sv",ref:w,autoPlay:!0,muted:!0,playsInline:!0,style:{width:"100%",height:"100%",objectFit:"cover",transform:"scaleX(-1)",display:"block"}}),!a.cameraEnabled&&t("div",{key:"off",style:{position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:"8px",background:"#161618",color:"#6b6b73"}},[n(r.camOff,24,1.8),t("span",{key:"t",style:{fontSize:"10.5px",color:"#6b6b73",fontFamily:i}},f("call.cameraOff"))])]),t("div",{key:"ctrls",style:{position:"absolute",bottom:0,left:0,right:0,display:"flex",alignItems:"center",justifyContent:"center",gap:"18px",padding:"22px 24px 28px",background:"linear-gradient(0deg, rgba(0,0,0,0.6), transparent)"}},[t("button",{key:"mute",onClick:ye,title:f("call.mute"),style:a.micEnabled?E:C},n(a.micEnabled?r.micOn:r.micOff,21,1.9)),t("button",{key:"cam",onClick:Re,title:f("call.camera"),style:a.cameraEnabled?E:C},n(a.cameraEnabled?r.camOn:r.camOff,21,1.8)),t("button",{key:"flip",onClick:j,title:f("call.flipCamera"),style:E},n(r.flip,21,1.8)),t("button",{key:"end",onClick:te,title:f("call.end"),style:M},n(r.phoneHangup,22,1.9))])]):t("div",{style:{position:"absolute",inset:0,zIndex:40,display:"flex",flexDirection:"column",background:"radial-gradient(680px 460px at 50% 36%, rgba(240,137,42,0.08), transparent 70%), #0d0d0f",animation:"sbExpand .2s ease"}},[H,t("div",{key:"top",style:{flex:"none",display:"flex",alignItems:"center",justifyContent:"space-between",padding:"16px 18px"}},[t("span",{key:"enc",style:{display:"inline-flex",alignItems:"center",gap:"7px",fontSize:"12px",fontWeight:600,color:"#3ecf8e"}},[n(r.lock,13,2),f("call.encrypted")]),t("button",{key:"min",onClick:()=>l(!0),title:f("call.minimize"),style:v(!1)},n(r.minimize,16,2))]),t("div",{key:"mid",style:{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"}},[F(46,D),t("div",{key:"nm",style:{fontSize:"24px",fontWeight:800,letterSpacing:"-0.5px",color:"#f4f4f6"}},R),t("div",{key:"st",style:{fontFamily:i,fontSize:"14px",fontWeight:500,color:"#9a9aa2",marginTop:"8px"}},_),g==="active"&&t("div",{key:"q",style:{marginTop:"12px"}},x(!1))]),t("div",{key:"ctrls",style:{flex:"none",display:"flex",alignItems:"flex-start",justifyContent:"center",gap:"26px",padding:"28px 24px 34px"}},[A("mute",t("button",{onClick:ye,title:f("call.mute"),style:a.micEnabled?E:C},n(a.micEnabled?r.micOn:r.micOff,22,1.9)),a.micEnabled?"Mute":f("call.muted")),A("video",t("button",{onClick:U,title:f("call.addVideo"),style:E},n(r.camOn,22,1.8)),f("call.video")),A("end",t("button",{onClick:te,title:f("call.end"),style:M},n(r.phoneHangup,22,1.9)),f("call.endShort"))])])};typeof window<"u"&&(window.CallUIComponent=Oa);window.EnhancedSecureCryptoUtils=xt;window.EnhancedSecureWebRTCManager=Vt;window.EnhancedSecureFileTransfer=je;window.NotificationIntegration=Fn.NotificationIntegration;var Ua=()=>{try{let s=[];for(let e=0;e(window.__qrReady||(window.__qrReady=import("/dist/qr-local.js").then(()=>{window.dispatchEvent(new Event("securebit:qr-ready"))}).catch(s=>{console.warn("QR bundle failed to load:",s&&s.message),window.__qrReady=null})),window.__qrReady),za=()=>{typeof window.requestIdleCallback=="function"?window.requestIdleCallback(Dn,{timeout:3e3}):setTimeout(Dn,1200)},Pn=()=>{Ua(),typeof window.initializeApp=="function"?window.initializeApp():window.DEBUG_MODE&&console.error("initializeApp is not defined on window"),za()};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Pn):Pn(); /** * Secure and Reliable Notification Manager for P2P WebRTC Chat * Follows best practices: OWASP, MDN, Chrome DevRel * * @version 1.0.0 * @author SecureBit Team * @license MIT */ /** * Notification Integration Module for SecureBit WebRTC Chat * Integrates secure notifications with existing WebRTC architecture * * @version 1.0.0 * @author SecureBit Team * @license MIT */ /*! Bundled license information: dompurify/dist/purify.es.mjs: (*! @license DOMPurify 3.4.10 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.10/LICENSE *) */ //# sourceMappingURL=app-boot.js.map