1import{a as B}from"./chunk-XW6WFGHF.js";import{T as v}from"./chunk-5WB6OT6J.js";import{w as p}from"./chunk-3ETYRU43.js";import{Ca as I,O as w,Oa as u,Ta as g,g as l,ga as f,id as d,la as m,ma as y,ta as x}from"./chunk-BZRRMV4J.js";import{a as b,b as C,f as a}from"./chunk-ZY7WU73K.js";var A=(()=>{class h{constructor(e){this.platformId=e,this.encryptionKey=null,this.securityConfig={useHttpOnlyCookies:!1,encryptTokens:!0,tokenExpiration:24*60*60*1e3,csrfProtection:!0},this.tokenExpiring$=new l(!1),this.expirationWarningTime=5*60*1e3,this.isBrowser=p(this.platformId),this.isBrowser&&(this.initializeEncryption(),this.startExpirationChecker(),this.migrateFromLocalStorage())}initializeEncryption(){return a(this,null,function*(){if(!window.crypto?.subtle){console.warn("Web Crypto API not available. Tokens will be stored unencrypted."),this.securityConfig.encryptTokens=!1;return}try{let e=yield this.getStoredKey();e?this.encryptionKey=e:(this.encryptionKey=yield this.generateEncryptionKey(),yield this.storeKey(this.encryptionKey))}catch(e){console.error("Failed to initialize encryption:",e),this.securityConfig.encryptTokens=!1}})}generateEncryptionKey(){return a(this,null,function*(){return yield window.crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"])})}storeKey(e){return a(this,null,function*(){try{let t=yield window.crypto.subtle.exportKey("jwk",e),o=indexedDB.open("SecureStorage",2);o.onupgradeneeded=r=>{let s=r.target.result;s.objectStoreNames.contains("keys")||s.createObjectStore("keys")},o.onsuccess=r=>{let s=r.target.result;if(!s.objectStoreNames.contains("keys")){console.warn("Keys object store not found, skipping key storage"),s.close();return}let i=s.transaction(["keys"],"readwrite");i.objectStore("keys").put(t,"encryptionKey"),i.oncomplete=()=>s.close(),i.onerror=()=>s.close()},o.onerror=r=>{console.error("Failed to open IndexedDB:",r.target.error)}}catch(t){console.error("Failed to store encryption key:",t)}})}getStoredKey(){return a(this,null,function*(){return new Promise(e=>{let t=indexedDB.open("SecureStorage",2);t.onupgradeneeded=o=>{let r=o.target.result;r.objectStoreNames.contains("keys")||r.createObjectStore("keys")},t.onsuccess=o=>a(this,null,function*(){let r=o.target.result;if(!r.objectStoreNames.contains("keys")){r.close(),e(null);return}try{let s=r.transaction(["keys"],"readonly"),n=s.objectStore("keys").get("encryptionKey");n.onsuccess=()=>a(this,null,function*(){if(n.result)try{let c=yield window.crypto.subtle.importKey("jwk",n.result,{name:"AES-GCM"},!0,["encrypt","decrypt"]);r.close(),e(c)}catch(c){console.error("Failed to import key:",c),r.close(),e(null)}else r.close(),e(null)}),n.onerror=()=>{r.close(),e(null)},s.onerror=()=>{r.close(),e(null)}}catch(s){console.error("Transaction error:",s),r.close(),e(null)}}),t.onerror=()=>e(null)})})}encrypt(e){return a(this,null,function*(){if(!this.encryptionKey||!this.securityConfig.encryptTokens)return e;try{let o=new TextEncoder().encode(e),r=window.crypto.getRandomValues(new Uint8Array(12)),s=yield window.crypto.subtle.encrypt({name:"AES-GCM",iv:r},this.encryptionKey,o),i=new Uint8Array(r.length+s.byteLength);return i.set(r),i.set(new Uint8Array(s),r.length),btoa(String.fromCharCode(...i))}catch(t){return console.error("Encryption failed:",t),e}})}decrypt(e){return a(this,null,function*(){if(!this.encryptionKey||!this.securityConfig.encryptTokens)return e;try{let t=new Uint8Array(atob(e).split("").map(n=>n.charCodeAt(0))),o=t.slice(0,12),r=t.slice(12),s=yield window.crypto.subtle.decrypt({name:"AES-GCM",iv:o},this.encryptionKey,r);return new TextDecoder().decode(s)}catch(t){return console.error("Decryption failed:",t),e}})}setItem(e,t,o){return a(this,null,function*(){if(!this.isBrowser)return;let r=o?.expires?.getTime(),i={value:yield this.encrypt(t),expires:r,encrypted:this.securityConfig.encryptTokens};try{(this.isTokenKey(e)?sessionStorage:localStorage).setItem(`secure_${e}`,JSON.stringify(i)),r&&this.setExpirationTimer(e,r)}catch(n){console.error("Failed to store item securely:",n)}})}getItem(e){return a(this,null,function*(){if(!this.isBrowser)return null;try{let t=sessionStorage.getItem(`secure_${e}`);if(t||(t=localStorage.getItem(`secure_${e}`)),!t)return null;let o=JSON.parse(t);if(o.expires&&Date.now()>o.expires)return this.removeItem(e),null;let r=o.encrypted?yield this.decrypt(o.value):o.value;return o.expires&&this.isTokenKey(e)&&o.expires-Date.now()<=this.expirationWarningTime&&this.tokenExpiring$.next(!0),r}catch(t){return console.error("Failed to retrieve item securely:",t),null}})}removeItem(e){this.isBrowser&&(sessionStorage.removeItem(`secure_${e}`),localStorage.removeItem(`secure_${e}`),this.clearExpirationTimer(e))}setAuthToken(e,t){return a(this,null,function*(){let o=new Date(Date.now()+this.securityConfig.tokenExpiration);if(yield this.setItem("auth_token",e,{expires:o}),t){let r=new Date(Date.now()+this.securityConfig.tokenExpiration*7);yield this.setItem("refresh_token",t,{expires:r})}yield this.setItem("token_metadata",JSON.stringify({issuedAt:Date.now(),userAgent:navigator.userAgent,ipAddress:yield this.getClientIP()}))})}getAuthToken(){return a(this,null,function*(){return yield this.getItem("auth_token")})}getRefreshToken(){return a(this,null,function*(){return yield this.getItem("refresh_token")})}clearAuthData(){this.removeItem("auth_token"),this.removeItem("refresh_token"),this.removeItem("token_metadata"),this.removeItem("user_data"),this.removeItem("organization_data"),this.tokenExpiring$.next(!1)}getTokenExpirationWarning(){return this.tokenExpiring$.asObservable()}validateTokenIntegrity(){return a(this,null,function*(){try{if(!(yield this.getAuthToken()))return!1;let t=yield this.getItem("token_metadata");return t?JSON.parse(t).userAgent!==navigator.userAgent?(console.warn("Token tampering detected: User agent mismatch"),this.clearAuthData(),!1):!0:!1}catch(e){return console.error("Token validation failed:",e),!1}})}migrateFromLocalStorage(){return a(this,null,function*(){let e=["auth_token","refresh_token","user_data","organization_data"];for(let t of e){let o=localStorage.getItem(t);o&&!sessionStorage.getItem(`secure_${t}`)&&!localStorage.getItem(`secure_${t}`)&&(yield this.setItem(t,o),localStorage.removeItem(t),console.log(`Migrated ${t} to secure storage`))}})}isTokenKey(e){return["auth_token","refresh_token","user_data","organization_data"].includes(e)}setExpirationTimer(e,t){let o=t-Date.now();o>0&&setTimeout(()=>{this.removeItem(e)},o)}clearExpirationTimer(e){}startExpirationChecker(){setInterval(()=>{this.checkTokenExpiration()},6e4)}checkTokenExpiration(){return a(this,null,function*(){if(yield this.getAuthToken())try{let t=sessionStorage.getItem("secure_auth_token")||localStorage.getItem("secure_auth_token");if(t){let o=JSON.parse(t);if(o.expires){let r=o.expires-Date.now();r<=this.expirationWarningTime&&r>0&&this.tokenExpiring$.next(!0)}}}catch(t){console.error("Error checking token expiration:",t)}})}getClientIP(){return a(this,null,function*(){return"unknown"})}generateCSRFToken(){let e=new Uint8Array(32);return window.crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}logSecurityEvent(e,t){let o={timestamp:new Date().toISOString(),event:e,details:t,userAgent:navigator.userAgent,url:window.location.href};console.log("Security Event:",o)}static{this.\u0275fac=function(t){return new(t||h)(m(g))}}static{this.\u0275prov=f({token:h,factory:h.\u0275fac,providedIn:"root"})}}return h})();var V=(()=>{class h{constructor(e,t){this.platformId=e,this.secureStorage=t,this.currentTheme=u("system"),this.currentColorScheme=u("light"),this.systemPreference=u("light"),this.themes=new Map,this.currentThemeId=u("default"),this.theme$=new l("system"),this.colorScheme$=new l("light"),this.userPreferencesService=y(B),this.authService=y(v),this.injector=y(I),this.hasLoadedFromBackend=!1,this.isLoadingFromBackend=!1,this.isBrowser=p(this.platformId),this.isBrowser&&(this.initializeThemes(),this.setupSystemThemeDetection(),this.setupThemeEffects(),this.loadSavedTheme(),this.setupAuthStateListener(),this.checkAndLoadFromBackendIfAuthenticated())}
1initializeThemes(){let e={id:"default",name:"default",displayName:"Timix.AI Default",config:{light:{primaryColor:"#ea580c",accentColor:"#2563eb",backgroundColor:"#ffffff",surfaceColor:"#f9fafb",textColor:"#111827",borderColor:"#e5e7eb"},dark:{primaryColor:"#fb923c",accentColor:"#60a5fa",backgroundColor:"#111827",surfaceColor:"#1f2937",textColor:"#f9fafb",borderColor:"#374151"}}},t={id:"modern",name:"modern",displayName:"Modern Blue",config:{light:{primaryColor:"#3b82f6",accentColor:"#8b5cf6",backgroundColor:"#ffffff",surfaceColor:"#f8fafc",textColor:"#0f172a",borderColor:"#e2e8f0"},dark:{primaryColor:"#60a5fa",accentColor:"#a78bfa",backgroundColor:"#0f172a",surfaceColor:"#1e293b",textColor:"#f8fafc",borderColor:"#475569"}}};this.themes.set("default",e),this.themes.set("modern",t)}loadSavedTheme(){return a(this,null,function*(){try{let e=(yield this.secureStorage.getItem("user_theme"))||"system",t=(yield this.secureStorage.getItem("theme_id"))||"default";if(this.hasLoadedFromBackend||this.isLoadingFromBackend)return;this.currentTheme.set(e),this.currentThemeId.set(t),this.theme$.next(e),this.updateColorScheme()}catch(e){console.error("Failed to load saved theme:",e)}})}setupAuthStateListener(){x(this.injector,()=>{d(()=>{let e=this.authService.isAuthenticatedSignal();e&&!this.hasLoadedFromBackend?this.loadThemeFromBackend():e||(this.hasLoadedFromBackend=!1)})})}checkAndLoadFromBackendIfAuthenticated(){let e=this.authService.isAuthenticated();console.log("[ThemeService] Initial auth check:",e,"hasLoadedFromBackend:",this.hasLoadedFromBackend),e&&!this.hasLoadedFromBackend&&(console.log("[ThemeService] User is authenticated on init, loading theme from backend"),this.loadThemeFromBackend())}loadThemeFromBackend(){if(this.hasLoadedFromBackend||this.isLoadingFromBackend){console.log("[ThemeService] Skipping backend load - already loaded or loading");return}this.isLoadingFromBackend=!0,console.log("[ThemeService] Starting to load theme from backend..."),this.userPreferencesService.loadPreferences().pipe(w(1)).subscribe({next:e=>{if(console.log("[ThemeService] Backend response:",e),e.success&&e.data){let t=e.data.themePreference;console.log("[ThemeService] Backend theme value:",t),t&&["light","dark","system"].includes(t)&&(console.log("[ThemeService] Applying backend theme:",t),this.currentTheme.set(t),this.theme$.next(t),this.updateColorScheme(),this.secureStorage.setItem("user_theme",t)),this.hasLoadedFromBackend=!0,this.isLoadingFromBackend=!1}},error:e=>{console.error("[ThemeService] Failed to load theme from backend:",e),this.hasLoadedFromBackend=!0,this.isLoadingFromBackend=!1}})}saveThemeToBackend(e){if(!this.authService.isAuthenticated())return;let t=this.userPreferencesService.getCurrentPreferences(),o=C(b({},t),{themePreference:e});this.userPreferencesService.updatePreferences(o).pipe(w(1)).subscribe({next:r=>{r.success&&console.log("Theme preference saved to backend")},error:r=>{console.error("Failed to save theme preference to backend:",r)}})}setupSystemThemeDetection(){window.matchMedia&&(this.mediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.systemPreference.set(this.mediaQuery.matches?"dark":"light"),this.mediaQuery.addEventListener("change",e=>{this.systemPreference.set(e.matches?"dark":"light"),this.updateColorScheme()}))}setupThemeEffects(){d(()=>{this.applyThemeToDOM()}),d(()=>{this.theme$.next(this.currentTheme())}),d(()=>{this.colorScheme$.next(this.currentColorScheme())})}updateColorScheme(){let e=this.currentTheme(),t;e==="system"?t=this.systemPreference():t=e,this.currentColorScheme.set(t)}applyThemeToDOM(){if(!this.isBrowser)return;let e=this.currentColorScheme(),t=this.currentThemeId(),o=this.themes.get(t);if(!o)return;let r=o.config[e];if(!r)return;let s=document.documentElement;s.style.setProperty("--color-primary",r.primaryColor);let{r:i,g:n,b:c}=this.hexToRgb(r.primaryColor);s.style.setProperty("--color-primary-rgb",`${i}, ${n}, ${c}`),s.style.setProperty("--color-accent",r.accentColor),s.style.setProperty("--color-background",r.backgroundColor),s.style.setProperty("--color-surface",r.surfaceColor),s.style.setProperty("--color-text",r.textColor),s.style.setProperty("--color-border",r.borderColor),this.applyOrgBranding(s,r.surfaceColor),s.classList.remove("light","dark"),s.classList.add(e),s.className=s.className.replace(/theme-\w+/g,""),s.classList.add(`theme-${t}`),this.updateMetaThemeColor(r.primaryColor),window.dispatchEvent(new CustomEvent("themechange",{detail:{theme:this.currentTheme(
1),colorScheme:e,themeId:t}}))}applyOrgBranding(e,t){let o=this.authService.currentOrgSignal()?.primaryColor?.trim();if(!o||!/^#[0-9a-fA-F]{6}$/.test(o)){this.clearOrgBranding(e);return}if(this.contrastWithWhite(o)<3){this.clearOrgBranding(e);return}let r=this.makeReadableOnSurface(o,t);e.style.setProperty("--color-primary",r),e.style.setProperty("--color-primary-light",this.mixHex(r,"#ffffff",.25)),e.style.setProperty("--color-primary-dark",this.mixHex(r,"#000000",.2)),e.style.setProperty("--color-primary-alpha-10",this.hexToRgba(r,.1)),e.style.setProperty("--color-primary-alpha-20",this.hexToRgba(r,.2)),e.style.setProperty("--color-primary-alpha-30",this.hexToRgba(r,.3));let{r:s,g:i,b:n}=this.hexToRgb(r);e.style.setProperty("--color-primary-rgb",`${s}, ${i}, ${n}`)}clearOrgBranding(e){e.style.removeProperty("--color-primary-light"),e.style.removeProperty("--color-primary-dark"),e.style.removeProperty("--color-primary-alpha-10"),e.style.removeProperty("--color-primary-alpha-20"),e.style.removeProperty("--color-primary-alpha-30")}relativeLuminance(e){let{r:t,g:o,b:r}=this.hexToRgb(e),s=i=>{let n=i/255;return n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4)};return .2126*s(t)+.7152*s(o)+.0722*s(r)}makeReadableOnSurface(e,t){if(this.contrastBetween(e,t)>=3)return e;let o=this.relativeLuminance(t)<.5?"#ffffff":"#000000",r=e;for(let s=.1;s<=.85;s+=.1)if(r=this.mixHex(e,o,s),this.contrastBetween(r,t)>=3)return r;return r}hexToRgb(e){let t=e.replace("#","");return{r:parseInt(t.slice(0,2),16),g:parseInt(t.slice(2,4),16),b:parseInt(t.slice(4,6),16)}}hexToRgba(e,t){let{r:o,g:r,b:s}=this.hexToRgb(e);return`rgba(${o}, ${r}, ${s}, ${t})`}mixHex(e,t,o){let r=this.hexToRgb(e),s=this.hexToRgb(t),i=(c,k)=>Math.round(c+(k-c)*o),n=c=>c.toString(16).padStart(2,"0");return`#${n(i(r.r,s.r))}${n(i(r.g,s.g))}${n(i(r.b,s.b))}`}contrastWithWhite(e){let{r:t,g:o,b:r}=this.hexToRgb(e),s=n=>{let c=n/255;return c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4)};return 1.05/(.2126*s(t)+.7152*s(o)+.0722*s(r)+.05)}contrastBetween(e,t){let o=c=>{let{r:k,g:P,b:E}=this.hexToRgb(c),T=$=>{let S=$/255;return S<=.03928?S/12.92:Math.pow((S+.055)/1.055,2.4)};return .2126*T(k)+.7152*T(P)+.0722*T(E)},r=o(e),s=o(t),i=Math.max(r,s),n=Math.min(r,s);return(i+.05)/(n+.05)}updateMetaThemeColor(e){let t=document.querySelector('meta[name="theme-color"]');t||(t=document.createElement("meta"),t.setAttribute("name","theme-color"),document.head.appendChild(t)),t.setAttribute("content",e)}setTheme(e){return a(this,null,function*(){this.currentTheme.set(e),this.updateColorScheme(),yield this.secureStorage.setItem("user_theme",e),this.saveThemeToBackend(e)})}setThemeId(e){return a(this,null,function*(){this.themes.has(e)&&(this.currentThemeId.set(e),yield this.secureStorage.setItem("theme_id",e),this.applyThemeToDOM())})}toggleTheme(){return a(this,null,function*(){let e=this.currentTheme(),t;e==="system"?t=this.systemPreference()==="light"?"dark":"light":t=e==="light"?"dark":"light",yield this.setTheme(t)})}getCurrentTheme(){return this.currentTheme()}getCurrentColorScheme(){return this.currentColorScheme()}getCurrentThemeConfig(){let e=this.currentThemeId(),t=this.themes.get(e);return t?t.config[this.currentColorScheme()]:null}getAvailableThemes(){return Array.from(this.themes.values())}getTheme$(){return this.theme$.asObservable()}getColorScheme$(){return this.colorScheme$.asObservable()}isSystemDarkModeSupported(){return this.isBrowser&&window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches}getSystemPreference(){return this.systemPreference()}addCustomTheme(e){this.themes.set(e.id,e)}removeCustomTheme(e){e!=="default"&&(this.themes.delete(e),this.currentThemeId()===e&&this.setThemeId("default"))}exportThemeConfig(){let e={theme:this.currentTheme(),themeId:this.currentThemeId(),customThemes:Array.from(this.themes.entries()).filter(([t])=>!["default","modern"].includes(t))};return JSON.stringify(e,null,2)}importThemeConfig(e){return a(this,null,function*(){try{let t=JSON.parse(e);t.customThemes&&t.customThemes.forEach(([o,r])=>{this.addCustomTheme(r)}),t.theme&&(yield this.setTheme(t.theme)),t.themeId&&(yield this.setThemeId(t.themeId))}catch(t){throw console.error("Failed to import theme configuration:",t),new Error("Invalid theme configuration format")}})}generateCSSVariables(){let e=this.getCurrentThemeConfig();return e?` 2 :root { 3 --color-primary: ${e.primaryColor}; 4 --color-accent: ${e.accentColor}; 5 --color-background: ${e.backgroundColor}; 6 --color-surface: ${e.surfaceColor}; 7 --color-text: ${e.textColor}; 8 --color-border: ${e.borderColor}; 9 } 10 `:""}
10autoDetectTheme(){let e=new Date().getHours();return e>=18||e<6?"dark":"light"}enableAutoThemeSchedule(){let e=()=>{let t=this.autoDetectTheme();t!==this.currentColorScheme()&&this.setTheme(t)};setInterval(e,60*60*1e3),e()}static{this.\u0275fac=function(t){return new(t||h)(m(g),m(A))}}static{this.\u0275prov=f({token:h,factory:h.\u0275fac,providedIn:"root"})}}return h})();export{V as a};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.