@usex/mikrotik-mcp 3.34.0 → 3.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -76,12 +76,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
76
76
  `).length;return(0,J.jsxs)(`div`,{className:`cfgstudio`,children:[(0,J.jsxs)(`div`,{className:`cfg-toolbar`,children:[(0,J.jsx)(`span`,{className:`cfg-status ${A?`is-ok`:`is-bad`}`,children:l?`invalid JSON`:s.length?`${s.length} schema issue(s)`:`valid ✓`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`button`,{className:`topo-btn`,onClick:()=>void F(),children:`Test devices`}),(0,J.jsx)(`button`,{className:`topo-btn`,onClick:()=>void I(),disabled:!A,children:`Preview diff`}),(0,J.jsx)(`select`,{className:`cfg-select`,value:S,onChange:e=>C(Number(e.target.value)),title:`Auto-revert window`,children:pY.map(([e,t])=>(0,J.jsx)(`option`,{value:t,children:e},t))}),(0,J.jsx)(`button`,{className:`topo-btn cfg-save`,onClick:()=>void L(),disabled:!A||!!_,children:`Save`}),(0,J.jsx)(`button`,{className:`topo-btn`,onClick:t,children:`Close`})]}),w&&(0,J.jsx)(`div`,{className:`cfg-msg`,children:w}),_&&(0,J.jsxs)(`div`,{className:`cfg-banner`,children:[(0,J.jsx)(`strong`,{children:`Applied.`}),` `,(_.rollbackMs??0)>0?(0,J.jsxs)(J.Fragment,{children:[`Reverting in `,(0,J.jsxs)(`span`,{className:`cfg-count`,children:[b,`s`]}),` unless you keep it.`]}):(0,J.jsx)(J.Fragment,{children:`Saved without an auto-revert window.`}),_.devicesChanged&&(0,J.jsxs)(`span`,{className:`cfg-warn`,children:[` `,`· device list changed — reconnect the MCP client to expose it to the model`]}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`button`,{className:`topo-btn cfg-save`,onClick:()=>void ee(),children:`Keep changes`}),(0,J.jsx)(`button`,{className:`topo-btn`,onClick:()=>void te(),children:`Revert now`})]}),(0,J.jsxs)(`div`,{className:`cfg-editor`,children:[(0,J.jsx)(`pre`,{className:`cfg-gutter`,"aria-hidden":`true`,ref:k,children:Array.from({length:R},(e,t)=>t+1).join(`
77
77
  `)}),(0,J.jsxs)(`div`,{className:`cfg-ta-wrap`,children:[(0,J.jsxs)(`pre`,{className:`cfg-hl`,"aria-hidden":`true`,ref:O,children:[rY(r),`
78
78
  `]}),(0,J.jsx)(`textarea`,{ref:E,className:`cfg-ta`,spellCheck:!1,wrap:`off`,value:r,onChange:e=>{i(e.target.value),j(e.currentTarget)},onKeyDown:N,onClick:()=>f(null),onScroll:e=>{let t=e.currentTarget;O.current&&(O.current.scrollTop=t.scrollTop,O.current.scrollLeft=t.scrollLeft),k.current&&(k.current.scrollTop=t.scrollTop)}}),d&&(0,J.jsx)(`div`,{className:`cfg-ac`,style:{left:d.x,top:d.y},children:d.items.map((e,t)=>(0,J.jsx)(`div`,{className:`cfg-ac-item${t===d.index?` is-sel`:``}`,onMouseDown:t=>{t.preventDefault(),M(e)},children:e},e))})]})]}),Object.keys(p).length>0&&(0,J.jsx)(`div`,{className:`cfg-chips`,children:Object.entries(p).map(([e,t])=>(0,J.jsxs)(`span`,{className:`cfg-chip ${t.ok?`is-ok`:`is-bad`}`,children:[t.ok?`●`:`○`,` `,e,`: `,t.label]},e))}),(l||s.length>0)&&(0,J.jsx)(`div`,{className:`cfg-errors`,children:l?(0,J.jsxs)(`div`,{className:`cfg-err`,children:[`JSON: `,l]}):s.slice(0,12).map((e,t)=>(0,J.jsxs)(`div`,{className:`cfg-err`,children:[(0,J.jsx)(`code`,{children:e.path}),` — `,e.message]},t))}),h&&(0,J.jsxs)(`div`,{className:`cfg-preview`,children:[(0,J.jsxs)(`div`,{className:`cfg-preview__hd`,children:[(0,J.jsx)(`strong`,{children:`Diff vs current`}),(0,J.jsx)(`span`,{className:`muted`,children:h.summary?.changed?`+${h.summary.added} / -${h.summary.removed}`:`no changes`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`button`,{className:`topo-btn`,onClick:()=>g(null),children:`✕`})]}),(0,J.jsx)(`pre`,{className:`cfg-diff`,children:(h.unified||`(identical)`).split(`
