const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/latin-400-BcR6IdUc.css","assets/latin-500-DCnAHIrw.css","assets/latin-600-CnkPk-vb.css","assets/latin-700-UC1i-VSI.css"])))=>i.map(i=>d[i]);
import{e as ke,r as a,j as e,c as m,ev as Is,cT as oe,a2 as U,a0 as J,bM as Z,aE as Ke,ew as ze,ex as os,ey as as,_ as De,a8 as xe,E as jt,S as vt,ez as Nt,a7 as X,cu as cs,eA as wt,B as L,V as ns,eB as Ks,bY as Le,X as Ws,eC as kt,a6 as _t,dK as Os,c3 as St,c7 as ls,dV as Xs,eD as Ct,eE as zs,eF as Tt,eG as Ft,eH as Et,aa as Rt,eI as Je,I as Mt,a1 as Dt,a3 as At}from"./index-BuFgUdF6.js";import{g as Pt,a as Lt,c as It,r as Kt,s as Ot,b as zt,u as Vt,d as $t}from"./system-DM8P2mc4.js";import{C as Ht}from"./ConfirmModal-nA8_-uZY.js";import{S as qt,A as Bt,a as Gt,N as Ut}from"./AutoConfigureDialog-BFchIKu3.js";import{W as rs}from"./wand-sparkles-MByCKABI.js";import{P as is,F as Vs}from"./pencil-7yK1WFXk.js";import{i as Wt,g as Xt,s as Yt,a as Jt,k as Qt}from"./keycap-sfx-ByZp-njj.js";import{C as Y,P as Zt,a as ea,B as sa}from"./PageLayout-DKfh0Blq.js";import{T as Ys}from"./trash-2-BxJacC3X.js";import{R as ta}from"./rotate-ccw-WUzJwqzZ.js";import{S as aa}from"./shield-BMVOQHpc.js";import{R as na}from"./repeat-DXY29LNo.js";import{G as la}from"./git-branch-CfbKq2-d.js";import{C as ra}from"./clock-CiO_tPRQ.js";import{C as Js}from"./chevron-right-Bn33xBBB.js";import{R as se,C as me}from"./Grid-CVvPTnwu.js";import{A as ia}from"./antenna-QOX4KGiv.js";import{P as $s}from"./plus-DzDLhCtU.js";import{K as Hs}from"./key-round-ZmTqrNwT.js";import"./arrow-right-DMRkyqKR.js";/**
 * @license lucide-react v0.559.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */const oa=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],Qs=ke("external-link",oa);/**
 * @license lucide-react v0.559.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */const ca=[["circle",{cx:"16",cy:"20",r:"2",key:"1vifvg"}],["path",{d:"M10 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v2",key:"3hgo9p"}],["path",{d:"m22 14-4.5 4.5",key:"1ef6z8"}],["path",{d:"m21 15 1 1",key:"1ejcpy"}]],da=ke("folder-key",ca);/**
 * @license lucide-react v0.559.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */const ua=[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["line",{x1:"3",x2:"9",y1:"12",y2:"12",key:"1dyftd"}],["line",{x1:"15",x2:"21",y1:"12",y2:"12",key:"oup4p8"}]],ma=ke("git-commit-horizontal",ua);/**
 * @license lucide-react v0.559.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */const fa=[["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2",key:"48i651"}],["line",{x1:"8",x2:"16",y1:"21",y2:"21",key:"1svkeh"}],["line",{x1:"12",x2:"12",y1:"17",y2:"21",key:"vw1qmm"}]],xa=ke("monitor",fa);/**
 * @license lucide-react v0.559.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */const ha=[["path",{d:"M10.17 4.193a2 2 0 0 1 3.666.013",key:"pltmmw"}],["path",{d:"M14 21h2",key:"v4qezv"}],["path",{d:"m15.874 7.743 1 1.732",key:"10m0iw"}],["path",{d:"m18.849 12.952 1 1.732",key:"zadnam"}],["path",{d:"M21.824 18.18a2 2 0 0 1-1.835 2.824",key:"fvwuk4"}],["path",{d:"M4.024 21a2 2 0 0 1-1.839-2.839",key:"1e1kah"}],["path",{d:"m5.136 12.952-1 1.732",key:"1u4ldi"}],["path",{d:"M8 21h2",key:"i9zjee"}],["path",{d:"m8.102 7.743-1 1.732",key:"1zzo4u"}]],pa=ke("triangle-dashed",ha),Oe=1500,he={stacked:"h-[38px]",inline:"h-[32px]"},pe={stacked:"px-3",inline:"px-2.5"},ye="rounded-lg";function P({label:t,value:l,editValue:n,onSave:c,type:i="text",suffix:o,placeholder:j,readOnly:p=!1,layout:y="stacked",min:u,max:r,step:h,maxLength:F,description:g,tooltip:E,autoConfigured:k,className:N}){const[x,b]=a.useState(!1),[v,R]=a.useState(""),[M,w]=a.useState("idle"),_=a.useRef(null),C=a.useRef(!0),f=a.useRef(null),A=!p&&!!c;a.useEffect(()=>(C.current=!0,()=>{C.current=!1,f.current&&clearTimeout(f.current)}),[]);const S=a.useCallback(()=>{A&&(R(n??l),b(!0),w("idle"),requestAnimationFrame(()=>{var K;return(K=_.current)==null?void 0:K.select()}))},[A,n,l]),I=a.useCallback(()=>{b(!1),R(""),w("idle")},[]),V=a.useCallback(async()=>{if(!c||M==="loading")return;if(v===(n??l)){I();return}f.current&&clearTimeout(f.current),w("loading");try{if(await c(v),!C.current)return;w("success"),b(!1),f.current=setTimeout(()=>{C.current&&w("idle")},Oe)}catch{if(!C.current)return;w("error"),f.current=setTimeout(()=>{C.current&&w("idle")},Oe)}},[c,v,n,l,I,M]),H=a.useCallback(K=>{K.key==="Enter"?(K.preventDefault(),V()):K.key==="Escape"&&(K.preventDefault(),I())},[V,I]);return y==="inline"?e.jsxs("div",{className:m("group flex items-center justify-between gap-3",N),children:[e.jsxs("div",{className:"flex items-center gap-1 truncate",children:[e.jsx("label",{className:"type-label text-fg-muted truncate",children:t}),E&&e.jsx(Is,{content:E,placement:"top",children:e.jsx("span",{className:"text-fg-muted/50 hover:text-fg-muted cursor-help transition-colors flex-shrink-0",children:e.jsx(oe,{className:"w-3 h-3"})})})]}),x?e.jsxs("div",{className:m(he.inline,ye,pe.inline,"flex items-center transition-all","bg-transparent border border-sys-blue/50 ring-1 ring-sys-blue/20","min-w-[100px]"),children:[e.jsx("input",{ref:_,type:i,value:v,onChange:K=>R(K.target.value),onKeyDown:H,placeholder:j,min:u,max:r,step:h,maxLength:F,disabled:M==="loading",className:m("bg-transparent text-fg-primary focus:outline-none type-data flex-1 min-w-0",o?"w-12 text-right":"w-full")}),o&&e.jsx("span",{className:"text-fg-muted type-data ml-1 shrink-0",children:o}),e.jsx("div",{className:"flex items-center gap-0.5 ml-2 shrink-0",children:M==="loading"?e.jsx(U,{className:"w-3.5 h-3.5 text-fg-muted animate-spin"}):e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:V,className:"p-0.5 rounded hover:bg-sys-green/15 text-sys-green transition-colors",title:"Save (Enter)",children:e.jsx(J,{className:"w-3 h-3"})}),e.jsx("button",{onClick:I,className:"p-0.5 rounded hover:bg-sys-red/15 text-fg-muted hover:text-sys-red transition-colors",title:"Cancel (Esc)",children:e.jsx(Z,{className:"w-3 h-3"})})]})})]}):e.jsxs("div",{className:m(he.inline,ye,pe.inline,"flex items-center justify-end transition-all min-w-[80px]","bg-input-bg border border-input-border",A&&"cursor-pointer hover:border-edge-strong"),onClick:A?S:void 0,children:[e.jsx("span",{className:"type-data text-fg-primary",children:l}),M==="success"&&e.jsx(J,{className:"w-3 h-3 text-sys-green ml-1.5 shrink-0"}),M==="error"&&e.jsx(Z,{className:"w-3 h-3 text-sys-red ml-1.5 shrink-0"}),M==="idle"&&k&&e.jsx(rs,{className:"w-3 h-3 text-sys-blue ml-1.5 shrink-0"}),M==="idle"&&!k&&A&&e.jsx(is,{className:"w-3 h-3 text-fg-muted ml-1.5 opacity-0 group-hover:opacity-100 transition-opacity shrink-0"})]})]}):e.jsxs("div",{className:m("group",N),children:[e.jsxs("div",{className:"flex items-center gap-1 mb-1",children:[e.jsx("label",{className:"type-label text-fg-muted",children:t}),E&&e.jsx(Is,{content:E,placement:"top",children:e.jsx("span",{className:"text-fg-muted/50 hover:text-fg-muted cursor-help transition-colors flex-shrink-0",children:e.jsx(oe,{className:"w-3 h-3"})})})]}),x?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:m(he.stacked,ye,pe.stacked,"flex items-center transition-all","bg-transparent border border-sys-blue/50 ring-1 ring-sys-blue/20"),children:[e.jsx("input",{ref:_,type:i,value:v,onChange:K=>R(K.target.value),onKeyDown:H,placeholder:j,min:u,max:r,step:h,maxLength:F,disabled:M==="loading",className:"w-full bg-transparent text-fg-primary focus:outline-none type-data flex-1 min-w-0"}),o&&e.jsx("span",{className:"text-fg-muted type-data ml-1 shrink-0",children:o}),e.jsx("div",{className:"flex items-center gap-0.5 ml-2 shrink-0",children:M==="loading"?e.jsx(U,{className:"w-3.5 h-3.5 text-fg-muted animate-spin"}):e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:V,className:"p-1 rounded hover:bg-sys-green/15 text-sys-green transition-colors",title:"Save (Enter)",children:e.jsx(J,{className:"w-3.5 h-3.5"})}),e.jsx("button",{onClick:I,className:"p-1 rounded hover:bg-sys-red/15 text-fg-muted hover:text-sys-red transition-colors",title:"Cancel (Esc)",children:e.jsx(Z,{className:"w-3.5 h-3.5"})})]})})]}),g&&e.jsx("p",{className:"type-data-xs text-fg-muted mt-1 ml-3",children:g})]}):e.jsxs("div",{className:m(he.stacked,ye,pe.stacked,"flex items-center transition-all","bg-input-bg border border-input-border",A&&"cursor-pointer hover:border-edge-strong"),onClick:A?S:void 0,children:[e.jsx("span",{className:"type-data text-fg-primary flex-1 whitespace-nowrap",children:l}),M==="success"&&e.jsx(J,{className:"w-3.5 h-3.5 text-sys-green shrink-0"}),M==="error"&&e.jsx(Z,{className:"w-3.5 h-3.5 text-sys-red shrink-0"}),M==="idle"&&k&&e.jsx(rs,{className:"w-3.5 h-3.5 text-sys-blue shrink-0"}),M==="idle"&&!k&&A&&e.jsx(is,{className:"w-3.5 h-3.5 text-fg-muted opacity-0 group-hover:opacity-100 transition-opacity shrink-0"})]})]})}function Ae({label:t,value:l,editValue:n,options:c,onSave:i,readOnly:o=!1,layout:j="stacked",className:p}){const[y,u]=a.useState(!1),[r,h]=a.useState(""),[F,g]=a.useState("idle"),E=a.useRef(null),k=a.useRef(!0),N=a.useRef(null),x=!o&&!!i;a.useEffect(()=>(k.current=!0,()=>{k.current=!1,N.current&&clearTimeout(N.current)}),[]);const b=a.useCallback(()=>{x&&(h(String(n)),u(!0),g("idle"),requestAnimationFrame(()=>{var S;return(S=E.current)==null?void 0:S.focus()}))},[x,n]),v=a.useCallback(()=>{u(!1),h(""),g("idle")},[]),R=a.useCallback(async()=>{if(!(!i||F==="loading")){if(r===String(n)){v();return}N.current&&clearTimeout(N.current),g("loading");try{if(await i(r),!k.current)return;g("success"),u(!1),N.current=setTimeout(()=>{k.current&&g("idle")},Oe)}catch{if(!k.current)return;g("error"),N.current=setTimeout(()=>{k.current&&g("idle")},Oe)}}},[i,r,n,v,F]),M=a.useCallback(S=>{S.key==="Escape"&&(S.preventDefault(),v())},[v]),w=j==="inline",_=w?he.inline:he.stacked,C=w?pe.inline:pe.stacked,f=e.jsxs("div",{className:m(_,ye,C,"flex items-center transition-all relative","bg-transparent border border-sys-blue/50 ring-1 ring-sys-blue/20",w&&"min-w-[100px]"),children:[e.jsx("select",{ref:E,value:r,onChange:S=>h(S.target.value),onKeyDown:M,disabled:F==="loading",className:m("bg-transparent text-fg-primary focus:outline-none appearance-none cursor-pointer type-data flex-1 min-w-0","pr-6"),children:c.map(S=>e.jsx("option",{value:S.value,children:S.label},String(S.value)))}),e.jsx(Ke,{className:"absolute right-auto w-3.5 h-3.5 text-fg-muted pointer-events-none",style:{right:F==="loading"?"2rem":"3.5rem"}}),e.jsx("div",{className:"flex items-center gap-0.5 ml-1 shrink-0",children:F==="loading"?e.jsx(U,{className:m("text-fg-muted animate-spin",w?"w-3 h-3":"w-3.5 h-3.5")}):e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:R,className:m("rounded hover:bg-sys-green/15 text-sys-green transition-colors",w?"p-0.5":"p-1"),title:"Save",children:e.jsx(J,{className:w?"w-3 h-3":"w-3.5 h-3.5"})}),e.jsx("button",{onClick:v,className:m("rounded hover:bg-sys-red/15 text-fg-muted hover:text-sys-red transition-colors",w?"p-0.5":"p-1"),title:"Cancel (Esc)",children:e.jsx(Z,{className:w?"w-3 h-3":"w-3.5 h-3.5"})})]})})]}),A=e.jsxs("div",{className:m(_,ye,C,"flex items-center transition-all","bg-input-bg border border-input-border",x&&"cursor-pointer hover:border-edge-strong",w?"justify-end min-w-[80px]":""),onClick:x?b:void 0,children:[e.jsx("span",{className:m("type-data text-fg-primary",!w&&"flex-1"),children:l}),F==="success"&&e.jsx(J,{className:m("text-sys-green shrink-0",w?"w-3 h-3 ml-1.5":"w-3.5 h-3.5")}),F==="error"&&e.jsx(Z,{className:m("text-sys-red shrink-0",w?"w-3 h-3 ml-1.5":"w-3.5 h-3.5")}),F==="idle"&&x&&e.jsx(Ke,{className:m("text-fg-muted opacity-0 group-hover:opacity-100 transition-opacity shrink-0",w?"w-3 h-3 ml-1.5":"w-3.5 h-3.5")})]});return w?e.jsxs("div",{className:m("group flex items-center justify-between",p),children:[e.jsx("label",{className:"type-label text-fg-muted shrink-0",children:t}),y?f:A]}):e.jsxs("div",{className:m("group",p),children:[e.jsx("label",{className:"type-label text-fg-muted block mb-1",children:t}),y?f:A]})}async function ya(){try{return await ze("/api/auth/tokens")}catch{return{tokens:[]}}}async function ga(t){return ze("/api/auth/tokens",{method:"POST",body:JSON.stringify({name:t})})}async function ba(t){return ze(`/api/auth/tokens/${t}`,{method:"DELETE"})}async function qs(t){return ze("/api/update_web_config",{method:"POST",body:JSON.stringify(t)})}a.memo(function(){const{theme:l}=os(),{themeId:n}=l,c=as.find(i=>i.meta.id===n)??as[0];return e.jsx("div",{className:"h-10 flex items-center justify-center",children:e.jsx("span",{className:"font-medium transition-all duration-300 leading-none text-center text-fg-secondary",style:{fontFamily:"Inter, system-ui, sans-serif",fontSize:"clamp(0.75rem, 0.6rem + 1.5vw, 1.1rem)",letterSpacing:"-0.02em"},children:c.meta.name})})});const Qe=a.memo(function({compact:l=!1}){const{theme:n,setTheme:c}=os(),{themeId:i}=n;return e.jsx("div",{className:m("grid grid-cols-2 gap-2",l?"w-full min-w-0 self-stretch":"w-full"),children:[...as].reverse().map(o=>{const j=i===o.meta.id,p=o.meta.isDark;return e.jsxs("button",{type:"button",title:o.meta.name,className:m("flex flex-row items-stretch radius-inner transition-all duration-200 ease-out overflow-hidden cursor-pointer",l&&"h-6",j?"ring-2 ring-sys-blue scale-[1.02]":"opacity-70 hover:opacity-100"),onClick:()=>c(o.meta.id),children:[e.jsx("div",{className:m("flex-1 h-full",p?"bg-[#18181b]":"bg-[#EFF0F1]")}),e.jsx("div",{className:"flex flex-col h-full",children:o.display.palette.map((y,u)=>e.jsx("div",{className:"flex flex-1",children:y.map((r,h)=>e.jsx("div",{className:"w-2 h-full",style:{backgroundColor:r}},h))},u))})]},o.meta.id)})})});let Bs=!1,Pe=null;async function ja(){if(!Bs)return Pe||(Pe=(async()=>{try{await Promise.all([De(()=>Promise.resolve({}),__vite__mapDeps([0])),De(()=>Promise.resolve({}),__vite__mapDeps([1])),De(()=>Promise.resolve({}),__vite__mapDeps([2])),De(()=>Promise.resolve({}),__vite__mapDeps([3]))]),Bs=!0}catch(t){console.warn("Failed to load theme fonts:",t)}})(),Pe)}const Ze=a.memo(function(){const{theme:l,setTheme:n}=os(),{themeId:c}=l,i=c==="breeze dark",o=a.useCallback(j=>{n(j?"breeze dark":"breeze light")},[n]);return e.jsx(xe,{enabled:i,onChange:o,label:e.jsxs(e.Fragment,{children:["Dark Mode: ",i?e.jsx(jt,{className:"w-3.5 h-3.5 text-sys-blue inline"}):e.jsx(vt,{className:"w-3.5 h-3.5 text-[#e8a517] inline"})]}),tooltip:"Switch between dark and light mode",size:"md"})}),va=a.memo(function({layout:l="horizontal"}){return a.useEffect(()=>{ja()},[]),l==="toggle-only"?e.jsx(Ze,{}):l==="thumbnails-only"?e.jsx(Qe,{}):l==="vertical"?e.jsxs("div",{className:"flex flex-col items-start gap-3",children:[e.jsx(Ze,{}),e.jsx(Qe,{})]}):e.jsxs("div",{className:"flex items-stretch gap-4",children:[e.jsx("div",{className:"flex-shrink-0 flex items-start",children:e.jsx(Ze,{})}),e.jsx(Qe,{compact:!0})]})}),Na=1e4,es=2e3;function ss(t,l,n){const[c,i]=a.useState("idle"),[o,j]=a.useState(null),p=a.useRef(!0),y=a.useRef(null),u=a.useRef(null),r=a.useRef(!1),h=a.useRef("idle"),F=a.useRef(t),g=a.useRef(l),E=a.useRef(n);h.current=c,F.current=t,g.current=l,E.current=n,a.useEffect(()=>(p.current=!0,()=>{p.current=!1,y.current&&clearTimeout(y.current),u.current&&clearTimeout(u.current)}),[]);const k=a.useCallback(async x=>{if(h.current==="loading")return;const b=F.current;y.current&&clearTimeout(y.current),u.current&&clearTimeout(u.current),r.current=!1,j(x),i("loading"),y.current=setTimeout(()=>{r.current||!p.current||(j(b),i("error"),u.current=setTimeout(()=>{p.current&&(i("idle"),j(null))},es))},Na);try{if(await g.current(x),r.current=!0,y.current&&clearTimeout(y.current),!p.current)return;i("success"),u.current=setTimeout(()=>{var v;p.current&&(i("idle"),j(null),(v=E.current)==null||v.call(E))},es)}catch{if(r.current=!0,y.current&&clearTimeout(y.current),!p.current)return;j(b),i("error"),u.current=setTimeout(()=>{p.current&&(i("idle"),j(null))},es)}},[]);return{enabled:o!==null?o:t,status:c,toggle:k}}function wa(){const{latitude:t,longitude:l,enabled:n,setLocation:c,enable:i,disable:o,clear:j}=Nt(),[p,y]=a.useState(!1),[u,r]=a.useState(""),[h,F]=a.useState(""),[g,E]=a.useState("idle"),[k,N]=a.useState(null),x=a.useRef(null),b=a.useRef(null),v=a.useRef(!0);a.useEffect(()=>(v.current=!0,()=>{v.current=!1,b.current&&clearTimeout(b.current)}),[]);const R=()=>{r((t==null?void 0:t.toFixed(6))??""),F((l==null?void 0:l.toFixed(6))??""),N(null),y(!0)},M=()=>{y(!1),N(null)};a.useEffect(()=>{if(!p)return;const S=I=>{g!=="loading"&&x.current&&!x.current.contains(I.target)&&M()};return document.addEventListener("mouseup",S),()=>document.removeEventListener("mouseup",S)},[p,g]);const w=(S,I)=>{const V=parseFloat(S),H=parseFloat(I);return isNaN(V)||isNaN(H)?"Please enter valid numbers":V<-90||V>90?"Latitude must be between -90 and 90":H<-180||H>180?"Longitude must be between -180 and 180":V===0&&H===0?"Coordinates (0, 0) are invalid":null},_=()=>{if(g==="loading")return;b.current&&clearTimeout(b.current);const S=w(u,h);if(S){N(S);return}E("loading"),N(null);const I=parseFloat(u),V=parseFloat(h);c(I,V),n||i(),E("success"),b.current=setTimeout(()=>{v.current&&(E("idle"),y(!1))},1e3)},C=()=>{n?o():i()},f=()=>{j(),y(!1)},A=t!==null&&l!==null;return e.jsx(Y,{children:e.jsxs("div",{ref:x,children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx(X,{icon:e.jsx(pa,{}),title:"Stealth"}),e.jsxs("div",{className:"flex items-center gap-1",children:[A&&!p&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:C,className:m("relative inline-flex h-6 w-11 items-center rounded-full transition-colors border-2 mr-2",n?"bg-toggle-on border-toggle-on":"bg-toggle-off border-edge-subtle"),title:n?"Disable stealth location":"Enable stealth location",children:e.jsx("span",{className:m("inline-block h-4 w-4 transform rounded-full bg-white transition-transform shadow-lg",n?"translate-x-5":"translate-x-0.5")})}),e.jsx("button",{onClick:f,className:"p-2 rounded-lg transition-colors text-fg-muted hover:text-sys-red hover:bg-sys-red/10",title:"Clear stealth location",children:e.jsx(Ys,{className:"w-4 h-4"})})]}),p?e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:M,disabled:g==="loading",className:m("p-2 rounded-lg transition-colors",g==="loading"?"text-fg-muted cursor-not-allowed":"text-fg-muted hover:text-sys-red hover:bg-sys-red/10"),title:"Cancel",children:e.jsx(Z,{className:"w-4 h-4"})}),e.jsx("button",{onClick:_,disabled:g==="loading",className:m("p-2 rounded-lg transition-colors",g==="loading"?"text-sys-blue cursor-wait":g==="success"?"text-sys-green":g==="error"?"text-sys-red":"text-sys-green hover:bg-sys-green/10"),title:"Save",children:g==="loading"?e.jsx(U,{className:"w-4 h-4 animate-spin"}):g==="success"?e.jsx(J,{className:"w-4 h-4"}):g==="error"?e.jsx(Z,{className:"w-4 h-4"}):e.jsx(J,{className:"w-4 h-4"})})]}):e.jsx("button",{onClick:R,className:"p-2 rounded-lg transition-colors text-fg-muted hover:text-fg-primary hover:bg-subtle",title:A?"Edit stealth location":"Set stealth location",children:e.jsx(is,{className:"w-4 h-4"})})]})]}),e.jsx("div",{className:"bg-sys-cyan/5 rounded-xl p-3 mb-4",children:e.jsxs("div",{className:"flex gap-2",children:[e.jsx(oe,{className:"w-4 h-4 text-sys-cyan flex-shrink-0 mt-0.5"}),e.jsxs("p",{className:"type-body-sm text-fg-muted",children:[e.jsx("span",{className:"text-fg-secondary",children:"Stealth mode"})," allows you to appear on the map and in topology analysis without broadcasting your location. Coordinates are stored locally in your browser only — ",e.jsx("span",{className:"text-sys-cyan",children:"never sent to config.yaml or the mesh"}),"."]})]})}),k&&e.jsx("div",{className:"text-xs mb-3 px-2 py-1.5 rounded-md text-sys-red bg-sys-red/10",children:k}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"type-label text-fg-muted block mb-1",children:p?"Latitude (°)":"Latitude"}),e.jsx("div",{className:m("h-[38px] rounded-full px-4 flex items-center transition-colors","bg-subtle-fill"),children:p?e.jsx("input",{type:"number",value:u,onChange:S=>r(S.target.value),step:"0.000001",min:"-90",max:"90",placeholder:"e.g. 34.052234",className:"w-full bg-transparent text-fg-primary focus:outline-none type-data placeholder:text-fg-muted/50"}):e.jsx("span",{className:m("type-data",A&&n?"text-fg-primary":"text-fg-muted"),children:A?t.toFixed(6):"Not set"})})]}),e.jsxs("div",{children:[e.jsx("label",{className:"type-label text-fg-muted block mb-1",children:p?"Longitude (°)":"Longitude"}),e.jsx("div",{className:m("h-[38px] rounded-full px-4 flex items-center transition-colors","bg-subtle-fill"),children:p?e.jsx("input",{type:"number",value:h,onChange:S=>F(S.target.value),step:"0.000001",min:"-180",max:"180",placeholder:"e.g. -118.243685",className:"w-full bg-transparent text-fg-primary focus:outline-none type-data placeholder:text-fg-muted/50"}):e.jsx("span",{className:m("type-data",A&&n?"text-fg-primary":"text-fg-muted"),children:A?l.toFixed(6):"Not set"})})]})]}),A&&!p&&e.jsx("div",{className:"mt-3 pt-3 border-t border-edge-subtle",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:m("w-2 h-2 rounded-full",n?"bg-sys-green":"bg-fg-muted")}),e.jsx("span",{className:"type-body-sm text-fg-muted",children:n?"Stealth location active — you appear on maps with these coordinates":"Stealth location disabled — coordinates saved but not in use"})]})})]})})}function fe(t){if(t<60)return`${t}s`;if(t<3600){const c=Math.floor(t/60),i=t%60;return i>0?`${c}m ${i}s`:`${c}m`}const l=Math.floor(t/3600),n=Math.floor(t%3600/60);return n>0?`${l}h ${n}m`:`${l}h`}function ts({title:t,defaultOpen:l=!1,children:n}){const[c,i]=a.useState(l);return e.jsxs("div",{className:"bg-subtle-fill radius-inner overflow-hidden",children:[e.jsxs("button",{type:"button",onClick:()=>i(!c),className:"w-full flex items-center justify-between px-4 py-3 hover:bg-subtle-fill-hover transition-colors",children:[e.jsx("span",{className:"type-label text-fg-muted",children:t}),e.jsx(Ke,{className:m("w-4 h-4 text-fg-muted transition-transform",c&&"rotate-180")})]}),c&&e.jsx("div",{className:"px-4 pb-4 pt-1",children:n})]})}const Ie={off:{label:"Off",description:"All rate limiting disabled. Every advert is forwarded unconditionally.",color:"text-fg-muted",config:qt},light:{label:"Light",description:"Gentle throttling for sparse meshes. Allows short bursts but penalizes repeat offenders. Good for small networks with few nodes.",color:"text-sys-green",config:{rate_limit_enabled:!0,bucket_capacity:3,refill_tokens:1,refill_interval_seconds:3600,min_interval_seconds:15,penalty_enabled:!0,violation_threshold:2,base_penalty_seconds:1800,penalty_multiplier:2,max_penalty_seconds:43200,violation_decay_seconds:7200,adaptive_enabled:!0,ewma_alpha:.15,hysteresis_seconds:480,quiet_max:2,normal_max:6,busy_max:10}},standard:{label:"Standard",description:"Balanced protection for most meshes. One advert per source is enough for discovery — repeated adverts are suppressed to protect channel capacity.",color:"text-sys-blue",recommended:!0,config:{rate_limit_enabled:!0,bucket_capacity:2,refill_tokens:1,refill_interval_seconds:7200,min_interval_seconds:30,penalty_enabled:!0,violation_threshold:1,base_penalty_seconds:7200,penalty_multiplier:4,max_penalty_seconds:172800,violation_decay_seconds:14400,adaptive_enabled:!0,ewma_alpha:.1,hysteresis_seconds:300,quiet_max:1,normal_max:3,busy_max:8}},strict:{label:"Strict",description:"Maximum suppression for dense or congested meshes. One token, long refill, immediate jail. Protects GRP_TXT capacity at all costs.",color:"text-sys-amber",config:{rate_limit_enabled:!0,bucket_capacity:1,refill_tokens:1,refill_interval_seconds:14400,min_interval_seconds:60,penalty_enabled:!0,violation_threshold:1,base_penalty_seconds:10800,penalty_multiplier:4,max_penalty_seconds:259200,violation_decay_seconds:21600,adaptive_enabled:!0,ewma_alpha:.05,hysteresis_seconds:180,quiet_max:.5,normal_max:2,busy_max:5}}},Zs=["off","light","standard","strict"];function ka(t,l,n){if(!t&&!l&&!n||!((t==null?void 0:t.enabled)||(l==null?void 0:l.enabled)||(n==null?void 0:n.enabled)))return"off";for(const i of Zs){if(i==="off")continue;const o=Ie[i].config;if((t==null?void 0:t.bucket_capacity)===o.bucket_capacity&&(t==null?void 0:t.refill_tokens)===o.refill_tokens&&(t==null?void 0:t.refill_interval_seconds)===o.refill_interval_seconds&&(t==null?void 0:t.min_interval_seconds)===o.min_interval_seconds&&(l==null?void 0:l.violation_threshold)===o.violation_threshold&&(l==null?void 0:l.base_penalty_seconds)===o.base_penalty_seconds&&(l==null?void 0:l.penalty_multiplier)===o.penalty_multiplier&&(l==null?void 0:l.max_penalty_seconds)===o.max_penalty_seconds&&(l==null?void 0:l.violation_decay_seconds)===o.violation_decay_seconds&&(n==null?void 0:n.ewma_alpha)===o.ewma_alpha&&(n==null?void 0:n.hysteresis_seconds)===o.hysteresis_seconds)return i}return null}function _a(){var S,I,V,H,K,ee;const{stats:t,fetchStats:l}=cs(),n=a.useRef(!0),[c,i]=a.useState(!0),[o,j]=a.useState(!1),[p,y]=a.useState(null),[u,r]=a.useState("idle"),h=a.useRef(null),[F,g]=a.useState(!1),[E,k]=a.useState(new Set);a.useEffect(()=>(n.current=!0,()=>{n.current=!1,h.current&&clearTimeout(h.current)}),[]);const N=a.useCallback(async()=>{var d;try{const O=await wt();if(!n.current)return;O.success&&O.data&&((d=O.data.adaptive)!=null&&d.current_tier)?i(!0):i(!1)}catch{n.current&&i(!1)}},[]);a.useEffect(()=>{N();const d=setInterval(N,3e4);return()=>clearInterval(d)},[N]);const x=(I=(S=t==null?void 0:t.config)==null?void 0:S.repeater)==null?void 0:I.advert_rate_limit,b=(H=(V=t==null?void 0:t.config)==null?void 0:V.repeater)==null?void 0:H.advert_penalty_box,v=(ee=(K=t==null?void 0:t.config)==null?void 0:K.repeater)==null?void 0:ee.advert_adaptive;if(!c&&!x&&!b&&!v)return null;const R=d=>E.has(d),M=d=>{k(O=>{if(!O.has(d))return O;const W=new Set(O);return W.delete(d),W})},w=ka(x,b,v),_=w?Ie[w]:null,C=async(d,O)=>{M(d),j(!0),y(null),h.current&&clearTimeout(h.current);try{const W=await Ks({[d]:O});if(!n.current)return;W.success?(r("success"),await Promise.all([l({force:!0}).catch(()=>{}),N()])):(r("error"),y(W.error||"Failed to save"))}catch{n.current&&(r("error"),y("Failed to save"))}finally{n.current&&(j(!1),h.current=setTimeout(()=>{n.current&&(r("idle"),y(null))},1500))}},f=async d=>{if(!(d===w||o)){j(!0),y(null),k(new Set),h.current&&clearTimeout(h.current);try{const O=await Ks(Ie[d].config);if(!n.current)return;O.success?(r("success"),await Promise.all([l({force:!0}).catch(()=>{}),N()])):(r("error"),y(O.error||"Failed to save"))}catch{n.current&&(r("error"),y("Failed to save"))}finally{n.current&&(j(!1),h.current=setTimeout(()=>{n.current&&r("idle")},1500))}}},A=()=>f("off");return e.jsxs(Y,{neomorphic:!0,children:[e.jsx(X,{icon:e.jsx(aa,{}),title:"Advert Rate Limiting",actions:e.jsxs("div",{className:"flex items-center gap-3",children:[u!=="idle"&&e.jsxs("span",{className:"flex items-center",children:[u==="success"&&e.jsx(J,{className:"w-4 h-4 text-sys-green"}),u==="error"&&e.jsx(Z,{className:"w-4 h-4 text-sys-red"})]}),e.jsxs(L,{plain:!0,onClick:A,className:"flex items-center gap-1.5 text-zinc-500 hover:text-zinc-400 transition-colors",children:[e.jsx(ta,{className:"w-3.5 h-3.5"}),e.jsx("span",{className:"type-body-xs font-medium hidden sm:inline",children:"Reset"})]}),e.jsxs(L,{plain:!0,onClick:()=>g(!0),className:"flex items-center gap-1.5 text-sys-blue hover:text-sys-blue/80 transition-colors",children:[e.jsx(rs,{className:"w-3.5 h-3.5"}),e.jsx("span",{className:"type-body-xs font-medium",children:"Auto"})]})]})}),p&&e.jsx("div",{className:"type-body-sm mb-3 px-3 py-2 rounded-full text-sys-red bg-sys-red/10",children:p}),e.jsx("div",{className:"toggle-group w-full mb-4",children:Zs.map(d=>{const O=Ie[d],W=d===w;return e.jsx("button",{onClick:()=>f(d),disabled:o,className:m("toggle-group-item flex-1",W&&"active",W&&O.color),children:O.label},d)})}),e.jsx("div",{className:"bg-subtle-fill radius-inner p-4 mb-4",children:e.jsxs("div",{className:"flex gap-3",children:[e.jsx("div",{className:"w-8 h-8 rounded-full bg-sys-blue/20 flex items-center justify-center flex-shrink-0",children:e.jsx(oe,{className:"w-4 h-4 text-sys-blue"})}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:m("type-data-xs font-medium uppercase tracking-wide",(_==null?void 0:_.color)??"text-fg-muted"),children:(_==null?void 0:_.label)??"Custom"}),(_==null?void 0:_.recommended)&&e.jsx(ns,{color:"green",children:"Recommended"}),!w&&e.jsx(ns,{color:"zinc",children:"Custom"})]}),e.jsx("p",{className:"type-body-sm text-fg-muted mt-1",children:(_==null?void 0:_.description)??"Settings have been manually tuned and don’t match any preset."})]})]})}),e.jsxs("div",{className:m("space-y-3",w==="off"&&"opacity-40 pointer-events-none"),children:[e.jsx(ts,{title:"Token Rules",children:x?e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsx(P,{label:"Bucket Capacity",value:String(x.bucket_capacity),type:"number",suffix:"tokens",min:1,max:100,tooltip:"Max tokens a source can hold — determines burst capacity. Each advert costs one token; tokens refill over time.",autoConfigured:R("bucket_capacity"),onSave:async d=>C("bucket_capacity",parseInt(d,10))}),e.jsx(P,{label:"Refill Tokens",value:String(x.refill_tokens),type:"number",suffix:"tokens",min:1,max:50,tooltip:"Tokens added back each refill cycle. Higher = more forgiving over time.",autoConfigured:R("refill_tokens"),onSave:async d=>C("refill_tokens",parseInt(d,10))}),e.jsx(P,{label:"Refill Interval",value:fe(x.refill_interval_seconds),editValue:String(parseFloat((x.refill_interval_seconds/3600).toFixed(2))),type:"number",suffix:"hr",step:.5,min:.5,max:24,tooltip:"How often the bucket gets topped up. Shorter = faster recovery from bursts.",autoConfigured:R("refill_interval_seconds"),onSave:async d=>C("refill_interval_seconds",Math.round(parseFloat(d)*3600))}),e.jsx(P,{label:"Min Interval",value:fe(x.min_interval_seconds),editValue:String(x.min_interval_seconds),type:"number",suffix:"sec",min:0,max:3600,tooltip:"Minimum gap between adverts from the same source, even if tokens are available. 0 = no minimum.",autoConfigured:R("min_interval_seconds"),onSave:async d=>C("min_interval_seconds",parseInt(d,10))})]}):e.jsx("p",{className:"type-body-sm text-fg-muted",children:"Not configured on this backend."})}),e.jsx(ts,{title:"Jail Settings",children:b?e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsx(P,{label:"Violation Threshold",value:String(b.violation_threshold),type:"number",suffix:"violations",min:1,max:100,tooltip:"How many rate-limit violations before a source gets penalized. Think of it as strikes before timeout.",autoConfigured:R("violation_threshold"),onSave:async d=>C("violation_threshold",parseInt(d,10))}),e.jsx(P,{label:"Base Penalty",value:fe(b.base_penalty_seconds),editValue:String(parseFloat((b.base_penalty_seconds/3600).toFixed(2))),type:"number",suffix:"hr",step:.5,min:.5,max:24,tooltip:"First offense penalty duration. Repeat offenders get this multiplied.",autoConfigured:R("base_penalty_seconds"),onSave:async d=>C("base_penalty_seconds",Math.round(parseFloat(d)*3600))}),e.jsx(P,{label:"Multiplier",value:`${b.penalty_multiplier}x`,editValue:String(b.penalty_multiplier),type:"number",suffix:"x",step:.5,min:1,max:10,tooltip:"Each repeat offense multiplies the penalty by this factor. 2x means penalties double each time.",autoConfigured:R("penalty_multiplier"),onSave:async d=>C("penalty_multiplier",parseFloat(d))}),e.jsx(P,{label:"Max Penalty",value:fe(b.max_penalty_seconds),editValue:String(parseFloat((b.max_penalty_seconds/3600).toFixed(2))),type:"number",suffix:"hr",step:1,min:1,max:168,tooltip:"Upper limit on penalty duration. No matter how many offenses, it won't exceed this.",autoConfigured:R("max_penalty_seconds"),onSave:async d=>C("max_penalty_seconds",Math.round(parseFloat(d)*3600))}),e.jsx(P,{label:"Violation Decay",value:fe(b.violation_decay_seconds),editValue:String(parseFloat((b.violation_decay_seconds/3600).toFixed(2))),type:"number",suffix:"hr",step:1,min:1,max:168,tooltip:"How long until a source's violation count resets. Good behavior earns a clean slate.",autoConfigured:R("violation_decay_seconds"),onSave:async d=>C("violation_decay_seconds",Math.round(parseFloat(d)*3600))})]}):e.jsx("p",{className:"type-body-sm text-fg-muted",children:"Not configured on this backend."})}),e.jsx(ts,{title:"Traffic Tiers",children:v?e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsx(P,{label:"EWMA α",value:String(v.ewma_alpha),type:"number",step:.01,min:.01,max:1,tooltip:"How quickly the system reacts to traffic changes. Lower = smoother, higher = more responsive.",autoConfigured:R("ewma_alpha"),onSave:async d=>C("ewma_alpha",parseFloat(d))}),e.jsx(P,{label:"Hysteresis",value:fe(v.hysteresis_seconds),editValue:String(parseFloat((v.hysteresis_seconds/60).toFixed(2))),type:"number",suffix:"min",step:.5,min:0,max:60,tooltip:"Cooldown before switching tiers again. Prevents rapid flip-flopping during traffic spikes.",autoConfigured:R("hysteresis_seconds"),onSave:async d=>C("hysteresis_seconds",Math.round(parseFloat(d)*60))}),e.jsx(P,{label:"Quiet Max",value:String(v.thresholds.quiet_max),type:"number",min:0,max:1e4,suffix:"pkts/hr",tooltip:"Traffic below this = quiet mesh. Rate limits are most relaxed here.",autoConfigured:R("quiet_max"),onSave:async d=>C("quiet_max",parseFloat(d))}),e.jsx(P,{label:"Normal Max",value:String(v.thresholds.normal_max),type:"number",min:0,max:1e4,suffix:"pkts/hr",tooltip:"Traffic below this = normal activity. Standard rate limits apply.",autoConfigured:R("normal_max"),onSave:async d=>C("normal_max",parseFloat(d))}),e.jsx(P,{label:"Busy Max",value:String(v.thresholds.busy_max),type:"number",min:0,max:1e4,suffix:"pkts/hr",tooltip:"Traffic above this = congested mesh. Strictest rate limits kick in.",autoConfigured:R("busy_max"),onSave:async d=>C("busy_max",parseFloat(d))})]}):e.jsx("p",{className:"type-body-sm text-fg-muted",children:"Not configured on this backend."})})]}),e.jsx("div",{className:"bg-sys-blue/5 radius-inner p-4 mt-4",children:e.jsxs("div",{className:"flex gap-3",children:[e.jsx("div",{className:"w-8 h-8 rounded-full bg-sys-blue/20 flex items-center justify-center flex-shrink-0",children:e.jsx(oe,{className:"w-4 h-4 text-sys-blue"})}),e.jsx("div",{className:"type-body-sm text-fg-muted",children:e.jsxs("p",{children:[e.jsx("span",{className:"text-fg-secondary",children:"Three layers"})," work together: the ",e.jsx("span",{className:"text-sys-blue",children:"Token Rules"})," throttle per-source adverts, the ",e.jsx("span",{className:"text-sys-amber",children:"Jail"})," escalates penalties for repeat violators, and ",e.jsx("span",{className:"text-sys-green",children:"Traffic Tiers"})," adjust limits based on overall mesh activity. The ",e.jsx("span",{className:"text-sys-blue",children:"“Auto”"})," button analyzes 1 week of mesh traffic to suggest optimal settings."]})})]})}),e.jsx(Bt,{open:F,onClose:()=>g(!1),currentConfig:{tokenBucket:x,penaltyBox:b,adaptive:v},onApplied:async()=>{k(new Set(Gt)),await Promise.all([l({force:!0}).catch(()=>{}),N()])}})]})}const Gs={off:{label:"Off",threshold:null,description:"No loop detection. All flood packets forwarded regardless of path history.",color:"text-fg-muted"},minimal:{label:"Minimal",threshold:4,description:"Drops flood packets when your local hash appears 4+ times in the path. Catches only the most obvious routing loops.",color:"text-sys-green",recommended:!0},moderate:{label:"Moderate",threshold:2,description:"Drops flood packets when your local hash appears 2+ times in the path. Good balance for most networks.",color:"text-sys-blue"},strict:{label:"Strict",threshold:1,description:"Drops flood packets if your local hash appears even once in the path. Strongest loop prevention — may drop some legitimate retransmissions in dense meshes.",color:"text-sys-amber"}},Sa=["off","minimal","moderate","strict"];function Ca(){var N;const{stats:t,fetchStats:l}=cs(),n=a.useRef(!0),c=(N=t==null?void 0:t.config)==null?void 0:N.mesh,i=!!c,o=(c==null?void 0:c.loop_detect)??"off",j=Gs[o],p=t==null?void 0:t.local_hash,[y,u]=a.useState(!1),[r,h]=a.useState(null),[F,g]=a.useState("idle"),E=a.useRef(null);if(a.useEffect(()=>(n.current=!0,()=>{n.current=!1,E.current&&clearTimeout(E.current)}),[]),a.useEffect(()=>{if(!r)return;const x=setTimeout(()=>{n.current&&h(null)},4e3);return()=>clearTimeout(x)},[r]),!t)return null;const k=async x=>{if(!(!i||x===o||y)){u(!0),h(null),E.current&&clearTimeout(E.current);try{const b=await Ws({loop_detect:x});if(!n.current)return;b.success?(g("success"),await l({force:!0}).catch(()=>{})):(g("error"),h(b.error||"Failed to save"))}catch{n.current&&(g("error"),h("Failed to save"))}finally{n.current&&(u(!1),E.current=setTimeout(()=>{n.current&&g("idle")},1500))}}};return e.jsxs(Y,{neomorphic:!0,children:[e.jsx(X,{icon:e.jsx(na,{}),title:"Flood Loop Detection",actions:F!=="idle"?e.jsxs("span",{className:"flex items-center",children:[F==="success"&&e.jsx(J,{className:"w-4 h-4 text-sys-green"}),F==="error"&&e.jsx(Z,{className:"w-4 h-4 text-sys-red"})]}):void 0}),!i&&e.jsxs("div",{className:"flex items-start gap-2.5 mb-3 px-3 py-2.5 radius-inner bg-sys-amber/10 text-sys-amber",children:[e.jsx(Le,{className:"w-4 h-4 mt-0.5 flex-shrink-0"}),e.jsxs("p",{className:"type-body-sm",children:["Backend does not expose mesh config. Update pyMC_Repeater to enable live configuration. Set ",e.jsx("code",{className:"font-mono text-fg-secondary",children:"loop_detect"})," in"," ",e.jsx("code",{className:"font-mono text-fg-secondary",children:"config.yaml"})," manually."]})]}),r&&e.jsx("div",{className:"type-body-sm mb-3 px-3 py-2 rounded-full text-sys-red bg-sys-red/10",children:r}),e.jsx("div",{className:m("toggle-group w-full mb-4",!i&&"opacity-50 pointer-events-none"),children:Sa.map(x=>{const b=Gs[x],v=x===o;return e.jsx("button",{onClick:()=>k(x),disabled:y||!i,className:m("toggle-group-item flex-1",v&&"active",v&&b.color),children:b.label},x)})}),e.jsx("div",{className:"bg-subtle-fill radius-inner p-4",children:e.jsxs("div",{className:"flex gap-3",children:[e.jsx("div",{className:"w-8 h-8 rounded-full bg-sys-blue/20 flex items-center justify-center flex-shrink-0",children:e.jsx(oe,{className:"w-4 h-4 text-sys-blue"})}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:m("type-data-xs font-medium uppercase tracking-wide",j.color),children:j.label}),j.threshold!==null&&e.jsxs("span",{className:"data-box data-box-compact text-fg-secondary tabular-nums",children:["≥",j.threshold,"× → drop"]}),j.recommended&&e.jsx(ns,{color:"green",children:"Recommended"})]}),e.jsx("p",{className:"type-body-sm text-fg-muted mt-1",children:j.description}),p&&o!=="off"&&e.jsxs("p",{className:"type-data-xs text-fg-muted/60 mt-2 font-mono",children:["Local hash: ",p]})]})]})})]})}function Ta(t){if(!t)return"Never";const l=new Date(t).getTime();if(isNaN(l))return"Never";const c=(Date.now()-l)/1e3;return c<60?"Just now":c<3600?`${Math.floor(c/60)}m ago`:c<86400?`${Math.floor(c/3600)}h ago`:`${Math.floor(c/86400)}d ago`}function Fa(){const{status:t,updateAvailable:l,isChecking:n,channels:c,changelog:i,error:o,available:j,checkForUpdate:p,fetchChannels:y,fetchChangelog:u,setChannel:r,openModal:h}=kt(),F=_t(),[g,E]=a.useState(!1),[k,N]=a.useState(!1);if(a.useEffect(()=>{y(),u()},[y,u]),!j)return null;const x=f=>f.split("+")[0],b=f=>f!=null&&f.includes("+")?f.split("+")[1]:null,v=(t==null?void 0:t.current_version)??(F==null?void 0:F.version)??null,R=(t==null?void 0:t.latest_version)??null,M=v?x(v):null,w=R?x(R):null,_=b(v),C=(t==null?void 0:t.channel)??"main";return e.jsxs(Y,{neomorphic:!0,children:[e.jsx(X,{icon:e.jsx(Os,{}),title:"Software Update"}),e.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-3 gap-4 mb-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-fg-secondary",children:"Installed"}),e.jsxs("div",{className:"flex items-center gap-1.5 mt-0.5",children:[e.jsx("p",{className:"type-data text-fg-primary truncate font-mono",children:M?`v${M}`:"—"}),_&&e.jsx(St,{copy:!0,copyValue:_,title:`Build: ${_}`,children:_})]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-fg-secondary",children:"Git Branch"}),e.jsxs("div",{className:"mt-0.5 flex items-center gap-1.5",children:[e.jsx(la,{className:"w-3.5 h-3.5 text-sys-indigo flex-shrink-0"}),e.jsx("span",{className:"type-data text-sys-indigo truncate",children:C})]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-fg-secondary",children:"Last Checked"}),e.jsxs("div",{className:"mt-0.5 flex items-center gap-1.5",children:[e.jsx(ra,{className:"w-3.5 h-3.5 text-fg-muted flex-shrink-0"}),e.jsx("span",{className:"type-data text-fg-muted",children:Ta((t==null?void 0:t.last_checked)??null)})]})]})]}),c.length>0&&e.jsxs("div",{className:"bg-subtle-fill radius-inner p-4 mb-4",children:[e.jsx("div",{className:"flex items-center justify-between gap-3",children:e.jsxs("div",{children:[e.jsx("h4",{className:"type-body-sm text-fg-primary font-medium",children:"Release Channel"}),e.jsx("p",{className:"type-data-xs text-fg-muted mt-0.5",children:"Switch between stable and development branches"})]})}),e.jsx("div",{className:"flex flex-wrap gap-2 mt-3",children:c.map(f=>e.jsxs("button",{onClick:async()=>{f.active||k||(N(!0),await r(f.name),N(!1))},disabled:f.active||k,className:m("px-3 py-1.5 radius-inner type-data-xs font-medium transition-colors",f.active?"bg-sys-indigo/15 text-sys-indigo ring-1 ring-sys-indigo/30":"bg-subtle-fill-strong text-fg-muted hover:text-fg-primary hover:bg-subtle-fill-hover",k&&!f.active&&"opacity-50 cursor-not-allowed"),children:[f.name,f.active&&e.jsx(ls,{className:"w-3 h-3 ml-1.5 inline-block"})]},f.name))})]}),i.length>0&&e.jsxs("div",{className:"bg-subtle-fill radius-inner mb-4",children:[e.jsxs("button",{onClick:()=>E(!g),className:"w-full flex items-center gap-2 px-4 py-3 text-left hover:bg-subtle-fill-hover transition-colors radius-inner",children:[g?e.jsx(Ke,{className:"w-4 h-4 text-fg-muted flex-shrink-0"}):e.jsx(Js,{className:"w-4 h-4 text-fg-muted flex-shrink-0"}),e.jsx("span",{className:"type-body-sm text-fg-primary font-medium flex-1",children:"Changelog"}),e.jsxs("span",{className:"type-data-xs text-fg-muted",children:[i.length," commit",i.length!==1?"s":""]})]}),g&&e.jsx("div",{className:"px-4 pb-3 space-y-1 max-h-[300px] overflow-y-auto",children:i.map(f=>e.jsxs("div",{className:"flex items-start gap-2 py-1.5 group",children:[e.jsx(ma,{className:"w-3.5 h-3.5 text-fg-muted flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[f.url?e.jsx("a",{href:f.url,target:"_blank",rel:"noopener noreferrer",className:"type-data-xs text-fg-primary truncate hover:text-sys-blue transition-colors",children:f.title}):e.jsx("p",{className:"type-data-xs text-fg-primary truncate",children:f.title}),f.url&&e.jsx("a",{href:f.url,target:"_blank",rel:"noopener noreferrer",className:"opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0",children:e.jsx(Qs,{className:"w-3 h-3 text-fg-muted"})})]}),f.body&&e.jsx("p",{className:"type-data-xs text-fg-muted mt-0.5 line-clamp-2 whitespace-pre-line",children:f.body}),e.jsxs("div",{className:"flex items-center gap-2 mt-0.5",children:[e.jsx("span",{className:"type-data-xs text-fg-muted font-mono",children:f.short_sha}),e.jsx("span",{className:"text-fg-muted/30",children:"·"}),e.jsx("span",{className:"type-data-xs text-fg-muted",children:f.author}),e.jsx("span",{className:"text-fg-muted/30",children:"·"}),e.jsx("span",{className:"type-data-xs text-fg-muted",children:f.date?new Date(f.date).toLocaleDateString():""})]})]})]},f.sha))})]}),o&&e.jsx("div",{className:"type-body-sm mb-3 px-3 py-2 rounded-full text-sys-red bg-sys-red/10",children:o}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[l&&e.jsxs(L,{color:"danger",onClick:h,children:[e.jsx(Os,{"data-slot":"icon"}),"Update to v",w]}),e.jsx("div",{className:"flex-1"}),!l&&t&&e.jsxs("span",{className:"flex items-center gap-1.5 type-data-xs text-sys-green",children:[e.jsx(ls,{className:"w-3.5 h-3.5"}),"Up to date"]}),e.jsx(L,{color:"primary",outline:!0,onClick:()=>p(!0),disabled:n,children:n?e.jsxs(e.Fragment,{children:[e.jsx(U,{"data-slot":"icon",className:"animate-spin"}),"Checking..."]}):e.jsxs(e.Fragment,{children:[e.jsx(Xs,{"data-slot":"icon"}),"Check for Updates"]})})]})]})}const Ea=[{value:7.8,label:"7.8 kHz"},{value:10.4,label:"10.4 kHz"},{value:15.6,label:"15.6 kHz"},{value:20.8,label:"20.8 kHz"},{value:31.25,label:"31.25 kHz"},{value:41.7,label:"41.7 kHz"},{value:62.5,label:"62.5 kHz"},{value:125,label:"125 kHz"},{value:250,label:"250 kHz"},{value:500,label:"500 kHz"}],Ra=[5,6,7,8,9,10,11,12],Ma=[{value:5,label:"4/5"},{value:6,label:"4/6"},{value:7,label:"4/7"},{value:8,label:"4/8"}],Da=[{value:0,label:"1-byte — 0x00"},{value:1,label:"2-byte — 0x0000"},{value:2,label:"3-byte — 0x000000"}],Us={RADIO_CONFIG:"radioConfig"};function Aa(t){if(!t)return"Never";const n=Date.now()-t*1e3,c=Math.floor(n/6e4),i=Math.floor(n/36e5),o=Math.floor(n/864e5);return c<1?"Just now":c<60?`${c}m ago`:i<24?`${i}h ago`:o<365?`${o}d ago`:`${Math.floor(o/365)}y ago`}function et({node:t,level:l,expandedKeys:n,selectedKeyId:c,globalFloodPolicy:i,onSelect:o,onToggle:j}){const p=n.has(t.id),y=c===t.id,u=t.children&&t.children.length>0,r=i==="allow";return e.jsxs("div",{children:[e.jsxs("div",{className:m("flex items-center gap-2 h-[36px] px-3 rounded-full cursor-pointer transition-colors",y?"bg-sys-blue/15":"hover:bg-subtle-fill",r&&"opacity-50 cursor-not-allowed"),style:{marginLeft:`${l*16}px`},onClick:()=>!r&&o(t.id),children:[u?e.jsx("button",{onClick:h=>{h.stopPropagation(),j(t.id)},className:"p-1 hover:bg-subtle-fill-hover rounded-full transition-colors",children:e.jsx(Js,{className:m("w-3.5 h-3.5 text-fg-muted transition-transform",p&&"rotate-90")})}):e.jsx("span",{className:"w-5"}),e.jsx(da,{className:"w-4 h-4 text-sys-blue flex-shrink-0"}),e.jsx("span",{className:"type-data text-fg-primary flex-1 truncate",children:t.name}),e.jsx("span",{className:"type-data-xs text-fg-muted hidden sm:inline",title:t.last_used?new Date(t.last_used*1e3).toLocaleString():void 0,children:Aa(t.last_used)}),e.jsx("span",{className:m("type-data-xs px-2 py-0.5 rounded-full",t.floodPolicy==="allow"?"bg-sys-green/15 text-sys-green":"bg-sys-red/15 text-sys-red"),children:t.floodPolicy==="allow"?"Allow":"Deny"})]}),u&&p&&e.jsx("div",{children:t.children.map(h=>e.jsx(et,{node:h,level:l+1,expandedKeys:n,selectedKeyId:c,globalFloodPolicy:i,onSelect:o,onToggle:j},h.id))})]})}function Pa(){const[t,l]=a.useState(Wt),[n,c]=a.useState(Xt),[i,o]=a.useState(!1),j=a.useCallback(u=>{l(u),Yt(u)},[]),p=a.useCallback(u=>{const r=parseFloat(u.target.value);c(r),Jt(r)},[]),y=a.useCallback(async()=>{i||(o(!0),await Qt(),o(!1))},[i]);return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx(xe,{enabled:t,onChange:j,label:e.jsxs(e.Fragment,{children:["Sound: ",e.jsx("span",{className:t?"text-sys-green":"text-sys-red",children:t?"On":"Off"})]}),tooltip:"Enable or disable UI sound effects and haptic audio feedback",size:"md"}),e.jsx(L,{color:"primary",outline:!0,onClick:y,disabled:!t||i,className:"w-16 justify-center",children:i?"…":"Test"})]}),e.jsxs("div",{className:m("flex items-center gap-3",!t&&"opacity-40 pointer-events-none"),children:[e.jsx("span",{className:"type-label text-fg-muted w-14 shrink-0",children:"Volume"}),e.jsx("input",{type:"range",min:0,max:1,step:.05,value:n,onChange:p,className:"flex-1 accent-sys-blue h-1.5 cursor-pointer"}),e.jsxs("span",{className:"data-box w-16 justify-center",children:[Math.round(n*100),"%"]})]})]})}function tn(){var Cs,Ts,Fs,Es,Rs,Ms,Ds,As,Ps,Ls;const{stats:t,setMode:l,clearModeMutation:n,setDutyCycleConfig:c,clearDutyCycleMutation:i,fetchStats:o,startMutation:j,clearMutation:p}=cs(),y=Ct(),u=(Cs=t==null?void 0:t.config)==null?void 0:Cs.radio,r=(Ts=t==null?void 0:t.config)==null?void 0:Ts.repeater,h=(Fs=t==null?void 0:t.config)==null?void 0:Fs.duty_cycle,F=(t==null?void 0:t.node_name)||((Es=t==null?void 0:t.config)==null?void 0:Es.node_name)||"Unknown Node",g=(r==null?void 0:r.mode)??"forward",E=(h==null?void 0:h.enforcement_enabled)??!1,k=(Rs=t==null?void 0:t.config)==null?void 0:Rs.delays,N=a.useRef(!0);a.useEffect(()=>(N.current=!0,()=>{N.current=!1}),[]);const x=(Ms=t==null?void 0:t.config)==null?void 0:Ms.web,[b,v]=a.useState([]),[R,M]=a.useState(!1),[w,_]=a.useState(null),[C,f]=a.useState(!1),[A,S]=a.useState(""),[I,V]=a.useState(null),[H,K]=a.useState(!1),[ee,d]=a.useState(null),[O,W]=a.useState(!1),[ds,us]=a.useState(!1),[ms,fs]=a.useState(!1),[te,st]=a.useState([]),[tt,xs]=a.useState(!1),[hs,$]=a.useState(null),[ne,at]=a.useState(()=>localStorage.getItem("pymc:globalFloodPolicy")==="allow"?"allow":"deny"),ps=a.useCallback(s=>{at(s),localStorage.setItem("pymc:globalFloodPolicy",s)},[]),[ys,gs]=a.useState(!1),[B,Ve]=a.useState(null),[nt,lt]=a.useState(new Set),[_e,ge]=a.useState(!1),[Se,ce]=a.useState(!1),[Ce,de]=a.useState(!1),[q,ae]=a.useState(null),[le,be]=a.useState(null),[Te,Fe]=a.useState(""),[$e,je]=a.useState("allow"),[Q,ue]=a.useState(!1),[Ee,bs]=a.useState(!0),[ve,He]=a.useState(!1),[rt,js]=a.useState(!0),[Ne,re]=a.useState("idle"),[it,qe]=a.useState(!1),[Be,ot]=a.useState(!1),vs=a.useCallback(()=>{const s=k==null?void 0:k.tx_delay_factor;return s&&typeof s=="object"&&"parsedValue"in s?s.parsedValue??1:typeof s=="number"?s:1},[k]),Ns=a.useCallback(()=>{const s=k==null?void 0:k.direct_tx_delay_factor;return typeof s=="number"?s:.5},[k]),Ge=a.useCallback(()=>{const s=h==null?void 0:h.max_airtime_percent;return typeof s=="number"?s:s&&typeof s=="object"&&"parsedValue"in s?s.parsedValue??6:6},[h]),Ue=ss(g==="forward",async s=>{await l(s?"forward":"monitor")},n),We=ss(E,async s=>{await c({max_airtime_percent:Ge(),enforcement_enabled:s})},i),Xe=ss((x==null?void 0:x.cors_enabled)??!1,async s=>{var D;const T=await qs({web:{cors_enabled:s}});if(!T.success&&!((D=T.data)!=null&&D.persisted))throw new Error("CORS update failed");await o()}),G=a.useCallback(async s=>{j(Us.RADIO_CONFIG);try{const T=await Ws(s);if(!T.success)throw new Error(T.error||"Failed to save");await o({force:!0}).catch(()=>{})}finally{p(Us.RADIO_CONFIG)}},[j,p,o]);a.useEffect(()=>{(async()=>{js(!0);try{const T=await It();T.success&&T.data?He(T.data.exists):He(!1);const D=x==null?void 0:x.web_path;bs(!D||D==="")}catch{He(!1)}finally{js(!1)}})()},[x==null?void 0:x.web_path]);const ws=async s=>{var T;if(Ne!=="loading"){re("loading");try{const D=await qs({web:{web_path:s?null:"/opt/pymc_console/web/html"}});if(!N.current)return;D.success||(T=D.data)!=null&&T.persisted?(bs(s),re("success"),qe(!0),setTimeout(()=>{N.current&&re("idle")},2e3)):(re("error"),setTimeout(()=>{N.current&&re("idle")},2e3))}catch{if(!N.current)return;re("error"),setTimeout(()=>{N.current&&re("idle")},2e3)}}},ct=async()=>{if(!Be){ot(!0);try{await Kt(),qe(!1),setTimeout(()=>{window.location.reload()},2e3)}catch{qe(!1),setTimeout(()=>{window.location.reload()},3e3)}}},Re=a.useCallback(async()=>{M(!0),_(null);try{const s=await ya();v(s.tokens||[])}catch(s){_(s instanceof Error?s.message:"Failed to fetch tokens")}finally{M(!1)}},[]);a.useEffect(()=>{Re()},[Re]);const ks=async()=>{if(!A.trim()){_("Token name is required");return}W(!0),_(null);try{const s=await ga(A.trim());V(s.token||null),f(!1),K(!0),S(""),await Re()}catch(s){_(s instanceof Error?s.message:"Failed to create token")}finally{W(!1)}},dt=async()=>{if(ee){us(!0),_(null);try{await ba(ee.id),await Re(),d(null)}catch(s){_(s instanceof Error?s.message:"Failed to revoke token")}finally{us(!1)}}},ut=async()=>{I&&(await At(I),fs(!0),setTimeout(()=>fs(!1),2e3))},mt=s=>s?new Date(s*1e3).toLocaleString():"Never",_s=a.useCallback(s=>{const T=new Map,D=[];return s.forEach(z=>{const Me={id:z.id,name:z.name,floodPolicy:z.flood_policy,transport_key:z.transport_key,last_used:z.last_used,parent_id:z.parent_id,children:[]};T.set(z.id,Me)}),T.forEach(z=>{z.parent_id&&T.has(z.parent_id)?T.get(z.parent_id).children.push(z):D.push(z)}),D},[]),we=a.useCallback(async()=>{xs(!0),$(null);try{const s=await Pt();if(s.success&&s.data){const T=_s(s.data);st(T),Ve(D=>{if(D===null)return null;const z=Me=>{for(const Ye of Me)if(Ye.id===D||Ye.children&&z(Ye.children))return!0;return!1};return z(T)?D:null})}else $(s.error||"Failed to load transport keys")}catch(s){$(s instanceof Error?s.message:"Unknown error occurred")}finally{xs(!1)}},[_s]);a.useEffect(()=>{we(),Lt().then(s=>{s.success&&s.data&&ps(s.data.global_flood_allow?"allow":"deny")}).catch(()=>{})},[we]);const ie=a.useCallback((s,T)=>{for(const D of s){if(D.id===T)return D;if(D.children){const z=ie(D.children,T);if(z)return z}}return null},[]),ft=a.useCallback(()=>{if(!B)return;const s=ie(te,B);return s==null?void 0:s.name},[B,te,ie]),xt=a.useCallback(s=>{lt(T=>{const D=new Set(T);return D.has(s)?D.delete(s):D.add(s),D})},[]),ht=async s=>{gs(!0),$(null);try{const T=await Ot(s==="allow");T.success?ps(s):$(T.error||"Failed to update global flood policy")}catch(T){$(T instanceof Error?T.message:"Failed to update global flood policy")}finally{gs(!1)}},Ss=async()=>{if(!Te.trim()){$("Key name is required");return}ue(!0),$(null);try{const s=await zt({name:Te.trim(),flood_policy:$e,parent_id:B??void 0});s.success?(await we(),ge(!1),Fe(""),je("allow")):$(s.error||"Failed to add transport key")}catch(s){$(s instanceof Error?s.message:"Failed to add transport key")}finally{ue(!1)}},pt=async()=>{if(q){ue(!0),$(null);try{const s=await Vt(q.id,{name:q.name,flood_policy:q.floodPolicy});s.success?(await we(),ce(!1),ae(null)):$(s.error||"Failed to update transport key")}catch(s){$(s instanceof Error?s.message:"Failed to update transport key")}finally{ue(!1)}}},yt=async()=>{if(le){ue(!0),$(null);try{const s=await $t(le.id);s.success?(await we(),de(!1),be(null),Ve(null)):$(s.error||"Failed to delete transport key")}catch(s){$(s instanceof Error?s.message:"Failed to delete transport key")}finally{ue(!1)}}},gt=a.useCallback(()=>{if(!B)return;const s=ie(te,B);s&&(ae({...s}),ce(!0))},[B,te,ie]);a.useEffect(()=>{const s=D=>{D.key==="Escape"&&(_e&&(ge(!1),Fe(""),je("allow")),Se&&(ce(!1),ae(null)),Ce&&(de(!1),be(null)),C&&(f(!1),S("")),H&&(K(!1),V(null)))};if(_e||Se||Ce||C||H)return window.addEventListener("keydown",s),()=>window.removeEventListener("keydown",s)},[_e,Se,Ce,C,H]);const bt=a.useCallback(()=>{if(!B)return;const s=ie(te,B);s&&(be(s),de(!0))},[B,te,ie]);return e.jsxs(Zt,{children:[e.jsx(ea,{title:"Configuration",icon:e.jsx(zs,{})}),e.jsxs(sa,{ready:y,children:[e.jsxs(se,{template:"standard",children:[e.jsx(me,{span:12,md:6,children:e.jsxs(Y,{neomorphic:!0,children:[e.jsx(X,{icon:e.jsx(Tt,{}),title:"Repeater Settings"}),r?e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsx("div",{className:"col-span-2",children:e.jsx(P,{label:"Node Name",value:F,onSave:async s=>G({node_name:s}),placeholder:"Enter node name",maxLength:50})}),e.jsx(P,{label:"Latitude",value:r.latitude!==0?r.latitude.toFixed(6):"Not set",editValue:String(r.latitude),type:"number",suffix:"°",step:1e-6,min:-90,max:90,onSave:async s=>G({latitude:parseFloat(s)})}),e.jsx(P,{label:"Longitude",value:r.longitude!==0?r.longitude.toFixed(6):"Not set",editValue:String(r.longitude),type:"number",suffix:"°",step:1e-6,min:-180,max:180,onSave:async s=>G({longitude:parseFloat(s)})}),e.jsx(P,{label:"Advert Interval",value:r.send_advert_interval_hours>0?`${r.send_advert_interval_hours}h`:"Disabled",editValue:String(r.send_advert_interval_hours),type:"number",suffix:"hours",min:0,max:48,description:"0 = disabled, 3-48 hours",onSave:async s=>G({flood_advert_interval_hours:parseInt(s,10)})}),e.jsx(P,{label:"Score-based TX",value:r.use_score_for_tx?"Enabled":"Disabled",readOnly:!0})]}):e.jsx("p",{className:"text-fg-muted",children:"Loading repeater settings..."})]})}),e.jsx(me,{span:12,md:6,children:e.jsxs(Y,{neomorphic:!0,children:[e.jsx(X,{icon:e.jsx(ia,{}),title:"Radio Configuration"}),u?e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsx(P,{label:"Frequency",value:Ft(u.frequency),editValue:(u.frequency/1e6).toFixed(3),type:"number",suffix:"MHz",step:.001,min:400,max:930,onSave:async s=>G({frequency_mhz:parseFloat(s)})}),e.jsx(P,{label:"TX Power",value:`${u.tx_power} dBm`,editValue:String(u.tx_power),type:"number",suffix:"dBm",min:2,max:30,onSave:async s=>G({tx_power:parseInt(s,10)})}),e.jsx(Ae,{label:"Bandwidth",value:Et(u.bandwidth),editValue:u.bandwidth/1e3,options:Ea,onSave:async s=>G({bandwidth_khz:parseFloat(s)})}),e.jsx(Ae,{label:"Spreading Factor",value:`SF${u.spreading_factor}`,editValue:u.spreading_factor,options:Ra.map(s=>({value:s,label:`SF${s}`})),onSave:async s=>G({spreading_factor:parseInt(s,10)})}),e.jsx(Ae,{label:"Coding Rate",value:`4/${u.coding_rate}`,editValue:u.coding_rate,options:Ma,onSave:async s=>G({coding_rate:parseInt(s,10)})}),e.jsx(P,{label:"Preamble",value:`${u.preamble_length} symbols`,readOnly:!0})]}):e.jsx("p",{className:"text-fg-muted",children:"Loading radio configuration..."})]})})]}),e.jsxs(se,{template:"standard",children:[e.jsx(me,{span:12,md:6,children:e.jsxs(Y,{neomorphic:!0,children:[e.jsx(X,{icon:e.jsx(Rt,{}),title:"Operating Mode"}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsx(xe,{enabled:Ue.enabled,onChange:Ue.toggle,label:"Repeat",tooltip:"Toggles repeater or monitor mode. In monitor mode, the repeater will not repeat packets from the mesh.",status:Ue.status,size:"md"}),e.jsx(xe,{enabled:We.enabled,onChange:We.toggle,label:"Duty Cycle",tooltip:"Limit transmission time to comply with airtime utilization regulations",status:We.status,size:"md"}),e.jsx(P,{label:"Max Airtime",value:`${Ge().toFixed(1)}%`,editValue:String(Ge()),type:"number",suffix:"%",step:.5,min:.1,max:100,onSave:async s=>{await c({max_airtime_percent:parseFloat(s),enforcement_enabled:E}),i()}}),e.jsx(P,{label:"Flood TX Delay",value:`${vs().toFixed(2)}x`,editValue:String(vs()),type:"number",suffix:"x",step:.1,min:0,max:5,onSave:async s=>G({tx_delay_factor:parseFloat(s)})}),e.jsx(P,{label:"Direct TX Delay",value:`${Ns().toFixed(2)}s`,editValue:String(Ns()),type:"number",suffix:"s",step:.1,min:0,max:5,onSave:async s=>G({direct_tx_delay_factor:parseFloat(s)})}),e.jsx(P,{label:"Max Flood Hops",value:String((r==null?void 0:r.max_flood_hops)??3),type:"number",min:0,max:64,description:"0–64 hops",onSave:async s=>G({max_flood_hops:parseInt(s,10)})})]}),e.jsx("div",{className:"mt-4",children:e.jsx(Ae,{label:"Path Hash Size",value:`${(((As=(Ds=t==null?void 0:t.config)==null?void 0:Ds.mesh)==null?void 0:As.path_hash_mode)??0)+1}-byte`,editValue:((Ls=(Ps=t==null?void 0:t.config)==null?void 0:Ps.mesh)==null?void 0:Ls.path_hash_mode)??0,options:Da,onSave:async s=>G({path_hash_mode:parseInt(s,10)})})})]})}),e.jsx(me,{span:12,md:6,children:e.jsxs(Y,{neomorphic:!0,children:[e.jsx(X,{icon:e.jsx(zs,{}),title:"App Settings"}),e.jsx("p",{className:"type-body-sm text-fg-muted mb-4",children:"Appearance and web server options."}),e.jsxs("div",{className:"space-y-4",children:[e.jsx(xe,{enabled:Xe.enabled,onChange:Xe.toggle,label:"Enable CORS",tooltip:"Allow cross-origin API access",status:Xe.status,size:"md"}),e.jsx("div",{children:e.jsx(va,{})}),e.jsx(Pa,{})]})]})})]}),e.jsx(se,{template:"auto",children:e.jsx(_a,{})}),e.jsx(se,{template:"auto",children:e.jsxs(Y,{neomorphic:!0,children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4",children:[e.jsx(X,{icon:e.jsx(Vs,{}),title:"Regions Transport Keys"}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsxs(L,{color:"primary",outline:!0,onClick:()=>ge(!0),disabled:ne==="allow",children:[e.jsx($s,{"data-slot":"icon"}),"Add"]}),e.jsx(L,{color:"primary",outline:!0,onClick:gt,disabled:!B||ne==="allow",children:"Edit"}),e.jsx(L,{color:"danger",outline:!0,onClick:bt,disabled:!B||ne==="allow",children:"Delete"})]})]}),e.jsx("div",{className:"bg-subtle-fill radius-inner p-4 mb-4",children:e.jsx(xe,{enabled:ne==="deny",onChange:s=>ht(s?"deny":"allow"),label:e.jsxs(e.Fragment,{children:["Require Transport Keys: ",e.jsx("span",{className:ne==="deny"?"text-sys-green":"text-sys-red",children:ne==="deny"?"On":"Off"})]}),tooltip:"When enabled, only packets with matching transport keys are forwarded. When disabled, all packets flood freely.",status:ys?"loading":"idle",disabled:ys,dangerOff:!0,size:"md",className:"flex-row-reverse justify-between w-full"})}),hs&&e.jsx("div",{className:"type-body-sm mb-3 px-3 py-2 rounded-full text-sys-red bg-sys-red/10",children:hs}),e.jsx("div",{className:"bg-subtle-fill radius-inner p-4 min-h-[120px]",children:tt?e.jsxs("div",{className:"flex items-center justify-center py-6",children:[e.jsx(U,{className:"w-5 h-5 animate-spin text-sys-blue mr-2"}),e.jsx("span",{className:"type-body-sm text-fg-muted",children:"Loading transport keys..."})]}):te.length===0?e.jsxs("div",{className:"text-center py-6",children:[e.jsx("div",{className:"w-12 h-12 rounded-full bg-subtle-fill mx-auto mb-3 flex items-center justify-center",children:e.jsx(Vs,{className:"w-6 h-6 text-fg-muted/50"})}),e.jsx("p",{className:"type-body text-fg-muted",children:"No transport keys found"}),e.jsx("p",{className:"type-body-sm text-fg-muted/70 mt-1",children:"Add your first transport key to get started"})]}):e.jsx("div",{className:"space-y-1",children:te.map(s=>e.jsx(et,{node:s,level:0,expandedKeys:nt,selectedKeyId:B,globalFloodPolicy:ne,onSelect:Ve,onToggle:xt},s.id))})})]})}),e.jsxs(se,{template:"standard",children:[e.jsx(me,{span:12,md:6,children:e.jsx(Ca,{})}),e.jsx(me,{span:12,md:6,children:e.jsxs(Y,{neomorphic:!0,className:"h-full flex flex-col",children:[e.jsx(X,{icon:e.jsx(Hs,{}),title:"API Tokens"}),w&&e.jsx("div",{className:"type-body-sm mb-3 px-3 py-2 rounded-full text-sys-red bg-sys-red/10",children:w}),e.jsx("div",{className:"flex-1 flex flex-col min-h-0",children:R&&b.length===0?e.jsxs("div",{className:"flex-1 flex items-center justify-center",children:[e.jsx(U,{className:"w-4 h-4 animate-spin text-sys-blue mr-2"}),e.jsx("span",{className:"type-body-sm text-fg-muted",children:"Loading tokens..."})]}):b.length>0?e.jsx("div",{className:"space-y-1.5 flex-1 overflow-y-auto mb-3",children:b.map(s=>e.jsxs("div",{className:"bg-subtle-fill hover:bg-subtle-fill-strong radius-inner px-3 py-2 transition-base flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("h3",{className:"type-body-sm text-fg-primary font-medium truncate",children:s.name}),e.jsxs("span",{className:"type-data-xs text-fg-muted truncate",children:["Last used: ",mt(s.last_used)]})]}),e.jsx("button",{type:"button",onClick:()=>d({id:s.id,name:s.name}),disabled:ds,className:"text-sys-red/70 hover:text-sys-red transition-colors flex-shrink-0 p-1",title:"Revoke token",children:e.jsx(Ys,{className:"w-3.5 h-3.5"})})]},s.id))}):e.jsxs("div",{className:"bg-subtle-fill radius-inner flex-1 flex flex-col items-center justify-center mb-3",children:[e.jsx(Hs,{className:"w-5 h-5 text-fg-muted/50 mb-2"}),e.jsx("p",{className:"type-body-sm text-fg-muted",children:"No API tokens"})]})}),e.jsxs(L,{color:"primary",outline:!0,onClick:()=>f(!0),className:"w-full justify-center mt-auto",children:[e.jsx($s,{"data-slot":"icon"}),"Create Token"]})]})})]}),e.jsx(se,{template:"auto",children:e.jsxs(Y,{neomorphic:!0,children:[e.jsx(X,{icon:e.jsx(xa,{}),title:"Web Frontend"}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-3",children:[e.jsxs("label",{className:m("flex items-start gap-3 p-4 bg-subtle-fill radius-card border-2 cursor-pointer transition-base",Ee?"border-sys-blue bg-sys-blue/5":"border-transparent hover:border-sys-blue/30",Ne==="loading"&&"opacity-50 pointer-events-none"),children:[e.jsx("input",{type:"radio",name:"frontend",checked:Ee,onChange:()=>ws(!0),disabled:Ne==="loading",className:"mt-1 h-4 w-4 text-sys-blue focus:ring-sys-blue focus:ring-offset-bg-elevated"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("div",{className:"type-body text-fg-primary font-medium",children:"Default Frontend"}),e.jsx("a",{href:"https://github.com/rightup/pyMC_Repeater",target:"_blank",rel:"noopener noreferrer",onClick:s=>s.stopPropagation(),className:"type-data-xs bg-sys-cyan/15 text-sys-cyan px-2.5 py-0.5 rounded-full font-medium hover:bg-sys-cyan/25 transition-colors",children:"@RightUp"})]}),e.jsx("div",{className:"type-body-sm text-fg-muted mt-1",children:"Built-in pyMC Repeater web interface"}),e.jsx("div",{className:"type-data-xs text-fg-muted/60 mt-1",children:"/opt/pymc_repeater/repeater/web/html"})]})]}),e.jsxs("label",{className:m("flex items-start gap-3 p-4 bg-subtle-fill radius-card border-2 cursor-pointer transition-base",Ee?"border-transparent hover:border-sys-blue/30":"border-sys-blue bg-sys-blue/5",Ne==="loading"&&"opacity-50 pointer-events-none"),children:[e.jsx("input",{type:"radio",name:"frontend",checked:!Ee,onChange:()=>ws(!1),disabled:Ne==="loading",className:"mt-1 h-4 w-4 text-sys-blue focus:ring-sys-blue focus:ring-offset-bg-elevated"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("div",{className:"type-body text-fg-primary font-medium",children:"PyMC Console"}),e.jsx("span",{className:"type-data-xs bg-sys-indigo/15 text-sys-indigo px-2.5 py-0.5 rounded-full font-medium",children:"@Treehouse ⚡"})]}),e.jsx("div",{className:"type-body-sm text-fg-muted mt-1",children:"Alternative web interface for pyMC Repeater"}),e.jsx("div",{className:"type-data-xs text-fg-muted/60 mt-1",children:"/opt/pymc_console/web/html"})]})]})]}),!rt&&e.jsx("div",{className:m("bg-subtle-fill radius-card p-4",ve?"border border-sys-green/20":"border border-sys-cyan/20"),children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:m("w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0",ve?"bg-sys-green/20":"bg-sys-cyan/20"),children:ve?e.jsx(ls,{className:"w-4 h-4 text-sys-green"}):e.jsx(oe,{className:"w-4 h-4 text-sys-cyan"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h4",{className:"type-body text-fg-primary font-medium",children:ve?"PyMC Console has been detected":"PyMC Console Not Installed"}),ve?e.jsxs("p",{className:"type-body-sm text-fg-muted mt-1",children:["PyMC Console is installed at ",e.jsx("code",{className:"type-code bg-sys-green/10 px-1.5 py-0.5 rounded-full text-sys-green",children:"/opt/pymc_console/web/html"})]}):e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"type-body-sm text-fg-muted mt-1 mb-3",children:["PyMC Console must be installed at ",e.jsx("code",{className:"type-code bg-sys-cyan/10 px-1.5 py-0.5 rounded-full text-sys-cyan",children:"/opt/pymc_console/web/html"})," before selecting this option."]}),e.jsxs(L,{color:"primary",outline:!0,href:"https://github.com/dmduran12/pymc_console-dist",children:[e.jsx(Qs,{"data-slot":"icon"}),"PyMC Console Install Instructions"]})]})]})]})}),it&&e.jsx("div",{className:"bg-subtle-fill radius-card p-4 border border-sys-indigo/30",children:e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3",children:[e.jsxs("div",{className:"flex items-start gap-3 flex-1",children:[e.jsx("div",{className:"w-8 h-8 rounded-full bg-sys-indigo/20 flex items-center justify-center flex-shrink-0",children:e.jsx(Le,{className:"w-4 h-4 text-sys-indigo"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h4",{className:"type-body text-fg-primary font-medium",children:"Service restart required"}),e.jsx("p",{className:"type-body-sm text-fg-muted mt-1",children:"Web frontend changes will take effect after restarting the pymc-repeater service."})]})]}),e.jsx(L,{color:"warning",outline:!0,onClick:ct,disabled:Be,children:Be?e.jsxs(e.Fragment,{children:[e.jsx(U,{"data-slot":"icon",className:"animate-spin"}),"Restarting..."]}):e.jsxs(e.Fragment,{children:[e.jsx(Xs,{"data-slot":"icon"}),"Restart Now"]})})]})})]})]})}),e.jsx(se,{template:"auto",children:e.jsx(Fa,{})}),t&&e.jsx(se,{template:"auto",children:e.jsx(Ut,{nodeName:F,publicKey:t.public_key})}),t&&((r==null?void 0:r.latitude)===0||!(r!=null&&r.latitude))&&((r==null?void 0:r.longitude)===0||!(r!=null&&r.longitude))&&e.jsx(se,{template:"auto",children:e.jsx(wa,{})})]}),C&&e.jsx("div",{className:"fixed inset-0 z-[10010] flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm",onClick:s=>s.target===s.currentTarget&&f(!1),role:"dialog","aria-modal":"true","aria-labelledby":"create-token-modal-title",children:e.jsxs("div",{className:"surface-modal radius-card p-6 max-w-md w-full",children:[e.jsx("h3",{id:"create-token-modal-title",className:"type-micro mb-4",children:"Create API Token"}),e.jsxs("div",{className:"space-y-4",children:[e.jsx(Je,{label:"Token Name",type:"text",value:A,onChange:s=>S(s.target.value),placeholder:"e.g., Production Server, CI/CD Pipeline",description:"Give your token a descriptive name to identify its purpose",onKeyDown:s=>s.key==="Enter"&&ks(),autoFocus:!0}),e.jsxs("div",{className:"flex justify-end gap-3 mt-6",children:[e.jsx(L,{color:"muted",outline:!0,onClick:()=>{f(!1),S(""),_(null)},disabled:O,children:"Cancel"}),e.jsx(L,{color:"primary",onClick:ks,disabled:O||!A.trim(),children:O?e.jsxs(e.Fragment,{children:[e.jsx(U,{"data-slot":"icon",className:"animate-spin"}),"Creating..."]}):"Create Token"})]})]})]})}),H&&I&&e.jsx("div",{className:"fixed inset-0 z-[10010] flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm",onClick:s=>s.target===s.currentTarget&&K(!1),role:"dialog","aria-modal":"true","aria-labelledby":"show-token-modal-title",children:e.jsxs("div",{className:"surface-modal radius-card p-6 max-w-lg w-full",children:[e.jsx("h3",{id:"show-token-modal-title",className:"type-micro mb-4",children:"Token Created Successfully"}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"bg-sys-indigo/10 border border-sys-indigo/30 radius-inner p-3",children:e.jsxs("div",{className:"flex gap-2",children:[e.jsx(Le,{className:"w-4 h-4 text-sys-indigo flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"text-sm text-fg-secondary",children:[e.jsx("strong",{children:"Save this token now!"})," For security reasons, it will not be shown again."]})]})}),e.jsxs("div",{children:[e.jsx("label",{className:"type-label text-fg-primary block mb-1.5",children:"Your API Token"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(Mt,{value:I,readOnly:!0,className:"flex-1 font-mono"}),e.jsxs(L,{color:"primary",outline:!0,onClick:ut,children:[ms?e.jsx(J,{"data-slot":"icon",className:"text-sys-green"}):e.jsx(Dt,{"data-slot":"icon"}),ms?"Copied!":"Copy"]})]})]}),e.jsxs("div",{className:"bg-sys-cyan/10 border border-sys-cyan/30 radius-inner p-3",children:[e.jsx("p",{className:"text-sm text-fg-secondary mb-2",children:e.jsx("strong",{children:"Usage Example:"})}),e.jsxs("code",{className:"block bg-sys-cyan/20 px-3 py-2 rounded type-code text-sys-cyan overflow-x-auto",children:['curl -H "X-API-Key: ',I.slice(0,12),'..." ',window.location.origin,"/api/stats"]})]}),e.jsx("div",{className:"flex justify-end mt-6",children:e.jsx(L,{color:"primary",onClick:()=>{K(!1),V(null)},children:"Done"})})]})]})}),e.jsx(Ht,{isOpen:!!ee,title:"Revoke API Token",message:`Are you sure you want to revoke the token '${ee==null?void 0:ee.name}'? This action cannot be undone.`,confirmLabel:ds?"Revoking...":"Revoke",cancelLabel:"Cancel",variant:"danger",onConfirm:dt,onCancel:()=>d(null)}),_e&&e.jsx("div",{className:"fixed inset-0 z-[10010] flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm",onClick:s=>s.target===s.currentTarget&&ge(!1),role:"dialog","aria-modal":"true","aria-labelledby":"add-key-modal-title",children:e.jsxs("div",{className:"surface-modal radius-card p-6 max-w-md w-full",children:[e.jsx("h3",{id:"add-key-modal-title",className:"type-micro mb-4",children:"Add Transport Key"}),e.jsxs("div",{className:"space-y-4",children:[B&&e.jsxs("div",{className:"bg-sys-cyan/10 border border-sys-cyan/30 radius-inner p-3 text-sm text-fg-secondary",children:["Adding as child of: ",e.jsx("strong",{className:"text-fg-primary",children:ft()})]}),e.jsx(Je,{label:"Key Name",type:"text",value:Te,onChange:s=>Fe(s.target.value),placeholder:"e.g., Region Name, Group Key",onKeyDown:s=>s.key==="Enter"&&Ss(),autoFocus:!0}),e.jsxs("div",{children:[e.jsx("label",{className:"type-label text-fg-muted block mb-2",children:"Flood Policy"}),e.jsxs("div",{className:"toggle-group w-full",children:[e.jsx("button",{onClick:()=>je("deny"),className:m("toggle-group-item flex-1",$e==="deny"&&"active !text-sys-red"),children:"Deny"}),e.jsx("button",{onClick:()=>je("allow"),className:m("toggle-group-item flex-1",$e==="allow"&&"active !text-sys-green"),children:"Allow"})]})]}),e.jsxs("div",{className:"flex justify-end gap-3 mt-6",children:[e.jsx(L,{color:"muted",outline:!0,onClick:()=>{ge(!1),Fe(""),je("allow")},disabled:Q,children:"Cancel"}),e.jsx(L,{color:"primary",onClick:Ss,disabled:Q||!Te.trim(),children:Q?e.jsxs(e.Fragment,{children:[e.jsx(U,{"data-slot":"icon",className:"animate-spin"}),"Adding..."]}):"Add Key"})]})]})]})}),Se&&q&&e.jsx("div",{className:"fixed inset-0 z-[10010] flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm",onClick:s=>s.target===s.currentTarget&&ce(!1),role:"dialog","aria-modal":"true","aria-labelledby":"edit-key-modal-title",children:e.jsxs("div",{className:"surface-modal radius-card p-6 max-w-md w-full",children:[e.jsx("h3",{id:"edit-key-modal-title",className:"type-micro mb-4",children:"Edit Transport Key"}),e.jsxs("div",{className:"space-y-4",children:[e.jsx(Je,{label:"Key Name",type:"text",value:q.name,onChange:s=>ae({...q,name:s.target.value}),autoFocus:!0}),e.jsxs("div",{children:[e.jsx("label",{className:"type-label text-fg-muted block mb-2",children:"Flood Policy"}),e.jsxs("div",{className:"toggle-group w-full",children:[e.jsx("button",{onClick:()=>ae({...q,floodPolicy:"deny"}),className:m("toggle-group-item flex-1",q.floodPolicy==="deny"&&"active !text-sys-red"),children:"Deny"}),e.jsx("button",{onClick:()=>ae({...q,floodPolicy:"allow"}),className:m("toggle-group-item flex-1",q.floodPolicy==="allow"&&"active !text-sys-green"),children:"Allow"})]})]}),q.transport_key&&e.jsxs("div",{children:[e.jsx("label",{className:"type-label text-fg-muted block mb-2",children:"Transport Key"}),e.jsx("code",{className:"block bg-input-bg px-3 py-2 radius-inner border border-input-border type-code text-fg-muted overflow-x-auto",children:q.transport_key})]}),e.jsxs("div",{className:"flex justify-between gap-3 mt-6",children:[e.jsx(L,{color:"danger",outline:!0,onClick:()=>{ce(!1),be(q),de(!0),ae(null)},disabled:Q,children:"Delete"}),e.jsxs("div",{className:"flex gap-3",children:[e.jsx(L,{color:"muted",outline:!0,onClick:()=>{ce(!1),ae(null)},disabled:Q,children:"Cancel"}),e.jsx(L,{color:"primary",onClick:pt,disabled:Q||!q.name.trim(),children:Q?e.jsxs(e.Fragment,{children:[e.jsx(U,{"data-slot":"icon",className:"animate-spin"}),"Saving..."]}):"Save"})]})]})]})]})}),Ce&&le&&e.jsx("div",{className:"fixed inset-0 z-[10010] flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm",onClick:s=>s.target===s.currentTarget&&de(!1),role:"dialog","aria-modal":"true","aria-labelledby":"delete-key-modal-title",children:e.jsxs("div",{className:"surface-modal radius-card p-6 max-w-md w-full",children:[e.jsx("h3",{id:"delete-key-modal-title",className:"type-micro mb-4",children:"Delete Transport Key"}),e.jsxs("p",{className:"text-fg-secondary mb-4",children:["Are you sure you want to delete ",e.jsxs("strong",{className:"text-fg-primary",children:["'",le.name,"'"]}),"?"]}),le.children&&le.children.length>0&&e.jsx("div",{className:"bg-sys-indigo/10 border border-sys-indigo/30 radius-inner p-3 mb-4",children:e.jsxs("div",{className:"flex gap-2",children:[e.jsx(Le,{className:"w-4 h-4 text-sys-indigo flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"text-sm text-fg-secondary",children:["This key has ",le.children.length," child key(s). Deleting will also remove all children."]})]})}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(L,{color:"muted",outline:!0,onClick:()=>{de(!1),be(null)},disabled:Q,children:"Cancel"}),e.jsx(L,{color:"danger",onClick:yt,disabled:Q,children:Q?e.jsxs(e.Fragment,{children:[e.jsx(U,{"data-slot":"icon",className:"animate-spin"}),"Deleting..."]}):"Delete"})]})]})})]})}export{tn as default};
