@@ -160,7 +160,7 @@
font-family: monospace;
margin-right: 4px;
}
- `,document.head.appendChild(t),document.body.appendChild(n),u=document.getElementById("quick-search-input"),l=document.getElementById("quick-search-results"),u.addEventListener("input",r),u.addEventListener("keydown",w),n.addEventListener("click",e=>{e.target===n&&p()})}function q(t){try{if((t.ctrlKey||t.metaKey)&&t.key==="k"){t.preventDefault(),g();return}if(t.key==="Escape"){if(n&&n.classList.contains("show")){p();return}a()}}catch(e){console.warn("[Keyboard Shortcuts] Error handling keydown:",e.message)}}function g(){try{n.classList.add("show"),u.value="",u.focus(),c()}catch(t){console.warn("[Keyboard Shortcuts] Error opening quick search:",t.message)}}function p(){try{n.classList.remove("show"),u.value="",l.innerHTML=""}catch(t){console.warn("[Keyboard Shortcuts] Error closing quick search:",t.message)}}function a(){for(const t of k){const e=document.querySelector(t);if(e&&(e.classList.contains("show")||e.style.display==="flex"))return e.classList.remove("show"),e.style.display="none",!0}return!1}function c(){const t=`
+ `,document.head.appendChild(t),document.body.appendChild(n),u=document.getElementById("quick-search-input"),l=document.getElementById("quick-search-results"),u.addEventListener("input",h),u.addEventListener("keydown",v),n.addEventListener("click",e=>{e.target===n&&a()})}function b(t){try{if((t.ctrlKey||t.metaKey)&&t.key==="k"){t.preventDefault(),k();return}if(t.key==="Escape"){if(n&&n.classList.contains("show")){a();return}c()}}catch(e){console.warn("[Keyboard Shortcuts] Error handling keydown:",e.message)}}function k(){try{n.classList.add("show"),u.value="",u.focus(),i()}catch(t){console.warn("[Keyboard Shortcuts] Error opening quick search:",t.message)}}function a(){try{n.classList.remove("show"),u.value="",l.innerHTML=""}catch(t){console.warn("[Keyboard Shortcuts] Error closing quick search:",t.message)}}function c(){for(const t of y){const e=document.querySelector(t);if(e&&(e.classList.contains("show")||e.style.display==="flex"))return e.classList.remove("show"),e.style.display="none",!0}return!1}function i(){const t=`
- ${i()}
- `;l.innerHTML=t,y()}function i(){const t=document.querySelectorAll(".card[data-app], #cards .card");let e="";return t.forEach(s=>{const d=s.querySelector(".name")?.textContent||"Unknown",o=s.dataset.status||"unknown",b=s.dataset.app||"";d&&d!=="--"&&(e+=`
-
+ ${r()}
+ `;l.innerHTML=t,f()}function r(){const t=document.querySelectorAll(".card[data-app], #cards .card");let e="";return t.forEach(s=>{const d=s.querySelector(".name")?.textContent||"Unknown",o=s.dataset.status||"unknown",g=s.dataset.app||"";d&&d!=="--"&&(e+=`
+
${o==="on"?"\u{1F7E2}":"\u{1F534}"}
${o.toUpperCase()}
- `)}),e||'
No services found
'}function r(t){try{const e=t.target.value.toLowerCase().trim();if(!e){c();return}const s=h(e);S(s)}catch(e){console.warn("[Keyboard Shortcuts] Error handling search input:",e.message)}}function h(t){const e={actions:[],services:[]};return[{id:"refresh",title:"Refresh Dashboard",icon:"\u{1F504}",keywords:"refresh reload update status"},{id:"reload-caddy",title:"Reload Caddy",icon:"\u26A1",keywords:"reload caddy proxy config"},{id:"add-service",title:"Add Service",icon:"\u2795",keywords:"add new service create"},{id:"app-selector",title:"App Selector",icon:"\u{1F4F1}",keywords:"app deploy install docker container"},{id:"backup",title:"Backup & Restore",icon:"\u{1F4BE}",keywords:"backup restore export import"},{id:"stats",title:"Container Stats",icon:"\u{1F4CA}",keywords:"stats resources cpu memory"},{id:"logs",title:"View Logs",icon:"\u{1F4CB}",keywords:"logs error debug"},{id:"tokens",title:"Manage Tokens",icon:"\u{1F511}",keywords:"tokens api keys credentials"},{id:"notifications",title:"Notifications",icon:"\u{1F514}",keywords:"alerts notifications discord telegram"},{id:"theme",title:"Change Theme",icon:"\u{1F3A8}",keywords:"theme dark light appearance"},{id:"tour",title:"Help Tour",icon:"\u{1F393}",keywords:"help tour guide onboarding"}].forEach(o=>{(o.title.toLowerCase().includes(t)||o.keywords.includes(t))&&e.actions.push(o)}),document.querySelectorAll(".card[data-app], #cards .card").forEach(o=>{const b=o.querySelector(".name")?.textContent||"",x=o.dataset.app||"",E=o.dataset.status||"unknown";(b.toLowerCase().includes(t)||x.toLowerCase().includes(t))&&e.services.push({id:x,title:b,status:E,icon:E==="on"?"\u{1F7E2}":"\u{1F534}"})}),e}function S(t){let e="";t.actions.length>0&&(e+='
Actions
',t.actions.forEach(s=>{e+=`
+ `)}),e||'
No services found
'}function h(t){try{const e=t.target.value.toLowerCase().trim();if(!e){i();return}const s=q(e);S(s)}catch(e){console.warn("[Keyboard Shortcuts] Error handling search input:",e.message)}}function q(t){const e={actions:[],services:[]};return[{id:"refresh",title:"Refresh Dashboard",icon:"\u{1F504}",keywords:"refresh reload update status"},{id:"reload-caddy",title:"Reload Caddy",icon:"\u26A1",keywords:"reload caddy proxy config"},{id:"add-service",title:"Add Service",icon:"\u2795",keywords:"add new service create"},{id:"app-selector",title:"App Selector",icon:"\u{1F4F1}",keywords:"app deploy install docker container"},{id:"backup",title:"Backup & Restore",icon:"\u{1F4BE}",keywords:"backup restore export import"},{id:"stats",title:"Container Stats",icon:"\u{1F4CA}",keywords:"stats resources cpu memory"},{id:"logs",title:"View Logs",icon:"\u{1F4CB}",keywords:"logs error debug"},{id:"tokens",title:"Manage Tokens",icon:"\u{1F511}",keywords:"tokens api keys credentials"},{id:"notifications",title:"Notifications",icon:"\u{1F514}",keywords:"alerts notifications discord telegram"},{id:"theme",title:"Change Theme",icon:"\u{1F3A8}",keywords:"theme dark light appearance"},{id:"tour",title:"Help Tour",icon:"\u{1F393}",keywords:"help tour guide onboarding"}].forEach(o=>{(o.title.toLowerCase().includes(t)||o.keywords.includes(t))&&e.actions.push(o)}),document.querySelectorAll(".card[data-app], #cards .card").forEach(o=>{const g=o.querySelector(".name")?.textContent||"",E=o.dataset.app||"",C=o.dataset.status||"unknown";(g.toLowerCase().includes(t)||E.toLowerCase().includes(t))&&e.services.push({id:E,title:g,status:C,icon:C==="on"?"\u{1F7E2}":"\u{1F534}"})}),e}function S(t){let e="";t.actions.length>0&&(e+='
Actions
',t.actions.forEach(s=>{e+=`
${s.icon}
@@ -217,4 +217,4 @@
${s.status.toUpperCase()}
- `})),e||(e='
No results found
'),l.innerHTML=e,y()}function y(){l.querySelectorAll(".quick-search-item").forEach((e,s)=>{e.addEventListener("click",()=>f(e)),s===0&&e.classList.add("selected")})}function w(t){try{const e=l.querySelectorAll(".quick-search-item"),s=l.querySelector(".quick-search-item.selected"),d=Array.from(e).indexOf(s);if(t.key==="ArrowDown"){t.preventDefault(),s&&s.classList.remove("selected");const o=(d+1)%e.length;e[o]?.classList.add("selected"),e[o]?.scrollIntoView({block:"nearest"})}else if(t.key==="ArrowUp"){t.preventDefault(),s&&s.classList.remove("selected");const o=d<=0?e.length-1:d-1;e[o]?.classList.add("selected"),e[o]?.scrollIntoView({block:"nearest"})}else t.key==="Enter"&&(t.preventDefault(),s&&f(s))}catch(e){console.warn("[Keyboard Shortcuts] Error handling search navigation:",e.message)}}function f(t){try{const e=t.dataset.action,s=t.dataset.service;switch(p(),e){case"refresh":document.getElementById("refresh")?.click();break;case"reload-caddy":document.getElementById("reload-caddy-top")?.click();break;case"add-service":document.getElementById("add-service")?.click();break;case"app-selector":document.getElementById("add-service-btn")?.click();break;case"backup":document.getElementById("backup-restore-btn")?.click();break;case"stats":document.getElementById("container-stats-btn")?.click();break;case"logs":document.getElementById("view-error-logs")?.click();break;case"tokens":document.getElementById("manage-tokens")?.click();break;case"notifications":document.getElementById("manage-notifications")?.click();break;case"theme":document.getElementById("theme")?.click();break;case"tour":document.getElementById("restart-tour-btn")?.click();break;case"open-service":if(s){const d=document.querySelector(`[data-app="${s}"] [id$="-open"], [data-app="${s}"] button:not(.restart-btn):not(.logs-btn):not(.settings-btn)`);if(d)d.click();else{const o=document.querySelector(`[data-app="${s}"]`);o&&o.click()}}break;default:console.log("[Keyboard Shortcuts] Unknown action:",e)}}catch(e){console.warn("[Keyboard Shortcuts] Error executing action:",e.message)}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",m):m(),window.DashCaddyKeyboardShortcuts={openQuickSearch:g,closeQuickSearch:p}})();
+ `})),e||(e='
No results found
'),l.innerHTML=e,f()}function f(){l.querySelectorAll(".quick-search-item").forEach((e,s)=>{e.addEventListener("click",()=>x(e)),s===0&&e.classList.add("selected")})}function v(t){try{const e=l.querySelectorAll(".quick-search-item"),s=l.querySelector(".quick-search-item.selected"),d=Array.from(e).indexOf(s);if(t.key==="ArrowDown"){t.preventDefault(),s&&s.classList.remove("selected");const o=(d+1)%e.length;e[o]?.classList.add("selected"),e[o]?.scrollIntoView({block:"nearest"})}else if(t.key==="ArrowUp"){t.preventDefault(),s&&s.classList.remove("selected");const o=d<=0?e.length-1:d-1;e[o]?.classList.add("selected"),e[o]?.scrollIntoView({block:"nearest"})}else t.key==="Enter"&&(t.preventDefault(),s&&x(s))}catch(e){console.warn("[Keyboard Shortcuts] Error handling search navigation:",e.message)}}function x(t){try{const e=t.dataset.action,s=t.dataset.service;switch(a(),e){case"refresh":document.getElementById("refresh")?.click();break;case"reload-caddy":document.getElementById("reload-caddy-top")?.click();break;case"add-service":document.getElementById("add-service")?.click();break;case"app-selector":document.getElementById("add-service-btn")?.click();break;case"backup":document.getElementById("backup-restore-btn")?.click();break;case"stats":document.getElementById("container-stats-btn")?.click();break;case"logs":document.getElementById("view-error-logs")?.click();break;case"tokens":document.getElementById("manage-tokens")?.click();break;case"notifications":document.getElementById("manage-notifications")?.click();break;case"theme":document.getElementById("theme")?.click();break;case"tour":document.getElementById("restart-tour-btn")?.click();break;case"open-service":if(s){const d=document.querySelector(`[data-app="${s}"] [id$="-open"], [data-app="${s}"] button:not(.restart-btn):not(.logs-btn):not(.settings-btn)`);if(d)d.click();else{const o=document.querySelector(`[data-app="${s}"]`);o&&o.click()}}break;default:p("[Keyboard Shortcuts] Unknown action:",e)}}catch(e){console.warn("[Keyboard Shortcuts] Error executing action:",e.message)}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",m):m(),window.DashCaddyKeyboardShortcuts={openQuickSearch:k,closeQuickSearch:a}})();
diff --git a/status/dist/onboarding.js b/status/dist/onboarding.js
index eca6a29..5771f91 100644
--- a/status/dist/onboarding.js
+++ b/status/dist/onboarding.js
@@ -1,5 +1,5 @@
-this.driver=this.driver||{},this.driver.js=(function(v){"use strict";let T={};function P(o={}){T={animate:!0,allowClose:!0,overlayOpacity:.7,smoothScroll:!1,disableActiveInteraction:!1,showProgress:!1,stagePadding:10,stageRadius:5,popoverOffset:10,showButtons:["next","previous","close"],disableButtons:[],overlayColor:"#000",...o}}function e(o){return o?T[o]:T}function t(o,r,n,s){return(o/=s/2)<1?n/2*o*o+r:-n/2*(--o*(o-2)-1)+r}function a(o){const r='a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])';return o.flatMap(n=>{const s=n.matches(r),i=Array.from(n.querySelectorAll(r));return[...s?[n]:[],...i]}).filter(n=>getComputedStyle(n).pointerEvents!=="none"&&A(n))}function p(o){if(!o||m(o))return;const r=e("smoothScroll");o.scrollIntoView({behavior:!r||y(o)?"auto":"smooth",inline:"center",block:"center"})}function y(o){if(!o||!o.parentElement)return;const r=o.parentElement;return r.scrollHeight>r.clientHeight}function m(o){const r=o.getBoundingClientRect();return r.top>=0&&r.left>=0&&r.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&r.right<=(window.innerWidth||document.documentElement.clientWidth)}function A(o){return!!(o.offsetWidth||o.offsetHeight||o.getClientRects().length)}let L={};function E(o,r){L[o]=r}function d(o){return o?L[o]:L}function K(){L={}}let F={};function R(o,r){F[o]=r}function O(o){var r;(r=F[o])==null||r.call(F)}function se(){F={}}function ae(o,r,n,s){let i=d("__activeStagePosition");const u=i||n.getBoundingClientRect(),b=s.getBoundingClientRect(),S=t(o,u.x,b.x-u.x,r),c=t(o,u.y,b.y-u.y,r),w=t(o,u.width,b.width-u.width,r),l=t(o,u.height,b.height-u.height,r);i={x:S,y:c,width:w,height:l},J(i),E("__activeStagePosition",i)}function Y(o){if(!o)return;const r=o.getBoundingClientRect(),n={x:r.x,y:r.y,width:r.width,height:r.height};E("__activeStagePosition",n),J(n)}function le(){const o=d("__activeStagePosition"),r=d("__overlaySvg");if(!o)return;if(!r){console.warn("No stage svg found.");return}const n=window.innerWidth,s=window.innerHeight;r.setAttribute("viewBox",`0 0 ${n} ${s}`)}function de(o){const r=ce(o);document.body.appendChild(r),ee(r,n=>{n.target.tagName==="path"&&O("overlayClick")}),E("__overlaySvg",r)}function J(o){const r=d("__overlaySvg");if(!r){de(o);return}const n=r.firstElementChild;if(n?.tagName!=="path")throw new Error("no path element found in stage svg");n.setAttribute("d",Q(o))}function ce(o){const r=window.innerWidth,n=window.innerHeight,s=document.createElementNS("http://www.w3.org/2000/svg","svg");s.classList.add("driver-overlay","driver-overlay-animated"),s.setAttribute("viewBox",`0 0 ${r} ${n}`),s.setAttribute("xmlSpace","preserve"),s.setAttribute("xmlnsXlink","http://www.w3.org/1999/xlink"),s.setAttribute("version","1.1"),s.setAttribute("preserveAspectRatio","xMinYMin slice"),s.style.fillRule="evenodd",s.style.clipRule="evenodd",s.style.strokeLinejoin="round",s.style.strokeMiterlimit="2",s.style.zIndex="10000",s.style.position="fixed",s.style.top="0",s.style.left="0",s.style.width="100%",s.style.height="100%";const i=document.createElementNS("http://www.w3.org/2000/svg","path");return i.setAttribute("d",Q(o)),i.style.fill=e("overlayColor")||"rgb(0,0,0)",i.style.opacity=`${e("overlayOpacity")}`,i.style.pointerEvents="auto",i.style.cursor="auto",s.appendChild(i),s}function Q(o){const r=window.innerWidth,n=window.innerHeight,s=e("stagePadding")||0,i=e("stageRadius")||0,u=o.width+s*2,b=o.height+s*2,S=Math.min(i,u/2,b/2),c=Math.floor(Math.max(S,0)),w=o.x-s+c,l=o.y-s,h=u-c*2,g=b-c*2;return`M${r},0L0,0L0,${n}L${r},${n}L${r},0Z
- M${w},${l} h${h} a${c},${c} 0 0 1 ${c},${c} v${g} a${c},${c} 0 0 1 -${c},${c} h-${h} a${c},${c} 0 0 1 -${c},-${c} v-${g} a${c},${c} 0 0 1 ${c},-${c} z`}function pe(){const o=d("__overlaySvg");o&&o.remove()}function ue(){const o=document.getElementById("driver-dummy-element");if(o)return o;let r=document.createElement("div");return r.id="driver-dummy-element",r.style.width="0",r.style.height="0",r.style.pointerEvents="none",r.style.opacity="0",r.style.position="fixed",r.style.top="50%",r.style.left="50%",document.body.appendChild(r),r}function X(o){const{element:r}=o;let n=typeof r=="string"?document.querySelector(r):r;n||(n=ue()),he(n,o)}function me(){const o=d("__activeElement"),r=d("__activeStep");o&&(Y(o),le(),ne(o,r))}function he(o,r){const n=Date.now(),s=d("__activeStep"),i=d("__activeElement")||o,u=!i||i===o,b=o.id==="driver-dummy-element",S=i.id==="driver-dummy-element",c=e("animate"),w=r.onHighlightStarted||e("onHighlightStarted"),l=r?.onHighlighted||e("onHighlighted"),h=s?.onDeselected||e("onDeselected"),g=e(),C=d();!u&&h&&h(S?void 0:i,s,{config:g,state:C}),w&&w(b?void 0:o,r,{config:g,state:C});const k=!u&&c;let x=!1;we(),E("previousStep",s),E("previousElement",i),E("activeStep",r),E("activeElement",o);const f=()=>{if(d("__transitionCallback")!==f)return;const D=Date.now()-n,B=400-D<=400/2;r.popover&&B&&!x&&k&&(te(o,r),x=!0),e("animate")&&D<400?ae(D,400,i,o):(Y(o),l&&l(b?void 0:o,r,{config:e(),state:d()}),E("__transitionCallback",void 0),E("__previousStep",s),E("__previousElement",i),E("__activeStep",r),E("__activeElement",o)),window.requestAnimationFrame(f)};E("__transitionCallback",f),window.requestAnimationFrame(f),p(o),!k&&r.popover&&te(o,r),i.classList.remove("driver-active-element","driver-no-interaction"),i.removeAttribute("aria-haspopup"),i.removeAttribute("aria-expanded"),i.removeAttribute("aria-controls"),e("disableActiveInteraction")&&o.classList.add("driver-no-interaction"),o.classList.add("driver-active-element"),o.setAttribute("aria-haspopup","dialog"),o.setAttribute("aria-expanded","true"),o.setAttribute("aria-controls","driver-popover-content")}function ge(){var o;(o=document.getElementById("driver-dummy-element"))==null||o.remove(),document.querySelectorAll(".driver-active-element").forEach(r=>{r.classList.remove("driver-active-element","driver-no-interaction"),r.removeAttribute("aria-haspopup"),r.removeAttribute("aria-expanded"),r.removeAttribute("aria-controls")})}function z(){const o=d("__resizeTimeout");o&&window.cancelAnimationFrame(o),E("__resizeTimeout",window.requestAnimationFrame(me))}function ve(o){var r;if(!d("isInitialized")||!(o.key==="Tab"||o.keyCode===9))return;const n=d("__activeElement"),s=(r=d("popover"))==null?void 0:r.wrapper,i=a([...s?[s]:[],...n?[n]:[]]),u=i[0],b=i[i.length-1];if(o.preventDefault(),o.shiftKey){const S=i[i.indexOf(document.activeElement)-1]||b;S?.focus()}else{const S=i[i.indexOf(document.activeElement)+1]||u;S?.focus()}}function Z(o){var r;((r=e("allowKeyboardControl"))==null||r)&&(o.key==="Escape"?O("escapePress"):o.key==="ArrowRight"?O("arrowRightPress"):o.key==="ArrowLeft"&&O("arrowLeftPress"))}function ee(o,r,n){const s=(i,u)=>{const b=i.target;o.contains(b)&&((!n||n(b))&&(i.preventDefault(),i.stopPropagation(),i.stopImmediatePropagation()),u?.(i))};document.addEventListener("pointerdown",s,!0),document.addEventListener("mousedown",s,!0),document.addEventListener("pointerup",s,!0),document.addEventListener("mouseup",s,!0),document.addEventListener("click",i=>{s(i,r)},!0)}function fe(){window.addEventListener("keyup",Z,!1),window.addEventListener("keydown",ve,!1),window.addEventListener("resize",z),window.addEventListener("scroll",z)}function ye(){window.removeEventListener("keyup",Z),window.removeEventListener("resize",z),window.removeEventListener("scroll",z)}function we(){const o=d("popover");o&&(o.wrapper.style.display="none")}function te(o,r){var n,s;let i=d("popover");i&&document.body.removeChild(i.wrapper),i=Te(),document.body.appendChild(i.wrapper);const{title:u,description:b,showButtons:S,disableButtons:c,showProgress:w,nextBtnText:l=e("nextBtnText")||"Next →",prevBtnText:h=e("prevBtnText")||"← Previous",progressText:g=e("progressText")||"{current} of {total}"}=r.popover||{};i.nextButton.innerHTML=l,i.previousButton.innerHTML=h,i.progress.innerHTML=g,u?(i.title.innerHTML=u,i.title.style.display="block"):i.title.style.display="none",b?(i.description.innerHTML=b,i.description.style.display="block"):i.description.style.display="none";const C=S||e("showButtons"),k=w||e("showProgress")||!1,x=C?.includes("next")||C?.includes("previous")||k;i.closeButton.style.display=C.includes("close")?"block":"none",x?(i.footer.style.display="flex",i.progress.style.display=k?"block":"none",i.nextButton.style.display=C.includes("next")?"block":"none",i.previousButton.style.display=C.includes("previous")?"block":"none"):i.footer.style.display="none";const f=c||e("disableButtons")||[];f!=null&&f.includes("next")&&(i.nextButton.disabled=!0,i.nextButton.classList.add("driver-popover-btn-disabled")),f!=null&&f.includes("previous")&&(i.previousButton.disabled=!0,i.previousButton.classList.add("driver-popover-btn-disabled")),f!=null&&f.includes("close")&&(i.closeButton.disabled=!0,i.closeButton.classList.add("driver-popover-btn-disabled"));const D=i.wrapper;D.style.display="block",D.style.left="",D.style.top="",D.style.bottom="",D.style.right="",D.id="driver-popover-content",D.setAttribute("role","dialog"),D.setAttribute("aria-labelledby","driver-popover-title"),D.setAttribute("aria-describedby","driver-popover-description");const B=i.arrow;B.className="driver-popover-arrow";const $=((n=r.popover)==null?void 0:n.popoverClass)||e("popoverClass")||"";D.className=`driver-popover ${$}`.trim(),ee(i.wrapper,M=>{var W,U,j;const H=M.target,V=((W=r.popover)==null?void 0:W.onNextClick)||e("onNextClick"),q=((U=r.popover)==null?void 0:U.onPrevClick)||e("onPrevClick"),G=((j=r.popover)==null?void 0:j.onCloseClick)||e("onCloseClick");if(H.classList.contains("driver-popover-next-btn"))return V?V(o,r,{config:e(),state:d()}):O("nextClick");if(H.classList.contains("driver-popover-prev-btn"))return q?q(o,r,{config:e(),state:d()}):O("prevClick");if(H.classList.contains("driver-popover-close-btn"))return G?G(o,r,{config:e(),state:d()}):O("closeClick")},M=>!(i!=null&&i.description.contains(M))&&!(i!=null&&i.title.contains(M))&&typeof M.className=="string"&&M.className.includes("driver-popover")),E("popover",i);const _=((s=r.popover)==null?void 0:s.onPopoverRender)||e("onPopoverRender");_&&_(i,{config:e(),state:d()}),ne(o,r),p(D);const I=o.classList.contains("driver-dummy-element"),N=a([D,...I?[]:[o]]);N.length>0&&N[0].focus()}function oe(){const o=d("popover");if(!(o!=null&&o.wrapper))return;const r=o.wrapper.getBoundingClientRect(),n=e("stagePadding")||0,s=e("popoverOffset")||0;return{width:r.width+n+s,height:r.height+n+s,realWidth:r.width,realHeight:r.height}}function re(o,r){const{elementDimensions:n,popoverDimensions:s,popoverPadding:i,popoverArrowDimensions:u}=r;return o==="start"?Math.max(Math.min(n.top-i,window.innerHeight-s.realHeight-u.width),u.width):o==="end"?Math.max(Math.min(n.top-s?.realHeight+n.height+i,window.innerHeight-s?.realHeight-u.width),u.width):o==="center"?Math.max(Math.min(n.top+n.height/2-s?.realHeight/2,window.innerHeight-s?.realHeight-u.width),u.width):0}function ie(o,r){const{elementDimensions:n,popoverDimensions:s,popoverPadding:i,popoverArrowDimensions:u}=r;return o==="start"?Math.max(Math.min(n.left-i,window.innerWidth-s.realWidth-u.width),u.width):o==="end"?Math.max(Math.min(n.left-s?.realWidth+n.width+i,window.innerWidth-s?.realWidth-u.width),u.width):o==="center"?Math.max(Math.min(n.left+n.width/2-s?.realWidth/2,window.innerWidth-s?.realWidth-u.width),u.width):0}function ne(o,r){const n=d("popover");if(!n)return;const{align:s="start",side:i="left"}=r?.popover||{},u=s,b=o.id==="driver-dummy-element"?"over":i,S=e("stagePadding")||0,c=oe(),w=n.arrow.getBoundingClientRect(),l=o.getBoundingClientRect(),h=l.top-c.height;let g=h>=0;const C=window.innerHeight-(l.bottom+c.height);let k=C>=0;const x=l.left-c.width;let f=x>=0;const D=window.innerWidth-(l.right+c.width);let B=D>=0;const $=!g&&!k&&!f&&!B;let _=b;if(b==="top"&&g?B=f=k=!1:b==="bottom"&&k?B=f=g=!1:b==="left"&&f?B=g=k=!1:b==="right"&&B&&(f=g=k=!1),b==="over"){const I=window.innerWidth/2-c.realWidth/2,N=window.innerHeight/2-c.realHeight/2;n.wrapper.style.left=`${I}px`,n.wrapper.style.right="auto",n.wrapper.style.top=`${N}px`,n.wrapper.style.bottom="auto"}else if($){const I=window.innerWidth/2-c?.realWidth/2,N=10;n.wrapper.style.left=`${I}px`,n.wrapper.style.right="auto",n.wrapper.style.bottom=`${N}px`,n.wrapper.style.top="auto"}else if(f){const I=Math.min(x,window.innerWidth-c?.realWidth-w.width),N=re(u,{elementDimensions:l,popoverDimensions:c,popoverPadding:S,popoverArrowDimensions:w});n.wrapper.style.left=`${I}px`,n.wrapper.style.top=`${N}px`,n.wrapper.style.bottom="auto",n.wrapper.style.right="auto",_="left"}else if(B){const I=Math.min(D,window.innerWidth-c?.realWidth-w.width),N=re(u,{elementDimensions:l,popoverDimensions:c,popoverPadding:S,popoverArrowDimensions:w});n.wrapper.style.right=`${I}px`,n.wrapper.style.top=`${N}px`,n.wrapper.style.bottom="auto",n.wrapper.style.left="auto",_="right"}else if(g){const I=Math.min(h,window.innerHeight-c.realHeight-w.width);let N=ie(u,{elementDimensions:l,popoverDimensions:c,popoverPadding:S,popoverArrowDimensions:w});n.wrapper.style.top=`${I}px`,n.wrapper.style.left=`${N}px`,n.wrapper.style.bottom="auto",n.wrapper.style.right="auto",_="top"}else if(k){const I=Math.min(C,window.innerHeight-c?.realHeight-w.width);let N=ie(u,{elementDimensions:l,popoverDimensions:c,popoverPadding:S,popoverArrowDimensions:w});n.wrapper.style.left=`${N}px`,n.wrapper.style.bottom=`${I}px`,n.wrapper.style.top="auto",n.wrapper.style.right="auto",_="bottom"}$?n.arrow.classList.add("driver-popover-arrow-none"):be(u,_,o)}function be(o,r,n){const s=d("popover");if(!s)return;const i=n.getBoundingClientRect(),u=oe(),b=s.arrow,S=u.width,c=window.innerWidth,w=i.width,l=i.left,h=u.height,g=window.innerHeight,C=i.top,k=i.height;b.className="driver-popover-arrow";let x=r,f=o;r==="top"?(l+w<=0?(x="right",f="end"):l+w-S<=0&&(x="top",f="start"),l>=c?(x="left",f="end"):l+S>=c&&(x="top",f="end")):r==="bottom"?(l+w<=0?(x="right",f="start"):l+w-S<=0&&(x="bottom",f="start"),l>=c?(x="left",f="start"):l+S>=c&&(x="bottom",f="end")):r==="left"?(C+k<=0?(x="bottom",f="end"):C+k-h<=0&&(x="left",f="start"),C>=g?(x="top",f="end"):C+h>=g&&(x="left",f="end")):r==="right"&&(C+k<=0?(x="bottom",f="start"):C+k-h<=0&&(x="right",f="start"),C>=g?(x="top",f="start"):C+h>=g&&(x="right",f="end")),x?(b.classList.add(`driver-popover-arrow-side-${x}`),b.classList.add(`driver-popover-arrow-align-${f}`)):b.classList.add("driver-popover-arrow-none")}function Te(){const o=document.createElement("div");o.classList.add("driver-popover");const r=document.createElement("div");r.classList.add("driver-popover-arrow");const n=document.createElement("header");n.id="driver-popover-title",n.classList.add("driver-popover-title"),n.style.display="none",n.innerText="Popover Title";const s=document.createElement("div");s.id="driver-popover-description",s.classList.add("driver-popover-description"),s.style.display="none",s.innerText="Popover description is here";const i=document.createElement("button");i.type="button",i.classList.add("driver-popover-close-btn"),i.setAttribute("aria-label","Close"),i.innerHTML="×";const u=document.createElement("footer");u.classList.add("driver-popover-footer");const b=document.createElement("span");b.classList.add("driver-popover-progress-text"),b.innerText="";const S=document.createElement("span");S.classList.add("driver-popover-navigation-btns");const c=document.createElement("button");c.type="button",c.classList.add("driver-popover-prev-btn"),c.innerHTML="← Previous";const w=document.createElement("button");return w.type="button",w.classList.add("driver-popover-next-btn"),w.innerHTML="Next →",S.appendChild(c),S.appendChild(w),u.appendChild(b),u.appendChild(S),o.appendChild(i),o.appendChild(r),o.appendChild(n),o.appendChild(s),o.appendChild(u),{wrapper:o,arrow:r,title:n,description:s,footer:u,previousButton:c,nextButton:w,closeButton:i,footerButtons:S,progress:b}}function Se(){var o;const r=d("popover");r&&((o=r.wrapper.parentElement)==null||o.removeChild(r.wrapper))}const Ee="";function Ce(o={}){P(o);function r(){e("allowClose")&&w()}function n(){const l=d("activeIndex"),h=e("steps")||[];if(typeof l>"u")return;const g=l+1;h[g]?c(g):w()}function s(){const l=d("activeIndex"),h=e("steps")||[];if(typeof l>"u")return;const g=l-1;h[g]?c(g):w()}function i(l){(e("steps")||[])[l]?c(l):w()}function u(){var l;if(d("__transitionCallback"))return;const h=d("activeIndex"),g=d("__activeStep"),C=d("__activeElement");if(typeof h>"u"||typeof g>"u"||typeof d("activeIndex")>"u")return;const k=((l=g.popover)==null?void 0:l.onPrevClick)||e("onPrevClick");if(k)return k(C,g,{config:e(),state:d()});s()}function b(){var l;if(d("__transitionCallback"))return;const h=d("activeIndex"),g=d("__activeStep"),C=d("__activeElement");if(typeof h>"u"||typeof g>"u")return;const k=((l=g.popover)==null?void 0:l.onNextClick)||e("onNextClick");if(k)return k(C,g,{config:e(),state:d()});n()}function S(){d("isInitialized")||(E("isInitialized",!0),document.body.classList.add("driver-active",e("animate")?"driver-fade":"driver-simple"),fe(),R("overlayClick",r),R("escapePress",r),R("arrowLeftPress",u),R("arrowRightPress",b))}function c(l=0){var h,g,C,k,x,f,D,B;const $=e("steps");if(!$){console.error("No steps to drive through"),w();return}if(!$[l]){w();return}E("__activeOnDestroyed",document.activeElement),E("activeIndex",l);const _=$[l],I=$[l+1],N=$[l-1],M=((h=_.popover)==null?void 0:h.doneBtnText)||e("doneBtnText")||"Done",W=e("allowClose"),U=typeof((g=_.popover)==null?void 0:g.showProgress)<"u"?(C=_.popover)==null?void 0:C.showProgress:e("showProgress"),j=(((k=_.popover)==null?void 0:k.progressText)||e("progressText")||"{{current}} of {{total}}").replace("{{current}}",`${l+1}`).replace("{{total}}",`${$.length}`),H=((x=_.popover)==null?void 0:x.showButtons)||e("showButtons"),V=["next","previous",...W?["close"]:[]].filter(ke=>!(H!=null&&H.length)||H.includes(ke)),q=((f=_.popover)==null?void 0:f.onNextClick)||e("onNextClick"),G=((D=_.popover)==null?void 0:D.onPrevClick)||e("onPrevClick"),xe=((B=_.popover)==null?void 0:B.onCloseClick)||e("onCloseClick");X({..._,popover:{showButtons:V,nextBtnText:I?void 0:M,disableButtons:[...N?[]:["previous"]],showProgress:U,progressText:j,onNextClick:q||(()=>{I?c(l+1):w()}),onPrevClick:G||(()=>{c(l-1)}),onCloseClick:xe||(()=>{w()}),..._?.popover||{}}})}function w(l=!0){const h=d("__activeElement"),g=d("__activeStep"),C=d("__activeOnDestroyed"),k=e("onDestroyStarted");if(l&&k){const D=!h||h?.id==="driver-dummy-element";k(D?void 0:h,g,{config:e(),state:d()});return}const x=g?.onDeselected||e("onDeselected"),f=e("onDestroyed");if(document.body.classList.remove("driver-active","driver-fade","driver-simple"),ye(),Se(),ge(),pe(),se(),K(),h&&g){const D=h.id==="driver-dummy-element";x&&x(D?void 0:h,g,{config:e(),state:d()}),f&&f(D?void 0:h,g,{config:e(),state:d()})}C&&C.focus()}return{isActive:()=>d("isInitialized")||!1,refresh:z,drive:(l=0)=>{S(),c(l)},setConfig:P,setSteps:l=>{K(),P({...e(),steps:l})},getConfig:e,getState:d,getActiveIndex:()=>d("activeIndex"),isFirstStep:()=>d("activeIndex")===0,isLastStep:()=>{const l=e("steps")||[],h=d("activeIndex");return h!==void 0&&h===l.length-1},getActiveStep:()=>d("activeStep"),getActiveElement:()=>d("activeElement"),getPreviousElement:()=>d("previousElement"),getPreviousStep:()=>d("previousStep"),moveNext:n,movePrevious:s,moveTo:i,hasNextStep:()=>{const l=e("steps")||[],h=d("activeIndex");return h!==void 0&&l[h+1]},hasPreviousStep:()=>{const l=e("steps")||[],h=d("activeIndex");return h!==void 0&&l[h-1]},highlight:l=>{S(),X({...l,popover:l.popover?{showButtons:[],showProgress:!1,progressText:"",...l.popover}:void 0})},destroy:()=>{w(!1)}}}return v.driver=Ce,Object.defineProperty(v,Symbol.toStringTag,{value:"Module"}),v})({}),(function(v){"use strict";class T{constructor(){this.errors=[],this.maxErrors=50}logError(e,t,a={}){const p={timestamp:new Date().toISOString(),context:e,message:t instanceof Error?t.message:t,stack:t instanceof Error?t.stack:null,metadata:a};this.errors.push(p),this.errors.length>this.maxErrors&&this.errors.shift(),console.error(`[Onboarding Error] ${e}:`,t,a)}recoverFromError(e,t){switch(this.classifyError(e)){case"ELEMENT_NOT_FOUND":return this.logError("Element Not Found",e,{currentStep:t}),{action:"SKIP_STEP",nextStep:t+1,message:"Target element not found, skipping to next step"};case"STORAGE_UNAVAILABLE":return this.logError("Storage Unavailable",e),{action:"USE_MEMORY_STORAGE",message:"Local storage unavailable, using in-memory storage"};case"DRIVER_NOT_LOADED":return this.logError("Driver.js Not Loaded",e),{action:"ABORT_TOUR",message:"Driver.js library not loaded, cannot start tour"};case"INVALID_TOOLTIP":return this.logError("Invalid Tooltip Configuration",e,{currentStep:t}),{action:"SKIP_STEP",nextStep:t+1,message:"Invalid tooltip configuration, skipping"};case"THEME_DETECTION_FAILED":return this.logError("Theme Detection Failed",e),{action:"USE_DEFAULT_THEME",message:"Using default dark theme"};default:return this.logError("Unknown Error",e,{currentStep:t}),{action:"ABORT_TOUR",message:"Unexpected error occurred, aborting tour"}}}classifyError(e){const t=e.message||e.toString();return t.includes("element")&&t.includes("not found")?"ELEMENT_NOT_FOUND":t.includes("storage")||t.includes("quota")?"STORAGE_UNAVAILABLE":t.includes("driver")||t.includes("undefined")?"DRIVER_NOT_LOADED":t.includes("invalid")||t.includes("validation")?"INVALID_TOOLTIP":t.includes("theme")?"THEME_DETECTION_FAILED":"UNKNOWN"}getErrors(){return[...this.errors]}clearErrors(){this.errors=[]}getStatistics(){const e={total:this.errors.length,byContext:{},byType:{},recent:this.errors.slice(-10)};return this.errors.forEach(t=>{e.byContext[t.context]=(e.byContext[t.context]||0)+1;const a=this.classifyError({message:t.message});e.byType[a]=(e.byType[a]||0)+1}),e}handleDriverLoadFailure(){this.logError("Driver.js Load Failure","Driver.js library failed to load");const e=document.createElement("div");return e.id="onboarding-fallback",e.style.cssText=`
+this.driver=this.driver||{},this.driver.js=(function(v){"use strict";let b={};function k(e={}){b={animate:!0,allowClose:!0,overlayOpacity:.7,smoothScroll:!1,disableActiveInteraction:!1,showProgress:!1,stagePadding:10,stageRadius:5,popoverOffset:10,showButtons:["next","previous","close"],disableButtons:[],overlayColor:"#000",...e}}function o(e){return e?b[e]:b}function s(e,r,n,l){return(e/=l/2)<1?n/2*e*e+r:-n/2*(--e*(e-2)-1)+r}function t(e){const r='a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])';return e.flatMap(n=>{const l=n.matches(r),i=Array.from(n.querySelectorAll(r));return[...l?[n]:[],...i]}).filter(n=>getComputedStyle(n).pointerEvents!=="none"&&T(n))}function a(e){if(!e||h(e))return;const r=o("smoothScroll");e.scrollIntoView({behavior:!r||d(e)?"auto":"smooth",inline:"center",block:"center"})}function d(e){if(!e||!e.parentElement)return;const r=e.parentElement;return r.scrollHeight>r.clientHeight}function h(e){const r=e.getBoundingClientRect();return r.top>=0&&r.left>=0&&r.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&r.right<=(window.innerWidth||document.documentElement.clientWidth)}function T(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}let c={};function x(e,r){c[e]=r}function p(e){return e?c[e]:c}function B(){c={}}let R={};function U(e,r){R[e]=r}function H(e){var r;(r=R[e])==null||r.call(R)}function se(){R={}}function ae(e,r,n,l){let i=p("__activeStagePosition");const g=i||n.getBoundingClientRect(),C=l.getBoundingClientRect(),E=s(e,g.x,C.x-g.x,r),m=s(e,g.y,C.y-g.y,r),S=s(e,g.width,C.width-g.width,r),u=s(e,g.height,C.height-g.height,r);i={x:E,y:m,width:S,height:u},J(i),x("__activeStagePosition",i)}function K(e){if(!e)return;const r=e.getBoundingClientRect(),n={x:r.x,y:r.y,width:r.width,height:r.height};x("__activeStagePosition",n),J(n)}function le(){const e=p("__activeStagePosition"),r=p("__overlaySvg");if(!e)return;if(!r){console.warn("No stage svg found.");return}const n=window.innerWidth,l=window.innerHeight;r.setAttribute("viewBox",`0 0 ${n} ${l}`)}function de(e){const r=pe(e);document.body.appendChild(r),ee(r,n=>{n.target.tagName==="path"&&H("overlayClick")}),x("__overlaySvg",r)}function J(e){const r=p("__overlaySvg");if(!r){de(e);return}const n=r.firstElementChild;if(n?.tagName!=="path")throw new Error("no path element found in stage svg");n.setAttribute("d",Q(e))}function pe(e){const r=window.innerWidth,n=window.innerHeight,l=document.createElementNS("http://www.w3.org/2000/svg","svg");l.classList.add("driver-overlay","driver-overlay-animated"),l.setAttribute("viewBox",`0 0 ${r} ${n}`),l.setAttribute("xmlSpace","preserve"),l.setAttribute("xmlnsXlink","http://www.w3.org/1999/xlink"),l.setAttribute("version","1.1"),l.setAttribute("preserveAspectRatio","xMinYMin slice"),l.style.fillRule="evenodd",l.style.clipRule="evenodd",l.style.strokeLinejoin="round",l.style.strokeMiterlimit="2",l.style.zIndex="10000",l.style.position="fixed",l.style.top="0",l.style.left="0",l.style.width="100%",l.style.height="100%";const i=document.createElementNS("http://www.w3.org/2000/svg","path");return i.setAttribute("d",Q(e)),i.style.fill=o("overlayColor")||"rgb(0,0,0)",i.style.opacity=`${o("overlayOpacity")}`,i.style.pointerEvents="auto",i.style.cursor="auto",l.appendChild(i),l}function Q(e){const r=window.innerWidth,n=window.innerHeight,l=o("stagePadding")||0,i=o("stageRadius")||0,g=e.width+l*2,C=e.height+l*2,E=Math.min(i,g/2,C/2),m=Math.floor(Math.max(E,0)),S=e.x-l+m,u=e.y-l,f=g-m*2,y=C-m*2;return`M${r},0L0,0L0,${n}L${r},${n}L${r},0Z
+ M${S},${u} h${f} a${m},${m} 0 0 1 ${m},${m} v${y} a${m},${m} 0 0 1 -${m},${m} h-${f} a${m},${m} 0 0 1 -${m},-${m} v-${y} a${m},${m} 0 0 1 ${m},-${m} z`}function ce(){const e=p("__overlaySvg");e&&e.remove()}function ue(){const e=document.getElementById("driver-dummy-element");if(e)return e;let r=document.createElement("div");return r.id="driver-dummy-element",r.style.width="0",r.style.height="0",r.style.pointerEvents="none",r.style.opacity="0",r.style.position="fixed",r.style.top="50%",r.style.left="50%",document.body.appendChild(r),r}function X(e){const{element:r}=e;let n=typeof r=="string"?document.querySelector(r):r;n||(n=ue()),he(n,e)}function me(){const e=p("__activeElement"),r=p("__activeStep");e&&(K(e),le(),ne(e,r))}function he(e,r){const n=Date.now(),l=p("__activeStep"),i=p("__activeElement")||e,g=!i||i===e,C=e.id==="driver-dummy-element",E=i.id==="driver-dummy-element",m=o("animate"),S=r.onHighlightStarted||o("onHighlightStarted"),u=r?.onHighlighted||o("onHighlighted"),f=l?.onDeselected||o("onDeselected"),y=o(),D=p();!g&&f&&f(E?void 0:i,l,{config:y,state:D}),S&&S(C?void 0:e,r,{config:y,state:D});const _=!g&&m;let A=!1;we(),x("previousStep",l),x("previousElement",i),x("activeStep",r),x("activeElement",e);const w=()=>{if(p("__transitionCallback")!==w)return;const P=Date.now()-n,$=400-P<=400/2;r.popover&&$&&!A&&_&&(te(e,r),A=!0),o("animate")&&P<400?ae(P,400,i,e):(K(e),u&&u(C?void 0:e,r,{config:o(),state:p()}),x("__transitionCallback",void 0),x("__previousStep",l),x("__previousElement",i),x("__activeStep",r),x("__activeElement",e)),window.requestAnimationFrame(w)};x("__transitionCallback",w),window.requestAnimationFrame(w),a(e),!_&&r.popover&&te(e,r),i.classList.remove("driver-active-element","driver-no-interaction"),i.removeAttribute("aria-haspopup"),i.removeAttribute("aria-expanded"),i.removeAttribute("aria-controls"),o("disableActiveInteraction")&&e.classList.add("driver-no-interaction"),e.classList.add("driver-active-element"),e.setAttribute("aria-haspopup","dialog"),e.setAttribute("aria-expanded","true"),e.setAttribute("aria-controls","driver-popover-content")}function ge(){var e;(e=document.getElementById("driver-dummy-element"))==null||e.remove(),document.querySelectorAll(".driver-active-element").forEach(r=>{r.classList.remove("driver-active-element","driver-no-interaction"),r.removeAttribute("aria-haspopup"),r.removeAttribute("aria-expanded"),r.removeAttribute("aria-controls")})}function F(){const e=p("__resizeTimeout");e&&window.cancelAnimationFrame(e),x("__resizeTimeout",window.requestAnimationFrame(me))}function ve(e){var r;if(!p("isInitialized")||!(e.key==="Tab"||e.keyCode===9))return;const n=p("__activeElement"),l=(r=p("popover"))==null?void 0:r.wrapper,i=t([...l?[l]:[],...n?[n]:[]]),g=i[0],C=i[i.length-1];if(e.preventDefault(),e.shiftKey){const E=i[i.indexOf(document.activeElement)-1]||C;E?.focus()}else{const E=i[i.indexOf(document.activeElement)+1]||g;E?.focus()}}function Z(e){var r;((r=o("allowKeyboardControl"))==null||r)&&(e.key==="Escape"?H("escapePress"):e.key==="ArrowRight"?H("arrowRightPress"):e.key==="ArrowLeft"&&H("arrowLeftPress"))}function ee(e,r,n){const l=(i,g)=>{const C=i.target;e.contains(C)&&((!n||n(C))&&(i.preventDefault(),i.stopPropagation(),i.stopImmediatePropagation()),g?.(i))};document.addEventListener("pointerdown",l,!0),document.addEventListener("mousedown",l,!0),document.addEventListener("pointerup",l,!0),document.addEventListener("mouseup",l,!0),document.addEventListener("click",i=>{l(i,r)},!0)}function fe(){window.addEventListener("keyup",Z,!1),window.addEventListener("keydown",ve,!1),window.addEventListener("resize",F),window.addEventListener("scroll",F)}function ye(){window.removeEventListener("keyup",Z),window.removeEventListener("resize",F),window.removeEventListener("scroll",F)}function we(){const e=p("popover");e&&(e.wrapper.style.display="none")}function te(e,r){var n,l;let i=p("popover");i&&document.body.removeChild(i.wrapper),i=Te(),document.body.appendChild(i.wrapper);const{title:g,description:C,showButtons:E,disableButtons:m,showProgress:S,nextBtnText:u=o("nextBtnText")||"Next →",prevBtnText:f=o("prevBtnText")||"← Previous",progressText:y=o("progressText")||"{current} of {total}"}=r.popover||{};i.nextButton.innerHTML=u,i.previousButton.innerHTML=f,i.progress.innerHTML=y,g?(i.title.innerHTML=g,i.title.style.display="block"):i.title.style.display="none",C?(i.description.innerHTML=C,i.description.style.display="block"):i.description.style.display="none";const D=E||o("showButtons"),_=S||o("showProgress")||!1,A=D?.includes("next")||D?.includes("previous")||_;i.closeButton.style.display=D.includes("close")?"block":"none",A?(i.footer.style.display="flex",i.progress.style.display=_?"block":"none",i.nextButton.style.display=D.includes("next")?"block":"none",i.previousButton.style.display=D.includes("previous")?"block":"none"):i.footer.style.display="none";const w=m||o("disableButtons")||[];w!=null&&w.includes("next")&&(i.nextButton.disabled=!0,i.nextButton.classList.add("driver-popover-btn-disabled")),w!=null&&w.includes("previous")&&(i.previousButton.disabled=!0,i.previousButton.classList.add("driver-popover-btn-disabled")),w!=null&&w.includes("close")&&(i.closeButton.disabled=!0,i.closeButton.classList.add("driver-popover-btn-disabled"));const P=i.wrapper;P.style.display="block",P.style.left="",P.style.top="",P.style.bottom="",P.style.right="",P.id="driver-popover-content",P.setAttribute("role","dialog"),P.setAttribute("aria-labelledby","driver-popover-title"),P.setAttribute("aria-describedby","driver-popover-description");const $=i.arrow;$.className="driver-popover-arrow";const M=((n=r.popover)==null?void 0:n.popoverClass)||o("popoverClass")||"";P.className=`driver-popover ${M}`.trim(),ee(i.wrapper,O=>{var W,j,V;const z=O.target,G=((W=r.popover)==null?void 0:W.onNextClick)||o("onNextClick"),q=((j=r.popover)==null?void 0:j.onPrevClick)||o("onPrevClick"),Y=((V=r.popover)==null?void 0:V.onCloseClick)||o("onCloseClick");if(z.classList.contains("driver-popover-next-btn"))return G?G(e,r,{config:o(),state:p()}):H("nextClick");if(z.classList.contains("driver-popover-prev-btn"))return q?q(e,r,{config:o(),state:p()}):H("prevClick");if(z.classList.contains("driver-popover-close-btn"))return Y?Y(e,r,{config:o(),state:p()}):H("closeClick")},O=>!(i!=null&&i.description.contains(O))&&!(i!=null&&i.title.contains(O))&&typeof O.className=="string"&&O.className.includes("driver-popover")),x("popover",i);const L=((l=r.popover)==null?void 0:l.onPopoverRender)||o("onPopoverRender");L&&L(i,{config:o(),state:p()}),ne(e,r),a(P);const I=e.classList.contains("driver-dummy-element"),N=t([P,...I?[]:[e]]);N.length>0&&N[0].focus()}function re(){const e=p("popover");if(!(e!=null&&e.wrapper))return;const r=e.wrapper.getBoundingClientRect(),n=o("stagePadding")||0,l=o("popoverOffset")||0;return{width:r.width+n+l,height:r.height+n+l,realWidth:r.width,realHeight:r.height}}function oe(e,r){const{elementDimensions:n,popoverDimensions:l,popoverPadding:i,popoverArrowDimensions:g}=r;return e==="start"?Math.max(Math.min(n.top-i,window.innerHeight-l.realHeight-g.width),g.width):e==="end"?Math.max(Math.min(n.top-l?.realHeight+n.height+i,window.innerHeight-l?.realHeight-g.width),g.width):e==="center"?Math.max(Math.min(n.top+n.height/2-l?.realHeight/2,window.innerHeight-l?.realHeight-g.width),g.width):0}function ie(e,r){const{elementDimensions:n,popoverDimensions:l,popoverPadding:i,popoverArrowDimensions:g}=r;return e==="start"?Math.max(Math.min(n.left-i,window.innerWidth-l.realWidth-g.width),g.width):e==="end"?Math.max(Math.min(n.left-l?.realWidth+n.width+i,window.innerWidth-l?.realWidth-g.width),g.width):e==="center"?Math.max(Math.min(n.left+n.width/2-l?.realWidth/2,window.innerWidth-l?.realWidth-g.width),g.width):0}function ne(e,r){const n=p("popover");if(!n)return;const{align:l="start",side:i="left"}=r?.popover||{},g=l,C=e.id==="driver-dummy-element"?"over":i,E=o("stagePadding")||0,m=re(),S=n.arrow.getBoundingClientRect(),u=e.getBoundingClientRect(),f=u.top-m.height;let y=f>=0;const D=window.innerHeight-(u.bottom+m.height);let _=D>=0;const A=u.left-m.width;let w=A>=0;const P=window.innerWidth-(u.right+m.width);let $=P>=0;const M=!y&&!_&&!w&&!$;let L=C;if(C==="top"&&y?$=w=_=!1:C==="bottom"&&_?$=w=y=!1:C==="left"&&w?$=y=_=!1:C==="right"&&$&&(w=y=_=!1),C==="over"){const I=window.innerWidth/2-m.realWidth/2,N=window.innerHeight/2-m.realHeight/2;n.wrapper.style.left=`${I}px`,n.wrapper.style.right="auto",n.wrapper.style.top=`${N}px`,n.wrapper.style.bottom="auto"}else if(M){const I=window.innerWidth/2-m?.realWidth/2,N=10;n.wrapper.style.left=`${I}px`,n.wrapper.style.right="auto",n.wrapper.style.bottom=`${N}px`,n.wrapper.style.top="auto"}else if(w){const I=Math.min(A,window.innerWidth-m?.realWidth-S.width),N=oe(g,{elementDimensions:u,popoverDimensions:m,popoverPadding:E,popoverArrowDimensions:S});n.wrapper.style.left=`${I}px`,n.wrapper.style.top=`${N}px`,n.wrapper.style.bottom="auto",n.wrapper.style.right="auto",L="left"}else if($){const I=Math.min(P,window.innerWidth-m?.realWidth-S.width),N=oe(g,{elementDimensions:u,popoverDimensions:m,popoverPadding:E,popoverArrowDimensions:S});n.wrapper.style.right=`${I}px`,n.wrapper.style.top=`${N}px`,n.wrapper.style.bottom="auto",n.wrapper.style.left="auto",L="right"}else if(y){const I=Math.min(f,window.innerHeight-m.realHeight-S.width);let N=ie(g,{elementDimensions:u,popoverDimensions:m,popoverPadding:E,popoverArrowDimensions:S});n.wrapper.style.top=`${I}px`,n.wrapper.style.left=`${N}px`,n.wrapper.style.bottom="auto",n.wrapper.style.right="auto",L="top"}else if(_){const I=Math.min(D,window.innerHeight-m?.realHeight-S.width);let N=ie(g,{elementDimensions:u,popoverDimensions:m,popoverPadding:E,popoverArrowDimensions:S});n.wrapper.style.left=`${N}px`,n.wrapper.style.bottom=`${I}px`,n.wrapper.style.top="auto",n.wrapper.style.right="auto",L="bottom"}M?n.arrow.classList.add("driver-popover-arrow-none"):be(g,L,e)}function be(e,r,n){const l=p("popover");if(!l)return;const i=n.getBoundingClientRect(),g=re(),C=l.arrow,E=g.width,m=window.innerWidth,S=i.width,u=i.left,f=g.height,y=window.innerHeight,D=i.top,_=i.height;C.className="driver-popover-arrow";let A=r,w=e;r==="top"?(u+S<=0?(A="right",w="end"):u+S-E<=0&&(A="top",w="start"),u>=m?(A="left",w="end"):u+E>=m&&(A="top",w="end")):r==="bottom"?(u+S<=0?(A="right",w="start"):u+S-E<=0&&(A="bottom",w="start"),u>=m?(A="left",w="start"):u+E>=m&&(A="bottom",w="end")):r==="left"?(D+_<=0?(A="bottom",w="end"):D+_-f<=0&&(A="left",w="start"),D>=y?(A="top",w="end"):D+f>=y&&(A="left",w="end")):r==="right"&&(D+_<=0?(A="bottom",w="start"):D+_-f<=0&&(A="right",w="start"),D>=y?(A="top",w="start"):D+f>=y&&(A="right",w="end")),A?(C.classList.add(`driver-popover-arrow-side-${A}`),C.classList.add(`driver-popover-arrow-align-${w}`)):C.classList.add("driver-popover-arrow-none")}function Te(){const e=document.createElement("div");e.classList.add("driver-popover");const r=document.createElement("div");r.classList.add("driver-popover-arrow");const n=document.createElement("header");n.id="driver-popover-title",n.classList.add("driver-popover-title"),n.style.display="none",n.innerText="Popover Title";const l=document.createElement("div");l.id="driver-popover-description",l.classList.add("driver-popover-description"),l.style.display="none",l.innerText="Popover description is here";const i=document.createElement("button");i.type="button",i.classList.add("driver-popover-close-btn"),i.setAttribute("aria-label","Close"),i.innerHTML="×";const g=document.createElement("footer");g.classList.add("driver-popover-footer");const C=document.createElement("span");C.classList.add("driver-popover-progress-text"),C.innerText="";const E=document.createElement("span");E.classList.add("driver-popover-navigation-btns");const m=document.createElement("button");m.type="button",m.classList.add("driver-popover-prev-btn"),m.innerHTML="← Previous";const S=document.createElement("button");return S.type="button",S.classList.add("driver-popover-next-btn"),S.innerHTML="Next →",E.appendChild(m),E.appendChild(S),g.appendChild(C),g.appendChild(E),e.appendChild(i),e.appendChild(r),e.appendChild(n),e.appendChild(l),e.appendChild(g),{wrapper:e,arrow:r,title:n,description:l,footer:g,previousButton:m,nextButton:S,closeButton:i,footerButtons:E,progress:C}}function Se(){var e;const r=p("popover");r&&((e=r.wrapper.parentElement)==null||e.removeChild(r.wrapper))}const Ee="";function Ce(e={}){k(e);function r(){o("allowClose")&&S()}function n(){const u=p("activeIndex"),f=o("steps")||[];if(typeof u>"u")return;const y=u+1;f[y]?m(y):S()}function l(){const u=p("activeIndex"),f=o("steps")||[];if(typeof u>"u")return;const y=u-1;f[y]?m(y):S()}function i(u){(o("steps")||[])[u]?m(u):S()}function g(){var u;if(p("__transitionCallback"))return;const f=p("activeIndex"),y=p("__activeStep"),D=p("__activeElement");if(typeof f>"u"||typeof y>"u"||typeof p("activeIndex")>"u")return;const _=((u=y.popover)==null?void 0:u.onPrevClick)||o("onPrevClick");if(_)return _(D,y,{config:o(),state:p()});l()}function C(){var u;if(p("__transitionCallback"))return;const f=p("activeIndex"),y=p("__activeStep"),D=p("__activeElement");if(typeof f>"u"||typeof y>"u")return;const _=((u=y.popover)==null?void 0:u.onNextClick)||o("onNextClick");if(_)return _(D,y,{config:o(),state:p()});n()}function E(){p("isInitialized")||(x("isInitialized",!0),document.body.classList.add("driver-active",o("animate")?"driver-fade":"driver-simple"),fe(),U("overlayClick",r),U("escapePress",r),U("arrowLeftPress",g),U("arrowRightPress",C))}function m(u=0){var f,y,D,_,A,w,P,$;const M=o("steps");if(!M){console.error("No steps to drive through"),S();return}if(!M[u]){S();return}x("__activeOnDestroyed",document.activeElement),x("activeIndex",u);const L=M[u],I=M[u+1],N=M[u-1],O=((f=L.popover)==null?void 0:f.doneBtnText)||o("doneBtnText")||"Done",W=o("allowClose"),j=typeof((y=L.popover)==null?void 0:y.showProgress)<"u"?(D=L.popover)==null?void 0:D.showProgress:o("showProgress"),V=(((_=L.popover)==null?void 0:_.progressText)||o("progressText")||"{{current}} of {{total}}").replace("{{current}}",`${u+1}`).replace("{{total}}",`${M.length}`),z=((A=L.popover)==null?void 0:A.showButtons)||o("showButtons"),G=["next","previous",...W?["close"]:[]].filter(ke=>!(z!=null&&z.length)||z.includes(ke)),q=((w=L.popover)==null?void 0:w.onNextClick)||o("onNextClick"),Y=((P=L.popover)==null?void 0:P.onPrevClick)||o("onPrevClick"),xe=(($=L.popover)==null?void 0:$.onCloseClick)||o("onCloseClick");X({...L,popover:{showButtons:G,nextBtnText:I?void 0:O,disableButtons:[...N?[]:["previous"]],showProgress:j,progressText:V,onNextClick:q||(()=>{I?m(u+1):S()}),onPrevClick:Y||(()=>{m(u-1)}),onCloseClick:xe||(()=>{S()}),...L?.popover||{}}})}function S(u=!0){const f=p("__activeElement"),y=p("__activeStep"),D=p("__activeOnDestroyed"),_=o("onDestroyStarted");if(u&&_){const P=!f||f?.id==="driver-dummy-element";_(P?void 0:f,y,{config:o(),state:p()});return}const A=y?.onDeselected||o("onDeselected"),w=o("onDestroyed");if(document.body.classList.remove("driver-active","driver-fade","driver-simple"),ye(),Se(),ge(),ce(),se(),B(),f&&y){const P=f.id==="driver-dummy-element";A&&A(P?void 0:f,y,{config:o(),state:p()}),w&&w(P?void 0:f,y,{config:o(),state:p()})}D&&D.focus()}return{isActive:()=>p("isInitialized")||!1,refresh:F,drive:(u=0)=>{E(),m(u)},setConfig:k,setSteps:u=>{B(),k({...o(),steps:u})},getConfig:o,getState:p,getActiveIndex:()=>p("activeIndex"),isFirstStep:()=>p("activeIndex")===0,isLastStep:()=>{const u=o("steps")||[],f=p("activeIndex");return f!==void 0&&f===u.length-1},getActiveStep:()=>p("activeStep"),getActiveElement:()=>p("activeElement"),getPreviousElement:()=>p("previousElement"),getPreviousStep:()=>p("previousStep"),moveNext:n,movePrevious:l,moveTo:i,hasNextStep:()=>{const u=o("steps")||[],f=p("activeIndex");return f!==void 0&&u[f+1]},hasPreviousStep:()=>{const u=o("steps")||[],f=p("activeIndex");return f!==void 0&&u[f-1]},highlight:u=>{E(),X({...u,popover:u.popover?{showButtons:[],showProgress:!1,progressText:"",...u.popover}:void 0})},destroy:()=>{S(!1)}}}return v.driver=Ce,Object.defineProperty(v,Symbol.toStringTag,{value:"Module"}),v})({}),(function(v){"use strict";class b{constructor(){this.errors=[],this.maxErrors=50}logError(o,s,t={}){const a={timestamp:new Date().toISOString(),context:o,message:s instanceof Error?s.message:s,stack:s instanceof Error?s.stack:null,metadata:t};this.errors.push(a),this.errors.length>this.maxErrors&&this.errors.shift(),console.error(`[Onboarding Error] ${o}:`,s,t)}recoverFromError(o,s){switch(this.classifyError(o)){case"ELEMENT_NOT_FOUND":return this.logError("Element Not Found",o,{currentStep:s}),{action:"SKIP_STEP",nextStep:s+1,message:"Target element not found, skipping to next step"};case"STORAGE_UNAVAILABLE":return this.logError("Storage Unavailable",o),{action:"USE_MEMORY_STORAGE",message:"Local storage unavailable, using in-memory storage"};case"DRIVER_NOT_LOADED":return this.logError("Driver.js Not Loaded",o),{action:"ABORT_TOUR",message:"Driver.js library not loaded, cannot start tour"};case"INVALID_TOOLTIP":return this.logError("Invalid Tooltip Configuration",o,{currentStep:s}),{action:"SKIP_STEP",nextStep:s+1,message:"Invalid tooltip configuration, skipping"};case"THEME_DETECTION_FAILED":return this.logError("Theme Detection Failed",o),{action:"USE_DEFAULT_THEME",message:"Using default dark theme"};default:return this.logError("Unknown Error",o,{currentStep:s}),{action:"ABORT_TOUR",message:"Unexpected error occurred, aborting tour"}}}classifyError(o){const s=o.message||o.toString();return s.includes("element")&&s.includes("not found")?"ELEMENT_NOT_FOUND":s.includes("storage")||s.includes("quota")?"STORAGE_UNAVAILABLE":s.includes("driver")||s.includes("undefined")?"DRIVER_NOT_LOADED":s.includes("invalid")||s.includes("validation")?"INVALID_TOOLTIP":s.includes("theme")?"THEME_DETECTION_FAILED":"UNKNOWN"}getErrors(){return[...this.errors]}clearErrors(){this.errors=[]}getStatistics(){const o={total:this.errors.length,byContext:{},byType:{},recent:this.errors.slice(-10)};return this.errors.forEach(s=>{o.byContext[s.context]=(o.byContext[s.context]||0)+1;const t=this.classifyError({message:s.message});o.byType[t]=(o.byType[t]||0)+1}),o}handleDriverLoadFailure(){this.logError("Driver.js Load Failure","Driver.js library failed to load");const o=document.createElement("div");return o.id="onboarding-fallback",o.style.cssText=`
position: fixed;
bottom: 20px;
right: 20px;
@@ -11,38 +11,38 @@ this.driver=this.driver||{},this.driver.js=(function(v){"use strict";let T={};fu
z-index: 9999;
max-width: 300px;
font-size: 14px;
- `,e.innerHTML=`
+ `,o.innerHTML=`
Welcome to DashCaddy!
The interactive tour is unavailable, but you can explore the dashboard freely.
Check the documentation for help getting started.
- `,document.body.appendChild(e),setTimeout(()=>{e.parentNode&&e.parentNode.removeChild(e)},1e4),!0}handleStorageUnavailable(){this.logError("Storage Unavailable","Local storage is not available");const e={data:{},getItem(t){return this.data[t]||null},setItem(t,a){this.data[t]=a},removeItem(t){delete this.data[t]},clear(){this.data={}}};return console.warn("[ErrorHandler] Using in-memory storage - progress will not persist"),e}sendToErrorTracking(e){}}v.ErrorHandler=T,console.log("[ErrorHandler] Module loaded")})(window),(function(v){"use strict";class T{constructor(e="dashcaddy_onboarding"){this.storageKey=e,this.storageVersion="1.0",this.installOnboardingCompleted=typeof SITE<"u"&&SITE.onboardingCompleted===!0,this._initializeStorage(),this._updateLastVisit()}_initializeStorage(){const e=this._getStorage();if(!e||e.version!==this.storageVersion){const t={version:this.storageVersion,tourCompleted:!1,completedTooltips:[],currentStep:0,completionTimestamp:null,dnsSetupDeferred:!1,lastVisit:new Date().toISOString()};this._setStorage(t)}}_getStorage(){try{const e=localStorage.getItem(this.storageKey);return e?JSON.parse(e):null}catch(e){return console.error("[ProgressTracker] Error reading from storage:",e),null}}_setStorage(e){try{localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(t){console.error("[ProgressTracker] Error writing to storage:",t),this._handleStorageError(t)}}_handleStorageError(e){try{sessionStorage.setItem(this.storageKey,JSON.stringify(this._getStorage())),console.warn("[ProgressTracker] Falling back to session storage")}catch(t){console.error("[ProgressTracker] Session storage also unavailable:",t)}}_updateLastVisit(){const e=this._getStorage();e&&(e.lastVisit=new Date().toISOString(),this._setStorage(e))}isTooltipCompleted(e){const t=this._getStorage();return t?t.completedTooltips.includes(e):!1}markTooltipCompleted(e){const t=this._getStorage();t&&(t.completedTooltips.includes(e)||(t.completedTooltips.push(e),t.tooltipTimestamps||(t.tooltipTimestamps={}),t.tooltipTimestamps[e]=new Date().toISOString(),this._setStorage(t)))}isTourCompleted(){const e=this._getStorage();return e?e.tourCompleted===!0:!1}isInstallOnboardingCompleted(){return this.installOnboardingCompleted===!0}async markInstallOnboardingCompleted(){if(!this.installOnboardingCompleted){this.installOnboardingCompleted=!0,typeof SITE<"u"&&(SITE.onboardingCompleted=!0);try{await secureFetch("/api/v1/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({onboardingCompleted:!0})})}catch(e){console.error("[ProgressTracker] Failed to persist install onboarding state:",e)}}}markTourCompleted(){const e=this._getStorage();e&&(e.tourCompleted=!0,e.completionTimestamp=new Date().toISOString(),this._setStorage(e))}getCurrentStep(){const e=this._getStorage();return e&&e.currentStep||0}setCurrentStep(e){const t=this._getStorage();t&&(t.currentStep=e,this._setStorage(t))}resetProgress(){const e={version:this.storageVersion,tourCompleted:!1,completedTooltips:[],currentStep:0,completionTimestamp:null,dnsSetupDeferred:!1,lastVisit:new Date().toISOString()};this._setStorage(e)}getCompletionTimestamp(){const e=this._getStorage();return!e||!e.completionTimestamp?null:new Date(e.completionTimestamp)}isDnsSetupDeferred(){const e=this._getStorage();return e?e.dnsSetupDeferred===!0:!1}markDnsSetupDeferred(){const e=this._getStorage();e&&(e.dnsSetupDeferred=!0,this._setStorage(e))}getTooltipTimestamp(e){const t=this._getStorage();return!t||!t.tooltipTimestamps||!t.tooltipTimestamps[e]?null:new Date(t.tooltipTimestamps[e])}getCompletedTooltips(){const e=this._getStorage();return e?e.completedTooltips||[]:[]}getLastVisit(){const e=this._getStorage();return!e||!e.lastVisit?null:new Date(e.lastVisit)}}v.ProgressTracker=T,console.log("[ProgressTracker] Module loaded")})(window),(function(v){"use strict";const T={dark:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(0, 0, 0, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},light:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent-strong)",overlayColor:"rgba(0, 0, 0, 0.5)",borderColor:"var(--border)",highlightColor:"var(--accent-strong)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},blue:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(25, 8, 172, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},nord:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(46, 52, 64, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},dracula:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(40, 42, 54, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},"solarized-dark":{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(0, 43, 54, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},"solarized-light":{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(253, 246, 227, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"}};class P{constructor(){this.currentTheme=this.getCurrentTheme(),this.themeChangeCallbacks=[],this._setupThemeChangeListener()}getCurrentTheme(){const t=document.documentElement,a=Array.from(t.classList);return(v.THEMES||[]).filter(m=>m!=="dark").find(m=>a.includes(m))||"dark"}getDriverTheme(){const t=this.getCurrentTheme(),a=T[t]||T.dark,p={};for(const[y,m]of Object.entries(a))if(typeof m=="string"&&m.startsWith("var(")){const A=m.match(/var\((--[^)]+)\)/)?.[1];if(A){const L=getComputedStyle(document.documentElement).getPropertyValue(A).trim();p[y]=L||m}else p[y]=m}else p[y]=m;return p}onThemeChange(t){typeof t=="function"&&this.themeChangeCallbacks.push(t)}_setupThemeChangeListener(){const t=document.documentElement;new MutationObserver(p=>{p.forEach(y=>{if(y.type==="attributes"&&y.attributeName==="class"){const m=this.getCurrentTheme();if(m!==this.currentTheme){const A=this.currentTheme;this.currentTheme=m,this._notifyThemeChange(m,A)}}})}).observe(t,{attributes:!0,attributeFilter:["class"]}),console.log("[ThemeAdapter] Theme change listener initialized")}_notifyThemeChange(t,a){console.log(`[ThemeAdapter] Theme changed: ${a} \u2192 ${t}`),this.themeChangeCallbacks.forEach(p=>{try{p(t,a)}catch(y){console.error("[ThemeAdapter] Error in theme change callback:",y)}})}applyTheme(t){if(!t){console.warn("[ThemeAdapter] No driver instance provided");return}const a=this.getDriverTheme();this._injectDriverStyles(a),console.log("[ThemeAdapter] Theme applied to driver:",this.currentTheme)}_injectDriverStyles(t){const a=document.getElementById("driver-theme-styles");a&&a.remove();const p=document.createElement("style");p.id="driver-theme-styles",p.textContent=`
+ `,document.body.appendChild(o),setTimeout(()=>{o.parentNode&&o.parentNode.removeChild(o)},1e4),!0}handleStorageUnavailable(){this.logError("Storage Unavailable","Local storage is not available");const o={data:{},getItem(s){return this.data[s]||null},setItem(s,t){this.data[s]=t},removeItem(s){delete this.data[s]},clear(){this.data={}}};return console.warn("[ErrorHandler] Using in-memory storage - progress will not persist"),o}sendToErrorTracking(o){}}v.ErrorHandler=b,console.log("[ErrorHandler] Module loaded")})(window),(function(v){"use strict";const b=new ErrorHandler,k=(...s)=>{v.DASHCADDY_DEBUG&&console.log(...s)};class o{constructor(t="dashcaddy_onboarding"){this.storageKey=t,this.storageVersion="1.0",this.installOnboardingCompleted=typeof SITE<"u"&&SITE.onboardingCompleted===!0,this._initializeStorage(),this._updateLastVisit()}_initializeStorage(){const t=this._getStorage();if(!t||t.version!==this.storageVersion){const a={version:this.storageVersion,tourCompleted:!1,completedTooltips:[],currentStep:0,completionTimestamp:null,dnsSetupDeferred:!1,lastVisit:new Date().toISOString()};this._setStorage(a)}}_getStorage(){try{const t=localStorage.getItem(this.storageKey);return t?JSON.parse(t):null}catch(t){return b.logError("[ProgressTracker] Read Storage",t,{function:"_getStorage"}),null}}_setStorage(t){try{localStorage.setItem(this.storageKey,JSON.stringify(t))}catch(a){b.logError("[ProgressTracker] Write Storage",a,{function:"_setStorage"}),this._handleStorageError(a)}}_handleStorageError(t){try{sessionStorage.setItem(this.storageKey,JSON.stringify(this._getStorage())),console.warn("[ProgressTracker] Falling back to session storage")}catch(a){b.logError("[ProgressTracker] Session Storage Unavailable",a,{function:"_handleStorageError"})}}_updateLastVisit(){const t=this._getStorage();t&&(t.lastVisit=new Date().toISOString(),this._setStorage(t))}isTooltipCompleted(t){const a=this._getStorage();return a?a.completedTooltips.includes(t):!1}markTooltipCompleted(t){const a=this._getStorage();a&&(a.completedTooltips.includes(t)||(a.completedTooltips.push(t),a.tooltipTimestamps||(a.tooltipTimestamps={}),a.tooltipTimestamps[t]=new Date().toISOString(),this._setStorage(a)))}isTourCompleted(){const t=this._getStorage();return t?t.tourCompleted===!0:!1}isInstallOnboardingCompleted(){return this.installOnboardingCompleted===!0}async markInstallOnboardingCompleted(){if(!this.installOnboardingCompleted){this.installOnboardingCompleted=!0,typeof SITE<"u"&&(SITE.onboardingCompleted=!0);try{await secureFetch("/api/v1/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({onboardingCompleted:!0})})}catch(t){b.logError("[ProgressTracker] Persist Install Onboarding",t,{function:"markInstallOnboardingCompleted"})}}}markTourCompleted(){const t=this._getStorage();t&&(t.tourCompleted=!0,t.completionTimestamp=new Date().toISOString(),this._setStorage(t))}getCurrentStep(){const t=this._getStorage();return t&&t.currentStep||0}setCurrentStep(t){const a=this._getStorage();a&&(a.currentStep=t,this._setStorage(a))}resetProgress(){const t={version:this.storageVersion,tourCompleted:!1,completedTooltips:[],currentStep:0,completionTimestamp:null,dnsSetupDeferred:!1,lastVisit:new Date().toISOString()};this._setStorage(t)}getCompletionTimestamp(){const t=this._getStorage();return!t||!t.completionTimestamp?null:new Date(t.completionTimestamp)}isDnsSetupDeferred(){const t=this._getStorage();return t?t.dnsSetupDeferred===!0:!1}markDnsSetupDeferred(){const t=this._getStorage();t&&(t.dnsSetupDeferred=!0,this._setStorage(t))}getTooltipTimestamp(t){const a=this._getStorage();return!a||!a.tooltipTimestamps||!a.tooltipTimestamps[t]?null:new Date(a.tooltipTimestamps[t])}getCompletedTooltips(){const t=this._getStorage();return t?t.completedTooltips||[]:[]}getLastVisit(){const t=this._getStorage();return!t||!t.lastVisit?null:new Date(t.lastVisit)}}v.ProgressTracker=o,k("[ProgressTracker] Module loaded")})(window),(function(v){"use strict";const b=new ErrorHandler,k=(...t)=>{v.DASHCADDY_DEBUG&&console.log(...t)},o={dark:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(0, 0, 0, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},light:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent-strong)",overlayColor:"rgba(0, 0, 0, 0.5)",borderColor:"var(--border)",highlightColor:"var(--accent-strong)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},blue:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(25, 8, 172, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},nord:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(46, 52, 64, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},dracula:{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(40, 42, 54, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},"solarized-dark":{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(0, 43, 54, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"},"solarized-light":{backgroundColor:"var(--card-base)",textColor:"var(--fg)",primaryColor:"var(--accent)",overlayColor:"rgba(253, 246, 227, 0.7)",borderColor:"var(--border)",highlightColor:"var(--accent)",fontFamily:"'Sami Grotesk', 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"}};class s{constructor(){this.currentTheme=this.getCurrentTheme(),this.themeChangeCallbacks=[],this._setupThemeChangeListener()}getCurrentTheme(){const a=document.documentElement,d=Array.from(a.classList);return(v.THEMES||[]).filter(c=>c!=="dark").find(c=>d.includes(c))||"dark"}getDriverTheme(){const a=this.getCurrentTheme(),d=o[a]||o.dark,h={};for(const[T,c]of Object.entries(d))if(typeof c=="string"&&c.startsWith("var(")){const x=c.match(/var\((--[^)]+)\)/)?.[1];if(x){const p=getComputedStyle(document.documentElement).getPropertyValue(x).trim();h[T]=p||c}else h[T]=c}else h[T]=c;return h}onThemeChange(a){typeof a=="function"&&this.themeChangeCallbacks.push(a)}_setupThemeChangeListener(){const a=document.documentElement;new MutationObserver(h=>{h.forEach(T=>{if(T.type==="attributes"&&T.attributeName==="class"){const c=this.getCurrentTheme();if(c!==this.currentTheme){const x=this.currentTheme;this.currentTheme=c,this._notifyThemeChange(c,x)}}})}).observe(a,{attributes:!0,attributeFilter:["class"]}),k("[ThemeAdapter] Theme change listener initialized")}_notifyThemeChange(a,d){k(`[ThemeAdapter] Theme changed: ${d} \u2192 ${a}`),this.themeChangeCallbacks.forEach(h=>{try{h(a,d)}catch(T){b.logError("[ThemeAdapter] Theme Change Callback",T,{function:"_notifyThemeChange"})}})}applyTheme(a){if(!a){console.warn("[ThemeAdapter] No driver instance provided");return}const d=this.getDriverTheme();this._injectDriverStyles(d),k("[ThemeAdapter] Theme applied to driver:",this.currentTheme)}_injectDriverStyles(a){const d=document.getElementById("driver-theme-styles");d&&d.remove();const h=document.createElement("style");h.id="driver-theme-styles",h.textContent=`
.driver-popover {
- background: ${t.backgroundColor} !important;
- color: ${t.textColor} !important;
- border: 1px solid ${t.borderColor} !important;
+ background: ${a.backgroundColor} !important;
+ color: ${a.textColor} !important;
+ border: 1px solid ${a.borderColor} !important;
border-radius: 12px !important;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4) !important;
- font-family: ${t.fontFamily} !important;
+ font-family: ${a.fontFamily} !important;
}
.driver-popover-title {
- color: ${t.textColor} !important;
+ color: ${a.textColor} !important;
font-weight: 600 !important;
- font-family: ${t.fontFamily} !important;
+ font-family: ${a.fontFamily} !important;
}
.driver-popover-description {
- color: ${t.textColor} !important;
- font-family: ${t.fontFamily} !important;
+ color: ${a.textColor} !important;
+ font-family: ${a.fontFamily} !important;
}
.driver-popover-footer button {
- background: ${t.primaryColor} !important;
- color: ${t.backgroundColor} !important;
+ background: ${a.primaryColor} !important;
+ color: ${a.backgroundColor} !important;
border: none !important;
- font-family: ${t.fontFamily} !important;
+ font-family: ${a.fontFamily} !important;
font-weight: 500 !important;
}
@@ -51,26 +51,26 @@ this.driver=this.driver||{},this.driver.js=(function(v){"use strict";let T={};fu
}
.driver-popover-close-btn {
- color: ${t.textColor} !important;
+ color: ${a.textColor} !important;
}
.driver-overlay {
- background: ${t.overlayColor} !important;
+ background: ${a.overlayColor} !important;
}
.driver-highlighted-element {
- outline: 2px solid ${t.highlightColor} !important;
+ outline: 2px solid ${a.highlightColor} !important;
outline-offset: 4px !important;
}
.driver-popover-progress-text {
- color: ${t.textColor} !important;
+ color: ${a.textColor} !important;
opacity: 0.7 !important;
- font-family: ${t.fontFamily} !important;
+ font-family: ${a.fontFamily} !important;
}
- `,document.head.appendChild(p)}getAvailableThemes(){return Object.keys(T)}isThemeAvailable(t){return T.hasOwnProperty(t)}}v.ThemeAdapter=P,console.log("[ThemeAdapter] Module loaded")})(window),(function(v){"use strict";function T(a){const p=[];if((!a.id||typeof a.id!="string")&&p.push("Tooltip must have a valid string id"),a.element||p.push("Tooltip must have an element selector or HTMLElement"),!a.popover||typeof a.popover!="object")p.push("Tooltip must have a popover object");else{if((!a.popover.title||typeof a.popover.title!="string")&&p.push("Tooltip popover must have a valid string title"),(!a.popover.description||typeof a.popover.description!="string")&&p.push("Tooltip popover must have a valid string description"),a.popover.position){const m=["top","bottom","left","right","center"];m.includes(a.popover.position)||p.push(`Invalid position: ${a.popover.position}. Must be one of: ${m.join(", ")}`)}if(a.popover.align){const m=["start","center","end"];m.includes(a.popover.align)||p.push(`Invalid align: ${a.popover.align}. Must be one of: ${m.join(", ")}`)}a.popover.showButtons&&!Array.isArray(a.popover.showButtons)&&p.push("showButtons must be an array"),["onNext","onPrevious","onClose","onSetupNow","onLater"].forEach(m=>{a.popover[m]&&typeof a.popover[m]!="function"&&p.push(`${m} must be a function`)})}return a.condition&&typeof a.condition!="function"&&p.push("condition must be a function"),a.priority!==void 0&&typeof a.priority!="number"&&p.push("priority must be a number"),{valid:p.length===0,errors:p}}function P(a){if(!Array.isArray(a))return{valid:!1,errors:[{tooltip:null,errors:["tooltips must be an array"]}]};const p=[],y=new Set;return a.forEach((m,A)=>{const L=T(m);L.valid||p.push({tooltip:m.id||`index ${A}`,errors:L.errors}),m.id&&(y.has(m.id)&&p.push({tooltip:m.id,errors:[`Duplicate tooltip ID: ${m.id}`]}),y.add(m.id))}),{valid:p.length===0,errors:p}}class e extends Error{constructor(p,y=null){super(p),this.name="TooltipError",this.tooltipId=y}}function t(a){if(!a.valid){const p=a.errors.map(y=>`${y.tooltip}: ${y.errors.join(", ")}`).join(`
-`);throw console.error("[TooltipDefinitions] Validation errors:",p),new e(`Tooltip validation failed:
-${p}`)}}v.TooltipValidation={validateTooltipDefinition:T,validateTooltipDefinitions:P,handleValidationErrors:t,TooltipError:e},console.log("[TooltipDefinitions] Validation module loaded")})(window);const TOOLTIP_DEFINITIONS=[{id:"welcome",element:"#brand",popover:{title:"Welcome to DashCaddy!",description:`
+ `,document.head.appendChild(h)}getAvailableThemes(){return Object.keys(o)}isThemeAvailable(a){return o.hasOwnProperty(a)}}v.ThemeAdapter=s,k("[ThemeAdapter] Module loaded")})(window),(function(v){"use strict";const b=new ErrorHandler,k=(...d)=>{v.DASHCADDY_DEBUG&&console.log(...d)};function o(d){const h=[];if((!d.id||typeof d.id!="string")&&h.push("Tooltip must have a valid string id"),d.element||h.push("Tooltip must have an element selector or HTMLElement"),!d.popover||typeof d.popover!="object")h.push("Tooltip must have a popover object");else{if((!d.popover.title||typeof d.popover.title!="string")&&h.push("Tooltip popover must have a valid string title"),(!d.popover.description||typeof d.popover.description!="string")&&h.push("Tooltip popover must have a valid string description"),d.popover.position){const c=["top","bottom","left","right","center"];c.includes(d.popover.position)||h.push(`Invalid position: ${d.popover.position}. Must be one of: ${c.join(", ")}`)}if(d.popover.align){const c=["start","center","end"];c.includes(d.popover.align)||h.push(`Invalid align: ${d.popover.align}. Must be one of: ${c.join(", ")}`)}d.popover.showButtons&&!Array.isArray(d.popover.showButtons)&&h.push("showButtons must be an array"),["onNext","onPrevious","onClose","onSetupNow","onLater"].forEach(c=>{d.popover[c]&&typeof d.popover[c]!="function"&&h.push(`${c} must be a function`)})}return d.condition&&typeof d.condition!="function"&&h.push("condition must be a function"),d.priority!==void 0&&typeof d.priority!="number"&&h.push("priority must be a number"),{valid:h.length===0,errors:h}}function s(d){if(!Array.isArray(d))return{valid:!1,errors:[{tooltip:null,errors:["tooltips must be an array"]}]};const h=[],T=new Set;return d.forEach((c,x)=>{const p=o(c);p.valid||h.push({tooltip:c.id||`index ${x}`,errors:p.errors}),c.id&&(T.has(c.id)&&h.push({tooltip:c.id,errors:[`Duplicate tooltip ID: ${c.id}`]}),T.add(c.id))}),{valid:h.length===0,errors:h}}class t extends Error{constructor(h,T=null){super(h),this.name="TooltipError",this.tooltipId=T}}function a(d){if(!d.valid){const h=d.errors.map(T=>`${T.tooltip}: ${T.errors.join(", ")}`).join(`
+`);throw b.logError("[TooltipDefinitions] Validation",h,{function:"validateTooltip"}),new t(`Tooltip validation failed:
+${h}`)}}v.TooltipValidation={validateTooltipDefinition:o,validateTooltipDefinitions:s,handleValidationErrors:a,TooltipError:t},k("[TooltipDefinitions] Validation module loaded")})(window);const TOOLTIP_DEFINITIONS=[{id:"welcome",element:"#brand",popover:{title:"Welcome to DashCaddy!",description:`
Your unified control panel for Docker, Caddy, and DNS — all in one place.
This tour will walk you through every section so you know exactly where everything is.
You can click your logo anytime to customize it.
@@ -172,7 +172,7 @@ ${p}`)}}v.TooltipValidation={validateTooltipDefinition:T,validateTooltipDefiniti
Activate in Admin → License
- `,position:"bottom",align:"start",showButtons:["previous","close"],showProgress:!0},priority:13}];function getTooltipDefinitions(){return TOOLTIP_DEFINITIONS}function getTooltipById(v){return TOOLTIP_DEFINITIONS.find(T=>T.id===v)||null}function getActiveTooltips(){return TOOLTIP_DEFINITIONS.filter(v=>{if(v.condition&&typeof v.condition=="function")try{return v.condition()}catch(T){return console.error(`[TooltipDefinitions] Error evaluating condition for ${v.id}:`,T),!1}return!0})}function getSortedTooltips(){return getActiveTooltips().sort((T,P)=>{const e=T.priority||999,t=P.priority||999;return e-t})}function getNewFeatureTooltips(){return getActiveTooltips().filter(T=>T.isNewFeature===!0).sort((T,P)=>{const e=T.priority||999,t=P.priority||999;return e-t})}window.TooltipDefinitions={TOOLTIP_DEFINITIONS,getTooltipDefinitions,getTooltipById,getActiveTooltips,getSortedTooltips,getNewFeatureTooltips},console.log("[TooltipDefinitions] Definitions loaded:",TOOLTIP_DEFINITIONS.length,"tooltips"),(function(v){"use strict";class T{constructor(e){this.progressTracker=e,this.modal=null,this.onTemplateSelected=null,console.log("[DnsTemplateSelector] Module loaded")}getDnsTemplates(){return[{id:"technitium",name:"Technitium DNS Server",description:"Modern DNS server with web UI for managing private zones",icon:"\u{1F310}",difficulty:"Easy",features:["Web-based management interface","Private zone management for .sami domain","DHCP server integration","DNS-over-HTTPS and DNS-over-TLS support"],recommended:!0},{id:"bind9",name:"BIND9 DNS Server",description:"Industry-standard DNS server - powerful and flexible",icon:"\u{1F527}",difficulty:"Advanced",features:["Industry standard DNS server","Full RFC compliance","Advanced zone management","DNSSEC support"],recommended:!1},{id:"pihole",name:"Pi-hole",description:"Network-wide ad blocker with DNS capabilities",icon:"\u{1F6E1}\uFE0F",difficulty:"Intermediate",features:["Ad blocking at DNS level","Web interface for management","DHCP server included","Query logging and statistics"],recommended:!1},{id:"powerdns",name:"PowerDNS",description:"High-performance DNS server with SQL backend",icon:"\u26A1",difficulty:"Intermediate",features:["SQL database backend","RESTful API for automation","Geographic load balancing","DNSSEC support"],recommended:!1},{id:"coredns",name:"CoreDNS",description:"Cloud-native DNS server - lightweight and flexible",icon:"\u2601\uFE0F",difficulty:"Intermediate",features:["Plugin-based architecture","Kubernetes-native","Lightweight and fast","Prometheus metrics"],recommended:!1}]}showTemplateSelector(){this.modal||this.createModal(),this.populateTemplates(),this.modal.style.display="flex",document.body.style.overflow="hidden"}createModal(){const e=document.createElement("div");e.id="dns-template-modal",e.className="dns-template-modal",e.innerHTML=`
+ `,position:"bottom",align:"start",showButtons:["previous","close"],showProgress:!0},priority:13}];function getTooltipDefinitions(){return TOOLTIP_DEFINITIONS}function getTooltipById(v){return TOOLTIP_DEFINITIONS.find(b=>b.id===v)||null}function getActiveTooltips(){return TOOLTIP_DEFINITIONS.filter(v=>{if(v.condition&&typeof v.condition=="function")try{return v.condition()}catch(b){return errorHandler.logError("[TooltipDefinitions] Condition Eval",b,{function:"evaluateCondition",tooltipId:v.id}),!1}return!0})}function getSortedTooltips(){return getActiveTooltips().sort((b,k)=>{const o=b.priority||999,s=k.priority||999;return o-s})}function getNewFeatureTooltips(){return getActiveTooltips().filter(b=>b.isNewFeature===!0).sort((b,k)=>{const o=b.priority||999,s=k.priority||999;return o-s})}window.TooltipDefinitions={TOOLTIP_DEFINITIONS,getTooltipDefinitions,getTooltipById,getActiveTooltips,getSortedTooltips,getNewFeatureTooltips},debug("[TooltipDefinitions] Definitions loaded:",TOOLTIP_DEFINITIONS.length,"tooltips"),(function(v){"use strict";const b=(...o)=>{v.DASHCADDY_DEBUG&&console.log(...o)};class k{constructor(s){this.progressTracker=s,this.modal=null,this.onTemplateSelected=null,b("[DnsTemplateSelector] Module loaded")}getDnsTemplates(){return[{id:"technitium",name:"Technitium DNS Server",description:"Modern DNS server with web UI for managing private zones",icon:"\u{1F310}",difficulty:"Easy",features:["Web-based management interface","Private zone management for .sami domain","DHCP server integration","DNS-over-HTTPS and DNS-over-TLS support"],recommended:!0},{id:"bind9",name:"BIND9 DNS Server",description:"Industry-standard DNS server - powerful and flexible",icon:"\u{1F527}",difficulty:"Advanced",features:["Industry standard DNS server","Full RFC compliance","Advanced zone management","DNSSEC support"],recommended:!1},{id:"pihole",name:"Pi-hole",description:"Network-wide ad blocker with DNS capabilities",icon:"\u{1F6E1}\uFE0F",difficulty:"Intermediate",features:["Ad blocking at DNS level","Web interface for management","DHCP server included","Query logging and statistics"],recommended:!1},{id:"powerdns",name:"PowerDNS",description:"High-performance DNS server with SQL backend",icon:"\u26A1",difficulty:"Intermediate",features:["SQL database backend","RESTful API for automation","Geographic load balancing","DNSSEC support"],recommended:!1},{id:"coredns",name:"CoreDNS",description:"Cloud-native DNS server - lightweight and flexible",icon:"\u2601\uFE0F",difficulty:"Intermediate",features:["Plugin-based architecture","Kubernetes-native","Lightweight and fast","Prometheus metrics"],recommended:!1}]}showTemplateSelector(){this.modal||this.createModal(),this.populateTemplates(),this.modal.style.display="flex",document.body.style.overflow="hidden"}createModal(){const s=document.createElement("div");s.id="dns-template-modal",s.className="dns-template-modal",s.innerHTML=`
- `,document.body.appendChild(e),this.modal=e,e.querySelector(".dns-template-close").addEventListener("click",()=>this.close()),e.querySelector("#dns-setup-later").addEventListener("click",()=>this.handleSetupLater()),e.addEventListener("click",t=>{t.target===e&&this.close()}),document.addEventListener("keydown",t=>{t.key==="Escape"&&e.style.display==="flex"&&this.close()})}populateTemplates(){const e=document.getElementById("dns-template-grid");if(!e)return;const t=this.getDnsTemplates();e.innerHTML="",t.forEach(a=>{const p=this.createTemplateCard(a);e.appendChild(p)})}createTemplateCard(e){const t=document.createElement("div");t.className="dns-template-card",e.recommended&&t.classList.add("recommended");const a=e.difficulty.toLowerCase();return t.innerHTML=`
- ${e.recommended?'
+ `,document.body.appendChild(s),this.modal=s,s.querySelector(".dns-template-close").addEventListener("click",()=>this.close()),s.querySelector("#dns-setup-later").addEventListener("click",()=>this.handleSetupLater()),s.addEventListener("click",t=>{t.target===s&&this.close()}),document.addEventListener("keydown",t=>{t.key==="Escape"&&s.style.display==="flex"&&this.close()})}populateTemplates(){const s=document.getElementById("dns-template-grid");if(!s)return;const t=this.getDnsTemplates();s.innerHTML="",t.forEach(a=>{const d=this.createTemplateCard(a);s.appendChild(d)})}createTemplateCard(s){const t=document.createElement("div");t.className="dns-template-card",s.recommended&&t.classList.add("recommended");const a=s.difficulty.toLowerCase();return t.innerHTML=`
+ ${s.recommended?'