79
- `).map((e,t)=>(0,J.jsx)(`div`,{className:e.startsWith(`+`)?`d-add`:e.startsWith(`-`)?`d-del`:e.startsWith(`@@`)?`d-hunk`:``,children:e||` `},t))})]})]})}function hY(e){return e.reachable===!0?{label:`online`,color:`#d4d4d8`}:e.reachable===!1?{label:`offline`,color:`#f87171`}:{label:`checking…`,color:`#71717a`}}function gY(e){let t=0;for(let n=0;n<e.length;n++)t=Math.imul(t,31)+e.charCodeAt(n)>>>0;return`hsl(${t%360} 70% 62%)`}function _Y(e,t,n,r){let i=1-r;return{x:i*i*e.x+2*i*r*t.x+r*r*n.x,y:i*i*e.y+2*i*r*t.y+r*r*n.y}}function vY(e,t,n,r){let i=1-r,a=2*i*(t.x-e.x)+2*r*(n.x-t.x),o=2*i*(t.y-e.y)+2*r*(n.y-t.y);return Math.atan2(o,a)*180/Math.PI}var yY=`#e4e4e7`,bY=`#d4d4d8`,xY=`#f59e0b`;function SY(e){return e.jumpVia?e.jumpVia:e.jumpHost?`${e.jumpHost.host}:${e.jumpHost.port}`:null}var CY=18,wY=e=>e.length>CY?`${e.slice(0,CY-1)}…`:e,TY=e=>Math.max(23,Math.min(70,e.length*3.1+12));function EY({payload:e,pulses:t}){let n=e.devices,r=Math.max(1,n.length),i=n.map(e=>{let t=wY(e.name);return{d:e,label:t,r:TY(t)}}),a=Math.max(23,...i.map(e=>e.r)),o=r>1?(a+18)/Math.sin(Math.PI/r):0,s=Math.max(110+a,o,120),c=a+60,l=Math.max(700,Math.round((s+a+40)*2)),u=Math.round((s+c)*2),d=l/2,f=u/2,p={x:d,y:f},m=i.map((e,t)=>{let n=t/r*Math.PI*2-Math.PI/2+(r%2==0?Math.PI/r:0);return{...e,i:t,x:d+s*Math.cos(n),y:f+s*Math.sin(n)}});return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`svg`,{className:`conn`,viewBox:`0 0 ${l} ${u}`,width:`100%`,height:u,preserveAspectRatio:`xMidYMid meet`,children:[(0,J.jsxs)(`defs`,{children:[(0,J.jsxs)(`radialGradient`,{id:`conn-hub`,cx:`0.5`,cy:`0.34`,r:`0.75`,children:[(0,J.jsx)(`stop`,{offset:`0`,stopColor:`#fafafa`}),(0,J.jsx)(`stop`,{offset:`0.6`,stopColor:`#d4d4d8`}),(0,J.jsx)(`stop`,{offset:`1`,stopColor:`#a1a1aa`})]}),(0,J.jsxs)(`radialGradient`,{id:`conn-orb`,cx:`0.5`,cy:`0.32`,r:`0.85`,children:[(0,J.jsx)(`stop`,{offset:`0`,stopColor:`#27272a`}),(0,J.jsx)(`stop`,{offset:`1`,stopColor:`#18181b`})]}),(0,J.jsxs)(`radialGradient`,{id:`conn-burst`,cx:`0.5`,cy:`0.5`,r:`0.5`,children:[(0,J.jsx)(`stop`,{offset:`0`,stopColor:`#fafafa`}),(0,J.jsx)(`stop`,{offset:`0.5`,stopColor:`#e4e4e7`}),(0,J.jsx)(`stop`,{offset:`1`,stopColor:`#a1a1aa`,stopOpacity:`0`})]}),(0,J.jsxs)(`linearGradient`,{id:`conn-tunnel-grad`,x1:`0`,y1:`0`,x2:`1`,y2:`0`,children:[(0,J.jsx)(`stop`,{offset:`0`,stopColor:xY,stopOpacity:`0.15`}),(0,J.jsx)(`stop`,{offset:`0.5`,stopColor:xY,stopOpacity:`0.95`}),(0,J.jsx)(`stop`,{offset:`1`,stopColor:xY,stopOpacity:`0.15`})]}),(0,J.jsxs)(`filter`,{id:`conn-tunnel-glow`,x:`-40%`,y:`-40%`,width:`180%`,height:`180%`,children:[(0,J.jsx)(`feGaussianBlur`,{stdDeviation:`3`,result:`b`}),(0,J.jsxs)(`feMerge`,{children:[(0,J.jsx)(`feMergeNode`,{in:`b`}),(0,J.jsx)(`feMergeNode`,{in:`SourceGraphic`})]})]})]}),[.5,.78,1].map((e,t)=>(0,J.jsx)(`circle`,{className:`conn-grid`,cx:d,cy:f,r:s*e},`g-${t}`)),[0,1,2].map(e=>(0,J.jsx)(`circle`,{className:`conn-sonar`,cx:d,cy:f,style:{animationDelay:`${e*1.1}s`}},`s-${e}`)),m.map(({d:e,i:n,x:r,y:i})=>{let a=hY(e.status),o=e.status.reachable===!0,s=e.status.reachable==null,c={x:r,y:i},l=(d+r)/2,u=(f+i)/2,m=r-d,h=i-f,g=Math.hypot(m,h)||1,_=-h/g,v=m/g,y={x:l+_*16,y:u+v*16},b={x:l-_*16,y:u-v*16},x=`M${d},${f} Q${y.x.toFixed(1)},${y.y.toFixed(1)} ${r.toFixed(1)},${i.toFixed(1)}`,S=`M${d},${f} Q${b.x.toFixed(1)},${b.y.toFixed(1)} ${r.toFixed(1)},${i.toFixed(1)}`,C=`M${d},${f} Q${l.toFixed(1)},${u.toFixed(1)} ${r.toFixed(1)},${i.toFixed(1)}`,w=_Y(p,y,c,.52),T=vY(p,y,c,.52),E=_Y(p,b,c,.48),D=vY(p,b,c,.48)+180,O=t[e.name]??0;return(0,J.jsxs)(`g`,{children:[(0,J.jsx)(`path`,{id:`conn-cmd-${n}`,className:`conn-link`,d:x,stroke:o?yY:a.color,strokeOpacity:o?.5:.32,strokeDasharray:s?`2 8`:o?void 0:`6 7`}),(0,J.jsx)(`path`,{id:`conn-res-${n}`,className:`conn-link`,d:S,stroke:o?bY:a.color,strokeOpacity:o?.5:.18,strokeDasharray:o?void 0:`6 7`}),o&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{className:`conn-flow`,d:x,stroke:`#e4e4e7`}),(0,J.jsx)(`circle`,{className:`conn-packet`,r:3.2,fill:`#e4e4e7`,children:(0,J.jsx)(`animateMotion`,{dur:`2.6s`,repeatCount:`indefinite`,calcMode:`linear`,children:(0,J.jsx)(`mpath`,{href:`#conn-cmd-${n}`})})}),(0,J.jsx)(`rect`,{className:`conn-packet`,x:-2.6,y:-2.6,width:5.2,height:5.2,fill:`#d4d4d8`,transform:`rotate(45)`,children:(0,J.jsx)(`animateMotion`,{dur:`2.6s`,begin:`0.9s`,repeatCount:`indefinite`,calcMode:`linear`,keyPoints:`1;0`,keyTimes:`0;1`,children:(0,J.jsx)(`mpath`,{href:`#conn-res-${n}`})})}),(0,J.jsx)(`path`,{className:`conn-chevron`,d:`M-4,-3 L4,0 L-4,3`,stroke:`#e4e4e7`,transform:`translate(${w.x.toFixed(1)},${w.y.toFixed(1)}) rotate(${T.toFixed(1)})`}),(0,J.jsx)(`path`,{className:`conn-chevron`,d:`M-4,-3 L4,0 L-4,3`,stroke:`#d4d4d8`,transform:`translate(${E.x.toFixed(1)},${E.y.toFixed(1)}) rotate(${D.toFixed(1)})`})]}),O>0&&(0,J.jsx)(`g`,{children:(0,J.jsxs)(`circle`,{r:6,fill:`url(#conn-burst)`,children:[(0,J.jsx)(`animateMotion`,{dur:`1.1s`,repeatCount:`1`,calcMode:`linear`,keyPoints:`0;1;0`,keyTimes:`0;0.5;1`,path:C}),(0,J.jsx)(`animate`,{attributeName:`opacity`,values:`0;1;1;0`,keyTimes:`0;0.1;0.85;1`,dur:`1.1s`,repeatCount:`1`,fill:`freeze`})]})},`burst-${e.name}-${O}`)]},`l-${e.name}`)}),m.map(e=>{let t=e.d.jumpVia,n=t?m.find(e=>e.d.name===t):void 0,r=!n&&e.d.jumpHost?e.d.jumpHost:void 0;if(!n&&!r)return null;let i={x:e.x,y:e.y},a=Math.hypot(e.x-d,e.y-f)||1,o=(e.x-d)/a,s=(e.y-f)/a,c=n?{x:n.x,y:n.y}:{x:e.x+o*(e.r+46),y:e.y+s*(e.r+46)},l=(c.x+i.x)/2,u=(c.y+i.y)/2,p=Math.hypot(l-d,u-f)||1,h=n?50:16,g={x:l+(l-d)/p*h,y:u+(u-f)/p*h},_=`M${c.x.toFixed(1)},${c.y.toFixed(1)} Q${g.x.toFixed(1)},${g.y.toFixed(1)} ${i.x.toFixed(1)},${i.y.toFixed(1)}`,v=SY(e.d)??``,y=_Y(c,g,i,.5),b=`conn-tunnel-${e.i}`;return(0,J.jsxs)(`g`,{className:`conn-tunnel-g`,children:[(0,J.jsx)(`path`,{className:`conn-tunnel-halo`,d:_,stroke:xY}),(0,J.jsx)(`path`,{id:b,className:`conn-tunnel`,d:_,stroke:`url(#conn-tunnel-grad)`,filter:`url(#conn-tunnel-glow)`}),r&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{className:`conn-tunnel-sat`,cx:c.x,cy:c.y,r:11,fill:`#1c1917`,stroke:`#f59e0b`}),(0,J.jsx)(`text`,{x:c.x,y:c.y+3.5,textAnchor:`middle`,fontSize:11,children:`🛡️`})]}),(0,J.jsxs)(`text`,{className:`conn-tunnel-lock`,fontSize:13,textAnchor:`middle`,children:[`🔒`,(0,J.jsx)(`animateMotion`,{dur:`2.4s`,repeatCount:`indefinite`,calcMode:`linear`,rotate:`auto`,children:(0,J.jsx)(`mpath`,{href:`#${b}`})})]}),(0,J.jsxs)(`g`,{transform:`translate(${y.x.toFixed(1)},${y.y.toFixed(1)})`,children:[(0,J.jsx)(`rect`,{className:`conn-tunnel-badge`,x:-Math.max(24,v.length*3.3+14),y:-9,rx:9,width:Math.max(48,v.length*6.6+28),height:18}),(0,J.jsxs)(`text`,{className:`conn-tunnel-badge-tx`,x:0,y:3.5,textAnchor:`middle`,fontSize:9,children:[`⤳ via `,v]})]})]},`jump-${e.d.name}`)}),(0,J.jsx)(`circle`,{className:`conn-hub-glow`,cx:d,cy:f,r:42}),(0,J.jsx)(`circle`,{className:`conn-hub-ring`,cx:d,cy:f,r:37}),(0,J.jsx)(`circle`,{cx:d,cy:f,r:29,fill:`url(#conn-hub)`,stroke:`#71717a`,strokeWidth:1.5}),(0,J.jsx)(`text`,{x:d,y:f-4,textAnchor:`middle`,fill:`#09090b`,fontSize:12,fontWeight:700,children:`LLM`}),(0,J.jsx)(`text`,{x:d,y:f+8,textAnchor:`middle`,fill:`#3f3f46`,fontSize:8,fontWeight:600,children:`⇄ MCP`}),(0,J.jsx)(`text`,{x:d,y:f+18,textAnchor:`middle`,fill:`#3f3f46`,fontSize:7.5,fontWeight:600,children:`server`}),m.map(({d:e,x:t,y:n,r,label:i})=>{let a=hY(e.status),o=e.status.reachable===!0,s=o?`${e.status.latencyMs??`?`} ms`:a.label,c=gY(e.name);return(0,J.jsxs)(`g`,{className:`conn-node`,children:[o&&(0,J.jsx)(`circle`,{className:`conn-node-halo`,cx:t,cy:n,r:r+1,stroke:c}),(0,J.jsx)(`circle`,{cx:t,cy:n,r,fill:`url(#conn-orb)`}),(0,J.jsx)(`circle`,{cx:t,cy:n,r,fill:c,opacity:.16}),(0,J.jsx)(`circle`,{cx:t,cy:n,r,fill:`none`,stroke:c,strokeWidth:2.5}),(0,J.jsx)(`circle`,{className:o?`conn-blink`:void 0,cx:t+r*.7,cy:n-r*.7,r:4.5,fill:a.color,stroke:`#0a121b`,strokeWidth:1.5}),(0,J.jsx)(`text`,{x:t,y:n+3.5,textAnchor:`middle`,fill:`#fafafa`,fontSize:10,fontWeight:600,children:i}),(0,J.jsx)(`text`,{x:t,y:n+r+14,textAnchor:`middle`,fill:`#a1a1aa`,fontSize:9,children:e.address??e.host}),(0,J.jsx)(`text`,{x:t,y:n+r+26,textAnchor:`middle`,fill:a.color,fontSize:9,fontWeight:600,children:s})]},`n-${e.name}`)})]}),(0,J.jsxs)(`div`,{className:`conn-legend`,children:[(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{style:{background:yY}}),` command · LLM → device`]}),(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{style:{background:bY}}),` response · device → LLM`]}),(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{style:{background:`#e4e4e7`}}),` live call (round-trip)`]}),e.devices.some(e=>SY(e))&&(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{style:{background:`#f59e0b`}}),` 🔒 SSH jump tunnel (ProxyJump)`]})]})]})}function DY({d:e}){let t=hY(e.status),n=e.status.reachable===!0?`${t.label} · ${e.status.latencyMs??`?`}ms${e.status.version?` · v${e.status.version}`:``}`:e.status.reachable===!1?`${t.label}${e.status.error?` · ${e.status.error}`:``}`:t.label,r=gY(e.name);return(0,J.jsxs)(`div`,{className:`card dev-card`,style:{borderLeft:`3px solid ${r}`},children:[(0,J.jsxs)(`div`,{className:`dev-card__top`,children:[(0,J.jsx)(`span`,{className:`dot`,style:{background:r},title:`device colour`}),(0,J.jsx)(`span`,{className:`dev-card__name`,children:e.name}),e.isDefault&&(0,J.jsx)(Mc,{type:`accent`,children:`default`}),(0,J.jsx)(`span`,{className:`dot dot--status`,style:{background:t.color},title:t.label}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`span`,{className:`chip`,children:e.authMode})]}),(0,J.jsxs)(`div`,{className:`dev-card__meta`,children:[(0,J.jsx)(`span`,{children:e.mac?`mac`:`host`}),(0,J.jsx)(`b`,{children:e.address??`${e.host}:${e.port}`}),(0,J.jsx)(`span`,{children:`user`}),(0,J.jsx)(`b`,{children:e.username}),(0,J.jsx)(`span`,{children:`status`}),(0,J.jsx)(`b`,{style:{color:t.color},children:n}),(0,J.jsx)(`span`,{children:`activity`}),(0,J.jsxs)(`b`,{children:[e.activity.calls,` calls · `,e.activity.errors,` err`,e.activity.avgMs?` · ${xc(e.activity.avgMs)} avg`:``]}),e.description&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`span`,{children:`note`}),(0,J.jsx)(`b`,{children:e.description})]})]}),SY(e)&&(0,J.jsxs)(`div`,{className:`jump-route`,title:`Reached over SSH through the bastion ${SY(e)} (ProxyJump) — no port exposed on ${e.name}.`,children:[(0,J.jsx)(`span`,{className:`jump-route__hop jump-route__hop--src`,title:`MCP server`,children:`🛰️`}),(0,J.jsx)(`span`,{className:`jump-route__wire`}),(0,J.jsxs)(`span`,{className:`jump-route__hop jump-route__hop--bastion`,children:[`🛡️ `,SY(e),e.jumpVia?(0,J.jsx)(`i`,{className:`jump-route__tag`,children:`jump`}):null]}),(0,J.jsx)(`span`,{className:`jump-route__wire jump-route__wire--enc`,children:(0,J.jsx)(`span`,{className:`jump-route__lock`,"aria-hidden":!0,children:`🔒`})}),(0,J.jsxs)(`span`,{className:`jump-route__hop jump-route__hop--dest`,style:{borderColor:r},title:e.name,children:[`📡 `,e.name]})]})]})}function OY({event:e,onClose:t}){let[n,r]=(0,v.useState)(sY);return(0,J.jsx)(`div`,{className:`overlay`,onClick:e=>e.target===e.currentTarget&&t(),children:(0,J.jsxs)(`div`,{className:`sheet`,children:[(0,J.jsxs)(`div`,{className:`sheet__hd`,children:[(0,J.jsx)(`span`,{className:`risk risk-${e.risk}`,children:e.risk}),(0,J.jsxs)(`h3`,{className:`sheet__tool`,children:[e.tool,(0,J.jsx)(bc,{text:e.tool,className:`iconbtn`,icon:!0,title:`Copy tool name`})]}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(Ac,{type:`secondary`,size:`sm`,onClick:t,children:`✕ Close`})]}),(0,J.jsxs)(`div`,{className:`kv__body`,children:[(0,J.jsx)(`div`,{className:`kv__k`,children:`title`}),(0,J.jsx)(`div`,{className:`kv__v`,children:e.title}),(0,J.jsx)(`div`,{className:`kv__k`,children:`time`}),(0,J.jsx)(`div`,{className:`kv__v`,children:new Date(e.ts).toLocaleString(void 0,{hour12:!1})}),(0,J.jsx)(`div`,{className:`kv__k`,children:`device`}),(0,J.jsx)(`div`,{className:`kv__v`,children:e.device??`—`}),(0,J.jsx)(`div`,{className:`kv__k`,children:`transport`}),(0,J.jsx)(`div`,{className:`kv__v`,children:e.transport??`—`}),(0,J.jsx)(`div`,{className:`kv__k`,children:`duration`}),(0,J.jsx)(`div`,{className:`kv__v`,children:xc(e.durationMs)}),(0,J.jsx)(`div`,{className:`kv__k`,children:`status`}),(0,J.jsx)(`div`,{className:`kv__v`,children:(0,J.jsx)(`span`,{className:e.isError?`status-err`:`status-ok`,children:e.isError?`error`:`ok`})}),(0,J.jsx)(`div`,{className:`kv__k`,children:`output size`}),(0,J.jsxs)(`div`,{className:`kv__v`,children:[Sc(e.outputBytes),e.truncated?` (truncated)`:``]}),(0,J.jsx)(`div`,{className:`kv__k`,children:`structured`}),(0,J.jsx)(`div`,{className:`kv__v`,children:e.hasStructured?`yes (renders an MCP App view)`:`no`})]}),e.error&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`h2`,{className:`muted`,children:`ERROR`}),(0,J.jsx)(`pre`,{className:`body`,style:{color:`var(--mt-bad)`},children:e.error})]}),(0,J.jsxs)(`div`,{className:`sheet__hd`,children:[(0,J.jsx)(`h2`,{className:`muted`,style:{margin:0},children:`INPUT`}),(0,J.jsx)(`span`,{style:{flex:1}}),e.input&&(0,J.jsx)(Ac,{type:`secondary`,size:`sm`,ghost:!0,onClick:()=>r(e=>{let t=!e;return cY(t),t}),title:n?`Showing pretty-printed JSON — click for raw`:`Showing raw JSON — click to pretty-print`,children:n?`✦ Pretty`:`{ } Raw`}),(0,J.jsx)(bc,{text:e.input,title:`Copy input JSON`})]}),e.input?(0,J.jsx)(uY,{value:lY(e.input,n)}):(0,J.jsx)(`pre`,{className:`body`,children:`—`}),(0,J.jsxs)(`div`,{className:`sheet__hd`,children:[(0,J.jsx)(`h2`,{className:`muted`,style:{margin:0},children:`OUTPUT`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(bc,{text:e.output,title:`Copy output`})]}),(0,J.jsx)(`pre`,{className:`body ros`,children:e.output?aY(e.output):`—`})]})})}var kY=e=>e==null?`?`:Sc(e);function AY({d:e}){let t=e.status,n=e.history??[];return t.reachable===!0||n.length>0?(0,J.jsxs)(`div`,{className:`card health-card`,children:[(0,J.jsxs)(`div`,{className:`health-card__hd`,children:[(0,J.jsx)(Nc,{color:hY(t).color}),(0,J.jsx)(`span`,{className:`dev-card__name`,children:e.name}),e.isDefault&&(0,J.jsx)(Mc,{type:`accent`,children:`default`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(Mc,{type:t.version?`success`:`default`,children:t.version?`v${t.version}`:`—`})]}),(0,J.jsxs)(`div`,{className:`health-card__sub muted`,children:[t.boardName??`router`,t.architecture?` · ${t.architecture}`:``,t.cpuCount?` · ${t.cpuCount} cpu`:``,t.uptime?` · up ${t.uptime}`:``]}),(0,J.jsxs)(`div`,{className:`health-card__gauges`,children:[(0,J.jsx)(HJ,{value:t.cpuLoad,label:`CPU`,color:Ec.cpu}),(0,J.jsx)(HJ,{value:t.memUsedPct,label:`MEM`,color:Ec.mem}),(0,J.jsx)(HJ,{value:t.hddUsedPct,label:`DISK`,color:Ec.disk})]}),(0,J.jsxs)(`div`,{className:`health-card__charts`,children:[(0,J.jsxs)(`div`,{className:`health-chart`,children:[(0,J.jsx)(`span`,{className:`health-chart__k`,children:`CPU load`}),(0,J.jsx)(VJ,{id:`${e.name}-cpu`,values:n.map(e=>e.cpuLoad),color:Ec.cpu,maxValue:100,unit:`%`})]}),(0,J.jsxs)(`div`,{className:`health-chart`,children:[(0,J.jsx)(`span`,{className:`health-chart__k`,children:`Memory used`}),(0,J.jsx)(VJ,{id:`${e.name}-mem`,values:n.map(e=>e.memUsedPct),color:Ec.mem,maxValue:100,unit:`%`})]}),(0,J.jsxs)(`div`,{className:`health-chart`,children:[(0,J.jsx)(`span`,{className:`health-chart__k`,children:`Probe latency`}),(0,J.jsx)(VJ,{id:`${e.name}-lat`,values:n.map(e=>e.latencyMs),color:Ec.latency,unit:`ms`})]})]}),(0,J.jsxs)(`div`,{className:`health-card__foot muted`,children:[`RAM `,kY(t.totalMemory&&t.freeMemory?t.totalMemory-t.freeMemory:void 0),` /`,` `,kY(t.totalMemory),` · free disk `,kY(t.freeHdd)]})]}):(0,J.jsxs)(`div`,{className:`card health-card health-card--na`,children:[(0,J.jsxs)(`div`,{className:`health-card__hd`,children:[(0,J.jsx)(Nc,{color:hY(t).color}),(0,J.jsx)(`span`,{className:`dev-card__name`,children:e.name}),e.isDefault&&(0,J.jsx)(Mc,{type:`accent`,children:`default`})]}),(0,J.jsx)(`p`,{className:`muted`,style:{margin:0},children:t.reachable===!1?`Offline — ${t.error??`unreachable`}`:e.mac?`Waiting for the first MAC-Telnet probe (these run every few minutes to avoid contending with tool calls)…`:`Waiting for the first health probe…`})]})}function jY(e,t){let n=(0,v.useRef)(e),r=(0,v.useRef)(t);n.current=e,r.current=t,(0,v.useEffect)(()=>{let e=!1,t=null,i=null,a=()=>{e||(i=new EventSource(dc(`/api/sse`)),i.addEventListener(`hello`,()=>r.current(`sse`)),i.addEventListener(`tool`,e=>{try{n.current(JSON.parse(e.data))}catch{}}),i.onerror=()=>{i&&i.readyState===EventSource.CONNECTING&&r.current(`off`)})},o=()=>{if(e)return;let i=location.protocol===`https:`?`wss`:`ws`;t=new WebSocket(dc(`${i}://${location.host}/api/stream`));let s=!1;t.onopen=()=>{s=!0,r.current(`ws`)},t.onerror=()=>t?.close(),t.onmessage=e=>{try{let t=JSON.parse(e.data);t.type===`event`&&t.event&&n.current(t.event)}catch{}},t.onclose=()=>{e||(r.current(`off`),s?setTimeout(o,2e3):a())}};return o(),()=>{e=!0,t?.close(),i?.close()}},[])}function MY(e){(0,v.useLayoutEffect)(()=>{let t=e.current;if(!t||window.matchMedia(`(prefers-reduced-motion: reduce)`).matches)return;document.documentElement.classList.add(`js-motion`);let n=new WeakSet,r=e=>{n.has(e)||(n.add(e),Ri.set(e,{opacity:0,y:26}),q.create({trigger:e,start:`top 90%`,once:!0,onEnter:()=>Ri.to(e,{opacity:1,y:0,duration:.7,ease:`power3.out`})}))},i=e=>{for(let t of e.querySelectorAll(`.reveal`))r(t)};i(t);let a=new MutationObserver(e=>{for(let t of e)for(let e of t.addedNodes)e instanceof Element&&(e.matches(`.reveal`)&&r(e),i(e))});a.observe(t,{childList:!0,subtree:!0});let o=setInterval(()=>q.refresh(),1200),s=setTimeout(()=>clearInterval(o),7e3);return()=>{a.disconnect(),clearInterval(o),clearTimeout(s);for(let e of q.getAll())e.kill();document.documentElement.classList.remove(`js-motion`)}},[e])}function NY({m:e,busy:t,onToggle:n}){return(0,J.jsxs)(`label`,{className:`mod-row`,"data-on":e.enabled?`1`:void 0,title:e.description,children:[(0,J.jsx)(`input`,{type:`checkbox`,checked:e.enabled,disabled:t,onChange:()=>n(e.slug,!e.enabled)}),(0,J.jsxs)(`span`,{className:`mod-row__main`,children:[(0,J.jsxs)(`span`,{className:`mod-row__name`,children:[e.label,(0,J.jsx)(`code`,{className:`mod-row__slug`,children:e.slug})]}),(0,J.jsx)(`span`,{className:`mod-row__desc muted`,children:e.description})]}),(0,J.jsxs)(`span`,{className:`mod-row__count muted`,children:[e.toolCount,` tool`,e.toolCount===1?``:`s`]})]})}function PY(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(new Set),[i,a]=(0,v.useState)(null),[o,s]=(0,v.useState)(``),c=(0,v.useCallback)(()=>{fc(`/api/modules`).then(t).catch(()=>a(`could not load modules`))},[]);(0,v.useEffect)(()=>c(),[c]);let l=e=>t(t=>t?{...t,...e}:e),u=(0,v.useCallback)(async(e,n)=>{r(t=>new Set(t).add(e)),t(t=>t&&{...t,modules:t.modules.map(t=>t.slug===e?{...t,enabled:n}:t)});let i=await pc(`/api/modules/toggle`,{slug:e,enabled:n}).catch(()=>({error:`request failed`}));if(r(t=>{let n=new Set(t);return n.delete(e),n}),i.error||i.ok===!1){a(i.error??`toggle failed`),c();return}l(i);let o=i.persisted?`saved to config`:`applied live (not saved)`,s=i.warning?` ⚠ ${i.warning}`:``;a(`${e} ${n?`enabled`:`disabled`} — ${o}. Reconnect the MCP client (or restart the server) for the tool list to update.${s}`)},[c]),d=(0,v.useCallback)(async(e,t)=>{for(let n of e)await u(n,t)},[u]),f=(0,v.useMemo)(()=>{if(!e)return[];let t=o.trim().toLowerCase(),n=e=>!t||e.slug.toLowerCase().includes(t)||e.label.toLowerCase().includes(t)||e.group.toLowerCase().includes(t)||e.description.toLowerCase().includes(t),r=new Map;for(let t of e.modules){if(!n(t))continue;let e=r.get(t.group)??[];e.push(t),r.set(t.group,e)}return[...r.entries()].map(([e,t])=>({group:e,modules:t}))},[e,o]);if(!e)return(0,J.jsx)(`div`,{className:`muted`,children:`loading modules…`});let p=f.reduce((e,t)=>e+t.modules.length,0);return(0,J.jsx)(`section`,{className:`view`,children:(0,J.jsxs)(gc,{title:`Tool modules`,className:`reveal`,extra:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`span`,{className:`muted`,children:[e.enabledModules,`/`,e.total,` modules · `,e.enabledTools,`/`,e.totalTools,` `,`tools exposed`]}),(0,J.jsx)(`button`,{className:`btn`,onClick:c,style:{marginLeft:10},children:`↻ Refresh`})]}),children:[(0,J.jsxs)(`div`,{className:`legend`,style:{margin:`0 0 10px`},children:[(0,J.jsxs)(`span`,{children:[`writes to: `,(0,J.jsx)(`code`,{children:e.source?.path??`config file`})]}),(0,J.jsx)(`span`,{children:e.hasAllowList?`allow-list active`:`all modules on by default`})]}),(0,J.jsxs)(`p`,{className:`muted`,style:{margin:`0 0 12px`,fontSize:12},children:[`Toggle a module to expose or hide all of its tools. Disabling adds it to`,` `,(0,J.jsx)(`code`,{children:`tools.disabledModules`}),` in your config file; enabling removes it (or adds it to`,` `,(0,J.jsx)(`code`,{children:`tools.enabledModules`}),` when an allow-list is in force). Trimming the surface below ~150–200 tools makes every remaining tool reliably findable by the MCP client. The client must reconnect for changes to take effect.`]}),(0,J.jsxs)(`div`,{className:`mod-toolbar`,children:[(0,J.jsx)(`input`,{className:`input`,placeholder:`Filter modules by name, slug, group or description…`,value:o,onChange:e=>s(e.target.value)}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>void d(e.modules.filter(e=>!e.enabled).map(e=>e.slug),!0),children:`Enable all`}),` `,(0,J.jsx)(`button`,{className:`btn`,onClick:()=>void d(e.modules.filter(e=>e.enabled).map(e=>e.slug),!1),children:`Disable all`})]}),i&&(0,J.jsx)(`div`,{className:`cfg-msg`,style:{marginTop:12},children:i}),p===0?(0,J.jsxs)(`div`,{className:`muted`,style:{padding:12},children:[`No modules match “`,o,`”.`]}):(0,J.jsx)(`div`,{className:`mod-groups`,children:f.map(({group:e,modules:t})=>{let r=t.filter(e=>e.enabled).length,i=t.map(e=>e.slug);return(0,J.jsxs)(`div`,{className:`mod-group`,children:[(0,J.jsxs)(`div`,{className:`mod-group__hd`,children:[(0,J.jsx)(`h3`,{className:`mod-group__title`,children:e}),(0,J.jsxs)(`span`,{className:`muted`,children:[r,`/`,t.length,` on`]}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`button`,{className:`btn btn-sm`,onClick:()=>void d(i.filter(e=>{let n=t.find(t=>t.slug===e);return n?!n.enabled:!1}),!0),children:`Enable group`}),` `,(0,J.jsx)(`button`,{className:`btn btn-sm`,onClick:()=>void d(i.filter(e=>{let n=t.find(t=>t.slug===e);return n?n.enabled:!1}),!1),children:`Disable group`})]}),(0,J.jsx)(`div`,{className:`mod-list`,children:t.map(e=>(0,J.jsx)(NY,{m:e,busy:n.has(e.slug),onToggle:(e,t)=>void u(e,t)},e.slug))})]},e)})})]})})}var FY={TCP:`#e4e4e7`,UDP:`#d4d4d8`,ICMP:`#a1a1aa`,ICMPv6:`#a1a1aa`,ARP:`#e4e4e7`,IPv6:`#a1a1aa`},IY=e=>e&&FY[e]||`#71717a`;function LY(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(!1);(0,v.useEffect)(()=>{let e=()=>void fc(`/api/capture/packets?limit=150`).then(t).catch(()=>{});e();let n=setInterval(e,1500);return()=>clearInterval(n)},[]);let i=e?.stats,a=e?.packets??[],o=async()=>{r(!0),await pc(`/api/capture/stop`,{}).catch(()=>{}),r(!1)};if(!i||!i.running&&i.packets===0)return(0,J.jsxs)(`div`,{className:`cap-idle muted`,children:[`No capture running. Start one with the `,(0,J.jsx)(`code`,{children:`start_packet_capture`}),` tool — point the device's TZSP stream at this host — and decoded packets stream in here live.`]});let s=Math.max(1,...Object.values(i.protocols));return(0,J.jsxs)(`div`,{className:`cap`,children:[(0,J.jsxs)(`div`,{className:`cap-bar`,children:[(0,J.jsx)(`span`,{className:`cap-dot${i.running?` is-on`:``}`}),(0,J.jsx)(`b`,{children:i.running?`capturing`:`stopped`}),(0,J.jsxs)(`span`,{className:`muted`,children:[`UDP `,i.port]}),(0,J.jsxs)(`span`,{className:`muted`,children:[wc(i.packets),` pkts · `,Sc(i.bytes)]}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`a`,{className:`btn`,href:dc(`/api/capture/pcap`),download:`capture.pcap`,children:`⤓ pcap`}),(0,J.jsx)(`button`,{className:`btn btn-danger`,onClick:()=>void o(),disabled:n||!i.running,children:`■ Stop`})]}),(0,J.jsxs)(`div`,{className:`cap-cols`,children:[(0,J.jsxs)(`div`,{className:`cap-side`,children:[(0,J.jsx)(`div`,{className:`cap-h`,children:`Protocols`}),Object.entries(i.protocols).map(([e,t])=>(0,J.jsxs)(`div`,{className:`cap-pbar`,children:[(0,J.jsx)(`span`,{className:`cap-plabel`,style:{color:IY(e)},children:e}),(0,J.jsx)(`span`,{className:`cap-ptrack`,children:(0,J.jsx)(`i`,{style:{width:`${t/s*100}%`,background:IY(e)}})}),(0,J.jsx)(`span`,{className:`cap-pn`,children:t})]},e)),(0,J.jsx)(`div`,{className:`cap-h`,style:{marginTop:12},children:`Top talkers`}),i.topTalkers.length===0&&(0,J.jsx)(`div`,{className:`muted`,children:`—`}),i.topTalkers.map(e=>(0,J.jsxs)(`div`,{className:`cap-talker`,children:[(0,J.jsx)(`span`,{children:e.addr}),(0,J.jsx)(`b`,{children:e.count})]},e.addr))]}),(0,J.jsx)(`div`,{className:`cap-list`,children:a.length===0?(0,J.jsx)(`div`,{className:`muted`,style:{padding:10},children:`waiting for packets…`}):a.map((e,t)=>(0,J.jsxs)(`div`,{className:`cap-row`,children:[(0,J.jsx)(`span`,{className:`cap-tt`,children:Cc(e.ts)}),(0,J.jsx)(`span`,{className:`cap-proto`,style:{color:IY(e.protocol)},children:e.protocol??e.ethType}),(0,J.jsx)(`span`,{className:`cap-len`,children:e.len}),(0,J.jsx)(`span`,{className:`cap-info`,children:e.info})]},t))})]})]})}function RY(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(null),[i,a]=(0,v.useState)(null),[o,s]=(0,v.useState)(null),c=(0,v.useCallback)(()=>{fc(`/api/s3/list`).then(t).catch(()=>t({configured:!1,objects:[]}))},[]);(0,v.useEffect)(()=>c(),[c]);let l=e=>{fc(`/api/s3/presign?key=${encodeURIComponent(e)}`).then(e=>{e.url?window.open(e.url,`_blank`,`noopener`):s(`could not generate download link`)}).catch(()=>s(`could not generate download link`))},u=async e=>{a(e);let t=await pc(`/api/s3/delete`,{key:e}).catch(()=>({error:`request failed`}));a(null),r(null),t.ok?(s(`Deleted ${e}`),c()):s(t.error??`delete failed`)};return e?e.configured?(0,J.jsx)(`section`,{className:`view`,children:(0,J.jsxs)(gc,{title:`S3 backups`,className:`reveal`,extra:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`span`,{className:`muted`,children:[e.target,` · `,e.objects.length,` object`,e.objects.length===1?``:`s`,e.truncated?` (truncated)`:``]}),(0,J.jsx)(`button`,{className:`btn`,onClick:c,style:{marginLeft:10},children:`↻ Refresh`})]}),children:[o&&(0,J.jsx)(`div`,{className:`cfg-msg`,children:o}),e.objects.length===0?(0,J.jsxs)(`div`,{className:`muted`,style:{padding:12},children:[`No objects in the bucket. Upload one with the `,(0,J.jsx)(`code`,{children:`upload_backup_to_s3`}),` tool.`]}):(0,J.jsx)(`div`,{className:`feedwrap`,children:(0,J.jsxs)(`table`,{className:`feed`,children:[(0,J.jsx)(`thead`,{children:(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`th`,{children:`key`}),(0,J.jsx)(`th`,{className:`num`,children:`size`}),(0,J.jsx)(`th`,{children:`modified`}),(0,J.jsx)(`th`,{style:{width:200},children:`actions`})]})}),(0,J.jsx)(`tbody`,{children:e.objects.map(e=>(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`td`,{children:e.key}),(0,J.jsx)(`td`,{className:`num`,children:Sc(e.size)}),(0,J.jsx)(`td`,{children:e.lastModified?new Date(e.lastModified).toLocaleString(void 0,{hour12:!1}):`—`}),(0,J.jsxs)(`td`,{onClick:e=>e.stopPropagation(),children:[(0,J.jsx)(`button`,{className:`btn`,onClick:()=>l(e.key),children:`⤓ Download`}),` `,n===e.key?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{className:`btn btn-danger`,disabled:i===e.key,onClick:()=>void u(e.key),children:`✓ Confirm`}),` `,(0,J.jsx)(`button`,{className:`btn`,onClick:()=>r(null),children:`Cancel`})]}):(0,J.jsx)(`button`,{className:`btn`,onClick:()=>r(e.key),children:`🗑 Delete`})]})]},e.key))})]})})]})}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`☁️`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`S3 is not configured`}),(0,J.jsxs)(`p`,{className:`feed-empty__sub`,children:[`Add an `,(0,J.jsx)(`code`,{children:`s3`}),` block (bucket + credentials) to your config to manage backup objects here.`]})]}):(0,J.jsx)(`div`,{className:`muted`,children:`loading S3 objects…`})}function zY(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(``),[i,a]=(0,v.useState)(``),[o,s]=(0,v.useState)(null),[c,l]=(0,v.useState)(null),u=(0,v.useCallback)(()=>{fc(`/api/snapshots`).then(e=>t(e.snapshots)).catch(()=>t([]))},[]);(0,v.useEffect)(()=>u(),[u]);let d=e=>{fc(`/api/snapshot/${encodeURIComponent(e)}`).then(s).catch(()=>{})},f=()=>{!n||!i||pc(`/api/snapshots/diff`,{from:n,to:i}).then(l).catch(()=>{})};if(!e)return(0,J.jsx)(`div`,{className:`muted`,children:`loading snapshots…`});if(e.length===0)return(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🕰️`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No config snapshots yet`}),(0,J.jsxs)(`p`,{className:`feed-empty__sub`,children:[`Capture one with the `,(0,J.jsx)(`code`,{children:`capture_config_snapshot`}),` tool — then time-travel diff any two here.`]})]});let p=e.map(e=>(0,J.jsxs)(`option`,{value:e.id,children:[e.device,` · `,e.label??e.id,` · `,Cc(e.ts)]},e.id));return(0,J.jsxs)(`section`,{className:`view`,children:[(0,J.jsxs)(gc,{title:`Config snapshots`,className:`reveal`,extra:(0,J.jsx)(`button`,{className:`btn`,onClick:u,children:`↻ Refresh`}),children:[(0,J.jsxs)(`div`,{className:`toolbar`,style:{marginBottom:12},children:[(0,J.jsxs)(`select`,{className:`btn`,value:n,onChange:e=>r(e.target.value),children:[(0,J.jsx)(`option`,{value:``,children:`diff from…`}),p]}),(0,J.jsxs)(`select`,{className:`btn`,value:i,onChange:e=>a(e.target.value),children:[(0,J.jsx)(`option`,{value:``,children:`to…`}),p]}),(0,J.jsx)(`button`,{className:`btn is-active`,onClick:f,disabled:!n||!i,children:`Diff →`}),(0,J.jsxs)(`span`,{className:`muted`,children:[e.length,` snapshots`]})]}),(0,J.jsx)(`div`,{className:`feedwrap`,children:(0,J.jsxs)(`table`,{className:`feed`,children:[(0,J.jsx)(`thead`,{children:(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`th`,{children:`captured`}),(0,J.jsx)(`th`,{children:`device`}),(0,J.jsx)(`th`,{children:`label`}),(0,J.jsx)(`th`,{children:`version`}),(0,J.jsx)(`th`,{className:`num`,children:`lines`}),(0,J.jsx)(`th`,{className:`num`,children:`size`}),(0,J.jsx)(`th`,{children:`output`})]})}),(0,J.jsx)(`tbody`,{children:e.map(e=>(0,J.jsxs)(`tr`,{className:o?.id===e.id?`is-selected`:void 0,onClick:()=>d(e.id),children:[(0,J.jsx)(`td`,{children:Cc(e.ts)}),(0,J.jsx)(`td`,{children:e.device}),(0,J.jsx)(`td`,{children:e.label??`—`}),(0,J.jsx)(`td`,{children:e.rosVersion??`—`}),(0,J.jsx)(`td`,{className:`num`,children:e.lines}),(0,J.jsx)(`td`,{className:`num`,children:Sc(e.bytes)}),(0,J.jsx)(`td`,{className:`preview`,children:`view export →`})]},e.id))})]})})]}),c&&(0,J.jsx)(gc,{title:`Time-travel diff`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:c.summary.changed?`+${c.summary.added} / -${c.summary.removed}`:`identical`}),children:(0,J.jsx)(`pre`,{className:`cfg-diff`,children:(c.unified||`(identical)`).split(`
80
- `).map((e,t)=>(0,J.jsx)(`div`,{className:e.startsWith(`+`)?`d-add`:e.startsWith(`-`)?`d-del`:e.startsWith(`@@`)?`d-hunk`:``,children:e||` `},t))})}),o&&(0,J.jsx)(gc,{title:`Snapshot · ${o.label??o.id}`,className:`reveal`,extra:(0,J.jsx)(Ac,{type:`secondary`,size:`sm`,onClick:()=>s(null),children:`✕ Close`}),children:(0,J.jsx)(`pre`,{className:`body`,style:{maxHeight:460},children:o.body||`(empty)`})})]})}function BY(e){return e==null?`#3f3f46`:e>=85?`#f87171`:e>=60?`#a1a1aa`:`#d4d4d8`}function VY({topo:e,onOnboard:t}){let[n,r]=(0,v.useState)(null),i=e.nodes.filter(e=>e.kind===`device`),a=e.nodes.filter(e=>e.kind===`neighbor`),o=Math.max(1,i.length),s=i.length<=1?0:Math.min(150,76+o*8),c=s+(i.length<=1?180:140),l=Math.max(360,Math.round((c+78)*2)),u=l/2,d=new Map,f=new Map;i.forEach((e,t)=>{if(i.length===1){d.set(e.id,{x:380,y:u}),f.set(e.id,-Math.PI/2);return}let n=t/o*Math.PI*2-Math.PI/2;f.set(e.id,n),d.set(e.id,{x:380+s*Math.cos(n),y:u+s*Math.sin(n)})});let p=new Map,m=new Set(a.map(e=>e.id));for(let t of e.edges)m.has(t.to)&&!p.has(t.to)&&p.set(t.to,t.from);let h=new Map;for(let e of a){let t=p.get(e.id)??i[0]?.id??``;h.set(t,[...h.get(t)??[],e.id])}if(i.length<=1)a.forEach((e,t)=>{let n=t/Math.max(1,a.length)*Math.PI*2-Math.PI/2;d.set(e.id,{x:380+c*Math.cos(n),y:u+c*Math.sin(n)})});else for(let[e,t]of h){let n=f.get(e)??-Math.PI/2,r=Math.min(Math.PI/2.2,.32*t.length);t.forEach((e,i)=>{let a=t.length===1?n:n-r/2+r*i/(t.length-1);d.set(e,{x:380+c*Math.cos(a),y:u+c*Math.sin(a)})})}let g=new Map(e.nodes.map(e=>[e.id,e])),_=n?g.get(n):null;return(0,J.jsxs)(`div`,{className:`topo`,children:[(0,J.jsxs)(`svg`,{viewBox:`0 0 760 ${l}`,width:`100%`,height:Math.min(l,540),preserveAspectRatio:`xMidYMid meet`,children:[e.edges.map((e,t)=>{let n=d.get(e.from),r=d.get(e.to);return!n||!r?null:(0,J.jsx)(`line`,{className:`topo-edge${m.has(e.to)?` is-dashed`:``}`,x1:n.x,y1:n.y,x2:r.x,y2:r.y,children:(0,J.jsxs)(`title`,{children:[e.from,` → `,e.to,e.interface?` (${e.interface})`:``]})},`e-${t}`)}),e.nodes.map(e=>{let t=d.get(e.id);if(!t)return null;let i=e.kind===`device`,a=i?132:108,o=i?50:38,s=t.x-a/2,c=t.y-o/2,l=e.reachable===!0?`#d4d4d8`:e.reachable===!1?`#f87171`:i?`#71717a`:`#e4e4e7`,u=n===e.id;return(0,J.jsxs)(`g`,{className:`topo-node${i?` is-device`:` is-neighbor`}${e.onboardable?` is-onboard`:``}${u?` is-picked`:``}`,transform:`translate(${s},${c})`,onClick:()=>r(t=>t===e.id?null:e.id),children:[(0,J.jsx)(`rect`,{width:a,height:o,rx:9,style:{stroke:l}}),(0,J.jsx)(`text`,{className:`topo-label`,x:9,y:16,children:(e.label||e.id).slice(0,16)}),i?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`text`,{className:`topo-sub`,x:9,y:30,children:(e.board||e.ip||``).slice(0,18)}),(0,J.jsx)(`rect`,{className:`topo-bar-bg`,x:9,y:37,width:a-18,height:4,rx:2}),(0,J.jsx)(`rect`,{x:9,y:37,width:(a-18)*Math.min(100,e.cpuLoad??0)/100,height:4,rx:2,style:{fill:BY(e.cpuLoad)}}),(0,J.jsx)(`rect`,{className:`topo-bar-bg`,x:9,y:43,width:a-18,height:4,rx:2}),(0,J.jsx)(`rect`,{x:9,y:43,width:(a-18)*Math.min(100,e.memUsedPct??0)/100,height:4,rx:2,style:{fill:BY(e.memUsedPct)}})]}):(0,J.jsx)(`text`,{className:`topo-sub`,x:9,y:29,children:e.onboardable?`+ onboard`:e.ip||e.mac||``})]},e.id)})]}),(0,J.jsxs)(`div`,{className:`topo-foot`,children:[(0,J.jsxs)(`span`,{className:`legend`,children:[(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{className:`dot`,style:{background:`#d4d4d8`}}),` online`]}),(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{className:`dot`,style:{background:`#f87171`}}),` offline`]}),(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{className:`dot`,style:{background:`#e4e4e7`}}),` neighbour`]}),(0,J.jsxs)(`span`,{className:`muted`,children:[e.stats.devices,` devices · `,e.stats.neighbors,` discovered ·`,` `,e.stats.onboardable,` onboardable`]})]}),_&&(0,J.jsxs)(`div`,{className:`topo-pop`,children:[(0,J.jsxs)(`div`,{className:`topo-pop__hd`,children:[(0,J.jsx)(`strong`,{children:_.label}),(0,J.jsx)(`span`,{className:`muted`,children:[_.board,_.version,_.mac].filter(Boolean).join(` · `)||`no details advertised`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`button`,{className:`topo-btn`,onClick:()=>r(null),children:`✕`})]}),_.suggestedConfig?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`div`,{className:`muted`,style:{margin:`2px 0 6px`},children:`Not managed yet — add this to your device config to onboard it:`}),(0,J.jsx)(`pre`,{className:`topo-stub`,children:JSON.stringify({[_.suggestedConfig.name]:HY(_.suggestedConfig)},null,2)}),(0,J.jsx)(bc,{className:`topo-btn`,title:`Copy config stub`,label:`Copy config stub`,text:JSON.stringify({[_.suggestedConfig.name]:HY(_.suggestedConfig)},null,2)}),t&&(0,J.jsx)(`button`,{className:`topo-btn cfg-save`,onClick:()=>t(_.suggestedConfig.name,HY(_.suggestedConfig)),children:`Add to config →`})]}):(0,J.jsxs)(`div`,{className:`muted`,children:[`Managed device`,_.ip?` · ${_.ip}`:``,_.uptime?` · up ${_.uptime}`:``]})]})]})]})}function HY(e){let t={port:e.port,username:e.username};return e.host&&(t.host=e.host),e.mac&&(t.mac=e.mac),t}Ri.registerPlugin(q);function UY(e,t,n){let r=URL.createObjectURL(new Blob([t],{type:`${n};charset=utf-8`})),i=document.createElement(`a`);i.href=r,i.download=e,document.body.append(i),i.click(),i.remove(),URL.revokeObjectURL(r)}var WY=[{id:`overview`,label:`Overview`,sub:`Calls, latency & risk at a glance`},{id:`devices`,label:`Devices`,sub:`Connectivity radar & system health`},{id:`clients`,label:`Clients`,sub:`Connected LAN devices — usage, block/allow, pin IP`},{id:`aaa`,label:`RADIUS & UM`,sub:`RADIUS client & User Manager RADIUS server`},{id:`topology`,label:`Topology`,sub:`Layer-2 neighbours via MNDP / CDP / LLDP`},{id:`packets`,label:`Packets`,sub:`Live TZSP capture & decode`},{id:`snapshots`,label:`Snapshots`,sub:`Config history & time-travel diff`},{id:`plan`,label:`Change Plan`,sub:`Dry-run intended RouterOS commands`},{id:`s3`,label:`S3 Backups`,sub:`List, download & delete S3 backup objects`},{id:`backups`,label:`Backups`,sub:`Local config vault — create, restore, manage`},{id:`modules`,label:`Modules`,sub:`Enable/disable tool modules — curate the surface`},{id:`config`,label:`Config`,sub:`Effective configuration & safe editor`},{id:`feed`,label:`Live Feed`,sub:`Every tool call, in real time`}],GY=new Set(WY.map(e=>e.id)),KY=`mt-view`;function qY(){try{let e=location.hash.replace(/^#\/?/,``);return GY.has(e)?e:null}catch{return null}}function JY(){let e=qY();if(e)return e;try{let e=localStorage.getItem(KY);if(e&&GY.has(e))return e}catch{}return`overview`}var YY=[`#ededed`,`#a1a1a1`],XY={overview:YY,devices:YY,clients:YY,aaa:YY,topology:YY,packets:YY,snapshots:YY,plan:YY,s3:YY,backups:YY,modules:YY,config:YY,feed:YY},ZY={overview:{what:`A live pulse of all MCP tool activity: total calls, error rate, p50/p95 latency, the busiest tools, and a risk breakdown — over a time window you choose.`,tips:[`Change the time window (top-right) to zoom from the last 5 minutes out to 24 hours.`,`The risk donut splits calls by annotation: read · write · destructive · dangerous.`,`A rising error line usually points at one device or one tool — jump to Live Feed to see which.`]},devices:{what:`Every configured router with its live reachability (SSH or MAC-Telnet), latency, identity, and system health — CPU, memory and disk — refreshed continuously.`,tips:[`Each device gets a stable colour so you can track it across the connectivity radar.`,`Health (CPU/Mem/Disk) is probed periodically; MAC-Telnet devices are probed on a slower cadence.`,`Latency tiers are colour-coded green → amber → red; a grey node is currently unreachable.`]},clients:{what:`The LAN devices connected to a router — merged from its DHCP leases and ARP table — with live Download/Upload charts, and one-click controls to block/allow a device, pin (reserve) its IP, change that IP, or relabel it.`,tips:[`Pick the router (top-right) to inspect its connected devices; filter by IP, MAC or name.`,`Click a device to open its live ↓/↑ traffic chart — needs a simple queue targeting its IP.`,`Block/allow is enforced by MAC, so it survives the device changing IP; “Pin IP” makes its lease static.`]},aaa:{what:"Full management of the router's RADIUS client (`/radius`) and the built-in User Manager RADIUS server (`/user-manager`): RADIUS servers + incoming CoA, and User Manager users, service profiles, rate/quota limitations, NAS clients, profile assignments, accounting sessions, and global settings.",tips:[`Pick the router (top-right), then switch tabs across RADIUS, Users, Profiles, Limitations, NAS, Assignments, Sessions and Settings.`,`Every tab is full CRUD: add, edit, enable/disable and remove — secrets are write-only and shown redacted.`,`The Usage & Heatmap tab shows each user's 3-month download/upload and a GitHub-style connection heatmap, persisted locally.`,`If a device lacks the user-manager package, the User Manager tabs explain how to install it; RADIUS-client tabs still work.`]},topology:{what:`A Layer-2 map of neighbours each router discovers via MNDP / CDP / LLDP — the physical adjacency of your network, drawn live.`,tips:[`Solid nodes are configured devices; faint nodes are discovered-but-unmanaged neighbours.`,`Use “Add to config →” on an unmanaged neighbour to pre-fill it in the Config editor.`,`Drag to pan; the layout settles automatically as new neighbours arrive.`]},packets:{what:`Live packet capture streamed from a router over TZSP — decode headers in real time without leaving the dashboard.`,tips:[`Pick a device and start the capture; packets decode as they arrive.`,`Stop the capture when done — it frees the router-side sniffer.`,`Great for debugging a protocol issue alongside the Live Feed of tool calls.`]},snapshots:{what:`Point-in-time captures of a device’s full configuration (/export), stored locally so you can diff any two and see exactly what changed.`,tips:[`Capture a snapshot before a risky change, then diff after to audit the delta.`,`The diff is line-level: green added, red removed.`,`Snapshots are device config exports — for the dashboard’s OWN config history see the Config page.`]},plan:{what:`Dry-run the exact RouterOS commands a change would run before it touches a device — a change plan you can review and trust.`,tips:[`Paste or build intended commands to see them validated and ordered.`,`Nothing is sent to the device from here — it’s a preview.`,`Pair with Safe Mode (auto-revert) when you do apply for real.`]},s3:{what:`Browse, download, and delete backup objects in your configured S3-compatible bucket — your off-box archive of device backups and exports.`,tips:[`Filter by key prefix to find a device’s backups quickly.`,`Download fetches the object through a presigned URL; delete is permanent.`,`For host-side .rsc backups instead, use the Backups page.`]},backups:{what:`A local config vault on the MCP server: capture a device’s /export as a timestamped .rsc file, then download, upload, rename, restore (via Safe Mode), or delete it.`,tips:[`Restore offers a dry-run (applies then rolls back) before you commit for real.`,`Edit the vault path inline in the header — it’s saved to your config.`,`Filenames are stamped in the device’s local 24-hour clock.`]},modules:{what:"Every tool module in the catalog with a live on/off switch. Toggling one writes your config file's `tools` block (disabledModules / enabledModules) and applies it immediately, so you can curate exactly which scopes the MCP server exposes.",tips:[`MCP clients search-rank tools and degrade past ~100; trim the surface below ~150–200 tools so every remaining tool is reliably findable.`,`Disable adds the module to tools.disabledModules; enable removes it (or adds it to an active allow-list) — your config file is updated live on each toggle.`,`Changes need an MCP client reconnect (or a server restart) to actually shrink/grow the visible tool list.`]},config:{what:`View the effective configuration, edit it safely with schema-aware validation and auto-rollback, browse a full field guide, and travel through config version history.`,tips:[`Every successful apply is auto-saved to the version timeline — restore any point in time.`,`Save a named checkpoint before a big change for an easy, labelled rollback.`,`The Field Guide documents every config option, its type, and default — straight from the schema.`]},feed:{what:`Every tool call as it happens — tool, device, risk, duration, and success/error — with full request/response detail on click.`,tips:[`Filter by status to isolate failures, or by tool/device to follow one thread.`,`Click any row to open the full (secret-redacted) request and response.`,`Pause the stream when you want to inspect without rows shifting under you.`]}};function QY({view:e}){let t=ZY[e];return(0,J.jsxs)(`div`,{className:`pagehelp reveal`,role:`region`,"aria-label":`Page help`,children:[(0,J.jsx)(`div`,{className:`pagehelp__icon`,"aria-hidden":`true`,children:`?`}),(0,J.jsxs)(`div`,{className:`pagehelp__body`,children:[(0,J.jsx)(`p`,{className:`pagehelp__what`,children:t.what}),(0,J.jsx)(`ul`,{className:`pagehelp__tips`,children:t.tips.map((e,t)=>(0,J.jsx)(`li`,{children:e},t))})]})]})}function $Y({name:e}){return(0,J.jsx)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.7`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:{overview:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`rect`,{x:`3`,y:`3`,width:`8`,height:`8`,rx:`1.6`}),(0,J.jsx)(`rect`,{x:`13`,y:`3`,width:`8`,height:`5`,rx:`1.6`}),(0,J.jsx)(`rect`,{x:`13`,y:`10`,width:`8`,height:`11`,rx:`1.6`}),(0,J.jsx)(`rect`,{x:`3`,y:`13`,width:`8`,height:`8`,rx:`1.6`})]}),devices:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`rect`,{x:`3`,y:`4`,width:`18`,height:`7`,rx:`2`}),(0,J.jsx)(`rect`,{x:`3`,y:`13`,width:`18`,height:`7`,rx:`2`}),(0,J.jsx)(`path`,{d:`M7 7.5h.01M7 16.5h.01`})]}),clients:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{cx:`9`,cy:`8`,r:`3`}),(0,J.jsx)(`path`,{d:`M3.5 19a5.5 5.5 0 0 1 11 0`}),(0,J.jsx)(`path`,{d:`M16 7.5a2.5 2.5 0 0 1 0 5M17.5 19a4.5 4.5 0 0 0-2-3.6`})]}),aaa:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{d:`M12 3 4 6v5c0 4.4 3.2 7.6 8 9 4.8-1.4 8-4.6 8-9V6l-8-3Z`}),(0,J.jsx)(`path`,{d:`M9.5 11.5 11 13l3.5-3.5`})]}),topology:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{cx:`12`,cy:`5`,r:`2.4`}),(0,J.jsx)(`circle`,{cx:`5`,cy:`19`,r:`2.4`}),(0,J.jsx)(`circle`,{cx:`19`,cy:`19`,r:`2.4`}),(0,J.jsx)(`path`,{d:`M12 7.4 6.4 16.6M12 7.4 17.6 16.6`})]}),packets:(0,J.jsx)(`path`,{d:`M3 12h4l2-7 4 14 2-7h6`}),snapshots:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{d:`M12 3 3 7.5 12 12 21 7.5 12 3Z`}),(0,J.jsx)(`path`,{d:`M3 12 12 16.5 21 12`}),(0,J.jsx)(`path`,{d:`M3 16.5 12 21 21 16.5`})]}),plan:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{cx:`6`,cy:`6`,r:`2.3`}),(0,J.jsx)(`circle`,{cx:`6`,cy:`18`,r:`2.3`}),(0,J.jsx)(`circle`,{cx:`18`,cy:`8`,r:`2.3`}),(0,J.jsx)(`path`,{d:`M6 8.3v7.4M8.3 6H13a3 3 0 0 1 3 3v0`})]}),s3:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`ellipse`,{cx:`12`,cy:`6`,rx:`7`,ry:`2.6`}),(0,J.jsx)(`path`,{d:`M5 6v12c0 1.5 3.1 2.6 7 2.6s7-1.1 7-2.6V6`}),(0,J.jsx)(`path`,{d:`M5 12c0 1.5 3.1 2.6 7 2.6s7-1.1 7-2.6`})]}),backups:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{d:`M3 6.5 5 3.5h14l2 3`}),(0,J.jsx)(`rect`,{x:`3`,y:`6.5`,width:`18`,height:`14`,rx:`2`}),(0,J.jsx)(`path`,{d:`M9.5 12h5`})]}),modules:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`rect`,{x:`3`,y:`5`,width:`18`,height:`6`,rx:`3`}),(0,J.jsx)(`circle`,{cx:`8`,cy:`8`,r:`1.5`}),(0,J.jsx)(`rect`,{x:`3`,y:`13`,width:`18`,height:`6`,rx:`3`}),(0,J.jsx)(`circle`,{cx:`16`,cy:`16`,r:`1.5`})]}),config:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{d:`M4 7h8M16 7h4M4 17h4M12 17h8`}),(0,J.jsx)(`circle`,{cx:`14`,cy:`7`,r:`2.2`}),(0,J.jsx)(`circle`,{cx:`10`,cy:`17`,r:`2.2`})]}),feed:(0,J.jsx)(`path`,{d:`M4 6h16M4 12h16M4 18h10`})}[e]})}function eX(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(null),[i,a]=(0,v.useState)(null),[o,s]=(0,v.useState)(null),[c,l]=(0,v.useState)(null),[u,d]=(0,v.useState)(!1),[f,p]=(0,v.useState)(null),[m,h]=(0,v.useState)([]),[g,_]=(0,v.useState)(36e5),[y,b]=(0,v.useState)(!1),[x,S]=(0,v.useState)(`off`),[C,w]=(0,v.useState)(null),[T,E]=(0,v.useState)(()=>new Set),[D,O]=(0,v.useState)({}),[k,A]=(0,v.useState)({tool:``,risk:``,device:``,status:``,q:``}),j=(0,v.useRef)(y);j.current=y;let M=(0,v.useRef)(null);MY(M);let[N,P]=(0,v.useState)(JY),F=(0,v.useCallback)(e=>{P(e);try{qY()!==e&&(location.hash=e),localStorage.setItem(KY,e)}catch{}},[]);(0,v.useEffect)(()=>{if(qY()!==N)try{location.hash=N}catch{}let e=()=>{let e=qY();e&&F(e)};return window.addEventListener(`hashchange`,e),()=>window.removeEventListener(`hashchange`,e)},[]);let[I,L]=(0,v.useState)(()=>{try{let e=localStorage.getItem(`mt-help-open`);return new Set(e?JSON.parse(e):[])}catch{return new Set}}),ee=e=>L(t=>{let n=new Set(t);n.has(e)?n.delete(e):n.add(e);try{localStorage.setItem(`mt-help-open`,JSON.stringify([...n]))}catch{}return n}),[te,R]=(0,v.useState)(``),[z,ne]=(0,v.useState)(`all`),B=(0,v.useMemo)(()=>{let e=i?.devices??[];return{online:e.filter(e=>e.status.reachable===!0).length,offline:e.filter(e=>e.status.reachable===!1).length,total:e.length}},[i]),V=(0,v.useMemo)(()=>{let e=i?.devices??[],t=te.trim().toLowerCase();return e.filter(e=>!(z===`online`&&e.status.reachable!==!0||z===`offline`&&e.status.reachable!==!1||t&&!e.name.toLowerCase().includes(t)&&!(e.address??e.host??``).toLowerCase().includes(t)))},[i,te,z]);jY((0,v.useCallback)(e=>{if(j.current)return;h(t=>[e,...t].slice(0,kc));let t=e.device;t&&O(e=>({...e,[t]:(e[t]??0)+1}))},[]),(0,v.useCallback)(e=>S(e),[])),(0,v.useEffect)(()=>{fc(`/api/events?limit=${kc}`).then(e=>h(e.events)).catch(()=>{})},[]);let re=(0,v.useCallback)(()=>{fc(`/api/stats?window=${g}&buckets=60`).then(t).catch(()=>{})},[g]);(0,v.useEffect)(()=>{re();let e=()=>{re(),fc(`/api/meta`).then(r).catch(()=>{}),fc(`/api/devices`).then(a).catch(()=>{}),fc(`/api/topology`).then(s).catch(()=>{})};e();let t=setInterval(()=>{j.current||e()},4e3);return()=>clearInterval(t)},[re]),(0,v.useEffect)(()=>{let e=()=>void fc(`/api/config`).then(l).catch(()=>{});e();let t=setInterval(e,3e4);return()=>clearInterval(t)},[]),(0,v.useEffect)(()=>{let e=e=>{e.key===`Escape`&&w(null)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]);let ie=(0,v.useMemo)(()=>{let e=k.q.trim().toLowerCase();return m.filter(t=>!(k.tool&&t.tool!==k.tool||k.risk&&t.risk!==k.risk||k.device&&t.device!==k.device||k.status===`ok`&&t.isError||k.status===`error`&&!t.isError||e&&!t.tool.toLowerCase().includes(e)&&!t.input.toLowerCase().includes(e)&&!t.output.toLowerCase().includes(e)&&!(t.error??``).toLowerCase().includes(e))).sort((e,t)=>t.ts-e.ts)},[m,k]),ae=!!(k.tool||k.risk||k.device||k.status||k.q),oe=(0,v.useMemo)(()=>m.filter(e=>e.isError),[m]),se=(0,v.useMemo)(()=>({ok:m.length-oe.length,error:oe.length}),[m,oe]),H=(0,v.useCallback)(async e=>{try{w(await fc(`/api/event/${encodeURIComponent(e.id)}`))}catch{w(e)}},[]),ce=(0,v.useMemo)(()=>ie.slice(0,200),[ie]),le=(0,v.useMemo)(()=>ce.map(e=>e.id),[ce]),ue=le.length>0&&le.every(e=>T.has(e)),de=!ue&&le.some(e=>T.has(e)),fe=(0,v.useCallback)(e=>{E(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),pe=(0,v.useCallback)(()=>{E(e=>{let t=new Set(e);if(le.length>0&&le.every(e=>t.has(e)))for(let e of le)t.delete(e);else for(let e of le)t.add(e);return t})},[le]),[me,he]=(0,v.useState)(!1),ge=(0,v.useCallback)(async()=>{let e=[...T];if(e.length!==0)try{await mc({ids:e});let t=new Set(e);h(e=>e.filter(e=>!t.has(e.id))),E(new Set)}catch{}finally{he(!1)}},[T]),_e=e=>{if(e===`json`){UY(`mcp-events.json`,JSON.stringify(ie,null,2),`application/json`);return}let t=[`ts`,`tool`,`risk`,`device`,`durationMs`,`isError`,`error`],n=e=>/[",\n]/.test(e)?`"${e.replace(/"/g,`""`)}"`:e,r=ie.map(e=>[new Date(e.ts).toISOString(),e.tool,e.risk,e.device??``,String(e.durationMs),String(e.isError),e.error??``].map(n).join(`,`)).join(`
81
- `);UY(`mcp-events.csv`,`${t.join(`,`)}\n${r}\n`,`text/csv`)},ve=e?e.errorRate>=.2?`is-bad`:e.errorRate>=.05?`is-warn`:`is-good`:``,ye=c?.mcp??{},be=c?.dashboard??{},xe=(e,t,n)=>(0,J.jsxs)(`select`,{className:`btn`,value:k[e],onChange:t=>A(n=>({...n,[e]:t.target.value})),children:[(0,J.jsx)(`option`,{value:``,children:t}),n.map(e=>(0,J.jsx)(`option`,{value:e,children:e},e))]}),Se=WY.find(e=>e.id===N)??WY[0];return(0,J.jsxs)(`div`,{className:`shell`,ref:M,"data-view":N,style:{"--page-accent":XY[N][0],"--page-accent-2":XY[N][1]},children:[(0,J.jsxs)(`aside`,{className:`nav`,children:[(0,J.jsxs)(`div`,{className:`nav__brand`,children:[(0,J.jsx)(`div`,{className:`nav__mark`,children:(0,J.jsx)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,"aria-hidden":`true`,children:(0,J.jsxs)(`g`,{stroke:`#18181b`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,J.jsx)(`path`,{d:`M12 12 L4 5 M12 12 L20 5 M12 12 L12 20`}),(0,J.jsx)(`circle`,{cx:`12`,cy:`12`,r:`3`,fill:`#18181b`,stroke:`none`}),(0,J.jsx)(`circle`,{cx:`4`,cy:`5`,r:`1.9`,fill:`#18181b`,stroke:`none`}),(0,J.jsx)(`circle`,{cx:`20`,cy:`5`,r:`1.9`,fill:`#18181b`,stroke:`none`}),(0,J.jsx)(`circle`,{cx:`12`,cy:`20`,r:`1.9`,fill:`#18181b`,stroke:`none`})]})})}),(0,J.jsxs)(`div`,{className:`nav__brandtext`,children:[(0,J.jsx)(`b`,{children:`MikroTik MCP`}),(0,J.jsx)(`small`,{children:`Observability`})]})]}),(0,J.jsx)(`nav`,{className:`nav__items`,children:WY.map(e=>(0,J.jsxs)(`button`,{className:`nav__item${N===e.id?` is-active`:``}`,onClick:()=>F(e.id),children:[(0,J.jsx)($Y,{name:e.id}),(0,J.jsx)(`span`,{children:e.label}),e.id===`feed`&&m.length>0&&(0,J.jsx)(`span`,{className:`nav__badge`,children:m.length>999?`999+`:m.length},m.length)]},e.id))}),(0,J.jsxs)(`div`,{className:`nav__foot`,children:[(0,J.jsxs)(`span`,{className:`hero__live${x===`off`?``:` is-on`}${x===`ws`?` is-ws`:x===`sse`?` is-sse`:``}`,title:`Live transport: WebSocket (preferred) or SSE fallback`,children:[(0,J.jsx)(`span`,{className:`dot`}),x===`off`?`offline`:`live · ${x}`]}),(0,J.jsx)(`small`,{className:`muted`,children:n?`${wc(n.total)} events · ${n.transport}`:`connecting…`})]})]}),(0,J.jsxs)(`main`,{className:`main`,"data-view":N,children:[(0,J.jsxs)(`header`,{className:`topline reveal`,children:[(0,J.jsxs)(`div`,{className:`topline__txt`,children:[(0,J.jsx)(`h1`,{children:Se.label}),(0,J.jsx)(`small`,{children:Se.sub})]}),(0,J.jsx)(`span`,{className:`topline__spacer`}),N===`overview`&&(0,J.jsx)(`select`,{className:`btn`,value:g,onChange:e=>_(Number(e.target.value)),title:`Stats time window`,children:Oc.map(([e,t])=>(0,J.jsxs)(`option`,{value:t,children:[`window: `,e]},t))}),(0,J.jsxs)(`button`,{className:`help-toggle${I.has(N)?` is-on`:``}`,onClick:()=>ee(N),"aria-expanded":I.has(N),title:`About this page`,children:[(0,J.jsx)(`span`,{className:`help-toggle__q`,"aria-hidden":`true`,children:`?`}),`Help`]})]}),I.has(N)&&(0,J.jsx)(QY,{view:N}),N===`overview`&&(0,J.jsxs)(`section`,{className:`view`,children:[(0,J.jsx)(`div`,{className:`cards reveal`,children:e?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(_c,{k:`Calls (window)`,v:wc(e.total)}),(0,J.jsx)(_c,{k:`Calls / min`,v:e.callsPerMin.toFixed(1)}),(0,J.jsx)(_c,{k:`Error rate`,v:`${(e.errorRate*100).toFixed(1)}%`,sub:`${e.errors} err`,cls:ve}),(0,J.jsx)(_c,{k:`Avg latency`,v:xc(e.latency.avg)}),(0,J.jsx)(_c,{k:`p95 latency`,v:xc(e.latency.p95)}),(0,J.jsx)(_c,{k:`p99 latency`,v:xc(e.latency.p99)}),(0,J.jsx)(_c,{k:`Distinct tools`,v:wc(e.distinctTools)}),(0,J.jsx)(_c,{k:`Output volume`,v:Sc(e.outputBytes)})]}):(0,J.jsxs)(`div`,{className:`stat`,children:[(0,J.jsx)(`p`,{className:`k`,children:`Loading…`}),(0,J.jsx)(`div`,{className:`v`,children:`—`})]})}),(0,J.jsxs)(`div`,{className:`bento reveal`,children:[(0,J.jsx)(gc,{title:`Calls over time`,className:`b-series`,children:e?(0,J.jsx)(zJ,{series:e.series}):(0,J.jsx)(`div`,{className:`muted`,children:`no data`})}),e&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(gc,{title:`By risk`,className:`b-risk`,children:(0,J.jsx)(BJ,{segments:Object.keys(e.byRisk).map(t=>({label:t,value:e.byRisk[t],color:Dc[t]}))})}),(0,J.jsx)(gc,{title:`Top tools`,className:`b-tools`,children:(0,J.jsx)(vc,{rows:e.byTool.map(e=>({label:e.tool,value:e.count,sub:`${e.count}× · ${xc(e.p95Ms)} p95${e.errors?` · ${e.errors} err`:``}`,color:e.errors?`var(--mt-bad)`:void 0}))})}),(0,J.jsx)(gc,{title:`Status`,className:`b-status`,children:(0,J.jsx)(BJ,{centerLabel:`calls`,segments:[{label:`ok`,value:se.ok,color:`#a1a1a1`},{label:`error`,value:se.error,color:`#ff5c5c`}]})}),(0,J.jsx)(gc,{title:`By device`,className:`b-device`,children:e.byDevice.length?(0,J.jsx)(vc,{rows:e.byDevice.map(e=>({label:e.device,value:e.count}))}):(0,J.jsx)(`div`,{className:`muted`,children:`single device`})}),(0,J.jsx)(gc,{title:`Recent errors`,className:`b-errors`,children:oe.length?(0,J.jsx)(`div`,{className:`hbar`,children:oe.slice(0,8).map(e=>(0,J.jsxs)(`div`,{className:`hbar__row conn-errrow`,style:{gridTemplateColumns:`auto 1fr`},onClick:()=>void H(e),children:[(0,J.jsx)(`span`,{className:`muted`,children:Cc(e.ts)}),(0,J.jsxs)(`span`,{style:{color:`var(--mt-bad)`,whiteSpace:`nowrap`,overflow:`hidden`,textOverflow:`ellipsis`,minWidth:0},title:e.error??e.output,children:[e.tool,`: `,e.error??e.output??`error`]})]},e.id))}):(0,J.jsx)(`div`,{className:`muted`,children:`no errors 🎉`})})]})]})]}),N===`devices`&&(i&&i.devices.length>0?(0,J.jsxs)(`section`,{className:`view`,children:[(0,J.jsxs)(`div`,{className:`dev-toolbar reveal`,children:[(0,J.jsx)(`input`,{className:`search`,type:`search`,placeholder:`Search devices by name or address…`,value:te,onChange:e=>R(e.target.value),style:{flex:1,minWidth:180}}),(0,J.jsx)(`div`,{className:`dev-filters`,children:[`all`,`online`,`offline`].map(e=>(0,J.jsx)(`button`,{className:`dev-fbtn${z===e?` is-active`:``}`,onClick:()=>ne(e),children:e===`all`?`All ${B.total}`:e===`online`?`Online ${B.online}`:`Offline ${B.offline}`},e))}),(0,J.jsxs)(`span`,{className:`muted`,children:[V.length,`/`,B.total,` shown`]})]}),(0,J.jsxs)(`details`,{className:`dev-collapse reveal`,open:B.total<=8,children:[(0,J.jsxs)(`summary`,{children:[`Connectivity radar`,(0,J.jsxs)(`span`,{className:`muted`,children:[` `,`· `,B.online,` online · `,B.offline,` offline ·`,` `,B.total,` total`]})]}),(0,J.jsx)(EY,{payload:i,pulses:D})]}),V.length===0?(0,J.jsxs)(`div`,{className:`feed-empty reveal`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🔍`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No devices match`}),(0,J.jsx)(`p`,{className:`feed-empty__sub`,children:`Try a different search or status filter.`})]}):(0,J.jsx)(`div`,{className:`dev-grid-wide reveal`,children:V.map(e=>(0,J.jsx)(DY,{d:e},e.name))}),V.length>0&&(0,J.jsx)(gc,{title:`Device system health`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`CPU · memory · disk · latency · live probe`}),children:(0,J.jsx)(`div`,{className:`health-grid`,children:V.map(e=>(0,J.jsx)(AY,{d:e},e.name))})})]}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🖧`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No devices configured`}),(0,J.jsx)(jc,{type:`secondary`,label:`Tip`,children:`Add a device to your config to see connectivity and system health here.`})]})),N===`clients`&&(0,J.jsx)(XJ,{}),N===`aaa`&&(0,J.jsx)(pl,{}),N===`topology`&&(o&&o.nodes.length>0?(0,J.jsx)(`section`,{className:`view`,children:(0,J.jsx)(gc,{title:`Network topology`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`Layer-2 neighbours via MNDP/CDP/LLDP · click a neighbour to onboard it`}),children:(0,J.jsx)(VY,{topo:o,onOnboard:(e,t)=>{p({name:e,body:t}),d(!0),F(`config`)}})})}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🛰️`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No neighbours discovered yet`}),(0,J.jsx)(`p`,{className:`feed-empty__sub`,children:`Layer-2 neighbours (MNDP / CDP / LLDP) appear here as the device reports them.`})]})),N===`packets`&&(0,J.jsx)(`section`,{className:`view`,children:(0,J.jsx)(gc,{title:`Packet capture`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`live TZSP decode · /tool sniffer streaming`}),children:(0,J.jsx)(LY,{})})}),N===`snapshots`&&(0,J.jsx)(zY,{}),N===`plan`&&(0,J.jsx)(hl,{}),N===`s3`&&(0,J.jsx)(RY,{}),N===`backups`&&(0,J.jsx)(Lc,{}),N===`modules`&&(0,J.jsx)(PY,{}),N===`config`&&(c?(0,J.jsxs)(`section`,{className:`view`,children:[(0,J.jsx)(gc,{title:`Configuration`,className:`reveal`,extra:(0,J.jsx)(`button`,{className:`btn`,onClick:()=>d(e=>!e),title:`Edit the config JSON with autocomplete, validation and safe-apply`,children:u?`View`:`✎ Edit config`}),children:u?(0,J.jsx)(mY,{initial:f?{...c,devices:{...c.devices,[f.name]:f.body}}:c,onClose:()=>{d(!1),p(null)},onReload:()=>{p(null),fc(`/api/config`).then(l).catch(()=>{})}},f?`seed-${f.name}`:`config`):(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`div`,{className:`legend`,style:{margin:`0 0 10px`},children:[(0,J.jsxs)(`span`,{children:[`transport: `,Tc(ye.transport)]}),(0,J.jsxs)(`span`,{children:[`read-only: `,c.readOnly?`yes`:`no`]}),(0,J.jsxs)(`span`,{children:[`dashboard: `,Tc(be.host),`:`,Tc(be.port)]}),(0,J.jsxs)(`span`,{children:[`capture: `,be.captureBody?`on`:`off`]}),(0,J.jsxs)(`span`,{children:[`s3: `,c.s3?`configured`:`off`]})]}),(0,J.jsxs)(`details`,{className:`cfg`,children:[(0,J.jsx)(`summary`,{children:`Full effective configuration (secrets redacted)`}),(0,J.jsx)(uY,{value:c,maxHeight:340})]})]})}),(0,J.jsx)(gc,{title:`Version history`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`point-in-time snapshots · diff & restore`}),children:(0,J.jsx)($J,{onRestored:()=>void fc(`/api/config`).then(l).catch(()=>{})})}),(0,J.jsx)(gc,{title:`Field guide`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`every config option, documented from the schema`}),children:(0,J.jsx)(tY,{})})]}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(Pc,{}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`Loading configuration…`})]})),N===`feed`&&(0,J.jsxs)(`div`,{className:`panel reveal`,children:[(0,J.jsxs)(`div`,{className:`sheet__hd`,style:{marginBottom:12},children:[(0,J.jsx)(`h2`,{style:{margin:0},children:`Live tool calls`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsxs)(`span`,{className:`muted`,children:[ie.length,` shown · `,m.length,` buffered`]})]}),(0,J.jsxs)(`div`,{className:`toolbar`,style:{marginBottom:12},children:[(0,J.jsx)(`div`,{className:`grow`,style:{flex:1,minWidth:180},children:(0,J.jsx)(`input`,{className:`search`,type:`search`,placeholder:`Search tool / input / output / error…`,value:k.q,onChange:e=>A(t=>({...t,q:e.target.value}))})}),xe(`tool`,`all tools`,n?.tools??[]),xe(`risk`,`all risk`,[`READ`,`WRITE`,`WRITE_IDEMPOTENT`,`DESTRUCTIVE`,`DANGEROUS`]),xe(`device`,`all devices`,n?.devices??[]),xe(`status`,`all status`,[`ok`,`error`]),(0,J.jsx)(`button`,{className:`btn${y?` is-active`:``}`,onClick:()=>b(e=>!e),children:y?`▶ Resume`:`⏸ Pause`}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>_e(`csv`),children:`CSV`}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>_e(`json`),children:`JSON`}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>A({tool:``,risk:``,device:``,status:``,q:``}),children:`Clear`}),me&&T.size>0?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`button`,{className:`btn btn-danger`,onClick:()=>void ge(),children:[`✓ Confirm delete (`,T.size,`)`]}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>he(!1),children:`Cancel`})]}):(0,J.jsxs)(`button`,{className:`btn`,disabled:T.size===0,onClick:()=>he(!0),title:`Delete the selected rows`,children:[`🗑 Delete`,T.size>0?` (${T.size})`:``]})]}),ie.length===0?ae?(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🔍`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No calls match your filters`}),(0,J.jsxs)(`p`,{className:`feed-empty__sub`,children:[m.length,` call`,m.length===1?``:`s`,` buffered — try widening the search or the risk / device / status filters.`]}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>A({tool:``,risk:``,device:``,status:``,q:``}),children:`Clear filters`})]}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__pulse${x===`off`?``:` is-on`}`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:x===`off`?`Not connected`:`Listening for tool calls…`}),(0,J.jsx)(`p`,{className:`feed-empty__sub`,children:x===`off`?`The live stream is offline — it will reconnect automatically.`:`Tool calls the LLM makes against this server stream in here in real time.`})]}):(0,J.jsx)(`div`,{className:`feedwrap`,children:(0,J.jsxs)(`table`,{className:`feed`,children:[(0,J.jsx)(`thead`,{children:(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`th`,{style:{width:28},children:(0,J.jsx)(`input`,{type:`checkbox`,"aria-label":`Select all shown rows`,checked:ue,ref:e=>{e&&(e.indeterminate=de)},onChange:pe})}),(0,J.jsx)(`th`,{children:`time`}),(0,J.jsx)(`th`,{children:`tool`}),(0,J.jsx)(`th`,{children:`risk`}),(0,J.jsx)(`th`,{children:`device`}),(0,J.jsx)(`th`,{className:`num`,children:`dur`}),(0,J.jsx)(`th`,{children:`status`}),(0,J.jsx)(`th`,{children:`output`})]})}),(0,J.jsx)(`tbody`,{children:ce.map(e=>(0,J.jsxs)(`tr`,{className:`${e.isError?`is-err`:``}${T.has(e.id)?` is-selected`:``}`.trim()||void 0,onClick:()=>void H(e),children:[(0,J.jsx)(`td`,{onClick:e=>e.stopPropagation(),children:(0,J.jsx)(`input`,{type:`checkbox`,"aria-label":`Select row`,checked:T.has(e.id),onChange:()=>fe(e.id)})}),(0,J.jsx)(`td`,{children:Cc(e.ts)}),(0,J.jsx)(`td`,{children:e.tool}),(0,J.jsx)(`td`,{children:(0,J.jsx)(`span`,{className:`risk risk-${e.risk}`,children:e.risk.replace(`WRITE_IDEMPOTENT`,`WRITE·I`)})}),(0,J.jsx)(`td`,{children:e.device??`—`}),(0,J.jsx)(`td`,{className:`num`,children:xc(e.durationMs)}),(0,J.jsx)(`td`,{children:(0,J.jsx)(`span`,{className:e.isError?`status-err`:`status-ok`,children:e.isError?`error`:`ok`})}),(0,J.jsx)(`td`,{className:`preview`,children:e.isError?e.error??`error`:e.output||`—`})]},e.id))})]})})]})]}),C&&(0,J.jsx)(OY,{event:C,onClose:()=>w(null)})]})}var tX=document.getElementById(`root`);tX&&(0,y.createRoot)(tX).render((0,J.jsx)(eX,{}));
79
+ `).map((e,t)=>(0,J.jsx)(`div`,{className:e.startsWith(`+`)?`d-add`:e.startsWith(`-`)?`d-del`:e.startsWith(`@@`)?`d-hunk`:``,children:e||` `},t))})]})]})}function hY({x:e,y:t,text:n,className:r,textClassName:i,padX:a=9,fontSize:o=9}){let s=(0,v.useRef)(null),[c,l]=(0,v.useState)(()=>n.length*o*.62);(0,v.useLayoutEffect)(()=>{let e=s.current?.getComputedTextLength();e&&e>0&&l(e)},[n,o]);let u=Math.round(c+a*2);return(0,J.jsxs)(`g`,{transform:`translate(${e.toFixed(1)},${t.toFixed(1)})`,children:[(0,J.jsx)(`rect`,{className:r,x:-u/2,y:-9,rx:9,width:u,height:18}),(0,J.jsx)(`text`,{ref:s,className:i,x:0,y:3.5,textAnchor:`middle`,fontSize:o,children:n})]})}function gY(e){return e.reachable===!0?{label:`online`,color:`#d4d4d8`}:e.reachable===!1?{label:`offline`,color:`#f87171`}:{label:`checking…`,color:`#71717a`}}function _Y(e){let t=0;for(let n=0;n<e.length;n++)t=Math.imul(t,31)+e.charCodeAt(n)>>>0;return`hsl(${t%360} 70% 62%)`}function vY(e,t,n,r){let i=1-r;return{x:i*i*e.x+2*i*r*t.x+r*r*n.x,y:i*i*e.y+2*i*r*t.y+r*r*n.y}}function yY(e,t,n,r){let i=1-r,a=2*i*(t.x-e.x)+2*r*(n.x-t.x),o=2*i*(t.y-e.y)+2*r*(n.y-t.y);return Math.atan2(o,a)*180/Math.PI}var bY=`#e4e4e7`,xY=`#d4d4d8`,SY=`#f59e0b`;function CY(e){return e.jumpVia?e.jumpVia:e.jumpHost?`${e.jumpHost.host}:${e.jumpHost.port}`:null}var wY=18,TY=e=>e.length>wY?`${e.slice(0,wY-1)}…`:e,EY=e=>Math.max(23,Math.min(70,e.length*3.1+12));function DY({payload:e,pulses:t}){let n=e.devices,r=Math.max(1,n.length),i=n.map(e=>{let t=TY(e.name);return{d:e,label:t,r:EY(t)}}),a=Math.max(23,...i.map(e=>e.r)),o=r>1?(a+18)/Math.sin(Math.PI/r):0,s=Math.max(110+a,o,120),c=a+60,l=Math.max(700,Math.round((s+a+40)*2)),u=Math.round((s+c)*2),d=l/2,f=u/2,p={x:d,y:f},m=i.map((e,t)=>{let n=t/r*Math.PI*2-Math.PI/2+(r%2==0?Math.PI/r:0);return{...e,i:t,x:d+s*Math.cos(n),y:f+s*Math.sin(n)}});return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`svg`,{className:`conn`,viewBox:`0 0 ${l} ${u}`,width:`100%`,height:u,preserveAspectRatio:`xMidYMid meet`,children:[(0,J.jsxs)(`defs`,{children:[(0,J.jsxs)(`radialGradient`,{id:`conn-hub`,cx:`0.5`,cy:`0.34`,r:`0.75`,children:[(0,J.jsx)(`stop`,{offset:`0`,stopColor:`#fafafa`}),(0,J.jsx)(`stop`,{offset:`0.6`,stopColor:`#d4d4d8`}),(0,J.jsx)(`stop`,{offset:`1`,stopColor:`#a1a1aa`})]}),(0,J.jsxs)(`radialGradient`,{id:`conn-orb`,cx:`0.5`,cy:`0.32`,r:`0.85`,children:[(0,J.jsx)(`stop`,{offset:`0`,stopColor:`#27272a`}),(0,J.jsx)(`stop`,{offset:`1`,stopColor:`#18181b`})]}),(0,J.jsxs)(`radialGradient`,{id:`conn-burst`,cx:`0.5`,cy:`0.5`,r:`0.5`,children:[(0,J.jsx)(`stop`,{offset:`0`,stopColor:`#fafafa`}),(0,J.jsx)(`stop`,{offset:`0.5`,stopColor:`#e4e4e7`}),(0,J.jsx)(`stop`,{offset:`1`,stopColor:`#a1a1aa`,stopOpacity:`0`})]}),(0,J.jsxs)(`linearGradient`,{id:`conn-tunnel-grad`,x1:`0`,y1:`0`,x2:`1`,y2:`0`,children:[(0,J.jsx)(`stop`,{offset:`0`,stopColor:SY,stopOpacity:`0.15`}),(0,J.jsx)(`stop`,{offset:`0.5`,stopColor:SY,stopOpacity:`0.95`}),(0,J.jsx)(`stop`,{offset:`1`,stopColor:SY,stopOpacity:`0.15`})]}),(0,J.jsxs)(`filter`,{id:`conn-tunnel-glow`,x:`-40%`,y:`-40%`,width:`180%`,height:`180%`,children:[(0,J.jsx)(`feGaussianBlur`,{stdDeviation:`3`,result:`b`}),(0,J.jsxs)(`feMerge`,{children:[(0,J.jsx)(`feMergeNode`,{in:`b`}),(0,J.jsx)(`feMergeNode`,{in:`SourceGraphic`})]})]})]}),[.5,.78,1].map((e,t)=>(0,J.jsx)(`circle`,{className:`conn-grid`,cx:d,cy:f,r:s*e},`g-${t}`)),[0,1,2].map(e=>(0,J.jsx)(`circle`,{className:`conn-sonar`,cx:d,cy:f,style:{animationDelay:`${e*1.1}s`}},`s-${e}`)),m.map(({d:e,i:n,x:r,y:i})=>{let a=gY(e.status),o=e.status.reachable===!0,s=e.status.reachable==null,c={x:r,y:i},l=(d+r)/2,u=(f+i)/2,m=r-d,h=i-f,g=Math.hypot(m,h)||1,_=-h/g,v=m/g,y={x:l+_*16,y:u+v*16},b={x:l-_*16,y:u-v*16},x=`M${d},${f} Q${y.x.toFixed(1)},${y.y.toFixed(1)} ${r.toFixed(1)},${i.toFixed(1)}`,S=`M${d},${f} Q${b.x.toFixed(1)},${b.y.toFixed(1)} ${r.toFixed(1)},${i.toFixed(1)}`,C=`M${d},${f} Q${l.toFixed(1)},${u.toFixed(1)} ${r.toFixed(1)},${i.toFixed(1)}`,w=vY(p,y,c,.52),T=yY(p,y,c,.52),E=vY(p,b,c,.48),D=yY(p,b,c,.48)+180,O=t[e.name]??0;return(0,J.jsxs)(`g`,{children:[(0,J.jsx)(`path`,{id:`conn-cmd-${n}`,className:`conn-link`,d:x,stroke:o?bY:a.color,strokeOpacity:o?.5:.32,strokeDasharray:s?`2 8`:o?void 0:`6 7`}),(0,J.jsx)(`path`,{id:`conn-res-${n}`,className:`conn-link`,d:S,stroke:o?xY:a.color,strokeOpacity:o?.5:.18,strokeDasharray:o?void 0:`6 7`}),o&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{className:`conn-flow`,d:x,stroke:`#e4e4e7`}),(0,J.jsx)(`circle`,{className:`conn-packet`,r:3.2,fill:`#e4e4e7`,children:(0,J.jsx)(`animateMotion`,{dur:`2.6s`,repeatCount:`indefinite`,calcMode:`linear`,children:(0,J.jsx)(`mpath`,{href:`#conn-cmd-${n}`})})}),(0,J.jsx)(`rect`,{className:`conn-packet`,x:-2.6,y:-2.6,width:5.2,height:5.2,fill:`#d4d4d8`,transform:`rotate(45)`,children:(0,J.jsx)(`animateMotion`,{dur:`2.6s`,begin:`0.9s`,repeatCount:`indefinite`,calcMode:`linear`,keyPoints:`1;0`,keyTimes:`0;1`,children:(0,J.jsx)(`mpath`,{href:`#conn-res-${n}`})})}),(0,J.jsx)(`path`,{className:`conn-chevron`,d:`M-4,-3 L4,0 L-4,3`,stroke:`#e4e4e7`,transform:`translate(${w.x.toFixed(1)},${w.y.toFixed(1)}) rotate(${T.toFixed(1)})`}),(0,J.jsx)(`path`,{className:`conn-chevron`,d:`M-4,-3 L4,0 L-4,3`,stroke:`#d4d4d8`,transform:`translate(${E.x.toFixed(1)},${E.y.toFixed(1)}) rotate(${D.toFixed(1)})`})]}),O>0&&(0,J.jsx)(`g`,{children:(0,J.jsxs)(`circle`,{r:6,fill:`url(#conn-burst)`,children:[(0,J.jsx)(`animateMotion`,{dur:`1.1s`,repeatCount:`1`,calcMode:`linear`,keyPoints:`0;1;0`,keyTimes:`0;0.5;1`,path:C}),(0,J.jsx)(`animate`,{attributeName:`opacity`,values:`0;1;1;0`,keyTimes:`0;0.1;0.85;1`,dur:`1.1s`,repeatCount:`1`,fill:`freeze`})]})},`burst-${e.name}-${O}`)]},`l-${e.name}`)}),m.map(e=>{let t=e.d.jumpVia,n=t?m.find(e=>e.d.name===t):void 0,r=!n&&e.d.jumpHost?e.d.jumpHost:void 0;if(!n&&!r)return null;let i={x:e.x,y:e.y},a=Math.hypot(e.x-d,e.y-f)||1,o=(e.x-d)/a,s=(e.y-f)/a,c=n?{x:n.x,y:n.y}:{x:e.x+o*(e.r+46),y:e.y+s*(e.r+46)},l=(c.x+i.x)/2,u=(c.y+i.y)/2,p=Math.hypot(l-d,u-f)||1,h=n?50:16,g={x:l+(l-d)/p*h,y:u+(u-f)/p*h},_=`M${c.x.toFixed(1)},${c.y.toFixed(1)} Q${g.x.toFixed(1)},${g.y.toFixed(1)} ${i.x.toFixed(1)},${i.y.toFixed(1)}`,v=CY(e.d)??``,y=vY(c,g,i,.5),b=`conn-tunnel-${e.i}`;return(0,J.jsxs)(`g`,{className:`conn-tunnel-g`,children:[(0,J.jsx)(`path`,{className:`conn-tunnel-halo`,d:_,stroke:SY}),(0,J.jsx)(`path`,{id:b,className:`conn-tunnel`,d:_,stroke:`url(#conn-tunnel-grad)`,filter:`url(#conn-tunnel-glow)`}),r&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{className:`conn-tunnel-sat`,cx:c.x,cy:c.y,r:11,fill:`#1c1917`,stroke:`#f59e0b`}),(0,J.jsx)(`text`,{x:c.x,y:c.y+3.5,textAnchor:`middle`,fontSize:11,children:`🛡️`})]}),(0,J.jsxs)(`text`,{className:`conn-tunnel-lock`,fontSize:13,textAnchor:`middle`,children:[`🔒`,(0,J.jsx)(`animateMotion`,{dur:`2.4s`,repeatCount:`indefinite`,calcMode:`linear`,rotate:`auto`,children:(0,J.jsx)(`mpath`,{href:`#${b}`})})]}),(0,J.jsx)(hY,{x:y.x,y:y.y,text:`⤳ via ${v}`,className:`conn-tunnel-badge`,textClassName:`conn-tunnel-badge-tx`})]},`jump-${e.d.name}`)}),(0,J.jsx)(`circle`,{className:`conn-hub-glow`,cx:d,cy:f,r:42}),(0,J.jsx)(`circle`,{className:`conn-hub-ring`,cx:d,cy:f,r:37}),(0,J.jsx)(`circle`,{cx:d,cy:f,r:29,fill:`url(#conn-hub)`,stroke:`#71717a`,strokeWidth:1.5}),(0,J.jsx)(`text`,{x:d,y:f-4,textAnchor:`middle`,fill:`#09090b`,fontSize:12,fontWeight:700,children:`LLM`}),(0,J.jsx)(`text`,{x:d,y:f+8,textAnchor:`middle`,fill:`#3f3f46`,fontSize:8,fontWeight:600,children:`⇄ MCP`}),(0,J.jsx)(`text`,{x:d,y:f+18,textAnchor:`middle`,fill:`#3f3f46`,fontSize:7.5,fontWeight:600,children:`server`}),m.map(({d:e,x:t,y:n,r,label:i})=>{let a=gY(e.status),o=e.status.reachable===!0,s=o?`${e.status.latencyMs??`?`} ms`:a.label,c=_Y(e.name);return(0,J.jsxs)(`g`,{className:`conn-node`,children:[o&&(0,J.jsx)(`circle`,{className:`conn-node-halo`,cx:t,cy:n,r:r+1,stroke:c}),(0,J.jsx)(`circle`,{cx:t,cy:n,r,fill:`url(#conn-orb)`}),(0,J.jsx)(`circle`,{cx:t,cy:n,r,fill:c,opacity:.16}),(0,J.jsx)(`circle`,{cx:t,cy:n,r,fill:`none`,stroke:c,strokeWidth:2.5}),(0,J.jsx)(`circle`,{className:o?`conn-blink`:void 0,cx:t+r*.7,cy:n-r*.7,r:4.5,fill:a.color,stroke:`#0a121b`,strokeWidth:1.5}),(0,J.jsx)(`text`,{x:t,y:n+3.5,textAnchor:`middle`,fill:`#fafafa`,fontSize:10,fontWeight:600,children:i}),(0,J.jsx)(`text`,{x:t,y:n+r+14,textAnchor:`middle`,fill:`#a1a1aa`,fontSize:9,children:e.address??e.host}),(0,J.jsx)(`text`,{x:t,y:n+r+26,textAnchor:`middle`,fill:a.color,fontSize:9,fontWeight:600,children:s})]},`n-${e.name}`)})]}),(0,J.jsxs)(`div`,{className:`conn-legend`,children:[(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{style:{background:bY}}),` command · LLM → device`]}),(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{style:{background:xY}}),` response · device → LLM`]}),(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{style:{background:`#e4e4e7`}}),` live call (round-trip)`]}),e.devices.some(e=>CY(e))&&(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{style:{background:`#f59e0b`}}),` 🔒 SSH jump tunnel (ProxyJump)`]})]})]})}function OY({d:e}){let t=gY(e.status),n=e.status.reachable===!0?`${t.label} · ${e.status.latencyMs??`?`}ms${e.status.version?` · v${e.status.version}`:``}`:e.status.reachable===!1?`${t.label}${e.status.error?` · ${e.status.error}`:``}`:t.label,r=_Y(e.name);return(0,J.jsxs)(`div`,{className:`card dev-card`,style:{borderLeft:`3px solid ${r}`},children:[(0,J.jsxs)(`div`,{className:`dev-card__top`,children:[(0,J.jsx)(`span`,{className:`dot`,style:{background:r},title:`device colour`}),(0,J.jsx)(`span`,{className:`dev-card__name`,children:e.name}),e.isDefault&&(0,J.jsx)(Mc,{type:`accent`,children:`default`}),(0,J.jsx)(`span`,{className:`dot dot--status`,style:{background:t.color},title:t.label}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`span`,{className:`chip`,children:e.authMode})]}),(0,J.jsxs)(`div`,{className:`dev-card__meta`,children:[(0,J.jsx)(`span`,{children:e.mac?`mac`:`host`}),(0,J.jsx)(`b`,{children:e.address??`${e.host}:${e.port}`}),(0,J.jsx)(`span`,{children:`user`}),(0,J.jsx)(`b`,{children:e.username}),(0,J.jsx)(`span`,{children:`status`}),(0,J.jsx)(`b`,{style:{color:t.color},children:n}),(0,J.jsx)(`span`,{children:`activity`}),(0,J.jsxs)(`b`,{children:[e.activity.calls,` calls · `,e.activity.errors,` err`,e.activity.avgMs?` · ${xc(e.activity.avgMs)} avg`:``]}),e.description&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`span`,{children:`note`}),(0,J.jsx)(`b`,{children:e.description})]})]}),CY(e)&&(0,J.jsxs)(`div`,{className:`jump-route`,title:`Reached over SSH through the bastion ${CY(e)} (ProxyJump) — no port exposed on ${e.name}.`,children:[(0,J.jsx)(`span`,{className:`jump-route__hop jump-route__hop--src`,title:`MCP server`,children:`🛰️`}),(0,J.jsx)(`span`,{className:`jump-route__wire`}),(0,J.jsxs)(`span`,{className:`jump-route__hop jump-route__hop--bastion`,children:[`🛡️ `,CY(e),e.jumpVia?(0,J.jsx)(`i`,{className:`jump-route__tag`,children:`jump`}):null]}),(0,J.jsx)(`span`,{className:`jump-route__wire jump-route__wire--enc`,children:(0,J.jsx)(`span`,{className:`jump-route__lock`,"aria-hidden":!0,children:`🔒`})}),(0,J.jsxs)(`span`,{className:`jump-route__hop jump-route__hop--dest`,style:{borderColor:r},title:e.name,children:[`📡 `,e.name]})]})]})}function kY({event:e,onClose:t}){let[n,r]=(0,v.useState)(sY);return(0,J.jsx)(`div`,{className:`overlay`,onClick:e=>e.target===e.currentTarget&&t(),children:(0,J.jsxs)(`div`,{className:`sheet`,children:[(0,J.jsxs)(`div`,{className:`sheet__hd`,children:[(0,J.jsx)(`span`,{className:`risk risk-${e.risk}`,children:e.risk}),(0,J.jsxs)(`h3`,{className:`sheet__tool`,children:[e.tool,(0,J.jsx)(bc,{text:e.tool,className:`iconbtn`,icon:!0,title:`Copy tool name`})]}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(Ac,{type:`secondary`,size:`sm`,onClick:t,children:`✕ Close`})]}),(0,J.jsxs)(`div`,{className:`kv__body`,children:[(0,J.jsx)(`div`,{className:`kv__k`,children:`title`}),(0,J.jsx)(`div`,{className:`kv__v`,children:e.title}),(0,J.jsx)(`div`,{className:`kv__k`,children:`time`}),(0,J.jsx)(`div`,{className:`kv__v`,children:new Date(e.ts).toLocaleString(void 0,{hour12:!1})}),(0,J.jsx)(`div`,{className:`kv__k`,children:`device`}),(0,J.jsx)(`div`,{className:`kv__v`,children:e.device??`—`}),(0,J.jsx)(`div`,{className:`kv__k`,children:`transport`}),(0,J.jsx)(`div`,{className:`kv__v`,children:e.transport??`—`}),(0,J.jsx)(`div`,{className:`kv__k`,children:`duration`}),(0,J.jsx)(`div`,{className:`kv__v`,children:xc(e.durationMs)}),(0,J.jsx)(`div`,{className:`kv__k`,children:`status`}),(0,J.jsx)(`div`,{className:`kv__v`,children:(0,J.jsx)(`span`,{className:e.isError?`status-err`:`status-ok`,children:e.isError?`error`:`ok`})}),(0,J.jsx)(`div`,{className:`kv__k`,children:`output size`}),(0,J.jsxs)(`div`,{className:`kv__v`,children:[Sc(e.outputBytes),e.truncated?` (truncated)`:``]}),(0,J.jsx)(`div`,{className:`kv__k`,children:`structured`}),(0,J.jsx)(`div`,{className:`kv__v`,children:e.hasStructured?`yes (renders an MCP App view)`:`no`})]}),e.error&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`h2`,{className:`muted`,children:`ERROR`}),(0,J.jsx)(`pre`,{className:`body`,style:{color:`var(--mt-bad)`},children:e.error})]}),(0,J.jsxs)(`div`,{className:`sheet__hd`,children:[(0,J.jsx)(`h2`,{className:`muted`,style:{margin:0},children:`INPUT`}),(0,J.jsx)(`span`,{style:{flex:1}}),e.input&&(0,J.jsx)(Ac,{type:`secondary`,size:`sm`,ghost:!0,onClick:()=>r(e=>{let t=!e;return cY(t),t}),title:n?`Showing pretty-printed JSON — click for raw`:`Showing raw JSON — click to pretty-print`,children:n?`✦ Pretty`:`{ } Raw`}),(0,J.jsx)(bc,{text:e.input,title:`Copy input JSON`})]}),e.input?(0,J.jsx)(uY,{value:lY(e.input,n)}):(0,J.jsx)(`pre`,{className:`body`,children:`—`}),(0,J.jsxs)(`div`,{className:`sheet__hd`,children:[(0,J.jsx)(`h2`,{className:`muted`,style:{margin:0},children:`OUTPUT`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(bc,{text:e.output,title:`Copy output`})]}),(0,J.jsx)(`pre`,{className:`body ros`,children:e.output?aY(e.output):`—`})]})})}var AY=e=>e==null?`?`:Sc(e);function jY({d:e}){let t=e.status,n=e.history??[];return t.reachable===!0||n.length>0?(0,J.jsxs)(`div`,{className:`card health-card`,children:[(0,J.jsxs)(`div`,{className:`health-card__hd`,children:[(0,J.jsx)(Nc,{color:gY(t).color}),(0,J.jsx)(`span`,{className:`dev-card__name`,children:e.name}),e.isDefault&&(0,J.jsx)(Mc,{type:`accent`,children:`default`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(Mc,{type:t.version?`success`:`default`,children:t.version?`v${t.version}`:`—`})]}),(0,J.jsxs)(`div`,{className:`health-card__sub muted`,children:[t.boardName??`router`,t.architecture?` · ${t.architecture}`:``,t.cpuCount?` · ${t.cpuCount} cpu`:``,t.uptime?` · up ${t.uptime}`:``]}),(0,J.jsxs)(`div`,{className:`health-card__gauges`,children:[(0,J.jsx)(HJ,{value:t.cpuLoad,label:`CPU`,color:Ec.cpu}),(0,J.jsx)(HJ,{value:t.memUsedPct,label:`MEM`,color:Ec.mem}),(0,J.jsx)(HJ,{value:t.hddUsedPct,label:`DISK`,color:Ec.disk})]}),(0,J.jsxs)(`div`,{className:`health-card__charts`,children:[(0,J.jsxs)(`div`,{className:`health-chart`,children:[(0,J.jsx)(`span`,{className:`health-chart__k`,children:`CPU load`}),(0,J.jsx)(VJ,{id:`${e.name}-cpu`,values:n.map(e=>e.cpuLoad),color:Ec.cpu,maxValue:100,unit:`%`})]}),(0,J.jsxs)(`div`,{className:`health-chart`,children:[(0,J.jsx)(`span`,{className:`health-chart__k`,children:`Memory used`}),(0,J.jsx)(VJ,{id:`${e.name}-mem`,values:n.map(e=>e.memUsedPct),color:Ec.mem,maxValue:100,unit:`%`})]}),(0,J.jsxs)(`div`,{className:`health-chart`,children:[(0,J.jsx)(`span`,{className:`health-chart__k`,children:`Probe latency`}),(0,J.jsx)(VJ,{id:`${e.name}-lat`,values:n.map(e=>e.latencyMs),color:Ec.latency,unit:`ms`})]})]}),(0,J.jsxs)(`div`,{className:`health-card__foot muted`,children:[`RAM `,AY(t.totalMemory&&t.freeMemory?t.totalMemory-t.freeMemory:void 0),` /`,` `,AY(t.totalMemory),` · free disk `,AY(t.freeHdd)]})]}):(0,J.jsxs)(`div`,{className:`card health-card health-card--na`,children:[(0,J.jsxs)(`div`,{className:`health-card__hd`,children:[(0,J.jsx)(Nc,{color:gY(t).color}),(0,J.jsx)(`span`,{className:`dev-card__name`,children:e.name}),e.isDefault&&(0,J.jsx)(Mc,{type:`accent`,children:`default`})]}),(0,J.jsx)(`p`,{className:`muted`,style:{margin:0},children:t.reachable===!1?`Offline — ${t.error??`unreachable`}`:e.mac?`Waiting for the first MAC-Telnet probe (these run every few minutes to avoid contending with tool calls)…`:`Waiting for the first health probe…`})]})}function MY(e,t){let n=(0,v.useRef)(e),r=(0,v.useRef)(t);n.current=e,r.current=t,(0,v.useEffect)(()=>{let e=!1,t=null,i=null,a=()=>{e||(i=new EventSource(dc(`/api/sse`)),i.addEventListener(`hello`,()=>r.current(`sse`)),i.addEventListener(`tool`,e=>{try{n.current(JSON.parse(e.data))}catch{}}),i.onerror=()=>{i&&i.readyState===EventSource.CONNECTING&&r.current(`off`)})},o=()=>{if(e)return;let i=location.protocol===`https:`?`wss`:`ws`;t=new WebSocket(dc(`${i}://${location.host}/api/stream`));let s=!1;t.onopen=()=>{s=!0,r.current(`ws`)},t.onerror=()=>t?.close(),t.onmessage=e=>{try{let t=JSON.parse(e.data);t.type===`event`&&t.event&&n.current(t.event)}catch{}},t.onclose=()=>{e||(r.current(`off`),s?setTimeout(o,2e3):a())}};return o(),()=>{e=!0,t?.close(),i?.close()}},[])}function NY(e){(0,v.useLayoutEffect)(()=>{let t=e.current;if(!t||window.matchMedia(`(prefers-reduced-motion: reduce)`).matches)return;document.documentElement.classList.add(`js-motion`);let n=new WeakSet,r=e=>{n.has(e)||(n.add(e),Ri.set(e,{opacity:0,y:26}),q.create({trigger:e,start:`top 90%`,once:!0,onEnter:()=>Ri.to(e,{opacity:1,y:0,duration:.7,ease:`power3.out`})}))},i=e=>{for(let t of e.querySelectorAll(`.reveal`))r(t)};i(t);let a=new MutationObserver(e=>{for(let t of e)for(let e of t.addedNodes)e instanceof Element&&(e.matches(`.reveal`)&&r(e),i(e))});a.observe(t,{childList:!0,subtree:!0});let o=setInterval(()=>q.refresh(),1200),s=setTimeout(()=>clearInterval(o),7e3);return()=>{a.disconnect(),clearInterval(o),clearTimeout(s);for(let e of q.getAll())e.kill();document.documentElement.classList.remove(`js-motion`)}},[e])}function PY({m:e,busy:t,onToggle:n}){return(0,J.jsxs)(`label`,{className:`mod-row`,"data-on":e.enabled?`1`:void 0,title:e.description,children:[(0,J.jsx)(`input`,{type:`checkbox`,checked:e.enabled,disabled:t,onChange:()=>n(e.slug,!e.enabled)}),(0,J.jsxs)(`span`,{className:`mod-row__main`,children:[(0,J.jsxs)(`span`,{className:`mod-row__name`,children:[e.label,(0,J.jsx)(`code`,{className:`mod-row__slug`,children:e.slug})]}),(0,J.jsx)(`span`,{className:`mod-row__desc muted`,children:e.description})]}),(0,J.jsxs)(`span`,{className:`mod-row__count muted`,children:[e.toolCount,` tool`,e.toolCount===1?``:`s`]})]})}function FY(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(new Set),[i,a]=(0,v.useState)(null),[o,s]=(0,v.useState)(``),c=(0,v.useCallback)(()=>{fc(`/api/modules`).then(t).catch(()=>a(`could not load modules`))},[]);(0,v.useEffect)(()=>c(),[c]);let l=e=>t(t=>t?{...t,...e}:e),u=(0,v.useCallback)(async(e,n)=>{r(t=>new Set(t).add(e)),t(t=>t&&{...t,modules:t.modules.map(t=>t.slug===e?{...t,enabled:n}:t)});let i=await pc(`/api/modules/toggle`,{slug:e,enabled:n}).catch(()=>({error:`request failed`}));if(r(t=>{let n=new Set(t);return n.delete(e),n}),i.error||i.ok===!1){a(i.error??`toggle failed`),c();return}l(i);let o=i.persisted?`saved to config`:`applied live (not saved)`,s=i.warning?` ⚠ ${i.warning}`:``;a(`${e} ${n?`enabled`:`disabled`} — ${o}. Reconnect the MCP client (or restart the server) for the tool list to update.${s}`)},[c]),d=(0,v.useCallback)(async(e,t)=>{for(let n of e)await u(n,t)},[u]),f=(0,v.useMemo)(()=>{if(!e)return[];let t=o.trim().toLowerCase(),n=e=>!t||e.slug.toLowerCase().includes(t)||e.label.toLowerCase().includes(t)||e.group.toLowerCase().includes(t)||e.description.toLowerCase().includes(t),r=new Map;for(let t of e.modules){if(!n(t))continue;let e=r.get(t.group)??[];e.push(t),r.set(t.group,e)}return[...r.entries()].map(([e,t])=>({group:e,modules:t}))},[e,o]);if(!e)return(0,J.jsx)(`div`,{className:`muted`,children:`loading modules…`});let p=f.reduce((e,t)=>e+t.modules.length,0);return(0,J.jsx)(`section`,{className:`view`,children:(0,J.jsxs)(gc,{title:`Tool modules`,className:`reveal`,extra:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`span`,{className:`muted`,children:[e.enabledModules,`/`,e.total,` modules · `,e.enabledTools,`/`,e.totalTools,` `,`tools exposed`]}),(0,J.jsx)(`button`,{className:`btn`,onClick:c,style:{marginLeft:10},children:`↻ Refresh`})]}),children:[(0,J.jsxs)(`div`,{className:`legend`,style:{margin:`0 0 10px`},children:[(0,J.jsxs)(`span`,{children:[`writes to: `,(0,J.jsx)(`code`,{children:e.source?.path??`config file`})]}),(0,J.jsx)(`span`,{children:e.hasAllowList?`allow-list active`:`all modules on by default`})]}),(0,J.jsxs)(`p`,{className:`muted`,style:{margin:`0 0 12px`,fontSize:12},children:[`Toggle a module to expose or hide all of its tools. Disabling adds it to`,` `,(0,J.jsx)(`code`,{children:`tools.disabledModules`}),` in your config file; enabling removes it (or adds it to`,` `,(0,J.jsx)(`code`,{children:`tools.enabledModules`}),` when an allow-list is in force). Trimming the surface below ~150–200 tools makes every remaining tool reliably findable by the MCP client. The client must reconnect for changes to take effect.`]}),(0,J.jsxs)(`div`,{className:`mod-toolbar`,children:[(0,J.jsx)(`input`,{className:`input`,placeholder:`Filter modules by name, slug, group or description…`,value:o,onChange:e=>s(e.target.value)}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>void d(e.modules.filter(e=>!e.enabled).map(e=>e.slug),!0),children:`Enable all`}),` `,(0,J.jsx)(`button`,{className:`btn`,onClick:()=>void d(e.modules.filter(e=>e.enabled).map(e=>e.slug),!1),children:`Disable all`})]}),i&&(0,J.jsx)(`div`,{className:`cfg-msg`,style:{marginTop:12},children:i}),p===0?(0,J.jsxs)(`div`,{className:`muted`,style:{padding:12},children:[`No modules match “`,o,`”.`]}):(0,J.jsx)(`div`,{className:`mod-groups`,children:f.map(({group:e,modules:t})=>{let r=t.filter(e=>e.enabled).length,i=t.map(e=>e.slug);return(0,J.jsxs)(`div`,{className:`mod-group`,children:[(0,J.jsxs)(`div`,{className:`mod-group__hd`,children:[(0,J.jsx)(`h3`,{className:`mod-group__title`,children:e}),(0,J.jsxs)(`span`,{className:`muted`,children:[r,`/`,t.length,` on`]}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`button`,{className:`btn btn-sm`,onClick:()=>void d(i.filter(e=>{let n=t.find(t=>t.slug===e);return n?!n.enabled:!1}),!0),children:`Enable group`}),` `,(0,J.jsx)(`button`,{className:`btn btn-sm`,onClick:()=>void d(i.filter(e=>{let n=t.find(t=>t.slug===e);return n?n.enabled:!1}),!1),children:`Disable group`})]}),(0,J.jsx)(`div`,{className:`mod-list`,children:t.map(e=>(0,J.jsx)(PY,{m:e,busy:n.has(e.slug),onToggle:(e,t)=>void u(e,t)},e.slug))})]},e)})})]})})}var IY={TCP:`#e4e4e7`,UDP:`#d4d4d8`,ICMP:`#a1a1aa`,ICMPv6:`#a1a1aa`,ARP:`#e4e4e7`,IPv6:`#a1a1aa`},LY=e=>e&&IY[e]||`#71717a`;function RY(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(!1);(0,v.useEffect)(()=>{let e=()=>void fc(`/api/capture/packets?limit=150`).then(t).catch(()=>{});e();let n=setInterval(e,1500);return()=>clearInterval(n)},[]);let i=e?.stats,a=e?.packets??[],o=async()=>{r(!0),await pc(`/api/capture/stop`,{}).catch(()=>{}),r(!1)};if(!i||!i.running&&i.packets===0)return(0,J.jsxs)(`div`,{className:`cap-idle muted`,children:[`No capture running. Start one with the `,(0,J.jsx)(`code`,{children:`start_packet_capture`}),` tool — point the device's TZSP stream at this host — and decoded packets stream in here live.`]});let s=Math.max(1,...Object.values(i.protocols));return(0,J.jsxs)(`div`,{className:`cap`,children:[(0,J.jsxs)(`div`,{className:`cap-bar`,children:[(0,J.jsx)(`span`,{className:`cap-dot${i.running?` is-on`:``}`}),(0,J.jsx)(`b`,{children:i.running?`capturing`:`stopped`}),(0,J.jsxs)(`span`,{className:`muted`,children:[`UDP `,i.port]}),(0,J.jsxs)(`span`,{className:`muted`,children:[wc(i.packets),` pkts · `,Sc(i.bytes)]}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`a`,{className:`btn`,href:dc(`/api/capture/pcap`),download:`capture.pcap`,children:`⤓ pcap`}),(0,J.jsx)(`button`,{className:`btn btn-danger`,onClick:()=>void o(),disabled:n||!i.running,children:`■ Stop`})]}),(0,J.jsxs)(`div`,{className:`cap-cols`,children:[(0,J.jsxs)(`div`,{className:`cap-side`,children:[(0,J.jsx)(`div`,{className:`cap-h`,children:`Protocols`}),Object.entries(i.protocols).map(([e,t])=>(0,J.jsxs)(`div`,{className:`cap-pbar`,children:[(0,J.jsx)(`span`,{className:`cap-plabel`,style:{color:LY(e)},children:e}),(0,J.jsx)(`span`,{className:`cap-ptrack`,children:(0,J.jsx)(`i`,{style:{width:`${t/s*100}%`,background:LY(e)}})}),(0,J.jsx)(`span`,{className:`cap-pn`,children:t})]},e)),(0,J.jsx)(`div`,{className:`cap-h`,style:{marginTop:12},children:`Top talkers`}),i.topTalkers.length===0&&(0,J.jsx)(`div`,{className:`muted`,children:`—`}),i.topTalkers.map(e=>(0,J.jsxs)(`div`,{className:`cap-talker`,children:[(0,J.jsx)(`span`,{children:e.addr}),(0,J.jsx)(`b`,{children:e.count})]},e.addr))]}),(0,J.jsx)(`div`,{className:`cap-list`,children:a.length===0?(0,J.jsx)(`div`,{className:`muted`,style:{padding:10},children:`waiting for packets…`}):a.map((e,t)=>(0,J.jsxs)(`div`,{className:`cap-row`,children:[(0,J.jsx)(`span`,{className:`cap-tt`,children:Cc(e.ts)}),(0,J.jsx)(`span`,{className:`cap-proto`,style:{color:LY(e.protocol)},children:e.protocol??e.ethType}),(0,J.jsx)(`span`,{className:`cap-len`,children:e.len}),(0,J.jsx)(`span`,{className:`cap-info`,children:e.info})]},t))})]})]})}function zY(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(null),[i,a]=(0,v.useState)(null),[o,s]=(0,v.useState)(null),c=(0,v.useCallback)(()=>{fc(`/api/s3/list`).then(t).catch(()=>t({configured:!1,objects:[]}))},[]);(0,v.useEffect)(()=>c(),[c]);let l=e=>{fc(`/api/s3/presign?key=${encodeURIComponent(e)}`).then(e=>{e.url?window.open(e.url,`_blank`,`noopener`):s(`could not generate download link`)}).catch(()=>s(`could not generate download link`))},u=async e=>{a(e);let t=await pc(`/api/s3/delete`,{key:e}).catch(()=>({error:`request failed`}));a(null),r(null),t.ok?(s(`Deleted ${e}`),c()):s(t.error??`delete failed`)};return e?e.configured?(0,J.jsx)(`section`,{className:`view`,children:(0,J.jsxs)(gc,{title:`S3 backups`,className:`reveal`,extra:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`span`,{className:`muted`,children:[e.target,` · `,e.objects.length,` object`,e.objects.length===1?``:`s`,e.truncated?` (truncated)`:``]}),(0,J.jsx)(`button`,{className:`btn`,onClick:c,style:{marginLeft:10},children:`↻ Refresh`})]}),children:[o&&(0,J.jsx)(`div`,{className:`cfg-msg`,children:o}),e.objects.length===0?(0,J.jsxs)(`div`,{className:`muted`,style:{padding:12},children:[`No objects in the bucket. Upload one with the `,(0,J.jsx)(`code`,{children:`upload_backup_to_s3`}),` tool.`]}):(0,J.jsx)(`div`,{className:`feedwrap`,children:(0,J.jsxs)(`table`,{className:`feed`,children:[(0,J.jsx)(`thead`,{children:(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`th`,{children:`key`}),(0,J.jsx)(`th`,{className:`num`,children:`size`}),(0,J.jsx)(`th`,{children:`modified`}),(0,J.jsx)(`th`,{style:{width:200},children:`actions`})]})}),(0,J.jsx)(`tbody`,{children:e.objects.map(e=>(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`td`,{children:e.key}),(0,J.jsx)(`td`,{className:`num`,children:Sc(e.size)}),(0,J.jsx)(`td`,{children:e.lastModified?new Date(e.lastModified).toLocaleString(void 0,{hour12:!1}):`—`}),(0,J.jsxs)(`td`,{onClick:e=>e.stopPropagation(),children:[(0,J.jsx)(`button`,{className:`btn`,onClick:()=>l(e.key),children:`⤓ Download`}),` `,n===e.key?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{className:`btn btn-danger`,disabled:i===e.key,onClick:()=>void u(e.key),children:`✓ Confirm`}),` `,(0,J.jsx)(`button`,{className:`btn`,onClick:()=>r(null),children:`Cancel`})]}):(0,J.jsx)(`button`,{className:`btn`,onClick:()=>r(e.key),children:`🗑 Delete`})]})]},e.key))})]})})]})}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`☁️`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`S3 is not configured`}),(0,J.jsxs)(`p`,{className:`feed-empty__sub`,children:[`Add an `,(0,J.jsx)(`code`,{children:`s3`}),` block (bucket + credentials) to your config to manage backup objects here.`]})]}):(0,J.jsx)(`div`,{className:`muted`,children:`loading S3 objects…`})}function BY(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(``),[i,a]=(0,v.useState)(``),[o,s]=(0,v.useState)(null),[c,l]=(0,v.useState)(null),u=(0,v.useCallback)(()=>{fc(`/api/snapshots`).then(e=>t(e.snapshots)).catch(()=>t([]))},[]);(0,v.useEffect)(()=>u(),[u]);let d=e=>{fc(`/api/snapshot/${encodeURIComponent(e)}`).then(s).catch(()=>{})},f=()=>{!n||!i||pc(`/api/snapshots/diff`,{from:n,to:i}).then(l).catch(()=>{})};if(!e)return(0,J.jsx)(`div`,{className:`muted`,children:`loading snapshots…`});if(e.length===0)return(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🕰️`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No config snapshots yet`}),(0,J.jsxs)(`p`,{className:`feed-empty__sub`,children:[`Capture one with the `,(0,J.jsx)(`code`,{children:`capture_config_snapshot`}),` tool — then time-travel diff any two here.`]})]});let p=e.map(e=>(0,J.jsxs)(`option`,{value:e.id,children:[e.device,` · `,e.label??e.id,` · `,Cc(e.ts)]},e.id));return(0,J.jsxs)(`section`,{className:`view`,children:[(0,J.jsxs)(gc,{title:`Config snapshots`,className:`reveal`,extra:(0,J.jsx)(`button`,{className:`btn`,onClick:u,children:`↻ Refresh`}),children:[(0,J.jsxs)(`div`,{className:`toolbar`,style:{marginBottom:12},children:[(0,J.jsxs)(`select`,{className:`btn`,value:n,onChange:e=>r(e.target.value),children:[(0,J.jsx)(`option`,{value:``,children:`diff from…`}),p]}),(0,J.jsxs)(`select`,{className:`btn`,value:i,onChange:e=>a(e.target.value),children:[(0,J.jsx)(`option`,{value:``,children:`to…`}),p]}),(0,J.jsx)(`button`,{className:`btn is-active`,onClick:f,disabled:!n||!i,children:`Diff →`}),(0,J.jsxs)(`span`,{className:`muted`,children:[e.length,` snapshots`]})]}),(0,J.jsx)(`div`,{className:`feedwrap`,children:(0,J.jsxs)(`table`,{className:`feed`,children:[(0,J.jsx)(`thead`,{children:(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`th`,{children:`captured`}),(0,J.jsx)(`th`,{children:`device`}),(0,J.jsx)(`th`,{children:`label`}),(0,J.jsx)(`th`,{children:`version`}),(0,J.jsx)(`th`,{className:`num`,children:`lines`}),(0,J.jsx)(`th`,{className:`num`,children:`size`}),(0,J.jsx)(`th`,{children:`output`})]})}),(0,J.jsx)(`tbody`,{children:e.map(e=>(0,J.jsxs)(`tr`,{className:o?.id===e.id?`is-selected`:void 0,onClick:()=>d(e.id),children:[(0,J.jsx)(`td`,{children:Cc(e.ts)}),(0,J.jsx)(`td`,{children:e.device}),(0,J.jsx)(`td`,{children:e.label??`—`}),(0,J.jsx)(`td`,{children:e.rosVersion??`—`}),(0,J.jsx)(`td`,{className:`num`,children:e.lines}),(0,J.jsx)(`td`,{className:`num`,children:Sc(e.bytes)}),(0,J.jsx)(`td`,{className:`preview`,children:`view export →`})]},e.id))})]})})]}),c&&(0,J.jsx)(gc,{title:`Time-travel diff`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:c.summary.changed?`+${c.summary.added} / -${c.summary.removed}`:`identical`}),children:(0,J.jsx)(`pre`,{className:`cfg-diff`,children:(c.unified||`(identical)`).split(`
80
+ `).map((e,t)=>(0,J.jsx)(`div`,{className:e.startsWith(`+`)?`d-add`:e.startsWith(`-`)?`d-del`:e.startsWith(`@@`)?`d-hunk`:``,children:e||` `},t))})}),o&&(0,J.jsx)(gc,{title:`Snapshot · ${o.label??o.id}`,className:`reveal`,extra:(0,J.jsx)(Ac,{type:`secondary`,size:`sm`,onClick:()=>s(null),children:`✕ Close`}),children:(0,J.jsx)(`pre`,{className:`body`,style:{maxHeight:460},children:o.body||`(empty)`})})]})}function VY(e){return e==null?`#3f3f46`:e>=85?`#f87171`:e>=60?`#a1a1aa`:`#d4d4d8`}function HY({topo:e,onOnboard:t}){let[n,r]=(0,v.useState)(null),i=e.nodes.filter(e=>e.kind===`device`),a=e.nodes.filter(e=>e.kind===`neighbor`),o=Math.max(1,i.length),s=i.length<=1?0:Math.min(150,76+o*8),c=s+(i.length<=1?180:140),l=Math.max(360,Math.round((c+78)*2)),u=l/2,d=new Map,f=new Map;i.forEach((e,t)=>{if(i.length===1){d.set(e.id,{x:380,y:u}),f.set(e.id,-Math.PI/2);return}let n=t/o*Math.PI*2-Math.PI/2;f.set(e.id,n),d.set(e.id,{x:380+s*Math.cos(n),y:u+s*Math.sin(n)})});let p=new Map,m=new Set(a.map(e=>e.id));for(let t of e.edges)m.has(t.to)&&!p.has(t.to)&&p.set(t.to,t.from);let h=new Map;for(let e of a){let t=p.get(e.id)??i[0]?.id??``;h.set(t,[...h.get(t)??[],e.id])}if(i.length<=1)a.forEach((e,t)=>{let n=t/Math.max(1,a.length)*Math.PI*2-Math.PI/2;d.set(e.id,{x:380+c*Math.cos(n),y:u+c*Math.sin(n)})});else for(let[e,t]of h){let n=f.get(e)??-Math.PI/2,r=Math.min(Math.PI/2.2,.32*t.length);t.forEach((e,i)=>{let a=t.length===1?n:n-r/2+r*i/(t.length-1);d.set(e,{x:380+c*Math.cos(a),y:u+c*Math.sin(a)})})}let g=new Map(e.nodes.map(e=>[e.id,e])),_=n?g.get(n):null;return(0,J.jsxs)(`div`,{className:`topo`,children:[(0,J.jsxs)(`svg`,{viewBox:`0 0 760 ${l}`,width:`100%`,height:Math.min(l,540),preserveAspectRatio:`xMidYMid meet`,children:[e.edges.map((e,t)=>{let n=d.get(e.from),r=d.get(e.to);return!n||!r?null:(0,J.jsx)(`line`,{className:`topo-edge${m.has(e.to)?` is-dashed`:``}`,x1:n.x,y1:n.y,x2:r.x,y2:r.y,children:(0,J.jsxs)(`title`,{children:[e.from,` → `,e.to,e.interface?` (${e.interface})`:``]})},`e-${t}`)}),e.nodes.map(e=>{let t=d.get(e.id);if(!t)return null;let i=e.kind===`device`,a=i?132:108,o=i?50:38,s=t.x-a/2,c=t.y-o/2,l=e.reachable===!0?`#d4d4d8`:e.reachable===!1?`#f87171`:i?`#71717a`:`#e4e4e7`,u=n===e.id;return(0,J.jsxs)(`g`,{className:`topo-node${i?` is-device`:` is-neighbor`}${e.onboardable?` is-onboard`:``}${u?` is-picked`:``}`,transform:`translate(${s},${c})`,onClick:()=>r(t=>t===e.id?null:e.id),children:[(0,J.jsx)(`rect`,{width:a,height:o,rx:9,style:{stroke:l}}),(0,J.jsx)(`text`,{className:`topo-label`,x:9,y:16,children:(e.label||e.id).slice(0,16)}),i?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`text`,{className:`topo-sub`,x:9,y:30,children:(e.board||e.ip||``).slice(0,18)}),(0,J.jsx)(`rect`,{className:`topo-bar-bg`,x:9,y:37,width:a-18,height:4,rx:2}),(0,J.jsx)(`rect`,{x:9,y:37,width:(a-18)*Math.min(100,e.cpuLoad??0)/100,height:4,rx:2,style:{fill:VY(e.cpuLoad)}}),(0,J.jsx)(`rect`,{className:`topo-bar-bg`,x:9,y:43,width:a-18,height:4,rx:2}),(0,J.jsx)(`rect`,{x:9,y:43,width:(a-18)*Math.min(100,e.memUsedPct??0)/100,height:4,rx:2,style:{fill:VY(e.memUsedPct)}})]}):(0,J.jsx)(`text`,{className:`topo-sub`,x:9,y:29,children:e.onboardable?`+ onboard`:e.ip||e.mac||``})]},e.id)})]}),(0,J.jsxs)(`div`,{className:`topo-foot`,children:[(0,J.jsxs)(`span`,{className:`legend`,children:[(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{className:`dot`,style:{background:`#d4d4d8`}}),` online`]}),(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{className:`dot`,style:{background:`#f87171`}}),` offline`]}),(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`i`,{className:`dot`,style:{background:`#e4e4e7`}}),` neighbour`]}),(0,J.jsxs)(`span`,{className:`muted`,children:[e.stats.devices,` devices · `,e.stats.neighbors,` discovered ·`,` `,e.stats.onboardable,` onboardable`]})]}),_&&(0,J.jsxs)(`div`,{className:`topo-pop`,children:[(0,J.jsxs)(`div`,{className:`topo-pop__hd`,children:[(0,J.jsx)(`strong`,{children:_.label}),(0,J.jsx)(`span`,{className:`muted`,children:[_.board,_.version,_.mac].filter(Boolean).join(` · `)||`no details advertised`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsx)(`button`,{className:`topo-btn`,onClick:()=>r(null),children:`✕`})]}),_.suggestedConfig?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`div`,{className:`muted`,style:{margin:`2px 0 6px`},children:`Not managed yet — add this to your device config to onboard it:`}),(0,J.jsx)(`pre`,{className:`topo-stub`,children:JSON.stringify({[_.suggestedConfig.name]:UY(_.suggestedConfig)},null,2)}),(0,J.jsx)(bc,{className:`topo-btn`,title:`Copy config stub`,label:`Copy config stub`,text:JSON.stringify({[_.suggestedConfig.name]:UY(_.suggestedConfig)},null,2)}),t&&(0,J.jsx)(`button`,{className:`topo-btn cfg-save`,onClick:()=>t(_.suggestedConfig.name,UY(_.suggestedConfig)),children:`Add to config →`})]}):(0,J.jsxs)(`div`,{className:`muted`,children:[`Managed device`,_.ip?` · ${_.ip}`:``,_.uptime?` · up ${_.uptime}`:``]})]})]})]})}function UY(e){let t={port:e.port,username:e.username};return e.host&&(t.host=e.host),e.mac&&(t.mac=e.mac),t}Ri.registerPlugin(q);function WY(e,t,n){let r=URL.createObjectURL(new Blob([t],{type:`${n};charset=utf-8`})),i=document.createElement(`a`);i.href=r,i.download=e,document.body.append(i),i.click(),i.remove(),URL.revokeObjectURL(r)}var GY=[{id:`overview`,label:`Overview`,sub:`Calls, latency & risk at a glance`},{id:`devices`,label:`Devices`,sub:`Connectivity radar & system health`},{id:`clients`,label:`Clients`,sub:`Connected LAN devices — usage, block/allow, pin IP`},{id:`aaa`,label:`RADIUS & UM`,sub:`RADIUS client & User Manager RADIUS server`},{id:`topology`,label:`Topology`,sub:`Layer-2 neighbours via MNDP / CDP / LLDP`},{id:`packets`,label:`Packets`,sub:`Live TZSP capture & decode`},{id:`snapshots`,label:`Snapshots`,sub:`Config history & time-travel diff`},{id:`plan`,label:`Change Plan`,sub:`Dry-run intended RouterOS commands`},{id:`s3`,label:`S3 Backups`,sub:`List, download & delete S3 backup objects`},{id:`backups`,label:`Backups`,sub:`Local config vault — create, restore, manage`},{id:`modules`,label:`Modules`,sub:`Enable/disable tool modules — curate the surface`},{id:`config`,label:`Config`,sub:`Effective configuration & safe editor`},{id:`feed`,label:`Live Feed`,sub:`Every tool call, in real time`}],KY=new Set(GY.map(e=>e.id)),qY=`mt-view`;function JY(){try{let e=location.hash.replace(/^#\/?/,``);return KY.has(e)?e:null}catch{return null}}function YY(){let e=JY();if(e)return e;try{let e=localStorage.getItem(qY);if(e&&KY.has(e))return e}catch{}return`overview`}var XY=[`#ededed`,`#a1a1a1`],ZY={overview:XY,devices:XY,clients:XY,aaa:XY,topology:XY,packets:XY,snapshots:XY,plan:XY,s3:XY,backups:XY,modules:XY,config:XY,feed:XY},QY={overview:{what:`A live pulse of all MCP tool activity: total calls, error rate, p50/p95 latency, the busiest tools, and a risk breakdown — over a time window you choose.`,tips:[`Change the time window (top-right) to zoom from the last 5 minutes out to 24 hours.`,`The risk donut splits calls by annotation: read · write · destructive · dangerous.`,`A rising error line usually points at one device or one tool — jump to Live Feed to see which.`]},devices:{what:`Every configured router with its live reachability (SSH or MAC-Telnet), latency, identity, and system health — CPU, memory and disk — refreshed continuously.`,tips:[`Each device gets a stable colour so you can track it across the connectivity radar.`,`Health (CPU/Mem/Disk) is probed periodically; MAC-Telnet devices are probed on a slower cadence.`,`Latency tiers are colour-coded green → amber → red; a grey node is currently unreachable.`]},clients:{what:`The LAN devices connected to a router — merged from its DHCP leases and ARP table — with live Download/Upload charts, and one-click controls to block/allow a device, pin (reserve) its IP, change that IP, or relabel it.`,tips:[`Pick the router (top-right) to inspect its connected devices; filter by IP, MAC or name.`,`Click a device to open its live ↓/↑ traffic chart — needs a simple queue targeting its IP.`,`Block/allow is enforced by MAC, so it survives the device changing IP; “Pin IP” makes its lease static.`]},aaa:{what:"Full management of the router's RADIUS client (`/radius`) and the built-in User Manager RADIUS server (`/user-manager`): RADIUS servers + incoming CoA, and User Manager users, service profiles, rate/quota limitations, NAS clients, profile assignments, accounting sessions, and global settings.",tips:[`Pick the router (top-right), then switch tabs across RADIUS, Users, Profiles, Limitations, NAS, Assignments, Sessions and Settings.`,`Every tab is full CRUD: add, edit, enable/disable and remove — secrets are write-only and shown redacted.`,`The Usage & Heatmap tab shows each user's 3-month download/upload and a GitHub-style connection heatmap, persisted locally.`,`If a device lacks the user-manager package, the User Manager tabs explain how to install it; RADIUS-client tabs still work.`]},topology:{what:`A Layer-2 map of neighbours each router discovers via MNDP / CDP / LLDP — the physical adjacency of your network, drawn live.`,tips:[`Solid nodes are configured devices; faint nodes are discovered-but-unmanaged neighbours.`,`Use “Add to config →” on an unmanaged neighbour to pre-fill it in the Config editor.`,`Drag to pan; the layout settles automatically as new neighbours arrive.`]},packets:{what:`Live packet capture streamed from a router over TZSP — decode headers in real time without leaving the dashboard.`,tips:[`Pick a device and start the capture; packets decode as they arrive.`,`Stop the capture when done — it frees the router-side sniffer.`,`Great for debugging a protocol issue alongside the Live Feed of tool calls.`]},snapshots:{what:`Point-in-time captures of a device’s full configuration (/export), stored locally so you can diff any two and see exactly what changed.`,tips:[`Capture a snapshot before a risky change, then diff after to audit the delta.`,`The diff is line-level: green added, red removed.`,`Snapshots are device config exports — for the dashboard’s OWN config history see the Config page.`]},plan:{what:`Dry-run the exact RouterOS commands a change would run before it touches a device — a change plan you can review and trust.`,tips:[`Paste or build intended commands to see them validated and ordered.`,`Nothing is sent to the device from here — it’s a preview.`,`Pair with Safe Mode (auto-revert) when you do apply for real.`]},s3:{what:`Browse, download, and delete backup objects in your configured S3-compatible bucket — your off-box archive of device backups and exports.`,tips:[`Filter by key prefix to find a device’s backups quickly.`,`Download fetches the object through a presigned URL; delete is permanent.`,`For host-side .rsc backups instead, use the Backups page.`]},backups:{what:`A local config vault on the MCP server: capture a device’s /export as a timestamped .rsc file, then download, upload, rename, restore (via Safe Mode), or delete it.`,tips:[`Restore offers a dry-run (applies then rolls back) before you commit for real.`,`Edit the vault path inline in the header — it’s saved to your config.`,`Filenames are stamped in the device’s local 24-hour clock.`]},modules:{what:"Every tool module in the catalog with a live on/off switch. Toggling one writes your config file's `tools` block (disabledModules / enabledModules) and applies it immediately, so you can curate exactly which scopes the MCP server exposes.",tips:[`MCP clients search-rank tools and degrade past ~100; trim the surface below ~150–200 tools so every remaining tool is reliably findable.`,`Disable adds the module to tools.disabledModules; enable removes it (or adds it to an active allow-list) — your config file is updated live on each toggle.`,`Changes need an MCP client reconnect (or a server restart) to actually shrink/grow the visible tool list.`]},config:{what:`View the effective configuration, edit it safely with schema-aware validation and auto-rollback, browse a full field guide, and travel through config version history.`,tips:[`Every successful apply is auto-saved to the version timeline — restore any point in time.`,`Save a named checkpoint before a big change for an easy, labelled rollback.`,`The Field Guide documents every config option, its type, and default — straight from the schema.`]},feed:{what:`Every tool call as it happens — tool, device, risk, duration, and success/error — with full request/response detail on click.`,tips:[`Filter by status to isolate failures, or by tool/device to follow one thread.`,`Click any row to open the full (secret-redacted) request and response.`,`Pause the stream when you want to inspect without rows shifting under you.`]}};function $Y({view:e}){let t=QY[e];return(0,J.jsxs)(`div`,{className:`pagehelp reveal`,role:`region`,"aria-label":`Page help`,children:[(0,J.jsx)(`div`,{className:`pagehelp__icon`,"aria-hidden":`true`,children:`?`}),(0,J.jsxs)(`div`,{className:`pagehelp__body`,children:[(0,J.jsx)(`p`,{className:`pagehelp__what`,children:t.what}),(0,J.jsx)(`ul`,{className:`pagehelp__tips`,children:t.tips.map((e,t)=>(0,J.jsx)(`li`,{children:e},t))})]})]})}function eX({name:e}){return(0,J.jsx)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.7`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:{overview:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`rect`,{x:`3`,y:`3`,width:`8`,height:`8`,rx:`1.6`}),(0,J.jsx)(`rect`,{x:`13`,y:`3`,width:`8`,height:`5`,rx:`1.6`}),(0,J.jsx)(`rect`,{x:`13`,y:`10`,width:`8`,height:`11`,rx:`1.6`}),(0,J.jsx)(`rect`,{x:`3`,y:`13`,width:`8`,height:`8`,rx:`1.6`})]}),devices:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`rect`,{x:`3`,y:`4`,width:`18`,height:`7`,rx:`2`}),(0,J.jsx)(`rect`,{x:`3`,y:`13`,width:`18`,height:`7`,rx:`2`}),(0,J.jsx)(`path`,{d:`M7 7.5h.01M7 16.5h.01`})]}),clients:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{cx:`9`,cy:`8`,r:`3`}),(0,J.jsx)(`path`,{d:`M3.5 19a5.5 5.5 0 0 1 11 0`}),(0,J.jsx)(`path`,{d:`M16 7.5a2.5 2.5 0 0 1 0 5M17.5 19a4.5 4.5 0 0 0-2-3.6`})]}),aaa:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{d:`M12 3 4 6v5c0 4.4 3.2 7.6 8 9 4.8-1.4 8-4.6 8-9V6l-8-3Z`}),(0,J.jsx)(`path`,{d:`M9.5 11.5 11 13l3.5-3.5`})]}),topology:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{cx:`12`,cy:`5`,r:`2.4`}),(0,J.jsx)(`circle`,{cx:`5`,cy:`19`,r:`2.4`}),(0,J.jsx)(`circle`,{cx:`19`,cy:`19`,r:`2.4`}),(0,J.jsx)(`path`,{d:`M12 7.4 6.4 16.6M12 7.4 17.6 16.6`})]}),packets:(0,J.jsx)(`path`,{d:`M3 12h4l2-7 4 14 2-7h6`}),snapshots:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{d:`M12 3 3 7.5 12 12 21 7.5 12 3Z`}),(0,J.jsx)(`path`,{d:`M3 12 12 16.5 21 12`}),(0,J.jsx)(`path`,{d:`M3 16.5 12 21 21 16.5`})]}),plan:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{cx:`6`,cy:`6`,r:`2.3`}),(0,J.jsx)(`circle`,{cx:`6`,cy:`18`,r:`2.3`}),(0,J.jsx)(`circle`,{cx:`18`,cy:`8`,r:`2.3`}),(0,J.jsx)(`path`,{d:`M6 8.3v7.4M8.3 6H13a3 3 0 0 1 3 3v0`})]}),s3:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`ellipse`,{cx:`12`,cy:`6`,rx:`7`,ry:`2.6`}),(0,J.jsx)(`path`,{d:`M5 6v12c0 1.5 3.1 2.6 7 2.6s7-1.1 7-2.6V6`}),(0,J.jsx)(`path`,{d:`M5 12c0 1.5 3.1 2.6 7 2.6s7-1.1 7-2.6`})]}),backups:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{d:`M3 6.5 5 3.5h14l2 3`}),(0,J.jsx)(`rect`,{x:`3`,y:`6.5`,width:`18`,height:`14`,rx:`2`}),(0,J.jsx)(`path`,{d:`M9.5 12h5`})]}),modules:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`rect`,{x:`3`,y:`5`,width:`18`,height:`6`,rx:`3`}),(0,J.jsx)(`circle`,{cx:`8`,cy:`8`,r:`1.5`}),(0,J.jsx)(`rect`,{x:`3`,y:`13`,width:`18`,height:`6`,rx:`3`}),(0,J.jsx)(`circle`,{cx:`16`,cy:`16`,r:`1.5`})]}),config:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{d:`M4 7h8M16 7h4M4 17h4M12 17h8`}),(0,J.jsx)(`circle`,{cx:`14`,cy:`7`,r:`2.2`}),(0,J.jsx)(`circle`,{cx:`10`,cy:`17`,r:`2.2`})]}),feed:(0,J.jsx)(`path`,{d:`M4 6h16M4 12h16M4 18h10`})}[e]})}function tX(){let[e,t]=(0,v.useState)(null),[n,r]=(0,v.useState)(null),[i,a]=(0,v.useState)(null),[o,s]=(0,v.useState)(null),[c,l]=(0,v.useState)(null),[u,d]=(0,v.useState)(!1),[f,p]=(0,v.useState)(null),[m,h]=(0,v.useState)([]),[g,_]=(0,v.useState)(36e5),[y,b]=(0,v.useState)(!1),[x,S]=(0,v.useState)(`off`),[C,w]=(0,v.useState)(null),[T,E]=(0,v.useState)(()=>new Set),[D,O]=(0,v.useState)({}),[k,A]=(0,v.useState)({tool:``,risk:``,device:``,status:``,q:``}),j=(0,v.useRef)(y);j.current=y;let M=(0,v.useRef)(null);NY(M);let[N,P]=(0,v.useState)(YY),F=(0,v.useCallback)(e=>{P(e);try{JY()!==e&&(location.hash=e),localStorage.setItem(qY,e)}catch{}},[]);(0,v.useEffect)(()=>{if(JY()!==N)try{location.hash=N}catch{}let e=()=>{let e=JY();e&&F(e)};return window.addEventListener(`hashchange`,e),()=>window.removeEventListener(`hashchange`,e)},[]);let[I,L]=(0,v.useState)(()=>{try{let e=localStorage.getItem(`mt-help-open`);return new Set(e?JSON.parse(e):[])}catch{return new Set}}),ee=e=>L(t=>{let n=new Set(t);n.has(e)?n.delete(e):n.add(e);try{localStorage.setItem(`mt-help-open`,JSON.stringify([...n]))}catch{}return n}),[te,R]=(0,v.useState)(``),[z,ne]=(0,v.useState)(`all`),B=(0,v.useMemo)(()=>{let e=i?.devices??[];return{online:e.filter(e=>e.status.reachable===!0).length,offline:e.filter(e=>e.status.reachable===!1).length,total:e.length}},[i]),V=(0,v.useMemo)(()=>{let e=i?.devices??[],t=te.trim().toLowerCase();return e.filter(e=>!(z===`online`&&e.status.reachable!==!0||z===`offline`&&e.status.reachable!==!1||t&&!e.name.toLowerCase().includes(t)&&!(e.address??e.host??``).toLowerCase().includes(t)))},[i,te,z]);MY((0,v.useCallback)(e=>{if(j.current)return;h(t=>[e,...t].slice(0,kc));let t=e.device;t&&O(e=>({...e,[t]:(e[t]??0)+1}))},[]),(0,v.useCallback)(e=>S(e),[])),(0,v.useEffect)(()=>{fc(`/api/events?limit=${kc}`).then(e=>h(e.events)).catch(()=>{})},[]);let re=(0,v.useCallback)(()=>{fc(`/api/stats?window=${g}&buckets=60`).then(t).catch(()=>{})},[g]);(0,v.useEffect)(()=>{re();let e=()=>{re(),fc(`/api/meta`).then(r).catch(()=>{}),fc(`/api/devices`).then(a).catch(()=>{}),fc(`/api/topology`).then(s).catch(()=>{})};e();let t=setInterval(()=>{j.current||e()},4e3);return()=>clearInterval(t)},[re]),(0,v.useEffect)(()=>{let e=()=>void fc(`/api/config`).then(l).catch(()=>{});e();let t=setInterval(e,3e4);return()=>clearInterval(t)},[]),(0,v.useEffect)(()=>{let e=e=>{e.key===`Escape`&&w(null)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]);let ie=(0,v.useMemo)(()=>{let e=k.q.trim().toLowerCase();return m.filter(t=>!(k.tool&&t.tool!==k.tool||k.risk&&t.risk!==k.risk||k.device&&t.device!==k.device||k.status===`ok`&&t.isError||k.status===`error`&&!t.isError||e&&!t.tool.toLowerCase().includes(e)&&!t.input.toLowerCase().includes(e)&&!t.output.toLowerCase().includes(e)&&!(t.error??``).toLowerCase().includes(e))).sort((e,t)=>t.ts-e.ts)},[m,k]),ae=!!(k.tool||k.risk||k.device||k.status||k.q),oe=(0,v.useMemo)(()=>m.filter(e=>e.isError),[m]),se=(0,v.useMemo)(()=>({ok:m.length-oe.length,error:oe.length}),[m,oe]),H=(0,v.useCallback)(async e=>{try{w(await fc(`/api/event/${encodeURIComponent(e.id)}`))}catch{w(e)}},[]),ce=(0,v.useMemo)(()=>ie.slice(0,200),[ie]),le=(0,v.useMemo)(()=>ce.map(e=>e.id),[ce]),ue=le.length>0&&le.every(e=>T.has(e)),de=!ue&&le.some(e=>T.has(e)),fe=(0,v.useCallback)(e=>{E(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),pe=(0,v.useCallback)(()=>{E(e=>{let t=new Set(e);if(le.length>0&&le.every(e=>t.has(e)))for(let e of le)t.delete(e);else for(let e of le)t.add(e);return t})},[le]),[me,he]=(0,v.useState)(!1),ge=(0,v.useCallback)(async()=>{let e=[...T];if(e.length!==0)try{await mc({ids:e});let t=new Set(e);h(e=>e.filter(e=>!t.has(e.id))),E(new Set)}catch{}finally{he(!1)}},[T]),_e=e=>{if(e===`json`){WY(`mcp-events.json`,JSON.stringify(ie,null,2),`application/json`);return}let t=[`ts`,`tool`,`risk`,`device`,`durationMs`,`isError`,`error`],n=e=>/[",\n]/.test(e)?`"${e.replace(/"/g,`""`)}"`:e,r=ie.map(e=>[new Date(e.ts).toISOString(),e.tool,e.risk,e.device??``,String(e.durationMs),String(e.isError),e.error??``].map(n).join(`,`)).join(`
81
+ `);WY(`mcp-events.csv`,`${t.join(`,`)}\n${r}\n`,`text/csv`)},ve=e?e.errorRate>=.2?`is-bad`:e.errorRate>=.05?`is-warn`:`is-good`:``,ye=c?.mcp??{},be=c?.dashboard??{},xe=(e,t,n)=>(0,J.jsxs)(`select`,{className:`btn`,value:k[e],onChange:t=>A(n=>({...n,[e]:t.target.value})),children:[(0,J.jsx)(`option`,{value:``,children:t}),n.map(e=>(0,J.jsx)(`option`,{value:e,children:e},e))]}),Se=GY.find(e=>e.id===N)??GY[0];return(0,J.jsxs)(`div`,{className:`shell`,ref:M,"data-view":N,style:{"--page-accent":ZY[N][0],"--page-accent-2":ZY[N][1]},children:[(0,J.jsxs)(`aside`,{className:`nav`,children:[(0,J.jsxs)(`div`,{className:`nav__brand`,children:[(0,J.jsx)(`div`,{className:`nav__mark`,children:(0,J.jsx)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,"aria-hidden":`true`,children:(0,J.jsxs)(`g`,{stroke:`#18181b`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,J.jsx)(`path`,{d:`M12 12 L4 5 M12 12 L20 5 M12 12 L12 20`}),(0,J.jsx)(`circle`,{cx:`12`,cy:`12`,r:`3`,fill:`#18181b`,stroke:`none`}),(0,J.jsx)(`circle`,{cx:`4`,cy:`5`,r:`1.9`,fill:`#18181b`,stroke:`none`}),(0,J.jsx)(`circle`,{cx:`20`,cy:`5`,r:`1.9`,fill:`#18181b`,stroke:`none`}),(0,J.jsx)(`circle`,{cx:`12`,cy:`20`,r:`1.9`,fill:`#18181b`,stroke:`none`})]})})}),(0,J.jsxs)(`div`,{className:`nav__brandtext`,children:[(0,J.jsx)(`b`,{children:`MikroTik MCP`}),(0,J.jsx)(`small`,{children:`Observability`})]})]}),(0,J.jsx)(`nav`,{className:`nav__items`,children:GY.map(e=>(0,J.jsxs)(`button`,{className:`nav__item${N===e.id?` is-active`:``}`,onClick:()=>F(e.id),children:[(0,J.jsx)(eX,{name:e.id}),(0,J.jsx)(`span`,{children:e.label}),e.id===`feed`&&m.length>0&&(0,J.jsx)(`span`,{className:`nav__badge`,children:m.length>999?`999+`:m.length},m.length)]},e.id))}),(0,J.jsxs)(`div`,{className:`nav__foot`,children:[(0,J.jsxs)(`span`,{className:`hero__live${x===`off`?``:` is-on`}${x===`ws`?` is-ws`:x===`sse`?` is-sse`:``}`,title:`Live transport: WebSocket (preferred) or SSE fallback`,children:[(0,J.jsx)(`span`,{className:`dot`}),x===`off`?`offline`:`live · ${x}`]}),(0,J.jsx)(`small`,{className:`muted`,children:n?`${wc(n.total)} events · ${n.transport}`:`connecting…`})]})]}),(0,J.jsxs)(`main`,{className:`main`,"data-view":N,children:[(0,J.jsxs)(`header`,{className:`topline reveal`,children:[(0,J.jsxs)(`div`,{className:`topline__txt`,children:[(0,J.jsx)(`h1`,{children:Se.label}),(0,J.jsx)(`small`,{children:Se.sub})]}),(0,J.jsx)(`span`,{className:`topline__spacer`}),N===`overview`&&(0,J.jsx)(`select`,{className:`btn`,value:g,onChange:e=>_(Number(e.target.value)),title:`Stats time window`,children:Oc.map(([e,t])=>(0,J.jsxs)(`option`,{value:t,children:[`window: `,e]},t))}),(0,J.jsxs)(`button`,{className:`help-toggle${I.has(N)?` is-on`:``}`,onClick:()=>ee(N),"aria-expanded":I.has(N),title:`About this page`,children:[(0,J.jsx)(`span`,{className:`help-toggle__q`,"aria-hidden":`true`,children:`?`}),`Help`]})]}),I.has(N)&&(0,J.jsx)($Y,{view:N}),N===`overview`&&(0,J.jsxs)(`section`,{className:`view`,children:[(0,J.jsx)(`div`,{className:`cards reveal`,children:e?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(_c,{k:`Calls (window)`,v:wc(e.total)}),(0,J.jsx)(_c,{k:`Calls / min`,v:e.callsPerMin.toFixed(1)}),(0,J.jsx)(_c,{k:`Error rate`,v:`${(e.errorRate*100).toFixed(1)}%`,sub:`${e.errors} err`,cls:ve}),(0,J.jsx)(_c,{k:`Avg latency`,v:xc(e.latency.avg)}),(0,J.jsx)(_c,{k:`p95 latency`,v:xc(e.latency.p95)}),(0,J.jsx)(_c,{k:`p99 latency`,v:xc(e.latency.p99)}),(0,J.jsx)(_c,{k:`Distinct tools`,v:wc(e.distinctTools)}),(0,J.jsx)(_c,{k:`Output volume`,v:Sc(e.outputBytes)})]}):(0,J.jsxs)(`div`,{className:`stat`,children:[(0,J.jsx)(`p`,{className:`k`,children:`Loading…`}),(0,J.jsx)(`div`,{className:`v`,children:`—`})]})}),(0,J.jsxs)(`div`,{className:`bento reveal`,children:[(0,J.jsx)(gc,{title:`Calls over time`,className:`b-series`,children:e?(0,J.jsx)(zJ,{series:e.series}):(0,J.jsx)(`div`,{className:`muted`,children:`no data`})}),e&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(gc,{title:`By risk`,className:`b-risk`,children:(0,J.jsx)(BJ,{segments:Object.keys(e.byRisk).map(t=>({label:t,value:e.byRisk[t],color:Dc[t]}))})}),(0,J.jsx)(gc,{title:`Top tools`,className:`b-tools`,children:(0,J.jsx)(vc,{rows:e.byTool.map(e=>({label:e.tool,value:e.count,sub:`${e.count}× · ${xc(e.p95Ms)} p95${e.errors?` · ${e.errors} err`:``}`,color:e.errors?`var(--mt-bad)`:void 0}))})}),(0,J.jsx)(gc,{title:`Status`,className:`b-status`,children:(0,J.jsx)(BJ,{centerLabel:`calls`,segments:[{label:`ok`,value:se.ok,color:`#a1a1a1`},{label:`error`,value:se.error,color:`#ff5c5c`}]})}),(0,J.jsx)(gc,{title:`By device`,className:`b-device`,children:e.byDevice.length?(0,J.jsx)(vc,{rows:e.byDevice.map(e=>({label:e.device,value:e.count}))}):(0,J.jsx)(`div`,{className:`muted`,children:`single device`})}),(0,J.jsx)(gc,{title:`Recent errors`,className:`b-errors`,children:oe.length?(0,J.jsx)(`div`,{className:`hbar`,children:oe.slice(0,8).map(e=>(0,J.jsxs)(`div`,{className:`hbar__row conn-errrow`,style:{gridTemplateColumns:`auto 1fr`},onClick:()=>void H(e),children:[(0,J.jsx)(`span`,{className:`muted`,children:Cc(e.ts)}),(0,J.jsxs)(`span`,{style:{color:`var(--mt-bad)`,whiteSpace:`nowrap`,overflow:`hidden`,textOverflow:`ellipsis`,minWidth:0},title:e.error??e.output,children:[e.tool,`: `,e.error??e.output??`error`]})]},e.id))}):(0,J.jsx)(`div`,{className:`muted`,children:`no errors 🎉`})})]})]})]}),N===`devices`&&(i&&i.devices.length>0?(0,J.jsxs)(`section`,{className:`view`,children:[(0,J.jsxs)(`div`,{className:`dev-toolbar reveal`,children:[(0,J.jsx)(`input`,{className:`search`,type:`search`,placeholder:`Search devices by name or address…`,value:te,onChange:e=>R(e.target.value),style:{flex:1,minWidth:180}}),(0,J.jsx)(`div`,{className:`dev-filters`,children:[`all`,`online`,`offline`].map(e=>(0,J.jsx)(`button`,{className:`dev-fbtn${z===e?` is-active`:``}`,onClick:()=>ne(e),children:e===`all`?`All ${B.total}`:e===`online`?`Online ${B.online}`:`Offline ${B.offline}`},e))}),(0,J.jsxs)(`span`,{className:`muted`,children:[V.length,`/`,B.total,` shown`]})]}),(0,J.jsxs)(`details`,{className:`dev-collapse reveal`,open:B.total<=8,children:[(0,J.jsxs)(`summary`,{children:[`Connectivity radar`,(0,J.jsxs)(`span`,{className:`muted`,children:[` `,`· `,B.online,` online · `,B.offline,` offline ·`,` `,B.total,` total`]})]}),(0,J.jsx)(DY,{payload:i,pulses:D})]}),V.length===0?(0,J.jsxs)(`div`,{className:`feed-empty reveal`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🔍`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No devices match`}),(0,J.jsx)(`p`,{className:`feed-empty__sub`,children:`Try a different search or status filter.`})]}):(0,J.jsx)(`div`,{className:`dev-grid-wide reveal`,children:V.map(e=>(0,J.jsx)(OY,{d:e},e.name))}),V.length>0&&(0,J.jsx)(gc,{title:`Device system health`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`CPU · memory · disk · latency · live probe`}),children:(0,J.jsx)(`div`,{className:`health-grid`,children:V.map(e=>(0,J.jsx)(jY,{d:e},e.name))})})]}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🖧`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No devices configured`}),(0,J.jsx)(jc,{type:`secondary`,label:`Tip`,children:`Add a device to your config to see connectivity and system health here.`})]})),N===`clients`&&(0,J.jsx)(XJ,{}),N===`aaa`&&(0,J.jsx)(pl,{}),N===`topology`&&(o&&o.nodes.length>0?(0,J.jsx)(`section`,{className:`view`,children:(0,J.jsx)(gc,{title:`Network topology`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`Layer-2 neighbours via MNDP/CDP/LLDP · click a neighbour to onboard it`}),children:(0,J.jsx)(HY,{topo:o,onOnboard:(e,t)=>{p({name:e,body:t}),d(!0),F(`config`)}})})}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🛰️`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No neighbours discovered yet`}),(0,J.jsx)(`p`,{className:`feed-empty__sub`,children:`Layer-2 neighbours (MNDP / CDP / LLDP) appear here as the device reports them.`})]})),N===`packets`&&(0,J.jsx)(`section`,{className:`view`,children:(0,J.jsx)(gc,{title:`Packet capture`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`live TZSP decode · /tool sniffer streaming`}),children:(0,J.jsx)(RY,{})})}),N===`snapshots`&&(0,J.jsx)(BY,{}),N===`plan`&&(0,J.jsx)(hl,{}),N===`s3`&&(0,J.jsx)(zY,{}),N===`backups`&&(0,J.jsx)(Lc,{}),N===`modules`&&(0,J.jsx)(FY,{}),N===`config`&&(c?(0,J.jsxs)(`section`,{className:`view`,children:[(0,J.jsx)(gc,{title:`Configuration`,className:`reveal`,extra:(0,J.jsx)(`button`,{className:`btn`,onClick:()=>d(e=>!e),title:`Edit the config JSON with autocomplete, validation and safe-apply`,children:u?`View`:`✎ Edit config`}),children:u?(0,J.jsx)(mY,{initial:f?{...c,devices:{...c.devices,[f.name]:f.body}}:c,onClose:()=>{d(!1),p(null)},onReload:()=>{p(null),fc(`/api/config`).then(l).catch(()=>{})}},f?`seed-${f.name}`:`config`):(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`div`,{className:`legend`,style:{margin:`0 0 10px`},children:[(0,J.jsxs)(`span`,{children:[`transport: `,Tc(ye.transport)]}),(0,J.jsxs)(`span`,{children:[`read-only: `,c.readOnly?`yes`:`no`]}),(0,J.jsxs)(`span`,{children:[`dashboard: `,Tc(be.host),`:`,Tc(be.port)]}),(0,J.jsxs)(`span`,{children:[`capture: `,be.captureBody?`on`:`off`]}),(0,J.jsxs)(`span`,{children:[`s3: `,c.s3?`configured`:`off`]})]}),(0,J.jsxs)(`details`,{className:`cfg`,children:[(0,J.jsx)(`summary`,{children:`Full effective configuration (secrets redacted)`}),(0,J.jsx)(uY,{value:c,maxHeight:340})]})]})}),(0,J.jsx)(gc,{title:`Version history`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`point-in-time snapshots · diff & restore`}),children:(0,J.jsx)($J,{onRestored:()=>void fc(`/api/config`).then(l).catch(()=>{})})}),(0,J.jsx)(gc,{title:`Field guide`,className:`reveal`,extra:(0,J.jsx)(`span`,{className:`muted`,children:`every config option, documented from the schema`}),children:(0,J.jsx)(tY,{})})]}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(Pc,{}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`Loading configuration…`})]})),N===`feed`&&(0,J.jsxs)(`div`,{className:`panel reveal`,children:[(0,J.jsxs)(`div`,{className:`sheet__hd`,style:{marginBottom:12},children:[(0,J.jsx)(`h2`,{style:{margin:0},children:`Live tool calls`}),(0,J.jsx)(`span`,{style:{flex:1}}),(0,J.jsxs)(`span`,{className:`muted`,children:[ie.length,` shown · `,m.length,` buffered`]})]}),(0,J.jsxs)(`div`,{className:`toolbar`,style:{marginBottom:12},children:[(0,J.jsx)(`div`,{className:`grow`,style:{flex:1,minWidth:180},children:(0,J.jsx)(`input`,{className:`search`,type:`search`,placeholder:`Search tool / input / output / error…`,value:k.q,onChange:e=>A(t=>({...t,q:e.target.value}))})}),xe(`tool`,`all tools`,n?.tools??[]),xe(`risk`,`all risk`,[`READ`,`WRITE`,`WRITE_IDEMPOTENT`,`DESTRUCTIVE`,`DANGEROUS`]),xe(`device`,`all devices`,n?.devices??[]),xe(`status`,`all status`,[`ok`,`error`]),(0,J.jsx)(`button`,{className:`btn${y?` is-active`:``}`,onClick:()=>b(e=>!e),children:y?`▶ Resume`:`⏸ Pause`}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>_e(`csv`),children:`CSV`}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>_e(`json`),children:`JSON`}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>A({tool:``,risk:``,device:``,status:``,q:``}),children:`Clear`}),me&&T.size>0?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`button`,{className:`btn btn-danger`,onClick:()=>void ge(),children:[`✓ Confirm delete (`,T.size,`)`]}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>he(!1),children:`Cancel`})]}):(0,J.jsxs)(`button`,{className:`btn`,disabled:T.size===0,onClick:()=>he(!0),title:`Delete the selected rows`,children:[`🗑 Delete`,T.size>0?` (${T.size})`:``]})]}),ie.length===0?ae?(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__icon`,children:`🔍`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:`No calls match your filters`}),(0,J.jsxs)(`p`,{className:`feed-empty__sub`,children:[m.length,` call`,m.length===1?``:`s`,` buffered — try widening the search or the risk / device / status filters.`]}),(0,J.jsx)(`button`,{className:`btn`,onClick:()=>A({tool:``,risk:``,device:``,status:``,q:``}),children:`Clear filters`})]}):(0,J.jsxs)(`div`,{className:`feed-empty`,children:[(0,J.jsx)(`div`,{className:`feed-empty__pulse${x===`off`?``:` is-on`}`}),(0,J.jsx)(`p`,{className:`feed-empty__title`,children:x===`off`?`Not connected`:`Listening for tool calls…`}),(0,J.jsx)(`p`,{className:`feed-empty__sub`,children:x===`off`?`The live stream is offline — it will reconnect automatically.`:`Tool calls the LLM makes against this server stream in here in real time.`})]}):(0,J.jsx)(`div`,{className:`feedwrap`,children:(0,J.jsxs)(`table`,{className:`feed`,children:[(0,J.jsx)(`thead`,{children:(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`th`,{style:{width:28},children:(0,J.jsx)(`input`,{type:`checkbox`,"aria-label":`Select all shown rows`,checked:ue,ref:e=>{e&&(e.indeterminate=de)},onChange:pe})}),(0,J.jsx)(`th`,{children:`time`}),(0,J.jsx)(`th`,{children:`tool`}),(0,J.jsx)(`th`,{children:`risk`}),(0,J.jsx)(`th`,{children:`device`}),(0,J.jsx)(`th`,{className:`num`,children:`dur`}),(0,J.jsx)(`th`,{children:`status`}),(0,J.jsx)(`th`,{children:`output`})]})}),(0,J.jsx)(`tbody`,{children:ce.map(e=>(0,J.jsxs)(`tr`,{className:`${e.isError?`is-err`:``}${T.has(e.id)?` is-selected`:``}`.trim()||void 0,onClick:()=>void H(e),children:[(0,J.jsx)(`td`,{onClick:e=>e.stopPropagation(),children:(0,J.jsx)(`input`,{type:`checkbox`,"aria-label":`Select row`,checked:T.has(e.id),onChange:()=>fe(e.id)})}),(0,J.jsx)(`td`,{children:Cc(e.ts)}),(0,J.jsx)(`td`,{children:e.tool}),(0,J.jsx)(`td`,{children:(0,J.jsx)(`span`,{className:`risk risk-${e.risk}`,children:e.risk.replace(`WRITE_IDEMPOTENT`,`WRITE·I`)})}),(0,J.jsx)(`td`,{children:e.device??`—`}),(0,J.jsx)(`td`,{className:`num`,children:xc(e.durationMs)}),(0,J.jsx)(`td`,{children:(0,J.jsx)(`span`,{className:e.isError?`status-err`:`status-ok`,children:e.isError?`error`:`ok`})}),(0,J.jsx)(`td`,{className:`preview`,children:e.isError?e.error??`error`:e.output||`—`})]},e.id))})]})})]})]}),C&&(0,J.jsx)(kY,{event:C,onClose:()=>w(null)})]})}var nX=document.getElementById(`root`);nX&&(0,y.createRoot)(nX).render((0,J.jsx)(tX,{}));
82
82
  </script>
