diff --git a/repeater/web/html/assets/CADCalibration-CPSu0tWy.js b/repeater/web/html/assets/CADCalibration-N3xuvAD8.js
similarity index 98%
rename from repeater/web/html/assets/CADCalibration-CPSu0tWy.js
rename to repeater/web/html/assets/CADCalibration-N3xuvAD8.js
index 72330d3..0b91496 100644
--- a/repeater/web/html/assets/CADCalibration-CPSu0tWy.js
+++ b/repeater/web/html/assets/CADCalibration-N3xuvAD8.js
@@ -1 +1 @@
-import{r as e}from"./chunk-DECur_0Z.js";import{C as t,S as n,f as r,ft as i,g as a,l as o,o as s,p as c,pt as l,s as u,u as d,w as f,z as p}from"./runtime-core.esm-bundler-HnidnMFy.js";import{c as m,t as h}from"./api-B2W0XzZe.js";import{t as g}from"./system-m4eSASWi.js";import{t as _}from"./_plugin-vue_export-helper-B7aGp3iI.js";import{t as v}from"./plotly.min-Dl7ekyci.js";var y=e(v(),1),ee={class:`p-6 space-y-6`},b={class:`glass-card rounded-[15px] p-6`},te={class:`flex justify-center`},ne={class:`flex gap-4`},re=[`disabled`],ie=[`disabled`],ae={class:`glass-card rounded-[15px] p-6 space-y-4`},oe={class:`text-content-primary dark:text-content-primary`},se={key:0,class:`p-4 bg-primary/10 border border-primary/30 rounded-lg`},ce={class:`text-content-primary dark:text-primary`},le={class:`space-y-2`},ue={class:`w-full bg-white/10 rounded-full h-2`},de={class:`text-content-secondary dark:text-content-muted text-sm`},fe={class:`grid grid-cols-2 md:grid-cols-4 gap-4`},x={class:`glass-card rounded-[15px] p-4 text-center`},S={class:`text-2xl font-bold text-primary`},C={class:`glass-card rounded-[15px] p-4 text-center`},w={class:`text-2xl font-bold text-primary`},T={class:`glass-card rounded-[15px] p-4 text-center`},E={class:`text-2xl font-bold text-primary`},D={class:`glass-card rounded-[15px] p-4 text-center`},O={class:`text-2xl font-bold text-primary`},k={key:0,class:`glass-card rounded-[15px] p-6 space-y-4`},A={key:0,class:`p-4 bg-accent-green/10 border border-accent-green/30 rounded-lg`},j={class:`text-content-primary dark:text-content-primary mb-4`},M={key:1,class:`p-4 bg-secondary/20 border border-secondary/40 rounded-lg`},N=_(a({name:`CADCalibrationView`,__name:`CADCalibration`,setup(e){let a=g(),_=s(()=>document.documentElement.classList.contains(`dark`)),v=()=>{let e=_.value;return{title:e?`#F9FAFB`:`#111827`,subtitle:e?`#9CA3AF`:`#6B7280`,axis:e?`#D1D5DB`:`#374151`,tick:e?`#9CA3AF`:`#6B7280`,grid:e?`rgba(148, 163, 184, 0.1)`:`rgba(107, 114, 128, 0.15)`,zeroline:e?`rgba(148, 163, 184, 0.2)`:`rgba(107, 114, 128, 0.25)`,line:e?`rgba(148, 163, 184, 0.3)`:`rgba(107, 114, 128, 0.35)`,colorbarBorder:e?`rgba(255,255,255,0.2)`:`rgba(0,0,0,0.15)`,markerLine:e?`rgba(255,255,255,0.2)`:`rgba(0,0,0,0.15)`}},N=p(!1),P=p(null),F=p(null),I=p({}),L=p(null),R=p([]),z=p({}),B=p(`Ready to start calibration`),V=p(0),H=p(0),U=p(0),W=p(0),G=p(0),K=p(0),q=p(null),J=p(!1),Y=p(!1),X=p(!1),Z=p(!1),Q=null,pe={responsive:!0,displayModeBar:!0,modeBarButtonsToRemove:[`pan2d`,`select2d`,`lasso2d`,`autoScale2d`],displaylogo:!1,toImageButtonOptions:{format:`png`,filename:`cad-calibration-heatmap`,height:600,width:800,scale:2}};function me(){let e=v(),t=[{x:[],y:[],z:[],mode:`markers`,type:`scatter`,marker:{size:12,color:[],colorscale:[[0,`rgba(75, 85, 99, 0.4)`],[.1,`rgba(6, 182, 212, 0.3)`],[.5,`rgba(6, 182, 212, 0.6)`],[1,`rgba(16, 185, 129, 0.9)`]],showscale:!0,colorbar:{title:{text:`Detection Rate (%)`,font:{color:e.axis,size:14}},tickfont:{color:e.tick},bgcolor:`rgba(0,0,0,0)`,bordercolor:e.colorbarBorder,borderwidth:1,thickness:15},line:{color:e.markerLine,width:1}},hovertemplate:`Peak: %{x}Min: %{y}Detection Rate: %{marker.color:.1f}% `,name:`Test Results`}],n={title:{text:`CAD Detection RateChannel Activity Detection Calibration `,font:{color:e.title,size:18},x:.5},xaxis:{title:{text:`CAD Peak Threshold`,font:{color:e.axis,size:14}},tickfont:{color:e.tick},gridcolor:e.grid,zerolinecolor:e.zeroline,linecolor:e.line},yaxis:{title:{text:`CAD Min Threshold`,font:{color:e.axis,size:14}},tickfont:{color:e.tick},gridcolor:e.grid,zerolinecolor:e.zeroline,linecolor:e.line},plot_bgcolor:`rgba(0, 0, 0, 0)`,paper_bgcolor:`rgba(0, 0, 0, 0)`,font:{color:e.title,family:`Inter, system-ui, sans-serif`},margin:{l:80,r:80,t:100,b:80},showlegend:!1};y.default.newPlot(`plotly-chart`,t,n,pe)}function he(){if(Object.keys(I.value).length===0)return;let e=Object.values(I.value),t=[],n=[],r=[];for(let i of e)t.push(i.det_peak),n.push(i.det_min),r.push(i.detection_rate);let i={x:[t],y:[n],"marker.color":[r],hovertemplate:`Peak: %{x}Min: %{y}Detection Rate: %{marker.color:.1f}%Status: Tested `};y.default.restyle(`plotly-chart`,i,[0])}async function ge(){try{let e=await h.post(`/cad-calibration-start`,{samples:10,delay_ms:50});if(e.success)N.value=!0,P.value=Date.now(),a.setCadCalibrationRunning(!0),I.value={},R.value=[],z.value={},L.value=null,J.value=!1,Y.value=!1,X.value=!1,Z.value=!1,U.value=0,W.value=0,G.value=0,K.value=0,V.value=0,H.value=0,Q=setInterval(()=>{P.value&&(K.value=Math.floor((Date.now()-P.value)/1e3))},1e3),_e();else throw Error(e.error||`Failed to start calibration`)}catch(e){B.value=`Error: ${e instanceof Error?e.message:`Unknown error`}`}}async function $(){try{(await h.post(`/cad-calibration-stop`)).success&&(N.value=!1,a.setCadCalibrationRunning(!1),F.value&&=(F.value.close(),null),Q&&=(clearInterval(Q),null))}catch(e){console.error(`Failed to stop calibration:`,e)}}function _e(){F.value&&F.value.close();let e=m(),t=e?`?token=${encodeURIComponent(e)}`:``;F.value=new EventSource(`/api/cad-calibration-stream${t}`),F.value.onmessage=function(e){try{ve(JSON.parse(e.data))}catch(e){console.error(`Failed to parse SSE data:`,e)}},F.value.onerror=function(e){console.error(`SSE connection error:`,e),N.value||(F.value&&=(F.value.close(),null))}}function ve(e){switch(e.type){case`status`:B.value=e.message||`Status update`,e.test_ranges&&(q.value=e.test_ranges,J.value=!0);break;case`progress`:V.value=e.current||0,H.value=e.total||0,U.value=e.current||0;break;case`result`:if(e.det_peak!==void 0&&e.det_min!==void 0&&e.detection_rate!==void 0&&e.detections!==void 0&&e.samples!==void 0){let t=`${e.det_peak}_${e.det_min}`;I.value[t]={det_peak:e.det_peak,det_min:e.det_min,detection_rate:e.detection_rate,detections:e.detections,samples:e.samples},he(),ye()}break;case`complete`:case`completed`:N.value=!1,B.value=e.message||`Calibration completed`,a.setCadCalibrationRunning(!1),be(),F.value&&=(F.value.close(),null),Q&&=(clearInterval(Q),null);break;case`error`:B.value=`Error: ${e.message}`,a.setCadCalibrationRunning(!1),$();break}}function ye(){let e=Object.values(I.value).map(e=>e.detection_rate);e.length!==0&&(W.value=Math.max(...e),G.value=e.reduce((e,t)=>e+t,0)/e.length)}function be(){Y.value=!0;let e=null,t=0;for(let n of Object.values(I.value))n.detection_rate>t&&(t=n.detection_rate,e=n);L.value=e,e&&t>0?(X.value=!0,Z.value=!1):(X.value=!1,Z.value=!0)}async function xe(){if(!L.value){B.value=`Error: No calibration results to save`;return}try{let e=await h.post(`/save_cad_settings`,{peak:L.value.det_peak,min_val:L.value.det_min,detection_rate:L.value.detection_rate});if(e.success)B.value=`Settings saved! Peak=${L.value.det_peak}, Min=${L.value.det_min} applied to configuration.`;else throw Error(e.error||`Failed to save settings`)}catch(e){B.value=`Error: Failed to save settings: ${e instanceof Error?e.message:`Unknown error`}`}}return n(()=>{me()}),t(()=>{F.value&&F.value.close(),Q&&clearInterval(Q),a.setCadCalibrationRunning(!1),document.getElementById(`plotly-chart`)&&y.default.purge(`plotly-chart`)}),(e,t)=>(f(),d(`div`,ee,[t[14]||=u(`div`,null,[u(`h1`,{class:`text-2xl font-bold text-content-primary dark:text-content-primary`},` CAD Calibration Tool `),u(`p`,{class:`text-content-secondary dark:text-content-muted mt-2`},` Channel Activity Detection calibration `)],-1),u(`div`,b,[u(`div`,te,[u(`div`,ne,[u(`button`,{onClick:ge,disabled:N.value,class:`flex items-center gap-3 px-6 py-3 bg-accent-green/10 hover:bg-accent-green/20 disabled:bg-gray-500/10 text-accent-green disabled:text-gray-400 rounded-lg border border-accent-green/30 disabled:border-gray-500/20 transition-colors disabled:cursor-not-allowed`},[...t[0]||=[r(`
Start Calibration
Begin testing
`,2)]],8,re),u(`button`,{onClick:$,disabled:!N.value,class:`flex items-center gap-3 px-6 py-3 bg-accent-red/10 hover:bg-accent-red/20 disabled:bg-gray-500/10 text-accent-red disabled:text-gray-400 rounded-lg border border-accent-red/30 disabled:border-gray-500/20 transition-colors disabled:cursor-not-allowed`},[...t[1]||=[r(` `,2)]],8,ie)])])]),u(`div`,ae,[u(`div`,oe,l(B.value),1),J.value&&q.value?(f(),d(`div`,se,[u(`div`,ce,[t[2]||=u(`strong`,null,`Configuration:`,-1),c(` SF`+l(q.value.spreading_factor)+` | Peak: `+l(q.value.peak_min)+` - `+l(q.value.peak_max)+` | Min: `+l(q.value.min_min)+` - `+l(q.value.min_max)+` | `+l((q.value.peak_max-q.value.peak_min+1)*(q.value.min_max-q.value.min_min+1))+` tests `,1)])])):o(``,!0),u(`div`,le,[u(`div`,ue,[u(`div`,{class:`bg-gradient-to-r from-primary to-accent-green h-2 rounded-full transition-all duration-300`,style:i({width:H.value>0?`${V.value/H.value*100}%`:`0%`})},null,4)]),u(`div`,de,l(V.value)+` / `+l(H.value)+` tests completed `,1)])]),u(`div`,fe,[u(`div`,x,[u(`div`,S,l(U.value),1),t[3]||=u(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Tests Completed`,-1)]),u(`div`,C,[u(`div`,w,l(W.value.toFixed(1))+`%`,1),t[4]||=u(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},` Best Detection Rate `,-1)]),u(`div`,T,[u(`div`,E,l(G.value.toFixed(1))+`%`,1),t[5]||=u(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Average Rate`,-1)]),u(`div`,D,[u(`div`,O,l(K.value)+`s`,1),t[6]||=u(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Elapsed Time`,-1)])]),t[15]||=u(`div`,{class:`glass-card rounded-[15px] p-6`},[u(`div`,{id:`plotly-chart`,class:`w-full h-96`})],-1),Y.value?(f(),d(`div`,k,[t[13]||=u(`h3`,{class:`text-xl font-bold text-content-primary dark:text-content-primary`},` Calibration Results `,-1),X.value&&L.value?(f(),d(`div`,A,[t[11]||=u(`h4`,{class:`font-medium text-accent-green mb-2`},`Optimal Settings Found:`,-1),u(`p`,j,[t[7]||=c(` Peak: `,-1),u(`strong`,null,l(L.value.det_peak),1),t[8]||=c(`, Min: `,-1),u(`strong`,null,l(L.value.det_min),1),t[9]||=c(`, Rate: `,-1),u(`strong`,null,l(L.value.detection_rate.toFixed(1))+`%`,1)]),u(`div`,{class:`flex justify-center`},[u(`button`,{onClick:xe,class:`flex items-center gap-3 px-6 py-3 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors`},[...t[10]||=[r(`Save Settings
Apply to configuration
`,2)]])])])):o(``,!0),Z.value?(f(),d(`div`,M,[...t[12]||=[u(`h4`,{class:`font-medium text-secondary mb-2`},`No Optimal Settings Found`,-1),u(`p`,{class:`text-content-secondary dark:text-content-muted`},` All tested combinations showed low detection rates. Consider running calibration again or adjusting test parameters. `,-1)]])):o(``,!0)])):o(``,!0)]))}}),[[`__scopeId`,`data-v-60d82848`]]);export{N as default};
\ No newline at end of file
+import{r as e}from"./chunk-DECur_0Z.js";import{C as t,S as n,f as r,ft as i,g as a,l as o,o as s,p as c,pt as l,s as u,u as d,w as f,z as p}from"./runtime-core.esm-bundler-HnidnMFy.js";import{c as m,t as h}from"./api-BXShkfsc.js";import{t as g}from"./system-A4EFgrwh.js";import{t as _}from"./_plugin-vue_export-helper-B7aGp3iI.js";import{t as v}from"./plotly.min-Dl7ekyci.js";var y=e(v(),1),ee={class:`p-6 space-y-6`},b={class:`glass-card rounded-[15px] p-6`},te={class:`flex justify-center`},ne={class:`flex gap-4`},re=[`disabled`],ie=[`disabled`],ae={class:`glass-card rounded-[15px] p-6 space-y-4`},oe={class:`text-content-primary dark:text-content-primary`},se={key:0,class:`p-4 bg-primary/10 border border-primary/30 rounded-lg`},ce={class:`text-content-primary dark:text-primary`},le={class:`space-y-2`},ue={class:`w-full bg-white/10 rounded-full h-2`},de={class:`text-content-secondary dark:text-content-muted text-sm`},fe={class:`grid grid-cols-2 md:grid-cols-4 gap-4`},x={class:`glass-card rounded-[15px] p-4 text-center`},S={class:`text-2xl font-bold text-primary`},C={class:`glass-card rounded-[15px] p-4 text-center`},w={class:`text-2xl font-bold text-primary`},T={class:`glass-card rounded-[15px] p-4 text-center`},E={class:`text-2xl font-bold text-primary`},D={class:`glass-card rounded-[15px] p-4 text-center`},O={class:`text-2xl font-bold text-primary`},k={key:0,class:`glass-card rounded-[15px] p-6 space-y-4`},A={key:0,class:`p-4 bg-accent-green/10 border border-accent-green/30 rounded-lg`},j={class:`text-content-primary dark:text-content-primary mb-4`},M={key:1,class:`p-4 bg-secondary/20 border border-secondary/40 rounded-lg`},N=_(a({name:`CADCalibrationView`,__name:`CADCalibration`,setup(e){let a=g(),_=s(()=>document.documentElement.classList.contains(`dark`)),v=()=>{let e=_.value;return{title:e?`#F9FAFB`:`#111827`,subtitle:e?`#9CA3AF`:`#6B7280`,axis:e?`#D1D5DB`:`#374151`,tick:e?`#9CA3AF`:`#6B7280`,grid:e?`rgba(148, 163, 184, 0.1)`:`rgba(107, 114, 128, 0.15)`,zeroline:e?`rgba(148, 163, 184, 0.2)`:`rgba(107, 114, 128, 0.25)`,line:e?`rgba(148, 163, 184, 0.3)`:`rgba(107, 114, 128, 0.35)`,colorbarBorder:e?`rgba(255,255,255,0.2)`:`rgba(0,0,0,0.15)`,markerLine:e?`rgba(255,255,255,0.2)`:`rgba(0,0,0,0.15)`}},N=p(!1),P=p(null),F=p(null),I=p({}),L=p(null),R=p([]),z=p({}),B=p(`Ready to start calibration`),V=p(0),H=p(0),U=p(0),W=p(0),G=p(0),K=p(0),q=p(null),J=p(!1),Y=p(!1),X=p(!1),Z=p(!1),Q=null,pe={responsive:!0,displayModeBar:!0,modeBarButtonsToRemove:[`pan2d`,`select2d`,`lasso2d`,`autoScale2d`],displaylogo:!1,toImageButtonOptions:{format:`png`,filename:`cad-calibration-heatmap`,height:600,width:800,scale:2}};function me(){let e=v(),t=[{x:[],y:[],z:[],mode:`markers`,type:`scatter`,marker:{size:12,color:[],colorscale:[[0,`rgba(75, 85, 99, 0.4)`],[.1,`rgba(6, 182, 212, 0.3)`],[.5,`rgba(6, 182, 212, 0.6)`],[1,`rgba(16, 185, 129, 0.9)`]],showscale:!0,colorbar:{title:{text:`Detection Rate (%)`,font:{color:e.axis,size:14}},tickfont:{color:e.tick},bgcolor:`rgba(0,0,0,0)`,bordercolor:e.colorbarBorder,borderwidth:1,thickness:15},line:{color:e.markerLine,width:1}},hovertemplate:`Peak: %{x}Min: %{y}Detection Rate: %{marker.color:.1f}% `,name:`Test Results`}],n={title:{text:`CAD Detection RateChannel Activity Detection Calibration `,font:{color:e.title,size:18},x:.5},xaxis:{title:{text:`CAD Peak Threshold`,font:{color:e.axis,size:14}},tickfont:{color:e.tick},gridcolor:e.grid,zerolinecolor:e.zeroline,linecolor:e.line},yaxis:{title:{text:`CAD Min Threshold`,font:{color:e.axis,size:14}},tickfont:{color:e.tick},gridcolor:e.grid,zerolinecolor:e.zeroline,linecolor:e.line},plot_bgcolor:`rgba(0, 0, 0, 0)`,paper_bgcolor:`rgba(0, 0, 0, 0)`,font:{color:e.title,family:`Inter, system-ui, sans-serif`},margin:{l:80,r:80,t:100,b:80},showlegend:!1};y.default.newPlot(`plotly-chart`,t,n,pe)}function he(){if(Object.keys(I.value).length===0)return;let e=Object.values(I.value),t=[],n=[],r=[];for(let i of e)t.push(i.det_peak),n.push(i.det_min),r.push(i.detection_rate);let i={x:[t],y:[n],"marker.color":[r],hovertemplate:`Peak: %{x}Min: %{y}Detection Rate: %{marker.color:.1f}%Status: Tested `};y.default.restyle(`plotly-chart`,i,[0])}async function ge(){try{let e=await h.post(`/cad-calibration-start`,{samples:10,delay_ms:50});if(e.success)N.value=!0,P.value=Date.now(),a.setCadCalibrationRunning(!0),I.value={},R.value=[],z.value={},L.value=null,J.value=!1,Y.value=!1,X.value=!1,Z.value=!1,U.value=0,W.value=0,G.value=0,K.value=0,V.value=0,H.value=0,Q=setInterval(()=>{P.value&&(K.value=Math.floor((Date.now()-P.value)/1e3))},1e3),_e();else throw Error(e.error||`Failed to start calibration`)}catch(e){B.value=`Error: ${e instanceof Error?e.message:`Unknown error`}`}}async function $(){try{(await h.post(`/cad-calibration-stop`)).success&&(N.value=!1,a.setCadCalibrationRunning(!1),F.value&&=(F.value.close(),null),Q&&=(clearInterval(Q),null))}catch(e){console.error(`Failed to stop calibration:`,e)}}function _e(){F.value&&F.value.close();let e=m(),t=e?`?token=${encodeURIComponent(e)}`:``;F.value=new EventSource(`/api/cad-calibration-stream${t}`),F.value.onmessage=function(e){try{ve(JSON.parse(e.data))}catch(e){console.error(`Failed to parse SSE data:`,e)}},F.value.onerror=function(e){console.error(`SSE connection error:`,e),N.value||(F.value&&=(F.value.close(),null))}}function ve(e){switch(e.type){case`status`:B.value=e.message||`Status update`,e.test_ranges&&(q.value=e.test_ranges,J.value=!0);break;case`progress`:V.value=e.current||0,H.value=e.total||0,U.value=e.current||0;break;case`result`:if(e.det_peak!==void 0&&e.det_min!==void 0&&e.detection_rate!==void 0&&e.detections!==void 0&&e.samples!==void 0){let t=`${e.det_peak}_${e.det_min}`;I.value[t]={det_peak:e.det_peak,det_min:e.det_min,detection_rate:e.detection_rate,detections:e.detections,samples:e.samples},he(),ye()}break;case`complete`:case`completed`:N.value=!1,B.value=e.message||`Calibration completed`,a.setCadCalibrationRunning(!1),be(),F.value&&=(F.value.close(),null),Q&&=(clearInterval(Q),null);break;case`error`:B.value=`Error: ${e.message}`,a.setCadCalibrationRunning(!1),$();break}}function ye(){let e=Object.values(I.value).map(e=>e.detection_rate);e.length!==0&&(W.value=Math.max(...e),G.value=e.reduce((e,t)=>e+t,0)/e.length)}function be(){Y.value=!0;let e=null,t=0;for(let n of Object.values(I.value))n.detection_rate>t&&(t=n.detection_rate,e=n);L.value=e,e&&t>0?(X.value=!0,Z.value=!1):(X.value=!1,Z.value=!0)}async function xe(){if(!L.value){B.value=`Error: No calibration results to save`;return}try{let e=await h.post(`/save_cad_settings`,{peak:L.value.det_peak,min_val:L.value.det_min,detection_rate:L.value.detection_rate});if(e.success)B.value=`Settings saved! Peak=${L.value.det_peak}, Min=${L.value.det_min} applied to configuration.`;else throw Error(e.error||`Failed to save settings`)}catch(e){B.value=`Error: Failed to save settings: ${e instanceof Error?e.message:`Unknown error`}`}}return n(()=>{me()}),t(()=>{F.value&&F.value.close(),Q&&clearInterval(Q),a.setCadCalibrationRunning(!1),document.getElementById(`plotly-chart`)&&y.default.purge(`plotly-chart`)}),(e,t)=>(f(),d(`div`,ee,[t[14]||=u(`div`,null,[u(`h1`,{class:`text-2xl font-bold text-content-primary dark:text-content-primary`},` CAD Calibration Tool `),u(`p`,{class:`text-content-secondary dark:text-content-muted mt-2`},` Channel Activity Detection calibration `)],-1),u(`div`,b,[u(`div`,te,[u(`div`,ne,[u(`button`,{onClick:ge,disabled:N.value,class:`flex items-center gap-3 px-6 py-3 bg-accent-green/10 hover:bg-accent-green/20 disabled:bg-gray-500/10 text-accent-green disabled:text-gray-400 rounded-lg border border-accent-green/30 disabled:border-gray-500/20 transition-colors disabled:cursor-not-allowed`},[...t[0]||=[r(`Start Calibration
Begin testing
`,2)]],8,re),u(`button`,{onClick:$,disabled:!N.value,class:`flex items-center gap-3 px-6 py-3 bg-accent-red/10 hover:bg-accent-red/20 disabled:bg-gray-500/10 text-accent-red disabled:text-gray-400 rounded-lg border border-accent-red/30 disabled:border-gray-500/20 transition-colors disabled:cursor-not-allowed`},[...t[1]||=[r(` `,2)]],8,ie)])])]),u(`div`,ae,[u(`div`,oe,l(B.value),1),J.value&&q.value?(f(),d(`div`,se,[u(`div`,ce,[t[2]||=u(`strong`,null,`Configuration:`,-1),c(` SF`+l(q.value.spreading_factor)+` | Peak: `+l(q.value.peak_min)+` - `+l(q.value.peak_max)+` | Min: `+l(q.value.min_min)+` - `+l(q.value.min_max)+` | `+l((q.value.peak_max-q.value.peak_min+1)*(q.value.min_max-q.value.min_min+1))+` tests `,1)])])):o(``,!0),u(`div`,le,[u(`div`,ue,[u(`div`,{class:`bg-gradient-to-r from-primary to-accent-green h-2 rounded-full transition-all duration-300`,style:i({width:H.value>0?`${V.value/H.value*100}%`:`0%`})},null,4)]),u(`div`,de,l(V.value)+` / `+l(H.value)+` tests completed `,1)])]),u(`div`,fe,[u(`div`,x,[u(`div`,S,l(U.value),1),t[3]||=u(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Tests Completed`,-1)]),u(`div`,C,[u(`div`,w,l(W.value.toFixed(1))+`%`,1),t[4]||=u(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},` Best Detection Rate `,-1)]),u(`div`,T,[u(`div`,E,l(G.value.toFixed(1))+`%`,1),t[5]||=u(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Average Rate`,-1)]),u(`div`,D,[u(`div`,O,l(K.value)+`s`,1),t[6]||=u(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Elapsed Time`,-1)])]),t[15]||=u(`div`,{class:`glass-card rounded-[15px] p-6`},[u(`div`,{id:`plotly-chart`,class:`w-full h-96`})],-1),Y.value?(f(),d(`div`,k,[t[13]||=u(`h3`,{class:`text-xl font-bold text-content-primary dark:text-content-primary`},` Calibration Results `,-1),X.value&&L.value?(f(),d(`div`,A,[t[11]||=u(`h4`,{class:`font-medium text-accent-green mb-2`},`Optimal Settings Found:`,-1),u(`p`,j,[t[7]||=c(` Peak: `,-1),u(`strong`,null,l(L.value.det_peak),1),t[8]||=c(`, Min: `,-1),u(`strong`,null,l(L.value.det_min),1),t[9]||=c(`, Rate: `,-1),u(`strong`,null,l(L.value.detection_rate.toFixed(1))+`%`,1)]),u(`div`,{class:`flex justify-center`},[u(`button`,{onClick:xe,class:`flex items-center gap-3 px-6 py-3 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors`},[...t[10]||=[r(`Save Settings
Apply to configuration
`,2)]])])])):o(``,!0),Z.value?(f(),d(`div`,M,[...t[12]||=[u(`h4`,{class:`font-medium text-secondary mb-2`},`No Optimal Settings Found`,-1),u(`p`,{class:`text-content-secondary dark:text-content-muted`},` All tested combinations showed low detection rates. Consider running calibration again or adjusting test parameters. `,-1)]])):o(``,!0)])):o(``,!0)]))}}),[[`__scopeId`,`data-v-60d82848`]]);export{N as default};
\ No newline at end of file
diff --git a/repeater/web/html/assets/Companions-D9nl_wM0.js b/repeater/web/html/assets/Companions-C2UI6lCU.js
similarity index 99%
rename from repeater/web/html/assets/Companions-D9nl_wM0.js
rename to repeater/web/html/assets/Companions-C2UI6lCU.js
index 0622de3..e65ec30 100644
--- a/repeater/web/html/assets/Companions-D9nl_wM0.js
+++ b/repeater/web/html/assets/Companions-C2UI6lCU.js
@@ -1 +1 @@
-import{E as e,K as t,S as n,b as r,dt as i,f as a,g as o,j as s,k as c,l,m as u,o as d,p as f,pt as p,r as m,s as h,u as g,w as _,z as v}from"./runtime-core.esm-bundler-HnidnMFy.js";import{t as y}from"./api-B2W0XzZe.js";import{f as b,h as x,l as S,u as C}from"./index-DiHOFPOZ.js";import{t as w}from"./ConfirmDialog-BECkBcWW.js";import{t as T}from"./MessageDialog-DdGM4RU0.js";var E={id:`import-modal-description`,class:`text-content-secondary dark:text-content-muted text-sm mb-4`},D={class:`mb-4`},O={class:`flex items-center gap-2 mb-2`},k={key:0,class:`text-content-muted dark:text-content-muted text-xs mb-2`},A={key:1,class:`flex flex-wrap gap-3 ml-6`},j=[`value`],M={class:`text-content-primary dark:text-content-primary text-sm capitalize`},N={class:`border-t border-stroke-subtle dark:border-white/10 pt-4 mt-4 mb-4`},P={class:`flex flex-wrap gap-3 mb-2`},F=[`value`],ee={class:`text-content-primary dark:text-content-primary text-sm`},te={class:`flex flex-wrap items-center gap-2 mt-2`},ne={class:`flex items-center gap-2`},I={key:1,class:`text-content-muted dark:text-content-muted text-sm`},L={class:`border-t border-stroke-subtle dark:border-white/10 pt-4 mt-4 mb-4`},R={class:`flex flex-wrap items-center gap-2`},z={key:0,role:`alert`,class:`mb-4 p-3 rounded-lg bg-accent-red/10 dark:bg-accent-red/20 border border-accent-red/30 text-accent-red text-sm`},B={key:1,class:`text-content-muted dark:text-content-muted text-sm mb-4`},V={class:`flex justify-end gap-3`},H=[`disabled`],U=[`disabled`],W=o({name:`ImportRepeaterContactsModal`,__name:`ImportRepeaterContactsModal`,props:{isOpen:{type:Boolean},companionName:{}},emits:[`close`,`imported`],setup(n,{emit:i}){let a=[`companion`,`repeater`,`room_server`,`sensor`],o=[{label:`All time`,value:null},{label:`Last 24 hours`,value:24},{label:`Last 7 days`,value:168},{label:`Last 30 days`,value:720},{label:`Custom`,value:`custom`}].slice(0,4),u=n,w=i,T=v(!1),W=v(null),G=v(!0),K=v([]),q=v(null),J=v(``),Y=v(``),X=v(null),Z=v(null);function Q(){let e=q.value;if(e===null||e===`custom`){if(e===`custom`){let e=J.value;if(e===``||e===null)return;let t=Number(e);return Number.isInteger(t)&&t>=1?t:void 0}return}return e}function $(){let e=Y.value;if(e===``||e===null)return;let t=Number(e);return Number.isInteger(t)&&t>=1?t:void 0}function re(){G.value=!0,K.value=[],q.value=null,J.value=``,Y.value=``,W.value=null}c(()=>u.isOpen,e=>{e&&(re(),r(()=>{Z.value?.focus()}))}),c(q,e=>{e===`custom`&&r(()=>{X.value?.focus()})});let ie=d(()=>{let e=G.value?`All types`:K.value.map(e=>e.replace(`_`,` `)).join(`, `),t,n=q.value;if(n===null)t=`all time`;else if(n===`custom`){let e=Q();t=e===void 0?`custom`:`last ${e} hours`}else t=n===24?`last 24 hours`:n===168?`last 7 days`:n===720?`last 30 days`:`all time`;let r=$(),i=r===void 0?`no limit`:`max ${r} contacts`;return`Import: ${e}, ${t}, ${i}.`});function ae(){if(q.value===`custom`){let e=Q();if(e===void 0||e<1)return`Custom recency must be at least 1 hour.`}let e=$();if(Y.value!==``&&(e===void 0||e<1))return`Limit must be at least 1.`;if(!G.value&&K.value.length===0)return`Select at least one contact type or use All types.`;if(!G.value){let e=K.value.filter(e=>!a.includes(e));if(e.length>0)return`Invalid contact type: ${e.join(`, `)}`}return null}async function oe(){W.value=null;let e=ae();if(e){W.value=e;return}let t={companion_name:u.companionName};!G.value&&K.value.length>0&&(t.contact_types=[...K.value]);let n=Q();n!==void 0&&(t.hours=n);let r=$();r!==void 0&&(t.limit=r),T.value=!0;try{let e=await y.importRepeaterContacts(t);e.success&&e.data?(w(`imported`,e.data.imported),w(`close`)):W.value=e.error||`Import failed.`}catch(e){W.value=e instanceof Error?e.message:`Import failed.`}finally{T.value=!1}}function se(e){e.target===e.currentTarget&&w(`close`)}function ce(e){e.key===`Escape`&&w(`close`)}return(r,i)=>n.isOpen?(_(),g(`div`,{key:0,class:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,onClick:se,onKeydown:ce},[h(`div`,{role:`dialog`,"aria-describedby":`import-modal-description`,class:`bg-white dark:bg-surface-elevated backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-6 max-w-lg w-full max-h-[90vh] overflow-y-auto`,onClick:i[7]||=x(()=>{},[`stop`])},[i[18]||=h(`h2`,{class:`text-xl font-bold text-content-primary dark:text-content-primary mb-4`},` Import repeater contacts `,-1),h(`p`,E,[i[8]||=f(` Seed `,-1),h(`strong`,null,p(n.companionName),1),i[9]||=f(` with contacts from the repeater's adverts. Results are ordered by most recent first. `,-1)]),h(`div`,D,[i[11]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},` Contact types `,-1),h(`label`,O,[s(h(`input`,{ref_key:`firstFocusRef`,ref:Z,"onUpdate:modelValue":i[0]||=e=>G.value=e,type:`checkbox`,class:`rounded border-stroke-subtle dark:border-stroke/20 text-primary focus:ring-primary/50`},null,512),[[S,G.value]]),i[10]||=h(`span`,{class:`text-content-primary dark:text-content-primary text-sm`},`All types`,-1)]),G.value?(_(),g(`p`,k,` Uncheck to filter by type (repeater, companion, room server, sensor). `)):l(``,!0),G.value?l(``,!0):(_(),g(`div`,A,[(_(),g(m,null,e(a,e=>h(`label`,{key:e,class:`flex items-center gap-2`},[s(h(`input`,{"onUpdate:modelValue":i[1]||=e=>K.value=e,type:`checkbox`,value:e,class:`rounded border-stroke-subtle dark:border-stroke/20 text-primary focus:ring-primary/50`},null,8,j),[[S,K.value]]),h(`span`,M,p(e.replace(`_`,` `)),1)])),64))]))]),h(`div`,N,[i[13]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},` Recency `,-1),h(`div`,P,[(_(!0),g(m,null,e(t(o),e=>(_(),g(`label`,{key:e.label,class:`flex items-center gap-2`},[s(h(`input`,{"onUpdate:modelValue":i[2]||=e=>q.value=e,type:`radio`,value:e.value,class:`border-stroke-subtle dark:border-stroke/20 text-primary focus:ring-primary/50`},null,8,F),[[C,q.value]]),h(`span`,ee,p(e.label),1)]))),128))]),h(`div`,te,[h(`label`,ne,[s(h(`input`,{"onUpdate:modelValue":i[3]||=e=>q.value=e,type:`radio`,value:`custom`,class:`border-stroke-subtle dark:border-stroke/20 text-primary focus:ring-primary/50`},null,512),[[C,q.value]]),i[12]||=h(`span`,{class:`text-content-primary dark:text-content-primary text-sm`},`Custom:`,-1)]),q.value===`custom`?s((_(),g(`input`,{key:0,ref_key:`customHoursInputRef`,ref:X,"onUpdate:modelValue":i[4]||=e=>J.value=e,type:`number`,min:`1`,placeholder:`e.g. 48`,class:`w-24 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-3 py-1.5 text-content-primary dark:text-content-primary text-sm placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50`},null,512)),[[b,J.value,void 0,{number:!0}]]):l(``,!0),q.value===`custom`?(_(),g(`span`,I,`hours`)):l(``,!0)])]),h(`div`,L,[i[16]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},` Max contacts (optional) `,-1),h(`div`,R,[i[14]||=h(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`Import at most`,-1),s(h(`input`,{"onUpdate:modelValue":i[5]||=e=>Y.value=e,type:`number`,inputmode:`numeric`,min:`1`,placeholder:`No limit`,class:`w-32 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-3 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50`},null,512),[[b,Y.value,void 0,{number:!0}]]),i[15]||=h(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`contacts`,-1)]),i[17]||=h(`p`,{class:`text-content-muted dark:text-content-muted text-xs mt-1`},` Leave empty for no cap. Server caps at companion max. `,-1)]),W.value?(_(),g(`div`,z,p(W.value),1)):l(``,!0),W.value?l(``,!0):(_(),g(`p`,B,p(ie.value),1)),h(`div`,V,[h(`button`,{type:`button`,disabled:T.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors disabled:opacity-50`,onClick:i[6]||=e=>w(`close`)},` Cancel `,8,H),h(`button`,{type:`button`,disabled:T.value,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors disabled:opacity-50`,onClick:oe},p(T.value?`Importing…`:`Import`),9,U)])])],32)):l(``,!0)}}),G={class:`p-6 space-y-6`},K={key:0,class:`grid grid-cols-1 md:grid-cols-2 gap-4`},q={class:`group relative overflow-hidden glass-card backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-5`},J={class:`relative flex items-center justify-between`},Y={class:`text-3xl font-bold text-content-primary dark:text-content-primary`},X={class:`glass-card backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-6`},Z={key:0,class:`flex items-center justify-center py-12`},Q={key:1,class:`flex items-center justify-center py-12`},$={class:`text-center`},re={class:`text-content-secondary dark:text-content-muted text-sm mb-4`},ie={key:2,class:`space-y-4`},ae={class:`relative flex items-start justify-between`},oe={class:`flex-1`},se={class:`flex items-center gap-3 mb-4`},ce={class:`relative`},le={key:0,class:`absolute inset-0 bg-accent-green/50 rounded-full animate-ping`},ue={class:`text-xl font-bold text-content-primary dark:text-content-primary`},de={key:0,class:`text-content-muted dark:text-content-muted text-sm`},fe={class:`grid grid-cols-1 md:grid-cols-2 gap-3 text-sm mb-3`},pe={class:`text-content-primary dark:text-content-primary/90 ml-2`},me={class:`text-content-primary dark:text-content-primary/90 ml-2`},he={class:`text-content-primary dark:text-content-primary/90 ml-2`},ge={class:`flex items-center gap-2`},_e={key:0,class:`text-content-primary dark:text-content-primary/90 font-mono ml-2 text-xs`},ve={key:1,class:`text-content-muted dark:text-content-muted ml-2 text-xs`},ye=[`onClick`],be={class:`text-xs text-content-muted dark:text-content-muted`},xe={key:0,class:`ml-2 font-mono text-content-primary dark:text-content-primary/90 break-all`},Se={key:1,class:`ml-2 text-content-muted dark:text-content-muted`},Ce={class:`ml-4 flex flex-wrap gap-2`},we=[`onClick`],Te=[`onClick`],Ee=[`onClick`],De={key:3,class:`text-center py-12 text-content-secondary dark:text-content-muted`},Oe={key:1,class:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`},ke={class:`bg-white dark:bg-surface-elevated backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-6 max-w-2xl w-full max-h-[90vh] overflow-y-auto`},Ae={class:`space-y-4`},je={class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},Me={key:0},Ne={key:1,class:`text-content-secondary dark:text-content-muted text-sm`},Pe={class:`grid grid-cols-2 gap-4`},Fe={key:2,class:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`},Ie={class:`bg-white dark:bg-surface-elevated backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-6 max-w-2xl w-full max-h-[90vh] overflow-y-auto`},Le={class:`space-y-4`},Re=[`value`],ze={class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},Be={key:0},Ve={class:`grid grid-cols-2 gap-4`},He=5050,Ue=1,We=65535,Ge=o({name:`CompanionsView`,__name:`Companions`,setup(t){let r=v(!1),o=v(null),c=v(null),d=v(!1),x=v(!1),S=v(null),C=v(!1),E=v(!1),D=v(new Set),O=v(!1),k=v(``),A=v(!1),j=v(``),M=v(!1),N=v({message:``,variant:`success`}),P=v({name:``,identity_key:``,type:`companion`,settings:{node_name:``,tcp_port:5e3,bind_address:`0.0.0.0`}});n(async()=>{await F()});async function F(){r.value=!0,o.value=null;try{let e=await y.getIdentities();e.success?c.value=e.data:o.value=e.error||`Failed to load identities`}catch(e){o.value=e instanceof Error?e.message:`Failed to load identities`}finally{r.value=!1}}async function ee(){try{let e=await y.createIdentity({...P.value,settings:{node_name:P.value.settings.node_name||P.value.name,tcp_port:P.value.settings.tcp_port??5e3,bind_address:P.value.settings.bind_address||`0.0.0.0`}});e.success?(d.value=!1,z(),await F(),L(e.message||`Companion created successfully!`,`success`)):L(`Failed to create companion: ${e.error}`,`error`)}catch(e){L(`Error creating companion: ${e}`,`error`)}}async function te(){try{let e=await y.updateIdentity({name:S.value.name,new_name:S.value.new_name,identity_key:S.value.identity_key,type:`companion`,settings:{node_name:S.value.settings?.node_name,tcp_port:S.value.settings?.tcp_port,bind_address:S.value.settings?.bind_address}});e.success?(x.value=!1,S.value=null,await F(),L(e.message||`Companion updated successfully!`,`success`)):L(`Failed to update companion: ${e.error}`,`error`)}catch(e){L(`Error updating companion: ${e}`,`error`)}}function ne(e){k.value=e,O.value=!0}async function I(){let e=k.value;O.value=!1;try{let t=await y.deleteIdentity(e,`companion`);t.success?(await F(),L(t.message||`Companion deleted successfully!`,`success`)):L(`Failed to delete companion: ${t.error}`,`error`)}catch(e){L(`Error deleting companion: ${e}`,`error`)}finally{k.value=``}}function L(e,t){N.value={message:e,variant:t},M.value=!0}function R(e){S.value=JSON.parse(JSON.stringify(e)),S.value.settings||(S.value.settings={node_name:``,tcp_port:5e3,bind_address:`0.0.0.0`}),S.value.new_name=``,E.value=!1,x.value=!0}function z(){P.value={name:``,identity_key:``,type:`companion`,settings:{node_name:``,tcp_port:5e3,bind_address:`0.0.0.0`}},C.value=!1}function B(){d.value=!1,x.value=!1,S.value=null,C.value=!1,E.value=!1,z()}function V(e){D.value.has(e)?D.value.delete(e):D.value.add(e)}let H=()=>c.value?.configured_companions??[],U=()=>c.value?.total_configured_companions??0;function Ge(){let e=H();if(e.length===0)return He;let t=e.map(e=>e.settings?.tcp_port??5e3),n=Math.max(...t)+1;return Math.min(We,Math.max(Ue,n))}function Ke(){z(),P.value.settings.tcp_port=Ge(),d.value=!0}function qe(e){j.value=e,A.value=!0}function Je(){A.value=!1,j.value=``}function Ye(e){L(`Imported ${e} contact${e===1?``:`s`}.`,`success`),Je()}return(t,n)=>(_(),g(m,null,[h(`div`,G,[h(`div`,{class:`relative overflow-hidden rounded-[20px] p-6 mb-6 glass-card backdrop-blur-xl border border-stroke-subtle dark:border-white/10`},[n[16]||=h(`div`,{class:`absolute inset-0 bg-gradient-to-br from-primary/20 via-secondary/10 to-accent-purple/20 opacity-50`},null,-1),n[17]||=h(`div`,{class:`absolute inset-0 bg-gradient-to-tl from-accent-green/10 via-transparent to-primary/10 animate-pulse`},null,-1),h(`div`,{class:`relative flex items-center justify-between`},[n[15]||=a(` Companions Manage companion identities (TCP frame server)
`,1),h(`button`,{onClick:Ke,class:`group relative px-6 py-3 bg-gradient-to-r from-primary/30 to-secondary/30 hover:from-primary/40 hover:to-secondary/40 text-content-primary dark:text-content-primary rounded-[12px] border border-primary/50 transition-all hover:scale-105 hover:shadow-lg hover:shadow-primary/20`},[...n[14]||=[h(`span`,{class:`flex items-center gap-2`},[h(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[h(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 4v16m8-8H4`})]),f(` Add Companion `)],-1)]])])]),c.value&&U()>0?(_(),g(`div`,K,[h(`div`,q,[h(`div`,J,[h(`div`,null,[n[18]||=h(`div`,{class:`text-content-secondary dark:text-content-muted text-xs font-medium mb-2 uppercase tracking-wide`},` Total Configured `,-1),h(`div`,Y,p(U()),1)])])])])):l(``,!0),h(`div`,X,[r.value?(_(),g(`div`,Z,[...n[19]||=[h(`div`,{class:`text-center`},[h(`div`,{class:`animate-spin w-8 h-8 border-2 border-stroke-subtle dark:border-stroke/20 border-t-primary rounded-full mx-auto mb-4`}),h(`div`,{class:`text-content-secondary dark:text-content-primary/70`},` Loading companions... `)],-1)]])):o.value?(_(),g(`div`,Q,[h(`div`,$,[n[20]||=h(`div`,{class:`text-red-600 dark:text-red-400 mb-2`},`Failed to load companions`,-1),h(`div`,re,p(o.value),1),h(`button`,{onClick:F,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors`},` Retry `)])])):c.value&&H().length>0?(_(),g(`div`,ie,[(_(!0),g(m,null,e(H(),e=>(_(),g(`div`,{key:e.name,class:`group relative overflow-hidden glass-card backdrop-blur-xl rounded-[15px] p-5 border border-stroke-subtle dark:border-white/10 hover:border-primary/30 transition-all duration-300`},[h(`div`,ae,[h(`div`,oe,[h(`div`,se,[h(`div`,ce,[e.registered?(_(),g(`div`,le)):l(``,!0),h(`div`,{class:i([`relative w-3 h-3 rounded-full`,e.registered?`bg-accent-green`:`bg-accent-red`])},null,2)]),h(`h3`,ue,p(e.name),1),h(`span`,{class:i([`px-3 py-1 text-xs font-semibold rounded-full`,e.registered?`bg-accent-green/20 text-accent-green border border-accent-green/30`:`bg-accent-red/20 text-accent-red border border-accent-red/30`])},p(e.registered?`● Active`:`○ Inactive`),3),e.hash?(_(),g(`span`,de,p(e.hash),1)):l(``,!0)]),h(`div`,fe,[h(`div`,null,[n[21]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`Node Name:`,-1),h(`span`,pe,p(e.settings?.node_name||e.name),1)]),h(`div`,null,[n[22]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`TCP Port:`,-1),h(`span`,me,p(e.settings?.tcp_port??5e3),1)]),h(`div`,null,[n[23]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`Bind Address:`,-1),h(`span`,he,p(e.settings?.bind_address||`0.0.0.0`),1)]),h(`div`,ge,[n[24]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`Identity Key:`,-1),D.value.has(e.name)?(_(),g(`span`,_e,p(e.identity_key),1)):(_(),g(`span`,ve,`••••••••••••••••`)),h(`button`,{onClick:t=>V(e.name),class:`text-primary/70 hover:text-primary text-xs underline`},p(D.value.has(e.name)?`Hide`:`Show`),9,ye)])]),h(`div`,be,[n[25]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`Public Key:`,-1),e.public_key?(_(),g(`span`,xe,p(e.public_key),1)):(_(),g(`span`,Se,`—`))])]),h(`div`,Ce,[h(`button`,{onClick:t=>qe(e.name),class:`px-3 py-1 bg-primary/20 hover:bg-primary/30 text-primary rounded text-xs transition-colors`},` Import contacts `,8,we),h(`button`,{onClick:t=>R(e),class:`px-3 py-1 bg-primary/20 hover:bg-primary/30 text-primary rounded text-xs transition-colors`},` Edit `,8,Te),h(`button`,{onClick:t=>ne(e.name),class:`px-3 py-1 bg-accent-red/20 hover:bg-accent-red/30 text-accent-red rounded text-xs transition-colors`},` Delete `,8,Ee)])])]))),128))])):(_(),g(`div`,De,[n[26]||=h(`svg`,{class:`w-16 h-16 mx-auto mb-4 text-content-muted dark:text-content-muted/60`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[h(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z`})],-1),n[27]||=h(`p`,{class:`text-lg mb-2`},`No companions configured`,-1),n[28]||=h(`p`,{class:`text-sm mb-4`},` Add a companion to run a TCP frame server for firmware or other clients `,-1),h(`button`,{onClick:Ke,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors`},` + Add Companion `)]))]),d.value?(_(),g(`div`,Oe,[h(`div`,ke,[n[35]||=h(`h2`,{class:`text-xl font-bold text-content-primary dark:text-content-primary mb-4`},` Add Companion `,-1),h(`div`,Ae,[h(`div`,null,[n[29]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Name *`,-1),s(h(`input`,{"onUpdate:modelValue":n[0]||=e=>P.value.name=e,type:`text`,placeholder:`e.g., TestCompanion`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.name]])]),h(`div`,null,[h(`label`,je,[n[30]||=f(` Identity Key (Optional) `,-1),h(`button`,{onClick:n[1]||=e=>C.value=!C.value,type:`button`,class:`ml-2 text-primary/70 hover:text-primary text-xs underline`},p(C.value?`Hide`:`Show/Edit`),1)]),C.value?(_(),g(`div`,Me,[s(h(`input`,{"onUpdate:modelValue":n[2]||=e=>P.value.identity_key=e,type:`text`,placeholder:`Leave empty to auto-generate (32 bytes hex)`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary font-mono text-sm placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.identity_key]]),n[31]||=h(`p`,{class:`text-content-secondary dark:text-content-muted text-xs mt-1`},` 32 or 64 bytes hex. Leave empty to auto-generate. `,-1)])):(_(),g(`div`,Ne,` Will be auto-generated if not provided `))]),h(`div`,null,[n[32]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Node Name`,-1),s(h(`input`,{"onUpdate:modelValue":n[3]||=e=>P.value.settings.node_name=e,type:`text`,placeholder:`Display name (defaults to Name)`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.settings.node_name]])]),h(`div`,Pe,[h(`div`,null,[n[33]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`TCP Port`,-1),s(h(`input`,{"onUpdate:modelValue":n[4]||=e=>P.value.settings.tcp_port=e,type:`number`,min:`1`,max:`65535`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.settings.tcp_port,void 0,{number:!0}]])]),h(`div`,null,[n[34]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Bind Address`,-1),s(h(`input`,{"onUpdate:modelValue":n[5]||=e=>P.value.settings.bind_address=e,type:`text`,placeholder:`0.0.0.0`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.settings.bind_address]])])])]),h(`div`,{class:`flex justify-end gap-3 mt-6`},[h(`button`,{onClick:B,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),h(`button`,{onClick:ee,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors`},` Create `)])])])):l(``,!0),x.value&&S.value?(_(),g(`div`,Fe,[h(`div`,Ie,[n[42]||=h(`h2`,{class:`text-xl font-bold text-content-primary dark:text-content-primary mb-4`},` Edit Companion `,-1),h(`div`,Le,[h(`div`,null,[n[36]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Current Name`,-1),h(`input`,{value:S.value.name,disabled:``,type:`text`,class:`w-full bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-muted dark:text-content-muted cursor-not-allowed`},null,8,Re)]),h(`div`,null,[n[37]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`New Name (optional)`,-1),s(h(`input`,{"onUpdate:modelValue":n[6]||=e=>S.value.new_name=e,type:`text`,placeholder:`Leave empty to keep current name`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.new_name]])]),h(`div`,null,[h(`label`,ze,[n[38]||=f(` Identity Key (Optional) `,-1),h(`button`,{onClick:n[7]||=e=>E.value=!E.value,type:`button`,class:`ml-2 text-primary/70 hover:text-primary text-xs underline`},p(E.value?`Hide`:`Show/Edit`),1)]),E.value?(_(),g(`div`,Be,[s(h(`input`,{"onUpdate:modelValue":n[8]||=e=>S.value.identity_key=e,type:`text`,placeholder:`Leave empty to keep current key`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary font-mono text-sm placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.identity_key]])])):l(``,!0)]),h(`div`,null,[n[39]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Node Name`,-1),s(h(`input`,{"onUpdate:modelValue":n[9]||=e=>S.value.settings.node_name=e,type:`text`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.settings.node_name]])]),h(`div`,Ve,[h(`div`,null,[n[40]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`TCP Port`,-1),s(h(`input`,{"onUpdate:modelValue":n[10]||=e=>S.value.settings.tcp_port=e,type:`number`,min:`1`,max:`65535`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.settings.tcp_port,void 0,{number:!0}]])]),h(`div`,null,[n[41]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Bind Address`,-1),s(h(`input`,{"onUpdate:modelValue":n[11]||=e=>S.value.settings.bind_address=e,type:`text`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.settings.bind_address]])])])]),h(`div`,{class:`flex justify-end gap-3 mt-6`},[h(`button`,{onClick:B,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),h(`button`,{onClick:te,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors`},` Update `)])])])):l(``,!0)]),u(W,{"is-open":A.value,"companion-name":j.value,onClose:Je,onImported:Ye},null,8,[`is-open`,`companion-name`]),u(w,{show:O.value,title:`Delete Companion`,message:`Are you sure you want to delete '${k.value}'? Restart required to fully remove.`,"confirm-text":`Delete`,"cancel-text":`Cancel`,variant:`danger`,onClose:n[12]||=e=>O.value=!1,onConfirm:I},null,8,[`show`,`message`]),u(T,{show:M.value,message:N.value.message,variant:N.value.variant,onClose:n[13]||=e=>M.value=!1},null,8,[`show`,`message`,`variant`])],64))}});export{Ge as default};
\ No newline at end of file
+import{E as e,K as t,S as n,b as r,dt as i,f as a,g as o,j as s,k as c,l,m as u,o as d,p as f,pt as p,r as m,s as h,u as g,w as _,z as v}from"./runtime-core.esm-bundler-HnidnMFy.js";import{t as y}from"./api-BXShkfsc.js";import{f as b,h as x,l as S,u as C}from"./index-C6ELfnbI.js";import{t as w}from"./ConfirmDialog-COAlYCXc.js";import{t as T}from"./MessageDialog-Bxq30GhY.js";var E={id:`import-modal-description`,class:`text-content-secondary dark:text-content-muted text-sm mb-4`},D={class:`mb-4`},O={class:`flex items-center gap-2 mb-2`},k={key:0,class:`text-content-muted dark:text-content-muted text-xs mb-2`},A={key:1,class:`flex flex-wrap gap-3 ml-6`},j=[`value`],M={class:`text-content-primary dark:text-content-primary text-sm capitalize`},N={class:`border-t border-stroke-subtle dark:border-white/10 pt-4 mt-4 mb-4`},P={class:`flex flex-wrap gap-3 mb-2`},F=[`value`],ee={class:`text-content-primary dark:text-content-primary text-sm`},te={class:`flex flex-wrap items-center gap-2 mt-2`},ne={class:`flex items-center gap-2`},I={key:1,class:`text-content-muted dark:text-content-muted text-sm`},L={class:`border-t border-stroke-subtle dark:border-white/10 pt-4 mt-4 mb-4`},R={class:`flex flex-wrap items-center gap-2`},z={key:0,role:`alert`,class:`mb-4 p-3 rounded-lg bg-accent-red/10 dark:bg-accent-red/20 border border-accent-red/30 text-accent-red text-sm`},B={key:1,class:`text-content-muted dark:text-content-muted text-sm mb-4`},V={class:`flex justify-end gap-3`},H=[`disabled`],U=[`disabled`],W=o({name:`ImportRepeaterContactsModal`,__name:`ImportRepeaterContactsModal`,props:{isOpen:{type:Boolean},companionName:{}},emits:[`close`,`imported`],setup(n,{emit:i}){let a=[`companion`,`repeater`,`room_server`,`sensor`],o=[{label:`All time`,value:null},{label:`Last 24 hours`,value:24},{label:`Last 7 days`,value:168},{label:`Last 30 days`,value:720},{label:`Custom`,value:`custom`}].slice(0,4),u=n,w=i,T=v(!1),W=v(null),G=v(!0),K=v([]),q=v(null),J=v(``),Y=v(``),X=v(null),Z=v(null);function Q(){let e=q.value;if(e===null||e===`custom`){if(e===`custom`){let e=J.value;if(e===``||e===null)return;let t=Number(e);return Number.isInteger(t)&&t>=1?t:void 0}return}return e}function $(){let e=Y.value;if(e===``||e===null)return;let t=Number(e);return Number.isInteger(t)&&t>=1?t:void 0}function re(){G.value=!0,K.value=[],q.value=null,J.value=``,Y.value=``,W.value=null}c(()=>u.isOpen,e=>{e&&(re(),r(()=>{Z.value?.focus()}))}),c(q,e=>{e===`custom`&&r(()=>{X.value?.focus()})});let ie=d(()=>{let e=G.value?`All types`:K.value.map(e=>e.replace(`_`,` `)).join(`, `),t,n=q.value;if(n===null)t=`all time`;else if(n===`custom`){let e=Q();t=e===void 0?`custom`:`last ${e} hours`}else t=n===24?`last 24 hours`:n===168?`last 7 days`:n===720?`last 30 days`:`all time`;let r=$(),i=r===void 0?`no limit`:`max ${r} contacts`;return`Import: ${e}, ${t}, ${i}.`});function ae(){if(q.value===`custom`){let e=Q();if(e===void 0||e<1)return`Custom recency must be at least 1 hour.`}let e=$();if(Y.value!==``&&(e===void 0||e<1))return`Limit must be at least 1.`;if(!G.value&&K.value.length===0)return`Select at least one contact type or use All types.`;if(!G.value){let e=K.value.filter(e=>!a.includes(e));if(e.length>0)return`Invalid contact type: ${e.join(`, `)}`}return null}async function oe(){W.value=null;let e=ae();if(e){W.value=e;return}let t={companion_name:u.companionName};!G.value&&K.value.length>0&&(t.contact_types=[...K.value]);let n=Q();n!==void 0&&(t.hours=n);let r=$();r!==void 0&&(t.limit=r),T.value=!0;try{let e=await y.importRepeaterContacts(t);e.success&&e.data?(w(`imported`,e.data.imported),w(`close`)):W.value=e.error||`Import failed.`}catch(e){W.value=e instanceof Error?e.message:`Import failed.`}finally{T.value=!1}}function se(e){e.target===e.currentTarget&&w(`close`)}function ce(e){e.key===`Escape`&&w(`close`)}return(r,i)=>n.isOpen?(_(),g(`div`,{key:0,class:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,onClick:se,onKeydown:ce},[h(`div`,{role:`dialog`,"aria-describedby":`import-modal-description`,class:`bg-white dark:bg-surface-elevated backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-6 max-w-lg w-full max-h-[90vh] overflow-y-auto`,onClick:i[7]||=x(()=>{},[`stop`])},[i[18]||=h(`h2`,{class:`text-xl font-bold text-content-primary dark:text-content-primary mb-4`},` Import repeater contacts `,-1),h(`p`,E,[i[8]||=f(` Seed `,-1),h(`strong`,null,p(n.companionName),1),i[9]||=f(` with contacts from the repeater's adverts. Results are ordered by most recent first. `,-1)]),h(`div`,D,[i[11]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},` Contact types `,-1),h(`label`,O,[s(h(`input`,{ref_key:`firstFocusRef`,ref:Z,"onUpdate:modelValue":i[0]||=e=>G.value=e,type:`checkbox`,class:`rounded border-stroke-subtle dark:border-stroke/20 text-primary focus:ring-primary/50`},null,512),[[S,G.value]]),i[10]||=h(`span`,{class:`text-content-primary dark:text-content-primary text-sm`},`All types`,-1)]),G.value?(_(),g(`p`,k,` Uncheck to filter by type (repeater, companion, room server, sensor). `)):l(``,!0),G.value?l(``,!0):(_(),g(`div`,A,[(_(),g(m,null,e(a,e=>h(`label`,{key:e,class:`flex items-center gap-2`},[s(h(`input`,{"onUpdate:modelValue":i[1]||=e=>K.value=e,type:`checkbox`,value:e,class:`rounded border-stroke-subtle dark:border-stroke/20 text-primary focus:ring-primary/50`},null,8,j),[[S,K.value]]),h(`span`,M,p(e.replace(`_`,` `)),1)])),64))]))]),h(`div`,N,[i[13]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},` Recency `,-1),h(`div`,P,[(_(!0),g(m,null,e(t(o),e=>(_(),g(`label`,{key:e.label,class:`flex items-center gap-2`},[s(h(`input`,{"onUpdate:modelValue":i[2]||=e=>q.value=e,type:`radio`,value:e.value,class:`border-stroke-subtle dark:border-stroke/20 text-primary focus:ring-primary/50`},null,8,F),[[C,q.value]]),h(`span`,ee,p(e.label),1)]))),128))]),h(`div`,te,[h(`label`,ne,[s(h(`input`,{"onUpdate:modelValue":i[3]||=e=>q.value=e,type:`radio`,value:`custom`,class:`border-stroke-subtle dark:border-stroke/20 text-primary focus:ring-primary/50`},null,512),[[C,q.value]]),i[12]||=h(`span`,{class:`text-content-primary dark:text-content-primary text-sm`},`Custom:`,-1)]),q.value===`custom`?s((_(),g(`input`,{key:0,ref_key:`customHoursInputRef`,ref:X,"onUpdate:modelValue":i[4]||=e=>J.value=e,type:`number`,min:`1`,placeholder:`e.g. 48`,class:`w-24 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-3 py-1.5 text-content-primary dark:text-content-primary text-sm placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50`},null,512)),[[b,J.value,void 0,{number:!0}]]):l(``,!0),q.value===`custom`?(_(),g(`span`,I,`hours`)):l(``,!0)])]),h(`div`,L,[i[16]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},` Max contacts (optional) `,-1),h(`div`,R,[i[14]||=h(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`Import at most`,-1),s(h(`input`,{"onUpdate:modelValue":i[5]||=e=>Y.value=e,type:`number`,inputmode:`numeric`,min:`1`,placeholder:`No limit`,class:`w-32 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-3 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50`},null,512),[[b,Y.value,void 0,{number:!0}]]),i[15]||=h(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`contacts`,-1)]),i[17]||=h(`p`,{class:`text-content-muted dark:text-content-muted text-xs mt-1`},` Leave empty for no cap. Server caps at companion max. `,-1)]),W.value?(_(),g(`div`,z,p(W.value),1)):l(``,!0),W.value?l(``,!0):(_(),g(`p`,B,p(ie.value),1)),h(`div`,V,[h(`button`,{type:`button`,disabled:T.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors disabled:opacity-50`,onClick:i[6]||=e=>w(`close`)},` Cancel `,8,H),h(`button`,{type:`button`,disabled:T.value,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors disabled:opacity-50`,onClick:oe},p(T.value?`Importing…`:`Import`),9,U)])])],32)):l(``,!0)}}),G={class:`p-6 space-y-6`},K={key:0,class:`grid grid-cols-1 md:grid-cols-2 gap-4`},q={class:`group relative overflow-hidden glass-card backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-5`},J={class:`relative flex items-center justify-between`},Y={class:`text-3xl font-bold text-content-primary dark:text-content-primary`},X={class:`glass-card backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-6`},Z={key:0,class:`flex items-center justify-center py-12`},Q={key:1,class:`flex items-center justify-center py-12`},$={class:`text-center`},re={class:`text-content-secondary dark:text-content-muted text-sm mb-4`},ie={key:2,class:`space-y-4`},ae={class:`relative flex items-start justify-between`},oe={class:`flex-1`},se={class:`flex items-center gap-3 mb-4`},ce={class:`relative`},le={key:0,class:`absolute inset-0 bg-accent-green/50 rounded-full animate-ping`},ue={class:`text-xl font-bold text-content-primary dark:text-content-primary`},de={key:0,class:`text-content-muted dark:text-content-muted text-sm`},fe={class:`grid grid-cols-1 md:grid-cols-2 gap-3 text-sm mb-3`},pe={class:`text-content-primary dark:text-content-primary/90 ml-2`},me={class:`text-content-primary dark:text-content-primary/90 ml-2`},he={class:`text-content-primary dark:text-content-primary/90 ml-2`},ge={class:`flex items-center gap-2`},_e={key:0,class:`text-content-primary dark:text-content-primary/90 font-mono ml-2 text-xs`},ve={key:1,class:`text-content-muted dark:text-content-muted ml-2 text-xs`},ye=[`onClick`],be={class:`text-xs text-content-muted dark:text-content-muted`},xe={key:0,class:`ml-2 font-mono text-content-primary dark:text-content-primary/90 break-all`},Se={key:1,class:`ml-2 text-content-muted dark:text-content-muted`},Ce={class:`ml-4 flex flex-wrap gap-2`},we=[`onClick`],Te=[`onClick`],Ee=[`onClick`],De={key:3,class:`text-center py-12 text-content-secondary dark:text-content-muted`},Oe={key:1,class:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`},ke={class:`bg-white dark:bg-surface-elevated backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-6 max-w-2xl w-full max-h-[90vh] overflow-y-auto`},Ae={class:`space-y-4`},je={class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},Me={key:0},Ne={key:1,class:`text-content-secondary dark:text-content-muted text-sm`},Pe={class:`grid grid-cols-2 gap-4`},Fe={key:2,class:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`},Ie={class:`bg-white dark:bg-surface-elevated backdrop-blur-xl border border-stroke-subtle dark:border-white/10 rounded-[15px] p-6 max-w-2xl w-full max-h-[90vh] overflow-y-auto`},Le={class:`space-y-4`},Re=[`value`],ze={class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},Be={key:0},Ve={class:`grid grid-cols-2 gap-4`},He=5050,Ue=1,We=65535,Ge=o({name:`CompanionsView`,__name:`Companions`,setup(t){let r=v(!1),o=v(null),c=v(null),d=v(!1),x=v(!1),S=v(null),C=v(!1),E=v(!1),D=v(new Set),O=v(!1),k=v(``),A=v(!1),j=v(``),M=v(!1),N=v({message:``,variant:`success`}),P=v({name:``,identity_key:``,type:`companion`,settings:{node_name:``,tcp_port:5e3,bind_address:`0.0.0.0`}});n(async()=>{await F()});async function F(){r.value=!0,o.value=null;try{let e=await y.getIdentities();e.success?c.value=e.data:o.value=e.error||`Failed to load identities`}catch(e){o.value=e instanceof Error?e.message:`Failed to load identities`}finally{r.value=!1}}async function ee(){try{let e=await y.createIdentity({...P.value,settings:{node_name:P.value.settings.node_name||P.value.name,tcp_port:P.value.settings.tcp_port??5e3,bind_address:P.value.settings.bind_address||`0.0.0.0`}});e.success?(d.value=!1,z(),await F(),L(e.message||`Companion created successfully!`,`success`)):L(`Failed to create companion: ${e.error}`,`error`)}catch(e){L(`Error creating companion: ${e}`,`error`)}}async function te(){try{let e=await y.updateIdentity({name:S.value.name,new_name:S.value.new_name,identity_key:S.value.identity_key,type:`companion`,settings:{node_name:S.value.settings?.node_name,tcp_port:S.value.settings?.tcp_port,bind_address:S.value.settings?.bind_address}});e.success?(x.value=!1,S.value=null,await F(),L(e.message||`Companion updated successfully!`,`success`)):L(`Failed to update companion: ${e.error}`,`error`)}catch(e){L(`Error updating companion: ${e}`,`error`)}}function ne(e){k.value=e,O.value=!0}async function I(){let e=k.value;O.value=!1;try{let t=await y.deleteIdentity(e,`companion`);t.success?(await F(),L(t.message||`Companion deleted successfully!`,`success`)):L(`Failed to delete companion: ${t.error}`,`error`)}catch(e){L(`Error deleting companion: ${e}`,`error`)}finally{k.value=``}}function L(e,t){N.value={message:e,variant:t},M.value=!0}function R(e){S.value=JSON.parse(JSON.stringify(e)),S.value.settings||(S.value.settings={node_name:``,tcp_port:5e3,bind_address:`0.0.0.0`}),S.value.new_name=``,E.value=!1,x.value=!0}function z(){P.value={name:``,identity_key:``,type:`companion`,settings:{node_name:``,tcp_port:5e3,bind_address:`0.0.0.0`}},C.value=!1}function B(){d.value=!1,x.value=!1,S.value=null,C.value=!1,E.value=!1,z()}function V(e){D.value.has(e)?D.value.delete(e):D.value.add(e)}let H=()=>c.value?.configured_companions??[],U=()=>c.value?.total_configured_companions??0;function Ge(){let e=H();if(e.length===0)return He;let t=e.map(e=>e.settings?.tcp_port??5e3),n=Math.max(...t)+1;return Math.min(We,Math.max(Ue,n))}function Ke(){z(),P.value.settings.tcp_port=Ge(),d.value=!0}function qe(e){j.value=e,A.value=!0}function Je(){A.value=!1,j.value=``}function Ye(e){L(`Imported ${e} contact${e===1?``:`s`}.`,`success`),Je()}return(t,n)=>(_(),g(m,null,[h(`div`,G,[h(`div`,{class:`relative overflow-hidden rounded-[20px] p-6 mb-6 glass-card backdrop-blur-xl border border-stroke-subtle dark:border-white/10`},[n[16]||=h(`div`,{class:`absolute inset-0 bg-gradient-to-br from-primary/20 via-secondary/10 to-accent-purple/20 opacity-50`},null,-1),n[17]||=h(`div`,{class:`absolute inset-0 bg-gradient-to-tl from-accent-green/10 via-transparent to-primary/10 animate-pulse`},null,-1),h(`div`,{class:`relative flex items-center justify-between`},[n[15]||=a(` Companions Manage companion identities (TCP frame server)
`,1),h(`button`,{onClick:Ke,class:`group relative px-6 py-3 bg-gradient-to-r from-primary/30 to-secondary/30 hover:from-primary/40 hover:to-secondary/40 text-content-primary dark:text-content-primary rounded-[12px] border border-primary/50 transition-all hover:scale-105 hover:shadow-lg hover:shadow-primary/20`},[...n[14]||=[h(`span`,{class:`flex items-center gap-2`},[h(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[h(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 4v16m8-8H4`})]),f(` Add Companion `)],-1)]])])]),c.value&&U()>0?(_(),g(`div`,K,[h(`div`,q,[h(`div`,J,[h(`div`,null,[n[18]||=h(`div`,{class:`text-content-secondary dark:text-content-muted text-xs font-medium mb-2 uppercase tracking-wide`},` Total Configured `,-1),h(`div`,Y,p(U()),1)])])])])):l(``,!0),h(`div`,X,[r.value?(_(),g(`div`,Z,[...n[19]||=[h(`div`,{class:`text-center`},[h(`div`,{class:`animate-spin w-8 h-8 border-2 border-stroke-subtle dark:border-stroke/20 border-t-primary rounded-full mx-auto mb-4`}),h(`div`,{class:`text-content-secondary dark:text-content-primary/70`},` Loading companions... `)],-1)]])):o.value?(_(),g(`div`,Q,[h(`div`,$,[n[20]||=h(`div`,{class:`text-red-600 dark:text-red-400 mb-2`},`Failed to load companions`,-1),h(`div`,re,p(o.value),1),h(`button`,{onClick:F,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors`},` Retry `)])])):c.value&&H().length>0?(_(),g(`div`,ie,[(_(!0),g(m,null,e(H(),e=>(_(),g(`div`,{key:e.name,class:`group relative overflow-hidden glass-card backdrop-blur-xl rounded-[15px] p-5 border border-stroke-subtle dark:border-white/10 hover:border-primary/30 transition-all duration-300`},[h(`div`,ae,[h(`div`,oe,[h(`div`,se,[h(`div`,ce,[e.registered?(_(),g(`div`,le)):l(``,!0),h(`div`,{class:i([`relative w-3 h-3 rounded-full`,e.registered?`bg-accent-green`:`bg-accent-red`])},null,2)]),h(`h3`,ue,p(e.name),1),h(`span`,{class:i([`px-3 py-1 text-xs font-semibold rounded-full`,e.registered?`bg-accent-green/20 text-accent-green border border-accent-green/30`:`bg-accent-red/20 text-accent-red border border-accent-red/30`])},p(e.registered?`● Active`:`○ Inactive`),3),e.hash?(_(),g(`span`,de,p(e.hash),1)):l(``,!0)]),h(`div`,fe,[h(`div`,null,[n[21]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`Node Name:`,-1),h(`span`,pe,p(e.settings?.node_name||e.name),1)]),h(`div`,null,[n[22]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`TCP Port:`,-1),h(`span`,me,p(e.settings?.tcp_port??5e3),1)]),h(`div`,null,[n[23]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`Bind Address:`,-1),h(`span`,he,p(e.settings?.bind_address||`0.0.0.0`),1)]),h(`div`,ge,[n[24]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`Identity Key:`,-1),D.value.has(e.name)?(_(),g(`span`,_e,p(e.identity_key),1)):(_(),g(`span`,ve,`••••••••••••••••`)),h(`button`,{onClick:t=>V(e.name),class:`text-primary/70 hover:text-primary text-xs underline`},p(D.value.has(e.name)?`Hide`:`Show`),9,ye)])]),h(`div`,be,[n[25]||=h(`span`,{class:`text-content-muted dark:text-content-muted`},`Public Key:`,-1),e.public_key?(_(),g(`span`,xe,p(e.public_key),1)):(_(),g(`span`,Se,`—`))])]),h(`div`,Ce,[h(`button`,{onClick:t=>qe(e.name),class:`px-3 py-1 bg-primary/20 hover:bg-primary/30 text-primary rounded text-xs transition-colors`},` Import contacts `,8,we),h(`button`,{onClick:t=>R(e),class:`px-3 py-1 bg-primary/20 hover:bg-primary/30 text-primary rounded text-xs transition-colors`},` Edit `,8,Te),h(`button`,{onClick:t=>ne(e.name),class:`px-3 py-1 bg-accent-red/20 hover:bg-accent-red/30 text-accent-red rounded text-xs transition-colors`},` Delete `,8,Ee)])])]))),128))])):(_(),g(`div`,De,[n[26]||=h(`svg`,{class:`w-16 h-16 mx-auto mb-4 text-content-muted dark:text-content-muted/60`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[h(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z`})],-1),n[27]||=h(`p`,{class:`text-lg mb-2`},`No companions configured`,-1),n[28]||=h(`p`,{class:`text-sm mb-4`},` Add a companion to run a TCP frame server for firmware or other clients `,-1),h(`button`,{onClick:Ke,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors`},` + Add Companion `)]))]),d.value?(_(),g(`div`,Oe,[h(`div`,ke,[n[35]||=h(`h2`,{class:`text-xl font-bold text-content-primary dark:text-content-primary mb-4`},` Add Companion `,-1),h(`div`,Ae,[h(`div`,null,[n[29]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Name *`,-1),s(h(`input`,{"onUpdate:modelValue":n[0]||=e=>P.value.name=e,type:`text`,placeholder:`e.g., TestCompanion`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.name]])]),h(`div`,null,[h(`label`,je,[n[30]||=f(` Identity Key (Optional) `,-1),h(`button`,{onClick:n[1]||=e=>C.value=!C.value,type:`button`,class:`ml-2 text-primary/70 hover:text-primary text-xs underline`},p(C.value?`Hide`:`Show/Edit`),1)]),C.value?(_(),g(`div`,Me,[s(h(`input`,{"onUpdate:modelValue":n[2]||=e=>P.value.identity_key=e,type:`text`,placeholder:`Leave empty to auto-generate (32 bytes hex)`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary font-mono text-sm placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.identity_key]]),n[31]||=h(`p`,{class:`text-content-secondary dark:text-content-muted text-xs mt-1`},` 32 or 64 bytes hex. Leave empty to auto-generate. `,-1)])):(_(),g(`div`,Ne,` Will be auto-generated if not provided `))]),h(`div`,null,[n[32]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Node Name`,-1),s(h(`input`,{"onUpdate:modelValue":n[3]||=e=>P.value.settings.node_name=e,type:`text`,placeholder:`Display name (defaults to Name)`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.settings.node_name]])]),h(`div`,Pe,[h(`div`,null,[n[33]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`TCP Port`,-1),s(h(`input`,{"onUpdate:modelValue":n[4]||=e=>P.value.settings.tcp_port=e,type:`number`,min:`1`,max:`65535`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.settings.tcp_port,void 0,{number:!0}]])]),h(`div`,null,[n[34]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Bind Address`,-1),s(h(`input`,{"onUpdate:modelValue":n[5]||=e=>P.value.settings.bind_address=e,type:`text`,placeholder:`0.0.0.0`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,P.value.settings.bind_address]])])])]),h(`div`,{class:`flex justify-end gap-3 mt-6`},[h(`button`,{onClick:B,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),h(`button`,{onClick:ee,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors`},` Create `)])])])):l(``,!0),x.value&&S.value?(_(),g(`div`,Fe,[h(`div`,Ie,[n[42]||=h(`h2`,{class:`text-xl font-bold text-content-primary dark:text-content-primary mb-4`},` Edit Companion `,-1),h(`div`,Le,[h(`div`,null,[n[36]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Current Name`,-1),h(`input`,{value:S.value.name,disabled:``,type:`text`,class:`w-full bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-muted dark:text-content-muted cursor-not-allowed`},null,8,Re)]),h(`div`,null,[n[37]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`New Name (optional)`,-1),s(h(`input`,{"onUpdate:modelValue":n[6]||=e=>S.value.new_name=e,type:`text`,placeholder:`Leave empty to keep current name`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.new_name]])]),h(`div`,null,[h(`label`,ze,[n[38]||=f(` Identity Key (Optional) `,-1),h(`button`,{onClick:n[7]||=e=>E.value=!E.value,type:`button`,class:`ml-2 text-primary/70 hover:text-primary text-xs underline`},p(E.value?`Hide`:`Show/Edit`),1)]),E.value?(_(),g(`div`,Be,[s(h(`input`,{"onUpdate:modelValue":n[8]||=e=>S.value.identity_key=e,type:`text`,placeholder:`Leave empty to keep current key`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary font-mono text-sm placeholder-gray-500 dark:placeholder-white/40 focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.identity_key]])])):l(``,!0)]),h(`div`,null,[n[39]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Node Name`,-1),s(h(`input`,{"onUpdate:modelValue":n[9]||=e=>S.value.settings.node_name=e,type:`text`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.settings.node_name]])]),h(`div`,Ve,[h(`div`,null,[n[40]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`TCP Port`,-1),s(h(`input`,{"onUpdate:modelValue":n[10]||=e=>S.value.settings.tcp_port=e,type:`number`,min:`1`,max:`65535`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.settings.tcp_port,void 0,{number:!0}]])]),h(`div`,null,[n[41]||=h(`label`,{class:`block text-content-secondary dark:text-content-primary/70 text-sm mb-2`},`Bind Address`,-1),s(h(`input`,{"onUpdate:modelValue":n[11]||=e=>S.value.settings.bind_address=e,type:`text`,class:`w-full bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg px-4 py-2 text-content-primary dark:text-content-primary focus:outline-none focus:border-primary/50 transition-colors`},null,512),[[b,S.value.settings.bind_address]])])])]),h(`div`,{class:`flex justify-end gap-3 mt-6`},[h(`button`,{onClick:B,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),h(`button`,{onClick:te,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-primary rounded-lg border border-primary/50 transition-colors`},` Update `)])])])):l(``,!0)]),u(W,{"is-open":A.value,"companion-name":j.value,onClose:Je,onImported:Ye},null,8,[`is-open`,`companion-name`]),u(w,{show:O.value,title:`Delete Companion`,message:`Are you sure you want to delete '${k.value}'? Restart required to fully remove.`,"confirm-text":`Delete`,"cancel-text":`Cancel`,variant:`danger`,onClose:n[12]||=e=>O.value=!1,onConfirm:I},null,8,[`show`,`message`]),u(T,{show:M.value,message:N.value.message,variant:N.value.variant,onClose:n[13]||=e=>M.value=!1},null,8,[`show`,`message`,`variant`])],64))}});export{Ge as default};
\ No newline at end of file
diff --git a/repeater/web/html/assets/Configuration--kPP7Ybw.js b/repeater/web/html/assets/Configuration-tPiZc7Z6.js
similarity index 99%
rename from repeater/web/html/assets/Configuration--kPP7Ybw.js
rename to repeater/web/html/assets/Configuration-tPiZc7Z6.js
index ebf2931..b0d110b 100644
--- a/repeater/web/html/assets/Configuration--kPP7Ybw.js
+++ b/repeater/web/html/assets/Configuration-tPiZc7Z6.js
@@ -1,2 +1,2 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/leaflet-src-PYB8oVmQ.js","assets/chunk-DECur_0Z.js"])))=>i.map(i=>d[i]);
-import{r as e}from"./chunk-DECur_0Z.js";import{A as t,C as n,D as r,E as i,K as a,R as o,S as s,b as c,c as l,dt as u,f as d,g as f,i as p,j as m,k as h,l as g,m as _,o as v,p as y,pt as b,r as x,s as S,u as C,w,x as T,z as E}from"./runtime-core.esm-bundler-HnidnMFy.js";import{o as D}from"./vue-router-Cr0wB7EX.js";import{a as O,n as k,t as A}from"./api-B2W0XzZe.js";import{t as j}from"./system-m4eSASWi.js";import{t as M}from"./_plugin-vue_export-helper-B7aGp3iI.js";import{c as N,d as P,f as F,h as I,l as L,m as R,p as z,u as B}from"./index-DiHOFPOZ.js";import{t as V}from"./ConfirmDialog-BECkBcWW.js";/* empty css */import{n as ee,t as H}from"./preferences-Bv8i60GL.js";var U={class:`space-y-4`},W={key:0,class:`bg-green-100 dark:bg-green-500/20 border border-green-500/50 rounded-lg p-3`},G={class:`text-green-600 dark:text-green-400 text-sm`},te={key:1,class:`bg-red-100 dark:bg-red-500/20 border border-red-500/50 rounded-lg p-3`},K={class:`text-red-600 dark:text-red-400 text-sm`},ne={class:`flex justify-end gap-2`},q=[`disabled`],J=[`disabled`],Y={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},X={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Z={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Q={key:1,class:`flex items-center gap-2`},re={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},$={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},ie={key:1},ae=[`value`],oe={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},se={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},ce={key:1},le=[`value`],ue={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},de={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},fe={key:1,class:`flex items-center gap-2`},pe={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},me={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},he={key:1},ge={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 gap-1`},_e={class:`text-content-primary dark:text-content-primary font-mono text-sm`},ve={key:2,class:`bg-yellow-500/10 dark:bg-yellow-500/10 border border-yellow-500/30 rounded-lg p-3`},ye=f({__name:`RadioSettings`,setup(e){let t=j(),n=v(()=>t.stats?.config?.radio||{}),r=E(!1),a=E(!1),o=E(null),s=E(null),c=E(0),l=E(0),u=E(0),d=E(0),f=E(0),p=E(0),_=[{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`}];h(n,e=>{e&&!r.value&&(c.value=e.frequency?Number((e.frequency/1e6).toFixed(3)):0,l.value=e.spreading_factor??0,u.value=e.bandwidth?Number((e.bandwidth/1e3).toFixed(1)):0,d.value=e.tx_power??0,f.value=e.coding_rate??0,p.value=e.preamble_length??0)},{immediate:!0});let T=v(()=>{let e=n.value.frequency;return e?(e/1e6).toFixed(3)+` MHz`:`Not set`}),D=v(()=>{let e=n.value.bandwidth;return e?(e/1e3).toFixed(1)+` kHz`:`Not set`}),O=v(()=>{let e=n.value.tx_power;return e===void 0?`Not set`:e+` dBm`}),k=v(()=>{let e=n.value.coding_rate;return e?`4/`+e:`Not set`}),M=v(()=>{let e=n.value.preamble_length;return e?e+` symbols`:`Not set`}),N=v(()=>n.value.spreading_factor??`Not set`),I=()=>{r.value=!0,o.value=null,s.value=null},L=()=>{r.value=!1,o.value=null;let e=n.value;c.value=e.frequency?Number((e.frequency/1e6).toFixed(3)):0,l.value=e.spreading_factor??0,u.value=e.bandwidth?Number((e.bandwidth/1e3).toFixed(1)):0,d.value=e.tx_power??0,f.value=e.coding_rate??0,p.value=e.preamble_length??0},R=async()=>{a.value=!0,o.value=null,s.value=null;try{let e={};c.value&&(e.frequency=c.value*1e6),l.value&&(e.spreading_factor=l.value),u.value&&(e.bandwidth=u.value*1e3),d.value&&(e.tx_power=d.value),f.value&&(e.coding_rate=f.value);let n=(await A.post(`/update_radio_config`,e)).data;n.message||n.persisted?(s.value=n.message||`Settings saved successfully`,r.value=!1,await t.fetchStats(),setTimeout(()=>{s.value=null},3e3)):n.error?o.value=n.error:o.value=`Unknown response from server`}catch(e){console.error(`Failed to update radio settings:`,e),o.value=e.response?.data?.error||`Failed to update settings`}finally{a.value=!1}};return(e,t)=>(w(),C(`div`,U,[s.value?(w(),C(`div`,W,[S(`p`,G,b(s.value),1)])):g(``,!0),o.value?(w(),C(`div`,te,[S(`p`,K,b(o.value),1)])):g(``,!0),S(`div`,ne,[r.value?(w(),C(x,{key:1},[S(`button`,{onClick:L,disabled:a.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,q),S(`button`,{onClick:R,disabled:a.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(a.value?`Saving...`:`Save Changes`),9,J)],64)):(w(),C(`button`,{key:0,onClick:I,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))]),S(`div`,Y,[S(`div`,X,[t[6]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Frequency`,-1),r.value?(w(),C(`div`,Q,[m(S(`input`,{"onUpdate:modelValue":t[0]||=e=>c.value=e,type:`number`,step:`0.001`,min:`100`,max:`1000`,class:`w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,c.value,void 0,{number:!0}]]),t[5]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`MHz`,-1)])):(w(),C(`div`,Z,b(T.value),1))]),S(`div`,re,[t[7]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Spreading Factor`,-1),r.value?(w(),C(`div`,ie,[m(S(`select`,{"onUpdate:modelValue":t[1]||=e=>l.value=e,class:`px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[(w(),C(x,null,i([5,6,7,8,9,10,11,12],e=>S(`option`,{key:e,value:e},b(e),9,ae)),64))],512),[[P,l.value,void 0,{number:!0}]])])):(w(),C(`div`,$,b(N.value),1))]),S(`div`,oe,[t[8]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Bandwidth`,-1),r.value?(w(),C(`div`,ce,[m(S(`select`,{"onUpdate:modelValue":t[2]||=e=>u.value=e,class:`px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[(w(),C(x,null,i(_,e=>S(`option`,{key:e.value,value:e.value},b(e.label),9,le)),64))],512),[[P,u.value,void 0,{number:!0}]])])):(w(),C(`div`,se,b(D.value),1))]),S(`div`,ue,[t[10]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`TX Power`,-1),r.value?(w(),C(`div`,fe,[m(S(`input`,{"onUpdate:modelValue":t[3]||=e=>d.value=e,type:`number`,min:`2`,max:`30`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,d.value,void 0,{number:!0}]]),t[9]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`dBm`,-1)])):(w(),C(`div`,de,b(O.value),1))]),S(`div`,pe,[t[12]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Coding Rate`,-1),r.value?(w(),C(`div`,he,[m(S(`select`,{"onUpdate:modelValue":t[4]||=e=>f.value=e,class:`px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[11]||=[S(`option`,{value:5},`4/5`,-1),S(`option`,{value:6},`4/6`,-1),S(`option`,{value:7},`4/7`,-1),S(`option`,{value:8},`4/8`,-1)]],512),[[P,f.value,void 0,{number:!0}]])])):(w(),C(`div`,me,b(k.value),1))]),S(`div`,ge,[t[13]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Preamble Length`,-1),S(`span`,_e,b(M.value),1)])]),r.value?(w(),C(`div`,ve,[...t[14]||=[S(`p`,{class:`text-yellow-700 dark:text-yellow-400 text-xs`},[S(`strong`,null,`Note:`),y(` Radio hardware changes (frequency, bandwidth, spreading factor, coding rate) may require a service restart to apply. `)],-1)]])):g(``,!0)]))}}),be={class:`glass-card border border-stroke-subtle dark:border-white/20 rounded-[15px] w-full max-w-3xl max-h-[90vh] flex flex-col shadow-2xl`},xe={class:`flex-1 relative min-h-[400px]`},Se={class:`p-6 border-t border-stroke-subtle dark:border-stroke/10 space-y-4`},Ce={class:`grid grid-cols-2 gap-4`},we=M(f({__name:`LocationPicker`,props:{isOpen:{type:Boolean},latitude:{},longitude:{}},emits:[`close`,`select`],setup(t,{emit:r}){let i=t,a=r,o=E(null),s=E(i.latitude||0),l=E(i.longitude||0),u=null,d=null,f=async()=>{if(o.value){p();try{let t=(await O(async()=>{let{default:t}=await import(`./leaflet-src-PYB8oVmQ.js`).then(t=>e(t.t(),1));return{default:t}},__vite__mapDeps([0,1]))).default;delete t.Icon.Default.prototype._getIconUrl,t.Icon.Default.mergeOptions({iconRetinaUrl:`https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png`,iconUrl:`https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png`,shadowUrl:`https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png`}),await c();let n=s.value||0,r=l.value||0,i=n===0&&r===0?2:13;u=t.map(o.value).setView([n,r],i);try{let e=t.tileLayer(`https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png`,{maxZoom:19,attribution:`© OpenStreetMap contributors © CARTO `,errorTileUrl:`data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==`}),n=t.tileLayer(`https://{s}.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}{r}.png`,{maxZoom:19,attribution:``,errorTileUrl:`data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==`});e.addTo(u),n.addTo(u)}catch(e){console.warn(`Error loading tiles:`,e)}(n!==0||r!==0)&&(d=t.marker([n,r]).addTo(u)),u.on(`click`,e=>{s.value=e.latlng.lat,l.value=e.latlng.lng,d?d.setLatLng(e.latlng):d=t.marker(e.latlng).addTo(u)}),setTimeout(()=>{u?.invalidateSize()},200)}catch(e){console.error(`Failed to initialize map:`,e)}}},p=()=>{u&&(u.remove(),u=null,d=null)};h(()=>i.isOpen,async e=>{e?(await c(),await f()):p()}),h(()=>[i.latitude,i.longitude],([e,t])=>{s.value=e,l.value=t});let _=()=>{a(`select`,{latitude:s.value,longitude:l.value}),a(`close`)},v=()=>{a(`close`)},b=()=>{navigator.geolocation?navigator.geolocation.getCurrentPosition(async t=>{if(s.value=t.coords.latitude,l.value=t.coords.longitude,u){u.setView([s.value,l.value],13);let t=(await O(async()=>{let{default:t}=await import(`./leaflet-src-PYB8oVmQ.js`).then(t=>e(t.t(),1));return{default:t}},__vite__mapDeps([0,1]))).default;d?d.setLatLng([s.value,l.value]):d=t.marker([s.value,l.value]).addTo(u)}},e=>{console.error(`Error getting location:`,e),alert(`Unable to get current location. Please check browser permissions.`)}):alert(`Geolocation is not supported by this browser.`)};return n(()=>{p()}),(e,n)=>t.isOpen?(w(),C(`div`,{key:0,class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm`,onClick:I(v,[`self`])},[S(`div`,be,[S(`div`,{class:`flex items-center justify-between p-6 border-b border-stroke-subtle dark:border-stroke/10`},[n[3]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Select Location `,-1),S(`button`,{onClick:v,class:`text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary transition-colors`},[...n[2]||=[S(`svg`,{class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),S(`div`,xe,[S(`div`,{ref_key:`mapContainer`,ref:o,class:`absolute inset-0 rounded-b-[15px] overflow-hidden`},null,512)]),S(`div`,Se,[S(`div`,Ce,[S(`div`,null,[n[4]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},`Latitude`,-1),m(S(`input`,{"onUpdate:modelValue":n[0]||=e=>s.value=e,type:`number`,step:`0.000001`,class:`w-full px-4 py-2 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary focus:outline-none focus:border-primary`,readonly:``},null,512),[[F,s.value,void 0,{number:!0}]])]),S(`div`,null,[n[5]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},`Longitude`,-1),m(S(`input`,{"onUpdate:modelValue":n[1]||=e=>l.value=e,type:`number`,step:`0.000001`,class:`w-full px-4 py-2 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary focus:outline-none focus:border-primary`,readonly:``},null,512),[[F,l.value,void 0,{number:!0}]])])]),S(`div`,{class:`flex gap-3`},[S(`button`,{onClick:b,class:`flex-1 px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm flex items-center justify-center gap-2`},[...n[6]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z`}),S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 11a3 3 0 11-6 0 3 3 0 016 0z`})],-1),y(` Use Current Location `,-1)]]),S(`button`,{onClick:v,class:`px-6 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm`},` Cancel `),S(`button`,{onClick:_,class:`px-6 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Select Location `)]),n[7]||=S(`p`,{class:`text-content-muted dark:text-content-muted text-xs text-center`},` Click on the map to select a location `,-1)])])])):g(``,!0)}}),[[`__scopeId`,`data-v-fd94857e`]]),Te={class:`space-y-4`},Ee={key:0,class:`bg-green-100 dark:bg-green-500/10 border border-green-300 dark:border-green-500/30 rounded-lg p-3`},De={class:`text-green-700 dark:text-green-400 text-sm`},Oe={key:1,class:`bg-red-100 dark:bg-red-500/10 border border-red-300 dark:border-red-500/30 rounded-lg p-3`},ke={class:`text-red-700 dark:text-red-400 text-sm`},Ae={class:`flex justify-end gap-2`},je=[`disabled`],Me=[`disabled`],Ne={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},Pe={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Fe={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm break-all`},Ie={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Le={class:`text-content-primary dark:text-content-primary font-mono text-xs break-all`},Re={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},ze={class:`flex flex-col items-end gap-1`},Be={class:`text-content-primary dark:text-content-primary font-mono text-xs break-all sm:text-right sm:max-w-xs`},Ve={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},He={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ue={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},We={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ge={key:0,class:`flex justify-end`},Ke={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},qe={class:`text-content-primary dark:text-content-primary font-mono text-sm`},Je={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ye={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Xe={class:`flex flex-col py-2 gap-2`},Ze={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-1`},Qe={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm sm:ml-4`},$e={key:1,class:`flex items-center gap-2`},et={class:`bg-surface dark:bg-surface-elevated border border-stroke-subtle dark:border-stroke/20 rounded-[15px] shadow-2xl w-full max-w-md p-6 space-y-4`},tt={class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},nt=[`maxlength`,`disabled`],rt={key:0,class:`text-red-500 text-xs mt-1`},it={key:1,class:`text-content-muted dark:text-content-muted text-xs mt-1`},at=[`disabled`],ot={key:0,class:`mt-2 bg-amber-500/10 border border-amber-500/30 rounded-lg p-3`},st={key:0,class:`flex items-center gap-3 bg-blue-500/10 border border-blue-500/30 rounded-lg p-3`},ct={class:`text-blue-700 dark:text-blue-400 text-xs font-medium`},lt={class:`text-blue-600 dark:text-blue-500 text-xs mt-0.5`},ut={key:1,class:`bg-red-500/10 border border-red-500/30 rounded-lg p-3`},dt={class:`text-red-600 dark:text-red-400 text-sm`},ft={key:2,class:`bg-green-500/10 border border-green-600/40 dark:border-green-500/30 rounded-lg p-3 space-y-2`},pt={class:`text-green-600 dark:text-green-400 text-sm font-medium`},mt={class:`font-mono text-xs break-all text-content-primary dark:text-content-primary`},ht={key:3,class:`bg-amber-500/10 border border-amber-500/30 rounded-lg p-3`},gt={class:`flex gap-2 mt-3`},_t=[`disabled`],vt=[`disabled`],yt={class:`flex justify-end gap-3 mt-6`},bt=[`disabled`],xt=[`disabled`],St=f({__name:`RepeaterSettings`,setup(e){let t=j(),n=v(()=>t.stats?.config||{}),r=v(()=>n.value.repeater||{}),i=v(()=>t.stats),a=E(!1),o=E(!1),s=E(null),c=E(null),d=E(!1),f=E(``),D=E(0),O=E(0),k=E(0),M=E(1),N=v(()=>n.value.mesh||{});h([n,r,N],()=>{if(!a.value){f.value=n.value.node_name||``,D.value=r.value.latitude||0,O.value=r.value.longitude||0,k.value=r.value.send_advert_interval_hours||0;let e=N.value.path_hash_mode;M.value=e===0||e===1||e===2?e+1:1}},{immediate:!0});let L=v(()=>n.value.node_name||`Not set`),R=v(()=>i.value?.local_hash||`Not available`),z=v(()=>{let e=i.value?.public_key;return!e||e===`Not set`?`Not set`:e}),B=v(()=>{let e=r.value.latitude;return e&&e!==0?e.toFixed(6):`Not set`}),V=v(()=>{let e=r.value.longitude;return e&&e!==0?e.toFixed(6):`Not set`}),ee=v(()=>{let e=r.value.mode;return e?e===`no_tx`?`No TX`:e.charAt(0).toUpperCase()+e.slice(1):`Not set`}),H=v(()=>{let e=r.value.send_advert_interval_hours;return e===void 0?`Not set`:e===0?`Disabled`:e+` hour`+(e===1?``:`s`)}),U=v(()=>{let e=N.value.path_hash_mode;return e===0||e===1||e===2?e+1+(e===0?` byte`:` bytes`):`Not set`}),W=()=>{a.value=!0,s.value=null,c.value=null},G=()=>{a.value=!1,s.value=null,f.value=n.value.node_name||``,D.value=r.value.latitude||0,O.value=r.value.longitude||0,k.value=r.value.send_advert_interval_hours||0;let e=N.value.path_hash_mode;M.value=e===0||e===1||e===2?e+1:1},te=async()=>{o.value=!0,s.value=null,c.value=null;try{let e={};f.value&&(e.node_name=f.value),e.latitude=D.value,e.longitude=O.value,e.flood_advert_interval_hours=k.value,e.path_hash_mode=M.value-1;let n=(await A.post(`/update_radio_config`,e)).data;n.message||n.persisted?(c.value=n.message||`Settings saved successfully`,a.value=!1,await t.fetchStats(),setTimeout(()=>{c.value=null},3e3)):n.error?s.value=n.error:s.value=`Unknown response from server`}catch(e){console.error(`Failed to update repeater settings:`,e),s.value=e.response?.data?.error||`Failed to update settings`}finally{o.value=!1}},K=()=>{d.value=!0},ne=e=>{D.value=e.latitude,O.value=e.longitude},q=E(!1),J=E(``),Y=E(!1),X=E(null),Z=E(null),Q=E(!1),re=E(!1),$=E(!1),ie=E(0),ae=null,oe=v(()=>$.value?8:4),se=v(()=>{let e=J.value.trim();return!e||e.length>oe.value?!1:/^[0-9a-fA-F]+$/.test(e)}),ce=v(()=>{let e=J.value.trim().length;return e===0?``:e===1?`Very fast — ~16 attempts on average`:e===2?`Fast — ~256 attempts on average`:e===3?`Moderate — ~4,096 attempts, a few seconds`:e===4?`Slow — ~65,536 attempts, may take 10-30 seconds`:e===5?`Very slow — ~1 million attempts, could take minutes`:e===6?`Extremely slow — ~16 million attempts, could take a very long time`:e===7?`Extreme — ~268 million attempts, may not complete`:`Extreme — ~4 billion attempts, extremely unlikely to complete`}),le=()=>{ie.value=0,ae=setInterval(()=>{ie.value++},1e3)},ue=()=>{ae&&=(clearInterval(ae),null)};T(()=>ue());let de=()=>{J.value=``,X.value=null,Z.value=null,Q.value=!1,$.value=!1,q.value=!0},fe=async()=>{Y.value=!0,Z.value=null,X.value=null,le();try{let e=await A.generateVanityKey(J.value.trim());e.success&&e.data?X.value=e.data:Z.value=e.error||`Generation failed`}catch(e){let t=e;Z.value=t.response?.data?.error||t.message||`Generation failed`}finally{ue(),Y.value=!1}},pe=async()=>{if(X.value){re.value=!0,Z.value=null;try{let e=await A.generateVanityKey(J.value.trim(),!0);e.success&&e.data?(X.value=e.data,Q.value=!1,q.value=!1,c.value=`New identity key applied. Restart the repeater for the change to take effect.`,await t.fetchStats(),setTimeout(()=>{c.value=null},8e3)):Z.value=e.error||`Failed to apply key`}catch(e){let t=e;Z.value=t.response?.data?.error||t.message||`Failed to apply key`}finally{re.value=!1}}};return(e,t)=>(w(),C(`div`,Te,[c.value?(w(),C(`div`,Ee,[S(`p`,De,b(c.value),1)])):g(``,!0),s.value?(w(),C(`div`,Oe,[S(`p`,ke,b(s.value),1)])):g(``,!0),S(`div`,Ae,[a.value?(w(),C(x,{key:1},[S(`button`,{onClick:G,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,je),S(`button`,{onClick:te,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(o.value?`Saving...`:`Save Changes`),9,Me)],64)):(w(),C(`button`,{key:0,onClick:W,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))]),S(`div`,Ne,[S(`div`,Pe,[t[13]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Node Name`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[0]||=e=>f.value=e,type:`text`,maxlength:`50`,class:`w-full sm:w-64 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`,placeholder:`Enter node name`},null,512)),[[F,f.value]]):(w(),C(`div`,Fe,b(L.value),1))]),S(`div`,Ie,[t[14]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Local Hash`,-1),S(`span`,Le,b(R.value),1)]),S(`div`,Re,[t[15]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm flex-shrink-0`},`Public Key`,-1),S(`div`,ze,[S(`span`,Be,b(z.value),1),S(`button`,{onClick:de,class:`px-2 py-1 text-xs bg-primary/10 hover:bg-primary/20 text-content-secondary dark:text-content-muted rounded border border-primary/30 transition-colors`},` Generate New Key `)])]),S(`div`,Ve,[t[16]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Manual Latitude`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[1]||=e=>D.value=e,type:`number`,step:`0.000001`,min:`-90`,max:`90`,class:`w-full sm:w-48 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,D.value,void 0,{number:!0}]]):(w(),C(`div`,He,b(B.value),1))]),S(`div`,Ue,[t[17]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Manual Longitude`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[2]||=e=>O.value=e,type:`number`,step:`0.000001`,min:`-180`,max:`180`,class:`w-full sm:w-48 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,O.value,void 0,{number:!0}]]):(w(),C(`div`,We,b(V.value),1))]),a.value?(w(),C(`div`,Ge,[S(`button`,{onClick:K,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm flex items-center gap-2`,title:`Pick location on map`},[...t[18]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z`}),S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 11a3 3 0 11-6 0 3 3 0 016 0z`})],-1),y(` Pick Location on Map `,-1)]])])):g(``,!0),S(`div`,Ke,[t[19]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Mode`,-1),S(`span`,qe,b(ee.value),1)]),S(`div`,Je,[t[21]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Path hash length`,-1),a.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[3]||=e=>M.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[20]||=[S(`option`,{value:1},`1 byte`,-1),S(`option`,{value:2},`2 bytes`,-1),S(`option`,{value:3},`3 bytes`,-1)]],512)),[[P,M.value,void 0,{number:!0}]]):(w(),C(`div`,Ye,b(U.value),1))]),S(`div`,Xe,[S(`div`,Ze,[t[23]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Periodic Advertisement Interval`,-1),a.value?(w(),C(`div`,$e,[m(S(`input`,{"onUpdate:modelValue":t[4]||=e=>k.value=e,type:`number`,min:`0`,max:`48`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,k.value,void 0,{number:!0}]]),t[22]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`hours`,-1)])):(w(),C(`div`,Qe,b(H.value),1))]),t[24]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-xs`},`How often the repeater sends an advertisement packet (0 = disabled, 3-48 hours)`,-1)])]),_(we,{"is-open":d.value,latitude:D.value,longitude:O.value,onClose:t[5]||=e=>d.value=!1,onSelect:ne},null,8,[`is-open`,`latitude`,`longitude`]),(w(),l(p,{to:`body`},[q.value?(w(),C(`div`,{key:0,class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm`,onClick:t[12]||=I(e=>q.value=!1,[`self`])},[S(`div`,et,[t[32]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Generate Vanity Identity Key `,-1),t[33]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Generate a new Ed25519 identity key whose public key starts with your chosen hex prefix (0-9, A-F). Longer prefixes take more time to find. `,-1),S(`div`,null,[S(`label`,tt,`Hex Prefix (1-`+b(oe.value)+` characters)`,1),m(S(`input`,{"onUpdate:modelValue":t[6]||=e=>J.value=e,type:`text`,maxlength:oe.value,placeholder:`e.g. F8A1`,disabled:Y.value,class:`w-full px-4 py-2 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-400 dark:placeholder-white/40 font-mono text-sm uppercase focus:outline-none focus:border-primary transition-colors disabled:opacity-50`},null,8,nt),[[F,J.value]]),J.value&&!se.value?(w(),C(`p`,rt,` Enter 1-`+b(oe.value)+` valid hex characters (0-9, A-F) `,1)):ce.value?(w(),C(`p`,it,b(ce.value),1)):g(``,!0)]),S(`div`,null,[S(`button`,{onClick:t[7]||=e=>$.value=!$.value,disabled:Y.value,class:`text-xs text-content-muted dark:text-content-muted hover:text-content-secondary dark:hover:text-content-secondary transition-colors disabled:opacity-50 flex items-center gap-1`},[(w(),C(`svg`,{class:u([`w-3 h-3 transition-transform`,{"rotate-90":$.value}]),fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[...t[25]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 5l7 7-7 7`},null,-1)]],2)),t[26]||=y(` Advanced `,-1)],8,at),$.value?(w(),C(`div`,ot,[...t[27]||=[S(`p`,{class:`text-amber-600 dark:text-amber-400 text-xs font-medium`},` Extended prefix mode (up to 8 characters) `,-1),S(`p`,{class:`text-amber-600 dark:text-amber-500 text-xs mt-1`},` Prefixes longer than 4 characters require exponentially more attempts and can take a very long time or may not complete at all. The request may time out. `,-1)]])):g(``,!0)]),Y.value?(w(),C(`div`,st,[t[28]||=S(`svg`,{class:`animate-spin h-5 w-5 text-blue-500 flex-shrink-0`,xmlns:`http://www.w3.org/2000/svg`,fill:`none`,viewBox:`0 0 24 24`},[S(`circle`,{class:`opacity-25`,cx:`12`,cy:`12`,r:`10`,stroke:`currentColor`,"stroke-width":`4`}),S(`path`,{class:`opacity-75`,fill:`currentColor`,d:`M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z`})],-1),S(`div`,null,[S(`p`,ct,` Searching for key with prefix "`+b(J.value.toUpperCase())+`"... `,1),S(`p`,lt,` Elapsed: `+b(ie.value)+`s `,1)])])):g(``,!0),Z.value?(w(),C(`div`,ut,[S(`p`,dt,b(Z.value),1)])):g(``,!0),X.value?(w(),C(`div`,ft,[S(`p`,pt,` Key found in `+b(X.value.attempts.toLocaleString())+` attempts `,1),S(`div`,null,[t[29]||=S(`span`,{class:`text-xs text-content-muted dark:text-content-muted`},`Public Key:`,-1),S(`p`,mt,b(X.value.public_hex),1)])])):g(``,!0),Q.value&&X.value?(w(),C(`div`,ht,[t[30]||=S(`p`,{class:`text-amber-600 dark:text-amber-400 text-sm font-medium`},` Warning: This will replace your current identity key. `,-1),t[31]||=S(`p`,{class:`text-amber-600 dark:text-amber-500 text-xs mt-1`},` Your node address and public key will change. Other nodes will need to re-discover you. This cannot be undone unless you have a backup. `,-1),S(`div`,gt,[S(`button`,{onClick:pe,disabled:re.value,class:`px-3 py-1.5 bg-red-600 hover:bg-red-700 text-white rounded-lg text-xs transition-colors disabled:opacity-50`},b(re.value?`Applying...`:`Confirm Replace Key`),9,_t),S(`button`,{onClick:t[8]||=e=>Q.value=!1,disabled:re.value,class:`px-3 py-1.5 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 text-xs transition-colors`},` Cancel `,8,vt)])])):g(``,!0),S(`div`,yt,[S(`button`,{onClick:t[9]||=e=>q.value=!1,disabled:Y.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/10 transition-colors`},` Close `,8,bt),X.value?(w(),C(x,{key:1},[S(`button`,{onClick:t[10]||=e=>{X.value=null,Z.value=null},class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 text-sm transition-colors`},` Try Again `),Q.value?g(``,!0):(w(),C(`button`,{key:0,onClick:t[11]||=e=>Q.value=!0,class:`px-4 py-2 bg-red-600/20 hover:bg-red-600/30 text-red-600 dark:text-red-400 rounded-lg border border-red-500/50 text-sm transition-colors`},` Apply Key `))],64)):(w(),C(`button`,{key:0,onClick:fe,disabled:!se.value||Y.value,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 text-sm transition-colors disabled:opacity-50 disabled:cursor-not-allowed`},b(Y.value?`Generating...`:`Generate`),9,xt))])])])):g(``,!0)]))]))}}),Ct={class:`space-y-4`},wt={key:0,class:`bg-green-100 dark:bg-green-500/20 border border-green-500 dark:border-green-500/50 rounded-lg p-3 text-green-700 dark:text-green-400 text-sm`},Tt={key:1,class:`bg-red-100 dark:bg-red-500/20 border border-red-500 dark:border-red-500/50 rounded-lg p-3 text-red-700 dark:text-red-400 text-sm`},Et={class:`flex justify-end gap-2`},Dt=[`disabled`],Ot=[`disabled`],kt={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},At={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},jt={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Mt={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 gap-1`},Nt={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Pt=f({__name:`DutyCycle`,setup(e){let t=j(),n=v(()=>t.stats?.config?.duty_cycle||{}),r=v(()=>{let e=n.value.max_airtime_percent;return typeof e==`number`?e.toFixed(1)+`%`:e&&typeof e==`object`&&`parsedValue`in e?(e.parsedValue||0).toFixed(1)+`%`:`Not set`}),i=v(()=>n.value.enforcement_enabled?`Enabled`:`Disabled`),a=E(!1),o=E(!1),s=E(``),c=E(``),l=E(0),u=E(!0),d=()=>{let e=n.value.max_airtime_percent;typeof e==`number`?l.value=e:e&&typeof e==`object`&&`parsedValue`in e?l.value=e.parsedValue||0:l.value=6,u.value=n.value.enforcement_enabled!==!1,a.value=!0,s.value=``,c.value=``},f=()=>{a.value=!1,s.value=``,c.value=``},p=async()=>{o.value=!0,c.value=``,s.value=``;try{let e=(await k.post(`/api/update_duty_cycle_config`,{max_airtime_percent:l.value,enforcement_enabled:u.value})).data;e.message||e.persisted?(s.value=e.message||`Settings saved successfully`,a.value=!1,await t.fetchStats(),setTimeout(()=>{s.value=``},3e3)):c.value=`Failed to save settings`}catch(e){console.error(`Failed to save duty cycle settings:`,e),c.value=e.response?.data?.error||`Failed to save settings`}finally{o.value=!1}};return(e,t)=>(w(),C(`div`,Ct,[s.value?(w(),C(`div`,wt,b(s.value),1)):g(``,!0),c.value?(w(),C(`div`,Tt,b(c.value),1)):g(``,!0),S(`div`,Et,[a.value?(w(),C(x,{key:1},[S(`button`,{onClick:f,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,Dt),S(`button`,{onClick:p,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(o.value?`Saving...`:`Save Changes`),9,Ot)],64)):(w(),C(`button`,{key:0,onClick:d,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))]),S(`div`,kt,[S(`div`,At,[t[2]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Max Airtime %`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[0]||=e=>l.value=e,type:`number`,step:`0.1`,min:`0.1`,max:`100`,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,l.value,void 0,{number:!0}]]):(w(),C(`div`,jt,b(r.value),1))]),S(`div`,Mt,[t[4]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Enforcement`,-1),a.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[1]||=e=>u.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[3]||=[S(`option`,{value:!0},`Enabled`,-1),S(`option`,{value:!1},`Disabled`,-1)]],512)),[[P,u.value]]):(w(),C(`div`,Nt,b(i.value),1))])])]))}}),Ft={class:`space-y-4`},It={key:0,class:`bg-green-100 dark:bg-green-500/20 border border-green-500 dark:border-green-500/50 rounded-lg p-3 text-green-700 dark:text-green-400 text-sm`},Lt={key:1,class:`bg-red-100 dark:bg-red-500/20 border border-red-500 dark:border-red-500/50 rounded-lg p-3 text-red-700 dark:text-red-400 text-sm`},Rt={class:`flex justify-end gap-2`},zt=[`disabled`],Bt=[`disabled`],Vt={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},Ht={class:`flex flex-col py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-2`},Ut={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-1`},Wt={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm sm:ml-4`},Gt={class:`flex flex-col py-2 gap-2`},Kt={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-1`},qt={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm sm:ml-4`},Jt=f({__name:`TransmissionDelays`,setup(e){let t=j(),n=v(()=>t.stats?.config?.delays||{}),r=v(()=>{let e=n.value.tx_delay_factor;if(e&&typeof e==`object`&&e&&`parsedValue`in e){let t=e.parsedValue;if(typeof t==`number`)return t.toFixed(2)+`x`}return`Not set`}),i=v(()=>{let e=n.value.direct_tx_delay_factor;return typeof e==`number`?e.toFixed(2)+`s`:`Not set`}),a=E(!1),o=E(!1),s=E(``),c=E(``),l=E(0),u=E(0),d=()=>{let e=n.value.tx_delay_factor;e&&typeof e==`object`&&`parsedValue`in e?l.value=e.parsedValue||1:typeof e==`number`?l.value=e:l.value=1;let t=n.value.direct_tx_delay_factor;u.value=typeof t==`number`?t:.5,a.value=!0,s.value=``,c.value=``},f=()=>{a.value=!1,s.value=``,c.value=``},p=async()=>{o.value=!0,c.value=``,s.value=``;try{let e=(await k.post(`/api/update_radio_config`,{tx_delay_factor:l.value,direct_tx_delay_factor:u.value})).data;e.message||e.persisted?(s.value=e.message||`Settings saved successfully`,a.value=!1,await t.fetchStats(),setTimeout(()=>{s.value=``},3e3)):c.value=`Failed to save settings`}catch(e){console.error(`Failed to save delay settings:`,e),c.value=e.response?.data?.error||`Failed to save settings`}finally{o.value=!1}};return(e,t)=>(w(),C(`div`,Ft,[s.value?(w(),C(`div`,It,b(s.value),1)):g(``,!0),c.value?(w(),C(`div`,Lt,b(c.value),1)):g(``,!0),S(`div`,Rt,[a.value?(w(),C(x,{key:1},[S(`button`,{onClick:f,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,zt),S(`button`,{onClick:p,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(o.value?`Saving...`:`Save Changes`),9,Bt)],64)):(w(),C(`button`,{key:0,onClick:d,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))]),S(`div`,Vt,[S(`div`,Ht,[S(`div`,Ut,[t[2]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Flood TX Delay Factor`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[0]||=e=>l.value=e,type:`number`,step:`0.1`,min:`0`,max:`5`,class:`w-full sm:w-32 px-3 py-1.5 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,l.value,void 0,{number:!0}]]):(w(),C(`div`,Wt,b(r.value),1))]),t[3]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-xs`},`Multiplier for flood packet transmission delays (collision avoidance)`,-1)]),S(`div`,Gt,[S(`div`,Kt,[t[4]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Direct TX Delay Factor`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[1]||=e=>u.value=e,type:`number`,step:`0.1`,min:`0`,max:`5`,class:`w-full sm:w-32 px-3 py-1.5 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,u.value,void 0,{number:!0}]]):(w(),C(`div`,qt,b(i.value),1))]),t[5]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-xs`},`Base delay for direct-routed packet transmission (seconds)`,-1)])])]))}}),Yt=D(`treeState`,()=>{let e=o(new Set),t=o({value:null}),n=t=>{e.add(t)},r=t=>{e.delete(t)};return{expandedNodes:e,selectedNodeId:t,addExpandedNode:n,removeExpandedNode:r,isNodeExpanded:t=>e.has(t),setSelectedNode:e=>{t.value=e},toggleExpanded:t=>{e.has(t)?r(t):n(t)}}}),Xt={class:`select-none`},Zt={class:`flex-shrink-0`},Qt={key:0,class:`w-3.5 h-3.5 sm:w-4 sm:h-4 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},$t={key:1,class:`w-3.5 h-3.5 sm:w-4 sm:h-4 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},en={key:0,class:`hidden sm:flex items-center gap-1 ml-2`},tn={class:`relative group`},nn=[`title`],rn={key:0,class:`text-xs font-mono text-white/50 bg-white/5 px-1.5 py-0.5 rounded border border-white/10`},an={class:`flex justify-between items-start mb-4`},on={class:`bg-black/20 border border-white/10 rounded-md p-4 mb-4`},sn={class:`text-sm font-mono text-white/80 break-all leading-relaxed`},cn={class:`flex items-center gap-1 sm:gap-2 ml-auto flex-shrink-0`},ln={key:0,class:`hidden sm:flex items-center gap-1`},un=[`title`],dn={key:1,class:`hidden sm:flex items-center gap-1`},fn={key:2,class:`hidden sm:inline-block px-2 py-1 bg-white/10 text-white/60 text-xs rounded-full ml-1`},pn={key:0,class:`space-y-1`},mn=M(f({__name:`TreeNode`,props:{node:{},selectedNodeId:{},level:{},disabled:{type:Boolean}},emits:[`select`],setup(e,{emit:n}){let a=e,o=n,s=Yt(),c=E(!1),d=v({get:()=>s.isNodeExpanded(a.node.id),set:e=>{e?s.addExpandedNode(a.node.id):s.removeExpandedNode(a.node.id)}}),f=v(()=>a.node.children.length>0);function p(e){if(!e)return`Never`;let t=new Date().getTime()-e.getTime(),n=Math.floor(t/(1e3*60)),r=Math.floor(t/(1e3*60*60)),i=Math.floor(t/(1e3*60*60*24)),a=Math.floor(i/365);return n<60?`${n}m ago`:r<24?`${r}h ago`:i<365?`${i}d ago`:`${a}y ago`}function m(e){return e?e.length<=16?e:`${e.slice(0,8)}...${e.slice(-8)}`:`No key`}function h(){f.value&&(d.value=!d.value)}function T(){o(`select`,a.node.id)}function D(e){o(`select`,e)}function O(e){e.stopPropagation(),c.value=!c.value}function k(e){e.stopPropagation(),a.node.transport_key&&window.navigator?.clipboard&&window.navigator.clipboard.writeText(a.node.transport_key)}return(n,o)=>{let s=r(`TreeNode`,!0);return w(),C(`div`,Xt,[S(`div`,{class:u([`flex flex-wrap sm:flex-nowrap items-start sm:items-center gap-1 sm:gap-2 py-2 px-2 sm:px-3 rounded-lg cursor-pointer transition-all duration-200`,a.disabled?`opacity-50 cursor-not-allowed`:`hover:bg-white/5`,e.selectedNodeId===e.node.id&&!a.disabled?`bg-primary/20 text-primary`:`text-white/80 hover:text-white`,`ml-${e.level*4}`]),onClick:o[3]||=e=>!a.disabled&&T()},[S(`div`,{class:`flex-shrink-0 w-3 h-3 sm:w-4 sm:h-4 flex items-center justify-center`,onClick:I(h,[`stop`])},[f.value?(w(),C(`svg`,{key:0,class:u([`w-2.5 h-2.5 sm:w-3 sm:h-3 transition-transform duration-200`,d.value?`rotate-90`:`rotate-0`]),fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[...o[4]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 5l7 7-7 7`},null,-1)]],2)):g(``,!0)]),S(`div`,Zt,[a.node.name.startsWith(`#`)?(w(),C(`svg`,Qt,[...o[5]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,$t,[...o[6]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`},null,-1)]]))]),S(`span`,{class:u([`font-mono text-xs sm:text-sm transition-colors duration-200 break-all`,e.selectedNodeId===e.node.id?`text-primary font-medium`:``])},b(e.node.name),3),e.node.transport_key?(w(),C(`div`,en,[S(`div`,tn,[S(`button`,{onClick:O,class:`p-1 rounded hover:bg-white/10 transition-colors`,title:c.value?`Hide full key`:`Show full key`},[...o[7]||=[S(`svg`,{class:`w-3 h-3 text-white/60 hover:text-white/80`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 12a3 3 0 11-6 0 3 3 0 016 0z`}),S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z`})],-1)]],8,nn),c.value?g(``,!0):(w(),C(`span`,rn,b(m(e.node.transport_key)),1)),c.value?(w(),C(`div`,{key:1,class:`fixed inset-0 z-[9998] flex items-center justify-center bg-black/70 backdrop-blur-md`,onClick:o[2]||=e=>c.value=!1},[S(`div`,{class:`bg-black/20 border border-white/20 rounded-lg shadow-lg p-6 max-w-2xl w-full mx-4`,onClick:o[1]||=I(()=>{},[`stop`])},[S(`div`,an,[o[9]||=S(`h3`,{class:`text-lg font-semibold text-white`},`Transport Key`,-1),S(`button`,{onClick:o[0]||=e=>c.value=!1,class:`text-white/60 hover:text-white transition-colors`},[...o[8]||=[S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),S(`div`,on,[S(`div`,sn,b(e.node.transport_key),1)]),S(`div`,{class:`flex justify-end`},[S(`button`,{onClick:k,class:`px-4 py-2 bg-accent-green/20 hover:bg-accent-green/30 border border-accent-green/50 text-accent-green rounded-lg transition-colors flex items-center gap-2`,title:`Copy to clipboard`},[...o[10]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z`})],-1),y(` Copy Key `,-1)]])])])])):g(``,!0)])])):g(``,!0),S(`div`,cn,[e.node.last_used?(w(),C(`div`,ln,[o[11]||=S(`svg`,{class:`w-3 h-3 text-white/40`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),S(`span`,{class:`text-xs text-white/50`,title:e.node.last_used.toLocaleString()},b(p(e.node.last_used)),9,un)])):(w(),C(`div`,dn,[...o[12]||=[S(`svg`,{class:`w-3 h-3 text-white/30`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),S(`span`,{class:`text-xs text-white/30 italic`},`Never`,-1)]])),S(`span`,{class:u([`px-1.5 sm:px-2 py-0.5 text-[10px] sm:text-xs font-medium rounded-md transition-colors`,e.node.floodPolicy===`allow`?`bg-accent-green/10 text-accent-green/90 border border-accent-green/20`:`bg-accent-red/10 text-accent-red/90 border border-accent-red/20`])},b(e.node.floodPolicy===`allow`?`ALLOW`:`DENY`),3),f.value?(w(),C(`span`,fn,` > `+b(e.node.children.length),1)):g(``,!0)])],2),_(N,{"enter-active-class":`transition-all duration-300 ease-out`,"enter-from-class":`opacity-0 max-h-0 overflow-hidden`,"enter-to-class":`opacity-100 max-h-screen overflow-visible`,"leave-active-class":`transition-all duration-300 ease-in`,"leave-from-class":`opacity-100 max-h-screen overflow-visible`,"leave-to-class":`opacity-0 max-h-0 overflow-hidden`},{default:t(()=>[d.value&&e.node.children.length>0?(w(),C(`div`,pn,[(w(!0),C(x,null,i(e.node.children,t=>(w(),l(s,{key:t.id,node:t,"selected-node-id":e.selectedNodeId,level:e.level+1,disabled:a.disabled,onSelect:D},null,8,[`node`,`selected-node-id`,`level`,`disabled`]))),128))])):g(``,!0)]),_:1})])}}}),[[`__scopeId`,`data-v-ed9c8a11`]]),hn={class:`flex items-center justify-between mb-6`},gn={class:`text-content-secondary dark:text-content-muted text-sm mt-1`},_n={key:0},vn={class:`text-primary font-mono`},yn={key:1},bn={for:`keyName`,class:`block text-sm font-medium text-white mb-2`},xn={class:`flex items-center gap-2`},Sn={key:0,class:`w-4 h-4 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Cn={key:1,class:`w-4 h-4 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},wn={class:`bg-gray-50 dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-4`},Tn={class:`flex items-center gap-3 mb-2`},En={class:`flex items-center gap-2`},Dn={key:0,class:`w-5 h-5 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},On={key:1,class:`w-5 h-5 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},kn={class:`text-content-secondary dark:text-content-muted text-sm`},An={class:`grid grid-cols-2 gap-3`},jn={class:`relative cursor-pointer group`},Mn={class:`relative cursor-pointer group`},Nn={class:`flex gap-3 pt-4`},Pn=[`disabled`],Fn=f({__name:`AddKeyModal`,props:{show:{type:Boolean},selectedNodeName:{},selectedNodeId:{}},emits:[`close`,`add`],setup(e,{emit:t}){let n=e,r=t,i=E(``),a=E(``),o=E(`allow`),s=v(()=>i.value.startsWith(`#`)),c=v(()=>({type:s.value?`Region`:`Private Key`,description:s.value?`Regional organizational key`:`Individual assigned key`}));h(s,e=>{e?a.value=`This will create a new region for organizing keys`:a.value=`This will create a new private key entry`},{immediate:!0});let l=v(()=>i.value.trim().length>0),f=()=>{l.value&&(r(`add`,{name:i.value.trim(),floodPolicy:o.value,parentId:n.selectedNodeId}),i.value=``,a.value=``,o.value=`allow`)},p=()=>{i.value=``,a.value=``,o.value=`allow`,r(`close`)},_=e=>{e.target===e.currentTarget&&p()};return(t,r)=>e.show?(w(),C(`div`,{key:0,onClick:_,class:`fixed inset-0 bg-black/40 backdrop-blur-lg z-[99999] flex items-center justify-center p-4`,style:{"backdrop-filter":`blur(8px) saturate(180%)`,position:`fixed`,top:`0`,left:`0`,right:`0`,bottom:`0`}},[S(`div`,{class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] p-6 w-full max-w-md border border-stroke-subtle dark:border-white/10`,onClick:r[3]||=I(()=>{},[`stop`])},[S(`div`,hn,[S(`div`,null,[r[5]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Add New Entry `,-1),S(`p`,gn,[n.selectedNodeName?(w(),C(`span`,_n,[r[4]||=y(` Add to: `,-1),S(`span`,vn,b(n.selectedNodeName),1)])):(w(),C(`span`,yn,` Add to root level (#uk) `))])]),S(`button`,{onClick:p,class:`text-white/60 hover:text-white transition-colors`},[...r[6]||=[S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),S(`form`,{onSubmit:I(f,[`prevent`]),class:`space-y-4`},[S(`div`,null,[S(`label`,bn,[S(`div`,xn,[s.value?(w(),C(`svg`,Sn,[...r[7]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,Cn,[...r[8]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`},null,-1)]])),r[9]||=y(` Region/Key Name `,-1)])]),m(S(`input`,{id:`keyName`,"onUpdate:modelValue":r[0]||=e=>i.value=e,type:`text`,placeholder:`Enter name (prefix with # for regions)`,class:`w-full px-4 py-3 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/20 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/50 focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20 transition-colors`,autocomplete:`off`},null,512),[[F,i.value]])]),S(`div`,wn,[S(`div`,Tn,[S(`div`,En,[s.value?(w(),C(`svg`,Dn,[...r[10]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,On,[...r[11]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1221 9z`},null,-1)]])),S(`span`,{class:u([s.value?`text-secondary`:`text-accent-green`,`font-medium`])},b(c.value.type),3)]),S(`div`,{class:u([`flex-1 h-px`,s.value?`bg-secondary/20`:`bg-accent-green/20`])},null,2)]),S(`p`,kn,b(c.value.description),1)]),S(`div`,null,[r[14]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-3`},[S(`div`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4 text-primary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z`})]),y(` Flood Policy `)])],-1),S(`div`,An,[S(`label`,jn,[m(S(`input`,{type:`radio`,"onUpdate:modelValue":r[1]||=e=>o.value=e,value:`allow`,class:`sr-only`},null,512),[[B,o.value]]),r[12]||=d(``,1)]),S(`label`,Mn,[m(S(`input`,{type:`radio`,"onUpdate:modelValue":r[2]||=e=>o.value=e,value:`deny`,class:`sr-only`},null,512),[[B,o.value]]),r[13]||=d(``,1)])])]),S(`div`,Nn,[S(`button`,{type:`button`,onClick:p,class:`flex-1 px-4 py-3 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),S(`button`,{type:`submit`,disabled:!l.value,class:u([`flex-1 px-4 py-3 rounded-lg transition-colors font-medium`,l.value?`bg-accent-green/20 hover:bg-accent-green/30 border border-accent-green/50 text-accent-green`:`bg-background-mute dark:bg-stroke/5 border border-stroke-subtle dark:border-stroke/20 text-content-muted dark:text-content-muted cursor-not-allowed`])},` Add `+b(c.value.type),11,Pn)])],32)])])):g(``,!0)}}),In={class:`flex items-center justify-between mb-6`},Ln={class:`text-content-secondary dark:text-content-muted text-sm mt-1`},Rn={class:`text-primary font-mono`},zn={for:`keyName`,class:`block text-sm font-medium text-content-secondary dark:text-content-primary mb-2`},Bn={class:`flex items-center gap-2`},Vn={key:0,class:`w-4 h-4 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Hn={key:1,class:`w-4 h-4 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Un={class:`bg-gray-50 dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-4`},Wn={class:`flex items-center gap-3 mb-2`},Gn={class:`flex items-center gap-2`},Kn={key:0,class:`w-5 h-5 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},qn={key:1,class:`w-5 h-5 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Jn={class:`text-content-secondary dark:text-content-muted text-sm`},Yn={key:0,class:`space-y-4`},Xn={key:0,class:`bg-gray-50 dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-4`},Zn={class:`bg-background-mute dark:bg-black/20 border border-stroke-subtle dark:border-stroke/10 rounded-md p-3`},Qn={class:`text-xs font-mono text-content-primary dark:text-content-primary/80 break-all`},$n={key:1,class:`bg-gray-50 dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-4`},er={class:`flex items-center justify-between`},tr={class:`text-sm text-content-secondary dark:text-content-muted`},nr={class:`text-xs text-content-muted dark:text-content-muted`},rr={class:`grid grid-cols-2 gap-3`},ir={class:`relative cursor-pointer group`},ar={class:`relative cursor-pointer group`},or={class:`flex gap-3 pt-4`},sr=[`disabled`],cr=f({__name:`EditKeyModal`,props:{show:{type:Boolean},node:{}},emits:[`close`,`save`,`request-delete`],setup(e,{emit:t}){let n=e,r=t,i=E(``),a=E(`allow`),o=v(()=>i.value.startsWith(`#`)),s=v(()=>({type:o.value?`Region`:`Private Key`,description:o.value?`Regional organizational key`:`Individual assigned key`}));h(()=>n.node,e=>{e?(i.value=e.name,a.value=e.floodPolicy):(i.value=``,a.value=`allow`)},{immediate:!0});let c=v(()=>i.value.trim().length>0&&n.node),l=e=>{let t=new Date().getTime()-e.getTime(),n=Math.floor(t/(1e3*60)),r=Math.floor(t/(1e3*60*60)),i=Math.floor(t/(1e3*60*60*24)),a=Math.floor(i/365);return n<60?`${n}m ago`:r<24?`${r}h ago`:i<365?`${i}d ago`:`${a}y ago`},f=e=>{window.navigator?.clipboard&&window.navigator.clipboard.writeText(e)},p=()=>{!c.value||!n.node||(r(`save`,{id:n.node.id,name:i.value.trim(),floodPolicy:a.value}),x())},_=()=>{n.node&&(r(`request-delete`,n.node),x())},x=()=>{r(`close`)},T=e=>{e.target===e.currentTarget&&x()};return(t,n)=>e.show?(w(),C(`div`,{key:0,onClick:T,class:`fixed inset-0 bg-black/50 backdrop-blur-lg z-[99999] flex items-center justify-center p-4`,style:{"backdrop-filter":`blur(8px) saturate(180%)`,position:`fixed`,top:`0`,left:`0`,right:`0`,bottom:`0`}},[S(`div`,{class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] p-6 w-full max-w-lg border border-stroke-subtle dark:border-white/10`,onClick:n[4]||=I(()=>{},[`stop`])},[S(`div`,In,[S(`div`,null,[n[6]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Edit Entry `,-1),S(`p`,Ln,[n[5]||=y(` Modify `,-1),S(`span`,Rn,b(e.node?.name),1)])]),S(`button`,{onClick:x,class:`text-white/60 hover:text-white transition-colors`},[...n[7]||=[S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),S(`form`,{onSubmit:I(p,[`prevent`]),class:`space-y-4`},[S(`div`,null,[S(`label`,zn,[S(`div`,Bn,[o.value?(w(),C(`svg`,Vn,[...n[8]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,Hn,[...n[9]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1721 9z`},null,-1)]])),n[10]||=y(` Region/Key Name `,-1)])]),m(S(`input`,{id:`keyName`,"onUpdate:modelValue":n[0]||=e=>i.value=e,type:`text`,placeholder:`Enter name (prefix with # for regions)`,class:`w-full px-4 py-3 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/20 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/50 focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20 transition-colors`,autocomplete:`off`},null,512),[[F,i.value]])]),S(`div`,Un,[S(`div`,Wn,[S(`div`,Gn,[o.value?(w(),C(`svg`,Kn,[...n[11]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,qn,[...n[12]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1721 9z`},null,-1)]])),S(`span`,{class:u([o.value?`text-secondary`:`text-accent-green`,`font-medium`])},b(s.value.type),3)]),S(`div`,{class:u([`flex-1 h-px`,o.value?`bg-secondary/20`:`bg-accent-green/20`])},null,2)]),S(`p`,Jn,b(s.value.description),1)]),e.node?(w(),C(`div`,Yn,[e.node.transport_key?(w(),C(`div`,Xn,[n[14]||=d(``,1),S(`div`,Zn,[S(`div`,Qn,b(e.node.transport_key),1),S(`button`,{onClick:n[1]||=t=>f(e.node.transport_key||``),class:`mt-2 text-xs text-accent-green hover:text-accent-green/80 flex items-center gap-1`,title:`Copy to clipboard`},[...n[13]||=[S(`svg`,{class:`w-3 h-3`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z`})],-1),y(` Copy Key `,-1)]])])])):g(``,!0),e.node.last_used?(w(),C(`div`,$n,[n[15]||=S(`div`,{class:`flex items-center gap-2 mb-3`},[S(`svg`,{class:`w-4 h-4 text-primary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`})]),S(`span`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},`Last Used`)],-1),S(`div`,er,[S(`div`,tr,b(e.node.last_used.toLocaleDateString())+` at `+b(e.node.last_used.toLocaleTimeString()),1),S(`div`,nr,b(l(e.node.last_used)),1)])])):g(``,!0)])):g(``,!0),S(`div`,null,[n[18]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-primary mb-3`},[S(`div`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4 text-primary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z`})]),y(` Flood Policy `)])],-1),S(`div`,rr,[S(`label`,ir,[m(S(`input`,{type:`radio`,"onUpdate:modelValue":n[2]||=e=>a.value=e,value:`allow`,class:`sr-only`},null,512),[[B,a.value]]),n[16]||=d(``,1)]),S(`label`,ar,[m(S(`input`,{type:`radio`,"onUpdate:modelValue":n[3]||=e=>a.value=e,value:`deny`,class:`sr-only`},null,512),[[B,a.value]]),n[17]||=d(``,1)])])]),S(`div`,or,[S(`button`,{type:`button`,onClick:_,class:`px-4 py-3 bg-accent-red/20 hover:bg-accent-red/30 border border-accent-red/50 text-accent-red rounded-lg transition-colors`},` Delete `),S(`button`,{type:`button`,onClick:x,class:`flex-1 px-4 py-3 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),S(`button`,{type:`submit`,disabled:!c.value,class:u([`flex-1 px-4 py-3 rounded-lg transition-colors font-medium`,c.value?`bg-accent-green/20 hover:bg-accent-green/30 border border-accent-green/50 text-accent-green`:`bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/20 text-content-muted dark:text-content-muted/70 cursor-not-allowed`])},` Save Changes `,10,sr)])],32)])])):g(``,!0)}}),lr={class:`flex items-center gap-3 mb-6`},ur={class:`text-content-secondary dark:text-content-muted text-sm mt-1`},dr={class:`text-accent-red font-mono`},fr={key:0,class:`bg-accent-red/10 border border-accent-red/30 rounded-lg p-4 mb-6`},pr={class:`flex items-start gap-3`},mr={class:`flex-1`},hr={class:`text-accent-red font-medium text-sm mb-2`},gr={class:`space-y-1 max-h-32 overflow-y-auto`},_r={key:0,class:`w-3 h-3 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},vr={key:1,class:`w-3 h-3 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},yr={class:`font-mono`},br={key:0,class:`text-content-secondary dark:text-content-muted text-xs`},xr={key:1,class:`mb-6`},Sr={class:`mb-3`},Cr={class:`relative`},wr={class:`space-y-2 max-h-40 overflow-y-auto border border-stroke-subtle dark:border-stroke/20 rounded-lg p-3 bg-gray-50 dark:bg-white/5`},Tr={key:0,class:`text-center py-4 text-content-secondary dark:text-content-muted text-sm`},Er={class:`relative`},Dr=[`value`],Or={class:`flex items-center gap-2 flex-1`},kr={class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ar={key:0,class:`ml-auto px-2 py-0.5 bg-background-mute dark:bg-stroke/10 text-content-secondary dark:text-content-muted text-xs rounded-full`},jr={class:`flex gap-3`},Mr=f({__name:`DeleteConfirmModal`,props:{show:{type:Boolean},node:{},allNodes:{}},emits:[`close`,`delete-all`,`move-children`],setup(e,{emit:t}){let n=e,r=t,a=E(null),o=E(``),s=e=>{let t=[],n=e=>{for(let r of e.children)t.push(r),n(r)};return n(e),t},c=v(()=>n.node?s(n.node):[]),l=v(()=>{if(!n.node)return[];let e=new Set([n.node.id,...c.value.map(e=>e.id)]),t=n=>{let r=[];for(let i of n)i.name.startsWith(`#`)&&!e.has(i.id)&&r.push(i),i.children.length>0&&r.push(...t(i.children));return r};return t(n.allNodes)}),d=v(()=>{if(!o.value.trim())return l.value;let e=o.value.toLowerCase();return l.value.filter(t=>t.name.toLowerCase().includes(e))}),f=()=>{n.node&&(r(`delete-all`,n.node.id),h())},p=()=>{!n.node||!a.value||(r(`move-children`,{nodeId:n.node.id,targetParentId:a.value}),h())},h=()=>{a.value=null,o.value=``,r(`close`)},_=e=>{e.target===e.currentTarget&&h()};return(t,n)=>e.show&&e.node?(w(),C(`div`,{key:0,onClick:_,class:`fixed inset-0 bg-black/80 backdrop-blur-lg z-[99999] flex items-center justify-center p-4`,style:{"backdrop-filter":`blur(8px) saturate(180%)`,position:`fixed`,top:`0`,left:`0`,right:`0`,bottom:`0`}},[S(`div`,{class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] p-6 w-full max-w-lg border border-stroke-subtle dark:border-white/10`,onClick:n[2]||=I(()=>{},[`stop`])},[S(`div`,lr,[n[6]||=S(`svg`,{class:`w-6 h-6 text-accent-red`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,null,[n[4]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Confirm Deletion `,-1),S(`p`,ur,[n[3]||=y(` Deleting `,-1),S(`span`,dr,b(e.node?.name),1)])]),S(`button`,{onClick:h,class:`ml-auto text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary transition-colors`},[...n[5]||=[S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),c.value.length>0?(w(),C(`div`,fr,[S(`div`,pr,[n[9]||=S(`svg`,{class:`w-5 h-5 text-accent-red flex-shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),S(`div`,mr,[S(`h4`,hr,` This will affect `+b(c.value.length)+` child `+b(c.value.length===1?`entry`:`entries`)+`: `,1),S(`div`,gr,[(w(!0),C(x,null,i(c.value.slice(0,10),e=>(w(),C(`div`,{key:e.id,class:`flex items-center gap-2 text-xs text-content-secondary dark:text-content-primary/80`},[e.name.startsWith(`#`)?(w(),C(`svg`,_r,[...n[7]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,vr,[...n[8]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1721 9z`},null,-1)]])),S(`span`,yr,b(e.name),1),S(`span`,{class:u([`px-1 py-0.5 text-xs rounded`,e.floodPolicy===`allow`?`bg-accent-green/20 text-accent-green`:`bg-accent-red/20 text-accent-red`])},b(e.floodPolicy),3)]))),128)),c.value.length>10?(w(),C(`div`,br,` ...and `+b(c.value.length-10)+` more `,1)):g(``,!0)])])])])):g(``,!0),c.value.length>0&&l.value.length>0?(w(),C(`div`,xr,[n[13]||=S(`h4`,{class:`text-content-primary dark:text-content-primary font-medium text-sm mb-3`},` Move children to another region: `,-1),S(`div`,Sr,[S(`div`,Cr,[n[10]||=S(`svg`,{class:`absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-content-muted dark:text-content-muted`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z`})],-1),m(S(`input`,{"onUpdate:modelValue":n[0]||=e=>o.value=e,type:`text`,placeholder:`Search regions...`,class:`w-full pl-9 pr-4 py-2 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/20 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/50 focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20 transition-colors text-sm`},null,512),[[F,o.value]])])]),S(`div`,wr,[d.value.length===0?(w(),C(`div`,Tr,b(o.value?`No regions match your search`:`No available regions`),1)):g(``,!0),(w(!0),C(x,null,i(d.value,e=>(w(),C(`label`,{key:e.id,class:`flex items-center gap-3 p-2 rounded cursor-pointer hover:bg-stroke-subtle dark:hover:bg-white/10 transition-colors group`},[S(`div`,Er,[m(S(`input`,{type:`radio`,value:e.id,"onUpdate:modelValue":n[1]||=e=>a.value=e,class:`sr-only peer`},null,8,Dr),[[B,a.value]]),n[11]||=S(`div`,{class:`w-4 h-4 border-2 border-stroke dark:border-stroke/30 rounded-full group-hover:border-stroke dark:group-hover:border-stroke/50 peer-checked:border-primary peer-checked:bg-primary/20 transition-all`},[S(`div`,{class:`w-2 h-2 rounded-full bg-primary scale-0 peer-checked:scale-100 transition-transform absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2`})],-1)]),S(`div`,Or,[n[12]||=S(`svg`,{class:`w-4 h-4 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`})],-1),S(`span`,kr,b(e.name),1),e.children.length>0?(w(),C(`span`,Ar,b(e.children.length),1)):g(``,!0)])]))),128))])])):g(``,!0),S(`div`,jr,[S(`button`,{onClick:h,class:`flex-1 px-4 py-3 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),c.value.length>0&&a.value?(w(),C(`button`,{key:0,onClick:p,class:`flex-1 px-4 py-3 bg-primary/20 hover:bg-primary/30 border border-primary/50 text-primary rounded-lg transition-colors`},` Move & Delete `)):g(``,!0),S(`button`,{onClick:f,class:`flex-1 px-4 py-3 bg-accent-red/20 hover:bg-accent-red/30 border border-accent-red/50 text-accent-red rounded-lg transition-colors font-medium`},b(c.value.length>0?`Delete All`:`Delete`),1)])])])):g(``,!0)}}),Nr={class:`space-y-4 sm:space-y-6`},Pr={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3`},Fr={class:`flex gap-2 flex-wrap`},Ir=[`disabled`],Lr=[`disabled`],Rr={class:`glass-card rounded-[15px] p-3 sm:p-4 border border-stroke-subtle dark:border-stroke/10 bg-background-mute dark:bg-white/5`},zr={class:`flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3`},Br={class:`flex items-center gap-2 sm:gap-3`},Vr={class:`flex bg-background-mute dark:bg-stroke/5 rounded-lg border border-stroke-subtle dark:border-stroke/20 p-0.5 sm:p-1`},Hr={class:`glass-card rounded-[15px] p-3 sm:p-6 border border-stroke-subtle dark:border-stroke/10`},Ur={key:0,class:`flex items-center justify-center py-8`},Wr={key:1,class:`text-center py-8`},Gr={class:`text-content-secondary dark:text-content-muted text-sm`},Kr={key:2,class:`text-center py-8`},qr={key:3,class:`space-y-2`},Jr=f({name:`TransportKeys`,__name:`TransportKeys`,setup(e){let t=Yt(),n=j(),r=E(!1),o=E(!1),c=E(!1),d=E(null),f=E(null),p=E(`deny`);h(v(()=>n.stats?.config?.mesh?.unscoped_flood_allow??null),e=>{e!==null&&(p.value=e?`allow`:`deny`)},{immediate:!0});let m=E([]),g=E(!1),T=E(null),D=e=>{let t=new Map,n=[];return e.forEach(e=>{let n={id:e.id,name:e.name,floodPolicy:e.flood_policy,transport_key:e.transport_key,last_used:e.last_used?new Date(e.last_used*1e3):void 0,parent_id:e.parent_id,children:[]};t.set(e.id,n)}),t.forEach(e=>{e.parent_id&&t.has(e.parent_id)?t.get(e.parent_id).children.push(e):n.push(e)}),n},O=async()=>{try{g.value=!0,T.value=null;let e=await A.getTransportKeys();e.success&&e.data?m.value=D(e.data):T.value=e.error||`Failed to load transport keys`}catch(e){T.value=e instanceof Error?e.message:`Unknown error occurred`,console.error(`Error loading transport keys:`,e)}finally{g.value=!1}};s(()=>{O()});function k(e,t){for(let n of e){if(n.id===t)return n;if(n.children){let e=k(n.children,t);if(e)return e}}return null}function M(){let e=t.selectedNodeId.value;if(e)return k(m.value,e)?.name}function N(e){t.setSelectedNode(e)}function P(){r.value=!0}function F(){if(t.selectedNodeId.value){let e=k(m.value,t.selectedNodeId.value);e&&(f.value=e,c.value=!0)}}function I(){if(t.selectedNodeId.value){let e=k(m.value,t.selectedNodeId.value);e&&(d.value=e,o.value=!0)}}let L=async e=>{try{let t=await A.createTransportKey(e.name,e.floodPolicy,void 0,e.parentId,void 0);t.success?await O():(console.error(`Failed to add transport key:`,t.error),T.value=t.error||`Failed to add transport key`)}catch(e){console.error(`Error adding transport key:`,e),T.value=e instanceof Error?e.message:`Unknown error occurred`}finally{r.value=!1}};function R(){r.value=!1}async function z(e){try{let t=e===`allow`,r=await A.updateUnscopedFloodPolicy(t);r.success?(p.value=e,await n.fetchStats()):(console.error(`Failed to update unscoped flood policy:`,r.error),T.value=r.error||`Failed to update unscoped flood policy`)}catch(e){console.error(`Error updating unscoped flood policy:`,e),T.value=e instanceof Error?e.message:`Failed to update unscoped flood policy`}}function B(){o.value=!1,d.value=null}async function V(e){try{let t=await A.updateTransportKey(e.id,e.name,e.floodPolicy);t.success?await O():(console.error(`Failed to update transport key:`,t.error),T.value=t.error||`Failed to update transport key`)}catch(e){console.error(`Error updating transport key:`,e),T.value=e instanceof Error?e.message:`Unknown error occurred`}finally{B()}}function ee(e){o.value=!1,d.value=null,f.value=e,c.value=!0}function H(){c.value=!1,f.value=null}async function U(e){try{let n=await A.deleteTransportKey(e);n.success?(await O(),t.setSelectedNode(null)):(console.error(`Failed to delete transport key:`,n.error),T.value=n.error||`Failed to delete transport key`)}catch(e){console.error(`Error deleting transport key:`,e),T.value=e instanceof Error?e.message:`Unknown error occurred`}finally{H()}}async function W(e){try{let n=await A.deleteTransportKey(e.nodeId);n.success?(await O(),t.setSelectedNode(null)):(console.error(`Failed to delete transport key:`,n.error),T.value=n.error||`Failed to delete transport key`)}catch(e){console.error(`Error deleting transport key:`,e),T.value=e instanceof Error?e.message:`Unknown error occurred`}finally{H()}}return(e,n)=>(w(),C(`div`,Nr,[S(`div`,Pr,[n[3]||=S(`div`,null,[S(`h3`,{class:`text-base sm:text-lg font-semibold text-content-primary dark:text-content-primary mb-1 sm:mb-2`},` Regions/Keys `),S(`p`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},` Manage regional key hierarchy `)],-1),S(`div`,Fr,[S(`button`,{onClick:P,class:`flex items-center gap-1.5 sm:gap-2 px-2.5 sm:px-3 py-1.5 sm:py-2 rounded-lg border transition-colors text-xs sm:text-sm bg-accent-green/10 hover:bg-accent-green/20 text-accent-green border-accent-green/30`},[...n[2]||=[S(`svg`,{class:`w-3.5 h-3.5 sm:w-4 sm:h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 4v16m8-8H4`})],-1),y(` Add `,-1)]]),S(`button`,{onClick:I,disabled:!a(t).selectedNodeId.value,class:u([`px-2.5 sm:px-4 py-1.5 sm:py-2 rounded-lg border transition-colors text-xs sm:text-sm`,a(t).selectedNodeId.value?`bg-accent-green/20 hover:bg-accent-green/30 text-accent-green border-accent-green/50`:`bg-background-mute dark:bg-stroke/10 text-content-muted dark:text-content-muted/70 border-stroke-subtle dark:border-stroke/20 cursor-not-allowed`])},` Edit `,10,Ir),S(`button`,{onClick:F,disabled:!a(t).selectedNodeId.value,class:u([`px-2.5 sm:px-4 py-1.5 sm:py-2 rounded-lg border transition-colors text-xs sm:text-sm`,a(t).selectedNodeId.value?`bg-accent-red/20 hover:bg-accent-red/30 text-accent-red border-accent-red/50`:`bg-background-mute dark:bg-stroke/10 text-content-muted dark:text-content-muted/70 border-stroke-subtle dark:border-stroke/20 cursor-not-allowed`])},` Delete `,10,Lr)])]),S(`div`,Rr,[S(`div`,zr,[n[4]||=S(`div`,null,[S(`h4`,{class:`text-xs sm:text-sm font-medium text-content-primary dark:text-content-primary mb-1`},` Unscoped Flood Policy (*) `),S(`p`,{class:`text-content-secondary dark:text-content-muted text-[10px] sm:text-xs`},` Allow or Deny unscoped flood packets `)],-1),S(`div`,Br,[S(`div`,Vr,[S(`button`,{onClick:n[0]||=e=>z(`deny`),class:u([`px-2 sm:px-3 py-1 text-[10px] sm:text-xs font-medium rounded transition-colors`,p.value===`deny`?`bg-accent-red/20 text-accent-red border border-accent-red/50`:`text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-secondary`])},` DENY `,2),S(`button`,{onClick:n[1]||=e=>z(`allow`),class:u([`px-2 sm:px-3 py-1 text-[10px] sm:text-xs font-medium rounded transition-colors`,p.value===`allow`?`bg-accent-green/20 text-accent-green border border-accent-green/50`:`text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-secondary`])},` ALLOW `,2)])])])]),S(`div`,Hr,[g.value?(w(),C(`div`,Ur,[...n[5]||=[S(`div`,{class:`animate-spin rounded-full h-8 w-8 border-b-2 border-accent-green`},null,-1),S(`span`,{class:`ml-2 text-content-secondary dark:text-content-muted`},`Loading transport keys...`,-1)]])):T.value?(w(),C(`div`,Wr,[n[6]||=S(`div`,{class:`text-accent-red mb-2`},`⚠️ Error loading transport keys`,-1),S(`div`,Gr,b(T.value),1),S(`button`,{onClick:O,class:`mt-4 px-4 py-2 bg-accent-green/20 hover:bg-accent-green/30 text-accent-green border border-accent-green/50 rounded-lg transition-colors`},` Retry `)])):m.value.length===0?(w(),C(`div`,Kr,[...n[7]||=[S(`div`,{class:`text-content-muted dark:text-content-muted mb-2`},` 📝 No transport keys found `,-1),S(`div`,{class:`text-content-muted dark:text-content-muted/60 text-sm`},` Add your first transport key to get started `,-1)]])):(w(),C(`div`,qr,[(w(!0),C(x,null,i(m.value,e=>(w(),l(mn,{key:e.id,node:e,"selected-node-id":a(t).selectedNodeId.value,level:0,onSelect:N},null,8,[`node`,`selected-node-id`]))),128))]))]),_(Fn,{show:r.value,"selected-node-name":M(),"selected-node-id":a(t).selectedNodeId.value||void 0,onClose:R,onAdd:L},null,8,[`show`,`selected-node-name`,`selected-node-id`]),_(cr,{show:o.value,node:d.value,onClose:B,onSave:V,onRequestDelete:ee},null,8,[`show`,`node`]),_(Mr,{show:c.value,node:f.value,"all-nodes":m.value,onClose:H,onDeleteAll:U,onMoveChildren:W},null,8,[`show`,`node`,`all-nodes`])]))}}),Yr={class:`space-y-4 sm:space-y-6`},Xr={class:`flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3`},Zr={key:0,class:`bg-red-500/10 border border-red-500/30 rounded-lg p-4`},Qr={class:`flex items-center gap-2 text-red-600 dark:text-red-400`},$r={key:1,class:`flex items-center justify-center py-12`},ei={key:2,class:`space-y-3`},ti={class:`flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3`},ni={class:`flex-1`},ri={class:`flex items-center gap-2 sm:gap-3`},ii={class:`min-w-0 flex-1`},ai={class:`text-content-primary dark:text-content-primary font-medium text-sm sm:text-base break-all`},oi={class:`flex flex-col sm:flex-row sm:items-center sm:gap-4 mt-1 text-xs text-content-secondary dark:text-content-muted`},si={class:`truncate`},ci={class:`truncate`},li=[`onClick`,`disabled`],ui={key:3,class:`text-center py-12`},di={class:`bg-surface dark:bg-surface-elevated border border-stroke-subtle dark:border-stroke/20 rounded-[15px] p-6 max-w-md w-full shadow-2xl`},fi={class:`space-y-4`},pi={class:`flex justify-end gap-3 mt-6`},mi=[`disabled`],hi=[`disabled`],gi={class:`bg-surface dark:bg-surface-elevated border border-stroke-subtle dark:border-stroke/20 rounded-[15px] p-6 max-w-lg w-full shadow-2xl`},_i={class:`space-y-4`},vi={class:`flex gap-2`},yi=[`value`],bi={class:`bg-blue-500/10 border border-blue-500/30 rounded-lg p-4`},xi={class:`block bg-blue-500/20 px-3 py-2 rounded text-xs text-blue-100 font-mono overflow-x-auto`},Si=f({name:`APITokens`,__name:`APITokens`,setup(e){let t=E([]),n=E(!1),r=E(null),a=E(!1),o=E(``),c=E(null),l=E(!1),u=E(!1),f=E(null),p=async()=>{n.value=!0,r.value=null;try{let e=await A.get(`/auth/tokens`);t.value=(e.data||e).tokens||[]}catch(e){console.error(`Failed to fetch API tokens:`,e),r.value=e instanceof Error?e.message:`Failed to fetch tokens`}finally{n.value=!1}},h=async()=>{if(!o.value.trim()){r.value=`Token name is required`;return}n.value=!0,r.value=null;try{let e=await A.post(`/auth/tokens`,{name:o.value.trim()});c.value=(e.data||e).token||null,a.value=!1,l.value=!0,o.value=``,await p()}catch(e){console.error(`Failed to create API token:`,e),r.value=e instanceof Error?e.message:`Failed to create token`}finally{n.value=!1}},T=(e,t)=>{f.value={id:e,name:t},u.value=!0},D=async()=>{if(f.value){n.value=!0,r.value=null;try{await A.delete(`/auth/tokens/${f.value.id}`),await p(),u.value=!1,f.value=null}catch(e){console.error(`Failed to revoke API token:`,e),r.value=e instanceof Error?e.message:`Failed to revoke token`}finally{n.value=!1}}},O=()=>{a.value=!1,o.value=``,r.value=null},k=()=>{l.value=!1,c.value=null},j=()=>{c.value&&navigator.clipboard.writeText(c.value)},M=e=>e?new Date(e*1e3).toLocaleString():`Never`,N=v(()=>`${window.location.origin}/api/stats`);return s(()=>{p()}),(e,s)=>(w(),C(x,null,[S(`div`,Yr,[S(`div`,Xr,[s[5]||=S(`div`,null,[S(`h2`,{class:`text-lg sm:text-xl font-semibold text-content-primary dark:text-content-primary`},` API Tokens `),S(`p`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm mt-1`},` Manage API tokens for machine-to-machine authentication `)],-1),S(`button`,{onClick:s[0]||=e=>a.value=!0,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors flex items-center justify-center gap-2 text-sm sm:text-base`},[...s[4]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 4v16m8-8H4`})],-1),y(` Create Token `,-1)]])]),s[20]||=d(`API tokens are used for machine-to-machine authentication. Include the token in the X-API-Key header when making API requests.
Tokens are only shown once at creation. Store them securely.
`,1),r.value?(w(),C(`div`,Zr,[S(`div`,Qr,[s[6]||=S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),y(` `+b(r.value),1)])])):g(``,!0),n.value&&t.value.length===0?(w(),C(`div`,$r,[...s[7]||=[S(`div`,{class:`text-center`},[S(`div`,{class:`animate-spin w-8 h-8 border-2 border-stroke-subtle dark:border-stroke/20 border-t-primary rounded-full mx-auto mb-4`}),S(`div`,{class:`text-content-secondary dark:text-content-muted`},`Loading tokens...`)],-1)]])):t.value.length>0?(w(),C(`div`,ei,[(w(!0),C(x,null,i(t.value,e=>(w(),C(`div`,{key:e.id,class:`bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-3 sm:p-4 hover:bg-stroke-subtle dark:hover:bg-white/10 transition-colors`},[S(`div`,ti,[S(`div`,ni,[S(`div`,ri,[s[8]||=S(`svg`,{class:`w-4 h-4 sm:w-5 sm:h-5 text-primary flex-shrink-0`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`})],-1),S(`div`,ii,[S(`h3`,ai,b(e.name),1),S(`div`,oi,[S(`span`,si,`Created: `+b(M(e.created_at)),1),S(`span`,ci,`Last used: `+b(M(e.last_used)),1)])])])]),S(`button`,{onClick:t=>T(e.id,e.name),disabled:n.value,class:`w-full sm:w-auto px-3 py-1.5 bg-red-100 dark:bg-red-500/20 hover:bg-red-500/30 text-red-600 dark:text-red-400 rounded-lg border border-red-500/50 transition-colors disabled:opacity-50 text-sm`},` Revoke `,8,li)])]))),128))])):(w(),C(`div`,ui,[s[9]||=S(`svg`,{class:`w-16 h-16 text-content-muted dark:text-content-muted/40 mx-auto mb-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`})],-1),s[10]||=S(`h3`,{class:`text-content-primary dark:text-content-primary font-medium mb-2`},`No API Tokens`,-1),s[11]||=S(`p`,{class:`text-content-secondary dark:text-content-muted text-sm mb-4`},` Create a token to enable API access `,-1),S(`button`,{onClick:s[1]||=e=>a.value=!0,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors`},` Create Your First Token `)])),a.value?(w(),C(`div`,{key:4,class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm`,onClick:I(O,[`self`])},[S(`div`,di,[s[14]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary mb-4`},` Create API Token `,-1),S(`div`,fi,[S(`div`,null,[s[12]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},`Token Name`,-1),m(S(`input`,{"onUpdate:modelValue":s[2]||=e=>o.value=e,type:`text`,placeholder:`e.g., Production Server, CI/CD Pipeline`,class:`w-full px-4 py-2 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-400 dark:placeholder-white/40 focus:outline-none focus:border-primary transition-colors`,onKeydown:R(h,[`enter`])},null,544),[[F,o.value]]),s[13]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted mt-1`},` Give your token a descriptive name to identify its purpose `,-1)]),S(`div`,pi,[S(`button`,{onClick:O,disabled:n.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/10 transition-colors disabled:opacity-50`},` Cancel `,8,mi),S(`button`,{onClick:h,disabled:n.value||!o.value.trim(),class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors disabled:opacity-50`},b(n.value?`Creating...`:`Create Token`),9,hi)])])])])):g(``,!0),l.value&&c.value?(w(),C(`div`,{key:5,class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm`,onClick:I(k,[`self`])},[S(`div`,gi,[s[19]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary mb-4`},` Token Created Successfully `,-1),S(`div`,_i,[s[18]||=d(`Save this token now! For security reasons, it will not be shown again.
`,1),S(`div`,null,[s[16]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},`Your API Token`,-1),S(`div`,vi,[S(`input`,{value:c.value,readonly:``,class:`flex-1 px-4 py-2 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary font-mono text-sm`},null,8,yi),S(`button`,{onClick:j,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors flex items-center gap-2`,title:`Copy to clipboard`},[...s[15]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z`})],-1),y(` Copy `,-1)]])])]),S(`div`,bi,[s[17]||=S(`p`,{class:`text-sm text-blue-200 mb-2`},[S(`strong`,null,`Usage Example:`)],-1),S(`code`,xi,` curl -H "X-API-Key: `+b(c.value)+`" `+b(N.value),1)]),S(`div`,{class:`flex justify-end mt-6`},[S(`button`,{onClick:k,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors`},` Done `)])])])])):g(``,!0)]),_(V,{show:u.value,title:`Revoke API Token`,message:`Are you sure you want to revoke the token '${f.value?.name}'? This action cannot be undone.`,"confirm-text":`Revoke`,"cancel-text":`Cancel`,variant:`danger`,onConfirm:D,onClose:s[3]||=e=>u.value=!1},null,8,[`show`,`message`])],64))}}),Ci={class:`space-y-6`},wi={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Ti={class:`space-y-4`},Ei={class:`flex items-center justify-between`},Di=[`disabled`],Oi={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},ki={class:`space-y-4`},Ai={class:`space-y-3`},ji=[`checked`,`disabled`],Mi=[`checked`,`disabled`],Ni={class:`flex items-start gap-3`},Pi={key:0,class:`w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0 mt-0.5`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},Fi={key:1,class:`w-5 h-5 text-accent-cyan flex-shrink-0 mt-0.5`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},Ii={class:`flex-1`},Li={class:`text-sm font-medium text-content-primary dark:text-content-primary`},Ri={key:0,class:`text-xs text-green-600 dark:text-green-400 mt-1`},zi={key:1,class:`p-4 bg-amber-500/10 border border-amber-500/30 rounded-lg`},Bi={class:`flex items-start justify-between gap-3`},Vi=[`disabled`],Hi={key:0,class:`animate-spin h-4 w-4`,fill:`none`,viewBox:`0 0 24 24`},Ui={key:1,class:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},Wi={class:`flex items-center space-x-2`},Gi={key:0,class:`w-5 h-5 text-green-600 dark:text-green-400`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},Ki={key:1,class:`w-5 h-5 text-red-600 dark:text-red-400`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},qi=f({name:`WebSettings`,__name:`WebSettings`,setup(e){let t=E(!1),n=E(``),r=E(!1),i=E(!1),a=E(!1),c=E(!1),l=E(!0),f=o({cors_enabled:!1,use_default_frontend:!0}),p=v(()=>r.value?`bg-green-500/10 border-green-600/40 dark:border-green-500/30`:`bg-red-500/10 border-red-500/30`);async function m(){try{l.value=!0;let e=await A.get(`/check_pymc_console`);e.success&&e.data&&(c.value=e.data.exists,console.log(`PyMC Console exists:`,c.value))}catch(e){console.error(`Failed to check PyMC Console:`,e),c.value=!1}finally{l.value=!1}}async function h(){try{let e=await A.get(`/stats`);console.log(`WebSettings: Full response:`,e);let t=null;if(e.success&&e.data?t=e.data:e&&`version`in e&&(t=e),t){let e=t.config?.web||{};console.log(`WebSettings: webConfig:`,e),f.cors_enabled=e.cors_enabled===!0,console.log(`WebSettings: Set cors_enabled to:`,f.cors_enabled);let n=e.web_path;f.use_default_frontend=!n||n===``,console.log(`WebSettings: Set use_default_frontend to:`,f.use_default_frontend,`from web_path:`,n)}}catch(e){console.error(`Failed to load web settings:`,e),k(`Failed to load settings`,!1)}}async function _(){t.value=!0,n.value=``;try{let e={web:{cors_enabled:f.cors_enabled}};f.use_default_frontend?e.web.web_path=null:e.web.web_path=`/opt/pymc_console/web/html`;let t=await A.post(`/update_web_config`,e);t.success?(k(`Settings saved successfully`,!0),i.value=!0):k(t.error||`Failed to save settings`,!1)}catch(e){console.error(`Failed to save web settings:`,e),k(e.message||`Failed to save settings`,!1)}finally{t.value=!1}}async function T(){f.cors_enabled=!f.cors_enabled,await _()}async function D(){f.use_default_frontend=!0,await _()}async function O(){f.use_default_frontend=!1,await _()}function k(e,t){n.value=e,r.value=t,setTimeout(()=>{n.value=``},5e3)}async function j(){a.value=!0,n.value=``;try{let e=await A.post(`/restart_service`,{});e.success?(k(`Service restart initiated. Page will reload...`,!0),i.value=!1,setTimeout(()=>{window.location.reload()},2e3)):k(e.error||`Failed to restart service`,!1)}catch(e){e.code===`ERR_NETWORK`||e.message?.includes(`Network error`)?(k(`Service restarting... Page will reload`,!0),i.value=!1,setTimeout(()=>{window.location.reload()},3e3)):(console.error(`Failed to restart service:`,e),k(e.message||`Failed to restart service`,!1))}finally{a.value=!1}}return s(()=>{h(),m()}),(e,o)=>(w(),C(`div`,Ci,[S(`div`,wi,[o[1]||=S(`div`,{class:`flex items-start justify-between mb-4`},[S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` CORS Settings `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Control cross-origin resource sharing for API access `)])],-1),S(`div`,Ti,[S(`div`,Ei,[o[0]||=S(`div`,null,[S(`label`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},`Enable CORS`),S(`p`,{class:`text-xs text-content-secondary dark:text-content-muted mt-1`},` Allow web frontends from different origins to access the API `)],-1),S(`button`,{onClick:T,disabled:t.value,class:u([`relative inline-flex h-6 w-11 items-center rounded-full transition-colors border-2`,f.cors_enabled?`bg-cyan-600 dark:bg-teal-500 border-cyan-600 dark:border-teal-500`:`bg-gray-400 dark:bg-gray-600 border-gray-400 dark:border-gray-600`,t.value?`opacity-50 cursor-not-allowed`:`cursor-pointer`])},[S(`span`,{class:u([`inline-block h-4 w-4 transform rounded-full bg-white transition-transform shadow-lg`,f.cors_enabled?`translate-x-5`:`translate-x-0.5`])},null,2)],10,Di)])])]),S(`div`,Oi,[o[11]||=S(`div`,{class:`flex items-start justify-between mb-4`},[S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Web Frontend `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Choose which web interface to use `)])],-1),S(`div`,ki,[S(`div`,Ai,[S(`label`,{class:u([`flex items-start space-x-3 p-4 bg-background-mute dark:bg-background/30 rounded-lg border-2 cursor-pointer transition-all`,f.use_default_frontend?`border-accent-cyan bg-accent-cyan/10`:`border-stroke-subtle dark:border-stroke/10 hover:border-accent-cyan/50`])},[S(`input`,{type:`radio`,name:`frontend`,checked:f.use_default_frontend,onChange:D,disabled:t.value,class:`mt-1 h-4 w-4 text-accent-cyan focus:ring-accent-cyan focus:ring-offset-background`},null,40,ji),o[2]||=S(`div`,{class:`flex-1`},[S(`div`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},` Default Frontend `),S(`div`,{class:`text-xs text-content-secondary dark:text-content-muted mt-1`},` Built-in pyMC Repeater web interface `),S(`div`,{class:`text-xs text-content-muted dark:text-content-muted/60 mt-1 font-mono`},` Built-in `)],-1)],2),S(`label`,{class:u([`flex items-start space-x-3 p-4 bg-background-mute dark:bg-background/30 rounded-lg border-2 cursor-pointer transition-all`,f.use_default_frontend?`border-stroke-subtle dark:border-stroke/10 hover:border-accent-cyan/50`:`border-accent-cyan bg-accent-cyan/10`])},[S(`input`,{type:`radio`,name:`frontend`,checked:!f.use_default_frontend,onChange:O,disabled:t.value,class:`mt-1 h-4 w-4 text-accent-cyan focus:ring-accent-cyan focus:ring-offset-background`},null,40,Mi),o[3]||=d(` Alternative web interface for pyMC Repeater
/opt/pymc_console/web/html
`,1)],2)]),l.value?g(``,!0):(w(),C(`div`,{key:0,class:u([`p-4 rounded-lg border`,c.value?`bg-green-500/5 border-green-500/20`:`bg-accent-cyan/5 border-accent-cyan/20`])},[S(`div`,Ni,[c.value?(w(),C(`svg`,Pi,[...o[4]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]])):(w(),C(`svg`,Fi,[...o[5]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]])),S(`div`,Ii,[S(`h4`,Li,b(c.value?`PyMC Console has been detected`:`PyMC Console Not Installed`),1),c.value?(w(),C(`p`,Ri,[...o[6]||=[y(` PyMC Console is installed at `,-1),S(`code`,{class:`text-green-700 dark:text-green-300`},`/opt/pymc_console/web/html`,-1)]])):(w(),C(x,{key:1},[o[7]||=d(` PyMC Console must be installed at /opt/pymc_console/web/html before selecting this option.
PyMC Console Install Instructions `,2)],64))])])],2)),i.value?(w(),C(`div`,zi,[S(`div`,Bi,[o[10]||=d(` Service restart required Web frontend changes will take effect after restarting the pymc-repeater service.
`,1),S(`button`,{onClick:j,disabled:a.value,class:`px-4 py-2 bg-amber-500 hover:bg-amber-600 disabled:bg-amber-500/50 text-white font-medium rounded-lg transition-colors disabled:cursor-not-allowed flex items-center gap-2 whitespace-nowrap`},[a.value?(w(),C(`svg`,Hi,[...o[8]||=[S(`circle`,{class:`opacity-25`,cx:`12`,cy:`12`,r:`10`,stroke:`currentColor`,"stroke-width":`4`},null,-1),S(`path`,{class:`opacity-75`,fill:`currentColor`,d:`M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z`},null,-1)]])):(w(),C(`svg`,Ui,[...o[9]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15`},null,-1)]])),y(` `+b(a.value?`Restarting...`:`Restart Now`),1)],8,Vi)])])):g(``,!0)])]),n.value?(w(),C(`div`,{key:0,class:u([`p-4 rounded-lg border`,p.value])},[S(`div`,Wi,[r.value?(w(),C(`svg`,Gi,[...o[12]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M5 13l4 4L19 7`},null,-1)]])):(w(),C(`svg`,Ki,[...o[13]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`},null,-1)]])),S(`span`,{class:u(r.value?`text-green-600 dark:text-green-400`:`text-red-600 dark:text-red-400`)},b(n.value),3)])],2)):g(``,!0)]))}}),Ji={class:`space-y-4`},Yi={key:0,class:`bg-green-100 dark:bg-green-500/20 border border-green-500 dark:border-green-500/50 rounded-lg p-3 text-green-700 dark:text-green-400 text-sm`},Xi={key:1,class:`bg-red-100 dark:bg-red-500/20 border border-red-500 dark:border-red-500/50 rounded-lg p-3 text-red-700 dark:text-red-400 text-sm`},Zi={class:`flex justify-between items-center`},Qi={class:`flex gap-2`},$i=[`disabled`],ea={class:`flex gap-2`},ta=[`disabled`],na=[`disabled`],ra={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},ia={key:0,class:`flex items-center justify-center py-4`},aa={key:1,class:`text-center py-4`},oa={class:`grid grid-cols-2 sm:grid-cols-4 gap-3`},sa={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},ca={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},la={class:`text-lg font-mono text-content-primary dark:text-content-primary`},ua={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},da={class:`text-lg font-mono text-green-600 dark:text-green-400`},fa={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},pa={class:`text-lg font-mono text-red-600 dark:text-red-400`},ma={key:0,class:`mt-2 p-2 bg-red-50 dark:bg-red-500/10 rounded-lg border border-red-200 dark:border-red-500/30`},ha={key:1,class:`mt-2 p-2 bg-orange-50 dark:bg-orange-500/10 rounded-lg border border-orange-200 dark:border-orange-500/30`},ga={class:`font-medium`},_a={class:`font-mono text-[10px] opacity-70`},va={class:`text-[10px]`},ya={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},ba={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},xa={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Sa={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ca={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},wa={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ta={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ea={key:1,class:`flex items-center gap-2`},Da={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 gap-1`},Oa={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},ka={key:1,class:`flex items-center gap-2`},Aa={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},ja={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ma={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Na={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Pa={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Fa={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ia={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},La={key:1,class:`flex items-center gap-2`},Ra={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},za={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ba={key:1,class:`flex items-center gap-2`},Va={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 gap-1`},Ha={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ua={key:1,class:`flex items-center gap-2`},Wa={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},Ga={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ka={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},qa={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ja={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ya={key:1,class:`flex items-center gap-2`},Xa={class:`py-2`},Za={class:`grid grid-cols-3 gap-2 mt-2`},Qa={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},$a={key:0,class:`font-mono text-sm text-content-primary dark:text-content-primary`},eo={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},to={key:0,class:`font-mono text-sm text-content-primary dark:text-content-primary`},no={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},ro={key:0,class:`font-mono text-sm text-content-primary dark:text-content-primary`},io={class:`p-6 space-y-4`},ao={class:`flex justify-between items-start`},oo={class:`flex justify-end pt-4 border-t border-stroke-subtle dark:border-stroke/20`},so=f({__name:`AdvertSettings`,setup(e){let t=j(),n=v(()=>t.stats?.config?.repeater||{}),r=v(()=>n.value.advert_rate_limit||{}),a=v(()=>n.value.advert_penalty_box||{}),o=v(()=>n.value.advert_adaptive||{}),l=v(()=>o.value.thresholds||{}),f=E(!1),p=E(!1),_=E(``),T=E(``),D=E(!1),O=E(!1),A=E(null),M=E(!0),N=E(2),L=E(1),R=E(10),z=E(60),B=E(!0),V=E(2),ee=E(12),H=E(6),U=E(2),W=E(24),G=E(!0),te=E(.1),K=E(5),ne=E(.05),q=E(.2),J=E(.5),Y=async()=>{O.value=!0;try{let e=await k.get(`/api/advert_rate_limit_stats`);e.data?.success&&(A.value=e.data.data)}catch(e){console.error(`Failed to fetch rate limit stats:`,e)}finally{O.value=!1}};h([r,a,o],()=>{f.value||(M.value=r.value.enabled??!1,N.value=r.value.bucket_capacity??2,L.value=r.value.refill_tokens??1,R.value=Math.round((r.value.refill_interval_seconds??36e3)/3600),z.value=Math.round((r.value.min_interval_seconds??0)/60),B.value=a.value.enabled??!1,V.value=a.value.violation_threshold??2,ee.value=Math.round((a.value.violation_decay_seconds??43200)/3600),H.value=Math.round((a.value.base_penalty_seconds??21600)/3600),U.value=a.value.penalty_multiplier??2,W.value=Math.round((a.value.max_penalty_seconds??86400)/3600),G.value=o.value.enabled??!1,te.value=o.value.ewma_alpha??.1,K.value=Math.round((o.value.hysteresis_seconds??300)/60),ne.value=l.value.quiet_max??.05,q.value=l.value.normal_max??.2,J.value=l.value.busy_max??.5)},{immediate:!0}),s(()=>{Y()});let X=()=>{M.value=r.value.enabled??!1,N.value=r.value.bucket_capacity??2,L.value=r.value.refill_tokens??1,R.value=Math.round((r.value.refill_interval_seconds??36e3)/3600),z.value=Math.round((r.value.min_interval_seconds??0)/60),B.value=a.value.enabled??!1,V.value=a.value.violation_threshold??2,ee.value=Math.round((a.value.violation_decay_seconds??43200)/3600),H.value=Math.round((a.value.base_penalty_seconds??21600)/3600),U.value=a.value.penalty_multiplier??2,W.value=Math.round((a.value.max_penalty_seconds??86400)/3600),G.value=o.value.enabled??!1,te.value=o.value.ewma_alpha??.1,K.value=Math.round((o.value.hysteresis_seconds??300)/60),ne.value=l.value.quiet_max??.05,q.value=l.value.normal_max??.2,J.value=l.value.busy_max??.5},Z=()=>{f.value=!0,_.value=``,T.value=``},Q=()=>{f.value=!1,_.value=``,T.value=``,X()},re=async()=>{p.value=!0,T.value=``,_.value=``;try{let e={rate_limit_enabled:M.value,bucket_capacity:N.value,refill_tokens:L.value,refill_interval_seconds:R.value*3600,min_interval_seconds:z.value*60,penalty_enabled:B.value,violation_threshold:V.value,violation_decay_seconds:ee.value*3600,base_penalty_seconds:H.value*3600,penalty_multiplier:U.value,max_penalty_seconds:W.value*3600,adaptive_enabled:G.value,ewma_alpha:te.value,hysteresis_seconds:K.value*60,quiet_max:ne.value,normal_max:q.value,busy_max:J.value},n=(await k.post(`/api/update_advert_rate_limit_config`,e)).data;n.success?(_.value=n.data?.message||`Settings saved successfully`,await t.fetchStats(),await Y(),await c(),X(),f.value=!1,setTimeout(()=>{_.value=``},3e3)):(T.value=n.error||`Failed to save settings`,console.error(`[AdvertSettings] Save failed:`,n.error))}catch(e){console.error(`Failed to save advert settings:`,e),T.value=e.response?.data?.error||`Failed to save settings`}finally{p.value=!1}},$=v(()=>A.value?.adaptive?.current_tier||`unknown`),ie=v(()=>{switch($.value){case`quiet`:return`bg-green-100 dark:bg-green-500/20 text-green-700 dark:text-green-400 border-green-500`;case`normal`:return`bg-blue-100 dark:bg-blue-500/20 text-blue-700 dark:text-blue-400 border-blue-500`;case`busy`:return`bg-yellow-100 dark:bg-yellow-500/20 text-yellow-700 dark:text-yellow-400 border-yellow-500`;case`congested`:return`bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400 border-red-500`;default:return`bg-gray-100 dark:bg-gray-500/20 text-gray-700 dark:text-gray-400 border-gray-500`}});return(e,t)=>(w(),C(`div`,Ji,[_.value?(w(),C(`div`,Yi,b(_.value),1)):g(``,!0),T.value?(w(),C(`div`,Xi,b(T.value),1)):g(``,!0),S(`div`,Zi,[S(`div`,Qi,[S(`button`,{onClick:Y,disabled:O.value,class:`px-3 py-1.5 text-xs bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-secondary dark:text-content-muted rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors disabled:opacity-50`},b(O.value?`Loading...`:`Refresh Stats`),9,$i),S(`button`,{onClick:t[0]||=e=>D.value=!0,class:`px-3 py-1.5 text-xs bg-blue-100 dark:bg-blue-500/20 hover:bg-blue-200 dark:hover:bg-blue-500/30 text-blue-700 dark:text-blue-400 rounded-lg border border-blue-500/50 transition-colors`,title:`How rate limiting works`},[...t[19]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`})],-1)]])]),S(`div`,ea,[f.value?(w(),C(x,{key:1},[S(`button`,{onClick:Q,disabled:p.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,ta),S(`button`,{onClick:re,disabled:p.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(p.value?`Saving...`:`Save Changes`),9,na)],64)):(w(),C(`button`,{key:0,onClick:Z,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))])]),S(`div`,ra,[t[28]||=S(`h3`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},` Current Status `,-1),O.value&&!A.value?(w(),C(`div`,ia,[...t[20]||=[S(`div`,{class:`animate-spin w-5 h-5 border-2 border-stroke-subtle dark:border-stroke/20 border-t-cyan-500 dark:border-t-primary rounded-full`},null,-1),S(`span`,{class:`ml-2 text-sm text-content-muted`},`Loading stats...`,-1)]])):A.value?(w(),C(x,{key:2},[S(`div`,oa,[S(`div`,sa,[t[22]||=S(`div`,{class:`text-xs text-content-muted dark:text-content-muted`},`Mesh Tier`,-1),S(`div`,{class:u([`mt-1 px-2 py-0.5 rounded border text-xs font-medium inline-block`,ie.value])},b($.value.toUpperCase()),3)]),S(`div`,ca,[t[23]||=S(`div`,{class:`text-xs text-content-muted dark:text-content-muted`},`Adverts/min`,-1),S(`div`,la,b(A.value.metrics?.adverts_per_min_ewma?.toFixed(2)||`0.00`),1)]),S(`div`,ua,[t[24]||=S(`div`,{class:`text-xs text-content-muted dark:text-content-muted`},`Allowed`,-1),S(`div`,da,b(A.value.stats?.adverts_allowed||0),1)]),S(`div`,fa,[t[25]||=S(`div`,{class:`text-xs text-content-muted dark:text-content-muted`},`Dropped`,-1),S(`div`,pa,b(A.value.stats?.adverts_dropped||0),1)])]),Object.keys(A.value.active_penalties||{}).length>0?(w(),C(`div`,ma,[t[26]||=S(`div`,{class:`text-xs font-medium text-red-700 dark:text-red-400 mb-1`},` Active Penalties `,-1),(w(!0),C(x,null,i(A.value.active_penalties,(e,t)=>(w(),C(`div`,{key:t,class:`text-xs font-mono text-red-600 dark:text-red-400`},b(t)+`... - `+b(Math.round(e))+`s remaining `,1))),128))])):g(``,!0),A.value.recent_drops&&A.value.recent_drops.length>0?(w(),C(`div`,ha,[t[27]||=S(`div`,{class:`text-xs font-medium text-orange-700 dark:text-orange-400 mb-1`},` Recently Dropped Adverts `,-1),(w(!0),C(x,null,i(A.value.recent_drops,(e,t)=>(w(),C(`div`,{key:t,class:`text-xs text-orange-600 dark:text-orange-400 py-0.5`},[S(`span`,ga,b(e.name),1),S(`span`,_a,`(`+b(e.pubkey)+`...)`,1),S(`span`,va,` - `+b(e.reason)+` (`+b(e.seconds_ago)+`s ago)`,1)]))),128))])):g(``,!0)],64)):(w(),C(`div`,aa,[...t[21]||=[S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Stats not available. Click "Refresh Stats" to load. `,-1)]]))]),S(`div`,ya,[t[36]||=S(`h3`,{class:`text-sm font-medium text-content-primary dark:text-content-primary flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`})]),y(` Token Bucket Rate Limiting `)],-1),t[37]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Controls how many adverts each pubkey can send in a given time period. `,-1),S(`div`,ba,[t[30]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Rate Limiting`,-1),f.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[1]||=e=>M.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[29]||=[S(`option`,{value:!0},`Enabled`,-1),S(`option`,{value:!1},`Disabled`,-1)]],512)),[[P,M.value]]):(w(),C(`div`,xa,b(M.value?`Enabled`:`Disabled`),1))]),S(`div`,Sa,[t[31]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Bucket Capacity`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`Max burst size (adverts)`)],-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[2]||=e=>N.value=e,type:`number`,min:`1`,max:`10`,class:`w-full sm:w-24 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,N.value,void 0,{number:!0}]]):(w(),C(`div`,Ca,b(N.value),1))]),S(`div`,wa,[t[33]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Refill Interval`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Time between token refills `)],-1),f.value?(w(),C(`div`,Ea,[m(S(`input`,{"onUpdate:modelValue":t[3]||=e=>R.value=e,type:`number`,min:`1`,max:`48`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,R.value,void 0,{number:!0}]]),t[32]||=S(`span`,{class:`text-content-muted text-sm`},`hours`,-1)])):(w(),C(`div`,Ta,b(R.value)+` hours `,1))]),S(`div`,Da,[t[35]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Minimum Interval`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Hard minimum between adverts `)],-1),f.value?(w(),C(`div`,ka,[m(S(`input`,{"onUpdate:modelValue":t[4]||=e=>z.value=e,type:`number`,min:`0`,max:`1440`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,z.value,void 0,{number:!0}]]),t[34]||=S(`span`,{class:`text-content-muted text-sm`},`min`,-1)])):(w(),C(`div`,Oa,b(z.value)+` min `,1))])]),S(`div`,Aa,[t[47]||=S(`h3`,{class:`text-sm font-medium text-content-primary dark:text-content-primary flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636`})]),y(` Penalty Box (Repeat Offenders) `)],-1),t[48]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Applies escalating cooldowns to pubkeys that repeatedly violate limits. `,-1),S(`div`,ja,[t[39]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Penalty Box`,-1),f.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[5]||=e=>B.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[38]||=[S(`option`,{value:!0},`Enabled`,-1),S(`option`,{value:!1},`Disabled`,-1)]],512)),[[P,B.value]]):(w(),C(`div`,Ma,b(B.value?`Enabled`:`Disabled`),1))]),S(`div`,Na,[t[40]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Violation Threshold`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Violations before penalty `)],-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[6]||=e=>V.value=e,type:`number`,min:`1`,max:`10`,class:`w-full sm:w-24 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,V.value,void 0,{number:!0}]]):(w(),C(`div`,Pa,b(V.value),1))]),S(`div`,Fa,[t[42]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Base Penalty Duration`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`First penalty duration`)],-1),f.value?(w(),C(`div`,La,[m(S(`input`,{"onUpdate:modelValue":t[7]||=e=>H.value=e,type:`number`,min:`1`,max:`48`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,H.value,void 0,{number:!0}]]),t[41]||=S(`span`,{class:`text-content-muted text-sm`},`hours`,-1)])):(w(),C(`div`,Ia,b(H.value)+` hours `,1))]),S(`div`,Ra,[t[44]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Penalty Multiplier`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`Escalation factor`)],-1),f.value?(w(),C(`div`,Ba,[m(S(`input`,{"onUpdate:modelValue":t[8]||=e=>U.value=e,type:`number`,min:`1`,max:`5`,step:`0.5`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,U.value,void 0,{number:!0}]]),t[43]||=S(`span`,{class:`text-content-muted text-sm`},`x`,-1)])):(w(),C(`div`,za,b(U.value)+`x `,1))]),S(`div`,Va,[t[46]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Max Penalty Duration`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`Maximum cooldown cap`)],-1),f.value?(w(),C(`div`,Ua,[m(S(`input`,{"onUpdate:modelValue":t[9]||=e=>W.value=e,type:`number`,min:`1`,max:`168`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,W.value,void 0,{number:!0}]]),t[45]||=S(`span`,{class:`text-content-muted text-sm`},`hours`,-1)])):(w(),C(`div`,Ha,b(W.value)+` hours `,1))])]),S(`div`,Wa,[t[58]||=d(` Adaptive Rate Limiting How the three systems work together: Each layer can be enabled/disabled independently and the others will still function.
Rate Limiting OFF: All limiting disabled — adverts pass through freely Adaptive OFF: Token bucket uses fixed limits (no tier scaling), penalty box still works Penalty Box OFF: Token bucket still applies, but no escalating cooldowns for repeat offenders Decision flow when all enabled: Adaptive tier check → Penalty box check → Token bucket check → Violation recording (triggers penalty box)
Activity tiers: Quiet (bypass limiting) → Normal (lighter: 0.5x intervals) → Busy (base: 1.0x intervals) → Congested (stricter: 2.0x intervals)
Note: Adaptive mode scales refill/min-interval timing; bucket capacity stays at the configured base value.
`,2),S(`div`,Ga,[t[50]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Adaptive Mode`,-1),f.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[10]||=e=>G.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[49]||=[S(`option`,{value:!0},`Enabled`,-1),S(`option`,{value:!1},`Disabled`,-1)]],512)),[[P,G.value]]):(w(),C(`div`,Ka,b(G.value?`Enabled`:`Disabled`),1))]),S(`div`,qa,[t[52]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Tier Change Delay`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`Prevents tier flapping`)],-1),f.value?(w(),C(`div`,Ya,[m(S(`input`,{"onUpdate:modelValue":t[11]||=e=>K.value=e,type:`number`,min:`0`,max:`60`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,K.value,void 0,{number:!0}]]),t[51]||=S(`span`,{class:`text-content-muted text-sm`},`min`,-1)])):(w(),C(`div`,Ja,b(K.value)+` min `,1))]),S(`div`,Xa,[t[56]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm mb-2 block`},`Activity Tier Thresholds (adverts/min)`,-1),S(`div`,Za,[S(`div`,Qa,[t[53]||=S(`div`,{class:`text-xs text-green-600 dark:text-green-400 mb-1`},`Quiet Max`,-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[12]||=e=>ne.value=e,type:`number`,min:`0`,max:`1`,step:`0.01`,class:`w-full px-2 py-1 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded text-content-primary dark:text-content-primary text-sm text-center focus:outline-none focus:border-primary`},null,512)),[[F,ne.value,void 0,{number:!0}]]):(w(),C(`div`,$a,b(ne.value),1))]),S(`div`,eo,[t[54]||=S(`div`,{class:`text-xs text-blue-600 dark:text-blue-400 mb-1`},`Normal Max`,-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[13]||=e=>q.value=e,type:`number`,min:`0`,max:`5`,step:`0.01`,class:`w-full px-2 py-1 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded text-content-primary dark:text-content-primary text-sm text-center focus:outline-none focus:border-primary`},null,512)),[[F,q.value,void 0,{number:!0}]]):(w(),C(`div`,to,b(q.value),1))]),S(`div`,no,[t[55]||=S(`div`,{class:`text-xs text-yellow-600 dark:text-yellow-400 mb-1`},`Busy Max`,-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[14]||=e=>J.value=e,type:`number`,min:`0`,max:`10`,step:`0.01`,class:`w-full px-2 py-1 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded text-content-primary dark:text-content-primary text-sm text-center focus:outline-none focus:border-primary`},null,512)),[[F,J.value,void 0,{number:!0}]]):(w(),C(`div`,ro,b(J.value),1))])]),t[57]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted mt-2`},` Above Busy Max = Congested tier (strictest limiting) `,-1)])]),D.value?(w(),C(`div`,{key:2,class:`fixed inset-0 bg-black/50 flex items-start justify-center z-50 p-4 overflow-y-auto`,onClick:t[18]||=I(e=>D.value=!1,[`self`])},[S(`div`,{class:`bg-background dark:bg-background-dark rounded-lg shadow-xl max-w-3xl w-full my-8`,onClick:t[17]||=I(()=>{},[`stop`])},[S(`div`,io,[S(`div`,ao,[t[60]||=S(`h2`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` How Advert Rate Limiting Works `,-1),S(`button`,{onClick:t[15]||=e=>D.value=!1,class:`text-content-muted hover:text-content-primary dark:text-content-muted dark:hover:text-content-primary`},[...t[59]||=[S(`svg`,{class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),t[61]||=d(` Why you may see the same advert more than once Mesh traffic can reach your repeater through different paths, so duplicate advert packets are expected.
First copy arrives and is forwarded Second copy arrives through another repeater path Later copies may be dropped once limits are hit This is normal behavior and helps prevent repeated rebroadcasts from flooding the mesh.
Token Bucket Rate Limiting Each sender has a token bucket. Every forwarded advert uses one token.
Bucket Capacity: How many adverts can pass in a burst.Refill Rate: How quickly tokens come back over time.Min Interval: Optional gap between adverts from the same sender (usually set to 0). Example (capacity 2): - Copy 1 forwarded (2 → 1 tokens) - Copy 2 forwarded (1 → 0 tokens) - Copy 3 dropped (no tokens left)
Penalty Box (Repeat Offenders) If a sender keeps hitting the limit, it is temporarily blocked.
Violation Threshold: How many hits before penalty starts.Base Penalty: First block duration.Multiplier: Repeated penalties get longer.Decay Time: Violations age out after stable behavior. Adaptive Mesh Activity Tiers Adaptive mode adjusts limits based on recent advert activity.
How Congestion is Measured: What is counted: Advert packets only (not chat/data traffic) Smoothing: 60-second EWMA to avoid reacting to short spikes Score: Tier is based on adverts per minuteHysteresis: Tier changes must hold for 5 minutesQUIET
Activity < 0.05/min
No rate limiting
NORMAL
Activity 0.05-0.20/min
Light limiting (50%)
BUSY
Activity 0.20-0.50/min
Standard limiting (100%)
CONGESTED
Activity > 0.50/min
Aggressive (200%)
Quick examples: - 0.02 adverts/min → QUIET (bypass) - 0.35 adverts/min → BUSY (tighter limits) - 0.68 adverts/min → CONGESTED (strict limits)
Recommended starting settings Min Interval: 0 (disabled), let adaptive mode do the workBucket Capacity: 2-3 tokens for normal mesh propagationAdaptive Mode: OnPenalty Box: On `,5),S(`div`,oo,[S(`button`,{onClick:t[16]||=e=>D.value=!1,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors`},` Got it! `)])])])])):g(``,!0)]))}}),co=[{name:`US West only (US v1)`,website:`letsmesh.net`,brokers:[{enabled:!0,name:`MeshMapper`,host:`mqtt-us-v1.letsmesh.net`,port:443,audience:`mqtt-us-v1.letsmesh.net`,use_jwt_auth:!0,format:`letsmesh`,transport:`websockets`,retain_status:!1,tls:{enabled:!0,insecure:!1}}]},{name:`Europe only (EU v1)`,website:`letsmesh.net`,brokers:[{enabled:!0,name:`MeshMapper`,host:`mqtt-eu-v1.letsmesh.net`,port:443,audience:`mqtt-eu-v1.letsmesh.net`,use_jwt_auth:!0,format:`letsmesh`,transport:`websockets`,retain_status:!1,tls:{enabled:!0,insecure:!1}}]},{name:`Waev`,website:`https://waev.app`,brokers:[{enabled:!0,name:`Waev`,host:`mqtt-a.waev.app`,port:443,audience:`mqtt.waev.app`,use_jwt_auth:!0,format:`letsmesh`,transport:`websockets`,retain_status:!1,tls:{enabled:!0,insecure:!1}}]},{name:`MeshMapper`,website:`https://meshmapper.net`,brokers:[{enabled:!0,name:`MeshMapper`,host:`mqtt.meshmapper.cc`,port:443,audience:`mqtt.meshmapper.cc`,use_jwt_auth:!0,format:`letsmesh`,transport:`websockets`,retain_status:!1,tls:{enabled:!0,insecure:!1}}]}],lo={class:`space-y-6`},uo={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},fo={class:`flex items-center justify-between mb-4`},po=[`disabled`],mo={key:0},ho={key:1},go={key:0,class:`text-sm text-content-secondary dark:text-content-muted`},_o={key:1,class:`space-y-3`},vo={class:`flex items-center gap-2`},yo={key:0,class:`space-y-2`},bo=[`title`],xo={key:1,class:`text-sm text-content-muted dark:text-content-muted/60 italic`},So={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Co={class:`flex items-start justify-between mb-6`},wo={key:0,class:`space-y-4`},To={class:`grid grid-cols-1 sm:grid-cols-2 gap-x-8 gap-y-3`},Eo={class:`mt-1 text-sm text-content-primary dark:text-content-primary font-mono`},Do={class:`mt-1 text-sm text-content-primary dark:text-content-primary`},Oo={class:`mt-1 text-sm text-content-primary dark:text-content-primary`},ko={class:`mt-1 text-sm text-content-primary dark:text-content-primary`},Ao={key:0,class:`mt-2 text-sm text-content-muted dark:text-content-muted/60 italic`},jo={key:1,class:`mt-2 space-y-1.5`},Mo={class:`min-w-0 flex-1`},No={class:u([`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium`])},Po={key:0,class:`w-4 h-4 text-green-600 dark:text-green-500`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Fo={class:`text-sm font-medium text-content-primary dark:text-content-primary`},Io={class:`text-xs text-content-secondary dark:text-content-muted ml-2 font-mono`},Lo=[`title`],Ro={key:1,class:`space-y-5`},zo={class:`grid grid-cols-1 sm:grid-cols-2 gap-4`},Bo={class:`grid grid-cols-1 sm:grid-cols-2 gap-4`},Vo={class:`grid grid-cols-1 sm:grid-cols-2 gap-4`},Ho={class:`flex items-start justify-between mb-3 gap-3`},Uo={class:`flex items-center gap-2 flex-shrink-0`},Wo={class:`relative`},Go={key:0,class:`absolute right-0 top-full mt-1 z-20 w-64 rounded-lg shadow-lg border border-stroke-subtle dark:border-stroke/20 bg-white dark:bg-[var(--color-surface)] overflow-hidden`},Ko={class:`py-1`},qo=[`onClick`],Jo={class:`min-w-0 flex-1`},Yo={class:`text-sm font-medium text-content-primary dark:text-content-primary group-hover:text-cyan-700 dark:group-hover:text-primary transition-colors`},Xo={class:`text-xs text-content-secondary dark:text-content-muted`},Zo=[`href`],Qo={key:0,class:`flex flex-col items-center justify-center py-7 rounded-lg border-2 border-dashed border-stroke-subtle dark:border-stroke/20 text-content-secondary dark:text-content-muted`},$o={key:1,class:`space-y-2`},es={key:0,class:`flex items-center gap-3 px-4 py-2.5`},ts={class:`min-w-0 flex-1`},ns={class:`text-sm font-medium text-content-primary dark:text-content-primary`},rs={class:`text-xs font-mono text-content-secondary dark:text-content-muted ml-2`},is={key:0,class:`ml-2 text-xs text-red-500 dark:text-red-400`},as={class:`flex items-center gap-0.5 flex-shrink-0`},os=[`onClick`],ss=[`onClick`],cs={key:1,class:`p-4 space-y-3 bg-background-mute/60 dark:bg-background/20`},ls={class:`grid grid-cols-1 sm:grid-cols-2 gap-3`},us={class:`grid grid-cols-1 sm:grid-cols-2 gap-3`},ds={class:`sm:col-span-2`},fs={key:0},ps={key:1},ms={class:`grid grid-cols-1 sm:grid-cols-2 gap-3`},hs={class:`sm:col-span-2`},gs={class:`sm:col-span-2`},_s={key:2},vs={class:`col-span-full`},ys={class:`flex flex-wrap gap-2`},bs=[`onClick`],xs={class:`flex items-center gap-2 pt-1`},Ss=[`disabled`],Cs=[`onClick`],ws={key:0,class:`p-3 rounded-lg bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-700/30 text-green-700 dark:text-green-400 text-sm`},Ts={key:1,class:`p-3 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-700/30 text-red-700 dark:text-red-400 text-sm`},Es={class:`flex items-center gap-3 pt-2`},Ds=[`disabled`],Os={key:0},ks={key:1},As=[`disabled`],js=M(f({__name:`LetsMeshSettings`,setup(e){let n=j(),r=v(()=>n.stats?.config?.mqtt_brokers||{}),o=[`REQ`,`RESPONSE`,`TXT_MSG`,`ACK`,`ADVERT`,`GRP_TXT`,`GRP_DATA`,`ANON_REQ`,`PATH`,`TRACE`,`RAW_CUSTOM`],c=co,l=E(!1),d=E(!1),f=E(``),p=E(``),T=E(``),D=E(300),O=E(``),A=E(``),M=E([]),R=E(null),z=E({_id:0,enabled:!0,name:``,host:``,port:443,format:`letsmesh`,use_jwt_auth:!1,transport:`websockets`,disallowedInput:[],retain_status:!1,tls:{enabled:!0,insecure:!1}}),B=E(!1);function V(e){B.value=!1,R.value!==null&&K(),e.brokers.forEach(e=>{let t=H(e);M.value.push(t)})}let ee=1;function H(e={}){return{_id:ee++,enabled:e.enabled??!0,name:e.name??``,host:e.host??``,port:e.port??0,audience:e.audience??``,format:e.format??`letsmesh`,use_jwt_auth:e.use_jwt_auth??!1,username:e.username??``,password:e.password??``,transport:e.transport??`websockets`,disallowedInput:Array.isArray(e.disallowedInput)?[...e.disallowedInput]:[],retain_status:e.retain_status??!1,base_topic:e.base_topic??``,tls:{enabled:e.tls?.enabled??!1,insecure:e.tls?.insecure??!1}}}function U(){let e=H();M.value.push(e),z.value={...e},R.value=e._id}function W(e){M.value=M.value.filter(t=>t._id!==e),R.value===e&&(R.value=null)}function G(e){z.value={...e},R.value=e._id}function te(){R.value=null}function K(){let e=z.value;if(!e.name.trim()||!e.host.trim()||e.use_jwt_auth&&!e.audience?.trim())return;let t=M.value.findIndex(t=>t._id===e._id);t!==-1&&M.value.splice(t,1,{...e}),R.value=null}function ne(){let e=z.value;(!e.audience||e.audience===e.host)&&(e.audience=e.host)}let q=v(()=>{let e={};return M.value.forEach(t=>{t.name.trim()?t.host.trim()?t.use_jwt_auth&&!t.audience?.trim()?e[t._id]=`Audience required for JWT auth`:(t.port<1||t.port>65535)&&(e[t._id]=`Port must be 1–65535`):e[t._id]=`Host required`:e[t._id]=`Name required`}),e}),J=v(()=>Object.keys(q.value).length>0),Y=E(null),X=E(!1);async function Z(){X.value=!0;try{let e=await k.get(`/api/mqtt_status`);e.data?.success&&(Y.value=e.data.data)}catch{}finally{X.value=!1}}function Q(){let e=r.value;T.value=e.iata_code??``,D.value=e.status_interval??300,O.value=e.owner??``,A.value=e.email??``,M.value=Array.isArray(e.brokers)?e.brokers.map(e=>H(e)):[]}h(r,()=>{l.value||Q()},{immediate:!0});function re(){Q(),R.value=null,l.value=!0,f.value=``,p.value=``}function $(){R.value=null,l.value=!1,f.value=``,p.value=``}function ie(e,t){e.disallowedInput||=[];let n=e.disallowedInput.indexOf(t);n===-1?e.disallowedInput.push(t):e.disallowedInput.splice(n,1)}async function ae(){if(R.value!==null&&K(),J.value){p.value=`Please fix broker errors before saving.`;return}d.value=!0,p.value=``,f.value=``;try{let e=(await k.post(`/api/update_mqtt_config`,{iata_code:T.value,status_interval:D.value,owner:O.value,email:A.value,brokers:M.value.map(e=>{let t={name:e.name,enabled:e.enabled,transport:e.transport,host:e.host,port:e.port,use_jwt_auth:e.use_jwt_auth,format:e.format,disallowed_packet_types:e.disallowedInput,base_topic:e.base_topic,retain_status:e.retain_status,tls:{enabled:e.tls?.enabled??!1,insecure:e.tls?.insecure??!1}};return e.use_jwt_auth?{...t,audience:e.audience}:{...t,username:e.username,password:e.password}})})).data;e?.success?(f.value=e.data?.message||`Settings saved`,l.value=!1,await n.fetchStats(),await Z(),setTimeout(()=>{f.value=``},5e3)):p.value=e?.error||`Save failed`}catch(e){let t=e;p.value=t?.response?.data?.error||t?.message||`Request failed`}finally{d.value=!1}}return s(Z),(e,n)=>(w(),C(`div`,lo,[S(`div`,uo,[S(`div`,fo,[n[21]||=S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Observer Status `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Live LetsMesh broker connection state `)],-1),S(`button`,{onClick:Z,disabled:X.value,class:`px-3 py-1.5 text-xs rounded-lg bg-cyan-500/10 dark:bg-primary/10 hover:bg-cyan-500/20 dark:hover:bg-primary/20 text-cyan-700 dark:text-primary border border-cyan-400/30 dark:border-primary/30 transition-colors disabled:opacity-50`},[X.value?(w(),C(`span`,mo,`Refreshing…`)):(w(),C(`span`,ho,`↻ Refresh`))],8,po)]),Y.value?(w(),C(`div`,_o,[S(`div`,vo,[n[22]||=S(`span`,{class:`text-sm text-content-secondary dark:text-content-muted w-36`},`Handler`,-1),S(`span`,{class:u([`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium`,Y.value.handler_active?`bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400`:`bg-gray-100 dark:bg-gray-800/50 text-gray-500 dark:text-gray-400`])},[S(`span`,{class:u([`w-1.5 h-1.5 rounded-full`,Y.value.handler_active?`bg-green-500`:`bg-gray-400`])},null,2),y(` `+b(Y.value.handler_active?`Active`:`Inactive`),1)],2)]),Y.value.brokers.length?(w(),C(`div`,yo,[(w(!0),C(x,null,i(Y.value.brokers,e=>(w(),C(`div`,{key:e.host,class:`flex items-center gap-2`},[S(`span`,{class:`text-sm text-content-secondary dark:text-content-muted w-36 truncate`,title:e.name},b(e.name),9,bo),S(`span`,{class:u([`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium`,e.status.connected?`bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400`:e.status.reconnecting?`bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-400`:`bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400`])},[S(`span`,{class:u([`w-1.5 h-1.5 rounded-full`,e.status.connected?`bg-green-500`:e.status.reconnecting?`bg-amber-500`:`bg-red-500`])},null,2),y(` `+b(e.status.connected?`Connected`:e.status.reconnecting?`Reconnecting…`:`Disconnected`),1)],2)]))),128))])):(w(),C(`div`,xo,` No broker connections configured. `))])):(w(),C(`div`,go,` Status unavailable — service may not be running. `))]),S(`div`,So,[S(`div`,Co,[n[23]||=S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Observer Configuration `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Configure MQTT observer settings `)],-1),l.value?g(``,!0):(w(),C(`button`,{key:0,onClick:re,class:`px-4 py-2 text-sm rounded-lg bg-cyan-500/10 dark:bg-primary/10 hover:bg-cyan-500/20 dark:hover:bg-primary/20 text-cyan-700 dark:text-primary border border-cyan-400/30 dark:border-primary/30 transition-colors`},` Edit `))]),l.value?(w(),C(`div`,Ro,[S(`div`,zo,[S(`div`,null,[n[30]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-1.5`},[y(` IATA Code `),S(`span`,{class:`text-content-secondary dark:text-content-muted font-normal text-xs ml-1`},`(e.g. SFO, LHR)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[0]||=e=>T.value=e,type:`text`,maxlength:`10`,placeholder:`TEST`,class:`w-full px-3 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[F,T.value]])])]),S(`div`,Bo,[S(`div`,null,[n[31]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-1.5`},`Owner / Callsign`,-1),m(S(`input`,{"onUpdate:modelValue":n[1]||=e=>O.value=e,type:`text`,placeholder:`Optional`,class:`w-full px-3 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,O.value]])]),S(`div`,null,[n[32]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-1.5`},`Email`,-1),m(S(`input`,{"onUpdate:modelValue":n[2]||=e=>A.value=e,type:`email`,placeholder:`Optional`,class:`w-full px-3 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,A.value]])])]),S(`div`,Vo,[n[33]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-1.5`},[y(` Status Heartbeat Interval `),S(`span`,{class:`text-content-secondary dark:text-content-muted font-normal text-xs ml-1`},`(seconds, min 60)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[3]||=e=>D.value=e,type:`number`,min:`60`,max:`3600`,class:`w-32 px-3 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[F,D.value,void 0,{number:!0}]])]),S(`div`,null,[S(`div`,Ho,[n[40]||=S(`div`,{class:`min-w-0`},[S(`label`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},`Brokers`),S(`p`,{class:`text-xs text-content-secondary dark:text-content-muted mt-0.5`},` MQTT brokers `)],-1),S(`div`,Uo,[S(`div`,Wo,[S(`button`,{onClick:n[4]||=e=>B.value=!B.value,class:`inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg bg-background-mute dark:bg-background/30 hover:bg-stroke-subtle dark:hover:bg-stroke/10 text-content-secondary dark:text-content-muted border border-stroke-subtle dark:border-stroke/20 transition-colors`},[n[35]||=S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M19 11H5m14 0l-4-4m4 4l-4 4`})],-1),n[36]||=y(` From Template `,-1),(w(),C(`svg`,{class:u([`w-3 h-3 ml-0.5 transition-transform`,B.value?`rotate-180`:``]),fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[...n[34]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M19 9l-7 7-7-7`},null,-1)]],2))]),_(N,{name:`dropdown`},{default:t(()=>[B.value?(w(),C(`div`,Go,[n[38]||=S(`div`,{class:`px-3 py-2 border-b border-stroke-subtle dark:border-stroke/10`},[S(`p`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},` Known Networks `)],-1),S(`div`,Ko,[(w(!0),C(x,null,i(a(c),e=>(w(),C(`div`,{key:e.name,class:`flex items-center gap-2 px-3 py-2.5 hover:bg-background-mute dark:hover:bg-background/30 cursor-pointer group`,onClick:t=>V(e)},[S(`div`,Jo,[S(`p`,Yo,b(e.name),1),S(`p`,Xo,b(e.brokers.length)+` broker`+b(e.brokers.length===1?``:`s`),1)]),S(`a`,{href:e.website,target:`_blank`,rel:`noopener noreferrer`,title:`Visit website`,class:`flex-shrink-0 p-1 rounded hover:bg-cyan-500/10 dark:hover:bg-primary/10 text-content-secondary dark:text-content-muted hover:text-cyan-700 dark:hover:text-primary transition-colors`,onClick:n[5]||=I(()=>{},[`stop`])},[...n[37]||=[S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14`})],-1)]],8,Zo)],8,qo))),128))])])):g(``,!0)]),_:1}),B.value?(w(),C(`div`,{key:0,class:`fixed inset-0 z-10`,onClick:n[6]||=e=>B.value=!1})):g(``,!0)]),S(`button`,{onClick:U,class:`inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg bg-cyan-500/10 dark:bg-primary/10 hover:bg-cyan-500/20 dark:hover:bg-primary/20 text-cyan-700 dark:text-primary border border-cyan-400/30 dark:border-primary/30 transition-colors`},[...n[39]||=[S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 4v16m8-8H4`})],-1),y(` Add `,-1)]])])]),M.value.length?(w(),C(`div`,$o,[(w(!0),C(x,null,i(M.value,e=>(w(),C(`div`,{key:e._id,class:u([`rounded-lg border overflow-hidden transition-colors`,q.value[e._id]?`border-red-300 dark:border-red-700/50`:`border-stroke-subtle dark:border-stroke/10`])},[R.value===e._id?(w(),C(`div`,cs,[S(`div`,ls,[S(`div`,null,[n[44]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Enabled `),S(`span`,{class:`text-red-500`},`*`)],-1),m(S(`input`,{"onUpdate:modelValue":n[7]||=e=>z.value.enabled=e,type:`checkbox`,class:`w-4 h-4 text-cyan-600 bg-background-mute border-stroke-subtle dark:border-stroke/20 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[L,z.value.enabled]])]),S(`div`,null,[n[45]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Retain Status`),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},[y(` (Enable MQTT `),S(`a`,{href:`https://www.hivemq.com/blog/mqtt-essentials-part-8-retained-messages/`,class:`w-4 h-4 text-cyan-600 border-stroke-subtle dark:border-stroke/20 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},`Retained`),y(` for status messages) `)])],-1),m(S(`input`,{"onUpdate:modelValue":n[8]||=e=>z.value.retain_status=e,type:`checkbox`,class:`w-4 h-4 text-cyan-600 bg-background-mute border-stroke-subtle dark:border-stroke/20 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[L,z.value.retain_status]])]),S(`div`,null,[n[46]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Name `),S(`span`,{class:`text-red-500`},`*`)],-1),m(S(`input`,{"onUpdate:modelValue":n[9]||=e=>z.value.name=e,type:`text`,placeholder:`Broker Name`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,z.value.name]])]),S(`div`,null,[n[48]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Transport `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`})],-1),m(S(`select`,{"onUpdate:modelValue":n[10]||=e=>z.value.transport=e,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},[...n[47]||=[S(`option`,{value:`websockets`},`Websockets`,-1),S(`option`,{value:`tcp`},`TCP`,-1)]],512),[[P,z.value.transport]])]),S(`div`,null,[n[49]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Host `),S(`span`,{class:`text-red-500`},`*`)],-1),m(S(`input`,{"onUpdate:modelValue":n[11]||=e=>z.value.host=e,type:`text`,placeholder:`mqtt.myserver.com`,onBlur:ne,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,544),[[F,z.value.host]])]),S(`div`,us,[S(`div`,ds,[n[50]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Port `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(Usually 443 for Websockets, 1883 for TCP)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[12]||=e=>z.value.port=e,type:`number`,min:`0`,max:`65535`,placeholder:`0`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[F,z.value.port,void 0,{number:!0}]])]),S(`div`,null,[n[51]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` TLS - Enabled `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(Enable TLS)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[13]||=e=>z.value.tls.enabled=e,type:`checkbox`,class:`px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[L,z.value.tls.enabled,void 0,{number:!0}]])]),S(`div`,null,[n[52]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` TLS - Insecure`),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(Allow insecure TLS connections)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[14]||=e=>z.value.tls.insecure=e,type:`checkbox`,class:`px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[L,z.value.tls.insecure,void 0,{number:!0}]])])]),S(`div`,null,[n[53]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Use JWT Auth `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`})],-1),m(S(`input`,{"onUpdate:modelValue":n[15]||=e=>z.value.use_jwt_auth=e,type:`checkbox`,placeholder:`true`,class:`px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[L,z.value.use_jwt_auth]])]),z.value.use_jwt_auth?(w(),C(`div`,fs,[n[54]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Audience `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(JWT aud — usually same as host)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[16]||=e=>z.value.audience=e,type:`text`,placeholder:`mqtt.myserver.com`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[F,z.value.audience]])])):(w(),C(`div`,ps,[S(`div`,ms,[n[57]||=S(`input`,{type:`text`,autocomplete:`username`,style:{display:`none`}},null,-1),n[58]||=S(`input`,{type:`password`,autocomplete:`current-password`,style:{display:`none`}},null,-1),S(`div`,hs,[n[55]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Username `),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},` (Leave blank for anonymous auth) `)],-1),m(S(`input`,{autocomplete:`username`,"onUpdate:modelValue":n[17]||=e=>z.value.username=e,type:`text`,placeholder:`username`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,z.value.username]])]),S(`div`,gs,[n[56]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},` Password `,-1),m(S(`input`,{autocomplete:`new-password`,"onUpdate:modelValue":n[18]||=e=>z.value.password=e,type:`password`,placeholder:``,readonly:``,onfocus:`this.removeAttribute('readonly');`,onblur:`this.setAttribute('readonly', true);`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,z.value.password]])])])])),S(`div`,null,[n[60]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Format `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`})],-1),m(S(`select`,{"onUpdate:modelValue":n[19]||=e=>z.value.format=e,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},[...n[59]||=[S(`option`,{value:`letsmesh`},`LetsMesh MQTT format`,-1),S(`option`,{value:`mqtt`},`pyMC MQTT format`,-1)]],512),[[P,z.value.format]])]),z.value.format===`mqtt`?(w(),C(`div`,_s,[n[61]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` MQTT base topic `),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(Messages are sent to topics under this path. Example: /advert) `)],-1),m(S(`input`,{"onUpdate:modelValue":n[20]||=e=>z.value.base_topic=e,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`,placeholder:`meshcore/repeater`},null,512),[[F,z.value.base_topic]])])):g(``,!0),S(`div`,vs,[n[62]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-2`},[y(` Block Packet Types `),S(`span`,{class:`text-content-secondary dark:text-content-muted font-normal text-xs ml-1`},` (prevent publishing to LetsMesh) `)],-1),S(`div`,ys,[(w(),C(x,null,i(o,e=>S(`button`,{key:e,onClick:t=>ie(z.value,e),class:u([`px-2.5 py-1 rounded text-xs font-mono font-medium border transition-colors`,z.value.disallowedInput?.includes(e)?`bg-red-100 dark:bg-red-900/30 border-red-300 dark:border-red-700/50 text-red-700 dark:text-red-400`:`bg-background-mute dark:bg-background/30 border-stroke-subtle dark:border-stroke/20 text-content-secondary dark:text-content-muted hover:border-cyan-400/50 dark:hover:border-primary/40`])},b(e),11,bs)),64))]),n[63]||=S(`p`,{class:`mt-1.5 text-xs text-content-secondary dark:text-content-muted`},[S(`span`,{class:`text-red-600 dark:text-red-400 font-medium`},`Red = blocked.`),y(` Leave all unselected to publish all packet types. `)],-1)])]),S(`div`,xs,[S(`button`,{onClick:K,disabled:!z.value.name.trim()||!z.value.host.trim()||z.value.port<=0||z.value.port>65535||z.value.use_jwt_auth&&!z.value.audience?.trim(),class:`px-3 py-1.5 text-xs font-medium rounded-md bg-cyan-600 dark:bg-teal-600 hover:bg-cyan-700 dark:hover:bg-teal-700 text-white transition-colors disabled:opacity-40 disabled:cursor-not-allowed`},` Done `,8,Ss),S(`button`,{onClick:te,class:`px-3 py-1.5 text-xs rounded-md border border-stroke-subtle dark:border-stroke/20 hover:bg-stroke-subtle dark:hover:bg-stroke/10 text-content-secondary dark:text-content-muted transition-colors`},` Cancel `),S(`button`,{onClick:t=>W(e._id),class:`ml-auto px-3 py-1.5 text-xs rounded-md border border-red-300/60 dark:border-red-700/30 hover:bg-red-50 dark:hover:bg-red-900/20 text-red-600 dark:text-red-400 transition-colors`},` Remove `,8,Cs)])])):(w(),C(`div`,es,[S(`div`,ts,[S(`span`,{class:u([`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium`,e.enabled?`bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400`:`bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400`])},[S(`span`,{class:u([`w-1.5 h-1.5 rounded-full`,e.enabled?`bg-green-500`:`bg-red-500`])},null,2),y(` `+b(e.enabled?`Enabled`:`Disabled`),1)],2),S(`span`,ns,b(e.name||`(unnamed)`),1),S(`span`,rs,b(e.host||`—`)+`:`+b(e.port),1),q.value[e._id]?(w(),C(`span`,is,b(q.value[e._id]),1)):g(``,!0)]),S(`div`,as,[S(`button`,{onClick:t=>G(e),title:`Edit`,class:`p-1.5 rounded hover:bg-cyan-500/10 dark:hover:bg-primary/10 text-content-secondary dark:text-content-muted hover:text-cyan-700 dark:hover:text-primary transition-colors`},[...n[42]||=[S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z`})],-1)]],8,os),S(`button`,{onClick:t=>W(e._id),title:`Remove`,class:`p-1.5 rounded hover:bg-red-500/10 dark:hover:bg-red-900/20 text-content-secondary dark:text-content-muted hover:text-red-600 dark:hover:text-red-400 transition-colors`},[...n[43]||=[S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16`})],-1)]],8,ss)])]))],2))),128))])):(w(),C(`div`,Qo,[...n[41]||=[S(`svg`,{class:`w-7 h-7 mb-2 opacity-40`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`1.5`,d:`M5 12h14M5 12l4-4m-4 4l4 4`})],-1),S(`p`,{class:`text-sm`},`No brokers`,-1),S(`p`,{class:`text-xs mt-0.5 opacity-70`},`Add a MQTT broker`,-1)]]))]),n[64]||=S(`div`,{class:`flex items-start gap-2 p-3 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-700/30 text-amber-700 dark:text-amber-400 text-xs`},[S(`svg`,{class:`w-4 h-4 mt-0.5 flex-shrink-0`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z`})]),y(` A service restart is required for MQTT broker changes to take effect. `)],-1),f.value?(w(),C(`div`,ws,b(f.value),1)):g(``,!0),p.value?(w(),C(`div`,Ts,b(p.value),1)):g(``,!0),S(`div`,Es,[S(`button`,{onClick:ae,disabled:d.value||J.value,class:`px-5 py-2 text-sm font-medium rounded-lg bg-cyan-600 dark:bg-teal-600 hover:bg-cyan-700 dark:hover:bg-teal-700 text-white transition-colors disabled:opacity-50 disabled:cursor-not-allowed`},[d.value?(w(),C(`span`,Os,`Saving…`)):(w(),C(`span`,ks,`Save Settings`))],8,Ds),S(`button`,{onClick:$,disabled:d.value,class:`px-4 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 hover:bg-stroke-subtle dark:hover:bg-stroke/10 text-content-secondary dark:text-content-muted border border-stroke-subtle dark:border-stroke/20 transition-colors disabled:opacity-50`},` Cancel `,8,As)])])):(w(),C(`div`,wo,[S(`div`,To,[S(`div`,null,[n[24]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`IATA Code`,-1),S(`p`,Eo,b(r.value.iata_code||`—`),1)]),S(`div`,null,[n[25]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`Status Interval`,-1),S(`p`,Do,b(r.value.status_interval??300)+`s `,1)]),S(`div`,null,[n[26]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`Owner`,-1),S(`p`,Oo,b(r.value.owner||`—`),1)]),S(`div`,null,[n[27]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`Email`,-1),S(`p`,ko,b(r.value.email||`—`),1)])]),S(`div`,null,[n[29]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`Brokers`,-1),r.value.brokers?.length?(w(),C(`div`,jo,[(w(!0),C(x,null,i(r.value.brokers,e=>(w(),C(`div`,{key:e.host,class:`flex items-center gap-3 px-3 py-2 rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/10`},[S(`div`,Mo,[S(`span`,No,[e.enabled?(w(),C(`svg`,Po,[...n[28]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M5 13l4 4L19 7`},null,-1)]])):g(``,!0)]),S(`span`,Fo,b(e.name),1),S(`span`,Io,`Host: `+b(e.host)+`:`+b(e.port),1)]),S(`span`,{class:`text-xs text-content-secondary dark:text-content-muted font-mono truncate max-w-[140px]`,title:e.format},b(e.format),9,Lo)]))),128))])):(w(),C(`div`,Ao,` None configured `))])]))])]))}}),[[`__scopeId`,`data-v-45835eb1`]]),Ms={class:`space-y-6`},Ns={key:0,class:`rounded-lg border-2 border-red-500/50 dark:border-red-400/40 bg-red-100 dark:bg-red-500/10 p-4`},Ps={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Fs=[`disabled`],Is={key:0,class:`flex items-center gap-2`},Ls={key:1,class:`flex items-center gap-2`},Rs={key:0,class:`text-xs text-green-600 dark:text-green-400 mt-2`},zs={key:1,class:`text-xs text-red-500 dark:text-red-400 mt-2`},Bs={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Vs={key:0},Hs={key:1,class:`rounded-lg border-2 border-red-500/50 dark:border-red-400/40 bg-red-50 dark:bg-red-500/10 p-4`},Us={class:`flex items-start gap-3`},Ws={class:`flex-1`},Gs={class:`text-xs text-red-600 dark:text-red-400/80 mt-1`},Ks={class:`flex gap-2 mt-3`},qs=[`disabled`],Js=[`disabled`],Ys={key:2,class:`text-xs text-green-600 dark:text-green-400 mt-2`},Xs={key:3,class:`text-xs text-red-500 dark:text-red-400 mt-2`},Zs={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Qs={class:`space-y-3`},$s={class:`flex items-center gap-3 cursor-pointer px-4 py-3 bg-background-mute dark:bg-background/30 rounded-lg border-2 border-dashed border-stroke-subtle dark:border-stroke/20 hover:border-cyan-500/50 dark:hover:border-primary/50 transition-colors`},ec={class:`text-sm text-content-secondary dark:text-content-muted`},tc={key:0,class:`bg-background-mute dark:bg-background/30 rounded-lg p-4 border border-stroke-subtle dark:border-stroke/10`},nc={key:0,class:`text-xs text-content-secondary dark:text-content-muted space-y-1 mb-3`},rc={class:`font-mono`},ic={class:`font-mono`},ac={key:0,class:`text-amber-600 dark:text-amber-400 font-medium`},oc={key:1,class:`text-content-muted`},sc={class:`text-xs text-content-secondary dark:text-content-muted`},cc={class:`font-mono`},lc={key:1},uc={key:2,class:`rounded-lg border-2 border-amber-500/50 dark:border-amber-400/40 bg-amber-50 dark:bg-amber-500/10 p-4`},dc={class:`flex items-start gap-3`},fc={class:`flex-1`},pc={class:`text-xs text-amber-700 dark:text-amber-300/80 mt-1`},mc={class:`flex gap-2 mt-3`},hc=[`disabled`],gc=[`disabled`],_c={key:3,class:`text-xs text-green-600 dark:text-green-400 mt-2`},vc={key:4,class:`text-xs text-red-500 dark:text-red-400 mt-2`},yc={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},bc={key:0},xc={key:1,class:`rounded-lg border-2 border-red-500/50 dark:border-red-400/40 bg-red-50 dark:bg-red-500/10 p-4`},Sc={class:`flex items-start gap-3`},Cc={class:`flex-1`},wc={class:`text-xs text-red-600 dark:text-red-400/80 mt-1`},Tc={class:`flex gap-2 mt-3`},Ec=[`disabled`],Dc=[`disabled`],Oc={key:2,class:`bg-background-mute dark:bg-background/30 rounded-lg p-4 border border-stroke-subtle dark:border-stroke/10 space-y-2`},kc={class:`flex items-center justify-between`},Ac={class:`text-xs text-content-secondary dark:text-content-muted space-y-1`},jc={class:`font-mono`},Mc={key:0},Nc={class:`font-mono`},Pc={key:1},Fc={class:`font-mono text-[10px] break-all`},Ic={key:3,class:`text-xs text-red-500 dark:text-red-400 mt-2`},Lc=f({__name:`BackupRestore`,setup(e){let t=v(()=>window.location.protocol===`http:`),n=E(!1),r=E(``),i=E(``);async function a(){n.value=!0,r.value=``,i.value=``;try{let e=await A.exportConfig(!1);if(!e.success||!e.data){i.value=e.error||`Export failed`;return}let t=new Blob([JSON.stringify(e.data,null,2)],{type:`application/json`}),n=URL.createObjectURL(t),a=document.createElement(`a`);a.href=n,a.download=`pymc-repeater-settings-${(e.data.meta?.exported_at||new Date().toISOString()).replace(/[:.]/g,`-`)}.json`,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(n),r.value=`Settings exported successfully (secrets redacted).`}catch(e){i.value=e instanceof Error?e.message:`Export failed`}finally{n.value=!1}}let o=E(!1),s=E(!1),c=E(``),l=E(``);async function u(){s.value=!0,c.value=``,l.value=``;try{let e=await A.exportConfig(!0);if(!e.success||!e.data){l.value=e.error||`Export failed`;return}let t=new Blob([JSON.stringify(e.data,null,2)],{type:`application/json`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`pymc-repeater-full-backup-${(e.data.meta?.exported_at||new Date().toISOString()).replace(/[:.]/g,`-`)}.json`,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n),c.value=`Full backup exported (includes all secrets).`,o.value=!1}catch(e){l.value=e instanceof Error?e.message:`Export failed`}finally{s.value=!1}}let f=E(null),p=E(null),m=E(!1),h=E(!1),_=E(``),T=E(``),D=E(null),O=v(()=>p.value?.config?Object.keys(p.value.config).join(`, `):``),k=v(()=>{let e=p.value?.meta?.includes_secrets;return e===!0||e===`true`});function j(e){let t=e.target.files?.[0];if(!t)return;f.value=t,p.value=null,m.value=!1,_.value=``,T.value=``;let n=new FileReader;n.onload=e=>{try{let t=JSON.parse(e.target?.result);t.config&&typeof t.config==`object`?p.value={meta:t.meta,config:t.config}:typeof t==`object`&&!Array.isArray(t)?p.value={config:t}:T.value=`Invalid file format — expected a JSON config object.`}catch{T.value=`Invalid JSON file.`}},n.readAsText(t)}function M(){m.value=!1,p.value=null,f.value=null,D.value&&(D.value.value=``)}async function N(){if(p.value?.config){h.value=!0,_.value=``,T.value=``;try{let e=await A.importConfig(p.value.config);if(e.success){let t=e.data,n=e.message||t?.message||`Configuration imported.`;t?.restart_required&&(n+=` A service restart is required for radio changes to take effect.`),_.value=n,m.value=!1,p.value=null,f.value=null,D.value&&(D.value.value=``)}else T.value=e.error||`Import failed`}catch(e){T.value=e instanceof Error?e.message:`Import failed`}finally{h.value=!1}}}let P=E(!1),F=E(!1),I=E(null),L=E(``);async function R(){F.value=!0,L.value=``;try{let e=await A.exportIdentityKey();if(!e.success||!e.data){L.value=e.error||`Export failed`;return}I.value=e.data;let t=new Blob([e.data.identity_key_hex],{type:`text/plain`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`pymc-identity-${e.data.node_address||`key`}.hex`,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n)}catch(e){L.value=e instanceof Error?e.message:`Export failed`}finally{F.value=!1}}return(e,v)=>(w(),C(`div`,Ms,[t.value?(w(),C(`div`,Ns,[...v[6]||=[d(` Unencrypted Connection This page is served over HTTP , not HTTPS. Exported data (including identity keys) will be transmitted in plain text . Only use these features on a trusted local network.
`,1)]])):g(``,!0),S(`div`,Ps,[v[9]||=S(`div`,{class:`flex items-start justify-between mb-4`},[S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Export Settings `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},[y(` Download the current configuration as a JSON file. Passwords, JWT secrets, and identity keys are `),S(`strong`,null,`redacted`),y(`. Safe to share or use as a template for other devices. `)])])],-1),S(`button`,{onClick:a,disabled:n.value,class:`px-4 py-2 bg-cyan-500/20 dark:bg-primary/20 hover:bg-cyan-500/30 dark:hover:bg-primary/30 text-cyan-900 dark:text-white rounded-lg border border-cyan-500/50 dark:border-primary/50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-sm`},[n.value?(w(),C(`span`,Is,[...v[7]||=[S(`span`,{class:`animate-spin w-4 h-4 border-2 border-current border-t-transparent rounded-full inline-block`},null,-1),y(` Exporting… `,-1)]])):(w(),C(`span`,Ls,[...v[8]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4`})],-1),y(` Export Settings `,-1)]]))],8,Fs),r.value?(w(),C(`p`,Rs,b(r.value),1)):g(``,!0),i.value?(w(),C(`p`,zs,b(i.value),1)):g(``,!0)]),S(`div`,Bs,[v[15]||=d(` Full Backup Download a complete backup including all passwords, JWT secrets, and identity keys . Required for restoring to a new device or recovering from a failed SD card.
Contains sensitive data. The backup file will include plain-text passwords and private keys. Store it securely and never share it.
`,2),o.value?g(``,!0):(w(),C(`div`,Vs,[S(`button`,{onClick:v[0]||=e=>o.value=!0,class:`px-4 py-2 bg-red-500/20 dark:bg-red-400/20 hover:bg-red-500/30 dark:hover:bg-red-400/30 text-red-900 dark:text-red-200 rounded-lg border border-red-500/50 dark:border-red-400/40 transition-colors text-sm`},[...v[10]||=[S(`span`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z`})]),y(` Full Backup `)],-1)]])])),o.value?(w(),C(`div`,Hs,[S(`div`,Us,[v[14]||=S(`svg`,{class:`w-5 h-5 text-red-600 dark:text-red-400 shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,Ws,[v[13]||=S(`h4`,{class:`text-sm font-semibold text-red-700 dark:text-red-400`},` Confirm Full Backup `,-1),S(`p`,Gs,[v[11]||=y(` This will export `,-1),v[12]||=S(`strong`,null,`all secrets in plain text`,-1),y(` including admin/guest passwords, JWT secret, and your repeater's private identity key`+b(t.value?` over an unencrypted HTTP connection`:``)+`. `,1)]),S(`div`,Ks,[S(`button`,{onClick:u,disabled:s.value,class:`px-4 py-2 bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 text-white rounded-lg transition-colors text-sm disabled:opacity-50`},b(s.value?`Exporting…`:`Yes, Export Full Backup`),9,qs),S(`button`,{onClick:v[1]||=e=>o.value=!1,disabled:s.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors text-sm`},` Cancel `,8,Js)])])])])):g(``,!0),c.value?(w(),C(`p`,Ys,b(c.value),1)):g(``,!0),l.value?(w(),C(`p`,Xs,b(l.value),1)):g(``,!0)]),S(`div`,Zs,[v[29]||=S(`div`,{class:`flex items-start justify-between mb-4`},[S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Import Configuration `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},[y(` Restore configuration from a previously exported JSON file. Importing a `),S(`strong`,null,`full backup`),y(` will also restore passwords and identity keys. Importing a `),S(`strong`,null,`settings export`),y(` will only update non-sensitive settings. `)])])],-1),S(`div`,Qs,[S(`label`,$s,[v[16]||=S(`svg`,{class:`w-5 h-5 text-content-secondary dark:text-content-muted`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12`})],-1),S(`span`,ec,b(f.value?f.value.name:`Choose a config JSON file…`),1),S(`input`,{ref_key:`fileInputRef`,ref:D,type:`file`,accept:`.json,application/json`,class:`hidden`,onChange:j},null,544)]),p.value?(w(),C(`div`,tc,[v[20]||=S(`h4`,{class:`text-sm font-medium text-content-primary dark:text-content-primary mb-2`},` Import Preview `,-1),p.value.meta?(w(),C(`div`,nc,[S(`p`,null,[v[17]||=y(` Exported: `,-1),S(`span`,rc,b(p.value.meta.exported_at),1)]),S(`p`,null,[v[18]||=y(` Version: `,-1),S(`span`,ic,b(p.value.meta.version),1)]),p.value.meta.includes_secrets===`true`||p.value.meta.includes_secrets===!0?(w(),C(`p`,ac,` ⚠ Full backup — will restore passwords and identity keys `)):(w(),C(`p`,oc,` Settings only — existing secrets will not be changed `))])):g(``,!0),S(`p`,sc,[v[19]||=y(` Sections: `,-1),S(`span`,cc,b(O.value),1)])])):g(``,!0),p.value&&!m.value?(w(),C(`div`,lc,[S(`button`,{onClick:v[2]||=e=>m.value=!0,class:`px-4 py-2 bg-amber-500/20 dark:bg-amber-400/20 hover:bg-amber-500/30 dark:hover:bg-amber-400/30 text-amber-900 dark:text-amber-200 rounded-lg border border-amber-500/50 dark:border-amber-400/40 transition-colors text-sm`},` Review & Import `)])):g(``,!0),m.value?(w(),C(`div`,uc,[S(`div`,dc,[v[28]||=S(`svg`,{class:`w-5 h-5 text-amber-600 dark:text-amber-400 shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,fc,[v[27]||=S(`h4`,{class:`text-sm font-semibold text-amber-800 dark:text-amber-300`},` Confirm Import `,-1),S(`p`,pc,[v[24]||=y(` This will overwrite current settings for: `,-1),S(`strong`,null,b(O.value),1),v[25]||=y(`. `,-1),k.value?(w(),C(x,{key:0},[v[21]||=y(` This is a full backup — `,-1),v[22]||=S(`strong`,null,`passwords, JWT secrets, and identity keys will also be overwritten`,-1),v[23]||=y(`. `,-1)],64)):(w(),C(x,{key:1},[y(` Passwords and identity keys will not be changed. `)],64)),v[26]||=y(` Some changes (radio settings) require a service restart. `,-1)]),S(`div`,mc,[S(`button`,{onClick:N,disabled:h.value,class:`px-4 py-2 bg-amber-600 hover:bg-amber-700 dark:bg-amber-500 dark:hover:bg-amber-600 text-white rounded-lg transition-colors text-sm disabled:opacity-50`},b(h.value?`Importing…`:`Yes, Import`),9,hc),S(`button`,{onClick:M,disabled:h.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors text-sm`},` Cancel `,8,gc)])])])])):g(``,!0),_.value?(w(),C(`p`,_c,b(_.value),1)):g(``,!0),T.value?(w(),C(`p`,vc,b(T.value),1)):g(``,!0)])]),S(`div`,yc,[v[38]||=d(` Export Identity Key Download the repeater's private identity key for backup. This key determines the node's address and cryptographic identity on the mesh.
Sensitive data. The identity key is the repeater's private key. Anyone with this key can impersonate your node. Store the exported file securely and never share it.
`,2),P.value?g(``,!0):(w(),C(`div`,bc,[S(`button`,{onClick:v[3]||=e=>P.value=!0,class:`px-4 py-2 bg-red-500/20 dark:bg-red-400/20 hover:bg-red-500/30 dark:hover:bg-red-400/30 text-red-900 dark:text-red-200 rounded-lg border border-red-500/50 dark:border-red-400/40 transition-colors text-sm`},[...v[30]||=[S(`span`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`})]),y(` Export Identity Key `)],-1)]])])),P.value&&!I.value?(w(),C(`div`,xc,[S(`div`,Sc,[v[32]||=S(`svg`,{class:`w-5 h-5 text-red-600 dark:text-red-400 shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,Cc,[v[31]||=S(`h4`,{class:`text-sm font-semibold text-red-700 dark:text-red-400`},`Are you sure?`,-1),S(`p`,wc,` This will transmit your private key `+b(t.value?`over an unencrypted HTTP connection. `:``)+` and download it as a file. `,1),S(`div`,Tc,[S(`button`,{onClick:R,disabled:F.value,class:`px-4 py-2 bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 text-white rounded-lg transition-colors text-sm disabled:opacity-50`},b(F.value?`Exporting…`:`Yes, Export Key`),9,Ec),S(`button`,{onClick:v[4]||=e=>P.value=!1,disabled:F.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors text-sm`},` Cancel `,8,Dc)])])])])):g(``,!0),I.value?(w(),C(`div`,Oc,[S(`div`,kc,[v[33]||=S(`h4`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},` Key Exported `,-1),S(`button`,{onClick:v[5]||=e=>{I.value=null,P.value=!1},class:`text-xs text-content-muted hover:text-content-secondary transition-colors`},` Dismiss `)]),S(`div`,Ac,[S(`p`,null,[v[34]||=y(` Key length: `,-1),S(`span`,jc,b(I.value.key_length_bytes)+` bytes`,1)]),I.value.node_address?(w(),C(`p`,Mc,[v[35]||=y(` Node address: `,-1),S(`span`,Nc,b(I.value.node_address),1)])):g(``,!0),I.value.public_key_hex?(w(),C(`p`,Pc,[v[36]||=y(` Public key: `,-1),S(`span`,Fc,b(I.value.public_key_hex),1)])):g(``,!0)]),v[37]||=S(`p`,{class:`text-xs text-green-600 dark:text-green-400`},`File downloaded successfully.`,-1)])):g(``,!0),L.value?(w(),C(`p`,Ic,b(L.value),1)):g(``,!0)])]))}}),Rc={class:`space-y-6`},zc={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Bc={class:`flex items-start justify-between mb-4`},Vc=[`disabled`],Hc={key:0,class:`flex items-center gap-1.5`},Uc={key:1},Wc={key:0,class:`grid grid-cols-2 sm:grid-cols-4 gap-3 mb-6`},Gc={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},Kc={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},qc={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},Jc={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},Yc={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},Xc={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},Zc={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},Qc={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},$c={key:1,class:`flex items-center justify-center py-12`},el={key:2,class:`rounded-lg border border-red-500/30 dark:border-red-400/30 bg-red-50 dark:bg-red-500/10 p-3 mb-4`},tl={class:`text-xs text-red-700 dark:text-red-400`},nl={key:3},rl={class:`overflow-x-auto`},il={class:`w-full text-sm`},al={class:`py-2.5 pr-4`},ol={class:`font-mono text-content-primary dark:text-content-primary`},sl={class:`py-2.5 pr-4 text-right`},cl={class:`font-mono text-content-secondary dark:text-content-muted`},ll={class:`py-2.5 pr-4 text-right hidden sm:table-cell`},ul={key:0,class:`text-xs text-content-muted`},dl={class:`text-content-muted/60 ml-1`},fl={key:1,class:`text-xs text-content-muted/50`},pl={key:2,class:`text-xs text-content-muted/50`},ml={class:`py-2.5 text-right`},hl=[`onClick`,`disabled`],gl={key:0,class:`flex items-center gap-1`},_l={key:1},vl={key:1,class:`text-xs text-content-muted/50`},yl={key:0,class:`glass-card rounded-lg border-2 border-red-500/50 dark:border-red-400/40 bg-red-50 dark:bg-red-500/10 p-6`},bl={class:`flex items-start gap-3`},xl={class:`flex-1`},Sl={class:`text-sm font-semibold text-red-700 dark:text-red-400`},Cl={class:`text-xs text-red-600 dark:text-red-400/80 mt-1`},wl={class:`flex gap-2 mt-3`},Tl=[`disabled`],El=[`disabled`],Dl={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Ol={class:`flex flex-wrap gap-3`},kl=[`disabled`],Al=[`disabled`],jl={class:`flex items-center gap-2`},Ml={key:0,class:`text-xs text-green-600 dark:text-green-400 mt-3`},Nl={key:1,class:`text-xs text-green-600 dark:text-green-400 mt-3`},Pl=f({__name:`DatabaseManagement`,setup(e){let t=new Set([`packets`,`adverts`,`noise_floor`,`crc_errors`,`room_messages`,`room_client_sync`,`companion_contacts`,`companion_channels`,`companion_messages`,`companion_prefs`]),n=E(!1),r=E(``),a=E(null),o=E({}),c=E(null),l=E(``),u=E(!1),d=E(``),f=v(()=>a.value?a.value.tables.reduce((e,t)=>e+t.row_count,0):0);function p(e){return t.has(e)}function m(e){if(e===0)return`0 B`;let t=[`B`,`KB`,`MB`,`GB`],n=Math.min(Math.floor(Math.log(e)/Math.log(1024)),t.length-1),r=e/1024**n;return`${r<10?r.toFixed(1):Math.round(r)} ${t[n]}`}function h(e){return e?new Date(e*1e3).toLocaleDateString(void 0,{month:`short`,day:`numeric`,year:`numeric`}):`—`}function _(e,t){return!e||!t?0:Math.max(1,Math.round((t-e)/86400))}async function T(){n.value=!0,r.value=``;try{let e=await A.getDbStats();e.success&&e.data?a.value=e.data:r.value=e.error||`Failed to load database stats`}catch(e){r.value=e instanceof Error?e.message:`Failed to load database stats`}finally{n.value=!1}}function D(e,t){l.value=``,c.value={table:e,rowCount:t,executing:!1}}async function O(){if(!c.value)return;let{table:e}=c.value;c.value.executing=!0,l.value=``;try{let t=e===`all`?`all`:[e];e!==`all`&&(o.value[e]=!0);let n=await A.purgeTable(t);if(n.success){let t=n.data||{};l.value=`Deleted ${Object.values(t).reduce((e,t)=>e+(t.deleted||0),0).toLocaleString()} rows${e===`all`?` from all tables`:` from ${e}`}.`,c.value=null,await T()}else r.value=n.error||`Purge failed`,c.value=null}catch(e){r.value=e instanceof Error?e.message:`Purge failed`,c.value=null}finally{e!==`all`&&(o.value[e]=!1)}}async function k(){u.value=!0,d.value=``,r.value=``;try{let e=await A.vacuumDb();if(e.success&&e.data){let t=e.data.freed_bytes;d.value=t>0?`Compacted database — freed ${m(t)} (${m(e.data.size_before)} → ${m(e.data.size_after)}).`:`Database already compact (${m(e.data.size_after)}).`,await T()}else r.value=e.error||`Vacuum failed`}catch(e){r.value=e instanceof Error?e.message:`Vacuum failed`}finally{u.value=!1}}return s(T),(e,t)=>(w(),C(`div`,Rc,[S(`div`,zc,[S(`div`,Bc,[t[3]||=S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Database Overview `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Storage usage and table statistics for the repeater database. `)],-1),S(`button`,{onClick:T,disabled:n.value,class:`px-3 py-1.5 bg-cyan-500/20 dark:bg-primary/20 hover:bg-cyan-500/30 dark:hover:bg-primary/30 text-cyan-900 dark:text-white rounded-lg border border-cyan-500/50 dark:border-primary/50 transition-colors text-sm disabled:opacity-50`},[n.value?(w(),C(`span`,Hc,[...t[2]||=[S(`span`,{class:`animate-spin w-3.5 h-3.5 border-2 border-current border-t-transparent rounded-full inline-block`},null,-1),y(` Loading… `,-1)]])):(w(),C(`span`,Uc,`Refresh`))],8,Vc)]),a.value?(w(),C(`div`,Wc,[S(`div`,Gc,[t[4]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Database Size`,-1),S(`p`,Kc,b(m(a.value.database_size_bytes)),1)]),S(`div`,qc,[t[5]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`RRD Metrics`,-1),S(`p`,Jc,b(m(a.value.rrd_size_bytes)),1)]),S(`div`,Yc,[t[6]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Total Size`,-1),S(`p`,Xc,b(m(a.value.database_size_bytes+a.value.rrd_size_bytes)),1)]),S(`div`,Zc,[t[7]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Total Rows`,-1),S(`p`,Qc,b(f.value.toLocaleString()),1)])])):g(``,!0),n.value&&!a.value?(w(),C(`div`,$c,[...t[8]||=[S(`div`,{class:`text-center`},[S(`div`,{class:`animate-spin w-8 h-8 border-2 border-stroke-subtle dark:border-stroke/20 border-t-cyan-500 dark:border-t-primary rounded-full mx-auto mb-4`}),S(`div`,{class:`text-content-secondary dark:text-content-muted`},`Loading database info…`)],-1)]])):g(``,!0),r.value?(w(),C(`div`,el,[S(`p`,tl,b(r.value),1)])):g(``,!0),a.value&&a.value.tables.length>0?(w(),C(`div`,nl,[S(`div`,rl,[S(`table`,il,[t[10]||=S(`thead`,null,[S(`tr`,{class:`border-b border-stroke-subtle dark:border-stroke/10`},[S(`th`,{class:`text-left py-2 pr-4 text-xs font-medium text-content-muted uppercase tracking-wider`},` Table `),S(`th`,{class:`text-right py-2 pr-4 text-xs font-medium text-content-muted uppercase tracking-wider`},` Rows `),S(`th`,{class:`text-right py-2 pr-4 text-xs font-medium text-content-muted uppercase tracking-wider hidden sm:table-cell`},` Date Range `),S(`th`,{class:`text-right py-2 text-xs font-medium text-content-muted uppercase tracking-wider`},` Actions `)])],-1),S(`tbody`,null,[(w(!0),C(x,null,i(a.value.tables,e=>(w(),C(`tr`,{key:e.name,class:`border-b border-stroke-subtle/50 dark:border-stroke/5`},[S(`td`,al,[S(`span`,ol,b(e.name),1)]),S(`td`,sl,[S(`span`,cl,b(e.row_count.toLocaleString()),1)]),S(`td`,ll,[e.has_timestamp&&e.row_count>0?(w(),C(`span`,ul,[y(b(h(e.oldest_timestamp))+` — `+b(h(e.newest_timestamp))+` `,1),S(`span`,dl,`(`+b(_(e.oldest_timestamp,e.newest_timestamp))+`d)`,1)])):e.row_count===0?(w(),C(`span`,fl,`—`)):(w(),C(`span`,pl,`n/a`))]),S(`td`,ml,[p(e.name)&&e.row_count>0?(w(),C(`button`,{key:0,onClick:t=>D(e.name,e.row_count),disabled:o.value[e.name],class:`px-2.5 py-1 bg-red-500/10 dark:bg-red-400/10 hover:bg-red-500/20 dark:hover:bg-red-400/20 text-red-700 dark:text-red-400 rounded border border-red-500/30 dark:border-red-400/20 transition-colors text-xs disabled:opacity-50`},[o.value[e.name]?(w(),C(`span`,gl,[...t[9]||=[S(`span`,{class:`animate-spin w-3 h-3 border border-current border-t-transparent rounded-full inline-block`},null,-1),y(` Purging… `,-1)]])):(w(),C(`span`,_l,`Empty`))],8,hl)):p(e.name)?g(``,!0):(w(),C(`span`,vl,`—`))])]))),128))])])])])):g(``,!0)]),c.value?(w(),C(`div`,yl,[S(`div`,bl,[t[16]||=S(`svg`,{class:`w-5 h-5 text-red-600 dark:text-red-400 shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,xl,[S(`h4`,Sl,b(c.value.table===`all`?`Confirm Purge All Tables`:`Confirm Purge "${c.value.table}"`),1),S(`p`,Cl,[c.value.table===`all`?(w(),C(x,{key:0},[t[11]||=y(` This will permanently delete `,-1),t[12]||=S(`strong`,null,`all data`,-1),y(` from every data table (`+b(f.value.toLocaleString())+` rows total). This cannot be undone. `,1)],64)):(w(),C(x,{key:1},[t[13]||=y(` This will permanently delete `,-1),S(`strong`,null,b(c.value.rowCount.toLocaleString())+` rows`,1),t[14]||=y(` from `,-1),S(`strong`,null,b(c.value.table),1),t[15]||=y(`. This cannot be undone. `,-1)],64))]),S(`div`,wl,[S(`button`,{onClick:O,disabled:c.value.executing,class:`px-4 py-2 bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 text-white rounded-lg transition-colors text-sm disabled:opacity-50`},b(c.value.executing?`Purging…`:`Yes, Delete Data`),9,Tl),S(`button`,{onClick:t[0]||=e=>c.value=null,disabled:c.value.executing,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors text-sm`},` Cancel `,8,El)])])])])):g(``,!0),S(`div`,Dl,[t[19]||=S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-4`},` Maintenance `,-1),S(`div`,Ol,[S(`button`,{onClick:t[1]||=e=>D(`all`,f.value),disabled:!a.value||f.value===0,class:`px-4 py-2 bg-red-500/20 dark:bg-red-400/20 hover:bg-red-500/30 dark:hover:bg-red-400/30 text-red-900 dark:text-red-200 rounded-lg border border-red-500/50 dark:border-red-400/40 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},[...t[17]||=[S(`span`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16`})]),y(` Purge All Data `)],-1)]],8,kl),S(`button`,{onClick:k,disabled:u.value||!a.value,class:`px-4 py-2 bg-amber-500/20 dark:bg-amber-400/20 hover:bg-amber-500/30 dark:hover:bg-amber-400/30 text-amber-900 dark:text-amber-200 rounded-lg border border-amber-500/50 dark:border-amber-400/40 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},[S(`span`,jl,[t[18]||=S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15`})],-1),y(` `+b(u.value?`Compacting…`:`Compact Database`),1)])],8,Al)]),d.value?(w(),C(`p`,Ml,b(d.value),1)):g(``,!0),l.value?(w(),C(`p`,Nl,b(l.value),1)):g(``,!0)])]))}}),Fl={class:`space-y-6`},Il={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Ll={class:`flex items-start justify-between mb-4`},Rl={class:`flex items-center gap-2`},zl=[`disabled`],Bl={key:0,class:`flex items-center gap-1.5`},Vl={key:1},Hl=[`disabled`],Ul={key:0,class:`flex items-center gap-1.5`},Wl={key:1},Gl={key:0,class:`mb-4 p-3 rounded-lg bg-red-500/10 border border-red-500/30 text-red-600 dark:text-red-400 text-sm`},Kl={key:1,class:`mb-4`},ql={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10 inline-block`},Jl={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},Yl={key:2,class:`p-4 rounded-lg bg-cyan-500/10 dark:bg-primary/10 border border-cyan-400/30 dark:border-primary/30`},Xl={key:3},Zl=[`innerHTML`],Ql={class:`font-semibold text-sm`},$l={class:`text-sm mt-0.5 opacity-80`},eu={class:`grid grid-cols-2 sm:grid-cols-3 gap-3 mb-6`},tu={key:0,class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},nu={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},ru={key:1,class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},iu={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},au={key:2,class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},ou={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},su={key:0,class:`mb-6`},cu={class:`space-y-2`},lu={class:`flex items-start justify-between gap-3`},uu={class:`flex items-center gap-2 min-w-0`},du={class:`shrink-0 text-xs font-medium text-content-muted w-5 text-right`},fu={class:`text-right shrink-0`},pu={class:`text-xs text-content-muted`},mu={class:`mt-1.5 ml-7`},hu={class:`text-xs font-mono text-content-secondary dark:text-content-muted break-all`},gu={key:0,class:`text-xs text-content-muted mt-0.5`},_u={key:1,class:`mb-6 p-4 rounded-lg bg-green-500/10 border border-green-500/30 text-sm flex items-center gap-3`},vu={key:2},yu={key:0,class:`overflow-x-auto rounded-lg border border-stroke-subtle dark:border-stroke/10`},bu={class:`w-full text-sm`},xu={class:`px-3 py-2 text-content-muted font-mono text-xs`},Su={class:`px-3 py-2 text-content-primary dark:text-content-primary font-mono text-xs break-all`},Cu={class:`px-3 py-2 text-right font-mono text-xs text-content-secondary dark:text-content-muted whitespace-nowrap`},wu={class:`px-3 py-2 text-right font-mono text-xs text-content-secondary dark:text-content-muted`},Tu={key:4,class:`py-8 text-center text-content-muted text-sm`},Eu=M(f({__name:`MemoryDebug`,setup(e){let n=E(!1),r=E(!1),a=E(``),o=E(null),c=E(!1),l=E(null),f=E(!1),p=v(()=>o.value&&(o.value.current_top_20||o.value.growth_since_baseline));async function m(){n.value=!0,a.value=``;try{let e=await A.get(`memory_debug`);e.success&&e.data?(c.value=!!e.data.tracing,l.value=e.data.rss_mb??null,(e.data.current_top_20||e.data.growth_since_baseline)&&(o.value=e.data)):a.value=e.error||`Failed to fetch memory status`}catch(e){a.value=e instanceof Error?e.message:`Failed to fetch memory status`}finally{n.value=!1}}async function h(){r.value=!0,a.value=``;let e=c.value?`stop`:`start`;try{let t=await A.post(`memory_debug`,{action:e});t.success&&t.data?(c.value=!!t.data.tracing,e===`stop`&&(o.value=null,l.value=null)):a.value=t.error||`Failed to ${e} tracing`}catch(t){a.value=t instanceof Error?t.message:`Failed to ${e} tracing`}finally{r.value=!1,c.value&&await m()}}function T(e){return e.size_diff_kb>=100?`critical`:e.size_diff_kb>=10?`warning`:e.size_diff_kb>=1?`low`:`ok`}function D(e){let t=T(e);return t===`critical`?`Investigate`:t===`warning`?`Watch`:t===`low`?`Minor`:`Normal`}function O(e){let t=T(e);return t===`critical`?`bg-red-500/20 text-red-700 dark:text-red-400 border border-red-500/30`:t===`warning`?`bg-amber-500/20 text-amber-700 dark:text-amber-400 border border-amber-500/30`:t===`low`?`bg-blue-500/15 text-blue-600 dark:text-blue-400 border border-blue-500/20`:`bg-green-500/15 text-green-700 dark:text-green-400 border border-green-500/20`}function k(e){let t=T(e);return t===`critical`?`border-red-500/40 dark:border-red-500/30 bg-red-500/5 dark:bg-red-500/5`:t===`warning`?`border-amber-500/40 dark:border-amber-500/30 bg-amber-500/5 dark:bg-amber-500/5`:t===`low`?`border-stroke-subtle dark:border-stroke/10 bg-background-mute/50 dark:bg-background/20`:`border-stroke-subtle/50 dark:border-stroke/5 bg-background-mute/30 dark:bg-background/10 opacity-60`}function j(e){let t=T(e);return t===`critical`?`text-red-600 dark:text-red-400`:t===`warning`?`text-amber-600 dark:text-amber-400`:t===`low`?`text-blue-600 dark:text-blue-400`:`text-green-600 dark:text-green-500`}function M(e){return e>=1024?`${(e/1024).toFixed(1)} MB`:e>=10?`${Math.round(e)} KB`:`${e.toFixed(1)} KB`}function P(e){return e.replace(/.*\/site-packages\//,``).replace(/.*\/lib\/python[^/]*\//,``).replace(/.*\/repeater\//,`repeater/`)}let F=v(()=>o.value?.growth_since_baseline?o.value.growth_since_baseline.reduce((e,t)=>e+t.size_diff_kb,0):0),I=v(()=>F.value>=500?`critical`:F.value>=50?`warning`:F.value>=5?`low`:`ok`),L=v(()=>{let e=I.value;return e===`critical`?`border-red-500/40 dark:border-red-500/30 bg-red-500/10 dark:bg-red-500/10 text-red-800 dark:text-red-300`:e===`warning`?`border-amber-500/40 dark:border-amber-500/30 bg-amber-500/10 dark:bg-amber-500/10 text-amber-800 dark:text-amber-300`:e===`low`?`border-blue-500/30 bg-blue-500/10 dark:bg-blue-500/10 text-blue-800 dark:text-blue-300`:`border-green-500/30 bg-green-500/10 dark:bg-green-500/10 text-green-800 dark:text-green-300`}),R=v(()=>{let e=I.value;return e===`critical`?` `:e===`warning`?` `:e===`low`?` `:` `}),z=v(()=>{let e=I.value;return e===`critical`?`Significant memory growth detected`:e===`warning`?`Some memory growth detected`:e===`low`?`Minor memory growth — likely normal`:`Memory looks healthy`}),B=v(()=>{let e=M(F.value),t=I.value;return t===`critical`?`Total growth: ${e}. Red items below need attention.`:t===`warning`?`Total growth: ${e}. Orange items below may need attention over time.`:t===`low`?`Total growth: ${e}. Nothing to worry about right now.`:`No significant growth since tracing started.`});return s(m),(e,s)=>(w(),C(`div`,Fl,[S(`div`,Il,[S(`div`,Ll,[s[3]||=S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Memory Diagnostics `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Trace memory allocations to find leaks. Tracing adds overhead — only enable when needed. `)],-1),S(`div`,Rl,[c.value&&p.value?(w(),C(`button`,{key:0,onClick:m,disabled:n.value,class:`px-3 py-1.5 bg-cyan-500/20 dark:bg-primary/20 hover:bg-cyan-500/30 dark:hover:bg-primary/30 text-cyan-900 dark:text-white rounded-lg border border-cyan-500/50 dark:border-primary/50 transition-colors text-sm disabled:opacity-50`},[n.value?(w(),C(`span`,Bl,[...s[1]||=[S(`span`,{class:`animate-spin w-3.5 h-3.5 border-2 border-current border-t-transparent rounded-full inline-block`},null,-1),y(` Checking… `,-1)]])):(w(),C(`span`,Vl,`Check Again`))],8,zl)):g(``,!0),S(`button`,{onClick:h,disabled:r.value,class:u([`px-3 py-1.5 rounded-lg border text-sm transition-colors disabled:opacity-50`,c.value?`bg-red-500/20 hover:bg-red-500/30 text-red-700 dark:text-red-400 border-red-500/50`:`bg-green-500/20 hover:bg-green-500/30 text-green-700 dark:text-green-400 border-green-500/50`])},[r.value?(w(),C(`span`,Ul,[s[2]||=S(`span`,{class:`animate-spin w-3.5 h-3.5 border-2 border-current border-t-transparent rounded-full inline-block`},null,-1),y(` `+b(c.value?`Stopping…`:`Starting…`),1)])):(w(),C(`span`,Wl,b(c.value?`Stop Tracing`:`Start Tracing`),1))],10,Hl)])]),a.value?(w(),C(`div`,Gl,b(a.value),1)):g(``,!0),!c.value&&l.value!==null&&!n.value?(w(),C(`div`,Kl,[S(`div`,ql,[s[4]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Current Memory (RSS)`,-1),S(`p`,Jl,b(l.value)+` MB`,1)])])):g(``,!0),c.value&&!p.value&&!n.value?(w(),C(`div`,Yl,[...s[5]||=[d(` Memory tracing is running. Let the repeater run for a few minutes, then click Check Again to see which parts of the code are using more memory.
`,2)]])):g(``,!0),o.value&&p.value?(w(),C(`div`,Xl,[S(`div`,{class:u([`mb-5 p-4 rounded-lg border flex items-start gap-3`,L.value])},[S(`div`,{class:`mt-0.5`,innerHTML:R.value},null,8,Zl),S(`div`,null,[S(`p`,Ql,b(z.value),1),S(`p`,$l,b(B.value),1)])],2),S(`div`,eu,[o.value.rss_mb===void 0?g(``,!0):(w(),C(`div`,tu,[s[6]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Total Memory Used`,-1),S(`p`,nu,b(o.value.rss_mb)+` MB`,1)])),o.value.traced_current_mb===void 0?g(``,!0):(w(),C(`div`,ru,[s[7]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Tracked Now`,-1),S(`p`,iu,b(o.value.traced_current_mb)+` MB`,1)])),o.value.traced_peak_mb===void 0?g(``,!0):(w(),C(`div`,au,[s[8]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Peak Tracked`,-1),S(`p`,ou,b(o.value.traced_peak_mb)+` MB`,1)]))]),o.value.growth_since_baseline&&o.value.growth_since_baseline.length>0?(w(),C(`div`,su,[s[9]||=S(`h4`,{class:`text-sm font-semibold text-content-primary dark:text-content-primary mb-1`},`Memory Growth Breakdown`,-1),s[10]||=S(`p`,{class:`text-xs text-content-muted mb-3`},` Items at the top with red/orange tags are the most likely cause of memory issues. Green items are normal and can be ignored. `,-1),S(`div`,cu,[(w(!0),C(x,null,i(o.value.growth_since_baseline,(e,t)=>(w(),C(`div`,{key:t,class:u([`rounded-lg border p-3 transition-colors`,k(e)])},[S(`div`,lu,[S(`div`,uu,[S(`span`,du,b(t+1),1),S(`span`,{class:u([`shrink-0 inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-semibold`,O(e)])},b(D(e)),3)]),S(`div`,fu,[S(`span`,{class:u([`font-mono text-sm font-semibold`,j(e)])},`+`+b(M(e.size_diff_kb)),3),S(`p`,pu,b(M(e.current_size_kb))+` total`,1)])]),S(`div`,mu,[S(`p`,hu,b(P(e.file)),1),e.count_diff===0?g(``,!0):(w(),C(`p`,gu,b(e.count_diff>0?`+`:``)+b(e.count_diff)+` new allocation`+b(Math.abs(e.count_diff)===1?``:`s`),1))])],2))),128))])])):o.value.growth_since_baseline&&o.value.growth_since_baseline.length===0?(w(),C(`div`,_u,[...s[11]||=[S(`svg`,{class:`w-5 h-5 text-green-600 dark:text-green-400 shrink-0`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),S(`span`,{class:`text-green-700 dark:text-green-400`},`No memory growth detected. Everything looks healthy.`,-1)]])):g(``,!0),o.value.current_top_20&&o.value.current_top_20.length>0?(w(),C(`div`,vu,[S(`button`,{onClick:s[0]||=e=>f.value=!f.value,class:`flex items-center gap-2 text-sm font-semibold text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary transition-colors mb-3`},[(w(),C(`svg`,{class:u([`w-4 h-4 transition-transform`,{"rotate-90":f.value}]),fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[...s[12]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 5l7 7-7 7`},null,-1)]],2)),s[13]||=y(` Advanced: Current Top Allocations `,-1)]),_(N,{name:`expand`},{default:t(()=>[f.value?(w(),C(`div`,yu,[S(`table`,bu,[s[14]||=S(`thead`,null,[S(`tr`,{class:`bg-background-mute dark:bg-background/30 text-left`},[S(`th`,{class:`px-3 py-2 text-xs font-medium text-content-muted`},`#`),S(`th`,{class:`px-3 py-2 text-xs font-medium text-content-muted`},`Location`),S(`th`,{class:`px-3 py-2 text-xs font-medium text-content-muted text-right`},`Size`),S(`th`,{class:`px-3 py-2 text-xs font-medium text-content-muted text-right`},`Count`)])],-1),S(`tbody`,null,[(w(!0),C(x,null,i(o.value.current_top_20,(e,t)=>(w(),C(`tr`,{key:t,class:`border-t border-stroke-subtle/50 dark:border-stroke/5 hover:bg-background-mute/50 dark:hover:bg-background/20 transition-colors`},[S(`td`,xu,b(t+1),1),S(`td`,Su,b(P(e.file)),1),S(`td`,Cu,b(M(e.size_kb)),1),S(`td`,wu,b(e.count),1)]))),128))])])])):g(``,!0)]),_:1})])):g(``,!0)])):g(``,!0),!n.value&&!r.value&&!c.value&&!p.value&&!a.value&&l.value===null?(w(),C(`div`,Tu,[...s[15]||=[y(` Click `,-1),S(`strong`,null,`Start Tracing`,-1),y(` to enable memory diagnostics. `,-1),S(`br`,null,null,-1),S(`span`,{class:`text-xs`},`Tracing uses extra memory — remember to stop it when done.`,-1)]])):g(``,!0)])]))}}),[[`__scopeId`,`data-v-50d93367`]]),Du={class:`p-3 sm:p-6 space-y-4 sm:space-y-6`},Ou={class:`glass-card rounded-[15px] z-10 p-3 sm:p-4 border border-cyan-400 dark:border-primary/30 bg-cyan-500/10 dark:bg-primary/10`},ku={class:`text-cyan-700 dark:text-primary text-sm sm:text-base`},Au={class:`mt-1 sm:mt-2 text-cyan-600 dark:text-primary/80`},ju={class:`glass-card rounded-[15px] p-3 sm:p-6`},Mu={class:`relative -mx-3 sm:mx-0 mb-4 sm:mb-6`},Nu={key:0,class:`absolute left-0 top-0 bottom-[1px] w-12 z-10 flex items-center`},Pu={key:0,class:`absolute right-0 top-0 bottom-[1px] w-12 z-10 flex items-center justify-end`},Fu=[`onClick`],Iu={class:`flex items-center gap-1 sm:gap-2`},Lu={key:0,class:`w-3.5 h-3.5 sm:w-4 sm:h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Ru={key:1,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},zu={key:2,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Bu={key:3,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Vu={key:4,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Hu={key:5,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Uu={key:6,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Wu={key:7,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Gu={key:8,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Ku={key:9,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},qu={key:10,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Ju={key:11,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Yu={class:`min-h-[400px]`},Xu={key:0,class:`flex items-center justify-center py-12`},Zu={key:1,class:`flex items-center justify-center py-12`},Qu={class:`text-center`},$u={class:`text-content-secondary dark:text-content-muted text-sm mb-4`},ed={key:2},td=M(f({name:`ConfigurationView`,__name:`Configuration`,setup(e){let n=j(),o=E(H(`configuration_activeTab`,`radio`)),l=E(!1),d=E(null),f=E(!1),p=E(!1);function v(){if(!d.value)return;let e=d.value;p.value=e.scrollLeft>4,f.value=e.scrollLeftee(`configuration_activeTab`,e));let D=[{id:`radio`,label:`Radio Settings`,icon:`radio`},{id:`repeater`,label:`Repeater Settings`,icon:`repeater`},{id:`advert`,label:`Advert Limits`,icon:`advert`},{id:`duty`,label:`Duty Cycle`,icon:`duty`},{id:`delays`,label:`TX Delays`,icon:`delays`},{id:`transport`,label:`Regions/Keys`,icon:`keys`},{id:`api-tokens`,label:`API Tokens`,icon:`tokens`},{id:`web`,label:`Web Options`,icon:`web`},{id:`observer`,label:`Observer`,icon:`observer`},{id:`backup`,label:`Backup`,icon:`backup`},{id:`database`,label:`Database`,icon:`database`},{id:`memory`,label:`Memory`,icon:`memory`}];s(async()=>{try{await n.fetchStats(),l.value=!0}catch(e){console.error(`Failed to load configuration data:`,e),l.value=!0}c(()=>v())});function O(e){o.value=e}return(e,s)=>{let c=r(`router-link`);return w(),C(`div`,Du,[s[24]||=S(`div`,null,[S(`h1`,{class:`text-xl sm:text-2xl font-bold text-content-primary dark:text-content-primary`},` Configuration `),S(`p`,{class:`text-content-secondary dark:text-content-muted mt-1 sm:mt-2 text-sm sm:text-base`},` System configuration and settings `)],-1),S(`div`,Ou,[S(`div`,ku,[s[5]||=S(`strong`,null,`CAD Calibration Tool Available`,-1),S(`p`,Au,[s[4]||=y(` Optimize your Channel Activity Detection settings. `,-1),_(c,{to:`/cad-calibration`,class:`underline hover:text-cyan-800 dark:hover:text-primary transition-colors`},{default:t(()=>[...s[3]||=[y(` Launch CAD Calibration Tool → `,-1)]]),_:1})])])]),S(`div`,ju,[S(`div`,Mu,[_(N,{name:`tab-fade`},{default:t(()=>[p.value?(w(),C(`div`,Nu,[s[7]||=S(`div`,{class:`tab-fade-left absolute inset-0 pointer-events-none`},null,-1),S(`button`,{onClick:s[0]||=e=>T(`left`),class:`relative z-10 ml-1.5 w-6 h-6 flex items-center justify-center rounded-full bg-white dark:bg-zinc-900 shadow-md border border-gray-200 dark:border-white/10 text-gray-500 dark:text-gray-300`},[...s[6]||=[S(`svg`,{class:`w-3 h-3`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2.5`,d:`M15 19l-7-7 7-7`})],-1)]])])):g(``,!0)]),_:1}),_(N,{name:`tab-fade`},{default:t(()=>[f.value?(w(),C(`div`,Pu,[s[9]||=S(`div`,{class:`tab-fade-right absolute inset-0 pointer-events-none`},null,-1),S(`button`,{onClick:s[1]||=e=>T(`right`),class:`relative z-10 mr-1.5 w-6 h-6 flex items-center justify-center rounded-full bg-white dark:bg-zinc-900 shadow-md border border-gray-200 dark:border-white/10 text-gray-500 dark:text-gray-300`},[...s[8]||=[S(`svg`,{class:`w-3 h-3`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2.5`,d:`M9 5l7 7-7 7`})],-1)]])])):g(``,!0)]),_:1}),S(`div`,{ref_key:`tabsContainer`,ref:d,onScroll:v,class:`flex overflow-x-auto border-b border-stroke-subtle dark:border-stroke/10 px-3 sm:px-0 scrollbar-hide`},[(w(),C(x,null,i(D,e=>S(`button`,{key:e.id,onClick:t=>O(e.id),class:u([`px-3 sm:px-4 py-2 text-xs sm:text-sm font-medium transition-colors duration-200 border-b-2 mr-3 sm:mr-6 whitespace-nowrap flex-shrink-0`,o.value===e.id?`text-cyan-500 dark:text-primary border-cyan-500 dark:border-primary`:`text-content-secondary dark:text-content-muted border-transparent hover:text-content-primary dark:hover:text-content-primary hover:border-stroke-subtle dark:hover:border-stroke/30`])},[S(`div`,Iu,[e.icon===`radio`?(w(),C(`svg`,Lu,[...s[10]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.822c5.716-5.716 14.976-5.716 20.692 0`},null,-1)]])):e.icon===`repeater`?(w(),C(`svg`,Ru,[...s[11]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M5 12h14M5 12l4-4m-4 4l4 4`},null,-1)]])):e.icon===`advert`?(w(),C(`svg`,zu,[...s[12]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z`},null,-1)]])):e.icon===`duty`?(w(),C(`svg`,Bu,[...s[13]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]])):e.icon===`delays`?(w(),C(`svg`,Vu,[...s[14]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z`},null,-1)]])):e.icon===`keys`?(w(),C(`svg`,Hu,[...s[15]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`},null,-1)]])):e.icon===`tokens`?(w(),C(`svg`,Uu,[...s[16]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z`},null,-1)]])):e.icon===`web`?(w(),C(`svg`,Wu,[...s[17]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9`},null,-1)]])):e.icon===`observer`?(w(),C(`svg`,Gu,[...s[18]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]])):e.icon===`backup`?(w(),C(`svg`,Ku,[...s[19]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4`},null,-1)]])):e.icon===`database`?(w(),C(`svg`,qu,[...s[20]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4`},null,-1)]])):e.icon===`memory`?(w(),C(`svg`,Ju,[...s[21]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z`},null,-1)]])):g(``,!0),y(` `+b(e.label),1)])],10,Fu)),64))],544)]),S(`div`,Yu,[!l.value&&a(n).isLoading?(w(),C(`div`,Xu,[...s[22]||=[S(`div`,{class:`text-center`},[S(`div`,{class:`animate-spin w-8 h-8 border-2 border-stroke-subtle dark:border-stroke/20 border-t-cyan-500 dark:border-t-primary rounded-full mx-auto mb-4`}),S(`div`,{class:`text-content-secondary dark:text-content-muted`},` Loading configuration... `)],-1)]])):a(n).error&&!l.value?(w(),C(`div`,Zu,[S(`div`,Qu,[s[23]||=S(`div`,{class:`text-red-500 dark:text-red-400 mb-2`},`Failed to load configuration`,-1),S(`div`,$u,b(a(n).error),1),S(`button`,{onClick:s[2]||=e=>a(n).fetchStats(),class:`px-4 py-2 bg-cyan-500/20 dark:bg-primary/20 hover:bg-cyan-500/30 dark:hover:bg-primary/30 text-cyan-900 dark:text-white rounded-lg border border-cyan-500/50 dark:border-primary/50 transition-colors`},` Retry `)])])):(w(),C(`div`,ed,[m(S(`div`,null,[_(ye,{key:`radio-settings`})],512),[[z,o.value===`radio`]]),m(S(`div`,null,[_(St,{key:`repeater-settings`})],512),[[z,o.value===`repeater`]]),m(S(`div`,null,[_(so,{key:`advert-settings`})],512),[[z,o.value===`advert`]]),m(S(`div`,null,[_(Pt,{key:`duty-cycle`})],512),[[z,o.value===`duty`]]),m(S(`div`,null,[_(Jt,{key:`transmission-delays`})],512),[[z,o.value===`delays`]]),m(S(`div`,null,[_(Jr,{key:`transport-keys`})],512),[[z,o.value===`transport`]]),m(S(`div`,null,[_(Si,{key:`api-tokens`})],512),[[z,o.value===`api-tokens`]]),m(S(`div`,null,[_(qi,{key:`web-settings`})],512),[[z,o.value===`web`]]),m(S(`div`,null,[_(js,{key:`letsmesh-settings`})],512),[[z,o.value===`observer`]]),m(S(`div`,null,[_(Lc,{key:`backup-restore`})],512),[[z,o.value===`backup`]]),m(S(`div`,null,[_(Pl,{key:`database-management`})],512),[[z,o.value===`database`]]),m(S(`div`,null,[_(Eu,{key:`memory-debug`})],512),[[z,o.value===`memory`]])]))])])])}}}),[[`__scopeId`,`data-v-e8f5e632`]]);export{td as default};
\ No newline at end of file
+import{r as e}from"./chunk-DECur_0Z.js";import{A as t,C as n,D as r,E as i,K as a,R as o,S as s,b as c,c as l,dt as u,f as d,g as f,i as p,j as m,k as h,l as g,m as _,o as v,p as y,pt as b,r as x,s as S,u as C,w,x as T,z as E}from"./runtime-core.esm-bundler-HnidnMFy.js";import{o as D}from"./vue-router-Cr0wB7EX.js";import{a as O,n as k,t as A}from"./api-BXShkfsc.js";import{t as j}from"./system-A4EFgrwh.js";import{t as M}from"./_plugin-vue_export-helper-B7aGp3iI.js";import{c as N,d as P,f as F,h as I,l as L,m as R,p as z,u as B}from"./index-C6ELfnbI.js";import{t as V}from"./ConfirmDialog-COAlYCXc.js";/* empty css */import{n as ee,t as H}from"./preferences-Bv8i60GL.js";var U={class:`space-y-4`},W={key:0,class:`bg-green-100 dark:bg-green-500/20 border border-green-500/50 rounded-lg p-3`},G={class:`text-green-600 dark:text-green-400 text-sm`},te={key:1,class:`bg-red-100 dark:bg-red-500/20 border border-red-500/50 rounded-lg p-3`},K={class:`text-red-600 dark:text-red-400 text-sm`},ne={class:`flex justify-end gap-2`},q=[`disabled`],J=[`disabled`],Y={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},X={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Z={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Q={key:1,class:`flex items-center gap-2`},re={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},$={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},ie={key:1},ae=[`value`],oe={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},se={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},ce={key:1},le=[`value`],ue={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},de={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},fe={key:1,class:`flex items-center gap-2`},pe={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},me={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},he={key:1},ge={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 gap-1`},_e={class:`text-content-primary dark:text-content-primary font-mono text-sm`},ve={key:2,class:`bg-yellow-500/10 dark:bg-yellow-500/10 border border-yellow-500/30 rounded-lg p-3`},ye=f({__name:`RadioSettings`,setup(e){let t=j(),n=v(()=>t.stats?.config?.radio||{}),r=E(!1),a=E(!1),o=E(null),s=E(null),c=E(0),l=E(0),u=E(0),d=E(0),f=E(0),p=E(0),_=[{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`}];h(n,e=>{e&&!r.value&&(c.value=e.frequency?Number((e.frequency/1e6).toFixed(3)):0,l.value=e.spreading_factor??0,u.value=e.bandwidth?Number((e.bandwidth/1e3).toFixed(1)):0,d.value=e.tx_power??0,f.value=e.coding_rate??0,p.value=e.preamble_length??0)},{immediate:!0});let T=v(()=>{let e=n.value.frequency;return e?(e/1e6).toFixed(3)+` MHz`:`Not set`}),D=v(()=>{let e=n.value.bandwidth;return e?(e/1e3).toFixed(1)+` kHz`:`Not set`}),O=v(()=>{let e=n.value.tx_power;return e===void 0?`Not set`:e+` dBm`}),k=v(()=>{let e=n.value.coding_rate;return e?`4/`+e:`Not set`}),M=v(()=>{let e=n.value.preamble_length;return e?e+` symbols`:`Not set`}),N=v(()=>n.value.spreading_factor??`Not set`),I=()=>{r.value=!0,o.value=null,s.value=null},L=()=>{r.value=!1,o.value=null;let e=n.value;c.value=e.frequency?Number((e.frequency/1e6).toFixed(3)):0,l.value=e.spreading_factor??0,u.value=e.bandwidth?Number((e.bandwidth/1e3).toFixed(1)):0,d.value=e.tx_power??0,f.value=e.coding_rate??0,p.value=e.preamble_length??0},R=async()=>{a.value=!0,o.value=null,s.value=null;try{let e={};c.value&&(e.frequency=c.value*1e6),l.value&&(e.spreading_factor=l.value),u.value&&(e.bandwidth=u.value*1e3),d.value&&(e.tx_power=d.value),f.value&&(e.coding_rate=f.value);let n=(await A.post(`/update_radio_config`,e)).data;n.message||n.persisted?(s.value=n.message||`Settings saved successfully`,r.value=!1,await t.fetchStats(),setTimeout(()=>{s.value=null},3e3)):n.error?o.value=n.error:o.value=`Unknown response from server`}catch(e){console.error(`Failed to update radio settings:`,e),o.value=e.response?.data?.error||`Failed to update settings`}finally{a.value=!1}};return(e,t)=>(w(),C(`div`,U,[s.value?(w(),C(`div`,W,[S(`p`,G,b(s.value),1)])):g(``,!0),o.value?(w(),C(`div`,te,[S(`p`,K,b(o.value),1)])):g(``,!0),S(`div`,ne,[r.value?(w(),C(x,{key:1},[S(`button`,{onClick:L,disabled:a.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,q),S(`button`,{onClick:R,disabled:a.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(a.value?`Saving...`:`Save Changes`),9,J)],64)):(w(),C(`button`,{key:0,onClick:I,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))]),S(`div`,Y,[S(`div`,X,[t[6]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Frequency`,-1),r.value?(w(),C(`div`,Q,[m(S(`input`,{"onUpdate:modelValue":t[0]||=e=>c.value=e,type:`number`,step:`0.001`,min:`100`,max:`1000`,class:`w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,c.value,void 0,{number:!0}]]),t[5]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`MHz`,-1)])):(w(),C(`div`,Z,b(T.value),1))]),S(`div`,re,[t[7]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Spreading Factor`,-1),r.value?(w(),C(`div`,ie,[m(S(`select`,{"onUpdate:modelValue":t[1]||=e=>l.value=e,class:`px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[(w(),C(x,null,i([5,6,7,8,9,10,11,12],e=>S(`option`,{key:e,value:e},b(e),9,ae)),64))],512),[[P,l.value,void 0,{number:!0}]])])):(w(),C(`div`,$,b(N.value),1))]),S(`div`,oe,[t[8]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Bandwidth`,-1),r.value?(w(),C(`div`,ce,[m(S(`select`,{"onUpdate:modelValue":t[2]||=e=>u.value=e,class:`px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[(w(),C(x,null,i(_,e=>S(`option`,{key:e.value,value:e.value},b(e.label),9,le)),64))],512),[[P,u.value,void 0,{number:!0}]])])):(w(),C(`div`,se,b(D.value),1))]),S(`div`,ue,[t[10]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`TX Power`,-1),r.value?(w(),C(`div`,fe,[m(S(`input`,{"onUpdate:modelValue":t[3]||=e=>d.value=e,type:`number`,min:`2`,max:`30`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,d.value,void 0,{number:!0}]]),t[9]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`dBm`,-1)])):(w(),C(`div`,de,b(O.value),1))]),S(`div`,pe,[t[12]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Coding Rate`,-1),r.value?(w(),C(`div`,he,[m(S(`select`,{"onUpdate:modelValue":t[4]||=e=>f.value=e,class:`px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[11]||=[S(`option`,{value:5},`4/5`,-1),S(`option`,{value:6},`4/6`,-1),S(`option`,{value:7},`4/7`,-1),S(`option`,{value:8},`4/8`,-1)]],512),[[P,f.value,void 0,{number:!0}]])])):(w(),C(`div`,me,b(k.value),1))]),S(`div`,ge,[t[13]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Preamble Length`,-1),S(`span`,_e,b(M.value),1)])]),r.value?(w(),C(`div`,ve,[...t[14]||=[S(`p`,{class:`text-yellow-700 dark:text-yellow-400 text-xs`},[S(`strong`,null,`Note:`),y(` Radio hardware changes (frequency, bandwidth, spreading factor, coding rate) may require a service restart to apply. `)],-1)]])):g(``,!0)]))}}),be={class:`glass-card border border-stroke-subtle dark:border-white/20 rounded-[15px] w-full max-w-3xl max-h-[90vh] flex flex-col shadow-2xl`},xe={class:`flex-1 relative min-h-[400px]`},Se={class:`p-6 border-t border-stroke-subtle dark:border-stroke/10 space-y-4`},Ce={class:`grid grid-cols-2 gap-4`},we=M(f({__name:`LocationPicker`,props:{isOpen:{type:Boolean},latitude:{},longitude:{}},emits:[`close`,`select`],setup(t,{emit:r}){let i=t,a=r,o=E(null),s=E(i.latitude||0),l=E(i.longitude||0),u=null,d=null,f=async()=>{if(o.value){p();try{let t=(await O(async()=>{let{default:t}=await import(`./leaflet-src-PYB8oVmQ.js`).then(t=>e(t.t(),1));return{default:t}},__vite__mapDeps([0,1]))).default;delete t.Icon.Default.prototype._getIconUrl,t.Icon.Default.mergeOptions({iconRetinaUrl:`https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png`,iconUrl:`https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png`,shadowUrl:`https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png`}),await c();let n=s.value||0,r=l.value||0,i=n===0&&r===0?2:13;u=t.map(o.value).setView([n,r],i);try{let e=t.tileLayer(`https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png`,{maxZoom:19,attribution:`© OpenStreetMap contributors © CARTO `,errorTileUrl:`data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==`}),n=t.tileLayer(`https://{s}.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}{r}.png`,{maxZoom:19,attribution:``,errorTileUrl:`data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==`});e.addTo(u),n.addTo(u)}catch(e){console.warn(`Error loading tiles:`,e)}(n!==0||r!==0)&&(d=t.marker([n,r]).addTo(u)),u.on(`click`,e=>{s.value=e.latlng.lat,l.value=e.latlng.lng,d?d.setLatLng(e.latlng):d=t.marker(e.latlng).addTo(u)}),setTimeout(()=>{u?.invalidateSize()},200)}catch(e){console.error(`Failed to initialize map:`,e)}}},p=()=>{u&&(u.remove(),u=null,d=null)};h(()=>i.isOpen,async e=>{e?(await c(),await f()):p()}),h(()=>[i.latitude,i.longitude],([e,t])=>{s.value=e,l.value=t});let _=()=>{a(`select`,{latitude:s.value,longitude:l.value}),a(`close`)},v=()=>{a(`close`)},b=()=>{navigator.geolocation?navigator.geolocation.getCurrentPosition(async t=>{if(s.value=t.coords.latitude,l.value=t.coords.longitude,u){u.setView([s.value,l.value],13);let t=(await O(async()=>{let{default:t}=await import(`./leaflet-src-PYB8oVmQ.js`).then(t=>e(t.t(),1));return{default:t}},__vite__mapDeps([0,1]))).default;d?d.setLatLng([s.value,l.value]):d=t.marker([s.value,l.value]).addTo(u)}},e=>{console.error(`Error getting location:`,e),alert(`Unable to get current location. Please check browser permissions.`)}):alert(`Geolocation is not supported by this browser.`)};return n(()=>{p()}),(e,n)=>t.isOpen?(w(),C(`div`,{key:0,class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm`,onClick:I(v,[`self`])},[S(`div`,be,[S(`div`,{class:`flex items-center justify-between p-6 border-b border-stroke-subtle dark:border-stroke/10`},[n[3]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Select Location `,-1),S(`button`,{onClick:v,class:`text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary transition-colors`},[...n[2]||=[S(`svg`,{class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),S(`div`,xe,[S(`div`,{ref_key:`mapContainer`,ref:o,class:`absolute inset-0 rounded-b-[15px] overflow-hidden`},null,512)]),S(`div`,Se,[S(`div`,Ce,[S(`div`,null,[n[4]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},`Latitude`,-1),m(S(`input`,{"onUpdate:modelValue":n[0]||=e=>s.value=e,type:`number`,step:`0.000001`,class:`w-full px-4 py-2 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary focus:outline-none focus:border-primary`,readonly:``},null,512),[[F,s.value,void 0,{number:!0}]])]),S(`div`,null,[n[5]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},`Longitude`,-1),m(S(`input`,{"onUpdate:modelValue":n[1]||=e=>l.value=e,type:`number`,step:`0.000001`,class:`w-full px-4 py-2 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary focus:outline-none focus:border-primary`,readonly:``},null,512),[[F,l.value,void 0,{number:!0}]])])]),S(`div`,{class:`flex gap-3`},[S(`button`,{onClick:b,class:`flex-1 px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm flex items-center justify-center gap-2`},[...n[6]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z`}),S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 11a3 3 0 11-6 0 3 3 0 016 0z`})],-1),y(` Use Current Location `,-1)]]),S(`button`,{onClick:v,class:`px-6 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm`},` Cancel `),S(`button`,{onClick:_,class:`px-6 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Select Location `)]),n[7]||=S(`p`,{class:`text-content-muted dark:text-content-muted text-xs text-center`},` Click on the map to select a location `,-1)])])])):g(``,!0)}}),[[`__scopeId`,`data-v-fd94857e`]]),Te={class:`space-y-4`},Ee={key:0,class:`bg-green-100 dark:bg-green-500/10 border border-green-300 dark:border-green-500/30 rounded-lg p-3`},De={class:`text-green-700 dark:text-green-400 text-sm`},Oe={key:1,class:`bg-red-100 dark:bg-red-500/10 border border-red-300 dark:border-red-500/30 rounded-lg p-3`},ke={class:`text-red-700 dark:text-red-400 text-sm`},Ae={class:`flex justify-end gap-2`},je=[`disabled`],Me=[`disabled`],Ne={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},Pe={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Fe={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm break-all`},Ie={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Le={class:`text-content-primary dark:text-content-primary font-mono text-xs break-all`},Re={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},ze={class:`flex flex-col items-end gap-1`},Be={class:`text-content-primary dark:text-content-primary font-mono text-xs break-all sm:text-right sm:max-w-xs`},Ve={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},He={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ue={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},We={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ge={key:0,class:`flex justify-end`},Ke={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},qe={class:`text-content-primary dark:text-content-primary font-mono text-sm`},Je={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ye={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Xe={class:`flex flex-col py-2 gap-2`},Ze={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-1`},Qe={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm sm:ml-4`},$e={key:1,class:`flex items-center gap-2`},et={class:`bg-surface dark:bg-surface-elevated border border-stroke-subtle dark:border-stroke/20 rounded-[15px] shadow-2xl w-full max-w-md p-6 space-y-4`},tt={class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},nt=[`maxlength`,`disabled`],rt={key:0,class:`text-red-500 text-xs mt-1`},it={key:1,class:`text-content-muted dark:text-content-muted text-xs mt-1`},at=[`disabled`],ot={key:0,class:`mt-2 bg-amber-500/10 border border-amber-500/30 rounded-lg p-3`},st={key:0,class:`flex items-center gap-3 bg-blue-500/10 border border-blue-500/30 rounded-lg p-3`},ct={class:`text-blue-700 dark:text-blue-400 text-xs font-medium`},lt={class:`text-blue-600 dark:text-blue-500 text-xs mt-0.5`},ut={key:1,class:`bg-red-500/10 border border-red-500/30 rounded-lg p-3`},dt={class:`text-red-600 dark:text-red-400 text-sm`},ft={key:2,class:`bg-green-500/10 border border-green-600/40 dark:border-green-500/30 rounded-lg p-3 space-y-2`},pt={class:`text-green-600 dark:text-green-400 text-sm font-medium`},mt={class:`font-mono text-xs break-all text-content-primary dark:text-content-primary`},ht={key:3,class:`bg-amber-500/10 border border-amber-500/30 rounded-lg p-3`},gt={class:`flex gap-2 mt-3`},_t=[`disabled`],vt=[`disabled`],yt={class:`flex justify-end gap-3 mt-6`},bt=[`disabled`],xt=[`disabled`],St=f({__name:`RepeaterSettings`,setup(e){let t=j(),n=v(()=>t.stats?.config||{}),r=v(()=>n.value.repeater||{}),i=v(()=>t.stats),a=E(!1),o=E(!1),s=E(null),c=E(null),d=E(!1),f=E(``),D=E(0),O=E(0),k=E(0),M=E(1),N=v(()=>n.value.mesh||{});h([n,r,N],()=>{if(!a.value){f.value=n.value.node_name||``,D.value=r.value.latitude||0,O.value=r.value.longitude||0,k.value=r.value.send_advert_interval_hours||0;let e=N.value.path_hash_mode;M.value=e===0||e===1||e===2?e+1:1}},{immediate:!0});let L=v(()=>n.value.node_name||`Not set`),R=v(()=>i.value?.local_hash||`Not available`),z=v(()=>{let e=i.value?.public_key;return!e||e===`Not set`?`Not set`:e}),B=v(()=>{let e=r.value.latitude;return e&&e!==0?e.toFixed(6):`Not set`}),V=v(()=>{let e=r.value.longitude;return e&&e!==0?e.toFixed(6):`Not set`}),ee=v(()=>{let e=r.value.mode;return e?e===`no_tx`?`No TX`:e.charAt(0).toUpperCase()+e.slice(1):`Not set`}),H=v(()=>{let e=r.value.send_advert_interval_hours;return e===void 0?`Not set`:e===0?`Disabled`:e+` hour`+(e===1?``:`s`)}),U=v(()=>{let e=N.value.path_hash_mode;return e===0||e===1||e===2?e+1+(e===0?` byte`:` bytes`):`Not set`}),W=()=>{a.value=!0,s.value=null,c.value=null},G=()=>{a.value=!1,s.value=null,f.value=n.value.node_name||``,D.value=r.value.latitude||0,O.value=r.value.longitude||0,k.value=r.value.send_advert_interval_hours||0;let e=N.value.path_hash_mode;M.value=e===0||e===1||e===2?e+1:1},te=async()=>{o.value=!0,s.value=null,c.value=null;try{let e={};f.value&&(e.node_name=f.value),e.latitude=D.value,e.longitude=O.value,e.flood_advert_interval_hours=k.value,e.path_hash_mode=M.value-1;let n=(await A.post(`/update_radio_config`,e)).data;n.message||n.persisted?(c.value=n.message||`Settings saved successfully`,a.value=!1,await t.fetchStats(),setTimeout(()=>{c.value=null},3e3)):n.error?s.value=n.error:s.value=`Unknown response from server`}catch(e){console.error(`Failed to update repeater settings:`,e),s.value=e.response?.data?.error||`Failed to update settings`}finally{o.value=!1}},K=()=>{d.value=!0},ne=e=>{D.value=e.latitude,O.value=e.longitude},q=E(!1),J=E(``),Y=E(!1),X=E(null),Z=E(null),Q=E(!1),re=E(!1),$=E(!1),ie=E(0),ae=null,oe=v(()=>$.value?8:4),se=v(()=>{let e=J.value.trim();return!e||e.length>oe.value?!1:/^[0-9a-fA-F]+$/.test(e)}),ce=v(()=>{let e=J.value.trim().length;return e===0?``:e===1?`Very fast — ~16 attempts on average`:e===2?`Fast — ~256 attempts on average`:e===3?`Moderate — ~4,096 attempts, a few seconds`:e===4?`Slow — ~65,536 attempts, may take 10-30 seconds`:e===5?`Very slow — ~1 million attempts, could take minutes`:e===6?`Extremely slow — ~16 million attempts, could take a very long time`:e===7?`Extreme — ~268 million attempts, may not complete`:`Extreme — ~4 billion attempts, extremely unlikely to complete`}),le=()=>{ie.value=0,ae=setInterval(()=>{ie.value++},1e3)},ue=()=>{ae&&=(clearInterval(ae),null)};T(()=>ue());let de=()=>{J.value=``,X.value=null,Z.value=null,Q.value=!1,$.value=!1,q.value=!0},fe=async()=>{Y.value=!0,Z.value=null,X.value=null,le();try{let e=await A.generateVanityKey(J.value.trim());e.success&&e.data?X.value=e.data:Z.value=e.error||`Generation failed`}catch(e){let t=e;Z.value=t.response?.data?.error||t.message||`Generation failed`}finally{ue(),Y.value=!1}},pe=async()=>{if(X.value){re.value=!0,Z.value=null;try{let e=await A.generateVanityKey(J.value.trim(),!0);e.success&&e.data?(X.value=e.data,Q.value=!1,q.value=!1,c.value=`New identity key applied. Restart the repeater for the change to take effect.`,await t.fetchStats(),setTimeout(()=>{c.value=null},8e3)):Z.value=e.error||`Failed to apply key`}catch(e){let t=e;Z.value=t.response?.data?.error||t.message||`Failed to apply key`}finally{re.value=!1}}};return(e,t)=>(w(),C(`div`,Te,[c.value?(w(),C(`div`,Ee,[S(`p`,De,b(c.value),1)])):g(``,!0),s.value?(w(),C(`div`,Oe,[S(`p`,ke,b(s.value),1)])):g(``,!0),S(`div`,Ae,[a.value?(w(),C(x,{key:1},[S(`button`,{onClick:G,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,je),S(`button`,{onClick:te,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(o.value?`Saving...`:`Save Changes`),9,Me)],64)):(w(),C(`button`,{key:0,onClick:W,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))]),S(`div`,Ne,[S(`div`,Pe,[t[13]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Node Name`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[0]||=e=>f.value=e,type:`text`,maxlength:`50`,class:`w-full sm:w-64 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`,placeholder:`Enter node name`},null,512)),[[F,f.value]]):(w(),C(`div`,Fe,b(L.value),1))]),S(`div`,Ie,[t[14]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Local Hash`,-1),S(`span`,Le,b(R.value),1)]),S(`div`,Re,[t[15]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm flex-shrink-0`},`Public Key`,-1),S(`div`,ze,[S(`span`,Be,b(z.value),1),S(`button`,{onClick:de,class:`px-2 py-1 text-xs bg-primary/10 hover:bg-primary/20 text-content-secondary dark:text-content-muted rounded border border-primary/30 transition-colors`},` Generate New Key `)])]),S(`div`,Ve,[t[16]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Manual Latitude`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[1]||=e=>D.value=e,type:`number`,step:`0.000001`,min:`-90`,max:`90`,class:`w-full sm:w-48 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,D.value,void 0,{number:!0}]]):(w(),C(`div`,He,b(B.value),1))]),S(`div`,Ue,[t[17]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Manual Longitude`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[2]||=e=>O.value=e,type:`number`,step:`0.000001`,min:`-180`,max:`180`,class:`w-full sm:w-48 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,O.value,void 0,{number:!0}]]):(w(),C(`div`,We,b(V.value),1))]),a.value?(w(),C(`div`,Ge,[S(`button`,{onClick:K,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm flex items-center gap-2`,title:`Pick location on map`},[...t[18]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z`}),S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 11a3 3 0 11-6 0 3 3 0 016 0z`})],-1),y(` Pick Location on Map `,-1)]])])):g(``,!0),S(`div`,Ke,[t[19]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Mode`,-1),S(`span`,qe,b(ee.value),1)]),S(`div`,Je,[t[21]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Path hash length`,-1),a.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[3]||=e=>M.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[20]||=[S(`option`,{value:1},`1 byte`,-1),S(`option`,{value:2},`2 bytes`,-1),S(`option`,{value:3},`3 bytes`,-1)]],512)),[[P,M.value,void 0,{number:!0}]]):(w(),C(`div`,Ye,b(U.value),1))]),S(`div`,Xe,[S(`div`,Ze,[t[23]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Periodic Advertisement Interval`,-1),a.value?(w(),C(`div`,$e,[m(S(`input`,{"onUpdate:modelValue":t[4]||=e=>k.value=e,type:`number`,min:`0`,max:`48`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,k.value,void 0,{number:!0}]]),t[22]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-sm`},`hours`,-1)])):(w(),C(`div`,Qe,b(H.value),1))]),t[24]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-xs`},`How often the repeater sends an advertisement packet (0 = disabled, 3-48 hours)`,-1)])]),_(we,{"is-open":d.value,latitude:D.value,longitude:O.value,onClose:t[5]||=e=>d.value=!1,onSelect:ne},null,8,[`is-open`,`latitude`,`longitude`]),(w(),l(p,{to:`body`},[q.value?(w(),C(`div`,{key:0,class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm`,onClick:t[12]||=I(e=>q.value=!1,[`self`])},[S(`div`,et,[t[32]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Generate Vanity Identity Key `,-1),t[33]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Generate a new Ed25519 identity key whose public key starts with your chosen hex prefix (0-9, A-F). Longer prefixes take more time to find. `,-1),S(`div`,null,[S(`label`,tt,`Hex Prefix (1-`+b(oe.value)+` characters)`,1),m(S(`input`,{"onUpdate:modelValue":t[6]||=e=>J.value=e,type:`text`,maxlength:oe.value,placeholder:`e.g. F8A1`,disabled:Y.value,class:`w-full px-4 py-2 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-400 dark:placeholder-white/40 font-mono text-sm uppercase focus:outline-none focus:border-primary transition-colors disabled:opacity-50`},null,8,nt),[[F,J.value]]),J.value&&!se.value?(w(),C(`p`,rt,` Enter 1-`+b(oe.value)+` valid hex characters (0-9, A-F) `,1)):ce.value?(w(),C(`p`,it,b(ce.value),1)):g(``,!0)]),S(`div`,null,[S(`button`,{onClick:t[7]||=e=>$.value=!$.value,disabled:Y.value,class:`text-xs text-content-muted dark:text-content-muted hover:text-content-secondary dark:hover:text-content-secondary transition-colors disabled:opacity-50 flex items-center gap-1`},[(w(),C(`svg`,{class:u([`w-3 h-3 transition-transform`,{"rotate-90":$.value}]),fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[...t[25]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 5l7 7-7 7`},null,-1)]],2)),t[26]||=y(` Advanced `,-1)],8,at),$.value?(w(),C(`div`,ot,[...t[27]||=[S(`p`,{class:`text-amber-600 dark:text-amber-400 text-xs font-medium`},` Extended prefix mode (up to 8 characters) `,-1),S(`p`,{class:`text-amber-600 dark:text-amber-500 text-xs mt-1`},` Prefixes longer than 4 characters require exponentially more attempts and can take a very long time or may not complete at all. The request may time out. `,-1)]])):g(``,!0)]),Y.value?(w(),C(`div`,st,[t[28]||=S(`svg`,{class:`animate-spin h-5 w-5 text-blue-500 flex-shrink-0`,xmlns:`http://www.w3.org/2000/svg`,fill:`none`,viewBox:`0 0 24 24`},[S(`circle`,{class:`opacity-25`,cx:`12`,cy:`12`,r:`10`,stroke:`currentColor`,"stroke-width":`4`}),S(`path`,{class:`opacity-75`,fill:`currentColor`,d:`M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z`})],-1),S(`div`,null,[S(`p`,ct,` Searching for key with prefix "`+b(J.value.toUpperCase())+`"... `,1),S(`p`,lt,` Elapsed: `+b(ie.value)+`s `,1)])])):g(``,!0),Z.value?(w(),C(`div`,ut,[S(`p`,dt,b(Z.value),1)])):g(``,!0),X.value?(w(),C(`div`,ft,[S(`p`,pt,` Key found in `+b(X.value.attempts.toLocaleString())+` attempts `,1),S(`div`,null,[t[29]||=S(`span`,{class:`text-xs text-content-muted dark:text-content-muted`},`Public Key:`,-1),S(`p`,mt,b(X.value.public_hex),1)])])):g(``,!0),Q.value&&X.value?(w(),C(`div`,ht,[t[30]||=S(`p`,{class:`text-amber-600 dark:text-amber-400 text-sm font-medium`},` Warning: This will replace your current identity key. `,-1),t[31]||=S(`p`,{class:`text-amber-600 dark:text-amber-500 text-xs mt-1`},` Your node address and public key will change. Other nodes will need to re-discover you. This cannot be undone unless you have a backup. `,-1),S(`div`,gt,[S(`button`,{onClick:pe,disabled:re.value,class:`px-3 py-1.5 bg-red-600 hover:bg-red-700 text-white rounded-lg text-xs transition-colors disabled:opacity-50`},b(re.value?`Applying...`:`Confirm Replace Key`),9,_t),S(`button`,{onClick:t[8]||=e=>Q.value=!1,disabled:re.value,class:`px-3 py-1.5 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 text-xs transition-colors`},` Cancel `,8,vt)])])):g(``,!0),S(`div`,yt,[S(`button`,{onClick:t[9]||=e=>q.value=!1,disabled:Y.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/10 transition-colors`},` Close `,8,bt),X.value?(w(),C(x,{key:1},[S(`button`,{onClick:t[10]||=e=>{X.value=null,Z.value=null},class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 text-sm transition-colors`},` Try Again `),Q.value?g(``,!0):(w(),C(`button`,{key:0,onClick:t[11]||=e=>Q.value=!0,class:`px-4 py-2 bg-red-600/20 hover:bg-red-600/30 text-red-600 dark:text-red-400 rounded-lg border border-red-500/50 text-sm transition-colors`},` Apply Key `))],64)):(w(),C(`button`,{key:0,onClick:fe,disabled:!se.value||Y.value,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 text-sm transition-colors disabled:opacity-50 disabled:cursor-not-allowed`},b(Y.value?`Generating...`:`Generate`),9,xt))])])])):g(``,!0)]))]))}}),Ct={class:`space-y-4`},wt={key:0,class:`bg-green-100 dark:bg-green-500/20 border border-green-500 dark:border-green-500/50 rounded-lg p-3 text-green-700 dark:text-green-400 text-sm`},Tt={key:1,class:`bg-red-100 dark:bg-red-500/20 border border-red-500 dark:border-red-500/50 rounded-lg p-3 text-red-700 dark:text-red-400 text-sm`},Et={class:`flex justify-end gap-2`},Dt=[`disabled`],Ot=[`disabled`],kt={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},At={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},jt={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Mt={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 gap-1`},Nt={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Pt=f({__name:`DutyCycle`,setup(e){let t=j(),n=v(()=>t.stats?.config?.duty_cycle||{}),r=v(()=>{let e=n.value.max_airtime_percent;return typeof e==`number`?e.toFixed(1)+`%`:e&&typeof e==`object`&&`parsedValue`in e?(e.parsedValue||0).toFixed(1)+`%`:`Not set`}),i=v(()=>n.value.enforcement_enabled?`Enabled`:`Disabled`),a=E(!1),o=E(!1),s=E(``),c=E(``),l=E(0),u=E(!0),d=()=>{let e=n.value.max_airtime_percent;typeof e==`number`?l.value=e:e&&typeof e==`object`&&`parsedValue`in e?l.value=e.parsedValue||0:l.value=6,u.value=n.value.enforcement_enabled!==!1,a.value=!0,s.value=``,c.value=``},f=()=>{a.value=!1,s.value=``,c.value=``},p=async()=>{o.value=!0,c.value=``,s.value=``;try{let e=(await k.post(`/api/update_duty_cycle_config`,{max_airtime_percent:l.value,enforcement_enabled:u.value})).data;e.message||e.persisted?(s.value=e.message||`Settings saved successfully`,a.value=!1,await t.fetchStats(),setTimeout(()=>{s.value=``},3e3)):c.value=`Failed to save settings`}catch(e){console.error(`Failed to save duty cycle settings:`,e),c.value=e.response?.data?.error||`Failed to save settings`}finally{o.value=!1}};return(e,t)=>(w(),C(`div`,Ct,[s.value?(w(),C(`div`,wt,b(s.value),1)):g(``,!0),c.value?(w(),C(`div`,Tt,b(c.value),1)):g(``,!0),S(`div`,Et,[a.value?(w(),C(x,{key:1},[S(`button`,{onClick:f,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,Dt),S(`button`,{onClick:p,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(o.value?`Saving...`:`Save Changes`),9,Ot)],64)):(w(),C(`button`,{key:0,onClick:d,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))]),S(`div`,kt,[S(`div`,At,[t[2]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Max Airtime %`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[0]||=e=>l.value=e,type:`number`,step:`0.1`,min:`0.1`,max:`100`,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,l.value,void 0,{number:!0}]]):(w(),C(`div`,jt,b(r.value),1))]),S(`div`,Mt,[t[4]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Enforcement`,-1),a.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[1]||=e=>u.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[3]||=[S(`option`,{value:!0},`Enabled`,-1),S(`option`,{value:!1},`Disabled`,-1)]],512)),[[P,u.value]]):(w(),C(`div`,Nt,b(i.value),1))])])]))}}),Ft={class:`space-y-4`},It={key:0,class:`bg-green-100 dark:bg-green-500/20 border border-green-500 dark:border-green-500/50 rounded-lg p-3 text-green-700 dark:text-green-400 text-sm`},Lt={key:1,class:`bg-red-100 dark:bg-red-500/20 border border-red-500 dark:border-red-500/50 rounded-lg p-3 text-red-700 dark:text-red-400 text-sm`},Rt={class:`flex justify-end gap-2`},zt=[`disabled`],Bt=[`disabled`],Vt={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},Ht={class:`flex flex-col py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-2`},Ut={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-1`},Wt={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm sm:ml-4`},Gt={class:`flex flex-col py-2 gap-2`},Kt={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-1`},qt={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm sm:ml-4`},Jt=f({__name:`TransmissionDelays`,setup(e){let t=j(),n=v(()=>t.stats?.config?.delays||{}),r=v(()=>{let e=n.value.tx_delay_factor;if(e&&typeof e==`object`&&e&&`parsedValue`in e){let t=e.parsedValue;if(typeof t==`number`)return t.toFixed(2)+`x`}return`Not set`}),i=v(()=>{let e=n.value.direct_tx_delay_factor;return typeof e==`number`?e.toFixed(2)+`s`:`Not set`}),a=E(!1),o=E(!1),s=E(``),c=E(``),l=E(0),u=E(0),d=()=>{let e=n.value.tx_delay_factor;e&&typeof e==`object`&&`parsedValue`in e?l.value=e.parsedValue||1:typeof e==`number`?l.value=e:l.value=1;let t=n.value.direct_tx_delay_factor;u.value=typeof t==`number`?t:.5,a.value=!0,s.value=``,c.value=``},f=()=>{a.value=!1,s.value=``,c.value=``},p=async()=>{o.value=!0,c.value=``,s.value=``;try{let e=(await k.post(`/api/update_radio_config`,{tx_delay_factor:l.value,direct_tx_delay_factor:u.value})).data;e.message||e.persisted?(s.value=e.message||`Settings saved successfully`,a.value=!1,await t.fetchStats(),setTimeout(()=>{s.value=``},3e3)):c.value=`Failed to save settings`}catch(e){console.error(`Failed to save delay settings:`,e),c.value=e.response?.data?.error||`Failed to save settings`}finally{o.value=!1}};return(e,t)=>(w(),C(`div`,Ft,[s.value?(w(),C(`div`,It,b(s.value),1)):g(``,!0),c.value?(w(),C(`div`,Lt,b(c.value),1)):g(``,!0),S(`div`,Rt,[a.value?(w(),C(x,{key:1},[S(`button`,{onClick:f,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,zt),S(`button`,{onClick:p,disabled:o.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(o.value?`Saving...`:`Save Changes`),9,Bt)],64)):(w(),C(`button`,{key:0,onClick:d,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))]),S(`div`,Vt,[S(`div`,Ht,[S(`div`,Ut,[t[2]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Flood TX Delay Factor`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[0]||=e=>l.value=e,type:`number`,step:`0.1`,min:`0`,max:`5`,class:`w-full sm:w-32 px-3 py-1.5 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,l.value,void 0,{number:!0}]]):(w(),C(`div`,Wt,b(r.value),1))]),t[3]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-xs`},`Multiplier for flood packet transmission delays (collision avoidance)`,-1)]),S(`div`,Gt,[S(`div`,Kt,[t[4]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Direct TX Delay Factor`,-1),a.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[1]||=e=>u.value=e,type:`number`,step:`0.1`,min:`0`,max:`5`,class:`w-full sm:w-32 px-3 py-1.5 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,u.value,void 0,{number:!0}]]):(w(),C(`div`,qt,b(i.value),1))]),t[5]||=S(`span`,{class:`text-content-muted dark:text-content-muted text-xs`},`Base delay for direct-routed packet transmission (seconds)`,-1)])])]))}}),Yt=D(`treeState`,()=>{let e=o(new Set),t=o({value:null}),n=t=>{e.add(t)},r=t=>{e.delete(t)};return{expandedNodes:e,selectedNodeId:t,addExpandedNode:n,removeExpandedNode:r,isNodeExpanded:t=>e.has(t),setSelectedNode:e=>{t.value=e},toggleExpanded:t=>{e.has(t)?r(t):n(t)}}}),Xt={class:`select-none`},Zt={class:`flex-shrink-0`},Qt={key:0,class:`w-3.5 h-3.5 sm:w-4 sm:h-4 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},$t={key:1,class:`w-3.5 h-3.5 sm:w-4 sm:h-4 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},en={key:0,class:`hidden sm:flex items-center gap-1 ml-2`},tn={class:`relative group`},nn=[`title`],rn={key:0,class:`text-xs font-mono text-white/50 bg-white/5 px-1.5 py-0.5 rounded border border-white/10`},an={class:`flex justify-between items-start mb-4`},on={class:`bg-black/20 border border-white/10 rounded-md p-4 mb-4`},sn={class:`text-sm font-mono text-white/80 break-all leading-relaxed`},cn={class:`flex items-center gap-1 sm:gap-2 ml-auto flex-shrink-0`},ln={key:0,class:`hidden sm:flex items-center gap-1`},un=[`title`],dn={key:1,class:`hidden sm:flex items-center gap-1`},fn={key:2,class:`hidden sm:inline-block px-2 py-1 bg-white/10 text-white/60 text-xs rounded-full ml-1`},pn={key:0,class:`space-y-1`},mn=M(f({__name:`TreeNode`,props:{node:{},selectedNodeId:{},level:{},disabled:{type:Boolean}},emits:[`select`],setup(e,{emit:n}){let a=e,o=n,s=Yt(),c=E(!1),d=v({get:()=>s.isNodeExpanded(a.node.id),set:e=>{e?s.addExpandedNode(a.node.id):s.removeExpandedNode(a.node.id)}}),f=v(()=>a.node.children.length>0);function p(e){if(!e)return`Never`;let t=new Date().getTime()-e.getTime(),n=Math.floor(t/(1e3*60)),r=Math.floor(t/(1e3*60*60)),i=Math.floor(t/(1e3*60*60*24)),a=Math.floor(i/365);return n<60?`${n}m ago`:r<24?`${r}h ago`:i<365?`${i}d ago`:`${a}y ago`}function m(e){return e?e.length<=16?e:`${e.slice(0,8)}...${e.slice(-8)}`:`No key`}function h(){f.value&&(d.value=!d.value)}function T(){o(`select`,a.node.id)}function D(e){o(`select`,e)}function O(e){e.stopPropagation(),c.value=!c.value}function k(e){e.stopPropagation(),a.node.transport_key&&window.navigator?.clipboard&&window.navigator.clipboard.writeText(a.node.transport_key)}return(n,o)=>{let s=r(`TreeNode`,!0);return w(),C(`div`,Xt,[S(`div`,{class:u([`flex flex-wrap sm:flex-nowrap items-start sm:items-center gap-1 sm:gap-2 py-2 px-2 sm:px-3 rounded-lg cursor-pointer transition-all duration-200`,a.disabled?`opacity-50 cursor-not-allowed`:`hover:bg-white/5`,e.selectedNodeId===e.node.id&&!a.disabled?`bg-primary/20 text-primary`:`text-white/80 hover:text-white`,`ml-${e.level*4}`]),onClick:o[3]||=e=>!a.disabled&&T()},[S(`div`,{class:`flex-shrink-0 w-3 h-3 sm:w-4 sm:h-4 flex items-center justify-center`,onClick:I(h,[`stop`])},[f.value?(w(),C(`svg`,{key:0,class:u([`w-2.5 h-2.5 sm:w-3 sm:h-3 transition-transform duration-200`,d.value?`rotate-90`:`rotate-0`]),fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[...o[4]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 5l7 7-7 7`},null,-1)]],2)):g(``,!0)]),S(`div`,Zt,[a.node.name.startsWith(`#`)?(w(),C(`svg`,Qt,[...o[5]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,$t,[...o[6]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`},null,-1)]]))]),S(`span`,{class:u([`font-mono text-xs sm:text-sm transition-colors duration-200 break-all`,e.selectedNodeId===e.node.id?`text-primary font-medium`:``])},b(e.node.name),3),e.node.transport_key?(w(),C(`div`,en,[S(`div`,tn,[S(`button`,{onClick:O,class:`p-1 rounded hover:bg-white/10 transition-colors`,title:c.value?`Hide full key`:`Show full key`},[...o[7]||=[S(`svg`,{class:`w-3 h-3 text-white/60 hover:text-white/80`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 12a3 3 0 11-6 0 3 3 0 016 0z`}),S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z`})],-1)]],8,nn),c.value?g(``,!0):(w(),C(`span`,rn,b(m(e.node.transport_key)),1)),c.value?(w(),C(`div`,{key:1,class:`fixed inset-0 z-[9998] flex items-center justify-center bg-black/70 backdrop-blur-md`,onClick:o[2]||=e=>c.value=!1},[S(`div`,{class:`bg-black/20 border border-white/20 rounded-lg shadow-lg p-6 max-w-2xl w-full mx-4`,onClick:o[1]||=I(()=>{},[`stop`])},[S(`div`,an,[o[9]||=S(`h3`,{class:`text-lg font-semibold text-white`},`Transport Key`,-1),S(`button`,{onClick:o[0]||=e=>c.value=!1,class:`text-white/60 hover:text-white transition-colors`},[...o[8]||=[S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),S(`div`,on,[S(`div`,sn,b(e.node.transport_key),1)]),S(`div`,{class:`flex justify-end`},[S(`button`,{onClick:k,class:`px-4 py-2 bg-accent-green/20 hover:bg-accent-green/30 border border-accent-green/50 text-accent-green rounded-lg transition-colors flex items-center gap-2`,title:`Copy to clipboard`},[...o[10]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z`})],-1),y(` Copy Key `,-1)]])])])])):g(``,!0)])])):g(``,!0),S(`div`,cn,[e.node.last_used?(w(),C(`div`,ln,[o[11]||=S(`svg`,{class:`w-3 h-3 text-white/40`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),S(`span`,{class:`text-xs text-white/50`,title:e.node.last_used.toLocaleString()},b(p(e.node.last_used)),9,un)])):(w(),C(`div`,dn,[...o[12]||=[S(`svg`,{class:`w-3 h-3 text-white/30`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),S(`span`,{class:`text-xs text-white/30 italic`},`Never`,-1)]])),S(`span`,{class:u([`px-1.5 sm:px-2 py-0.5 text-[10px] sm:text-xs font-medium rounded-md transition-colors`,e.node.floodPolicy===`allow`?`bg-accent-green/10 text-accent-green/90 border border-accent-green/20`:`bg-accent-red/10 text-accent-red/90 border border-accent-red/20`])},b(e.node.floodPolicy===`allow`?`ALLOW`:`DENY`),3),f.value?(w(),C(`span`,fn,` > `+b(e.node.children.length),1)):g(``,!0)])],2),_(N,{"enter-active-class":`transition-all duration-300 ease-out`,"enter-from-class":`opacity-0 max-h-0 overflow-hidden`,"enter-to-class":`opacity-100 max-h-screen overflow-visible`,"leave-active-class":`transition-all duration-300 ease-in`,"leave-from-class":`opacity-100 max-h-screen overflow-visible`,"leave-to-class":`opacity-0 max-h-0 overflow-hidden`},{default:t(()=>[d.value&&e.node.children.length>0?(w(),C(`div`,pn,[(w(!0),C(x,null,i(e.node.children,t=>(w(),l(s,{key:t.id,node:t,"selected-node-id":e.selectedNodeId,level:e.level+1,disabled:a.disabled,onSelect:D},null,8,[`node`,`selected-node-id`,`level`,`disabled`]))),128))])):g(``,!0)]),_:1})])}}}),[[`__scopeId`,`data-v-ed9c8a11`]]),hn={class:`flex items-center justify-between mb-6`},gn={class:`text-content-secondary dark:text-content-muted text-sm mt-1`},_n={key:0},vn={class:`text-primary font-mono`},yn={key:1},bn={for:`keyName`,class:`block text-sm font-medium text-white mb-2`},xn={class:`flex items-center gap-2`},Sn={key:0,class:`w-4 h-4 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Cn={key:1,class:`w-4 h-4 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},wn={class:`bg-gray-50 dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-4`},Tn={class:`flex items-center gap-3 mb-2`},En={class:`flex items-center gap-2`},Dn={key:0,class:`w-5 h-5 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},On={key:1,class:`w-5 h-5 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},kn={class:`text-content-secondary dark:text-content-muted text-sm`},An={class:`grid grid-cols-2 gap-3`},jn={class:`relative cursor-pointer group`},Mn={class:`relative cursor-pointer group`},Nn={class:`flex gap-3 pt-4`},Pn=[`disabled`],Fn=f({__name:`AddKeyModal`,props:{show:{type:Boolean},selectedNodeName:{},selectedNodeId:{}},emits:[`close`,`add`],setup(e,{emit:t}){let n=e,r=t,i=E(``),a=E(``),o=E(`allow`),s=v(()=>i.value.startsWith(`#`)),c=v(()=>({type:s.value?`Region`:`Private Key`,description:s.value?`Regional organizational key`:`Individual assigned key`}));h(s,e=>{e?a.value=`This will create a new region for organizing keys`:a.value=`This will create a new private key entry`},{immediate:!0});let l=v(()=>i.value.trim().length>0),f=()=>{l.value&&(r(`add`,{name:i.value.trim(),floodPolicy:o.value,parentId:n.selectedNodeId}),i.value=``,a.value=``,o.value=`allow`)},p=()=>{i.value=``,a.value=``,o.value=`allow`,r(`close`)},_=e=>{e.target===e.currentTarget&&p()};return(t,r)=>e.show?(w(),C(`div`,{key:0,onClick:_,class:`fixed inset-0 bg-black/40 backdrop-blur-lg z-[99999] flex items-center justify-center p-4`,style:{"backdrop-filter":`blur(8px) saturate(180%)`,position:`fixed`,top:`0`,left:`0`,right:`0`,bottom:`0`}},[S(`div`,{class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] p-6 w-full max-w-md border border-stroke-subtle dark:border-white/10`,onClick:r[3]||=I(()=>{},[`stop`])},[S(`div`,hn,[S(`div`,null,[r[5]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Add New Entry `,-1),S(`p`,gn,[n.selectedNodeName?(w(),C(`span`,_n,[r[4]||=y(` Add to: `,-1),S(`span`,vn,b(n.selectedNodeName),1)])):(w(),C(`span`,yn,` Add to root level (#uk) `))])]),S(`button`,{onClick:p,class:`text-white/60 hover:text-white transition-colors`},[...r[6]||=[S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),S(`form`,{onSubmit:I(f,[`prevent`]),class:`space-y-4`},[S(`div`,null,[S(`label`,bn,[S(`div`,xn,[s.value?(w(),C(`svg`,Sn,[...r[7]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,Cn,[...r[8]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`},null,-1)]])),r[9]||=y(` Region/Key Name `,-1)])]),m(S(`input`,{id:`keyName`,"onUpdate:modelValue":r[0]||=e=>i.value=e,type:`text`,placeholder:`Enter name (prefix with # for regions)`,class:`w-full px-4 py-3 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/20 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/50 focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20 transition-colors`,autocomplete:`off`},null,512),[[F,i.value]])]),S(`div`,wn,[S(`div`,Tn,[S(`div`,En,[s.value?(w(),C(`svg`,Dn,[...r[10]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,On,[...r[11]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1221 9z`},null,-1)]])),S(`span`,{class:u([s.value?`text-secondary`:`text-accent-green`,`font-medium`])},b(c.value.type),3)]),S(`div`,{class:u([`flex-1 h-px`,s.value?`bg-secondary/20`:`bg-accent-green/20`])},null,2)]),S(`p`,kn,b(c.value.description),1)]),S(`div`,null,[r[14]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-3`},[S(`div`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4 text-primary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z`})]),y(` Flood Policy `)])],-1),S(`div`,An,[S(`label`,jn,[m(S(`input`,{type:`radio`,"onUpdate:modelValue":r[1]||=e=>o.value=e,value:`allow`,class:`sr-only`},null,512),[[B,o.value]]),r[12]||=d(``,1)]),S(`label`,Mn,[m(S(`input`,{type:`radio`,"onUpdate:modelValue":r[2]||=e=>o.value=e,value:`deny`,class:`sr-only`},null,512),[[B,o.value]]),r[13]||=d(``,1)])])]),S(`div`,Nn,[S(`button`,{type:`button`,onClick:p,class:`flex-1 px-4 py-3 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),S(`button`,{type:`submit`,disabled:!l.value,class:u([`flex-1 px-4 py-3 rounded-lg transition-colors font-medium`,l.value?`bg-accent-green/20 hover:bg-accent-green/30 border border-accent-green/50 text-accent-green`:`bg-background-mute dark:bg-stroke/5 border border-stroke-subtle dark:border-stroke/20 text-content-muted dark:text-content-muted cursor-not-allowed`])},` Add `+b(c.value.type),11,Pn)])],32)])])):g(``,!0)}}),In={class:`flex items-center justify-between mb-6`},Ln={class:`text-content-secondary dark:text-content-muted text-sm mt-1`},Rn={class:`text-primary font-mono`},zn={for:`keyName`,class:`block text-sm font-medium text-content-secondary dark:text-content-primary mb-2`},Bn={class:`flex items-center gap-2`},Vn={key:0,class:`w-4 h-4 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Hn={key:1,class:`w-4 h-4 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Un={class:`bg-gray-50 dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-4`},Wn={class:`flex items-center gap-3 mb-2`},Gn={class:`flex items-center gap-2`},Kn={key:0,class:`w-5 h-5 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},qn={key:1,class:`w-5 h-5 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Jn={class:`text-content-secondary dark:text-content-muted text-sm`},Yn={key:0,class:`space-y-4`},Xn={key:0,class:`bg-gray-50 dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-4`},Zn={class:`bg-background-mute dark:bg-black/20 border border-stroke-subtle dark:border-stroke/10 rounded-md p-3`},Qn={class:`text-xs font-mono text-content-primary dark:text-content-primary/80 break-all`},$n={key:1,class:`bg-gray-50 dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-4`},er={class:`flex items-center justify-between`},tr={class:`text-sm text-content-secondary dark:text-content-muted`},nr={class:`text-xs text-content-muted dark:text-content-muted`},rr={class:`grid grid-cols-2 gap-3`},ir={class:`relative cursor-pointer group`},ar={class:`relative cursor-pointer group`},or={class:`flex gap-3 pt-4`},sr=[`disabled`],cr=f({__name:`EditKeyModal`,props:{show:{type:Boolean},node:{}},emits:[`close`,`save`,`request-delete`],setup(e,{emit:t}){let n=e,r=t,i=E(``),a=E(`allow`),o=v(()=>i.value.startsWith(`#`)),s=v(()=>({type:o.value?`Region`:`Private Key`,description:o.value?`Regional organizational key`:`Individual assigned key`}));h(()=>n.node,e=>{e?(i.value=e.name,a.value=e.floodPolicy):(i.value=``,a.value=`allow`)},{immediate:!0});let c=v(()=>i.value.trim().length>0&&n.node),l=e=>{let t=new Date().getTime()-e.getTime(),n=Math.floor(t/(1e3*60)),r=Math.floor(t/(1e3*60*60)),i=Math.floor(t/(1e3*60*60*24)),a=Math.floor(i/365);return n<60?`${n}m ago`:r<24?`${r}h ago`:i<365?`${i}d ago`:`${a}y ago`},f=e=>{window.navigator?.clipboard&&window.navigator.clipboard.writeText(e)},p=()=>{!c.value||!n.node||(r(`save`,{id:n.node.id,name:i.value.trim(),floodPolicy:a.value}),x())},_=()=>{n.node&&(r(`request-delete`,n.node),x())},x=()=>{r(`close`)},T=e=>{e.target===e.currentTarget&&x()};return(t,n)=>e.show?(w(),C(`div`,{key:0,onClick:T,class:`fixed inset-0 bg-black/50 backdrop-blur-lg z-[99999] flex items-center justify-center p-4`,style:{"backdrop-filter":`blur(8px) saturate(180%)`,position:`fixed`,top:`0`,left:`0`,right:`0`,bottom:`0`}},[S(`div`,{class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] p-6 w-full max-w-lg border border-stroke-subtle dark:border-white/10`,onClick:n[4]||=I(()=>{},[`stop`])},[S(`div`,In,[S(`div`,null,[n[6]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Edit Entry `,-1),S(`p`,Ln,[n[5]||=y(` Modify `,-1),S(`span`,Rn,b(e.node?.name),1)])]),S(`button`,{onClick:x,class:`text-white/60 hover:text-white transition-colors`},[...n[7]||=[S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),S(`form`,{onSubmit:I(p,[`prevent`]),class:`space-y-4`},[S(`div`,null,[S(`label`,zn,[S(`div`,Bn,[o.value?(w(),C(`svg`,Vn,[...n[8]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,Hn,[...n[9]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1721 9z`},null,-1)]])),n[10]||=y(` Region/Key Name `,-1)])]),m(S(`input`,{id:`keyName`,"onUpdate:modelValue":n[0]||=e=>i.value=e,type:`text`,placeholder:`Enter name (prefix with # for regions)`,class:`w-full px-4 py-3 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/20 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/50 focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20 transition-colors`,autocomplete:`off`},null,512),[[F,i.value]])]),S(`div`,Un,[S(`div`,Wn,[S(`div`,Gn,[o.value?(w(),C(`svg`,Kn,[...n[11]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,qn,[...n[12]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1721 9z`},null,-1)]])),S(`span`,{class:u([o.value?`text-secondary`:`text-accent-green`,`font-medium`])},b(s.value.type),3)]),S(`div`,{class:u([`flex-1 h-px`,o.value?`bg-secondary/20`:`bg-accent-green/20`])},null,2)]),S(`p`,Jn,b(s.value.description),1)]),e.node?(w(),C(`div`,Yn,[e.node.transport_key?(w(),C(`div`,Xn,[n[14]||=d(``,1),S(`div`,Zn,[S(`div`,Qn,b(e.node.transport_key),1),S(`button`,{onClick:n[1]||=t=>f(e.node.transport_key||``),class:`mt-2 text-xs text-accent-green hover:text-accent-green/80 flex items-center gap-1`,title:`Copy to clipboard`},[...n[13]||=[S(`svg`,{class:`w-3 h-3`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z`})],-1),y(` Copy Key `,-1)]])])])):g(``,!0),e.node.last_used?(w(),C(`div`,$n,[n[15]||=S(`div`,{class:`flex items-center gap-2 mb-3`},[S(`svg`,{class:`w-4 h-4 text-primary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`})]),S(`span`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},`Last Used`)],-1),S(`div`,er,[S(`div`,tr,b(e.node.last_used.toLocaleDateString())+` at `+b(e.node.last_used.toLocaleTimeString()),1),S(`div`,nr,b(l(e.node.last_used)),1)])])):g(``,!0)])):g(``,!0),S(`div`,null,[n[18]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-primary mb-3`},[S(`div`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4 text-primary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z`})]),y(` Flood Policy `)])],-1),S(`div`,rr,[S(`label`,ir,[m(S(`input`,{type:`radio`,"onUpdate:modelValue":n[2]||=e=>a.value=e,value:`allow`,class:`sr-only`},null,512),[[B,a.value]]),n[16]||=d(``,1)]),S(`label`,ar,[m(S(`input`,{type:`radio`,"onUpdate:modelValue":n[3]||=e=>a.value=e,value:`deny`,class:`sr-only`},null,512),[[B,a.value]]),n[17]||=d(``,1)])])]),S(`div`,or,[S(`button`,{type:`button`,onClick:_,class:`px-4 py-3 bg-accent-red/20 hover:bg-accent-red/30 border border-accent-red/50 text-accent-red rounded-lg transition-colors`},` Delete `),S(`button`,{type:`button`,onClick:x,class:`flex-1 px-4 py-3 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),S(`button`,{type:`submit`,disabled:!c.value,class:u([`flex-1 px-4 py-3 rounded-lg transition-colors font-medium`,c.value?`bg-accent-green/20 hover:bg-accent-green/30 border border-accent-green/50 text-accent-green`:`bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/20 text-content-muted dark:text-content-muted/70 cursor-not-allowed`])},` Save Changes `,10,sr)])],32)])])):g(``,!0)}}),lr={class:`flex items-center gap-3 mb-6`},ur={class:`text-content-secondary dark:text-content-muted text-sm mt-1`},dr={class:`text-accent-red font-mono`},fr={key:0,class:`bg-accent-red/10 border border-accent-red/30 rounded-lg p-4 mb-6`},pr={class:`flex items-start gap-3`},mr={class:`flex-1`},hr={class:`text-accent-red font-medium text-sm mb-2`},gr={class:`space-y-1 max-h-32 overflow-y-auto`},_r={key:0,class:`w-3 h-3 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},vr={key:1,class:`w-3 h-3 text-accent-green`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},yr={class:`font-mono`},br={key:0,class:`text-content-secondary dark:text-content-muted text-xs`},xr={key:1,class:`mb-6`},Sr={class:`mb-3`},Cr={class:`relative`},wr={class:`space-y-2 max-h-40 overflow-y-auto border border-stroke-subtle dark:border-stroke/20 rounded-lg p-3 bg-gray-50 dark:bg-white/5`},Tr={key:0,class:`text-center py-4 text-content-secondary dark:text-content-muted text-sm`},Er={class:`relative`},Dr=[`value`],Or={class:`flex items-center gap-2 flex-1`},kr={class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ar={key:0,class:`ml-auto px-2 py-0.5 bg-background-mute dark:bg-stroke/10 text-content-secondary dark:text-content-muted text-xs rounded-full`},jr={class:`flex gap-3`},Mr=f({__name:`DeleteConfirmModal`,props:{show:{type:Boolean},node:{},allNodes:{}},emits:[`close`,`delete-all`,`move-children`],setup(e,{emit:t}){let n=e,r=t,a=E(null),o=E(``),s=e=>{let t=[],n=e=>{for(let r of e.children)t.push(r),n(r)};return n(e),t},c=v(()=>n.node?s(n.node):[]),l=v(()=>{if(!n.node)return[];let e=new Set([n.node.id,...c.value.map(e=>e.id)]),t=n=>{let r=[];for(let i of n)i.name.startsWith(`#`)&&!e.has(i.id)&&r.push(i),i.children.length>0&&r.push(...t(i.children));return r};return t(n.allNodes)}),d=v(()=>{if(!o.value.trim())return l.value;let e=o.value.toLowerCase();return l.value.filter(t=>t.name.toLowerCase().includes(e))}),f=()=>{n.node&&(r(`delete-all`,n.node.id),h())},p=()=>{!n.node||!a.value||(r(`move-children`,{nodeId:n.node.id,targetParentId:a.value}),h())},h=()=>{a.value=null,o.value=``,r(`close`)},_=e=>{e.target===e.currentTarget&&h()};return(t,n)=>e.show&&e.node?(w(),C(`div`,{key:0,onClick:_,class:`fixed inset-0 bg-black/80 backdrop-blur-lg z-[99999] flex items-center justify-center p-4`,style:{"backdrop-filter":`blur(8px) saturate(180%)`,position:`fixed`,top:`0`,left:`0`,right:`0`,bottom:`0`}},[S(`div`,{class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] p-6 w-full max-w-lg border border-stroke-subtle dark:border-white/10`,onClick:n[2]||=I(()=>{},[`stop`])},[S(`div`,lr,[n[6]||=S(`svg`,{class:`w-6 h-6 text-accent-red`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,null,[n[4]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` Confirm Deletion `,-1),S(`p`,ur,[n[3]||=y(` Deleting `,-1),S(`span`,dr,b(e.node?.name),1)])]),S(`button`,{onClick:h,class:`ml-auto text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary transition-colors`},[...n[5]||=[S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),c.value.length>0?(w(),C(`div`,fr,[S(`div`,pr,[n[9]||=S(`svg`,{class:`w-5 h-5 text-accent-red flex-shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),S(`div`,mr,[S(`h4`,hr,` This will affect `+b(c.value.length)+` child `+b(c.value.length===1?`entry`:`entries`)+`: `,1),S(`div`,gr,[(w(!0),C(x,null,i(c.value.slice(0,10),e=>(w(),C(`div`,{key:e.id,class:`flex items-center gap-2 text-xs text-content-secondary dark:text-content-primary/80`},[e.name.startsWith(`#`)?(w(),C(`svg`,_r,[...n[7]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`},null,-1)]])):(w(),C(`svg`,vr,[...n[8]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1721 9z`},null,-1)]])),S(`span`,yr,b(e.name),1),S(`span`,{class:u([`px-1 py-0.5 text-xs rounded`,e.floodPolicy===`allow`?`bg-accent-green/20 text-accent-green`:`bg-accent-red/20 text-accent-red`])},b(e.floodPolicy),3)]))),128)),c.value.length>10?(w(),C(`div`,br,` ...and `+b(c.value.length-10)+` more `,1)):g(``,!0)])])])])):g(``,!0),c.value.length>0&&l.value.length>0?(w(),C(`div`,xr,[n[13]||=S(`h4`,{class:`text-content-primary dark:text-content-primary font-medium text-sm mb-3`},` Move children to another region: `,-1),S(`div`,Sr,[S(`div`,Cr,[n[10]||=S(`svg`,{class:`absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-content-muted dark:text-content-muted`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z`})],-1),m(S(`input`,{"onUpdate:modelValue":n[0]||=e=>o.value=e,type:`text`,placeholder:`Search regions...`,class:`w-full pl-9 pr-4 py-2 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/20 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-500 dark:placeholder-white/50 focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20 transition-colors text-sm`},null,512),[[F,o.value]])])]),S(`div`,wr,[d.value.length===0?(w(),C(`div`,Tr,b(o.value?`No regions match your search`:`No available regions`),1)):g(``,!0),(w(!0),C(x,null,i(d.value,e=>(w(),C(`label`,{key:e.id,class:`flex items-center gap-3 p-2 rounded cursor-pointer hover:bg-stroke-subtle dark:hover:bg-white/10 transition-colors group`},[S(`div`,Er,[m(S(`input`,{type:`radio`,value:e.id,"onUpdate:modelValue":n[1]||=e=>a.value=e,class:`sr-only peer`},null,8,Dr),[[B,a.value]]),n[11]||=S(`div`,{class:`w-4 h-4 border-2 border-stroke dark:border-stroke/30 rounded-full group-hover:border-stroke dark:group-hover:border-stroke/50 peer-checked:border-primary peer-checked:bg-primary/20 transition-all`},[S(`div`,{class:`w-2 h-2 rounded-full bg-primary scale-0 peer-checked:scale-100 transition-transform absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2`})],-1)]),S(`div`,Or,[n[12]||=S(`svg`,{class:`w-4 h-4 text-secondary`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M7 20l4-16m2 16l4-16M6 9h14M4 15h14`})],-1),S(`span`,kr,b(e.name),1),e.children.length>0?(w(),C(`span`,Ar,b(e.children.length),1)):g(``,!0)])]))),128))])])):g(``,!0),S(`div`,jr,[S(`button`,{onClick:h,class:`flex-1 px-4 py-3 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary rounded-lg transition-colors`},` Cancel `),c.value.length>0&&a.value?(w(),C(`button`,{key:0,onClick:p,class:`flex-1 px-4 py-3 bg-primary/20 hover:bg-primary/30 border border-primary/50 text-primary rounded-lg transition-colors`},` Move & Delete `)):g(``,!0),S(`button`,{onClick:f,class:`flex-1 px-4 py-3 bg-accent-red/20 hover:bg-accent-red/30 border border-accent-red/50 text-accent-red rounded-lg transition-colors font-medium`},b(c.value.length>0?`Delete All`:`Delete`),1)])])])):g(``,!0)}}),Nr={class:`space-y-4 sm:space-y-6`},Pr={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3`},Fr={class:`flex gap-2 flex-wrap`},Ir=[`disabled`],Lr=[`disabled`],Rr={class:`glass-card rounded-[15px] p-3 sm:p-4 border border-stroke-subtle dark:border-stroke/10 bg-background-mute dark:bg-white/5`},zr={class:`flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3`},Br={class:`flex items-center gap-2 sm:gap-3`},Vr={class:`flex bg-background-mute dark:bg-stroke/5 rounded-lg border border-stroke-subtle dark:border-stroke/20 p-0.5 sm:p-1`},Hr={class:`glass-card rounded-[15px] p-3 sm:p-6 border border-stroke-subtle dark:border-stroke/10`},Ur={key:0,class:`flex items-center justify-center py-8`},Wr={key:1,class:`text-center py-8`},Gr={class:`text-content-secondary dark:text-content-muted text-sm`},Kr={key:2,class:`text-center py-8`},qr={key:3,class:`space-y-2`},Jr=f({name:`TransportKeys`,__name:`TransportKeys`,setup(e){let t=Yt(),n=j(),r=E(!1),o=E(!1),c=E(!1),d=E(null),f=E(null),p=E(`deny`);h(v(()=>n.stats?.config?.mesh?.unscoped_flood_allow??null),e=>{e!==null&&(p.value=e?`allow`:`deny`)},{immediate:!0});let m=E([]),g=E(!1),T=E(null),D=e=>{let t=new Map,n=[];return e.forEach(e=>{let n={id:e.id,name:e.name,floodPolicy:e.flood_policy,transport_key:e.transport_key,last_used:e.last_used?new Date(e.last_used*1e3):void 0,parent_id:e.parent_id,children:[]};t.set(e.id,n)}),t.forEach(e=>{e.parent_id&&t.has(e.parent_id)?t.get(e.parent_id).children.push(e):n.push(e)}),n},O=async()=>{try{g.value=!0,T.value=null;let e=await A.getTransportKeys();e.success&&e.data?m.value=D(e.data):T.value=e.error||`Failed to load transport keys`}catch(e){T.value=e instanceof Error?e.message:`Unknown error occurred`,console.error(`Error loading transport keys:`,e)}finally{g.value=!1}};s(()=>{O()});function k(e,t){for(let n of e){if(n.id===t)return n;if(n.children){let e=k(n.children,t);if(e)return e}}return null}function M(){let e=t.selectedNodeId.value;if(e)return k(m.value,e)?.name}function N(e){t.setSelectedNode(e)}function P(){r.value=!0}function F(){if(t.selectedNodeId.value){let e=k(m.value,t.selectedNodeId.value);e&&(f.value=e,c.value=!0)}}function I(){if(t.selectedNodeId.value){let e=k(m.value,t.selectedNodeId.value);e&&(d.value=e,o.value=!0)}}let L=async e=>{try{let t=await A.createTransportKey(e.name,e.floodPolicy,void 0,e.parentId,void 0);t.success?await O():(console.error(`Failed to add transport key:`,t.error),T.value=t.error||`Failed to add transport key`)}catch(e){console.error(`Error adding transport key:`,e),T.value=e instanceof Error?e.message:`Unknown error occurred`}finally{r.value=!1}};function R(){r.value=!1}async function z(e){try{let t=e===`allow`,r=await A.updateUnscopedFloodPolicy(t);r.success?(p.value=e,await n.fetchStats()):(console.error(`Failed to update unscoped flood policy:`,r.error),T.value=r.error||`Failed to update unscoped flood policy`)}catch(e){console.error(`Error updating unscoped flood policy:`,e),T.value=e instanceof Error?e.message:`Failed to update unscoped flood policy`}}function B(){o.value=!1,d.value=null}async function V(e){try{let t=await A.updateTransportKey(e.id,e.name,e.floodPolicy);t.success?await O():(console.error(`Failed to update transport key:`,t.error),T.value=t.error||`Failed to update transport key`)}catch(e){console.error(`Error updating transport key:`,e),T.value=e instanceof Error?e.message:`Unknown error occurred`}finally{B()}}function ee(e){o.value=!1,d.value=null,f.value=e,c.value=!0}function H(){c.value=!1,f.value=null}async function U(e){try{let n=await A.deleteTransportKey(e);n.success?(await O(),t.setSelectedNode(null)):(console.error(`Failed to delete transport key:`,n.error),T.value=n.error||`Failed to delete transport key`)}catch(e){console.error(`Error deleting transport key:`,e),T.value=e instanceof Error?e.message:`Unknown error occurred`}finally{H()}}async function W(e){try{let n=await A.deleteTransportKey(e.nodeId);n.success?(await O(),t.setSelectedNode(null)):(console.error(`Failed to delete transport key:`,n.error),T.value=n.error||`Failed to delete transport key`)}catch(e){console.error(`Error deleting transport key:`,e),T.value=e instanceof Error?e.message:`Unknown error occurred`}finally{H()}}return(e,n)=>(w(),C(`div`,Nr,[S(`div`,Pr,[n[3]||=S(`div`,null,[S(`h3`,{class:`text-base sm:text-lg font-semibold text-content-primary dark:text-content-primary mb-1 sm:mb-2`},` Regions/Keys `),S(`p`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},` Manage regional key hierarchy `)],-1),S(`div`,Fr,[S(`button`,{onClick:P,class:`flex items-center gap-1.5 sm:gap-2 px-2.5 sm:px-3 py-1.5 sm:py-2 rounded-lg border transition-colors text-xs sm:text-sm bg-accent-green/10 hover:bg-accent-green/20 text-accent-green border-accent-green/30`},[...n[2]||=[S(`svg`,{class:`w-3.5 h-3.5 sm:w-4 sm:h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 4v16m8-8H4`})],-1),y(` Add `,-1)]]),S(`button`,{onClick:I,disabled:!a(t).selectedNodeId.value,class:u([`px-2.5 sm:px-4 py-1.5 sm:py-2 rounded-lg border transition-colors text-xs sm:text-sm`,a(t).selectedNodeId.value?`bg-accent-green/20 hover:bg-accent-green/30 text-accent-green border-accent-green/50`:`bg-background-mute dark:bg-stroke/10 text-content-muted dark:text-content-muted/70 border-stroke-subtle dark:border-stroke/20 cursor-not-allowed`])},` Edit `,10,Ir),S(`button`,{onClick:F,disabled:!a(t).selectedNodeId.value,class:u([`px-2.5 sm:px-4 py-1.5 sm:py-2 rounded-lg border transition-colors text-xs sm:text-sm`,a(t).selectedNodeId.value?`bg-accent-red/20 hover:bg-accent-red/30 text-accent-red border-accent-red/50`:`bg-background-mute dark:bg-stroke/10 text-content-muted dark:text-content-muted/70 border-stroke-subtle dark:border-stroke/20 cursor-not-allowed`])},` Delete `,10,Lr)])]),S(`div`,Rr,[S(`div`,zr,[n[4]||=S(`div`,null,[S(`h4`,{class:`text-xs sm:text-sm font-medium text-content-primary dark:text-content-primary mb-1`},` Unscoped Flood Policy (*) `),S(`p`,{class:`text-content-secondary dark:text-content-muted text-[10px] sm:text-xs`},` Allow or Deny unscoped flood packets `)],-1),S(`div`,Br,[S(`div`,Vr,[S(`button`,{onClick:n[0]||=e=>z(`deny`),class:u([`px-2 sm:px-3 py-1 text-[10px] sm:text-xs font-medium rounded transition-colors`,p.value===`deny`?`bg-accent-red/20 text-accent-red border border-accent-red/50`:`text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-secondary`])},` DENY `,2),S(`button`,{onClick:n[1]||=e=>z(`allow`),class:u([`px-2 sm:px-3 py-1 text-[10px] sm:text-xs font-medium rounded transition-colors`,p.value===`allow`?`bg-accent-green/20 text-accent-green border border-accent-green/50`:`text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-secondary`])},` ALLOW `,2)])])])]),S(`div`,Hr,[g.value?(w(),C(`div`,Ur,[...n[5]||=[S(`div`,{class:`animate-spin rounded-full h-8 w-8 border-b-2 border-accent-green`},null,-1),S(`span`,{class:`ml-2 text-content-secondary dark:text-content-muted`},`Loading transport keys...`,-1)]])):T.value?(w(),C(`div`,Wr,[n[6]||=S(`div`,{class:`text-accent-red mb-2`},`⚠️ Error loading transport keys`,-1),S(`div`,Gr,b(T.value),1),S(`button`,{onClick:O,class:`mt-4 px-4 py-2 bg-accent-green/20 hover:bg-accent-green/30 text-accent-green border border-accent-green/50 rounded-lg transition-colors`},` Retry `)])):m.value.length===0?(w(),C(`div`,Kr,[...n[7]||=[S(`div`,{class:`text-content-muted dark:text-content-muted mb-2`},` 📝 No transport keys found `,-1),S(`div`,{class:`text-content-muted dark:text-content-muted/60 text-sm`},` Add your first transport key to get started `,-1)]])):(w(),C(`div`,qr,[(w(!0),C(x,null,i(m.value,e=>(w(),l(mn,{key:e.id,node:e,"selected-node-id":a(t).selectedNodeId.value,level:0,onSelect:N},null,8,[`node`,`selected-node-id`]))),128))]))]),_(Fn,{show:r.value,"selected-node-name":M(),"selected-node-id":a(t).selectedNodeId.value||void 0,onClose:R,onAdd:L},null,8,[`show`,`selected-node-name`,`selected-node-id`]),_(cr,{show:o.value,node:d.value,onClose:B,onSave:V,onRequestDelete:ee},null,8,[`show`,`node`]),_(Mr,{show:c.value,node:f.value,"all-nodes":m.value,onClose:H,onDeleteAll:U,onMoveChildren:W},null,8,[`show`,`node`,`all-nodes`])]))}}),Yr={class:`space-y-4 sm:space-y-6`},Xr={class:`flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3`},Zr={key:0,class:`bg-red-500/10 border border-red-500/30 rounded-lg p-4`},Qr={class:`flex items-center gap-2 text-red-600 dark:text-red-400`},$r={key:1,class:`flex items-center justify-center py-12`},ei={key:2,class:`space-y-3`},ti={class:`flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3`},ni={class:`flex-1`},ri={class:`flex items-center gap-2 sm:gap-3`},ii={class:`min-w-0 flex-1`},ai={class:`text-content-primary dark:text-content-primary font-medium text-sm sm:text-base break-all`},oi={class:`flex flex-col sm:flex-row sm:items-center sm:gap-4 mt-1 text-xs text-content-secondary dark:text-content-muted`},si={class:`truncate`},ci={class:`truncate`},li=[`onClick`,`disabled`],ui={key:3,class:`text-center py-12`},di={class:`bg-surface dark:bg-surface-elevated border border-stroke-subtle dark:border-stroke/20 rounded-[15px] p-6 max-w-md w-full shadow-2xl`},fi={class:`space-y-4`},pi={class:`flex justify-end gap-3 mt-6`},mi=[`disabled`],hi=[`disabled`],gi={class:`bg-surface dark:bg-surface-elevated border border-stroke-subtle dark:border-stroke/20 rounded-[15px] p-6 max-w-lg w-full shadow-2xl`},_i={class:`space-y-4`},vi={class:`flex gap-2`},yi=[`value`],bi={class:`bg-blue-500/10 border border-blue-500/30 rounded-lg p-4`},xi={class:`block bg-blue-500/20 px-3 py-2 rounded text-xs text-blue-100 font-mono overflow-x-auto`},Si=f({name:`APITokens`,__name:`APITokens`,setup(e){let t=E([]),n=E(!1),r=E(null),a=E(!1),o=E(``),c=E(null),l=E(!1),u=E(!1),f=E(null),p=async()=>{n.value=!0,r.value=null;try{let e=await A.get(`/auth/tokens`);t.value=(e.data||e).tokens||[]}catch(e){console.error(`Failed to fetch API tokens:`,e),r.value=e instanceof Error?e.message:`Failed to fetch tokens`}finally{n.value=!1}},h=async()=>{if(!o.value.trim()){r.value=`Token name is required`;return}n.value=!0,r.value=null;try{let e=await A.post(`/auth/tokens`,{name:o.value.trim()});c.value=(e.data||e).token||null,a.value=!1,l.value=!0,o.value=``,await p()}catch(e){console.error(`Failed to create API token:`,e),r.value=e instanceof Error?e.message:`Failed to create token`}finally{n.value=!1}},T=(e,t)=>{f.value={id:e,name:t},u.value=!0},D=async()=>{if(f.value){n.value=!0,r.value=null;try{await A.delete(`/auth/tokens/${f.value.id}`),await p(),u.value=!1,f.value=null}catch(e){console.error(`Failed to revoke API token:`,e),r.value=e instanceof Error?e.message:`Failed to revoke token`}finally{n.value=!1}}},O=()=>{a.value=!1,o.value=``,r.value=null},k=()=>{l.value=!1,c.value=null},j=()=>{c.value&&navigator.clipboard.writeText(c.value)},M=e=>e?new Date(e*1e3).toLocaleString():`Never`,N=v(()=>`${window.location.origin}/api/stats`);return s(()=>{p()}),(e,s)=>(w(),C(x,null,[S(`div`,Yr,[S(`div`,Xr,[s[5]||=S(`div`,null,[S(`h2`,{class:`text-lg sm:text-xl font-semibold text-content-primary dark:text-content-primary`},` API Tokens `),S(`p`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm mt-1`},` Manage API tokens for machine-to-machine authentication `)],-1),S(`button`,{onClick:s[0]||=e=>a.value=!0,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors flex items-center justify-center gap-2 text-sm sm:text-base`},[...s[4]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 4v16m8-8H4`})],-1),y(` Create Token `,-1)]])]),s[20]||=d(`API tokens are used for machine-to-machine authentication. Include the token in the X-API-Key header when making API requests.
Tokens are only shown once at creation. Store them securely.
`,1),r.value?(w(),C(`div`,Zr,[S(`div`,Qr,[s[6]||=S(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),y(` `+b(r.value),1)])])):g(``,!0),n.value&&t.value.length===0?(w(),C(`div`,$r,[...s[7]||=[S(`div`,{class:`text-center`},[S(`div`,{class:`animate-spin w-8 h-8 border-2 border-stroke-subtle dark:border-stroke/20 border-t-primary rounded-full mx-auto mb-4`}),S(`div`,{class:`text-content-secondary dark:text-content-muted`},`Loading tokens...`)],-1)]])):t.value.length>0?(w(),C(`div`,ei,[(w(!0),C(x,null,i(t.value,e=>(w(),C(`div`,{key:e.id,class:`bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg p-3 sm:p-4 hover:bg-stroke-subtle dark:hover:bg-white/10 transition-colors`},[S(`div`,ti,[S(`div`,ni,[S(`div`,ri,[s[8]||=S(`svg`,{class:`w-4 h-4 sm:w-5 sm:h-5 text-primary flex-shrink-0`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`})],-1),S(`div`,ii,[S(`h3`,ai,b(e.name),1),S(`div`,oi,[S(`span`,si,`Created: `+b(M(e.created_at)),1),S(`span`,ci,`Last used: `+b(M(e.last_used)),1)])])])]),S(`button`,{onClick:t=>T(e.id,e.name),disabled:n.value,class:`w-full sm:w-auto px-3 py-1.5 bg-red-100 dark:bg-red-500/20 hover:bg-red-500/30 text-red-600 dark:text-red-400 rounded-lg border border-red-500/50 transition-colors disabled:opacity-50 text-sm`},` Revoke `,8,li)])]))),128))])):(w(),C(`div`,ui,[s[9]||=S(`svg`,{class:`w-16 h-16 text-content-muted dark:text-content-muted/40 mx-auto mb-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`})],-1),s[10]||=S(`h3`,{class:`text-content-primary dark:text-content-primary font-medium mb-2`},`No API Tokens`,-1),s[11]||=S(`p`,{class:`text-content-secondary dark:text-content-muted text-sm mb-4`},` Create a token to enable API access `,-1),S(`button`,{onClick:s[1]||=e=>a.value=!0,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors`},` Create Your First Token `)])),a.value?(w(),C(`div`,{key:4,class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm`,onClick:I(O,[`self`])},[S(`div`,di,[s[14]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary mb-4`},` Create API Token `,-1),S(`div`,fi,[S(`div`,null,[s[12]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},`Token Name`,-1),m(S(`input`,{"onUpdate:modelValue":s[2]||=e=>o.value=e,type:`text`,placeholder:`e.g., Production Server, CI/CD Pipeline`,class:`w-full px-4 py-2 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary placeholder-gray-400 dark:placeholder-white/40 focus:outline-none focus:border-primary transition-colors`,onKeydown:R(h,[`enter`])},null,544),[[F,o.value]]),s[13]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted mt-1`},` Give your token a descriptive name to identify its purpose `,-1)]),S(`div`,pi,[S(`button`,{onClick:O,disabled:n.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/10 transition-colors disabled:opacity-50`},` Cancel `,8,mi),S(`button`,{onClick:h,disabled:n.value||!o.value.trim(),class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors disabled:opacity-50`},b(n.value?`Creating...`:`Create Token`),9,hi)])])])])):g(``,!0),l.value&&c.value?(w(),C(`div`,{key:5,class:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm`,onClick:I(k,[`self`])},[S(`div`,gi,[s[19]||=S(`h3`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary mb-4`},` Token Created Successfully `,-1),S(`div`,_i,[s[18]||=d(`Save this token now! For security reasons, it will not be shown again.
`,1),S(`div`,null,[s[16]||=S(`label`,{class:`block text-sm font-medium text-content-secondary dark:text-content-muted mb-2`},`Your API Token`,-1),S(`div`,vi,[S(`input`,{value:c.value,readonly:``,class:`flex-1 px-4 py-2 bg-background-mute dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary font-mono text-sm`},null,8,yi),S(`button`,{onClick:j,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors flex items-center gap-2`,title:`Copy to clipboard`},[...s[15]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z`})],-1),y(` Copy `,-1)]])])]),S(`div`,bi,[s[17]||=S(`p`,{class:`text-sm text-blue-200 mb-2`},[S(`strong`,null,`Usage Example:`)],-1),S(`code`,xi,` curl -H "X-API-Key: `+b(c.value)+`" `+b(N.value),1)]),S(`div`,{class:`flex justify-end mt-6`},[S(`button`,{onClick:k,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors`},` Done `)])])])])):g(``,!0)]),_(V,{show:u.value,title:`Revoke API Token`,message:`Are you sure you want to revoke the token '${f.value?.name}'? This action cannot be undone.`,"confirm-text":`Revoke`,"cancel-text":`Cancel`,variant:`danger`,onConfirm:D,onClose:s[3]||=e=>u.value=!1},null,8,[`show`,`message`])],64))}}),Ci={class:`space-y-6`},wi={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Ti={class:`space-y-4`},Ei={class:`flex items-center justify-between`},Di=[`disabled`],Oi={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},ki={class:`space-y-4`},Ai={class:`space-y-3`},ji=[`checked`,`disabled`],Mi=[`checked`,`disabled`],Ni={class:`flex items-start gap-3`},Pi={key:0,class:`w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0 mt-0.5`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},Fi={key:1,class:`w-5 h-5 text-accent-cyan flex-shrink-0 mt-0.5`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},Ii={class:`flex-1`},Li={class:`text-sm font-medium text-content-primary dark:text-content-primary`},Ri={key:0,class:`text-xs text-green-600 dark:text-green-400 mt-1`},zi={key:1,class:`p-4 bg-amber-500/10 border border-amber-500/30 rounded-lg`},Bi={class:`flex items-start justify-between gap-3`},Vi=[`disabled`],Hi={key:0,class:`animate-spin h-4 w-4`,fill:`none`,viewBox:`0 0 24 24`},Ui={key:1,class:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},Wi={class:`flex items-center space-x-2`},Gi={key:0,class:`w-5 h-5 text-green-600 dark:text-green-400`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},Ki={key:1,class:`w-5 h-5 text-red-600 dark:text-red-400`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`},qi=f({name:`WebSettings`,__name:`WebSettings`,setup(e){let t=E(!1),n=E(``),r=E(!1),i=E(!1),a=E(!1),c=E(!1),l=E(!0),f=o({cors_enabled:!1,use_default_frontend:!0}),p=v(()=>r.value?`bg-green-500/10 border-green-600/40 dark:border-green-500/30`:`bg-red-500/10 border-red-500/30`);async function m(){try{l.value=!0;let e=await A.get(`/check_pymc_console`);e.success&&e.data&&(c.value=e.data.exists,console.log(`PyMC Console exists:`,c.value))}catch(e){console.error(`Failed to check PyMC Console:`,e),c.value=!1}finally{l.value=!1}}async function h(){try{let e=await A.get(`/stats`);console.log(`WebSettings: Full response:`,e);let t=null;if(e.success&&e.data?t=e.data:e&&`version`in e&&(t=e),t){let e=t.config?.web||{};console.log(`WebSettings: webConfig:`,e),f.cors_enabled=e.cors_enabled===!0,console.log(`WebSettings: Set cors_enabled to:`,f.cors_enabled);let n=e.web_path;f.use_default_frontend=!n||n===``,console.log(`WebSettings: Set use_default_frontend to:`,f.use_default_frontend,`from web_path:`,n)}}catch(e){console.error(`Failed to load web settings:`,e),k(`Failed to load settings`,!1)}}async function _(){t.value=!0,n.value=``;try{let e={web:{cors_enabled:f.cors_enabled}};f.use_default_frontend?e.web.web_path=null:e.web.web_path=`/opt/pymc_console/web/html`;let t=await A.post(`/update_web_config`,e);t.success?(k(`Settings saved successfully`,!0),i.value=!0):k(t.error||`Failed to save settings`,!1)}catch(e){console.error(`Failed to save web settings:`,e),k(e.message||`Failed to save settings`,!1)}finally{t.value=!1}}async function T(){f.cors_enabled=!f.cors_enabled,await _()}async function D(){f.use_default_frontend=!0,await _()}async function O(){f.use_default_frontend=!1,await _()}function k(e,t){n.value=e,r.value=t,setTimeout(()=>{n.value=``},5e3)}async function j(){a.value=!0,n.value=``;try{let e=await A.post(`/restart_service`,{});e.success?(k(`Service restart initiated. Page will reload...`,!0),i.value=!1,setTimeout(()=>{window.location.reload()},2e3)):k(e.error||`Failed to restart service`,!1)}catch(e){e.code===`ERR_NETWORK`||e.message?.includes(`Network error`)?(k(`Service restarting... Page will reload`,!0),i.value=!1,setTimeout(()=>{window.location.reload()},3e3)):(console.error(`Failed to restart service:`,e),k(e.message||`Failed to restart service`,!1))}finally{a.value=!1}}return s(()=>{h(),m()}),(e,o)=>(w(),C(`div`,Ci,[S(`div`,wi,[o[1]||=S(`div`,{class:`flex items-start justify-between mb-4`},[S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` CORS Settings `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Control cross-origin resource sharing for API access `)])],-1),S(`div`,Ti,[S(`div`,Ei,[o[0]||=S(`div`,null,[S(`label`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},`Enable CORS`),S(`p`,{class:`text-xs text-content-secondary dark:text-content-muted mt-1`},` Allow web frontends from different origins to access the API `)],-1),S(`button`,{onClick:T,disabled:t.value,class:u([`relative inline-flex h-6 w-11 items-center rounded-full transition-colors border-2`,f.cors_enabled?`bg-cyan-600 dark:bg-teal-500 border-cyan-600 dark:border-teal-500`:`bg-gray-400 dark:bg-gray-600 border-gray-400 dark:border-gray-600`,t.value?`opacity-50 cursor-not-allowed`:`cursor-pointer`])},[S(`span`,{class:u([`inline-block h-4 w-4 transform rounded-full bg-white transition-transform shadow-lg`,f.cors_enabled?`translate-x-5`:`translate-x-0.5`])},null,2)],10,Di)])])]),S(`div`,Oi,[o[11]||=S(`div`,{class:`flex items-start justify-between mb-4`},[S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Web Frontend `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Choose which web interface to use `)])],-1),S(`div`,ki,[S(`div`,Ai,[S(`label`,{class:u([`flex items-start space-x-3 p-4 bg-background-mute dark:bg-background/30 rounded-lg border-2 cursor-pointer transition-all`,f.use_default_frontend?`border-accent-cyan bg-accent-cyan/10`:`border-stroke-subtle dark:border-stroke/10 hover:border-accent-cyan/50`])},[S(`input`,{type:`radio`,name:`frontend`,checked:f.use_default_frontend,onChange:D,disabled:t.value,class:`mt-1 h-4 w-4 text-accent-cyan focus:ring-accent-cyan focus:ring-offset-background`},null,40,ji),o[2]||=S(`div`,{class:`flex-1`},[S(`div`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},` Default Frontend `),S(`div`,{class:`text-xs text-content-secondary dark:text-content-muted mt-1`},` Built-in pyMC Repeater web interface `),S(`div`,{class:`text-xs text-content-muted dark:text-content-muted/60 mt-1 font-mono`},` Built-in `)],-1)],2),S(`label`,{class:u([`flex items-start space-x-3 p-4 bg-background-mute dark:bg-background/30 rounded-lg border-2 cursor-pointer transition-all`,f.use_default_frontend?`border-stroke-subtle dark:border-stroke/10 hover:border-accent-cyan/50`:`border-accent-cyan bg-accent-cyan/10`])},[S(`input`,{type:`radio`,name:`frontend`,checked:!f.use_default_frontend,onChange:O,disabled:t.value,class:`mt-1 h-4 w-4 text-accent-cyan focus:ring-accent-cyan focus:ring-offset-background`},null,40,Mi),o[3]||=d(` Alternative web interface for pyMC Repeater
/opt/pymc_console/web/html
`,1)],2)]),l.value?g(``,!0):(w(),C(`div`,{key:0,class:u([`p-4 rounded-lg border`,c.value?`bg-green-500/5 border-green-500/20`:`bg-accent-cyan/5 border-accent-cyan/20`])},[S(`div`,Ni,[c.value?(w(),C(`svg`,Pi,[...o[4]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]])):(w(),C(`svg`,Fi,[...o[5]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]])),S(`div`,Ii,[S(`h4`,Li,b(c.value?`PyMC Console has been detected`:`PyMC Console Not Installed`),1),c.value?(w(),C(`p`,Ri,[...o[6]||=[y(` PyMC Console is installed at `,-1),S(`code`,{class:`text-green-700 dark:text-green-300`},`/opt/pymc_console/web/html`,-1)]])):(w(),C(x,{key:1},[o[7]||=d(` PyMC Console must be installed at /opt/pymc_console/web/html before selecting this option.
PyMC Console Install Instructions `,2)],64))])])],2)),i.value?(w(),C(`div`,zi,[S(`div`,Bi,[o[10]||=d(` Service restart required Web frontend changes will take effect after restarting the pymc-repeater service.
`,1),S(`button`,{onClick:j,disabled:a.value,class:`px-4 py-2 bg-amber-500 hover:bg-amber-600 disabled:bg-amber-500/50 text-white font-medium rounded-lg transition-colors disabled:cursor-not-allowed flex items-center gap-2 whitespace-nowrap`},[a.value?(w(),C(`svg`,Hi,[...o[8]||=[S(`circle`,{class:`opacity-25`,cx:`12`,cy:`12`,r:`10`,stroke:`currentColor`,"stroke-width":`4`},null,-1),S(`path`,{class:`opacity-75`,fill:`currentColor`,d:`M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z`},null,-1)]])):(w(),C(`svg`,Ui,[...o[9]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15`},null,-1)]])),y(` `+b(a.value?`Restarting...`:`Restart Now`),1)],8,Vi)])])):g(``,!0)])]),n.value?(w(),C(`div`,{key:0,class:u([`p-4 rounded-lg border`,p.value])},[S(`div`,Wi,[r.value?(w(),C(`svg`,Gi,[...o[12]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M5 13l4 4L19 7`},null,-1)]])):(w(),C(`svg`,Ki,[...o[13]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`},null,-1)]])),S(`span`,{class:u(r.value?`text-green-600 dark:text-green-400`:`text-red-600 dark:text-red-400`)},b(n.value),3)])],2)):g(``,!0)]))}}),Ji={class:`space-y-4`},Yi={key:0,class:`bg-green-100 dark:bg-green-500/20 border border-green-500 dark:border-green-500/50 rounded-lg p-3 text-green-700 dark:text-green-400 text-sm`},Xi={key:1,class:`bg-red-100 dark:bg-red-500/20 border border-red-500 dark:border-red-500/50 rounded-lg p-3 text-red-700 dark:text-red-400 text-sm`},Zi={class:`flex justify-between items-center`},Qi={class:`flex gap-2`},$i=[`disabled`],ea={class:`flex gap-2`},ta=[`disabled`],na=[`disabled`],ra={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},ia={key:0,class:`flex items-center justify-center py-4`},aa={key:1,class:`text-center py-4`},oa={class:`grid grid-cols-2 sm:grid-cols-4 gap-3`},sa={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},ca={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},la={class:`text-lg font-mono text-content-primary dark:text-content-primary`},ua={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},da={class:`text-lg font-mono text-green-600 dark:text-green-400`},fa={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},pa={class:`text-lg font-mono text-red-600 dark:text-red-400`},ma={key:0,class:`mt-2 p-2 bg-red-50 dark:bg-red-500/10 rounded-lg border border-red-200 dark:border-red-500/30`},ha={key:1,class:`mt-2 p-2 bg-orange-50 dark:bg-orange-500/10 rounded-lg border border-orange-200 dark:border-orange-500/30`},ga={class:`font-medium`},_a={class:`font-mono text-[10px] opacity-70`},va={class:`text-[10px]`},ya={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},ba={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},xa={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Sa={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ca={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},wa={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ta={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ea={key:1,class:`flex items-center gap-2`},Da={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 gap-1`},Oa={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},ka={key:1,class:`flex items-center gap-2`},Aa={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},ja={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ma={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Na={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Pa={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Fa={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ia={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},La={key:1,class:`flex items-center gap-2`},Ra={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},za={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ba={key:1,class:`flex items-center gap-2`},Va={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 gap-1`},Ha={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ua={key:1,class:`flex items-center gap-2`},Wa={class:`bg-background-mute dark:bg-white/5 rounded-lg p-3 sm:p-4 space-y-3`},Ga={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ka={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},qa={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center py-2 border-b border-stroke-subtle dark:border-stroke/10 gap-1`},Ja={key:0,class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ya={key:1,class:`flex items-center gap-2`},Xa={class:`py-2`},Za={class:`grid grid-cols-3 gap-2 mt-2`},Qa={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},$a={key:0,class:`font-mono text-sm text-content-primary dark:text-content-primary`},eo={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},to={key:0,class:`font-mono text-sm text-content-primary dark:text-content-primary`},no={class:`text-center p-2 bg-white dark:bg-white/5 rounded-lg`},ro={key:0,class:`font-mono text-sm text-content-primary dark:text-content-primary`},io={class:`p-6 space-y-4`},ao={class:`flex justify-between items-start`},oo={class:`flex justify-end pt-4 border-t border-stroke-subtle dark:border-stroke/20`},so=f({__name:`AdvertSettings`,setup(e){let t=j(),n=v(()=>t.stats?.config?.repeater||{}),r=v(()=>n.value.advert_rate_limit||{}),a=v(()=>n.value.advert_penalty_box||{}),o=v(()=>n.value.advert_adaptive||{}),l=v(()=>o.value.thresholds||{}),f=E(!1),p=E(!1),_=E(``),T=E(``),D=E(!1),O=E(!1),A=E(null),M=E(!0),N=E(2),L=E(1),R=E(10),z=E(60),B=E(!0),V=E(2),ee=E(12),H=E(6),U=E(2),W=E(24),G=E(!0),te=E(.1),K=E(5),ne=E(.05),q=E(.2),J=E(.5),Y=async()=>{O.value=!0;try{let e=await k.get(`/api/advert_rate_limit_stats`);e.data?.success&&(A.value=e.data.data)}catch(e){console.error(`Failed to fetch rate limit stats:`,e)}finally{O.value=!1}};h([r,a,o],()=>{f.value||(M.value=r.value.enabled??!1,N.value=r.value.bucket_capacity??2,L.value=r.value.refill_tokens??1,R.value=Math.round((r.value.refill_interval_seconds??36e3)/3600),z.value=Math.round((r.value.min_interval_seconds??0)/60),B.value=a.value.enabled??!1,V.value=a.value.violation_threshold??2,ee.value=Math.round((a.value.violation_decay_seconds??43200)/3600),H.value=Math.round((a.value.base_penalty_seconds??21600)/3600),U.value=a.value.penalty_multiplier??2,W.value=Math.round((a.value.max_penalty_seconds??86400)/3600),G.value=o.value.enabled??!1,te.value=o.value.ewma_alpha??.1,K.value=Math.round((o.value.hysteresis_seconds??300)/60),ne.value=l.value.quiet_max??.05,q.value=l.value.normal_max??.2,J.value=l.value.busy_max??.5)},{immediate:!0}),s(()=>{Y()});let X=()=>{M.value=r.value.enabled??!1,N.value=r.value.bucket_capacity??2,L.value=r.value.refill_tokens??1,R.value=Math.round((r.value.refill_interval_seconds??36e3)/3600),z.value=Math.round((r.value.min_interval_seconds??0)/60),B.value=a.value.enabled??!1,V.value=a.value.violation_threshold??2,ee.value=Math.round((a.value.violation_decay_seconds??43200)/3600),H.value=Math.round((a.value.base_penalty_seconds??21600)/3600),U.value=a.value.penalty_multiplier??2,W.value=Math.round((a.value.max_penalty_seconds??86400)/3600),G.value=o.value.enabled??!1,te.value=o.value.ewma_alpha??.1,K.value=Math.round((o.value.hysteresis_seconds??300)/60),ne.value=l.value.quiet_max??.05,q.value=l.value.normal_max??.2,J.value=l.value.busy_max??.5},Z=()=>{f.value=!0,_.value=``,T.value=``},Q=()=>{f.value=!1,_.value=``,T.value=``,X()},re=async()=>{p.value=!0,T.value=``,_.value=``;try{let e={rate_limit_enabled:M.value,bucket_capacity:N.value,refill_tokens:L.value,refill_interval_seconds:R.value*3600,min_interval_seconds:z.value*60,penalty_enabled:B.value,violation_threshold:V.value,violation_decay_seconds:ee.value*3600,base_penalty_seconds:H.value*3600,penalty_multiplier:U.value,max_penalty_seconds:W.value*3600,adaptive_enabled:G.value,ewma_alpha:te.value,hysteresis_seconds:K.value*60,quiet_max:ne.value,normal_max:q.value,busy_max:J.value},n=(await k.post(`/api/update_advert_rate_limit_config`,e)).data;n.success?(_.value=n.data?.message||`Settings saved successfully`,await t.fetchStats(),await Y(),await c(),X(),f.value=!1,setTimeout(()=>{_.value=``},3e3)):(T.value=n.error||`Failed to save settings`,console.error(`[AdvertSettings] Save failed:`,n.error))}catch(e){console.error(`Failed to save advert settings:`,e),T.value=e.response?.data?.error||`Failed to save settings`}finally{p.value=!1}},$=v(()=>A.value?.adaptive?.current_tier||`unknown`),ie=v(()=>{switch($.value){case`quiet`:return`bg-green-100 dark:bg-green-500/20 text-green-700 dark:text-green-400 border-green-500`;case`normal`:return`bg-blue-100 dark:bg-blue-500/20 text-blue-700 dark:text-blue-400 border-blue-500`;case`busy`:return`bg-yellow-100 dark:bg-yellow-500/20 text-yellow-700 dark:text-yellow-400 border-yellow-500`;case`congested`:return`bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400 border-red-500`;default:return`bg-gray-100 dark:bg-gray-500/20 text-gray-700 dark:text-gray-400 border-gray-500`}});return(e,t)=>(w(),C(`div`,Ji,[_.value?(w(),C(`div`,Yi,b(_.value),1)):g(``,!0),T.value?(w(),C(`div`,Xi,b(T.value),1)):g(``,!0),S(`div`,Zi,[S(`div`,Qi,[S(`button`,{onClick:Y,disabled:O.value,class:`px-3 py-1.5 text-xs bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-secondary dark:text-content-muted rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors disabled:opacity-50`},b(O.value?`Loading...`:`Refresh Stats`),9,$i),S(`button`,{onClick:t[0]||=e=>D.value=!0,class:`px-3 py-1.5 text-xs bg-blue-100 dark:bg-blue-500/20 hover:bg-blue-200 dark:hover:bg-blue-500/30 text-blue-700 dark:text-blue-400 rounded-lg border border-blue-500/50 transition-colors`,title:`How rate limiting works`},[...t[19]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`})],-1)]])]),S(`div`,ea,[f.value?(w(),C(x,{key:1},[S(`button`,{onClick:Q,disabled:p.value,class:`px-3 sm:px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg border border-stroke-subtle dark:border-stroke/20 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},` Cancel `,8,ta),S(`button`,{onClick:re,disabled:p.value,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},b(p.value?`Saving...`:`Save Changes`),9,na)],64)):(w(),C(`button`,{key:0,onClick:Z,class:`px-3 sm:px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors text-sm`},` Edit Settings `))])]),S(`div`,ra,[t[28]||=S(`h3`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},` Current Status `,-1),O.value&&!A.value?(w(),C(`div`,ia,[...t[20]||=[S(`div`,{class:`animate-spin w-5 h-5 border-2 border-stroke-subtle dark:border-stroke/20 border-t-cyan-500 dark:border-t-primary rounded-full`},null,-1),S(`span`,{class:`ml-2 text-sm text-content-muted`},`Loading stats...`,-1)]])):A.value?(w(),C(x,{key:2},[S(`div`,oa,[S(`div`,sa,[t[22]||=S(`div`,{class:`text-xs text-content-muted dark:text-content-muted`},`Mesh Tier`,-1),S(`div`,{class:u([`mt-1 px-2 py-0.5 rounded border text-xs font-medium inline-block`,ie.value])},b($.value.toUpperCase()),3)]),S(`div`,ca,[t[23]||=S(`div`,{class:`text-xs text-content-muted dark:text-content-muted`},`Adverts/min`,-1),S(`div`,la,b(A.value.metrics?.adverts_per_min_ewma?.toFixed(2)||`0.00`),1)]),S(`div`,ua,[t[24]||=S(`div`,{class:`text-xs text-content-muted dark:text-content-muted`},`Allowed`,-1),S(`div`,da,b(A.value.stats?.adverts_allowed||0),1)]),S(`div`,fa,[t[25]||=S(`div`,{class:`text-xs text-content-muted dark:text-content-muted`},`Dropped`,-1),S(`div`,pa,b(A.value.stats?.adverts_dropped||0),1)])]),Object.keys(A.value.active_penalties||{}).length>0?(w(),C(`div`,ma,[t[26]||=S(`div`,{class:`text-xs font-medium text-red-700 dark:text-red-400 mb-1`},` Active Penalties `,-1),(w(!0),C(x,null,i(A.value.active_penalties,(e,t)=>(w(),C(`div`,{key:t,class:`text-xs font-mono text-red-600 dark:text-red-400`},b(t)+`... - `+b(Math.round(e))+`s remaining `,1))),128))])):g(``,!0),A.value.recent_drops&&A.value.recent_drops.length>0?(w(),C(`div`,ha,[t[27]||=S(`div`,{class:`text-xs font-medium text-orange-700 dark:text-orange-400 mb-1`},` Recently Dropped Adverts `,-1),(w(!0),C(x,null,i(A.value.recent_drops,(e,t)=>(w(),C(`div`,{key:t,class:`text-xs text-orange-600 dark:text-orange-400 py-0.5`},[S(`span`,ga,b(e.name),1),S(`span`,_a,`(`+b(e.pubkey)+`...)`,1),S(`span`,va,` - `+b(e.reason)+` (`+b(e.seconds_ago)+`s ago)`,1)]))),128))])):g(``,!0)],64)):(w(),C(`div`,aa,[...t[21]||=[S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Stats not available. Click "Refresh Stats" to load. `,-1)]]))]),S(`div`,ya,[t[36]||=S(`h3`,{class:`text-sm font-medium text-content-primary dark:text-content-primary flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`})]),y(` Token Bucket Rate Limiting `)],-1),t[37]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Controls how many adverts each pubkey can send in a given time period. `,-1),S(`div`,ba,[t[30]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Rate Limiting`,-1),f.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[1]||=e=>M.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[29]||=[S(`option`,{value:!0},`Enabled`,-1),S(`option`,{value:!1},`Disabled`,-1)]],512)),[[P,M.value]]):(w(),C(`div`,xa,b(M.value?`Enabled`:`Disabled`),1))]),S(`div`,Sa,[t[31]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Bucket Capacity`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`Max burst size (adverts)`)],-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[2]||=e=>N.value=e,type:`number`,min:`1`,max:`10`,class:`w-full sm:w-24 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,N.value,void 0,{number:!0}]]):(w(),C(`div`,Ca,b(N.value),1))]),S(`div`,wa,[t[33]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Refill Interval`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Time between token refills `)],-1),f.value?(w(),C(`div`,Ea,[m(S(`input`,{"onUpdate:modelValue":t[3]||=e=>R.value=e,type:`number`,min:`1`,max:`48`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,R.value,void 0,{number:!0}]]),t[32]||=S(`span`,{class:`text-content-muted text-sm`},`hours`,-1)])):(w(),C(`div`,Ta,b(R.value)+` hours `,1))]),S(`div`,Da,[t[35]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Minimum Interval`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Hard minimum between adverts `)],-1),f.value?(w(),C(`div`,ka,[m(S(`input`,{"onUpdate:modelValue":t[4]||=e=>z.value=e,type:`number`,min:`0`,max:`1440`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,z.value,void 0,{number:!0}]]),t[34]||=S(`span`,{class:`text-content-muted text-sm`},`min`,-1)])):(w(),C(`div`,Oa,b(z.value)+` min `,1))])]),S(`div`,Aa,[t[47]||=S(`h3`,{class:`text-sm font-medium text-content-primary dark:text-content-primary flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636`})]),y(` Penalty Box (Repeat Offenders) `)],-1),t[48]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Applies escalating cooldowns to pubkeys that repeatedly violate limits. `,-1),S(`div`,ja,[t[39]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Penalty Box`,-1),f.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[5]||=e=>B.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[38]||=[S(`option`,{value:!0},`Enabled`,-1),S(`option`,{value:!1},`Disabled`,-1)]],512)),[[P,B.value]]):(w(),C(`div`,Ma,b(B.value?`Enabled`:`Disabled`),1))]),S(`div`,Na,[t[40]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Violation Threshold`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},` Violations before penalty `)],-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[6]||=e=>V.value=e,type:`number`,min:`1`,max:`10`,class:`w-full sm:w-24 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512)),[[F,V.value,void 0,{number:!0}]]):(w(),C(`div`,Pa,b(V.value),1))]),S(`div`,Fa,[t[42]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Base Penalty Duration`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`First penalty duration`)],-1),f.value?(w(),C(`div`,La,[m(S(`input`,{"onUpdate:modelValue":t[7]||=e=>H.value=e,type:`number`,min:`1`,max:`48`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,H.value,void 0,{number:!0}]]),t[41]||=S(`span`,{class:`text-content-muted text-sm`},`hours`,-1)])):(w(),C(`div`,Ia,b(H.value)+` hours `,1))]),S(`div`,Ra,[t[44]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Penalty Multiplier`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`Escalation factor`)],-1),f.value?(w(),C(`div`,Ba,[m(S(`input`,{"onUpdate:modelValue":t[8]||=e=>U.value=e,type:`number`,min:`1`,max:`5`,step:`0.5`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,U.value,void 0,{number:!0}]]),t[43]||=S(`span`,{class:`text-content-muted text-sm`},`x`,-1)])):(w(),C(`div`,za,b(U.value)+`x `,1))]),S(`div`,Va,[t[46]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Max Penalty Duration`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`Maximum cooldown cap`)],-1),f.value?(w(),C(`div`,Ua,[m(S(`input`,{"onUpdate:modelValue":t[9]||=e=>W.value=e,type:`number`,min:`1`,max:`168`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,W.value,void 0,{number:!0}]]),t[45]||=S(`span`,{class:`text-content-muted text-sm`},`hours`,-1)])):(w(),C(`div`,Ha,b(W.value)+` hours `,1))])]),S(`div`,Wa,[t[58]||=d(` Adaptive Rate Limiting How the three systems work together: Each layer can be enabled/disabled independently and the others will still function.
Rate Limiting OFF: All limiting disabled — adverts pass through freely Adaptive OFF: Token bucket uses fixed limits (no tier scaling), penalty box still works Penalty Box OFF: Token bucket still applies, but no escalating cooldowns for repeat offenders Decision flow when all enabled: Adaptive tier check → Penalty box check → Token bucket check → Violation recording (triggers penalty box)
Activity tiers: Quiet (bypass limiting) → Normal (lighter: 0.5x intervals) → Busy (base: 1.0x intervals) → Congested (stricter: 2.0x intervals)
Note: Adaptive mode scales refill/min-interval timing; bucket capacity stays at the configured base value.
`,2),S(`div`,Ga,[t[50]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Adaptive Mode`,-1),f.value?m((w(),C(`select`,{key:1,"onUpdate:modelValue":t[10]||=e=>G.value=e,class:`w-full sm:w-32 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},[...t[49]||=[S(`option`,{value:!0},`Enabled`,-1),S(`option`,{value:!1},`Disabled`,-1)]],512)),[[P,G.value]]):(w(),C(`div`,Ka,b(G.value?`Enabled`:`Disabled`),1))]),S(`div`,qa,[t[52]||=S(`div`,null,[S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm`},`Tier Change Delay`),S(`p`,{class:`text-xs text-content-muted dark:text-content-muted`},`Prevents tier flapping`)],-1),f.value?(w(),C(`div`,Ya,[m(S(`input`,{"onUpdate:modelValue":t[11]||=e=>K.value=e,type:`number`,min:`0`,max:`60`,class:`w-20 px-3 py-1.5 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded-lg text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary`},null,512),[[F,K.value,void 0,{number:!0}]]),t[51]||=S(`span`,{class:`text-content-muted text-sm`},`min`,-1)])):(w(),C(`div`,Ja,b(K.value)+` min `,1))]),S(`div`,Xa,[t[56]||=S(`span`,{class:`text-content-secondary dark:text-content-muted text-xs sm:text-sm mb-2 block`},`Activity Tier Thresholds (adverts/min)`,-1),S(`div`,Za,[S(`div`,Qa,[t[53]||=S(`div`,{class:`text-xs text-green-600 dark:text-green-400 mb-1`},`Quiet Max`,-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[12]||=e=>ne.value=e,type:`number`,min:`0`,max:`1`,step:`0.01`,class:`w-full px-2 py-1 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded text-content-primary dark:text-content-primary text-sm text-center focus:outline-none focus:border-primary`},null,512)),[[F,ne.value,void 0,{number:!0}]]):(w(),C(`div`,$a,b(ne.value),1))]),S(`div`,eo,[t[54]||=S(`div`,{class:`text-xs text-blue-600 dark:text-blue-400 mb-1`},`Normal Max`,-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[13]||=e=>q.value=e,type:`number`,min:`0`,max:`5`,step:`0.01`,class:`w-full px-2 py-1 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded text-content-primary dark:text-content-primary text-sm text-center focus:outline-none focus:border-primary`},null,512)),[[F,q.value,void 0,{number:!0}]]):(w(),C(`div`,to,b(q.value),1))]),S(`div`,no,[t[55]||=S(`div`,{class:`text-xs text-yellow-600 dark:text-yellow-400 mb-1`},`Busy Max`,-1),f.value?m((w(),C(`input`,{key:1,"onUpdate:modelValue":t[14]||=e=>J.value=e,type:`number`,min:`0`,max:`10`,step:`0.01`,class:`w-full px-2 py-1 bg-white dark:bg-white/5 border border-stroke-subtle dark:border-stroke/10 rounded text-content-primary dark:text-content-primary text-sm text-center focus:outline-none focus:border-primary`},null,512)),[[F,J.value,void 0,{number:!0}]]):(w(),C(`div`,ro,b(J.value),1))])]),t[57]||=S(`p`,{class:`text-xs text-content-muted dark:text-content-muted mt-2`},` Above Busy Max = Congested tier (strictest limiting) `,-1)])]),D.value?(w(),C(`div`,{key:2,class:`fixed inset-0 bg-black/50 flex items-start justify-center z-50 p-4 overflow-y-auto`,onClick:t[18]||=I(e=>D.value=!1,[`self`])},[S(`div`,{class:`bg-background dark:bg-background-dark rounded-lg shadow-xl max-w-3xl w-full my-8`,onClick:t[17]||=I(()=>{},[`stop`])},[S(`div`,io,[S(`div`,ao,[t[60]||=S(`h2`,{class:`text-xl font-semibold text-content-primary dark:text-content-primary`},` How Advert Rate Limiting Works `,-1),S(`button`,{onClick:t[15]||=e=>D.value=!1,class:`text-content-muted hover:text-content-primary dark:text-content-muted dark:hover:text-content-primary`},[...t[59]||=[S(`svg`,{class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),t[61]||=d(` Why you may see the same advert more than once Mesh traffic can reach your repeater through different paths, so duplicate advert packets are expected.
First copy arrives and is forwarded Second copy arrives through another repeater path Later copies may be dropped once limits are hit This is normal behavior and helps prevent repeated rebroadcasts from flooding the mesh.
Token Bucket Rate Limiting Each sender has a token bucket. Every forwarded advert uses one token.
Bucket Capacity: How many adverts can pass in a burst.Refill Rate: How quickly tokens come back over time.Min Interval: Optional gap between adverts from the same sender (usually set to 0). Example (capacity 2): - Copy 1 forwarded (2 → 1 tokens) - Copy 2 forwarded (1 → 0 tokens) - Copy 3 dropped (no tokens left)
Penalty Box (Repeat Offenders) If a sender keeps hitting the limit, it is temporarily blocked.
Violation Threshold: How many hits before penalty starts.Base Penalty: First block duration.Multiplier: Repeated penalties get longer.Decay Time: Violations age out after stable behavior. Adaptive Mesh Activity Tiers Adaptive mode adjusts limits based on recent advert activity.
How Congestion is Measured: What is counted: Advert packets only (not chat/data traffic) Smoothing: 60-second EWMA to avoid reacting to short spikes Score: Tier is based on adverts per minuteHysteresis: Tier changes must hold for 5 minutesQUIET
Activity < 0.05/min
No rate limiting
NORMAL
Activity 0.05-0.20/min
Light limiting (50%)
BUSY
Activity 0.20-0.50/min
Standard limiting (100%)
CONGESTED
Activity > 0.50/min
Aggressive (200%)
Quick examples: - 0.02 adverts/min → QUIET (bypass) - 0.35 adverts/min → BUSY (tighter limits) - 0.68 adverts/min → CONGESTED (strict limits)
Recommended starting settings Min Interval: 0 (disabled), let adaptive mode do the workBucket Capacity: 2-3 tokens for normal mesh propagationAdaptive Mode: OnPenalty Box: On `,5),S(`div`,oo,[S(`button`,{onClick:t[16]||=e=>D.value=!1,class:`px-4 py-2 bg-primary/20 hover:bg-primary/30 text-content-primary dark:text-content-primary rounded-lg border border-primary/50 transition-colors`},` Got it! `)])])])])):g(``,!0)]))}}),co=[{name:`US West only (US v1)`,website:`letsmesh.net`,brokers:[{enabled:!0,name:`MeshMapper`,host:`mqtt-us-v1.letsmesh.net`,port:443,audience:`mqtt-us-v1.letsmesh.net`,use_jwt_auth:!0,format:`letsmesh`,transport:`websockets`,retain_status:!1,tls:{enabled:!0,insecure:!1}}]},{name:`Europe only (EU v1)`,website:`letsmesh.net`,brokers:[{enabled:!0,name:`MeshMapper`,host:`mqtt-eu-v1.letsmesh.net`,port:443,audience:`mqtt-eu-v1.letsmesh.net`,use_jwt_auth:!0,format:`letsmesh`,transport:`websockets`,retain_status:!1,tls:{enabled:!0,insecure:!1}}]},{name:`Waev`,website:`https://waev.app`,brokers:[{enabled:!0,name:`Waev`,host:`mqtt-a.waev.app`,port:443,audience:`mqtt.waev.app`,use_jwt_auth:!0,format:`letsmesh`,transport:`websockets`,retain_status:!1,tls:{enabled:!0,insecure:!1}}]},{name:`MeshMapper`,website:`https://meshmapper.net`,brokers:[{enabled:!0,name:`MeshMapper`,host:`mqtt.meshmapper.cc`,port:443,audience:`mqtt.meshmapper.cc`,use_jwt_auth:!0,format:`letsmesh`,transport:`websockets`,retain_status:!1,tls:{enabled:!0,insecure:!1}}]}],lo={class:`space-y-6`},uo={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},fo={class:`flex items-center justify-between mb-4`},po=[`disabled`],mo={key:0},ho={key:1},go={key:0,class:`text-sm text-content-secondary dark:text-content-muted`},_o={key:1,class:`space-y-3`},vo={class:`flex items-center gap-2`},yo={key:0,class:`space-y-2`},bo=[`title`],xo={key:1,class:`text-sm text-content-muted dark:text-content-muted/60 italic`},So={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Co={class:`flex items-start justify-between mb-6`},wo={key:0,class:`space-y-4`},To={class:`grid grid-cols-1 sm:grid-cols-2 gap-x-8 gap-y-3`},Eo={class:`mt-1 text-sm text-content-primary dark:text-content-primary font-mono`},Do={class:`mt-1 text-sm text-content-primary dark:text-content-primary`},Oo={class:`mt-1 text-sm text-content-primary dark:text-content-primary`},ko={class:`mt-1 text-sm text-content-primary dark:text-content-primary`},Ao={key:0,class:`mt-2 text-sm text-content-muted dark:text-content-muted/60 italic`},jo={key:1,class:`mt-2 space-y-1.5`},Mo={class:`min-w-0 flex-1`},No={class:u([`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium`])},Po={key:0,class:`w-4 h-4 text-green-600 dark:text-green-500`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Fo={class:`text-sm font-medium text-content-primary dark:text-content-primary`},Io={class:`text-xs text-content-secondary dark:text-content-muted ml-2 font-mono`},Lo=[`title`],Ro={key:1,class:`space-y-5`},zo={class:`grid grid-cols-1 sm:grid-cols-2 gap-4`},Bo={class:`grid grid-cols-1 sm:grid-cols-2 gap-4`},Vo={class:`grid grid-cols-1 sm:grid-cols-2 gap-4`},Ho={class:`flex items-start justify-between mb-3 gap-3`},Uo={class:`flex items-center gap-2 flex-shrink-0`},Wo={class:`relative`},Go={key:0,class:`absolute right-0 top-full mt-1 z-20 w-64 rounded-lg shadow-lg border border-stroke-subtle dark:border-stroke/20 bg-white dark:bg-[var(--color-surface)] overflow-hidden`},Ko={class:`py-1`},qo=[`onClick`],Jo={class:`min-w-0 flex-1`},Yo={class:`text-sm font-medium text-content-primary dark:text-content-primary group-hover:text-cyan-700 dark:group-hover:text-primary transition-colors`},Xo={class:`text-xs text-content-secondary dark:text-content-muted`},Zo=[`href`],Qo={key:0,class:`flex flex-col items-center justify-center py-7 rounded-lg border-2 border-dashed border-stroke-subtle dark:border-stroke/20 text-content-secondary dark:text-content-muted`},$o={key:1,class:`space-y-2`},es={key:0,class:`flex items-center gap-3 px-4 py-2.5`},ts={class:`min-w-0 flex-1`},ns={class:`text-sm font-medium text-content-primary dark:text-content-primary`},rs={class:`text-xs font-mono text-content-secondary dark:text-content-muted ml-2`},is={key:0,class:`ml-2 text-xs text-red-500 dark:text-red-400`},as={class:`flex items-center gap-0.5 flex-shrink-0`},os=[`onClick`],ss=[`onClick`],cs={key:1,class:`p-4 space-y-3 bg-background-mute/60 dark:bg-background/20`},ls={class:`grid grid-cols-1 sm:grid-cols-2 gap-3`},us={class:`grid grid-cols-1 sm:grid-cols-2 gap-3`},ds={class:`sm:col-span-2`},fs={key:0},ps={key:1},ms={class:`grid grid-cols-1 sm:grid-cols-2 gap-3`},hs={class:`sm:col-span-2`},gs={class:`sm:col-span-2`},_s={key:2},vs={class:`col-span-full`},ys={class:`flex flex-wrap gap-2`},bs=[`onClick`],xs={class:`flex items-center gap-2 pt-1`},Ss=[`disabled`],Cs=[`onClick`],ws={key:0,class:`p-3 rounded-lg bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-700/30 text-green-700 dark:text-green-400 text-sm`},Ts={key:1,class:`p-3 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-700/30 text-red-700 dark:text-red-400 text-sm`},Es={class:`flex items-center gap-3 pt-2`},Ds=[`disabled`],Os={key:0},ks={key:1},As=[`disabled`],js=M(f({__name:`LetsMeshSettings`,setup(e){let n=j(),r=v(()=>n.stats?.config?.mqtt_brokers||{}),o=[`REQ`,`RESPONSE`,`TXT_MSG`,`ACK`,`ADVERT`,`GRP_TXT`,`GRP_DATA`,`ANON_REQ`,`PATH`,`TRACE`,`RAW_CUSTOM`],c=co,l=E(!1),d=E(!1),f=E(``),p=E(``),T=E(``),D=E(300),O=E(``),A=E(``),M=E([]),R=E(null),z=E({_id:0,enabled:!0,name:``,host:``,port:443,format:`letsmesh`,use_jwt_auth:!1,transport:`websockets`,disallowedInput:[],retain_status:!1,tls:{enabled:!0,insecure:!1}}),B=E(!1);function V(e){B.value=!1,R.value!==null&&K(),e.brokers.forEach(e=>{let t=H(e);M.value.push(t)})}let ee=1;function H(e={}){return{_id:ee++,enabled:e.enabled??!0,name:e.name??``,host:e.host??``,port:e.port??0,audience:e.audience??``,format:e.format??`letsmesh`,use_jwt_auth:e.use_jwt_auth??!1,username:e.username??``,password:e.password??``,transport:e.transport??`websockets`,disallowedInput:Array.isArray(e.disallowedInput)?[...e.disallowedInput]:[],retain_status:e.retain_status??!1,base_topic:e.base_topic??``,tls:{enabled:e.tls?.enabled??!1,insecure:e.tls?.insecure??!1}}}function U(){let e=H();M.value.push(e),z.value={...e},R.value=e._id}function W(e){M.value=M.value.filter(t=>t._id!==e),R.value===e&&(R.value=null)}function G(e){z.value={...e},R.value=e._id}function te(){R.value=null}function K(){let e=z.value;if(!e.name.trim()||!e.host.trim()||e.use_jwt_auth&&!e.audience?.trim())return;let t=M.value.findIndex(t=>t._id===e._id);t!==-1&&M.value.splice(t,1,{...e}),R.value=null}function ne(){let e=z.value;(!e.audience||e.audience===e.host)&&(e.audience=e.host)}let q=v(()=>{let e={};return M.value.forEach(t=>{t.name.trim()?t.host.trim()?t.use_jwt_auth&&!t.audience?.trim()?e[t._id]=`Audience required for JWT auth`:(t.port<1||t.port>65535)&&(e[t._id]=`Port must be 1–65535`):e[t._id]=`Host required`:e[t._id]=`Name required`}),e}),J=v(()=>Object.keys(q.value).length>0),Y=E(null),X=E(!1);async function Z(){X.value=!0;try{let e=await k.get(`/api/mqtt_status`);e.data?.success&&(Y.value=e.data.data)}catch{}finally{X.value=!1}}function Q(){let e=r.value;T.value=e.iata_code??``,D.value=e.status_interval??300,O.value=e.owner??``,A.value=e.email??``,M.value=Array.isArray(e.brokers)?e.brokers.map(e=>H(e)):[]}h(r,()=>{l.value||Q()},{immediate:!0});function re(){Q(),R.value=null,l.value=!0,f.value=``,p.value=``}function $(){R.value=null,l.value=!1,f.value=``,p.value=``}function ie(e,t){e.disallowedInput||=[];let n=e.disallowedInput.indexOf(t);n===-1?e.disallowedInput.push(t):e.disallowedInput.splice(n,1)}async function ae(){if(R.value!==null&&K(),J.value){p.value=`Please fix broker errors before saving.`;return}d.value=!0,p.value=``,f.value=``;try{let e=(await k.post(`/api/update_mqtt_config`,{iata_code:T.value,status_interval:D.value,owner:O.value,email:A.value,brokers:M.value.map(e=>{let t={name:e.name,enabled:e.enabled,transport:e.transport,host:e.host,port:e.port,use_jwt_auth:e.use_jwt_auth,format:e.format,disallowed_packet_types:e.disallowedInput,base_topic:e.base_topic,retain_status:e.retain_status,tls:{enabled:e.tls?.enabled??!1,insecure:e.tls?.insecure??!1}};return e.use_jwt_auth?{...t,audience:e.audience}:{...t,username:e.username,password:e.password}})})).data;e?.success?(f.value=e.data?.message||`Settings saved`,l.value=!1,await n.fetchStats(),await Z(),setTimeout(()=>{f.value=``},5e3)):p.value=e?.error||`Save failed`}catch(e){let t=e;p.value=t?.response?.data?.error||t?.message||`Request failed`}finally{d.value=!1}}return s(Z),(e,n)=>(w(),C(`div`,lo,[S(`div`,uo,[S(`div`,fo,[n[21]||=S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Observer Status `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Live LetsMesh broker connection state `)],-1),S(`button`,{onClick:Z,disabled:X.value,class:`px-3 py-1.5 text-xs rounded-lg bg-cyan-500/10 dark:bg-primary/10 hover:bg-cyan-500/20 dark:hover:bg-primary/20 text-cyan-700 dark:text-primary border border-cyan-400/30 dark:border-primary/30 transition-colors disabled:opacity-50`},[X.value?(w(),C(`span`,mo,`Refreshing…`)):(w(),C(`span`,ho,`↻ Refresh`))],8,po)]),Y.value?(w(),C(`div`,_o,[S(`div`,vo,[n[22]||=S(`span`,{class:`text-sm text-content-secondary dark:text-content-muted w-36`},`Handler`,-1),S(`span`,{class:u([`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium`,Y.value.handler_active?`bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400`:`bg-gray-100 dark:bg-gray-800/50 text-gray-500 dark:text-gray-400`])},[S(`span`,{class:u([`w-1.5 h-1.5 rounded-full`,Y.value.handler_active?`bg-green-500`:`bg-gray-400`])},null,2),y(` `+b(Y.value.handler_active?`Active`:`Inactive`),1)],2)]),Y.value.brokers.length?(w(),C(`div`,yo,[(w(!0),C(x,null,i(Y.value.brokers,e=>(w(),C(`div`,{key:e.host,class:`flex items-center gap-2`},[S(`span`,{class:`text-sm text-content-secondary dark:text-content-muted w-36 truncate`,title:e.name},b(e.name),9,bo),S(`span`,{class:u([`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium`,e.status.connected?`bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400`:e.status.reconnecting?`bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-400`:`bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400`])},[S(`span`,{class:u([`w-1.5 h-1.5 rounded-full`,e.status.connected?`bg-green-500`:e.status.reconnecting?`bg-amber-500`:`bg-red-500`])},null,2),y(` `+b(e.status.connected?`Connected`:e.status.reconnecting?`Reconnecting…`:`Disconnected`),1)],2)]))),128))])):(w(),C(`div`,xo,` No broker connections configured. `))])):(w(),C(`div`,go,` Status unavailable — service may not be running. `))]),S(`div`,So,[S(`div`,Co,[n[23]||=S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Observer Configuration `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Configure MQTT observer settings `)],-1),l.value?g(``,!0):(w(),C(`button`,{key:0,onClick:re,class:`px-4 py-2 text-sm rounded-lg bg-cyan-500/10 dark:bg-primary/10 hover:bg-cyan-500/20 dark:hover:bg-primary/20 text-cyan-700 dark:text-primary border border-cyan-400/30 dark:border-primary/30 transition-colors`},` Edit `))]),l.value?(w(),C(`div`,Ro,[S(`div`,zo,[S(`div`,null,[n[30]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-1.5`},[y(` IATA Code `),S(`span`,{class:`text-content-secondary dark:text-content-muted font-normal text-xs ml-1`},`(e.g. SFO, LHR)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[0]||=e=>T.value=e,type:`text`,maxlength:`10`,placeholder:`TEST`,class:`w-full px-3 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[F,T.value]])])]),S(`div`,Bo,[S(`div`,null,[n[31]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-1.5`},`Owner / Callsign`,-1),m(S(`input`,{"onUpdate:modelValue":n[1]||=e=>O.value=e,type:`text`,placeholder:`Optional`,class:`w-full px-3 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,O.value]])]),S(`div`,null,[n[32]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-1.5`},`Email`,-1),m(S(`input`,{"onUpdate:modelValue":n[2]||=e=>A.value=e,type:`email`,placeholder:`Optional`,class:`w-full px-3 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,A.value]])])]),S(`div`,Vo,[n[33]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-1.5`},[y(` Status Heartbeat Interval `),S(`span`,{class:`text-content-secondary dark:text-content-muted font-normal text-xs ml-1`},`(seconds, min 60)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[3]||=e=>D.value=e,type:`number`,min:`60`,max:`3600`,class:`w-32 px-3 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[F,D.value,void 0,{number:!0}]])]),S(`div`,null,[S(`div`,Ho,[n[40]||=S(`div`,{class:`min-w-0`},[S(`label`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},`Brokers`),S(`p`,{class:`text-xs text-content-secondary dark:text-content-muted mt-0.5`},` MQTT brokers `)],-1),S(`div`,Uo,[S(`div`,Wo,[S(`button`,{onClick:n[4]||=e=>B.value=!B.value,class:`inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg bg-background-mute dark:bg-background/30 hover:bg-stroke-subtle dark:hover:bg-stroke/10 text-content-secondary dark:text-content-muted border border-stroke-subtle dark:border-stroke/20 transition-colors`},[n[35]||=S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M19 11H5m14 0l-4-4m4 4l-4 4`})],-1),n[36]||=y(` From Template `,-1),(w(),C(`svg`,{class:u([`w-3 h-3 ml-0.5 transition-transform`,B.value?`rotate-180`:``]),fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[...n[34]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M19 9l-7 7-7-7`},null,-1)]],2))]),_(N,{name:`dropdown`},{default:t(()=>[B.value?(w(),C(`div`,Go,[n[38]||=S(`div`,{class:`px-3 py-2 border-b border-stroke-subtle dark:border-stroke/10`},[S(`p`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},` Known Networks `)],-1),S(`div`,Ko,[(w(!0),C(x,null,i(a(c),e=>(w(),C(`div`,{key:e.name,class:`flex items-center gap-2 px-3 py-2.5 hover:bg-background-mute dark:hover:bg-background/30 cursor-pointer group`,onClick:t=>V(e)},[S(`div`,Jo,[S(`p`,Yo,b(e.name),1),S(`p`,Xo,b(e.brokers.length)+` broker`+b(e.brokers.length===1?``:`s`),1)]),S(`a`,{href:e.website,target:`_blank`,rel:`noopener noreferrer`,title:`Visit website`,class:`flex-shrink-0 p-1 rounded hover:bg-cyan-500/10 dark:hover:bg-primary/10 text-content-secondary dark:text-content-muted hover:text-cyan-700 dark:hover:text-primary transition-colors`,onClick:n[5]||=I(()=>{},[`stop`])},[...n[37]||=[S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14`})],-1)]],8,Zo)],8,qo))),128))])])):g(``,!0)]),_:1}),B.value?(w(),C(`div`,{key:0,class:`fixed inset-0 z-10`,onClick:n[6]||=e=>B.value=!1})):g(``,!0)]),S(`button`,{onClick:U,class:`inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg bg-cyan-500/10 dark:bg-primary/10 hover:bg-cyan-500/20 dark:hover:bg-primary/20 text-cyan-700 dark:text-primary border border-cyan-400/30 dark:border-primary/30 transition-colors`},[...n[39]||=[S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 4v16m8-8H4`})],-1),y(` Add `,-1)]])])]),M.value.length?(w(),C(`div`,$o,[(w(!0),C(x,null,i(M.value,e=>(w(),C(`div`,{key:e._id,class:u([`rounded-lg border overflow-hidden transition-colors`,q.value[e._id]?`border-red-300 dark:border-red-700/50`:`border-stroke-subtle dark:border-stroke/10`])},[R.value===e._id?(w(),C(`div`,cs,[S(`div`,ls,[S(`div`,null,[n[44]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Enabled `),S(`span`,{class:`text-red-500`},`*`)],-1),m(S(`input`,{"onUpdate:modelValue":n[7]||=e=>z.value.enabled=e,type:`checkbox`,class:`w-4 h-4 text-cyan-600 bg-background-mute border-stroke-subtle dark:border-stroke/20 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[L,z.value.enabled]])]),S(`div`,null,[n[45]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Retain Status`),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},[y(` (Enable MQTT `),S(`a`,{href:`https://www.hivemq.com/blog/mqtt-essentials-part-8-retained-messages/`,class:`w-4 h-4 text-cyan-600 border-stroke-subtle dark:border-stroke/20 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},`Retained`),y(` for status messages) `)])],-1),m(S(`input`,{"onUpdate:modelValue":n[8]||=e=>z.value.retain_status=e,type:`checkbox`,class:`w-4 h-4 text-cyan-600 bg-background-mute border-stroke-subtle dark:border-stroke/20 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[L,z.value.retain_status]])]),S(`div`,null,[n[46]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Name `),S(`span`,{class:`text-red-500`},`*`)],-1),m(S(`input`,{"onUpdate:modelValue":n[9]||=e=>z.value.name=e,type:`text`,placeholder:`Broker Name`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,z.value.name]])]),S(`div`,null,[n[48]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Transport `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`})],-1),m(S(`select`,{"onUpdate:modelValue":n[10]||=e=>z.value.transport=e,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},[...n[47]||=[S(`option`,{value:`websockets`},`Websockets`,-1),S(`option`,{value:`tcp`},`TCP`,-1)]],512),[[P,z.value.transport]])]),S(`div`,null,[n[49]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Host `),S(`span`,{class:`text-red-500`},`*`)],-1),m(S(`input`,{"onUpdate:modelValue":n[11]||=e=>z.value.host=e,type:`text`,placeholder:`mqtt.myserver.com`,onBlur:ne,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,544),[[F,z.value.host]])]),S(`div`,us,[S(`div`,ds,[n[50]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Port `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(Usually 443 for Websockets, 1883 for TCP)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[12]||=e=>z.value.port=e,type:`number`,min:`0`,max:`65535`,placeholder:`0`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[F,z.value.port,void 0,{number:!0}]])]),S(`div`,null,[n[51]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` TLS - Enabled `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(Enable TLS)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[13]||=e=>z.value.tls.enabled=e,type:`checkbox`,class:`px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[L,z.value.tls.enabled,void 0,{number:!0}]])]),S(`div`,null,[n[52]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` TLS - Insecure`),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(Allow insecure TLS connections)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[14]||=e=>z.value.tls.insecure=e,type:`checkbox`,class:`px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[L,z.value.tls.insecure,void 0,{number:!0}]])])]),S(`div`,null,[n[53]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Use JWT Auth `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`})],-1),m(S(`input`,{"onUpdate:modelValue":n[15]||=e=>z.value.use_jwt_auth=e,type:`checkbox`,placeholder:`true`,class:`px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[L,z.value.use_jwt_auth]])]),z.value.use_jwt_auth?(w(),C(`div`,fs,[n[54]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Audience `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(JWT aud — usually same as host)`)],-1),m(S(`input`,{"onUpdate:modelValue":n[16]||=e=>z.value.audience=e,type:`text`,placeholder:`mqtt.myserver.com`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40 font-mono`},null,512),[[F,z.value.audience]])])):(w(),C(`div`,ps,[S(`div`,ms,[n[57]||=S(`input`,{type:`text`,autocomplete:`username`,style:{display:`none`}},null,-1),n[58]||=S(`input`,{type:`password`,autocomplete:`current-password`,style:{display:`none`}},null,-1),S(`div`,hs,[n[55]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Username `),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},` (Leave blank for anonymous auth) `)],-1),m(S(`input`,{autocomplete:`username`,"onUpdate:modelValue":n[17]||=e=>z.value.username=e,type:`text`,placeholder:`username`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,z.value.username]])]),S(`div`,gs,[n[56]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},` Password `,-1),m(S(`input`,{autocomplete:`new-password`,"onUpdate:modelValue":n[18]||=e=>z.value.password=e,type:`password`,placeholder:``,readonly:``,onfocus:`this.removeAttribute('readonly');`,onblur:`this.setAttribute('readonly', true);`,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary placeholder-content-muted dark:placeholder-content-muted/50 focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},null,512),[[F,z.value.password]])])])])),S(`div`,null,[n[60]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` Format `),S(`span`,{class:`text-red-500`},`*`),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`})],-1),m(S(`select`,{"onUpdate:modelValue":n[19]||=e=>z.value.format=e,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`},[...n[59]||=[S(`option`,{value:`letsmesh`},`LetsMesh MQTT format`,-1),S(`option`,{value:`mqtt`},`pyMC MQTT format`,-1)]],512),[[P,z.value.format]])]),z.value.format===`mqtt`?(w(),C(`div`,_s,[n[61]||=S(`label`,{class:`block text-xs font-medium text-content-secondary dark:text-content-muted mb-1`},[y(` MQTT base topic `),S(`span`,{class:`font-normal text-content-muted dark:text-content-muted/60 ml-1`},`(Messages are sent to topics under this path. Example: /advert) `)],-1),m(S(`input`,{"onUpdate:modelValue":n[20]||=e=>z.value.base_topic=e,class:`w-full px-3 py-1.5 text-sm rounded-md bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/20 text-content-primary dark:text-content-primary focus:outline-none focus:ring-2 focus:ring-cyan-500/40 dark:focus:ring-primary/40`,placeholder:`meshcore/repeater`},null,512),[[F,z.value.base_topic]])])):g(``,!0),S(`div`,vs,[n[62]||=S(`label`,{class:`block text-sm font-medium text-content-primary dark:text-content-primary mb-2`},[y(` Block Packet Types `),S(`span`,{class:`text-content-secondary dark:text-content-muted font-normal text-xs ml-1`},` (prevent publishing to LetsMesh) `)],-1),S(`div`,ys,[(w(),C(x,null,i(o,e=>S(`button`,{key:e,onClick:t=>ie(z.value,e),class:u([`px-2.5 py-1 rounded text-xs font-mono font-medium border transition-colors`,z.value.disallowedInput?.includes(e)?`bg-red-100 dark:bg-red-900/30 border-red-300 dark:border-red-700/50 text-red-700 dark:text-red-400`:`bg-background-mute dark:bg-background/30 border-stroke-subtle dark:border-stroke/20 text-content-secondary dark:text-content-muted hover:border-cyan-400/50 dark:hover:border-primary/40`])},b(e),11,bs)),64))]),n[63]||=S(`p`,{class:`mt-1.5 text-xs text-content-secondary dark:text-content-muted`},[S(`span`,{class:`text-red-600 dark:text-red-400 font-medium`},`Red = blocked.`),y(` Leave all unselected to publish all packet types. `)],-1)])]),S(`div`,xs,[S(`button`,{onClick:K,disabled:!z.value.name.trim()||!z.value.host.trim()||z.value.port<=0||z.value.port>65535||z.value.use_jwt_auth&&!z.value.audience?.trim(),class:`px-3 py-1.5 text-xs font-medium rounded-md bg-cyan-600 dark:bg-teal-600 hover:bg-cyan-700 dark:hover:bg-teal-700 text-white transition-colors disabled:opacity-40 disabled:cursor-not-allowed`},` Done `,8,Ss),S(`button`,{onClick:te,class:`px-3 py-1.5 text-xs rounded-md border border-stroke-subtle dark:border-stroke/20 hover:bg-stroke-subtle dark:hover:bg-stroke/10 text-content-secondary dark:text-content-muted transition-colors`},` Cancel `),S(`button`,{onClick:t=>W(e._id),class:`ml-auto px-3 py-1.5 text-xs rounded-md border border-red-300/60 dark:border-red-700/30 hover:bg-red-50 dark:hover:bg-red-900/20 text-red-600 dark:text-red-400 transition-colors`},` Remove `,8,Cs)])])):(w(),C(`div`,es,[S(`div`,ts,[S(`span`,{class:u([`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium`,e.enabled?`bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400`:`bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400`])},[S(`span`,{class:u([`w-1.5 h-1.5 rounded-full`,e.enabled?`bg-green-500`:`bg-red-500`])},null,2),y(` `+b(e.enabled?`Enabled`:`Disabled`),1)],2),S(`span`,ns,b(e.name||`(unnamed)`),1),S(`span`,rs,b(e.host||`—`)+`:`+b(e.port),1),q.value[e._id]?(w(),C(`span`,is,b(q.value[e._id]),1)):g(``,!0)]),S(`div`,as,[S(`button`,{onClick:t=>G(e),title:`Edit`,class:`p-1.5 rounded hover:bg-cyan-500/10 dark:hover:bg-primary/10 text-content-secondary dark:text-content-muted hover:text-cyan-700 dark:hover:text-primary transition-colors`},[...n[42]||=[S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z`})],-1)]],8,os),S(`button`,{onClick:t=>W(e._id),title:`Remove`,class:`p-1.5 rounded hover:bg-red-500/10 dark:hover:bg-red-900/20 text-content-secondary dark:text-content-muted hover:text-red-600 dark:hover:text-red-400 transition-colors`},[...n[43]||=[S(`svg`,{class:`w-3.5 h-3.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16`})],-1)]],8,ss)])]))],2))),128))])):(w(),C(`div`,Qo,[...n[41]||=[S(`svg`,{class:`w-7 h-7 mb-2 opacity-40`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`1.5`,d:`M5 12h14M5 12l4-4m-4 4l4 4`})],-1),S(`p`,{class:`text-sm`},`No brokers`,-1),S(`p`,{class:`text-xs mt-0.5 opacity-70`},`Add a MQTT broker`,-1)]]))]),n[64]||=S(`div`,{class:`flex items-start gap-2 p-3 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-700/30 text-amber-700 dark:text-amber-400 text-xs`},[S(`svg`,{class:`w-4 h-4 mt-0.5 flex-shrink-0`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z`})]),y(` A service restart is required for MQTT broker changes to take effect. `)],-1),f.value?(w(),C(`div`,ws,b(f.value),1)):g(``,!0),p.value?(w(),C(`div`,Ts,b(p.value),1)):g(``,!0),S(`div`,Es,[S(`button`,{onClick:ae,disabled:d.value||J.value,class:`px-5 py-2 text-sm font-medium rounded-lg bg-cyan-600 dark:bg-teal-600 hover:bg-cyan-700 dark:hover:bg-teal-700 text-white transition-colors disabled:opacity-50 disabled:cursor-not-allowed`},[d.value?(w(),C(`span`,Os,`Saving…`)):(w(),C(`span`,ks,`Save Settings`))],8,Ds),S(`button`,{onClick:$,disabled:d.value,class:`px-4 py-2 text-sm rounded-lg bg-background-mute dark:bg-background/30 hover:bg-stroke-subtle dark:hover:bg-stroke/10 text-content-secondary dark:text-content-muted border border-stroke-subtle dark:border-stroke/20 transition-colors disabled:opacity-50`},` Cancel `,8,As)])])):(w(),C(`div`,wo,[S(`div`,To,[S(`div`,null,[n[24]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`IATA Code`,-1),S(`p`,Eo,b(r.value.iata_code||`—`),1)]),S(`div`,null,[n[25]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`Status Interval`,-1),S(`p`,Do,b(r.value.status_interval??300)+`s `,1)]),S(`div`,null,[n[26]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`Owner`,-1),S(`p`,Oo,b(r.value.owner||`—`),1)]),S(`div`,null,[n[27]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`Email`,-1),S(`p`,ko,b(r.value.email||`—`),1)])]),S(`div`,null,[n[29]||=S(`span`,{class:`text-xs font-medium text-content-secondary dark:text-content-muted uppercase tracking-wide`},`Brokers`,-1),r.value.brokers?.length?(w(),C(`div`,jo,[(w(!0),C(x,null,i(r.value.brokers,e=>(w(),C(`div`,{key:e.host,class:`flex items-center gap-3 px-3 py-2 rounded-lg bg-background-mute dark:bg-background/30 border border-stroke-subtle dark:border-stroke/10`},[S(`div`,Mo,[S(`span`,No,[e.enabled?(w(),C(`svg`,Po,[...n[28]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M5 13l4 4L19 7`},null,-1)]])):g(``,!0)]),S(`span`,Fo,b(e.name),1),S(`span`,Io,`Host: `+b(e.host)+`:`+b(e.port),1)]),S(`span`,{class:`text-xs text-content-secondary dark:text-content-muted font-mono truncate max-w-[140px]`,title:e.format},b(e.format),9,Lo)]))),128))])):(w(),C(`div`,Ao,` None configured `))])]))])]))}}),[[`__scopeId`,`data-v-45835eb1`]]),Ms={class:`space-y-6`},Ns={key:0,class:`rounded-lg border-2 border-red-500/50 dark:border-red-400/40 bg-red-100 dark:bg-red-500/10 p-4`},Ps={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Fs=[`disabled`],Is={key:0,class:`flex items-center gap-2`},Ls={key:1,class:`flex items-center gap-2`},Rs={key:0,class:`text-xs text-green-600 dark:text-green-400 mt-2`},zs={key:1,class:`text-xs text-red-500 dark:text-red-400 mt-2`},Bs={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Vs={key:0},Hs={key:1,class:`rounded-lg border-2 border-red-500/50 dark:border-red-400/40 bg-red-50 dark:bg-red-500/10 p-4`},Us={class:`flex items-start gap-3`},Ws={class:`flex-1`},Gs={class:`text-xs text-red-600 dark:text-red-400/80 mt-1`},Ks={class:`flex gap-2 mt-3`},qs=[`disabled`],Js=[`disabled`],Ys={key:2,class:`text-xs text-green-600 dark:text-green-400 mt-2`},Xs={key:3,class:`text-xs text-red-500 dark:text-red-400 mt-2`},Zs={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Qs={class:`space-y-3`},$s={class:`flex items-center gap-3 cursor-pointer px-4 py-3 bg-background-mute dark:bg-background/30 rounded-lg border-2 border-dashed border-stroke-subtle dark:border-stroke/20 hover:border-cyan-500/50 dark:hover:border-primary/50 transition-colors`},ec={class:`text-sm text-content-secondary dark:text-content-muted`},tc={key:0,class:`bg-background-mute dark:bg-background/30 rounded-lg p-4 border border-stroke-subtle dark:border-stroke/10`},nc={key:0,class:`text-xs text-content-secondary dark:text-content-muted space-y-1 mb-3`},rc={class:`font-mono`},ic={class:`font-mono`},ac={key:0,class:`text-amber-600 dark:text-amber-400 font-medium`},oc={key:1,class:`text-content-muted`},sc={class:`text-xs text-content-secondary dark:text-content-muted`},cc={class:`font-mono`},lc={key:1},uc={key:2,class:`rounded-lg border-2 border-amber-500/50 dark:border-amber-400/40 bg-amber-50 dark:bg-amber-500/10 p-4`},dc={class:`flex items-start gap-3`},fc={class:`flex-1`},pc={class:`text-xs text-amber-700 dark:text-amber-300/80 mt-1`},mc={class:`flex gap-2 mt-3`},hc=[`disabled`],gc=[`disabled`],_c={key:3,class:`text-xs text-green-600 dark:text-green-400 mt-2`},vc={key:4,class:`text-xs text-red-500 dark:text-red-400 mt-2`},yc={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},bc={key:0},xc={key:1,class:`rounded-lg border-2 border-red-500/50 dark:border-red-400/40 bg-red-50 dark:bg-red-500/10 p-4`},Sc={class:`flex items-start gap-3`},Cc={class:`flex-1`},wc={class:`text-xs text-red-600 dark:text-red-400/80 mt-1`},Tc={class:`flex gap-2 mt-3`},Ec=[`disabled`],Dc=[`disabled`],Oc={key:2,class:`bg-background-mute dark:bg-background/30 rounded-lg p-4 border border-stroke-subtle dark:border-stroke/10 space-y-2`},kc={class:`flex items-center justify-between`},Ac={class:`text-xs text-content-secondary dark:text-content-muted space-y-1`},jc={class:`font-mono`},Mc={key:0},Nc={class:`font-mono`},Pc={key:1},Fc={class:`font-mono text-[10px] break-all`},Ic={key:3,class:`text-xs text-red-500 dark:text-red-400 mt-2`},Lc=f({__name:`BackupRestore`,setup(e){let t=v(()=>window.location.protocol===`http:`),n=E(!1),r=E(``),i=E(``);async function a(){n.value=!0,r.value=``,i.value=``;try{let e=await A.exportConfig(!1);if(!e.success||!e.data){i.value=e.error||`Export failed`;return}let t=new Blob([JSON.stringify(e.data,null,2)],{type:`application/json`}),n=URL.createObjectURL(t),a=document.createElement(`a`);a.href=n,a.download=`pymc-repeater-settings-${(e.data.meta?.exported_at||new Date().toISOString()).replace(/[:.]/g,`-`)}.json`,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(n),r.value=`Settings exported successfully (secrets redacted).`}catch(e){i.value=e instanceof Error?e.message:`Export failed`}finally{n.value=!1}}let o=E(!1),s=E(!1),c=E(``),l=E(``);async function u(){s.value=!0,c.value=``,l.value=``;try{let e=await A.exportConfig(!0);if(!e.success||!e.data){l.value=e.error||`Export failed`;return}let t=new Blob([JSON.stringify(e.data,null,2)],{type:`application/json`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`pymc-repeater-full-backup-${(e.data.meta?.exported_at||new Date().toISOString()).replace(/[:.]/g,`-`)}.json`,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n),c.value=`Full backup exported (includes all secrets).`,o.value=!1}catch(e){l.value=e instanceof Error?e.message:`Export failed`}finally{s.value=!1}}let f=E(null),p=E(null),m=E(!1),h=E(!1),_=E(``),T=E(``),D=E(null),O=v(()=>p.value?.config?Object.keys(p.value.config).join(`, `):``),k=v(()=>{let e=p.value?.meta?.includes_secrets;return e===!0||e===`true`});function j(e){let t=e.target.files?.[0];if(!t)return;f.value=t,p.value=null,m.value=!1,_.value=``,T.value=``;let n=new FileReader;n.onload=e=>{try{let t=JSON.parse(e.target?.result);t.config&&typeof t.config==`object`?p.value={meta:t.meta,config:t.config}:typeof t==`object`&&!Array.isArray(t)?p.value={config:t}:T.value=`Invalid file format — expected a JSON config object.`}catch{T.value=`Invalid JSON file.`}},n.readAsText(t)}function M(){m.value=!1,p.value=null,f.value=null,D.value&&(D.value.value=``)}async function N(){if(p.value?.config){h.value=!0,_.value=``,T.value=``;try{let e=await A.importConfig(p.value.config);if(e.success){let t=e.data,n=e.message||t?.message||`Configuration imported.`;t?.restart_required&&(n+=` A service restart is required for radio changes to take effect.`),_.value=n,m.value=!1,p.value=null,f.value=null,D.value&&(D.value.value=``)}else T.value=e.error||`Import failed`}catch(e){T.value=e instanceof Error?e.message:`Import failed`}finally{h.value=!1}}}let P=E(!1),F=E(!1),I=E(null),L=E(``);async function R(){F.value=!0,L.value=``;try{let e=await A.exportIdentityKey();if(!e.success||!e.data){L.value=e.error||`Export failed`;return}I.value=e.data;let t=new Blob([e.data.identity_key_hex],{type:`text/plain`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`pymc-identity-${e.data.node_address||`key`}.hex`,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n)}catch(e){L.value=e instanceof Error?e.message:`Export failed`}finally{F.value=!1}}return(e,v)=>(w(),C(`div`,Ms,[t.value?(w(),C(`div`,Ns,[...v[6]||=[d(` Unencrypted Connection This page is served over HTTP , not HTTPS. Exported data (including identity keys) will be transmitted in plain text . Only use these features on a trusted local network.
`,1)]])):g(``,!0),S(`div`,Ps,[v[9]||=S(`div`,{class:`flex items-start justify-between mb-4`},[S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Export Settings `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},[y(` Download the current configuration as a JSON file. Passwords, JWT secrets, and identity keys are `),S(`strong`,null,`redacted`),y(`. Safe to share or use as a template for other devices. `)])])],-1),S(`button`,{onClick:a,disabled:n.value,class:`px-4 py-2 bg-cyan-500/20 dark:bg-primary/20 hover:bg-cyan-500/30 dark:hover:bg-primary/30 text-cyan-900 dark:text-white rounded-lg border border-cyan-500/50 dark:border-primary/50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-sm`},[n.value?(w(),C(`span`,Is,[...v[7]||=[S(`span`,{class:`animate-spin w-4 h-4 border-2 border-current border-t-transparent rounded-full inline-block`},null,-1),y(` Exporting… `,-1)]])):(w(),C(`span`,Ls,[...v[8]||=[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4`})],-1),y(` Export Settings `,-1)]]))],8,Fs),r.value?(w(),C(`p`,Rs,b(r.value),1)):g(``,!0),i.value?(w(),C(`p`,zs,b(i.value),1)):g(``,!0)]),S(`div`,Bs,[v[15]||=d(` Full Backup Download a complete backup including all passwords, JWT secrets, and identity keys . Required for restoring to a new device or recovering from a failed SD card.
Contains sensitive data. The backup file will include plain-text passwords and private keys. Store it securely and never share it.
`,2),o.value?g(``,!0):(w(),C(`div`,Vs,[S(`button`,{onClick:v[0]||=e=>o.value=!0,class:`px-4 py-2 bg-red-500/20 dark:bg-red-400/20 hover:bg-red-500/30 dark:hover:bg-red-400/30 text-red-900 dark:text-red-200 rounded-lg border border-red-500/50 dark:border-red-400/40 transition-colors text-sm`},[...v[10]||=[S(`span`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z`})]),y(` Full Backup `)],-1)]])])),o.value?(w(),C(`div`,Hs,[S(`div`,Us,[v[14]||=S(`svg`,{class:`w-5 h-5 text-red-600 dark:text-red-400 shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,Ws,[v[13]||=S(`h4`,{class:`text-sm font-semibold text-red-700 dark:text-red-400`},` Confirm Full Backup `,-1),S(`p`,Gs,[v[11]||=y(` This will export `,-1),v[12]||=S(`strong`,null,`all secrets in plain text`,-1),y(` including admin/guest passwords, JWT secret, and your repeater's private identity key`+b(t.value?` over an unencrypted HTTP connection`:``)+`. `,1)]),S(`div`,Ks,[S(`button`,{onClick:u,disabled:s.value,class:`px-4 py-2 bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 text-white rounded-lg transition-colors text-sm disabled:opacity-50`},b(s.value?`Exporting…`:`Yes, Export Full Backup`),9,qs),S(`button`,{onClick:v[1]||=e=>o.value=!1,disabled:s.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors text-sm`},` Cancel `,8,Js)])])])])):g(``,!0),c.value?(w(),C(`p`,Ys,b(c.value),1)):g(``,!0),l.value?(w(),C(`p`,Xs,b(l.value),1)):g(``,!0)]),S(`div`,Zs,[v[29]||=S(`div`,{class:`flex items-start justify-between mb-4`},[S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Import Configuration `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},[y(` Restore configuration from a previously exported JSON file. Importing a `),S(`strong`,null,`full backup`),y(` will also restore passwords and identity keys. Importing a `),S(`strong`,null,`settings export`),y(` will only update non-sensitive settings. `)])])],-1),S(`div`,Qs,[S(`label`,$s,[v[16]||=S(`svg`,{class:`w-5 h-5 text-content-secondary dark:text-content-muted`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12`})],-1),S(`span`,ec,b(f.value?f.value.name:`Choose a config JSON file…`),1),S(`input`,{ref_key:`fileInputRef`,ref:D,type:`file`,accept:`.json,application/json`,class:`hidden`,onChange:j},null,544)]),p.value?(w(),C(`div`,tc,[v[20]||=S(`h4`,{class:`text-sm font-medium text-content-primary dark:text-content-primary mb-2`},` Import Preview `,-1),p.value.meta?(w(),C(`div`,nc,[S(`p`,null,[v[17]||=y(` Exported: `,-1),S(`span`,rc,b(p.value.meta.exported_at),1)]),S(`p`,null,[v[18]||=y(` Version: `,-1),S(`span`,ic,b(p.value.meta.version),1)]),p.value.meta.includes_secrets===`true`||p.value.meta.includes_secrets===!0?(w(),C(`p`,ac,` ⚠ Full backup — will restore passwords and identity keys `)):(w(),C(`p`,oc,` Settings only — existing secrets will not be changed `))])):g(``,!0),S(`p`,sc,[v[19]||=y(` Sections: `,-1),S(`span`,cc,b(O.value),1)])])):g(``,!0),p.value&&!m.value?(w(),C(`div`,lc,[S(`button`,{onClick:v[2]||=e=>m.value=!0,class:`px-4 py-2 bg-amber-500/20 dark:bg-amber-400/20 hover:bg-amber-500/30 dark:hover:bg-amber-400/30 text-amber-900 dark:text-amber-200 rounded-lg border border-amber-500/50 dark:border-amber-400/40 transition-colors text-sm`},` Review & Import `)])):g(``,!0),m.value?(w(),C(`div`,uc,[S(`div`,dc,[v[28]||=S(`svg`,{class:`w-5 h-5 text-amber-600 dark:text-amber-400 shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,fc,[v[27]||=S(`h4`,{class:`text-sm font-semibold text-amber-800 dark:text-amber-300`},` Confirm Import `,-1),S(`p`,pc,[v[24]||=y(` This will overwrite current settings for: `,-1),S(`strong`,null,b(O.value),1),v[25]||=y(`. `,-1),k.value?(w(),C(x,{key:0},[v[21]||=y(` This is a full backup — `,-1),v[22]||=S(`strong`,null,`passwords, JWT secrets, and identity keys will also be overwritten`,-1),v[23]||=y(`. `,-1)],64)):(w(),C(x,{key:1},[y(` Passwords and identity keys will not be changed. `)],64)),v[26]||=y(` Some changes (radio settings) require a service restart. `,-1)]),S(`div`,mc,[S(`button`,{onClick:N,disabled:h.value,class:`px-4 py-2 bg-amber-600 hover:bg-amber-700 dark:bg-amber-500 dark:hover:bg-amber-600 text-white rounded-lg transition-colors text-sm disabled:opacity-50`},b(h.value?`Importing…`:`Yes, Import`),9,hc),S(`button`,{onClick:M,disabled:h.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors text-sm`},` Cancel `,8,gc)])])])])):g(``,!0),_.value?(w(),C(`p`,_c,b(_.value),1)):g(``,!0),T.value?(w(),C(`p`,vc,b(T.value),1)):g(``,!0)])]),S(`div`,yc,[v[38]||=d(` Export Identity Key Download the repeater's private identity key for backup. This key determines the node's address and cryptographic identity on the mesh.
Sensitive data. The identity key is the repeater's private key. Anyone with this key can impersonate your node. Store the exported file securely and never share it.
`,2),P.value?g(``,!0):(w(),C(`div`,bc,[S(`button`,{onClick:v[3]||=e=>P.value=!0,class:`px-4 py-2 bg-red-500/20 dark:bg-red-400/20 hover:bg-red-500/30 dark:hover:bg-red-400/30 text-red-900 dark:text-red-200 rounded-lg border border-red-500/50 dark:border-red-400/40 transition-colors text-sm`},[...v[30]||=[S(`span`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`})]),y(` Export Identity Key `)],-1)]])])),P.value&&!I.value?(w(),C(`div`,xc,[S(`div`,Sc,[v[32]||=S(`svg`,{class:`w-5 h-5 text-red-600 dark:text-red-400 shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,Cc,[v[31]||=S(`h4`,{class:`text-sm font-semibold text-red-700 dark:text-red-400`},`Are you sure?`,-1),S(`p`,wc,` This will transmit your private key `+b(t.value?`over an unencrypted HTTP connection. `:``)+` and download it as a file. `,1),S(`div`,Tc,[S(`button`,{onClick:R,disabled:F.value,class:`px-4 py-2 bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 text-white rounded-lg transition-colors text-sm disabled:opacity-50`},b(F.value?`Exporting…`:`Yes, Export Key`),9,Ec),S(`button`,{onClick:v[4]||=e=>P.value=!1,disabled:F.value,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors text-sm`},` Cancel `,8,Dc)])])])])):g(``,!0),I.value?(w(),C(`div`,Oc,[S(`div`,kc,[v[33]||=S(`h4`,{class:`text-sm font-medium text-content-primary dark:text-content-primary`},` Key Exported `,-1),S(`button`,{onClick:v[5]||=e=>{I.value=null,P.value=!1},class:`text-xs text-content-muted hover:text-content-secondary transition-colors`},` Dismiss `)]),S(`div`,Ac,[S(`p`,null,[v[34]||=y(` Key length: `,-1),S(`span`,jc,b(I.value.key_length_bytes)+` bytes`,1)]),I.value.node_address?(w(),C(`p`,Mc,[v[35]||=y(` Node address: `,-1),S(`span`,Nc,b(I.value.node_address),1)])):g(``,!0),I.value.public_key_hex?(w(),C(`p`,Pc,[v[36]||=y(` Public key: `,-1),S(`span`,Fc,b(I.value.public_key_hex),1)])):g(``,!0)]),v[37]||=S(`p`,{class:`text-xs text-green-600 dark:text-green-400`},`File downloaded successfully.`,-1)])):g(``,!0),L.value?(w(),C(`p`,Ic,b(L.value),1)):g(``,!0)])]))}}),Rc={class:`space-y-6`},zc={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Bc={class:`flex items-start justify-between mb-4`},Vc=[`disabled`],Hc={key:0,class:`flex items-center gap-1.5`},Uc={key:1},Wc={key:0,class:`grid grid-cols-2 sm:grid-cols-4 gap-3 mb-6`},Gc={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},Kc={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},qc={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},Jc={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},Yc={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},Xc={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},Zc={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},Qc={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},$c={key:1,class:`flex items-center justify-center py-12`},el={key:2,class:`rounded-lg border border-red-500/30 dark:border-red-400/30 bg-red-50 dark:bg-red-500/10 p-3 mb-4`},tl={class:`text-xs text-red-700 dark:text-red-400`},nl={key:3},rl={class:`overflow-x-auto`},il={class:`w-full text-sm`},al={class:`py-2.5 pr-4`},ol={class:`font-mono text-content-primary dark:text-content-primary`},sl={class:`py-2.5 pr-4 text-right`},cl={class:`font-mono text-content-secondary dark:text-content-muted`},ll={class:`py-2.5 pr-4 text-right hidden sm:table-cell`},ul={key:0,class:`text-xs text-content-muted`},dl={class:`text-content-muted/60 ml-1`},fl={key:1,class:`text-xs text-content-muted/50`},pl={key:2,class:`text-xs text-content-muted/50`},ml={class:`py-2.5 text-right`},hl=[`onClick`,`disabled`],gl={key:0,class:`flex items-center gap-1`},_l={key:1},vl={key:1,class:`text-xs text-content-muted/50`},yl={key:0,class:`glass-card rounded-lg border-2 border-red-500/50 dark:border-red-400/40 bg-red-50 dark:bg-red-500/10 p-6`},bl={class:`flex items-start gap-3`},xl={class:`flex-1`},Sl={class:`text-sm font-semibold text-red-700 dark:text-red-400`},Cl={class:`text-xs text-red-600 dark:text-red-400/80 mt-1`},wl={class:`flex gap-2 mt-3`},Tl=[`disabled`],El=[`disabled`],Dl={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Ol={class:`flex flex-wrap gap-3`},kl=[`disabled`],Al=[`disabled`],jl={class:`flex items-center gap-2`},Ml={key:0,class:`text-xs text-green-600 dark:text-green-400 mt-3`},Nl={key:1,class:`text-xs text-green-600 dark:text-green-400 mt-3`},Pl=f({__name:`DatabaseManagement`,setup(e){let t=new Set([`packets`,`adverts`,`noise_floor`,`crc_errors`,`room_messages`,`room_client_sync`,`companion_contacts`,`companion_channels`,`companion_messages`,`companion_prefs`]),n=E(!1),r=E(``),a=E(null),o=E({}),c=E(null),l=E(``),u=E(!1),d=E(``),f=v(()=>a.value?a.value.tables.reduce((e,t)=>e+t.row_count,0):0);function p(e){return t.has(e)}function m(e){if(e===0)return`0 B`;let t=[`B`,`KB`,`MB`,`GB`],n=Math.min(Math.floor(Math.log(e)/Math.log(1024)),t.length-1),r=e/1024**n;return`${r<10?r.toFixed(1):Math.round(r)} ${t[n]}`}function h(e){return e?new Date(e*1e3).toLocaleDateString(void 0,{month:`short`,day:`numeric`,year:`numeric`}):`—`}function _(e,t){return!e||!t?0:Math.max(1,Math.round((t-e)/86400))}async function T(){n.value=!0,r.value=``;try{let e=await A.getDbStats();e.success&&e.data?a.value=e.data:r.value=e.error||`Failed to load database stats`}catch(e){r.value=e instanceof Error?e.message:`Failed to load database stats`}finally{n.value=!1}}function D(e,t){l.value=``,c.value={table:e,rowCount:t,executing:!1}}async function O(){if(!c.value)return;let{table:e}=c.value;c.value.executing=!0,l.value=``;try{let t=e===`all`?`all`:[e];e!==`all`&&(o.value[e]=!0);let n=await A.purgeTable(t);if(n.success){let t=n.data||{};l.value=`Deleted ${Object.values(t).reduce((e,t)=>e+(t.deleted||0),0).toLocaleString()} rows${e===`all`?` from all tables`:` from ${e}`}.`,c.value=null,await T()}else r.value=n.error||`Purge failed`,c.value=null}catch(e){r.value=e instanceof Error?e.message:`Purge failed`,c.value=null}finally{e!==`all`&&(o.value[e]=!1)}}async function k(){u.value=!0,d.value=``,r.value=``;try{let e=await A.vacuumDb();if(e.success&&e.data){let t=e.data.freed_bytes;d.value=t>0?`Compacted database — freed ${m(t)} (${m(e.data.size_before)} → ${m(e.data.size_after)}).`:`Database already compact (${m(e.data.size_after)}).`,await T()}else r.value=e.error||`Vacuum failed`}catch(e){r.value=e instanceof Error?e.message:`Vacuum failed`}finally{u.value=!1}}return s(T),(e,t)=>(w(),C(`div`,Rc,[S(`div`,zc,[S(`div`,Bc,[t[3]||=S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Database Overview `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Storage usage and table statistics for the repeater database. `)],-1),S(`button`,{onClick:T,disabled:n.value,class:`px-3 py-1.5 bg-cyan-500/20 dark:bg-primary/20 hover:bg-cyan-500/30 dark:hover:bg-primary/30 text-cyan-900 dark:text-white rounded-lg border border-cyan-500/50 dark:border-primary/50 transition-colors text-sm disabled:opacity-50`},[n.value?(w(),C(`span`,Hc,[...t[2]||=[S(`span`,{class:`animate-spin w-3.5 h-3.5 border-2 border-current border-t-transparent rounded-full inline-block`},null,-1),y(` Loading… `,-1)]])):(w(),C(`span`,Uc,`Refresh`))],8,Vc)]),a.value?(w(),C(`div`,Wc,[S(`div`,Gc,[t[4]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Database Size`,-1),S(`p`,Kc,b(m(a.value.database_size_bytes)),1)]),S(`div`,qc,[t[5]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`RRD Metrics`,-1),S(`p`,Jc,b(m(a.value.rrd_size_bytes)),1)]),S(`div`,Yc,[t[6]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Total Size`,-1),S(`p`,Xc,b(m(a.value.database_size_bytes+a.value.rrd_size_bytes)),1)]),S(`div`,Zc,[t[7]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Total Rows`,-1),S(`p`,Qc,b(f.value.toLocaleString()),1)])])):g(``,!0),n.value&&!a.value?(w(),C(`div`,$c,[...t[8]||=[S(`div`,{class:`text-center`},[S(`div`,{class:`animate-spin w-8 h-8 border-2 border-stroke-subtle dark:border-stroke/20 border-t-cyan-500 dark:border-t-primary rounded-full mx-auto mb-4`}),S(`div`,{class:`text-content-secondary dark:text-content-muted`},`Loading database info…`)],-1)]])):g(``,!0),r.value?(w(),C(`div`,el,[S(`p`,tl,b(r.value),1)])):g(``,!0),a.value&&a.value.tables.length>0?(w(),C(`div`,nl,[S(`div`,rl,[S(`table`,il,[t[10]||=S(`thead`,null,[S(`tr`,{class:`border-b border-stroke-subtle dark:border-stroke/10`},[S(`th`,{class:`text-left py-2 pr-4 text-xs font-medium text-content-muted uppercase tracking-wider`},` Table `),S(`th`,{class:`text-right py-2 pr-4 text-xs font-medium text-content-muted uppercase tracking-wider`},` Rows `),S(`th`,{class:`text-right py-2 pr-4 text-xs font-medium text-content-muted uppercase tracking-wider hidden sm:table-cell`},` Date Range `),S(`th`,{class:`text-right py-2 text-xs font-medium text-content-muted uppercase tracking-wider`},` Actions `)])],-1),S(`tbody`,null,[(w(!0),C(x,null,i(a.value.tables,e=>(w(),C(`tr`,{key:e.name,class:`border-b border-stroke-subtle/50 dark:border-stroke/5`},[S(`td`,al,[S(`span`,ol,b(e.name),1)]),S(`td`,sl,[S(`span`,cl,b(e.row_count.toLocaleString()),1)]),S(`td`,ll,[e.has_timestamp&&e.row_count>0?(w(),C(`span`,ul,[y(b(h(e.oldest_timestamp))+` — `+b(h(e.newest_timestamp))+` `,1),S(`span`,dl,`(`+b(_(e.oldest_timestamp,e.newest_timestamp))+`d)`,1)])):e.row_count===0?(w(),C(`span`,fl,`—`)):(w(),C(`span`,pl,`n/a`))]),S(`td`,ml,[p(e.name)&&e.row_count>0?(w(),C(`button`,{key:0,onClick:t=>D(e.name,e.row_count),disabled:o.value[e.name],class:`px-2.5 py-1 bg-red-500/10 dark:bg-red-400/10 hover:bg-red-500/20 dark:hover:bg-red-400/20 text-red-700 dark:text-red-400 rounded border border-red-500/30 dark:border-red-400/20 transition-colors text-xs disabled:opacity-50`},[o.value[e.name]?(w(),C(`span`,gl,[...t[9]||=[S(`span`,{class:`animate-spin w-3 h-3 border border-current border-t-transparent rounded-full inline-block`},null,-1),y(` Purging… `,-1)]])):(w(),C(`span`,_l,`Empty`))],8,hl)):p(e.name)?g(``,!0):(w(),C(`span`,vl,`—`))])]))),128))])])])])):g(``,!0)]),c.value?(w(),C(`div`,yl,[S(`div`,bl,[t[16]||=S(`svg`,{class:`w-5 h-5 text-red-600 dark:text-red-400 shrink-0 mt-0.5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z`})],-1),S(`div`,xl,[S(`h4`,Sl,b(c.value.table===`all`?`Confirm Purge All Tables`:`Confirm Purge "${c.value.table}"`),1),S(`p`,Cl,[c.value.table===`all`?(w(),C(x,{key:0},[t[11]||=y(` This will permanently delete `,-1),t[12]||=S(`strong`,null,`all data`,-1),y(` from every data table (`+b(f.value.toLocaleString())+` rows total). This cannot be undone. `,1)],64)):(w(),C(x,{key:1},[t[13]||=y(` This will permanently delete `,-1),S(`strong`,null,b(c.value.rowCount.toLocaleString())+` rows`,1),t[14]||=y(` from `,-1),S(`strong`,null,b(c.value.table),1),t[15]||=y(`. This cannot be undone. `,-1)],64))]),S(`div`,wl,[S(`button`,{onClick:O,disabled:c.value.executing,class:`px-4 py-2 bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 text-white rounded-lg transition-colors text-sm disabled:opacity-50`},b(c.value.executing?`Purging…`:`Yes, Delete Data`),9,Tl),S(`button`,{onClick:t[0]||=e=>c.value=null,disabled:c.value.executing,class:`px-4 py-2 bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary rounded-lg transition-colors text-sm`},` Cancel `,8,El)])])])])):g(``,!0),S(`div`,Dl,[t[19]||=S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-4`},` Maintenance `,-1),S(`div`,Ol,[S(`button`,{onClick:t[1]||=e=>D(`all`,f.value),disabled:!a.value||f.value===0,class:`px-4 py-2 bg-red-500/20 dark:bg-red-400/20 hover:bg-red-500/30 dark:hover:bg-red-400/30 text-red-900 dark:text-red-200 rounded-lg border border-red-500/50 dark:border-red-400/40 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},[...t[17]||=[S(`span`,{class:`flex items-center gap-2`},[S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16`})]),y(` Purge All Data `)],-1)]],8,kl),S(`button`,{onClick:k,disabled:u.value||!a.value,class:`px-4 py-2 bg-amber-500/20 dark:bg-amber-400/20 hover:bg-amber-500/30 dark:hover:bg-amber-400/30 text-amber-900 dark:text-amber-200 rounded-lg border border-amber-500/50 dark:border-amber-400/40 transition-colors text-sm disabled:opacity-50 disabled:cursor-not-allowed`},[S(`span`,jl,[t[18]||=S(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15`})],-1),y(` `+b(u.value?`Compacting…`:`Compact Database`),1)])],8,Al)]),d.value?(w(),C(`p`,Ml,b(d.value),1)):g(``,!0),l.value?(w(),C(`p`,Nl,b(l.value),1)):g(``,!0)])]))}}),Fl={class:`space-y-6`},Il={class:`glass-card rounded-lg border border-stroke-subtle dark:border-stroke/10 p-6`},Ll={class:`flex items-start justify-between mb-4`},Rl={class:`flex items-center gap-2`},zl=[`disabled`],Bl={key:0,class:`flex items-center gap-1.5`},Vl={key:1},Hl=[`disabled`],Ul={key:0,class:`flex items-center gap-1.5`},Wl={key:1},Gl={key:0,class:`mb-4 p-3 rounded-lg bg-red-500/10 border border-red-500/30 text-red-600 dark:text-red-400 text-sm`},Kl={key:1,class:`mb-4`},ql={class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10 inline-block`},Jl={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},Yl={key:2,class:`p-4 rounded-lg bg-cyan-500/10 dark:bg-primary/10 border border-cyan-400/30 dark:border-primary/30`},Xl={key:3},Zl=[`innerHTML`],Ql={class:`font-semibold text-sm`},$l={class:`text-sm mt-0.5 opacity-80`},eu={class:`grid grid-cols-2 sm:grid-cols-3 gap-3 mb-6`},tu={key:0,class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},nu={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},ru={key:1,class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},iu={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},au={key:2,class:`bg-background-mute dark:bg-background/30 rounded-lg p-3 border border-stroke-subtle dark:border-stroke/10`},ou={class:`text-lg font-semibold text-content-primary dark:text-content-primary font-mono`},su={key:0,class:`mb-6`},cu={class:`space-y-2`},lu={class:`flex items-start justify-between gap-3`},uu={class:`flex items-center gap-2 min-w-0`},du={class:`shrink-0 text-xs font-medium text-content-muted w-5 text-right`},fu={class:`text-right shrink-0`},pu={class:`text-xs text-content-muted`},mu={class:`mt-1.5 ml-7`},hu={class:`text-xs font-mono text-content-secondary dark:text-content-muted break-all`},gu={key:0,class:`text-xs text-content-muted mt-0.5`},_u={key:1,class:`mb-6 p-4 rounded-lg bg-green-500/10 border border-green-500/30 text-sm flex items-center gap-3`},vu={key:2},yu={key:0,class:`overflow-x-auto rounded-lg border border-stroke-subtle dark:border-stroke/10`},bu={class:`w-full text-sm`},xu={class:`px-3 py-2 text-content-muted font-mono text-xs`},Su={class:`px-3 py-2 text-content-primary dark:text-content-primary font-mono text-xs break-all`},Cu={class:`px-3 py-2 text-right font-mono text-xs text-content-secondary dark:text-content-muted whitespace-nowrap`},wu={class:`px-3 py-2 text-right font-mono text-xs text-content-secondary dark:text-content-muted`},Tu={key:4,class:`py-8 text-center text-content-muted text-sm`},Eu=M(f({__name:`MemoryDebug`,setup(e){let n=E(!1),r=E(!1),a=E(``),o=E(null),c=E(!1),l=E(null),f=E(!1),p=v(()=>o.value&&(o.value.current_top_20||o.value.growth_since_baseline));async function m(){n.value=!0,a.value=``;try{let e=await A.get(`memory_debug`);e.success&&e.data?(c.value=!!e.data.tracing,l.value=e.data.rss_mb??null,(e.data.current_top_20||e.data.growth_since_baseline)&&(o.value=e.data)):a.value=e.error||`Failed to fetch memory status`}catch(e){a.value=e instanceof Error?e.message:`Failed to fetch memory status`}finally{n.value=!1}}async function h(){r.value=!0,a.value=``;let e=c.value?`stop`:`start`;try{let t=await A.post(`memory_debug`,{action:e});t.success&&t.data?(c.value=!!t.data.tracing,e===`stop`&&(o.value=null,l.value=null)):a.value=t.error||`Failed to ${e} tracing`}catch(t){a.value=t instanceof Error?t.message:`Failed to ${e} tracing`}finally{r.value=!1,c.value&&await m()}}function T(e){return e.size_diff_kb>=100?`critical`:e.size_diff_kb>=10?`warning`:e.size_diff_kb>=1?`low`:`ok`}function D(e){let t=T(e);return t===`critical`?`Investigate`:t===`warning`?`Watch`:t===`low`?`Minor`:`Normal`}function O(e){let t=T(e);return t===`critical`?`bg-red-500/20 text-red-700 dark:text-red-400 border border-red-500/30`:t===`warning`?`bg-amber-500/20 text-amber-700 dark:text-amber-400 border border-amber-500/30`:t===`low`?`bg-blue-500/15 text-blue-600 dark:text-blue-400 border border-blue-500/20`:`bg-green-500/15 text-green-700 dark:text-green-400 border border-green-500/20`}function k(e){let t=T(e);return t===`critical`?`border-red-500/40 dark:border-red-500/30 bg-red-500/5 dark:bg-red-500/5`:t===`warning`?`border-amber-500/40 dark:border-amber-500/30 bg-amber-500/5 dark:bg-amber-500/5`:t===`low`?`border-stroke-subtle dark:border-stroke/10 bg-background-mute/50 dark:bg-background/20`:`border-stroke-subtle/50 dark:border-stroke/5 bg-background-mute/30 dark:bg-background/10 opacity-60`}function j(e){let t=T(e);return t===`critical`?`text-red-600 dark:text-red-400`:t===`warning`?`text-amber-600 dark:text-amber-400`:t===`low`?`text-blue-600 dark:text-blue-400`:`text-green-600 dark:text-green-500`}function M(e){return e>=1024?`${(e/1024).toFixed(1)} MB`:e>=10?`${Math.round(e)} KB`:`${e.toFixed(1)} KB`}function P(e){return e.replace(/.*\/site-packages\//,``).replace(/.*\/lib\/python[^/]*\//,``).replace(/.*\/repeater\//,`repeater/`)}let F=v(()=>o.value?.growth_since_baseline?o.value.growth_since_baseline.reduce((e,t)=>e+t.size_diff_kb,0):0),I=v(()=>F.value>=500?`critical`:F.value>=50?`warning`:F.value>=5?`low`:`ok`),L=v(()=>{let e=I.value;return e===`critical`?`border-red-500/40 dark:border-red-500/30 bg-red-500/10 dark:bg-red-500/10 text-red-800 dark:text-red-300`:e===`warning`?`border-amber-500/40 dark:border-amber-500/30 bg-amber-500/10 dark:bg-amber-500/10 text-amber-800 dark:text-amber-300`:e===`low`?`border-blue-500/30 bg-blue-500/10 dark:bg-blue-500/10 text-blue-800 dark:text-blue-300`:`border-green-500/30 bg-green-500/10 dark:bg-green-500/10 text-green-800 dark:text-green-300`}),R=v(()=>{let e=I.value;return e===`critical`?` `:e===`warning`?` `:e===`low`?` `:` `}),z=v(()=>{let e=I.value;return e===`critical`?`Significant memory growth detected`:e===`warning`?`Some memory growth detected`:e===`low`?`Minor memory growth — likely normal`:`Memory looks healthy`}),B=v(()=>{let e=M(F.value),t=I.value;return t===`critical`?`Total growth: ${e}. Red items below need attention.`:t===`warning`?`Total growth: ${e}. Orange items below may need attention over time.`:t===`low`?`Total growth: ${e}. Nothing to worry about right now.`:`No significant growth since tracing started.`});return s(m),(e,s)=>(w(),C(`div`,Fl,[S(`div`,Il,[S(`div`,Ll,[s[3]||=S(`div`,null,[S(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-1`},` Memory Diagnostics `),S(`p`,{class:`text-sm text-content-secondary dark:text-content-muted`},` Trace memory allocations to find leaks. Tracing adds overhead — only enable when needed. `)],-1),S(`div`,Rl,[c.value&&p.value?(w(),C(`button`,{key:0,onClick:m,disabled:n.value,class:`px-3 py-1.5 bg-cyan-500/20 dark:bg-primary/20 hover:bg-cyan-500/30 dark:hover:bg-primary/30 text-cyan-900 dark:text-white rounded-lg border border-cyan-500/50 dark:border-primary/50 transition-colors text-sm disabled:opacity-50`},[n.value?(w(),C(`span`,Bl,[...s[1]||=[S(`span`,{class:`animate-spin w-3.5 h-3.5 border-2 border-current border-t-transparent rounded-full inline-block`},null,-1),y(` Checking… `,-1)]])):(w(),C(`span`,Vl,`Check Again`))],8,zl)):g(``,!0),S(`button`,{onClick:h,disabled:r.value,class:u([`px-3 py-1.5 rounded-lg border text-sm transition-colors disabled:opacity-50`,c.value?`bg-red-500/20 hover:bg-red-500/30 text-red-700 dark:text-red-400 border-red-500/50`:`bg-green-500/20 hover:bg-green-500/30 text-green-700 dark:text-green-400 border-green-500/50`])},[r.value?(w(),C(`span`,Ul,[s[2]||=S(`span`,{class:`animate-spin w-3.5 h-3.5 border-2 border-current border-t-transparent rounded-full inline-block`},null,-1),y(` `+b(c.value?`Stopping…`:`Starting…`),1)])):(w(),C(`span`,Wl,b(c.value?`Stop Tracing`:`Start Tracing`),1))],10,Hl)])]),a.value?(w(),C(`div`,Gl,b(a.value),1)):g(``,!0),!c.value&&l.value!==null&&!n.value?(w(),C(`div`,Kl,[S(`div`,ql,[s[4]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Current Memory (RSS)`,-1),S(`p`,Jl,b(l.value)+` MB`,1)])])):g(``,!0),c.value&&!p.value&&!n.value?(w(),C(`div`,Yl,[...s[5]||=[d(` Memory tracing is running. Let the repeater run for a few minutes, then click Check Again to see which parts of the code are using more memory.
`,2)]])):g(``,!0),o.value&&p.value?(w(),C(`div`,Xl,[S(`div`,{class:u([`mb-5 p-4 rounded-lg border flex items-start gap-3`,L.value])},[S(`div`,{class:`mt-0.5`,innerHTML:R.value},null,8,Zl),S(`div`,null,[S(`p`,Ql,b(z.value),1),S(`p`,$l,b(B.value),1)])],2),S(`div`,eu,[o.value.rss_mb===void 0?g(``,!0):(w(),C(`div`,tu,[s[6]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Total Memory Used`,-1),S(`p`,nu,b(o.value.rss_mb)+` MB`,1)])),o.value.traced_current_mb===void 0?g(``,!0):(w(),C(`div`,ru,[s[7]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Tracked Now`,-1),S(`p`,iu,b(o.value.traced_current_mb)+` MB`,1)])),o.value.traced_peak_mb===void 0?g(``,!0):(w(),C(`div`,au,[s[8]||=S(`p`,{class:`text-xs text-content-muted mb-1`},`Peak Tracked`,-1),S(`p`,ou,b(o.value.traced_peak_mb)+` MB`,1)]))]),o.value.growth_since_baseline&&o.value.growth_since_baseline.length>0?(w(),C(`div`,su,[s[9]||=S(`h4`,{class:`text-sm font-semibold text-content-primary dark:text-content-primary mb-1`},`Memory Growth Breakdown`,-1),s[10]||=S(`p`,{class:`text-xs text-content-muted mb-3`},` Items at the top with red/orange tags are the most likely cause of memory issues. Green items are normal and can be ignored. `,-1),S(`div`,cu,[(w(!0),C(x,null,i(o.value.growth_since_baseline,(e,t)=>(w(),C(`div`,{key:t,class:u([`rounded-lg border p-3 transition-colors`,k(e)])},[S(`div`,lu,[S(`div`,uu,[S(`span`,du,b(t+1),1),S(`span`,{class:u([`shrink-0 inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-semibold`,O(e)])},b(D(e)),3)]),S(`div`,fu,[S(`span`,{class:u([`font-mono text-sm font-semibold`,j(e)])},`+`+b(M(e.size_diff_kb)),3),S(`p`,pu,b(M(e.current_size_kb))+` total`,1)])]),S(`div`,mu,[S(`p`,hu,b(P(e.file)),1),e.count_diff===0?g(``,!0):(w(),C(`p`,gu,b(e.count_diff>0?`+`:``)+b(e.count_diff)+` new allocation`+b(Math.abs(e.count_diff)===1?``:`s`),1))])],2))),128))])])):o.value.growth_since_baseline&&o.value.growth_since_baseline.length===0?(w(),C(`div`,_u,[...s[11]||=[S(`svg`,{class:`w-5 h-5 text-green-600 dark:text-green-400 shrink-0`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z`})],-1),S(`span`,{class:`text-green-700 dark:text-green-400`},`No memory growth detected. Everything looks healthy.`,-1)]])):g(``,!0),o.value.current_top_20&&o.value.current_top_20.length>0?(w(),C(`div`,vu,[S(`button`,{onClick:s[0]||=e=>f.value=!f.value,class:`flex items-center gap-2 text-sm font-semibold text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary transition-colors mb-3`},[(w(),C(`svg`,{class:u([`w-4 h-4 transition-transform`,{"rotate-90":f.value}]),fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[...s[12]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 5l7 7-7 7`},null,-1)]],2)),s[13]||=y(` Advanced: Current Top Allocations `,-1)]),_(N,{name:`expand`},{default:t(()=>[f.value?(w(),C(`div`,yu,[S(`table`,bu,[s[14]||=S(`thead`,null,[S(`tr`,{class:`bg-background-mute dark:bg-background/30 text-left`},[S(`th`,{class:`px-3 py-2 text-xs font-medium text-content-muted`},`#`),S(`th`,{class:`px-3 py-2 text-xs font-medium text-content-muted`},`Location`),S(`th`,{class:`px-3 py-2 text-xs font-medium text-content-muted text-right`},`Size`),S(`th`,{class:`px-3 py-2 text-xs font-medium text-content-muted text-right`},`Count`)])],-1),S(`tbody`,null,[(w(!0),C(x,null,i(o.value.current_top_20,(e,t)=>(w(),C(`tr`,{key:t,class:`border-t border-stroke-subtle/50 dark:border-stroke/5 hover:bg-background-mute/50 dark:hover:bg-background/20 transition-colors`},[S(`td`,xu,b(t+1),1),S(`td`,Su,b(P(e.file)),1),S(`td`,Cu,b(M(e.size_kb)),1),S(`td`,wu,b(e.count),1)]))),128))])])])):g(``,!0)]),_:1})])):g(``,!0)])):g(``,!0),!n.value&&!r.value&&!c.value&&!p.value&&!a.value&&l.value===null?(w(),C(`div`,Tu,[...s[15]||=[y(` Click `,-1),S(`strong`,null,`Start Tracing`,-1),y(` to enable memory diagnostics. `,-1),S(`br`,null,null,-1),S(`span`,{class:`text-xs`},`Tracing uses extra memory — remember to stop it when done.`,-1)]])):g(``,!0)])]))}}),[[`__scopeId`,`data-v-50d93367`]]),Du={class:`p-3 sm:p-6 space-y-4 sm:space-y-6`},Ou={class:`glass-card rounded-[15px] z-10 p-3 sm:p-4 border border-cyan-400 dark:border-primary/30 bg-cyan-500/10 dark:bg-primary/10`},ku={class:`text-cyan-700 dark:text-primary text-sm sm:text-base`},Au={class:`mt-1 sm:mt-2 text-cyan-600 dark:text-primary/80`},ju={class:`glass-card rounded-[15px] p-3 sm:p-6`},Mu={class:`relative -mx-3 sm:mx-0 mb-4 sm:mb-6`},Nu={key:0,class:`absolute left-0 top-0 bottom-[1px] w-12 z-10 flex items-center`},Pu={key:0,class:`absolute right-0 top-0 bottom-[1px] w-12 z-10 flex items-center justify-end`},Fu=[`onClick`],Iu={class:`flex items-center gap-1 sm:gap-2`},Lu={key:0,class:`w-3.5 h-3.5 sm:w-4 sm:h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Ru={key:1,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},zu={key:2,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Bu={key:3,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Vu={key:4,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Hu={key:5,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Uu={key:6,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Wu={key:7,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Gu={key:8,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Ku={key:9,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},qu={key:10,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Ju={key:11,class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Yu={class:`min-h-[400px]`},Xu={key:0,class:`flex items-center justify-center py-12`},Zu={key:1,class:`flex items-center justify-center py-12`},Qu={class:`text-center`},$u={class:`text-content-secondary dark:text-content-muted text-sm mb-4`},ed={key:2},td=M(f({name:`ConfigurationView`,__name:`Configuration`,setup(e){let n=j(),o=E(H(`configuration_activeTab`,`radio`)),l=E(!1),d=E(null),f=E(!1),p=E(!1);function v(){if(!d.value)return;let e=d.value;p.value=e.scrollLeft>4,f.value=e.scrollLeftee(`configuration_activeTab`,e));let D=[{id:`radio`,label:`Radio Settings`,icon:`radio`},{id:`repeater`,label:`Repeater Settings`,icon:`repeater`},{id:`advert`,label:`Advert Limits`,icon:`advert`},{id:`duty`,label:`Duty Cycle`,icon:`duty`},{id:`delays`,label:`TX Delays`,icon:`delays`},{id:`transport`,label:`Regions/Keys`,icon:`keys`},{id:`api-tokens`,label:`API Tokens`,icon:`tokens`},{id:`web`,label:`Web Options`,icon:`web`},{id:`observer`,label:`Observer`,icon:`observer`},{id:`backup`,label:`Backup`,icon:`backup`},{id:`database`,label:`Database`,icon:`database`},{id:`memory`,label:`Memory`,icon:`memory`}];s(async()=>{try{await n.fetchStats(),l.value=!0}catch(e){console.error(`Failed to load configuration data:`,e),l.value=!0}c(()=>v())});function O(e){o.value=e}return(e,s)=>{let c=r(`router-link`);return w(),C(`div`,Du,[s[24]||=S(`div`,null,[S(`h1`,{class:`text-xl sm:text-2xl font-bold text-content-primary dark:text-content-primary`},` Configuration `),S(`p`,{class:`text-content-secondary dark:text-content-muted mt-1 sm:mt-2 text-sm sm:text-base`},` System configuration and settings `)],-1),S(`div`,Ou,[S(`div`,ku,[s[5]||=S(`strong`,null,`CAD Calibration Tool Available`,-1),S(`p`,Au,[s[4]||=y(` Optimize your Channel Activity Detection settings. `,-1),_(c,{to:`/cad-calibration`,class:`underline hover:text-cyan-800 dark:hover:text-primary transition-colors`},{default:t(()=>[...s[3]||=[y(` Launch CAD Calibration Tool → `,-1)]]),_:1})])])]),S(`div`,ju,[S(`div`,Mu,[_(N,{name:`tab-fade`},{default:t(()=>[p.value?(w(),C(`div`,Nu,[s[7]||=S(`div`,{class:`tab-fade-left absolute inset-0 pointer-events-none`},null,-1),S(`button`,{onClick:s[0]||=e=>T(`left`),class:`relative z-10 ml-1.5 w-6 h-6 flex items-center justify-center rounded-full bg-white dark:bg-zinc-900 shadow-md border border-gray-200 dark:border-white/10 text-gray-500 dark:text-gray-300`},[...s[6]||=[S(`svg`,{class:`w-3 h-3`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2.5`,d:`M15 19l-7-7 7-7`})],-1)]])])):g(``,!0)]),_:1}),_(N,{name:`tab-fade`},{default:t(()=>[f.value?(w(),C(`div`,Pu,[s[9]||=S(`div`,{class:`tab-fade-right absolute inset-0 pointer-events-none`},null,-1),S(`button`,{onClick:s[1]||=e=>T(`right`),class:`relative z-10 mr-1.5 w-6 h-6 flex items-center justify-center rounded-full bg-white dark:bg-zinc-900 shadow-md border border-gray-200 dark:border-white/10 text-gray-500 dark:text-gray-300`},[...s[8]||=[S(`svg`,{class:`w-3 h-3`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2.5`,d:`M9 5l7 7-7 7`})],-1)]])])):g(``,!0)]),_:1}),S(`div`,{ref_key:`tabsContainer`,ref:d,onScroll:v,class:`flex overflow-x-auto border-b border-stroke-subtle dark:border-stroke/10 px-3 sm:px-0 scrollbar-hide`},[(w(),C(x,null,i(D,e=>S(`button`,{key:e.id,onClick:t=>O(e.id),class:u([`px-3 sm:px-4 py-2 text-xs sm:text-sm font-medium transition-colors duration-200 border-b-2 mr-3 sm:mr-6 whitespace-nowrap flex-shrink-0`,o.value===e.id?`text-cyan-500 dark:text-primary border-cyan-500 dark:border-primary`:`text-content-secondary dark:text-content-muted border-transparent hover:text-content-primary dark:hover:text-content-primary hover:border-stroke-subtle dark:hover:border-stroke/30`])},[S(`div`,Iu,[e.icon===`radio`?(w(),C(`svg`,Lu,[...s[10]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.822c5.716-5.716 14.976-5.716 20.692 0`},null,-1)]])):e.icon===`repeater`?(w(),C(`svg`,Ru,[...s[11]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M5 12h14M5 12l4-4m-4 4l4 4`},null,-1)]])):e.icon===`advert`?(w(),C(`svg`,zu,[...s[12]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z`},null,-1)]])):e.icon===`duty`?(w(),C(`svg`,Bu,[...s[13]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]])):e.icon===`delays`?(w(),C(`svg`,Vu,[...s[14]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z`},null,-1)]])):e.icon===`keys`?(w(),C(`svg`,Hu,[...s[15]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`},null,-1)]])):e.icon===`tokens`?(w(),C(`svg`,Uu,[...s[16]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z`},null,-1)]])):e.icon===`web`?(w(),C(`svg`,Wu,[...s[17]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9`},null,-1)]])):e.icon===`observer`?(w(),C(`svg`,Gu,[...s[18]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]])):e.icon===`backup`?(w(),C(`svg`,Ku,[...s[19]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4`},null,-1)]])):e.icon===`database`?(w(),C(`svg`,qu,[...s[20]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4`},null,-1)]])):e.icon===`memory`?(w(),C(`svg`,Ju,[...s[21]||=[S(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z`},null,-1)]])):g(``,!0),y(` `+b(e.label),1)])],10,Fu)),64))],544)]),S(`div`,Yu,[!l.value&&a(n).isLoading?(w(),C(`div`,Xu,[...s[22]||=[S(`div`,{class:`text-center`},[S(`div`,{class:`animate-spin w-8 h-8 border-2 border-stroke-subtle dark:border-stroke/20 border-t-cyan-500 dark:border-t-primary rounded-full mx-auto mb-4`}),S(`div`,{class:`text-content-secondary dark:text-content-muted`},` Loading configuration... `)],-1)]])):a(n).error&&!l.value?(w(),C(`div`,Zu,[S(`div`,Qu,[s[23]||=S(`div`,{class:`text-red-500 dark:text-red-400 mb-2`},`Failed to load configuration`,-1),S(`div`,$u,b(a(n).error),1),S(`button`,{onClick:s[2]||=e=>a(n).fetchStats(),class:`px-4 py-2 bg-cyan-500/20 dark:bg-primary/20 hover:bg-cyan-500/30 dark:hover:bg-primary/30 text-cyan-900 dark:text-white rounded-lg border border-cyan-500/50 dark:border-primary/50 transition-colors`},` Retry `)])])):(w(),C(`div`,ed,[m(S(`div`,null,[_(ye,{key:`radio-settings`})],512),[[z,o.value===`radio`]]),m(S(`div`,null,[_(St,{key:`repeater-settings`})],512),[[z,o.value===`repeater`]]),m(S(`div`,null,[_(so,{key:`advert-settings`})],512),[[z,o.value===`advert`]]),m(S(`div`,null,[_(Pt,{key:`duty-cycle`})],512),[[z,o.value===`duty`]]),m(S(`div`,null,[_(Jt,{key:`transmission-delays`})],512),[[z,o.value===`delays`]]),m(S(`div`,null,[_(Jr,{key:`transport-keys`})],512),[[z,o.value===`transport`]]),m(S(`div`,null,[_(Si,{key:`api-tokens`})],512),[[z,o.value===`api-tokens`]]),m(S(`div`,null,[_(qi,{key:`web-settings`})],512),[[z,o.value===`web`]]),m(S(`div`,null,[_(js,{key:`letsmesh-settings`})],512),[[z,o.value===`observer`]]),m(S(`div`,null,[_(Lc,{key:`backup-restore`})],512),[[z,o.value===`backup`]]),m(S(`div`,null,[_(Pl,{key:`database-management`})],512),[[z,o.value===`database`]]),m(S(`div`,null,[_(Eu,{key:`memory-debug`})],512),[[z,o.value===`memory`]])]))])])])}}}),[[`__scopeId`,`data-v-e8f5e632`]]);export{td as default};
\ No newline at end of file
diff --git a/repeater/web/html/assets/ConfirmDialog-BECkBcWW.js b/repeater/web/html/assets/ConfirmDialog-COAlYCXc.js
similarity index 97%
rename from repeater/web/html/assets/ConfirmDialog-BECkBcWW.js
rename to repeater/web/html/assets/ConfirmDialog-COAlYCXc.js
index c01ad52..86bc6af 100644
--- a/repeater/web/html/assets/ConfirmDialog-BECkBcWW.js
+++ b/repeater/web/html/assets/ConfirmDialog-COAlYCXc.js
@@ -1 +1 @@
-import{dt as e,g as t,l as n,pt as r,s as i,u as a,w as o}from"./runtime-core.esm-bundler-HnidnMFy.js";import{h as s}from"./index-DiHOFPOZ.js";var c={class:`flex items-center justify-between mb-4`},l={class:`text-xl font-semibold text-content-primary dark:text-content-primary`},u={class:`mb-6`},d={key:0,class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},f={key:1,class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},p={key:2,class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},m={class:`text-content-secondary dark:text-content-primary/80 text-base leading-relaxed`},h={class:`flex gap-3`},g=t({__name:`ConfirmDialog`,props:{show:{type:Boolean},title:{default:`Confirm Action`},message:{},confirmText:{default:`Confirm`},cancelText:{default:`Cancel`},variant:{default:`warning`}},emits:[`close`,`confirm`],setup(t,{emit:g}){let _=t,v=g,y=e=>{e.target===e.currentTarget&&v(`close`)},b={danger:`bg-red-100 dark:bg-red-500/20 border-red-500/30 text-red-600 dark:text-red-400`,warning:`bg-yellow-100 dark:bg-yellow-500/20 border-yellow-500/30 text-yellow-600 dark:text-yellow-400`,info:`bg-blue-500/20 border-blue-500/30 text-blue-600 dark:text-blue-400`},x={danger:`bg-red-500 hover:bg-red-600`,warning:`bg-yellow-500 hover:bg-yellow-600`,info:`bg-blue-500 hover:bg-blue-600`};return(t,g)=>_.show?(o(),a(`div`,{key:0,onClick:y,class:`fixed inset-0 bg-black/40 backdrop-blur-lg z-[99999] flex items-center justify-center p-4`,style:{"backdrop-filter":`blur(8px) saturate(180%)`,position:`fixed`,top:`0`,left:`0`,right:`0`,bottom:`0`}},[i(`div`,{class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] p-6 w-full max-w-md border border-stroke-subtle dark:border-white/10`,onClick:g[3]||=s(()=>{},[`stop`])},[i(`div`,c,[i(`h3`,l,r(_.title),1),i(`button`,{onClick:g[0]||=e=>v(`close`),class:`text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary transition-colors`},[...g[4]||=[i(`svg`,{class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[i(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),i(`div`,u,[i(`div`,{class:e([`inline-flex p-3 rounded-xl mb-4`,b[_.variant]])},[_.variant===`danger`?(o(),a(`svg`,d,[...g[5]||=[i(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z`},null,-1)]])):_.variant===`warning`?(o(),a(`svg`,f,[...g[6]||=[i(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z`},null,-1)]])):(o(),a(`svg`,p,[...g[7]||=[i(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]]))],2),i(`p`,m,r(_.message),1)]),i(`div`,h,[i(`button`,{onClick:g[1]||=e=>v(`close`),class:`flex-1 px-4 py-3 rounded-xl bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary transition-all duration-200 border border-stroke-subtle dark:border-stroke/10`},r(_.cancelText),1),i(`button`,{onClick:g[2]||=e=>v(`confirm`),class:e([`flex-1 px-4 py-3 rounded-xl text-white transition-all duration-200`,x[_.variant]])},r(_.confirmText),3)])])])):n(``,!0)}});export{g as t};
\ No newline at end of file
+import{dt as e,g as t,l as n,pt as r,s as i,u as a,w as o}from"./runtime-core.esm-bundler-HnidnMFy.js";import{h as s}from"./index-C6ELfnbI.js";var c={class:`flex items-center justify-between mb-4`},l={class:`text-xl font-semibold text-content-primary dark:text-content-primary`},u={class:`mb-6`},d={key:0,class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},f={key:1,class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},p={key:2,class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},m={class:`text-content-secondary dark:text-content-primary/80 text-base leading-relaxed`},h={class:`flex gap-3`},g=t({__name:`ConfirmDialog`,props:{show:{type:Boolean},title:{default:`Confirm Action`},message:{},confirmText:{default:`Confirm`},cancelText:{default:`Cancel`},variant:{default:`warning`}},emits:[`close`,`confirm`],setup(t,{emit:g}){let _=t,v=g,y=e=>{e.target===e.currentTarget&&v(`close`)},b={danger:`bg-red-100 dark:bg-red-500/20 border-red-500/30 text-red-600 dark:text-red-400`,warning:`bg-yellow-100 dark:bg-yellow-500/20 border-yellow-500/30 text-yellow-600 dark:text-yellow-400`,info:`bg-blue-500/20 border-blue-500/30 text-blue-600 dark:text-blue-400`},x={danger:`bg-red-500 hover:bg-red-600`,warning:`bg-yellow-500 hover:bg-yellow-600`,info:`bg-blue-500 hover:bg-blue-600`};return(t,g)=>_.show?(o(),a(`div`,{key:0,onClick:y,class:`fixed inset-0 bg-black/40 backdrop-blur-lg z-[99999] flex items-center justify-center p-4`,style:{"backdrop-filter":`blur(8px) saturate(180%)`,position:`fixed`,top:`0`,left:`0`,right:`0`,bottom:`0`}},[i(`div`,{class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] p-6 w-full max-w-md border border-stroke-subtle dark:border-white/10`,onClick:g[3]||=s(()=>{},[`stop`])},[i(`div`,c,[i(`h3`,l,r(_.title),1),i(`button`,{onClick:g[0]||=e=>v(`close`),class:`text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary transition-colors`},[...g[4]||=[i(`svg`,{class:`w-6 h-6`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[i(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])]),i(`div`,u,[i(`div`,{class:e([`inline-flex p-3 rounded-xl mb-4`,b[_.variant]])},[_.variant===`danger`?(o(),a(`svg`,d,[...g[5]||=[i(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z`},null,-1)]])):_.variant===`warning`?(o(),a(`svg`,f,[...g[6]||=[i(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z`},null,-1)]])):(o(),a(`svg`,p,[...g[7]||=[i(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]]))],2),i(`p`,m,r(_.message),1)]),i(`div`,h,[i(`button`,{onClick:g[1]||=e=>v(`close`),class:`flex-1 px-4 py-3 rounded-xl bg-background-mute dark:bg-white/5 hover:bg-stroke-subtle dark:hover:bg-white/10 text-content-primary dark:text-content-primary transition-all duration-200 border border-stroke-subtle dark:border-stroke/10`},r(_.cancelText),1),i(`button`,{onClick:g[2]||=e=>v(`confirm`),class:e([`flex-1 px-4 py-3 rounded-xl text-white transition-all duration-200`,x[_.variant]])},r(_.confirmText),3)])])])):n(``,!0)}});export{g as t};
\ No newline at end of file
diff --git a/repeater/web/html/assets/Dashboard-BtQjgaj6.js b/repeater/web/html/assets/Dashboard-CC5o9Zuu.js
similarity index 99%
rename from repeater/web/html/assets/Dashboard-BtQjgaj6.js
rename to repeater/web/html/assets/Dashboard-CC5o9Zuu.js
index c1ebad5..4060c5a 100644
--- a/repeater/web/html/assets/Dashboard-BtQjgaj6.js
+++ b/repeater/web/html/assets/Dashboard-CC5o9Zuu.js
@@ -1,2 +1,2 @@
-import{A as e,E as t,I as n,K as r,S as i,b as a,c as o,dt as s,f as c,ft as l,g as u,i as d,j as f,k as p,l as m,m as h,o as g,p as _,pt as v,r as y,s as b,u as x,w as S,x as C,z as w}from"./runtime-core.esm-bundler-HnidnMFy.js";import{t as T}from"./api-B2W0XzZe.js";import{t as E}from"./system-m4eSASWi.js";import{t as D}from"./packets-8O8X_yXW.js";import{t as O}from"./websocket-BofigUzY.js";import{t as k}from"./_plugin-vue_export-helper-B7aGp3iI.js";import{a as A,c as ee,d as te,h as j}from"./index-DiHOFPOZ.js";import{n as M,t as N}from"./preferences-Bv8i60GL.js";import{a as P,c as F,i as I,l as L,m as ne,s as R,u as re}from"./chart-B1uYMRrx.js";import{t as z}from"./useSignalQuality-DltR4z0f.js";var ie={class:`sparkline-card`},B={class:`card-header`},ae={class:`card-title`},V={class:`card-values`},H={class:`card-chart`},U=k(u({name:`ChartSparkline`,__name:`ChartSparkline`,props:{title:{},value:{},color:{},data:{default:()=>[]},showChart:{type:Boolean,default:!0},secondaryValue:{default:void 0},secondaryLabel:{default:``},secondaryColor:{default:``},secondaryData:{default:()=>[]}},setup(e){P.register(I,L,re,F,R,ne);let t=e,r=w(null),o=w(null),s=e=>{if(e.length<3)return e;let t=Math.min(15,Math.max(3,Math.floor(e.length*.2))),n=[];for(let r=0;re+t,0)/s.length)}let r=Math.min(12,n.length),i=n.length/r,a=[];for(let e=0;e!t.data||t.data.length===0?[]:s(t.data)),u=g(()=>!t.secondaryData||t.secondaryData.length===0?[]:s(t.secondaryData)),d=()=>{if(!r.value)return;let e=r.value.getContext(`2d`);if(!e)return;o.value&&=(o.value.destroy(),null);let i=c.value;if(i.length<2)return;let a=[{data:i,borderColor:t.color,borderWidth:2.5,fill:!1,tension:.4,pointRadius:0,pointHoverRadius:0}],s=u.value;s.length>=2&&t.secondaryColor&&a.push({data:s,borderColor:t.secondaryColor,borderWidth:2,borderDash:[4,3],fill:!1,tension:.4,pointRadius:0,pointHoverRadius:0}),o.value=n(new P(e,{type:`line`,data:{labels:i.map((e,t)=>t.toString()),datasets:a},options:{responsive:!0,maintainAspectRatio:!1,animation:{duration:800,easing:`easeOutQuart`},plugins:{legend:{display:!1},tooltip:{enabled:!1}},scales:{x:{display:!1,grid:{display:!1}},y:{display:!1,grid:{display:!1},grace:`10%`}},elements:{line:{capBezierPoints:!0}}}}))},f=()=>{if(!o.value){d();return}let e=c.value;if(e.length<2)return;o.value.data.labels=e.map((e,t)=>t.toString()),o.value.data.datasets[0].data=e;let n=u.value;n.length>=2&&t.secondaryColor&&(o.value.data.datasets.length<2?o.value.data.datasets.push({data:n,borderColor:t.secondaryColor,borderWidth:2,borderDash:[4,3],fill:!1,tension:.4,pointRadius:0,pointHoverRadius:0}):o.value.data.datasets[1].data=n),o.value.update(`default`)};return p(()=>t.data,()=>{a(()=>f())},{deep:!0}),p(()=>t.color,()=>{o.value&&(o.value.data.datasets[0].borderColor=t.color,o.value.update(`none`))}),i(()=>{a(()=>d())}),C(()=>{o.value&&=(o.value.destroy(),null)}),(t,n)=>(S(),x(`div`,ie,[b(`div`,B,[b(`p`,ae,v(e.title),1),b(`div`,V,[b(`span`,{class:`card-value`,style:l({color:e.color})},v(typeof e.value==`number`?e.value.toLocaleString():e.value),5),e.secondaryValue===void 0?m(``,!0):(S(),x(`span`,{key:0,class:`card-secondary-value`,style:l({color:e.secondaryColor})},v(e.secondaryLabel)+v(typeof e.secondaryValue==`number`?e.secondaryValue.toLocaleString():e.secondaryValue),5))])]),b(`div`,H,[e.showChart?(S(),x(`canvas`,{key:0,ref_key:`canvasRef`,ref:r},null,512)):m(``,!0)])]))}}),[[`__scopeId`,`data-v-d5c09182`]]),W={class:`grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3 lg:gap-4 mb-5 stats-cards-container`},G=k(u({name:`StatsCards`,__name:`StatsCards`,setup(e){let t=D(),n=O(),r=w(null),o=w(!1),s=g(()=>{let e=t.packetStats,n=t.systemStats,r=e=>{let t=Math.floor(e/86400),n=Math.floor(e%86400/3600),r=Math.floor(e%3600/60);return t>0?`${t}d ${n}h`:n>0?`${n}h ${r}m`:`${r}m`},i=e?.total_packets||0,a=e?.dropped_packets||0,o=i>0?Math.round(a/i*100):0;return{packetsReceived:i,packetsForwarded:e?.transmitted_packets||0,uptimeFormatted:n?r(n.uptime_seconds||0):`0m`,uptimeHours:n?Math.floor((n.uptime_seconds||0)/3600):0,droppedPackets:a,dropPercent:`${o}%`,signalQuality:Math.round((e?.avg_rssi||0)+120),crcErrorCount:t.crcErrorCount}}),c=g(()=>t.sparklineData),l=async()=>{if(!o.value)try{o.value=!0,await Promise.all([t.fetchSystemStats(),t.fetchPacketStats({hours:24})]),await a()}catch(e){console.error(`Error fetching stats:`,e)}finally{o.value=!1}};return i(async()=>{await t.initializeSparklineHistory(),l(),r.value=window.setInterval(()=>{t.interpolateRates()},6e4)}),A(l,{intervalMs:3e4,enabled:()=>!n.isConnected,immediate:!1}),C(()=>{r.value&&clearInterval(r.value)}),(e,t)=>(S(),x(`div`,W,[h(U,{title:`Up Time`,value:s.value.uptimeFormatted,color:`#EBA0FC`,data:[],showChart:!1,class:`stat-card`},null,8,[`value`]),h(U,{title:`RX Packets`,value:s.value.packetsReceived,color:`#AAE8E8`,data:c.value.totalPackets,class:`stat-card`},null,8,[`value`,`data`]),h(U,{title:`Forward`,value:s.value.packetsForwarded,color:`#FFC246`,data:c.value.transmittedPackets,class:`stat-card`},null,8,[`value`,`data`]),h(U,{title:`Dropped`,value:s.value.droppedPackets,color:`#FB787B`,data:c.value.droppedPackets,class:`stat-card`},null,8,[`value`,`data`]),h(U,{title:`CRC Errors`,value:s.value.crcErrorCount,color:`#F59E0B`,data:c.value.crcErrors,class:`stat-card`},null,8,[`value`,`data`])]))}}),[[`__scopeId`,`data-v-9aa769d6`]]),K={class:`glass-card rounded-[10px] p-4 lg:p-6`},q={class:`h-48 lg:h-56 relative`},oe={key:0,class:`absolute inset-0 flex items-center justify-center`},J={key:1,class:`absolute inset-0 flex items-center justify-center`},se={class:`text-red-600 dark:text-red-400 text-sm lg:text-base`},ce={key:2,class:`absolute inset-0 flex items-center justify-center`},Y={key:3,class:`h-full flex flex-col`},X={key:0,class:`absolute top-2 left-1/2 -translate-x-1/2 bg-white/95 dark:bg-surface-elevated border border-stroke-subtle dark:border-stroke rounded-lg px-3 py-2 z-10 pointer-events-none min-w-48`},le={class:`text-content-primary dark:text-content-primary text-sm font-medium mb-1`},ue={class:`text-content-primary dark:text-content-primary`},de={class:`flex-1 flex items-end justify-evenly gap-4 px-4`},Z=[`onMouseenter`],fe={class:`text-content-primary dark:text-content-primary text-xs sm:text-sm font-semibold text-center w-full`,style:{"padding-bottom":`5px`}},pe={class:`text-content-secondary dark:text-content-muted text-xs mt-2 text-center`},me={key:0,class:`mt-4 flex flex-wrap justify-center gap-3 sm:gap-4 px-2 sm:px-4 text-[10px] sm:text-xs text-content-secondary dark:text-content-muted`},he={class:`truncate text-left`},ge={key:1,class:`mt-3 text-xs text-content-secondary dark:text-content-muted text-center`},_e=k(u({name:`PacketTypesChart`,__name:`PacketTypesChart`,setup(e){let n=w([]),r=D(),a=O(),o=w(!0),s=w(null),c=w(null),u=[{name:`Payload`,types:[`Plain Text Message`,`Group Text Message`,`Group Datagram`,`Multi-part Packet`],subColors:[`#3B82F6`,`#60A5FA`,`#93C5FD`,`#BFDBFE`]},{name:`Requests`,types:[`Request`,`Response`,`Anonymous Request`],subColors:[`#10B981`,`#34D399`,`#6EE7B7`]},{name:`Control`,types:[`Node Advertisement`,`Acknowledgment`,`Returned Path`],subColors:[`#F59E0B`,`#FBBF24`,`#FCD34D`]},{name:`Routing`,types:[`Trace`],subColors:[`#8B5CF6`]},{name:`Reserved`,types:[`Reserved Type 11`,`Reserved Type 12`,`Reserved Type 13`],subColors:[`#6B7280`,`#9CA3AF`,`#D1D5DB`]}],d=g(()=>u.map(e=>{let t=n.value.filter(t=>e.types.some(e=>t.name.includes(e)||t.name===e)).sort((e,t)=>t.count-e.count).map((t,n)=>({...t,color:e.subColors[n%e.subColors.length]}));return{name:e.name,color:e.subColors[0],items:t,total:t.reduce((e,t)=>e+t.count,0)}}).filter(e=>e.total>0)),f=g(()=>Math.max(...d.value.map(e=>e.total),1)),h=g(()=>d.value.reduce((e,t)=>e+t.total,0)),_=async()=>{try{s.value=null;let e=await T.get(`/packet_type_graph_data`);if(e?.success&&e?.data){let t=e.data;if(t?.series){let e=[];t.series.forEach((t,n)=>{let r=0;t.data&&Array.isArray(t.data)&&(r=t.data.reduce((e,t)=>e+(t[1]||0),0)),r>0&&e.push({name:t.name||`Type ${t.type}`,type:t.type,count:r,color:``})}),n.value=e,o.value=!1}else s.value=`No series data in server response`,o.value=!1}else s.value=`Invalid response from server`,o.value=!1}catch(e){s.value=e instanceof Error?e.message:`Failed to load data`,o.value=!1}},C={0:`Request`,1:`Response`,2:`Plain Text Message`,3:`Acknowledgment`,4:`Node Advertisement`,5:`Group Text Message`,6:`Group Datagram`,7:`Anonymous Request`,8:`Returned Path`,9:`Trace`,10:`Multi-part Packet`,15:`Custom Packet`},E=()=>{let e=r.packetTypeBreakdown;!e||e.length===0||(n.value=e.map(e=>({name:C[Number(e.type)]||`Type ${e.type}`,type:e.type,count:e.count,color:``})),o.value=!1,s.value=null)},k=e=>Math.max(e/f.value*90,2),ee=(e,t)=>t===0?0:e/t*100;return i(()=>{_()}),p(()=>r.packetTypeBreakdown,()=>E(),{deep:!0,immediate:!0}),A(_,{intervalMs:3e4,enabled:()=>!a.isConnected,immediate:!0}),(e,n)=>(S(),x(`div`,K,[n[3]||=b(`div`,{class:`flex items-baseline justify-between mb-3 lg:mb-4`},[b(`h3`,{class:`text-content-primary dark:text-content-primary text-lg lg:text-xl font-semibold`},` Packet Types `),b(`p`,{class:`text-content-secondary dark:text-content-muted text-xs lg:text-sm uppercase`},` Distribution by Type `)],-1),b(`div`,q,[o.value?(S(),x(`div`,oe,[...n[1]||=[b(`div`,{class:`text-content-secondary dark:text-content-primary text-sm lg:text-base`},` Loading packet types... `,-1)]])):s.value?(S(),x(`div`,J,[b(`div`,se,v(s.value),1)])):d.value.length===0?(S(),x(`div`,ce,[...n[2]||=[b(`div`,{class:`text-content-secondary dark:text-content-primary text-sm lg:text-base`},` No packet data available `,-1)]])):(S(),x(`div`,Y,[c.value?(S(),x(`div`,X,[b(`div`,le,v(c.value.name)+` · `+v(c.value.total.toLocaleString()),1),(S(!0),x(y,null,t(c.value.items,e=>(S(),x(`div`,{key:e.type,class:`flex justify-between gap-4 text-xs text-content-secondary dark:text-content-muted`},[b(`span`,null,v(e.name),1),b(`span`,ue,v(e.count.toLocaleString()),1)]))),128))])):m(``,!0),b(`div`,de,[(S(!0),x(y,null,t(d.value,e=>(S(),x(`div`,{key:e.name,class:`flex flex-col items-center flex-1 max-w-32 h-full justify-end cursor-pointer`,onMouseenter:t=>c.value=e,onMouseleave:n[0]||=e=>c.value=null},[b(`span`,fe,v(e.total.toLocaleString()),1),b(`div`,{class:`w-full rounded-[5px] transition-all duration-300 ease-out hover:opacity-90 overflow-hidden flex flex-col-reverse`,style:l({height:k(e.total)+`%`,minHeight:`8px`})},[(S(!0),x(y,null,t(e.items,t=>(S(),x(`div`,{key:t.type,style:l({height:ee(t.count,e.total)+`%`,backgroundColor:t.color})},null,4))),128))],4),b(`span`,pe,v(e.name),1)],40,Z))),128))])]))]),d.value.length>0?(S(),x(`div`,me,[(S(!0),x(y,null,t(d.value,e=>(S(),x(`div`,{key:`legend-`+e.name,class:`flex flex-col gap-0.5 min-w-[100px] max-w-[140px] flex-shrink-0`},[(S(!0),x(y,null,t(e.items,e=>(S(),x(`div`,{key:e.type,class:`flex items-center gap-1.5`},[b(`span`,{class:`w-2 h-2 rounded-sm shrink-0`,style:l({backgroundColor:e.color})},null,4),b(`span`,he,v(e.name),1)]))),128))]))),128))])):m(``,!0),d.value.length>0?(S(),x(`div`,ge,` Total: `+v(h.value.toLocaleString())+` packets `,1)):m(``,!0)]))}}),[[`__scopeId`,`data-v-fdd759f8`]]),ve={class:`glass-card rounded-[10px] p-4 lg:p-6`},ye={class:`relative h-40 lg:h-48`},be={class:`mt-3 lg:mt-4 grid grid-cols-2 gap-3 lg:gap-4`},xe={class:`text-center`},Se={class:`text-lg lg:text-2xl font-bold text-content-primary dark:text-content-primary`},Ce={class:`text-center`},we={class:`text-lg lg:text-2xl font-bold text-content-primary dark:text-content-primary`},Te={class:`mt-2 lg:mt-3 grid grid-cols-3 gap-2 lg:gap-3 text-center`},Ee={class:`text-xs lg:text-sm font-semibold text-accent-purple flex items-center justify-center gap-1`},De={key:0,class:`inline-block w-1.5 h-1.5 rounded-full bg-secondary opacity-70`,title:`Early data - limited uptime`},Oe={class:`text-xs text-content-secondary dark:text-content-muted`},ke={class:`text-xs lg:text-sm font-semibold text-accent-red flex items-center justify-center gap-1`},Ae={key:0,class:`inline-block w-1.5 h-1.5 rounded-full bg-secondary opacity-70`,title:`Early data - limited uptime`},je={class:`text-xs text-content-secondary dark:text-content-muted`},Me={class:`text-xs lg:text-sm font-semibold text-white`},Ne=k(u({name:`AirtimeUtilizationChart`,__name:`AirtimeUtilizationChart`,setup(e){let t=D(),n=E(),o=w(null),s=w([]),l=w(!0),u=w(null),d=w(30),f=w({totalReceived:0,totalTransmitted:0,dropped:0,firstPacketTime:0}),p=w({sf:9,bwHz:62500,cr:5,preamble:17}),h=(e,t=60)=>{if(e.length===0)return[];let n=1-.5**(1/t),r=Math.min(e.length,Math.max(10,Math.floor(t/3))),i=0,a=0;for(let t=0;t(i=n*e.rxUtil+(1-n)*i,a=n*e.txUtil+(1-n)*a,{...e,rxUtil:i,txUtil:a}))},y=g(()=>{let e=t.packetStats?.total_packets||0,r=t.packetStats?.transmitted_packets||0,i=n.stats?.uptime_seconds||0,a=e||f.value.totalReceived,o=r||f.value.totalTransmitted,s=f.value.firstPacketTime>0?Math.floor(Date.now()/1e3)-f.value.firstPacketTime:0,c=i||s,l=Math.max(c/3600,.1);if(l<1){let e=Math.max(c/60,1);return{rxRate:{value:Math.round(a/e*100)/100,label:l<.5?`RX/min (early)`:`RX/min`},txRate:{value:Math.round(o/e*100)/100,label:l<.5?`TX/min (early)`:`TX/min`},confidence:`low`}}let u=Math.round(a/l*100)/100,d=Math.round(o/l*100)/100,p,m;return l<6?(p=`RX/hr (${Math.round(l)}h)`,m=`medium`):l<24?(p=`RX/hr (${Math.round(l)}h)`,m=`high`):(p=`RX/hr`,m=`high`),{rxRate:{value:u,label:p},txRate:{value:d,label:p.replace(`RX`,`TX`)},confidence:m}}),O=async()=>{l.value=!0;try{let e=60*1e3,t=Math.floor(Date.now()/1e3),n=t-24*3600,r=0;try{let e=await T.get(`/stats`);if(e.success&&e.data){let t=e.data,n=t.config;if(n?.radio){let e=n.radio;p.value={sf:e.spreading_factor??9,bwHz:e.bandwidth??62500,cr:e.coding_rate??5,preamble:e.preamble_length??17}}r=t.dropped_count??0}}catch{}let i=await T.get(`/airtime_chart_data`,{start_timestamp:n,end_timestamp:t,bucket_seconds:60,sf:p.value.sf,bw_hz:p.value.bwHz,cr:p.value.cr,preamble:p.value.preamble});if(!i.success){s.value=[],l.value=!1,a(()=>k());return}let o=i.data,c=o.buckets||[];f.value={totalReceived:o.rx_total||0,totalTransmitted:o.tx_total||0,dropped:r,firstPacketTime:c.length>0?c[0].timestamp:t};let u=24*3600/60,m=new Float64Array(u),g=new Float64Array(u);for(let t of c){let r=Math.floor((t.timestamp-n)/60);r>=0&&r[e.rxUtil,e.txUtil]))*1.05;d.value=Math.max(5,Math.ceil(x/5)*5),l.value=!1,a(()=>k())}catch(e){console.error(`Failed to fetch airtime data:`,e),s.value=[],l.value=!1,a(()=>k())}},k=()=>{if(!o.value)return;let e=o.value,t=e.getContext(`2d`);if(!t)return;let n=e.parentElement;if(!n)return;let r=n.getBoundingClientRect(),i=r.width,a=r.height;if(e.width=i*window.devicePixelRatio,e.height=a*window.devicePixelRatio,e.style.width=i+`px`,e.style.height=a+`px`,t.scale(window.devicePixelRatio,window.devicePixelRatio),t.clearRect(0,0,i,a),l.value){t.fillStyle=`#666`,t.font=`16px system-ui`,t.textAlign=`center`,t.fillText(`Loading chart data...`,i/2,a/2);return}if(s.value.length===0){t.fillStyle=`#666`,t.font=`16px system-ui`,t.textAlign=`center`,t.fillText(`No data available`,i/2,a/2);return}let c=i-45-20,u=a-40,f=d.value,p=d.value;t.strokeStyle=`rgba(255, 255, 255, 0.1)`,t.lineWidth=1,t.font=`10px system-ui`,t.textAlign=`right`;for(let e=0;e<=5;e++){let n=20+u*e/5;t.beginPath(),t.moveTo(45,n),t.lineTo(i-20,n),t.stroke();let r=f-e/5*p;t.fillStyle=`rgba(255, 255, 255, 0.5)`,t.fillText(`${r.toFixed(0)}%`,40,n+3)}for(let e=0;e<=6;e++){let n=45+c*e/6;t.beginPath(),t.moveTo(n,20),t.lineTo(n,a-20),t.stroke()}s.value.length>1&&(t.strokeStyle=`#EBA0FC`,t.lineWidth=2,t.beginPath(),s.value.forEach((e,n)=>{let r=45+c*n/(s.value.length-1),i=a-20-Math.min(e.rxUtil,d.value)/p*u;n===0?t.moveTo(r,i):t.lineTo(r,i)}),t.stroke()),s.value.length>1&&(t.strokeStyle=`#FB787B`,t.lineWidth=2,t.beginPath(),s.value.forEach((e,n)=>{let r=45+c*n/(s.value.length-1),i=a-20-Math.min(e.txUtil,d.value)/p*u;n===0?t.moveTo(r,i):t.lineTo(r,i)}),t.stroke())};return i(()=>{O(),u.value=window.setInterval(O,3e4),a(()=>{k(),setTimeout(()=>k(),100)}),window.addEventListener(`resize`,k)}),C(()=>{u.value&&clearInterval(u.value),window.removeEventListener(`resize`,k)}),(e,n)=>(S(),x(`div`,ve,[n[3]||=c(` Airtime Utilization Activity (Last 24 Hours)
`,3),b(`div`,ye,[b(`canvas`,{ref_key:`chartRef`,ref:o,class:`absolute inset-0 w-full h-full`},null,512)]),b(`div`,be,[b(`div`,xe,[b(`div`,Se,v(r(t).packetStats?.total_packets||f.value.totalReceived),1),n[0]||=b(`div`,{class:`text-xs text-content-secondary dark:text-content-muted uppercase tracking-wide`},` Total Received `,-1)]),b(`div`,Ce,[b(`div`,we,v(r(t).packetStats?.transmitted_packets||f.value.totalTransmitted),1),n[1]||=b(`div`,{class:`text-xs text-content-secondary dark:text-content-muted uppercase tracking-wide`},` Total Transmitted `,-1)])]),b(`div`,Te,[b(`div`,null,[b(`div`,Ee,[_(v(y.value.rxRate.value)+` `,1),y.value.confidence===`low`?(S(),x(`span`,De)):m(``,!0)]),b(`div`,Oe,v(y.value.rxRate.label),1)]),b(`div`,null,[b(`div`,ke,[_(v(y.value.txRate.value)+` `,1),y.value.confidence===`low`?(S(),x(`span`,Ae)):m(``,!0)]),b(`div`,je,v(y.value.txRate.label),1)]),b(`div`,null,[b(`div`,Me,v(r(t).packetStats?.dropped_packets||f.value.dropped),1),n[2]||=b(`div`,{class:`text-xs text-white/60`},`Dropped`,-1)])])]))}}),[[`__scopeId`,`data-v-51cd61e9`]]),Pe={class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] shadow-2xl border border-stroke-subtle dark:border-white/20 flex flex-col h-full overflow-hidden`},Fe={class:`flex items-center justify-between p-8 pb-4 flex-shrink-0`},Ie={class:`text-content-secondary dark:text-content-muted text-sm`},Le={class:`flex items-center gap-2`},Re=[`title`],ze={class:`flex-1 overflow-y-auto custom-scrollbar px-8`},Be={class:`mb-6`},Ve={class:`glass-card bg-white/5 rounded-[15px] p-4`},He={class:`grid grid-cols-1 md:grid-cols-2 gap-4`},Ue={class:`space-y-3`},We={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Ge={class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ke={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},qe={class:`text-content-primary dark:text-content-primary font-mono text-xs break-all`},Je={key:0,class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Ye={class:`text-content-primary dark:text-content-primary font-mono text-xs`},Xe={class:`space-y-3`},Ze={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Qe={class:`text-content-primary dark:text-content-primary font-semibold`},$e={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},et={class:`text-content-primary dark:text-content-primary font-semibold`},tt={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},nt={class:`mb-6`},rt={class:`bg-gray-50 dark:bg-white/5 rounded-[15px] p-4 border border-stroke-subtle dark:border-stroke/10`},it={class:`space-y-3`},at={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},ot={class:`text-content-primary dark:text-content-primary`},st={key:0,class:`pt-2`},ct={class:`glass-card bg-background-mute dark:bg-black/30 rounded-[10px] p-4 mb-4`},lt={class:`w-full overflow-x-auto`},ut={class:`text-content-primary dark:text-content-primary/90 text-xs font-mono whitespace-pre leading-relaxed min-w-full`},dt={class:`flex items-center justify-between mb-3`},ft={class:`text-content-secondary dark:text-content-primary/80 text-sm font-semibold`},pt={class:`text-content-muted dark:text-content-muted text-xs`},mt={class:`bg-background-mute dark:bg-black/40 rounded-[8px] p-3 mb-3`},ht={class:`font-mono text-xs text-content-primary dark:text-content-primary break-all whitespace-pre-wrap leading-relaxed`},gt={class:`bg-gray-50 dark:bg-white/5 rounded-[10px] overflow-hidden`},_t={key:0,class:`min-w-0`},vt={class:`text-cyan-500 text-sm font-mono break-words min-w-0`},yt={class:`text-content-primary dark:text-content-primary text-sm break-words min-w-0`},bt={class:`text-content-primary dark:text-content-primary text-sm font-semibold break-all min-w-0 overflow-hidden`},xt=[`title`],St={key:0,class:`text-orange-500 text-xs font-mono break-all min-w-0 overflow-hidden`},Ct=[`title`],wt={class:`grid grid-cols-2 gap-2`},Tt={class:`text-cyan-500 text-sm font-mono break-words`},Et={class:`text-content-primary dark:text-content-primary text-sm break-words`},Dt=[`title`],Ot={key:0},kt=[`title`],At={key:0,class:`text-content-muted dark:text-content-muted text-xs italic mt-2 px-1`},jt={key:1,class:`py-2`},Mt={class:`mb-6`},Nt={class:`bg-gray-50 dark:bg-white/5 rounded-[15px] p-4 border border-stroke-subtle dark:border-stroke/10`},Pt={class:`space-y-4`},Ft={class:`grid grid-cols-1 md:grid-cols-2 gap-4`},It={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Lt={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Rt={key:0,class:`py-2`},zt={class:`bg-background-mute dark:bg-black/20 rounded-[10px] p-4`},Bt={class:`flex items-center flex-wrap gap-2`},Vt={class:`relative group`},Ht={class:`relative px-3 py-2 bg-gradient-to-br from-blue-500/20 to-cyan-500/20 border border-cyan-400/40 rounded-lg transform transition-all hover:scale-105`},Ut={class:`font-mono text-[10px] font-semibold tracking-tight text-content-primary dark:text-content-primary/90 sm:text-xs`},Wt={class:`pointer-events-none absolute bottom-full left-1/2 z-50 mb-2 -translate-x-1/2 transform whitespace-nowrap rounded-md bg-neutral-900 px-2 py-1 font-mono text-xs text-white opacity-0 shadow-lg ring-1 ring-white/10 transition-opacity group-hover:opacity-100`},Gt={key:0,class:`mx-2 text-cyan-600 dark:text-cyan-400/60`},Kt={key:1,class:`py-2`},qt={class:`text-content-secondary dark:text-content-muted text-sm mb-2 flex items-center`},Jt={key:0,class:`w-4 h-4 ml-2 text-yellow-500`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Yt={key:1,class:`text-yellow-500 text-xs ml-1`},Xt={class:`bg-background-mute dark:bg-black/20 rounded-[10px] p-4`},Zt={class:`flex items-center flex-wrap gap-2`},Qt={class:`relative group`},$t={key:0,class:`absolute -top-1 -right-1 w-2 h-2 bg-yellow-400 rounded-full animate-pulse`},en={class:`pointer-events-none absolute bottom-full left-1/2 z-50 mb-2 -translate-x-1/2 transform whitespace-nowrap rounded-md bg-neutral-900 px-2 py-1 font-mono text-xs text-white opacity-0 shadow-lg ring-1 ring-white/10 transition-opacity group-hover:opacity-100`},tn={key:0,class:`mx-1 text-orange-600 dark:text-orange-400/60`},nn={class:`mb-6`},rn={class:`glass-card bg-gray-50 dark:bg-white/5 rounded-[15px] p-4`},an={class:`grid grid-cols-1 md:grid-cols-3 gap-4 mb-4`},on={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},sn={class:`text-lg font-bold text-content-primary dark:text-content-primary`},cn={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},ln={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},un={class:`text-lg font-bold text-content-primary dark:text-content-primary`},dn={key:0,class:`mb-4`},fn={class:`flex items-center gap-3`},pn={class:`flex gap-1`},mn={class:`text-content-secondary dark:text-content-primary/80 text-sm capitalize`},hn={key:1,class:`mb-4`},gn={key:2,class:`mb-4`},_n={class:`text-content-secondary dark:text-content-muted text-sm mb-3`},vn={class:`space-y-2`},yn={class:`flex items-center gap-3`},bn={class:`text-content-muted dark:text-content-muted text-sm`},xn={key:3,class:`mt-6 pt-4 border-t border-stroke-subtle dark:border-stroke/10`},Sn={class:`grid grid-cols-1 md:grid-cols-3 gap-3 mb-4`},Cn={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},wn={class:`text-2xl font-bold text-content-primary dark:text-content-primary`},Tn={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},En={class:`text-2xl font-bold text-content-primary dark:text-content-primary`},Dn={class:`text-content-muted dark:text-content-muted text-xs mt-1`},On={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},kn={class:`text-content-muted dark:text-content-muted text-xs mt-1`},An={key:0,class:`glass-card bg-background-mute dark:bg-black/20 rounded-[10px] p-4`},jn={class:`space-y-3`},Mn={class:`flex-shrink-0 w-16 text-right`},Nn={class:`text-content-secondary dark:text-content-muted text-xs`},Pn={class:`flex-1 relative`},Fn={class:`h-8 rounded-lg overflow-hidden bg-background-mute dark:bg-stroke/5 relative`},In={class:`absolute inset-0 flex items-center px-3`},Ln={class:`text-content-primary dark:text-content-primary text-xs font-mono font-semibold`},Rn={class:`flex-shrink-0 w-12 text-left`},zn={class:`text-content-muted dark:text-content-muted text-xs`},Bn={class:`grid grid-cols-1 md:grid-cols-2 gap-4`},Vn={class:`space-y-2`},Hn={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Un={class:`text-content-primary dark:text-content-primary`},Wn={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Gn={class:`space-y-2`},Kn={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},qn={key:0,class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Jn={class:`text-red-600 dark:text-red-400 text-sm`},Yn={class:`p-8 pt-4 border-t border-stroke-subtle dark:border-stroke/10 flex justify-end flex-shrink-0`},Xn=k(u({name:`PacketDetailsModal`,__name:`PacketDetailsModal`,props:{packet:{},isOpen:{type:Boolean},localHash:{}},emits:[`close`],setup(n,{emit:r}){let{getSignalQuality:i}=z(),a=n,c=r,u=w(!1),f=e=>new Date(e*1e3).toLocaleString(),g=e=>e.transmitted?e.is_duplicate?`text-amber-600 dark:text-amber-400`:e.drop_reason?`text-red-600 dark:text-red-400`:`text-green-600 dark:text-green-400`:`text-red-600 dark:text-red-400`,C=e=>e.transmitted?e.is_duplicate?`Duplicate`:e.drop_reason?`Dropped`:`Forwarded`:`Dropped`,T=e=>({0:`Request`,1:`Response`,2:`Plain Text Message`,3:`Acknowledgment`,4:`Node Advertisement`,5:`Group Text Message`,6:`Group Datagram`,7:`Anonymous Request`,8:`Returned Path`,9:`Trace`,10:`Multi-part Packet`,15:`Custom Packet`})[e]||`Unknown Type (${e})`,E=e=>({0:`Transport Flood`,1:`Flood`,2:`Direct`,3:`Transport Direct`})[e]||`Unknown Route (${e})`,D=e=>{if(!e)return`None`;let t=e.replace(/\s+/g,``).toUpperCase().match(/.{2}/g)||[],n=[];for(let e=0;e[]},showChart:{type:Boolean,default:!0},secondaryValue:{default:void 0},secondaryLabel:{default:``},secondaryColor:{default:``},secondaryData:{default:()=>[]}},setup(e){P.register(I,L,re,F,R,ne);let t=e,r=w(null),o=w(null),s=e=>{if(e.length<3)return e;let t=Math.min(15,Math.max(3,Math.floor(e.length*.2))),n=[];for(let r=0;re+t,0)/s.length)}let r=Math.min(12,n.length),i=n.length/r,a=[];for(let e=0;e!t.data||t.data.length===0?[]:s(t.data)),u=g(()=>!t.secondaryData||t.secondaryData.length===0?[]:s(t.secondaryData)),d=()=>{if(!r.value)return;let e=r.value.getContext(`2d`);if(!e)return;o.value&&=(o.value.destroy(),null);let i=c.value;if(i.length<2)return;let a=[{data:i,borderColor:t.color,borderWidth:2.5,fill:!1,tension:.4,pointRadius:0,pointHoverRadius:0}],s=u.value;s.length>=2&&t.secondaryColor&&a.push({data:s,borderColor:t.secondaryColor,borderWidth:2,borderDash:[4,3],fill:!1,tension:.4,pointRadius:0,pointHoverRadius:0}),o.value=n(new P(e,{type:`line`,data:{labels:i.map((e,t)=>t.toString()),datasets:a},options:{responsive:!0,maintainAspectRatio:!1,animation:{duration:800,easing:`easeOutQuart`},plugins:{legend:{display:!1},tooltip:{enabled:!1}},scales:{x:{display:!1,grid:{display:!1}},y:{display:!1,grid:{display:!1},grace:`10%`}},elements:{line:{capBezierPoints:!0}}}}))},f=()=>{if(!o.value){d();return}let e=c.value;if(e.length<2)return;o.value.data.labels=e.map((e,t)=>t.toString()),o.value.data.datasets[0].data=e;let n=u.value;n.length>=2&&t.secondaryColor&&(o.value.data.datasets.length<2?o.value.data.datasets.push({data:n,borderColor:t.secondaryColor,borderWidth:2,borderDash:[4,3],fill:!1,tension:.4,pointRadius:0,pointHoverRadius:0}):o.value.data.datasets[1].data=n),o.value.update(`default`)};return p(()=>t.data,()=>{a(()=>f())},{deep:!0}),p(()=>t.color,()=>{o.value&&(o.value.data.datasets[0].borderColor=t.color,o.value.update(`none`))}),i(()=>{a(()=>d())}),C(()=>{o.value&&=(o.value.destroy(),null)}),(t,n)=>(S(),x(`div`,ie,[b(`div`,B,[b(`p`,ae,v(e.title),1),b(`div`,V,[b(`span`,{class:`card-value`,style:l({color:e.color})},v(typeof e.value==`number`?e.value.toLocaleString():e.value),5),e.secondaryValue===void 0?m(``,!0):(S(),x(`span`,{key:0,class:`card-secondary-value`,style:l({color:e.secondaryColor})},v(e.secondaryLabel)+v(typeof e.secondaryValue==`number`?e.secondaryValue.toLocaleString():e.secondaryValue),5))])]),b(`div`,H,[e.showChart?(S(),x(`canvas`,{key:0,ref_key:`canvasRef`,ref:r},null,512)):m(``,!0)])]))}}),[[`__scopeId`,`data-v-d5c09182`]]),W={class:`grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3 lg:gap-4 mb-5 stats-cards-container`},G=k(u({name:`StatsCards`,__name:`StatsCards`,setup(e){let t=D(),n=O(),r=w(null),o=w(!1),s=g(()=>{let e=t.packetStats,n=t.systemStats,r=e=>{let t=Math.floor(e/86400),n=Math.floor(e%86400/3600),r=Math.floor(e%3600/60);return t>0?`${t}d ${n}h`:n>0?`${n}h ${r}m`:`${r}m`},i=e?.total_packets||0,a=e?.dropped_packets||0,o=i>0?Math.round(a/i*100):0;return{packetsReceived:i,packetsForwarded:e?.transmitted_packets||0,uptimeFormatted:n?r(n.uptime_seconds||0):`0m`,uptimeHours:n?Math.floor((n.uptime_seconds||0)/3600):0,droppedPackets:a,dropPercent:`${o}%`,signalQuality:Math.round((e?.avg_rssi||0)+120),crcErrorCount:t.crcErrorCount}}),c=g(()=>t.sparklineData),l=async()=>{if(!o.value)try{o.value=!0,await Promise.all([t.fetchSystemStats(),t.fetchPacketStats({hours:24})]),await a()}catch(e){console.error(`Error fetching stats:`,e)}finally{o.value=!1}};return i(async()=>{await t.initializeSparklineHistory(),l(),r.value=window.setInterval(()=>{t.interpolateRates()},6e4)}),A(l,{intervalMs:3e4,enabled:()=>!n.isConnected,immediate:!1}),C(()=>{r.value&&clearInterval(r.value)}),(e,t)=>(S(),x(`div`,W,[h(U,{title:`Up Time`,value:s.value.uptimeFormatted,color:`#EBA0FC`,data:[],showChart:!1,class:`stat-card`},null,8,[`value`]),h(U,{title:`RX Packets`,value:s.value.packetsReceived,color:`#AAE8E8`,data:c.value.totalPackets,class:`stat-card`},null,8,[`value`,`data`]),h(U,{title:`Forward`,value:s.value.packetsForwarded,color:`#FFC246`,data:c.value.transmittedPackets,class:`stat-card`},null,8,[`value`,`data`]),h(U,{title:`Dropped`,value:s.value.droppedPackets,color:`#FB787B`,data:c.value.droppedPackets,class:`stat-card`},null,8,[`value`,`data`]),h(U,{title:`CRC Errors`,value:s.value.crcErrorCount,color:`#F59E0B`,data:c.value.crcErrors,class:`stat-card`},null,8,[`value`,`data`])]))}}),[[`__scopeId`,`data-v-9aa769d6`]]),K={class:`glass-card rounded-[10px] p-4 lg:p-6`},q={class:`h-48 lg:h-56 relative`},oe={key:0,class:`absolute inset-0 flex items-center justify-center`},J={key:1,class:`absolute inset-0 flex items-center justify-center`},se={class:`text-red-600 dark:text-red-400 text-sm lg:text-base`},ce={key:2,class:`absolute inset-0 flex items-center justify-center`},Y={key:3,class:`h-full flex flex-col`},X={key:0,class:`absolute top-2 left-1/2 -translate-x-1/2 bg-white/95 dark:bg-surface-elevated border border-stroke-subtle dark:border-stroke rounded-lg px-3 py-2 z-10 pointer-events-none min-w-48`},le={class:`text-content-primary dark:text-content-primary text-sm font-medium mb-1`},ue={class:`text-content-primary dark:text-content-primary`},de={class:`flex-1 flex items-end justify-evenly gap-4 px-4`},Z=[`onMouseenter`],fe={class:`text-content-primary dark:text-content-primary text-xs sm:text-sm font-semibold text-center w-full`,style:{"padding-bottom":`5px`}},pe={class:`text-content-secondary dark:text-content-muted text-xs mt-2 text-center`},me={key:0,class:`mt-4 flex flex-wrap justify-center gap-3 sm:gap-4 px-2 sm:px-4 text-[10px] sm:text-xs text-content-secondary dark:text-content-muted`},he={class:`truncate text-left`},ge={key:1,class:`mt-3 text-xs text-content-secondary dark:text-content-muted text-center`},_e=k(u({name:`PacketTypesChart`,__name:`PacketTypesChart`,setup(e){let n=w([]),r=D(),a=O(),o=w(!0),s=w(null),c=w(null),u=[{name:`Payload`,types:[`Plain Text Message`,`Group Text Message`,`Group Datagram`,`Multi-part Packet`],subColors:[`#3B82F6`,`#60A5FA`,`#93C5FD`,`#BFDBFE`]},{name:`Requests`,types:[`Request`,`Response`,`Anonymous Request`],subColors:[`#10B981`,`#34D399`,`#6EE7B7`]},{name:`Control`,types:[`Node Advertisement`,`Acknowledgment`,`Returned Path`],subColors:[`#F59E0B`,`#FBBF24`,`#FCD34D`]},{name:`Routing`,types:[`Trace`],subColors:[`#8B5CF6`]},{name:`Reserved`,types:[`Reserved Type 11`,`Reserved Type 12`,`Reserved Type 13`],subColors:[`#6B7280`,`#9CA3AF`,`#D1D5DB`]}],d=g(()=>u.map(e=>{let t=n.value.filter(t=>e.types.some(e=>t.name.includes(e)||t.name===e)).sort((e,t)=>t.count-e.count).map((t,n)=>({...t,color:e.subColors[n%e.subColors.length]}));return{name:e.name,color:e.subColors[0],items:t,total:t.reduce((e,t)=>e+t.count,0)}}).filter(e=>e.total>0)),f=g(()=>Math.max(...d.value.map(e=>e.total),1)),h=g(()=>d.value.reduce((e,t)=>e+t.total,0)),_=async()=>{try{s.value=null;let e=await T.get(`/packet_type_graph_data`);if(e?.success&&e?.data){let t=e.data;if(t?.series){let e=[];t.series.forEach((t,n)=>{let r=0;t.data&&Array.isArray(t.data)&&(r=t.data.reduce((e,t)=>e+(t[1]||0),0)),r>0&&e.push({name:t.name||`Type ${t.type}`,type:t.type,count:r,color:``})}),n.value=e,o.value=!1}else s.value=`No series data in server response`,o.value=!1}else s.value=`Invalid response from server`,o.value=!1}catch(e){s.value=e instanceof Error?e.message:`Failed to load data`,o.value=!1}},C={0:`Request`,1:`Response`,2:`Plain Text Message`,3:`Acknowledgment`,4:`Node Advertisement`,5:`Group Text Message`,6:`Group Datagram`,7:`Anonymous Request`,8:`Returned Path`,9:`Trace`,10:`Multi-part Packet`,15:`Custom Packet`},E=()=>{let e=r.packetTypeBreakdown;!e||e.length===0||(n.value=e.map(e=>({name:C[Number(e.type)]||`Type ${e.type}`,type:e.type,count:e.count,color:``})),o.value=!1,s.value=null)},k=e=>Math.max(e/f.value*90,2),ee=(e,t)=>t===0?0:e/t*100;return i(()=>{_()}),p(()=>r.packetTypeBreakdown,()=>E(),{deep:!0,immediate:!0}),A(_,{intervalMs:3e4,enabled:()=>!a.isConnected,immediate:!0}),(e,n)=>(S(),x(`div`,K,[n[3]||=b(`div`,{class:`flex items-baseline justify-between mb-3 lg:mb-4`},[b(`h3`,{class:`text-content-primary dark:text-content-primary text-lg lg:text-xl font-semibold`},` Packet Types `),b(`p`,{class:`text-content-secondary dark:text-content-muted text-xs lg:text-sm uppercase`},` Distribution by Type `)],-1),b(`div`,q,[o.value?(S(),x(`div`,oe,[...n[1]||=[b(`div`,{class:`text-content-secondary dark:text-content-primary text-sm lg:text-base`},` Loading packet types... `,-1)]])):s.value?(S(),x(`div`,J,[b(`div`,se,v(s.value),1)])):d.value.length===0?(S(),x(`div`,ce,[...n[2]||=[b(`div`,{class:`text-content-secondary dark:text-content-primary text-sm lg:text-base`},` No packet data available `,-1)]])):(S(),x(`div`,Y,[c.value?(S(),x(`div`,X,[b(`div`,le,v(c.value.name)+` · `+v(c.value.total.toLocaleString()),1),(S(!0),x(y,null,t(c.value.items,e=>(S(),x(`div`,{key:e.type,class:`flex justify-between gap-4 text-xs text-content-secondary dark:text-content-muted`},[b(`span`,null,v(e.name),1),b(`span`,ue,v(e.count.toLocaleString()),1)]))),128))])):m(``,!0),b(`div`,de,[(S(!0),x(y,null,t(d.value,e=>(S(),x(`div`,{key:e.name,class:`flex flex-col items-center flex-1 max-w-32 h-full justify-end cursor-pointer`,onMouseenter:t=>c.value=e,onMouseleave:n[0]||=e=>c.value=null},[b(`span`,fe,v(e.total.toLocaleString()),1),b(`div`,{class:`w-full rounded-[5px] transition-all duration-300 ease-out hover:opacity-90 overflow-hidden flex flex-col-reverse`,style:l({height:k(e.total)+`%`,minHeight:`8px`})},[(S(!0),x(y,null,t(e.items,t=>(S(),x(`div`,{key:t.type,style:l({height:ee(t.count,e.total)+`%`,backgroundColor:t.color})},null,4))),128))],4),b(`span`,pe,v(e.name),1)],40,Z))),128))])]))]),d.value.length>0?(S(),x(`div`,me,[(S(!0),x(y,null,t(d.value,e=>(S(),x(`div`,{key:`legend-`+e.name,class:`flex flex-col gap-0.5 min-w-[100px] max-w-[140px] flex-shrink-0`},[(S(!0),x(y,null,t(e.items,e=>(S(),x(`div`,{key:e.type,class:`flex items-center gap-1.5`},[b(`span`,{class:`w-2 h-2 rounded-sm shrink-0`,style:l({backgroundColor:e.color})},null,4),b(`span`,he,v(e.name),1)]))),128))]))),128))])):m(``,!0),d.value.length>0?(S(),x(`div`,ge,` Total: `+v(h.value.toLocaleString())+` packets `,1)):m(``,!0)]))}}),[[`__scopeId`,`data-v-fdd759f8`]]),ve={class:`glass-card rounded-[10px] p-4 lg:p-6`},ye={class:`relative h-40 lg:h-48`},be={class:`mt-3 lg:mt-4 grid grid-cols-2 gap-3 lg:gap-4`},xe={class:`text-center`},Se={class:`text-lg lg:text-2xl font-bold text-content-primary dark:text-content-primary`},Ce={class:`text-center`},we={class:`text-lg lg:text-2xl font-bold text-content-primary dark:text-content-primary`},Te={class:`mt-2 lg:mt-3 grid grid-cols-3 gap-2 lg:gap-3 text-center`},Ee={class:`text-xs lg:text-sm font-semibold text-accent-purple flex items-center justify-center gap-1`},De={key:0,class:`inline-block w-1.5 h-1.5 rounded-full bg-secondary opacity-70`,title:`Early data - limited uptime`},Oe={class:`text-xs text-content-secondary dark:text-content-muted`},ke={class:`text-xs lg:text-sm font-semibold text-accent-red flex items-center justify-center gap-1`},Ae={key:0,class:`inline-block w-1.5 h-1.5 rounded-full bg-secondary opacity-70`,title:`Early data - limited uptime`},je={class:`text-xs text-content-secondary dark:text-content-muted`},Me={class:`text-xs lg:text-sm font-semibold text-white`},Ne=k(u({name:`AirtimeUtilizationChart`,__name:`AirtimeUtilizationChart`,setup(e){let t=D(),n=E(),o=w(null),s=w([]),l=w(!0),u=w(null),d=w(30),f=w({totalReceived:0,totalTransmitted:0,dropped:0,firstPacketTime:0}),p=w({sf:9,bwHz:62500,cr:5,preamble:17}),h=(e,t=60)=>{if(e.length===0)return[];let n=1-.5**(1/t),r=Math.min(e.length,Math.max(10,Math.floor(t/3))),i=0,a=0;for(let t=0;t(i=n*e.rxUtil+(1-n)*i,a=n*e.txUtil+(1-n)*a,{...e,rxUtil:i,txUtil:a}))},y=g(()=>{let e=t.packetStats?.total_packets||0,r=t.packetStats?.transmitted_packets||0,i=n.stats?.uptime_seconds||0,a=e||f.value.totalReceived,o=r||f.value.totalTransmitted,s=f.value.firstPacketTime>0?Math.floor(Date.now()/1e3)-f.value.firstPacketTime:0,c=i||s,l=Math.max(c/3600,.1);if(l<1){let e=Math.max(c/60,1);return{rxRate:{value:Math.round(a/e*100)/100,label:l<.5?`RX/min (early)`:`RX/min`},txRate:{value:Math.round(o/e*100)/100,label:l<.5?`TX/min (early)`:`TX/min`},confidence:`low`}}let u=Math.round(a/l*100)/100,d=Math.round(o/l*100)/100,p,m;return l<6?(p=`RX/hr (${Math.round(l)}h)`,m=`medium`):l<24?(p=`RX/hr (${Math.round(l)}h)`,m=`high`):(p=`RX/hr`,m=`high`),{rxRate:{value:u,label:p},txRate:{value:d,label:p.replace(`RX`,`TX`)},confidence:m}}),O=async()=>{l.value=!0;try{let e=60*1e3,t=Math.floor(Date.now()/1e3),n=t-24*3600,r=0;try{let e=await T.get(`/stats`);if(e.success&&e.data){let t=e.data,n=t.config;if(n?.radio){let e=n.radio;p.value={sf:e.spreading_factor??9,bwHz:e.bandwidth??62500,cr:e.coding_rate??5,preamble:e.preamble_length??17}}r=t.dropped_count??0}}catch{}let i=await T.get(`/airtime_chart_data`,{start_timestamp:n,end_timestamp:t,bucket_seconds:60,sf:p.value.sf,bw_hz:p.value.bwHz,cr:p.value.cr,preamble:p.value.preamble});if(!i.success){s.value=[],l.value=!1,a(()=>k());return}let o=i.data,c=o.buckets||[];f.value={totalReceived:o.rx_total||0,totalTransmitted:o.tx_total||0,dropped:r,firstPacketTime:c.length>0?c[0].timestamp:t};let u=24*3600/60,m=new Float64Array(u),g=new Float64Array(u);for(let t of c){let r=Math.floor((t.timestamp-n)/60);r>=0&&r[e.rxUtil,e.txUtil]))*1.05;d.value=Math.max(5,Math.ceil(x/5)*5),l.value=!1,a(()=>k())}catch(e){console.error(`Failed to fetch airtime data:`,e),s.value=[],l.value=!1,a(()=>k())}},k=()=>{if(!o.value)return;let e=o.value,t=e.getContext(`2d`);if(!t)return;let n=e.parentElement;if(!n)return;let r=n.getBoundingClientRect(),i=r.width,a=r.height;if(e.width=i*window.devicePixelRatio,e.height=a*window.devicePixelRatio,e.style.width=i+`px`,e.style.height=a+`px`,t.scale(window.devicePixelRatio,window.devicePixelRatio),t.clearRect(0,0,i,a),l.value){t.fillStyle=`#666`,t.font=`16px system-ui`,t.textAlign=`center`,t.fillText(`Loading chart data...`,i/2,a/2);return}if(s.value.length===0){t.fillStyle=`#666`,t.font=`16px system-ui`,t.textAlign=`center`,t.fillText(`No data available`,i/2,a/2);return}let c=i-45-20,u=a-40,f=d.value,p=d.value;t.strokeStyle=`rgba(255, 255, 255, 0.1)`,t.lineWidth=1,t.font=`10px system-ui`,t.textAlign=`right`;for(let e=0;e<=5;e++){let n=20+u*e/5;t.beginPath(),t.moveTo(45,n),t.lineTo(i-20,n),t.stroke();let r=f-e/5*p;t.fillStyle=`rgba(255, 255, 255, 0.5)`,t.fillText(`${r.toFixed(0)}%`,40,n+3)}for(let e=0;e<=6;e++){let n=45+c*e/6;t.beginPath(),t.moveTo(n,20),t.lineTo(n,a-20),t.stroke()}s.value.length>1&&(t.strokeStyle=`#EBA0FC`,t.lineWidth=2,t.beginPath(),s.value.forEach((e,n)=>{let r=45+c*n/(s.value.length-1),i=a-20-Math.min(e.rxUtil,d.value)/p*u;n===0?t.moveTo(r,i):t.lineTo(r,i)}),t.stroke()),s.value.length>1&&(t.strokeStyle=`#FB787B`,t.lineWidth=2,t.beginPath(),s.value.forEach((e,n)=>{let r=45+c*n/(s.value.length-1),i=a-20-Math.min(e.txUtil,d.value)/p*u;n===0?t.moveTo(r,i):t.lineTo(r,i)}),t.stroke())};return i(()=>{O(),u.value=window.setInterval(O,3e4),a(()=>{k(),setTimeout(()=>k(),100)}),window.addEventListener(`resize`,k)}),C(()=>{u.value&&clearInterval(u.value),window.removeEventListener(`resize`,k)}),(e,n)=>(S(),x(`div`,ve,[n[3]||=c(` Airtime Utilization Activity (Last 24 Hours)
`,3),b(`div`,ye,[b(`canvas`,{ref_key:`chartRef`,ref:o,class:`absolute inset-0 w-full h-full`},null,512)]),b(`div`,be,[b(`div`,xe,[b(`div`,Se,v(r(t).packetStats?.total_packets||f.value.totalReceived),1),n[0]||=b(`div`,{class:`text-xs text-content-secondary dark:text-content-muted uppercase tracking-wide`},` Total Received `,-1)]),b(`div`,Ce,[b(`div`,we,v(r(t).packetStats?.transmitted_packets||f.value.totalTransmitted),1),n[1]||=b(`div`,{class:`text-xs text-content-secondary dark:text-content-muted uppercase tracking-wide`},` Total Transmitted `,-1)])]),b(`div`,Te,[b(`div`,null,[b(`div`,Ee,[_(v(y.value.rxRate.value)+` `,1),y.value.confidence===`low`?(S(),x(`span`,De)):m(``,!0)]),b(`div`,Oe,v(y.value.rxRate.label),1)]),b(`div`,null,[b(`div`,ke,[_(v(y.value.txRate.value)+` `,1),y.value.confidence===`low`?(S(),x(`span`,Ae)):m(``,!0)]),b(`div`,je,v(y.value.txRate.label),1)]),b(`div`,null,[b(`div`,Me,v(r(t).packetStats?.dropped_packets||f.value.dropped),1),n[2]||=b(`div`,{class:`text-xs text-white/60`},`Dropped`,-1)])])]))}}),[[`__scopeId`,`data-v-51cd61e9`]]),Pe={class:`bg-white dark:bg-surface-elevated backdrop-blur-xl rounded-[20px] shadow-2xl border border-stroke-subtle dark:border-white/20 flex flex-col h-full overflow-hidden`},Fe={class:`flex items-center justify-between p-8 pb-4 flex-shrink-0`},Ie={class:`text-content-secondary dark:text-content-muted text-sm`},Le={class:`flex items-center gap-2`},Re=[`title`],ze={class:`flex-1 overflow-y-auto custom-scrollbar px-8`},Be={class:`mb-6`},Ve={class:`glass-card bg-white/5 rounded-[15px] p-4`},He={class:`grid grid-cols-1 md:grid-cols-2 gap-4`},Ue={class:`space-y-3`},We={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Ge={class:`text-content-primary dark:text-content-primary font-mono text-sm`},Ke={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},qe={class:`text-content-primary dark:text-content-primary font-mono text-xs break-all`},Je={key:0,class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Ye={class:`text-content-primary dark:text-content-primary font-mono text-xs`},Xe={class:`space-y-3`},Ze={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Qe={class:`text-content-primary dark:text-content-primary font-semibold`},$e={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},et={class:`text-content-primary dark:text-content-primary font-semibold`},tt={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},nt={class:`mb-6`},rt={class:`bg-gray-50 dark:bg-white/5 rounded-[15px] p-4 border border-stroke-subtle dark:border-stroke/10`},it={class:`space-y-3`},at={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},ot={class:`text-content-primary dark:text-content-primary`},st={key:0,class:`pt-2`},ct={class:`glass-card bg-background-mute dark:bg-black/30 rounded-[10px] p-4 mb-4`},lt={class:`w-full overflow-x-auto`},ut={class:`text-content-primary dark:text-content-primary/90 text-xs font-mono whitespace-pre leading-relaxed min-w-full`},dt={class:`flex items-center justify-between mb-3`},ft={class:`text-content-secondary dark:text-content-primary/80 text-sm font-semibold`},pt={class:`text-content-muted dark:text-content-muted text-xs`},mt={class:`bg-background-mute dark:bg-black/40 rounded-[8px] p-3 mb-3`},ht={class:`font-mono text-xs text-content-primary dark:text-content-primary break-all whitespace-pre-wrap leading-relaxed`},gt={class:`bg-gray-50 dark:bg-white/5 rounded-[10px] overflow-hidden`},_t={key:0,class:`min-w-0`},vt={class:`text-cyan-500 text-sm font-mono break-words min-w-0`},yt={class:`text-content-primary dark:text-content-primary text-sm break-words min-w-0`},bt={class:`text-content-primary dark:text-content-primary text-sm font-semibold break-all min-w-0 overflow-hidden`},xt=[`title`],St={key:0,class:`text-orange-500 text-xs font-mono break-all min-w-0 overflow-hidden`},Ct=[`title`],wt={class:`grid grid-cols-2 gap-2`},Tt={class:`text-cyan-500 text-sm font-mono break-words`},Et={class:`text-content-primary dark:text-content-primary text-sm break-words`},Dt=[`title`],Ot={key:0},kt=[`title`],At={key:0,class:`text-content-muted dark:text-content-muted text-xs italic mt-2 px-1`},jt={key:1,class:`py-2`},Mt={class:`mb-6`},Nt={class:`bg-gray-50 dark:bg-white/5 rounded-[15px] p-4 border border-stroke-subtle dark:border-stroke/10`},Pt={class:`space-y-4`},Ft={class:`grid grid-cols-1 md:grid-cols-2 gap-4`},It={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Lt={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Rt={key:0,class:`py-2`},zt={class:`bg-background-mute dark:bg-black/20 rounded-[10px] p-4`},Bt={class:`flex items-center flex-wrap gap-2`},Vt={class:`relative group`},Ht={class:`relative px-3 py-2 bg-gradient-to-br from-blue-500/20 to-cyan-500/20 border border-cyan-400/40 rounded-lg transform transition-all hover:scale-105`},Ut={class:`font-mono text-[10px] font-semibold tracking-tight text-content-primary dark:text-content-primary/90 sm:text-xs`},Wt={class:`pointer-events-none absolute bottom-full left-1/2 z-50 mb-2 -translate-x-1/2 transform whitespace-nowrap rounded-md bg-neutral-900 px-2 py-1 font-mono text-xs text-white opacity-0 shadow-lg ring-1 ring-white/10 transition-opacity group-hover:opacity-100`},Gt={key:0,class:`mx-2 text-cyan-600 dark:text-cyan-400/60`},Kt={key:1,class:`py-2`},qt={class:`text-content-secondary dark:text-content-muted text-sm mb-2 flex items-center`},Jt={key:0,class:`w-4 h-4 ml-2 text-yellow-500`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Yt={key:1,class:`text-yellow-500 text-xs ml-1`},Xt={class:`bg-background-mute dark:bg-black/20 rounded-[10px] p-4`},Zt={class:`flex items-center flex-wrap gap-2`},Qt={class:`relative group`},$t={key:0,class:`absolute -top-1 -right-1 w-2 h-2 bg-yellow-400 rounded-full animate-pulse`},en={class:`pointer-events-none absolute bottom-full left-1/2 z-50 mb-2 -translate-x-1/2 transform whitespace-nowrap rounded-md bg-neutral-900 px-2 py-1 font-mono text-xs text-white opacity-0 shadow-lg ring-1 ring-white/10 transition-opacity group-hover:opacity-100`},tn={key:0,class:`mx-1 text-orange-600 dark:text-orange-400/60`},nn={class:`mb-6`},rn={class:`glass-card bg-gray-50 dark:bg-white/5 rounded-[15px] p-4`},an={class:`grid grid-cols-1 md:grid-cols-3 gap-4 mb-4`},on={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},sn={class:`text-lg font-bold text-content-primary dark:text-content-primary`},cn={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},ln={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},un={class:`text-lg font-bold text-content-primary dark:text-content-primary`},dn={key:0,class:`mb-4`},fn={class:`flex items-center gap-3`},pn={class:`flex gap-1`},mn={class:`text-content-secondary dark:text-content-primary/80 text-sm capitalize`},hn={key:1,class:`mb-4`},gn={key:2,class:`mb-4`},_n={class:`text-content-secondary dark:text-content-muted text-sm mb-3`},vn={class:`space-y-2`},yn={class:`flex items-center gap-3`},bn={class:`text-content-muted dark:text-content-muted text-sm`},xn={key:3,class:`mt-6 pt-4 border-t border-stroke-subtle dark:border-stroke/10`},Sn={class:`grid grid-cols-1 md:grid-cols-3 gap-3 mb-4`},Cn={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},wn={class:`text-2xl font-bold text-content-primary dark:text-content-primary`},Tn={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},En={class:`text-2xl font-bold text-content-primary dark:text-content-primary`},Dn={class:`text-content-muted dark:text-content-muted text-xs mt-1`},On={class:`text-center p-3 glass-card bg-background-mute dark:bg-black/20 rounded-[10px]`},kn={class:`text-content-muted dark:text-content-muted text-xs mt-1`},An={key:0,class:`glass-card bg-background-mute dark:bg-black/20 rounded-[10px] p-4`},jn={class:`space-y-3`},Mn={class:`flex-shrink-0 w-16 text-right`},Nn={class:`text-content-secondary dark:text-content-muted text-xs`},Pn={class:`flex-1 relative`},Fn={class:`h-8 rounded-lg overflow-hidden bg-background-mute dark:bg-stroke/5 relative`},In={class:`absolute inset-0 flex items-center px-3`},Ln={class:`text-content-primary dark:text-content-primary text-xs font-mono font-semibold`},Rn={class:`flex-shrink-0 w-12 text-left`},zn={class:`text-content-muted dark:text-content-muted text-xs`},Bn={class:`grid grid-cols-1 md:grid-cols-2 gap-4`},Vn={class:`space-y-2`},Hn={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Un={class:`text-content-primary dark:text-content-primary`},Wn={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Gn={class:`space-y-2`},Kn={class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},qn={key:0,class:`flex justify-between py-2 border-b border-stroke-subtle dark:border-stroke/10`},Jn={class:`text-red-600 dark:text-red-400 text-sm`},Yn={class:`p-8 pt-4 border-t border-stroke-subtle dark:border-stroke/10 flex justify-end flex-shrink-0`},Xn=k(u({name:`PacketDetailsModal`,__name:`PacketDetailsModal`,props:{packet:{},isOpen:{type:Boolean},localHash:{}},emits:[`close`],setup(n,{emit:r}){let{getSignalQuality:i}=z(),a=n,c=r,u=w(!1),f=e=>new Date(e*1e3).toLocaleString(),g=e=>e.transmitted?e.is_duplicate?`text-amber-600 dark:text-amber-400`:e.drop_reason?`text-red-600 dark:text-red-400`:`text-green-600 dark:text-green-400`:`text-red-600 dark:text-red-400`,C=e=>e.transmitted?e.is_duplicate?`Duplicate`:e.drop_reason?`Dropped`:`Forwarded`:`Dropped`,T=e=>({0:`Request`,1:`Response`,2:`Plain Text Message`,3:`Acknowledgment`,4:`Node Advertisement`,5:`Group Text Message`,6:`Group Datagram`,7:`Anonymous Request`,8:`Returned Path`,9:`Trace`,10:`Multi-part Packet`,15:`Custom Packet`})[e]||`Unknown Type (${e})`,E=e=>({0:`Transport Flood`,1:`Flood`,2:`Direct`,3:`Transport Direct`})[e]||`Unknown Route (${e})`,D=e=>{if(!e)return`None`;let t=e.replace(/\s+/g,``).toUpperCase().match(/.{2}/g)||[],n=[];for(let e=0;e{try{let r=0,i=t.length/2;if(i>=100){if(t.length>=r+64){let i=t.slice(r,r+64);e.push({name:`Public Key`,byteRange:`${(n+r)/2}-${(n+r+63)/2}`,hexData:i.match(/.{8}/g)?.join(` `)||i,description:`Ed25519 public key of the node (32 bytes)`,fields:[{bits:`0-255`,name:`Ed25519 Public Key`,value:`${i.slice(0,16)}...${i.slice(-16)}`,binary:`32 bytes (256 bits)`}]}),r+=64}if(t.length>=r+8){let i=t.slice(r,r+8),a=parseInt(i,16),o=new Date(a*1e3);e.push({name:`Timestamp`,byteRange:`${(n+r)/2}-${(n+r+7)/2}`,hexData:i.match(/.{2}/g)?.join(` `)||i,description:`Unix timestamp of advertisement`,fields:[{bits:`0-31`,name:`Unix Timestamp`,value:`${a} (${o.toLocaleString()})`,binary:a.toString(2).padStart(32,`0`)}]}),r+=8}if(t.length>=r+128){let i=t.slice(r,r+128);e.push({name:`Signature`,byteRange:`${(n+r)/2}-${(n+r+127)/2}`,hexData:i.match(/.{8}/g)?.join(` `)||i,description:`Ed25519 signature of public key, timestamp, and appdata`,fields:[{bits:`0-511`,name:`Ed25519 Signature`,value:`${i.slice(0,16)}...${i.slice(-16)}`,binary:`64 bytes (512 bits)`}]}),r+=128}t.length>r&&k(e,t.slice(r),n+r)}else e.push({name:`ADVERT AppData (Partial)`,byteRange:`${n/2}-${n/2+i-1}`,hexData:t.match(/.{2}/g)?.join(` `)||t,description:`Partial ADVERT data - appears to be just AppData portion (${i} bytes)`,fields:[{bits:`0-${i*8-1}`,name:`Partial Data`,value:`${i} bytes - attempting to decode as AppData`,binary:`${i} bytes (${i*8} bits)`}]}),k(e,t,n)}catch(n){e.push({name:`ADVERT Parse Error`,byteRange:`N/A`,hexData:t.slice(0,32)+`...`,description:`Failed to parse ADVERT payload structure`,fields:[{bits:`N/A`,name:`Error`,value:`Parse error: ${n instanceof Error?n.message:`Unknown error`}`,binary:`Invalid`}]})}},k=(e,t,n)=>{try{let r=t.length/2;e.push({name:`AppData`,byteRange:`${n/2}-${n/2+r-1}`,hexData:t.match(/.{2}/g)?.join(` `)||t,description:`Node advertisement application data (${r} bytes)`,fields:[{bits:`0-${r*8-1}`,name:`Application Data`,value:`${r} bytes (contains flags, location, name, etc.)`,binary:`${r} bytes (${r*8} bits)`}]});let i=0;if(t.length>=2){let r=parseInt(t.slice(i,i+2),16),a=[],o=!!(r&16),s=!!(r&32),c=!!(r&64),l=!!(r&128);if(r&1&&a.push(`is chat node`),r&2&&a.push(`is repeater`),r&4&&a.push(`is room server`),r&8&&a.push(`is sensor`),o&&a.push(`has location`),s&&a.push(`has feature 1`),c&&a.push(`has feature 2`),l&&a.push(`has name`),e.push({name:`AppData Flags`,byteRange:`${(n+i)/2}`,hexData:`0x${t.slice(i,i+2)}`,description:`Flags indicating which optional fields are present`,fields:[{bits:`0-7`,name:`Flags`,value:a.join(`, `)||`none`,binary:r.toString(2).padStart(8,`0`)}]}),i+=2,o&&t.length>=i+16){let r=t.slice(i,i+8),a=[];for(let e=6;e>=0;e-=2)a.push(r.slice(e,e+2));let o=parseInt(a.join(``),16),s=o>2147483647?o-4294967296:o,c=s/1e6,l=t.slice(i+8,i+16),u=[];for(let e=6;e>=0;e-=2)u.push(l.slice(e,e+2));let d=parseInt(u.join(``),16),f=d>2147483647?d-4294967296:d,p=f/1e6;e.push({name:`Location Data`,byteRange:`${(n+i)/2}-${(n+i+15)/2}`,hexData:`${r.match(/.{2}/g)?.join(` `)||r} ${l.match(/.{2}/g)?.join(` `)||l}`,description:`GPS coordinates (latitude and longitude)`,fields:[{bits:`0-31`,name:`Latitude`,value:`${c.toFixed(6)}° (raw: ${s})`,binary:s.toString(2).padStart(32,`0`)},{bits:`32-63`,name:`Longitude`,value:`${p.toFixed(6)}° (raw: ${f})`,binary:f.toString(2).padStart(32,`0`)}]}),i+=16}if(s&&t.length>=i+4){let r=t.slice(i,i+4),a=parseInt(r,16);e.push({name:`Feature 1`,byteRange:`${(n+i)/2}-${(n+i+3)/2}`,hexData:r.match(/.{2}/g)?.join(` `)||r,description:`Reserved feature 1 (2 bytes)`,fields:[{bits:`0-15`,name:`Feature 1 Value`,value:`${a}`,binary:a.toString(2).padStart(16,`0`)}]}),i+=4}if(c&&t.length>=i+4){let r=t.slice(i,i+4),a=parseInt(r,16);e.push({name:`Feature 2`,byteRange:`${(n+i)/2}-${(n+i+3)/2}`,hexData:r.match(/.{2}/g)?.join(` `)||r,description:`Reserved feature 2 (2 bytes)`,fields:[{bits:`0-15`,name:`Feature 2 Value`,value:`${a}`,binary:a.toString(2).padStart(16,`0`)}]}),i+=4}if(l&&t.length>i){let r=t.slice(i),a=r.match(/.{2}/g)||[],o=a.map(e=>{let t=parseInt(e,16);return t>=32&&t<=126?String.fromCharCode(t):`.`}).join(``).replace(/\.+$/,``);e.push({name:`Node Name`,byteRange:`${(n+i)/2}-${(n+t.length-1)/2}`,hexData:r.match(/.{2}/g)?.join(` `)||r,description:`Node name string (${a.length} bytes)`,fields:[{bits:`0-${a.length*8-1}`,name:`Node Name`,value:`"${o}"`,binary:`ASCII text (${a.length} bytes)`}]})}}}catch(n){e.push({name:`AppData Parse Error`,byteRange:`N/A`,hexData:t.slice(0,Math.min(32,t.length)),description:`Failed to parse AppData structure`,fields:[{bits:`N/A`,name:`Error`,value:`Parse error: ${n instanceof Error?n.message:`Unknown error`}`,binary:`Invalid`}]})}},A=e=>{if(!e)return[];if(Array.isArray(e))return e;if(typeof e==`string`)try{return JSON.parse(e)}catch{return[]}return[]},te=e=>{let t=[];if(!e)return t;try{let n=e.raw_packet;if(n){let e=n.replace(/\s+/g,``).toUpperCase(),r=0;if(e.length>=2){let n=e.slice(r,r+2),i=parseInt(n,16),a=i&3,o=(i&60)>>2,s=(i&192)>>6;if(t.push({name:`Header`,byteRange:`0`,hexData:`0x${n}`,description:`Contains routing type, payload type, and payload version`,fields:[{bits:`0-1`,name:`Route Type`,value:{0:`Transport Flood`,1:`Flood`,2:`Direct`,3:`Transport Direct`}[a]||`Unknown`,binary:a.toString(2).padStart(2,`0`)},{bits:`2-5`,name:`Payload Type`,value:{0:`REQ`,1:`RESPONSE`,2:`TXT_MSG`,3:`ACK`,4:`ADVERT`,5:`GRP_TXT`,6:`GRP_DATA`,7:`ANON_REQ`,8:`PATH`,9:`TRACE`,10:`MULTIPART`,15:`RAW_CUSTOM`}[o]||`Unknown`,binary:o.toString(2).padStart(4,`0`)},{bits:`6-7`,name:`Version`,value:s.toString(),binary:s.toString(2).padStart(2,`0`)}]}),r+=2,(a===0||a===3)&&e.length>=r+8){let n=e.slice(r,r+8),i=parseInt(n.slice(0,4),16),a=parseInt(n.slice(4,8),16);t.push({name:`Transport Codes`,byteRange:`1-4`,hexData:`${n.slice(0,4)} ${n.slice(4,8)}`,description:`2x 16-bit transport codes for routing optimization`,fields:[{bits:`0-15`,name:`Code 1`,value:i.toString(),binary:i.toString(2).padStart(16,`0`)},{bits:`16-31`,name:`Code 2`,value:a.toString(),binary:a.toString(2).padStart(16,`0`)}]}),r+=8}if(e.length>=r+2){let n=e.slice(r,r+2),i=parseInt(n,16),a=(i>>6)+1,o=i&63,s=o*a;if(t.push({name:`Path Length`,byteRange:`${r/2}`,hexData:`0x${n}`,description:`${o} hop${o===1?``:`s`}, ${a}-byte hash${a>1?`es`:``} (${s} bytes)`,fields:[{bits:`6-7`,name:`Hash Size`,value:`${a}-byte`,binary:(i>>6&3).toString(2).padStart(2,`0`)},{bits:`0-5`,name:`Hop Count`,value:`${o}`,binary:(i&63).toString(2).padStart(6,`0`)}]}),r+=2,s>0&&e.length>=r+s*2){let n=e.slice(r,r+s*2),i=RegExp(`.{${a*2}}`,`g`),c=n.match(i)||[];t.push({name:`Path Data`,byteRange:`${r/2}-${(r+s*2-2)/2}`,hexData:c.join(` `)||n,description:`${o} × ${a}-byte routing hash${o===1?``:`es`}`,fields:c.map((e,t)=>({bits:`${t*a*8}-${(t+1)*a*8-1}`,name:`Hop ${t+1}`,value:e.toUpperCase(),binary:`${a} byte${a>1?`s`:``}`}))}),r+=s*2}}if(e.length>r){let n=e.slice(r),i=n.length/2;o===4?O(t,n,r):t.push({name:`Payload Data`,byteRange:`${r/2}-${r/2+i-1}`,hexData:n.match(/.{2}/g)?.join(` `)||n,description:`Application data content`,fields:[{bits:`0-${i*8-1}`,name:`Application Data`,value:`${i} bytes`,binary:`${i} bytes (${i*8} bits)`}]})}}}else{if(e.header){let n=e.header.replace(/0x/gi,``).replace(/\s+/g,``).toUpperCase(),r=parseInt(n,16),i=r&3,a=(r&60)>>2,o=(r&192)>>6;t.push({name:`Header`,byteRange:`0`,hexData:`0x${n}`,description:`Contains routing type, payload type, and payload version`,fields:[{bits:`0-1`,name:`Route Type`,value:{0:`Transport Flood`,1:`Flood`,2:`Direct`,3:`Transport Direct`}[i]||`Unknown`,binary:i.toString(2).padStart(2,`0`)},{bits:`2-5`,name:`Payload Type`,value:{0:`REQ`,1:`RESPONSE`,2:`TXT_MSG`,3:`ACK`,4:`ADVERT`,5:`GRP_TXT`,6:`GRP_DATA`,7:`ANON_REQ`,8:`PATH`,9:`TRACE`,10:`MULTIPART`,15:`RAW_CUSTOM`}[a]||`Unknown`,binary:a.toString(2).padStart(4,`0`)},{bits:`6-7`,name:`Version`,value:o.toString(),binary:o.toString(2).padStart(2,`0`)}]}),e.transport_codes&&t.push({name:`Transport Codes`,byteRange:`1-4`,hexData:e.transport_codes,description:`2x 16-bit transport codes for routing optimization`,fields:[{bits:`0-31`,name:`Transport Codes`,value:e.transport_codes,binary:`Available in separate field`}]}),e.original_path&&e.original_path.length>0&&t.push({name:`Original Path`,byteRange:`?`,hexData:e.original_path.join(` `),description:`Original routing path (${e.original_path.length} nodes)`,fields:[{bits:`0-?`,name:`Path Nodes`,value:`${e.original_path.length} nodes`,binary:`Available as node list`}]}),e.forwarded_path&&e.forwarded_path.length>0&&t.push({name:`Forwarded Path`,byteRange:`?`,hexData:e.forwarded_path.join(` `),description:`Forwarded routing path (${e.forwarded_path.length} nodes)`,fields:[{bits:`0-?`,name:`Path Nodes`,value:`${e.forwarded_path.length} nodes`,binary:`Available as node list`}]})}if(e.payload){let n=e.payload.replace(/\s+/g,``).toUpperCase(),r=n.length/2;e.type===4?O(t,n,0):t.push({name:`Payload Data`,byteRange:`0-${r-1}`,hexData:n.match(/.{2}/g)?.join(` `)||n,description:`Application data content (${r} bytes)`,fields:[{bits:`0-${r*8-1}`,name:`Application Data`,value:`${r} bytes`,binary:`${r} bytes (${r*8} bits)`}]})}}}catch{t.push({name:`Parse Error`,byteRange:`N/A`,hexData:`Error`,description:`Unable to parse packet structure`,fields:[{bits:`N/A`,name:`Error`,value:`Parse failed`,binary:`Invalid`}]})}return t},M=(e,t)=>e==null||t==null?`text-content-muted dark:text-content-muted`:i(t).color,N=e=>{if(e==null)return{level:0,className:`signal-none`};let t=i(e),n,r;return t.bars>=5?(n=4,r=`signal-excellent`):t.bars>=4?(n=3,r=`signal-good`):t.bars>=2?(n=2,r=`signal-fair`):t.bars>=1?(n=1,r=`signal-poor`):(n=0,r=`signal-none`),{level:n,className:r}},P=e=>{if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}},F=e=>e>=1e3?`${(e/1e3).toFixed(2)}s`:`${Math.round(e)}ms`,I=e=>{e.key===`Escape`&&c(`close`)},L=e=>{e.target===e.currentTarget&&c(`close`)};return p(()=>a.isOpen,e=>{e?document.body.style.overflow=`hidden`:document.body.style.overflow=``},{immediate:!0}),(r,i)=>(S(),o(d,{to:`body`},[h(ee,{name:`modal`,appear:``},{default:e(()=>[n.isOpen&&n.packet?(S(),x(`div`,{key:0,class:`fixed inset-0 z-50 flex items-center justify-center p-4 overflow-hidden`,onClick:L,onKeydown:I,tabindex:`0`},[i[51]||=b(`div`,{class:`absolute inset-0 bg-black/60 backdrop-blur-md pointer-events-none`},null,-1),b(`div`,{class:`relative w-full max-w-4xl max-h-[90vh] flex flex-col`,onClick:i[3]||=j(()=>{},[`stop`])},[b(`div`,Pe,[b(`div`,Fe,[b(`div`,null,[i[4]||=b(`h2`,{class:`text-2xl font-bold text-content-primary dark:text-content-primary mb-1`},` Packet Details `,-1),b(`p`,Ie,v(T(n.packet.type))+` - `+v(E(n.packet.route)),1)]),b(`div`,Le,[b(`button`,{onClick:i[0]||=e=>u.value=!u.value,class:s([`flex items-center gap-2 px-3 py-1.5 rounded-lg transition-all duration-200`,u.value?`bg-cyan-500/20 border border-cyan-400/30 text-cyan-600 dark:text-cyan-400`:`bg-background-mute dark:bg-white/10 border border-stroke-subtle dark:border-stroke/20 text-content-secondary dark:text-content-muted`]),title:u.value?`Hide binary values`:`Show binary values`},[...i[5]||=[b(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[b(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4`})],-1),b(`span`,{class:`text-xs font-medium`},`Binary`,-1)]],10,Re),b(`button`,{onClick:i[1]||=e=>c(`close`),class:`w-8 h-8 flex items-center justify-center rounded-full bg-background-mute dark:bg-white/10 hover:bg-stroke-subtle dark:hover:bg-white/20 transition-colors duration-200 text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary`},[...i[6]||=[b(`svg`,{class:`w-5 h-5`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[b(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M6 18L18 6M6 6l12 12`})],-1)]])])]),b(`div`,ze,[b(`div`,Be,[i[13]||=b(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-4 flex items-center`},[b(`div`,{class:`w-2 h-2 rounded-full bg-cyan-400 mr-3`}),_(` Basic Information `)],-1),b(`div`,Ve,[b(`div`,He,[b(`div`,Ue,[b(`div`,We,[i[7]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Timestamp`,-1),b(`span`,Ge,v(f(n.packet.timestamp)),1)]),b(`div`,Ke,[i[8]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Packet Hash`,-1),b(`span`,qe,v(n.packet.packet_hash),1)]),n.packet.header?(S(),x(`div`,Je,[i[9]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Header`,-1),b(`span`,Ye,v(n.packet.header),1)])):m(``,!0)]),b(`div`,Xe,[b(`div`,Ze,[i[10]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Type`,-1),b(`span`,Qe,v(n.packet.type)+` (`+v(T(n.packet.type))+`)`,1)]),b(`div`,$e,[i[11]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Route`,-1),b(`span`,et,v(n.packet.route)+` (`+v(E(n.packet.route))+`)`,1)]),b(`div`,tt,[i[12]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Status`,-1),b(`span`,{class:s([`font-semibold`,g(n.packet)])},v(C(n.packet)),3)])])])])]),b(`div`,nt,[i[25]||=b(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-4 flex items-center`},[b(`div`,{class:`w-2 h-2 rounded-full bg-orange-400 mr-3`}),_(` Payload Data `)],-1),b(`div`,rt,[b(`div`,it,[b(`div`,at,[i[14]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Payload Length`,-1),b(`span`,ot,v(n.packet.payload_length||n.packet.length)+` bytes`,1)]),n.packet.payload?(S(),x(`div`,st,[i[23]||=b(`div`,{class:`text-content-secondary dark:text-content-muted text-sm mb-3`},` Payload Analysis `,-1),b(`div`,ct,[i[15]||=b(`div`,{class:`text-content-secondary dark:text-content-muted text-xs mb-2 font-semibold`},` Raw Hex Data `,-1),b(`div`,lt,[b(`pre`,ut,v(D(n.packet.payload)),1)])]),(S(!0),x(y,null,t(te(n.packet).filter(e=>!e.name.includes(`Parse Error`)),(e,n)=>(S(),x(`div`,{key:n,class:`mb-4`},[b(`div`,dt,[b(`h4`,ft,v(e.name),1),b(`span`,pt,`Bytes `+v(e.byteRange),1)]),b(`div`,mt,[b(`div`,ht,v(e.hexData),1)]),b(`div`,gt,[b(`div`,{class:s([`hidden md:grid gap-3 p-3 bg-background-mute dark:bg-white/10 text-content-secondary dark:text-content-muted text-xs font-semibold uppercase tracking-wide`,u.value?`grid-cols-4`:`grid-cols-3`])},[i[16]||=b(`div`,{class:`min-w-0`},`Bits`,-1),i[17]||=b(`div`,{class:`min-w-0`},`Field`,-1),i[18]||=b(`div`,{class:`min-w-0`},`Value`,-1),u.value?(S(),x(`div`,_t,`Binary`)):m(``,!0)],2),(S(!0),x(y,null,t(e.fields,(e,t)=>(S(),x(`div`,{key:t,class:s([`hidden md:grid gap-3 p-3 border-b border-stroke-subtle dark:border-stroke/5 last:border-b-0 hover:bg-background-mute dark:hover:bg-stroke/5 transition-colors`,u.value?`grid-cols-4`:`grid-cols-3`])},[b(`div`,vt,v(e.bits),1),b(`div`,yt,v(e.name),1),b(`div`,bt,[b(`span`,{class:`block`,title:e.value},v(e.value),9,xt)]),u.value?(S(),x(`div`,St,[b(`span`,{class:`block`,title:e.binary},v(e.binary),9,Ct)])):m(``,!0)],2))),128)),(S(!0),x(y,null,t(e.fields,(e,t)=>(S(),x(`div`,{key:`mobile-${t}`,class:`md:hidden p-3 border-b border-stroke-subtle dark:border-stroke/5 last:border-b-0 space-y-2`},[b(`div`,wt,[b(`div`,null,[i[19]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-xs uppercase tracking-wide`},`Bits:`,-1),b(`div`,Tt,v(e.bits),1)]),b(`div`,null,[i[20]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-xs uppercase tracking-wide`},`Field:`,-1),b(`div`,Et,v(e.name),1)])]),b(`div`,null,[i[21]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-xs uppercase tracking-wide`},`Value:`,-1),b(`div`,{class:`text-content-primary dark:text-content-primary text-sm font-semibold break-all`,title:e.value},v(e.value),9,Dt)]),u.value?(S(),x(`div`,Ot,[i[22]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-xs uppercase tracking-wide`},`Binary:`,-1),b(`div`,{class:`text-orange-500 text-xs font-mono break-all`,title:e.binary},v(e.binary),9,kt)])):m(``,!0)]))),128))]),e.description?(S(),x(`div`,At,v(e.description),1)):m(``,!0)]))),128))])):(S(),x(`div`,jt,[...i[24]||=[b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Payload:`,-1),b(`span`,{class:`text-content-muted dark:text-content-muted ml-2`},`None`,-1)]]))])])]),b(`div`,Mt,[i[33]||=b(`h3`,{class:`text-lg font-semibold text-content-primary dark:text-content-primary mb-4 flex items-center`},[b(`div`,{class:`w-2 h-2 rounded-full bg-purple-400 mr-3`}),_(` Path Information `)],-1),b(`div`,Nt,[b(`div`,Pt,[b(`div`,Ft,[b(`div`,It,[i[26]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Source Hash`,-1),b(`span`,{class:s([`text-content-primary dark:text-content-primary font-mono text-xs`,a.localHash&&n.packet.src_hash===a.localHash?`bg-cyan-400/20 text-cyan-600 dark:text-cyan-300 px-1 rounded`:``])},v(n.packet.src_hash||`Unknown`),3)]),b(`div`,Lt,[i[27]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Destination Hash`,-1),b(`span`,{class:s([`text-content-primary dark:text-content-primary font-mono text-xs`,a.localHash&&n.packet.dst_hash===a.localHash?`bg-cyan-400/20 text-cyan-600 dark:text-cyan-300 px-1 rounded`:``])},v(n.packet.dst_hash||`Broadcast`),3)])]),A(n.packet.original_path).length>0?(S(),x(`div`,Rt,[i[29]||=b(`div`,{class:`text-content-secondary dark:text-content-muted text-sm mb-2`},` Original Path `,-1),b(`div`,zt,[b(`div`,Bt,[(S(!0),x(y,null,t(A(n.packet.original_path),(e,t)=>(S(),x(`div`,{key:t,class:`flex items-center`},[b(`div`,Vt,[b(`div`,Ht,[b(`div`,Ut,v(e.toUpperCase()),1)]),b(`div`,Wt,` Node: `+v(e.toUpperCase()),1)]),t0?(S(),x(`div`,Kt,[b(`div`,qt,[i[31]||=_(` Forwarded Path `,-1),JSON.stringify(A(n.packet.original_path))===JSON.stringify(A(n.packet.forwarded_path))?m(``,!0):(S(),x(`svg`,Jt,[...i[30]||=[b(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`},null,-1)]])),JSON.stringify(A(n.packet.original_path))===JSON.stringify(A(n.packet.forwarded_path))?m(``,!0):(S(),x(`span`,Yt,`(Modified)`))]),b(`div`,Xt,[b(`div`,Zt,[(S(!0),x(y,null,t(A(n.packet.forwarded_path),(e,t)=>(S(),x(`div`,{key:t,class:`flex items-center`},[b(`div`,Qt,[b(`div`,{class:s([`relative px-3 py-2 bg-gradient-to-br from-orange-500/20 to-yellow-500/20 border border-orange-500 dark:border-orange-400/40 rounded-lg transform transition-all hover:scale-105`,a.localHash&&e===a.localHash?`bg-gradient-to-br from-yellow-400/30 to-orange-400/30 border-yellow-300 shadow-yellow-400/20 shadow-lg`:`hover:border-orange-500 dark:border-orange-400/60`])},[b(`div`,{class:s([`font-mono text-[10px] font-semibold tracking-tight sm:text-xs`,a.localHash&&e===a.localHash?`text-yellow-200`:`text-white/90`])},v(e.toUpperCase()),3),a.localHash&&e===a.localHash?(S(),x(`div`,$t)):m(``,!0)],2),b(`div`,en,v(e.toUpperCase()),1)]),t b(`div`,{key:e,class:s([`w-2 h-6 rounded-sm transition-all duration-300`,e<=N(n.packet.rssi).level?{"signal-excellent":`bg-green-400`,"signal-good":`bg-cyan-400`,"signal-fair":`bg-yellow-400`,"signal-poor":`bg-red-400`}[N(n.packet.rssi).className]:`bg-stroke-subtle dark:bg-stroke/10`])},null,2)),64))]),b(`span`,mn,v(N(n.packet.rssi).className.replace(`signal-`,``)),1)])])),n.packet.is_trace&&n.packet.path_snr_details&&n.packet.path_snr_details.length>0?(S(),x(`div`,gn,[b(`div`,_n,` Path SNR Details (`+v(n.packet.path_snr_details.length)+` hops) `,1),b(`div`,vn,[(S(!0),x(y,null,t(n.packet.path_snr_details,(e,t)=>(S(),x(`div`,{key:t,class:`flex items-center justify-between p-2 glass-card bg-background-mute dark:bg-black/20 rounded-[8px]`},[b(`div`,yn,[b(`span`,bn,v(t+1)+`.`,1),b(`span`,{class:s([`font-mono text-xs text-content-primary dark:text-content-primary`,a.localHash&&e.hash===a.localHash?`bg-cyan-400/20 text-cyan-600 dark:text-cyan-300 px-1 rounded`:``])},v(e.hash.toUpperCase()),3)]),b(`span`,{class:s([`text-sm font-bold`,M(e.snr_db,null)])},v(e.snr_db.toFixed(1))+`dB `,3)]))),128))])])):m(``,!0),n.packet.transmitted&&n.packet.lbt_attempts!==void 0?(S(),x(`div`,xn,[i[45]||=b(`div`,{class:`text-content-secondary dark:text-content-muted text-sm mb-3 flex items-center`},[b(`svg`,{class:`w-4 h-4 mr-2`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[b(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z`})]),_(` Listen Before Talk (LBT) Metrics `)],-1),b(`div`,Sn,[b(`div`,Cn,[i[41]||=b(`div`,{class:`text-content-secondary dark:text-content-muted text-xs mb-1`},` CAD Attempts `,-1),b(`div`,wn,v(n.packet.lbt_attempts),1)]),b(`div`,Tn,[i[42]||=b(`div`,{class:`text-content-secondary dark:text-content-muted text-xs mb-1`},` Total LBT Delay `,-1),b(`div`,En,v(F(P(n.packet.lbt_backoff_delays_ms).reduce((e,t)=>e+t,0))),1),b(`div`,Dn,v(P(n.packet.lbt_backoff_delays_ms).length)+` backoffs `,1)]),b(`div`,On,[i[43]||=b(`div`,{class:`text-content-secondary dark:text-content-muted text-xs mb-1`},` Channel Status `,-1),b(`div`,{class:s([`text-lg font-bold`,n.packet.lbt_channel_busy?`text-yellow-600 dark:text-yellow-400`:`text-green-600 dark:text-green-400`])},v(n.packet.lbt_channel_busy?`BUSY`:`CLEAR`),3),b(`div`,kn,v(n.packet.lbt_channel_busy?`Waited for clear`:`Immediate TX`),1)])]),P(n.packet.lbt_backoff_delays_ms).length>0?(S(),x(`div`,An,[i[44]||=b(`div`,{class:`text-content-secondary dark:text-content-muted text-xs mb-3 font-semibold`},` Backoff Pattern (Exponential with Jitter) `,-1),b(`div`,jn,[(S(!0),x(y,null,t(P(n.packet.lbt_backoff_delays_ms),(e,t)=>(S(),x(`div`,{key:t,class:`flex items-center gap-3`},[b(`div`,Mn,[b(`span`,Nn,`Attempt `+v(t+1),1)]),b(`div`,Pn,[b(`div`,Fn,[b(`div`,{class:s([`h-full rounded-lg transition-all duration-300`,[t===0?`bg-gradient-to-r from-cyan-500/50 to-cyan-600/50`:t===1?`bg-gradient-to-r from-yellow-500/50 to-yellow-600/50`:t===2?`bg-gradient-to-r from-orange-500/50 to-orange-600/50`:`bg-gradient-to-r from-red-500/50 to-red-600/50`]]),style:l({width:`${Math.min(100,e/Math.max(...P(n.packet.lbt_backoff_delays_ms))*100)}%`})},[b(`div`,In,[b(`span`,Ln,v(F(e)),1)])],6)])]),b(`div`,Rn,[b(`span`,zn,v(Math.round(e/P(n.packet.lbt_backoff_delays_ms).reduce((e,t)=>e+t,0)*100))+`% `,1)])]))),128))])])):m(``,!0)])):m(``,!0),b(`div`,Bn,[b(`div`,Vn,[b(`div`,Hn,[i[46]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`TX Delay`,-1),b(`span`,Un,v(Number(n.packet.tx_delay_ms)>0?Number(n.packet.tx_delay_ms).toFixed(1)+`ms`:`-`),1)]),b(`div`,Wn,[i[47]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Transmitted`,-1),b(`span`,{class:s(n.packet.transmitted?`text-green-600 dark:text-green-400`:`text-red-600 dark:text-red-400`)},v(n.packet.transmitted?`Yes`:`No`),3)])]),b(`div`,Gn,[b(`div`,Kn,[i[48]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Is Duplicate`,-1),b(`span`,{class:s(n.packet.is_duplicate?`text-amber-600 dark:text-amber-400`:`text-content-muted dark:text-content-muted`)},v(n.packet.is_duplicate?`Yes`:`No`),3)]),n.packet.drop_reason?(S(),x(`div`,qn,[i[49]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Drop Reason`,-1),b(`span`,Jn,v(n.packet.drop_reason),1)])):m(``,!0)])])])])]),b(`div`,Yn,[b(`button`,{onClick:i[2]||=e=>c(`close`),class:`px-6 py-2 bg-gradient-to-r from-cyan-500/20 to-cyan-400/20 hover:from-cyan-500/30 hover:to-cyan-400/30 border border-cyan-400/30 rounded-[10px] text-content-primary dark:text-content-primary transition-all duration-200 backdrop-blur-sm`},` Close `)])])])],32)):m(``,!0)]),_:1})]))}}),[[`__scopeId`,`data-v-c8711b75`]]),Zn={class:`glass-card rounded-[20px] p-6`},Qn={class:`flex flex-col lg:flex-row lg:justify-between lg:items-center mb-6 gap-4 filter-container`},$n={class:`flex items-center gap-2 header-info relative`},er={class:`text-content-secondary dark:text-content-muted text-sm packet-count`},tr=[`title`],nr={class:`hidden sm:inline`},rr={key:1,class:`text-accent-red text-sm error-indicator`},ir={class:`flex items-center gap-3 lg:flex filter-controls`},ar={class:`flex flex-col`},or=[`value`],sr={class:`flex flex-col`},cr=[`value`],lr={class:`flex flex-col`},ur={class:`flex flex-col reset-container`},dr=[`disabled`],fr={class:`space-y-4 overflow-hidden`},pr={class:`space-y-4`},mr=[`onClick`],hr={class:`hidden lg:grid grid-cols-12 gap-2 items-center`},gr={class:`col-span-1 text-content-primary dark:text-content-primary text-sm`},_r={class:`col-span-1 flex items-center gap-2`},vr={class:`flex flex-col`},yr={class:`text-content-primary dark:text-content-primary text-xs`},br=[`title`],xr={class:`col-span-2`},Sr={class:`col-span-1 text-content-primary dark:text-content-primary text-xs`},Cr={class:`col-span-2`},wr={class:`space-y-1`},Tr={key:0,class:`flex items-center gap-0.5 flex-wrap`},Er=[`title`],Dr={key:0,class:`w-2.5 h-2.5 text-content-muted dark:text-content-muted/60`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Or={key:0,class:`text-[9px] text-content-muted dark:text-content-muted ml-1`},kr={key:1,class:`flex items-center gap-1`},Ar={class:`inline-block px-2 py-0.5 rounded bg-badge-cyan-bg text-badge-cyan-text text-xs font-mono`},jr={class:`col-span-1 text-content-primary dark:text-content-primary text-xs`},Mr={class:`col-span-1 text-content-primary dark:text-content-primary text-xs`},Nr={class:`col-span-1 text-content-primary dark:text-content-primary text-xs`},Pr={class:`col-span-1 text-content-primary dark:text-content-primary text-xs`},Fr={key:0,class:`flex items-center gap-1`},Ir={class:`col-span-1`},Lr={key:0,class:`text-accent-red text-[8px] italic truncate`},Rr={class:`lg:hidden space-y-2`},zr={class:`flex items-center justify-between`},Br={class:`flex items-center gap-2`},Vr={class:`flex flex-col`},Hr={class:`text-content-primary dark:text-content-primary text-sm font-medium`},Ur=[`title`],Wr={class:`flex items-center gap-2 text-right`},Gr={class:`text-content-secondary dark:text-content-muted text-xs`},Kr={class:`flex items-center justify-between`},qr={class:`flex items-center gap-1.5`},Jr={key:0,class:`flex flex-wrap items-center gap-0.5`},Yr=[`title`],Xr={key:0,class:`w-2.5 h-2.5 text-content-muted dark:text-content-muted/60`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},Zr={key:0,class:`text-[9px] text-content-muted dark:text-content-muted ml-1`},Qr={class:`flex items-center gap-1`},$r={class:`inline-block px-2 py-0.5 rounded bg-badge-cyan-bg text-badge-cyan-text text-xs font-mono font-semibold`},ei={class:`flex items-center gap-0.5 text-content-muted dark:text-content-muted/60`},ti={key:0,class:`text-[9px] font-medium`,title:`Multi-hop path`},ni={class:`flex items-center gap-1`},ri={class:`flex items-center gap-2`},ii={class:`flex items-center gap-1`},ai={key:0,class:`flex gap-0.5`},oi={class:`text-content-primary dark:text-content-primary text-xs`},si={class:`flex items-center justify-between text-content-secondary dark:text-content-muted text-xs`},ci={class:`flex items-center gap-3`},li={class:`flex items-center gap-2`},ui={key:0,class:`flex items-center gap-1`},di={key:0,class:`text-accent-red text-xs italic`},fi={key:0,class:`flex justify-between items-center mt-6 pt-4 border-t border-stroke-subtle dark:border-stroke pagination-container`},pi={class:`flex items-center gap-4 pagination-info`},mi={class:`text-content-secondary dark:text-content-muted text-sm`},hi={key:0,class:`flex items-center gap-2 load-more-section`},gi=[`disabled`],_i={class:`text-content-secondary dark:text-content-muted text-xs load-more-count`},vi={class:`flex items-center gap-2 pagination-controls`},yi=[`disabled`],bi={class:`flex items-center gap-1 page-numbers`},xi={key:1,class:`text-content-secondary dark:text-content-muted text-sm px-2 ellipsis`},Si=[`onClick`],Ci={key:2,class:`text-content-secondary dark:text-content-muted text-sm px-2 ellipsis`},wi=[`disabled`],Ti={key:1,class:`flex justify-center mt-6 pt-4 border-t border-stroke-subtle dark:border-stroke`},Ei={class:`flex items-center gap-4`},Di={class:`text-content-secondary dark:text-content-muted text-sm`},Oi={class:`text-content-secondary dark:text-content-muted text-xs`},ki={key:2,class:`flex justify-center mt-6 pt-4 border-t border-stroke-subtle dark:border-stroke`},Q=10,$=1e3,Ai=k(u({name:`PacketTable`,__name:`PacketTable`,setup(e){let n=D(),a=O(),o=w(1),l=w(100),u=w(!1),d=w(!1),_=null;p(()=>n.isLoading,e=>{e?(_&&=(clearTimeout(_),null),d.value=!0):_=window.setTimeout(()=>{d.value=!1,_=null},600)});let T=w(null),E=w(!1),k=async e=>{if(T.value=e,E.value=!0,e.packet_hash&&(!e.header||!e.raw_packet))try{let t=await n.getPacketByHash(e.packet_hash);t&&T.value?.packet_hash===e.packet_hash&&(T.value={...T.value,...t})}catch{}},ee=()=>{E.value=!1,T.value=null},j=w(N(`packetTable_selectedType`,`all`)),P=w(N(`packetTable_selectedRoute`,`all`)),F=w(!1),I=w(null),L=[`all`,`0`,`1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`,`10`,`11`],ne=[`all`,`1`,`2`];p(j,e=>{M(`packetTable_selectedType`,e),o.value=1}),p(P,e=>{M(`packetTable_selectedRoute`,e),o.value=1}),p(F,()=>{o.value=1});let R=g(()=>{let e=n.recentPackets;if(j.value!==`all`){let t=parseInt(j.value);e=e.filter(e=>e.type===t)}if(P.value!==`all`){let t=parseInt(P.value);e=e.filter(e=>e.route===t)}return F.value&&I.value!==null&&(e=e.filter(e=>e.timestamp>=I.value)),e}),re=g(()=>{let e=(o.value-1)*Q,t=e+Q;return R.value.slice(e,t)}),z=g(()=>Math.ceil(R.value.length/Q)),ie=g(()=>o.value===z.value),B=g(()=>n.recentPackets.length>=l.value&&l.value<$),ae=g(()=>ie.value&&B.value&&!u.value),V=e=>new Date(e*1e3).toLocaleTimeString(void 0,{hour12:!0}),H=e=>({0:`REQ`,1:`RESPONSE`,2:`TXT_MSG`,3:`ACK`,4:`ADVERT`,5:`GRP_TXT`,6:`GRP_DATA`,7:`ANON_REQ`,8:`PATH`,9:`TRACE`,10:`MULTI_PART`,11:`CONTROL`})[e]||`TYPE_${e}`,U=e=>({0:`T-Flood`,1:`Flood`,2:`Direct`,3:`T-Direct`})[e]||`Route ${e}`,W=e=>e.transmitted?`text-accent-green`:`text-primary`,G=e=>e.drop_reason?`Dropped`:e.transmitted?`Forward`:`Received`,K=e=>e===1?`bg-badge-cyan-bg text-badge-cyan-text`:`bg-badge-neutral-bg text-badge-neutral-text`,q=e=>({0:`bg-primary`,1:`bg-accent-green`,2:`bg-secondary`,3:`bg-accent-purple`,4:`bg-accent-red`,5:`bg-accent-cyan`,6:`bg-primary`,7:`bg-accent-purple`,8:`bg-accent-green`,9:`bg-secondary`})[e]||`bg-gray-500`,oe=e=>({0:`border-l-primary`,1:`border-l-accent-green`,2:`border-l-secondary`,3:`border-l-accent-purple`,4:`border-l-accent-red`,5:`border-l-accent-cyan`,6:`border-l-primary`,7:`border-l-accent-purple`,8:`border-l-accent-green`,9:`border-l-secondary`})[e]||`border-l-gray-500`,J=e=>!e.transmitted||!e.lbt_attempts||e.lbt_attempts===0?`bg-green-400`:e.lbt_attempts===1?`bg-cyan-400`:e.lbt_attempts===2?`bg-yellow-400`:`bg-orange-400`,se=e=>e>=1e3?(e/1e3).toFixed(2)+`s`:e.toFixed(1)+`ms`,ce=e=>{if(!e)return[];if(Array.isArray(e))return e;if(typeof e==`string`)try{let t=JSON.parse(e);return typeof t==`string`?JSON.parse(t):Array.isArray(t)?t:[]}catch{return[]}return[]},Y=e=>{let t=ce(e.original_path),n=ce(e.forwarded_path),r=t.length>0?t:n;return r.length===0?null:{hops:r.length-1,nodes:r.map(e=>e.toUpperCase())}},X=e=>{if(e.type!==4||!e.payload)return null;try{let t=e.payload.replace(/\s+/g,``).toUpperCase(),n=t,r=0;if(t.length/2>=100)if(t.length>200)n=t.slice(200),r=0;else return null;if(n.length>=2){let e=parseInt(n.slice(0,2),16);r+=2;let t=!!(e&16),i=!!(e&32),a=!!(e&64);if(!(e&128))return null;if(t&&n.length>=r+16&&(r+=16),i&&n.length>=r+4&&(r+=4),a&&n.length>=r+4&&(r+=4),n.length>r){let e=(n.slice(r).match(/.{2}/g)||[]).map(e=>{let t=parseInt(e,16);return t>=32&&t<=126?String.fromCharCode(t):`.`}).join(``).replace(/\.*$/,``);return e.length>0?e:null}}}catch(e){console.error(`Error parsing ADVERT node name:`,e)}return null},le=()=>{j.value=`all`,P.value=`all`,F.value=!1,I.value=null,o.value=1},ue=()=>{F.value?(F.value=!1,I.value=null):(F.value=!0,I.value=Date.now()/1e3),o.value=1},de=g(()=>I.value?new Date(I.value*1e3).toLocaleTimeString(void 0,{hour12:!0}):``),Z=async e=>{try{let t=e||l.value;await n.fetchRecentPackets({limit:t})}catch(e){console.error(`Error fetching packet data:`,e)}},fe=async()=>{if(!(u.value||l.value>=$)){u.value=!0;try{let e=Math.min(l.value+200,$);l.value=e,await Z(e)}catch(e){console.error(`Error loading more records:`,e)}finally{u.value=!1}}};return i(async()=>{await Z()}),A(()=>Z(),{intervalMs:1e4,enabled:()=>!a.isConnected,immediate:!1}),C(()=>{_&&clearTimeout(_)}),(e,i)=>(S(),x(y,null,[b(`div`,Zn,[b(`div`,Qn,[b(`div`,$n,[i[7]||=b(`h3`,{class:`text-content-primary dark:text-content-primary text-xl font-semibold`},` Recent Packets `,-1),b(`span`,er,` (`+v(R.value.length)+` of `+v(r(n).recentPackets.length)+`) `,1),F.value?(S(),x(`span`,{key:0,class:`text-primary text-xs sm:text-sm bg-primary/10 px-2 py-1 rounded-md border border-primary/20 live-mode-badge whitespace-nowrap`,title:`Filter activated at ${de.value}`},[b(`span`,nr,`Live Mode (since `+v(de.value)+`)`,1),i[6]||=b(`span`,{class:`sm:hidden`},`Live`,-1)],8,tr)):m(``,!0),r(n).error?(S(),x(`span`,rr,v(r(n).error),1)):m(``,!0)]),b(`div`,ir,[b(`div`,ar,[i[8]||=b(`label`,{class:`text-content-secondary dark:text-content-muted text-xs mb-1`},`Type`,-1),f(b(`select`,{"onUpdate:modelValue":i[0]||=e=>j.value=e,class:`glass-card border border-stroke-subtle dark:border-stroke rounded-[10px] px-3 py-2 text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20 transition-all duration-200 min-w-[120px] cursor-pointer hover:border-primary/50`},[(S(),x(y,null,t(L,e=>b(`option`,{key:e,value:e,class:`bg-surface dark:bg-surface-elevated text-content-primary dark:text-content-primary`},v(e===`all`?`All Types`:`Type ${e} (${H(parseInt(e))})`),9,or)),64))],512),[[te,j.value]])]),b(`div`,sr,[i[9]||=b(`label`,{class:`text-content-secondary dark:text-content-muted text-xs mb-1`},`Route`,-1),f(b(`select`,{"onUpdate:modelValue":i[1]||=e=>P.value=e,class:`glass-card border border-stroke-subtle dark:border-stroke rounded-[10px] px-3 py-2 text-content-primary dark:text-content-primary text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20 transition-all duration-200 min-w-[120px] cursor-pointer hover:border-primary/50`},[(S(),x(y,null,t(ne,e=>b(`option`,{key:e,value:e,class:`bg-surface dark:bg-surface-elevated text-content-primary dark:text-content-primary`},v(e===`all`?`All Routes`:`Route ${e} (${U(parseInt(e))})`),9,cr)),64))],512),[[te,P.value]])]),b(`div`,lr,[i[10]||=b(`label`,{class:`text-content-secondary dark:text-content-muted text-xs mb-1`},`Filter`,-1),b(`button`,{onClick:ue,class:s([`glass-card border rounded-[10px] px-4 py-2 text-sm transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-primary/20 min-w-[120px]`,{"border-primary bg-primary/10 text-primary":F.value,"border-stroke-subtle dark:border-stroke text-content-secondary dark:text-content-muted hover:border-primary hover:text-content-primary dark:hover:text-content-primary hover:bg-primary/5":!F.value}])},v(F.value?`New Only`:`Show New`),3)]),b(`div`,ur,[i[11]||=b(`label`,{class:`text-transparent text-xs mb-1`},`.`,-1),b(`button`,{onClick:le,class:s([`glass-card border border-stroke-subtle dark:border-stroke hover:border-primary rounded-[10px] px-4 py-2 text-content-secondary dark:text-content-muted hover:text-content-primary dark:hover:text-content-primary text-sm transition-all duration-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20`,{"opacity-50 cursor-not-allowed hover:border-stroke-subtle dark:hover:border-stroke hover:text-content-secondary dark:hover:text-content-muted":j.value===`all`&&P.value===`all`&&!F.value,"hover:bg-primary/10":j.value!==`all`||P.value!==`all`||F.value}]),disabled:j.value===`all`&&P.value===`all`&&!F.value},` Reset `,10,dr)])])]),i[25]||=c(`Time
Type
Route
LEN
Path/Hashes
RSSI
SNR
Score
TX Delay
Status
`,1),b(`div`,fr,[b(`div`,pr,[(S(!0),x(y,null,t(re.value,(e,n)=>(S(),x(`div`,{key:`${e.packet_hash}_${e.timestamp}_${n}`,class:s([`packet-row border-b border-stroke-subtle dark:border-dark-border/50 pb-4 hover:bg-background-mute dark:hover:bg-stroke/5 transition-colors duration-150 cursor-pointer rounded-[10px] p-2 border-l-4`,oe(e.type)]),onClick:t=>k(e)},[b(`div`,hr,[b(`div`,gr,v(V(e.timestamp)),1),b(`div`,_r,[b(`div`,{class:s([`w-2 h-2 rounded-full`,q(e.type)])},null,2),b(`div`,vr,[b(`span`,yr,v(H(e.type)),1),e.type===4&&X(e)?(S(),x(`span`,{key:0,class:`text-accent-red/70 text-[10px] font-medium max-w-[80px] truncate`,title:X(e)||void 0},v(X(e)),9,br)):m(``,!0)])]),b(`div`,xr,[b(`span`,{class:s([`inline-block px-2 py-1 rounded text-xs font-medium`,K(e.route)])},v(U(e.route)),3)]),b(`div`,Sr,v(e.length)+`B `,1),b(`div`,Cr,[b(`div`,wr,[Y(e)?(S(),x(`div`,Tr,[(S(!0),x(y,null,t(Y(e).nodes,(t,n)=>(S(),x(y,{key:n},[b(`span`,{class:s([`inline-block max-w-full truncate px-1.5 py-0.5 rounded text-[9px] font-mono font-semibold leading-tight tracking-tight`,n===0?`bg-badge-cyan-bg text-badge-cyan-text`:`bg-gray-500/20 text-content-muted dark:text-content-muted`]),title:t},v(t),11,Er),n0?(S(),x(`span`,Or,` (`+v(Y(e).hops)+` hop`+v(Y(e).hops>1?`s`:``)+`) `,1)):m(``,!0)])):(S(),x(`div`,kr,[b(`span`,Ar,v(e.src_hash?.slice(-4).toUpperCase()||`????`),1),i[13]||=b(`svg`,{class:`w-3 h-3 text-content-muted dark:text-content-muted/60`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[b(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2.5`,d:`M9 5l7 7-7 7`})],-1),b(`span`,{class:s([`inline-block px-2 py-0.5 rounded text-xs font-mono`,e.dst_hash?`bg-badge-cyan-bg text-badge-cyan-text`:`bg-yellow-500/20 text-yellow-700 dark:text-yellow-300`])},v(e.dst_hash?e.dst_hash.slice(-4).toUpperCase():`BCAST`),3)]))])]),b(`div`,jr,v(e.rssi==null?`N/A`:e.rssi.toFixed(0)),1),b(`div`,Mr,v(e.snr==null?`N/A`:e.snr.toFixed(1)+`dB`),1),b(`div`,Nr,v(e.score==null?`N/A`:e.score.toFixed(2)),1),b(`div`,Pr,[Number(e.tx_delay_ms)>0?(S(),x(`div`,Fr,[e.transmitted?(S(),x(`div`,{key:0,class:s([`w-1.5 h-1.5 rounded-full flex-shrink-0`,J(e)])},null,2)):m(``,!0),b(`span`,null,v(se(Number(e.tx_delay_ms))),1)])):m(``,!0)]),b(`div`,Ir,[b(`div`,null,[b(`span`,{class:s([`text-xs font-medium`,W(e)])},v(G(e)),3),e.drop_reason?(S(),x(`p`,Lr,v(e.drop_reason),1)):m(``,!0)])])]),b(`div`,Rr,[b(`div`,zr,[b(`div`,Br,[b(`div`,{class:s([`w-2 h-2 rounded-full flex-shrink-0`,q(e.type)])},null,2),b(`div`,Vr,[b(`span`,Hr,v(H(e.type)),1),e.type===4&&X(e)?(S(),x(`span`,{key:0,class:`text-accent-red/70 text-[10px] font-medium leading-tight`,title:X(e)||void 0},v(X(e)),9,Ur)):m(``,!0)]),b(`span`,{class:s([`inline-block px-2 py-1 rounded text-xs font-medium ml-2`,K(e.route)])},v(U(e.route)),3)]),b(`div`,Wr,[b(`span`,Gr,v(V(e.timestamp)),1),b(`span`,{class:s([`text-xs font-medium`,W(e)])},v(G(e)),3)])]),b(`div`,Kr,[b(`div`,qr,[Y(e)?(S(),x(`div`,Jr,[i[15]||=b(`span`,{class:`text-content-muted dark:text-content-muted text-[10px] font-medium`},`PATH`,-1),(S(!0),x(y,null,t(Y(e).nodes,(t,n)=>(S(),x(y,{key:n},[b(`span`,{class:s([`inline-block max-w-full truncate px-1.5 py-0.5 rounded text-[9px] font-mono font-semibold leading-tight tracking-tight`,n===0?`bg-badge-cyan-bg text-badge-cyan-text`:`bg-gray-500/20 text-content-muted dark:text-content-muted`]),title:t},v(t),11,Yr),n0?(S(),x(`span`,Zr,` (`+v(Y(e).hops)+` hop`+v(Y(e).hops>1?`s`:``)+`) `,1)):m(``,!0)])):(S(),x(y,{key:1},[b(`div`,Qr,[i[16]||=b(`span`,{class:`text-content-muted dark:text-content-muted text-[10px] font-medium`},`SRC`,-1),b(`span`,$r,v(e.src_hash?.slice(-4)||`????`),1)]),b(`div`,ei,[i[18]||=b(`svg`,{class:`w-3 h-3`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[b(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2.5`,d:`M9 5l7 7-7 7`})],-1),e.route===1?(S(),x(`span`,ti,[...i[17]||=[b(`svg`,{class:`w-2.5 h-2.5 inline`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[b(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,"stroke-width":`2`,d:`M13 5l7 7-7 7M5 5l7 7-7 7`})],-1)]])):m(``,!0)]),b(`div`,ni,[b(`span`,{class:s([`inline-block px-2 py-0.5 rounded text-xs font-mono font-semibold`,e.dst_hash?`bg-badge-cyan-bg text-badge-cyan-text`:`bg-yellow-500/20 text-yellow-700 dark:text-yellow-300`])},v(e.dst_hash?e.dst_hash.slice(-4).toUpperCase():`BCAST`),3),i[19]||=b(`span`,{class:`text-content-muted dark:text-content-muted text-[10px] font-medium`},`DST`,-1)])],64))]),b(`div`,ri,[b(`div`,ii,[e.snr==null?m(``,!0):(S(),x(`div`,ai,[b(`div`,{class:s([`w-1 h-3 rounded-sm`,e.snr>=-10?`bg-green-400`:`bg-white/20`])},null,2),b(`div`,{class:s([`w-1 h-4 rounded-sm`,e.snr>=-5?`bg-green-400`:`bg-white/20`])},null,2),b(`div`,{class:s([`w-1 h-5 rounded-sm`,e.snr>=0?`bg-green-400`:`bg-white/20`])},null,2),b(`div`,{class:s([`w-1 h-6 rounded-sm`,e.snr>=10?`bg-green-400`:`bg-white/20`])},null,2)])),b(`span`,oi,v(e.rssi==null?`TX`:e.rssi.toFixed(0)+`dBm`),1)])])]),b(`div`,si,[b(`div`,ci,[b(`span`,null,v(e.length)+`B`,1),b(`span`,null,`SNR: `+v(e.snr==null?`N/A`:e.snr.toFixed(1)+`dB`),1),b(`span`,null,`Score: `+v(e.score==null?`N/A`:e.score.toFixed(2)),1)]),b(`div`,li,[Number(e.tx_delay_ms)>0?(S(),x(`span`,ui,[e.transmitted?(S(),x(`div`,{key:0,class:s([`w-1.5 h-1.5 rounded-full flex-shrink-0`,J(e)])},null,2)):m(``,!0),b(`span`,null,v(se(Number(e.tx_delay_ms))),1)])):m(``,!0)])]),e.drop_reason?(S(),x(`div`,di,v(e.drop_reason),1)):m(``,!0)])],10,mr))),128))])]),z.value>1?(S(),x(`div`,fi,[b(`div`,pi,[b(`span`,mi,` Showing `+v((o.value-1)*Q+1)+` - `+v(Math.min(o.value*Q,R.value.length))+` of `+v(R.value.length)+` packets `,1),ae.value?(S(),x(`div`,hi,[i[20]||=b(`span`,{class:`text-content-secondary dark:text-content-muted text-xs`},`•`,-1),b(`button`,{onClick:fe,disabled:u.value,class:s([`glass-card border border-primary rounded-[8px] px-3 py-1.5 text-xs transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-primary/20 hover:bg-primary/5`,{"text-primary border-primary cursor-pointer":!u.value,"text-content-secondary dark:text-content-muted border-stroke-subtle dark:border-stroke cursor-not-allowed opacity-50":u.value}])},v(u.value?`Loading...`:`Load ${Math.min(200,$-l.value)} more`),11,gi),b(`span`,_i,`(`+v(l.value)+`/`+v($)+` max)`,1)])):m(``,!0)]),b(`div`,vi,[b(`button`,{onClick:i[2]||=e=>--o.value,disabled:o.value<=1,class:s([`glass-card border rounded-[10px] px-3 py-2 text-sm transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-primary/20 prev-next-btn`,{"border-stroke-subtle dark:border-stroke text-content-muted dark:text-content-muted cursor-not-allowed opacity-50":o.value<=1,"border-stroke-subtle dark:border-stroke text-content-primary dark:text-content-primary hover:border-primary hover:text-primary hover:bg-primary/5":o.value>1}])},[...i[21]||=[b(`span`,{class:`hidden sm:inline`},`Previous`,-1),b(`span`,{class:`sm:hidden`},`‹`,-1)]],10,yi),b(`div`,bi,[o.value>3?(S(),x(`button`,{key:0,onClick:i[3]||=e=>o.value=1,class:`glass-card border border-stroke-subtle dark:border-stroke hover:border-primary rounded-[8px] px-3 py-2 text-sm text-content-primary dark:text-content-primary hover:text-primary hover:bg-primary/5 transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-primary/20`},` 1 `)):m(``,!0),o.value>4?(S(),x(`span`,xi,`...`)):m(``,!0),(S(!0),x(y,null,t(Array.from({length:Math.min(5,z.value)},(e,t)=>Math.max(1,Math.min(o.value-2,z.value-4))+t).filter(e=>e<=z.value),e=>(S(),x(`button`,{key:e,onClick:t=>o.value=e,class:s([`glass-card border rounded-[8px] px-3 py-2 text-sm transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-primary/20 page-number`,{"border-primary bg-primary/10 text-primary":o.value===e,"border-stroke-subtle dark:border-stroke text-content-primary dark:text-content-primary hover:border-primary hover:text-primary hover:bg-primary/5":o.value!==e}])},v(e),11,Si))),128)),o.valueo.value=z.value,class:`glass-card border border-stroke-subtle dark:border-stroke hover:border-primary rounded-[8px] px-3 py-2 text-sm text-content-primary dark:text-content-primary hover:text-primary hover:bg-primary/5 transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-primary/20`},v(z.value),1)):m(``,!0)]),b(`button`,{onClick:i[5]||=e=>o.value+=1,disabled:o.value>=z.value,class:s([`glass-card border rounded-[10px] px-3 py-2 text-sm transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-primary/20 prev-next-btn`,{"border-stroke-subtle dark:border-stroke text-content-muted dark:text-content-muted cursor-not-allowed opacity-50":o.value>=z.value,"border-stroke-subtle dark:border-stroke text-content-primary dark:text-content-primary hover:border-primary hover:text-primary hover:bg-primary/5":o.value(S(),x(`div`,null,[h(G),b(`div`,ji,[h(Ne),h(_e)]),h(Ai)]))}});export{Mi as default};
\ No newline at end of file
diff --git a/repeater/web/html/assets/GPSDiagnostics-BwWIzMvN.css b/repeater/web/html/assets/GPSDiagnostics-BwWIzMvN.css
deleted file mode 100644
index 928dec1..0000000
--- a/repeater/web/html/assets/GPSDiagnostics-BwWIzMvN.css
+++ /dev/null
@@ -1 +0,0 @@
-.globe-stage[data-v-dd3f03c2]{border:1px solid var(--color-border-subtle);background:radial-gradient(circle at 50% 46%, color-mix(in srgb, var(--color-primary) 24%, transparent), transparent 34%), radial-gradient(circle at 48% 50%, #ffffff24, transparent 20%), linear-gradient(145deg, var(--color-background-soft), var(--color-background));cursor:grab;touch-action:none;border-radius:10px;min-height:330px;position:relative;overflow:hidden}.globe-stage[data-v-dd3f03c2]:active{cursor:grabbing}.globe-stage canvas[data-v-dd3f03c2]{width:100%;height:330px;display:block}.globe-tooltip[data-v-dd3f03c2]{z-index:2;color:#fff;pointer-events:none;background:#050a0ceb;border:1px solid #ffffff2e;border-radius:12px;min-width:154px;padding:10px 11px;position:absolute;transform:translate(-50%,calc(-100% - 22px));box-shadow:0 14px 40px #0000005c}.tooltip-title[data-v-dd3f03c2]{color:var(--color-accent-green);letter-spacing:.06em;text-transform:uppercase;font-size:.82rem;font-weight:800}.tooltip-grid[data-v-dd3f03c2]{grid-template-columns:auto 1fr;gap:4px 10px;margin-top:7px;font-size:.78rem;display:grid}.tooltip-key[data-v-dd3f03c2]{color:#ffffffa8}.tooltip-value[data-v-dd3f03c2]{color:#fff;text-align:right;font-weight:700}.globe-fallback[data-v-dd3f03c2]{padding:18px;position:absolute;inset:0}.fallback-sky[data-v-dd3f03c2]{aspect-ratio:1;border:1px solid color-mix(in srgb, var(--color-primary) 34%, var(--color-border-subtle));background:radial-gradient(circle, color-mix(in srgb, var(--color-primary) 18%, transparent) 0 2px, transparent 3px), repeating-radial-gradient(circle, transparent 0 31%, color-mix(in srgb, var(--color-border) 70%, transparent) 31.5% 32%, transparent 32.5% 49%), linear-gradient(90deg, transparent 49.7%, color-mix(in srgb, var(--color-border) 78%, transparent) 49.7% 50.3%, transparent 50.3%), linear-gradient(0deg, transparent 49.7%, color-mix(in srgb, var(--color-border) 78%, transparent) 49.7% 50.3%, transparent 50.3%);border-radius:50%;width:min(250px,72vw);margin:0 auto;position:relative}.fallback-sat[data-v-dd3f03c2]{width:var(--size);height:var(--size);background:var(--color-primary);box-shadow:0 0 16px color-mix(in srgb, var(--color-primary) 70%, transparent);border-radius:999px;position:absolute;transform:translate(-50%,-50%)}.fallback-sat-used[data-v-dd3f03c2]{background:var(--color-accent-green);box-shadow:0 0 16px color-mix(in srgb, var(--color-accent-green) 70%, transparent)}.fallback-sat span[data-v-dd3f03c2]{color:var(--color-text-primary);white-space:nowrap;font-size:.65rem;font-weight:700;position:absolute;top:calc(100% + 4px);left:50%;transform:translate(-50%)}.sky-empty[data-v-dd3f03c2]{color:var(--color-text-muted);pointer-events:none;place-items:center;font-size:.875rem;display:grid;position:absolute;inset:0}
diff --git a/repeater/web/html/assets/GPSDiagnostics-Cecv5jtN.js b/repeater/web/html/assets/GPSDiagnostics-Cecv5jtN.js
deleted file mode 100644
index 38b65c2..0000000
--- a/repeater/web/html/assets/GPSDiagnostics-Cecv5jtN.js
+++ /dev/null
@@ -1,4104 +0,0 @@
-import{C as e,E as t,S as n,b as r,dt as i,ft as a,g as o,j as s,k as c,l,o as u,p as d,pt as f,r as p,s as m,u as h,w as g,x as _,z as v}from"./runtime-core.esm-bundler-HnidnMFy.js";import{c as y,t as b}from"./api-B2W0XzZe.js";import{t as x}from"./_plugin-vue_export-helper-B7aGp3iI.js";import{p as S}from"./index-DiHOFPOZ.js";var C={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},w={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},T=1e3,E=1001,D=1002,O=1003,k=1004,A=1005,j=1006,ee=1007,te=1008,M=1009,N=1010,P=1011,ne=1012,re=1013,ie=1014,ae=1015,oe=1016,se=1017,ce=1018,F=1020,le=35902,ue=35899,de=1021,fe=1022,pe=1023,me=1026,he=1027,I=1028,ge=1029,_e=1030,ve=1031,ye=1033,be=33776,xe=33777,Se=33778,Ce=33779,we=35840,Te=35841,Ee=35842,De=35843,Oe=36196,L=37492,ke=37496,R=37488,Ae=37489,z=37490,je=37491,B=37808,V=37809,Me=37810,Ne=37811,Pe=37812,Fe=37813,Ie=37814,Le=37815,Re=37816,ze=37817,Be=37818,Ve=37819,He=37820,Ue=37821,We=36492,Ge=36494,Ke=36495,qe=36283,Je=36284,Ye=36285,Xe=36286,Ze=2300,Qe=2301,$e=2302,et=2303,tt=2400,nt=2401,rt=2402,it=3200,at=`srgb`,ot=`srgb-linear`,st=`linear`,ct=`srgb`,lt=7680,ut=35044,dt=2e3;function ft(e){for(let t=e.length-1;t>=0;--t)if(e[t]>=65535)return!0;return!1}function pt(e){return ArrayBuffer.isView(e)&&!(e instanceof DataView)}function mt(e){return document.createElementNS(`http://www.w3.org/1999/xhtml`,e)}function ht(){let e=mt(`canvas`);return e.style.display=`block`,e}var gt={},_t=null;function vt(...e){let t=`THREE.`+e.shift();_t?_t(`log`,t,...e):console.log(t,...e)}function yt(e){let t=e[0];if(typeof t==`string`&&t.startsWith(`TSL:`)){let t=e[1];t&&t.isStackTrace?e[0]+=` `+t.getLocation():e[1]=`Stack trace not available. Enable "THREE.Node.captureStackTrace" to capture stack traces.`}return e}function H(...e){e=yt(e);let t=`THREE.`+e.shift();if(_t)_t(`warn`,t,...e);else{let n=e[0];n&&n.isStackTrace?console.warn(n.getError(t)):console.warn(t,...e)}}function U(...e){e=yt(e);let t=`THREE.`+e.shift();if(_t)_t(`error`,t,...e);else{let n=e[0];n&&n.isStackTrace?console.error(n.getError(t)):console.error(t,...e)}}function bt(...e){let t=e.join(` `);t in gt||(gt[t]=!0,H(...e))}function xt(e,t,n){return new Promise(function(r,i){function a(){switch(e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0)){case e.WAIT_FAILED:i();break;case e.TIMEOUT_EXPIRED:setTimeout(a,n);break;default:r()}}setTimeout(a,n)})}var St={0:1,2:6,4:7,3:5,1:0,6:2,7:4,5:3},Ct=class{addEventListener(e,t){this._listeners===void 0&&(this._listeners={});let n=this._listeners;n[e]===void 0&&(n[e]=[]),n[e].indexOf(t)===-1&&n[e].push(t)}hasEventListener(e,t){let n=this._listeners;return n===void 0?!1:n[e]!==void 0&&n[e].indexOf(t)!==-1}removeEventListener(e,t){let n=this._listeners;if(n===void 0)return;let r=n[e];if(r!==void 0){let e=r.indexOf(t);e!==-1&&r.splice(e,1)}}dispatchEvent(e){let t=this._listeners;if(t===void 0)return;let n=t[e.type];if(n!==void 0){e.target=this;let t=n.slice(0);for(let n=0,r=t.length;n>8&255]+wt[e>>16&255]+wt[e>>24&255]+`-`+wt[t&255]+wt[t>>8&255]+`-`+wt[t>>16&15|64]+wt[t>>24&255]+`-`+wt[n&63|128]+wt[n>>8&255]+`-`+wt[n>>16&255]+wt[n>>24&255]+wt[r&255]+wt[r>>8&255]+wt[r>>16&255]+wt[r>>24&255]).toLowerCase()}function W(e,t,n){return Math.max(t,Math.min(n,e))}function kt(e,t){return(e%t+t)%t}function At(e,t,n,r,i){return r+(e-t)*(i-r)/(n-t)}function jt(e,t,n){return e===t?0:(n-e)/(t-e)}function Mt(e,t,n){return(1-n)*e+n*t}function Nt(e,t,n,r){return Mt(e,t,1-Math.exp(-n*r))}function Pt(e,t=1){return t-Math.abs(kt(e,t*2)-t)}function Ft(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t),e*e*(3-2*e))}function It(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t),e*e*e*(e*(e*6-15)+10))}function Lt(e,t){return e+Math.floor(Math.random()*(t-e+1))}function Rt(e,t){return e+Math.random()*(t-e)}function zt(e){return e*(.5-Math.random())}function Bt(e){e!==void 0&&(Tt=e);let t=Tt+=1831565813;return t=Math.imul(t^t>>>15,t|1),t^=t+Math.imul(t^t>>>7,t|61),((t^t>>>14)>>>0)/4294967296}function Vt(e){return e*Et}function Ht(e){return e*Dt}function Ut(e){return(e&e-1)==0&&e!==0}function Wt(e){return 2**Math.ceil(Math.log(e)/Math.LN2)}function Gt(e){return 2**Math.floor(Math.log(e)/Math.LN2)}function Kt(e,t,n,r,i){let a=Math.cos,o=Math.sin,s=a(n/2),c=o(n/2),l=a((t+r)/2),u=o((t+r)/2),d=a((t-r)/2),f=o((t-r)/2),p=a((r-t)/2),m=o((r-t)/2);switch(i){case`XYX`:e.set(s*u,c*d,c*f,s*l);break;case`YZY`:e.set(c*f,s*u,c*d,s*l);break;case`ZXZ`:e.set(c*d,c*f,s*u,s*l);break;case`XZX`:e.set(s*u,c*m,c*p,s*l);break;case`YXY`:e.set(c*p,s*u,c*m,s*l);break;case`ZYZ`:e.set(c*m,c*p,s*u,s*l);break;default:H(`MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: `+i)}}function qt(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return e/4294967295;case Uint16Array:return e/65535;case Uint8Array:return e/255;case Int32Array:return Math.max(e/2147483647,-1);case Int16Array:return Math.max(e/32767,-1);case Int8Array:return Math.max(e/127,-1);default:throw Error(`Invalid component type.`)}}function G(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return Math.round(e*4294967295);case Uint16Array:return Math.round(e*65535);case Uint8Array:return Math.round(e*255);case Int32Array:return Math.round(e*2147483647);case Int16Array:return Math.round(e*32767);case Int8Array:return Math.round(e*127);default:throw Error(`Invalid component type.`)}}var Jt={DEG2RAD:Et,RAD2DEG:Dt,generateUUID:Ot,clamp:W,euclideanModulo:kt,mapLinear:At,inverseLerp:jt,lerp:Mt,damp:Nt,pingpong:Pt,smoothstep:Ft,smootherstep:It,randInt:Lt,randFloat:Rt,randFloatSpread:zt,seededRandom:Bt,degToRad:Vt,radToDeg:Ht,isPowerOfTwo:Ut,ceilPowerOfTwo:Wt,floorPowerOfTwo:Gt,setQuaternionFromProperEuler:Kt,normalize:G,denormalize:qt},K=class e{static{e.prototype.isVector2=!0}constructor(e=0,t=0){this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw Error(`index is out of range: `+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw Error(`index is out of range: `+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){let t=this.x,n=this.y,r=e.elements;return this.x=r[0]*t+r[3]*n+r[6],this.y=r[1]*t+r[4]*n+r[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=W(this.x,e.x,t.x),this.y=W(this.y,e.y,t.y),this}clampScalar(e,t){return this.x=W(this.x,e,t),this.y=W(this.y,e,t),this}clampLength(e,t){let n=this.length();return this.divideScalar(n||1).multiplyScalar(W(n,e,t))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(e){let t=Math.sqrt(this.lengthSq()*e.lengthSq());if(t===0)return Math.PI/2;let n=this.dot(e)/t;return Math.acos(W(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){let t=this.x-e.x,n=this.y-e.y;return t*t+n*n}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){let n=Math.cos(t),r=Math.sin(t),i=this.x-e.x,a=this.y-e.y;return this.x=i*n-a*r+e.x,this.y=i*r+a*n+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}},Yt=class{constructor(e=0,t=0,n=0,r=1){this.isQuaternion=!0,this._x=e,this._y=t,this._z=n,this._w=r}static slerpFlat(e,t,n,r,i,a,o){let s=n[r+0],c=n[r+1],l=n[r+2],u=n[r+3],d=i[a+0],f=i[a+1],p=i[a+2],m=i[a+3];if(u!==m||s!==d||c!==f||l!==p){let e=s*d+c*f+l*p+u*m;e<0&&(d=-d,f=-f,p=-p,m=-m,e=-e);let t=1-o;if(e<.9995){let n=Math.acos(e),r=Math.sin(n);t=Math.sin(t*n)/r,o=Math.sin(o*n)/r,s=s*t+d*o,c=c*t+f*o,l=l*t+p*o,u=u*t+m*o}else{s=s*t+d*o,c=c*t+f*o,l=l*t+p*o,u=u*t+m*o;let e=1/Math.sqrt(s*s+c*c+l*l+u*u);s*=e,c*=e,l*=e,u*=e}}e[t]=s,e[t+1]=c,e[t+2]=l,e[t+3]=u}static multiplyQuaternionsFlat(e,t,n,r,i,a){let o=n[r],s=n[r+1],c=n[r+2],l=n[r+3],u=i[a],d=i[a+1],f=i[a+2],p=i[a+3];return e[t]=o*p+l*u+s*f-c*d,e[t+1]=s*p+l*d+c*u-o*f,e[t+2]=c*p+l*f+o*d-s*u,e[t+3]=l*p-o*u-s*d-c*f,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,n,r){return this._x=e,this._y=t,this._z=n,this._w=r,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){let n=e._x,r=e._y,i=e._z,a=e._order,o=Math.cos,s=Math.sin,c=o(n/2),l=o(r/2),u=o(i/2),d=s(n/2),f=s(r/2),p=s(i/2);switch(a){case`XYZ`:this._x=d*l*u+c*f*p,this._y=c*f*u-d*l*p,this._z=c*l*p+d*f*u,this._w=c*l*u-d*f*p;break;case`YXZ`:this._x=d*l*u+c*f*p,this._y=c*f*u-d*l*p,this._z=c*l*p-d*f*u,this._w=c*l*u+d*f*p;break;case`ZXY`:this._x=d*l*u-c*f*p,this._y=c*f*u+d*l*p,this._z=c*l*p+d*f*u,this._w=c*l*u-d*f*p;break;case`ZYX`:this._x=d*l*u-c*f*p,this._y=c*f*u+d*l*p,this._z=c*l*p-d*f*u,this._w=c*l*u+d*f*p;break;case`YZX`:this._x=d*l*u+c*f*p,this._y=c*f*u+d*l*p,this._z=c*l*p-d*f*u,this._w=c*l*u-d*f*p;break;case`XZY`:this._x=d*l*u-c*f*p,this._y=c*f*u-d*l*p,this._z=c*l*p+d*f*u,this._w=c*l*u+d*f*p;break;default:H(`Quaternion: .setFromEuler() encountered an unknown order: `+a)}return t===!0&&this._onChangeCallback(),this}setFromAxisAngle(e,t){let n=t/2,r=Math.sin(n);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(e){let t=e.elements,n=t[0],r=t[4],i=t[8],a=t[1],o=t[5],s=t[9],c=t[2],l=t[6],u=t[10],d=n+o+u;if(d>0){let e=.5/Math.sqrt(d+1);this._w=.25/e,this._x=(l-s)*e,this._y=(i-c)*e,this._z=(a-r)*e}else if(n>o&&n>u){let e=2*Math.sqrt(1+n-o-u);this._w=(l-s)/e,this._x=.25*e,this._y=(r+a)/e,this._z=(i+c)/e}else if(o>u){let e=2*Math.sqrt(1+o-n-u);this._w=(i-c)/e,this._x=(r+a)/e,this._y=.25*e,this._z=(s+l)/e}else{let e=2*Math.sqrt(1+u-n-o);this._w=(a-r)/e,this._x=(i+c)/e,this._y=(s+l)/e,this._z=.25*e}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let n=e.dot(t)+1;return n<1e-8?(n=0,Math.abs(e.x)>Math.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=n):(this._x=0,this._y=-e.z,this._z=e.y,this._w=n)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=n),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs(W(this.dot(e),-1,1)))}rotateTowards(e,t){let n=this.angleTo(e);if(n===0)return this;let r=Math.min(1,t/n);return this.slerp(e,r),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let e=this.length();return e===0?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x*=e,this._y*=e,this._z*=e,this._w*=e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){let n=e._x,r=e._y,i=e._z,a=e._w,o=t._x,s=t._y,c=t._z,l=t._w;return this._x=n*l+a*o+r*c-i*s,this._y=r*l+a*s+i*o-n*c,this._z=i*l+a*c+n*s-r*o,this._w=a*l-n*o-r*s-i*c,this._onChangeCallback(),this}slerp(e,t){let n=e._x,r=e._y,i=e._z,a=e._w,o=this.dot(e);o<0&&(n=-n,r=-r,i=-i,a=-a,o=-o);let s=1-t;if(o<.9995){let e=Math.acos(o),c=Math.sin(e);s=Math.sin(s*e)/c,t=Math.sin(t*e)/c,this._x=this._x*s+n*t,this._y=this._y*s+r*t,this._z=this._z*s+i*t,this._w=this._w*s+a*t,this._onChangeCallback()}else this._x=this._x*s+n*t,this._y=this._y*s+r*t,this._z=this._z*s+i*t,this._w=this._w*s+a*t,this.normalize();return this}slerpQuaternions(e,t,n){return this.copy(e).slerp(t,n)}random(){let e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),n=Math.random(),r=Math.sqrt(1-n),i=Math.sqrt(n);return this.set(r*Math.sin(e),r*Math.cos(e),i*Math.sin(t),i*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}},q=class e{static{e.prototype.isVector3=!0}constructor(e=0,t=0,n=0){this.x=e,this.y=t,this.z=n}set(e,t,n){return n===void 0&&(n=this.z),this.x=e,this.y=t,this.z=n,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw Error(`index is out of range: `+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw Error(`index is out of range: `+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(Zt.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(Zt.setFromAxisAngle(e,t))}applyMatrix3(e){let t=this.x,n=this.y,r=this.z,i=e.elements;return this.x=i[0]*t+i[3]*n+i[6]*r,this.y=i[1]*t+i[4]*n+i[7]*r,this.z=i[2]*t+i[5]*n+i[8]*r,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){let t=this.x,n=this.y,r=this.z,i=e.elements,a=1/(i[3]*t+i[7]*n+i[11]*r+i[15]);return this.x=(i[0]*t+i[4]*n+i[8]*r+i[12])*a,this.y=(i[1]*t+i[5]*n+i[9]*r+i[13])*a,this.z=(i[2]*t+i[6]*n+i[10]*r+i[14])*a,this}applyQuaternion(e){let t=this.x,n=this.y,r=this.z,i=e.x,a=e.y,o=e.z,s=e.w,c=2*(a*r-o*n),l=2*(o*t-i*r),u=2*(i*n-a*t);return this.x=t+s*c+a*u-o*l,this.y=n+s*l+o*c-i*u,this.z=r+s*u+i*l-a*c,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){let t=this.x,n=this.y,r=this.z,i=e.elements;return this.x=i[0]*t+i[4]*n+i[8]*r,this.y=i[1]*t+i[5]*n+i[9]*r,this.z=i[2]*t+i[6]*n+i[10]*r,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=W(this.x,e.x,t.x),this.y=W(this.y,e.y,t.y),this.z=W(this.z,e.z,t.z),this}clampScalar(e,t){return this.x=W(this.x,e,t),this.y=W(this.y,e,t),this.z=W(this.z,e,t),this}clampLength(e,t){let n=this.length();return this.divideScalar(n||1).multiplyScalar(W(n,e,t))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){let n=e.x,r=e.y,i=e.z,a=t.x,o=t.y,s=t.z;return this.x=r*s-i*o,this.y=i*a-n*s,this.z=n*o-r*a,this}projectOnVector(e){let t=e.lengthSq();if(t===0)return this.set(0,0,0);let n=e.dot(this)/t;return this.copy(e).multiplyScalar(n)}projectOnPlane(e){return Xt.copy(this).projectOnVector(e),this.sub(Xt)}reflect(e){return this.sub(Xt.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){let t=Math.sqrt(this.lengthSq()*e.lengthSq());if(t===0)return Math.PI/2;let n=this.dot(e)/t;return Math.acos(W(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){let t=this.x-e.x,n=this.y-e.y,r=this.z-e.z;return t*t+n*n+r*r}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,n){let r=Math.sin(t)*e;return this.x=r*Math.sin(n),this.y=Math.cos(t)*e,this.z=r*Math.cos(n),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,n){return this.x=e*Math.sin(t),this.y=n,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){let t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){let t=this.setFromMatrixColumn(e,0).length(),n=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=n,this.z=r,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,t*4)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,t*3)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){let e=Math.random()*Math.PI*2,t=Math.random()*2-1,n=Math.sqrt(1-t*t);return this.x=n*Math.cos(e),this.y=t,this.z=n*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}},Xt=new q,Zt=new Yt,J=class e{static{e.prototype.isMatrix3=!0}constructor(e,t,n,r,i,a,o,s,c){this.elements=[1,0,0,0,1,0,0,0,1],e!==void 0&&this.set(e,t,n,r,i,a,o,s,c)}set(e,t,n,r,i,a,o,s,c){let l=this.elements;return l[0]=e,l[1]=r,l[2]=o,l[3]=t,l[4]=i,l[5]=s,l[6]=n,l[7]=a,l[8]=c,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){let t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],this}extractBasis(e,t,n){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(e){let t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){let n=e.elements,r=t.elements,i=this.elements,a=n[0],o=n[3],s=n[6],c=n[1],l=n[4],u=n[7],d=n[2],f=n[5],p=n[8],m=r[0],h=r[3],g=r[6],_=r[1],v=r[4],y=r[7],b=r[2],x=r[5],S=r[8];return i[0]=a*m+o*_+s*b,i[3]=a*h+o*v+s*x,i[6]=a*g+o*y+s*S,i[1]=c*m+l*_+u*b,i[4]=c*h+l*v+u*x,i[7]=c*g+l*y+u*S,i[2]=d*m+f*_+p*b,i[5]=d*h+f*v+p*x,i[8]=d*g+f*y+p*S,this}multiplyScalar(e){let t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){let e=this.elements,t=e[0],n=e[1],r=e[2],i=e[3],a=e[4],o=e[5],s=e[6],c=e[7],l=e[8];return t*a*l-t*o*c-n*i*l+n*o*s+r*i*c-r*a*s}invert(){let e=this.elements,t=e[0],n=e[1],r=e[2],i=e[3],a=e[4],o=e[5],s=e[6],c=e[7],l=e[8],u=l*a-o*c,d=o*s-l*i,f=c*i-a*s,p=t*u+n*d+r*f;if(p===0)return this.set(0,0,0,0,0,0,0,0,0);let m=1/p;return e[0]=u*m,e[1]=(r*c-l*n)*m,e[2]=(o*n-r*a)*m,e[3]=d*m,e[4]=(l*t-r*s)*m,e[5]=(r*i-o*t)*m,e[6]=f*m,e[7]=(n*s-c*t)*m,e[8]=(a*t-n*i)*m,this}transpose(){let e,t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){let t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,n,r,i,a,o){let s=Math.cos(i),c=Math.sin(i);return this.set(n*s,n*c,-n*(s*a+c*o)+a+e,-r*c,r*s,-r*(-c*a+s*o)+o+t,0,0,1),this}scale(e,t){return this.premultiply(Qt.makeScale(e,t)),this}rotate(e){return this.premultiply(Qt.makeRotation(-e)),this}translate(e,t){return this.premultiply(Qt.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){let t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,n,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){let t=this.elements,n=e.elements;for(let e=0;e<9;e++)if(t[e]!==n[e])return!1;return!0}fromArray(e,t=0){for(let n=0;n<9;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){let n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e}clone(){return new this.constructor().fromArray(this.elements)}},Qt=new J,$t=new J().set(.4123908,.3575843,.1804808,.212639,.7151687,.0721923,.0193308,.1191948,.9505322),en=new J().set(3.2409699,-1.5373832,-.4986108,-.9692436,1.8759675,.0415551,.0556301,-.203977,1.0569715);function tn(){let e={enabled:!0,workingColorSpace:ot,spaces:{},convert:function(e,t,n){return this.enabled===!1||t===n||!t||!n?e:(this.spaces[t].transfer===`srgb`&&(e.r=nn(e.r),e.g=nn(e.g),e.b=nn(e.b)),this.spaces[t].primaries!==this.spaces[n].primaries&&(e.applyMatrix3(this.spaces[t].toXYZ),e.applyMatrix3(this.spaces[n].fromXYZ)),this.spaces[n].transfer===`srgb`&&(e.r=rn(e.r),e.g=rn(e.g),e.b=rn(e.b)),e)},workingToColorSpace:function(e,t){return this.convert(e,this.workingColorSpace,t)},colorSpaceToWorking:function(e,t){return this.convert(e,t,this.workingColorSpace)},getPrimaries:function(e){return this.spaces[e].primaries},getTransfer:function(e){return e===``?st:this.spaces[e].transfer},getToneMappingMode:function(e){return this.spaces[e].outputColorSpaceConfig.toneMappingMode||`standard`},getLuminanceCoefficients:function(e,t=this.workingColorSpace){return e.fromArray(this.spaces[t].luminanceCoefficients)},define:function(e){Object.assign(this.spaces,e)},_getMatrix:function(e,t,n){return e.copy(this.spaces[t].toXYZ).multiply(this.spaces[n].fromXYZ)},_getDrawingBufferColorSpace:function(e){return this.spaces[e].outputColorSpaceConfig.drawingBufferColorSpace},_getUnpackColorSpace:function(e=this.workingColorSpace){return this.spaces[e].workingColorSpaceConfig.unpackColorSpace},fromWorkingColorSpace:function(t,n){return bt(`ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace().`),e.workingToColorSpace(t,n)},toWorkingColorSpace:function(t,n){return bt(`ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking().`),e.colorSpaceToWorking(t,n)}},t=[.64,.33,.3,.6,.15,.06],n=[.2126,.7152,.0722],r=[.3127,.329];return e.define({[ot]:{primaries:t,whitePoint:r,transfer:st,toXYZ:$t,fromXYZ:en,luminanceCoefficients:n,workingColorSpaceConfig:{unpackColorSpace:at},outputColorSpaceConfig:{drawingBufferColorSpace:at}},[at]:{primaries:t,whitePoint:r,transfer:ct,toXYZ:$t,fromXYZ:en,luminanceCoefficients:n,outputColorSpaceConfig:{drawingBufferColorSpace:at}}}),e}var Y=tn();function nn(e){return e<.04045?e*.0773993808:(e*.9478672986+.0521327014)**2.4}function rn(e){return e<.0031308?e*12.92:1.055*e**.41666-.055}var an,on=class{static getDataURL(e,t=`image/png`){if(/^data:/i.test(e.src)||typeof HTMLCanvasElement>`u`)return e.src;let n;if(e instanceof HTMLCanvasElement)n=e;else{an===void 0&&(an=mt(`canvas`)),an.width=e.width,an.height=e.height;let t=an.getContext(`2d`);e instanceof ImageData?t.putImageData(e,0,0):t.drawImage(e,0,0,e.width,e.height),n=an}return n.toDataURL(t)}static sRGBToLinear(e){if(typeof HTMLImageElement<`u`&&e instanceof HTMLImageElement||typeof HTMLCanvasElement<`u`&&e instanceof HTMLCanvasElement||typeof ImageBitmap<`u`&&e instanceof ImageBitmap){let t=mt(`canvas`);t.width=e.width,t.height=e.height;let n=t.getContext(`2d`);n.drawImage(e,0,0,e.width,e.height);let r=n.getImageData(0,0,e.width,e.height),i=r.data;for(let e=0;e1),this.pmremVersion=0,this.normalized=!1}get width(){return this.source.getSize(dn).x}get height(){return this.source.getSize(dn).y}get depth(){return this.source.getSize(dn).z}get image(){return this.source.data}set image(e){this.source.data=e}updateMatrix(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}clone(){return new this.constructor().copy(this)}copy(e){return this.name=e.name,this.source=e.source,this.mipmaps=e.mipmaps.slice(0),this.mapping=e.mapping,this.channel=e.channel,this.wrapS=e.wrapS,this.wrapT=e.wrapT,this.magFilter=e.magFilter,this.minFilter=e.minFilter,this.anisotropy=e.anisotropy,this.format=e.format,this.internalFormat=e.internalFormat,this.type=e.type,this.normalized=e.normalized,this.offset.copy(e.offset),this.repeat.copy(e.repeat),this.center.copy(e.center),this.rotation=e.rotation,this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrix.copy(e.matrix),this.generateMipmaps=e.generateMipmaps,this.premultiplyAlpha=e.premultiplyAlpha,this.flipY=e.flipY,this.unpackAlignment=e.unpackAlignment,this.colorSpace=e.colorSpace,this.renderTarget=e.renderTarget,this.isRenderTargetTexture=e.isRenderTargetTexture,this.isArrayTexture=e.isArrayTexture,this.userData=JSON.parse(JSON.stringify(e.userData)),this.needsUpdate=!0,this}setValues(e){for(let t in e){let n=e[t];if(n===void 0){H(`Texture.setValues(): parameter '${t}' has value of undefined.`);continue}let r=this[t];if(r===void 0){H(`Texture.setValues(): property '${t}' does not exist.`);continue}r&&n&&r.isVector2&&n.isVector2||r&&n&&r.isVector3&&n.isVector3||r&&n&&r.isMatrix3&&n.isMatrix3?r.copy(n):this[t]=n}}toJSON(e){let t=e===void 0||typeof e==`string`;if(!t&&e.textures[this.uuid]!==void 0)return e.textures[this.uuid];let n={metadata:{version:4.7,type:`Texture`,generator:`Texture.toJSON`},uuid:this.uuid,name:this.name,image:this.source.toJSON(e).uuid,mapping:this.mapping,channel:this.channel,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,internalFormat:this.internalFormat,type:this.type,normalized:this.normalized,colorSpace:this.colorSpace,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,generateMipmaps:this.generateMipmaps,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};return Object.keys(this.userData).length>0&&(n.userData=this.userData),t||(e.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:`dispose`})}transformUv(e){if(this.mapping!==300)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case T:e.x-=Math.floor(e.x);break;case E:e.x=e.x<0?0:1;break;case D:Math.abs(Math.floor(e.x)%2)===1?e.x=Math.ceil(e.x)-e.x:e.x-=Math.floor(e.x);break}if(e.y<0||e.y>1)switch(this.wrapT){case T:e.y-=Math.floor(e.y);break;case E:e.y=e.y<0?0:1;break;case D:Math.abs(Math.floor(e.y)%2)===1?e.y=Math.ceil(e.y)-e.y:e.y-=Math.floor(e.y);break}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){e===!0&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){e===!0&&this.pmremVersion++}};fn.DEFAULT_IMAGE=null,fn.DEFAULT_MAPPING=300,fn.DEFAULT_ANISOTROPY=1;var pn=class e{static{e.prototype.isVector4=!0}constructor(e=0,t=0,n=0,r=1){this.x=e,this.y=t,this.z=n,this.w=r}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,n,r){return this.x=e,this.y=t,this.z=n,this.w=r,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw Error(`index is out of range: `+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw Error(`index is out of range: `+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=e.w===void 0?1:e.w,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){let t=this.x,n=this.y,r=this.z,i=this.w,a=e.elements;return this.x=a[0]*t+a[4]*n+a[8]*r+a[12]*i,this.y=a[1]*t+a[5]*n+a[9]*r+a[13]*i,this.z=a[2]*t+a[6]*n+a[10]*r+a[14]*i,this.w=a[3]*t+a[7]*n+a[11]*r+a[15]*i,this}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this.w/=e.w,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);let t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,n,r,i,a=.01,o=.1,s=e.elements,c=s[0],l=s[4],u=s[8],d=s[1],f=s[5],p=s[9],m=s[2],h=s[6],g=s[10];if(Math.abs(l-d)s&&e>_?e _?s 1);this.dispose()}this.viewport.set(0,0,e,t),this.scissor.set(0,0,e,t)}clone(){return new this.constructor().copy(this)}copy(e){this.width=e.width,this.height=e.height,this.depth=e.depth,this.scissor.copy(e.scissor),this.scissorTest=e.scissorTest,this.viewport.copy(e.viewport),this.textures.length=0;for(let t=0,n=e.textures.length;t>>0}enable(e){this.mask|=1<1){for(let e=0;e1){for(let e=0;e0&&(r.userData=this.userData),r.layers=this.layers.mask,r.matrix=this.matrix.toArray(),r.up=this.up.toArray(),this.pivot!==null&&(r.pivot=this.pivot.toArray()),this.matrixAutoUpdate===!1&&(r.matrixAutoUpdate=!1),this.morphTargetDictionary!==void 0&&(r.morphTargetDictionary=Object.assign({},this.morphTargetDictionary)),this.morphTargetInfluences!==void 0&&(r.morphTargetInfluences=this.morphTargetInfluences.slice()),this.isInstancedMesh&&(r.type=`InstancedMesh`,r.count=this.count,r.instanceMatrix=this.instanceMatrix.toJSON(),this.instanceColor!==null&&(r.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(r.type=`BatchedMesh`,r.perObjectFrustumCulled=this.perObjectFrustumCulled,r.sortObjects=this.sortObjects,r.drawRanges=this._drawRanges,r.reservedRanges=this._reservedRanges,r.geometryInfo=this._geometryInfo.map(e=>({...e,boundingBox:e.boundingBox?e.boundingBox.toJSON():void 0,boundingSphere:e.boundingSphere?e.boundingSphere.toJSON():void 0})),r.instanceInfo=this._instanceInfo.map(e=>({...e})),r.availableInstanceIds=this._availableInstanceIds.slice(),r.availableGeometryIds=this._availableGeometryIds.slice(),r.nextIndexStart=this._nextIndexStart,r.nextVertexStart=this._nextVertexStart,r.geometryCount=this._geometryCount,r.maxInstanceCount=this._maxInstanceCount,r.maxVertexCount=this._maxVertexCount,r.maxIndexCount=this._maxIndexCount,r.geometryInitialized=this._geometryInitialized,r.matricesTexture=this._matricesTexture.toJSON(e),r.indirectTexture=this._indirectTexture.toJSON(e),this._colorsTexture!==null&&(r.colorsTexture=this._colorsTexture.toJSON(e)),this.boundingSphere!==null&&(r.boundingSphere=this.boundingSphere.toJSON()),this.boundingBox!==null&&(r.boundingBox=this.boundingBox.toJSON()));function i(t,n){return t[n.uuid]===void 0&&(t[n.uuid]=n.toJSON(e)),n.uuid}if(this.isScene)this.background&&(this.background.isColor?r.background=this.background.toJSON():this.background.isTexture&&(r.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&this.environment.isRenderTargetTexture!==!0&&(r.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){r.geometry=i(e.geometries,this.geometry);let t=this.geometry.parameters;if(t!==void 0&&t.shapes!==void 0){let n=t.shapes;if(Array.isArray(n))for(let t=0,r=n.length;t0){r.children=[];for(let t=0;t0){r.animations=[];for(let t=0;t0&&(n.geometries=t),r.length>0&&(n.materials=r),i.length>0&&(n.textures=i),o.length>0&&(n.images=o),s.length>0&&(n.shapes=s),c.length>0&&(n.skeletons=c),l.length>0&&(n.animations=l),u.length>0&&(n.nodes=u)}return n.object=r,n;function a(e){let t=[];for(let n in e){let r=e[n];delete r.metadata,t.push(r)}return t}}clone(e){return new this.constructor().copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.pivot=e.pivot===null?null:e.pivot.clone(),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.static=e.static,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),t===!0)for(let t=0;ts+l?(c.inputState.pinching=!1,this.dispatchEvent({type:`pinchend`,handedness:e.handedness,target:this})):!c.inputState.pinching&&o<=s-l&&(c.inputState.pinching=!0,this.dispatchEvent({type:`pinchstart`,handedness:e.handedness,target:this}))}else s!==null&&e.gripSpace&&(i=t.getPose(e.gripSpace,n),i!==null&&(s.matrix.fromArray(i.transform.matrix),s.matrix.decompose(s.position,s.rotation,s.scale),s.matrixWorldNeedsUpdate=!0,i.linearVelocity?(s.hasLinearVelocity=!0,s.linearVelocity.copy(i.linearVelocity)):s.hasLinearVelocity=!1,i.angularVelocity?(s.hasAngularVelocity=!0,s.angularVelocity.copy(i.angularVelocity)):s.hasAngularVelocity=!1,s.eventsEnabled&&s.dispatchEvent({type:`gripUpdated`,data:e,target:this})));o!==null&&(r=t.getPose(e.targetRaySpace,n),r===null&&i!==null&&(r=i),r!==null&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1,this.dispatchEvent(qn)))}return o!==null&&(o.visible=r!==null),s!==null&&(s.visible=i!==null),c!==null&&(c.visible=a!==null),this}_getHandJoint(e,t){if(e.joints[t.jointName]===void 0){let n=new Kn;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}},Yn={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Xn={h:0,s:0,l:0},Zn={h:0,s:0,l:0};function Qn(e,t,n){return n<0&&(n+=1),n>1&&--n,n<1/6?e+(t-e)*6*n:n<1/2?t:n<2/3?e+(t-e)*6*(2/3-n):e}var X=class{constructor(e,t,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,n)}set(e,t,n){if(t===void 0&&n===void 0){let t=e;t&&t.isColor?this.copy(t):typeof t==`number`?this.setHex(t):typeof t==`string`&&this.setStyle(t)}else this.setRGB(e,t,n);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t=at){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(e&255)/255,Y.colorSpaceToWorking(this,t),this}setRGB(e,t,n,r=Y.workingColorSpace){return this.r=e,this.g=t,this.b=n,Y.colorSpaceToWorking(this,r),this}setHSL(e,t,n,r=Y.workingColorSpace){if(e=kt(e,1),t=W(t,0,1),n=W(n,0,1),t===0)this.r=this.g=this.b=n;else{let r=n<=.5?n*(1+t):n+t-n*t,i=2*n-r;this.r=Qn(i,r,e+1/3),this.g=Qn(i,r,e),this.b=Qn(i,r,e-1/3)}return Y.colorSpaceToWorking(this,r),this}setStyle(e,t=at){function n(t){t!==void 0&&parseFloat(t)<1&&H(`Color: Alpha component of `+e+` will be ignored.`)}let r;if(r=/^(\w+)\(([^\)]*)\)/.exec(e)){let i,a=r[1],o=r[2];switch(a){case`rgb`:case`rgba`:if(i=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(i[4]),this.setRGB(Math.min(255,parseInt(i[1],10))/255,Math.min(255,parseInt(i[2],10))/255,Math.min(255,parseInt(i[3],10))/255,t);if(i=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(i[4]),this.setRGB(Math.min(100,parseInt(i[1],10))/100,Math.min(100,parseInt(i[2],10))/100,Math.min(100,parseInt(i[3],10))/100,t);break;case`hsl`:case`hsla`:if(i=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(i[4]),this.setHSL(parseFloat(i[1])/360,parseFloat(i[2])/100,parseFloat(i[3])/100,t);break;default:H(`Color: Unknown color model `+e)}}else if(r=/^\#([A-Fa-f\d]+)$/.exec(e)){let n=r[1],i=n.length;if(i===3)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,t);if(i===6)return this.setHex(parseInt(n,16),t);H(`Color: Invalid hex color `+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t=at){let n=Yn[e.toLowerCase()];return n===void 0?H(`Color: Unknown color `+e):this.setHex(n,t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=nn(e.r),this.g=nn(e.g),this.b=nn(e.b),this}copyLinearToSRGB(e){return this.r=rn(e.r),this.g=rn(e.g),this.b=rn(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e=at){return Y.workingToColorSpace($n.copy(this),e),Math.round(W($n.r*255,0,255))*65536+Math.round(W($n.g*255,0,255))*256+Math.round(W($n.b*255,0,255))}getHexString(e=at){return(`000000`+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=Y.workingColorSpace){Y.workingToColorSpace($n.copy(this),t);let n=$n.r,r=$n.g,i=$n.b,a=Math.max(n,r,i),o=Math.min(n,r,i),s,c,l=(o+a)/2;if(o===a)s=0,c=0;else{let e=a-o;switch(c=l<=.5?e/(a+o):e/(2-a-o),a){case n:s=(r-i)/e+(r0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),this.backgroundIntensity!==1&&(t.object.backgroundIntensity=this.backgroundIntensity),t.object.backgroundRotation=this.backgroundRotation.toArray(),this.environmentIntensity!==1&&(t.object.environmentIntensity=this.environmentIntensity),t.object.environmentRotation=this.environmentRotation.toArray(),t}},tr=new q,nr=new q,rr=new q,ir=new q,ar=new q,or=new q,sr=new q,cr=new q,lr=new q,ur=new q,dr=new pn,fr=new pn,pr=new pn,mr=class e{constructor(e=new q,t=new q,n=new q){this.a=e,this.b=t,this.c=n}static getNormal(e,t,n,r){r.subVectors(n,t),tr.subVectors(e,t),r.cross(tr);let i=r.lengthSq();return i>0?r.multiplyScalar(1/Math.sqrt(i)):r.set(0,0,0)}static getBarycoord(e,t,n,r,i){tr.subVectors(r,t),nr.subVectors(n,t),rr.subVectors(e,t);let a=tr.dot(tr),o=tr.dot(nr),s=tr.dot(rr),c=nr.dot(nr),l=nr.dot(rr),u=a*c-o*o;if(u===0)return i.set(0,0,0),null;let d=1/u,f=(c*s-o*l)*d,p=(a*l-o*s)*d;return i.set(1-f-p,p,f)}static containsPoint(e,t,n,r){return this.getBarycoord(e,t,n,r,ir)===null?!1:ir.x>=0&&ir.y>=0&&ir.x+ir.y<=1}static getInterpolation(e,t,n,r,i,a,o,s){return this.getBarycoord(e,t,n,r,ir)===null?(s.x=0,s.y=0,`z`in s&&(s.z=0),`w`in s&&(s.w=0),null):(s.setScalar(0),s.addScaledVector(i,ir.x),s.addScaledVector(a,ir.y),s.addScaledVector(o,ir.z),s)}static getInterpolatedAttribute(e,t,n,r,i,a){return dr.setScalar(0),fr.setScalar(0),pr.setScalar(0),dr.fromBufferAttribute(e,t),fr.fromBufferAttribute(e,n),pr.fromBufferAttribute(e,r),a.setScalar(0),a.addScaledVector(dr,i.x),a.addScaledVector(fr,i.y),a.addScaledVector(pr,i.z),a}static isFrontFacing(e,t,n,r){return tr.subVectors(n,t),nr.subVectors(e,t),tr.cross(nr).dot(r)<0}set(e,t,n){return this.a.copy(e),this.b.copy(t),this.c.copy(n),this}setFromPointsAndIndices(e,t,n,r){return this.a.copy(e[t]),this.b.copy(e[n]),this.c.copy(e[r]),this}setFromAttributeAndIndices(e,t,n,r){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,n),this.c.fromBufferAttribute(e,r),this}clone(){return new this.constructor().copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return tr.subVectors(this.c,this.b),nr.subVectors(this.a,this.b),tr.cross(nr).length()*.5}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return e.getNormal(this.a,this.b,this.c,t)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,n){return e.getBarycoord(t,this.a,this.b,this.c,n)}getInterpolation(t,n,r,i,a){return e.getInterpolation(t,this.a,this.b,this.c,n,r,i,a)}containsPoint(t){return e.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return e.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){let n=this.a,r=this.b,i=this.c,a,o;ar.subVectors(r,n),or.subVectors(i,n),cr.subVectors(e,n);let s=ar.dot(cr),c=or.dot(cr);if(s<=0&&c<=0)return t.copy(n);lr.subVectors(e,r);let l=ar.dot(lr),u=or.dot(lr);if(l>=0&&u<=l)return t.copy(r);let d=s*u-l*c;if(d<=0&&s>=0&&l<=0)return a=s/(s-l),t.copy(n).addScaledVector(ar,a);ur.subVectors(e,i);let f=ar.dot(ur),p=or.dot(ur);if(p>=0&&f<=p)return t.copy(i);let m=f*c-s*p;if(m<=0&&c>=0&&p<=0)return o=c/(c-p),t.copy(n).addScaledVector(or,o);let h=l*p-f*u;if(h<=0&&u-l>=0&&f-p>=0)return sr.subVectors(i,r),o=(u-l)/(u-l+(f-p)),t.copy(r).addScaledVector(sr,o);let g=1/(h+m+d);return a=m*g,o=d*g,t.copy(n).addScaledVector(ar,a).addScaledVector(or,o)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}},hr=class{constructor(e=new q(1/0,1/0,1/0),t=new q(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,n=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,_r),_r.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,n;return e.normal.x>0?(t=e.normal.x*this.min.x,n=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,n=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,n+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,n+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,n+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,n+=e.normal.z*this.min.z),t<=-e.constant&&n>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(Tr),Er.subVectors(this.max,Tr),yr.subVectors(e.a,Tr),br.subVectors(e.b,Tr),xr.subVectors(e.c,Tr),Sr.subVectors(br,yr),Cr.subVectors(xr,br),wr.subVectors(yr,xr);let t=[0,-Sr.z,Sr.y,0,-Cr.z,Cr.y,0,-wr.z,wr.y,Sr.z,0,-Sr.x,Cr.z,0,-Cr.x,wr.z,0,-wr.x,-Sr.y,Sr.x,0,-Cr.y,Cr.x,0,-wr.y,wr.x,0];return!kr(t,yr,br,xr,Er)||(t=[1,0,0,0,1,0,0,0,1],!kr(t,yr,br,xr,Er))?!1:(Dr.crossVectors(Sr,Cr),t=[Dr.x,Dr.y,Dr.z],kr(t,yr,br,xr,Er))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,_r).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=this.getSize(_r).length()*.5),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()?this:(gr[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),gr[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),gr[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),gr[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),gr[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),gr[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),gr[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),gr[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(gr),this)}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}toJSON(){return{min:this.min.toArray(),max:this.max.toArray()}}fromJSON(e){return this.min.fromArray(e.min),this.max.fromArray(e.max),this}},gr=[new q,new q,new q,new q,new q,new q,new q,new q],_r=new q,vr=new hr,yr=new q,br=new q,xr=new q,Sr=new q,Cr=new q,wr=new q,Tr=new q,Er=new q,Dr=new q,Or=new q;function kr(e,t,n,r,i){for(let a=0,o=e.length-3;a<=o;a+=3){Or.fromArray(e,a);let o=i.x*Math.abs(Or.x)+i.y*Math.abs(Or.y)+i.z*Math.abs(Or.z),s=t.dot(Or),c=n.dot(Or),l=r.dot(Or);if(Math.max(-Math.max(s,c,l),Math.min(s,c,l))>o)return!1}return!0}var Ar=new q,jr=new K,Mr=0,Nr=class extends Ct{constructor(e,t,n=!1){if(super(),Array.isArray(e))throw TypeError(`THREE.BufferAttribute: array should be a Typed Array.`);this.isBufferAttribute=!0,Object.defineProperty(this,`id`,{value:Mr++}),this.name=``,this.array=e,this.itemSize=t,this.count=e===void 0?0:e.length/t,this.normalized=n,this.usage=ut,this.updateRanges=[],this.gpuType=ae,this.version=0}onUploadCallback(){}set needsUpdate(e){e===!0&&this.version++}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,n){e*=this.itemSize,n*=t.itemSize;for(let r=0,i=this.itemSize;rthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius*=e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;Rr.subVectors(e,this.center);let t=Rr.lengthSq();if(t>this.radius*this.radius){let e=Math.sqrt(t),n=(e-this.radius)*.5;this.center.addScaledVector(Rr,n/e),this.radius+=n}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(this.center.equals(e.center)===!0?this.radius=Math.max(this.radius,e.radius):(zr.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(Rr.copy(e.center).add(zr)),this.expandByPoint(Rr.copy(e.center).sub(zr))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return new this.constructor().copy(this)}toJSON(){return{radius:this.radius,center:this.center.toArray()}}fromJSON(e){return this.radius=e.radius,this.center.fromArray(e.center),this}},Vr=0,Hr=new vn,Ur=new Gn,Wr=new q,Gr=new hr,Kr=new hr,qr=new q,Jr=class e extends Ct{constructor(){super(),this.isBufferGeometry=!0,Object.defineProperty(this,`id`,{value:Vr++}),this.uuid=Ot(),this.name=``,this.type=`BufferGeometry`,this.index=null,this.indirect=null,this.indirectOffset=0,this.attributes={},this.morphAttributes={},this.morphTargetsRelative=!1,this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.drawRange={start:0,count:1/0},this.userData={}}getIndex(){return this.index}setIndex(e){return Array.isArray(e)?this.index=new(ft(e)?Fr:Pr)(e,1):this.index=e,this}setIndirect(e,t=0){return this.indirect=e,this.indirectOffset=t,this}getIndirect(){return this.indirect}getAttribute(e){return this.attributes[e]}setAttribute(e,t){return this.attributes[e]=t,this}deleteAttribute(e){return delete this.attributes[e],this}hasAttribute(e){return this.attributes[e]!==void 0}addGroup(e,t,n=0){this.groups.push({start:e,count:t,materialIndex:n})}clearGroups(){this.groups=[]}setDrawRange(e,t){this.drawRange.start=e,this.drawRange.count=t}applyMatrix4(e){let t=this.attributes.position;t!==void 0&&(t.applyMatrix4(e),t.needsUpdate=!0);let n=this.attributes.normal;if(n!==void 0){let t=new J().getNormalMatrix(e);n.applyNormalMatrix(t),n.needsUpdate=!0}let r=this.attributes.tangent;return r!==void 0&&(r.transformDirection(e),r.needsUpdate=!0),this.boundingBox!==null&&this.computeBoundingBox(),this.boundingSphere!==null&&this.computeBoundingSphere(),this}applyQuaternion(e){return Hr.makeRotationFromQuaternion(e),this.applyMatrix4(Hr),this}rotateX(e){return Hr.makeRotationX(e),this.applyMatrix4(Hr),this}rotateY(e){return Hr.makeRotationY(e),this.applyMatrix4(Hr),this}rotateZ(e){return Hr.makeRotationZ(e),this.applyMatrix4(Hr),this}translate(e,t,n){return Hr.makeTranslation(e,t,n),this.applyMatrix4(Hr),this}scale(e,t,n){return Hr.makeScale(e,t,n),this.applyMatrix4(Hr),this}lookAt(e){return Ur.lookAt(e),Ur.updateMatrix(),this.applyMatrix4(Ur.matrix),this}center(){return this.computeBoundingBox(),this.boundingBox.getCenter(Wr).negate(),this.translate(Wr.x,Wr.y,Wr.z),this}setFromPoints(e){let t=this.getAttribute(`position`);if(t===void 0){let t=[];for(let n=0,r=e.length;nt.count&&H(`BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry.`),t.needsUpdate=!0}return this}computeBoundingBox(){this.boundingBox===null&&(this.boundingBox=new hr);let e=this.attributes.position,t=this.morphAttributes.position;if(e&&e.isGLBufferAttribute){U(`BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.`,this),this.boundingBox.set(new q(-1/0,-1/0,-1/0),new q(1/0,1/0,1/0));return}if(e!==void 0){if(this.boundingBox.setFromBufferAttribute(e),t)for(let e=0,n=t.length;e0&&(e.userData=this.userData),this.parameters!==void 0){let t=this.parameters;for(let n in t)t[n]!==void 0&&(e[n]=t[n]);return e}e.data={attributes:{}};let t=this.index;t!==null&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});let n=this.attributes;for(let t in n){let r=n[t];e.data.attributes[t]=r.toJSON(e.data)}let r={},i=!1;for(let t in this.morphAttributes){let n=this.morphAttributes[t],a=[];for(let t=0,r=n.length;t0&&(r[t]=a,i=!0)}i&&(e.data.morphAttributes=r,e.data.morphTargetsRelative=this.morphTargetsRelative);let a=this.groups;a.length>0&&(e.data.groups=JSON.parse(JSON.stringify(a)));let o=this.boundingSphere;return o!==null&&(e.data.boundingSphere=o.toJSON()),e}clone(){return new this.constructor().copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;let t={};this.name=e.name;let n=e.index;n!==null&&this.setIndex(n.clone());let r=e.attributes;for(let e in r){let n=r[e];this.setAttribute(e,n.clone(t))}let i=e.morphAttributes;for(let e in i){let n=[],r=i[e];for(let e=0,i=r.length;e0!=e>0&&this.version++,this._alphaTest=e}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(e!==void 0)for(let t in e){let n=e[t];if(n===void 0){H(`Material: parameter '${t}' has value of undefined.`);continue}let r=this[t];if(r===void 0){H(`Material: '${t}' is not a property of THREE.${this.type}.`);continue}r&&r.isColor?r.set(n):r&&r.isVector3&&n&&n.isVector3?r.copy(n):this[t]=n}}toJSON(e){let t=e===void 0||typeof e==`string`;t&&(e={textures:{},images:{}});let n={metadata:{version:4.7,type:`Material`,generator:`Material.toJSON`}};n.uuid=this.uuid,n.type=this.type,this.name!==``&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),this.roughness!==void 0&&(n.roughness=this.roughness),this.metalness!==void 0&&(n.metalness=this.metalness),this.sheen!==void 0&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),this.sheenRoughness!==void 0&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity!==void 0&&this.emissiveIntensity!==1&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),this.specularIntensity!==void 0&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),this.shininess!==void 0&&(n.shininess=this.shininess),this.clearcoat!==void 0&&(n.clearcoat=this.clearcoat),this.clearcoatRoughness!==void 0&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),this.sheenColorMap&&this.sheenColorMap.isTexture&&(n.sheenColorMap=this.sheenColorMap.toJSON(e).uuid),this.sheenRoughnessMap&&this.sheenRoughnessMap.isTexture&&(n.sheenRoughnessMap=this.sheenRoughnessMap.toJSON(e).uuid),this.dispersion!==void 0&&(n.dispersion=this.dispersion),this.iridescence!==void 0&&(n.iridescence=this.iridescence),this.iridescenceIOR!==void 0&&(n.iridescenceIOR=this.iridescenceIOR),this.iridescenceThicknessRange!==void 0&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),this.anisotropy!==void 0&&(n.anisotropy=this.anisotropy),this.anisotropyRotation!==void 0&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(e).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(e).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(e).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(e).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(e).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(e).uuid,this.combine!==void 0&&(n.combine=this.combine)),this.envMapRotation!==void 0&&(n.envMapRotation=this.envMapRotation.toArray()),this.envMapIntensity!==void 0&&(n.envMapIntensity=this.envMapIntensity),this.reflectivity!==void 0&&(n.reflectivity=this.reflectivity),this.refractionRatio!==void 0&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(e).uuid),this.transmission!==void 0&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(e).uuid),this.thickness!==void 0&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(e).uuid),this.attenuationDistance!==void 0&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),this.attenuationColor!==void 0&&(n.attenuationColor=this.attenuationColor.getHex()),this.size!==void 0&&(n.size=this.size),this.shadowSide!==null&&(n.shadowSide=this.shadowSide),this.sizeAttenuation!==void 0&&(n.sizeAttenuation=this.sizeAttenuation),this.blending!==1&&(n.blending=this.blending),this.side!==0&&(n.side=this.side),this.vertexColors===!0&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),this.transparent===!0&&(n.transparent=!0),this.blendSrc!==204&&(n.blendSrc=this.blendSrc),this.blendDst!==205&&(n.blendDst=this.blendDst),this.blendEquation!==100&&(n.blendEquation=this.blendEquation),this.blendSrcAlpha!==null&&(n.blendSrcAlpha=this.blendSrcAlpha),this.blendDstAlpha!==null&&(n.blendDstAlpha=this.blendDstAlpha),this.blendEquationAlpha!==null&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),this.blendAlpha!==0&&(n.blendAlpha=this.blendAlpha),this.depthFunc!==3&&(n.depthFunc=this.depthFunc),this.depthTest===!1&&(n.depthTest=this.depthTest),this.depthWrite===!1&&(n.depthWrite=this.depthWrite),this.colorWrite===!1&&(n.colorWrite=this.colorWrite),this.stencilWriteMask!==255&&(n.stencilWriteMask=this.stencilWriteMask),this.stencilFunc!==519&&(n.stencilFunc=this.stencilFunc),this.stencilRef!==0&&(n.stencilRef=this.stencilRef),this.stencilFuncMask!==255&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==7680&&(n.stencilFail=this.stencilFail),this.stencilZFail!==7680&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==7680&&(n.stencilZPass=this.stencilZPass),this.stencilWrite===!0&&(n.stencilWrite=this.stencilWrite),this.rotation!==void 0&&this.rotation!==0&&(n.rotation=this.rotation),this.polygonOffset===!0&&(n.polygonOffset=!0),this.polygonOffsetFactor!==0&&(n.polygonOffsetFactor=this.polygonOffsetFactor),this.polygonOffsetUnits!==0&&(n.polygonOffsetUnits=this.polygonOffsetUnits),this.linewidth!==void 0&&this.linewidth!==1&&(n.linewidth=this.linewidth),this.dashSize!==void 0&&(n.dashSize=this.dashSize),this.gapSize!==void 0&&(n.gapSize=this.gapSize),this.scale!==void 0&&(n.scale=this.scale),this.dithering===!0&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),this.alphaHash===!0&&(n.alphaHash=!0),this.alphaToCoverage===!0&&(n.alphaToCoverage=!0),this.premultipliedAlpha===!0&&(n.premultipliedAlpha=!0),this.forceSinglePass===!0&&(n.forceSinglePass=!0),this.allowOverride===!1&&(n.allowOverride=!1),this.wireframe===!0&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),this.wireframeLinecap!==`round`&&(n.wireframeLinecap=this.wireframeLinecap),this.wireframeLinejoin!==`round`&&(n.wireframeLinejoin=this.wireframeLinejoin),this.flatShading===!0&&(n.flatShading=!0),this.visible===!1&&(n.visible=!1),this.toneMapped===!1&&(n.toneMapped=!1),this.fog===!1&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData);function r(e){let t=[];for(let n in e){let r=e[n];delete r.metadata,t.push(r)}return t}if(t){let t=r(e.textures),i=r(e.images);t.length>0&&(n.textures=t),i.length>0&&(n.images=i)}return n}clone(){return new this.constructor().copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;let t=e.clippingPlanes,n=null;if(t!==null){let e=t.length;n=Array(e);for(let r=0;r!==e;++r)n[r]=t[r].clone()}return this.clippingPlanes=n,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.allowOverride=e.allowOverride,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:`dispose`})}set needsUpdate(e){e===!0&&this.version++}},ei=class extends $r{constructor(e){super(),this.isSpriteMaterial=!0,this.type=`SpriteMaterial`,this.color=new X(16777215),this.map=null,this.alphaMap=null,this.rotation=0,this.sizeAttenuation=!0,this.transparent=!0,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.alphaMap=e.alphaMap,this.rotation=e.rotation,this.sizeAttenuation=e.sizeAttenuation,this.fog=e.fog,this}},ti,ni=new q,ri=new q,ii=new q,ai=new K,oi=new K,si=new vn,ci=new q,li=new q,ui=new q,di=new K,fi=new K,pi=new K,mi=class extends Gn{constructor(e=new ei){if(super(),this.isSprite=!0,this.type=`Sprite`,ti===void 0){ti=new Jr;let e=new Yr(new Float32Array([-.5,-.5,0,0,0,.5,-.5,0,1,0,.5,.5,0,1,1,-.5,.5,0,0,1]),5);ti.setIndex([0,1,2,0,2,3]),ti.setAttribute(`position`,new Zr(e,3,0,!1)),ti.setAttribute(`uv`,new Zr(e,2,3,!1))}this.geometry=ti,this.material=e,this.center=new K(.5,.5),this.count=1}raycast(e,t){e.camera===null&&U(`Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.`),ri.setFromMatrixScale(this.matrixWorld),si.copy(e.camera.matrixWorld),this.modelViewMatrix.multiplyMatrices(e.camera.matrixWorldInverse,this.matrixWorld),ii.setFromMatrixPosition(this.modelViewMatrix),e.camera.isPerspectiveCamera&&this.material.sizeAttenuation===!1&&ri.multiplyScalar(-ii.z);let n=this.material.rotation,r,i;n!==0&&(i=Math.cos(n),r=Math.sin(n));let a=this.center;hi(ci.set(-.5,-.5,0),ii,a,ri,r,i),hi(li.set(.5,-.5,0),ii,a,ri,r,i),hi(ui.set(.5,.5,0),ii,a,ri,r,i),di.set(0,0),fi.set(1,0),pi.set(1,1);let o=e.ray.intersectTriangle(ci,li,ui,!1,ni);if(o===null&&(hi(li.set(-.5,.5,0),ii,a,ri,r,i),fi.set(0,1),o=e.ray.intersectTriangle(ci,ui,li,!1,ni),o===null))return;let s=e.ray.origin.distanceTo(ni);se.far||t.push({distance:s,point:ni.clone(),uv:mr.getInterpolation(ni,ci,li,ui,di,fi,pi,new K),face:null,object:this})}copy(e,t){return super.copy(e,t),e.center!==void 0&&this.center.copy(e.center),this.material=e.material,this}};function hi(e,t,n,r,i,a){ai.subVectors(e,n).addScalar(.5).multiply(r),i===void 0?oi.copy(ai):(oi.x=a*ai.x-i*ai.y,oi.y=i*ai.x+a*ai.y),e.copy(t),e.x+=oi.x,e.y+=oi.y,e.applyMatrix4(si)}var gi=new q,_i=new q,vi=new q,yi=new q,bi=new q,xi=new q,Si=new q,Ci=class{constructor(e=new q,t=new q(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,gi)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);let n=t.dot(this.direction);return n<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){let t=gi.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(gi.copy(this.origin).addScaledVector(this.direction,t),gi.distanceToSquared(e))}distanceSqToSegment(e,t,n,r){_i.copy(e).add(t).multiplyScalar(.5),vi.copy(t).sub(e).normalize(),yi.copy(this.origin).sub(_i);let i=e.distanceTo(t)*.5,a=-this.direction.dot(vi),o=yi.dot(this.direction),s=-yi.dot(vi),c=yi.lengthSq(),l=Math.abs(1-a*a),u,d,f,p;if(l>0)if(u=a*s-o,d=a*o-s,p=i*l,u>=0)if(d>=-p)if(d<=p){let e=1/l;u*=e,d*=e,f=u*(u+a*d+2*o)+d*(a*u+d+2*s)+c}else d=i,u=Math.max(0,-(a*d+o)),f=-u*u+d*(d+2*s)+c;else d=-i,u=Math.max(0,-(a*d+o)),f=-u*u+d*(d+2*s)+c;else d<=-p?(u=Math.max(0,-(-a*i+o)),d=u>0?-i:Math.min(Math.max(-i,-s),i),f=-u*u+d*(d+2*s)+c):d<=p?(u=0,d=Math.min(Math.max(-i,-s),i),f=d*(d+2*s)+c):(u=Math.max(0,-(a*i+o)),d=u>0?i:Math.min(Math.max(-i,-s),i),f=-u*u+d*(d+2*s)+c);else d=a>0?-i:i,u=Math.max(0,-(a*d+o)),f=-u*u+d*(d+2*s)+c;return n&&n.copy(this.origin).addScaledVector(this.direction,u),r&&r.copy(_i).addScaledVector(vi,d),f}intersectSphere(e,t){gi.subVectors(e.center,this.origin);let n=gi.dot(this.direction),r=gi.dot(gi)-n*n,i=e.radius*e.radius;if(r>i)return null;let a=Math.sqrt(i-r),o=n-a,s=n+a;return s<0?null:o<0?this.at(s,t):this.at(o,t)}intersectsSphere(e){return e.radius<0?!1:this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){let t=e.normal.dot(this.direction);if(t===0)return e.distanceToPoint(this.origin)===0?0:null;let n=-(this.origin.dot(e.normal)+e.constant)/t;return n>=0?n:null}intersectPlane(e,t){let n=this.distanceToPlane(e);return n===null?null:this.at(n,t)}intersectsPlane(e){let t=e.distanceToPoint(this.origin);return t===0||e.normal.dot(this.direction)*t<0}intersectBox(e,t){let n,r,i,a,o,s,c=1/this.direction.x,l=1/this.direction.y,u=1/this.direction.z,d=this.origin;return c>=0?(n=(e.min.x-d.x)*c,r=(e.max.x-d.x)*c):(n=(e.max.x-d.x)*c,r=(e.min.x-d.x)*c),l>=0?(i=(e.min.y-d.y)*l,a=(e.max.y-d.y)*l):(i=(e.max.y-d.y)*l,a=(e.min.y-d.y)*l),n>a||i>r||((i>n||isNaN(n))&&(n=i),(a=0?(o=(e.min.z-d.z)*u,s=(e.max.z-d.z)*u):(o=(e.max.z-d.z)*u,s=(e.min.z-d.z)*u),n>s||o>r)||((o>n||n!==n)&&(n=o),(s=0?n:r,t)}intersectsBox(e){return this.intersectBox(e,gi)!==null}intersectTriangle(e,t,n,r,i){bi.subVectors(t,e),xi.subVectors(n,e),Si.crossVectors(bi,xi);let a=this.direction.dot(Si),o;if(a>0){if(r)return null;o=1}else if(a<0)o=-1,a=-a;else return null;yi.subVectors(this.origin,e);let s=o*this.direction.dot(xi.crossVectors(yi,xi));if(s<0)return null;let c=o*this.direction.dot(bi.cross(yi));if(c<0||s+c>a)return null;let l=-o*yi.dot(Si);return l<0?null:this.at(l/a,i)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return new this.constructor().copy(this)}},wi=class extends $r{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type=`MeshBasicMaterial`,this.color=new X(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new On,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap=`round`,this.wireframeLinejoin=`round`,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}},Ti=new vn,Ei=new Ci,Di=new Br,Oi=new q,ki=new q,Ai=new q,ji=new q,Mi=new q,Ni=new q,Pi=new q,Fi=new q,Ii=class extends Gn{constructor(e=new Jr,t=new wi){super(),this.isMesh=!0,this.type=`Mesh`,this.geometry=e,this.material=t,this.morphTargetDictionary=void 0,this.morphTargetInfluences=void 0,this.count=1,this.updateMorphTargets()}copy(e,t){return super.copy(e,t),e.morphTargetInfluences!==void 0&&(this.morphTargetInfluences=e.morphTargetInfluences.slice()),e.morphTargetDictionary!==void 0&&(this.morphTargetDictionary=Object.assign({},e.morphTargetDictionary)),this.material=Array.isArray(e.material)?e.material.slice():e.material,this.geometry=e.geometry,this}updateMorphTargets(){let e=this.geometry.morphAttributes,t=Object.keys(e);if(t.length>0){let n=e[t[0]];if(n!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;e(e.far-e.near)**2))&&(Ti.copy(i).invert(),Ei.copy(e.ray).applyMatrix4(Ti),!(n.boundingBox!==null&&Ei.intersectsBox(n.boundingBox)===!1)&&this._computeIntersections(e,t,Ei)))}_computeIntersections(e,t,n){let r,i=this.geometry,a=this.material,o=i.index,s=i.attributes.position,c=i.attributes.uv,l=i.attributes.uv1,u=i.attributes.normal,d=i.groups,f=i.drawRange;if(o!==null)if(Array.isArray(a))for(let i=0,s=d.length;in.far?null:{distance:l,point:Fi.clone(),object:e}}function Ri(e,t,n,r,i,a,o,s,c,l){e.getVertexPosition(s,ki),e.getVertexPosition(c,Ai),e.getVertexPosition(l,ji);let u=Li(e,t,n,r,ki,Ai,ji,Pi);if(u){let e=new q;mr.getBarycoord(Pi,ki,Ai,ji,e),i&&(u.uv=mr.getInterpolatedAttribute(i,s,c,l,e,new K)),a&&(u.uv1=mr.getInterpolatedAttribute(a,s,c,l,e,new K)),o&&(u.normal=mr.getInterpolatedAttribute(o,s,c,l,e,new q),u.normal.dot(r.direction)>0&&u.normal.multiplyScalar(-1));let t={a:s,b:c,c:l,normal:new q,materialIndex:0};mr.getNormal(ki,Ai,ji,t.normal),u.face=t,u.barycoord=e}return u}var zi=class extends fn{constructor(e=null,t=1,n=1,r,i,a,o,s,c=O,l=O,u,d){super(null,a,o,s,c,l,r,i,u,d),this.isDataTexture=!0,this.image={data:e,width:t,height:n},this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}},Bi=new q,Vi=new q,Hi=new J,Ui=class{constructor(e=new q(1,0,0),t=0){this.isPlane=!0,this.normal=e,this.constant=t}set(e,t){return this.normal.copy(e),this.constant=t,this}setComponents(e,t,n,r){return this.normal.set(e,t,n),this.constant=r,this}setFromNormalAndCoplanarPoint(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this}setFromCoplanarPoints(e,t,n){let r=Bi.subVectors(n,t).cross(Vi.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(r,e),this}copy(e){return this.normal.copy(e.normal),this.constant=e.constant,this}normalize(){let e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(e){return this.normal.dot(e)+this.constant}distanceToSphere(e){return this.distanceToPoint(e.center)-e.radius}projectPoint(e,t){return t.copy(e).addScaledVector(this.normal,-this.distanceToPoint(e))}intersectLine(e,t,n=!0){let r=e.delta(Bi),i=this.normal.dot(r);if(i===0)return this.distanceToPoint(e.start)===0?t.copy(e.start):null;let a=-(e.start.dot(this.normal)+this.constant)/i;return n===!0&&(a<0||a>1)?null:t.copy(e.start).addScaledVector(r,a)}intersectsLine(e){let t=this.distanceToPoint(e.start),n=this.distanceToPoint(e.end);return t<0&&n>0||n<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){let n=t||Hi.getNormalMatrix(e),r=this.coplanarPoint(Bi).applyMatrix4(e),i=this.normal.applyMatrix3(n).normalize();return this.constant=-r.dot(i),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return new this.constructor().copy(this)}},Wi=new Br,Gi=new K(.5,.5),Ki=new q,qi=class{constructor(e=new Ui,t=new Ui,n=new Ui,r=new Ui,i=new Ui,a=new Ui){this.planes=[e,t,n,r,i,a]}set(e,t,n,r,i,a){let o=this.planes;return o[0].copy(e),o[1].copy(t),o[2].copy(n),o[3].copy(r),o[4].copy(i),o[5].copy(a),this}copy(e){let t=this.planes;for(let n=0;n<6;n++)t[n].copy(e.planes[n]);return this}setFromProjectionMatrix(e,t=dt,n=!1){let r=this.planes,i=e.elements,a=i[0],o=i[1],s=i[2],c=i[3],l=i[4],u=i[5],d=i[6],f=i[7],p=i[8],m=i[9],h=i[10],g=i[11],_=i[12],v=i[13],y=i[14],b=i[15];if(r[0].setComponents(c-a,f-l,g-p,b-_).normalize(),r[1].setComponents(c+a,f+l,g+p,b+_).normalize(),r[2].setComponents(c+o,f+u,g+m,b+v).normalize(),r[3].setComponents(c-o,f-u,g-m,b-v).normalize(),n)r[4].setComponents(s,d,h,y).normalize(),r[5].setComponents(c-s,f-d,g-h,b-y).normalize();else if(r[4].setComponents(c-s,f-d,g-h,b-y).normalize(),t===2e3)r[5].setComponents(c+s,f+d,g+h,b+y).normalize();else if(t===2001)r[5].setComponents(s,d,h,y).normalize();else throw Error(`THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: `+t);return this}intersectsObject(e){if(e.boundingSphere!==void 0)e.boundingSphere===null&&e.computeBoundingSphere(),Wi.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{let t=e.geometry;t.boundingSphere===null&&t.computeBoundingSphere(),Wi.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(Wi)}intersectsSprite(e){return Wi.center.set(0,0,0),Wi.radius=.7071067811865476+Gi.distanceTo(e.center),Wi.applyMatrix4(e.matrixWorld),this.intersectsSphere(Wi)}intersectsSphere(e){let t=this.planes,n=e.center,r=-e.radius;for(let e=0;e<6;e++)if(t[e].distanceToPoint(n)0?e.max.x:e.min.x,Ki.y=r.normal.y>0?e.max.y:e.min.y,Ki.z=r.normal.z>0?e.max.z:e.min.z,r.distanceToPoint(Ki)<0)return!1}return!0}containsPoint(e){let t=this.planes;for(let n=0;n<6;n++)if(t[n].distanceToPoint(e)<0)return!1;return!0}clone(){return new this.constructor().copy(this)}},Ji=class extends $r{constructor(e){super(),this.isLineBasicMaterial=!0,this.type=`LineBasicMaterial`,this.color=new X(16777215),this.map=null,this.linewidth=1,this.linecap=`round`,this.linejoin=`round`,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.linewidth=e.linewidth,this.linecap=e.linecap,this.linejoin=e.linejoin,this.fog=e.fog,this}},Yi=new q,Xi=new q,Zi=new vn,Qi=new Ci,$i=new Br,ea=new q,ta=new q,na=class extends Gn{constructor(e=new Jr,t=new Ji){super(),this.isLine=!0,this.type=`Line`,this.geometry=e,this.material=t,this.morphTargetDictionary=void 0,this.morphTargetInfluences=void 0,this.updateMorphTargets()}copy(e,t){return super.copy(e,t),this.material=Array.isArray(e.material)?e.material.slice():e.material,this.geometry=e.geometry,this}computeLineDistances(){let e=this.geometry;if(e.index===null){let t=e.attributes.position,n=[0];for(let e=1,r=t.count;e0){let n=e[t[0]];if(n!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;er)return;ea.applyMatrix4(e.matrixWorld);let c=t.ray.origin.distanceTo(ea);if(!(ct.far))return{distance:c,point:ta.clone().applyMatrix4(e.matrixWorld),index:o,face:null,faceIndex:null,barycoord:null,object:e}}var ia=class extends fn{constructor(e=[],t=301,n,r,i,a,o,s,c,l){super(e,t,n,r,i,a,o,s,c,l),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}},aa=class extends fn{constructor(e,t,n,r,i,a,o,s,c){super(e,t,n,r,i,a,o,s,c),this.isCanvasTexture=!0,this.needsUpdate=!0}},oa=class extends fn{constructor(e,t,n=ie,r,i,a,o=O,s=O,c,l=me,u=1){if(l!==1026&&l!==1027)throw Error(`DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat`);super({width:e,height:t,depth:u},r,i,a,o,s,l,n,c),this.isDepthTexture=!0,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(e){return super.copy(e),this.source=new cn(Object.assign({},e.image)),this.compareFunction=e.compareFunction,this}toJSON(e){let t=super.toJSON(e);return this.compareFunction!==null&&(t.compareFunction=this.compareFunction),t}},sa=class extends oa{constructor(e,t=ie,n=301,r,i,a=O,o=O,s,c=me){let l={width:e,height:e,depth:1},u=[l,l,l,l,l,l];super(e,e,t,n,r,i,a,o,s,c),this.image=u,this.isCubeDepthTexture=!0,this.isCubeTexture=!0}get images(){return this.image}set images(e){this.image=e}},ca=class extends fn{constructor(e=null){super(),this.sourceTexture=e,this.isExternalTexture=!0}copy(e){return super.copy(e),this.sourceTexture=e.sourceTexture,this}},la=class e extends Jr{constructor(e=1,t=1,n=1,r=1,i=1,a=1){super(),this.type=`BoxGeometry`,this.parameters={width:e,height:t,depth:n,widthSegments:r,heightSegments:i,depthSegments:a};let o=this;r=Math.floor(r),i=Math.floor(i),a=Math.floor(a);let s=[],c=[],l=[],u=[],d=0,f=0;p(`z`,`y`,`x`,-1,-1,n,t,e,a,i,0),p(`z`,`y`,`x`,1,-1,n,t,-e,a,i,1),p(`x`,`z`,`y`,1,1,e,n,t,r,a,2),p(`x`,`z`,`y`,1,-1,e,n,-t,r,a,3),p(`x`,`y`,`z`,1,-1,e,t,n,r,i,4),p(`x`,`y`,`z`,-1,-1,e,t,-n,r,i,5),this.setIndex(s),this.setAttribute(`position`,new Ir(c,3)),this.setAttribute(`normal`,new Ir(l,3)),this.setAttribute(`uv`,new Ir(u,2));function p(e,t,n,r,i,a,p,m,h,g,_){let v=a/h,y=p/g,b=a/2,x=p/2,S=m/2,C=h+1,w=g+1,T=0,E=0,D=new q;for(let a=0;a0?1:-1,l.push(D.x,D.y,D.z),u.push(s/h),u.push(1-a/g),T+=1}for(let e=0;e0)&&f.push(t,i,c),(e!==n-1||s0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;let n={};for(let e in this.extensions)this.extensions[e]===!0&&(n[e]=!0);return Object.keys(n).length>0&&(t.extensions=n),t}},xa=class extends ba{constructor(e){super(e),this.isRawShaderMaterial=!0,this.type=`RawShaderMaterial`}},Sa=class extends $r{constructor(e){super(),this.isMeshStandardMaterial=!0,this.type=`MeshStandardMaterial`,this.defines={STANDARD:``},this.color=new X(16777215),this.roughness=1,this.metalness=0,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new X(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new K(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.roughnessMap=null,this.metalnessMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new On,this.envMapIntensity=1,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap=`round`,this.wireframeLinejoin=`round`,this.flatShading=!1,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.defines={STANDARD:``},this.color.copy(e.color),this.roughness=e.roughness,this.metalness=e.metalness,this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.roughnessMap=e.roughnessMap,this.metalnessMap=e.metalnessMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.envMapIntensity=e.envMapIntensity,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.flatShading=e.flatShading,this.fog=e.fog,this}},Ca=class extends $r{constructor(e){super(),this.isMeshDepthMaterial=!0,this.type=`MeshDepthMaterial`,this.depthPacking=it,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}},wa=class extends $r{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type=`MeshDistanceMaterial`,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}};function Ta(e,t){return!e||e.constructor===t?e:typeof t.BYTES_PER_ELEMENT==`number`?new t(e):Array.prototype.slice.call(e)}var Ea=class{constructor(e,t,n,r){this.parameterPositions=e,this._cachedIndex=0,this.resultBuffer=r===void 0?new t.constructor(n):r,this.sampleValues=t,this.valueSize=n,this.settings=null,this.DefaultSettings_={}}evaluate(e){let t=this.parameterPositions,n=this._cachedIndex,r=t[n],i=t[n-1];validate_interval:{seek:{let a;linear_scan:{forward_scan:if(!(e=i)){let o=t[1];e=i)break seek}a=n,n=0;break linear_scan}break validate_interval}for(;n>>1;et;)--a;if(++a,i!==0||a!==r){i>=a&&(a=Math.max(a,1),i=a-1);let e=this.getValueSize();this.times=n.slice(i,a),this.values=this.values.slice(i*e,a*e)}return this}validate(){let e=!0,t=this.getValueSize();t-Math.floor(t)!==0&&(U(`KeyframeTrack: Invalid value size in track.`,this),e=!1);let n=this.times,r=this.values,i=n.length;i===0&&(U(`KeyframeTrack: Track is empty.`,this),e=!1);let a=null;for(let t=0;t!==i;t++){let r=n[t];if(typeof r==`number`&&isNaN(r)){U(`KeyframeTrack: Time is not a valid number.`,this,t,r),e=!1;break}if(a!==null&&a>r){U(`KeyframeTrack: Out of order keys.`,this,t,r,a),e=!1;break}a=r}if(r!==void 0&&pt(r))for(let t=0,n=r.length;t!==n;++t){let n=r[t];if(isNaN(n)){U(`KeyframeTrack: Value is not a valid number.`,this,t,n),e=!1;break}}return e}optimize(){let e=this.times.slice(),t=this.values.slice(),n=this.getValueSize(),r=this.getInterpolation()===$e,i=e.length-1,a=1;for(let o=1;o0){e[a]=e[i];for(let e=i*n,r=a*n,o=0;o!==n;++o)t[r+o]=t[e+o];++a}return a===e.length?(this.times=e,this.values=t):(this.times=e.slice(0,a),this.values=t.slice(0,a*n)),this}clone(){let e=this.times.slice(),t=this.values.slice(),n=this.constructor,r=new n(this.name,e,t);return r.createInterpolant=this.createInterpolant,r}};ja.prototype.ValueTypeName=``,ja.prototype.TimeBufferType=Float32Array,ja.prototype.ValueBufferType=Float32Array,ja.prototype.DefaultInterpolation=Qe;var Ma=class extends ja{constructor(e,t,n){super(e,t,n)}};Ma.prototype.ValueTypeName=`bool`,Ma.prototype.ValueBufferType=Array,Ma.prototype.DefaultInterpolation=Ze,Ma.prototype.InterpolantFactoryMethodLinear=void 0,Ma.prototype.InterpolantFactoryMethodSmooth=void 0;var Na=class extends ja{constructor(e,t,n,r){super(e,t,n,r)}};Na.prototype.ValueTypeName=`color`;var Pa=class extends ja{constructor(e,t,n,r){super(e,t,n,r)}};Pa.prototype.ValueTypeName=`number`;var Fa=class extends Ea{constructor(e,t,n,r){super(e,t,n,r)}interpolate_(e,t,n,r){let i=this.resultBuffer,a=this.sampleValues,o=this.valueSize,s=(n-t)/(r-t),c=e*o;for(let e=c+o;c!==e;c+=4)Yt.slerpFlat(i,0,a,c-o,a,c,s);return i}},Ia=class extends ja{constructor(e,t,n,r){super(e,t,n,r)}InterpolantFactoryMethodLinear(e){return new Fa(this.times,this.values,this.getValueSize(),e)}};Ia.prototype.ValueTypeName=`quaternion`,Ia.prototype.InterpolantFactoryMethodSmooth=void 0;var La=class extends ja{constructor(e,t,n){super(e,t,n)}};La.prototype.ValueTypeName=`string`,La.prototype.ValueBufferType=Array,La.prototype.DefaultInterpolation=Ze,La.prototype.InterpolantFactoryMethodLinear=void 0,La.prototype.InterpolantFactoryMethodSmooth=void 0;var Ra=class extends ja{constructor(e,t,n,r){super(e,t,n,r)}};Ra.prototype.ValueTypeName=`vector`;var za={enabled:!1,files:{},add:function(e,t){this.enabled!==!1&&(Ba(e)||(this.files[e]=t))},get:function(e){if(this.enabled!==!1&&!Ba(e))return this.files[e]},remove:function(e){delete this.files[e]},clear:function(){this.files={}}};function Ba(e){try{let t=e.slice(e.indexOf(`:`)+1);return new URL(t).protocol===`blob:`}catch{return!1}}var Va=new class{constructor(e,t,n){let r=this,i=!1,a=0,o=0,s,c=[];this.onStart=void 0,this.onLoad=e,this.onProgress=t,this.onError=n,this._abortController=null,this.itemStart=function(e){o++,i===!1&&r.onStart!==void 0&&r.onStart(e,a,o),i=!0},this.itemEnd=function(e){a++,r.onProgress!==void 0&&r.onProgress(e,a,o),a===o&&(i=!1,r.onLoad!==void 0&&r.onLoad())},this.itemError=function(e){r.onError!==void 0&&r.onError(e)},this.resolveURL=function(e){return s?s(e):e},this.setURLModifier=function(e){return s=e,this},this.addHandler=function(e,t){return c.push(e,t),this},this.removeHandler=function(e){let t=c.indexOf(e);return t!==-1&&c.splice(t,2),this},this.getHandler=function(e){for(let t=0,n=c.length;te.start-t.start);let t=0;for(let e=1;e 0
- vec4 plane;
- #ifdef ALPHA_TO_COVERAGE
- float distanceToPlane, distanceGradient;
- float clipOpacity = 1.0;
- #pragma unroll_loop_start
- for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {
- plane = clippingPlanes[ i ];
- distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;
- distanceGradient = fwidth( distanceToPlane ) / 2.0;
- clipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );
- if ( clipOpacity == 0.0 ) discard;
- }
- #pragma unroll_loop_end
- #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES
- float unionClipOpacity = 1.0;
- #pragma unroll_loop_start
- for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {
- plane = clippingPlanes[ i ];
- distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;
- distanceGradient = fwidth( distanceToPlane ) / 2.0;
- unionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );
- }
- #pragma unroll_loop_end
- clipOpacity *= 1.0 - unionClipOpacity;
- #endif
- diffuseColor.a *= clipOpacity;
- if ( diffuseColor.a == 0.0 ) discard;
- #else
- #pragma unroll_loop_start
- for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {
- plane = clippingPlanes[ i ];
- if ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;
- }
- #pragma unroll_loop_end
- #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES
- bool clipped = true;
- #pragma unroll_loop_start
- for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {
- plane = clippingPlanes[ i ];
- clipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;
- }
- #pragma unroll_loop_end
- if ( clipped ) discard;
- #endif
- #endif
-#endif`,clipping_planes_pars_fragment:`#if NUM_CLIPPING_PLANES > 0
- varying vec3 vClipPosition;
- uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];
-#endif`,clipping_planes_pars_vertex:`#if NUM_CLIPPING_PLANES > 0
- varying vec3 vClipPosition;
-#endif`,clipping_planes_vertex:`#if NUM_CLIPPING_PLANES > 0
- vClipPosition = - mvPosition.xyz;
-#endif`,color_fragment:`#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA )
- diffuseColor *= vColor;
-#endif`,color_pars_fragment:`#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA )
- varying vec4 vColor;
-#endif`,color_pars_vertex:`#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )
- varying vec4 vColor;
-#endif`,color_vertex:`#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )
- vColor = vec4( 1.0 );
-#endif
-#ifdef USE_COLOR_ALPHA
- vColor *= color;
-#elif defined( USE_COLOR )
- vColor.rgb *= color;
-#endif
-#ifdef USE_INSTANCING_COLOR
- vColor.rgb *= instanceColor.rgb;
-#endif
-#ifdef USE_BATCHING_COLOR
- vColor *= getBatchingColor( getIndirectIndex( gl_DrawID ) );
-#endif`,common:`#define PI 3.141592653589793
-#define PI2 6.283185307179586
-#define PI_HALF 1.5707963267948966
-#define RECIPROCAL_PI 0.3183098861837907
-#define RECIPROCAL_PI2 0.15915494309189535
-#define EPSILON 1e-6
-#ifndef saturate
-#define saturate( a ) clamp( a, 0.0, 1.0 )
-#endif
-#define whiteComplement( a ) ( 1.0 - saturate( a ) )
-float pow2( const in float x ) { return x*x; }
-vec3 pow2( const in vec3 x ) { return x*x; }
-float pow3( const in float x ) { return x*x*x; }
-float pow4( const in float x ) { float x2 = x*x; return x2*x2; }
-float max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }
-float average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }
-highp float rand( const in vec2 uv ) {
- const highp float a = 12.9898, b = 78.233, c = 43758.5453;
- highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );
- return fract( sin( sn ) * c );
-}
-#ifdef HIGH_PRECISION
- float precisionSafeLength( vec3 v ) { return length( v ); }
-#else
- float precisionSafeLength( vec3 v ) {
- float maxComponent = max3( abs( v ) );
- return length( v / maxComponent ) * maxComponent;
- }
-#endif
-struct IncidentLight {
- vec3 color;
- vec3 direction;
- bool visible;
-};
-struct ReflectedLight {
- vec3 directDiffuse;
- vec3 directSpecular;
- vec3 indirectDiffuse;
- vec3 indirectSpecular;
-};
-#ifdef USE_ALPHAHASH
- varying vec3 vPosition;
-#endif
-vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
- return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
-}
-vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {
- return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );
-}
-bool isPerspectiveMatrix( mat4 m ) {
- return m[ 2 ][ 3 ] == - 1.0;
-}
-vec2 equirectUv( in vec3 dir ) {
- float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;
- float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;
- return vec2( u, v );
-}
-vec3 BRDF_Lambert( const in vec3 diffuseColor ) {
- return RECIPROCAL_PI * diffuseColor;
-}
-vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {
- float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );
- return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );
-}
-float F_Schlick( const in float f0, const in float f90, const in float dotVH ) {
- float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );
- return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );
-} // validated`,cube_uv_reflection_fragment:`#ifdef ENVMAP_TYPE_CUBE_UV
- #define cubeUV_minMipLevel 4.0
- #define cubeUV_minTileSize 16.0
- float getFace( vec3 direction ) {
- vec3 absDirection = abs( direction );
- float face = - 1.0;
- if ( absDirection.x > absDirection.z ) {
- if ( absDirection.x > absDirection.y )
- face = direction.x > 0.0 ? 0.0 : 3.0;
- else
- face = direction.y > 0.0 ? 1.0 : 4.0;
- } else {
- if ( absDirection.z > absDirection.y )
- face = direction.z > 0.0 ? 2.0 : 5.0;
- else
- face = direction.y > 0.0 ? 1.0 : 4.0;
- }
- return face;
- }
- vec2 getUV( vec3 direction, float face ) {
- vec2 uv;
- if ( face == 0.0 ) {
- uv = vec2( direction.z, direction.y ) / abs( direction.x );
- } else if ( face == 1.0 ) {
- uv = vec2( - direction.x, - direction.z ) / abs( direction.y );
- } else if ( face == 2.0 ) {
- uv = vec2( - direction.x, direction.y ) / abs( direction.z );
- } else if ( face == 3.0 ) {
- uv = vec2( - direction.z, direction.y ) / abs( direction.x );
- } else if ( face == 4.0 ) {
- uv = vec2( - direction.x, direction.z ) / abs( direction.y );
- } else {
- uv = vec2( direction.x, direction.y ) / abs( direction.z );
- }
- return 0.5 * ( uv + 1.0 );
- }
- vec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {
- float face = getFace( direction );
- float filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );
- mipInt = max( mipInt, cubeUV_minMipLevel );
- float faceSize = exp2( mipInt );
- highp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;
- if ( face > 2.0 ) {
- uv.y += faceSize;
- face -= 3.0;
- }
- uv.x += face * faceSize;
- uv.x += filterInt * 3.0 * cubeUV_minTileSize;
- uv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );
- uv.x *= CUBEUV_TEXEL_WIDTH;
- uv.y *= CUBEUV_TEXEL_HEIGHT;
- #ifdef texture2DGradEXT
- return texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;
- #else
- return texture2D( envMap, uv ).rgb;
- #endif
- }
- #define cubeUV_r0 1.0
- #define cubeUV_m0 - 2.0
- #define cubeUV_r1 0.8
- #define cubeUV_m1 - 1.0
- #define cubeUV_r4 0.4
- #define cubeUV_m4 2.0
- #define cubeUV_r5 0.305
- #define cubeUV_m5 3.0
- #define cubeUV_r6 0.21
- #define cubeUV_m6 4.0
- float roughnessToMip( float roughness ) {
- float mip = 0.0;
- if ( roughness >= cubeUV_r1 ) {
- mip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;
- } else if ( roughness >= cubeUV_r4 ) {
- mip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;
- } else if ( roughness >= cubeUV_r5 ) {
- mip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;
- } else if ( roughness >= cubeUV_r6 ) {
- mip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;
- } else {
- mip = - 2.0 * log2( 1.16 * roughness ); }
- return mip;
- }
- vec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {
- float mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );
- float mipF = fract( mip );
- float mipInt = floor( mip );
- vec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );
- if ( mipF == 0.0 ) {
- return vec4( color0, 1.0 );
- } else {
- vec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );
- return vec4( mix( color0, color1, mipF ), 1.0 );
- }
- }
-#endif`,defaultnormal_vertex:`vec3 transformedNormal = objectNormal;
-#ifdef USE_TANGENT
- vec3 transformedTangent = objectTangent;
-#endif
-#ifdef USE_BATCHING
- mat3 bm = mat3( batchingMatrix );
- transformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );
- transformedNormal = bm * transformedNormal;
- #ifdef USE_TANGENT
- transformedTangent = bm * transformedTangent;
- #endif
-#endif
-#ifdef USE_INSTANCING
- mat3 im = mat3( instanceMatrix );
- transformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );
- transformedNormal = im * transformedNormal;
- #ifdef USE_TANGENT
- transformedTangent = im * transformedTangent;
- #endif
-#endif
-transformedNormal = normalMatrix * transformedNormal;
-#ifdef FLIP_SIDED
- transformedNormal = - transformedNormal;
-#endif
-#ifdef USE_TANGENT
- transformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;
- #ifdef FLIP_SIDED
- transformedTangent = - transformedTangent;
- #endif
-#endif`,displacementmap_pars_vertex:`#ifdef USE_DISPLACEMENTMAP
- uniform sampler2D displacementMap;
- uniform float displacementScale;
- uniform float displacementBias;
-#endif`,displacementmap_vertex:`#ifdef USE_DISPLACEMENTMAP
- transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );
-#endif`,emissivemap_fragment:`#ifdef USE_EMISSIVEMAP
- vec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );
- #ifdef DECODE_VIDEO_TEXTURE_EMISSIVE
- emissiveColor = sRGBTransferEOTF( emissiveColor );
- #endif
- totalEmissiveRadiance *= emissiveColor.rgb;
-#endif`,emissivemap_pars_fragment:`#ifdef USE_EMISSIVEMAP
- uniform sampler2D emissiveMap;
-#endif`,colorspace_fragment:`gl_FragColor = linearToOutputTexel( gl_FragColor );`,colorspace_pars_fragment:`vec4 LinearTransferOETF( in vec4 value ) {
- return value;
-}
-vec4 sRGBTransferEOTF( in vec4 value ) {
- return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );
-}
-vec4 sRGBTransferOETF( in vec4 value ) {
- return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );
-}`,envmap_fragment:`#ifdef USE_ENVMAP
- #ifdef ENV_WORLDPOS
- vec3 cameraToFrag;
- if ( isOrthographic ) {
- cameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );
- } else {
- cameraToFrag = normalize( vWorldPosition - cameraPosition );
- }
- vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );
- #ifdef ENVMAP_MODE_REFLECTION
- vec3 reflectVec = reflect( cameraToFrag, worldNormal );
- #else
- vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );
- #endif
- #else
- vec3 reflectVec = vReflect;
- #endif
- #ifdef ENVMAP_TYPE_CUBE
- vec4 envColor = textureCube( envMap, envMapRotation * reflectVec );
- #ifdef ENVMAP_BLENDING_MULTIPLY
- outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );
- #elif defined( ENVMAP_BLENDING_MIX )
- outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );
- #elif defined( ENVMAP_BLENDING_ADD )
- outgoingLight += envColor.xyz * specularStrength * reflectivity;
- #endif
- #endif
-#endif`,envmap_common_pars_fragment:`#ifdef USE_ENVMAP
- uniform float envMapIntensity;
- uniform mat3 envMapRotation;
- #ifdef ENVMAP_TYPE_CUBE
- uniform samplerCube envMap;
- #else
- uniform sampler2D envMap;
- #endif
-#endif`,envmap_pars_fragment:`#ifdef USE_ENVMAP
- uniform float reflectivity;
- #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )
- #define ENV_WORLDPOS
- #endif
- #ifdef ENV_WORLDPOS
- varying vec3 vWorldPosition;
- uniform float refractionRatio;
- #else
- varying vec3 vReflect;
- #endif
-#endif`,envmap_pars_vertex:`#ifdef USE_ENVMAP
- #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )
- #define ENV_WORLDPOS
- #endif
- #ifdef ENV_WORLDPOS
-
- varying vec3 vWorldPosition;
- #else
- varying vec3 vReflect;
- uniform float refractionRatio;
- #endif
-#endif`,envmap_physical_pars_fragment:`#ifdef USE_ENVMAP
- vec3 getIBLIrradiance( const in vec3 normal ) {
- #ifdef ENVMAP_TYPE_CUBE_UV
- vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );
- vec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );
- return PI * envMapColor.rgb * envMapIntensity;
- #else
- return vec3( 0.0 );
- #endif
- }
- vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {
- #ifdef ENVMAP_TYPE_CUBE_UV
- vec3 reflectVec = reflect( - viewDir, normal );
- reflectVec = normalize( mix( reflectVec, normal, pow4( roughness ) ) );
- reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
- vec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );
- return envMapColor.rgb * envMapIntensity;
- #else
- return vec3( 0.0 );
- #endif
- }
- #ifdef USE_ANISOTROPY
- vec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {
- #ifdef ENVMAP_TYPE_CUBE_UV
- vec3 bentNormal = cross( bitangent, viewDir );
- bentNormal = normalize( cross( bentNormal, bitangent ) );
- bentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );
- return getIBLRadiance( viewDir, bentNormal, roughness );
- #else
- return vec3( 0.0 );
- #endif
- }
- #endif
-#endif`,envmap_vertex:`#ifdef USE_ENVMAP
- #ifdef ENV_WORLDPOS
- vWorldPosition = worldPosition.xyz;
- #else
- vec3 cameraToVertex;
- if ( isOrthographic ) {
- cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );
- } else {
- cameraToVertex = normalize( worldPosition.xyz - cameraPosition );
- }
- vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );
- #ifdef ENVMAP_MODE_REFLECTION
- vReflect = reflect( cameraToVertex, worldNormal );
- #else
- vReflect = refract( cameraToVertex, worldNormal, refractionRatio );
- #endif
- #endif
-#endif`,fog_vertex:`#ifdef USE_FOG
- vFogDepth = - mvPosition.z;
-#endif`,fog_pars_vertex:`#ifdef USE_FOG
- varying float vFogDepth;
-#endif`,fog_fragment:`#ifdef USE_FOG
- #ifdef FOG_EXP2
- float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );
- #else
- float fogFactor = smoothstep( fogNear, fogFar, vFogDepth );
- #endif
- gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );
-#endif`,fog_pars_fragment:`#ifdef USE_FOG
- uniform vec3 fogColor;
- varying float vFogDepth;
- #ifdef FOG_EXP2
- uniform float fogDensity;
- #else
- uniform float fogNear;
- uniform float fogFar;
- #endif
-#endif`,gradientmap_pars_fragment:`#ifdef USE_GRADIENTMAP
- uniform sampler2D gradientMap;
-#endif
-vec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {
- float dotNL = dot( normal, lightDirection );
- vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );
- #ifdef USE_GRADIENTMAP
- return vec3( texture2D( gradientMap, coord ).r );
- #else
- vec2 fw = fwidth( coord ) * 0.5;
- return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );
- #endif
-}`,lightmap_pars_fragment:`#ifdef USE_LIGHTMAP
- uniform sampler2D lightMap;
- uniform float lightMapIntensity;
-#endif`,lights_lambert_fragment:`LambertMaterial material;
-material.diffuseColor = diffuseColor.rgb;
-material.specularStrength = specularStrength;`,lights_lambert_pars_fragment:`varying vec3 vViewPosition;
-struct LambertMaterial {
- vec3 diffuseColor;
- float specularStrength;
-};
-void RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {
- float dotNL = saturate( dot( geometryNormal, directLight.direction ) );
- vec3 irradiance = dotNL * directLight.color;
- reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );
-}
-void RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {
- reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );
-}
-#define RE_Direct RE_Direct_Lambert
-#define RE_IndirectDiffuse RE_IndirectDiffuse_Lambert`,lights_pars_begin:`uniform bool receiveShadow;
-uniform vec3 ambientLightColor;
-#if defined( USE_LIGHT_PROBES )
- uniform vec3 lightProbe[ 9 ];
-#endif
-vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {
- float x = normal.x, y = normal.y, z = normal.z;
- vec3 result = shCoefficients[ 0 ] * 0.886227;
- result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;
- result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;
- result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;
- result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;
- result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;
- result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );
- result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;
- result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );
- return result;
-}
-vec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {
- vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );
- vec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );
- return irradiance;
-}
-vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
- vec3 irradiance = ambientLightColor;
- return irradiance;
-}
-float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
- float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );
- if ( cutoffDistance > 0.0 ) {
- distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );
- }
- return distanceFalloff;
-}
-float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {
- return smoothstep( coneCosine, penumbraCosine, angleCosine );
-}
-#if NUM_DIR_LIGHTS > 0
- struct DirectionalLight {
- vec3 direction;
- vec3 color;
- };
- uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
- void getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {
- light.color = directionalLight.color;
- light.direction = directionalLight.direction;
- light.visible = true;
- }
-#endif
-#if NUM_POINT_LIGHTS > 0
- struct PointLight {
- vec3 position;
- vec3 color;
- float distance;
- float decay;
- };
- uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
- void getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {
- vec3 lVector = pointLight.position - geometryPosition;
- light.direction = normalize( lVector );
- float lightDistance = length( lVector );
- light.color = pointLight.color;
- light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );
- light.visible = ( light.color != vec3( 0.0 ) );
- }
-#endif
-#if NUM_SPOT_LIGHTS > 0
- struct SpotLight {
- vec3 position;
- vec3 direction;
- vec3 color;
- float distance;
- float decay;
- float coneCos;
- float penumbraCos;
- };
- uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];
- void getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {
- vec3 lVector = spotLight.position - geometryPosition;
- light.direction = normalize( lVector );
- float angleCos = dot( light.direction, spotLight.direction );
- float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );
- if ( spotAttenuation > 0.0 ) {
- float lightDistance = length( lVector );
- light.color = spotLight.color * spotAttenuation;
- light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );
- light.visible = ( light.color != vec3( 0.0 ) );
- } else {
- light.color = vec3( 0.0 );
- light.visible = false;
- }
- }
-#endif
-#if NUM_RECT_AREA_LIGHTS > 0
- struct RectAreaLight {
- vec3 color;
- vec3 position;
- vec3 halfWidth;
- vec3 halfHeight;
- };
- uniform sampler2D ltc_1; uniform sampler2D ltc_2;
- uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];
-#endif
-#if NUM_HEMI_LIGHTS > 0
- struct HemisphereLight {
- vec3 direction;
- vec3 skyColor;
- vec3 groundColor;
- };
- uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];
- vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {
- float dotNL = dot( normal, hemiLight.direction );
- float hemiDiffuseWeight = 0.5 * dotNL + 0.5;
- vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );
- return irradiance;
- }
-#endif
-#include `,lights_toon_fragment:`ToonMaterial material;
-material.diffuseColor = diffuseColor.rgb;`,lights_toon_pars_fragment:`varying vec3 vViewPosition;
-struct ToonMaterial {
- vec3 diffuseColor;
-};
-void RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {
- vec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;
- reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );
-}
-void RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {
- reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );
-}
-#define RE_Direct RE_Direct_Toon
-#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon`,lights_phong_fragment:`BlinnPhongMaterial material;
-material.diffuseColor = diffuseColor.rgb;
-material.specularColor = specular;
-material.specularShininess = shininess;
-material.specularStrength = specularStrength;`,lights_phong_pars_fragment:`varying vec3 vViewPosition;
-struct BlinnPhongMaterial {
- vec3 diffuseColor;
- vec3 specularColor;
- float specularShininess;
- float specularStrength;
-};
-void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
- float dotNL = saturate( dot( geometryNormal, directLight.direction ) );
- vec3 irradiance = dotNL * directLight.color;
- reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );
- reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;
-}
-void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
- reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );
-}
-#define RE_Direct RE_Direct_BlinnPhong
-#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong`,lights_physical_fragment:`PhysicalMaterial material;
-material.diffuseColor = diffuseColor.rgb;
-material.diffuseContribution = diffuseColor.rgb * ( 1.0 - metalnessFactor );
-material.metalness = metalnessFactor;
-vec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );
-float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );
-material.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;
-material.roughness = min( material.roughness, 1.0 );
-#ifdef IOR
- material.ior = ior;
- #ifdef USE_SPECULAR
- float specularIntensityFactor = specularIntensity;
- vec3 specularColorFactor = specularColor;
- #ifdef USE_SPECULAR_COLORMAP
- specularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;
- #endif
- #ifdef USE_SPECULAR_INTENSITYMAP
- specularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;
- #endif
- material.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );
- #else
- float specularIntensityFactor = 1.0;
- vec3 specularColorFactor = vec3( 1.0 );
- material.specularF90 = 1.0;
- #endif
- material.specularColor = min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor;
- material.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );
-#else
- material.specularColor = vec3( 0.04 );
- material.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );
- material.specularF90 = 1.0;
-#endif
-#ifdef USE_CLEARCOAT
- material.clearcoat = clearcoat;
- material.clearcoatRoughness = clearcoatRoughness;
- material.clearcoatF0 = vec3( 0.04 );
- material.clearcoatF90 = 1.0;
- #ifdef USE_CLEARCOATMAP
- material.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;
- #endif
- #ifdef USE_CLEARCOAT_ROUGHNESSMAP
- material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;
- #endif
- material.clearcoat = saturate( material.clearcoat ); material.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );
- material.clearcoatRoughness += geometryRoughness;
- material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );
-#endif
-#ifdef USE_DISPERSION
- material.dispersion = dispersion;
-#endif
-#ifdef USE_IRIDESCENCE
- material.iridescence = iridescence;
- material.iridescenceIOR = iridescenceIOR;
- #ifdef USE_IRIDESCENCEMAP
- material.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;
- #endif
- #ifdef USE_IRIDESCENCE_THICKNESSMAP
- material.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;
- #else
- material.iridescenceThickness = iridescenceThicknessMaximum;
- #endif
-#endif
-#ifdef USE_SHEEN
- material.sheenColor = sheenColor;
- #ifdef USE_SHEEN_COLORMAP
- material.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;
- #endif
- material.sheenRoughness = clamp( sheenRoughness, 0.0001, 1.0 );
- #ifdef USE_SHEEN_ROUGHNESSMAP
- material.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;
- #endif
-#endif
-#ifdef USE_ANISOTROPY
- #ifdef USE_ANISOTROPYMAP
- mat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );
- vec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;
- vec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;
- #else
- vec2 anisotropyV = anisotropyVector;
- #endif
- material.anisotropy = length( anisotropyV );
- if( material.anisotropy == 0.0 ) {
- anisotropyV = vec2( 1.0, 0.0 );
- } else {
- anisotropyV /= material.anisotropy;
- material.anisotropy = saturate( material.anisotropy );
- }
- material.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );
- material.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;
- material.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;
-#endif`,lights_physical_pars_fragment:`uniform sampler2D dfgLUT;
-struct PhysicalMaterial {
- vec3 diffuseColor;
- vec3 diffuseContribution;
- vec3 specularColor;
- vec3 specularColorBlended;
- float roughness;
- float metalness;
- float specularF90;
- float dispersion;
- #ifdef USE_CLEARCOAT
- float clearcoat;
- float clearcoatRoughness;
- vec3 clearcoatF0;
- float clearcoatF90;
- #endif
- #ifdef USE_IRIDESCENCE
- float iridescence;
- float iridescenceIOR;
- float iridescenceThickness;
- vec3 iridescenceFresnel;
- vec3 iridescenceF0;
- vec3 iridescenceFresnelDielectric;
- vec3 iridescenceFresnelMetallic;
- #endif
- #ifdef USE_SHEEN
- vec3 sheenColor;
- float sheenRoughness;
- #endif
- #ifdef IOR
- float ior;
- #endif
- #ifdef USE_TRANSMISSION
- float transmission;
- float transmissionAlpha;
- float thickness;
- float attenuationDistance;
- vec3 attenuationColor;
- #endif
- #ifdef USE_ANISOTROPY
- float anisotropy;
- float alphaT;
- vec3 anisotropyT;
- vec3 anisotropyB;
- #endif
-};
-vec3 clearcoatSpecularDirect = vec3( 0.0 );
-vec3 clearcoatSpecularIndirect = vec3( 0.0 );
-vec3 sheenSpecularDirect = vec3( 0.0 );
-vec3 sheenSpecularIndirect = vec3(0.0 );
-vec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {
- float x = clamp( 1.0 - dotVH, 0.0, 1.0 );
- float x2 = x * x;
- float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );
- return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );
-}
-float V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {
- float a2 = pow2( alpha );
- float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );
- float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );
- return 0.5 / max( gv + gl, EPSILON );
-}
-float D_GGX( const in float alpha, const in float dotNH ) {
- float a2 = pow2( alpha );
- float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;
- return RECIPROCAL_PI * a2 / pow2( denom );
-}
-#ifdef USE_ANISOTROPY
- float V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {
- float gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );
- float gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );
- return 0.5 / max( gv + gl, EPSILON );
- }
- float D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {
- float a2 = alphaT * alphaB;
- highp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );
- highp float v2 = dot( v, v );
- float w2 = a2 / v2;
- return RECIPROCAL_PI * a2 * pow2 ( w2 );
- }
-#endif
-#ifdef USE_CLEARCOAT
- vec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {
- vec3 f0 = material.clearcoatF0;
- float f90 = material.clearcoatF90;
- float roughness = material.clearcoatRoughness;
- float alpha = pow2( roughness );
- vec3 halfDir = normalize( lightDir + viewDir );
- float dotNL = saturate( dot( normal, lightDir ) );
- float dotNV = saturate( dot( normal, viewDir ) );
- float dotNH = saturate( dot( normal, halfDir ) );
- float dotVH = saturate( dot( viewDir, halfDir ) );
- vec3 F = F_Schlick( f0, f90, dotVH );
- float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );
- float D = D_GGX( alpha, dotNH );
- return F * ( V * D );
- }
-#endif
-vec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {
- vec3 f0 = material.specularColorBlended;
- float f90 = material.specularF90;
- float roughness = material.roughness;
- float alpha = pow2( roughness );
- vec3 halfDir = normalize( lightDir + viewDir );
- float dotNL = saturate( dot( normal, lightDir ) );
- float dotNV = saturate( dot( normal, viewDir ) );
- float dotNH = saturate( dot( normal, halfDir ) );
- float dotVH = saturate( dot( viewDir, halfDir ) );
- vec3 F = F_Schlick( f0, f90, dotVH );
- #ifdef USE_IRIDESCENCE
- F = mix( F, material.iridescenceFresnel, material.iridescence );
- #endif
- #ifdef USE_ANISOTROPY
- float dotTL = dot( material.anisotropyT, lightDir );
- float dotTV = dot( material.anisotropyT, viewDir );
- float dotTH = dot( material.anisotropyT, halfDir );
- float dotBL = dot( material.anisotropyB, lightDir );
- float dotBV = dot( material.anisotropyB, viewDir );
- float dotBH = dot( material.anisotropyB, halfDir );
- float V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );
- float D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );
- #else
- float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );
- float D = D_GGX( alpha, dotNH );
- #endif
- return F * ( V * D );
-}
-vec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {
- const float LUT_SIZE = 64.0;
- const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;
- const float LUT_BIAS = 0.5 / LUT_SIZE;
- float dotNV = saturate( dot( N, V ) );
- vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );
- uv = uv * LUT_SCALE + LUT_BIAS;
- return uv;
-}
-float LTC_ClippedSphereFormFactor( const in vec3 f ) {
- float l = length( f );
- return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );
-}
-vec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {
- float x = dot( v1, v2 );
- float y = abs( x );
- float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;
- float b = 3.4175940 + ( 4.1616724 + y ) * y;
- float v = a / b;
- float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;
- return cross( v1, v2 ) * theta_sintheta;
-}
-vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {
- vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];
- vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];
- vec3 lightNormal = cross( v1, v2 );
- if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );
- vec3 T1, T2;
- T1 = normalize( V - N * dot( V, N ) );
- T2 = - cross( N, T1 );
- mat3 mat = mInv * transpose( mat3( T1, T2, N ) );
- vec3 coords[ 4 ];
- coords[ 0 ] = mat * ( rectCoords[ 0 ] - P );
- coords[ 1 ] = mat * ( rectCoords[ 1 ] - P );
- coords[ 2 ] = mat * ( rectCoords[ 2 ] - P );
- coords[ 3 ] = mat * ( rectCoords[ 3 ] - P );
- coords[ 0 ] = normalize( coords[ 0 ] );
- coords[ 1 ] = normalize( coords[ 1 ] );
- coords[ 2 ] = normalize( coords[ 2 ] );
- coords[ 3 ] = normalize( coords[ 3 ] );
- vec3 vectorFormFactor = vec3( 0.0 );
- vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );
- vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );
- vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );
- vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );
- float result = LTC_ClippedSphereFormFactor( vectorFormFactor );
- return vec3( result );
-}
-#if defined( USE_SHEEN )
-float D_Charlie( float roughness, float dotNH ) {
- float alpha = pow2( roughness );
- float invAlpha = 1.0 / alpha;
- float cos2h = dotNH * dotNH;
- float sin2h = max( 1.0 - cos2h, 0.0078125 );
- return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );
-}
-float V_Neubelt( float dotNV, float dotNL ) {
- return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );
-}
-vec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {
- vec3 halfDir = normalize( lightDir + viewDir );
- float dotNL = saturate( dot( normal, lightDir ) );
- float dotNV = saturate( dot( normal, viewDir ) );
- float dotNH = saturate( dot( normal, halfDir ) );
- float D = D_Charlie( sheenRoughness, dotNH );
- float V = V_Neubelt( dotNV, dotNL );
- return sheenColor * ( D * V );
-}
-#endif
-float IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {
- float dotNV = saturate( dot( normal, viewDir ) );
- float r2 = roughness * roughness;
- float rInv = 1.0 / ( roughness + 0.1 );
- float a = -1.9362 + 1.0678 * roughness + 0.4573 * r2 - 0.8469 * rInv;
- float b = -0.6014 + 0.5538 * roughness - 0.4670 * r2 - 0.1255 * rInv;
- float DG = exp( a * dotNV + b );
- return saturate( DG );
-}
-vec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {
- float dotNV = saturate( dot( normal, viewDir ) );
- vec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;
- return specularColor * fab.x + specularF90 * fab.y;
-}
-#ifdef USE_IRIDESCENCE
-void computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {
-#else
-void computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {
-#endif
- float dotNV = saturate( dot( normal, viewDir ) );
- vec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;
- #ifdef USE_IRIDESCENCE
- vec3 Fr = mix( specularColor, iridescenceF0, iridescence );
- #else
- vec3 Fr = specularColor;
- #endif
- vec3 FssEss = Fr * fab.x + specularF90 * fab.y;
- float Ess = fab.x + fab.y;
- float Ems = 1.0 - Ess;
- vec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619; vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );
- singleScatter += FssEss;
- multiScatter += Fms * Ems;
-}
-vec3 BRDF_GGX_Multiscatter( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {
- vec3 singleScatter = BRDF_GGX( lightDir, viewDir, normal, material );
- float dotNL = saturate( dot( normal, lightDir ) );
- float dotNV = saturate( dot( normal, viewDir ) );
- vec2 dfgV = texture2D( dfgLUT, vec2( material.roughness, dotNV ) ).rg;
- vec2 dfgL = texture2D( dfgLUT, vec2( material.roughness, dotNL ) ).rg;
- vec3 FssEss_V = material.specularColorBlended * dfgV.x + material.specularF90 * dfgV.y;
- vec3 FssEss_L = material.specularColorBlended * dfgL.x + material.specularF90 * dfgL.y;
- float Ess_V = dfgV.x + dfgV.y;
- float Ess_L = dfgL.x + dfgL.y;
- float Ems_V = 1.0 - Ess_V;
- float Ems_L = 1.0 - Ess_L;
- vec3 Favg = material.specularColorBlended + ( 1.0 - material.specularColorBlended ) * 0.047619;
- vec3 Fms = FssEss_V * FssEss_L * Favg / ( 1.0 - Ems_V * Ems_L * Favg + EPSILON );
- float compensationFactor = Ems_V * Ems_L;
- vec3 multiScatter = Fms * compensationFactor;
- return singleScatter + multiScatter;
-}
-#if NUM_RECT_AREA_LIGHTS > 0
- void RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
- vec3 normal = geometryNormal;
- vec3 viewDir = geometryViewDir;
- vec3 position = geometryPosition;
- vec3 lightPos = rectAreaLight.position;
- vec3 halfWidth = rectAreaLight.halfWidth;
- vec3 halfHeight = rectAreaLight.halfHeight;
- vec3 lightColor = rectAreaLight.color;
- float roughness = material.roughness;
- vec3 rectCoords[ 4 ];
- rectCoords[ 0 ] = lightPos + halfWidth - halfHeight; rectCoords[ 1 ] = lightPos - halfWidth - halfHeight;
- rectCoords[ 2 ] = lightPos - halfWidth + halfHeight;
- rectCoords[ 3 ] = lightPos + halfWidth + halfHeight;
- vec2 uv = LTC_Uv( normal, viewDir, roughness );
- vec4 t1 = texture2D( ltc_1, uv );
- vec4 t2 = texture2D( ltc_2, uv );
- mat3 mInv = mat3(
- vec3( t1.x, 0, t1.y ),
- vec3( 0, 1, 0 ),
- vec3( t1.z, 0, t1.w )
- );
- vec3 fresnel = ( material.specularColorBlended * t2.x + ( material.specularF90 - material.specularColorBlended ) * t2.y );
- reflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );
- reflectedLight.directDiffuse += lightColor * material.diffuseContribution * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );
- #ifdef USE_CLEARCOAT
- vec3 Ncc = geometryClearcoatNormal;
- vec2 uvClearcoat = LTC_Uv( Ncc, viewDir, material.clearcoatRoughness );
- vec4 t1Clearcoat = texture2D( ltc_1, uvClearcoat );
- vec4 t2Clearcoat = texture2D( ltc_2, uvClearcoat );
- mat3 mInvClearcoat = mat3(
- vec3( t1Clearcoat.x, 0, t1Clearcoat.y ),
- vec3( 0, 1, 0 ),
- vec3( t1Clearcoat.z, 0, t1Clearcoat.w )
- );
- vec3 fresnelClearcoat = material.clearcoatF0 * t2Clearcoat.x + ( material.clearcoatF90 - material.clearcoatF0 ) * t2Clearcoat.y;
- clearcoatSpecularDirect += lightColor * fresnelClearcoat * LTC_Evaluate( Ncc, viewDir, position, mInvClearcoat, rectCoords );
- #endif
- }
-#endif
-void RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
- float dotNL = saturate( dot( geometryNormal, directLight.direction ) );
- vec3 irradiance = dotNL * directLight.color;
- #ifdef USE_CLEARCOAT
- float dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );
- vec3 ccIrradiance = dotNLcc * directLight.color;
- clearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );
- #endif
- #ifdef USE_SHEEN
-
- sheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );
-
- float sheenAlbedoV = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );
- float sheenAlbedoL = IBLSheenBRDF( geometryNormal, directLight.direction, material.sheenRoughness );
-
- float sheenEnergyComp = 1.0 - max3( material.sheenColor ) * max( sheenAlbedoV, sheenAlbedoL );
-
- irradiance *= sheenEnergyComp;
-
- #endif
- reflectedLight.directSpecular += irradiance * BRDF_GGX_Multiscatter( directLight.direction, geometryViewDir, geometryNormal, material );
- reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseContribution );
-}
-void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
- vec3 diffuse = irradiance * BRDF_Lambert( material.diffuseContribution );
- #ifdef USE_SHEEN
- float sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );
- float sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;
- diffuse *= sheenEnergyComp;
- #endif
- reflectedLight.indirectDiffuse += diffuse;
-}
-void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {
- #ifdef USE_CLEARCOAT
- clearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );
- #endif
- #ifdef USE_SHEEN
- sheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ) * RECIPROCAL_PI;
- #endif
- vec3 singleScatteringDielectric = vec3( 0.0 );
- vec3 multiScatteringDielectric = vec3( 0.0 );
- vec3 singleScatteringMetallic = vec3( 0.0 );
- vec3 multiScatteringMetallic = vec3( 0.0 );
- #ifdef USE_IRIDESCENCE
- computeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnelDielectric, material.roughness, singleScatteringDielectric, multiScatteringDielectric );
- computeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.iridescence, material.iridescenceFresnelMetallic, material.roughness, singleScatteringMetallic, multiScatteringMetallic );
- #else
- computeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScatteringDielectric, multiScatteringDielectric );
- computeMultiscattering( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.roughness, singleScatteringMetallic, multiScatteringMetallic );
- #endif
- vec3 singleScattering = mix( singleScatteringDielectric, singleScatteringMetallic, material.metalness );
- vec3 multiScattering = mix( multiScatteringDielectric, multiScatteringMetallic, material.metalness );
- vec3 totalScatteringDielectric = singleScatteringDielectric + multiScatteringDielectric;
- vec3 diffuse = material.diffuseContribution * ( 1.0 - totalScatteringDielectric );
- vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;
- vec3 indirectSpecular = radiance * singleScattering;
- indirectSpecular += multiScattering * cosineWeightedIrradiance;
- vec3 indirectDiffuse = diffuse * cosineWeightedIrradiance;
- #ifdef USE_SHEEN
- float sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );
- float sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;
- indirectSpecular *= sheenEnergyComp;
- indirectDiffuse *= sheenEnergyComp;
- #endif
- reflectedLight.indirectSpecular += indirectSpecular;
- reflectedLight.indirectDiffuse += indirectDiffuse;
-}
-#define RE_Direct RE_Direct_Physical
-#define RE_Direct_RectArea RE_Direct_RectArea_Physical
-#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical
-#define RE_IndirectSpecular RE_IndirectSpecular_Physical
-float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {
- return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );
-}`,lights_fragment_begin:`
-vec3 geometryPosition = - vViewPosition;
-vec3 geometryNormal = normal;
-vec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );
-vec3 geometryClearcoatNormal = vec3( 0.0 );
-#ifdef USE_CLEARCOAT
- geometryClearcoatNormal = clearcoatNormal;
-#endif
-#ifdef USE_IRIDESCENCE
- float dotNVi = saturate( dot( normal, geometryViewDir ) );
- if ( material.iridescenceThickness == 0.0 ) {
- material.iridescence = 0.0;
- } else {
- material.iridescence = saturate( material.iridescence );
- }
- if ( material.iridescence > 0.0 ) {
- material.iridescenceFresnelDielectric = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );
- material.iridescenceFresnelMetallic = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.diffuseColor );
- material.iridescenceFresnel = mix( material.iridescenceFresnelDielectric, material.iridescenceFresnelMetallic, material.metalness );
- material.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );
- }
-#endif
-IncidentLight directLight;
-#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )
- PointLight pointLight;
- #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0
- PointLightShadow pointLightShadow;
- #endif
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {
- pointLight = pointLights[ i ];
- getPointLightInfo( pointLight, geometryPosition, directLight );
- #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) )
- pointLightShadow = pointLightShadows[ i ];
- directLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;
- #endif
- RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
- }
- #pragma unroll_loop_end
-#endif
-#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )
- SpotLight spotLight;
- vec4 spotColor;
- vec3 spotLightCoord;
- bool inSpotLightMap;
- #if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0
- SpotLightShadow spotLightShadow;
- #endif
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {
- spotLight = spotLights[ i ];
- getSpotLightInfo( spotLight, geometryPosition, directLight );
- #if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )
- #define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX
- #elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )
- #define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS
- #else
- #define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )
- #endif
- #if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )
- spotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;
- inSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );
- spotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );
- directLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;
- #endif
- #undef SPOT_LIGHT_MAP_INDEX
- #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )
- spotLightShadow = spotLightShadows[ i ];
- directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;
- #endif
- RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
- }
- #pragma unroll_loop_end
-#endif
-#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )
- DirectionalLight directionalLight;
- #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0
- DirectionalLightShadow directionalLightShadow;
- #endif
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
- directionalLight = directionalLights[ i ];
- getDirectionalLightInfo( directionalLight, directLight );
- #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
- directionalLightShadow = directionalLightShadows[ i ];
- directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
- #endif
- RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
- }
- #pragma unroll_loop_end
-#endif
-#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )
- RectAreaLight rectAreaLight;
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {
- rectAreaLight = rectAreaLights[ i ];
- RE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
- }
- #pragma unroll_loop_end
-#endif
-#if defined( RE_IndirectDiffuse )
- vec3 iblIrradiance = vec3( 0.0 );
- vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );
- #if defined( USE_LIGHT_PROBES )
- irradiance += getLightProbeIrradiance( lightProbe, geometryNormal );
- #endif
- #if ( NUM_HEMI_LIGHTS > 0 )
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {
- irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );
- }
- #pragma unroll_loop_end
- #endif
- #ifdef USE_LIGHT_PROBES_GRID
- vec3 probeWorldPos = ( ( vec4( geometryPosition, 1.0 ) - viewMatrix[ 3 ] ) * viewMatrix ).xyz;
- vec3 probeWorldNormal = inverseTransformDirection( geometryNormal, viewMatrix );
- irradiance += getLightProbeGridIrradiance( probeWorldPos, probeWorldNormal );
- #endif
-#endif
-#if defined( RE_IndirectSpecular )
- vec3 radiance = vec3( 0.0 );
- vec3 clearcoatRadiance = vec3( 0.0 );
-#endif`,lights_fragment_maps:`#if defined( RE_IndirectDiffuse )
- #ifdef USE_LIGHTMAP
- vec4 lightMapTexel = texture2D( lightMap, vLightMapUv );
- vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;
- irradiance += lightMapIrradiance;
- #endif
- #if defined( USE_ENVMAP ) && defined( ENVMAP_TYPE_CUBE_UV )
- #if defined( STANDARD ) || defined( LAMBERT ) || defined( PHONG )
- iblIrradiance += getIBLIrradiance( geometryNormal );
- #endif
- #endif
-#endif
-#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )
- #ifdef USE_ANISOTROPY
- radiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );
- #else
- radiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );
- #endif
- #ifdef USE_CLEARCOAT
- clearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );
- #endif
-#endif`,lights_fragment_end:`#if defined( RE_IndirectDiffuse )
- #if defined( LAMBERT ) || defined( PHONG )
- irradiance += iblIrradiance;
- #endif
- RE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
-#endif
-#if defined( RE_IndirectSpecular )
- RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
-#endif`,lightprobes_pars_fragment:`#ifdef USE_LIGHT_PROBES_GRID
-uniform highp sampler3D probesSH;
-uniform vec3 probesMin;
-uniform vec3 probesMax;
-uniform vec3 probesResolution;
-vec3 getLightProbeGridIrradiance( vec3 worldPos, vec3 worldNormal ) {
- vec3 res = probesResolution;
- vec3 gridRange = probesMax - probesMin;
- vec3 resMinusOne = res - 1.0;
- vec3 probeSpacing = gridRange / resMinusOne;
- vec3 samplePos = worldPos + worldNormal * probeSpacing * 0.5;
- vec3 uvw = clamp( ( samplePos - probesMin ) / gridRange, 0.0, 1.0 );
- uvw = uvw * resMinusOne / res + 0.5 / res;
- float nz = res.z;
- float paddedSlices = nz + 2.0;
- float atlasDepth = 7.0 * paddedSlices;
- float uvZBase = uvw.z * nz + 1.0;
- vec4 s0 = texture( probesSH, vec3( uvw.xy, ( uvZBase ) / atlasDepth ) );
- vec4 s1 = texture( probesSH, vec3( uvw.xy, ( uvZBase + paddedSlices ) / atlasDepth ) );
- vec4 s2 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 2.0 * paddedSlices ) / atlasDepth ) );
- vec4 s3 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 3.0 * paddedSlices ) / atlasDepth ) );
- vec4 s4 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 4.0 * paddedSlices ) / atlasDepth ) );
- vec4 s5 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 5.0 * paddedSlices ) / atlasDepth ) );
- vec4 s6 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 6.0 * paddedSlices ) / atlasDepth ) );
- vec3 c0 = s0.xyz;
- vec3 c1 = vec3( s0.w, s1.xy );
- vec3 c2 = vec3( s1.zw, s2.x );
- vec3 c3 = s2.yzw;
- vec3 c4 = s3.xyz;
- vec3 c5 = vec3( s3.w, s4.xy );
- vec3 c6 = vec3( s4.zw, s5.x );
- vec3 c7 = s5.yzw;
- vec3 c8 = s6.xyz;
- float x = worldNormal.x, y = worldNormal.y, z = worldNormal.z;
- vec3 result = c0 * 0.886227;
- result += c1 * 2.0 * 0.511664 * y;
- result += c2 * 2.0 * 0.511664 * z;
- result += c3 * 2.0 * 0.511664 * x;
- result += c4 * 2.0 * 0.429043 * x * y;
- result += c5 * 2.0 * 0.429043 * y * z;
- result += c6 * ( 0.743125 * z * z - 0.247708 );
- result += c7 * 2.0 * 0.429043 * x * z;
- result += c8 * 0.429043 * ( x * x - y * y );
- return max( result, vec3( 0.0 ) );
-}
-#endif`,logdepthbuf_fragment:`#if defined( USE_LOGARITHMIC_DEPTH_BUFFER )
- gl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;
-#endif`,logdepthbuf_pars_fragment:`#if defined( USE_LOGARITHMIC_DEPTH_BUFFER )
- uniform float logDepthBufFC;
- varying float vFragDepth;
- varying float vIsPerspective;
-#endif`,logdepthbuf_pars_vertex:`#ifdef USE_LOGARITHMIC_DEPTH_BUFFER
- varying float vFragDepth;
- varying float vIsPerspective;
-#endif`,logdepthbuf_vertex:`#ifdef USE_LOGARITHMIC_DEPTH_BUFFER
- vFragDepth = 1.0 + gl_Position.w;
- vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );
-#endif`,map_fragment:`#ifdef USE_MAP
- vec4 sampledDiffuseColor = texture2D( map, vMapUv );
- #ifdef DECODE_VIDEO_TEXTURE
- sampledDiffuseColor = sRGBTransferEOTF( sampledDiffuseColor );
- #endif
- diffuseColor *= sampledDiffuseColor;
-#endif`,map_pars_fragment:`#ifdef USE_MAP
- uniform sampler2D map;
-#endif`,map_particle_fragment:`#if defined( USE_MAP ) || defined( USE_ALPHAMAP )
- #if defined( USE_POINTS_UV )
- vec2 uv = vUv;
- #else
- vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;
- #endif
-#endif
-#ifdef USE_MAP
- diffuseColor *= texture2D( map, uv );
-#endif
-#ifdef USE_ALPHAMAP
- diffuseColor.a *= texture2D( alphaMap, uv ).g;
-#endif`,map_particle_pars_fragment:`#if defined( USE_POINTS_UV )
- varying vec2 vUv;
-#else
- #if defined( USE_MAP ) || defined( USE_ALPHAMAP )
- uniform mat3 uvTransform;
- #endif
-#endif
-#ifdef USE_MAP
- uniform sampler2D map;
-#endif
-#ifdef USE_ALPHAMAP
- uniform sampler2D alphaMap;
-#endif`,metalnessmap_fragment:`float metalnessFactor = metalness;
-#ifdef USE_METALNESSMAP
- vec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );
- metalnessFactor *= texelMetalness.b;
-#endif`,metalnessmap_pars_fragment:`#ifdef USE_METALNESSMAP
- uniform sampler2D metalnessMap;
-#endif`,morphinstance_vertex:`#ifdef USE_INSTANCING_MORPH
- float morphTargetInfluences[ MORPHTARGETS_COUNT ];
- float morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;
- for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {
- morphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;
- }
-#endif`,morphcolor_vertex:`#if defined( USE_MORPHCOLORS )
- vColor *= morphTargetBaseInfluence;
- for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {
- #if defined( USE_COLOR_ALPHA )
- if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];
- #elif defined( USE_COLOR )
- if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];
- #endif
- }
-#endif`,morphnormal_vertex:`#ifdef USE_MORPHNORMALS
- objectNormal *= morphTargetBaseInfluence;
- for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {
- if ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];
- }
-#endif`,morphtarget_pars_vertex:`#ifdef USE_MORPHTARGETS
- #ifndef USE_INSTANCING_MORPH
- uniform float morphTargetBaseInfluence;
- uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];
- #endif
- uniform sampler2DArray morphTargetsTexture;
- uniform ivec2 morphTargetsTextureSize;
- vec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {
- int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;
- int y = texelIndex / morphTargetsTextureSize.x;
- int x = texelIndex - y * morphTargetsTextureSize.x;
- ivec3 morphUV = ivec3( x, y, morphTargetIndex );
- return texelFetch( morphTargetsTexture, morphUV, 0 );
- }
-#endif`,morphtarget_vertex:`#ifdef USE_MORPHTARGETS
- transformed *= morphTargetBaseInfluence;
- for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {
- if ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];
- }
-#endif`,normal_fragment_begin:`float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;
-#ifdef FLAT_SHADED
- vec3 fdx = dFdx( vViewPosition );
- vec3 fdy = dFdy( vViewPosition );
- vec3 normal = normalize( cross( fdx, fdy ) );
-#else
- vec3 normal = normalize( vNormal );
- #ifdef DOUBLE_SIDED
- normal *= faceDirection;
- #endif
-#endif
-#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )
- #ifdef USE_TANGENT
- mat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );
- #else
- mat3 tbn = getTangentFrame( - vViewPosition, normal,
- #if defined( USE_NORMALMAP )
- vNormalMapUv
- #elif defined( USE_CLEARCOAT_NORMALMAP )
- vClearcoatNormalMapUv
- #else
- vUv
- #endif
- );
- #endif
- #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )
- tbn[0] *= faceDirection;
- tbn[1] *= faceDirection;
- #endif
-#endif
-#ifdef USE_CLEARCOAT_NORMALMAP
- #ifdef USE_TANGENT
- mat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );
- #else
- mat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );
- #endif
- #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )
- tbn2[0] *= faceDirection;
- tbn2[1] *= faceDirection;
- #endif
-#endif
-vec3 nonPerturbedNormal = normal;`,normal_fragment_maps:`#ifdef USE_NORMALMAP_OBJECTSPACE
- normal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;
- #ifdef FLIP_SIDED
- normal = - normal;
- #endif
- #ifdef DOUBLE_SIDED
- normal = normal * faceDirection;
- #endif
- normal = normalize( normalMatrix * normal );
-#elif defined( USE_NORMALMAP_TANGENTSPACE )
- vec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;
- #if defined( USE_PACKED_NORMALMAP )
- mapN = vec3( mapN.xy, sqrt( saturate( 1.0 - dot( mapN.xy, mapN.xy ) ) ) );
- #endif
- mapN.xy *= normalScale;
- normal = normalize( tbn * mapN );
-#elif defined( USE_BUMPMAP )
- normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );
-#endif`,normal_pars_fragment:`#ifndef FLAT_SHADED
- varying vec3 vNormal;
- #ifdef USE_TANGENT
- varying vec3 vTangent;
- varying vec3 vBitangent;
- #endif
-#endif`,normal_pars_vertex:`#ifndef FLAT_SHADED
- varying vec3 vNormal;
- #ifdef USE_TANGENT
- varying vec3 vTangent;
- varying vec3 vBitangent;
- #endif
-#endif`,normal_vertex:`#ifndef FLAT_SHADED
- vNormal = normalize( transformedNormal );
- #ifdef USE_TANGENT
- vTangent = normalize( transformedTangent );
- vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );
- #endif
-#endif`,normalmap_pars_fragment:`#ifdef USE_NORMALMAP
- uniform sampler2D normalMap;
- uniform vec2 normalScale;
-#endif
-#ifdef USE_NORMALMAP_OBJECTSPACE
- uniform mat3 normalMatrix;
-#endif
-#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )
- mat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {
- vec3 q0 = dFdx( eye_pos.xyz );
- vec3 q1 = dFdy( eye_pos.xyz );
- vec2 st0 = dFdx( uv.st );
- vec2 st1 = dFdy( uv.st );
- vec3 N = surf_norm;
- vec3 q1perp = cross( q1, N );
- vec3 q0perp = cross( N, q0 );
- vec3 T = q1perp * st0.x + q0perp * st1.x;
- vec3 B = q1perp * st0.y + q0perp * st1.y;
- float det = max( dot( T, T ), dot( B, B ) );
- float scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );
- return mat3( T * scale, B * scale, N );
- }
-#endif`,clearcoat_normal_fragment_begin:`#ifdef USE_CLEARCOAT
- vec3 clearcoatNormal = nonPerturbedNormal;
-#endif`,clearcoat_normal_fragment_maps:`#ifdef USE_CLEARCOAT_NORMALMAP
- vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;
- clearcoatMapN.xy *= clearcoatNormalScale;
- clearcoatNormal = normalize( tbn2 * clearcoatMapN );
-#endif`,clearcoat_pars_fragment:`#ifdef USE_CLEARCOATMAP
- uniform sampler2D clearcoatMap;
-#endif
-#ifdef USE_CLEARCOAT_NORMALMAP
- uniform sampler2D clearcoatNormalMap;
- uniform vec2 clearcoatNormalScale;
-#endif
-#ifdef USE_CLEARCOAT_ROUGHNESSMAP
- uniform sampler2D clearcoatRoughnessMap;
-#endif`,iridescence_pars_fragment:`#ifdef USE_IRIDESCENCEMAP
- uniform sampler2D iridescenceMap;
-#endif
-#ifdef USE_IRIDESCENCE_THICKNESSMAP
- uniform sampler2D iridescenceThicknessMap;
-#endif`,opaque_fragment:`#ifdef OPAQUE
-diffuseColor.a = 1.0;
-#endif
-#ifdef USE_TRANSMISSION
-diffuseColor.a *= material.transmissionAlpha;
-#endif
-gl_FragColor = vec4( outgoingLight, diffuseColor.a );`,packing:`vec3 packNormalToRGB( const in vec3 normal ) {
- return normalize( normal ) * 0.5 + 0.5;
-}
-vec3 unpackRGBToNormal( const in vec3 rgb ) {
- return 2.0 * rgb.xyz - 1.0;
-}
-const float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;
-const float Inv255 = 1. / 255.;
-const vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );
-const vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );
-const vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );
-const vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );
-vec4 packDepthToRGBA( const in float v ) {
- if( v <= 0.0 )
- return vec4( 0., 0., 0., 0. );
- if( v >= 1.0 )
- return vec4( 1., 1., 1., 1. );
- float vuf;
- float af = modf( v * PackFactors.a, vuf );
- float bf = modf( vuf * ShiftRight8, vuf );
- float gf = modf( vuf * ShiftRight8, vuf );
- return vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );
-}
-vec3 packDepthToRGB( const in float v ) {
- if( v <= 0.0 )
- return vec3( 0., 0., 0. );
- if( v >= 1.0 )
- return vec3( 1., 1., 1. );
- float vuf;
- float bf = modf( v * PackFactors.b, vuf );
- float gf = modf( vuf * ShiftRight8, vuf );
- return vec3( vuf * Inv255, gf * PackUpscale, bf );
-}
-vec2 packDepthToRG( const in float v ) {
- if( v <= 0.0 )
- return vec2( 0., 0. );
- if( v >= 1.0 )
- return vec2( 1., 1. );
- float vuf;
- float gf = modf( v * 256., vuf );
- return vec2( vuf * Inv255, gf );
-}
-float unpackRGBAToDepth( const in vec4 v ) {
- return dot( v, UnpackFactors4 );
-}
-float unpackRGBToDepth( const in vec3 v ) {
- return dot( v, UnpackFactors3 );
-}
-float unpackRGToDepth( const in vec2 v ) {
- return v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;
-}
-vec4 pack2HalfToRGBA( const in vec2 v ) {
- vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );
- return vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );
-}
-vec2 unpackRGBATo2Half( const in vec4 v ) {
- return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );
-}
-float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {
- return ( viewZ + near ) / ( near - far );
-}
-float orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {
- #ifdef USE_REVERSED_DEPTH_BUFFER
-
- return depth * ( far - near ) - far;
- #else
- return depth * ( near - far ) - near;
- #endif
-}
-float viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {
- return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );
-}
-float perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {
-
- #ifdef USE_REVERSED_DEPTH_BUFFER
- return ( near * far ) / ( ( near - far ) * depth - near );
- #else
- return ( near * far ) / ( ( far - near ) * depth - far );
- #endif
-}`,premultiplied_alpha_fragment:`#ifdef PREMULTIPLIED_ALPHA
- gl_FragColor.rgb *= gl_FragColor.a;
-#endif`,project_vertex:`vec4 mvPosition = vec4( transformed, 1.0 );
-#ifdef USE_BATCHING
- mvPosition = batchingMatrix * mvPosition;
-#endif
-#ifdef USE_INSTANCING
- mvPosition = instanceMatrix * mvPosition;
-#endif
-mvPosition = modelViewMatrix * mvPosition;
-gl_Position = projectionMatrix * mvPosition;`,dithering_fragment:`#ifdef DITHERING
- gl_FragColor.rgb = dithering( gl_FragColor.rgb );
-#endif`,dithering_pars_fragment:`#ifdef DITHERING
- vec3 dithering( vec3 color ) {
- float grid_position = rand( gl_FragCoord.xy );
- vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );
- dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );
- return color + dither_shift_RGB;
- }
-#endif`,roughnessmap_fragment:`float roughnessFactor = roughness;
-#ifdef USE_ROUGHNESSMAP
- vec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );
- roughnessFactor *= texelRoughness.g;
-#endif`,roughnessmap_pars_fragment:`#ifdef USE_ROUGHNESSMAP
- uniform sampler2D roughnessMap;
-#endif`,shadowmap_pars_fragment:`#if NUM_SPOT_LIGHT_COORDS > 0
- varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];
-#endif
-#if NUM_SPOT_LIGHT_MAPS > 0
- uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];
-#endif
-#ifdef USE_SHADOWMAP
- #if NUM_DIR_LIGHT_SHADOWS > 0
- #if defined( SHADOWMAP_TYPE_PCF )
- uniform sampler2DShadow directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];
- #else
- uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];
- #endif
- varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];
- struct DirectionalLightShadow {
- float shadowIntensity;
- float shadowBias;
- float shadowNormalBias;
- float shadowRadius;
- vec2 shadowMapSize;
- };
- uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];
- #endif
- #if NUM_SPOT_LIGHT_SHADOWS > 0
- #if defined( SHADOWMAP_TYPE_PCF )
- uniform sampler2DShadow spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];
- #else
- uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];
- #endif
- struct SpotLightShadow {
- float shadowIntensity;
- float shadowBias;
- float shadowNormalBias;
- float shadowRadius;
- vec2 shadowMapSize;
- };
- uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];
- #endif
- #if NUM_POINT_LIGHT_SHADOWS > 0
- #if defined( SHADOWMAP_TYPE_PCF )
- uniform samplerCubeShadow pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];
- #elif defined( SHADOWMAP_TYPE_BASIC )
- uniform samplerCube pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];
- #endif
- varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];
- struct PointLightShadow {
- float shadowIntensity;
- float shadowBias;
- float shadowNormalBias;
- float shadowRadius;
- vec2 shadowMapSize;
- float shadowCameraNear;
- float shadowCameraFar;
- };
- uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];
- #endif
- #if defined( SHADOWMAP_TYPE_PCF )
- float interleavedGradientNoise( vec2 position ) {
- return fract( 52.9829189 * fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) );
- }
- vec2 vogelDiskSample( int sampleIndex, int samplesCount, float phi ) {
- const float goldenAngle = 2.399963229728653;
- float r = sqrt( ( float( sampleIndex ) + 0.5 ) / float( samplesCount ) );
- float theta = float( sampleIndex ) * goldenAngle + phi;
- return vec2( cos( theta ), sin( theta ) ) * r;
- }
- #endif
- #if defined( SHADOWMAP_TYPE_PCF )
- float getShadow( sampler2DShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {
- float shadow = 1.0;
- shadowCoord.xyz /= shadowCoord.w;
- shadowCoord.z += shadowBias;
- bool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;
- bool frustumTest = inFrustum && shadowCoord.z <= 1.0;
- if ( frustumTest ) {
- vec2 texelSize = vec2( 1.0 ) / shadowMapSize;
- float radius = shadowRadius * texelSize.x;
- float phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;
- shadow = (
- texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 0, 5, phi ) * radius, shadowCoord.z ) ) +
- texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 1, 5, phi ) * radius, shadowCoord.z ) ) +
- texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 2, 5, phi ) * radius, shadowCoord.z ) ) +
- texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 3, 5, phi ) * radius, shadowCoord.z ) ) +
- texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 4, 5, phi ) * radius, shadowCoord.z ) )
- ) * 0.2;
- }
- return mix( 1.0, shadow, shadowIntensity );
- }
- #elif defined( SHADOWMAP_TYPE_VSM )
- float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {
- float shadow = 1.0;
- shadowCoord.xyz /= shadowCoord.w;
- #ifdef USE_REVERSED_DEPTH_BUFFER
- shadowCoord.z -= shadowBias;
- #else
- shadowCoord.z += shadowBias;
- #endif
- bool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;
- bool frustumTest = inFrustum && shadowCoord.z <= 1.0;
- if ( frustumTest ) {
- vec2 distribution = texture2D( shadowMap, shadowCoord.xy ).rg;
- float mean = distribution.x;
- float variance = distribution.y * distribution.y;
- #ifdef USE_REVERSED_DEPTH_BUFFER
- float hard_shadow = step( mean, shadowCoord.z );
- #else
- float hard_shadow = step( shadowCoord.z, mean );
- #endif
-
- if ( hard_shadow == 1.0 ) {
- shadow = 1.0;
- } else {
- variance = max( variance, 0.0000001 );
- float d = shadowCoord.z - mean;
- float p_max = variance / ( variance + d * d );
- p_max = clamp( ( p_max - 0.3 ) / 0.65, 0.0, 1.0 );
- shadow = max( hard_shadow, p_max );
- }
- }
- return mix( 1.0, shadow, shadowIntensity );
- }
- #else
- float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {
- float shadow = 1.0;
- shadowCoord.xyz /= shadowCoord.w;
- #ifdef USE_REVERSED_DEPTH_BUFFER
- shadowCoord.z -= shadowBias;
- #else
- shadowCoord.z += shadowBias;
- #endif
- bool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;
- bool frustumTest = inFrustum && shadowCoord.z <= 1.0;
- if ( frustumTest ) {
- float depth = texture2D( shadowMap, shadowCoord.xy ).r;
- #ifdef USE_REVERSED_DEPTH_BUFFER
- shadow = step( depth, shadowCoord.z );
- #else
- shadow = step( shadowCoord.z, depth );
- #endif
- }
- return mix( 1.0, shadow, shadowIntensity );
- }
- #endif
- #if NUM_POINT_LIGHT_SHADOWS > 0
- #if defined( SHADOWMAP_TYPE_PCF )
- float getPointShadow( samplerCubeShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {
- float shadow = 1.0;
- vec3 lightToPosition = shadowCoord.xyz;
- vec3 bd3D = normalize( lightToPosition );
- vec3 absVec = abs( lightToPosition );
- float viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );
- if ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {
- #ifdef USE_REVERSED_DEPTH_BUFFER
- float dp = ( shadowCameraNear * ( shadowCameraFar - viewSpaceZ ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );
- dp -= shadowBias;
- #else
- float dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );
- dp += shadowBias;
- #endif
- float texelSize = shadowRadius / shadowMapSize.x;
- vec3 absDir = abs( bd3D );
- vec3 tangent = absDir.x > absDir.z ? vec3( 0.0, 1.0, 0.0 ) : vec3( 1.0, 0.0, 0.0 );
- tangent = normalize( cross( bd3D, tangent ) );
- vec3 bitangent = cross( bd3D, tangent );
- float phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;
- vec2 sample0 = vogelDiskSample( 0, 5, phi );
- vec2 sample1 = vogelDiskSample( 1, 5, phi );
- vec2 sample2 = vogelDiskSample( 2, 5, phi );
- vec2 sample3 = vogelDiskSample( 3, 5, phi );
- vec2 sample4 = vogelDiskSample( 4, 5, phi );
- shadow = (
- texture( shadowMap, vec4( bd3D + ( tangent * sample0.x + bitangent * sample0.y ) * texelSize, dp ) ) +
- texture( shadowMap, vec4( bd3D + ( tangent * sample1.x + bitangent * sample1.y ) * texelSize, dp ) ) +
- texture( shadowMap, vec4( bd3D + ( tangent * sample2.x + bitangent * sample2.y ) * texelSize, dp ) ) +
- texture( shadowMap, vec4( bd3D + ( tangent * sample3.x + bitangent * sample3.y ) * texelSize, dp ) ) +
- texture( shadowMap, vec4( bd3D + ( tangent * sample4.x + bitangent * sample4.y ) * texelSize, dp ) )
- ) * 0.2;
- }
- return mix( 1.0, shadow, shadowIntensity );
- }
- #elif defined( SHADOWMAP_TYPE_BASIC )
- float getPointShadow( samplerCube shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {
- float shadow = 1.0;
- vec3 lightToPosition = shadowCoord.xyz;
- vec3 absVec = abs( lightToPosition );
- float viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );
- if ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {
- float dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );
- dp += shadowBias;
- vec3 bd3D = normalize( lightToPosition );
- float depth = textureCube( shadowMap, bd3D ).r;
- #ifdef USE_REVERSED_DEPTH_BUFFER
- depth = 1.0 - depth;
- #endif
- shadow = step( dp, depth );
- }
- return mix( 1.0, shadow, shadowIntensity );
- }
- #endif
- #endif
-#endif`,shadowmap_pars_vertex:`#if NUM_SPOT_LIGHT_COORDS > 0
- uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];
- varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];
-#endif
-#ifdef USE_SHADOWMAP
- #if NUM_DIR_LIGHT_SHADOWS > 0
- uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];
- varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];
- struct DirectionalLightShadow {
- float shadowIntensity;
- float shadowBias;
- float shadowNormalBias;
- float shadowRadius;
- vec2 shadowMapSize;
- };
- uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];
- #endif
- #if NUM_SPOT_LIGHT_SHADOWS > 0
- struct SpotLightShadow {
- float shadowIntensity;
- float shadowBias;
- float shadowNormalBias;
- float shadowRadius;
- vec2 shadowMapSize;
- };
- uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];
- #endif
- #if NUM_POINT_LIGHT_SHADOWS > 0
- uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];
- varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];
- struct PointLightShadow {
- float shadowIntensity;
- float shadowBias;
- float shadowNormalBias;
- float shadowRadius;
- vec2 shadowMapSize;
- float shadowCameraNear;
- float shadowCameraFar;
- };
- uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];
- #endif
-#endif`,shadowmap_vertex:`#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )
- #ifdef HAS_NORMAL
- vec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );
- #else
- vec3 shadowWorldNormal = vec3( 0.0 );
- #endif
- vec4 shadowWorldPosition;
-#endif
-#if defined( USE_SHADOWMAP )
- #if NUM_DIR_LIGHT_SHADOWS > 0
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {
- shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );
- vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;
- }
- #pragma unroll_loop_end
- #endif
- #if NUM_POINT_LIGHT_SHADOWS > 0
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {
- shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );
- vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;
- }
- #pragma unroll_loop_end
- #endif
-#endif
-#if NUM_SPOT_LIGHT_COORDS > 0
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {
- shadowWorldPosition = worldPosition;
- #if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )
- shadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;
- #endif
- vSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;
- }
- #pragma unroll_loop_end
-#endif`,shadowmask_pars_fragment:`float getShadowMask() {
- float shadow = 1.0;
- #ifdef USE_SHADOWMAP
- #if NUM_DIR_LIGHT_SHADOWS > 0
- DirectionalLightShadow directionalLight;
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {
- directionalLight = directionalLightShadows[ i ];
- shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
- }
- #pragma unroll_loop_end
- #endif
- #if NUM_SPOT_LIGHT_SHADOWS > 0
- SpotLightShadow spotLight;
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {
- spotLight = spotLightShadows[ i ];
- shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;
- }
- #pragma unroll_loop_end
- #endif
- #if NUM_POINT_LIGHT_SHADOWS > 0 && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) )
- PointLightShadow pointLight;
- #pragma unroll_loop_start
- for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {
- pointLight = pointLightShadows[ i ];
- shadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;
- }
- #pragma unroll_loop_end
- #endif
- #endif
- return shadow;
-}`,skinbase_vertex:`#ifdef USE_SKINNING
- mat4 boneMatX = getBoneMatrix( skinIndex.x );
- mat4 boneMatY = getBoneMatrix( skinIndex.y );
- mat4 boneMatZ = getBoneMatrix( skinIndex.z );
- mat4 boneMatW = getBoneMatrix( skinIndex.w );
-#endif`,skinning_pars_vertex:`#ifdef USE_SKINNING
- uniform mat4 bindMatrix;
- uniform mat4 bindMatrixInverse;
- uniform highp sampler2D boneTexture;
- mat4 getBoneMatrix( const in float i ) {
- int size = textureSize( boneTexture, 0 ).x;
- int j = int( i ) * 4;
- int x = j % size;
- int y = j / size;
- vec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );
- vec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );
- vec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );
- vec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );
- return mat4( v1, v2, v3, v4 );
- }
-#endif`,skinning_vertex:`#ifdef USE_SKINNING
- vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );
- vec4 skinned = vec4( 0.0 );
- skinned += boneMatX * skinVertex * skinWeight.x;
- skinned += boneMatY * skinVertex * skinWeight.y;
- skinned += boneMatZ * skinVertex * skinWeight.z;
- skinned += boneMatW * skinVertex * skinWeight.w;
- transformed = ( bindMatrixInverse * skinned ).xyz;
-#endif`,skinnormal_vertex:`#ifdef USE_SKINNING
- mat4 skinMatrix = mat4( 0.0 );
- skinMatrix += skinWeight.x * boneMatX;
- skinMatrix += skinWeight.y * boneMatY;
- skinMatrix += skinWeight.z * boneMatZ;
- skinMatrix += skinWeight.w * boneMatW;
- skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;
- objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;
- #ifdef USE_TANGENT
- objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;
- #endif
-#endif`,specularmap_fragment:`float specularStrength;
-#ifdef USE_SPECULARMAP
- vec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );
- specularStrength = texelSpecular.r;
-#else
- specularStrength = 1.0;
-#endif`,specularmap_pars_fragment:`#ifdef USE_SPECULARMAP
- uniform sampler2D specularMap;
-#endif`,tonemapping_fragment:`#if defined( TONE_MAPPING )
- gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );
-#endif`,tonemapping_pars_fragment:`#ifndef saturate
-#define saturate( a ) clamp( a, 0.0, 1.0 )
-#endif
-uniform float toneMappingExposure;
-vec3 LinearToneMapping( vec3 color ) {
- return saturate( toneMappingExposure * color );
-}
-vec3 ReinhardToneMapping( vec3 color ) {
- color *= toneMappingExposure;
- return saturate( color / ( vec3( 1.0 ) + color ) );
-}
-vec3 CineonToneMapping( vec3 color ) {
- color *= toneMappingExposure;
- color = max( vec3( 0.0 ), color - 0.004 );
- return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );
-}
-vec3 RRTAndODTFit( vec3 v ) {
- vec3 a = v * ( v + 0.0245786 ) - 0.000090537;
- vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;
- return a / b;
-}
-vec3 ACESFilmicToneMapping( vec3 color ) {
- const mat3 ACESInputMat = mat3(
- vec3( 0.59719, 0.07600, 0.02840 ), vec3( 0.35458, 0.90834, 0.13383 ),
- vec3( 0.04823, 0.01566, 0.83777 )
- );
- const mat3 ACESOutputMat = mat3(
- vec3( 1.60475, -0.10208, -0.00327 ), vec3( -0.53108, 1.10813, -0.07276 ),
- vec3( -0.07367, -0.00605, 1.07602 )
- );
- color *= toneMappingExposure / 0.6;
- color = ACESInputMat * color;
- color = RRTAndODTFit( color );
- color = ACESOutputMat * color;
- return saturate( color );
-}
-const mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(
- vec3( 1.6605, - 0.1246, - 0.0182 ),
- vec3( - 0.5876, 1.1329, - 0.1006 ),
- vec3( - 0.0728, - 0.0083, 1.1187 )
-);
-const mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(
- vec3( 0.6274, 0.0691, 0.0164 ),
- vec3( 0.3293, 0.9195, 0.0880 ),
- vec3( 0.0433, 0.0113, 0.8956 )
-);
-vec3 agxDefaultContrastApprox( vec3 x ) {
- vec3 x2 = x * x;
- vec3 x4 = x2 * x2;
- return + 15.5 * x4 * x2
- - 40.14 * x4 * x
- + 31.96 * x4
- - 6.868 * x2 * x
- + 0.4298 * x2
- + 0.1191 * x
- - 0.00232;
-}
-vec3 AgXToneMapping( vec3 color ) {
- const mat3 AgXInsetMatrix = mat3(
- vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),
- vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),
- vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )
- );
- const mat3 AgXOutsetMatrix = mat3(
- vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),
- vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),
- vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )
- );
- const float AgxMinEv = - 12.47393; const float AgxMaxEv = 4.026069;
- color *= toneMappingExposure;
- color = LINEAR_SRGB_TO_LINEAR_REC2020 * color;
- color = AgXInsetMatrix * color;
- color = max( color, 1e-10 ); color = log2( color );
- color = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );
- color = clamp( color, 0.0, 1.0 );
- color = agxDefaultContrastApprox( color );
- color = AgXOutsetMatrix * color;
- color = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );
- color = LINEAR_REC2020_TO_LINEAR_SRGB * color;
- color = clamp( color, 0.0, 1.0 );
- return color;
-}
-vec3 NeutralToneMapping( vec3 color ) {
- const float StartCompression = 0.8 - 0.04;
- const float Desaturation = 0.15;
- color *= toneMappingExposure;
- float x = min( color.r, min( color.g, color.b ) );
- float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;
- color -= offset;
- float peak = max( color.r, max( color.g, color.b ) );
- if ( peak < StartCompression ) return color;
- float d = 1. - StartCompression;
- float newPeak = 1. - d * d / ( peak + d - StartCompression );
- color *= newPeak / peak;
- float g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );
- return mix( color, vec3( newPeak ), g );
-}
-vec3 CustomToneMapping( vec3 color ) { return color; }`,transmission_fragment:`#ifdef USE_TRANSMISSION
- material.transmission = transmission;
- material.transmissionAlpha = 1.0;
- material.thickness = thickness;
- material.attenuationDistance = attenuationDistance;
- material.attenuationColor = attenuationColor;
- #ifdef USE_TRANSMISSIONMAP
- material.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;
- #endif
- #ifdef USE_THICKNESSMAP
- material.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;
- #endif
- vec3 pos = vWorldPosition;
- vec3 v = normalize( cameraPosition - pos );
- vec3 n = inverseTransformDirection( normal, viewMatrix );
- vec4 transmitted = getIBLVolumeRefraction(
- n, v, material.roughness, material.diffuseContribution, material.specularColorBlended, material.specularF90,
- pos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,
- material.attenuationColor, material.attenuationDistance );
- material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );
- totalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );
-#endif`,transmission_pars_fragment:`#ifdef USE_TRANSMISSION
- uniform float transmission;
- uniform float thickness;
- uniform float attenuationDistance;
- uniform vec3 attenuationColor;
- #ifdef USE_TRANSMISSIONMAP
- uniform sampler2D transmissionMap;
- #endif
- #ifdef USE_THICKNESSMAP
- uniform sampler2D thicknessMap;
- #endif
- uniform vec2 transmissionSamplerSize;
- uniform sampler2D transmissionSamplerMap;
- uniform mat4 modelMatrix;
- uniform mat4 projectionMatrix;
- varying vec3 vWorldPosition;
- float w0( float a ) {
- return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );
- }
- float w1( float a ) {
- return ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );
- }
- float w2( float a ){
- return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );
- }
- float w3( float a ) {
- return ( 1.0 / 6.0 ) * ( a * a * a );
- }
- float g0( float a ) {
- return w0( a ) + w1( a );
- }
- float g1( float a ) {
- return w2( a ) + w3( a );
- }
- float h0( float a ) {
- return - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );
- }
- float h1( float a ) {
- return 1.0 + w3( a ) / ( w2( a ) + w3( a ) );
- }
- vec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {
- uv = uv * texelSize.zw + 0.5;
- vec2 iuv = floor( uv );
- vec2 fuv = fract( uv );
- float g0x = g0( fuv.x );
- float g1x = g1( fuv.x );
- float h0x = h0( fuv.x );
- float h1x = h1( fuv.x );
- float h0y = h0( fuv.y );
- float h1y = h1( fuv.y );
- vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;
- vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;
- vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;
- vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;
- return g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +
- g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );
- }
- vec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {
- vec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );
- vec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );
- vec2 fLodSizeInv = 1.0 / fLodSize;
- vec2 cLodSizeInv = 1.0 / cLodSize;
- vec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );
- vec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );
- return mix( fSample, cSample, fract( lod ) );
- }
- vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {
- vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );
- vec3 modelScale;
- modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );
- modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );
- modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );
- return normalize( refractionVector ) * thickness * modelScale;
- }
- float applyIorToRoughness( const in float roughness, const in float ior ) {
- return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );
- }
- vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {
- float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );
- return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );
- }
- vec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {
- if ( isinf( attenuationDistance ) ) {
- return vec3( 1.0 );
- } else {
- vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;
- vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); return transmittance;
- }
- }
- vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,
- const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,
- const in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,
- const in vec3 attenuationColor, const in float attenuationDistance ) {
- vec4 transmittedLight;
- vec3 transmittance;
- #ifdef USE_DISPERSION
- float halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;
- vec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );
- for ( int i = 0; i < 3; i ++ ) {
- vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );
- vec3 refractedRayExit = position + transmissionRay;
- vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );
- vec2 refractionCoords = ndcPos.xy / ndcPos.w;
- refractionCoords += 1.0;
- refractionCoords /= 2.0;
- vec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );
- transmittedLight[ i ] = transmissionSample[ i ];
- transmittedLight.a += transmissionSample.a;
- transmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];
- }
- transmittedLight.a /= 3.0;
- #else
- vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );
- vec3 refractedRayExit = position + transmissionRay;
- vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );
- vec2 refractionCoords = ndcPos.xy / ndcPos.w;
- refractionCoords += 1.0;
- refractionCoords /= 2.0;
- transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );
- transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );
- #endif
- vec3 attenuatedColor = transmittance * transmittedLight.rgb;
- vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );
- float transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;
- return vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );
- }
-#endif`,uv_pars_fragment:`#if defined( USE_UV ) || defined( USE_ANISOTROPY )
- varying vec2 vUv;
-#endif
-#ifdef USE_MAP
- varying vec2 vMapUv;
-#endif
-#ifdef USE_ALPHAMAP
- varying vec2 vAlphaMapUv;
-#endif
-#ifdef USE_LIGHTMAP
- varying vec2 vLightMapUv;
-#endif
-#ifdef USE_AOMAP
- varying vec2 vAoMapUv;
-#endif
-#ifdef USE_BUMPMAP
- varying vec2 vBumpMapUv;
-#endif
-#ifdef USE_NORMALMAP
- varying vec2 vNormalMapUv;
-#endif
-#ifdef USE_EMISSIVEMAP
- varying vec2 vEmissiveMapUv;
-#endif
-#ifdef USE_METALNESSMAP
- varying vec2 vMetalnessMapUv;
-#endif
-#ifdef USE_ROUGHNESSMAP
- varying vec2 vRoughnessMapUv;
-#endif
-#ifdef USE_ANISOTROPYMAP
- varying vec2 vAnisotropyMapUv;
-#endif
-#ifdef USE_CLEARCOATMAP
- varying vec2 vClearcoatMapUv;
-#endif
-#ifdef USE_CLEARCOAT_NORMALMAP
- varying vec2 vClearcoatNormalMapUv;
-#endif
-#ifdef USE_CLEARCOAT_ROUGHNESSMAP
- varying vec2 vClearcoatRoughnessMapUv;
-#endif
-#ifdef USE_IRIDESCENCEMAP
- varying vec2 vIridescenceMapUv;
-#endif
-#ifdef USE_IRIDESCENCE_THICKNESSMAP
- varying vec2 vIridescenceThicknessMapUv;
-#endif
-#ifdef USE_SHEEN_COLORMAP
- varying vec2 vSheenColorMapUv;
-#endif
-#ifdef USE_SHEEN_ROUGHNESSMAP
- varying vec2 vSheenRoughnessMapUv;
-#endif
-#ifdef USE_SPECULARMAP
- varying vec2 vSpecularMapUv;
-#endif
-#ifdef USE_SPECULAR_COLORMAP
- varying vec2 vSpecularColorMapUv;
-#endif
-#ifdef USE_SPECULAR_INTENSITYMAP
- varying vec2 vSpecularIntensityMapUv;
-#endif
-#ifdef USE_TRANSMISSIONMAP
- uniform mat3 transmissionMapTransform;
- varying vec2 vTransmissionMapUv;
-#endif
-#ifdef USE_THICKNESSMAP
- uniform mat3 thicknessMapTransform;
- varying vec2 vThicknessMapUv;
-#endif`,uv_pars_vertex:`#if defined( USE_UV ) || defined( USE_ANISOTROPY )
- varying vec2 vUv;
-#endif
-#ifdef USE_MAP
- uniform mat3 mapTransform;
- varying vec2 vMapUv;
-#endif
-#ifdef USE_ALPHAMAP
- uniform mat3 alphaMapTransform;
- varying vec2 vAlphaMapUv;
-#endif
-#ifdef USE_LIGHTMAP
- uniform mat3 lightMapTransform;
- varying vec2 vLightMapUv;
-#endif
-#ifdef USE_AOMAP
- uniform mat3 aoMapTransform;
- varying vec2 vAoMapUv;
-#endif
-#ifdef USE_BUMPMAP
- uniform mat3 bumpMapTransform;
- varying vec2 vBumpMapUv;
-#endif
-#ifdef USE_NORMALMAP
- uniform mat3 normalMapTransform;
- varying vec2 vNormalMapUv;
-#endif
-#ifdef USE_DISPLACEMENTMAP
- uniform mat3 displacementMapTransform;
- varying vec2 vDisplacementMapUv;
-#endif
-#ifdef USE_EMISSIVEMAP
- uniform mat3 emissiveMapTransform;
- varying vec2 vEmissiveMapUv;
-#endif
-#ifdef USE_METALNESSMAP
- uniform mat3 metalnessMapTransform;
- varying vec2 vMetalnessMapUv;
-#endif
-#ifdef USE_ROUGHNESSMAP
- uniform mat3 roughnessMapTransform;
- varying vec2 vRoughnessMapUv;
-#endif
-#ifdef USE_ANISOTROPYMAP
- uniform mat3 anisotropyMapTransform;
- varying vec2 vAnisotropyMapUv;
-#endif
-#ifdef USE_CLEARCOATMAP
- uniform mat3 clearcoatMapTransform;
- varying vec2 vClearcoatMapUv;
-#endif
-#ifdef USE_CLEARCOAT_NORMALMAP
- uniform mat3 clearcoatNormalMapTransform;
- varying vec2 vClearcoatNormalMapUv;
-#endif
-#ifdef USE_CLEARCOAT_ROUGHNESSMAP
- uniform mat3 clearcoatRoughnessMapTransform;
- varying vec2 vClearcoatRoughnessMapUv;
-#endif
-#ifdef USE_SHEEN_COLORMAP
- uniform mat3 sheenColorMapTransform;
- varying vec2 vSheenColorMapUv;
-#endif
-#ifdef USE_SHEEN_ROUGHNESSMAP
- uniform mat3 sheenRoughnessMapTransform;
- varying vec2 vSheenRoughnessMapUv;
-#endif
-#ifdef USE_IRIDESCENCEMAP
- uniform mat3 iridescenceMapTransform;
- varying vec2 vIridescenceMapUv;
-#endif
-#ifdef USE_IRIDESCENCE_THICKNESSMAP
- uniform mat3 iridescenceThicknessMapTransform;
- varying vec2 vIridescenceThicknessMapUv;
-#endif
-#ifdef USE_SPECULARMAP
- uniform mat3 specularMapTransform;
- varying vec2 vSpecularMapUv;
-#endif
-#ifdef USE_SPECULAR_COLORMAP
- uniform mat3 specularColorMapTransform;
- varying vec2 vSpecularColorMapUv;
-#endif
-#ifdef USE_SPECULAR_INTENSITYMAP
- uniform mat3 specularIntensityMapTransform;
- varying vec2 vSpecularIntensityMapUv;
-#endif
-#ifdef USE_TRANSMISSIONMAP
- uniform mat3 transmissionMapTransform;
- varying vec2 vTransmissionMapUv;
-#endif
-#ifdef USE_THICKNESSMAP
- uniform mat3 thicknessMapTransform;
- varying vec2 vThicknessMapUv;
-#endif`,uv_vertex:`#if defined( USE_UV ) || defined( USE_ANISOTROPY )
- vUv = vec3( uv, 1 ).xy;
-#endif
-#ifdef USE_MAP
- vMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_ALPHAMAP
- vAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_LIGHTMAP
- vLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_AOMAP
- vAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_BUMPMAP
- vBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_NORMALMAP
- vNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_DISPLACEMENTMAP
- vDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_EMISSIVEMAP
- vEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_METALNESSMAP
- vMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_ROUGHNESSMAP
- vRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_ANISOTROPYMAP
- vAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_CLEARCOATMAP
- vClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_CLEARCOAT_NORMALMAP
- vClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_CLEARCOAT_ROUGHNESSMAP
- vClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_IRIDESCENCEMAP
- vIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_IRIDESCENCE_THICKNESSMAP
- vIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_SHEEN_COLORMAP
- vSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_SHEEN_ROUGHNESSMAP
- vSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_SPECULARMAP
- vSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_SPECULAR_COLORMAP
- vSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_SPECULAR_INTENSITYMAP
- vSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_TRANSMISSIONMAP
- vTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;
-#endif
-#ifdef USE_THICKNESSMAP
- vThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;
-#endif`,worldpos_vertex:`#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0
- vec4 worldPosition = vec4( transformed, 1.0 );
- #ifdef USE_BATCHING
- worldPosition = batchingMatrix * worldPosition;
- #endif
- #ifdef USE_INSTANCING
- worldPosition = instanceMatrix * worldPosition;
- #endif
- worldPosition = modelMatrix * worldPosition;
-#endif`,background_vert:`varying vec2 vUv;
-uniform mat3 uvTransform;
-void main() {
- vUv = ( uvTransform * vec3( uv, 1 ) ).xy;
- gl_Position = vec4( position.xy, 1.0, 1.0 );
-}`,background_frag:`uniform sampler2D t2D;
-uniform float backgroundIntensity;
-varying vec2 vUv;
-void main() {
- vec4 texColor = texture2D( t2D, vUv );
- #ifdef DECODE_VIDEO_TEXTURE
- texColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );
- #endif
- texColor.rgb *= backgroundIntensity;
- gl_FragColor = texColor;
- #include
- #include
-}`,backgroundCube_vert:`varying vec3 vWorldDirection;
-#include
-void main() {
- vWorldDirection = transformDirection( position, modelMatrix );
- #include
- #include
- gl_Position.z = gl_Position.w;
-}`,backgroundCube_frag:`#ifdef ENVMAP_TYPE_CUBE
- uniform samplerCube envMap;
-#elif defined( ENVMAP_TYPE_CUBE_UV )
- uniform sampler2D envMap;
-#endif
-uniform float backgroundBlurriness;
-uniform float backgroundIntensity;
-uniform mat3 backgroundRotation;
-varying vec3 vWorldDirection;
-#include
-void main() {
- #ifdef ENVMAP_TYPE_CUBE
- vec4 texColor = textureCube( envMap, backgroundRotation * vWorldDirection );
- #elif defined( ENVMAP_TYPE_CUBE_UV )
- vec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );
- #else
- vec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );
- #endif
- texColor.rgb *= backgroundIntensity;
- gl_FragColor = texColor;
- #include
- #include
-}`,cube_vert:`varying vec3 vWorldDirection;
-#include
-void main() {
- vWorldDirection = transformDirection( position, modelMatrix );
- #include
- #include
- gl_Position.z = gl_Position.w;
-}`,cube_frag:`uniform samplerCube tCube;
-uniform float tFlip;
-uniform float opacity;
-varying vec3 vWorldDirection;
-void main() {
- vec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );
- gl_FragColor = texColor;
- gl_FragColor.a *= opacity;
- #include
- #include
-}`,depth_vert:`#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-varying vec2 vHighPrecisionZW;
-void main() {
- #include
- #include
- #include
- #include
- #ifdef USE_DISPLACEMENTMAP
- #include
- #include
- #include
- #endif
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- vHighPrecisionZW = gl_Position.zw;
-}`,depth_frag:`#if DEPTH_PACKING == 3200
- uniform float opacity;
-#endif
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-varying vec2 vHighPrecisionZW;
-void main() {
- vec4 diffuseColor = vec4( 1.0 );
- #include
- #if DEPTH_PACKING == 3200
- diffuseColor.a = opacity;
- #endif
- #include
- #include
- #include
- #include
- #include
- #ifdef USE_REVERSED_DEPTH_BUFFER
- float fragCoordZ = vHighPrecisionZW[ 0 ] / vHighPrecisionZW[ 1 ];
- #else
- float fragCoordZ = 0.5 * vHighPrecisionZW[ 0 ] / vHighPrecisionZW[ 1 ] + 0.5;
- #endif
- #if DEPTH_PACKING == 3200
- gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );
- #elif DEPTH_PACKING == 3201
- gl_FragColor = packDepthToRGBA( fragCoordZ );
- #elif DEPTH_PACKING == 3202
- gl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );
- #elif DEPTH_PACKING == 3203
- gl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );
- #endif
-}`,distance_vert:`#define DISTANCE
-varying vec3 vWorldPosition;
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-void main() {
- #include
- #include
- #include
- #include
- #ifdef USE_DISPLACEMENTMAP
- #include
- #include
- #include
- #endif
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- vWorldPosition = worldPosition.xyz;
-}`,distance_frag:`#define DISTANCE
-uniform vec3 referencePosition;
-uniform float nearDistance;
-uniform float farDistance;
-varying vec3 vWorldPosition;
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-void main () {
- vec4 diffuseColor = vec4( 1.0 );
- #include
- #include
- #include
- #include
- #include
- float dist = length( vWorldPosition - referencePosition );
- dist = ( dist - nearDistance ) / ( farDistance - nearDistance );
- dist = saturate( dist );
- gl_FragColor = vec4( dist, 0.0, 0.0, 1.0 );
-}`,equirect_vert:`varying vec3 vWorldDirection;
-#include
-void main() {
- vWorldDirection = transformDirection( position, modelMatrix );
- #include
- #include
-}`,equirect_frag:`uniform sampler2D tEquirect;
-varying vec3 vWorldDirection;
-#include
-void main() {
- vec3 direction = normalize( vWorldDirection );
- vec2 sampleUV = equirectUv( direction );
- gl_FragColor = texture2D( tEquirect, sampleUV );
- #include
- #include
-}`,linedashed_vert:`uniform float scale;
-attribute float lineDistance;
-varying float vLineDistance;
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-void main() {
- vLineDistance = scale * lineDistance;
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-}`,linedashed_frag:`uniform vec3 diffuse;
-uniform float opacity;
-uniform float dashSize;
-uniform float totalSize;
-varying float vLineDistance;
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-void main() {
- vec4 diffuseColor = vec4( diffuse, opacity );
- #include
- if ( mod( vLineDistance, totalSize ) > dashSize ) {
- discard;
- }
- vec3 outgoingLight = vec3( 0.0 );
- #include
- #include
- #include
- outgoingLight = diffuseColor.rgb;
- #include
- #include
- #include
- #include
- #include
-}`,meshbasic_vert:`#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-void main() {
- #include
- #include
- #include
- #include
- #include
- #if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )
- #include
- #include
- #include
- #include
- #include
- #endif
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-}`,meshbasic_frag:`uniform vec3 diffuse;
-uniform float opacity;
-#ifndef FLAT_SHADED
- varying vec3 vNormal;
-#endif
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-void main() {
- vec4 diffuseColor = vec4( diffuse, opacity );
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
- #ifdef USE_LIGHTMAP
- vec4 lightMapTexel = texture2D( lightMap, vLightMapUv );
- reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;
- #else
- reflectedLight.indirectDiffuse += vec3( 1.0 );
- #endif
- #include
- reflectedLight.indirectDiffuse *= diffuseColor.rgb;
- vec3 outgoingLight = reflectedLight.indirectDiffuse;
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-}`,meshlambert_vert:`#define LAMBERT
-varying vec3 vViewPosition;
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-void main() {
- #include
- #include
- #include