mirror of
https://github.com/dmduran12/pymc_console-dist.git
synced 2026-03-28 17:43:04 +01:00
2 lines
140 KiB
JavaScript
2 lines
140 KiB
JavaScript
import{r as e,j as t,a as o}from"./vendor-react-alRNW2nb.js";import{u as n,S as r,L as s,P as a,M as i,b as l}from"./maplibre-gl-BwLPRSIs.js";import{u as c,r as u,e as d,f as m,g as h}from"./consumer-registry-BUFl6buY.js";import{L as g,c as p}from"./link-scoring-C0BjaK96.js";import{G as f,dd as x,bb as y,Z as b,de as v,df as j,dg as w,an as N,at as C,J as k,b as M,B as S,ap as F,Y as R,_ as T,dh as L,m as E,p as B,ba as D,di as H,V as $,a6 as A,a8 as P,ar as z,ca as I,dj as q,dk as O,cs as W,H as _,aF as U,dl as K,dm as V,a1 as Z,h as G,dn as J,ag as Y,db as Q,ai as X,b3 as ee,r as te,dp as oe,cm as ne,dq as re}from"./index-CkRTgHHA.js";import{C as se}from"./ConfirmModal-B6Rz8ROW.js";import{g as ae,a as ie,b as le,D as ce}from"./DeepAnalysisModal-L9EkN490.js";import{c as ue,a as de,p as me,e as he}from"./vendor-core-FtpmsTnh.js";import{j as ge,K as pe,bo as fe,aX as xe,ah as ye,C as be,W as ve,Y as je,bp as we,d as Ne,c as Ce,bq as ke,aS as Me,aL as Se,b7 as Fe,b as Re,aG as Te,br as Le,L as Ee,bs as Be,Z as De,bt as He,R as $e,X as Ae,aM as Pe,as as ze,aR as Ie,bu as qe,bh as Oe,bv as We,bw as _e,a as Ue,a5 as Ke,aK as Ve,U as Ze,bx as Ge,D as Je,o as Ye,an as Qe,T as Xe,aq as et,a1 as tt,by as ot}from"./vendor-icons-TO0PZKGR.js";import{m as nt,A as rt,b as st}from"./vendor-motion-DNp0Qg4F.js";import{A as at,D as it,u as lt}from"./useMapViewStore-sFZdb1_p.js";import{u as ct,a as ut,B as dt}from"./BasemapLayer-CSqjQAiA.js";import{l as mt,c as ht,a as gt}from"./vendor-geo-2MTwbTwv.js";import{c as pt}from"./node-types-DRVunROD.js";import{a as ft,b as xt,c as yt}from"./easing-GXZYrvDD.js";import{H as bt,C as vt,N as jt,a as wt}from"./badge-colors-BxLppqaF.js";import{L as Nt}from"./LightSparkline-BAD3v4m9.js";import{P as Ct}from"./Contacts-CcN2zB34.js";import{c as kt}from"./geo-utils-DJn8DnxF.js";import"./vendor-virt-BytWoLhu.js";import"./cosmograph-DqYT4sUA.js";import"./vendor-charts-C916_-gs.js";import"./vendor-fonts-CRZaZSFf.js";import"./ping-DPgnsJJf.js";import"./PageLayout-BWMUVZgC.js";import"./listbox-DrzA7Ewq.js";import"./TimeRangeStepper-CsLZzi5t.js";import"./chat-utils-mqGCinix.js";import"./SignalIndicator-Bdj3-1hL.js";import"./CollisionExplorerModal-BUHEIiWh.js";import"./DataBox-DpDXI-WX.js";function Mt(e,t){const o=Math.max(5,Math.min(e,300)),n=Math.log(5),r=Math.log(300);return 1+(Math.log(o)-n)/(r-n)*5}function St(){const t=f();return e.useMemo(()=>x.getPackets(),[t])}const Ft={textPrimary:b[900],textSecondary:"#4A4A4A",textMuted:b[500],border:"rgba(0, 0, 0, 0.12)",hoverBg:"rgba(0, 0, 0, 0.06)",disabledText:"rgba(0, 0, 0, 0.25)"},Rt={nodeFill:y.blue,nodeStroke:"rgba(255,255,255,0.9)",nodeColor:y.indigo,localColor:y.amber,hubColor:y.purple,gatewayColor:y.indigo,mobileColor:y.orange,roomServerColor:y.pink,neighborColor:y.amber,edges:{rest:b[700],restBright:b[600],restDim:b[800],hoverDirect:"#6FBCBD",hoverLoop:"#8B7BAD",hoverStandard:b[400],hoverNeighbor:y.amber,neighborRest:b[500],neighborHover:y.amber,highlight:"#FFD700"},edgeOpacity:.82};function Tt(){if("undefined"==typeof window)return Rt;const e=v(),t=j();return{nodeFill:e.nodeFill,nodeStroke:e.nodeStroke,nodeColor:Rt.nodeColor,localColor:e.localColor,hubColor:e.hubColor,gatewayColor:e.gatewayColor,mobileColor:e.mobileColor,roomServerColor:e.roomColor,neighborColor:e.neighborColor,edges:{rest:t.rest,restBright:t.restBright,restDim:t.restDim,hoverDirect:t.hoverDirect,hoverLoop:t.hoverLoop,hoverStandard:t.hoverStandard,hoverNeighbor:t.hoverNeighbor,neighborRest:Rt.edges.neighborRest,neighborHover:Rt.edges.neighborHover,highlight:t.highlight},edgeOpacity:Rt.edgeOpacity}}const Lt=2e3,Et=M.snappy,Bt=Ft,Dt=e.createContext("dark"),Ht=()=>e.useContext(Dt);function $t({color:e,ring:o}){return t.jsx("span",{className:"shrink-0 rounded-full","aria-hidden":"true",style:{width:14,height:14,backgroundColor:o?"transparent":e,border:o?`4px solid ${e}`:void 0,boxSizing:"border-box"}})}function At({color:e,pattern:o="solid"}){return t.jsx("svg",{className:"shrink-0","aria-hidden":"true",width:18,height:6,viewBox:"0 0 18 6",children:t.jsx("line",{x1:0,y1:3,x2:18,y2:3,stroke:e,strokeWidth:3,strokeLinecap:"round",strokeDasharray:"dashed"===o?"5,3":"dotted"===o?"2,3":void 0})})}function Pt({indicator:e,label:o,tooltip:n}){const r="light"===Ht();return t.jsxs("div",{className:"flex items-center gap-1.5",children:[e,t.jsx("span",{className:ue(!r&&"text-fg-secondary"),style:r?{color:Bt.textSecondary}:void 0,children:o}),n&&t.jsx(k,{content:n,delay:200,children:t.jsx("span",{className:ue("cursor-help text-[11px] opacity-75 hover:opacity-100 transition-opacity",!r&&"text-fg-muted"),style:r?{color:Bt.textMuted}:void 0,children:"ⓘ"})})]})}function zt({title:e,tooltip:o,isOpen:n,onToggle:r,showDivider:s,children:a}){const i="light"===Ht(),l=function(e){return`legend-section-${e.toLowerCase().replace(/\s+/g,"-")}`}(e);return t.jsxs("div",{className:s?"mt-2 pt-2 border-t":"",style:s?{borderColor:i?Bt.border:"var(--map-ui-border)"}:void 0,children:[t.jsxs("button",{type:"button",onClick:r,"aria-expanded":n,"aria-controls":l,className:ue("group w-full flex items-center justify-between py-1 min-h-[44px] sm:min-h-0 font-medium transition-colors",!i&&"text-fg-secondary hover:text-fg-primary"),style:i?{color:Bt.textSecondary}:void 0,children:[t.jsxs("span",{className:"flex items-center gap-1",children:[e,t.jsx(k,{content:o,delay:200,children:t.jsx("span",{className:ue("cursor-help text-[11px] opacity-75 group-hover:opacity-100 transition-opacity",!i&&"text-fg-muted"),style:i?{color:Bt.textMuted}:void 0,children:"ⓘ"})})]}),t.jsx(nt.span,{animate:{rotate:n?0:-90},transition:{duration:.15},"aria-hidden":"true",children:t.jsx(be,{className:"w-3 h-3",style:i?{color:Bt.textMuted}:{color:"var(--fg-muted)"}})})]}),t.jsx(rt,{initial:!1,children:n&&t.jsx(nt.div,{id:l,role:"region","aria-label":e,initial:{height:0,opacity:0},animate:{height:"auto",opacity:1},exit:{height:0,opacity:0},transition:Et,className:"overflow-hidden",children:t.jsx("div",{className:"flex flex-col gap-1 pt-1.5",children:a})})})]})}function It({label:e,value:o,color:n}){const r="light"===Ht();return t.jsxs("div",{className:ue("flex justify-between tabular-nums",!r&&"text-fg-muted"),style:r?{color:Bt.textMuted}:void 0,children:[t.jsx("span",{children:e}),t.jsx("span",{style:n?{color:n}:r?{color:Bt.textSecondary}:{color:"var(--fg-secondary)"},children:o})]})}function qt({icon:e,color:o,title:n,subtitle:r}){const s="light"===Ht();return t.jsx("div",{className:"mt-1.5 pt-1.5 border-t",style:{borderColor:s?Bt.border:"var(--map-ui-border)"},children:t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx("span",{className:"shrink-0",style:{color:o},children:e}),t.jsxs("div",{className:"flex flex-col min-w-0",children:[t.jsx("span",{className:"font-medium truncate",style:{color:o},children:n}),t.jsx("span",{className:ue("text-[10px] leading-tight",!s&&"text-fg-muted"),style:s?{color:Bt.textMuted}:void 0,children:r})]})]})})}function Ot({showTopology:o,validatedPolylineCount:n,filteredNeighborCount:r,hasLocalNode:s,meshTopology:a,zeroHopNeighbors:i,neighborsWithLocation:l,basemapMode:c="dark"}){const u=w(),d=N(),m=C(),h=d.filter(e=>e.isLikelyReal).length,p=function(e){let t=0;for(const o of e.txDelayRecommendations.values())"backbone"===o.networkRole&&t++;return t}(a),f=i.size>0,[x,y]=e.useState(!0),[b,v]=e.useState(!0),[j,k]=e.useState(!0);return t.jsx(Dt.Provider,{value:c,children:t.jsxs("div",{className:"map-control-surface p-2.5 text-xs",children:[t.jsxs(zt,{title:"Nodes",tooltip:"Node type shown by shape + color. Yellow = direct RF neighbor.",isOpen:x,onToggle:()=>y(e=>!e),children:[t.jsx(Pt,{indicator:t.jsx($t,{color:u.nodeFill}),label:"Node",tooltip:"Standard mesh node. Repeater, client, or companion device."}),t.jsx(Pt,{indicator:t.jsx($t,{color:u.hubColor}),label:"Hub",tooltip:"Network hub (≥10% of last-hop traffic)."}),(M=l,M.some(([,e])=>{var t;const o=null==(t=e.contact_type)?void 0:t.toLowerCase();return"room server"===o||"room_server"===o||"room"===o||"server"===o})&&t.jsx(Pt,{indicator:t.jsx(ge,{className:"w-3 h-3 shrink-0",style:{color:u.roomColor},strokeWidth:2.5}),label:"Room",tooltip:"Room Server identity for client sync."})),t.jsx(Pt,{indicator:t.jsx(pe,{className:"w-3 h-3 shrink-0",style:{color:u.localColor},strokeWidth:2.5}),label:"Local",tooltip:"Your repeater running pyMC_Repeater."}),f&&t.jsx(Pt,{indicator:t.jsx($t,{color:u.neighborColor}),label:"Neighbor",tooltip:"Zero-hop direct RF contact."}),a.gatewayNodes.length>0&&t.jsx(Pt,{indicator:t.jsx($t,{color:u.gatewayColor}),label:"Gateway",tooltip:"Significant forwarder (7-10% traffic)."}),p>0&&t.jsx(Pt,{indicator:t.jsx($t,{color:u.hubColor}),label:"Backbone",tooltip:"Critical relay with high centrality."}),a.mobileNodes.length>0&&t.jsx(Pt,{indicator:t.jsx($t,{color:u.mobileColor,ring:!0}),label:"Mobile",tooltip:"Volatile node that appears/disappears."}),h>0&&t.jsx(Pt,{indicator:t.jsx(fe,{className:"w-3 h-3 shrink-0",style:{color:u.ghostColor},strokeWidth:2.5}),label:`Ghost (${h})`,tooltip:"Unknown repeater from Viterbi analysis."})]}),f&&t.jsxs(zt,{title:"Link Quality",tooltip:"Neighbor edge colors based on bidirectional balance.",isOpen:b,onToggle:()=>v(e=>!e),showDivider:!0,children:[t.jsx(Pt,{indicator:t.jsx(At,{color:g.YELLOW,pattern:"solid"}),label:"2-Way",tooltip:"33-67% balanced. Ideal bidirectional link."}),t.jsx(Pt,{indicator:t.jsx(At,{color:g.GREEN,pattern:"dashed"}),label:"Listener",tooltip:">67% listener. They hear us well."}),t.jsx(Pt,{indicator:t.jsx(At,{color:g.RED,pattern:"dotted"}),label:"Loud",tooltip:"<33% listener. They route more to us."})]}),o&&n>0&&t.jsxs(zt,{title:"Topology",tooltip:"Links with 5+ validations. Thickness = strength.",isOpen:j,onToggle:()=>k(e=>!e),showDivider:!0,children:[t.jsx(It,{label:"Nodes",value:r+(s?1:0)}),a.hubNodes.length>0&&t.jsx(It,{label:"Hubs",value:a.hubNodes.length,color:Rt.hubColor}),a.loops.length>0&&t.jsx(qt,{icon:t.jsx(xe,{className:"w-3 h-3"}),color:Rt.edges.hoverLoop,title:`${a.loops.length} ${1===a.loops.length?"Loop":"Loops"}`,subtitle:"Redundant paths"}),m.totalPaths>0&&t.jsx(qt,{icon:t.jsx(ye,{className:"w-3 h-3"}),color:u.ghostColor,title:`${m.totalPaths.toLocaleString()} Viterbi`,subtitle:"HMM decoded paths"})]})]})});var M}const Wt={repeater:"blue",companion:"cyan",room_server:"pink",hubs:"indigo",direct:"green"},_t={repeater:"Repeaters",companion:"Companions",room_server:"Rooms",hubs:"Hubs",direct:"Direct"},Ut={repeater:"Repeater nodes (mesh relays)",companion:"Companion devices (clients)",room_server:"Room server nodes",hubs:"Hub nodes and their connections",direct:"Zero-hop (direct RF) neighbors"},Kt=["repeater","companion","room_server"],Vt=["hubs","direct"],Zt="!p-2.5 sm:!p-1.5 !rounded-md min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 shrink-0 flex items-center justify-center",Gt="!p-2.5 sm:!p-1.5 !rounded-none min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 shrink-0 flex items-center justify-center";function Jt({mapRef:o,showNeighborLines:n,onToggleNeighborLines:r,hasNeighborPolylines:s,nodeFilters:a,onToggleFilter:i,onToggleAll:l,filterCounts:c,showCoverage:u,onToggleCoverage:d,showMinCut:m=!1,onToggleMinCut:h,hasMinCutData:g=!1,show3DTerrain:p,onToggle3DTerrain:f,basemapMode:x,onToggleBasemap:y,isFullscreen:b,onToggleFullscreen:v,showLinkQuality:j=!1,onToggleLinkQuality:w,hasTraceLinks:N=!1}){const[C,k]=e.useState(()=>!("undefined"!=typeof window&&window.innerWidth<640)),M="w-4 h-4",R="light"===x?"#525252":"var(--fg-secondary)",T=a.length>=at.length;return t.jsx(t.Fragment,{children:t.jsxs("div",{className:"absolute top-3 right-3 z-[600] flex flex-col gap-2 sm:top-4 sm:right-4 max-w-[calc(100vw-1.5rem)] sm:max-w-none pr-[env(safe-area-inset-right)]",children:[t.jsxs("div",{className:"map-control-surface flex flex-nowrap items-center gap-0.5 sm:gap-1 p-1 overflow-hidden",children:[s&&t.jsx(S,{plain:!0,color:n?"warning":"muted",onClick:r,title:n?"Hide edge lines":"Show edge lines","aria-label":n?"Hide edge lines":"Show edge lines","aria-pressed":n,className:Zt,"data-tint":n?"warning":void 0,children:t.jsx(ve,{className:M})}),t.jsx(S,{plain:!0,color:"muted",onClick:()=>k(e=>!e),title:C?"Hide node filters":"Show node filters","aria-label":C?"Collapse node filters":"Expand node filters","aria-expanded":C,className:Zt,children:t.jsx(je,{className:M})}),t.jsx(rt,{initial:!1,children:C&&t.jsxs(nt.div,{className:"flex items-center gap-0.5 flex-nowrap overflow-x-auto scrollbar-none max-w-[50vw] sm:max-w-none sm:overflow-visible",role:"group","aria-label":"Node type filters",initial:{width:0,opacity:0},animate:{width:"auto",opacity:1},exit:{width:0,opacity:0},transition:{duration:.2,ease:[.4,0,.2,1]},children:[t.jsx(F,{color:T?"green":"zinc",customColor:T?void 0:R,onClick:l,title:"Show all nodes","aria-pressed":T,"aria-label":"Show all node types",className:"shrink-0",children:"All"}),Kt.map(e=>{const o=c[e];if(0===o)return null;const n=!T&&a.includes(e);return t.jsx(F,{color:n?Wt[e]:"zinc",customColor:n?void 0:R,onClick:()=>i(e),title:Ut[e],"aria-pressed":n,"aria-label":`${_t[e]} (${o})`,className:"shrink-0",children:_t[e]},e)}),Vt.some(e=>c[e]>0)&&t.jsx("span",{className:"mx-0.5 h-3 w-px bg-[var(--map-ui-border,var(--edge-subtle))] hidden sm:block shrink-0","aria-hidden":"true"}),Vt.map(e=>{const o=c[e];if(0===o)return null;const n=!T&&a.includes(e);return t.jsx(F,{color:n?Wt[e]:"zinc",customColor:n?void 0:R,onClick:()=>i(e),title:Ut[e],"aria-pressed":n,"aria-label":`${_t[e]} (${o})`,className:"shrink-0",children:_t[e]},e)})]})}),g&&h&&t.jsx(S,{plain:!0,color:m?"primary":"muted",onClick:h,title:m?"Hide community partition":"Show community partition","aria-label":m?"Hide community partition":"Show community partition","aria-pressed":m,className:Zt,"data-tint":m?"primary":void 0,children:t.jsx(we,{className:M})}),t.jsx(S,{plain:!0,color:"light"===x?"primary":"muted",onClick:y,title:"light"===x?"Switch to dark map":"Switch to light map","aria-label":"light"===x?"Switch to dark map":"Switch to light map","aria-pressed":"light"===x,className:Zt,"data-tint":"light"===x?"primary":void 0,children:"light"===x?t.jsx(Ne,{className:M}):t.jsx(Ce,{className:M})}),t.jsx(S,{plain:!0,color:p?"success":"muted",onClick:f,title:p?"Disable 3D terrain":"Enable 3D terrain","aria-label":p?"Disable 3D terrain":"Enable 3D terrain","aria-pressed":p,className:Zt,"data-tint":p?"success":void 0,children:t.jsx(ke,{className:M})}),t.jsx(S,{plain:!0,color:"muted",onClick:v,title:b?"Exit fullscreen":"Fullscreen","aria-label":b?"Exit fullscreen":"Enter fullscreen","aria-pressed":b,className:Zt,children:b?t.jsx(Me,{className:M}):t.jsx(Se,{className:M})})]}),t.jsxs("div",{className:"map-control-surface flex flex-col items-stretch !overflow-hidden self-end !p-0",children:[t.jsx(S,{plain:!0,color:"muted",onClick:()=>{var e,t;null==(t=null==(e=o.current)?void 0:e.getMap())||t.zoomIn()},title:"Zoom in","aria-label":"Zoom in",className:Gt,children:t.jsx(Fe,{className:M})}),t.jsx("div",{className:"h-px bg-border-subtle","aria-hidden":"true"}),t.jsx(S,{plain:!0,color:"muted",onClick:()=>{var e,t;null==(t=null==(e=o.current)?void 0:e.getMap())||t.zoomOut()},title:"Zoom out","aria-label":"Zoom out",className:Gt,children:t.jsx(Re,{className:M})}),t.jsx("div",{className:"h-px bg-border-subtle","aria-hidden":"true"}),t.jsx(S,{plain:!0,color:"muted",onClick:()=>{var e;const t=null==(e=o.current)?void 0:e.getMap();t&&t.easeTo({bearing:0,pitch:0,duration:300})},title:"Reset bearing to north","aria-label":"Reset bearing to north",className:Gt,children:t.jsx(Te,{className:M})})]}),N&&w&&t.jsx("div",{className:"map-control-surface flex flex-col items-stretch !overflow-hidden self-end !p-0",children:t.jsx(S,{plain:!0,color:j?"success":"muted",onClick:w,title:j?"Hide link quality overlay":"Show link quality overlay","aria-label":j?"Hide link quality overlay":"Show link quality overlay","aria-pressed":j,className:Gt,"data-tint":j?"success":void 0,children:t.jsx(Le,{className:M})})})]})})}const Yt={text:Ft.textSecondary,activeText:"#16A34A",activeBg:"rgba(220, 252, 231, 1)"},Qt="DeepAnalysis";function Xt(){return"abcdefghijklmnopqrstuvwxyz0123456789"[Math.floor(36*Math.random())]}function eo({isActive:o,hasAnalyzed:n,isLoading:r,onClick:s,basemapMode:a="dark"}){const i="light"===a,l=i?Yt.text:void 0,c=i?Yt.activeText:"#4ADE80",[u,d]=e.useState(!1),[m,h]=e.useState(Qt),g=e.useRef(!1),p=e.useRef(null),[f]=e.useState(()=>{var e;return"undefined"!=typeof window&&((null==(e=window.matchMedia)?void 0:e.call(window,"(hover: hover)").matches)??!1)}),x=u&&!o&&!r&&f;e.useEffect(()=>{if(u&&!o&&!r&&!g.current){g.current=!0;const e=performance.now(),t=o=>{const n=o-e,r=Math.min(n/700,1),s=Math.floor(12*r);let a="";for(let e=0;e<12;e++)a+=e<s?Qt[e]:" "===Qt[e]?" ":Xt();h(a),r<1?p.current=requestAnimationFrame(t):h(Qt)};p.current=requestAnimationFrame(t)}return u||(p.current&&(cancelAnimationFrame(p.current),p.current=null),g.current=!1,h(Qt)),()=>{p.current&&cancelAnimationFrame(p.current)}},[u,o,r]);const y=r?"Analyzing...":m,b=r?"Analyzing packet history":n?o?"Hide topology edges":"Show topology edges":"Load full packet history and build topology";return t.jsxs("button",{onClick:s,onMouseEnter:()=>f&&d(!0),onMouseLeave:()=>f&&d(!1),onPointerEnter:()=>f&&d(!0),onPointerLeave:()=>f&&d(!1),disabled:r,className:"map-tool-btn flex items-center gap-2 w-full text-left radius-inner transition-base "+(r?"cursor-wait":""),style:{padding:"0.5rem 0.625rem",...o&&{backgroundColor:i?Yt.activeBg:"rgba(10, 26, 10, 1)"}},title:b,"aria-label":b,"aria-pressed":o,children:[r?t.jsx(Ee,{className:"w-3.5 h-3.5 shrink-0 animate-spin",style:{color:c}}):t.jsx(Be,{className:"w-3.5 h-3.5 shrink-0 transition-colors "+(o?"":"text-fg-secondary"),style:{...o&&{color:c},...x&&{color:c},...!o&&!x&&l&&{color:l}}}),t.jsx("span",{className:o?"":"text-fg-secondary","aria-hidden":"true",style:{fontFamily:"ui-monospace, SFMono-Regular, monospace",fontSize:"0.6875rem",fontWeight:o||x?700:500,letterSpacing:"-0.01em",lineHeight:1,...o&&{color:c},...x&&{color:c},...!o&&!x&&l&&{color:l}},children:y})]})}const to=y.teal,oo={text:Ft.textSecondary,activeTeal:"#0D7377",activeBg:"rgba(204, 251, 241, 1)"};function no({isActive:o,onClick:n,basemapMode:r="dark"}){const s="light"===r,a=s?oo.text:void 0,i=s?oo.activeTeal:to,[l,c]=e.useState(!1),[u,d]=e.useState(0),m=e.useRef(!1),h=e.useRef(null),[g,p]=e.useState(0),f=e.useRef(!1),[x]=e.useState(()=>{var e;return"undefined"!=typeof window&&((null==(e=window.matchMedia)?void 0:e.call(window,"(hover: hover)").matches)??!1)}),y=l&&!o&&x;e.useEffect(()=>{y&&!f.current&&(f.current=!0,p(1),setTimeout(()=>p(2),100),setTimeout(()=>p(3),200)),l||(f.current=!1,p(0))},[y,l]),e.useEffect(()=>{if(l&&!o&&!m.current){m.current=!0;const e=performance.now(),t=o=>{const n=o-e,r=Math.min(n/400,1);d(r),r<1&&(h.current=requestAnimationFrame(t))};h.current=requestAnimationFrame(t)}return l||(h.current&&(cancelAnimationFrame(h.current),h.current=null),m.current=!1,d(0)),()=>{h.current&&cancelAnimationFrame(h.current)}},[l,o]);const b=e=>{if(o)return i;if(!y)return a;const t=11*u;return e>=t-2&&e<t?"#FFFFFF":i},v=o?"Disable live packet tracing":"Enable live packet tracing";return t.jsxs("button",{onClick:n,onMouseEnter:()=>x&&c(!0),onMouseLeave:()=>x&&c(!1),onPointerEnter:()=>x&&c(!0),onPointerLeave:()=>x&&c(!1),className:"map-tool-btn flex items-center gap-2 w-full text-left radius-inner transition-base",style:{padding:"0.5rem 0.625rem",...o&&{backgroundColor:s?oo.activeBg:"rgba(10, 36, 32, 1)"}},title:o?"Disable live packet tracing (reduces CPU usage)":"Enable live packet tracing","aria-label":v,"aria-pressed":o,children:[t.jsx(De,{className:"w-3.5 h-3.5 shrink-0 "+(o?"":"text-fg-secondary"),fill:1===g?"#FFFFFF":3===g?i:"none",stroke:1===g||2===g?"#FFFFFF":o||y?i:a||"currentColor",style:{transition:"fill 0.05s, stroke 0.05s"}}),t.jsx("span",{className:o?"":"text-fg-secondary","aria-hidden":"true",style:{fontFamily:"ui-monospace, SFMono-Regular, monospace",fontSize:"0.6875rem",fontWeight:o||y?700:500,letterSpacing:"-0.01em",lineHeight:1},children:"LiveTrace".split("").map((e,o)=>t.jsx("span",{style:{color:b(o)||void 0},children:e},o))})]})}const ro={text:Ft.textSecondary,activeBg:"rgba(254, 243, 199, 1)",disabledText:Ft.disabledText},so="#fe8019";function ao({isActive:o,onClick:n,brightness:r=.7,onBrightnessChange:s,basemapMode:a="dark"}){const i="light"===a,l=i?ro.text:void 0,[c,u]=e.useState(!1),[d,m]=e.useState(!1),[h]=e.useState(()=>{var e;return"undefined"!=typeof window&&((null==(e=window.matchMedia)?void 0:e.call(window,"(hover: hover)").matches)??!1)});e.useEffect(()=>{if(!c||o)return;const e=requestAnimationFrame(()=>m(!0)),t=setTimeout(()=>m(!1),80);return()=>{cancelAnimationFrame(e),clearTimeout(t)}},[c,o]);const g=Math.max(.01,Math.min(1,r)),p=g<.999,f=g>.011,x=c&&!o&&h,y=o?"Configure wardriving coverage":"Show wardriving coverage";return t.jsxs("button",{onClick:n,onMouseEnter:()=>h&&u(!0),onMouseLeave:()=>h&&u(!1),onPointerEnter:()=>h&&u(!0),onPointerLeave:()=>h&&u(!1),className:"map-tool-btn flex items-center gap-2 w-full text-left radius-inner transition-base",style:{padding:"0.5rem 0.625rem",...o&&{backgroundColor:i?ro.activeBg:"rgba(26, 20, 8, 1)"}},title:y,"aria-label":y,"aria-pressed":o,children:[t.jsx(He,{className:"w-3.5 h-3.5 shrink-0 transition-colors "+(o?"text-sys-amber":"text-fg-secondary"),style:x?{color:so}:!o&&l?{color:l}:void 0}),t.jsx("span",{className:o?"text-sys-amber":"text-fg-secondary","aria-hidden":"true",style:{fontFamily:o||x?"'Wardrive', serif":"ui-monospace, SFMono-Regular, monospace",fontSize:o||x?"0.75rem":"0.6875rem",fontWeight:500,letterSpacing:"-0.01em",lineHeight:1,transition:"none",transform:o?"scale(1.45)":x?`scale(${d?1.595:1.45})`:void 0,transformOrigin:"left center",...x?{color:so}:!o&&l?{color:l}:{}},children:"Wardrive"}),o&&s&&t.jsxs("div",{className:"ml-auto flex items-center gap-0.5",children:[t.jsx("button",{onClick:e=>{e.stopPropagation();const t=Math.max(.01,g-.2);null==s||s(t)},disabled:!f,className:"p-1 sm:p-0.5 min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 flex items-center justify-center rounded transition-colors "+(f?"text-sys-amber hover:bg-[var(--map-ui-hover,var(--elevated))] active:bg-[var(--map-ui-active,var(--subtle))]":"cursor-not-allowed"),style:f?void 0:{color:i?ro.disabledText:"rgba(251, 191, 36, 0.3)"},title:`Decrease opacity (${Math.round(100*g)}%)`,"aria-label":`Decrease opacity, currently ${Math.round(100*g)}%`,children:t.jsx(Ne,{className:"w-3.5 h-3.5"})}),t.jsx("button",{onClick:e=>{e.stopPropagation();const t=Math.min(1,g+.2);null==s||s(t)},disabled:!p,className:"p-1 sm:p-0.5 min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 flex items-center justify-center rounded transition-colors "+(p?"text-sys-amber hover:bg-[var(--map-ui-hover,var(--elevated))] active:bg-[var(--map-ui-active,var(--subtle))]":"cursor-not-allowed"),style:p?void 0:{color:i?ro.disabledText:"rgba(251, 191, 36, 0.3)"},title:`Increase opacity (${Math.round(100*g)}%)`,"aria-label":`Increase opacity, currently ${Math.round(100*g)}%`,children:t.jsx(Ce,{className:"w-3.5 h-3.5"})})]})]})}function io(e){let t=!0,o=-90,n=90,r=-180,s=180;for(const a of e.toLowerCase()){const e="0123456789bcdefghjkmnpqrstuvwxyz".indexOf(a);if(-1!==e)for(let a=4;a>=0;a--){const i=e>>a&1;if(t){const e=(r+s)/2;i?r=e:s=e}else{const e=(o+n)/2;i?o=e:n=e}t=!t}}return{lat:(o+n)/2,lon:(r+s)/2}}function lo(e){return Math.exp(-e*Math.LN2/7)}const co="pymc-wardriving-url",uo="pymc-wardriving-enabled",mo="pymc-wardriving-brightness";function ho(e){"undefined"!=typeof localStorage&&(e?localStorage.setItem(co,e):localStorage.removeItem(co))}function go(e){"undefined"!=typeof localStorage&&localStorage.setItem(uo,String(e))}function po(){if("undefined"==typeof localStorage)return.7;const e=localStorage.getItem(mo);if(e){const t=parseFloat(e);if(!isNaN(t)&&t>=.01&&t<=1)return t}return.7}function fo(e,t=null){if(null!==e){const o=(Math.max(-12,Math.min(12,e))+12)/24;return null!==t?.8*o+(Math.max(-120,Math.min(-50,t))+120)/70*.2:o}return null!==t?(Math.max(-120,Math.min(-50,t))+120)/70:.5}const xo=de((e,t)=>({status:"idle",isVisible:"undefined"!=typeof localStorage&&"true"===localStorage.getItem(uo),coveragePoints:[],repeaters:[],error:null,stats:{coverageCount:0,repeaterCount:0,lastUpdated:null},url:"undefined"==typeof localStorage?"":localStorage.getItem(co)||"",brightness:po(),isModalOpen:!1,openModal:()=>e({isModalOpen:!0}),closeModal:()=>e({isModalOpen:!1}),setUrl:t=>e({url:t}),setBrightness:t=>{const o=Math.max(.01,Math.min(1,t));!function(e){if("undefined"==typeof localStorage)return;const t=Math.max(.01,Math.min(1,e));localStorage.setItem(mo,String(t))}(o),e({brightness:o})},toggleVisibility:()=>{const o=!t().isVisible;go(o),e({isVisible:o})},setVisible:t=>{go(t),e({isVisible:t})},loadCoverage:async t=>{if(!t.trim())return e({error:"Please enter a URL",status:"error"}),!1;try{new URL(t.trim())}catch{return e({error:"Invalid URL format",status:"error"}),!1}e({error:null,status:"connecting"});try{e({status:"loading"});const o=await async function(e){const t=`${e.replace(/\/+$/,"").replace(/\/get-nodes$/,"").replace(/\/get-samples$/,"")}/get-samples`,o=await async function(e,t={},o=8e3){const n=new AbortController,r=setTimeout(()=>n.abort(),o);try{return await fetch(e,{...t,signal:n.signal})}catch(s){if(s instanceof Error&&"AbortError"===s.name)throw new Error(`Connection timed out after ${o/1e3}s`);throw s}finally{clearTimeout(r)}}(t,{headers:{Accept:"application/json"}});if(!o.ok)throw new Error(`Failed to fetch precise samples: ${o.status}`);return o.json()}(t.trim());if(!o||"object"!=typeof o)throw new Error("Invalid response from server");if(!Array.isArray(o.keys))throw new Error("No sample data found in response");e({status:"processing"});const n=function(e){var t;const o=[];for(const n of e.keys){if(!n.observed)continue;const{lat:e,lon:r}=io(n.hash),s=parseInt(n.time,10),a=isNaN(s)?30:(Date.now()-s)/864e5,i=lo(a),l=fo(n.snr,n.rssi)*(.3+.7*i);o.push({lat:e,lon:r,successRate:n.observed?1:0,weight:l,totalSamples:1,ageDays:a,geohash:n.hash,repeaters:(null==(t=n.path)?void 0:t.map(e=>e.toLowerCase()))||[]})}return o}(o);if(0===n.length)throw new Error("No valid coverage points found");return e({coveragePoints:n,repeaters:[],stats:{coverageCount:n.length,repeaterCount:0,lastUpdated:new Date},status:"success",isVisible:!0,url:t.trim()}),ho(t.trim()),go(!0),!0}catch(o){const t=o instanceof Error?o.message:"Failed to load coverage data";let n=t;return t.includes("timed out")?n="Connection timed out. Server may be unreachable or slow.":t.includes("Failed to fetch")||t.includes("NetworkError")?n="Could not connect to server. Check the URL and try again.":t.includes("CORS")?n="Server does not allow cross-origin requests.":t.includes("404")?n="Coverage endpoint not found. Check the URL.":(t.includes("ERR_NAME_NOT_RESOLVED")||t.includes("DNS"))&&(n="Server not found. Check the URL for typos."),e({error:n,status:"error"}),!1}},clearCoverage:()=>{e({coveragePoints:[],repeaters:[],stats:{coverageCount:0,repeaterCount:0,lastUpdated:null},status:"idle",error:null,isVisible:!1,url:""}),ho(""),go(!1)}})),yo={bg:"#F8F8F8",bgSubtle:"#F0F0F0",bgElevated:"#FFFFFF",bgInput:"#FFFFFF",border:"rgba(0, 0, 0, 0.12)",borderStrong:"rgba(0, 0, 0, 0.20)",borderFocus:"#3B82F6",text:"#1A1A1A",textSecondary:"#4A4A4A",textMuted:"#737373",success:"#059669",successBg:"#ECFDF5",successBorder:"#A7F3D0",error:"#DC2626",errorBg:"#FEF2F2",errorBorder:"#FECACA",info:"#2563EB",infoBg:"#EFF6FF",infoBorder:"#BFDBFE",warning:"#D97706",warningBg:"#FFFBEB",warningBorder:"#FDE68A",primary:"#F59E0B",hoverBg:"rgba(0, 0, 0, 0.04)",sliderTrack:"#E5E7EB",sliderThumb:"#F59E0B"},bo={bg:"var(--surface)",bgSubtle:"var(--subtle)",bgElevated:"var(--elevated)",bgInput:"var(--subtle)",border:"var(--edge-subtle)",borderStrong:"var(--edge-strong)",borderFocus:"var(--sys-blue)",text:"var(--fg-primary)",textSecondary:"var(--fg-secondary)",textMuted:"var(--fg-muted)",success:"var(--sys-green)",successBg:"rgba(74, 222, 128, 0.1)",successBorder:"rgba(74, 222, 128, 0.3)",error:"var(--sys-red)",errorBg:"rgba(239, 68, 68, 0.1)",errorBorder:"rgba(239, 68, 68, 0.3)",info:"var(--sys-indigo)",infoBg:"rgba(249, 210, 111, 0.1)",infoBorder:"rgba(249, 210, 111, 0.3)",warning:"var(--sys-indigo)",warningBg:"rgba(249, 210, 111, 0.1)",warningBorder:"rgba(249, 210, 111, 0.3)",primary:"var(--sys-indigo)",hoverBg:"var(--hover-tint)",sliderTrack:"var(--elevated)",sliderThumb:"var(--sys-indigo)"},vo=e.createContext({theme:bo,isLight:!1});function jo(){return e.useContext(vo)}function wo({status:o,hasData:n}){const{theme:r,isLight:s}=jo(),a=e.useMemo(()=>"connecting"===o||"loading"===o||"processing"===o?{icon:t.jsx(Ee,{className:"w-3.5 h-3.5 animate-spin"}),label:"connecting"===o?"Connecting...":"loading"===o?"Loading...":"Processing...",color:r.warning,bg:r.warningBg}:"error"===o?{icon:t.jsx(qe,{className:"w-3.5 h-3.5"}),label:"Disconnected",color:r.error,bg:r.errorBg}:n?{icon:t.jsx(Oe,{className:"w-3.5 h-3.5"}),label:"Connected",color:r.success,bg:r.successBg}:{icon:t.jsx($e,{className:"w-3.5 h-3.5"}),label:"Ready",color:r.textMuted,bg:s?"rgba(0,0,0,0.04)":"rgba(255,255,255,0.04)"},[o,n,r,s]);return t.jsxs(nt.div,{initial:{opacity:0,scale:.9},animate:{opacity:1,scale:1},className:"flex items-center gap-1.5 px-2 py-1 rounded-full text-xs font-medium",style:{backgroundColor:a.bg,color:a.color},children:[a.icon,t.jsx("span",{children:a.label})]},a.label)}function No({status:o}){const{theme:n}=jo(),r=e.useMemo(()=>{switch(o){case"connecting":return 25;case"loading":return 60;case"processing":return 90;default:return 0}},[o]);return 0===r?null:t.jsx(nt.div,{initial:{opacity:0,scaleY:0},animate:{opacity:1,scaleY:1},exit:{opacity:0,scaleY:0},className:"h-1 rounded-full overflow-hidden origin-top",style:{backgroundColor:n.sliderTrack},children:t.jsx(nt.div,{className:"h-full rounded-full",style:{backgroundColor:n.primary},initial:{width:0},animate:{width:`${r}%`},transition:{duration:.4,ease:"easeOut"}})})}function Co({variant:o,title:n,description:r,onDismiss:s}){const{theme:a}=jo(),i=e.useMemo(()=>{switch(o){case"success":return{icon:t.jsx(Ue,{className:"w-4 h-4"}),color:a.success,bg:a.successBg,border:a.successBorder};case"error":return{icon:t.jsx(_e,{className:"w-4 h-4"}),color:a.error,bg:a.errorBg,border:a.errorBorder};case"info":return{icon:t.jsx(We,{className:"w-4 h-4"}),color:a.info,bg:a.infoBg,border:a.infoBorder}}},[o,a]);return t.jsxs(nt.div,{initial:{opacity:0,y:-8},animate:{opacity:1,y:0},exit:{opacity:0,y:-8},transition:M.snappy,className:"flex items-start gap-3 p-3 rounded-lg border",style:{backgroundColor:i.bg,borderColor:i.border,color:i.color},children:[t.jsx("div",{className:"shrink-0 mt-0.5",children:i.icon}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsx("p",{className:"text-sm font-medium",children:n}),r&&t.jsx("p",{className:"text-xs mt-0.5 opacity-80",children:r})]}),s&&t.jsx("button",{onClick:s,className:"shrink-0 p-1 rounded hover:bg-black/10 transition-colors","aria-label":"Dismiss",children:t.jsx(Ae,{className:"w-3.5 h-3.5"})})]})}function ko({value:o,onChange:n,onSubmit:r,disabled:s}){const{theme:a,isLight:i}=jo(),[l,c]=e.useState(!1);return t.jsxs("div",{className:"space-y-1.5",children:[t.jsx("label",{className:"block text-sm font-medium",style:{color:a.textSecondary},children:"Coverage Server URL"}),t.jsxs("div",{className:"relative",children:[t.jsx("input",{type:"url",value:o,onChange:e=>n(e.target.value),onKeyDown:e=>{"Enter"!==e.key||e.shiftKey||s||(e.preventDefault(),r())},onFocus:()=>c(!0),onBlur:()=>c(!1),placeholder:"https://coverage.wcmesh.com",disabled:s,className:ue("w-full pl-3 pr-10 py-2.5 rounded-lg border text-sm transition-all duration-150","focus:outline-none",s&&"opacity-50 cursor-not-allowed"),style:{backgroundColor:a.bgInput,borderColor:l?a.borderFocus:a.border,color:a.text,boxShadow:l?"0 0 0 3px "+(i?"rgba(59, 130, 246, 0.15)":"rgba(139, 92, 246, 0.15)"):"none"}}),o&&!s&&t.jsx("button",{onClick:()=>n(""),className:"absolute right-2.5 top-1/2 -translate-y-1/2 p-1 rounded transition-colors",style:{color:a.textMuted},onMouseEnter:e=>e.currentTarget.style.color=a.text,onMouseLeave:e=>e.currentTarget.style.color=a.textMuted,"aria-label":"Clear URL",children:t.jsx(Ae,{className:"w-4 h-4"})})]}),t.jsx("p",{className:"text-xs",style:{color:a.textMuted},children:"Press Enter to connect, or use the Connect button below"})]})}function Mo({value:e,onChange:o}){const{theme:n,isLight:r}=jo(),s=Math.round(100*e);return t.jsx(nt.div,{initial:{opacity:0,height:0},animate:{opacity:1,height:"auto"},exit:{opacity:0,height:0},transition:M.gentle,className:"overflow-hidden",children:t.jsx("div",{className:"p-3 rounded-lg border",style:{backgroundColor:n.bgSubtle,borderColor:n.border},children:t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsxs("div",{className:"relative w-4 h-4",children:[t.jsx(Ne,{className:"w-4 h-4 absolute inset-0 transition-opacity",style:{color:n.textMuted,opacity:e<.5?1:0}}),t.jsx(Ce,{className:"w-4 h-4 absolute inset-0 transition-opacity",style:{color:n.primary,opacity:e>=.5?1:0}})]}),t.jsxs("div",{className:"flex-1",children:[t.jsxs("div",{className:"flex items-center justify-between mb-1.5",children:[t.jsx("span",{className:"text-xs font-medium",style:{color:n.textSecondary},children:"Layer Opacity"}),t.jsxs("span",{className:"text-xs font-mono tabular-nums px-1.5 py-0.5 rounded",style:{color:n.text,backgroundColor:r?"rgba(0,0,0,0.06)":"rgba(255,255,255,0.06)"},children:[s,"%"]})]}),t.jsx("input",{type:"range",min:5,max:100,value:s,onChange:e=>o(Number(e.target.value)/100),className:ue("w-full h-2 rounded-full appearance-none cursor-pointer","[&::-webkit-slider-thumb]:appearance-none","[&::-webkit-slider-thumb]:w-4","[&::-webkit-slider-thumb]:h-4","[&::-webkit-slider-thumb]:rounded-full","[&::-webkit-slider-thumb]:cursor-pointer","[&::-webkit-slider-thumb]:transition-transform","[&::-webkit-slider-thumb]:hover:scale-110","[&::-webkit-slider-thumb]:shadow-lg","[&::-moz-range-thumb]:appearance-none","[&::-moz-range-thumb]:w-4","[&::-moz-range-thumb]:h-4","[&::-moz-range-thumb]:rounded-full","[&::-moz-range-thumb]:border-0","[&::-moz-range-thumb]:cursor-pointer"),style:{background:`linear-gradient(to right, ${n.primary} ${s}%, ${n.sliderTrack} ${s}%)`,"--thumb-color":n.sliderThumb}}),t.jsx("style",{children:`\n input[type="range"]::-webkit-slider-thumb {\n background-color: ${n.sliderThumb};\n }\n input[type="range"]::-moz-range-thumb {\n background-color: ${n.sliderThumb};\n }\n `})]})]})})})}function So({coverageCount:e,repeaterCount:o,lastUpdated:n}){const{theme:r}=jo();return t.jsxs("div",{className:"grid grid-cols-3 gap-2 p-3 rounded-lg border",style:{backgroundColor:r.bgSubtle,borderColor:r.border},children:[t.jsxs("div",{className:"text-center",children:[t.jsx(it,{value:e,format:{useGrouping:!0,maximumFractionDigits:0},className:"text-lg font-semibold tabular-nums block",style:{color:r.text}}),t.jsx("div",{className:"text-xs mt-0.5",style:{color:r.textMuted},children:"Points"})]}),t.jsxs("div",{className:"text-center border-x",style:{borderColor:r.border},children:[t.jsx(it,{value:o,format:{useGrouping:!0,maximumFractionDigits:0},className:"text-lg font-semibold tabular-nums block",style:{color:r.text}}),t.jsx("div",{className:"text-xs mt-0.5",style:{color:r.textMuted},children:"Repeaters"})]}),t.jsxs("div",{className:"text-center",children:[t.jsxs("div",{className:"flex items-center justify-center gap-1",children:[t.jsx(Ke,{className:"w-3.5 h-3.5",style:{color:r.textMuted}}),t.jsx("span",{className:"text-lg font-semibold tabular-nums",style:{color:r.text},children:n?n.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):"—"})]}),t.jsx("div",{className:"text-xs mt-0.5",style:{color:r.textMuted},children:"Updated"})]})]})}function Fo({icon:o,label:n,onClick:r,disabled:s,variant:a="default",active:i}){const{theme:l,isLight:c}=jo(),u=e.useMemo(()=>"danger"===a?{text:l.error,hoverBg:c?"rgba(220, 38, 38, 0.08)":"rgba(239, 68, 68, 0.15)"}:{text:i?l.primary:l.textSecondary,hoverBg:l.hoverBg},[a,i,l,c]);return t.jsxs("button",{onClick:r,disabled:s,className:ue("flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-sm font-medium transition-colors",s&&"opacity-50 cursor-not-allowed"),style:{color:u.text},onMouseEnter:e=>!s&&(e.currentTarget.style.backgroundColor=u.hoverBg),onMouseLeave:e=>e.currentTarget.style.backgroundColor="transparent",children:[o,t.jsx("span",{children:n})]})}function Ro(){const o=ct(),n="light"===o,r=n?yo:bo,{isModalOpen:s,closeModal:a,status:i,isVisible:l,stats:c,error:u,url:d,brightness:m,loadCoverage:h,clearCoverage:g,toggleVisibility:p,setUrl:f,setBrightness:x}=xo(),y="connecting"===i||"loading"===i||"processing"===i,b=c.coverageCount>0,[v,j]=e.useState(!0),[w,N]=e.useState(d);e.useEffect(()=>{N(d)},[d]),e.useEffect(()=>{"error"===i&&j(!0)},[i]);const C=e.useCallback(async()=>{await h(w)},[w,h]),k=e.useCallback(()=>{N(""),g()},[g]),F=e.useCallback(e=>{N(e),f(e)},[f]),L=e.useCallback(()=>{y||a()},[y,a]),E=w.trim().length>0&&!y;return t.jsx(vo.Provider,{value:{theme:r,isLight:n},children:t.jsxs(R,{open:s,onClose:L,size:"md",bottomSheet:!0,basemapMode:o,children:[t.jsxs("div",{className:"flex items-center justify-between p-4 border-b",style:{borderColor:r.border},children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:"p-2 rounded-lg",style:{backgroundColor:r.bgSubtle,color:r.primary},children:t.jsx($e,{className:"w-5 h-5"})}),t.jsxs("div",{children:[t.jsx("h2",{className:"type-micro",style:{color:r.text},children:"Wardriving Coverage"}),t.jsx("p",{className:"text-xs",style:{color:r.textMuted},children:"RF coverage heatmap overlay"})]})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(wo,{status:i,hasData:b}),!y&&t.jsxs(t.Fragment,{children:[t.jsx("button",{onClick:L,className:"sm:hidden min-h-[44px] min-w-[44px] px-3 flex items-center justify-center text-[15px] font-medium transition-base radius-inner active:bg-subtle-fill",style:{color:r.primary},children:"Done"}),t.jsx("button",{onClick:L,className:"hidden sm:flex items-center justify-center p-2 rounded-lg transition-colors",style:{color:r.textMuted},onMouseEnter:e=>{e.currentTarget.style.color=r.text,e.currentTarget.style.backgroundColor=r.hoverBg},onMouseLeave:e=>{e.currentTarget.style.color=r.textMuted,e.currentTarget.style.backgroundColor="transparent"},"aria-label":"Close",children:t.jsx(Ae,{className:"w-5 h-5"})})]})]})]}),t.jsx(rt,{children:y&&t.jsx(No,{status:i})}),t.jsxs(T,{className:"space-y-4",children:[t.jsx(ko,{value:w,onChange:F,onSubmit:C,disabled:y}),t.jsx(rt,{children:"error"===i&&u&&v&&t.jsx(Co,{variant:"error",title:"Connection Failed",description:u,onDismiss:()=>j(!1)})}),t.jsx(rt,{children:"success"===i&&b&&t.jsx(Co,{variant:"success",title:"Coverage Data Loaded",description:"Adjust opacity below, then close to view on map"})}),t.jsx(rt,{children:b&&!y&&t.jsx(nt.div,{initial:{opacity:0,y:8},animate:{opacity:1,y:0},exit:{opacity:0,y:8},transition:M.snappy,children:t.jsx(So,{coverageCount:c.coverageCount,repeaterCount:c.repeaterCount,lastUpdated:c.lastUpdated})})}),t.jsx(rt,{children:b&&!y&&t.jsx(Mo,{value:m,onChange:x})})]}),t.jsxs("div",{className:"flex items-center justify-between p-4 border-t",style:{borderColor:r.border},children:[t.jsx("div",{className:"flex items-center gap-1",children:t.jsx(rt,{children:b&&t.jsxs(nt.div,{initial:{opacity:0,x:-10},animate:{opacity:1,x:0},exit:{opacity:0,x:-10},transition:M.snappy,className:"flex items-center gap-1",children:[t.jsx(Fo,{icon:l?t.jsx(Pe,{className:"w-4 h-4"}):t.jsx(ye,{className:"w-4 h-4"}),label:l?"Hide":"Show",onClick:p,disabled:y,active:l}),t.jsx(Fo,{icon:t.jsx(ze,{className:"w-4 h-4"}),label:"Clear",onClick:k,disabled:y,variant:"danger"})]})})}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(S,{plain:!0,color:"muted",onClick:L,disabled:y,children:b?"Done":"Cancel"}),t.jsx(S,{color:"warning",onClick:C,disabled:!E,children:y?t.jsxs(t.Fragment,{children:[t.jsx(Ee,{"data-slot":"icon",className:"animate-spin"}),"connecting"===i?"Connecting...":"loading"===i?"Loading...":"Processing..."]}):b?t.jsxs(t.Fragment,{children:[t.jsx(xe,{"data-slot":"icon"}),"Refresh"]}):t.jsxs(t.Fragment,{children:[t.jsx(Ie,{"data-slot":"icon"}),"Connect"]})})]})]})]})})}const To={bandwidth:.07,threshold:.1,opacity:1,strokeWidth:4.5},Lo={...Ft,trackBg:Ft.border};function Eo({label:e,value:o,min:n,max:r,step:s,unit:a,formatValue:i,onChange:l,isLightMode:c}){const u=i?i(o):o.toFixed(2);return t.jsxs("div",{className:"flex items-center gap-2 sm:gap-2",children:[t.jsx("span",{className:"text-xs font-medium w-14 sm:w-16 shrink-0",style:c?{color:Lo.textSecondary}:{color:"var(--fg-secondary)"},children:e}),t.jsx("input",{type:"range",min:n,max:r,step:s,value:o,onChange:e=>l(parseFloat(e.target.value)),className:"flex-1 h-1.5 rounded-full appearance-none cursor-pointer\n [&::-webkit-slider-thumb]:appearance-none\n [&::-webkit-slider-thumb]:w-3.5\n [&::-webkit-slider-thumb]:h-3.5\n [&::-webkit-slider-thumb]:rounded-full\n [&::-webkit-slider-thumb]:bg-sys-indigo\n [&::-webkit-slider-thumb]:cursor-pointer\n [&::-webkit-slider-thumb]:transition-transform\n [&::-webkit-slider-thumb]:hover:scale-110\n [&::-webkit-slider-thumb]:shadow-md",style:c?{backgroundColor:Lo.trackBg}:{backgroundColor:"var(--elevated)"}}),t.jsxs("span",{className:"text-xs font-mono tabular-nums w-12 sm:w-14 text-right shrink-0",style:c?{color:Lo.textPrimary}:{color:"var(--fg-muted)"},children:[u,a&&t.jsx("span",{className:"ml-0.5 opacity-70",style:c?{color:Lo.textMuted}:void 0,children:a})]})]})}function Bo({icon:e,label:o,value:n,subtext:r,isLightMode:s}){return t.jsxs("div",{className:"flex items-center gap-1.5 sm:gap-2 py-0.5 sm:py-1",children:[t.jsx("div",{style:s?{color:Lo.textMuted}:{color:"var(--fg-muted)"},children:e}),t.jsx("div",{className:"flex-1 min-w-0",children:t.jsx("div",{className:"text-[10px] sm:text-xs truncate",style:s?{color:Lo.textSecondary}:{color:"var(--fg-secondary)"},children:o})}),t.jsxs("div",{className:"text-right",children:[t.jsx("div",{className:"text-xs font-mono tabular-nums",style:s?{color:Lo.textPrimary}:{color:"var(--fg-primary)"},children:n}),r&&t.jsx("div",{className:"text-[9px] leading-tight opacity-70",style:s?{color:Lo.textMuted}:{color:"var(--fg-muted)"},children:r})]})]})}function Do({visible:o,onClose:n,settings:r,onSettingsChange:s,partition:a,totalNodes:i,basemapMode:l="dark"}){const c=st(),u=e.useRef(null),d="light"===l,m=e.useMemo(()=>{if(!a)return{numCommunities:0,avgCommunitySize:0,minCommunitySize:0,maxCommunitySize:0,fiedlerValue:0,modularity:0,coveragePercent:0};const e=Array.from(a.communities.values()).map(e=>e.length),t=e.reduce((e,t)=>e+t,0);return{numCommunities:a.numCommunities,avgCommunitySize:e.length>0?Math.round(t/e.length):0,minCommunitySize:e.length>0?Math.min(...e):0,maxCommunitySize:e.length>0?Math.max(...e):0,fiedlerValue:a.fiedlerValue,modularity:0,coveragePercent:i>0?Math.round(t/i*100):0}},[a,i]),h=(e,t)=>{s({...r,[e]:t})},g=(111*r.bandwidth).toFixed(1);return t.jsx("div",{ref:u,className:"absolute inset-0 z-[600] pointer-events-none",children:t.jsx(rt,{children:o&&t.jsx(nt.div,{drag:!0,dragControls:c,dragConstraints:u,dragElastic:.1,dragMomentum:!1,initial:{opacity:0,scale:.95,y:10},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.95,y:10},transition:M.smooth,className:"\n absolute pointer-events-auto\n /* Mobile: bottom sheet style, full width with margins */\n bottom-2 left-2 right-2\n /* sm+: floating panel in bottom-right */\n sm:bottom-16 sm:left-auto sm:right-3 sm:w-64\n /* md+: slightly wider */\n md:w-72\n ",style:{touchAction:"none"},children:t.jsxs("div",{className:"\n map-control-surface rounded-lg overflow-hidden shadow-lg\n /* Mobile: limit height, allow scroll */\n max-h-[45vh] sm:max-h-[calc(100vh-180px)] overflow-y-auto\n /* iOS momentum scrolling */\n overscroll-contain\n ",children:[t.jsxs("div",{className:"\n flex items-center justify-between \n px-3 py-2 sm:px-2.5 sm:py-1.5 \n border-b \n cursor-grab active:cursor-grabbing\n /* Larger touch target on mobile */\n min-h-[44px] sm:min-h-0\n ",style:d?{borderColor:Lo.border}:void 0,onPointerDown:e=>c.start(e),children:[t.jsxs("div",{className:"flex items-center gap-2 sm:gap-1.5",children:[t.jsx(Ve,{className:"w-4 h-4 sm:w-3 sm:h-3",style:d?{color:Lo.textMuted}:void 0}),t.jsx(we,{className:"w-4 h-4 sm:w-3.5 sm:h-3.5 text-sys-blue"}),t.jsx("span",{className:"text-sm sm:text-xs font-medium",style:d?{color:Lo.textPrimary}:void 0,children:"Partition"})]}),t.jsx(S,{plain:!0,color:"muted",onClick:n,className:"!p-1.5 sm:!p-0.5 !rounded min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 flex items-center justify-center","aria-label":"Close toolbox",children:t.jsx(Ae,{className:"w-4 h-4 sm:w-3 sm:h-3"})})]}),t.jsx("div",{className:"px-3 py-2 sm:px-2.5 sm:py-1.5 border-b",style:d?{borderColor:Lo.border}:void 0,children:t.jsxs("div",{className:"grid grid-cols-2 gap-x-4 sm:gap-x-3 gap-y-1 sm:gap-y-0.5",children:[t.jsx(Bo,{icon:t.jsx(we,{className:"w-3.5 h-3.5 sm:w-3 sm:h-3"}),label:"Communities",value:m.numCommunities,isLightMode:d}),t.jsx(Bo,{icon:t.jsx(Ze,{className:"w-3.5 h-3.5 sm:w-3 sm:h-3"}),label:"Avg Size",value:m.avgCommunitySize,subtext:`${m.minCommunitySize}–${m.maxCommunitySize}`,isLightMode:d}),t.jsx(Bo,{icon:t.jsx(Ge,{className:"w-3.5 h-3.5 sm:w-3 sm:h-3"}),label:"Fiedler λ₂",value:m.fiedlerValue.toFixed(3),isLightMode:d}),t.jsx(Bo,{icon:t.jsx(Ze,{className:"w-3.5 h-3.5 sm:w-3 sm:h-3"}),label:"Coverage",value:`${m.coveragePercent}%`,subtext:`of ${i}`,isLightMode:d})]})}),t.jsx("div",{className:"px-3 py-2 sm:px-2.5 sm:py-1.5",children:t.jsxs("div",{className:"space-y-3 sm:space-y-1.5",children:[t.jsx(Eo,{label:"Bandwidth",value:r.bandwidth,min:.01,max:.15,step:.005,formatValue:()=>g,unit:"km",onChange:e=>h("bandwidth",e),isLightMode:d}),t.jsx(Eo,{label:"Threshold",value:r.threshold,min:.05,max:.5,step:.01,formatValue:e=>`${Math.round(100*(1-e))}%`,unit:"cov",onChange:e=>h("threshold",e),isLightMode:d}),t.jsx(Eo,{label:"Opacity",value:r.opacity,min:.1,max:1,step:.05,formatValue:e=>`${Math.round(100*e)}%`,onChange:e=>h("opacity",e),isLightMode:d}),t.jsx(Eo,{label:"Stroke",value:r.strokeWidth,min:0,max:5,step:.5,unit:"px",formatValue:e=>e.toFixed(1),onChange:e=>h("strokeWidth",e),isLightMode:d})]})})]})})})})}const Ho={excellent:"text-signal-excellent",good:"text-signal-good",fair:"text-signal-fair",poor:"text-signal-poor",critical:"text-signal-critical"};function $o(e,t){return Ho[I(e,t)]}const Ao={backgroundColor:"var(--map-ui-hover, var(--elevated))",color:"var(--map-ui-text, var(--fg-primary))",boxShadow:"inset 0 0 0 1px var(--map-ui-border-strong, var(--edge-strong))"},Po={backgroundColor:"var(--map-ui-bg, var(--body))",color:"var(--map-ui-text, var(--fg-primary))",boxShadow:"0 1px 4px rgba(0,0,0,0.15), inset 0 0 0 1px var(--map-ui-border, var(--edge-subtle))"};function zo({prefix:n,name:r}){const s=e.useRef(null),[a,i]=e.useState(!1),[l,c]=e.useState({top:0,left:0});return t.jsxs(t.Fragment,{children:[t.jsx("span",{ref:s,className:"inline-flex items-center px-1.5 py-0.5 rounded font-mono text-[10px] font-semibold transition-opacity hover:opacity-80 cursor-default",style:Ao,onMouseEnter:()=>{if(!r||!s.current)return;const e=s.current.getBoundingClientRect();c({top:e.top-4,left:e.left+e.width/2}),i(!0)},onMouseLeave:()=>i(!1),children:n}),r&&a&&o.createPortal(t.jsx("span",{className:"fixed z-[9999] pointer-events-none -translate-x-1/2 -translate-y-full whitespace-nowrap rounded px-1.5 py-0.5 text-[10px] font-medium",style:{...Po,top:l.top,left:l.left},children:r}),document.body)]})}function Io(e){if(e._tracePathHashes)return e._tracePathHashes;if(e.payload&&e.payload.length>=20){const t=e.payload.slice(18),o=[];for(let e=0;e<t.length;e+=2){const n=t.slice(e,e+2).toUpperCase();2===n.length&&o.push(n)}return o.length>0?o:null}return null}function qo(e,t){return e.src_hash?[e.src_hash.replace(/^0x/i,"").slice(0,2).toUpperCase(),...t.map(e=>e.toUpperCase())]:t.map(e=>e.toUpperCase())}function Oo(e){switch(e){case"improving":return t.jsx(Xe,{className:"w-3 h-3 text-sys-green"});case"degrading":return t.jsx(Qe,{className:"w-3 h-3 text-sys-red"});case"stable":return t.jsx(Re,{className:"w-3 h-3 text-fg-muted"});default:return null}}const Wo={backgroundColor:"var(--map-ui-stripe)"};function _o({label:e,value:o,unit:n,color:r,tooltip:s}){return t.jsxs("div",{className:"flex items-center justify-between gap-2 py-[3px] "+(s?"cursor-help":""),title:s,children:[t.jsx("span",{className:"type-data-xs text-fg-muted",children:e}),t.jsxs("span",{className:`data-box data-box-compact ${r||""}`,children:[o,n&&t.jsx("span",{className:"text-fg-muted ml-0.5",children:n})]})]})}function Uo({stats:e,direction:o,sf:n,noiseFloor:r}){if(!e)return t.jsxs("div",{className:"min-w-0",children:[t.jsx("div",{className:"flex items-center justify-between mb-1.5",children:t.jsx("p",{className:"type-data-xs text-fg-secondary font-medium",children:o})}),t.jsx("p",{className:"type-data-xs text-fg-muted italic px-1.5",children:"No data"})]});const s=e.max-e.min,a=e.median-e.mean,i=q(n),l=e.mean-i,c=I(e.mean,n),u=[`Mean SNR: ${e.mean.toFixed(1)} dB (${c}) from ${e.count} measurement${1!==e.count?"s":""}`,`Variability: ±${e.stdDev.toFixed(1)} dB`,"",`Link budget (SF${n}, 3.5 dBi omni):`,` Demod threshold: ${i.toFixed(1)} dB`,` SNR margin: ${l>=0?"+":""}${l.toFixed(1)} dB`];return null!=r&&u.push(` Noise floor: ${r} dBm`),t.jsxs("div",{className:"min-w-0",children:[t.jsxs("div",{className:"flex items-center justify-between mb-1.5",children:[t.jsx("p",{className:"type-data-xs text-fg-secondary font-medium",children:o}),t.jsxs("span",{className:"type-data-xs text-fg-muted tabular-nums",title:`${e.count} measurement${1!==e.count?"s":""}`,children:["n=",e.count]})]}),t.jsx(_o,{label:"Mean",value:e.mean.toFixed(1),unit:"dB",color:$o(e.mean,n),tooltip:u.join("\n")}),t.jsx(_o,{label:"Median",value:e.median.toFixed(1),unit:"dB",tooltip:"Middle value — less affected by unusual readings than the average."+(Math.abs(a)>=.15?`\nDiffers from mean by ${a>0?"+":""}${a.toFixed(1)} dB`:"")}),t.jsx(_o,{label:"Range",value:`${e.min.toFixed(1)}–${e.max.toFixed(1)}`,unit:"dB",tooltip:`Best to worst signal observed. Total spread: ${s.toFixed(1)} dB.`})]})}function Ko({pair:o,onClose:n,prefixToName:r}){var s,a,i,l,c,u,d,m,h,g,p,f;const x=L(),y=E(),b=B(),v=D(),[j,w]=e.useState(null),N=(null==(a=null==(s=null==b?void 0:b.config)?void 0:s.radio)?void 0:a.spreading_factor)??H,C=e.useMemo(()=>{const e=`${o.nodeA.hash}>${o.nodeB.hash}`,t=`${o.nodeB.hash}>${o.nodeA.hash}`;return{forward:x.get(e)??null,reverse:x.get(t)??null}},[x,o.nodeA.hash,o.nodeB.hash]),k=e.useMemo(()=>y&&0!==y.length?function(e,t,o,n=15){const r=[],s=t.toUpperCase(),a=o.toUpperCase();for(const i of e){if((i.type??i.payload_type)!==z.TRACE)continue;const e=Io(i);if(!e||e.length<1)continue;const t=qo(i,e);if(!(t.length<2)){for(let e=0;e<t.length-1;e++)if(t[e]===s&&t[e+1]===a||t[e]===a&&t[e+1]===s){r.push(i);break}if(r.length>=n)break}}return r}(y,o.nodeA.prefix,o.nodeB.prefix):[],[y,o.nodeA.prefix,o.nodeB.prefix]),M=o.nodeA.name||(null==r?void 0:r.get(o.nodeA.prefix.toUpperCase()))||null,F=o.nodeB.name||(null==r?void 0:r.get(o.nodeB.prefix.toUpperCase()))||null,R=(null==(i=C.forward)?void 0:i.trend)??(null==(l=C.reverse)?void 0:l.trend)??"insufficient",T=Math.max((null==(c=C.forward)?void 0:c.lastSeen)??0,(null==(u=C.reverse)?void 0:u.lastSeen)??0),I=((null==(d=C.forward)?void 0:d.uniqueTraceCount)??0)+((null==(m=C.reverse)?void 0:m.uniqueTraceCount)??0),q="insufficient"===R?"Not enough data to determine trend (need at least 4 measurements).":"Whether signal quality is getting better or worse over time.\nCompares older measurements to newer ones.",O=(null==(h=C.forward)?void 0:h.uniqueTraceCount)??0,W=(null==(g=C.reverse)?void 0:g.uniqueTraceCount)??0,_=["Number of trace packets that traveled through this link.",`${o.nodeA.prefix}→${o.nodeB.prefix}: ${O}`,`${o.nodeB.prefix}→${o.nodeA.prefix}: ${W}`].join("\n");return t.jsx("div",{className:"\n absolute z-[700] overflow-hidden\n /* Mobile: full-width bottom sheet with breathing room */\n bottom-2 left-2 right-2\n /* sm+: right-aligned floating panel */\n sm:bottom-16 sm:left-auto sm:right-4 sm:w-[280px]\n ",children:t.jsxs("div",{className:"\n map-control-surface flex flex-col\n /* Mobile: cap at 45vh so map stays visible */\n max-h-[45vh]\n /* sm+: taller allowance */\n sm:max-h-[420px]\n ",children:[t.jsxs("div",{className:"flex items-center justify-between gap-2 px-3 py-2 sm:py-2 min-h-[44px] sm:min-h-0 border-b border-edge-subtle",children:[t.jsxs("div",{className:"flex items-center gap-1.5 min-w-0",children:[t.jsx(Le,{className:"w-4 h-4 sm:w-3.5 sm:h-3.5 text-sys-green shrink-0"}),t.jsx(zo,{prefix:o.nodeA.prefix,name:M}),t.jsx("span",{className:"type-data-xs text-fg-muted",children:"↔"}),t.jsx(zo,{prefix:o.nodeB.prefix,name:F})]}),t.jsxs("div",{className:"flex items-center gap-1.5 shrink-0",children:[T>0&&t.jsx("span",{className:"type-data-xs text-fg-muted",title:A(T),children:$(T)}),t.jsx(S,{plain:!0,color:"muted",onClick:n,className:"!p-1.5 sm:!p-0.5 !rounded-md min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 flex items-center justify-center",children:t.jsx(Ae,{className:"w-4 h-4 sm:w-3.5 sm:h-3.5"})})]})]}),t.jsxs("div",{className:"px-3 py-2.5 border-b border-edge-subtle",children:[t.jsxs("div",{className:"space-y-1.5 mb-2",children:[t.jsxs("div",{className:"flex items-center justify-between cursor-help",title:`${o.nodeA.prefix}→${o.nodeB.prefix}: mean of ${(null==(p=o.aToB)?void 0:p.count)??0} measurements`,children:[t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx(zo,{prefix:o.nodeA.prefix,name:M}),t.jsx("span",{className:"type-data-xs text-fg-muted",children:"→"}),t.jsx(zo,{prefix:o.nodeB.prefix,name:F})]}),o.aToB?t.jsxs("span",{className:`type-data-sm tabular-nums font-semibold ${$o(o.aToB.mean,N)}`,children:[o.aToB.mean.toFixed(1),t.jsx("span",{className:"text-fg-muted font-normal ml-0.5",children:"dB"})]}):t.jsx("span",{className:"type-data-sm text-fg-muted",children:"—"})]}),t.jsxs("div",{className:"flex items-center justify-between cursor-help",title:`${o.nodeB.prefix}→${o.nodeA.prefix}: mean of ${(null==(f=o.bToA)?void 0:f.count)??0} measurements`,children:[t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx(zo,{prefix:o.nodeB.prefix,name:F}),t.jsx("span",{className:"type-data-xs text-fg-muted",children:"→"}),t.jsx(zo,{prefix:o.nodeA.prefix,name:M})]}),o.bToA?t.jsxs("span",{className:`type-data-sm tabular-nums font-semibold ${$o(o.bToA.mean,N)}`,children:[o.bToA.mean.toFixed(1),t.jsx("span",{className:"text-fg-muted font-normal ml-0.5",children:"dB"})]}):t.jsx("span",{className:"type-data-sm text-fg-muted",children:"—"})]})]}),t.jsxs("div",{className:"grid grid-cols-2 gap-0 -mx-3 border-t border-edge-subtle",children:[t.jsx("div",{className:"px-3 pt-2 pb-1 border-r border-edge-subtle",children:t.jsx(Uo,{stats:o.aToB,direction:`${o.nodeA.prefix}→${o.nodeB.prefix}`,sf:N,noiseFloor:v})}),t.jsx("div",{className:"px-3 pt-2 pb-1",children:t.jsx(Uo,{stats:o.bToA,direction:`${o.nodeB.prefix}→${o.nodeA.prefix}`,sf:N,noiseFloor:v})})]})]}),t.jsxs("div",{className:"px-3 py-1.5 border-b border-edge-subtle",children:["insufficient"!==R&&t.jsxs("div",{className:"flex items-center justify-between gap-2 py-[3px] cursor-help",title:q,children:[t.jsx("span",{className:"type-data-xs text-fg-muted",children:"Trend"}),t.jsx("span",{className:"data-box data-box-compact",children:t.jsxs("span",{className:"flex items-center gap-1",children:[Oo(R),t.jsx("span",{className:"text-fg-secondary capitalize",children:R})]})})]}),I>0&&t.jsx(_o,{label:"Unique traces",value:I.toString(),tooltip:_})]}),k.length>0&&t.jsxs("div",{className:"px-3 py-2 flex-1 min-h-0 flex flex-col",children:[t.jsxs("p",{className:"type-micro text-fg-secondary mb-1 shrink-0",children:["Source packets (",k.length,")"]}),t.jsx("div",{className:"overflow-y-auto flex-1 min-h-0 overscroll-contain",style:{scrollbarGutter:"stable"},children:k.map((e,o)=>{const n=Io(e),s=n?qo(e,n):null,a=s?Math.max(0,s.length-1):0,i=s?s.map(e=>(null==r?void 0:r.get(e))??e).join(" → "):null,l=j===o,c=e.id??`${e.packet_hash}-${e.timestamp}`;return t.jsxs("div",{className:"rounded-sm",style:o%2==1?Wo:void 0,children:[t.jsxs("button",{onClick:()=>w(l?null:o),className:"flex items-center gap-1.5 py-[3px] px-1 w-full text-left text-[10px] font-mono text-fg-secondary hover:text-fg-primary transition-colors group",children:[l?t.jsx(be,{className:"w-2.5 h-2.5 text-fg-muted shrink-0"}):t.jsx(Je,{className:"w-2.5 h-2.5 text-fg-muted shrink-0 opacity-0 group-hover:opacity-100 transition-opacity"}),t.jsx("span",{className:"text-fg-muted w-[52px] shrink-0",children:A(e.timestamp)}),i?t.jsx("span",{className:"text-fg-secondary truncate min-w-0",title:s.join(" → "),children:i}):t.jsx("span",{className:"text-fg-muted truncate min-w-0 italic",children:"path n/a"}),t.jsxs("span",{className:"text-fg-muted shrink-0",children:[a,"h"]}),null!=e.snr&&t.jsx("span",{className:`shrink-0 tabular-nums ${$o(e.snr,N)}`,children:e.snr.toFixed(1)})]}),l&&t.jsxs("div",{className:"mb-1 mt-0.5 mx-1 pl-2 border-l border-edge-subtle space-y-0.5 text-[10px]",children:[null!=e.rssi&&t.jsxs("div",{className:"flex items-center justify-between gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"RSSI"}),t.jsxs("span",{className:"font-mono tabular-nums text-fg-secondary",children:[e.rssi," dBm"]})]}),null!=e.snr&&t.jsxs("div",{className:"flex items-center justify-between gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"SNR"}),t.jsxs("span",{className:`font-mono tabular-nums ${$o(e.snr,N)}`,children:[e.snr.toFixed(1)," dB"]})]}),t.jsxs("div",{className:"flex items-center justify-between gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"Route"}),t.jsx("span",{className:"font-mono text-fg-secondary",children:P(e.route??e.route_type)})]}),e.packet_hash&&t.jsxs("div",{className:"flex items-center justify-between gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"Hash"}),t.jsxs("button",{onClick:t=>{t.stopPropagation(),navigator.clipboard.writeText(e.packet_hash)},className:"flex items-center gap-1 font-mono text-fg-secondary hover:text-fg-primary transition-colors",title:"Copy packet hash",children:[t.jsx("span",{className:"truncate max-w-[120px]",children:e.packet_hash}),t.jsx(Ye,{className:"w-2.5 h-2.5 text-fg-muted shrink-0"})]})]}),e.src_hash&&t.jsxs("div",{className:"flex items-center justify-between gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"Source"}),t.jsx("span",{className:"font-mono text-fg-secondary truncate max-w-[140px]",title:e.src_hash,children:e.src_hash})]}),s&&s.length>0&&t.jsxs("div",{className:"flex items-center justify-between gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"Path"}),t.jsx("span",{className:"font-mono text-fg-secondary truncate max-w-[140px]",title:s.join(" → "),children:s.join(" → ")})]})]})]},c)})})]})]})})}const Vo={getItem:e=>{try{return localStorage.getItem(e)}catch{return null}},setItem:(e,t)=>{try{localStorage.setItem(e,t)}catch{}},removeItem:e=>{try{localStorage.removeItem(e)}catch{}}},Zo=de()(me(e=>({isEnabled:!1,toggle:()=>e(e=>({isEnabled:!e.isEnabled})),setEnabled:t=>e({isEnabled:t})}),{name:"pymc-live-trace",storage:he(()=>Vo)})),Go="wardriving-hexagons",Jo="wardriving-hexagons-fill",Yo=[[15,5,30,255],[35,10,55,255],[55,15,75,255],[75,20,90,255],[95,25,100,255],[115,30,105,255],[135,35,100,255],[155,45,90,255],[175,55,75,255],[195,70,60,255],[210,90,50,255],[225,110,45,255],[235,135,45,255],[245,160,50,255],[250,185,60,255],[252,205,80,255],[254,225,105,255],[255,240,135,255],[255,248,170,255],[255,252,200,255],[255,254,225,255],[255,255,240,255],[255,255,250,255],[255,255,255,255]],Qo=[[60,20,120,255],[80,30,140,255],[100,40,160,255],[120,50,170,255],[140,60,175,255],[160,70,175,255],[180,60,150,255],[200,55,120,255],[215,55,90,255],[230,65,60,255],[240,80,40,255],[250,100,30,255],[255,130,30,255],[255,155,35,255],[255,175,40,255],[255,195,50,255],[255,210,60,255],[255,225,70,255],[255,200,40,255],[255,185,30,255],[255,170,20,255],[245,155,15,255],[235,140,10,255],[225,125,5,255]];function Xo(e){return`rgb(${e[0]}, ${e[1]}, ${e[2]})`}function en(e,t,o,n){const r=o-t;if(r<.001)return Xo(n[12]);const s=(a=Math.max(0,Math.min(1,(e-t)/r)))<.15?a/.15*.1:a>.85?.9+(a-.85)/.15*.1:.1+(a-.15)/.7*.8;var a;return Xo(n[Math.min(23,Math.floor(24*s))])}function tn({coveragePoints:o,visible:r,terrainEnabled:s=!1,brightness:a=.7,basemapMode:i="dark"}){const{current:l}=n(),[c,u]=e.useState(null);e.useEffect(()=>{const e=()=>{var e;const t=null==(e=null==l?void 0:l.getMap)?void 0:e.call(l);t&&!c&&u(t)};e();const t=setInterval(e,50),o=setTimeout(()=>clearInterval(t),5e3);return()=>{clearInterval(t),clearTimeout(o)}},[l,c]);const[d,m]=e.useState(null),[h,g]=e.useState(!1),p=e.useRef({aborted:!1}),f=e.useRef(0),x=e.useRef(i),y=function(t){const[o,n]=e.useState(t);return e.useEffect(()=>{const e=setTimeout(()=>n(t),300);return()=>clearTimeout(e)},[t,300]),o}(o),b=e.useMemo(()=>function(e="dark"){var t;if("light"===e)return Qo;const o=O();return 24===o.length&&0!==(null==(t=o[0])?void 0:t[0])?o:Yo}(i),[i]);e.useEffect(()=>{if(!y||!Array.isArray(y)||0===y.length)return void queueMicrotask(()=>{m(null),f.current=0});const e=x.current!==i;if(y.length===f.current&&d&&!e)return;f.current=y.length,x.current=i,p.current.aborted=!0,p.current={aborted:!1};const t=p.current;g(!0);const{cells:o,minQuality:n,maxQuality:r}=function(e){const t=new Map;for(const s of e){if("number"!=typeof s.lat||"number"!=typeof s.lon||isNaN(s.lat)||isNaN(s.lon))continue;const e=mt(s.lat,s.lon,8),o=t.get(e),n=s.weight;o?(o.count++,o.qualitySum+=n):t.set(e,{count:1,qualitySum:n})}const o=[];let n=1/0,r=-1/0;for(const[s,a]of t.entries()){const e=a.qualitySum/a.count;o.push({hexId:s,count:a.count,avgQuality:e}),n=Math.min(n,e),r=Math.max(r,e)}return{cells:o,minQuality:o.length>0?n:0,maxQuality:o.length>0?r:0}}(y);if(0===o.length)return m(null),void g(!1);if(o.length<500){const e=function(e,t,o,n){const r=[];for(const s of e){const e=ht(s.hexId).map(([e,t])=>[t,e]);e.push(e[0]);const a=en(s.avgQuality,t,o,n);r.push({type:"Feature",properties:{color:a,quality:s.avgQuality,count:s.count},geometry:{type:"Polygon",coordinates:[e]}})}return{type:"FeatureCollection",features:r}}(o,n,r,b);return void(t.aborted||(m(e),g(!1)))}return async function(e,t,o,n,r){const s=[];let a=0;for(;a<e.length;){if(r.aborted)return null;const i=Math.min(a+500,e.length);for(;a<i;a++){const r=e[a],i=ht(r.hexId).map(([e,t])=>[t,e]);i.push(i[0]);const l=en(r.avgQuality,t,o,n);s.push({type:"Feature",properties:{color:l,quality:r.avgQuality,count:r.count},geometry:{type:"Polygon",coordinates:[i]}})}a<e.length&&await new Promise(e=>requestAnimationFrame(e))}return{type:"FeatureCollection",features:s}}(o,n,r,b,t).then(e=>{!t.aborted&&e&&m(e)}).finally(()=>{t.aborted||g(!1)}),()=>{t.aborted=!0}},[y,b]),e.useEffect(()=>{if(!c)return;const e=()=>{var e,t;try{const o=c.getLayer(Jo),n=c.getSource(Go);if(r&&d&&d.features.length>0){if(n?c.getSource(Go).setData(d):c.addSource(Go,{type:"geojson",data:d}),!o){const o=c.getLayer("topology-weak-edges-native"),n=null==(t=null==(e=c.getStyle())?void 0:e.layers)?void 0:t.find(e=>"symbol"===e.type),r=o?"topology-weak-edges-native":null==n?void 0:n.id;c.addLayer({id:Jo,type:"fill",source:Go,paint:{"fill-color":["get","color"],"fill-opacity":a}},r)}}else o&&c.removeLayer(Jo),n&&c.removeSource(Go)}catch(o){console.warn("[WardrivingHexLayerMapLibre] Layer update error:",o)}};c.isStyleLoaded()?e():c.once("style.load",e)},[c,r,d,s]),e.useEffect(()=>{if(c&&r)try{c.getLayer(Jo)&&c.setPaintProperty(Jo,"fill-opacity",a)}catch{}},[c,a,r]),e.useEffect(()=>()=>{if(c)try{c.getLayer(Jo)&&c.removeLayer(Jo),c.getSource(Go)&&c.removeSource(Go)}catch{}},[c]);const v=(null==d?void 0:d.features.length)??0;return v>0&&r?t.jsx("div",{"data-testid":"wardriving-hexlayer-maplibre-active","data-point-count":(null==o?void 0:o.length)||0,"data-cell-count":v,"data-terrain-enabled":s,"data-is-processing":h,style:{display:"none"}}):null}const on="https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png",nn="terrarium",rn="terrain-dem",sn="hillshade-dem",an="terrain-hillshade";function ln({enabled:t,exaggeration:o=4}){const{current:r}=n(),[s,a]=e.useState(null),i=e.useRef(null);return e.useEffect(()=>{const e=()=>{var e;const t=null==(e=null==r?void 0:r.getMap)?void 0:e.call(r);t&&!s&&a(t)};e();const t=setInterval(e,50),o=setTimeout(()=>clearInterval(t),5e3);return()=>{clearInterval(t),clearTimeout(o)}},[r,s]),e.useEffect(()=>{if(!s)return;let e=!0;const t=()=>{var t,o;if(e)try{if(s.getSource(sn)||s.addSource(sn,{type:"raster-dem",tiles:[on],encoding:nn,tileSize:256,maxzoom:14}),!s.getLayer(an)){const e=null==(o=null==(t=s.getStyle())?void 0:t.layers)?void 0:o.find(e=>"symbol"===e.type);s.addLayer({id:an,type:"hillshade",source:sn,paint:{"hillshade-shadow-color":"rgba(10, 10, 10, 0.6)","hillshade-highlight-color":"rgba(245, 240, 230, 0.4)","hillshade-accent-color":"rgba(90, 75, 65, 0.3)","hillshade-illumination-direction":315,"hillshade-exaggeration":.35}},null==e?void 0:e.id)}s.getSource(rn)||s.addSource(rn,{type:"raster-dem",tiles:[on],encoding:nn,tileSize:256,maxzoom:14})}catch(n){console.error("[TerrainLayer] Source/layer setup error:",n)}};return s.isStyleLoaded()?t():(s.once("style.load",t),s.once("load",()=>{e&&!s.getSource(sn)&&t()})),()=>{e=!1}},[s]),e.useEffect(()=>{if(!s)return;let e=!0,n=!1;const r=()=>{if(e&&s.getSource(rn))try{t?(s.setCenterClampedToGround(!1),s.setTerrain({source:rn,exaggeration:o}),s.setMaxPitch(70),!n&&s.getPitch()<30&&!s.isMoving()&&(n=!0,null!==i.current&&clearTimeout(i.current),i.current=window.setTimeout(()=>{i.current=null,e&&!s.isMoving()&&s.getPitch()<30&&s.easeTo({pitch:45,duration:1e3})},200))):(s.setTerrain(null),s.setCenterClampedToGround(!0),s.getPitch()>0&&!s.isMoving()&&s.easeTo({pitch:0,duration:800}),s.setMaxPitch(60))}catch(r){console.error("[TerrainLayer] Terrain state error:",r)}};if(s.isStyleLoaded()&&s.getSource(rn))r();else{const e=()=>{s.getSource(rn)&&r()};s.once("idle",e)}return()=>{e=!1,null!==i.current&&(clearTimeout(i.current),i.current=null)}},[s,t,o]),e.useEffect(()=>()=>{var e;try{(null==(e=null==s?void 0:s.getStyle)?void 0:e.call(s))&&s.isStyleLoaded()&&(s.setTerrain(null),s.getLayer(an)&&s.removeLayer(an),s.getSource(sn)&&s.removeSource(sn),s.getSource(rn)&&s.removeSource(rn))}catch{}},[s]),null}const cn=.03,un=.1,dn=2;function mn(e,t=3){if(e.length<3||t<=0)return e;let o=e;for(let n=0;n<t;n++){const e=[],t=o.length,n=o[0][0]===o[t-1][0]&&o[0][1]===o[t-1][1],r=n?t-1:t;for(let s=0;s<r;s++){const t=o[s],n=o[(s+1)%r],a=.75*t[0]+.25*n[0],i=.75*t[1]+.25*n[1],l=.25*t[0]+.75*n[0],c=.25*t[1]+.75*n[1];e.push([a,i]),e.push([l,c])}n&&e.length>0&&e.push([e[0][0],e[0][1]]),o=e}return o}function hn(e,t={}){const o=function(e,t={}){if(e.length<3)return{coordinates:[],valid:!1};const{bandwidth:o=cn,threshold:n=un,cellSize:r=dn}=t,s=function(e,t){let o=1/0,n=-1/0,r=1/0,s=-1/0;for(const[a,i]of e)a<o&&(o=a),a>n&&(n=a),i<r&&(r=i),i>s&&(s=i);return o-=t,n+=t,r-=t,s+=t,{minX:o,minY:r,maxX:n,maxY:s,width:n-o,height:s-r}}(e,.02),a=Math.ceil(s.width/(o/2)),i=Math.ceil(s.height/(o/2)),l=Math.min(1,200/Math.max(a,i)),c=Math.max(10,Math.ceil(a*l)),u=Math.max(10,Math.ceil(i*l)),d=e=>e/c*s.width+s.minX,m=e=>e/u*s.height+s.minY,h=o/s.width*c;try{const t=gt().x(e=>(e[0]-s.minX)/s.width*c).y(e=>(e[1]-s.minY)/s.height*u).size([c,u]).bandwidth(Math.max(5,h)).cellSize(r)(e);if(0===t.length)return{coordinates:[],valid:!1};const o=Math.max(...t.map(e=>e.value))*n;let a=t[0],i=1/0;for(const e of t){const t=Math.abs(e.value-o);t<i&&(i=t,a=e)}const l=[];for(const e of a.coordinates){const t=[];for(const o of e){const e=[];for(const t of o){const o=d(t[0]),n=m(t[1]);e.push([o,n])}if(e.length>0){const t=e[0],o=e[e.length-1];t[0]===o[0]&&t[1]===o[1]||e.push([t[0],t[1]])}if(e.length>=4){const o=mn(e);t.push(o)}}t.length>0&&l.push(t)}const g=[];for(const e of l)for(const t of e)g.push(t);return{coordinates:l,valid:l.length>0}}catch(g){return console.warn("[KDE Contour] Failed to generate contour:",g),{coordinates:[],valid:!1}}}(e,t);return o.valid&&0!==o.coordinates.length?1===o.coordinates.length?{type:"Polygon",coordinates:o.coordinates[0]}:{type:"MultiPolygon",coordinates:o.coordinates}:null}function gn(e,t,o){return(t[0]-e[0])*(o[1]-e[1])-(t[1]-e[1])*(o[0]-e[0])}function pn(e,t,o,n,r){const s=r*r,a=s*r;return[.5*(2*t[0]+(-e[0]+o[0])*r+(2*e[0]-5*t[0]+4*o[0]-n[0])*s+(-e[0]+3*t[0]-3*o[0]+n[0])*a),.5*(2*t[1]+(-e[1]+o[1])*r+(2*e[1]-5*t[1]+4*o[1]-n[1])*s+(-e[1]+3*t[1]-3*o[1]+n[1])*a)]}function fn(e){let t=function(e){if(e.length<3)return e;const t=[...e].sort((e,t)=>e[0]-t[0]||e[1]-t[1]),o=[];for(const r of t){for(;o.length>=2&&gn(o[o.length-2],o[o.length-1],r)<=0;)o.pop();o.push(r)}const n=[];for(let r=t.length-1;r>=0;r--){const e=t[r];for(;n.length>=2&&gn(n[n.length-2],n[n.length-1],e)<=0;)n.pop();n.push(e)}return o.pop(),n.pop(),o.concat(n)}(e);if(t.length<3)return null;t=function(e){if(e.length<3)return e;let t=0,o=0;for(const[n,r]of e)t+=n,o+=r;return t/=e.length,o/=e.length,e.map(([e,n])=>{const r=e-t,s=n-o,a=Math.sqrt(r*r+s*s);if(a<1e-4)return[e,n];const i=(a+.008)/a;return[t+r*i,o+s*i]})}(t);const o=function(e){if(e.length<3)return e;const t=[],o=e.length;for(let n=0;n<o;n++){const r=e[(n-1+o)%o],s=e[n],a=e[(n+1)%o],i=e[(n+2)%o];for(let e=0;e<12;e++)t.push(pn(r,s,a,i,e/12))}return t}(t);return{type:"Polygon",coordinates:[[...o,o[0]]]}}function xn({partition:o,nodeCoordinates:n,visible:a,opacity:i=.7,bandwidth:l=.05,threshold:c=.15,strokeWidth:u=2}){const d=e.useMemo(()=>o?function(e,t,o,n){const r=[];for(const[s,a]of e.communities){const e=[];for(const o of a){const n=t.get(o);n&&e.push([n[1],n[0]])}if(e.length<3)continue;let i=hn(e,{bandwidth:o,threshold:n});i||(i=fn(e)),i&&r.push({type:"Feature",properties:{community:s,color:ie(s),borderColor:ae(s),nodeCount:a.length},geometry:i})}return{type:"FeatureCollection",features:r}}(o,n,l,c):{type:"FeatureCollection",features:[]},[o,n,l,c]),m=a?i:0,h={"fill-color":["get","color"],"fill-opacity":m},g={"line-color":["get","borderColor"],"line-width":u,"line-opacity":m};return t.jsxs(r,{id:"mincut-partition",type:"geojson",data:d,children:[t.jsx(s,{id:"mincut-partition-fill",type:"fill",paint:h}),t.jsx(s,{id:"mincut-partition-stroke",type:"line",paint:g})]})}function yn(e,t=!1,o=!1,n=!1,r=.7,s){const a=j(s);return n?r>=.75?a.restBright:a.rest:r>=.85?a.rest:a.restDim}function bn(e){return[e[1],e[0]]}function vn(e,t,o,n=12){const[r,s]=e,[a,i]=t,l=[];for(let c=0;c<=n;c++){const e=c/n,t=s+(i-s)*e,u=r+(a-r)*e,d=4*o*e*(1-e);l.push([t,u,d])}return l}function jn(e,t,o,n,r,s,a,i,l,c,u,d="dark"){const m=Tt(),h=[];let g=1/0,p=-1/0;const f=[];for(const y of e){const e=.7*(y.edge.avgConfidence??(t?.7:.5))+y.edge.certainCount/Math.max(a,1)*.3+(t?.5:0);f.push({polyline:y,brightnessScore:e}),g=Math.min(g,e),p=Math.max(p,e)}if(0===f.length)return{type:"FeatureCollection",features:[]};const x=p-g||1;f.sort((e,t)=>e.brightnessScore-t.brightnessScore);for(const{polyline:y,brightnessScore:b}of f){const{from:e,to:a,edge:p}=y,f=o.get(p.key)??0;if(f<=0)continue;const v=i.has(p.key),j=l.has(p.key),w=p.avgConfidence??(t?.7:.5),N=c===p.key,C=u[p.fromHash],k=u[p.toHash],M=(null==C?void 0:C.node_name)||(null==C?void 0:C.name)||p.fromHash.slice(0,8),S=(null==k?void 0:k.node_name)||(null==k?void 0:k.name)||p.toHash.slice(0,8),F=[e[0]+(a[0]-e[0])*f,e[1]+(a[1]-e[1])*f];let R,T,L,E;if(t){const e=s.get(p.key)??Mt(p.certainCount),t=r.get(p.key)??e;R=t+(e-t)*n,N?R=Math.max(1.6*R,4.5):j&&(R*=1.3)}else R=1.5;if(T=N?m.edges.highlight:yn(0,p.isDirectPathEdge??!1,v,j,w,d),L=N?m.edges.highlight:p.isDirectPathEdge?m.edges.hoverDirect:v?m.edges.hoverLoop:m.edges.hoverStandard,t){const e=Math.min(1.5*f,1)*m.edgeOpacity;E=j?1.15*e:e}else E=(.3+.3*w)*f;N&&(E=.95);const B=(b-g)/x;h.push({type:"Feature",properties:{key:p.key,baseColor:T,hoverColor:L,baseWidth:R,baseOpacity:E,brightnessScore:B,isLoopEdge:v,isBackbone:j,isDirectPath:p.isDirectPathEdge??!1,isHubConnection:p.isHubConnection??!1,isZeroHop:p.isZeroHop??!1,isValidated:t,certainCount:p.certainCount,confidence:w,symmetryRatio:p.symmetryRatio??1,dominantDirection:p.dominantDirection??"balanced",fromName:M,toName:S,fromHash:p.fromHash,toHash:p.toHash},geometry:{type:"LineString",coordinates:[bn(e),bn(F)]}})}return{type:"FeatureCollection",features:h}}function wn(e,t){const o=Tt(),n=[];let r=0;for(const s of e){const e=t.get(s.hash);e&&e.blendedScore>r&&(r=e.blendedScore)}for(const s of e){const{from:e,to:a,hash:i,neighbor:l,lastHopData:c}=s,u=`neighbor-${i}`,d=(null==c?void 0:c.avgRssi)??l.rssi??null,m=(null==c?void 0:c.avgSnr)??l.snr??null,h=(null==c?void 0:c.count)??0,g=(null==c?void 0:c.confidence)??1,p=t.get(i),f=(null==p?void 0:p.listenerScore)??0,x=(null==p?void 0:p.loudScore)??0,y=(null==p?void 0:p.blendedScore)??0,b=r>0?y/r:0,v=s.rxAdvertCount??0,j=s.txProxyCount??0,w=v+j,N=w>0?(j-v)/w:0,C=vn(e,a,150,8);n.push({type:"Feature",properties:{key:u,hash:i,name:l.node_name||l.name||i.slice(0,8),prefix:i.slice(2,4).toUpperCase(),color:o.neighborColor,width:2.5,opacity:.85,rssi:d,snr:m,packetCount:h,confidence:g,hasAvgRssi:void 0!==(null==c?void 0:c.avgRssi),hasAvgSnr:void 0!==(null==c?void 0:c.avgSnr),isNeighborEdge:!0,listenerScore:f,loudScore:x,blendedScore:y,trafficWeight:b,linkAsymmetry:N,rxAdvertCount:v,txProxyCount:j},geometry:{type:"LineString",coordinates:C}})}return{type:"FeatureCollection",features:n}}function Nn(e,t){if(e<240)return.5;if(e<480)return 1;const o=(e-480)/(t-480);return Math.max(0,.33*(1-o))}function Cn(e,t,o){const n=o?_(o):null,r=[];for(const s of e){if(n&&s.toUpperCase()===n){o&&r.push(o);continue}const e=t.get(s.toUpperCase());e&&r.push(e)}return r}const kn="edge-blink-source",Mn="edge-blink-layer",Sn=1e3,Fn=1e3,Rn=y.teal,Tn="node-markers-layer";function Ln(e){return e<0||e>=Sn?0:1-e/Sn}function En(e){if(e<0)return 0;if(e>=Fn)return 0;const t=e/Fn;return Math.pow(1-t,3)}function Bn(e){return[e[1],e[0]]}const Dn=[{target:"Sparklines",fn:"sparklines",minStage:2}];u(Dn);const Hn=e.memo(function({nodeHash:e,width:o=60,height:n=20,color:r,showArea:s=!0,showTooltip:a=!1,className:i=""}){c(Dn);const l=K(e),u=V(),d=!Z().backgroundLoadComplete||u,m="number"==typeof o?o:60;return t.jsx(Nt,{data:l,width:m,height:n,color:r,isLoading:d,className:i})});function $n(e){const t=new Date(1e3*e);return`${(t.getMonth()+1).toString().padStart(2,"0")}/${t.getDate().toString().padStart(2,"0")}`}function An({txDelayRec:o,onRemove:n}){const[r,s]=e.useState(!1),a=o.floodFactor??o.txDelayFactor,i=o.directFactor??o.directTxDelayFactor;return t.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[t.jsxs("button",{onClick:async()=>{const e=`set txdelay ${a.toFixed(1)}\nset direct.txdelay ${i.toFixed(1)}`;try{await navigator.clipboard.writeText(e),s(!0),setTimeout(()=>s(!1),1500)}catch(t){const o=document.createElement("textarea");o.value=e,o.style.position="fixed",o.style.opacity="0",document.body.appendChild(o),o.select();try{document.execCommand("copy"),s(!0),setTimeout(()=>s(!1),1500)}catch{console.error("Failed to copy")}document.body.removeChild(o)}},className:"flex items-center gap-2 flex-1 py-1 px-1.5 bg-sys-amber/5 hover:bg-sys-amber/10 rounded transition-colors group",title:"Click to copy CLI commands",children:[t.jsx(ot,{className:"w-3 h-3 text-sys-amber shrink-0"}),t.jsx("span",{className:"text-fg-muted",children:"TxDelay"}),t.jsxs("div",{className:"flex gap-2",children:[t.jsxs("div",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"text-fg-muted",children:"F"}),t.jsxs("span",{className:"data-box data-box-compact text-sys-amber",children:["×",a.toFixed(1)]})]}),t.jsxs("div",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"text-fg-muted",children:"D"}),t.jsxs("span",{className:"data-box data-box-compact text-sys-amber",children:["×",i.toFixed(1)]})]})]}),r?t.jsx(Ue,{className:"w-3 h-3 text-sys-green ml-auto"}):t.jsx(Ye,{className:"w-3 h-3 text-fg-muted opacity-0 group-hover:opacity-100 transition-opacity ml-auto"})]}),n&&t.jsx("button",{onClick:n,className:"p-1 text-fg-secondary hover:text-sys-red hover:bg-sys-red/10 rounded transition-colors",title:"Remove from contacts",children:t.jsx(ze,{className:"w-3.5 h-3.5"})})]})}function Pn({hash:o,hashPrefix:n,name:r,isHub:s,isGateway:a,isBackbone:i,isZeroHop:l,isMobile:c,isRoomServer:u,isStale:d,lastSeenTimestamp:m,centrality:h,affinity:g,meanSnr:p,meanRssi:f,neighbor:x,onRemove:y,txDelayRec:b}){const[v,j]=e.useState(!1),w=l?"Direct":(null==g?void 0:g.typicalHopPosition)?`${g.typicalHopPosition}-hop`:null,N=b&&!b.insufficientData;return t.jsxs("div",{className:"w-[240px] pr-2",children:[t.jsx("div",{className:"text-[14px] font-semibold text-fg-primary leading-tight truncate mb-1",children:r}),t.jsxs("div",{className:"flex items-center gap-1 flex-wrap mb-1.5",children:[t.jsx("code",{className:"type-data-xs text-fg-secondary bg-data-box-bg border border-data-box-border px-1 py-0.5 rounded",children:n}),t.jsx("button",{onClick:async()=>{try{await navigator.clipboard.writeText(o),j(!0),setTimeout(()=>j(!1),1500)}catch(e){console.error("Failed to copy hash:",e);const t=document.createElement("textarea");t.value=o,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select();try{document.execCommand("copy"),j(!0),setTimeout(()=>j(!1),1500)}catch{console.error("Fallback copy also failed")}document.body.removeChild(t)}},className:"p-0.5 hover:bg-subtle-fill-hover rounded transition-colors",title:"Copy full hash",children:v?t.jsx(Ue,{className:"w-3 h-3 text-sys-green"}):t.jsx(Ye,{className:"w-3 h-3 text-fg-secondary"})}),t.jsx(Ct,{hash:o,size:"sm"}),w&&t.jsx(G,{color:l?bt.direct:bt.multihop,compact:!0,children:w}),x.is_repeater&&t.jsx(G,{color:vt.repeater,compact:!0,children:"Rptr"}),s&&t.jsx(G,{color:vt.hub,compact:!0,title:"Hub: ≥10% of last-hop traffic",children:"Hub"}),a&&!s&&t.jsx(G,{color:vt.gateway,compact:!0,title:"Gateway: 7-10% of last-hop traffic",children:"Gate"}),i&&t.jsx(G,{color:vt.backbone,compact:!0,title:"Backbone",children:"Bone"}),c&&t.jsx(G,{color:vt.mobile,compact:!0,children:"Mobile"}),u&&t.jsx(G,{color:vt.room,compact:!0,children:"Room"}),d&&m&&t.jsxs(G,{compact:!0,title:"Neighbor not heard in 7+ days",children:["Idle ",$n(m)]})]}),t.jsxs("div",{className:"flex items-center gap-2 text-xs text-fg-secondary mb-1.5",children:[t.jsxs("span",{className:"flex items-center gap-0.5",children:[t.jsx(Ke,{className:"w-3 h-3 text-fg-muted shrink-0"}),t.jsx("span",{className:"font-mono",children:$(x.last_seen)})]}),(null==g?void 0:g.distanceMeters)&&t.jsxs("span",{className:"flex items-center gap-0.5",children:[t.jsx(et,{className:"w-3 h-3 text-fg-muted shrink-0"}),t.jsx("span",{className:"font-mono font-semibold text-fg-primary",children:(C=g.distanceMeters,null===C?"—":C<1e3?`${Math.round(C)}m`:`${(C/1e3).toFixed(1)}km`)})]}),x.latitude&&x.longitude&&0!==x.latitude&&0!==x.longitude&&t.jsxs("span",{className:"flex items-center gap-0.5",children:[t.jsx(tt,{className:"w-3 h-3 text-fg-muted shrink-0"}),t.jsxs("span",{className:"font-mono text-fg-muted",children:[x.latitude.toFixed(2),", ",x.longitude.toFixed(2)]})]})]}),t.jsx("div",{className:"mb-1.5",style:{width:224},children:t.jsx(Hn,{nodeHash:o,width:224,height:26,showArea:!0,showTooltip:!0})}),t.jsxs("div",{className:"flex gap-3 text-xs mb-1.5",children:[t.jsxs("div",{className:"flex-1 space-y-1",children:[t.jsxs("div",{className:"flex justify-between items-center gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"Packets"}),t.jsx("span",{className:"data-box data-box-compact",children:(null==g?void 0:g.frequency)||0})]}),l&&void 0!==p&&t.jsxs("div",{className:"flex justify-between items-center gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"SNR"}),t.jsxs("span",{className:"data-box data-box-compact",children:[p.toFixed(1)," dB"]})]}),N&&b.networkRole&&t.jsxs("div",{className:"flex justify-between items-center gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"Role"}),t.jsx(G,{color:jt[b.networkRole],compact:!0,title:{hub:"Hub: High-connectivity node that bridges many paths",backbone:"Backbone: Critical relay with high traffic",relay:"Relay: Standard forwarding node",edge:"Edge: Peripheral node"}[b.networkRole],children:b.networkRole})]})]}),t.jsxs("div",{className:"flex-1 space-y-1",children:[t.jsxs("div",{className:"flex justify-between items-center gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"Adverts"}),t.jsx("span",{className:"data-box data-box-compact",children:x.advert_count||0})]}),l&&void 0!==f&&t.jsxs("div",{className:"flex justify-between items-center gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"RSSI"}),t.jsxs("span",{className:"data-box data-box-compact",children:[Math.round(f)," dBm"]})]}),N&&b.dataConfidence&&t.jsxs("div",{className:"flex justify-between items-center gap-2",children:[t.jsx("span",{className:"text-fg-muted",children:"Data"}),t.jsx(G,{color:wt[b.dataConfidence],compact:!0,title:{high:"1000+ packets",medium:"500-999 packets",low:"100-499 packets",insufficient:"Insufficient data"}[b.dataConfidence],children:b.dataConfidence})]})]}),!N&&y&&t.jsx("button",{onClick:y,className:"p-1 self-start text-fg-secondary hover:text-sys-red hover:bg-sys-red/10 rounded transition-colors",title:"Remove from contacts",children:t.jsx(ze,{className:"w-3.5 h-3.5"})})]}),N&&t.jsx(An,{txDelayRec:b,onRemove:y})]});var C}const zn="node-markers-native",In="node-markers-layer",qn="node-markers-layer-local",On="marker-standard",Wn="marker-standard-neighbor",_n="marker-hub",Un="marker-hub-neighbor",Kn="marker-gateway",Vn="marker-gateway-neighbor",Zn="marker-mobile",Gn="marker-mobile-neighbor",Jn="marker-room-server",Yn="marker-room-server-neighbor",Qn="marker-local",Xn="marker-stale-5day",er="marker-stale-10day",tr="marker-blink-black",or="marker-blink-black-local",nr="marker-blink",rr="marker-blink-local",sr={tier1:b[500],tier2:b[700]};function ar(e){if(!e)return 0;const t=(Date.now()-1e3*e)/864e5;return t>=10?2:t>=5?1:0}function ir(e){var t;const o=null==(t=e.contact_type)?void 0:t.toLowerCase();return"room server"===o||"room_server"===o||"room"===o||"server"===o}function lr(e){return e.startsWith("0x")?e.slice(2,4).toUpperCase():e.slice(0,2).toUpperCase()}function cr({neighborsWithLocation:o,localNode:i,localHash:l,zeroHopNeighbors:c,lastHopNeighborMap:u,meshTopology:d,hoveredMarker:m,onMarkerHover:h,getNodeOpacity:g,shouldShowNode:p,onRequestRemove:f,openPopupId:x,onOpenPopup:y,onClosePopup:b,onNodeClick:j,blinkingNodes:w}){const{current:N}=n(),C=e.useRef(!1),[k,M]=e.useState(!1);e.useEffect(()=>{var e;const t=null==(e=null==N?void 0:N.getMap)?void 0:e.call(N);if(!t)return;const o=()=>{try{!function(e){const t=v(),o=(e,t,o=0,n=!1)=>{const r=document.createElement("canvas");r.width=32,r.height=32;const s=r.getContext("2d",n?{colorSpace:"display-p3"}:void 0),a=14-o/2;return s.beginPath(),s.arc(16,16,a,0,2*Math.PI),s.fillStyle=e,s.fill(),t&&o>0&&(s.strokeStyle=t,s.lineWidth=2*o,s.stroke()),s.shadowColor="rgba(0,0,0,0.3)",s.shadowBlur=4,s.shadowOffsetY=2,{data:s.getImageData(0,0,32,32),pixelRatio:2}},n=(e,t=!1)=>{const o=document.createElement("canvas");o.width=48,o.height=48;const n=o.getContext("2d",t?{colorSpace:"display-p3"}:void 0),r=24*.35*2;return n.strokeStyle=e,n.lineWidth=5,n.lineCap="round",n.lineJoin="round",n.beginPath(),n.moveTo(24-r,24),n.lineTo(24,24-r),n.lineTo(40.8,24),n.stroke(),n.beginPath(),n.moveTo(24-.7*r,24),n.lineTo(24-.7*r,35.76),n.lineTo(35.76,35.76),n.lineTo(35.76,24),n.stroke(),n.beginPath(),n.moveTo(20.64,35.76),n.lineTo(20.64,27.36),n.lineTo(27.36,27.36),n.lineTo(27.36,35.76),n.stroke(),{data:n.getImageData(0,0,48,48),pixelRatio:2}},r=(e,t)=>{const o=document.createElement("canvas");o.width=48,o.height=48;const n=o.getContext("2d"),r=24*.35*2;return n.strokeStyle=e,n.lineWidth=5,n.lineCap="round",n.lineJoin="round",t&&(n.fillStyle=t),n.beginPath(),n.roundRect(24-r,24-.6*r,1.6*r,1.2*r,6),t&&n.fill(),n.stroke(),n.beginPath(),n.moveTo(18.96,34.08),n.lineTo(24-.6*r,40.8),n.lineTo(24,34.08),n.stroke(),{data:n.getImageData(0,0,48,48),pixelRatio:2}},s="#00FF00",a={[On]:o(t.nodeFill),[Wn]:o(t.neighborColor),[_n]:o(t.hubColor),[Un]:o(t.neighborColor),[Kn]:o(t.gatewayColor),[Vn]:o(t.neighborColor),[Zn]:o("transparent",t.mobileColor,2.5),[Gn]:o(t.neighborColor),[Jn]:r(t.roomColor),[Yn]:r(t.neighborColor,"#1a1a1c"),[Qn]:n(t.localColor),[Xn]:o(sr.tier1),[er]:o(sr.tier2),[tr]:o("#000000"),[or]:n("#000000"),[nr]:o(s,void 0,0,!0),[rr]:n(s,!0)};for(const[i,l]of Object.entries(a))try{e.hasImage(i)&&e.removeImage(i),e.addImage(i,l.data,{pixelRatio:l.pixelRatio})}catch{}}(t),C.current=!0,k||M(!0)}catch(e){console.warn("Failed to load node marker icons:",e)}};t.isStyleLoaded()?o():t.once("style.load",o);const n=()=>{t.hasImage(On)||o()};t.on("styledata",n);const r=()=>{C.current=!1,o()},s=new MutationObserver(e=>{for(const t of e)if("data-theme"===t.attributeName){setTimeout(r,100);break}});s.observe(document.documentElement,{attributes:!0});const a=document.querySelector("[data-basemap]");let i=null;return a&&(i=new MutationObserver(e=>{for(const t of e)if("data-basemap"===t.attributeName){setTimeout(r,100);break}}),i.observe(a,{attributes:!0})),()=>{t.off("styledata",n),s.disconnect(),null==i||i.disconnect()}},[N,k]);const S=e.useMemo(()=>{var e;const t=[],n=[...o].sort(([e,t],[o,n])=>{const r=(e,t)=>{var o;return ir(t)?5e3:c.has(e)?3e3:d.hubNodes.includes(e)?2e3:(null==(o=d.gatewayNodes)?void 0:o.includes(e))?1e3:0};return r(e,t)-r(o,n)});for(const[o,r]of n){if(!r.latitude||!r.longitude)continue;if(l&&((l.startsWith("0x")?l.slice(2,4).toLowerCase():l.slice(0,2).toLowerCase())===(o.startsWith("0x")?o.slice(2,4).toLowerCase():o.slice(0,2).toLowerCase())||o===l))continue;const n=p(o),s=g(o,n);if(s<=.01)continue;const a=c.has(o),i=d.hubNodes.includes(o),m=(null==(e=d.gatewayNodes)?void 0:e.includes(o))??!1,h=d.mobileNodes.includes(o),f=ir(r),x=d.centrality.get(o)||0,y=u.get(o),b=r.last_seen||(null==y?void 0:y.lastSeen),v=ar(b),j=v>0;let w=s;2===v?w=Math.min(s,.25):1===v&&(w=Math.min(s,.5));let N="standard";f?N="roomServer":i?N="hub":m?N="gateway":h&&(N="mobile");const C=d.fullAffinity.get(o),k=d.txDelayRecommendations.get(o);t.push({type:"Feature",geometry:{type:"Point",coordinates:[r.longitude,r.latitude]},properties:{hash:o,name:r.node_name||r.name||"Unknown",hashPrefix:lr(o),iconType:N,isNeighbor:a,isHub:i,isGateway:m,isMobile:h,isRoomServer:f,isStale:j,staleTier:v,isZeroHop:a,opacity:w,blinkIntensity:0,lastSeenTimestamp:b,centrality:x,neighborJson:JSON.stringify(r),affinityJson:C?JSON.stringify(C):void 0,txDelayRecJson:k?JSON.stringify(k):void 0,meanSnr:(null==y?void 0:y.avgSnr)??void 0,meanRssi:(null==y?void 0:y.avgRssi)??void 0}})}return{type:"FeatureCollection",features:t}},[o,l,c,u,d,g,p]),F=e.useMemo(()=>(null==i?void 0:i.latitude)&&(null==i?void 0:i.longitude)?{type:"FeatureCollection",features:[{type:"Feature",geometry:{type:"Point",coordinates:[i.longitude,i.latitude]},properties:{hash:"local",name:i.name,hashPrefix:l?lr(l):"",iconType:"local",isNeighbor:!1,isHub:!1,isGateway:!1,isMobile:!1,isRoomServer:!1,isStale:!1,staleTier:0,isZeroHop:!1,opacity:1,blinkIntensity:0,centrality:0}}]}:{type:"FeatureCollection",features:[]},[i,l]),R=e.useCallback(e=>{var t;if(!e.features||0===e.features.length)return;const o=null==(t=e.features[0].properties)?void 0:t.hash;o&&(y&&y(o),j&&"local"!==o&&j(o))},[y,j]),T=e.useCallback(e=>{var t,o;if(!e.features||0===e.features.length)return;const n=null==(t=null==N?void 0:N.getMap)?void 0:t.call(N);n&&(n.getCanvas().style.cursor="pointer");const r=null==(o=e.features[0].properties)?void 0:o.hash;r&&h(r)},[N,h]),L=e.useCallback(()=>{var e;const t=null==(e=null==N?void 0:N.getMap)?void 0:e.call(N);t&&(t.getCanvas().style.cursor=""),h(null)},[N,h]);e.useEffect(()=>{var e;const t=null==(e=null==N?void 0:N.getMap)?void 0:e.call(N);if(!t||!k)return;const o=[In,qn];for(const n of o)t.on("click",n,R),t.on("mouseenter",n,T),t.on("mouseleave",n,L);return()=>{for(const e of o)t.off("click",e,R),t.off("mouseenter",e,T),t.off("mouseleave",e,L)}},[N,k,R,T,L]);const E=e.useRef(S),B=e.useRef(F);e.useEffect(()=>{E.current=S,B.current=F},[S,F]),e.useEffect(()=>{var e;const t=null==(e=null==N?void 0:N.getMap)?void 0:e.call(N);if(!t||!k||!w||0===w.size)return;const o=t.getSource(zn),n=t.getSource(`${zn}-local`);if(o||n){if(o){const e=E.current;let t=!1;const n=e.features.map(e=>{const o=w.get(e.properties.hash)??0;return o!==e.properties.blinkIntensity?(t=!0,{...e,properties:{...e.properties,blinkIntensity:o}}):e});t&&o.setData({type:"FeatureCollection",features:n})}if(n&&l){const e=w.get(l)??0,t=B.current;t.features.length>0&&t.features[0].properties.blinkIntensity!==e&&n.setData({type:"FeatureCollection",features:[{...t.features[0],properties:{...t.features[0].properties,blinkIntensity:e}}]})}}},[N,k,w,l]);const D=e.useMemo(()=>{if(!x)return null;if("local"===x&&i)return{longitude:i.longitude,latitude:i.latitude,isLocal:!0,name:i.name,hash:l};const e=S.features.find(e=>e.properties.hash===x);if(!e)return null;const t=e.properties,o=t.txDelayRecJson?JSON.parse(t.txDelayRecJson):void 0;return{longitude:e.geometry.coordinates[0],latitude:e.geometry.coordinates[1],isLocal:!1,hash:t.hash,hashPrefix:t.hashPrefix,name:t.name,isHub:t.isHub,isGateway:t.isGateway,isBackbone:"backbone"===(null==o?void 0:o.networkRole),isZeroHop:t.isZeroHop,isMobile:t.isMobile,isRoomServer:t.isRoomServer,isStale:t.isStale,lastSeenTimestamp:t.lastSeenTimestamp,centrality:t.centrality,neighbor:t.neighborJson?JSON.parse(t.neighborJson):void 0,affinity:t.affinityJson?JSON.parse(t.affinityJson):void 0,txDelayRec:o,meanSnr:t.meanSnr,meanRssi:t.meanRssi}},[x,i,l,S]);if(!k)return null;const H=v(),$=["case",[">",["get","blinkIntensity"],.66],nr,[">",["get","blinkIntensity"],.33],tr,["==",["get","staleTier"],2],er,["==",["get","staleTier"],1],Xn,["==",["get","iconType"],"roomServer"],["case",["get","isNeighbor"],Yn,Jn],["==",["get","iconType"],"hub"],["case",["get","isNeighbor"],Un,_n],["==",["get","iconType"],"gateway"],["case",["get","isNeighbor"],Vn,Kn],["==",["get","iconType"],"mobile"],["case",["get","isNeighbor"],Gn,Zn],["case",["get","isNeighbor"],Wn,On]],A=["interpolate",["linear"],["zoom"],6,.25,10,1];return t.jsxs(t.Fragment,{children:[t.jsx(r,{id:zn,type:"geojson",data:S,children:t.jsx(s,{id:In,type:"symbol",layout:{"icon-image":$,"icon-size":A,"icon-allow-overlap":!0,"icon-ignore-placement":!0,"symbol-sort-key":["get","opacity"]},paint:{"icon-opacity":["get","opacity"]}})}),t.jsx(r,{id:`${zn}-local`,type:"geojson",data:F,children:t.jsx(s,{id:qn,type:"symbol",layout:{"icon-image":["case",[">",["get","blinkIntensity"],.66],rr,[">",["get","blinkIntensity"],.33],or,Qn],"icon-size":A,"icon-allow-overlap":!0,"icon-ignore-placement":!0},paint:{"icon-opacity":1}})}),D&&b&&t.jsx(a,{longitude:D.longitude,latitude:D.latitude,offset:{center:[0,0],top:[0,12],"top-left":[6,12],"top-right":[-6,12],bottom:[0,-12],"bottom-left":[6,-12],"bottom-right":[-6,-12],left:[12,0],right:[-12,0]},maxWidth:"280px",closeOnClick:!0,onClose:b,className:"maplibre-popup",children:D.isLocal?t.jsxs("div",{className:"text-sm",children:[t.jsx("strong",{className:"text-base",children:D.name}),D.hash&&t.jsx("span",{className:"ml-2 font-mono text-xs text-fg-muted surface-badge px-1.5 py-0.5 rounded",children:lr(D.hash)}),t.jsx("br",{}),t.jsx("span",{style:{color:H.localColor},className:"font-medium",children:"This Node (Local)"}),t.jsx("br",{}),i&&t.jsxs("span",{className:"text-xs text-fg-muted",children:[i.latitude.toFixed(5),", ",i.longitude.toFixed(5)]})]}):D.neighbor&&D.hash?t.jsx(Pn,{hash:D.hash,hashPrefix:D.hashPrefix,name:D.name,isHub:D.isHub,isGateway:D.isGateway,isBackbone:D.isBackbone,isZeroHop:D.isZeroHop,isMobile:D.isMobile,isRoomServer:D.isRoomServer,isStale:D.isStale,lastSeenTimestamp:D.lastSeenTimestamp,centrality:D.centrality,affinity:D.affinity,meanSnr:D.meanSnr,meanRssi:D.meanRssi,neighbor:D.neighbor,txDelayRec:D.txDelayRec,onRemove:f?()=>f(D.hash,D.name):void 0}):null})]})}const ur=[In,qn],dr="topology-validated-edges-native",mr="topology-weak-edges-native",hr="neighbor-edges-native",gr="topology-weak-edges-native",pr="topology-validated-edges-native",fr="neighbor-edges-native",xr={type:"FeatureCollection",features:[]},yr={"line-cap":"round","line-join":"round"},br={"line-color":"transparent","line-width":16,"line-opacity":0};function vr({showTopology:o,isExiting:a,hoveredEdgeKey:i,highlightedLoopEdges:l,highlightedFocusEdges:c,onEdgeHover:u,onLoopHover:d,loops:m=[],neighborNames:h={},opacityBias:p=.5,widthMultiplier:f=1,trafficFilter:x=0,showNeighborLines:y=!0,disableHover:b=!1}){const{current:v}=n(),j=o||a,w=!0,N=y?"visible":"none",C=b||a,k=e.useRef(null),M=e.useRef(C),S=e.useRef(new Map),F=e.useRef(h),R=e.useRef(d);e.useLayoutEffect(()=>{M.current=C,F.current=h,R.current=d});const T=e.useMemo(()=>function(e){const t=new Map;for(const o of e)for(const e of o.edgeKeys){const n=t.get(e)??[];n.push(o),t.set(e,n)}return t}(m),[m]);e.useLayoutEffect(()=>{S.current=T},[T]);const L=e.useCallback(e=>{var t,o;if(M.current)return;if(!e.features||0===e.features.length)return;const n=e.features[0].properties;if(!(null==n?void 0:n.key))return;const r=n.key;if(r!==k.current){k.current=r;const s=!0===n.isNeighborEdge||"true"===n.isNeighborEdge,a=!0===n.isLoopEdge||"true"===n.isLoopEdge;if(s){const o={key:r,fromName:"Local",toName:n.name,certainCount:Number(n.packetCount)||0,confidence:1,isBackbone:!1,isLoopEdge:!1,isDirectPath:!0,isZeroHop:!0,symmetryRatio:1,dominantDirection:"balanced",isHubConnection:!1};u(r,[e.lngLat.lng,e.lngLat.lat],o),null==(t=R.current)||t.call(R,null)}else if(a&&R.current){const t=S.current.get(r)??[];if(t.length>0){const o=new Set;for(const e of t)for(const t of e.edgeKeys)o.add(t);const n={loops:t,highlightedEdgeKeys:o,hoveredEdgeKey:r,nodeNames:t[0].nodes.map(e=>F.current[e]||e.substring(0,4))};R.current(n,[e.lngLat.lng,e.lngLat.lat]),u(r)}else{const t={key:r,fromName:n.fromName,toName:n.toName,certainCount:Number(n.certainCount),confidence:Number(n.confidence),isBackbone:!0===n.isBackbone||"true"===n.isBackbone,isLoopEdge:!0,isDirectPath:!0===n.isDirectPath||"true"===n.isDirectPath,isZeroHop:!0===n.isZeroHop||"true"===n.isZeroHop,symmetryRatio:Number(n.symmetryRatio),dominantDirection:n.dominantDirection,isHubConnection:!0===n.isHubConnection||"true"===n.isHubConnection};u(r,[e.lngLat.lng,e.lngLat.lat],t)}}else{const t={key:r,fromName:n.fromName,toName:n.toName,certainCount:Number(n.certainCount),confidence:Number(n.confidence),isBackbone:!0===n.isBackbone||"true"===n.isBackbone,isLoopEdge:a,isDirectPath:!0===n.isDirectPath||"true"===n.isDirectPath,isZeroHop:!0===n.isZeroHop||"true"===n.isZeroHop,symmetryRatio:Number(n.symmetryRatio),dominantDirection:n.dominantDirection,isHubConnection:!0===n.isHubConnection||"true"===n.isHubConnection};u(r,[e.lngLat.lng,e.lngLat.lat],t),null==(o=R.current)||o.call(R,null)}}},[u]),E=e.useCallback(()=>{var e;null!==k.current&&(k.current=null,u(null),null==(e=R.current)||e.call(R,null))},[u]);e.useEffect(()=>{var e;const t=null==(e=null==v?void 0:v.getMap)?void 0:e.call(v);if(!t||!j)return;const o="topology-validated-edges-hitarea-native",n=()=>{try{return t.getStyle()&&t.getLayer(o)}catch{return!1}},r=()=>!!n()&&(t.on("mousemove",o,L),t.on("mouseleave",o,E),!0);if(!r()){const e=()=>{r()&&t.off("styledata",e)};return t.on("styledata",e),()=>{try{t.off("styledata",e),n()&&(t.off("mousemove",o,L),t.off("mouseleave",o,E))}catch{}}}return()=>{try{n()&&(t.off("mousemove",o,L),t.off("mouseleave",o,E))}catch{}}},[v,j,L,E]),e.useEffect(()=>{var e;const t=null==(e=null==v?void 0:v.getMap)?void 0:e.call(v);if(!t||!y)return;const o="neighbor-edges-hitarea-native",n=()=>{try{return t.getStyle()&&t.getLayer(o)}catch{return!1}},r=()=>!!n()&&(t.on("mousemove",o,L),t.on("mouseleave",o,E),!0);if(!r()){const e=()=>{r()&&t.off("styledata",e)};return t.on("styledata",e),()=>{try{t.off("styledata",e),n()&&(t.off("mousemove",o,L),t.off("mouseleave",o,E))}catch{}}}return()=>{try{n()&&(t.off("mousemove",o,L),t.off("mouseleave",o,E))}catch{}}},[v,w,y,L,E]),e.useEffect(()=>{var e;const t=null==(e=null==v?void 0:v.getMap)?void 0:e.call(v);if(!t)return;let o=null;const n=(e,o)=>{try{if(t.getLayer(e)&&t.getLayer(o))return t.moveLayer(e,o),!0}catch{}return!1},r=()=>{try{if(!t.getLayer("node-markers-layer"))return;n(fr,"node-markers-layer"),n("neighbor-edges-hitarea-native",fr),(n(pr,"neighbor-edges-hitarea-native")||n(pr,"node-markers-layer"))&&n("topology-validated-edges-hitarea-native",pr),n(gr,"topology-validated-edges-hitarea-native")}catch{}},s=()=>{o&&clearTimeout(o),o=setTimeout(r,50)},a=setTimeout(r,100);t.on("styledata",s);const i=e=>{(e.sourceId===dr||e.sourceId===mr||e.sourceId===hr)&&s()};return t.on("sourcedata",i),()=>{clearTimeout(a),o&&clearTimeout(o);try{t.off("styledata",s),t.off("sourcedata",i)}catch{}}},[v,j,w,y]);const B=C?null:i,D=function(e,t,o,n,r,s){const a=Tt(),i=null!==e,l=r&&r.size>0,c=s&&s.size>0,u=l?Array.from(r):[],d=c?Array.from(s):[],m=t<=0?["get","baseColor"]:["case",[">=",["get","brightnessScore"],1-.5*t],"#FFFFFF",["get","baseColor"]],h=t<=0?1:["max",.1,["+",1,["*",t,3,["-",["get","brightnessScore"],.5]]]],g=l?["in",["get","key"],["literal",u]]:c?["in",["get","key"],["literal",d]]:!!i&&["==",["get","key"],e],p=i||l||c,f=a.edges.hoverLoop,x=a.edges.highlight;return{"line-color":p?["case",g,l?f:c?x:["get","hoverColor"],m]:m,"line-width":p?["case",g,["max",["*",["get","baseWidth"],o,1.3],3.5],["*",["get","baseWidth"],o]]:["*",["get","baseWidth"],o],"line-opacity":["case",["<",["get","brightnessScore"],n],0,p?["case",g,["min",["*",["get","baseOpacity"],1.25],1],["*",["get","baseOpacity"],h,.35]]:["*",["get","baseOpacity"],h]]}}(B,p,f,x,C?null:l,c??null),H=function(e){const t=null!==e,{YELLOW:o,GREEN:n,RED:r,GRAY:s}=g,a=["to-number",["get","listenerScore"],0],i=["to-number",["get","loudScore"],0],l=["/",a,["max",["+",a,i],1]],c=["*",["+",.2,["*",["to-number",["get","trafficWeight"],0],.8]],8];return{"line-color":["case",["all",["==",a,0],["==",i,0]],s,[">=",l,.97],n,["<=",l,.03],r,["interpolate",["linear"],l,.03,r,.5,o,.97,n]],"line-width":["interpolate",["linear"],["zoom"],6,t?["case",["==",["get","key"],e],["max",["*",c,.25],1.25],["*",c,.25]]:["*",c,.25],10,t?["case",["==",["get","key"],e],["max",c,5],c]:c],"line-opacity":t?["case",["==",["get","key"],e],1,.35]:.9}}(B);return t.jsxs(t.Fragment,{children:[j&&t.jsx(r,{id:mr,type:"geojson",data:xr,children:t.jsx(s,{id:gr,type:"line",paint:D,layout:{...yr,visibility:N}})}),j&&t.jsxs(r,{id:dr,type:"geojson",data:xr,children:[t.jsx(s,{id:"topology-validated-edges-hitarea-native",type:"line",paint:br,layout:{...yr,visibility:N}}),t.jsx(s,{id:pr,type:"line",paint:D,layout:{...yr,visibility:N}})]}),t.jsxs(r,{id:hr,type:"geojson",data:xr,children:[t.jsx(s,{id:"neighbor-edges-hitarea-native",type:"line",paint:br,layout:{...yr,visibility:N}}),t.jsx(s,{id:fr,type:"line",paint:H,layout:{...yr,visibility:N}})]})]})}const jr=["topology-validated-edges-hitarea-native","topology-validated-edges-native","topology-weak-edges-native","neighbor-edges-hitarea-native","neighbor-edges-native"];function wr({targetHash:t,nodeCoordinates:o,onComplete:r}){const{current:s}=n(),a=e.useRef(null);return e.useEffect(()=>{if(!s||!t||t===a.current)return;const e=o.get(t);if(!e)return;const n=s.getMap();n.isMoving()&&n.stop(),a.current=t;const[i,l]=e;s.flyTo({center:[l,i],zoom:10,duration:2500,essential:!0}),setTimeout(()=>{null==r||r()},2600)},[t,o,s,r]),null}function Nr({highlightedEdgeKey:t,validatedPolylines:o,weakPolylines:r,onEnsureTopology:s}){const{current:a}=n(),i=e.useRef(null);return e.useEffect(()=>{if(!a||!t)return;if(t===i.current)return;i.current=t,s();const e=o.find(e=>e.edge.key===t)||r.find(e=>e.edge.key===t);if(!e)return;if(a.getMap().isMoving())return;const n=(e.from[0]+e.to[0])/2,l=(e.from[1]+e.to[1])/2,c=a.getZoom(),u=Math.max(c,11);a.easeTo({center:[l,n],zoom:u,duration:500})},[t,o,r,a,s]),null}const Cr="link-quality-edges",kr="link-quality-edges-hitarea",Mr={type:"FeatureCollection",features:[]};function Sr(e,t){return e<t?`${e}|${t}`:`${t}|${e}`}const Fr={"line-cap":"round","line-join":"round"},Rr={"line-color":["get","color"],"line-width":["get","width"],"line-opacity":.85},Tr={"line-color":"transparent","line-width":16,"line-opacity":0};function Lr({visible:o,nodeCoordinates:a,focusedNodeHash:i=null,basemapMode:l}){const{current:c}=n(),u=J(),d=L(),m=Y(),h=e.useMemo(()=>Q(),[]),g=e.useMemo(()=>o&&0!==u.length&&0!==d.size?function(e,t,o,n,r){const s=[];for(const a of e){if(o&&a.nodeA.hash!==o&&a.nodeB.hash!==o)continue;const e=t.get(a.nodeA.hash),i=t.get(a.nodeB.hash);if(!e||!i)continue;const l=n[X(a.composite.mean,r)]||"#888888",c=2+2*a.confidence,u=Sr(a.nodeA.hash,a.nodeB.hash);s.push({type:"Feature",geometry:{type:"LineString",coordinates:[[e[1],e[0]],[i[1],i[0]]]},properties:{key:u,color:l,width:c,quality:a.quality,compositeMeanSnr:a.composite.mean,confidence:a.confidence,fromHash:a.nodeA.hash,toHash:a.nodeB.hash,fromPrefix:a.nodeA.prefix,toPrefix:a.nodeB.prefix,fromName:a.nodeA.name||a.nodeA.prefix,toName:a.nodeB.name||a.nodeB.prefix,asymmetryDb:a.asymmetryDb}})}return{type:"FeatureCollection",features:s}}(u,a,i,h,m):Mr,[o,u,d.size,a,i,h,m]);e.useEffect(()=>{if(!c)return;const e=c.getMap();if(e)try{const t=e.getSource(Cr);t&&"setData"in t&&(t.setData(g),e.triggerRepaint())}catch{}},[g,c]);const p=o?"visible":"none";return t.jsxs(r,{id:Cr,type:"geojson",data:Mr,children:[t.jsx(s,{id:"link-quality-edges-layer",type:"line",layout:{...Fr,visibility:p},paint:Rr}),t.jsx(s,{id:kr,type:"line",layout:{...Fr,visibility:p},paint:Tr})]})}function Er(e,t,o,n=64){const r=[],s=o/6371e3*(180/Math.PI),a=s/Math.cos(t*Math.PI/180);for(let i=0;i<=n;i++){const o=i/n*2*Math.PI,l=e+a*Math.cos(o),c=t+s*Math.sin(o);r.push([l,c])}return{type:"Feature",properties:{},geometry:{type:"Polygon",coordinates:[r]}}}function Br({ghost:o,neighborCoordinates:a,onHighlightedNeighborsChange:i}){const{current:l}=n(),c=e.useRef(null),u=e.useRef(null),d=e.useMemo(()=>o?new Set(o.commonNeighbors):new Set,[o]);e.useEffect(()=>{null==i||i(d)},[d,i]);const m=e.useMemo(()=>{if(!(null==o?void 0:o.commonNeighbors)||o.commonNeighbors.length<2)return 8e3;let e=0;const t=[];for(const n of o.commonNeighbors){const e=a.get(n);e&&t.push(e)}o.estimatedLocation&&t.push([o.estimatedLocation.lat,o.estimatedLocation.lon]);for(let o=0;o<t.length;o++)for(let n=o+1;n<t.length;n++){const r=kt(t[o][0],t[o][1],t[n][0],t[n][1]);r>e&&(e=r)}return Math.max(e,2e3)},[o,a]),h=e.useMemo(()=>{if(!(null==o?void 0:o.estimatedLocation))return{type:"FeatureCollection",features:[]};const{lat:e,lon:t,uncertaintyM:n}=o.estimatedLocation,r=.5*m,s=n>0?n:2e3;return{type:"FeatureCollection",features:[Er(t,e,Math.max(500,Math.min(s,r)))]}},[o,m]);if(e.useEffect(()=>{if(!l)return;const e=l.getMap();if(o&&o.prefix!==u.current){if(u.current=o.prefix,!c.current&&e.getZoom()>3){const t=e.getCenter();c.current={center:[t.lng,t.lat],zoom:e.getZoom(),pitch:e.getPitch(),bearing:e.getBearing()}}const t=[];for(const e of o.commonNeighbors){const o=a.get(e);o&&t.push([o[1],o[0]])}if(o.estimatedLocation&&t.push([o.estimatedLocation.lon,o.estimatedLocation.lat]),t.length>0){const n=()=>{var r;if(e.isMoving())setTimeout(n,100);else if(1===t.length)l.flyTo({center:t[0],zoom:13,duration:1500});else{let e=1/0,n=-1/0,s=1/0,a=-1/0;for(const[o,r]of t)e=Math.min(e,o),n=Math.max(n,o),s=Math.min(s,r),a=Math.max(a,r);if(null==(r=o.estimatedLocation)?void 0:r.uncertaintyM){const t=o.estimatedLocation.uncertaintyM/111e3;e-=t,n+=t,s-=t,a+=t}l.fitBounds([[e,s],[n,a]],{padding:{top:60,bottom:60,left:60,right:60},maxZoom:14,duration:1500})}};setTimeout(n,50)}}if(!o&&null!==u.current&&(u.current=null,c.current)){const t=c.current,o=()=>{e.isMoving()?setTimeout(o,100):(l.flyTo({center:t.center,zoom:t.zoom,pitch:t.pitch,bearing:t.bearing,duration:1e3}),c.current=null)};setTimeout(o,50)}},[o,l,a]),!(null==o?void 0:o.estimatedLocation))return null;return t.jsx(r,{id:"ghost-uncertainty-circle",type:"geojson",data:h,children:t.jsx(s,{id:"ghost-uncertainty-fill",type:"fill",paint:{"fill-color":"rgba(167, 139, 250, 0.15)","fill-opacity":.8}})})}const Dr=[{target:"Map",fn:"gps",minStage:1,when:d},{target:"Map",fn:"_advertNodeType",minStage:1,when:d},{target:"Topology",fn:"traceHops",minStage:1,when:m},{target:"Topology",fn:"path.entries",minStage:1,when:h},{target:"Topology",fn:"traceSrc",minStage:1,when:m}];u(Dr);const Hr={version:8,sources:{},layers:[],glyphs:"https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf"},$r={longitude:0,latitude:0,zoom:2};function Ar({data:e}){const o=e.subtitle&&"loop"===e.type,n=e.subtitle&&"loop"!==e.type;return t.jsxs("div",{className:"w-[540px]",children:[t.jsxs("div",{className:"flex items-center justify-between h-5",children:[t.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.title.icon&&t.jsx("span",{className:`${e.title.color} text-base leading-none flex-shrink-0`,children:e.title.icon}),t.jsx("span",{className:`${e.title.color} font-semibold text-[13px] truncate`,children:e.title.text}),n&&t.jsx("span",{className:`${e.subtitle.color} text-[11px] flex-shrink-0`,children:e.subtitle.text})]}),e.badges.length>0&&t.jsx("div",{className:"flex items-center gap-2 flex-shrink-0 ml-3",children:e.badges.map((e,o)=>t.jsx("span",{className:`${e.color} text-[11px] font-medium`,children:e.text},o))})]}),o&&t.jsx("div",{className:"h-4 mt-0.5 overflow-hidden",children:t.jsx("span",{className:"type-data-xs text-fg-muted truncate block",children:e.subtitle.text})}),t.jsx("div",{className:`flex items-center gap-4 h-4 ${o?"mt-1":"mt-1.5"} text-[11px]`,children:e.stats.map((e,o)=>t.jsxs("span",{className:"whitespace-nowrap",children:[t.jsx("span",{className:`font-mono tabular-nums font-semibold ${e.color??"text-fg-primary"}`,children:e.value}),t.jsx("span",{className:"text-fg-muted ml-1",children:e.label}),e.unit&&t.jsx("span",{className:"text-fg-muted/50 ml-0.5",children:e.unit})]},o))})]})}function Pr({neighbors:o,localNode:n,localHash:r,onRemoveNode:s,selectedNodeHash:a,onNodeSelected:u,highlightedEdgeKey:d,highlightedGhost:m}){c(Dr);const h=e.useRef(null),g=ee(),f=te(),x=Z(),y=oe(),b=ne(),v=J(),[j,w]=e.useState(!1),N=lt(e=>e.viewState),C=lt(e=>e.toggles),k=lt(e=>e.hasAnalyzed),M=lt(e=>e.setViewState),S=lt(e=>e.setToggle),F=lt(e=>e.setHasAnalyzed),R=lt(e=>e.modalMapOpen),T=re(e=>e.preloadFromNodes),L=re(e=>e.isLoading),E=re(e=>e.terrainGrid),B=r??y,D=e.useMemo(()=>{const e=[];for(const[,t]of Object.entries(o))t.latitude&&t.longitude&&e.push([t.latitude,t.longitude]);return e},[o]),H=e.useMemo(()=>function(e,t){let o=[...e];if((null==t?void 0:t.latitude)&&(null==t?void 0:t.longitude)&&o.push([t.latitude,t.longitude]),0===o.length)return null;if(1===o.length){const[e,t]=o[0];return{longitude:t,latitude:e,zoom:14}}o=function(e,t){if(e.length<=2)return e;let o,n;if((null==t?void 0:t.latitude)&&(null==t?void 0:t.longitude))o=t.latitude,n=t.longitude;else{let t=0,r=0;for(const[o,n]of e)t+=o,r+=n;o=t/e.length,n=r/e.length}const r=e.map(([e,t])=>{return{pos:[e,t],dist:(r=o,s=n,a=e,i=t,kt(r,s,a,i)/1e3)};var r,s,a,i});r.sort((e,t)=>e.dist-t.dist);const s=r[Math.floor(r.length/2)].dist,a=Math.max(3*s,50),i=r.filter(e=>e.dist<=a).map(e=>e.pos);return i.length<.5*e.length?e:i}(o,t);let n=1/0,r=-1/0,s=1/0,a=-1/0;for(const[h,g]of o)n=Math.min(n,g),r=Math.max(r,g),s=Math.min(s,h),a=Math.max(a,h);const i=(n+r)/2,l=(s+a)/2,c=a-s,u=r-n,d=Math.max(c,u);let m=16;return d>0&&(m=Math.floor(Math.log2(360/d*1.2)),m=Math.max(1,Math.min(14,m))),m=Math.min(m+1,12),{longitude:i,latitude:l,zoom:m}}(D,n),[D,n]),[$,A]=e.useState(()=>N??H??$r),P=e.useCallback(e=>{A(e),queueMicrotask(()=>M(e))},[M]),z=e.useRef(!!N);e.useEffect(()=>{z.current||!H||N?N&&setTimeout(()=>w(!0),50):(A(H),queueMicrotask(()=>M(H)),z.current=!0,setTimeout(()=>w(!0),50))},[H,N,M]);const[I,q]=e.useState(!1),[O,K]=e.useState(()=>!(C.showTopology&&!x.topologyLoadComplete)&&C.showTopology),[V,G]=e.useState(C.showNeighborLines),[Y,Q]=e.useState(!1),[X,ae]=e.useState(C.showMinCut),[ie,ue]=e.useState(To),[de,me]=e.useState(C.show3DTerrain),[he,ge]=e.useState(C.showLinkQuality),[pe,fe]=e.useState(()=>C.nodeFilters.length>0?C.nodeFilters:[...at]),xe=e.useCallback(e=>{K(t=>{const o="function"==typeof e?e(t):e;return queueMicrotask(()=>S("showTopology",o)),o})},[S]),ye=e.useCallback(e=>{G(t=>{const o="function"==typeof e?e(t):e;return queueMicrotask(()=>S("showNeighborLines",o)),o})},[S]),be=e.useCallback(e=>{ae(t=>{const o="function"==typeof e?e(t):e;return queueMicrotask(()=>S("showMinCut",o)),o})},[S]),ve=e.useCallback(e=>{me(t=>{const o="function"==typeof e?e(t):e;return queueMicrotask(()=>S("show3DTerrain",o)),o})},[S]),je=e.useCallback(e=>{ge(t=>{const o="function"==typeof e?e(t):e;return queueMicrotask(()=>S("showLinkQuality",o)),o})},[S]),we=e.useCallback(e=>{fe(e),queueMicrotask(()=>S("nodeFilters",e))},[S]),[Ne,Ce]=e.useState(null),[ke,Me]=e.useState(null),[Se,Fe]=e.useState(null),[Re,Te]=e.useState(null),[Le]=e.useState(0),[Ee]=e.useState(.5),[Be]=e.useState(0),[De,He]=e.useState(null),[$e,Ae]=e.useState(""),[Pe,ze]=e.useState(!1),[Ie,qe]=e.useState(!1),[Oe,We]=e.useState(()=>!(k&&!x.topologyLoadComplete)&&k);e.useEffect(()=>{if(x.topologyLoadComplete)return;const e=k&&!Oe,t=C.showTopology&&!O;(e||t)&&queueMicrotask(()=>{e&&F(!1),t&&S("showTopology",!1)})},[k,C.showTopology,x.topologyLoadComplete,Oe,O,F,S]);const _e=e.useCallback(e=>{We(e),queueMicrotask(()=>F(e))},[F]),[Ue,Ke]=e.useState(null),Ve=e.useCallback(e=>Ke(e),[]),Ze=e.useCallback(()=>Ke(null),[]),[,Ge]=e.useState(new Set),Je=xo(e=>e.coveragePoints),Ye=xo(e=>e.isVisible),Qe=xo(e=>e.brightness),Xe=xo(e=>e.openModal),et=Zo(e=>e.isEnabled),tt=Zo(e=>e.toggle),ot=ct(),nt=ut(),rt=e.useRef(!1);e.useEffect(()=>{Je.length>0&&Ye&&!rt.current&&(ye(!1),rt.current=!0)},[Je.length,Ye]);const st=e.useRef(null);e.useEffect(()=>{if(a&&a!==st.current){st.current=a;const e=setTimeout(()=>{Ke(a)},1250);return()=>clearTimeout(e)}},[a]);const[it,mt]=e.useState(null),[ht,gt]=e.useState(null),bt=e.useCallback((e,t,o)=>{Me(e),e&&t&&o?mt({longitude:t[0],latitude:t[1],type:"topology",properties:{key:o.key,fromName:o.fromName,toName:o.toName,certainCount:o.certainCount,confidence:o.confidence,isBackbone:o.isBackbone,isLoopEdge:o.isLoopEdge,isDirectPath:o.isDirectPath,isHubConnection:o.isHubConnection,symmetryRatio:o.symmetryRatio,dominantDirection:o.dominantDirection}}):e||mt(null)},[]),vt=e.useCallback((e,t)=>{gt(e),e&&mt(null)},[]),jt=e.useMemo(()=>{var e;if(!O)return null;if(!Ne)return null;if(ke)return null;const t=g.loops;if(0===t.length)return null;const n=function(e,t,o){const n=function(e,t){return t.filter(t=>t.nodes.includes(e)).sort((e,t)=>t.avgCertainCount-e.avgCertainCount)}(e,t),r=new Set,s=[];for(const a of n)for(const e of a.edgeKeys)if(!r.has(e)){r.add(e);const t=o.get(e);s.push({key:e,certainCount:(null==t?void 0:t.certainCount)??0})}return s.sort((e,t)=>t.certainCount-e.certainCount),{loops:n,highlightedEdgeKeys:r,sortedEdges:s}}(Ne,t,g.edgeMap);if(0===n.loops.length)return null;const r=n.loops[0].nodes.map(e=>{var t,n;return e===B?"You":(null==(t=o[e])?void 0:t.node_name)||(null==(n=o[e])?void 0:n.name)||e.substring(0,4)});return{loops:n.loops,highlightedEdgeKeys:n.highlightedEdgeKeys,hoveredEdgeKey:(null==(e=n.sortedEdges[0])?void 0:e.key)||"",nodeNames:r}},[O,Ne,ke,g.loops,g.edgeMap,o,B]);e.useEffect(()=>{ke||gt(jt)},[jt,ke]);const wt=e.useMemo(()=>{const e={};for(const[t,n]of Object.entries(o))e[t]=n.node_name||n.name||t.substring(0,4);return B&&(e[B]="You"),e},[o,B]),Nt=e.useMemo(()=>{const e=new Map;for(const[t,n]of Object.entries(o)){const o=t.slice(0,2).toUpperCase(),r=n.node_name||n.name||o;e.set(o,r)}return B&&e.set(B.slice(0,2).toUpperCase(),"You"),e},[o,B]),Ct=e.useMemo(()=>Object.entries(o).filter(([,e])=>e.latitude&&e.longitude),[o]),Ft=e.useMemo(()=>{const e=new Map;B&&(null==n?void 0:n.latitude)&&(null==n?void 0:n.longitude)&&e.set(B,[n.latitude,n.longitude]);for(const[t,o]of Ct)o.latitude&&o.longitude&&e.set(t,[o.latitude,o.longitude]);return e},[B,n,Ct]),Rt=e.useMemo(()=>{const e=new Map;for(const t of f)"expired"!==t.status&&e.set(t.hash,{hash:t.hash,prefix:t.prefix,count:t.count,avgRssi:t.avgRssi,avgSnr:t.avgSnr,lastSeen:t.lastSeen,confidence:1,status:t.status});return e},[f]),Tt=e.useMemo(()=>{var e,t;const n=new Set;for(const r of Rt.keys())(null==(e=o[r])?void 0:e.latitude)&&(null==(t=o[r])?void 0:t.longitude)&&n.add(r);return n},[Rt,o]),Et=St(),Bt=e.useMemo(()=>{if(0===Tt.size||!B)return new Map;if(0===Et.length)return new Map;const e=_(B);return p(Et,Tt,e).scores},[Tt,B,Et]),Dt=e.useCallback(e=>!!(B&&(e.fromHash===B&&Tt.has(e.toHash)||e.toHash===B&&Tt.has(e.fromHash))),[B,Tt]),Ht=e.useMemo(()=>{var e,t;if(0===f.length||!B)return[];if(x.backgroundLoadComplete)return[];const n=[];for(const r of f){if("expired"===r.status)continue;if(!(null==(e=o[r.hash])?void 0:e.latitude)||!(null==(t=o[r.hash])?void 0:t.longitude))continue;const s=[B,r.hash].sort(),a=`${s[0]}~${s[1]}`;n.push({fromHash:B,toHash:r.hash,key:a,packetCount:r.count,avgConfidence:1,strength:.8,avgRecency:1,hopDistanceFromLocal:0,isHubConnection:!1,isCertain:!0,certainCount:r.count,isLoopEdge:!1,forwardCount:r.count,reverseCount:0,symmetryRatio:0,dominantDirection:"forward",floodCount:r.count,directCount:0,isDirectPathEdge:!1,isZeroHop:!0,avgRssi:r.avgRssi,avgSnr:r.avgSnr})}return n},[f,B,x.backgroundLoadComplete,o]),$t=e.useMemo(()=>{const e=[];if(Ht.length>0&&!x.backgroundLoadComplete){for(const t of Ht){const o=Ft.get(t.fromHash),n=Ft.get(t.toHash);o&&n&&e.push({from:o,to:n,edge:t})}return e}for(const t of g.validatedEdges){if(Dt(t))continue;const o=Ft.get(t.fromHash),n=Ft.get(t.toHash);o&&n&&e.push({from:o,to:n,edge:t})}return e},[g.validatedEdges,Ft,Dt,Ht,x.backgroundLoadComplete]),At=e.useMemo(()=>{const e=[];for(const t of g.weakEdges){if(Dt(t))continue;const o=Ft.get(t.fromHash),n=Ft.get(t.toHash);o&&n&&e.push({from:o,to:n,edge:t})}return e},[g.weakEdges,Ft,Dt]),Pt=e.useMemo(()=>{if(!(null==n?void 0:n.latitude)||!(null==n?void 0:n.longitude))return[];const e=[],t=[n.latitude,n.longitude],r=new Map;for(const o of g.lastHopNeighbors)r.set(o.hash,o.count);const s=new Map;for(const o of f)s.set(o.hash,o.count);for(const n of Tt){const a=o[n];if(!(null==a?void 0:a.latitude)||!(null==a?void 0:a.longitude))continue;const i=s.get(n),l=r.get(n);e.push({from:t,to:[a.latitude,a.longitude],hash:n,neighbor:a,lastHopData:Rt.get(n)??null,rxAdvertCount:i,txProxyCount:l})}return e},[n,Tt,o,Rt,g.lastHopNeighbors,f]),zt=e.useMemo(()=>new Set(g.loopEdgeKeys),[g.loopEdgeKeys]),It=e.useMemo(()=>new Set(g.backboneEdges),[g.backboneEdges]),qt=e.useMemo(()=>{if(!Se)return null;const e=g.validatedEdges.filter(e=>e.fromHash===Se||e.toHash===Se);if(0===e.length)return null;const t=[...e].sort((e,t)=>t.certainCount-e.certainCount),o=Math.max(1,Math.ceil(.2*t.length)),n=t.slice(0,o);return new Set(n.map(e=>e.key))},[Se,g.validatedEdges]),Wt=e.useMemo(()=>{let e=0;if(Ht.length>0&&!x.backgroundLoadComplete){for(const t of Ht)t.certainCount>e&&(e=t.certainCount);return e||1}for(const t of g.validatedEdges)t.certainCount>e&&(e=t.certainCount);return e||1},[g.validatedEdges,Ht,x.backgroundLoadComplete]),_t=e.useMemo(()=>{if(0===g.validatedEdges.length)return null;const e=new Set;for(const n of g.validatedEdges)e.add(n.fromHash),e.add(n.toHash);const t=Array.from(e).filter(e=>Ft.has(e)).sort();if(t.length<3)return null;const o=new Map;for(const n of t){const e=Ft.get(n);e&&o.set(n,e)}return le(g.validatedEdges,t,o,g.edgeBetweenness)},[g.validatedEdges,Ft,g.edgeBetweenness]),Ut=e.useCallback(()=>{be(e=>{const t=!e;if(t&&_t&&h.current){const e=h.current.getMap();if(!e)return t;let o=1/0,n=-1/0,r=1/0,s=-1/0,a=!1;for(const[,t]of _t.communities)for(const e of t){const t=Ft.get(e);if(t){const[e,i]=t;r=Math.min(r,e),s=Math.max(s,e),o=Math.min(o,i),n=Math.max(n,i),a=!0}}a&&e.fitBounds([[o,r],[n,s]],{padding:{top:60,bottom:100,left:60,right:320},duration:800,maxZoom:14})}return t})},[_t,Ft]),Kt=e.useRef(null);e.useLayoutEffect(()=>{var e,t;Kt.current=(null==(t=null==(e=h.current)?void 0:e.getMap)?void 0:t.call(e))??null});const Vt=St();!function({map:t,nodeCoordinates:o,packets:n,localHash:r,neighbors:s,meshTopology:a,enabled:i=!0}){const l=e.useRef(null),c=t&&"current"in t?t.current:t;e.useEffect(()=>{l.current=c},[c]);const u=e.useRef(!1),d=e.useRef(null),m=e.useRef([]),h=e.useRef(0),g=e.useRef(!1),[p,f]=e.useState(!1),x=e.useRef(null),y=e.useRef([]),b=e.useRef(new Map),v=e.useRef(o);e.useEffect(()=>{v.current=o},[o]),e.useEffect(()=>{b.current=function(e,t){const o=new Map;for(const n of Object.keys(e)){const e=_(n);o.has(e)||o.set(e,n)}if(t){const e=_(t);o.set(e,t)}return o}(s,r)},[s,r]),e.useEffect(()=>{if(!i){x.current&&(clearTimeout(x.current),x.current=null),y.current=[],null!==d.current&&(cancelAnimationFrame(d.current),d.current=null),m.current=[];const e=l.current;if(e&&u.current){const t=e.getSource(kn);t&&t.setData({type:"FeatureCollection",features:[]})}g.current=!1,h.current=0}},[i]),e.useEffect(()=>{const e=c;if(!e)return;let t=null,o=!1;const n=()=>{if(!o&&!u.current)try{e.getLayer(Mn)&&e.removeLayer(Mn),e.getSource(kn)&&e.removeSource(kn),e.addSource(kn,{type:"geojson",data:{type:"FeatureCollection",features:[]}});const o=e.getLayer(Tn)?Tn:void 0;e.addLayer({id:Mn,type:"line",source:kn,layout:{"line-cap":"round","line-join":"round"},paint:{"line-color":["case",["any",["==",["get","isSpeculative"],!0],["==",["get","isSpeculative"],"true"]],"#8B7BAD",Rn],"line-width":["case",["any",["==",["get","isSpeculative"],!0],["==",["get","isSpeculative"],"true"]],1.875,2.5],"line-opacity":["*",["get","opacityMult"],["interpolate",["linear"],["get","intensity"],0,0,.1,.8,.5,1,1,1]]}},o),u.current=!0,f(!0),t&&(clearInterval(t),t=null)}catch{}};return e.isStyleLoaded()&&n(),e.once("style.load",()=>{n()}),u.current||(t=setInterval(()=>{u.current?t&&clearInterval(t):n()},100),setTimeout(()=>{t&&(clearInterval(t),t=null)},5e3)),()=>{o=!0,t&&clearInterval(t),null!==d.current&&(cancelAnimationFrame(d.current),d.current=null);const e=l.current;if(e&&u.current){try{e.getLayer(Mn)&&e.removeLayer(Mn),e.getSource(kn)&&e.removeSource(kn)}catch{}u.current=!1,f(!1)}}},[c]);const j=e.useRef(()=>{});e.useEffect(()=>{j.current=()=>{const e=l.current;if(!e)return;const t=e.getSource(kn);if(!t)return;const o=performance.now(),n=m.current,r=[],s=[];for(const a of n){const e=o-a.startTime-a.delay;if(e<(a.isSpeculative?Fn:Sn)){s.push(a);const t=a.isSpeculative?En(e):Ln(e);t>0&&r.push({type:"Feature",properties:{intensity:t,opacityMult:a.isSpeculative?.5:1,isSpeculative:a.isSpeculative??!1},geometry:{type:"LineString",coordinates:[a.fromCoord,a.toCoord]}})}}t.setData({type:"FeatureCollection",features:r}),m.current=s,s.length>0?d.current=requestAnimationFrame(()=>j.current()):d.current=null}},[]);const w=e.useCallback(()=>{const e=l.current;e&&function(e){if(!e.getLayer(Mn))return;const t=e.getLayer(Tn)?Tn:void 0;try{e.moveLayer(Mn,t)}catch{}}(e),null===d.current&&(d.current=requestAnimationFrame(()=>j.current()))},[]),N=e.useCallback(()=>{if(!l.current||!u.current)return;const e=y.current;if(y.current=[],x.current=null,0===e.length)return;const t=b.current,o=v.current;if(0===t.size)return;const n=performance.now();let s=0,i=!1;const c=new Set;for(const l of e){const e=W(l,r);if(!e||e.original.length<2)continue;const u=e.original;let d=0,h=null;for(let r=0;r<u.length-1;r++){const e=u[r].toUpperCase(),a=u[r+1].toUpperCase(),l=t.get(e),g=t.get(a);if(!l||!g)continue;const p=o.get(l),f=o.get(g);if(!p||!f)continue;const x=[l,g].sort().join("-");m.current.push({edgeKey:x,fromCoord:Bn(p),toCoord:Bn(f),startTime:n,delay:s+150*d}),c.add(x),h=g,d++,i=!0}const g=l.route??l.route_type;if(U(g)&&h&&h!==r&&(null==a?void 0:a.edgeMap)){const e=[];for(const[t,n]of a.edgeMap){if(n.fromHash!==h&&n.toHash!==h)continue;if(c.has(t))continue;const r=n.fromHash===h?n.toHash:n.fromHash,s=o.get(h),a=o.get(r);s&&a&&e.push({edgeKey:t,otherHash:r,confidence:n.avgConfidence??0})}if(e.length>0){e.sort((e,t)=>t.confidence-e.confidence);const t=Math.max(1,Math.ceil(.25*e.length)),r=e.slice(0,t),a=s+150*d;for(const{edgeKey:e,otherHash:s}of r){const t=o.get(h),r=o.get(s);m.current.push({edgeKey:e,fromCoord:Bn(t),toCoord:Bn(r),startTime:n,delay:a,isSpeculative:!0}),c.add(e),i=!0}}}d>0&&(s+=150*d*.5)}i&&w()},[r,a,w]);e.useEffect(()=>{const e=l.current;if(!i)return;if(!e)return;if(!p)return;if(0===n.length)return;const t=Date.now(),o=h.current;if(!g.current){g.current=!0;const e=(t-3e4)/1e3,o=n.filter(t=>(t.timestamp??0)>=e);let r=0;for(const t of n){const e=t.timestamp??0;e>r&&(r=e)}if(h.current=r,o.length>0){o.sort((e,t)=>(e.timestamp??0)-(t.timestamp??0));const e=o.slice(-20);y.current.push(...e),N()}return}const r=n.filter(e=>(e.timestamp??0)>o);if(0===r.length)return;let s=0;for(const n of r){const e=n.timestamp??0;e>s&&(s=e)}h.current=s,y.current.push(...r),x.current&&clearTimeout(x.current),x.current=setTimeout(N,175)},[i,n,N,p]),e.useEffect(()=>()=>{x.current&&clearTimeout(x.current)},[])}({map:Kt,nodeCoordinates:Ft,packets:Vt,localHash:B,neighbors:o,meshTopology:g,enabled:et});const{isExiting:Zt,isAnimating:Gt,resetAnimationState:Yt}=function({map:t,showTopology:o,validatedPolylines:n,weakPolylines:r,maxCertainCount:s,loopEdgeKeys:a,backboneEdgeKeys:i,highlightedEdgeKey:l,neighbors:c,validatedSourceId:u,weakSourceId:d,neighborPolylines:m=[],showNeighborLines:h=!0,neighborSourceId:g,neighborLinkScores:p=new Map,basemapMode:f}){const x=e.useRef(null);e.useEffect(()=>{const e=t&&"current"in t?t.current:t;x.current=e});const y=e.useRef(new Map),b=e.useRef(1),v=e.useRef(new Map),j=e.useRef(new Map),w=e.useRef(!1),N=e.useRef(null),C=e.useRef(o),k=e.useRef(new Set),M=e.useRef(""),S=e.useRef(new Map),F=e.useRef(""),R=e.useRef(""),T=e.useRef(""),L=e.useRef(n),E=e.useRef(r),B=e.useRef(s),D=e.useRef(a),H=e.useRef(i),$=e.useRef(l),A=e.useRef(c),P=e.useRef(m),z=e.useRef(h),I=e.useRef(p),q=e.useRef(f);e.useEffect(()=>{L.current=n,E.current=r,B.current=s,D.current=a,H.current=i,$.current=l,A.current=c,P.current=m,z.current=h,I.current=p,q.current=f},[n,r,s,a,i,l,c,m,h,p,f]);const O=e.useCallback((e=!1)=>{var t,o,n,r,s,a,i,l,c,m;const h=x.current;if(!h)return;const p=h.getSource(u),f=h.getSource(d),w=h.getSource(g);if(p){const s=jn(L.current,!0,y.current,b.current,v.current,j.current,B.current,D.current,H.current,$.current,A.current,q.current),a=`${s.features.length}:${(null==(o=null==(t=s.features[0])?void 0:t.properties)?void 0:o.key)??""}:${(null==(r=null==(n=s.features[s.features.length-1])?void 0:n.properties)?void 0:r.key)??""}:${Array.from(y.current.values()).reduce((e,t)=>e+t,0).toFixed(2)}`;(e||a!==F.current)&&(p.setData(s),F.current=a)}if(f){const t=jn(E.current,!1,y.current,b.current,v.current,j.current,B.current,D.current,H.current,$.current,A.current,q.current),o=`${t.features.length}:${(null==(a=null==(s=t.features[0])?void 0:s.properties)?void 0:a.key)??""}:${(null==(l=null==(i=t.features[t.features.length-1])?void 0:i.properties)?void 0:l.key)??""}`;(e||o!==R.current)&&(f.setData(t),R.current=o)}if(w&&P.current.length>0){const t=wn(P.current,I.current),o=`${t.features.length}:${(null==(m=null==(c=t.features[0])?void 0:c.properties)?void 0:m.hash)??""}`;(e||o!==T.current)&&(w.setData(t),T.current=o)}},[u,d,g]),W=e.useCallback(()=>{N.current&&(cancelAnimationFrame(N.current),N.current=null),y.current=new Map,b.current=1,v.current=new Map,j.current=new Map,w.current=!1,k.current=new Set,M.current="",S.current=new Map},[]);e.useEffect(()=>{const e=C.current,t=o;if(C.current=o,x.current){if(N.current&&(cancelAnimationFrame(N.current),N.current=null),e&&!t&&!w.current){w.current=!0;const e=new Map(y.current);let t=null;const o=n=>{t||(t=n);const r=n-t,s=Math.min(r/500,1),a=ft(s);for(const[t,o]of e)y.current.set(t,o*(1-a));O(!0),s<1?N.current=requestAnimationFrame(o):(w.current=!1,y.current=new Map,k.current=new Set,M.current="",v.current=new Map,j.current=new Map,N.current=null,O(!0))};N.current=requestAnimationFrame(o)}!e&&t&&(y.current=new Map,k.current=new Set,M.current="")}},[o,O]),e.useEffect(()=>{const e=x.current;if(!o||w.current||!e)return;const t=[...n,...r],s=t.map(e=>`${e.edge.key}:${e.edge.certainCount}`).sort().join(","),a=0===k.current.size,i=""!==M.current&&M.current!==s;if(!a&&!i)return void O();const l=[],c=[];for(const{edge:o}of t)k.current.has(o.key)?c.push(o.key):l.push(o.key);i&&c.length>0&&(v.current=new Map(S.current),b.current=0),j.current=new Map;for(const{edge:o}of n){const e=Mt(o.certainCount);j.current.set(o.key,e)}for(const o of l)y.current.set(o,0);for(const o of c)y.current.has(o)||y.current.set(o,1);if(l.length>0||i&&c.length>0){N.current&&(cancelAnimationFrame(N.current),N.current=null);let e=null;const t=Math.min(100,Lt/Math.max(l.length,1)/2),o=n=>{e||(e=n);const r=n-e;for(let e=0;e<l.length;e++){const o=l[e],n=e*t,s=Math.max(0,r-n),a=Math.min(s/Lt,1);y.current.set(o,xt(a))}if(i&&c.length>0){const e=Math.min(r/Lt,1);b.current=xt(e)}O(!0);const s=Lt+(l.length-1)*t;N.current=r<s?requestAnimationFrame(o):null};N.current=requestAnimationFrame(o)}else O();for(const o of l)k.current.add(o);for(const{edge:o}of n){const e=Mt(o.certainCount);S.current.set(o.key,e)}M.current=s},[o,n,r,s,O]),e.useEffect(()=>{const e=x.current;if(!e||!g)return;const t=()=>{const t=e.getSource(g);if(!t)return!1;if(m.length>0){const e=wn(m,p);t.setData(e)}else t.setData({type:"FeatureCollection",features:[]});return!0};if(t())return;const o=n=>{n.sourceId===g&&t()&&e.off("sourcedata",o)};e.on("sourcedata",o);const n=()=>{t()&&(e.off("styledata",n),e.off("sourcedata",o))};return e.on("styledata",n),()=>{e.off("sourcedata",o),e.off("styledata",n)}},[g,m,p]);const _=e.useRef(f);return e.useEffect(()=>{f!==_.current&&(_.current=f,F.current="",R.current="",T.current="",O(!0))},[f,O]),e.useEffect(()=>()=>{N.current&&(cancelAnimationFrame(N.current),N.current=null)},[]),{isExiting:w.current,isAnimating:null!==N.current,resetAnimationState:W,weightAnimProgress:b.current,animStartWeights:v.current,animTargetWeights:j.current}}({map:Kt,showTopology:O,validatedPolylines:$t,weakPolylines:At,maxCertainCount:Wt,loopEdgeKeys:zt,backboneEdgeKeys:It,highlightedEdgeKey:d,neighbors:o,validatedSourceId:dr,weakSourceId:mr,neighborPolylines:Pt,showNeighborLines:V,neighborSourceId:hr,neighborLinkScores:Bt,basemapMode:ot}),Qt=e.useMemo(()=>{const e=new Set;for(const t of g.hubNodes){e.add(t);for(const o of g.validatedEdges)o.fromHash===t&&e.add(o.toHash),o.toHash===t&&e.add(o.fromHash)}return e},[g.hubNodes,g.validatedEdges]),Xt=e.useMemo(()=>{const e=new Set;if(!r)return e;for(const t of g.validatedEdges)t.fromHash===r&&e.add(t.toHash),t.toHash===r&&e.add(t.fromHash);return e},[r,g.validatedEdges]),to=e.useMemo(()=>{const e=new Map;for(const[t,o]of Ct)e.set(t,pt(o).type);return e},[Ct]),oo=e.useMemo(()=>{let e=0,t=0,o=0;for(const[,n]of to)"repeater"===n?e++:"companion"===n||"unknown"===n?t++:"room_server"===n&&o++;return{repeater:e,companion:t,room_server:o,hubs:g.hubNodes.length,direct:Tt.size}},[to,g.hubNodes.length,Tt.size]),ro=e.useMemo(()=>new Set(pe),[pe]),{getNodeOpacity:so}=function({activeFilters:t,neighborHashes:o,hubConnectedNodes:n,directNodeSet:r,localConnectedNodes:s,nodeTypeMap:a,showTopology:i}){const[l,c]=e.useState(new Map),u=e.useMemo(()=>[...t].sort().join(","),[t]),d=e.useRef(u),m=e.useRef(!1),h=e.useRef(new Map),g=e.useRef(null),p=e.useRef(n),f=e.useRef(r),x=e.useRef(s),y=e.useRef(a),b=e.useRef(i);return e.useEffect(()=>{p.current=n,f.current=r,x.current=s,y.current=a,b.current=i},[n,r,s,a,i]),e.useEffect(()=>{const e=d.current,n=u;if(d.current=u,e===n)return;g.current&&(cancelAnimationFrame(g.current),g.current=null);const r=new Set(e?e.split(",").filter(Boolean):[]),s=t,a=p.current,i=f.current,l=y.current;for(const t of o)h.current.has(t)||h.current.set(t,Math.random());const x=(e,t)=>{if(0===t.size)return!1;const o=l.get(e)??"unknown";return!!(t.has("repeater")&&"repeater"===o||t.has("companion")&&("companion"===o||"unknown"===o)||t.has("room_server")&&"room_server"===o||t.has("direct")&&i.has(e)||t.has("hubs")&&a.has(e))},b=[];for(const t of o){const e=x(t,r),o=x(t,s);e!==o&&b.push({hash:t,startOpacity:e?1:0,targetOpacity:o?1:0})}if(0===b.length)return;m.current=!0,c(e=>{const t=new Map(e);for(const{hash:o,startOpacity:n}of b)t.set(o,n);return t});const v=b;let j=null;const w=e=>{j||(j=e);const t=e-j;let o=!0;c(()=>{const e=new Map;for(const{hash:n,startOpacity:r,targetOpacity:s}of v){const a=250*(h.current.get(n)??0),i=Math.max(0,t-a),l=Math.min(i/500,1),c=r+(s-r)*xt(l);e.set(n,c),l<1&&(o=!1)}return e}),t<750&&!o?g.current=requestAnimationFrame(w):(g.current=null,m.current=!1,c(new Map))};return g.current=requestAnimationFrame(w),()=>{g.current&&(cancelAnimationFrame(g.current),g.current=null),m.current=!1}},[u,t,o]),{nodeOpacities:l,getNodeOpacity:(e,t)=>m.current&&l.has(e)?l.get(e):t?1:0}}({activeFilters:ro,neighborHashes:Ct.map(([e])=>e),hubConnectedNodes:Qt,directNodeSet:Tt,localConnectedNodes:Xt,nodeTypeMap:to,showTopology:O}),{blinkingNodes:io,blinkColor:lo}=function({neighbors:t,localHash:o,enabled:n=!0}){const[r,s]=e.useState(new Map),a=St(),i=e.useRef(a);e.useEffect(()=>{i.current=a},[a]);const l=e.useRef(0),c=e.useRef(null),u=e.useRef(new Map),d=e.useRef(new Map);e.useEffect(()=>{d.current=function(e){const t=new Map;for(const o of Object.keys(e)){const e=_(o);t.has(e)||t.set(e,o)}return t}(t)},[t]);const m=e.useRef(null);return e.useEffect(()=>{m.current=()=>{const e=performance.now(),t=u.current;if(0===t.size)return c.current=null,void s(new Map);const o=new Map,n=[];for(const[r,{startTime:s,staggerDelay:a}]of t){const t=e-s-a;if(t<0);else if(t>=750)n.push(r);else{const e=Nn(t,750);e>0&&o.set(r,e)}}for(const r of n)t.delete(r);s(o),t.size>0&&m.current?c.current=requestAnimationFrame(m.current):c.current=null}},[]),e.useEffect(()=>{if(!n)return;const e=i.current;if(0===e.length)return;const t=l.current,r=e.filter(e=>(e.timestamp??0)>t);if(0===t){const t=e.reduce((e,t)=>Math.max(e,t.timestamp??0),0);return void(l.current=t)}if(0===r.length)return;const s=r.reduce((e,t)=>Math.max(e,t.timestamp??0),0);l.current=s;const a=performance.now();let h=0;for(const n of r){const e=W(n,o);if(!e||0===e.original.length)continue;const t=Cn(e.original,d.current,o);if(0===t.length)continue;const r=375;for(let o=0;o<t.length;o++){const e=t[o];u.current.has(e)||u.current.set(e,{startTime:a,staggerDelay:h+o*r})}h+=225}null===c.current&&m.current&&(c.current=requestAnimationFrame(m.current))},[a,o,n]),e.useEffect(()=>()=>{null!==c.current&&(cancelAnimationFrame(c.current),c.current=null)},[]),{blinkingNodes:r,blinkColor:"#00FF00"}}({neighbors:o,localHash:r,enabled:et}),co=e.useCallback(e=>{if(0===ro.size)return!1;const t=to.get(e)??"unknown";return!!(ro.has("repeater")&&"repeater"===t||ro.has("companion")&&("companion"===t||"unknown"===t)||ro.has("room_server")&&"room_server"===t||ro.has("direct")&&Tt.has(e)||ro.has("hubs")&&Qt.has(e))},[ro,to,Tt,Qt]),uo=e.useCallback(()=>{qe(!0),ze(!0)},[]),mo=e.useCallback(()=>{Oe?xe(e=>!e):uo()},[Oe,uo]),ho=e.useCallback(e=>{P(e.viewState),(e.viewState.pitch??0)>10&&!de&&ve(!0)},[de]),go=e.useCallback(()=>{q(e=>{var t,o,n,r,s,a,i;const l=!e,c=null==(n=null==(o=null==(t=h.current)?void 0:t.getContainer())?void 0:o.closest(".map-container-fullscreen, .map-container-16-9"))?void 0:n.parentElement;return l?c&&document.fullscreenEnabled?null==(r=c.requestFullscreen)||r.call(c).catch(()=>{}):c&&document.webkitFullscreenEnabled&&(null==(s=c.webkitRequestFullscreen)||s.call(c)):document.fullscreenElement?null==(a=document.exitFullscreen)||a.call(document).catch(()=>{}):document.webkitFullscreenElement&&(null==(i=document.webkitExitFullscreen)||i.call(document)),l})},[]),po=e.useCallback(()=>{const e=pe.length>=at.length;we(e?[]:[...at])},[pe,we]),fo=e.useCallback(e=>{pe.length>=at.length?we([e]):pe.includes(e)?we(pe.filter(t=>t!==e)):we([...pe,e])},[pe,we]),yo=e.useCallback(()=>{ye(e=>!e)},[]),bo=e.useCallback(()=>{Q(e=>!e)},[]),vo=e.useCallback(()=>{je(e=>{const t=!e;return t||Te(null),t})},[]),jo=e.useCallback(()=>{ve(e=>{const t=!e;if(h.current){const e=h.current.getMap();e&&e.stop()}if(t&&h.current){const e=h.current.getMap();e&&e.easeTo({pitch:45,duration:1500,easing:ft})}if(!t&&h.current){const e=h.current.getMap();e&&e.easeTo({pitch:0,bearing:0,duration:800,easing:yt})}return t})},[]),wo=e.useCallback(()=>{O||xe(!0)},[O]),No=e.useCallback((e,t)=>{He(e),Ae(t)},[]),Co=e.useCallback(()=>{De&&s&&s(De),He(null),Ae("")},[De,s]),ko=e.useMemo(()=>[...jr,...ur,...he?[kr]:[]],[he]),Mo=e.useRef(!1);e.useEffect(()=>{Mo.current="ontouchstart"in window||navigator.maxTouchPoints>0},[]);const So=e.useCallback(e=>{if(he&&e.features&&e.features.length>0){const t=e.features.find(e=>{var t;return(null==(t=e.layer)?void 0:t.id)===kr});if(null==t?void 0:t.properties){const{fromHash:e,toHash:o}=t.properties;if(e&&o){const t=v.find(t=>t.nodeA.hash===e&&t.nodeB.hash===o||t.nodeA.hash===o&&t.nodeB.hash===e);if(t)return void Te(t)}}}e.features&&0!==e.features.length||(Mo.current&&it&&(mt(null),Me(null)),Se&&Fe(null),Re&&Te(null))},[it,Se,he,v,Re]),Fo=e.useCallback(e=>{Fe(t=>t===e?null:e),Te(null)},[]),Lo=e.useCallback(e=>{var t,o,n;if(!e.features||0===e.features.length)return;if(e.features.some(e=>{var t,o;return null==(o=null==(t=e.layer)?void 0:t.id)?void 0:o.startsWith("node-markers-")}))return void(ke&&(Me(null),mt(null)));if(he&&e.features.some(e=>{var t;return(null==(t=e.layer)?void 0:t.id)===kr})){try{(null==(t=h.current)?void 0:t.getCanvas())&&(h.current.getCanvas().style.cursor="pointer")}catch{}return}const r=e.features.find(e=>{var t;const o=null==(t=e.layer)?void 0:t.id;return(null==o?void 0:o.startsWith("topology-"))||(null==o?void 0:o.startsWith("neighbor-"))});if(!r)return;const s=null==(o=r.layer)?void 0:o.id,a=r.properties;if(!(null==a?void 0:a.key))return;const i=null==s?void 0:s.startsWith("topology-"),l=null==s?void 0:s.startsWith("neighbor-");if(i||l){const t=a.key.replace(/-loop[12]$/,"");Me(t),e.lngLat&&mt({longitude:e.lngLat.lng,latitude:e.lngLat.lat,type:i?"topology":"neighbor",properties:a})}try{(null==(n=h.current)?void 0:n.getCanvas())&&(h.current.getCanvas().style.cursor="pointer")}catch{}},[ke,he]),Eo=e.useCallback(()=>{var e;Me(null),mt(null);try{(null==(e=h.current)?void 0:e.getCanvas())&&(h.current.getCanvas().style.cursor="")}catch{}},[]),Bo=I?"map-container-fullscreen":"map-container-16-9",Ho=D.length>0||(null==n?void 0:n.latitude)&&(null==n?void 0:n.longitude),$o=!j||!Ho,Ao=Ho;return t.jsxs("div",{className:`relative ${Bo} ${I?"":"rounded-2xl overflow-hidden"}`,role:"application","aria-label":"Mesh network contacts map","aria-describedby":"map-instructions","data-basemap":ot,children:[t.jsx("span",{id:"map-instructions",className:"sr-only",children:"Interactive map showing mesh network contacts. Use mouse or touch to pan and zoom. Press Tab to navigate map controls. Press Escape to exit fullscreen mode."}),$o&&t.jsx("div",{className:"absolute inset-0 z-50 surface-base rounded-2xl flex items-center justify-center","aria-hidden":"true",children:t.jsxs("div",{className:"flex flex-col items-center gap-3",children:[t.jsx("div",{className:"w-6 h-6 border-2 border-sys-blue border-t-transparent rounded-full animate-spin"}),t.jsx("span",{className:"text-sm text-fg-muted",children:"Loading map..."})]})}),Ao&&t.jsx("div",{className:`relative w-full h-full ${I?"":"rounded-[1.125rem] overflow-hidden"} ${$o?"opacity-0":"opacity-100 transition-opacity duration-300"}`,style:R?{visibility:"hidden"}:void 0,children:t.jsxs(i,{ref:h,...$,onMove:ho,mapStyle:Hr,style:{width:"100%",height:"100%"},attributionControl:!1,interactiveLayerIds:ko,onMouseMove:Lo,onMouseLeave:Eo,onClick:So,onError:e=>{console.error("MapLibre error:",e.error)},onIdle:()=>{if(!E&&!L&&h.current){const e=h.current.getMap();if(e){const t=Object.values(o).filter(e=>e.latitude&&e.longitude).map(e=>({latitude:e.latitude,longitude:e.longitude}));(null==n?void 0:n.latitude)&&(null==n?void 0:n.longitude)&&t.push({latitude:n.latitude,longitude:n.longitude}),t.length>0&&T(t,e)}}},children:[t.jsx(l,{position:"bottom-right"}),t.jsx(dt,{mode:ot}),t.jsx(ln,{enabled:de,exaggeration:4}),t.jsx(tn,{coveragePoints:Je,visible:Je.length>0&&Ye,terrainEnabled:de,brightness:Qe,basemapMode:ot}),t.jsx(xn,{partition:_t,nodeCoordinates:Ft,visible:X&&Oe,opacity:ie.opacity,bandwidth:ie.bandwidth,threshold:ie.threshold,strokeWidth:ie.strokeWidth}),t.jsx(vr,{showTopology:O,isExiting:Zt,hoveredEdgeKey:ke,highlightedLoopEdges:null==ht?void 0:ht.highlightedEdgeKeys,highlightedFocusEdges:qt,onEdgeHover:bt,onLoopHover:vt,loops:g.loops,neighborNames:wt,opacityBias:Le,widthMultiplier:Ee,trafficFilter:Be,showNeighborLines:V,disableHover:Gt||Ie}),t.jsx(Lr,{visible:he,nodeCoordinates:Ft,focusedNodeHash:Se,basemapMode:ot}),a&&t.jsx(wr,{targetHash:a,nodeCoordinates:Ft,onComplete:u}),d&&t.jsx(Nr,{highlightedEdgeKey:d,validatedPolylines:$t,weakPolylines:At,onEnsureTopology:wo}),t.jsx(Br,{ghost:m??null,neighborCoordinates:Ft,onHighlightedNeighborsChange:Ge}),t.jsx(cr,{neighborsWithLocation:Ct,localNode:n,localHash:r,zeroHopNeighbors:Tt,lastHopNeighborMap:Rt,meshTopology:g,hoveredMarker:Ne,onMarkerHover:Ce,getNodeOpacity:so,shouldShowNode:co,onRequestRemove:s?No:void 0,openPopupId:Ue,onOpenPopup:Ve,onClosePopup:Ze,onNodeClick:Fo,blinkingNodes:io,blinkColor:lo})]})}),(()=>{const e=function(e,t,o,n){var r;if(t){const e=t.loops[0],o=t.loops.length,n=[{label:"hops",value:e.size},{label:"seen",value:e.minCertainCount}],r=[];return e.includesLocal&&r.push({text:"★ Includes your node",color:"text-sys-amber"}),o>1&&r.push({text:`+${o-1} overlapping`,color:"text-sys-indigo/70"}),{type:"loop",title:{icon:"⟳",text:"Redundant Path"+(o>1?"s":""),color:"text-sys-indigo"},subtitle:{text:`${t.nodeNames.join(" → ")} → ${t.nodeNames[0]}`,color:"text-fg-secondary",mono:!0},stats:n,badges:r}}if("neighbor"===(null==e?void 0:e.type)){const t=e.properties,o=[];void 0!==t.rssi&&null!==t.rssi&&o.push({label:"RSSI",value:`${Math.round(t.rssi)} dBm`,unit:t.hasAvgRssi?"avg":void 0}),void 0!==t.snr&&null!==t.snr&&o.push({label:"SNR",value:`${Number(t.snr).toFixed(1)} dB`,unit:t.hasAvgSnr?"avg":void 0});const n=t.listenerScore??0,r=t.loudScore??0,s=n>0||r>0;return s&&(o.push({label:"listener",value:n,color:"text-sys-green"}),o.push({label:"loud",value:r,color:"text-sys-red"})),void 0===t.packetCount||s||o.push({label:"packets",value:Number(t.packetCount).toLocaleString()}),{type:"neighbor",title:{icon:"●",text:t.prefix?`${t.name} (${t.prefix})`:t.name,color:"text-sys-amber"},subtitle:{text:"Direct RF Neighbor",color:"text-sys-amber/70"},stats:o,badges:[]}}if("topology"===(null==e?void 0:e.type)){const t=e.properties,s=o>0?Number(t.certainCount)/o:0,a=[{label:"validations",value:t.certainCount},{label:"of max traffic",value:`${Math.round(100*s)}%`},{label:"confidence",value:`${Math.round(100*Number(t.confidence))}%`}];if(void 0!==t.symmetryRatio&&t.symmetryRatio<1){const e="forward"===t.dominantDirection?"→":"reverse"===t.dominantDirection?"←":"↔";a.push({label:"symmetric",value:`${e} ${Math.round(100*t.symmetryRatio)}%`,color:"text-fg-muted"})}const i=null==(r=null==n?void 0:n.get(t.key))?void 0:r.traceQuality;if(null==i?void 0:i.composite){const e=i.composite;a.push({label:"trace SNR",value:`${e.mean.toFixed(1)} dB`,unit:`n=${e.count}`,color:e.mean>=10?"text-sys-green":e.mean>=0?"text-sys-amber":"text-sys-red"}),null!=i.asymmetryDb&&i.asymmetryDb>1&&a.push({label:"asymmetry",value:`${i.asymmetryDb.toFixed(1)} dB`,color:i.asymmetryDb>5?"text-sys-red":"text-sys-amber"})}const l=[];if(t.isBackbone&&l.push({text:"Backbone",color:"text-zinc-300"}),t.isLoopEdge&&l.push({text:"Redundant",color:"text-sys-indigo"}),t.isDirectPath&&l.push({text:"Direct Path",color:"text-sys-teal"}),i){const e="excellent"===i.quality||"good"===i.quality?"text-sys-green":"fair"===i.quality?"text-sys-amber":"poor"===i.quality||"critical"===i.quality?"text-sys-red":"text-fg-muted";"unknown"!==i.quality&&l.push({text:`TRACE ${i.quality}`,color:e})}return{type:"topology",title:{icon:"",text:`${t.fromName} ↔ ${t.toName}`,color:"text-fg-primary"},stats:a,badges:l}}return null}(it?{type:it.type,properties:it.properties}:null,ht,Wt,g.edgeMap);return e&&t.jsx("div",{className:"map-edge-tooltip",children:t.jsx("div",{className:"map-control-surface map-edge-tooltip-inner",children:t.jsx(Ar,{data:e})})})})(),t.jsx(Jt,{mapRef:h,showNeighborLines:V,onToggleNeighborLines:yo,hasNeighborPolylines:Pt.length>0,nodeFilters:pe,onToggleFilter:fo,onToggleAll:po,filterCounts:oo,showCoverage:Y,onToggleCoverage:bo,showMinCut:X,onToggleMinCut:Ut,hasMinCutData:Oe&&null!==_t&&_t.numCommunities>1,show3DTerrain:de,onToggle3DTerrain:jo,basemapMode:ot,onToggleBasemap:nt,isFullscreen:I,onToggleFullscreen:go,showLinkQuality:he,onToggleLinkQuality:vo,hasTraceLinks:b}),he&&Re&&t.jsx(Ko,{pair:Re,onClose:()=>Te(null),prefixToName:Nt}),t.jsxs("div",{className:"map-legend-stack",children:[t.jsxs("div",{className:"map-tool-row",children:[t.jsx(eo,{isActive:O,hasAnalyzed:Oe,isLoading:Ie,onClick:mo,basemapMode:ot}),t.jsx(no,{isActive:et,onClick:tt,basemapMode:ot}),t.jsx(ao,{isActive:Je.length>0&&Ye,onClick:Xe,basemapMode:ot})]}),t.jsx(Ot,{showTopology:O,validatedPolylineCount:$t.length,filteredNeighborCount:Ct.length,hasLocalNode:!(!(null==n?void 0:n.latitude)||!(null==n?void 0:n.longitude)),meshTopology:g,zeroHopNeighbors:Tt,neighborsWithLocation:Ct,basemapMode:ot})]}),t.jsx(se,{isOpen:null!==De,onCancel:()=>He(null),onConfirm:Co,title:"Remove Node?",message:`Remove "${$e}" from the contacts list? This will hide the node until it sends a new packet.`,confirmLabel:"Remove",cancelLabel:"Cancel",variant:"danger"}),t.jsx(ce,{isOpen:Pe,onClose:()=>{ze(!1),qe(!1),Yt(),_e(!0),setTimeout(()=>xe(!0),150)}}),t.jsx(Ro,{}),t.jsx(Do,{visible:X&&Oe,onClose:()=>be(!1),settings:ie,onSettingsChange:ue,partition:_t,totalNodes:Object.keys(o).length,basemapMode:ot})]})}export{Pr as default};
|