83
83
  <style>
84
- @import "https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap";@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:var(--mt-sans);--font-mono:var(--mt-mono)}}@layer base,components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.isolate{isolation:isolate}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.table{display:table}.shrink{flex-shrink:1}.grow{flex-grow:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.border{border-style:var(--tw-border-style);border-width:1px}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}}:root{--background:#0a0a0a;--foreground:#ededed;--card:#111;--card-foreground:#ededed;--popover:#111;--popover-foreground:#ededed;--primary:#ededed;--primary-foreground:#0a0a0a;--secondary:#1a1a1a;--secondary-foreground:#ededed;--muted:#1a1a1a;--muted-foreground:#a1a1a1;--accent:var(--page-accent,#3291ff);--accent-foreground:#0a0a0a;--destructive:#ff5c5c;--destructive-foreground:#fff;--success:#2dd4a7;--warning:#f5a623;--border:#2a2a2a;--input:#2a2a2a;--ring:var(--page-accent,#3291ff);--radius:.5rem}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}:root{--mt-bg:var(--color-background-primary,#0b0d10);--mt-surface:var(--color-background-secondary,#14171c);--mt-surface-2:var(--color-background-tertiary,#1b1f26);--mt-border:var(--color-border-primary,#262b33);--mt-text:var(--color-text-primary,#e8eaed);--mt-text-dim:var(--color-text-secondary,#9aa3af);--mt-text-faint:var(--color-text-tertiary,#6b7280);--mt-accent:var(--color-accent-primary,#6ea8fe);--mt-good:#34d399;--mt-warn:#fbbf24;--mt-bad:#f87171;--mt-radius:var(--border-radius-md,14px);--mt-radius-sm:var(--border-radius-sm,9px);--mt-mono:var(--font-mono,ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace);--mt-sans:var(--font-sans,system-ui, -apple-system, "Segoe UI", sans-serif);--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}*{box-sizing:border-box}body{background:var(--mt-bg);color:var(--mt-text);font-family:var(--mt-sans);-webkit-font-smoothing:antialiased;margin:0;padding:16px;font-size:13px;line-height:1.5}.app{gap:14px;max-width:960px;margin:0 auto;display:grid}.hd{flex-wrap:wrap;align-items:center;gap:12px;display:flex}.hd__dot{background:var(--mt-good);width:9px;height:9px;box-shadow:0 0 0 4px color-mix(in srgb, var(--mt-good) 22%, transparent);border-radius:50%}.hd__title{letter-spacing:-.01em;margin:0;font-size:17px;font-weight:650}.hd__sub{color:var(--mt-text-dim);font-family:var(--mt-mono);margin:0;font-size:12px}.hd__spacer{flex:1}.pill{border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text-dim);font-family:var(--mt-mono);border-radius:999px;align-items:center;gap:6px;padding:3px 9px;font-size:11px;display:inline-flex}.pill b{color:var(--mt-text);font-weight:600}.grid{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;display:grid}.card{background:linear-gradient(180deg, var(--mt-surface), var(--mt-surface-2));border:1px solid var(--mt-border);border-radius:var(--mt-radius);padding:14px}.card__label{color:var(--mt-text-dim);text-transform:uppercase;letter-spacing:.06em;margin:0 0 8px;font-size:11px}.card__value{font-family:var(--mt-mono);letter-spacing:-.01em;font-size:20px;font-weight:600}.toolbar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.toolbar .grow{flex:1;min-width:140px}.search{appearance:none;border:1px solid var(--mt-border);background:var(--mt-surface);width:100%;color:var(--mt-text);font:inherit;border-radius:var(--mt-radius-sm);padding:7px 11px;font-size:13px}.search:focus{border-color:var(--mt-accent);outline:none}.search::placeholder{color:var(--mt-text-faint)}.btn{appearance:none;border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text);font:inherit;border-radius:var(--mt-radius-sm);cursor:pointer;white-space:nowrap;padding:6px 11px;font-size:12px;transition:border-color .15s,background .15s}.btn:disabled{opacity:.5;cursor:default}.btn.is-active{border-color:var(--mt-accent);color:var(--mt-accent)}.chip{border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text-dim);font-family:var(--mt-mono);border-radius:999px;align-items:center;gap:4px;padding:1px 7px;font-size:11px;display:inline-flex}.chip.is-good{color:var(--mt-good);border-color:color-mix(in srgb, var(--mt-good) 45%, var(--mt-border))}.chip.is-warn{color:var(--mt-warn);border-color:color-mix(in srgb, var(--mt-warn) 45%, var(--mt-border))}.chip.is-bad{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border))}.tablewrap{border:1px solid var(--mt-border);border-radius:var(--mt-radius);max-height:70vh;overflow:auto}table.tbl{border-collapse:collapse;width:100%;font-size:12px}table.tbl th,table.tbl td{text-align:left;border-bottom:1px solid color-mix(in srgb, var(--mt-border) 55%, transparent);white-space:nowrap;font-family:var(--mt-mono);padding:7px 12px}table.tbl thead th{z-index:1;background:var(--mt-surface-2);color:var(--mt-text-dim);cursor:pointer;-webkit-user-select:none;user-select:none;font-weight:600;position:sticky;top:0}table.tbl thead th:hover{color:var(--mt-text)}table.tbl thead th .arrow{color:var(--mt-accent);margin-left:4px}table.tbl tbody tr{cursor:pointer}table.tbl tbody tr:hover{background:color-mix(in srgb, var(--mt-accent) 8%, transparent)}table.tbl tbody tr.is-disabled td,table.tbl td.col-num{color:var(--mt-text-faint)}.kv__body{border:1px solid var(--mt-border);border-radius:var(--mt-radius);grid-template-columns:minmax(120px,.4fr) 1fr;display:grid;overflow:hidden}.kv__body>div{border-bottom:1px solid color-mix(in srgb, var(--mt-border) 55%, transparent);overflow-wrap:anywhere;min-width:0;font-size:12px;font-family:var(--mt-mono);padding:7px 14px}.kv__k{color:var(--mt-text-dim);background:color-mix(in srgb, var(--mt-surface) 60%, transparent)}.kv__v{color:var(--mt-text)}.drawer{border:1px solid var(--mt-accent);border-radius:var(--mt-radius);background:var(--mt-surface);gap:10px;padding:12px;display:grid}.drawer__hd{align-items:center;gap:8px;display:flex}.drawer__hd b{font-family:var(--mt-mono)}pre.raw{border:1px solid var(--mt-border);border-radius:var(--mt-radius);background:var(--mt-surface);color:var(--mt-text);font-family:var(--mt-mono);white-space:pre;max-height:70vh;margin:0;padding:14px;font-size:12px;overflow:auto}.foot{color:var(--mt-text-faint);font-size:11px;font-family:var(--mt-mono);flex-wrap:wrap;align-items:center;gap:10px;display:flex}.foot .grow{flex:1}.skeleton,.empty{color:var(--mt-text-faint);text-align:center;padding:40px 0}:root{--mt-sans:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;--mt-mono:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;--mt-display:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;--mt-bg:#0a0a0a;--mt-surface:#111;--mt-surface-2:#1a1a1a;--mt-border:#2a2a2a;--mt-border-strong:#3a3a3a;--mt-text:#ededed;--mt-text-dim:#a1a1a1;--mt-text-faint:#6e6e6e;--mt-good:#d4d4d8;--mt-warn:#a1a1a1;--mt-bad:#ff5c5c;--mt-radius:12px;--mt-radius-sm:8px;--sky:#3291ff;--teal:#2dd4bf;--cyan:#45d4ee;--lime:#69d05a;--coral:#ff5c5c;--amber:#f5a623;--pink:#ff4d8d;--violet:#9d7bff;--page-accent:#3291ff;--page-accent-2:#2dd4bf;--mt-accent:var(--page-accent);--grad:linear-gradient(115deg, var(--page-accent), var(--page-accent-2) 90%);--ease:cubic-bezier(.22, 1, .36, 1);--glass:#111111b8}html,body{background:var(--mt-bg);color:var(--mt-text);font-family:var(--mt-sans);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;margin:0;padding:0}body:after{content:"";z-index:-2;background-image:linear-gradient(color-mix(in srgb, var(--mt-border) 55%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--mt-border) 55%, transparent) 1px, transparent 1px);opacity:.32;pointer-events:none;background-size:52px 52px;position:fixed;inset:0;-webkit-mask-image:radial-gradient(circle at 50% 0,#000,#0000 72%);mask-image:radial-gradient(circle at 50% 0,#000,#0000 72%)}.main:before{content:"";z-index:-1;background:radial-gradient(52% 38% at 18% -8%, color-mix(in srgb, var(--page-accent) 14%, transparent), transparent 70%), radial-gradient(46% 36% at 100% 4%, color-mix(in srgb, var(--page-accent-2) 11%, transparent), transparent 68%);opacity:.9;transition:background .5s var(--ease);pointer-events:none;position:fixed;inset:0}.shell{grid-template-columns:250px minmax(0,1fr);align-items:start;min-height:100vh;display:grid}.nav{border-right:1px solid var(--mt-border);background:color-mix(in srgb, var(--mt-surface) 55%, transparent);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);flex-direction:column;gap:10px;height:100vh;padding:18px 14px;display:flex;position:sticky;top:0}.nav__brand{align-items:center;gap:11px;padding:6px 8px 14px;display:flex}.nav__mark{background:var(--grad);width:38px;height:38px;box-shadow:0 6px 20px color-mix(in srgb, var(--page-accent) 34%, transparent);transition:background .4s var(--ease), box-shadow .4s var(--ease);border-radius:11px;flex:none;place-items:center;display:grid}.nav__mark svg{width:22px;height:22px;display:block}.nav__brandtext{flex-direction:column;min-width:0;line-height:1.1;display:flex}.nav__brandtext b{font-family:var(--mt-display);letter-spacing:-.03em;font-size:15px;font-weight:700}.nav__brandtext small{font-family:var(--mt-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--mt-text-dim);margin-top:3px;font-size:10px}.nav__items{flex-direction:column;flex:1;gap:3px;display:flex}.nav__item{color:var(--mt-text-dim);font-family:var(--mt-sans);cursor:pointer;text-align:left;transition:background .18s var(--ease), color .18s, border-color .18s, transform .18s var(--ease);background:0 0;border:1px solid #0000;border-radius:11px;align-items:center;gap:11px;padding:10px 12px;font-size:13px;font-weight:500;display:flex}.nav__item svg{opacity:.85;flex:none;width:18px;height:18px}.nav__item:hover{color:var(--mt-text);background:color-mix(in srgb, var(--mt-text) 7%, transparent)}.nav__item.is-active{color:var(--mt-text);border-color:color-mix(in srgb, var(--page-accent) 36%, var(--mt-border));background:linear-gradient(100deg, color-mix(in srgb, var(--page-accent) 16%, transparent), color-mix(in srgb, var(--page-accent-2) 7%, transparent))}.nav__item.is-active svg{opacity:1;color:var(--page-accent)}.nav__item.is-active:before{content:"";background:var(--page-accent);width:3px;box-shadow:0 0 12px color-mix(in srgb, var(--page-accent) 70%, transparent);border-radius:999px;position:absolute;top:18%;bottom:18%;left:-1px}.nav__item{position:relative}.nav__badge{font-family:var(--mt-mono);background:color-mix(in srgb, var(--page-accent) 24%, transparent);color:var(--mt-text);border-radius:999px;margin-left:auto;padding:1px 7px;font-size:10px;animation:.4s cubic-bezier(.19,1,.22,1) nav-badge-pop;display:inline-block}@keyframes nav-badge-pop{0%{transform:scale(1)}35%{background:color-mix(in srgb, var(--page-accent) 60%, transparent);transform:scale(1.35)}to{transform:scale(1)}}@media (prefers-reduced-motion:reduce){.nav__badge{animation:none}}.nav__foot{border-top:1px solid var(--mt-border);flex-direction:column;gap:8px;padding:10px 8px 2px;display:flex}.main{align-content:start;gap:18px;min-width:0;padding:22px clamp(16px,3vw,44px) 64px;display:grid}.topline{flex-wrap:wrap;align-items:center;gap:14px;display:flex}.topline__txt h1{font-family:var(--mt-display);letter-spacing:-.03em;background:linear-gradient(100deg, var(--mt-text) 30%, color-mix(in srgb, var(--page-accent) 78%, var(--mt-text)));-webkit-text-fill-color:transparent;transition:background .4s var(--ease);-webkit-background-clip:text;background-clip:text;margin:0;font-size:clamp(20px,2.4vw,28px);font-weight:700;line-height:1.15}.topline__txt small{color:var(--mt-text-dim);font-family:var(--mt-mono);margin-top:3px;font-size:12px;display:block}.topline__spacer{flex:1;min-width:8px}.help-toggle{border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text-dim);font-family:var(--mt-sans);cursor:pointer;transition:color .18s, border-color .18s, background .18s, transform .12s var(--ease);border-radius:999px;align-items:center;gap:7px;padding:7px 13px 7px 10px;font-size:12.5px;font-weight:500;display:inline-flex}.help-toggle:hover{color:var(--mt-text);border-color:var(--mt-border-strong);transform:translateY(-1px)}.help-toggle.is-on{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 45%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 12%, var(--mt-surface))}.help-toggle__q{background:color-mix(in srgb, var(--page-accent) 22%, transparent);width:17px;height:17px;color:var(--page-accent);border-radius:999px;place-items:center;font-size:11px;font-weight:700;display:grid}.pagehelp{border-radius:var(--mt-radius);border:1px solid color-mix(in srgb, var(--page-accent) 28%, var(--mt-border));background:linear-gradient(120deg, color-mix(in srgb, var(--page-accent) 9%, var(--mt-surface)), var(--mt-surface) 60%);gap:14px;padding:16px 18px;display:flex}.pagehelp__icon{color:#0a0a0a;background:var(--grad);width:30px;height:30px;box-shadow:0 4px 14px color-mix(in srgb, var(--page-accent) 35%, transparent);border-radius:9px;flex:none;place-items:center;font-size:15px;font-weight:700;display:grid}.pagehelp__body{min-width:0}.pagehelp__what{color:var(--mt-text);margin:2px 0 8px;font-size:13.5px;line-height:1.55}.pagehelp__tips{gap:4px;margin:0;padding-left:18px;display:grid}.pagehelp__tips li{color:var(--mt-text-dim);font-size:12.5px;line-height:1.5}.pagehelp__tips li::marker{color:var(--page-accent)}.view{align-content:start;gap:18px;display:grid}.bento{grid-template-columns:repeat(6,1fr);gap:18px;display:grid}.bento .panel{margin:0}.b-series{grid-column:span 4}.b-risk{grid-column:span 2}.b-tools,.b-status,.b-device,.b-errors{grid-column:span 3}.b-risk,.b-status{flex-direction:column;display:flex}@media (width<=1040px){.bento{grid-template-columns:repeat(2,1fr)}.b-series,.b-risk,.b-tools,.b-status,.b-device,.b-errors{grid-column:span 2}}@media (width<=900px){.shell{grid-template-columns:1fr}.nav{border-right:0;border-bottom:1px solid var(--mt-border);z-index:5;flex-direction:row;align-items:center;gap:8px;height:auto;padding:10px 12px;position:sticky;top:0;overflow-x:auto}.nav__brand{padding:0 6px 0 2px}.nav__brandtext{display:none}.nav__items{flex-direction:row;flex:1;gap:4px}.nav__item span{display:none}.nav__item{padding:9px 11px}.nav__foot{border-top:0;flex-direction:row;align-items:center;padding:0}.nav__foot .muted{display:none}}@media (width<=560px){.nav__brand{display:none}}@media (prefers-reduced-motion:no-preference){.js-motion .reveal{opacity:0}}.hero__live{border:1px solid var(--mt-border);background:var(--glass);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);font-family:var(--mt-mono);letter-spacing:.04em;text-transform:uppercase;color:var(--mt-text-dim);border-radius:999px;align-items:center;gap:7px;padding:7px 13px;font-size:11px;display:inline-flex}.hero__live .dot{background:var(--mt-bad);border-radius:50%;width:8px;height:8px;transition:background .3s}.hero__live.is-ws{--lc:#34d399}.hero__live.is-sse{--lc:#f59e0b}.hero__live.is-on{color:var(--mt-text);border-color:color-mix(in srgb, var(--lc,var(--mt-good)) 40%, var(--mt-border))}.hero__live.is-on .dot{background:var(--lc,var(--mt-good));box-shadow:0 0 0 4px color-mix(in srgb, var(--lc,var(--mt-good)) 22%, transparent);animation:1.8s ease-out infinite hero-pulse}@keyframes hero-pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--lc,var(--mt-good)) 55%, transparent)}70%{box-shadow:0 0 0 9px color-mix(in srgb, var(--lc,var(--mt-good)) 0%, transparent)}to{box-shadow:0 0 0 0 color-mix(in srgb, var(--lc,var(--mt-good)) 0%, transparent)}}.panel>h2,.sheet__hd h2{font-family:var(--mt-sans)}.cards{grid-template-columns:repeat(2,1fr);gap:12px;display:grid}@media (width>=560px){.cards{grid-template-columns:repeat(4,1fr)}}@media (width>=1040px){.cards{grid-template-columns:repeat(8,1fr)}}.stat{background:linear-gradient(180deg, var(--mt-surface), color-mix(in srgb, var(--mt-surface-2) 80%, transparent));border:1px solid var(--mt-border);border-radius:var(--mt-radius);transition:transform .3s var(--ease), border-color .3s var(--ease);padding:14px 15px;position:relative;overflow:hidden}.stat:before{content:"";background:var(--grad);opacity:0;height:2px;transition:opacity .3s var(--ease);position:absolute;inset:0 0 auto}.stat:hover{border-color:color-mix(in srgb, var(--page-accent) 42%, var(--mt-border));transform:translateY(-3px)}.stat:hover:before{opacity:1}.stat .k{color:var(--mt-text-dim);text-transform:uppercase;letter-spacing:.08em;margin:0 0 7px;font-size:10px}.stat .v{font-family:var(--mt-mono);letter-spacing:-.02em;font-variant-numeric:tabular-nums;font-size:23px;font-weight:500}.stat .v small{color:var(--mt-text-dim);font-size:12px;font-weight:400}.stat.is-bad .v{color:var(--mt-bad)}.stat.is-warn .v{color:var(--mt-warn)}.stat.is-good .v{color:var(--mt-good)}.panel{background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius);transition:border-color .25s var(--ease);padding:18px;position:relative;box-shadow:0 1px 2px #0000004d,inset 0 1px #ffffff08}.panel:hover{border-color:color-mix(in srgb, var(--mt-text) 13%, var(--mt-border))}.panel>h2{color:var(--mt-text-dim);text-transform:uppercase;letter-spacing:.07em;align-items:center;gap:9px;margin:0 0 14px;font-size:12px;font-weight:600;display:inline-flex}.panel>h2:before,.sheet__hd h2:first-child:before{content:"";background:var(--grad);border-radius:2px;flex:none;width:3px;height:13px}.cols{grid-template-columns:1.4fr 1fr;gap:18px;display:grid}@media (width<=820px){.cols{grid-template-columns:1fr}}.cols-3{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px;display:grid}.cols-3 .panel{flex-direction:column;display:flex}.hbar{gap:9px;display:grid}.hbar__row{grid-template-columns:minmax(90px,.9fr) 2fr auto;align-items:center;gap:10px;font-size:12px;display:grid}.hbar__label{font-family:var(--mt-mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.hbar__track{background:color-mix(in srgb, var(--mt-surface-2) 90%, transparent);border-radius:999px;height:8px;overflow:hidden}.hbar__fill{background:var(--grad);height:100%;box-shadow:0 0 10px color-mix(in srgb, var(--teal) 45%, transparent);border-radius:999px}.hbar__val{font-family:var(--mt-mono);color:var(--mt-text-dim);text-align:right;font-variant-numeric:tabular-nums;font-size:11px}.legend{font-family:var(--mt-mono);color:var(--mt-text-dim);flex-wrap:wrap;gap:12px;margin-top:12px;font-size:11px;display:flex}.legend span{align-items:center;gap:5px;display:inline-flex}.legend i{border-radius:2px;width:9px;height:9px;display:inline-block}.risk{font-family:var(--mt-mono);color:var(--rc,var(--mt-text-dim));border:1px solid color-mix(in srgb, var(--rc,var(--mt-border)) 45%, var(--mt-border));background:color-mix(in srgb, var(--rc,transparent) 12%, transparent);text-transform:uppercase;letter-spacing:.04em;border-radius:999px;padding:1px 8px;font-size:10px;display:inline-block}.risk-READ{--rc:#34d399}.risk-WRITE{--rc:#3291ff}.risk-WRITE_IDEMPOTENT{--rc:#2dd4bf}.risk-DESTRUCTIVE{--rc:#f59e0b}.risk-DANGEROUS{--rc:#ef4444}.feed{border-collapse:collapse;width:100%;font-size:12px}.feed th,.feed td{text-align:left;border-bottom:1px solid color-mix(in srgb, var(--mt-border) 55%, transparent);white-space:nowrap;font-family:var(--mt-mono);padding:7px 11px}.feed thead th{background:color-mix(in srgb, var(--mt-surface-2) 96%, transparent);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);color:var(--mt-text-dim);text-transform:uppercase;letter-spacing:.05em;z-index:1;font-size:10px;font-weight:600;position:sticky;top:0}.feed tbody tr{cursor:pointer;transition:background .12s}.feed tbody tr:hover{background:color-mix(in srgb, var(--mt-accent) 9%, transparent)}.feed tbody tr.is-err{background:color-mix(in srgb, var(--mt-bad) 9%, transparent)}.feed tbody tr.is-selected{background:color-mix(in srgb, var(--mt-accent) 16%, transparent)}.feed td.preview{white-space:nowrap;text-overflow:ellipsis;max-width:320px;color:var(--mt-text-dim);overflow:hidden}.feed td.num{text-align:right;color:var(--mt-text-dim);font-variant-numeric:tabular-nums}.status-ok{color:var(--mt-good)}.status-err{color:var(--mt-bad)}.feedwrap{border:1px solid var(--mt-border);border-radius:var(--mt-radius);max-height:60vh;overflow:auto}.feed-empty{border:1px dashed var(--mt-border);border-radius:var(--mt-radius);text-align:center;justify-items:center;gap:8px;padding:54px 16px;display:grid}.feed-empty__icon{opacity:.8;font-size:28px}.feed-empty__title{color:var(--mt-text);margin:0;font-weight:600}.feed-empty__sub{max-width:460px;color:var(--mt-text-faint);margin:0;font-size:12px}.feed-empty .btn{margin-top:6px}.feed-empty__pulse{background:var(--mt-text-faint);border-radius:50%;width:12px;height:12px}.feed-empty__pulse.is-on{background:var(--mt-good);animation:1.6s ease-out infinite feed-pulse}@keyframes feed-pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--mt-good) 55%, transparent)}70%{box-shadow:0 0 0 12px color-mix(in srgb, var(--mt-good) 0%, transparent)}to{box-shadow:0 0 0 0 color-mix(in srgb, var(--mt-good) 0%, transparent)}}.conn{display:block;overflow:visible}.conn-grid{fill:none;stroke:var(--mt-border);stroke-opacity:.7;stroke-dasharray:2 7}.conn-sonar{fill:none;stroke:var(--mt-accent);stroke-width:1.5px;opacity:0;animation:3.3s ease-out infinite conn-sonar}@keyframes conn-sonar{0%{r:30px;opacity:.5}to{r:150px;opacity:0}}.conn-link{fill:none;stroke-width:1.6px;opacity:.38}.conn-flow{fill:none;stroke-width:2.4px;stroke-linecap:round;stroke-dasharray:2 13;opacity:.9;filter:drop-shadow(0 0 4px);animation:1.05s linear infinite conn-flow}@keyframes conn-flow{to{stroke-dashoffset:-60px}}.conn-packet{filter:drop-shadow(0 0 6px var(--teal))}.conn-hub-glow{fill:var(--mt-accent);opacity:.22;filter:blur(11px)}.conn-hub-ring{fill:none;stroke:var(--mt-accent);stroke-width:1.4px;stroke-dasharray:4 9;opacity:.7;transform-box:fill-box;transform-origin:50%;animation:15s linear infinite conn-rot}@keyframes conn-rot{to{transform:rotate(360deg)}}.conn-node-halo{fill:none;stroke-width:2px;transform-box:fill-box;transform-origin:50%;animation:2.4s ease-in-out infinite conn-halo}@keyframes conn-halo{0%,to{opacity:.45;transform:scale(1)}50%{opacity:0;transform:scale(1.55)}}.conn-blink{animation:1.6s ease-in-out infinite conn-blink}@keyframes conn-blink{0%,to{opacity:1}50%{opacity:.35}}.conn-node text{pointer-events:none}@media (prefers-reduced-motion:reduce){.conn-sonar,.conn-flow,.conn-hub-ring,.conn-node-halo,.conn-blink,.conn-packet animateMotion{animation:none}.conn-sonar{display:none}}.dev-grid{grid-template-columns:1fr;align-content:start;gap:12px;display:grid}@media (width>=600px) and (width<=819px){.dev-grid{grid-template-columns:1fr 1fr}}.dev-toolbar{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.dev-filters{border:1px solid var(--mt-border);background:color-mix(in srgb, var(--mt-surface-2) 70%, transparent);border-radius:999px;gap:4px;padding:3px;display:inline-flex}.dev-fbtn{appearance:none;color:var(--mt-text-dim);font:11px var(--mt-mono);cursor:pointer;white-space:nowrap;background:0 0;border:0;border-radius:999px;padding:5px 12px;transition:background .18s,color .18s}.dev-fbtn:hover{color:var(--mt-text)}.dev-fbtn.is-active{background:var(--grad);color:var(--mt-bg);font-weight:600}.dev-grid-wide{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));align-content:start;gap:14px;display:grid}.dev-collapse{border:1px solid var(--mt-border);border-radius:var(--mt-radius);background:var(--glass);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:6px 18px 18px}.dev-collapse>summary{cursor:pointer;text-transform:uppercase;letter-spacing:.07em;color:var(--mt-text-dim);align-items:center;gap:8px;padding:12px 0;font-size:12px;font-weight:600;list-style:none;display:flex}.dev-collapse>summary::-webkit-details-marker{display:none}.dev-collapse>summary:before{content:"▸";transition:transform .2s var(--ease);color:var(--teal);display:inline-block}.dev-collapse[open]>summary:before{transform:rotate(90deg)}.dev-card .dot--status{width:7px;height:7px}.dev-card{transition:transform .3s var(--ease), border-color .3s var(--ease);gap:8px;padding:14px 15px;display:grid}.dev-card:hover{border-color:color-mix(in srgb, var(--teal) 35%, var(--mt-border));transform:translateY(-2px)}.dev-card__top{align-items:center;gap:8px;display:flex}.dev-card__name{font-family:var(--mt-mono);font-size:13px;font-weight:500}.dev-card .dot{border-radius:50%;flex:none;width:9px;height:9px}.dev-card__meta{font-family:var(--mt-mono);color:var(--mt-text-dim);grid-template-columns:auto 1fr;gap:3px 12px;font-size:11px;display:grid}.dev-card__meta b{color:var(--mt-text);overflow-wrap:anywhere;font-weight:500}details.cfg>summary{cursor:pointer;color:var(--mt-text-dim);font-family:var(--mt-mono);-webkit-user-select:none;user-select:none;padding:4px 0;font-size:12px}.badge{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--mt-bg);background:var(--grad);border-radius:999px;padding:1px 7px;font-size:9px;font-weight:600}.overlay{-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10;background:#0000009e;justify-content:flex-end;display:flex;position:fixed;inset:0}.sheet{background:color-mix(in srgb, var(--mt-surface) 96%, var(--mt-bg));border-left:1px solid color-mix(in srgb, var(--teal) 28%, var(--mt-border));align-content:start;gap:12px;width:min(580px,100%);height:100%;padding:18px;display:grid;overflow:auto;box-shadow:-24px 0 60px #00000080}.sheet__hd{align-items:center;gap:10px;display:flex}.sheet__hd h3{font-family:var(--mt-mono);margin:0;font-size:15px}pre.body{background:var(--mt-bg);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);font-family:var(--mt-mono);white-space:pre-wrap;word-break:break-word;max-height:40vh;margin:0;padding:12px;font-size:12px;overflow:auto}pre.body.json{color:#a1a1aa}pre.body.json .j-key{color:#7dd3fc}pre.body.json .j-str{color:#86efac}pre.body.json .j-num{color:#fcd34d}pre.body.json .j-bool{color:#d8b4fe}pre.body.json .j-null{color:#71717a}pre.body.ros{color:#c9c9d1}pre.body.ros .ros-key{color:#7dd3fc}pre.body.ros .ros-str{color:#86efac}pre.body.ros .ros-num{color:#fcd34d}pre.body.ros .ros-ip{color:#5eead4}pre.body.ros .ros-mac{color:#c4b5fd}pre.body.ros .ros-good{color:#4ade80;font-weight:500}pre.body.ros .ros-bad{color:#f87171;font-weight:500}pre.body.ros .ros-bool{color:#d8b4fe}pre.body.ros .ros-dim{color:#8b8b94}pre.body.ros .ros-comment{color:#6b7280;font-style:italic}.muted{color:var(--mt-text-faint);font-family:var(--mt-mono);font-size:11px}.btn-danger{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border));background:color-mix(in srgb, var(--mt-bad) 12%, transparent)}.btn-danger:hover{background:color-mix(in srgb, var(--mt-bad) 22%, transparent);border-color:var(--mt-bad)}.btn:hover{border-color:color-mix(in srgb, var(--page-accent) 55%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 10%, var(--mt-surface-2))}.btn.is-active{border-color:color-mix(in srgb, var(--page-accent) 70%, var(--mt-border));color:var(--page-accent);background:color-mix(in srgb, var(--page-accent) 12%, var(--mt-surface-2))}:where(button,a,input,select,textarea,[tabindex]):focus-visible{outline:2px solid color-mix(in srgb, var(--page-accent) 70%, transparent);outline-offset:2px;border-radius:var(--mt-radius-sm)}.conn-legend{font-family:var(--mt-mono);color:var(--mt-text-dim);flex-wrap:wrap;justify-content:center;gap:16px;margin-top:8px;font-size:11px;display:flex}.conn-legend span{align-items:center;gap:6px;display:inline-flex}.conn-legend i{border-radius:3px;width:10px;height:10px;display:inline-block}.conn-chevron{fill:none;stroke-width:1.6px;stroke-linecap:round;stroke-linejoin:round;opacity:.85}.conn-errrow{cursor:pointer;border-radius:6px}.conn-errrow:hover{background:color-mix(in srgb, var(--mt-bad) 12%, transparent)}@media (prefers-reduced-motion:reduce){.conn-chevron{opacity:.6}}.health-grid{grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:14px;display:grid}.health-card{flex-direction:column;gap:10px;padding:16px;display:flex}.health-card--na{justify-content:center;gap:6px;min-height:120px}.health-card__hd{align-items:center;gap:8px;display:flex}.health-card__sub{font-family:var(--mt-mono);margin-top:-4px;font-size:11px}.health-card__gauges{justify-content:space-around;gap:14px;display:flex}.gauge{flex-direction:column;align-items:center;gap:2px;display:flex}.gauge__label{font-family:var(--mt-mono);letter-spacing:.06em;color:var(--mt-text-dim);font-size:10px}.health-card__charts{gap:8px;display:grid}.health-chart{gap:2px;display:grid}.health-chart__k{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.05em;color:var(--mt-text-dim);font-size:10px}.spark{background:color-mix(in srgb, var(--mt-surface-2) 60%, transparent);border-radius:6px;display:block}.spark--empty{font-family:var(--mt-mono);color:var(--mt-text-faint);text-align:center;padding:12px 6px;font-size:11px}.health-card__foot{font-family:var(--mt-mono);font-size:11px}.topo{flex-direction:column;gap:10px;display:flex}.topo svg{background:radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--mt-accent) 8%, transparent), transparent 60%);border-radius:var(--mt-radius-sm);width:100%;display:block}.topo-edge{stroke:color-mix(in srgb, var(--mt-text-faint) 55%, transparent);stroke-width:1.4px}.topo-edge.is-dashed{stroke:color-mix(in srgb, var(--mt-accent) 60%, transparent);stroke-dasharray:4 4}.topo-node{cursor:pointer}.topo-node rect{fill:var(--mt-surface-2);stroke-width:1.5px;transition:filter .15s}.topo-node.is-neighbor rect{fill:color-mix(in srgb, var(--mt-surface) 70%, transparent);stroke-dasharray:4 3}.topo-node.is-onboard rect{stroke-dasharray:4 3}.topo-node:hover rect,.topo-node.is-picked rect{filter:drop-shadow(0 0 6px color-mix(in srgb, var(--mt-accent) 55%, transparent))}.topo-node.is-picked rect{stroke-width:2.2px}.topo-label{fill:var(--mt-text);font:600 12px var(--mt-mono)}.topo-sub{fill:var(--mt-text-dim);font:10px var(--mt-mono)}.topo-bar-bg{fill:color-mix(in srgb, var(--mt-text-faint) 35%, transparent)}.topo-foot{flex-wrap:wrap;justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.topo-foot .legend{margin-top:0}.topo-pop{background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);flex:1;min-width:280px;max-width:460px;padding:12px}.topo-pop__hd{align-items:center;gap:8px;margin-bottom:6px;display:flex}.topo-pop__hd .muted{font-size:11px}.topo-stub{background:var(--mt-bg);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);font:11px/1.5 var(--mt-mono);color:var(--mt-text);white-space:pre;margin:0 0 8px;padding:8px 10px;overflow-x:auto}.topo-btn{font:11px var(--mt-mono);color:var(--mt-text);background:var(--mt-surface-2);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);cursor:pointer;padding:5px 10px;transition:border-color .15s,color .15s}.topo-btn:hover{border-color:var(--mt-accent);color:var(--mt-accent)}.cfgstudio{flex-direction:column;gap:10px;display:flex}.cfg-toolbar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.cfg-status{font:11px var(--mt-mono);border:1px solid var(--mt-border);border-radius:999px;padding:4px 10px}.cfg-status.is-ok{color:var(--mt-good);border-color:color-mix(in srgb, var(--mt-good) 45%, var(--mt-border));background:color-mix(in srgb, var(--mt-good) 10%, transparent)}.cfg-status.is-bad{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border));background:color-mix(in srgb, var(--mt-bad) 10%, transparent)}.cfg-select{font:11px var(--mt-mono);color:var(--mt-text);background:var(--mt-surface-2);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);padding:5px 9px}.cfg-save{border-color:color-mix(in srgb, var(--mt-accent) 55%, var(--mt-border));color:var(--mt-accent)}.backup-path{align-items:center;gap:8px;max-width:min(60vw,520px);display:inline-flex}.backup-path>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.backup-path-input{font:11px var(--mt-mono);color:var(--mt-text);background:var(--mt-surface-2);border:1px solid color-mix(in srgb, var(--mt-accent) 45%, var(--mt-border));border-radius:var(--mt-radius-sm);width:min(48vw,380px);padding:5px 9px}.backup-opts{flex-wrap:wrap;align-items:center}.backup-opt{font:11px var(--mt-mono);color:var(--mt-text-dim);background:var(--mt-surface-2);border:1px solid var(--mt-border);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:100px;align-items:center;gap:6px;padding:5px 11px 5px 9px;transition:border-color .18s,color .18s,background .18s;display:inline-flex}.backup-opt input{accent-color:var(--mt-accent);cursor:pointer;margin:0}.backup-opt[data-on]{color:var(--mt-text);border-color:color-mix(in srgb, var(--mt-accent) 55%, var(--mt-border));background:color-mix(in srgb, var(--mt-accent) 12%, var(--mt-surface-2))}.backup-opt[data-disabled]{opacity:.45;cursor:not-allowed}.backup-opt[data-disabled] input{cursor:not-allowed}.linkish{font:inherit;color:var(--mt-accent);cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:0}.linkish:hover{text-decoration:underline}.cfg-msg{font:12px var(--mt-mono);color:var(--mt-text-dim)}.cfg-banner{border-radius:var(--mt-radius-sm);background:color-mix(in srgb, var(--mt-warn) 12%, var(--mt-surface));border:1px solid color-mix(in srgb, var(--mt-warn) 45%, var(--mt-border));flex-wrap:wrap;align-items:center;gap:8px;padding:10px 13px;font-size:12px;display:flex}.cfg-count{font-family:var(--mt-mono);color:var(--mt-warn);font-weight:700}.cfg-warn{color:var(--mt-warn);font-size:11px}.cfg-editor{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-bg);max-height:420px;display:flex;overflow:hidden}.cfg-gutter{text-align:right;color:var(--mt-text-faint);background:var(--mt-surface-2);font:12px/1.5 var(--mt-mono);-webkit-user-select:none;user-select:none;min-width:38px;margin:0;padding:10px 8px;overflow:hidden}.cfg-ta-wrap{flex:1;position:relative}.cfg-hl,.cfg-ta{box-sizing:border-box;font:12px/1.5 var(--mt-mono);white-space:pre;tab-size:2;letter-spacing:normal;border:0;margin:0;padding:10px 12px}.cfg-hl{z-index:0;pointer-events:none;color:var(--mt-text-dim);position:absolute;inset:0;overflow:hidden}.cfg-ta{z-index:1;resize:vertical;color:#0000;width:100%;height:400px;caret-color:var(--mt-accent);background:0 0;outline:none;position:relative}.cfg-ta::selection{background:color-mix(in srgb, var(--mt-accent) 35%, transparent)}.cfg-hl .j-key{color:#7dd3fc}.cfg-hl .j-str{color:#86efac}.cfg-hl .j-num{color:#fcd34d}.cfg-hl .j-bool{color:#d8b4fe}.cfg-hl .j-null{color:#71717a}.cfg-ac{z-index:5;background:var(--mt-surface);border:1px solid var(--mt-accent);border-radius:var(--mt-radius-sm);min-width:150px;max-height:184px;position:absolute;overflow-y:auto;box-shadow:0 8px 24px #00000080}.cfg-ac-item{font:12px var(--mt-mono);color:var(--mt-text-dim);cursor:pointer;padding:5px 11px}.cfg-ac-item.is-sel{background:color-mix(in srgb, var(--mt-accent) 22%, transparent);color:var(--mt-text)}.cfg-chips{flex-wrap:wrap;gap:6px;display:flex}.cfg-chip{font:11px var(--mt-mono);border:1px solid var(--mt-border);border-radius:999px;padding:4px 10px}.cfg-chip.is-ok{color:var(--mt-good);border-color:color-mix(in srgb, var(--mt-good) 45%, var(--mt-border))}.cfg-chip.is-bad{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border))}.cfg-errors{flex-direction:column;gap:3px;display:flex}.cfg-err{font:11px var(--mt-mono);color:var(--mt-bad)}.cfg-err code{color:var(--mt-warn)}.cfg-preview{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);overflow:hidden}.cfg-preview__hd{background:var(--mt-surface-2);align-items:center;gap:8px;padding:9px 13px;font-size:12px;display:flex}.cfg-diff{max-height:320px;font:11px/1.5 var(--mt-mono);color:var(--mt-text-dim);background:var(--mt-bg);margin:0;padding:10px 12px;overflow:auto}.cfg-diff .d-add{color:var(--mt-good)}.cfg-diff .d-del{color:var(--mt-bad)}.cfg-diff .d-hunk{color:var(--mt-accent)}.cap-idle{font-size:13px;line-height:1.5}.cap-idle code{color:var(--mt-accent);font-family:var(--mt-mono)}.cap{flex-direction:column;gap:12px;display:flex}.cap-bar{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.cap-dot{background:var(--mt-text-faint);border-radius:999px;width:9px;height:9px}.cap-dot.is-on{background:var(--mt-good);box-shadow:0 0 0 4px color-mix(in srgb, var(--mt-good) 22%, transparent);animation:1.6s ease-out infinite feed-pulse}.cap-cols{grid-template-columns:220px 1fr;gap:12px;display:grid}@media (width<=720px){.cap-cols{grid-template-columns:1fr}}.cap-side{flex-direction:column;gap:5px;display:flex}.cap-h{text-transform:uppercase;letter-spacing:.05em;color:var(--mt-text-dim);font-size:11px}.cap-pbar{font:11px var(--mt-mono);grid-template-columns:52px 1fr 34px;align-items:center;gap:6px;display:grid}.cap-ptrack{background:var(--mt-surface-2);border-radius:999px;height:8px;overflow:hidden}.cap-ptrack i{border-radius:999px;height:100%;display:block}.cap-pn{text-align:right;color:var(--mt-text-dim)}.cap-talker{font:11px var(--mt-mono);color:var(--mt-text-dim);justify-content:space-between;display:flex}.cap-talker b{color:var(--mt-text)}.cap-list{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-bg);height:360px;font:11px/1.6 var(--mt-mono);overflow-y:auto}.cap-row{white-space:nowrap;grid-template-columns:90px 64px 48px 1fr;gap:8px;padding:1px 10px;display:grid;overflow:hidden}.cap-row:nth-child(odd){background:color-mix(in srgb, var(--mt-surface) 40%, transparent)}.cap-tt{color:var(--mt-text-faint)}.cap-proto{font-weight:600}.cap-len{color:var(--mt-text-dim);text-align:right}.cap-info{color:var(--mt-text);text-overflow:ellipsis;overflow:hidden}.plan-input{resize:vertical;box-sizing:border-box;border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-bg);width:100%;min-height:160px;color:var(--mt-text);font:12px/1.6 var(--mt-mono);outline:none;padding:12px 14px}.plan-input:focus{border-color:color-mix(in srgb, var(--teal) 55%, var(--mt-border))}.plan-input::placeholder{color:var(--mt-text-faint)}.plan-steps{flex-direction:column;gap:6px;margin-top:12px;display:flex}.plan-step{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:color-mix(in srgb, var(--mt-surface-2) 50%, transparent);font:12px var(--mt-mono);border-left-width:3px;align-items:center;gap:10px;padding:8px 12px;display:flex}.plan-step code{color:var(--mt-text);overflow-wrap:anywhere;flex:1}.plan-step.risk-high{border-left-color:var(--mt-bad)}.plan-step.risk-medium{border-left-color:var(--mt-warn)}.plan-step.risk-low{border-left-color:var(--mt-good)}.plan-op{background:color-mix(in srgb, var(--teal) 18%, transparent);width:18px;height:18px;color:var(--teal);border-radius:5px;flex:none;place-items:center;font-weight:700;display:grid}.plan-risk{text-transform:uppercase;letter-spacing:.05em;color:var(--mt-text-dim);font-size:10px}.plan-lock{color:var(--mt-bad);border:1px solid color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border));border-radius:999px;padding:1px 7px;font-size:10px}.cfgver-cp{align-items:center;gap:8px;display:inline-flex}.cfgver{gap:2px;margin:0;padding:0 0 0 4px;list-style:none;display:grid}.cfgver__row{border-radius:var(--mt-radius-sm);transition:background .18s var(--ease);grid-template-columns:18px minmax(0,1fr) auto;align-items:start;gap:10px;padding:11px 6px;display:grid;position:relative}.cfgver__row:hover{background:color-mix(in srgb, var(--mt-text) 4%, transparent)}.cfgver__row:before{content:"";background:var(--mt-border);width:1.5px;position:absolute;top:22px;bottom:-2px;left:12px}.cfgver__row:last-child:before{display:none}.cfgver__dot{border:2px solid var(--mt-border-strong);background:var(--mt-surface);z-index:1;border-radius:999px;width:11px;height:11px;margin-top:5px}.cfgver__row.is-head .cfgver__dot{border-color:var(--page-accent);background:var(--page-accent);box-shadow:0 0 0 4px color-mix(in srgb, var(--page-accent) 22%, transparent)}.cfgver__main{min-width:0}.cfgver__line{flex-wrap:wrap;align-items:center;gap:9px;font-size:12.5px;display:flex}.cfgver__kind{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--mt-border);color:var(--mt-text-dim);border-radius:999px;padding:2px 7px;font-size:10px}.cfgver__kind--checkpoint{color:var(--amber);border-color:color-mix(in srgb, var(--amber) 45%, var(--mt-border));background:color-mix(in srgb, var(--amber) 12%, transparent)}.cfgver__label{color:var(--mt-text);font-weight:600}.cfgver__time{font-family:var(--mt-mono);color:var(--mt-text-dim);font-size:11.5px}.cfgver__cur{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.05em;color:var(--page-accent);font-size:10px}.cfgver__same{color:var(--mt-text-faint);font-size:11.5px}.cfgver__drift{font-family:var(--mt-mono);align-items:baseline;gap:7px;font-size:11.5px;display:inline-flex}.cfgver__drift .add{color:var(--mt-good)}.cfgver__drift .rem{color:var(--mt-bad)}.cfgver__diff{margin-top:9px}.cfgver__diff pre.body{max-height:280px;margin:0;overflow:auto}.cfgver__actions{flex:none;align-items:center;gap:6px;display:inline-flex}.cfgver__del{color:var(--mt-text-faint);padding-left:8px;padding-right:8px}.cfgver__del:hover{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border))}.fguide{gap:18px;display:grid}.fguide__sechd{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.09em;color:var(--page-accent);margin:0 0 9px;font-size:11px}.fguide__list{gap:9px;display:grid}.fguide__item{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:color-mix(in srgb, var(--mt-surface-2) 45%, transparent);transition:border-color .18s, transform .12s var(--ease);padding:11px 13px}.fguide__item:hover{border-color:color-mix(in srgb, var(--page-accent) 40%, var(--mt-border));transform:translate(2px)}.fguide__top{flex-wrap:wrap;align-items:baseline;gap:10px;display:flex}.fguide__path{font-family:var(--mt-mono);color:var(--mt-text);font-size:12.5px;font-weight:500}.fguide__type{font-family:var(--mt-mono);color:var(--page-accent);background:color-mix(in srgb, var(--page-accent) 13%, transparent);border-radius:999px;padding:1px 7px;font-size:10.5px}.fguide__req{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.05em;color:var(--mt-bad);font-size:10px}.fguide__def{color:var(--mt-text-faint);font-size:11px}.fguide__def code{color:var(--mt-text-dim)}.fguide__desc{color:var(--mt-text-dim);margin:6px 0 0;font-size:12.5px;line-height:1.5}.fguide__enum{flex-wrap:wrap;gap:6px;margin-top:7px;display:flex}.fguide__enum code{font-family:var(--mt-mono);border:1px solid var(--mt-border);color:var(--mt-text-dim);border-radius:6px;padding:1px 7px;font-size:11px}.copybtn{position:relative}.copybtn.is-copied{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 55%, var(--mt-border))}.copybtn__tip{background:var(--page-accent);color:#0a0a0a;font-family:var(--mt-sans);white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .16s, transform .16s var(--ease);z-index:50;border-radius:6px;padding:3px 9px;font-size:11px;font-weight:600;position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%,4px)}.copybtn__tip:after{content:"";border:4px solid #0000;border-top-color:var(--page-accent);position:absolute;top:100%;left:50%;transform:translate(-50%)}.copybtn.is-copied .copybtn__tip{opacity:1;transform:translate(-50%)}.iconbtn{border:1px solid var(--mt-border);background:var(--mt-surface);width:26px;height:26px;color:var(--mt-text-dim);cursor:pointer;border-radius:7px;place-items:center;padding:0;transition:color .16s,border-color .16s,background .16s;display:inline-grid}.iconbtn:hover{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 50%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 10%, var(--mt-surface))}.copybtn--icon.is-copied{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 55%, var(--mt-border))}.sheet__tool{align-items:center;gap:9px;display:inline-flex}.chart{width:100%;font-family:var(--mt-mono)}.chart .recharts-cartesian-grid line{stroke:color-mix(in srgb, var(--mt-border) 80%, transparent)}.chart .recharts-text,.chart text{fill:var(--mt-text-faint)}.chart .recharts-surface:focus,.chart svg:focus{outline:none}.chart-tip{background:color-mix(in srgb, var(--mt-surface) 96%, transparent);border:1px solid var(--mt-border-strong);border-radius:var(--mt-radius-sm);font-family:var(--mt-mono);min-width:120px;padding:8px 10px;font-size:11.5px;box-shadow:0 8px 24px #00000073}.chart-tip__label{color:var(--mt-text-dim);margin-bottom:5px;font-size:10.5px}.chart-tip__row{align-items:center;gap:7px;display:flex}.chart-tip__dot{border-radius:3px;flex:none;width:9px;height:9px}.chart-tip__name{color:var(--mt-text-dim);text-transform:capitalize}.chart-tip__val{color:var(--mt-text);font-variant-numeric:tabular-nums;margin-left:auto;font-weight:500}.chart--donut{flex-direction:column;flex:1;justify-content:center;align-items:center;gap:12px;display:flex}.chart-donut__svg{width:100%;max-width:200px}.chart-legend{font-family:var(--mt-mono);color:var(--mt-text-dim);flex-wrap:wrap;justify-content:center;gap:6px 14px;font-size:11px;display:flex}.chart-legend span{align-items:center;gap:6px;display:inline-flex}.chart-legend i{border-radius:3px;width:9px;height:9px}.chart-legend b{color:var(--mt-text);font-weight:500}.chart--spark{position:relative}.chart-spark__last{font-family:var(--mt-mono);z-index:1;font-size:10px;font-weight:600;position:absolute;top:0;right:2px}.gauge__radial{place-items:center;width:72px;height:72px;display:grid;position:relative}.gauge__pct{font-family:var(--mt-mono);pointer-events:none;place-items:center;font-size:13px;font-weight:700;display:grid;position:absolute;inset:0}.geist-btn{font-family:var(--mt-sans);border-radius:var(--mt-radius-sm);border:1px solid var(--mt-border-strong);background:var(--mt-surface);color:var(--mt-text);cursor:pointer;white-space:nowrap;transition:background .16s var(--ease), border-color .16s, color .16s, transform .1s var(--ease), box-shadow .16s;justify-content:center;align-items:center;gap:7px;font-size:13px;font-weight:500;line-height:1;display:inline-flex}.geist-btn--sm{padding:6px 11px;font-size:12px}.geist-btn--md{padding:9px 15px}.geist-btn:hover{border-color:var(--mt-text);transform:translateY(-1px)}.geist-btn:active{transform:translateY(0)}.geist-btn:disabled{opacity:.5;cursor:not-allowed;transform:none}.geist-btn__icon{display:inline-flex}.geist-btn--accent{background:var(--page-accent);border-color:var(--page-accent);color:#0a0a0a;font-weight:600}.geist-btn--accent:hover{box-shadow:0 4px 16px color-mix(in srgb, var(--page-accent) 40%, transparent);border-color:var(--page-accent)}.geist-btn--success{border-color:color-mix(in srgb, var(--mt-good) 55%, var(--mt-border));color:var(--mt-good)}.geist-btn--warning{border-color:color-mix(in srgb, var(--mt-warn) 55%, var(--mt-border));color:var(--mt-warn)}.geist-btn--error{border-color:color-mix(in srgb, var(--mt-bad) 55%, var(--mt-border));color:var(--mt-bad)}.geist-btn--error:hover{background:color-mix(in srgb, var(--mt-bad) 14%, var(--mt-surface));border-color:var(--mt-bad)}.geist-btn--secondary{color:var(--mt-text-dim);border-color:var(--mt-border)}.geist-btn--ghost{background:0 0;border-color:#0000}.geist-btn--ghost:hover{background:color-mix(in srgb, var(--mt-text) 7%, transparent);border-color:var(--mt-border)}.geist-note{border-radius:var(--mt-radius-sm);border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text-dim);padding:11px 14px;font-size:13px;line-height:1.55}.geist-note__label{color:var(--mt-text);text-transform:capitalize}.geist-note--secondary{border-color:color-mix(in srgb, var(--page-accent) 30%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 7%, var(--mt-surface))}.geist-note--success{border-color:color-mix(in srgb, var(--mt-good) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-good) 8%, var(--mt-surface))}.geist-note--success .geist-note__label{color:var(--mt-good)}.geist-note--warning{border-color:color-mix(in srgb, var(--mt-warn) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-warn) 8%, var(--mt-surface))}.geist-note--warning .geist-note__label{color:var(--mt-warn)}.geist-note--error{border-color:color-mix(in srgb, var(--mt-bad) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-bad) 8%, var(--mt-surface))}.geist-note--error .geist-note__label{color:var(--mt-bad)}.geist-badge{font-family:var(--mt-mono);border:1px solid var(--mt-border);background:var(--mt-surface-2);color:var(--mt-text-dim);border-radius:999px;align-items:center;gap:5px;padding:2px 8px;font-size:10.5px;font-weight:500;display:inline-flex}.geist-badge--accent{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 40%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 12%, transparent)}.geist-badge--success{color:var(--mt-good);border-color:color-mix(in srgb, var(--mt-good) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-good) 10%, transparent)}.geist-badge--warning{color:var(--mt-warn);border-color:color-mix(in srgb, var(--mt-warn) 40%, var(--mt-border))}.geist-badge--error{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-bad) 10%, transparent)}.geist-dot{background:var(--mt-text-faint);border-radius:999px;flex:none;width:9px;height:9px;display:inline-block}.geist-dot--success{background:var(--mt-good)}.geist-dot--warning{background:var(--mt-warn)}.geist-dot--error{background:var(--mt-bad)}.geist-dot--accent{background:var(--page-accent)}.geist-dot.is-pulse{box-shadow:0 0 0 0 color-mix(in srgb, currentColor 60%, transparent);animation:1.8s infinite geist-pulse}@keyframes geist-pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--mt-good) 55%, transparent)}70%{box-shadow:0 0 0 7px #0000}to{box-shadow:0 0 #0000}}.geist-spinner{width:16px;height:16px;display:inline-block;position:relative}.geist-spinner--sm{width:13px;height:13px}.geist-spinner span{transform-origin:50% 178%;opacity:.15;background:currentColor;border-radius:2px;width:8%;height:28%;animation:1.2s linear infinite geist-spin;position:absolute;top:0;left:46%}@keyframes geist-spin{0%{opacity:1}to{opacity:.15}}.geist-input,.geist-select{font-family:var(--mt-mono);color:var(--mt-text);background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);padding:8px 11px;font-size:12.5px;transition:border-color .16s,box-shadow .16s}.geist-input:focus,.geist-select:focus{border-color:var(--page-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--page-accent) 22%, transparent);outline:none}.geist-card{border:1px solid var(--mt-border);border-radius:var(--mt-radius);background:var(--mt-surface);padding:16px}.geist-card.is-hoverable{transition:border-color .18s, transform .18s var(--ease)}.geist-card.is-hoverable:hover{border-color:color-mix(in srgb, var(--page-accent) 40%, var(--mt-border));transform:translateY(-2px)}.geist-tooltip{display:inline-flex;position:relative}.geist-tooltip__pop{border-radius:var(--mt-radius-sm);background:var(--mt-surface);border:1px solid var(--mt-border-strong);color:var(--mt-text);font-family:var(--mt-mono);white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .16s, transform .16s var(--ease);z-index:60;padding:6px 10px;font-size:11.5px;position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%,4px);box-shadow:0 8px 24px #00000073}.geist-tooltip:hover .geist-tooltip__pop,.geist-tooltip:focus-visible .geist-tooltip__pop{opacity:1;transform:translate(-50%)}.clients-toolbar{align-items:center;gap:8px;display:flex}.clients-toolbar .geist-input{width:200px}.clients-counts{margin-bottom:10px;font-size:12px}.clients-error{margin-bottom:10px}.clients-table{flex-direction:column;gap:2px;display:flex}.clients-row{border-radius:var(--mt-radius-sm);cursor:pointer;grid-template-columns:120px 1.3fr 150px 80px 130px minmax(280px,auto);align-items:center;gap:10px;padding:8px 10px;font-size:13px;display:grid}.clients-row--head{cursor:default;color:var(--mt-text-faint);text-transform:uppercase;letter-spacing:.04em;font-size:11px}.clients-row:not(.clients-row--head):hover{background:var(--mt-surface-2)}.clients-row.is-selected{background:color-mix(in srgb, var(--page-accent) 14%, var(--mt-surface-2))}.clients-row.is-blocked .clients-ip,.clients-row.is-blocked .clients-name{color:var(--mt-text-faint);text-decoration:line-through}.clients-ip,.clients-name{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.clients-mac{color:var(--mt-text-dim);font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:11.5px}.clients-badges{align-items:center;gap:6px;display:flex;overflow:hidden}.clients-actions,.clients-actions-h{justify-content:flex-end;gap:6px;display:flex}.clients-detail{border-top:1px solid var(--mt-border);margin-top:14px;padding-top:14px}.clients-detail__hd{flex-wrap:wrap;align-items:baseline;gap:12px;margin-bottom:10px;display:flex}.clients-detail__title{font-size:14px;font-weight:600}.clients-rates{font-variant-numeric:tabular-nums;gap:18px;margin-bottom:8px;display:flex}.clients-rates .rate{font-weight:600}.clients-rates .rate.rx{color:var(--lime)}.clients-rates .rate.tx{color:var(--amber)}.clients-chart{background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);width:100%;max-width:520px;height:150px;display:block}.clients-chart .line{fill:none;stroke-width:2px}.clients-chart .rx.line{stroke:var(--lime)}.clients-chart .tx.line{stroke:var(--amber)}.clients-chart .rx.area{fill:color-mix(in srgb, var(--lime) 18%, transparent);stroke:none}.clients-chart .tx.area{fill:color-mix(in srgb, var(--amber) 14%, transparent);stroke:none}.clients-totals{font-variant-numeric:tabular-nums;margin-top:8px;font-size:12px}.clients-edit{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-surface-2);flex-wrap:wrap;align-items:center;gap:8px;margin-top:14px;padding:10px 12px;display:flex}.clients-edit__label{color:var(--mt-text-dim);font-size:13px}.clients-edit .geist-input{width:220px}.aaa-tabs{border-bottom:1px solid var(--mt-border);flex-wrap:wrap;gap:4px;margin-bottom:14px;display:flex}.aaa-tab{appearance:none;color:var(--mt-text-dim);font:inherit;cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;margin-bottom:-1px;padding:7px 12px;font-size:13px}.aaa-tab:hover{color:var(--mt-text)}.aaa-tab.is-active{color:var(--mt-text);border-bottom-color:var(--page-accent)}.aaa-entity__toolbar{align-items:center;gap:10px;margin-bottom:12px;display:flex}.aaa-filter{width:200px}.aaa-error{margin-bottom:10px}.aaa-empty{padding:20px 4px}.aaa-table{flex-direction:column;gap:2px;display:flex}.aaa-table--scroll{overflow-x:auto}.aaa-row{border-radius:var(--mt-radius-sm);align-items:center;gap:10px;padding:8px 10px;font-size:13px;display:grid}.aaa-row--head{color:var(--mt-text-faint);text-transform:uppercase;letter-spacing:.04em;font-size:11px}.aaa-row:not(.aaa-row--head):hover{background:var(--mt-surface-2)}.aaa-row.is-off .aaa-cell{color:var(--mt-text-faint)}.aaa-row--sessions{grid-template-columns:repeat(9,minmax(90px,1fr));min-width:900px}.aaa-cell{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.aaa-actions,.aaa-actions-h{justify-content:flex-end;gap:6px;display:flex}.aaa-form,.aaa-singleton{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-surface-2);margin-bottom:14px;padding:14px}.aaa-form__title,.aaa-singleton__title{margin-bottom:10px;font-size:13px;font-weight:600}.aaa-singleton__current{margin-bottom:12px;font-size:12px}.aaa-form__grid{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px 14px;display:grid}.aaa-field{flex-direction:column;gap:4px;display:flex}.aaa-field__label{color:var(--mt-text-dim);font-size:11.5px}.aaa-form__actions{align-items:center;gap:10px;margin-top:14px;display:flex}.aaa-settings{flex-direction:column;gap:8px;display:flex}.clients-limits{border-top:1px solid var(--mt-border);max-width:520px;margin-top:14px;padding-top:12px}.clients-limits__hd{align-items:baseline;gap:12px;margin-bottom:8px;display:flex}.clients-limits__label{font-size:13px;font-weight:600}.clients-limits__row{flex-wrap:wrap;align-items:flex-end;gap:8px;display:flex}.clients-limits__field{flex-direction:column;gap:3px;font-size:11.5px;display:flex}.clients-limits__field .geist-input{width:150px}.clients-limits__msg{margin-top:6px;font-size:12px}.usage-chart__empty{padding:16px 4px;font-size:12.5px}.usage-chart__legend{font-variant-numeric:tabular-nums;align-items:baseline;gap:14px;margin-bottom:6px;font-size:12px;display:flex}.usage-chart__legend .rate{font-weight:600}.usage-chart__legend .rate.rx{color:var(--lime)}.usage-chart__legend .rate.tx{color:var(--amber)}.usage-chart__svg{background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);width:100%;height:160px;display:block}.usage-chart__svg .line{fill:none;stroke-width:2px;vector-effect:non-scaling-stroke}.usage-chart__svg .rx.line{stroke:var(--lime)}.usage-chart__svg .tx.line{stroke:var(--amber)}.usage-chart__svg .rx.area{fill:color-mix(in srgb, var(--lime) 18%, transparent);stroke:none}.usage-chart__svg .tx.area{fill:color-mix(in srgb, var(--amber) 14%, transparent);stroke:none}.clients-history,.aaa-usage__section{margin-top:16px}.clients-history__hd,.aaa-usage__title{color:var(--mt-text-dim);margin-bottom:8px;font-size:12px;font-weight:600}.aaa-usage__bar{align-items:center;gap:8px;margin-bottom:12px;display:flex}.heatmap__hd{align-items:baseline;gap:10px;margin-bottom:6px;display:flex}.heatmap__title{font-size:12.5px;font-weight:600}.heatmap__scroll{padding-bottom:4px;overflow-x:auto}.heatmap__svg{display:block}.heatmap__month,.heatmap__wd{fill:var(--mt-text-dim);font-family:inherit;font-size:9px}.heatmap{position:relative}.heatmap__cell{stroke:color-mix(in srgb, var(--mt-border) 60%, transparent);stroke-width:1px;cursor:pointer;transition:stroke .1s}.heatmap__cell.is-hover{stroke:var(--mt-text);stroke-width:1.5px}.heatmap__tip{z-index:30;background:linear-gradient(180deg, color-mix(in srgb, var(--mt-surface-2) 92%, var(--lime)), var(--mt-surface-2));border:1px solid color-mix(in srgb, var(--lime) 35%, var(--mt-border));pointer-events:none;min-width:150px;animation:heatmap-tip-in .12s var(--ease);border-radius:10px;padding:8px 10px;position:absolute;transform:translate(-50%,calc(-100% - 9px));box-shadow:0 8px 24px #00000073}.heatmap__tip:after{content:"";background:var(--mt-surface-2);border-right:1px solid color-mix(in srgb, var(--lime) 35%, var(--mt-border));border-bottom:1px solid color-mix(in srgb, var(--lime) 35%, var(--mt-border));width:11px;height:11px;position:absolute;bottom:-6px;left:50%;transform:translate(-50%)rotate(45deg)}@keyframes heatmap-tip-in{0%{opacity:0;transform:translate(-50%,calc(-100% - 3px))}to{opacity:1;transform:translate(-50%,calc(-100% - 9px))}}.heatmap__tip-head{align-items:center;gap:7px;font-size:13px;display:flex}.heatmap__tip-head b{font-weight:600}.heatmap__tip-head .heatmap__swatch{width:12px;height:12px}.heatmap__tip-date{color:var(--mt-text-dim);font-variant-numeric:tabular-nums;margin-top:3px;font-size:11.5px}.heatmap__cell.lvl0,.heatmap__swatch.lvl0{fill:var(--mt-surface-2);background:var(--mt-surface-2)}.heatmap__cell.lvl1,.heatmap__swatch.lvl1{fill:color-mix(in srgb, var(--lime) 30%, var(--mt-surface-2));background:color-mix(in srgb, var(--lime) 30%, var(--mt-surface-2))}.heatmap__cell.lvl2,.heatmap__swatch.lvl2{fill:color-mix(in srgb, var(--lime) 50%, var(--mt-surface-2));background:color-mix(in srgb, var(--lime) 50%, var(--mt-surface-2))}.heatmap__cell.lvl3,.heatmap__swatch.lvl3{fill:color-mix(in srgb, var(--lime) 72%, transparent);background:color-mix(in srgb, var(--lime) 72%, transparent)}.heatmap__cell.lvl4,.heatmap__swatch.lvl4{fill:var(--lime);background:var(--lime)}.heatmap__legend{align-items:center;gap:4px;margin-top:8px;font-size:11px;display:flex}.heatmap__swatch{border-radius:2px;width:11px;height:11px;display:inline-block}.input{font:12px var(--mt-mono);color:var(--mt-text);background:var(--mt-surface-2);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);width:min(52vw,420px);padding:6px 10px}.input:focus{border-color:color-mix(in srgb, var(--mt-accent) 55%, var(--mt-border));outline:none}.btn-sm{padding:3px 8px;font-size:10px}.mod-toolbar{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:6px;display:flex}.mod-groups{flex-direction:column;gap:18px;margin-top:12px;display:flex}.mod-group__hd{border-bottom:1px solid var(--mt-border);align-items:center;gap:10px;margin-bottom:8px;padding-bottom:6px;display:flex}.mod-group__title{color:var(--mt-text);margin:0;font-size:13px;font-weight:600}.mod-list{grid-template-columns:repeat(auto-fill,minmax(min(100%,360px),1fr));gap:8px;display:grid}.mod-row{background:var(--mt-surface-2);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);cursor:pointer;-webkit-user-select:none;user-select:none;align-items:flex-start;gap:10px;padding:9px 11px;transition:border-color .18s,background .18s;display:flex}.mod-row:hover{border-color:color-mix(in srgb, var(--mt-accent) 35%, var(--mt-border))}.mod-row[data-on]{border-color:color-mix(in srgb, var(--mt-accent) 50%, var(--mt-border));background:color-mix(in srgb, var(--mt-accent) 10%, var(--mt-surface-2))}.mod-row input{accent-color:var(--mt-accent);cursor:pointer;margin:2px 0 0}.mod-row__main{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.mod-row__name{color:var(--mt-text);flex-wrap:wrap;align-items:center;gap:7px;font-size:12px;font-weight:600;display:flex}.mod-row__slug{font:10px var(--mt-mono);color:var(--mt-text-dim);background:var(--mt-bg);border:1px solid var(--mt-border);border-radius:4px;padding:1px 5px}.mod-row__desc{font-size:11px;line-height:1.35}.mod-row__count{font:10px var(--mt-mono);white-space:nowrap;padding-top:1px}.conn-tunnel-halo{fill:none;stroke-width:8px;stroke-linecap:round;opacity:.1}.conn-tunnel{fill:none;stroke-width:2.4px;stroke-linecap:round;stroke-dasharray:6 6;animation:.9s linear infinite conn-tunnel-flow}@keyframes conn-tunnel-flow{to{stroke-dashoffset:-24px}}.conn-tunnel-lock{filter:drop-shadow(0 0 4px #f59e0bcc)}.conn-tunnel-sat{stroke-width:1.5px;filter:drop-shadow(0 0 5px #f59e0b88)}.conn-tunnel-badge{fill:#30220a;stroke:color-mix(in srgb, #f59e0b 60%, var(--mt-border));stroke-width:1px}.conn-tunnel-badge-tx{fill:#fbbf24;font-family:var(--mt-mono);letter-spacing:.02em;font-weight:700}.jump-route{background:color-mix(in srgb, #f59e0b 7%, var(--mt-surface-2));border:1px solid color-mix(in srgb, #f59e0b 28%, var(--mt-border));font:10px var(--mt-mono);border-radius:10px;align-items:center;gap:6px;margin:10px 0 2px;padding:7px 9px;display:flex;overflow:hidden}.jump-route__hop{background:var(--mt-bg);border:1px solid var(--mt-border);color:var(--mt-text);white-space:nowrap;border-radius:7px;align-items:center;gap:5px;padding:3px 8px;display:inline-flex}.jump-route__hop--src{padding:3px 7px;font-size:12px}.jump-route__hop--bastion{border-color:color-mix(in srgb, #f59e0b 60%, var(--mt-border));color:#fbbf24;box-shadow:0 0 10px -3px #f59e0b99}.jump-route__tag{text-transform:uppercase;letter-spacing:.08em;color:#0a0a0a;background:#f59e0b;border-radius:4px;padding:1px 4px;font-size:7px;font-style:normal}.jump-route__wire{background-image:linear-gradient(90deg, var(--mt-border) 0 50%, transparent 50% 100%);background-size:8px 2px;border-radius:2px;flex:1;min-width:18px;height:2px;animation:.7s linear infinite jump-wire}.jump-route__wire--enc{background-image:linear-gradient(90deg,#f59e0b 0 55%,#0000 55% 100%);background-size:10px 3px;min-width:34px;height:3px;position:relative;box-shadow:0 0 8px -1px #f59e0b88}.jump-route__lock{filter:drop-shadow(0 0 3px #f59e0b);font-size:11px;animation:2.2s linear infinite jump-lock;position:absolute;top:50%}@keyframes jump-wire{to{background-position:8px 0}}@keyframes jump-lock{0%{left:-4px;transform:translateY(-50%)scale(.9)}50%{transform:translateY(-50%)scale(1.1)}to{left:calc(100% - 8px);transform:translateY(-50%)scale(.9)}}@media (prefers-reduced-motion:reduce){.conn-tunnel,.jump-route__wire,.jump-route__wire--enc,.jump-route__lock{animation:none}.conn-tunnel-lock animatemotion{display:none}}
84
+ @import "https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap";@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:var(--mt-sans);--font-mono:var(--mt-mono)}}@layer base,components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.isolate{isolation:isolate}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.table{display:table}.shrink{flex-shrink:1}.grow{flex-grow:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.rounded{border-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}}:root{--background:#0a0a0a;--foreground:#ededed;--card:#111;--card-foreground:#ededed;--popover:#111;--popover-foreground:#ededed;--primary:#ededed;--primary-foreground:#0a0a0a;--secondary:#1a1a1a;--secondary-foreground:#ededed;--muted:#1a1a1a;--muted-foreground:#a1a1a1;--accent:var(--page-accent,#3291ff);--accent-foreground:#0a0a0a;--destructive:#ff5c5c;--destructive-foreground:#fff;--success:#2dd4a7;--warning:#f5a623;--border:#2a2a2a;--input:#2a2a2a;--ring:var(--page-accent,#3291ff);--radius:.5rem}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}:root{--mt-bg:var(--color-background-primary,#0b0d10);--mt-surface:var(--color-background-secondary,#14171c);--mt-surface-2:var(--color-background-tertiary,#1b1f26);--mt-border:var(--color-border-primary,#262b33);--mt-text:var(--color-text-primary,#e8eaed);--mt-text-dim:var(--color-text-secondary,#9aa3af);--mt-text-faint:var(--color-text-tertiary,#6b7280);--mt-accent:var(--color-accent-primary,#6ea8fe);--mt-good:#34d399;--mt-warn:#fbbf24;--mt-bad:#f87171;--mt-radius:var(--border-radius-md,14px);--mt-radius-sm:var(--border-radius-sm,9px);--mt-mono:var(--font-mono,ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace);--mt-sans:var(--font-sans,system-ui, -apple-system, "Segoe UI", sans-serif);--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}*{box-sizing:border-box}body{background:var(--mt-bg);color:var(--mt-text);font-family:var(--mt-sans);-webkit-font-smoothing:antialiased;margin:0;padding:16px;font-size:13px;line-height:1.5}.app{gap:14px;max-width:960px;margin:0 auto;display:grid}.hd{flex-wrap:wrap;align-items:center;gap:12px;display:flex}.hd__dot{background:var(--mt-good);width:9px;height:9px;box-shadow:0 0 0 4px color-mix(in srgb, var(--mt-good) 22%, transparent);border-radius:50%}.hd__title{letter-spacing:-.01em;margin:0;font-size:17px;font-weight:650}.hd__sub{color:var(--mt-text-dim);font-family:var(--mt-mono);margin:0;font-size:12px}.hd__spacer{flex:1}.pill{border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text-dim);font-family:var(--mt-mono);border-radius:999px;align-items:center;gap:6px;padding:3px 9px;font-size:11px;display:inline-flex}.pill b{color:var(--mt-text);font-weight:600}.grid{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;display:grid}.card{background:linear-gradient(180deg, var(--mt-surface), var(--mt-surface-2));border:1px solid var(--mt-border);border-radius:var(--mt-radius);padding:14px}.card__label{color:var(--mt-text-dim);text-transform:uppercase;letter-spacing:.06em;margin:0 0 8px;font-size:11px}.card__value{font-family:var(--mt-mono);letter-spacing:-.01em;font-size:20px;font-weight:600}.toolbar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.toolbar .grow{flex:1;min-width:140px}.search{appearance:none;border:1px solid var(--mt-border);background:var(--mt-surface);width:100%;color:var(--mt-text);font:inherit;border-radius:var(--mt-radius-sm);padding:7px 11px;font-size:13px}.search:focus{border-color:var(--mt-accent);outline:none}.search::placeholder{color:var(--mt-text-faint)}.btn{appearance:none;border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text);font:inherit;border-radius:var(--mt-radius-sm);cursor:pointer;white-space:nowrap;padding:6px 11px;font-size:12px;transition:border-color .15s,background .15s}.btn:disabled{opacity:.5;cursor:default}.btn.is-active{border-color:var(--mt-accent);color:var(--mt-accent)}.chip{border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text-dim);font-family:var(--mt-mono);border-radius:999px;align-items:center;gap:4px;padding:1px 7px;font-size:11px;display:inline-flex}.chip.is-good{color:var(--mt-good);border-color:color-mix(in srgb, var(--mt-good) 45%, var(--mt-border))}.chip.is-warn{color:var(--mt-warn);border-color:color-mix(in srgb, var(--mt-warn) 45%, var(--mt-border))}.chip.is-bad{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border))}.tablewrap{border:1px solid var(--mt-border);border-radius:var(--mt-radius);max-height:70vh;overflow:auto}table.tbl{border-collapse:collapse;width:100%;font-size:12px}table.tbl th,table.tbl td{text-align:left;border-bottom:1px solid color-mix(in srgb, var(--mt-border) 55%, transparent);white-space:nowrap;font-family:var(--mt-mono);padding:7px 12px}table.tbl thead th{z-index:1;background:var(--mt-surface-2);color:var(--mt-text-dim);cursor:pointer;-webkit-user-select:none;user-select:none;font-weight:600;position:sticky;top:0}table.tbl thead th:hover{color:var(--mt-text)}table.tbl thead th .arrow{color:var(--mt-accent);margin-left:4px}table.tbl tbody tr{cursor:pointer}table.tbl tbody tr:hover{background:color-mix(in srgb, var(--mt-accent) 8%, transparent)}table.tbl tbody tr.is-disabled td,table.tbl td.col-num{color:var(--mt-text-faint)}.kv__body{border:1px solid var(--mt-border);border-radius:var(--mt-radius);grid-template-columns:minmax(120px,.4fr) 1fr;display:grid;overflow:hidden}.kv__body>div{border-bottom:1px solid color-mix(in srgb, var(--mt-border) 55%, transparent);overflow-wrap:anywhere;min-width:0;font-size:12px;font-family:var(--mt-mono);padding:7px 14px}.kv__k{color:var(--mt-text-dim);background:color-mix(in srgb, var(--mt-surface) 60%, transparent)}.kv__v{color:var(--mt-text)}.drawer{border:1px solid var(--mt-accent);border-radius:var(--mt-radius);background:var(--mt-surface);gap:10px;padding:12px;display:grid}.drawer__hd{align-items:center;gap:8px;display:flex}.drawer__hd b{font-family:var(--mt-mono)}pre.raw{border:1px solid var(--mt-border);border-radius:var(--mt-radius);background:var(--mt-surface);color:var(--mt-text);font-family:var(--mt-mono);white-space:pre;max-height:70vh;margin:0;padding:14px;font-size:12px;overflow:auto}.foot{color:var(--mt-text-faint);font-size:11px;font-family:var(--mt-mono);flex-wrap:wrap;align-items:center;gap:10px;display:flex}.foot .grow{flex:1}.skeleton,.empty{color:var(--mt-text-faint);text-align:center;padding:40px 0}:root{--mt-sans:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;--mt-mono:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;--mt-display:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;--mt-bg:#0a0a0a;--mt-surface:#111;--mt-surface-2:#1a1a1a;--mt-border:#2a2a2a;--mt-border-strong:#3a3a3a;--mt-text:#ededed;--mt-text-dim:#a1a1a1;--mt-text-faint:#6e6e6e;--mt-good:#d4d4d8;--mt-warn:#a1a1a1;--mt-bad:#ff5c5c;--mt-radius:12px;--mt-radius-sm:8px;--sky:#3291ff;--teal:#2dd4bf;--cyan:#45d4ee;--lime:#69d05a;--coral:#ff5c5c;--amber:#f5a623;--pink:#ff4d8d;--violet:#9d7bff;--page-accent:#3291ff;--page-accent-2:#2dd4bf;--mt-accent:var(--page-accent);--grad:linear-gradient(115deg, var(--page-accent), var(--page-accent-2) 90%);--ease:cubic-bezier(.22, 1, .36, 1);--glass:#111111b8}html,body{background:var(--mt-bg);color:var(--mt-text);font-family:var(--mt-sans);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;margin:0;padding:0}body:after{content:"";z-index:-2;background-image:linear-gradient(color-mix(in srgb, var(--mt-border) 55%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--mt-border) 55%, transparent) 1px, transparent 1px);opacity:.32;pointer-events:none;background-size:52px 52px;position:fixed;inset:0;-webkit-mask-image:radial-gradient(circle at 50% 0,#000,#0000 72%);mask-image:radial-gradient(circle at 50% 0,#000,#0000 72%)}.main:before{content:"";z-index:-1;background:radial-gradient(52% 38% at 18% -8%, color-mix(in srgb, var(--page-accent) 14%, transparent), transparent 70%), radial-gradient(46% 36% at 100% 4%, color-mix(in srgb, var(--page-accent-2) 11%, transparent), transparent 68%);opacity:.9;transition:background .5s var(--ease);pointer-events:none;position:fixed;inset:0}.shell{grid-template-columns:250px minmax(0,1fr);align-items:start;min-height:100vh;display:grid}.nav{border-right:1px solid var(--mt-border);background:color-mix(in srgb, var(--mt-surface) 55%, transparent);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);flex-direction:column;gap:10px;height:100vh;padding:18px 14px;display:flex;position:sticky;top:0}.nav__brand{align-items:center;gap:11px;padding:6px 8px 14px;display:flex}.nav__mark{background:var(--grad);width:38px;height:38px;box-shadow:0 6px 20px color-mix(in srgb, var(--page-accent) 34%, transparent);transition:background .4s var(--ease), box-shadow .4s var(--ease);border-radius:11px;flex:none;place-items:center;display:grid}.nav__mark svg{width:22px;height:22px;display:block}.nav__brandtext{flex-direction:column;min-width:0;line-height:1.1;display:flex}.nav__brandtext b{font-family:var(--mt-display);letter-spacing:-.03em;font-size:15px;font-weight:700}.nav__brandtext small{font-family:var(--mt-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--mt-text-dim);margin-top:3px;font-size:10px}.nav__items{flex-direction:column;flex:1;gap:3px;display:flex}.nav__item{color:var(--mt-text-dim);font-family:var(--mt-sans);cursor:pointer;text-align:left;transition:background .18s var(--ease), color .18s, border-color .18s, transform .18s var(--ease);background:0 0;border:1px solid #0000;border-radius:11px;align-items:center;gap:11px;padding:10px 12px;font-size:13px;font-weight:500;display:flex}.nav__item svg{opacity:.85;flex:none;width:18px;height:18px}.nav__item:hover{color:var(--mt-text);background:color-mix(in srgb, var(--mt-text) 7%, transparent)}.nav__item.is-active{color:var(--mt-text);border-color:color-mix(in srgb, var(--page-accent) 36%, var(--mt-border));background:linear-gradient(100deg, color-mix(in srgb, var(--page-accent) 16%, transparent), color-mix(in srgb, var(--page-accent-2) 7%, transparent))}.nav__item.is-active svg{opacity:1;color:var(--page-accent)}.nav__item.is-active:before{content:"";background:var(--page-accent);width:3px;box-shadow:0 0 12px color-mix(in srgb, var(--page-accent) 70%, transparent);border-radius:999px;position:absolute;top:18%;bottom:18%;left:-1px}.nav__item{position:relative}.nav__badge{font-family:var(--mt-mono);background:color-mix(in srgb, var(--page-accent) 24%, transparent);color:var(--mt-text);border-radius:999px;margin-left:auto;padding:1px 7px;font-size:10px;animation:.4s cubic-bezier(.19,1,.22,1) nav-badge-pop;display:inline-block}@keyframes nav-badge-pop{0%{transform:scale(1)}35%{background:color-mix(in srgb, var(--page-accent) 60%, transparent);transform:scale(1.35)}to{transform:scale(1)}}@media (prefers-reduced-motion:reduce){.nav__badge{animation:none}}.nav__foot{border-top:1px solid var(--mt-border);flex-direction:column;gap:8px;padding:10px 8px 2px;display:flex}.main{align-content:start;gap:18px;min-width:0;padding:22px clamp(16px,3vw,44px) 64px;display:grid}.topline{flex-wrap:wrap;align-items:center;gap:14px;display:flex}.topline__txt h1{font-family:var(--mt-display);letter-spacing:-.03em;background:linear-gradient(100deg, var(--mt-text) 30%, color-mix(in srgb, var(--page-accent) 78%, var(--mt-text)));-webkit-text-fill-color:transparent;transition:background .4s var(--ease);-webkit-background-clip:text;background-clip:text;margin:0;font-size:clamp(20px,2.4vw,28px);font-weight:700;line-height:1.15}.topline__txt small{color:var(--mt-text-dim);font-family:var(--mt-mono);margin-top:3px;font-size:12px;display:block}.topline__spacer{flex:1;min-width:8px}.help-toggle{border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text-dim);font-family:var(--mt-sans);cursor:pointer;transition:color .18s, border-color .18s, background .18s, transform .12s var(--ease);border-radius:999px;align-items:center;gap:7px;padding:7px 13px 7px 10px;font-size:12.5px;font-weight:500;display:inline-flex}.help-toggle:hover{color:var(--mt-text);border-color:var(--mt-border-strong);transform:translateY(-1px)}.help-toggle.is-on{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 45%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 12%, var(--mt-surface))}.help-toggle__q{background:color-mix(in srgb, var(--page-accent) 22%, transparent);width:17px;height:17px;color:var(--page-accent);border-radius:999px;place-items:center;font-size:11px;font-weight:700;display:grid}.pagehelp{border-radius:var(--mt-radius);border:1px solid color-mix(in srgb, var(--page-accent) 28%, var(--mt-border));background:linear-gradient(120deg, color-mix(in srgb, var(--page-accent) 9%, var(--mt-surface)), var(--mt-surface) 60%);gap:14px;padding:16px 18px;display:flex}.pagehelp__icon{color:#0a0a0a;background:var(--grad);width:30px;height:30px;box-shadow:0 4px 14px color-mix(in srgb, var(--page-accent) 35%, transparent);border-radius:9px;flex:none;place-items:center;font-size:15px;font-weight:700;display:grid}.pagehelp__body{min-width:0}.pagehelp__what{color:var(--mt-text);margin:2px 0 8px;font-size:13.5px;line-height:1.55}.pagehelp__tips{gap:4px;margin:0;padding-left:18px;display:grid}.pagehelp__tips li{color:var(--mt-text-dim);font-size:12.5px;line-height:1.5}.pagehelp__tips li::marker{color:var(--page-accent)}.view{align-content:start;gap:18px;display:grid}.bento{grid-template-columns:repeat(6,1fr);gap:18px;display:grid}.bento .panel{margin:0}.b-series{grid-column:span 4}.b-risk{grid-column:span 2}.b-tools,.b-status,.b-device,.b-errors{grid-column:span 3}.b-risk,.b-status{flex-direction:column;display:flex}@media (width<=1040px){.bento{grid-template-columns:repeat(2,1fr)}.b-series,.b-risk,.b-tools,.b-status,.b-device,.b-errors{grid-column:span 2}}@media (width<=900px){.shell{grid-template-columns:1fr}.nav{border-right:0;border-bottom:1px solid var(--mt-border);z-index:5;flex-direction:row;align-items:center;gap:8px;height:auto;padding:10px 12px;position:sticky;top:0;overflow-x:auto}.nav__brand{padding:0 6px 0 2px}.nav__brandtext{display:none}.nav__items{flex-direction:row;flex:1;gap:4px}.nav__item span{display:none}.nav__item{padding:9px 11px}.nav__foot{border-top:0;flex-direction:row;align-items:center;padding:0}.nav__foot .muted{display:none}}@media (width<=560px){.nav__brand{display:none}}@media (prefers-reduced-motion:no-preference){.js-motion .reveal{opacity:0}}.hero__live{border:1px solid var(--mt-border);background:var(--glass);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);font-family:var(--mt-mono);letter-spacing:.04em;text-transform:uppercase;color:var(--mt-text-dim);border-radius:999px;align-items:center;gap:7px;padding:7px 13px;font-size:11px;display:inline-flex}.hero__live .dot{background:var(--mt-bad);border-radius:50%;width:8px;height:8px;transition:background .3s}.hero__live.is-ws{--lc:#34d399}.hero__live.is-sse{--lc:#f59e0b}.hero__live.is-on{color:var(--mt-text);border-color:color-mix(in srgb, var(--lc,var(--mt-good)) 40%, var(--mt-border))}.hero__live.is-on .dot{background:var(--lc,var(--mt-good));box-shadow:0 0 0 4px color-mix(in srgb, var(--lc,var(--mt-good)) 22%, transparent);animation:1.8s ease-out infinite hero-pulse}@keyframes hero-pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--lc,var(--mt-good)) 55%, transparent)}70%{box-shadow:0 0 0 9px color-mix(in srgb, var(--lc,var(--mt-good)) 0%, transparent)}to{box-shadow:0 0 0 0 color-mix(in srgb, var(--lc,var(--mt-good)) 0%, transparent)}}.panel>h2,.sheet__hd h2{font-family:var(--mt-sans)}.cards{grid-template-columns:repeat(2,1fr);gap:12px;display:grid}@media (width>=560px){.cards{grid-template-columns:repeat(4,1fr)}}@media (width>=1040px){.cards{grid-template-columns:repeat(8,1fr)}}.stat{background:linear-gradient(180deg, var(--mt-surface), color-mix(in srgb, var(--mt-surface-2) 80%, transparent));border:1px solid var(--mt-border);border-radius:var(--mt-radius);transition:transform .3s var(--ease), border-color .3s var(--ease);padding:14px 15px;position:relative;overflow:hidden}.stat:before{content:"";background:var(--grad);opacity:0;height:2px;transition:opacity .3s var(--ease);position:absolute;inset:0 0 auto}.stat:hover{border-color:color-mix(in srgb, var(--page-accent) 42%, var(--mt-border));transform:translateY(-3px)}.stat:hover:before{opacity:1}.stat .k{color:var(--mt-text-dim);text-transform:uppercase;letter-spacing:.08em;margin:0 0 7px;font-size:10px}.stat .v{font-family:var(--mt-mono);letter-spacing:-.02em;font-variant-numeric:tabular-nums;font-size:23px;font-weight:500}.stat .v small{color:var(--mt-text-dim);font-size:12px;font-weight:400}.stat.is-bad .v{color:var(--mt-bad)}.stat.is-warn .v{color:var(--mt-warn)}.stat.is-good .v{color:var(--mt-good)}.panel{background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius);transition:border-color .25s var(--ease);padding:18px;position:relative;box-shadow:0 1px 2px #0000004d,inset 0 1px #ffffff08}.panel:hover{border-color:color-mix(in srgb, var(--mt-text) 13%, var(--mt-border))}.panel>h2{color:var(--mt-text-dim);text-transform:uppercase;letter-spacing:.07em;align-items:center;gap:9px;margin:0 0 14px;font-size:12px;font-weight:600;display:inline-flex}.panel>h2:before,.sheet__hd h2:first-child:before{content:"";background:var(--grad);border-radius:2px;flex:none;width:3px;height:13px}.cols{grid-template-columns:1.4fr 1fr;gap:18px;display:grid}@media (width<=820px){.cols{grid-template-columns:1fr}}.cols-3{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px;display:grid}.cols-3 .panel{flex-direction:column;display:flex}.hbar{gap:9px;display:grid}.hbar__row{grid-template-columns:minmax(90px,.9fr) 2fr auto;align-items:center;gap:10px;font-size:12px;display:grid}.hbar__label{font-family:var(--mt-mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.hbar__track{background:color-mix(in srgb, var(--mt-surface-2) 90%, transparent);border-radius:999px;height:8px;overflow:hidden}.hbar__fill{background:var(--grad);height:100%;box-shadow:0 0 10px color-mix(in srgb, var(--teal) 45%, transparent);border-radius:999px}.hbar__val{font-family:var(--mt-mono);color:var(--mt-text-dim);text-align:right;font-variant-numeric:tabular-nums;font-size:11px}.legend{font-family:var(--mt-mono);color:var(--mt-text-dim);flex-wrap:wrap;gap:12px;margin-top:12px;font-size:11px;display:flex}.legend span{align-items:center;gap:5px;display:inline-flex}.legend i{border-radius:2px;width:9px;height:9px;display:inline-block}.risk{font-family:var(--mt-mono);color:var(--rc,var(--mt-text-dim));border:1px solid color-mix(in srgb, var(--rc,var(--mt-border)) 45%, var(--mt-border));background:color-mix(in srgb, var(--rc,transparent) 12%, transparent);text-transform:uppercase;letter-spacing:.04em;border-radius:999px;padding:1px 8px;font-size:10px;display:inline-block}.risk-READ{--rc:#34d399}.risk-WRITE{--rc:#3291ff}.risk-WRITE_IDEMPOTENT{--rc:#2dd4bf}.risk-DESTRUCTIVE{--rc:#f59e0b}.risk-DANGEROUS{--rc:#ef4444}.feed{border-collapse:collapse;width:100%;font-size:12px}.feed th,.feed td{text-align:left;border-bottom:1px solid color-mix(in srgb, var(--mt-border) 55%, transparent);white-space:nowrap;font-family:var(--mt-mono);padding:7px 11px}.feed thead th{background:color-mix(in srgb, var(--mt-surface-2) 96%, transparent);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);color:var(--mt-text-dim);text-transform:uppercase;letter-spacing:.05em;z-index:1;font-size:10px;font-weight:600;position:sticky;top:0}.feed tbody tr{cursor:pointer;transition:background .12s}.feed tbody tr:hover{background:color-mix(in srgb, var(--mt-accent) 9%, transparent)}.feed tbody tr.is-err{background:color-mix(in srgb, var(--mt-bad) 9%, transparent)}.feed tbody tr.is-selected{background:color-mix(in srgb, var(--mt-accent) 16%, transparent)}.feed td.preview{white-space:nowrap;text-overflow:ellipsis;max-width:320px;color:var(--mt-text-dim);overflow:hidden}.feed td.num{text-align:right;color:var(--mt-text-dim);font-variant-numeric:tabular-nums}.status-ok{color:var(--mt-good)}.status-err{color:var(--mt-bad)}.feedwrap{border:1px solid var(--mt-border);border-radius:var(--mt-radius);max-height:60vh;overflow:auto}.feed-empty{border:1px dashed var(--mt-border);border-radius:var(--mt-radius);text-align:center;justify-items:center;gap:8px;padding:54px 16px;display:grid}.feed-empty__icon{opacity:.8;font-size:28px}.feed-empty__title{color:var(--mt-text);margin:0;font-weight:600}.feed-empty__sub{max-width:460px;color:var(--mt-text-faint);margin:0;font-size:12px}.feed-empty .btn{margin-top:6px}.feed-empty__pulse{background:var(--mt-text-faint);border-radius:50%;width:12px;height:12px}.feed-empty__pulse.is-on{background:var(--mt-good);animation:1.6s ease-out infinite feed-pulse}@keyframes feed-pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--mt-good) 55%, transparent)}70%{box-shadow:0 0 0 12px color-mix(in srgb, var(--mt-good) 0%, transparent)}to{box-shadow:0 0 0 0 color-mix(in srgb, var(--mt-good) 0%, transparent)}}.conn{display:block;overflow:visible}.conn-grid{fill:none;stroke:var(--mt-border);stroke-opacity:.7;stroke-dasharray:2 7}.conn-sonar{fill:none;stroke:var(--mt-accent);stroke-width:1.5px;opacity:0;animation:3.3s ease-out infinite conn-sonar}@keyframes conn-sonar{0%{r:30px;opacity:.5}to{r:150px;opacity:0}}.conn-link{fill:none;stroke-width:1.6px;opacity:.38}.conn-flow{fill:none;stroke-width:2.4px;stroke-linecap:round;stroke-dasharray:2 13;opacity:.9;filter:drop-shadow(0 0 4px);animation:1.05s linear infinite conn-flow}@keyframes conn-flow{to{stroke-dashoffset:-60px}}.conn-packet{filter:drop-shadow(0 0 6px var(--teal))}.conn-hub-glow{fill:var(--mt-accent);opacity:.22;filter:blur(11px)}.conn-hub-ring{fill:none;stroke:var(--mt-accent);stroke-width:1.4px;stroke-dasharray:4 9;opacity:.7;transform-box:fill-box;transform-origin:50%;animation:15s linear infinite conn-rot}@keyframes conn-rot{to{transform:rotate(360deg)}}.conn-node-halo{fill:none;stroke-width:2px;transform-box:fill-box;transform-origin:50%;animation:2.4s ease-in-out infinite conn-halo}@keyframes conn-halo{0%,to{opacity:.45;transform:scale(1)}50%{opacity:0;transform:scale(1.55)}}.conn-blink{animation:1.6s ease-in-out infinite conn-blink}@keyframes conn-blink{0%,to{opacity:1}50%{opacity:.35}}.conn-node text{pointer-events:none}@media (prefers-reduced-motion:reduce){.conn-sonar,.conn-flow,.conn-hub-ring,.conn-node-halo,.conn-blink,.conn-packet animateMotion{animation:none}.conn-sonar{display:none}}.dev-grid{grid-template-columns:1fr;align-content:start;gap:12px;display:grid}@media (width>=600px) and (width<=819px){.dev-grid{grid-template-columns:1fr 1fr}}.dev-toolbar{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.dev-filters{border:1px solid var(--mt-border);background:color-mix(in srgb, var(--mt-surface-2) 70%, transparent);border-radius:999px;gap:4px;padding:3px;display:inline-flex}.dev-fbtn{appearance:none;color:var(--mt-text-dim);font:11px var(--mt-mono);cursor:pointer;white-space:nowrap;background:0 0;border:0;border-radius:999px;padding:5px 12px;transition:background .18s,color .18s}.dev-fbtn:hover{color:var(--mt-text)}.dev-fbtn.is-active{background:var(--grad);color:var(--mt-bg);font-weight:600}.dev-grid-wide{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));align-content:start;gap:14px;display:grid}.dev-collapse{border:1px solid var(--mt-border);border-radius:var(--mt-radius);background:var(--glass);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:6px 18px 18px}.dev-collapse>summary{cursor:pointer;text-transform:uppercase;letter-spacing:.07em;color:var(--mt-text-dim);align-items:center;gap:8px;padding:12px 0;font-size:12px;font-weight:600;list-style:none;display:flex}.dev-collapse>summary::-webkit-details-marker{display:none}.dev-collapse>summary:before{content:"▸";transition:transform .2s var(--ease);color:var(--teal);display:inline-block}.dev-collapse[open]>summary:before{transform:rotate(90deg)}.dev-card .dot--status{width:7px;height:7px}.dev-card{transition:transform .3s var(--ease), border-color .3s var(--ease);gap:8px;padding:14px 15px;display:grid}.dev-card:hover{border-color:color-mix(in srgb, var(--teal) 35%, var(--mt-border));transform:translateY(-2px)}.dev-card__top{align-items:center;gap:8px;display:flex}.dev-card__name{font-family:var(--mt-mono);font-size:13px;font-weight:500}.dev-card .dot{border-radius:50%;flex:none;width:9px;height:9px}.dev-card__meta{font-family:var(--mt-mono);color:var(--mt-text-dim);grid-template-columns:auto 1fr;gap:3px 12px;font-size:11px;display:grid}.dev-card__meta b{color:var(--mt-text);overflow-wrap:anywhere;font-weight:500}details.cfg>summary{cursor:pointer;color:var(--mt-text-dim);font-family:var(--mt-mono);-webkit-user-select:none;user-select:none;padding:4px 0;font-size:12px}.badge{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--mt-bg);background:var(--grad);border-radius:999px;padding:1px 7px;font-size:9px;font-weight:600}.overlay{-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10;background:#0000009e;justify-content:flex-end;display:flex;position:fixed;inset:0}.sheet{background:color-mix(in srgb, var(--mt-surface) 96%, var(--mt-bg));border-left:1px solid color-mix(in srgb, var(--teal) 28%, var(--mt-border));align-content:start;gap:12px;width:min(580px,100%);height:100%;padding:18px;display:grid;overflow:auto;box-shadow:-24px 0 60px #00000080}.sheet__hd{align-items:center;gap:10px;display:flex}.sheet__hd h3{font-family:var(--mt-mono);margin:0;font-size:15px}pre.body{background:var(--mt-bg);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);font-family:var(--mt-mono);white-space:pre-wrap;word-break:break-word;max-height:40vh;margin:0;padding:12px;font-size:12px;overflow:auto}pre.body.json{color:#a1a1aa}pre.body.json .j-key{color:#7dd3fc}pre.body.json .j-str{color:#86efac}pre.body.json .j-num{color:#fcd34d}pre.body.json .j-bool{color:#d8b4fe}pre.body.json .j-null{color:#71717a}pre.body.ros{color:#c9c9d1}pre.body.ros .ros-key{color:#7dd3fc}pre.body.ros .ros-str{color:#86efac}pre.body.ros .ros-num{color:#fcd34d}pre.body.ros .ros-ip{color:#5eead4}pre.body.ros .ros-mac{color:#c4b5fd}pre.body.ros .ros-good{color:#4ade80;font-weight:500}pre.body.ros .ros-bad{color:#f87171;font-weight:500}pre.body.ros .ros-bool{color:#d8b4fe}pre.body.ros .ros-dim{color:#8b8b94}pre.body.ros .ros-comment{color:#6b7280;font-style:italic}.muted{color:var(--mt-text-faint);font-family:var(--mt-mono);font-size:11px}.btn-danger{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border));background:color-mix(in srgb, var(--mt-bad) 12%, transparent)}.btn-danger:hover{background:color-mix(in srgb, var(--mt-bad) 22%, transparent);border-color:var(--mt-bad)}.btn:hover{border-color:color-mix(in srgb, var(--page-accent) 55%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 10%, var(--mt-surface-2))}.btn.is-active{border-color:color-mix(in srgb, var(--page-accent) 70%, var(--mt-border));color:var(--page-accent);background:color-mix(in srgb, var(--page-accent) 12%, var(--mt-surface-2))}:where(button,a,input,select,textarea,[tabindex]):focus-visible{outline:2px solid color-mix(in srgb, var(--page-accent) 70%, transparent);outline-offset:2px;border-radius:var(--mt-radius-sm)}.conn-legend{font-family:var(--mt-mono);color:var(--mt-text-dim);flex-wrap:wrap;justify-content:center;gap:16px;margin-top:8px;font-size:11px;display:flex}.conn-legend span{align-items:center;gap:6px;display:inline-flex}.conn-legend i{border-radius:3px;width:10px;height:10px;display:inline-block}.conn-chevron{fill:none;stroke-width:1.6px;stroke-linecap:round;stroke-linejoin:round;opacity:.85}.conn-errrow{cursor:pointer;border-radius:6px}.conn-errrow:hover{background:color-mix(in srgb, var(--mt-bad) 12%, transparent)}@media (prefers-reduced-motion:reduce){.conn-chevron{opacity:.6}}.health-grid{grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:14px;display:grid}.health-card{flex-direction:column;gap:10px;padding:16px;display:flex}.health-card--na{justify-content:center;gap:6px;min-height:120px}.health-card__hd{align-items:center;gap:8px;display:flex}.health-card__sub{font-family:var(--mt-mono);margin-top:-4px;font-size:11px}.health-card__gauges{justify-content:space-around;gap:14px;display:flex}.gauge{flex-direction:column;align-items:center;gap:2px;display:flex}.gauge__label{font-family:var(--mt-mono);letter-spacing:.06em;color:var(--mt-text-dim);font-size:10px}.health-card__charts{gap:8px;display:grid}.health-chart{gap:2px;display:grid}.health-chart__k{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.05em;color:var(--mt-text-dim);font-size:10px}.spark{background:color-mix(in srgb, var(--mt-surface-2) 60%, transparent);border-radius:6px;display:block}.spark--empty{font-family:var(--mt-mono);color:var(--mt-text-faint);text-align:center;padding:12px 6px;font-size:11px}.health-card__foot{font-family:var(--mt-mono);font-size:11px}.topo{flex-direction:column;gap:10px;display:flex}.topo svg{background:radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--mt-accent) 8%, transparent), transparent 60%);border-radius:var(--mt-radius-sm);width:100%;display:block}.topo-edge{stroke:color-mix(in srgb, var(--mt-text-faint) 55%, transparent);stroke-width:1.4px}.topo-edge.is-dashed{stroke:color-mix(in srgb, var(--mt-accent) 60%, transparent);stroke-dasharray:4 4}.topo-node{cursor:pointer}.topo-node rect{fill:var(--mt-surface-2);stroke-width:1.5px;transition:filter .15s}.topo-node.is-neighbor rect{fill:color-mix(in srgb, var(--mt-surface) 70%, transparent);stroke-dasharray:4 3}.topo-node.is-onboard rect{stroke-dasharray:4 3}.topo-node:hover rect,.topo-node.is-picked rect{filter:drop-shadow(0 0 6px color-mix(in srgb, var(--mt-accent) 55%, transparent))}.topo-node.is-picked rect{stroke-width:2.2px}.topo-label{fill:var(--mt-text);font:600 12px var(--mt-mono)}.topo-sub{fill:var(--mt-text-dim);font:10px var(--mt-mono)}.topo-bar-bg{fill:color-mix(in srgb, var(--mt-text-faint) 35%, transparent)}.topo-foot{flex-wrap:wrap;justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.topo-foot .legend{margin-top:0}.topo-pop{background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);flex:1;min-width:280px;max-width:460px;padding:12px}.topo-pop__hd{align-items:center;gap:8px;margin-bottom:6px;display:flex}.topo-pop__hd .muted{font-size:11px}.topo-stub{background:var(--mt-bg);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);font:11px/1.5 var(--mt-mono);color:var(--mt-text);white-space:pre;margin:0 0 8px;padding:8px 10px;overflow-x:auto}.topo-btn{font:11px var(--mt-mono);color:var(--mt-text);background:var(--mt-surface-2);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);cursor:pointer;padding:5px 10px;transition:border-color .15s,color .15s}.topo-btn:hover{border-color:var(--mt-accent);color:var(--mt-accent)}.cfgstudio{flex-direction:column;gap:10px;display:flex}.cfg-toolbar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.cfg-status{font:11px var(--mt-mono);border:1px solid var(--mt-border);border-radius:999px;padding:4px 10px}.cfg-status.is-ok{color:var(--mt-good);border-color:color-mix(in srgb, var(--mt-good) 45%, var(--mt-border));background:color-mix(in srgb, var(--mt-good) 10%, transparent)}.cfg-status.is-bad{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border));background:color-mix(in srgb, var(--mt-bad) 10%, transparent)}.cfg-select{font:11px var(--mt-mono);color:var(--mt-text);background:var(--mt-surface-2);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);padding:5px 9px}.cfg-save{border-color:color-mix(in srgb, var(--mt-accent) 55%, var(--mt-border));color:var(--mt-accent)}.backup-path{align-items:center;gap:8px;max-width:min(60vw,520px);display:inline-flex}.backup-path>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.backup-path-input{font:11px var(--mt-mono);color:var(--mt-text);background:var(--mt-surface-2);border:1px solid color-mix(in srgb, var(--mt-accent) 45%, var(--mt-border));border-radius:var(--mt-radius-sm);width:min(48vw,380px);padding:5px 9px}.backup-opts{flex-wrap:wrap;align-items:center}.backup-opt{font:11px var(--mt-mono);color:var(--mt-text-dim);background:var(--mt-surface-2);border:1px solid var(--mt-border);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:100px;align-items:center;gap:6px;padding:5px 11px 5px 9px;transition:border-color .18s,color .18s,background .18s;display:inline-flex}.backup-opt input{accent-color:var(--mt-accent);cursor:pointer;margin:0}.backup-opt[data-on]{color:var(--mt-text);border-color:color-mix(in srgb, var(--mt-accent) 55%, var(--mt-border));background:color-mix(in srgb, var(--mt-accent) 12%, var(--mt-surface-2))}.backup-opt[data-disabled]{opacity:.45;cursor:not-allowed}.backup-opt[data-disabled] input{cursor:not-allowed}.linkish{font:inherit;color:var(--mt-accent);cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:0}.linkish:hover{text-decoration:underline}.cfg-msg{font:12px var(--mt-mono);color:var(--mt-text-dim)}.cfg-banner{border-radius:var(--mt-radius-sm);background:color-mix(in srgb, var(--mt-warn) 12%, var(--mt-surface));border:1px solid color-mix(in srgb, var(--mt-warn) 45%, var(--mt-border));flex-wrap:wrap;align-items:center;gap:8px;padding:10px 13px;font-size:12px;display:flex}.cfg-count{font-family:var(--mt-mono);color:var(--mt-warn);font-weight:700}.cfg-warn{color:var(--mt-warn);font-size:11px}.cfg-editor{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-bg);max-height:420px;display:flex;overflow:hidden}.cfg-gutter{text-align:right;color:var(--mt-text-faint);background:var(--mt-surface-2);font:12px/1.5 var(--mt-mono);-webkit-user-select:none;user-select:none;min-width:38px;margin:0;padding:10px 8px;overflow:hidden}.cfg-ta-wrap{flex:1;position:relative}.cfg-hl,.cfg-ta{box-sizing:border-box;font:12px/1.5 var(--mt-mono);white-space:pre;tab-size:2;letter-spacing:normal;border:0;margin:0;padding:10px 12px}.cfg-hl{z-index:0;pointer-events:none;color:var(--mt-text-dim);position:absolute;inset:0;overflow:hidden}.cfg-ta{z-index:1;resize:vertical;color:#0000;width:100%;height:400px;caret-color:var(--mt-accent);background:0 0;outline:none;position:relative}.cfg-ta::selection{background:color-mix(in srgb, var(--mt-accent) 35%, transparent)}.cfg-hl .j-key{color:#7dd3fc}.cfg-hl .j-str{color:#86efac}.cfg-hl .j-num{color:#fcd34d}.cfg-hl .j-bool{color:#d8b4fe}.cfg-hl .j-null{color:#71717a}.cfg-ac{z-index:5;background:var(--mt-surface);border:1px solid var(--mt-accent);border-radius:var(--mt-radius-sm);min-width:150px;max-height:184px;position:absolute;overflow-y:auto;box-shadow:0 8px 24px #00000080}.cfg-ac-item{font:12px var(--mt-mono);color:var(--mt-text-dim);cursor:pointer;padding:5px 11px}.cfg-ac-item.is-sel{background:color-mix(in srgb, var(--mt-accent) 22%, transparent);color:var(--mt-text)}.cfg-chips{flex-wrap:wrap;gap:6px;display:flex}.cfg-chip{font:11px var(--mt-mono);border:1px solid var(--mt-border);border-radius:999px;padding:4px 10px}.cfg-chip.is-ok{color:var(--mt-good);border-color:color-mix(in srgb, var(--mt-good) 45%, var(--mt-border))}.cfg-chip.is-bad{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border))}.cfg-errors{flex-direction:column;gap:3px;display:flex}.cfg-err{font:11px var(--mt-mono);color:var(--mt-bad)}.cfg-err code{color:var(--mt-warn)}.cfg-preview{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);overflow:hidden}.cfg-preview__hd{background:var(--mt-surface-2);align-items:center;gap:8px;padding:9px 13px;font-size:12px;display:flex}.cfg-diff{max-height:320px;font:11px/1.5 var(--mt-mono);color:var(--mt-text-dim);background:var(--mt-bg);margin:0;padding:10px 12px;overflow:auto}.cfg-diff .d-add{color:var(--mt-good)}.cfg-diff .d-del{color:var(--mt-bad)}.cfg-diff .d-hunk{color:var(--mt-accent)}.cap-idle{font-size:13px;line-height:1.5}.cap-idle code{color:var(--mt-accent);font-family:var(--mt-mono)}.cap{flex-direction:column;gap:12px;display:flex}.cap-bar{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.cap-dot{background:var(--mt-text-faint);border-radius:999px;width:9px;height:9px}.cap-dot.is-on{background:var(--mt-good);box-shadow:0 0 0 4px color-mix(in srgb, var(--mt-good) 22%, transparent);animation:1.6s ease-out infinite feed-pulse}.cap-cols{grid-template-columns:220px 1fr;gap:12px;display:grid}@media (width<=720px){.cap-cols{grid-template-columns:1fr}}.cap-side{flex-direction:column;gap:5px;display:flex}.cap-h{text-transform:uppercase;letter-spacing:.05em;color:var(--mt-text-dim);font-size:11px}.cap-pbar{font:11px var(--mt-mono);grid-template-columns:52px 1fr 34px;align-items:center;gap:6px;display:grid}.cap-ptrack{background:var(--mt-surface-2);border-radius:999px;height:8px;overflow:hidden}.cap-ptrack i{border-radius:999px;height:100%;display:block}.cap-pn{text-align:right;color:var(--mt-text-dim)}.cap-talker{font:11px var(--mt-mono);color:var(--mt-text-dim);justify-content:space-between;display:flex}.cap-talker b{color:var(--mt-text)}.cap-list{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-bg);height:360px;font:11px/1.6 var(--mt-mono);overflow-y:auto}.cap-row{white-space:nowrap;grid-template-columns:90px 64px 48px 1fr;gap:8px;padding:1px 10px;display:grid;overflow:hidden}.cap-row:nth-child(odd){background:color-mix(in srgb, var(--mt-surface) 40%, transparent)}.cap-tt{color:var(--mt-text-faint)}.cap-proto{font-weight:600}.cap-len{color:var(--mt-text-dim);text-align:right}.cap-info{color:var(--mt-text);text-overflow:ellipsis;overflow:hidden}.plan-input{resize:vertical;box-sizing:border-box;border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-bg);width:100%;min-height:160px;color:var(--mt-text);font:12px/1.6 var(--mt-mono);outline:none;padding:12px 14px}.plan-input:focus{border-color:color-mix(in srgb, var(--teal) 55%, var(--mt-border))}.plan-input::placeholder{color:var(--mt-text-faint)}.plan-steps{flex-direction:column;gap:6px;margin-top:12px;display:flex}.plan-step{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:color-mix(in srgb, var(--mt-surface-2) 50%, transparent);font:12px var(--mt-mono);border-left-width:3px;align-items:center;gap:10px;padding:8px 12px;display:flex}.plan-step code{color:var(--mt-text);overflow-wrap:anywhere;flex:1}.plan-step.risk-high{border-left-color:var(--mt-bad)}.plan-step.risk-medium{border-left-color:var(--mt-warn)}.plan-step.risk-low{border-left-color:var(--mt-good)}.plan-op{background:color-mix(in srgb, var(--teal) 18%, transparent);width:18px;height:18px;color:var(--teal);border-radius:5px;flex:none;place-items:center;font-weight:700;display:grid}.plan-risk{text-transform:uppercase;letter-spacing:.05em;color:var(--mt-text-dim);font-size:10px}.plan-lock{color:var(--mt-bad);border:1px solid color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border));border-radius:999px;padding:1px 7px;font-size:10px}.cfgver-cp{align-items:center;gap:8px;display:inline-flex}.cfgver{gap:2px;margin:0;padding:0 0 0 4px;list-style:none;display:grid}.cfgver__row{border-radius:var(--mt-radius-sm);transition:background .18s var(--ease);grid-template-columns:18px minmax(0,1fr) auto;align-items:start;gap:10px;padding:11px 6px;display:grid;position:relative}.cfgver__row:hover{background:color-mix(in srgb, var(--mt-text) 4%, transparent)}.cfgver__row:before{content:"";background:var(--mt-border);width:1.5px;position:absolute;top:22px;bottom:-2px;left:12px}.cfgver__row:last-child:before{display:none}.cfgver__dot{border:2px solid var(--mt-border-strong);background:var(--mt-surface);z-index:1;border-radius:999px;width:11px;height:11px;margin-top:5px}.cfgver__row.is-head .cfgver__dot{border-color:var(--page-accent);background:var(--page-accent);box-shadow:0 0 0 4px color-mix(in srgb, var(--page-accent) 22%, transparent)}.cfgver__main{min-width:0}.cfgver__line{flex-wrap:wrap;align-items:center;gap:9px;font-size:12.5px;display:flex}.cfgver__kind{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--mt-border);color:var(--mt-text-dim);border-radius:999px;padding:2px 7px;font-size:10px}.cfgver__kind--checkpoint{color:var(--amber);border-color:color-mix(in srgb, var(--amber) 45%, var(--mt-border));background:color-mix(in srgb, var(--amber) 12%, transparent)}.cfgver__label{color:var(--mt-text);font-weight:600}.cfgver__time{font-family:var(--mt-mono);color:var(--mt-text-dim);font-size:11.5px}.cfgver__cur{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.05em;color:var(--page-accent);font-size:10px}.cfgver__same{color:var(--mt-text-faint);font-size:11.5px}.cfgver__drift{font-family:var(--mt-mono);align-items:baseline;gap:7px;font-size:11.5px;display:inline-flex}.cfgver__drift .add{color:var(--mt-good)}.cfgver__drift .rem{color:var(--mt-bad)}.cfgver__diff{margin-top:9px}.cfgver__diff pre.body{max-height:280px;margin:0;overflow:auto}.cfgver__actions{flex:none;align-items:center;gap:6px;display:inline-flex}.cfgver__del{color:var(--mt-text-faint);padding-left:8px;padding-right:8px}.cfgver__del:hover{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 45%, var(--mt-border))}.fguide{gap:18px;display:grid}.fguide__sechd{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.09em;color:var(--page-accent);margin:0 0 9px;font-size:11px}.fguide__list{gap:9px;display:grid}.fguide__item{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:color-mix(in srgb, var(--mt-surface-2) 45%, transparent);transition:border-color .18s, transform .12s var(--ease);padding:11px 13px}.fguide__item:hover{border-color:color-mix(in srgb, var(--page-accent) 40%, var(--mt-border));transform:translate(2px)}.fguide__top{flex-wrap:wrap;align-items:baseline;gap:10px;display:flex}.fguide__path{font-family:var(--mt-mono);color:var(--mt-text);font-size:12.5px;font-weight:500}.fguide__type{font-family:var(--mt-mono);color:var(--page-accent);background:color-mix(in srgb, var(--page-accent) 13%, transparent);border-radius:999px;padding:1px 7px;font-size:10.5px}.fguide__req{font-family:var(--mt-mono);text-transform:uppercase;letter-spacing:.05em;color:var(--mt-bad);font-size:10px}.fguide__def{color:var(--mt-text-faint);font-size:11px}.fguide__def code{color:var(--mt-text-dim)}.fguide__desc{color:var(--mt-text-dim);margin:6px 0 0;font-size:12.5px;line-height:1.5}.fguide__enum{flex-wrap:wrap;gap:6px;margin-top:7px;display:flex}.fguide__enum code{font-family:var(--mt-mono);border:1px solid var(--mt-border);color:var(--mt-text-dim);border-radius:6px;padding:1px 7px;font-size:11px}.copybtn{position:relative}.copybtn.is-copied{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 55%, var(--mt-border))}.copybtn__tip{background:var(--page-accent);color:#0a0a0a;font-family:var(--mt-sans);white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .16s, transform .16s var(--ease);z-index:50;border-radius:6px;padding:3px 9px;font-size:11px;font-weight:600;position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%,4px)}.copybtn__tip:after{content:"";border:4px solid #0000;border-top-color:var(--page-accent);position:absolute;top:100%;left:50%;transform:translate(-50%)}.copybtn.is-copied .copybtn__tip{opacity:1;transform:translate(-50%)}.iconbtn{border:1px solid var(--mt-border);background:var(--mt-surface);width:26px;height:26px;color:var(--mt-text-dim);cursor:pointer;border-radius:7px;place-items:center;padding:0;transition:color .16s,border-color .16s,background .16s;display:inline-grid}.iconbtn:hover{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 50%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 10%, var(--mt-surface))}.copybtn--icon.is-copied{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 55%, var(--mt-border))}.sheet__tool{align-items:center;gap:9px;display:inline-flex}.chart{width:100%;font-family:var(--mt-mono)}.chart .recharts-cartesian-grid line{stroke:color-mix(in srgb, var(--mt-border) 80%, transparent)}.chart .recharts-text,.chart text{fill:var(--mt-text-faint)}.chart .recharts-surface:focus,.chart svg:focus{outline:none}.chart-tip{background:color-mix(in srgb, var(--mt-surface) 96%, transparent);border:1px solid var(--mt-border-strong);border-radius:var(--mt-radius-sm);font-family:var(--mt-mono);min-width:120px;padding:8px 10px;font-size:11.5px;box-shadow:0 8px 24px #00000073}.chart-tip__label{color:var(--mt-text-dim);margin-bottom:5px;font-size:10.5px}.chart-tip__row{align-items:center;gap:7px;display:flex}.chart-tip__dot{border-radius:3px;flex:none;width:9px;height:9px}.chart-tip__name{color:var(--mt-text-dim);text-transform:capitalize}.chart-tip__val{color:var(--mt-text);font-variant-numeric:tabular-nums;margin-left:auto;font-weight:500}.chart--donut{flex-direction:column;flex:1;justify-content:center;align-items:center;gap:12px;display:flex}.chart-donut__svg{width:100%;max-width:200px}.chart-legend{font-family:var(--mt-mono);color:var(--mt-text-dim);flex-wrap:wrap;justify-content:center;gap:6px 14px;font-size:11px;display:flex}.chart-legend span{align-items:center;gap:6px;display:inline-flex}.chart-legend i{border-radius:3px;width:9px;height:9px}.chart-legend b{color:var(--mt-text);font-weight:500}.chart--spark{position:relative}.chart-spark__last{font-family:var(--mt-mono);z-index:1;font-size:10px;font-weight:600;position:absolute;top:0;right:2px}.gauge__radial{place-items:center;width:72px;height:72px;display:grid;position:relative}.gauge__pct{font-family:var(--mt-mono);pointer-events:none;place-items:center;font-size:13px;font-weight:700;display:grid;position:absolute;inset:0}.geist-btn{font-family:var(--mt-sans);border-radius:var(--mt-radius-sm);border:1px solid var(--mt-border-strong);background:var(--mt-surface);color:var(--mt-text);cursor:pointer;white-space:nowrap;transition:background .16s var(--ease), border-color .16s, color .16s, transform .1s var(--ease), box-shadow .16s;justify-content:center;align-items:center;gap:7px;font-size:13px;font-weight:500;line-height:1;display:inline-flex}.geist-btn--sm{padding:6px 11px;font-size:12px}.geist-btn--md{padding:9px 15px}.geist-btn:hover{border-color:var(--mt-text);transform:translateY(-1px)}.geist-btn:active{transform:translateY(0)}.geist-btn:disabled{opacity:.5;cursor:not-allowed;transform:none}.geist-btn__icon{display:inline-flex}.geist-btn--accent{background:var(--page-accent);border-color:var(--page-accent);color:#0a0a0a;font-weight:600}.geist-btn--accent:hover{box-shadow:0 4px 16px color-mix(in srgb, var(--page-accent) 40%, transparent);border-color:var(--page-accent)}.geist-btn--success{border-color:color-mix(in srgb, var(--mt-good) 55%, var(--mt-border));color:var(--mt-good)}.geist-btn--warning{border-color:color-mix(in srgb, var(--mt-warn) 55%, var(--mt-border));color:var(--mt-warn)}.geist-btn--error{border-color:color-mix(in srgb, var(--mt-bad) 55%, var(--mt-border));color:var(--mt-bad)}.geist-btn--error:hover{background:color-mix(in srgb, var(--mt-bad) 14%, var(--mt-surface));border-color:var(--mt-bad)}.geist-btn--secondary{color:var(--mt-text-dim);border-color:var(--mt-border)}.geist-btn--ghost{background:0 0;border-color:#0000}.geist-btn--ghost:hover{background:color-mix(in srgb, var(--mt-text) 7%, transparent);border-color:var(--mt-border)}.geist-note{border-radius:var(--mt-radius-sm);border:1px solid var(--mt-border);background:var(--mt-surface);color:var(--mt-text-dim);padding:11px 14px;font-size:13px;line-height:1.55}.geist-note__label{color:var(--mt-text);text-transform:capitalize}.geist-note--secondary{border-color:color-mix(in srgb, var(--page-accent) 30%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 7%, var(--mt-surface))}.geist-note--success{border-color:color-mix(in srgb, var(--mt-good) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-good) 8%, var(--mt-surface))}.geist-note--success .geist-note__label{color:var(--mt-good)}.geist-note--warning{border-color:color-mix(in srgb, var(--mt-warn) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-warn) 8%, var(--mt-surface))}.geist-note--warning .geist-note__label{color:var(--mt-warn)}.geist-note--error{border-color:color-mix(in srgb, var(--mt-bad) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-bad) 8%, var(--mt-surface))}.geist-note--error .geist-note__label{color:var(--mt-bad)}.geist-badge{font-family:var(--mt-mono);border:1px solid var(--mt-border);background:var(--mt-surface-2);color:var(--mt-text-dim);border-radius:999px;align-items:center;gap:5px;padding:2px 8px;font-size:10.5px;font-weight:500;display:inline-flex}.geist-badge--accent{color:var(--page-accent);border-color:color-mix(in srgb, var(--page-accent) 40%, var(--mt-border));background:color-mix(in srgb, var(--page-accent) 12%, transparent)}.geist-badge--success{color:var(--mt-good);border-color:color-mix(in srgb, var(--mt-good) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-good) 10%, transparent)}.geist-badge--warning{color:var(--mt-warn);border-color:color-mix(in srgb, var(--mt-warn) 40%, var(--mt-border))}.geist-badge--error{color:var(--mt-bad);border-color:color-mix(in srgb, var(--mt-bad) 40%, var(--mt-border));background:color-mix(in srgb, var(--mt-bad) 10%, transparent)}.geist-dot{background:var(--mt-text-faint);border-radius:999px;flex:none;width:9px;height:9px;display:inline-block}.geist-dot--success{background:var(--mt-good)}.geist-dot--warning{background:var(--mt-warn)}.geist-dot--error{background:var(--mt-bad)}.geist-dot--accent{background:var(--page-accent)}.geist-dot.is-pulse{box-shadow:0 0 0 0 color-mix(in srgb, currentColor 60%, transparent);animation:1.8s infinite geist-pulse}@keyframes geist-pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--mt-good) 55%, transparent)}70%{box-shadow:0 0 0 7px #0000}to{box-shadow:0 0 #0000}}.geist-spinner{width:16px;height:16px;display:inline-block;position:relative}.geist-spinner--sm{width:13px;height:13px}.geist-spinner span{transform-origin:50% 178%;opacity:.15;background:currentColor;border-radius:2px;width:8%;height:28%;animation:1.2s linear infinite geist-spin;position:absolute;top:0;left:46%}@keyframes geist-spin{0%{opacity:1}to{opacity:.15}}.geist-input,.geist-select{font-family:var(--mt-mono);color:var(--mt-text);background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);padding:8px 11px;font-size:12.5px;transition:border-color .16s,box-shadow .16s}.geist-input:focus,.geist-select:focus{border-color:var(--page-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--page-accent) 22%, transparent);outline:none}.geist-card{border:1px solid var(--mt-border);border-radius:var(--mt-radius);background:var(--mt-surface);padding:16px}.geist-card.is-hoverable{transition:border-color .18s, transform .18s var(--ease)}.geist-card.is-hoverable:hover{border-color:color-mix(in srgb, var(--page-accent) 40%, var(--mt-border));transform:translateY(-2px)}.geist-tooltip{display:inline-flex;position:relative}.geist-tooltip__pop{border-radius:var(--mt-radius-sm);background:var(--mt-surface);border:1px solid var(--mt-border-strong);color:var(--mt-text);font-family:var(--mt-mono);white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .16s, transform .16s var(--ease);z-index:60;padding:6px 10px;font-size:11.5px;position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%,4px);box-shadow:0 8px 24px #00000073}.geist-tooltip:hover .geist-tooltip__pop,.geist-tooltip:focus-visible .geist-tooltip__pop{opacity:1;transform:translate(-50%)}.clients-toolbar{align-items:center;gap:8px;display:flex}.clients-toolbar .geist-input{width:200px}.clients-counts{margin-bottom:10px;font-size:12px}.clients-error{margin-bottom:10px}.clients-table{flex-direction:column;gap:2px;display:flex}.clients-row{border-radius:var(--mt-radius-sm);cursor:pointer;grid-template-columns:120px 1.3fr 150px 80px 130px minmax(280px,auto);align-items:center;gap:10px;padding:8px 10px;font-size:13px;display:grid}.clients-row--head{cursor:default;color:var(--mt-text-faint);text-transform:uppercase;letter-spacing:.04em;font-size:11px}.clients-row:not(.clients-row--head):hover{background:var(--mt-surface-2)}.clients-row.is-selected{background:color-mix(in srgb, var(--page-accent) 14%, var(--mt-surface-2))}.clients-row.is-blocked .clients-ip,.clients-row.is-blocked .clients-name{color:var(--mt-text-faint);text-decoration:line-through}.clients-ip,.clients-name{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.clients-mac{color:var(--mt-text-dim);font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:11.5px}.clients-badges{align-items:center;gap:6px;display:flex;overflow:hidden}.clients-actions,.clients-actions-h{justify-content:flex-end;gap:6px;display:flex}.clients-detail{border-top:1px solid var(--mt-border);margin-top:14px;padding-top:14px}.clients-detail__hd{flex-wrap:wrap;align-items:baseline;gap:12px;margin-bottom:10px;display:flex}.clients-detail__title{font-size:14px;font-weight:600}.clients-rates{font-variant-numeric:tabular-nums;gap:18px;margin-bottom:8px;display:flex}.clients-rates .rate{font-weight:600}.clients-rates .rate.rx{color:var(--lime)}.clients-rates .rate.tx{color:var(--amber)}.clients-chart{background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);width:100%;max-width:520px;height:150px;display:block}.clients-chart .line{fill:none;stroke-width:2px}.clients-chart .rx.line{stroke:var(--lime)}.clients-chart .tx.line{stroke:var(--amber)}.clients-chart .rx.area{fill:color-mix(in srgb, var(--lime) 18%, transparent);stroke:none}.clients-chart .tx.area{fill:color-mix(in srgb, var(--amber) 14%, transparent);stroke:none}.clients-totals{font-variant-numeric:tabular-nums;margin-top:8px;font-size:12px}.clients-edit{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-surface-2);flex-wrap:wrap;align-items:center;gap:8px;margin-top:14px;padding:10px 12px;display:flex}.clients-edit__label{color:var(--mt-text-dim);font-size:13px}.clients-edit .geist-input{width:220px}.aaa-tabs{border-bottom:1px solid var(--mt-border);flex-wrap:wrap;gap:4px;margin-bottom:14px;display:flex}.aaa-tab{appearance:none;color:var(--mt-text-dim);font:inherit;cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;margin-bottom:-1px;padding:7px 12px;font-size:13px}.aaa-tab:hover{color:var(--mt-text)}.aaa-tab.is-active{color:var(--mt-text);border-bottom-color:var(--page-accent)}.aaa-entity__toolbar{align-items:center;gap:10px;margin-bottom:12px;display:flex}.aaa-filter{width:200px}.aaa-error{margin-bottom:10px}.aaa-empty{padding:20px 4px}.aaa-table{flex-direction:column;gap:2px;display:flex}.aaa-table--scroll{overflow-x:auto}.aaa-row{border-radius:var(--mt-radius-sm);align-items:center;gap:10px;padding:8px 10px;font-size:13px;display:grid}.aaa-row--head{color:var(--mt-text-faint);text-transform:uppercase;letter-spacing:.04em;font-size:11px}.aaa-row:not(.aaa-row--head):hover{background:var(--mt-surface-2)}.aaa-row.is-off .aaa-cell{color:var(--mt-text-faint)}.aaa-row--sessions{grid-template-columns:repeat(9,minmax(90px,1fr));min-width:900px}.aaa-cell{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.aaa-actions,.aaa-actions-h{justify-content:flex-end;gap:6px;display:flex}.aaa-form,.aaa-singleton{border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);background:var(--mt-surface-2);margin-bottom:14px;padding:14px}.aaa-form__title,.aaa-singleton__title{margin-bottom:10px;font-size:13px;font-weight:600}.aaa-singleton__current{margin-bottom:12px;font-size:12px}.aaa-form__grid{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px 14px;display:grid}.aaa-field{flex-direction:column;gap:4px;display:flex}.aaa-field__label{color:var(--mt-text-dim);font-size:11.5px}.aaa-form__actions{align-items:center;gap:10px;margin-top:14px;display:flex}.aaa-settings{flex-direction:column;gap:8px;display:flex}.clients-limits{border-top:1px solid var(--mt-border);max-width:520px;margin-top:14px;padding-top:12px}.clients-limits__hd{align-items:baseline;gap:12px;margin-bottom:8px;display:flex}.clients-limits__label{font-size:13px;font-weight:600}.clients-limits__row{flex-wrap:wrap;align-items:flex-end;gap:8px;display:flex}.clients-limits__field{flex-direction:column;gap:3px;font-size:11.5px;display:flex}.clients-limits__field .geist-input{width:150px}.clients-limits__msg{margin-top:6px;font-size:12px}.usage-chart__empty{padding:16px 4px;font-size:12.5px}.usage-chart__legend{font-variant-numeric:tabular-nums;align-items:baseline;gap:14px;margin-bottom:6px;font-size:12px;display:flex}.usage-chart__legend .rate{font-weight:600}.usage-chart__legend .rate.rx{color:var(--lime)}.usage-chart__legend .rate.tx{color:var(--amber)}.usage-chart__svg{background:var(--mt-surface);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);width:100%;height:160px;display:block}.usage-chart__svg .line{fill:none;stroke-width:2px;vector-effect:non-scaling-stroke}.usage-chart__svg .rx.line{stroke:var(--lime)}.usage-chart__svg .tx.line{stroke:var(--amber)}.usage-chart__svg .rx.area{fill:color-mix(in srgb, var(--lime) 18%, transparent);stroke:none}.usage-chart__svg .tx.area{fill:color-mix(in srgb, var(--amber) 14%, transparent);stroke:none}.clients-history,.aaa-usage__section{margin-top:16px}.clients-history__hd,.aaa-usage__title{color:var(--mt-text-dim);margin-bottom:8px;font-size:12px;font-weight:600}.aaa-usage__bar{align-items:center;gap:8px;margin-bottom:12px;display:flex}.heatmap__hd{align-items:baseline;gap:10px;margin-bottom:6px;display:flex}.heatmap__title{font-size:12.5px;font-weight:600}.heatmap__scroll{padding-bottom:4px;overflow-x:auto}.heatmap__svg{display:block}.heatmap__month,.heatmap__wd{fill:var(--mt-text-dim);font-family:inherit;font-size:9px}.heatmap{position:relative}.heatmap__cell{stroke:color-mix(in srgb, var(--mt-border) 60%, transparent);stroke-width:1px;cursor:pointer;transition:stroke .1s}.heatmap__cell.is-hover{stroke:var(--mt-text);stroke-width:1.5px}.heatmap__tip{z-index:30;background:linear-gradient(180deg, color-mix(in srgb, var(--mt-surface-2) 92%, var(--lime)), var(--mt-surface-2));border:1px solid color-mix(in srgb, var(--lime) 35%, var(--mt-border));pointer-events:none;min-width:150px;animation:heatmap-tip-in .12s var(--ease);border-radius:10px;padding:8px 10px;position:absolute;transform:translate(-50%,calc(-100% - 9px));box-shadow:0 8px 24px #00000073}.heatmap__tip:after{content:"";background:var(--mt-surface-2);border-right:1px solid color-mix(in srgb, var(--lime) 35%, var(--mt-border));border-bottom:1px solid color-mix(in srgb, var(--lime) 35%, var(--mt-border));width:11px;height:11px;position:absolute;bottom:-6px;left:50%;transform:translate(-50%)rotate(45deg)}@keyframes heatmap-tip-in{0%{opacity:0;transform:translate(-50%,calc(-100% - 3px))}to{opacity:1;transform:translate(-50%,calc(-100% - 9px))}}.heatmap__tip-head{align-items:center;gap:7px;font-size:13px;display:flex}.heatmap__tip-head b{font-weight:600}.heatmap__tip-head .heatmap__swatch{width:12px;height:12px}.heatmap__tip-date{color:var(--mt-text-dim);font-variant-numeric:tabular-nums;margin-top:3px;font-size:11.5px}.heatmap__cell.lvl0,.heatmap__swatch.lvl0{fill:var(--mt-surface-2);background:var(--mt-surface-2)}.heatmap__cell.lvl1,.heatmap__swatch.lvl1{fill:color-mix(in srgb, var(--lime) 30%, var(--mt-surface-2));background:color-mix(in srgb, var(--lime) 30%, var(--mt-surface-2))}.heatmap__cell.lvl2,.heatmap__swatch.lvl2{fill:color-mix(in srgb, var(--lime) 50%, var(--mt-surface-2));background:color-mix(in srgb, var(--lime) 50%, var(--mt-surface-2))}.heatmap__cell.lvl3,.heatmap__swatch.lvl3{fill:color-mix(in srgb, var(--lime) 72%, transparent);background:color-mix(in srgb, var(--lime) 72%, transparent)}.heatmap__cell.lvl4,.heatmap__swatch.lvl4{fill:var(--lime);background:var(--lime)}.heatmap__legend{align-items:center;gap:4px;margin-top:8px;font-size:11px;display:flex}.heatmap__swatch{border-radius:2px;width:11px;height:11px;display:inline-block}.input{font:12px var(--mt-mono);color:var(--mt-text);background:var(--mt-surface-2);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);width:min(52vw,420px);padding:6px 10px}.input:focus{border-color:color-mix(in srgb, var(--mt-accent) 55%, var(--mt-border));outline:none}.btn-sm{padding:3px 8px;font-size:10px}.mod-toolbar{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:6px;display:flex}.mod-groups{flex-direction:column;gap:18px;margin-top:12px;display:flex}.mod-group__hd{border-bottom:1px solid var(--mt-border);align-items:center;gap:10px;margin-bottom:8px;padding-bottom:6px;display:flex}.mod-group__title{color:var(--mt-text);margin:0;font-size:13px;font-weight:600}.mod-list{grid-template-columns:repeat(auto-fill,minmax(min(100%,360px),1fr));gap:8px;display:grid}.mod-row{background:var(--mt-surface-2);border:1px solid var(--mt-border);border-radius:var(--mt-radius-sm);cursor:pointer;-webkit-user-select:none;user-select:none;align-items:flex-start;gap:10px;padding:9px 11px;transition:border-color .18s,background .18s;display:flex}.mod-row:hover{border-color:color-mix(in srgb, var(--mt-accent) 35%, var(--mt-border))}.mod-row[data-on]{border-color:color-mix(in srgb, var(--mt-accent) 50%, var(--mt-border));background:color-mix(in srgb, var(--mt-accent) 10%, var(--mt-surface-2))}.mod-row input{accent-color:var(--mt-accent);cursor:pointer;margin:2px 0 0}.mod-row__main{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.mod-row__name{color:var(--mt-text);flex-wrap:wrap;align-items:center;gap:7px;font-size:12px;font-weight:600;display:flex}.mod-row__slug{font:10px var(--mt-mono);color:var(--mt-text-dim);background:var(--mt-bg);border:1px solid var(--mt-border);border-radius:4px;padding:1px 5px}.mod-row__desc{font-size:11px;line-height:1.35}.mod-row__count{font:10px var(--mt-mono);white-space:nowrap;padding-top:1px}.conn-tunnel-halo{fill:none;stroke-width:8px;stroke-linecap:round;opacity:.1}.conn-tunnel{fill:none;stroke-width:2.4px;stroke-linecap:round;stroke-dasharray:6 6;animation:.9s linear infinite conn-tunnel-flow}@keyframes conn-tunnel-flow{to{stroke-dashoffset:-24px}}.conn-tunnel-lock{filter:drop-shadow(0 0 4px #f59e0bcc)}.conn-tunnel-sat{stroke-width:1.5px;filter:drop-shadow(0 0 5px #f59e0b88)}.conn-tunnel-badge{fill:#30220a;stroke:color-mix(in srgb, #f59e0b 60%, var(--mt-border));stroke-width:1px}.conn-tunnel-badge-tx{fill:#fbbf24;font-family:var(--mt-mono);letter-spacing:.02em;font-weight:700}.jump-route{background:color-mix(in srgb, #f59e0b 7%, var(--mt-surface-2));border:1px solid color-mix(in srgb, #f59e0b 28%, var(--mt-border));font:10px var(--mt-mono);border-radius:10px;align-items:center;gap:6px;margin:10px 0 2px;padding:7px 9px;display:flex;overflow:hidden}.jump-route__hop{background:var(--mt-bg);border:1px solid var(--mt-border);color:var(--mt-text);white-space:nowrap;border-radius:7px;align-items:center;gap:5px;padding:3px 8px;display:inline-flex}.jump-route__hop--src{padding:3px 7px;font-size:12px}.jump-route__hop--bastion{border-color:color-mix(in srgb, #f59e0b 60%, var(--mt-border));color:#fbbf24;box-shadow:0 0 10px -3px #f59e0b99}.jump-route__tag{text-transform:uppercase;letter-spacing:.08em;color:#0a0a0a;background:#f59e0b;border-radius:4px;padding:1px 4px;font-size:7px;font-style:normal}.jump-route__wire{background-image:linear-gradient(90deg, var(--mt-border) 0 50%, transparent 50% 100%);background-size:8px 2px;border-radius:2px;flex:1;min-width:18px;height:2px;animation:.7s linear infinite jump-wire}.jump-route__wire--enc{background-image:linear-gradient(90deg,#f59e0b 0 55%,#0000 55% 100%);background-size:10px 3px;min-width:34px;height:3px;position:relative;box-shadow:0 0 8px -1px #f59e0b88}.jump-route__lock{filter:drop-shadow(0 0 3px #f59e0b);font-size:11px;animation:2.2s linear infinite jump-lock;position:absolute;top:50%}@keyframes jump-wire{to{background-position:8px 0}}@keyframes jump-lock{0%{left:-4px;transform:translateY(-50%)scale(.9)}50%{transform:translateY(-50%)scale(1.1)}to{left:calc(100% - 8px);transform:translateY(-50%)scale(.9)}}@media (prefers-reduced-motion:reduce){.conn-tunnel,.jump-route__wire,.jump-route__wire--enc,.jump-route__lock{animation:none}.conn-tunnel-lock animatemotion{display:none}}
85
85
  /*$vite$:1*/
86
86
  </style>
87
87
  </head>