diff --git a/rulesdocs/refector_rules_and_tracking.md b/rulesdocs/refector_rules_and_tracking.md index 67bb2ca6..9094b574 100644 --- a/rulesdocs/refector_rules_and_tracking.md +++ b/rulesdocs/refector_rules_and_tracking.md @@ -64,16 +64,18 @@ - [ ] gamepad mapping settings - [ ] mobile controls - [ ] top down map -- [ ] video tile +- [x] video tile - [ ] Sweep `webui` for unused or unneeded files/code with verification ### COMPLETED COMPONENTS - mini summary app - spectator app +- video tile ### LARGE CHANGES - Split `webui/src/mini/MiniSummaryApp.jsx` into folderized modules under `webui/src/mini/MiniSummaryApp/` with a compatibility entrypoint preserved. - Split `webui/src/spectate/SpectatorApp.jsx` into folderized modules under `webui/src/spectate/SpectatorApp/` with a compatibility entrypoint preserved. +- Split `webui/src/components/VideoTile.jsx` by extracting HUD, overlays, chat input, and constants into `webui/src/components/VideoTile/` while preserving the existing `VideoTile.jsx` public component API. ## Done criteria (per item) - [ ] Folderized structure created. diff --git a/server/public/assets/index-BK4DZOjR.js b/server/public/assets/index-L5eomcx0.js similarity index 82% rename from server/public/assets/index-BK4DZOjR.js rename to server/public/assets/index-L5eomcx0.js index 2e0761a6..63249474 100644 --- a/server/public/assets/index-BK4DZOjR.js +++ b/server/public/assets/index-L5eomcx0.js @@ -8,14 +8,14 @@ Error generating stack: `+i.message+` `+i.stack}}var se=Object.prototype.hasOwnProperty,P=n.unstable_scheduleCallback,de=n.unstable_cancelCallback,Ne=n.unstable_shouldYield,pt=n.unstable_requestPaint,Ve=n.unstable_now,st=n.unstable_getCurrentPriorityLevel,lt=n.unstable_ImmediatePriority,Ot=n.unstable_UserBlockingPriority,it=n.unstable_NormalPriority,ms=n.unstable_LowPriority,Yt=n.unstable_IdlePriority,La=n.log,Bo=n.unstable_setDisableYieldValue,Bn=null,Nt=null;function Ft(e){if(typeof La=="function"&&Bo(e),Nt&&typeof Nt.setStrictMode=="function")try{Nt.setStrictMode(Bn,e)}catch{}}var Mt=Math.clz32?Math.clz32:hs,fa=Math.log,Oo=Math.LN2;function hs(e){return e>>>=0,e===0?32:31-(fa(e)/Oo|0)|0}var ps=256,za=262144,Pe=4194304;function On(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Cn(e,t,a){var i=e.pendingLanes;if(i===0)return 0;var c=0,u=e.suspendedLanes,b=e.pingedLanes;e=e.warmLanes;var A=i&134217727;return A!==0?(i=A&~u,i!==0?c=On(i):(b&=A,b!==0?c=On(b):a||(a=A&~e,a!==0&&(c=On(a))))):(A=i&~u,A!==0?c=On(A):b!==0?c=On(b):a||(a=i&~e,a!==0&&(c=On(a)))),c===0?0:t!==0&&t!==c&&(t&u)===0&&(u=c&-c,a=t&-t,u>=a||u===32&&(a&4194048)!==0)?t:c}function Ln(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function xs(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function hl(){var e=Pe;return Pe<<=1,(Pe&62914560)===0&&(Pe=4194304),e}function pl(e){for(var t=[],a=0;31>a;a++)t.push(e);return t}function Ua(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Lo(e,t,a,i,c,u){var b=e.pendingLanes;e.pendingLanes=a,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=a,e.entangledLanes&=a,e.errorRecoveryDisabledLanes&=a,e.shellSuspendCounter=0;var A=e.entanglements,D=e.expirationTimes,Y=e.hiddenUpdates;for(a=b&~a;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var ov=/[\n"\\]/g;function ln(e){return e.replace(ov,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Ho(e,t,a,i,c,u,b,A){e.name="",b!=null&&typeof b!="function"&&typeof b!="symbol"&&typeof b!="boolean"?e.type=b:e.removeAttribute("type"),t!=null?b==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+sn(t)):e.value!==""+sn(t)&&(e.value=""+sn(t)):b!=="submit"&&b!=="reset"||e.removeAttribute("value"),t!=null?Vo(e,b,sn(t)):a!=null?Vo(e,b,sn(a)):i!=null&&e.removeAttribute("value"),c==null&&u!=null&&(e.defaultChecked=!!u),c!=null&&(e.checked=c&&typeof c!="function"&&typeof c!="symbol"),A!=null&&typeof A!="function"&&typeof A!="symbol"&&typeof A!="boolean"?e.name=""+sn(A):e.removeAttribute("name")}function qd(e,t,a,i,c,u,b,A){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.type=u),t!=null||a!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){Uo(e);return}a=a!=null?""+sn(a):"",t=t!=null?""+sn(t):a,A||t===e.value||(e.value=t),e.defaultValue=t}i=i??c,i=typeof i!="function"&&typeof i!="symbol"&&!!i,e.checked=A?e.checked:!!i,e.defaultChecked=!!i,b!=null&&typeof b!="function"&&typeof b!="symbol"&&typeof b!="boolean"&&(e.name=b),Uo(e)}function Vo(e,t,a){t==="number"&&Oi(e.ownerDocument)===e||e.defaultValue===""+a||(e.defaultValue=""+a)}function Ss(e,t,a,i){if(e=e.options,t){t={};for(var c=0;c"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Xo=!1;if(Vn)try{var yl={};Object.defineProperty(yl,"passive",{get:function(){Xo=!0}}),window.addEventListener("test",yl,yl),window.removeEventListener("test",yl,yl)}catch{Xo=!1}var da=null,Qo=null,zi=null;function zd(){if(zi)return zi;var e,t=Qo,a=t.length,i,c="value"in da?da.value:da.textContent,u=c.length;for(e=0;e=Al),Yd=" ",Fd=!1;function Xd(e,t){switch(e){case"keyup":return Ov.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Qd(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var ws=!1;function zv(e,t){switch(e){case"compositionend":return Qd(t);case"keypress":return t.which!==32?null:(Fd=!0,Yd);case"textInput":return e=t.data,e===Yd&&Fd?null:e;default:return null}}function Uv(e,t){if(ws)return e==="compositionend"||!Po&&Xd(e,t)?(e=zd(),zi=Qo=da=null,ws=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:a,offset:t-e};e=i}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=tm(a)}}function am(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?am(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function sm(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Oi(e.document);t instanceof e.HTMLIFrameElement;){try{var a=typeof t.contentWindow.location.href=="string"}catch{a=!1}if(a)e=t.contentWindow;else break;t=Oi(e.document)}return t}function tc(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var Qv=Vn&&"documentMode"in document&&11>=document.documentMode,Cs=null,nc=null,El=null,ac=!1;function lm(e,t,a){var i=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;ac||Cs==null||Cs!==Oi(i)||(i=Cs,"selectionStart"in i&&tc(i)?i={start:i.selectionStart,end:i.selectionEnd}:(i=(i.ownerDocument&&i.ownerDocument.defaultView||window).getSelection(),i={anchorNode:i.anchorNode,anchorOffset:i.anchorOffset,focusNode:i.focusNode,focusOffset:i.focusOffset}),El&&Cl(El,i)||(El=i,i=qr(nc,"onSelect"),0>=b,c-=b,En=1<<32-Mt(t)+c|a<Ee?(Te=ge,ge=null):Te=ge.sibling;var Le=Q(z,ge,G[Ee],W);if(Le===null){ge===null&&(ge=Te);break}e&&ge&&Le.alternate===null&&t(z,ge),B=u(Le,B,Ee),Oe===null?Se=Le:Oe.sibling=Le,Oe=Le,ge=Te}if(Ee===G.length)return a(z,ge),De&&Gn(z,Ee),Se;if(ge===null){for(;EeEe?(Te=ge,ge=null):Te=ge.sibling;var _a=Q(z,ge,Le.value,W);if(_a===null){ge===null&&(ge=Te);break}e&&ge&&_a.alternate===null&&t(z,ge),B=u(_a,B,Ee),Oe===null?Se=_a:Oe.sibling=_a,Oe=_a,ge=Te}if(Le.done)return a(z,ge),De&&Gn(z,Ee),Se;if(ge===null){for(;!Le.done;Ee++,Le=G.next())Le=ne(z,Le.value,W),Le!==null&&(B=u(Le,B,Ee),Oe===null?Se=Le:Oe.sibling=Le,Oe=Le);return De&&Gn(z,Ee),Se}for(ge=i(ge);!Le.done;Ee++,Le=G.next())Le=I(ge,z,Ee,Le.value,W),Le!==null&&(e&&Le.alternate!==null&&ge.delete(Le.key===null?Ee:Le.key),B=u(Le,B,Ee),Oe===null?Se=Le:Oe.sibling=Le,Oe=Le);return e&&ge.forEach(function(my){return t(z,my)}),De&&Gn(z,Ee),Se}function Ke(z,B,G,W){if(typeof G=="object"&&G!==null&&G.type===k&&G.key===null&&(G=G.props.children),typeof G=="object"&&G!==null){switch(G.$$typeof){case E:e:{for(var Se=G.key;B!==null;){if(B.key===Se){if(Se=G.type,Se===k){if(B.tag===7){a(z,B.sibling),W=c(B,G.props.children),W.return=z,z=W;break e}}else if(B.elementType===Se||typeof Se=="object"&&Se!==null&&Se.$$typeof===U&&Ia(Se)===B.type){a(z,B.sibling),W=c(B,G.props),Dl(W,G),W.return=z,z=W;break e}a(z,B);break}else t(z,B);B=B.sibling}G.type===k?(W=Fa(G.props.children,z.mode,W,G.key),W.return=z,z=W):(W=Ki(G.type,G.key,G.props,null,z.mode,W),Dl(W,G),W.return=z,z=W)}return b(z);case C:e:{for(Se=G.key;B!==null;){if(B.key===Se)if(B.tag===4&&B.stateNode.containerInfo===G.containerInfo&&B.stateNode.implementation===G.implementation){a(z,B.sibling),W=c(B,G.children||[]),W.return=z,z=W;break e}else{a(z,B);break}else t(z,B);B=B.sibling}W=uc(G,z.mode,W),W.return=z,z=W}return b(z);case U:return G=Ia(G),Ke(z,B,G,W)}if(V(G))return he(z,B,G,W);if(te(G)){if(Se=te(G),typeof Se!="function")throw Error(o(150));return G=Se.call(G),je(z,B,G,W)}if(typeof G.then=="function")return Ke(z,B,tr(G),W);if(G.$$typeof===T)return Ke(z,B,Ji(z,G),W);nr(z,G)}return typeof G=="string"&&G!==""||typeof G=="number"||typeof G=="bigint"?(G=""+G,B!==null&&B.tag===6?(a(z,B.sibling),W=c(B,G),W.return=z,z=W):(a(z,B),W=cc(G,z.mode,W),W.return=z,z=W),b(z)):a(z,B)}return function(z,B,G,W){try{Tl=0;var Se=Ke(z,B,G,W);return Ls=null,Se}catch(ge){if(ge===Os||ge===Wi)throw ge;var Oe=Qt(29,ge,null,z.mode);return Oe.lanes=W,Oe.return=z,Oe}finally{}}}var Pa=km(!0),Mm=km(!1),ga=!1;function jc(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ac(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function va(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function ba(e,t,a){var i=e.updateQueue;if(i===null)return null;if(i=i.shared,(Ue&2)!==0){var c=i.pending;return c===null?t.next=t:(t.next=c.next,c.next=t),i.pending=t,t=Qi(e),dm(e,null,a),t}return Xi(e,i,t,a),Qi(e)}function _l(e,t,a){if(t=t.updateQueue,t!==null&&(t=t.shared,(a&4194048)!==0)){var i=t.lanes;i&=e.pendingLanes,a|=i,t.lanes=a,an(e,a)}}function Nc(e,t){var a=e.updateQueue,i=e.alternate;if(i!==null&&(i=i.updateQueue,a===i)){var c=null,u=null;if(a=a.firstBaseUpdate,a!==null){do{var b={lane:a.lane,tag:a.tag,payload:a.payload,callback:null,next:null};u===null?c=u=b:u=u.next=b,a=a.next}while(a!==null);u===null?c=u=t:u=u.next=t}else c=u=t;a={baseState:i.baseState,firstBaseUpdate:c,lastBaseUpdate:u,shared:i.shared,callbacks:i.callbacks},e.updateQueue=a;return}e=a.lastBaseUpdate,e===null?a.firstBaseUpdate=t:e.next=t,a.lastBaseUpdate=t}var wc=!1;function Bl(){if(wc){var e=Bs;if(e!==null)throw e}}function Ol(e,t,a,i){wc=!1;var c=e.updateQueue;ga=!1;var u=c.firstBaseUpdate,b=c.lastBaseUpdate,A=c.shared.pending;if(A!==null){c.shared.pending=null;var D=A,Y=D.next;D.next=null,b===null?u=Y:b.next=Y,b=D;var J=e.alternate;J!==null&&(J=J.updateQueue,A=J.lastBaseUpdate,A!==b&&(A===null?J.firstBaseUpdate=Y:A.next=Y,J.lastBaseUpdate=D))}if(u!==null){var ne=c.baseState;b=0,J=Y=D=null,A=u;do{var Q=A.lane&-536870913,I=Q!==A.lane;if(I?(qe&Q)===Q:(i&Q)===Q){Q!==0&&Q===_s&&(wc=!0),J!==null&&(J=J.next={lane:0,tag:A.tag,payload:A.payload,callback:null,next:null});e:{var he=e,je=A;Q=t;var Ke=a;switch(je.tag){case 1:if(he=je.payload,typeof he=="function"){ne=he.call(Ke,ne,Q);break e}ne=he;break e;case 3:he.flags=he.flags&-65537|128;case 0:if(he=je.payload,Q=typeof he=="function"?he.call(Ke,ne,Q):he,Q==null)break e;ne=y({},ne,Q);break e;case 2:ga=!0}}Q=A.callback,Q!==null&&(e.flags|=64,I&&(e.flags|=8192),I=c.callbacks,I===null?c.callbacks=[Q]:I.push(Q))}else I={lane:Q,tag:A.tag,payload:A.payload,callback:A.callback,next:null},J===null?(Y=J=I,D=ne):J=J.next=I,b|=Q;if(A=A.next,A===null){if(A=c.shared.pending,A===null)break;I=A,A=I.next,I.next=null,c.lastBaseUpdate=I,c.shared.pending=null}}while(!0);J===null&&(D=ne),c.baseState=D,c.firstBaseUpdate=Y,c.lastBaseUpdate=J,u===null&&(c.shared.lanes=0),Na|=b,e.lanes=b,e.memoizedState=ne}}function Rm(e,t){if(typeof e!="function")throw Error(o(191,e));e.call(t)}function qm(e,t){var a=e.callbacks;if(a!==null)for(e.callbacks=null,e=0;eu?u:8;var b=q.T,A={};q.T=A,Yc(e,!1,t,a);try{var D=c(),Y=q.S;if(Y!==null&&Y(A,D),D!==null&&typeof D=="object"&&typeof D.then=="function"){var J=nb(D,i);Ul(e,t,J,Pt(e))}else Ul(e,t,i,Pt(e))}catch(ne){Ul(e,t,{then:function(){},status:"rejected",reason:ne},Pt())}finally{L.p=u,b!==null&&A.types!==null&&(b.types=A.types),q.T=b}}function ob(){}function $c(e,t,a,i){if(e.tag!==5)throw Error(o(476));var c=ch(e).queue;oh(e,c,t,Z,a===null?ob:function(){return uh(e),a(i)})}function ch(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:Z,baseState:Z,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Qn,lastRenderedState:Z},next:null};var a={};return t.next={memoizedState:a,baseState:a,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Qn,lastRenderedState:a},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function uh(e){var t=ch(e);t.next===null&&(t=e.alternate.memoizedState),Ul(e,t.next.queue,{},Pt())}function Gc(){return qt(ni)}function fh(){return gt().memoizedState}function dh(){return gt().memoizedState}function cb(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var a=Pt();e=va(a);var i=ba(t,e,a);i!==null&&(Gt(i,t,a),_l(i,t,a)),t={cache:vc()},e.payload=t;return}t=t.return}}function ub(e,t,a){var i=Pt();a={lane:i,revertLane:0,gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},dr(e)?hh(t,a):(a=rc(e,t,a,i),a!==null&&(Gt(a,e,i),ph(a,t,i)))}function mh(e,t,a){var i=Pt();Ul(e,t,a,i)}function Ul(e,t,a,i){var c={lane:i,revertLane:0,gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null};if(dr(e))hh(t,c);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var b=t.lastRenderedState,A=u(b,a);if(c.hasEagerState=!0,c.eagerState=A,Xt(A,b))return Xi(e,t,c,0),Ie===null&&Fi(),!1}catch{}finally{}if(a=rc(e,t,c,i),a!==null)return Gt(a,e,i),ph(a,t,i),!0}return!1}function Yc(e,t,a,i){if(i={lane:2,revertLane:ju(),gesture:null,action:i,hasEagerState:!1,eagerState:null,next:null},dr(e)){if(t)throw Error(o(479))}else t=rc(e,a,i,2),t!==null&&Gt(t,e,2)}function dr(e){var t=e.alternate;return e===Ce||t!==null&&t===Ce}function hh(e,t){Us=lr=!0;var a=e.pending;a===null?t.next=t:(t.next=a.next,a.next=t),e.pending=t}function ph(e,t,a){if((a&4194048)!==0){var i=t.lanes;i&=e.pendingLanes,a|=i,t.lanes=a,an(e,a)}}var Hl={readContext:qt,use:or,useCallback:dt,useContext:dt,useEffect:dt,useImperativeHandle:dt,useLayoutEffect:dt,useInsertionEffect:dt,useMemo:dt,useReducer:dt,useRef:dt,useState:dt,useDebugValue:dt,useDeferredValue:dt,useTransition:dt,useSyncExternalStore:dt,useId:dt,useHostTransitionStatus:dt,useFormState:dt,useActionState:dt,useOptimistic:dt,useMemoCache:dt,useCacheRefresh:dt};Hl.useEffectEvent=dt;var xh={readContext:qt,use:or,useCallback:function(e,t){return Lt().memoizedState=[e,t===void 0?null:t],e},useContext:qt,useEffect:Wm,useImperativeHandle:function(e,t,a){a=a!=null?a.concat([e]):null,ur(4194308,4,ah.bind(null,t,e),a)},useLayoutEffect:function(e,t){return ur(4194308,4,e,t)},useInsertionEffect:function(e,t){ur(4,2,e,t)},useMemo:function(e,t){var a=Lt();t=t===void 0?null:t;var i=e();if(Wa){Ft(!0);try{e()}finally{Ft(!1)}}return a.memoizedState=[i,t],i},useReducer:function(e,t,a){var i=Lt();if(a!==void 0){var c=a(t);if(Wa){Ft(!0);try{a(t)}finally{Ft(!1)}}}else c=t;return i.memoizedState=i.baseState=c,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:c},i.queue=e,e=e.dispatch=ub.bind(null,Ce,e),[i.memoizedState,e]},useRef:function(e){var t=Lt();return e={current:e},t.memoizedState=e},useState:function(e){e=Lc(e);var t=e.queue,a=mh.bind(null,Ce,t);return t.dispatch=a,[e.memoizedState,a]},useDebugValue:Hc,useDeferredValue:function(e,t){var a=Lt();return Vc(a,e,t)},useTransition:function(){var e=Lc(!1);return e=oh.bind(null,Ce,e.queue,!0,!1),Lt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,a){var i=Ce,c=Lt();if(De){if(a===void 0)throw Error(o(407));a=a()}else{if(a=t(),Ie===null)throw Error(o(349));(qe&127)!==0||Lm(i,t,a)}c.memoizedState=a;var u={value:a,getSnapshot:t};return c.queue=u,Wm(Um.bind(null,i,u,e),[e]),i.flags|=2048,Vs(9,{destroy:void 0},zm.bind(null,i,u,a,t),null),a},useId:function(){var e=Lt(),t=Ie.identifierPrefix;if(De){var a=kn,i=En;a=(i&~(1<<32-Mt(i)-1)).toString(32)+a,t="_"+t+"R_"+a,a=ir++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof i.is=="string"?b.createElement("select",{is:i.is}):b.createElement("select"),i.multiple?u.multiple=!0:i.size&&(u.size=i.size);break;default:u=typeof i.is=="string"?b.createElement(c,{is:i.is}):b.createElement(c)}}u[ot]=t,u[wt]=i;e:for(b=t.child;b!==null;){if(b.tag===5||b.tag===6)u.appendChild(b.stateNode);else if(b.tag!==4&&b.tag!==27&&b.child!==null){b.child.return=b,b=b.child;continue}if(b===t)break e;for(;b.sibling===null;){if(b.return===null||b.return===t)break e;b=b.return}b.sibling.return=b.return,b=b.sibling}t.stateNode=u;e:switch(Dt(u,c,i),c){case"button":case"input":case"select":case"textarea":i=!!i.autoFocus;break e;case"img":i=!0;break e;default:i=!1}i&&Zn(t)}}return et(t),su(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,a),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==i&&Zn(t);else{if(typeof i!="string"&&t.stateNode===null)throw Error(o(166));if(e=re.current,Ts(t)){if(e=t.stateNode,a=t.memoizedProps,i=null,c=Rt,c!==null)switch(c.tag){case 27:case 5:i=c.memoizedProps}e[ot]=t,e=!!(e.nodeValue===a||i!==null&&i.suppressHydrationWarning===!0||Bp(e.nodeValue,a)),e||pa(t,!0)}else e=Tr(e).createTextNode(i),e[ot]=t,t.stateNode=e}return et(t),null;case 31:if(a=t.memoizedState,e===null||e.memoizedState!==null){if(i=Ts(t),a!==null){if(e===null){if(!i)throw Error(o(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(o(557));e[ot]=t}else Xa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;et(t),e=!1}else a=hc(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),e=!0;if(!e)return t.flags&256?(Zt(t),t):(Zt(t),null);if((t.flags&128)!==0)throw Error(o(558))}return et(t),null;case 13:if(i=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(c=Ts(t),i!==null&&i.dehydrated!==null){if(e===null){if(!c)throw Error(o(318));if(c=t.memoizedState,c=c!==null?c.dehydrated:null,!c)throw Error(o(317));c[ot]=t}else Xa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;et(t),c=!1}else c=hc(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=c),c=!0;if(!c)return t.flags&256?(Zt(t),t):(Zt(t),null)}return Zt(t),(t.flags&128)!==0?(t.lanes=a,t):(a=i!==null,e=e!==null&&e.memoizedState!==null,a&&(i=t.child,c=null,i.alternate!==null&&i.alternate.memoizedState!==null&&i.alternate.memoizedState.cachePool!==null&&(c=i.alternate.memoizedState.cachePool.pool),u=null,i.memoizedState!==null&&i.memoizedState.cachePool!==null&&(u=i.memoizedState.cachePool.pool),u!==c&&(i.flags|=2048)),a!==e&&a&&(t.child.flags|=8192),gr(t,t.updateQueue),et(t),null);case 4:return be(),e===null&&Cu(t.stateNode.containerInfo),et(t),null;case 10:return Fn(t.type),et(t),null;case 19:if($(xt),i=t.memoizedState,i===null)return et(t),null;if(c=(t.flags&128)!==0,u=i.rendering,u===null)if(c)$l(i,!1);else{if(mt!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=sr(e),u!==null){for(t.flags|=128,$l(i,!1),e=u.updateQueue,t.updateQueue=e,gr(t,e),t.subtreeFlags=0,e=a,a=t.child;a!==null;)mm(a,e),a=a.sibling;return ee(xt,xt.current&1|2),De&&Gn(t,i.treeForkCount),t.child}e=e.sibling}i.tail!==null&&Ve()>jr&&(t.flags|=128,c=!0,$l(i,!1),t.lanes=4194304)}else{if(!c)if(e=sr(u),e!==null){if(t.flags|=128,c=!0,e=e.updateQueue,t.updateQueue=e,gr(t,e),$l(i,!0),i.tail===null&&i.tailMode==="hidden"&&!u.alternate&&!De)return et(t),null}else 2*Ve()-i.renderingStartTime>jr&&a!==536870912&&(t.flags|=128,c=!0,$l(i,!1),t.lanes=4194304);i.isBackwards?(u.sibling=t.child,t.child=u):(e=i.last,e!==null?e.sibling=u:t.child=u,i.last=u)}return i.tail!==null?(e=i.tail,i.rendering=e,i.tail=e.sibling,i.renderingStartTime=Ve(),e.sibling=null,a=xt.current,ee(xt,c?a&1|2:a&1),De&&Gn(t,i.treeForkCount),e):(et(t),null);case 22:case 23:return Zt(t),Ec(),i=t.memoizedState!==null,e!==null?e.memoizedState!==null!==i&&(t.flags|=8192):i&&(t.flags|=8192),i?(a&536870912)!==0&&(t.flags&128)===0&&(et(t),t.subtreeFlags&6&&(t.flags|=8192)):et(t),a=t.updateQueue,a!==null&&gr(t,a.retryQueue),a=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(a=e.memoizedState.cachePool.pool),i=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(i=t.memoizedState.cachePool.pool),i!==a&&(t.flags|=2048),e!==null&&$(Za),null;case 24:return a=null,e!==null&&(a=e.memoizedState.cache),t.memoizedState.cache!==a&&(t.flags|=2048),Fn(bt),et(t),null;case 25:return null;case 30:return null}throw Error(o(156,t.tag))}function pb(e,t){switch(dc(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Fn(bt),be(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Be(t),null;case 31:if(t.memoizedState!==null){if(Zt(t),t.alternate===null)throw Error(o(340));Xa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Zt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(o(340));Xa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return $(xt),null;case 4:return be(),null;case 10:return Fn(t.type),null;case 22:case 23:return Zt(t),Ec(),e!==null&&$(Za),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Fn(bt),null;case 25:return null;default:return null}}function Hh(e,t){switch(dc(t),t.tag){case 3:Fn(bt),be();break;case 26:case 27:case 5:Be(t);break;case 4:be();break;case 31:t.memoizedState!==null&&Zt(t);break;case 13:Zt(t);break;case 19:$(xt);break;case 10:Fn(t.type);break;case 22:case 23:Zt(t),Ec(),e!==null&&$(Za);break;case 24:Fn(bt)}}function Gl(e,t){try{var a=t.updateQueue,i=a!==null?a.lastEffect:null;if(i!==null){var c=i.next;a=c;do{if((a.tag&e)===e){i=void 0;var u=a.create,b=a.inst;i=u(),b.destroy=i}a=a.next}while(a!==c)}}catch(A){Ye(t,t.return,A)}}function ja(e,t,a){try{var i=t.updateQueue,c=i!==null?i.lastEffect:null;if(c!==null){var u=c.next;i=u;do{if((i.tag&e)===e){var b=i.inst,A=b.destroy;if(A!==void 0){b.destroy=void 0,c=t;var D=a,Y=A;try{Y()}catch(J){Ye(c,D,J)}}}i=i.next}while(i!==u)}}catch(J){Ye(t,t.return,J)}}function Vh(e){var t=e.updateQueue;if(t!==null){var a=e.stateNode;try{qm(t,a)}catch(i){Ye(e,e.return,i)}}}function $h(e,t,a){a.props=es(e.type,e.memoizedProps),a.state=e.memoizedState;try{a.componentWillUnmount()}catch(i){Ye(e,t,i)}}function Yl(e,t){try{var a=e.ref;if(a!==null){switch(e.tag){case 26:case 27:case 5:var i=e.stateNode;break;case 30:i=e.stateNode;break;default:i=e.stateNode}typeof a=="function"?e.refCleanup=a(i):a.current=i}}catch(c){Ye(e,t,c)}}function Mn(e,t){var a=e.ref,i=e.refCleanup;if(a!==null)if(typeof i=="function")try{i()}catch(c){Ye(e,t,c)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof a=="function")try{a(null)}catch(c){Ye(e,t,c)}else a.current=null}function Gh(e){var t=e.type,a=e.memoizedProps,i=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":a.autoFocus&&i.focus();break e;case"img":a.src?i.src=a.src:a.srcSet&&(i.srcset=a.srcSet)}}catch(c){Ye(e,e.return,c)}}function lu(e,t,a){try{var i=e.stateNode;Lb(i,e.type,a,t),i[wt]=t}catch(c){Ye(e,e.return,c)}}function Yh(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Ma(e.type)||e.tag===4}function iu(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Yh(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Ma(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function ru(e,t,a){var i=e.tag;if(i===5||i===6)e=e.stateNode,t?(a.nodeType===9?a.body:a.nodeName==="HTML"?a.ownerDocument.body:a).insertBefore(e,t):(t=a.nodeType===9?a.body:a.nodeName==="HTML"?a.ownerDocument.body:a,t.appendChild(e),a=a._reactRootContainer,a!=null||t.onclick!==null||(t.onclick=Hn));else if(i!==4&&(i===27&&Ma(e.type)&&(a=e.stateNode,t=null),e=e.child,e!==null))for(ru(e,t,a),e=e.sibling;e!==null;)ru(e,t,a),e=e.sibling}function vr(e,t,a){var i=e.tag;if(i===5||i===6)e=e.stateNode,t?a.insertBefore(e,t):a.appendChild(e);else if(i!==4&&(i===27&&Ma(e.type)&&(a=e.stateNode),e=e.child,e!==null))for(vr(e,t,a),e=e.sibling;e!==null;)vr(e,t,a),e=e.sibling}function Fh(e){var t=e.stateNode,a=e.memoizedProps;try{for(var i=e.type,c=t.attributes;c.length;)t.removeAttributeNode(c[0]);Dt(t,i,a),t[ot]=e,t[wt]=a}catch(u){Ye(e,e.return,u)}}var In=!1,jt=!1,ou=!1,Xh=typeof WeakSet=="function"?WeakSet:Set,kt=null;function xb(e,t){if(e=e.containerInfo,Mu=Ur,e=sm(e),tc(e)){if("selectionStart"in e)var a={start:e.selectionStart,end:e.selectionEnd};else e:{a=(a=e.ownerDocument)&&a.defaultView||window;var i=a.getSelection&&a.getSelection();if(i&&i.rangeCount!==0){a=i.anchorNode;var c=i.anchorOffset,u=i.focusNode;i=i.focusOffset;try{a.nodeType,u.nodeType}catch{a=null;break e}var b=0,A=-1,D=-1,Y=0,J=0,ne=e,Q=null;t:for(;;){for(var I;ne!==a||c!==0&&ne.nodeType!==3||(A=b+c),ne!==u||i!==0&&ne.nodeType!==3||(D=b+i),ne.nodeType===3&&(b+=ne.nodeValue.length),(I=ne.firstChild)!==null;)Q=ne,ne=I;for(;;){if(ne===e)break t;if(Q===a&&++Y===c&&(A=b),Q===u&&++J===i&&(D=b),(I=ne.nextSibling)!==null)break;ne=Q,Q=ne.parentNode}ne=I}a=A===-1||D===-1?null:{start:A,end:D}}else a=null}a=a||{start:0,end:0}}else a=null;for(Ru={focusedElem:e,selectionRange:a},Ur=!1,kt=t;kt!==null;)if(t=kt,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,kt=e;else for(;kt!==null;){switch(t=kt,u=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(a=0;a title"))),Dt(u,i,a),u[ot]=e,Et(u),i=u;break e;case"link":var b=Pp("link","href",c).get(i+(a.href||""));if(b){for(var A=0;AKe&&(b=Ke,Ke=je,je=b);var z=nm(A,je),B=nm(A,Ke);if(z&&B&&(I.rangeCount!==1||I.anchorNode!==z.node||I.anchorOffset!==z.offset||I.focusNode!==B.node||I.focusOffset!==B.offset)){var G=ne.createRange();G.setStart(z.node,z.offset),I.removeAllRanges(),je>Ke?(I.addRange(G),I.extend(B.node,B.offset)):(G.setEnd(B.node,B.offset),I.addRange(G))}}}}for(ne=[],I=A;I=I.parentNode;)I.nodeType===1&&ne.push({element:I,left:I.scrollLeft,top:I.scrollTop});for(typeof A.focus=="function"&&A.focus(),A=0;Aa?32:a,q.T=null,a=pu,pu=null;var u=Ca,b=ta;if(Ct=0,Xs=Ca=null,ta=0,(Ue&6)!==0)throw Error(o(331));var A=Ue;if(Ue|=4,ap(u.current),ep(u,u.current,b,a),Ue=A,Il(0,!1),Nt&&typeof Nt.onPostCommitFiberRoot=="function")try{Nt.onPostCommitFiberRoot(Bn,u)}catch{}return!0}finally{L.p=c,q.T=i,Sp(e,t)}}function Ap(e,t,a){t=on(a,t),t=Kc(e.stateNode,t,2),e=ba(e,t,2),e!==null&&(Ua(e,2),Rn(e))}function Ye(e,t,a){if(e.tag===3)Ap(e,e,a);else for(;t!==null;){if(t.tag===3){Ap(t,e,a);break}else if(t.tag===1){var i=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof i.componentDidCatch=="function"&&(wa===null||!wa.has(i))){e=on(a,e),a=Nh(2),i=ba(t,a,2),i!==null&&(wh(a,i,t,e),Ua(i,2),Rn(i));break}}t=t.return}}function bu(e,t,a){var i=e.pingCache;if(i===null){i=e.pingCache=new bb;var c=new Set;i.set(t,c)}else c=i.get(t),c===void 0&&(c=new Set,i.set(t,c));c.has(a)||(fu=!0,c.add(a),e=Nb.bind(null,e,t,a),t.then(e,e))}function Nb(e,t,a){var i=e.pingCache;i!==null&&i.delete(t),e.pingedLanes|=e.suspendedLanes&a,e.warmLanes&=~a,Ie===e&&(qe&a)===a&&(mt===4||mt===3&&(qe&62914560)===qe&&300>Ve()-Sr?(Ue&2)===0&&Qs(e,0):du|=a,Fs===qe&&(Fs=0)),Rn(e)}function Np(e,t){t===0&&(t=hl()),e=Ya(e,t),e!==null&&(Ua(e,t),Rn(e))}function wb(e){var t=e.memoizedState,a=0;t!==null&&(a=t.retryLane),Np(e,a)}function Cb(e,t){var a=0;switch(e.tag){case 31:case 13:var i=e.stateNode,c=e.memoizedState;c!==null&&(a=c.retryLane);break;case 19:i=e.stateNode;break;case 22:i=e.stateNode._retryCache;break;default:throw Error(o(314))}i!==null&&i.delete(t),Np(e,a)}function Eb(e,t){return P(e,t)}var kr=null,Zs=null,yu=!1,Mr=!1,Su=!1,ka=0;function Rn(e){e!==Zs&&e.next===null&&(Zs===null?kr=Zs=e:Zs=Zs.next=e),Mr=!0,yu||(yu=!0,Mb())}function Il(e,t){if(!Su&&Mr){Su=!0;do for(var a=!1,i=kr;i!==null;){if(e!==0){var c=i.pendingLanes;if(c===0)var u=0;else{var b=i.suspendedLanes,A=i.pingedLanes;u=(1<<31-Mt(42|e)+1)-1,u&=c&~(b&~A),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(a=!0,kp(i,u))}else u=qe,u=Cn(i,i===Ie?u:0,i.cancelPendingCommit!==null||i.timeoutHandle!==-1),(u&3)===0||Ln(i,u)||(a=!0,kp(i,u));i=i.next}while(a);Su=!1}}function kb(){wp()}function wp(){Mr=yu=!1;var e=0;ka!==0&&Ub()&&(e=ka);for(var t=Ve(),a=null,i=kr;i!==null;){var c=i.next,u=Cp(i,t);u===0?(i.next=null,a===null?kr=c:a.next=c,c===null&&(Zs=a)):(a=i,(e!==0||(u&3)!==0)&&(Mr=!0)),i=c}Ct!==0&&Ct!==5||Il(e),ka!==0&&(ka=0)}function Cp(e,t){for(var a=e.suspendedLanes,i=e.pingedLanes,c=e.expirationTimes,u=e.pendingLanes&-62914561;0A)break;var J=D.transferSize,ne=D.initiatorType;J&&Op(ne)&&(D=D.responseEnd,b+=J*(D"u"?null:document;function Kp(e,t,a){var i=Is;if(i&&typeof t=="string"&&t){var c=ln(t);c='link[rel="'+e+'"][href="'+c+'"]',typeof a=="string"&&(c+='[crossorigin="'+a+'"]'),Qp.has(c)||(Qp.add(c),e={rel:e,crossOrigin:a,href:t},i.querySelector(c)===null&&(t=i.createElement("link"),Dt(t,"link",e),Et(t),i.head.appendChild(t)))}}function Kb(e){na.D(e),Kp("dns-prefetch",e,null)}function Zb(e,t){na.C(e,t),Kp("preconnect",e,t)}function Ib(e,t,a){na.L(e,t,a);var i=Is;if(i&&e&&t){var c='link[rel="preload"][as="'+ln(t)+'"]';t==="image"&&a&&a.imageSrcSet?(c+='[imagesrcset="'+ln(a.imageSrcSet)+'"]',typeof a.imageSizes=="string"&&(c+='[imagesizes="'+ln(a.imageSizes)+'"]')):c+='[href="'+ln(e)+'"]';var u=c;switch(t){case"style":u=Js(e);break;case"script":u=Ps(e)}hn.has(u)||(e=y({rel:"preload",href:t==="image"&&a&&a.imageSrcSet?void 0:e,as:t},a),hn.set(u,e),i.querySelector(c)!==null||t==="style"&&i.querySelector(ei(u))||t==="script"&&i.querySelector(ti(u))||(t=i.createElement("link"),Dt(t,"link",e),Et(t),i.head.appendChild(t)))}}function Jb(e,t){na.m(e,t);var a=Is;if(a&&e){var i=t&&typeof t.as=="string"?t.as:"script",c='link[rel="modulepreload"][as="'+ln(i)+'"][href="'+ln(e)+'"]',u=c;switch(i){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ps(e)}if(!hn.has(u)&&(e=y({rel:"modulepreload",href:e},t),hn.set(u,e),a.querySelector(c)===null)){switch(i){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(a.querySelector(ti(u)))return}i=a.createElement("link"),Dt(i,"link",e),Et(i),a.head.appendChild(i)}}}function Pb(e,t,a){na.S(e,t,a);var i=Is;if(i&&e){var c=bs(i).hoistableStyles,u=Js(e);t=t||"default";var b=c.get(u);if(!b){var A={loading:0,preload:null};if(b=i.querySelector(ei(u)))A.loading=5;else{e=y({rel:"stylesheet",href:e,"data-precedence":t},a),(a=hn.get(u))&&Lu(e,a);var D=b=i.createElement("link");Et(D),Dt(D,"link",e),D._p=new Promise(function(Y,J){D.onload=Y,D.onerror=J}),D.addEventListener("load",function(){A.loading|=1}),D.addEventListener("error",function(){A.loading|=2}),A.loading|=4,_r(b,t,i)}b={type:"stylesheet",instance:b,count:1,state:A},c.set(u,b)}}}function Wb(e,t){na.X(e,t);var a=Is;if(a&&e){var i=bs(a).hoistableScripts,c=Ps(e),u=i.get(c);u||(u=a.querySelector(ti(c)),u||(e=y({src:e,async:!0},t),(t=hn.get(c))&&zu(e,t),u=a.createElement("script"),Et(u),Dt(u,"link",e),a.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},i.set(c,u))}}function ey(e,t){na.M(e,t);var a=Is;if(a&&e){var i=bs(a).hoistableScripts,c=Ps(e),u=i.get(c);u||(u=a.querySelector(ti(c)),u||(e=y({src:e,async:!0,type:"module"},t),(t=hn.get(c))&&zu(e,t),u=a.createElement("script"),Et(u),Dt(u,"link",e),a.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},i.set(c,u))}}function Zp(e,t,a,i){var c=(c=re.current)?Dr(c):null;if(!c)throw Error(o(446));switch(e){case"meta":case"title":return null;case"style":return typeof a.precedence=="string"&&typeof a.href=="string"?(t=Js(a.href),a=bs(c).hoistableStyles,i=a.get(t),i||(i={type:"style",instance:null,count:0,state:null},a.set(t,i)),i):{type:"void",instance:null,count:0,state:null};case"link":if(a.rel==="stylesheet"&&typeof a.href=="string"&&typeof a.precedence=="string"){e=Js(a.href);var u=bs(c).hoistableStyles,b=u.get(e);if(b||(c=c.ownerDocument||c,b={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(e,b),(u=c.querySelector(ei(e)))&&!u._p&&(b.instance=u,b.state.loading=5),hn.has(e)||(a={rel:"preload",as:"style",href:a.href,crossOrigin:a.crossOrigin,integrity:a.integrity,media:a.media,hrefLang:a.hrefLang,referrerPolicy:a.referrerPolicy},hn.set(e,a),u||ty(c,e,a,b.state))),t&&i===null)throw Error(o(528,""));return b}if(t&&i!==null)throw Error(o(529,""));return null;case"script":return t=a.async,a=a.src,typeof a=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Ps(a),a=bs(c).hoistableScripts,i=a.get(t),i||(i={type:"script",instance:null,count:0,state:null},a.set(t,i)),i):{type:"void",instance:null,count:0,state:null};default:throw Error(o(444,e))}}function Js(e){return'href="'+ln(e)+'"'}function ei(e){return'link[rel="stylesheet"]['+e+"]"}function Ip(e){return y({},e,{"data-precedence":e.precedence,precedence:null})}function ty(e,t,a,i){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?i.loading=1:(t=e.createElement("link"),i.preload=t,t.addEventListener("load",function(){return i.loading|=1}),t.addEventListener("error",function(){return i.loading|=2}),Dt(t,"link",a),Et(t),e.head.appendChild(t))}function Ps(e){return'[src="'+ln(e)+'"]'}function ti(e){return"script[async]"+e}function Jp(e,t,a){if(t.count++,t.instance===null)switch(t.type){case"style":var i=e.querySelector('style[data-href~="'+ln(a.href)+'"]');if(i)return t.instance=i,Et(i),i;var c=y({},a,{"data-href":a.href,"data-precedence":a.precedence,href:null,precedence:null});return i=(e.ownerDocument||e).createElement("style"),Et(i),Dt(i,"style",c),_r(i,a.precedence,e),t.instance=i;case"stylesheet":c=Js(a.href);var u=e.querySelector(ei(c));if(u)return t.state.loading|=4,t.instance=u,Et(u),u;i=Ip(a),(c=hn.get(c))&&Lu(i,c),u=(e.ownerDocument||e).createElement("link"),Et(u);var b=u;return b._p=new Promise(function(A,D){b.onload=A,b.onerror=D}),Dt(u,"link",i),t.state.loading|=4,_r(u,a.precedence,e),t.instance=u;case"script":return u=Ps(a.src),(c=e.querySelector(ti(u)))?(t.instance=c,Et(c),c):(i=a,(c=hn.get(u))&&(i=y({},a),zu(i,c)),e=e.ownerDocument||e,c=e.createElement("script"),Et(c),Dt(c,"link",i),e.head.appendChild(c),t.instance=c);case"void":return null;default:throw Error(o(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(i=t.instance,t.state.loading|=4,_r(i,a.precedence,e));return t.instance}function _r(e,t,a){for(var i=a.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),c=i.length?i[i.length-1]:null,u=c,b=0;b title"):null)}function ny(e,t,a){if(a===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return e=t.disabled,typeof t.precedence=="string"&&e==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function e0(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function ay(e,t,a,i){if(a.type==="stylesheet"&&(typeof i.media!="string"||matchMedia(i.media).matches!==!1)&&(a.state.loading&4)===0){if(a.instance===null){var c=Js(i.href),u=t.querySelector(ei(c));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=Or.bind(e),t.then(e,e)),a.state.loading|=4,a.instance=u,Et(u);return}u=t.ownerDocument||t,i=Ip(i),(c=hn.get(c))&&Lu(i,c),u=u.createElement("link"),Et(u);var b=u;b._p=new Promise(function(A,D){b.onload=A,b.onerror=D}),Dt(u,"link",i),a.instance=u}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(a,t),(t=a.state.preload)&&(a.state.loading&3)===0&&(e.count++,a=Or.bind(e),t.addEventListener("load",a),t.addEventListener("error",a))}}var Uu=0;function sy(e,t){return e.stylesheets&&e.count===0&&zr(e,e.stylesheets),0Uu?50:800)+t);return e.unsuspend=a,function(){e.unsuspend=null,clearTimeout(i),clearTimeout(c)}}:null}function Or(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)zr(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Lr=null;function zr(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Lr=new Map,t.forEach(ly,e),Lr=null,Or.call(e))}function ly(e,t){if(!(t.state.loading&4)){var a=Lr.get(e);if(a)var i=a.get(null);else{a=new Map,Lr.set(e,a);for(var c=e.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(s){console.error(s)}}return n(),Ku.exports=jy(),Ku.exports}var Ny=Ay();var N0="popstate";function wy(n={}){function s(o,f){let{pathname:d,search:h,hash:p}=o.location;return Af("",{pathname:d,search:h,hash:p},f.state&&f.state.usr||null,f.state&&f.state.key||"default")}function l(o,f){return typeof f=="string"?f:yi(f)}return Ey(s,l,null,n)}function ut(n,s){if(n===!1||n===null||typeof n>"u")throw new Error(s)}function Nn(n,s){if(!n){typeof console<"u"&&console.warn(s);try{throw new Error(s)}catch{}}}function Cy(){return Math.random().toString(36).substring(2,10)}function w0(n,s){return{usr:n.state,key:n.key,idx:s}}function Af(n,s,l=null,o){return{pathname:typeof n=="string"?n:n.pathname,search:"",hash:"",...typeof s=="string"?ul(s):s,state:l,key:s&&s.key||o||Cy()}}function yi({pathname:n="/",search:s="",hash:l=""}){return s&&s!=="?"&&(n+=s.charAt(0)==="?"?s:"?"+s),l&&l!=="#"&&(n+=l.charAt(0)==="#"?l:"#"+l),n}function ul(n){let s={};if(n){let l=n.indexOf("#");l>=0&&(s.hash=n.substring(l),n=n.substring(0,l));let o=n.indexOf("?");o>=0&&(s.search=n.substring(o),n=n.substring(0,o)),n&&(s.pathname=n)}return s}function Ey(n,s,l,o={}){let{window:f=document.defaultView,v5Compat:d=!1}=o,h=f.history,p="POP",x=null,g=v();g==null&&(g=0,h.replaceState({...h.state,idx:g},""));function v(){return(h.state||{idx:null}).idx}function y(){p="POP";let w=v(),j=w==null?null:w-g;g=w,x&&x({action:p,location:k.location,delta:j})}function S(w,j){p="PUSH";let N=Af(k.location,w,j);g=v()+1;let T=w0(N,g),M=k.createHref(N);try{h.pushState(T,"",M)}catch(O){if(O instanceof DOMException&&O.name==="DataCloneError")throw O;f.location.assign(M)}d&&x&&x({action:p,location:k.location,delta:1})}function E(w,j){p="REPLACE";let N=Af(k.location,w,j);g=v();let T=w0(N,g),M=k.createHref(N);h.replaceState(T,"",M),d&&x&&x({action:p,location:k.location,delta:0})}function C(w){return ky(w)}let k={get action(){return p},get location(){return n(f,h)},listen(w){if(x)throw new Error("A history only accepts one active listener");return f.addEventListener(N0,y),x=w,()=>{f.removeEventListener(N0,y),x=null}},createHref(w){return s(f,w)},createURL:C,encodeLocation(w){let j=C(w);return{pathname:j.pathname,search:j.search,hash:j.hash}},push:S,replace:E,go(w){return h.go(w)}};return k}function ky(n,s=!1){let l="http://localhost";typeof window<"u"&&(l=window.location.origin!=="null"?window.location.origin:window.location.href),ut(l,"No window.location.(origin|href) available to create URL");let o=typeof n=="string"?n:yi(n);return o=o.replace(/ $/,"%20"),!s&&o.startsWith("//")&&(o=l+o),new URL(o,l)}function kx(n,s,l="/"){return My(n,s,l,!1)}function My(n,s,l,o){let f=typeof s=="string"?ul(s):s,d=oa(f.pathname||"/",l);if(d==null)return null;let h=Mx(n);Ry(h);let p=null;for(let x=0;p==null&&x{let v={relativePath:g===void 0?h.path||"":g,caseSensitive:h.caseSensitive===!0,childrenIndex:p,route:h};if(v.relativePath.startsWith("/")){if(!v.relativePath.startsWith(o)&&x)return;ut(v.relativePath.startsWith(o),`Absolute route path "${v.relativePath}" nested under path "${o}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),v.relativePath=v.relativePath.slice(o.length)}let y=ra([o,v.relativePath]),S=l.concat(v);h.children&&h.children.length>0&&(ut(h.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${y}".`),Mx(h.children,s,S,y,x)),!(h.path==null&&!h.index)&&s.push({path:y,score:Ly(y,h.index),routesMeta:S})};return n.forEach((h,p)=>{if(h.path===""||!h.path?.includes("?"))d(h,p);else for(let x of Rx(h.path))d(h,p,!0,x)}),s}function Rx(n){let s=n.split("/");if(s.length===0)return[];let[l,...o]=s,f=l.endsWith("?"),d=l.replace(/\?$/,"");if(o.length===0)return f?[d,""]:[d];let h=Rx(o.join("/")),p=[];return p.push(...h.map(x=>x===""?d:[d,x].join("/"))),f&&p.push(...h),p.map(x=>n.startsWith("/")&&x===""?"/":x)}function Ry(n){n.sort((s,l)=>s.score!==l.score?l.score-s.score:zy(s.routesMeta.map(o=>o.childrenIndex),l.routesMeta.map(o=>o.childrenIndex)))}var qy=/^:[\w-]+$/,Ty=3,Dy=2,_y=1,By=10,Oy=-2,C0=n=>n==="*";function Ly(n,s){let l=n.split("/"),o=l.length;return l.some(C0)&&(o+=Oy),s&&(o+=Dy),l.filter(f=>!C0(f)).reduce((f,d)=>f+(qy.test(d)?Ty:d===""?_y:By),o)}function zy(n,s){return n.length===s.length&&n.slice(0,-1).every((o,f)=>o===s[f])?n[n.length-1]-s[s.length-1]:0}function Uy(n,s,l=!1){let{routesMeta:o}=n,f={},d="/",h=[];for(let p=0;p{if(v==="*"){let C=p[S]||"";h=d.slice(0,d.length-C.length).replace(/(.)\/+$/,"$1")}const E=p[S];return y&&!E?g[v]=void 0:g[v]=(E||"").replace(/%2F/g,"/"),g},{}),pathname:d,pathnameBase:h,pattern:n}}function Hy(n,s=!1,l=!0){Nn(n==="*"||!n.endsWith("*")||n.endsWith("/*"),`Route path "${n}" will be treated as if it were "${n.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${n.replace(/\*$/,"/*")}".`);let o=[],f="^"+n.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(h,p,x)=>(o.push({paramName:p,isOptional:x!=null}),x?"/?([^\\/]+)?":"/([^\\/]+)")).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return n.endsWith("*")?(o.push({paramName:"*"}),f+=n==="*"||n==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):l?f+="\\/*$":n!==""&&n!=="/"&&(f+="(?:(?=\\/|$))"),[new RegExp(f,s?void 0:"i"),o]}function Vy(n){try{return n.split("/").map(s=>decodeURIComponent(s).replace(/\//g,"%2F")).join("/")}catch(s){return Nn(!1,`The URL path "${n}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${s}).`),n}}function oa(n,s){if(s==="/")return n;if(!n.toLowerCase().startsWith(s.toLowerCase()))return null;let l=s.endsWith("/")?s.length-1:s.length,o=n.charAt(l);return o&&o!=="/"?null:n.slice(l)||"/"}var $y=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Gy=n=>$y.test(n);function Yy(n,s="/"){let{pathname:l,search:o="",hash:f=""}=typeof n=="string"?ul(n):n,d;if(l)if(Gy(l))d=l;else{if(l.includes("//")){let h=l;l=l.replace(/\/\/+/g,"/"),Nn(!1,`Pathnames cannot have embedded double slashes - normalizing ${h} -> ${l}`)}l.startsWith("/")?d=E0(l.substring(1),"/"):d=E0(l,s)}else d=s;return{pathname:d,search:Qy(o),hash:Ky(f)}}function E0(n,s){let l=s.replace(/\/+$/,"").split("/");return n.split("/").forEach(f=>{f===".."?l.length>1&&l.pop():f!=="."&&l.push(f)}),l.length>1?l.join("/"):"/"}function Pu(n,s,l,o){return`Cannot include a '${n}' character in a manually specified \`to.${s}\` field [${JSON.stringify(o)}]. Please separate it out to the \`to.${l}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function Fy(n){return n.filter((s,l)=>l===0||s.route.path&&s.route.path.length>0)}function qx(n){let s=Fy(n);return s.map((l,o)=>o===s.length-1?l.pathname:l.pathnameBase)}function Tx(n,s,l,o=!1){let f;typeof n=="string"?f=ul(n):(f={...n},ut(!f.pathname||!f.pathname.includes("?"),Pu("?","pathname","search",f)),ut(!f.pathname||!f.pathname.includes("#"),Pu("#","pathname","hash",f)),ut(!f.search||!f.search.includes("#"),Pu("#","search","hash",f)));let d=n===""||f.pathname==="",h=d?"/":f.pathname,p;if(h==null)p=l;else{let y=s.length-1;if(!o&&h.startsWith("..")){let S=h.split("/");for(;S[0]==="..";)S.shift(),y-=1;f.pathname=S.join("/")}p=y>=0?s[y]:"/"}let x=Yy(f,p),g=h&&h!=="/"&&h.endsWith("/"),v=(d||h===".")&&l.endsWith("/");return!x.pathname.endsWith("/")&&(g||v)&&(x.pathname+="/"),x}var ra=n=>n.join("/").replace(/\/\/+/g,"/"),Xy=n=>n.replace(/\/+$/,"").replace(/^\/*/,"/"),Qy=n=>!n||n==="?"?"":n.startsWith("?")?n:"?"+n,Ky=n=>!n||n==="#"?"":n.startsWith("#")?n:"#"+n;function Zy(n){return n!=null&&typeof n.status=="number"&&typeof n.statusText=="string"&&typeof n.internal=="boolean"&&"data"in n}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Dx=["POST","PUT","PATCH","DELETE"];new Set(Dx);var Iy=["GET",...Dx];new Set(Iy);var fl=m.createContext(null);fl.displayName="DataRouter";var No=m.createContext(null);No.displayName="DataRouterState";m.createContext(!1);var _x=m.createContext({isTransitioning:!1});_x.displayName="ViewTransition";var Jy=m.createContext(new Map);Jy.displayName="Fetchers";var Py=m.createContext(null);Py.displayName="Await";var _n=m.createContext(null);_n.displayName="Navigation";var Mi=m.createContext(null);Mi.displayName="Location";var ua=m.createContext({outlet:null,matches:[],isDataRoute:!1});ua.displayName="Route";var Gf=m.createContext(null);Gf.displayName="RouteError";function Wy(n,{relative:s}={}){ut(Ri(),"useHref() may be used only in the context of a component.");let{basename:l,navigator:o}=m.useContext(_n),{hash:f,pathname:d,search:h}=qi(n,{relative:s}),p=d;return l!=="/"&&(p=d==="/"?l:ra([l,d])),o.createHref({pathname:p,search:h,hash:f})}function Ri(){return m.useContext(Mi)!=null}function ds(){return ut(Ri(),"useLocation() may be used only in the context of a component."),m.useContext(Mi).location}var Bx="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Ox(n){m.useContext(_n).static||m.useLayoutEffect(n)}function e1(){let{isDataRoute:n}=m.useContext(ua);return n?m1():t1()}function t1(){ut(Ri(),"useNavigate() may be used only in the context of a component.");let n=m.useContext(fl),{basename:s,navigator:l}=m.useContext(_n),{matches:o}=m.useContext(ua),{pathname:f}=ds(),d=JSON.stringify(qx(o)),h=m.useRef(!1);return Ox(()=>{h.current=!0}),m.useCallback((x,g={})=>{if(Nn(h.current,Bx),!h.current)return;if(typeof x=="number"){l.go(x);return}let v=Tx(x,JSON.parse(d),f,g.relative==="path");n==null&&s!=="/"&&(v.pathname=v.pathname==="/"?s:ra([s,v.pathname])),(g.replace?l.replace:l.push)(v,g.state,g)},[s,l,d,f,n])}m.createContext(null);function qi(n,{relative:s}={}){let{matches:l}=m.useContext(ua),{pathname:o}=ds(),f=JSON.stringify(qx(l));return m.useMemo(()=>Tx(n,JSON.parse(f),o,s==="path"),[n,f,o,s])}function n1(n,s){return Lx(n,s)}function Lx(n,s,l,o,f){ut(Ri(),"useRoutes() may be used only in the context of a component.");let{navigator:d}=m.useContext(_n),{matches:h}=m.useContext(ua),p=h[h.length-1],x=p?p.params:{},g=p?p.pathname:"/",v=p?p.pathnameBase:"/",y=p&&p.route;{let N=y&&y.path||"";zx(g,!y||N.endsWith("*")||N.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${g}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. -Please change the parent to .`)}let S=ds(),E;if(s){let N=typeof s=="string"?ul(s):s;ut(v==="/"||N.pathname?.startsWith(v),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${v}" but pathname "${N.pathname}" was given in the \`location\` prop.`),E=N}else E=S;let C=E.pathname||"/",k=C;if(v!=="/"){let N=v.replace(/^\//,"").split("/");k="/"+C.replace(/^\//,"").split("/").slice(N.length).join("/")}let w=kx(n,{pathname:k});Nn(y||w!=null,`No routes matched location "${E.pathname}${E.search}${E.hash}" `),Nn(w==null||w[w.length-1].route.element!==void 0||w[w.length-1].route.Component!==void 0||w[w.length-1].route.lazy!==void 0,`Matched leaf route at location "${E.pathname}${E.search}${E.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let j=r1(w&&w.map(N=>Object.assign({},N,{params:Object.assign({},x,N.params),pathname:ra([v,d.encodeLocation?d.encodeLocation(N.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:N.pathname]),pathnameBase:N.pathnameBase==="/"?v:ra([v,d.encodeLocation?d.encodeLocation(N.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:N.pathnameBase])})),h,l,o,f);return s&&j?m.createElement(Mi.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...E},navigationType:"POP"}},j):j}function a1(){let n=d1(),s=Zy(n)?`${n.status} ${n.statusText}`:n instanceof Error?n.message:JSON.stringify(n),l=n instanceof Error?n.stack:null,o="rgba(200,200,200, 0.5)",f={padding:"0.5rem",backgroundColor:o},d={padding:"2px 4px",backgroundColor:o},h=null;return console.error("Error handled by React Router default ErrorBoundary:",n),h=m.createElement(m.Fragment,null,m.createElement("p",null,"💿 Hey developer 👋"),m.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",m.createElement("code",{style:d},"ErrorBoundary")," or"," ",m.createElement("code",{style:d},"errorElement")," prop on your route.")),m.createElement(m.Fragment,null,m.createElement("h2",null,"Unexpected Application Error!"),m.createElement("h3",{style:{fontStyle:"italic"}},s),l?m.createElement("pre",{style:f},l):null,h)}var s1=m.createElement(a1,null),l1=class extends m.Component{constructor(n){super(n),this.state={location:n.location,revalidation:n.revalidation,error:n.error}}static getDerivedStateFromError(n){return{error:n}}static getDerivedStateFromProps(n,s){return s.location!==n.location||s.revalidation!=="idle"&&n.revalidation==="idle"?{error:n.error,location:n.location,revalidation:n.revalidation}:{error:n.error!==void 0?n.error:s.error,location:s.location,revalidation:n.revalidation||s.revalidation}}componentDidCatch(n,s){this.props.onError?this.props.onError(n,s):console.error("React Router caught the following error during render",n)}render(){return this.state.error!==void 0?m.createElement(ua.Provider,{value:this.props.routeContext},m.createElement(Gf.Provider,{value:this.state.error,children:this.props.component})):this.props.children}};function i1({routeContext:n,match:s,children:l}){let o=m.useContext(fl);return o&&o.static&&o.staticContext&&(s.route.errorElement||s.route.ErrorBoundary)&&(o.staticContext._deepestRenderedBoundaryId=s.route.id),m.createElement(ua.Provider,{value:n},l)}function r1(n,s=[],l=null,o=null,f=null){if(n==null){if(!l)return null;if(l.errors)n=l.matches;else if(s.length===0&&!l.initialized&&l.matches.length>0)n=l.matches;else return null}let d=n,h=l?.errors;if(h!=null){let v=d.findIndex(y=>y.route.id&&h?.[y.route.id]!==void 0);ut(v>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(h).join(",")}`),d=d.slice(0,Math.min(d.length,v+1))}let p=!1,x=-1;if(l)for(let v=0;v=0?d=d.slice(0,x+1):d=[d[0]];break}}}let g=l&&o?(v,y)=>{o(v,{location:l.location,params:l.matches?.[0]?.params??{},errorInfo:y})}:void 0;return d.reduceRight((v,y,S)=>{let E,C=!1,k=null,w=null;l&&(E=h&&y.route.id?h[y.route.id]:void 0,k=y.route.errorElement||s1,p&&(x<0&&S===0?(zx("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),C=!0,w=null):x===S&&(C=!0,w=y.route.hydrateFallbackElement||null)));let j=s.concat(d.slice(0,S+1)),N=()=>{let T;return E?T=k:C?T=w:y.route.Component?T=m.createElement(y.route.Component,null):y.route.element?T=y.route.element:T=v,m.createElement(i1,{match:y,routeContext:{outlet:v,matches:j,isDataRoute:l!=null},children:T})};return l&&(y.route.ErrorBoundary||y.route.errorElement||S===0)?m.createElement(l1,{location:l.location,revalidation:l.revalidation,component:k,error:E,children:N(),routeContext:{outlet:null,matches:j,isDataRoute:!0},onError:g}):N()},null)}function Yf(n){return`${n} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function o1(n){let s=m.useContext(fl);return ut(s,Yf(n)),s}function c1(n){let s=m.useContext(No);return ut(s,Yf(n)),s}function u1(n){let s=m.useContext(ua);return ut(s,Yf(n)),s}function Ff(n){let s=u1(n),l=s.matches[s.matches.length-1];return ut(l.route.id,`${n} can only be used on routes that contain a unique "id"`),l.route.id}function f1(){return Ff("useRouteId")}function d1(){let n=m.useContext(Gf),s=c1("useRouteError"),l=Ff("useRouteError");return n!==void 0?n:s.errors?.[l]}function m1(){let{router:n}=o1("useNavigate"),s=Ff("useNavigate"),l=m.useRef(!1);return Ox(()=>{l.current=!0}),m.useCallback(async(f,d={})=>{Nn(l.current,Bx),l.current&&(typeof f=="number"?n.navigate(f):await n.navigate(f,{fromRouteId:s,...d}))},[n,s])}var k0={};function zx(n,s,l){!s&&!k0[n]&&(k0[n]=!0,Nn(!1,l))}m.memo(h1);function h1({routes:n,future:s,state:l,unstable_onError:o}){return Lx(n,void 0,l,o,s)}function no(n){ut(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function p1({basename:n="/",children:s=null,location:l,navigationType:o="POP",navigator:f,static:d=!1}){ut(!Ri(),"You cannot render a inside another . You should never have more than one in your app.");let h=n.replace(/^\/*/,"/"),p=m.useMemo(()=>({basename:h,navigator:f,static:d,future:{}}),[h,f,d]);typeof l=="string"&&(l=ul(l));let{pathname:x="/",search:g="",hash:v="",state:y=null,key:S="default"}=l,E=m.useMemo(()=>{let C=oa(x,h);return C==null?null:{location:{pathname:C,search:g,hash:v,state:y,key:S},navigationType:o}},[h,x,g,v,y,S,o]);return Nn(E!=null,` is not able to match the URL "${x}${g}${v}" because it does not start with the basename, so the won't render anything.`),E==null?null:m.createElement(_n.Provider,{value:p},m.createElement(Mi.Provider,{children:s,value:E}))}function x1({children:n,location:s}){return n1(Nf(n),s)}function Nf(n,s=[]){let l=[];return m.Children.forEach(n,(o,f)=>{if(!m.isValidElement(o))return;let d=[...s,f];if(o.type===m.Fragment){l.push.apply(l,Nf(o.props.children,d));return}ut(o.type===no,`[${typeof o.type=="string"?o.type:o.type.name}] is not a component. All component children of must be a or `),ut(!o.props.index||!o.props.children,"An index route cannot have child routes.");let h={id:o.props.id||d.join("-"),caseSensitive:o.props.caseSensitive,element:o.props.element,Component:o.props.Component,index:o.props.index,path:o.props.path,middleware:o.props.middleware,loader:o.props.loader,action:o.props.action,hydrateFallbackElement:o.props.hydrateFallbackElement,HydrateFallback:o.props.HydrateFallback,errorElement:o.props.errorElement,ErrorBoundary:o.props.ErrorBoundary,hasErrorBoundary:o.props.hasErrorBoundary===!0||o.props.ErrorBoundary!=null||o.props.errorElement!=null,shouldRevalidate:o.props.shouldRevalidate,handle:o.props.handle,lazy:o.props.lazy};o.props.children&&(h.children=Nf(o.props.children,d)),l.push(h)}),l}var ao="get",so="application/x-www-form-urlencoded";function wo(n){return n!=null&&typeof n.tagName=="string"}function g1(n){return wo(n)&&n.tagName.toLowerCase()==="button"}function v1(n){return wo(n)&&n.tagName.toLowerCase()==="form"}function b1(n){return wo(n)&&n.tagName.toLowerCase()==="input"}function y1(n){return!!(n.metaKey||n.altKey||n.ctrlKey||n.shiftKey)}function S1(n,s){return n.button===0&&(!s||s==="_self")&&!y1(n)}var Xr=null;function j1(){if(Xr===null)try{new FormData(document.createElement("form"),0),Xr=!1}catch{Xr=!0}return Xr}var A1=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Wu(n){return n!=null&&!A1.has(n)?(Nn(!1,`"${n}" is not a valid \`encType\` for \`\`/\`\` and will default to "${so}"`),null):n}function N1(n,s){let l,o,f,d,h;if(v1(n)){let p=n.getAttribute("action");o=p?oa(p,s):null,l=n.getAttribute("method")||ao,f=Wu(n.getAttribute("enctype"))||so,d=new FormData(n)}else if(g1(n)||b1(n)&&(n.type==="submit"||n.type==="image")){let p=n.form;if(p==null)throw new Error('Cannot submit a or without a ');let x=n.getAttribute("formaction")||p.getAttribute("action");if(o=x?oa(x,s):null,l=n.getAttribute("formmethod")||p.getAttribute("method")||ao,f=Wu(n.getAttribute("formenctype"))||Wu(p.getAttribute("enctype"))||so,d=new FormData(p,n),!j1()){let{name:g,type:v,value:y}=n;if(v==="image"){let S=g?`${g}.`:"";d.append(`${S}x`,"0"),d.append(`${S}y`,"0")}else g&&d.append(g,y)}}else{if(wo(n))throw new Error('Cannot submit element that is not , , or ');l=ao,o=null,f=so,h=n}return d&&f==="text/plain"&&(h=d,d=void 0),{action:o,method:l.toLowerCase(),encType:f,formData:d,body:h}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");function Xf(n,s){if(n===!1||n===null||typeof n>"u")throw new Error(s)}function w1(n,s,l){let o=typeof n=="string"?new URL(n,typeof window>"u"?"server://singlefetch/":window.location.origin):n;return o.pathname==="/"?o.pathname=`_root.${l}`:s&&oa(o.pathname,s)==="/"?o.pathname=`${s.replace(/\/$/,"")}/_root.${l}`:o.pathname=`${o.pathname.replace(/\/$/,"")}.${l}`,o}async function C1(n,s){if(n.id in s)return s[n.id];try{let l=await import(n.module);return s[n.id]=l,l}catch(l){return console.error(`Error loading route module \`${n.module}\`, reloading page...`),console.error(l),window.__reactRouterContext&&window.__reactRouterContext.isSpaMode,window.location.reload(),new Promise(()=>{})}}function E1(n){return n==null?!1:n.href==null?n.rel==="preload"&&typeof n.imageSrcSet=="string"&&typeof n.imageSizes=="string":typeof n.rel=="string"&&typeof n.href=="string"}async function k1(n,s,l){let o=await Promise.all(n.map(async f=>{let d=s.routes[f.route.id];if(d){let h=await C1(d,l);return h.links?h.links():[]}return[]}));return T1(o.flat(1).filter(E1).filter(f=>f.rel==="stylesheet"||f.rel==="preload").map(f=>f.rel==="stylesheet"?{...f,rel:"prefetch",as:"style"}:{...f,rel:"prefetch"}))}function M0(n,s,l,o,f,d){let h=(x,g)=>l[g]?x.route.id!==l[g].route.id:!0,p=(x,g)=>l[g].pathname!==x.pathname||l[g].route.path?.endsWith("*")&&l[g].params["*"]!==x.params["*"];return d==="assets"?s.filter((x,g)=>h(x,g)||p(x,g)):d==="data"?s.filter((x,g)=>{let v=o.routes[x.route.id];if(!v||!v.hasLoader)return!1;if(h(x,g)||p(x,g))return!0;if(x.route.shouldRevalidate){let y=x.route.shouldRevalidate({currentUrl:new URL(f.pathname+f.search+f.hash,window.origin),currentParams:l[0]?.params||{},nextUrl:new URL(n,window.origin),nextParams:x.params,defaultShouldRevalidate:!0});if(typeof y=="boolean")return y}return!0}):[]}function M1(n,s,{includeHydrateFallback:l}={}){return R1(n.map(o=>{let f=s.routes[o.route.id];if(!f)return[];let d=[f.module];return f.clientActionModule&&(d=d.concat(f.clientActionModule)),f.clientLoaderModule&&(d=d.concat(f.clientLoaderModule)),l&&f.hydrateFallbackModule&&(d=d.concat(f.hydrateFallbackModule)),f.imports&&(d=d.concat(f.imports)),d}).flat(1))}function R1(n){return[...new Set(n)]}function q1(n){let s={},l=Object.keys(n).sort();for(let o of l)s[o]=n[o];return s}function T1(n,s){let l=new Set;return new Set(s),n.reduce((o,f)=>{let d=JSON.stringify(q1(f));return l.has(d)||(l.add(d),o.push({key:d,link:f})),o},[])}function Ux(){let n=m.useContext(fl);return Xf(n,"You must render this element inside a element"),n}function D1(){let n=m.useContext(No);return Xf(n,"You must render this element inside a element"),n}var Qf=m.createContext(void 0);Qf.displayName="FrameworkContext";function Hx(){let n=m.useContext(Qf);return Xf(n,"You must render this element inside a element"),n}function _1(n,s){let l=m.useContext(Qf),[o,f]=m.useState(!1),[d,h]=m.useState(!1),{onFocus:p,onBlur:x,onMouseEnter:g,onMouseLeave:v,onTouchStart:y}=s,S=m.useRef(null);m.useEffect(()=>{if(n==="render"&&h(!0),n==="viewport"){let k=j=>{j.forEach(N=>{h(N.isIntersecting)})},w=new IntersectionObserver(k,{threshold:.5});return S.current&&w.observe(S.current),()=>{w.disconnect()}}},[n]),m.useEffect(()=>{if(o){let k=setTimeout(()=>{h(!0)},100);return()=>{clearTimeout(k)}}},[o]);let E=()=>{f(!0)},C=()=>{f(!1),h(!1)};return l?n!=="intent"?[d,S,{}]:[d,S,{onFocus:oi(p,E),onBlur:oi(x,C),onMouseEnter:oi(g,E),onMouseLeave:oi(v,C),onTouchStart:oi(y,E)}]:[!1,S,{}]}function oi(n,s){return l=>{n&&n(l),l.defaultPrevented||s(l)}}function B1({page:n,...s}){let{router:l}=Ux(),o=m.useMemo(()=>kx(l.routes,n,l.basename),[l.routes,n,l.basename]);return o?m.createElement(L1,{page:n,matches:o,...s}):null}function O1(n){let{manifest:s,routeModules:l}=Hx(),[o,f]=m.useState([]);return m.useEffect(()=>{let d=!1;return k1(n,s,l).then(h=>{d||f(h)}),()=>{d=!0}},[n,s,l]),o}function L1({page:n,matches:s,...l}){let o=ds(),{manifest:f,routeModules:d}=Hx(),{basename:h}=Ux(),{loaderData:p,matches:x}=D1(),g=m.useMemo(()=>M0(n,s,x,f,o,"data"),[n,s,x,f,o]),v=m.useMemo(()=>M0(n,s,x,f,o,"assets"),[n,s,x,f,o]),y=m.useMemo(()=>{if(n===o.pathname+o.search+o.hash)return[];let C=new Set,k=!1;if(s.forEach(j=>{let N=f.routes[j.route.id];!N||!N.hasLoader||(!g.some(T=>T.route.id===j.route.id)&&j.route.id in p&&d[j.route.id]?.shouldRevalidate||N.hasClientLoader?k=!0:C.add(j.route.id))}),C.size===0)return[];let w=w1(n,h,"data");return k&&C.size>0&&w.searchParams.set("_routes",s.filter(j=>C.has(j.route.id)).map(j=>j.route.id).join(",")),[w.pathname+w.search]},[h,p,o,f,g,s,n,d]),S=m.useMemo(()=>M1(v,f),[v,f]),E=O1(v);return m.createElement(m.Fragment,null,y.map(C=>m.createElement("link",{key:C,rel:"prefetch",as:"fetch",href:C,...l})),S.map(C=>m.createElement("link",{key:C,rel:"modulepreload",href:C,...l})),E.map(({key:C,link:k})=>m.createElement("link",{key:C,nonce:l.nonce,...k})))}function z1(...n){return s=>{n.forEach(l=>{typeof l=="function"?l(s):l!=null&&(l.current=s)})}}var Vx=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";try{Vx&&(window.__reactRouterVersion="7.9.6")}catch{}function U1({basename:n,children:s,window:l}){let o=m.useRef();o.current==null&&(o.current=wy({window:l,v5Compat:!0}));let f=o.current,[d,h]=m.useState({action:f.action,location:f.location}),p=m.useCallback(x=>{m.startTransition(()=>h(x))},[h]);return m.useLayoutEffect(()=>f.listen(p),[f,p]),m.createElement(p1,{basename:n,children:s,location:d.location,navigationType:d.action,navigator:f})}var $x=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Gx=m.forwardRef(function({onClick:s,discover:l="render",prefetch:o="none",relative:f,reloadDocument:d,replace:h,state:p,target:x,to:g,preventScrollReset:v,viewTransition:y,...S},E){let{basename:C}=m.useContext(_n),k=typeof g=="string"&&$x.test(g),w,j=!1;if(typeof g=="string"&&k&&(w=g,Vx))try{let X=new URL(window.location.href),F=g.startsWith("//")?new URL(X.protocol+g):new URL(g),H=oa(F.pathname,C);F.origin===X.origin&&H!=null?g=H+F.search+F.hash:j=!0}catch{Nn(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}let N=Wy(g,{relative:f}),[T,M,O]=_1(o,S),K=G1(g,{replace:h,state:p,target:x,preventScrollReset:v,relative:f,viewTransition:y});function _(X){s&&s(X),X.defaultPrevented||K(X)}let U=m.createElement("a",{...S,...O,href:w||N,onClick:j||d?s:_,ref:z1(E,M),target:x,"data-discover":!k&&l==="render"?"true":void 0});return T&&!k?m.createElement(m.Fragment,null,U,m.createElement(B1,{page:N})):U});Gx.displayName="Link";var H1=m.forwardRef(function({"aria-current":s="page",caseSensitive:l=!1,className:o="",end:f=!1,style:d,to:h,viewTransition:p,children:x,...g},v){let y=qi(h,{relative:g.relative}),S=ds(),E=m.useContext(No),{navigator:C,basename:k}=m.useContext(_n),w=E!=null&&K1(y)&&p===!0,j=C.encodeLocation?C.encodeLocation(y).pathname:y.pathname,N=S.pathname,T=E&&E.navigation&&E.navigation.location?E.navigation.location.pathname:null;l||(N=N.toLowerCase(),T=T?T.toLowerCase():null,j=j.toLowerCase()),T&&k&&(T=oa(T,k)||T);const M=j!=="/"&&j.endsWith("/")?j.length-1:j.length;let O=N===j||!f&&N.startsWith(j)&&N.charAt(M)==="/",K=T!=null&&(T===j||!f&&T.startsWith(j)&&T.charAt(j.length)==="/"),_={isActive:O,isPending:K,isTransitioning:w},U=O?s:void 0,X;typeof o=="function"?X=o(_):X=[o,O?"active":null,K?"pending":null,w?"transitioning":null].filter(Boolean).join(" ");let F=typeof d=="function"?d(_):d;return m.createElement(Gx,{...g,"aria-current":U,className:X,ref:v,style:F,to:h,viewTransition:p},typeof x=="function"?x(_):x)});H1.displayName="NavLink";var V1=m.forwardRef(({discover:n="render",fetcherKey:s,navigate:l,reloadDocument:o,replace:f,state:d,method:h=ao,action:p,onSubmit:x,relative:g,preventScrollReset:v,viewTransition:y,...S},E)=>{let C=X1(),k=Q1(p,{relative:g}),w=h.toLowerCase()==="get"?"get":"post",j=typeof p=="string"&&$x.test(p),N=T=>{if(x&&x(T),T.defaultPrevented)return;T.preventDefault();let M=T.nativeEvent.submitter,O=M?.getAttribute("formmethod")||h;C(M||T.currentTarget,{fetcherKey:s,method:O,navigate:l,replace:f,state:d,relative:g,preventScrollReset:v,viewTransition:y})};return m.createElement("form",{ref:E,method:w,action:k,onSubmit:o?x:N,...S,"data-discover":!j&&n==="render"?"true":void 0})});V1.displayName="Form";function $1(n){return`${n} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Yx(n){let s=m.useContext(fl);return ut(s,$1(n)),s}function G1(n,{target:s,replace:l,state:o,preventScrollReset:f,relative:d,viewTransition:h}={}){let p=e1(),x=ds(),g=qi(n,{relative:d});return m.useCallback(v=>{if(S1(v,s)){v.preventDefault();let y=l!==void 0?l:yi(x)===yi(g);p(n,{replace:y,state:o,preventScrollReset:f,relative:d,viewTransition:h})}},[x,p,g,l,o,s,n,f,d,h])}var Y1=0,F1=()=>`__${String(++Y1)}__`;function X1(){let{router:n}=Yx("useSubmit"),{basename:s}=m.useContext(_n),l=f1();return m.useCallback(async(o,f={})=>{let{action:d,method:h,encType:p,formData:x,body:g}=N1(o,s);if(f.navigate===!1){let v=f.fetcherKey||F1();await n.fetch(v,l,f.action||d,{preventScrollReset:f.preventScrollReset,formData:x,body:g,formMethod:f.method||h,formEncType:f.encType||p,flushSync:f.flushSync})}else await n.navigate(f.action||d,{preventScrollReset:f.preventScrollReset,formData:x,body:g,formMethod:f.method||h,formEncType:f.encType||p,replace:f.replace,state:f.state,fromRouteId:l,flushSync:f.flushSync,viewTransition:f.viewTransition})},[n,s,l])}function Q1(n,{relative:s}={}){let{basename:l}=m.useContext(_n),o=m.useContext(ua);ut(o,"useFormAction must be used inside a RouteContext");let[f]=o.matches.slice(-1),d={...qi(n||".",{relative:s})},h=ds();if(n==null){d.search=h.search;let p=new URLSearchParams(d.search),x=p.getAll("index");if(x.some(v=>v==="")){p.delete("index"),x.filter(y=>y).forEach(y=>p.append("index",y));let v=p.toString();d.search=v?`?${v}`:""}}return(!n||n===".")&&f.route.index&&(d.search=d.search?d.search.replace(/^\?/,"?index&"):"?index"),l!=="/"&&(d.pathname=d.pathname==="/"?l:ra([l,d.pathname])),yi(d)}function K1(n,{relative:s}={}){let l=m.useContext(_x);ut(l!=null,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:o}=Yx("useViewTransitionState"),f=qi(n,{relative:s});if(!l.isTransitioning)return!1;let d=oa(l.currentLocation.pathname,o)||l.currentLocation.pathname,h=oa(l.nextLocation.pathname,o)||l.nextLocation.pathname;return mo(f.pathname,h)!=null||mo(f.pathname,d)!=null}const Dn=Object.create(null);Dn.open="0";Dn.close="1";Dn.ping="2";Dn.pong="3";Dn.message="4";Dn.upgrade="5";Dn.noop="6";const lo=Object.create(null);Object.keys(Dn).forEach(n=>{lo[Dn[n]]=n});const wf={type:"error",data:"parser error"},Fx=typeof Blob=="function"||typeof Blob<"u"&&Object.prototype.toString.call(Blob)==="[object BlobConstructor]",Xx=typeof ArrayBuffer=="function",Qx=n=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(n):n&&n.buffer instanceof ArrayBuffer,Kf=({type:n,data:s},l,o)=>Fx&&s instanceof Blob?l?o(s):R0(s,o):Xx&&(s instanceof ArrayBuffer||Qx(s))?l?o(s):R0(new Blob([s]),o):o(Dn[n]+(s||"")),R0=(n,s)=>{const l=new FileReader;return l.onload=function(){const o=l.result.split(",")[1];s("b"+(o||""))},l.readAsDataURL(n)};function q0(n){return n instanceof Uint8Array?n:n instanceof ArrayBuffer?new Uint8Array(n):new Uint8Array(n.buffer,n.byteOffset,n.byteLength)}let ef;function Z1(n,s){if(Fx&&n.data instanceof Blob)return n.data.arrayBuffer().then(q0).then(s);if(Xx&&(n.data instanceof ArrayBuffer||Qx(n.data)))return s(q0(n.data));Kf(n,!1,l=>{ef||(ef=new TextEncoder),s(ef.encode(l))})}const T0="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",hi=typeof Uint8Array>"u"?[]:new Uint8Array(256);for(let n=0;n{let s=n.length*.75,l=n.length,o,f=0,d,h,p,x;n[n.length-1]==="="&&(s--,n[n.length-2]==="="&&s--);const g=new ArrayBuffer(s),v=new Uint8Array(g);for(o=0;o>4,v[f++]=(h&15)<<4|p>>2,v[f++]=(p&3)<<6|x&63;return g},J1=typeof ArrayBuffer=="function",Zf=(n,s)=>{if(typeof n!="string")return{type:"message",data:Kx(n,s)};const l=n.charAt(0);return l==="b"?{type:"message",data:P1(n.substring(1),s)}:lo[l]?n.length>1?{type:lo[l],data:n.substring(1)}:{type:lo[l]}:wf},P1=(n,s)=>{if(J1){const l=I1(n);return Kx(l,s)}else return{base64:!0,data:n}},Kx=(n,s)=>{switch(s){case"blob":return n instanceof Blob?n:new Blob([n]);case"arraybuffer":default:return n instanceof ArrayBuffer?n:n.buffer}},Zx="",W1=(n,s)=>{const l=n.length,o=new Array(l);let f=0;n.forEach((d,h)=>{Kf(d,!1,p=>{o[h]=p,++f===l&&s(o.join(Zx))})})},eS=(n,s)=>{const l=n.split(Zx),o=[];for(let f=0;f{const o=l.length;let f;if(o<126)f=new Uint8Array(1),new DataView(f.buffer).setUint8(0,o);else if(o<65536){f=new Uint8Array(3);const d=new DataView(f.buffer);d.setUint8(0,126),d.setUint16(1,o)}else{f=new Uint8Array(9);const d=new DataView(f.buffer);d.setUint8(0,127),d.setBigUint64(1,BigInt(o))}n.data&&typeof n.data!="string"&&(f[0]|=128),s.enqueue(f),s.enqueue(l)})}})}let tf;function Qr(n){return n.reduce((s,l)=>s+l.length,0)}function Kr(n,s){if(n[0].length===s)return n.shift();const l=new Uint8Array(s);let o=0;for(let f=0;fMath.pow(2,21)-1){p.enqueue(wf);break}f=v*Math.pow(2,32)+g.getUint32(4),o=3}else{if(Qr(l)n){p.enqueue(wf);break}}}})}const Ix=4;function At(n){if(n)return aS(n)}function aS(n){for(var s in At.prototype)n[s]=At.prototype[s];return n}At.prototype.on=At.prototype.addEventListener=function(n,s){return this._callbacks=this._callbacks||{},(this._callbacks["$"+n]=this._callbacks["$"+n]||[]).push(s),this};At.prototype.once=function(n,s){function l(){this.off(n,l),s.apply(this,arguments)}return l.fn=s,this.on(n,l),this};At.prototype.off=At.prototype.removeListener=At.prototype.removeAllListeners=At.prototype.removeEventListener=function(n,s){if(this._callbacks=this._callbacks||{},arguments.length==0)return this._callbacks={},this;var l=this._callbacks["$"+n];if(!l)return this;if(arguments.length==1)return delete this._callbacks["$"+n],this;for(var o,f=0;fPromise.resolve().then(s):(s,l)=>l(s,0),gn=typeof self<"u"?self:typeof window<"u"?window:Function("return this")(),sS="arraybuffer";function Jx(n,...s){return s.reduce((l,o)=>(n.hasOwnProperty(o)&&(l[o]=n[o]),l),{})}const lS=gn.setTimeout,iS=gn.clearTimeout;function Eo(n,s){s.useNativeTimers?(n.setTimeoutFn=lS.bind(gn),n.clearTimeoutFn=iS.bind(gn)):(n.setTimeoutFn=gn.setTimeout.bind(gn),n.clearTimeoutFn=gn.clearTimeout.bind(gn))}const rS=1.33;function oS(n){return typeof n=="string"?cS(n):Math.ceil((n.byteLength||n.size)*rS)}function cS(n){let s=0,l=0;for(let o=0,f=n.length;o=57344?l+=3:(o++,l+=4);return l}function Px(){return Date.now().toString(36).substring(3)+Math.random().toString(36).substring(2,5)}function uS(n){let s="";for(let l in n)n.hasOwnProperty(l)&&(s.length&&(s+="&"),s+=encodeURIComponent(l)+"="+encodeURIComponent(n[l]));return s}function fS(n){let s={},l=n.split("&");for(let o=0,f=l.length;o{this.readyState="paused",s()};if(this._polling||!this.writable){let o=0;this._polling&&(o++,this.once("pollComplete",function(){--o||l()})),this.writable||(o++,this.once("drain",function(){--o||l()}))}else l()}_poll(){this._polling=!0,this.doPoll(),this.emitReserved("poll")}onData(s){const l=o=>{if(this.readyState==="opening"&&o.type==="open"&&this.onOpen(),o.type==="close")return this.onClose({description:"transport closed by the server"}),!1;this.onPacket(o)};eS(s,this.socket.binaryType).forEach(l),this.readyState!=="closed"&&(this._polling=!1,this.emitReserved("pollComplete"),this.readyState==="open"&&this._poll())}doClose(){const s=()=>{this.write([{type:"close"}])};this.readyState==="open"?s():this.once("open",s)}write(s){this.writable=!1,W1(s,l=>{this.doWrite(l,()=>{this.writable=!0,this.emitReserved("drain")})})}uri(){const s=this.opts.secure?"https":"http",l=this.query||{};return this.opts.timestampRequests!==!1&&(l[this.opts.timestampParam]=Px()),!this.supportsBinary&&!l.sid&&(l.b64=1),this.createUri(s,l)}}let Wx=!1;try{Wx=typeof XMLHttpRequest<"u"&&"withCredentials"in new XMLHttpRequest}catch{}const hS=Wx;function pS(){}class xS extends mS{constructor(s){if(super(s),typeof location<"u"){const l=location.protocol==="https:";let o=location.port;o||(o=l?"443":"80"),this.xd=typeof location<"u"&&s.hostname!==location.hostname||o!==s.port}}doWrite(s,l){const o=this.request({method:"POST",data:s});o.on("success",l),o.on("error",(f,d)=>{this.onError("xhr post error",f,d)})}doPoll(){const s=this.request();s.on("data",this.onData.bind(this)),s.on("error",(l,o)=>{this.onError("xhr poll error",l,o)}),this.pollXhr=s}}class Tn extends At{constructor(s,l,o){super(),this.createRequest=s,Eo(this,o),this._opts=o,this._method=o.method||"GET",this._uri=l,this._data=o.data!==void 0?o.data:null,this._create()}_create(){var s;const l=Jx(this._opts,"agent","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","autoUnref");l.xdomain=!!this._opts.xd;const o=this._xhr=this.createRequest(l);try{o.open(this._method,this._uri,!0);try{if(this._opts.extraHeaders){o.setDisableHeaderCheck&&o.setDisableHeaderCheck(!0);for(let f in this._opts.extraHeaders)this._opts.extraHeaders.hasOwnProperty(f)&&o.setRequestHeader(f,this._opts.extraHeaders[f])}}catch{}if(this._method==="POST")try{o.setRequestHeader("Content-type","text/plain;charset=UTF-8")}catch{}try{o.setRequestHeader("Accept","*/*")}catch{}(s=this._opts.cookieJar)===null||s===void 0||s.addCookies(o),"withCredentials"in o&&(o.withCredentials=this._opts.withCredentials),this._opts.requestTimeout&&(o.timeout=this._opts.requestTimeout),o.onreadystatechange=()=>{var f;o.readyState===3&&((f=this._opts.cookieJar)===null||f===void 0||f.parseCookies(o.getResponseHeader("set-cookie"))),o.readyState===4&&(o.status===200||o.status===1223?this._onLoad():this.setTimeoutFn(()=>{this._onError(typeof o.status=="number"?o.status:0)},0))},o.send(this._data)}catch(f){this.setTimeoutFn(()=>{this._onError(f)},0);return}typeof document<"u"&&(this._index=Tn.requestsCount++,Tn.requests[this._index]=this)}_onError(s){this.emitReserved("error",s,this._xhr),this._cleanup(!0)}_cleanup(s){if(!(typeof this._xhr>"u"||this._xhr===null)){if(this._xhr.onreadystatechange=pS,s)try{this._xhr.abort()}catch{}typeof document<"u"&&delete Tn.requests[this._index],this._xhr=null}}_onLoad(){const s=this._xhr.responseText;s!==null&&(this.emitReserved("data",s),this.emitReserved("success"),this._cleanup())}abort(){this._cleanup()}}Tn.requestsCount=0;Tn.requests={};if(typeof document<"u"){if(typeof attachEvent=="function")attachEvent("onunload",D0);else if(typeof addEventListener=="function"){const n="onpagehide"in gn?"pagehide":"unload";addEventListener(n,D0,!1)}}function D0(){for(let n in Tn.requests)Tn.requests.hasOwnProperty(n)&&Tn.requests[n].abort()}const gS=(function(){const n=eg({xdomain:!1});return n&&n.responseType!==null})();class vS extends xS{constructor(s){super(s);const l=s&&s.forceBase64;this.supportsBinary=gS&&!l}request(s={}){return Object.assign(s,{xd:this.xd},this.opts),new Tn(eg,this.uri(),s)}}function eg(n){const s=n.xdomain;try{if(typeof XMLHttpRequest<"u"&&(!s||hS))return new XMLHttpRequest}catch{}if(!s)try{return new gn[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP")}catch{}}const tg=typeof navigator<"u"&&typeof navigator.product=="string"&&navigator.product.toLowerCase()==="reactnative";class bS extends If{get name(){return"websocket"}doOpen(){const s=this.uri(),l=this.opts.protocols,o=tg?{}:Jx(this.opts,"agent","perMessageDeflate","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","localAddress","protocolVersion","origin","maxPayload","family","checkServerIdentity");this.opts.extraHeaders&&(o.headers=this.opts.extraHeaders);try{this.ws=this.createSocket(s,l,o)}catch(f){return this.emitReserved("error",f)}this.ws.binaryType=this.socket.binaryType,this.addEventListeners()}addEventListeners(){this.ws.onopen=()=>{this.opts.autoUnref&&this.ws._socket.unref(),this.onOpen()},this.ws.onclose=s=>this.onClose({description:"websocket connection closed",context:s}),this.ws.onmessage=s=>this.onData(s.data),this.ws.onerror=s=>this.onError("websocket error",s)}write(s){this.writable=!1;for(let l=0;l{try{this.doWrite(o,d)}catch{}f&&Co(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){typeof this.ws<"u"&&(this.ws.onerror=()=>{},this.ws.close(),this.ws=null)}uri(){const s=this.opts.secure?"wss":"ws",l=this.query||{};return this.opts.timestampRequests&&(l[this.opts.timestampParam]=Px()),this.supportsBinary||(l.b64=1),this.createUri(s,l)}}const nf=gn.WebSocket||gn.MozWebSocket;class yS extends bS{createSocket(s,l,o){return tg?new nf(s,l,o):l?new nf(s,l):new nf(s)}doWrite(s,l){this.ws.send(l)}}class SS extends If{get name(){return"webtransport"}doOpen(){try{this._transport=new WebTransport(this.createUri("https"),this.opts.transportOptions[this.name])}catch(s){return this.emitReserved("error",s)}this._transport.closed.then(()=>{this.onClose()}).catch(s=>{this.onError("webtransport error",s)}),this._transport.ready.then(()=>{this._transport.createBidirectionalStream().then(s=>{const l=nS(Number.MAX_SAFE_INTEGER,this.socket.binaryType),o=s.readable.pipeThrough(l).getReader(),f=tS();f.readable.pipeTo(s.writable),this._writer=f.writable.getWriter();const d=()=>{o.read().then(({done:p,value:x})=>{p||(this.onPacket(x),d())}).catch(p=>{})};d();const h={type:"open"};this.query.sid&&(h.data=`{"sid":"${this.query.sid}"}`),this._writer.write(h).then(()=>this.onOpen())})})}write(s){this.writable=!1;for(let l=0;l{f&&Co(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){var s;(s=this._transport)===null||s===void 0||s.close()}}const jS={websocket:yS,webtransport:SS,polling:vS},AS=/^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,NS=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];function Cf(n){if(n.length>8e3)throw"URI too long";const s=n,l=n.indexOf("["),o=n.indexOf("]");l!=-1&&o!=-1&&(n=n.substring(0,l)+n.substring(l,o).replace(/:/g,";")+n.substring(o,n.length));let f=AS.exec(n||""),d={},h=14;for(;h--;)d[NS[h]]=f[h]||"";return l!=-1&&o!=-1&&(d.source=s,d.host=d.host.substring(1,d.host.length-1).replace(/;/g,":"),d.authority=d.authority.replace("[","").replace("]","").replace(/;/g,":"),d.ipv6uri=!0),d.pathNames=wS(d,d.path),d.queryKey=CS(d,d.query),d}function wS(n,s){const l=/\/{2,9}/g,o=s.replace(l,"/").split("/");return(s.slice(0,1)=="/"||s.length===0)&&o.splice(0,1),s.slice(-1)=="/"&&o.splice(o.length-1,1),o}function CS(n,s){const l={};return s.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,function(o,f,d){f&&(l[f]=d)}),l}const Ef=typeof addEventListener=="function"&&typeof removeEventListener=="function",io=[];Ef&&addEventListener("offline",()=>{io.forEach(n=>n())},!1);class Oa extends At{constructor(s,l){if(super(),this.binaryType=sS,this.writeBuffer=[],this._prevBufferLen=0,this._pingInterval=-1,this._pingTimeout=-1,this._maxPayload=-1,this._pingTimeoutTime=1/0,s&&typeof s=="object"&&(l=s,s=null),s){const o=Cf(s);l.hostname=o.host,l.secure=o.protocol==="https"||o.protocol==="wss",l.port=o.port,o.query&&(l.query=o.query)}else l.host&&(l.hostname=Cf(l.host).host);Eo(this,l),this.secure=l.secure!=null?l.secure:typeof location<"u"&&location.protocol==="https:",l.hostname&&!l.port&&(l.port=this.secure?"443":"80"),this.hostname=l.hostname||(typeof location<"u"?location.hostname:"localhost"),this.port=l.port||(typeof location<"u"&&location.port?location.port:this.secure?"443":"80"),this.transports=[],this._transportsByName={},l.transports.forEach(o=>{const f=o.prototype.name;this.transports.push(f),this._transportsByName[f]=o}),this.opts=Object.assign({path:"/engine.io",agent:!1,withCredentials:!1,upgrade:!0,timestampParam:"t",rememberUpgrade:!1,addTrailingSlash:!0,rejectUnauthorized:!0,perMessageDeflate:{threshold:1024},transportOptions:{},closeOnBeforeunload:!1},l),this.opts.path=this.opts.path.replace(/\/$/,"")+(this.opts.addTrailingSlash?"/":""),typeof this.opts.query=="string"&&(this.opts.query=fS(this.opts.query)),Ef&&(this.opts.closeOnBeforeunload&&(this._beforeunloadEventListener=()=>{this.transport&&(this.transport.removeAllListeners(),this.transport.close())},addEventListener("beforeunload",this._beforeunloadEventListener,!1)),this.hostname!=="localhost"&&(this._offlineEventListener=()=>{this._onClose("transport close",{description:"network connection lost"})},io.push(this._offlineEventListener))),this.opts.withCredentials&&(this._cookieJar=void 0),this._open()}createTransport(s){const l=Object.assign({},this.opts.query);l.EIO=Ix,l.transport=s,this.id&&(l.sid=this.id);const o=Object.assign({},this.opts,{query:l,socket:this,hostname:this.hostname,secure:this.secure,port:this.port},this.opts.transportOptions[s]);return new this._transportsByName[s](o)}_open(){if(this.transports.length===0){this.setTimeoutFn(()=>{this.emitReserved("error","No transports available")},0);return}const s=this.opts.rememberUpgrade&&Oa.priorWebsocketSuccess&&this.transports.indexOf("websocket")!==-1?"websocket":this.transports[0];this.readyState="opening";const l=this.createTransport(s);l.open(),this.setTransport(l)}setTransport(s){this.transport&&this.transport.removeAllListeners(),this.transport=s,s.on("drain",this._onDrain.bind(this)).on("packet",this._onPacket.bind(this)).on("error",this._onError.bind(this)).on("close",l=>this._onClose("transport close",l))}onOpen(){this.readyState="open",Oa.priorWebsocketSuccess=this.transport.name==="websocket",this.emitReserved("open"),this.flush()}_onPacket(s){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing")switch(this.emitReserved("packet",s),this.emitReserved("heartbeat"),s.type){case"open":this.onHandshake(JSON.parse(s.data));break;case"ping":this._sendPacket("pong"),this.emitReserved("ping"),this.emitReserved("pong"),this._resetPingTimeout();break;case"error":const l=new Error("server error");l.code=s.data,this._onError(l);break;case"message":this.emitReserved("data",s.data),this.emitReserved("message",s.data);break}}onHandshake(s){this.emitReserved("handshake",s),this.id=s.sid,this.transport.query.sid=s.sid,this._pingInterval=s.pingInterval,this._pingTimeout=s.pingTimeout,this._maxPayload=s.maxPayload,this.onOpen(),this.readyState!=="closed"&&this._resetPingTimeout()}_resetPingTimeout(){this.clearTimeoutFn(this._pingTimeoutTimer);const s=this._pingInterval+this._pingTimeout;this._pingTimeoutTime=Date.now()+s,this._pingTimeoutTimer=this.setTimeoutFn(()=>{this._onClose("ping timeout")},s),this.opts.autoUnref&&this._pingTimeoutTimer.unref()}_onDrain(){this.writeBuffer.splice(0,this._prevBufferLen),this._prevBufferLen=0,this.writeBuffer.length===0?this.emitReserved("drain"):this.flush()}flush(){if(this.readyState!=="closed"&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length){const s=this._getWritablePackets();this.transport.send(s),this._prevBufferLen=s.length,this.emitReserved("flush")}}_getWritablePackets(){if(!(this._maxPayload&&this.transport.name==="polling"&&this.writeBuffer.length>1))return this.writeBuffer;let l=1;for(let o=0;o0&&l>this._maxPayload)return this.writeBuffer.slice(0,o);l+=2}return this.writeBuffer}_hasPingExpired(){if(!this._pingTimeoutTime)return!0;const s=Date.now()>this._pingTimeoutTime;return s&&(this._pingTimeoutTime=0,Co(()=>{this._onClose("ping timeout")},this.setTimeoutFn)),s}write(s,l,o){return this._sendPacket("message",s,l,o),this}send(s,l,o){return this._sendPacket("message",s,l,o),this}_sendPacket(s,l,o,f){if(typeof l=="function"&&(f=l,l=void 0),typeof o=="function"&&(f=o,o=null),this.readyState==="closing"||this.readyState==="closed")return;o=o||{},o.compress=o.compress!==!1;const d={type:s,data:l,options:o};this.emitReserved("packetCreate",d),this.writeBuffer.push(d),f&&this.once("flush",f),this.flush()}close(){const s=()=>{this._onClose("forced close"),this.transport.close()},l=()=>{this.off("upgrade",l),this.off("upgradeError",l),s()},o=()=>{this.once("upgrade",l),this.once("upgradeError",l)};return(this.readyState==="opening"||this.readyState==="open")&&(this.readyState="closing",this.writeBuffer.length?this.once("drain",()=>{this.upgrading?o():s()}):this.upgrading?o():s()),this}_onError(s){if(Oa.priorWebsocketSuccess=!1,this.opts.tryAllTransports&&this.transports.length>1&&this.readyState==="opening")return this.transports.shift(),this._open();this.emitReserved("error",s),this._onClose("transport error",s)}_onClose(s,l){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing"){if(this.clearTimeoutFn(this._pingTimeoutTimer),this.transport.removeAllListeners("close"),this.transport.close(),this.transport.removeAllListeners(),Ef&&(this._beforeunloadEventListener&&removeEventListener("beforeunload",this._beforeunloadEventListener,!1),this._offlineEventListener)){const o=io.indexOf(this._offlineEventListener);o!==-1&&io.splice(o,1)}this.readyState="closed",this.id=null,this.emitReserved("close",s,l),this.writeBuffer=[],this._prevBufferLen=0}}}Oa.protocol=Ix;class ES extends Oa{constructor(){super(...arguments),this._upgrades=[]}onOpen(){if(super.onOpen(),this.readyState==="open"&&this.opts.upgrade)for(let s=0;s{o||(l.send([{type:"ping",data:"probe"}]),l.once("packet",y=>{if(!o)if(y.type==="pong"&&y.data==="probe"){if(this.upgrading=!0,this.emitReserved("upgrading",l),!l)return;Oa.priorWebsocketSuccess=l.name==="websocket",this.transport.pause(()=>{o||this.readyState!=="closed"&&(v(),this.setTransport(l),l.send([{type:"upgrade"}]),this.emitReserved("upgrade",l),l=null,this.upgrading=!1,this.flush())})}else{const S=new Error("probe error");S.transport=l.name,this.emitReserved("upgradeError",S)}}))};function d(){o||(o=!0,v(),l.close(),l=null)}const h=y=>{const S=new Error("probe error: "+y);S.transport=l.name,d(),this.emitReserved("upgradeError",S)};function p(){h("transport closed")}function x(){h("socket closed")}function g(y){l&&y.name!==l.name&&d()}const v=()=>{l.removeListener("open",f),l.removeListener("error",h),l.removeListener("close",p),this.off("close",x),this.off("upgrading",g)};l.once("open",f),l.once("error",h),l.once("close",p),this.once("close",x),this.once("upgrading",g),this._upgrades.indexOf("webtransport")!==-1&&s!=="webtransport"?this.setTimeoutFn(()=>{o||l.open()},200):l.open()}onHandshake(s){this._upgrades=this._filterUpgrades(s.upgrades),super.onHandshake(s)}_filterUpgrades(s){const l=[];for(let o=0;ojS[f]).filter(f=>!!f)),super(s,o)}};function MS(n,s="",l){let o=n;l=l||typeof location<"u"&&location,n==null&&(n=l.protocol+"//"+l.host),typeof n=="string"&&(n.charAt(0)==="/"&&(n.charAt(1)==="/"?n=l.protocol+n:n=l.host+n),/^(https?|wss?):\/\//.test(n)||(typeof l<"u"?n=l.protocol+"//"+n:n="https://"+n),o=Cf(n)),o.port||(/^(http|ws)$/.test(o.protocol)?o.port="80":/^(http|ws)s$/.test(o.protocol)&&(o.port="443")),o.path=o.path||"/";const d=o.host.indexOf(":")!==-1?"["+o.host+"]":o.host;return o.id=o.protocol+"://"+d+":"+o.port+s,o.href=o.protocol+"://"+d+(l&&l.port===o.port?"":":"+o.port),o}const RS=typeof ArrayBuffer=="function",qS=n=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(n):n.buffer instanceof ArrayBuffer,ng=Object.prototype.toString,TS=typeof Blob=="function"||typeof Blob<"u"&&ng.call(Blob)==="[object BlobConstructor]",DS=typeof File=="function"||typeof File<"u"&&ng.call(File)==="[object FileConstructor]";function Jf(n){return RS&&(n instanceof ArrayBuffer||qS(n))||TS&&n instanceof Blob||DS&&n instanceof File}function ro(n,s){if(!n||typeof n!="object")return!1;if(Array.isArray(n)){for(let l=0,o=n.length;l=0&&n.num{delete this.acks[s];for(let p=0;p{this.io.clearTimeoutFn(d),l.apply(this,p)};h.withError=!0,this.acks[s]=h}emitWithAck(s,...l){return new Promise((o,f)=>{const d=(h,p)=>h?f(h):o(p);d.withError=!0,l.push(d),this.emit(s,...l)})}_addToQueue(s){let l;typeof s[s.length-1]=="function"&&(l=s.pop());const o={id:this._queueSeq++,tryCount:0,pending:!1,args:s,flags:Object.assign({fromQueue:!0},this.flags)};s.push((f,...d)=>o!==this._queue[0]?void 0:(f!==null?o.tryCount>this._opts.retries&&(this._queue.shift(),l&&l(f)):(this._queue.shift(),l&&l(null,...d)),o.pending=!1,this._drainQueue())),this._queue.push(o),this._drainQueue()}_drainQueue(s=!1){if(!this.connected||this._queue.length===0)return;const l=this._queue[0];l.pending&&!s||(l.pending=!0,l.tryCount++,this.flags=l.flags,this.emit.apply(this,l.args))}packet(s){s.nsp=this.nsp,this.io._packet(s)}onopen(){typeof this.auth=="function"?this.auth(s=>{this._sendConnectPacket(s)}):this._sendConnectPacket(this.auth)}_sendConnectPacket(s){this.packet({type:_e.CONNECT,data:this._pid?Object.assign({pid:this._pid,offset:this._lastOffset},s):s})}onerror(s){this.connected||this.emitReserved("connect_error",s)}onclose(s,l){this.connected=!1,delete this.id,this.emitReserved("disconnect",s,l),this._clearAcks()}_clearAcks(){Object.keys(this.acks).forEach(s=>{if(!this.sendBuffer.some(o=>String(o.id)===s)){const o=this.acks[s];delete this.acks[s],o.withError&&o.call(this,new Error("socket has been disconnected"))}})}onpacket(s){if(s.nsp===this.nsp)switch(s.type){case _e.CONNECT:s.data&&s.data.sid?this.onconnect(s.data.sid,s.data.pid):this.emitReserved("connect_error",new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));break;case _e.EVENT:case _e.BINARY_EVENT:this.onevent(s);break;case _e.ACK:case _e.BINARY_ACK:this.onack(s);break;case _e.DISCONNECT:this.ondisconnect();break;case _e.CONNECT_ERROR:this.destroy();const o=new Error(s.data.message);o.data=s.data.data,this.emitReserved("connect_error",o);break}}onevent(s){const l=s.data||[];s.id!=null&&l.push(this.ack(s.id)),this.connected?this.emitEvent(l):this.receiveBuffer.push(Object.freeze(l))}emitEvent(s){if(this._anyListeners&&this._anyListeners.length){const l=this._anyListeners.slice();for(const o of l)o.apply(this,s)}super.emit.apply(this,s),this._pid&&s.length&&typeof s[s.length-1]=="string"&&(this._lastOffset=s[s.length-1])}ack(s){const l=this;let o=!1;return function(...f){o||(o=!0,l.packet({type:_e.ACK,id:s,data:f}))}}onack(s){const l=this.acks[s.id];typeof l=="function"&&(delete this.acks[s.id],l.withError&&s.data.unshift(null),l.apply(this,s.data))}onconnect(s,l){this.id=s,this.recovered=l&&this._pid===l,this._pid=l,this.connected=!0,this.emitBuffered(),this.emitReserved("connect"),this._drainQueue(!0)}emitBuffered(){this.receiveBuffer.forEach(s=>this.emitEvent(s)),this.receiveBuffer=[],this.sendBuffer.forEach(s=>{this.notifyOutgoingListeners(s),this.packet(s)}),this.sendBuffer=[]}ondisconnect(){this.destroy(),this.onclose("io server disconnect")}destroy(){this.subs&&(this.subs.forEach(s=>s()),this.subs=void 0),this.io._destroy(this)}disconnect(){return this.connected&&this.packet({type:_e.DISCONNECT}),this.destroy(),this.connected&&this.onclose("io client disconnect"),this}close(){return this.disconnect()}compress(s){return this.flags.compress=s,this}get volatile(){return this.flags.volatile=!0,this}timeout(s){return this.flags.timeout=s,this}onAny(s){return this._anyListeners=this._anyListeners||[],this._anyListeners.push(s),this}prependAny(s){return this._anyListeners=this._anyListeners||[],this._anyListeners.unshift(s),this}offAny(s){if(!this._anyListeners)return this;if(s){const l=this._anyListeners;for(let o=0;o0&&n.jitter<=1?n.jitter:0,this.attempts=0}dl.prototype.duration=function(){var n=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var s=Math.random(),l=Math.floor(s*this.jitter*n);n=(Math.floor(s*10)&1)==0?n-l:n+l}return Math.min(n,this.max)|0};dl.prototype.reset=function(){this.attempts=0};dl.prototype.setMin=function(n){this.ms=n};dl.prototype.setMax=function(n){this.max=n};dl.prototype.setJitter=function(n){this.jitter=n};class Rf extends At{constructor(s,l){var o;super(),this.nsps={},this.subs=[],s&&typeof s=="object"&&(l=s,s=void 0),l=l||{},l.path=l.path||"/socket.io",this.opts=l,Eo(this,l),this.reconnection(l.reconnection!==!1),this.reconnectionAttempts(l.reconnectionAttempts||1/0),this.reconnectionDelay(l.reconnectionDelay||1e3),this.reconnectionDelayMax(l.reconnectionDelayMax||5e3),this.randomizationFactor((o=l.randomizationFactor)!==null&&o!==void 0?o:.5),this.backoff=new dl({min:this.reconnectionDelay(),max:this.reconnectionDelayMax(),jitter:this.randomizationFactor()}),this.timeout(l.timeout==null?2e4:l.timeout),this._readyState="closed",this.uri=s;const f=l.parser||HS;this.encoder=new f.Encoder,this.decoder=new f.Decoder,this._autoConnect=l.autoConnect!==!1,this._autoConnect&&this.open()}reconnection(s){return arguments.length?(this._reconnection=!!s,s||(this.skipReconnect=!0),this):this._reconnection}reconnectionAttempts(s){return s===void 0?this._reconnectionAttempts:(this._reconnectionAttempts=s,this)}reconnectionDelay(s){var l;return s===void 0?this._reconnectionDelay:(this._reconnectionDelay=s,(l=this.backoff)===null||l===void 0||l.setMin(s),this)}randomizationFactor(s){var l;return s===void 0?this._randomizationFactor:(this._randomizationFactor=s,(l=this.backoff)===null||l===void 0||l.setJitter(s),this)}reconnectionDelayMax(s){var l;return s===void 0?this._reconnectionDelayMax:(this._reconnectionDelayMax=s,(l=this.backoff)===null||l===void 0||l.setMax(s),this)}timeout(s){return arguments.length?(this._timeout=s,this):this._timeout}maybeReconnectOnOpen(){!this._reconnecting&&this._reconnection&&this.backoff.attempts===0&&this.reconnect()}open(s){if(~this._readyState.indexOf("open"))return this;this.engine=new kS(this.uri,this.opts);const l=this.engine,o=this;this._readyState="opening",this.skipReconnect=!1;const f=jn(l,"open",function(){o.onopen(),s&&s()}),d=p=>{this.cleanup(),this._readyState="closed",this.emitReserved("error",p),s?s(p):this.maybeReconnectOnOpen()},h=jn(l,"error",d);if(this._timeout!==!1){const p=this._timeout,x=this.setTimeoutFn(()=>{f(),d(new Error("timeout")),l.close()},p);this.opts.autoUnref&&x.unref(),this.subs.push(()=>{this.clearTimeoutFn(x)})}return this.subs.push(f),this.subs.push(h),this}connect(s){return this.open(s)}onopen(){this.cleanup(),this._readyState="open",this.emitReserved("open");const s=this.engine;this.subs.push(jn(s,"ping",this.onping.bind(this)),jn(s,"data",this.ondata.bind(this)),jn(s,"error",this.onerror.bind(this)),jn(s,"close",this.onclose.bind(this)),jn(this.decoder,"decoded",this.ondecoded.bind(this)))}onping(){this.emitReserved("ping")}ondata(s){try{this.decoder.add(s)}catch(l){this.onclose("parse error",l)}}ondecoded(s){Co(()=>{this.emitReserved("packet",s)},this.setTimeoutFn)}onerror(s){this.emitReserved("error",s)}socket(s,l){let o=this.nsps[s];return o?this._autoConnect&&!o.active&&o.connect():(o=new ag(this,s,l),this.nsps[s]=o),o}_destroy(s){const l=Object.keys(this.nsps);for(const o of l)if(this.nsps[o].active)return;this._close()}_packet(s){const l=this.encoder.encode(s);for(let o=0;os()),this.subs.length=0,this.decoder.destroy()}_close(){this.skipReconnect=!0,this._reconnecting=!1,this.onclose("forced close")}disconnect(){return this._close()}onclose(s,l){var o;this.cleanup(),(o=this.engine)===null||o===void 0||o.close(),this.backoff.reset(),this._readyState="closed",this.emitReserved("close",s,l),this._reconnection&&!this.skipReconnect&&this.reconnect()}reconnect(){if(this._reconnecting||this.skipReconnect)return this;const s=this;if(this.backoff.attempts>=this._reconnectionAttempts)this.backoff.reset(),this.emitReserved("reconnect_failed"),this._reconnecting=!1;else{const l=this.backoff.duration();this._reconnecting=!0;const o=this.setTimeoutFn(()=>{s.skipReconnect||(this.emitReserved("reconnect_attempt",s.backoff.attempts),!s.skipReconnect&&s.open(f=>{f?(s._reconnecting=!1,s.reconnect(),this.emitReserved("reconnect_error",f)):s.onreconnect()}))},l);this.opts.autoUnref&&o.unref(),this.subs.push(()=>{this.clearTimeoutFn(o)})}}onreconnect(){const s=this.backoff.attempts;this._reconnecting=!1,this.backoff.reset(),this.emitReserved("reconnect",s)}}const ci={};function oo(n,s){typeof n=="object"&&(s=n,n=void 0),s=s||{};const l=MS(n,s.path||"/socket.io"),o=l.source,f=l.id,d=l.path,h=ci[f]&&d in ci[f].nsps,p=s.forceNew||s["force new connection"]||s.multiplex===!1||h;let x;return p?x=new Rf(o,s):(ci[f]||(ci[f]=new Rf(o,s)),x=ci[f]),l.query&&!s.query&&(s.query=l.queryKey),x.socket(l.path,s)}Object.assign(oo,{Manager:Rf,Socket:ag,io:oo,connect:oo});const sg="roverSettings",$S=3600*24*365;function GS(n){try{const s=decodeURIComponent(n??"");return JSON.parse(s)}catch(s){return console.warn("Failed to parse settings cookie",s),null}}function qf(){if(typeof document>"u")return{};const n=`${sg}=`,s=document.cookie.split(";").map(o=>o.trim()).find(o=>o.startsWith(n));if(!s)return{};const l=s.substring(n.length);return GS(l)??{}}function B0(n){if(typeof document>"u")return!1;try{const s=encodeURIComponent(JSON.stringify(n??{})),l=`${sg}=${s}; path=/; max-age=${$S}; samesite=strict`;return document.cookie=l,!0}catch(s){return console.warn("Failed to write settings cookie",s),!1}}const lg=window.location.origin;console.info("[socket] connecting to",lg);const YS=qf(),FS=YS?.page?.connectionTransport||"websocket",XS=FS==="polling"?["polling"]:["websocket","polling"],Wf=oo(lg,{transports:XS,timeout:15e3});Wf.on("connect_error",n=>console.error("connect_error",n.code,n.message,n.data));const ig=m.createContext(Wf),QS=({children:n})=>r.jsx(ig.Provider,{value:Wf,children:n}),tn=()=>m.useContext(ig),KS={connected:!1,session:null,logs:[],adminLogs:[],llmCommentaryState:null,llmCommentaryStatus:null,alerts:[]},ed=m.createContext(null);function ZS(n){return m.useCallback((s,l={})=>new Promise((o,f)=>{n.emit(s,l,(d={})=>{d.error?f(new Error(d.error)):o(d)})}),[n])}function IS(n){return typeof n=="function"?n:s=>s}function JS({children:n}){const s=tn(),l=ZS(s),o=m.useRef({...KS,connected:s.connected}),f=m.useRef(new Set),d=m.useCallback(()=>o.current,[]),h=m.useCallback(v=>{const y=o.current,S=typeof v=="function"?v(y):{...y,...v||{}};S!==y&&(o.current=S,f.current.forEach(E=>{const C=E.selector(S);E.equalityFn(E.current,C)||(E.current=C,E.listener(C))}))},[]),p=m.useCallback((v,y,S=Object.is)=>{const E=IS(v),C={selector:E,equalityFn:S,listener:y,current:E(o.current)};return f.current.add(C),()=>{f.current.delete(C)}},[]);m.useEffect(()=>{const v=()=>{h(S=>S.connected?S:{...S,connected:!0})},y=()=>{h(S=>S.connected?{...S,connected:!1}:S)};return s.on("connect",v),s.on("disconnect",y),()=>{s.off("connect",v),s.off("disconnect",y)}},[h,s]),m.useEffect(()=>{function v(j){h(N=>({...N,session:j}))}function y(j=[]){h(N=>({...N,logs:j}))}function S(j){h(N=>({...N,logs:[...N.logs.slice(-199),j]}))}function E(j=[]){h(N=>({...N,adminLogs:j}))}function C(j){h(N=>({...N,adminLogs:[...N.adminLogs.slice(-199),j]}))}function k(j=null){const N=j&&typeof j=="object"?j:null,T=N?.debug?.status&&typeof N.debug.status=="object"?N.debug.status:null;h(M=>({...M,llmCommentaryState:N,llmCommentaryStatus:T}))}function w(j={}){h(N=>({...N,alerts:[...N.alerts.slice(-49),{...j,receivedAt:Date.now()}]}))}return s.on("session:sync",v),s.on("log:init",y),s.on("log:entry",S),s.on("adminlog:init",E),s.on("adminlog:entry",C),s.on("llm:state",k),s.on("alert:new",w),()=>{s.off("session:sync",v),s.off("log:init",y),s.off("log:entry",S),s.off("adminlog:init",E),s.off("adminlog:entry",C),s.off("llm:state",k),s.off("alert:new",w)}},[h,s]);const x=m.useMemo(()=>({login:(v,y)=>l("auth:login",{username:v,password:y}),identifySession:({cookieUserId:v,nickname:y}={})=>l("session:identify",{cookieUserId:v,nickname:y}),setRole:v=>l("session:setRole",{role:v}),requestControl:(v,y={})=>l("session:requestControl",{roverId:v,...y}),releaseControl:v=>l("session:releaseControl",{roverId:v}),subscribeAll:()=>l("session:subscribeAll"),lockRover:(v,y)=>l("session:lockRover",{roverId:v,locked:y}),setMode:v=>l("setMode",{mode:v}),homeAssistantToggle:v=>l("homeAssistant:toggle",{entityId:v}),homeAssistantSetState:(v,y)=>l("homeAssistant:setState",{entityId:v,state:y}),homeAssistantSetLightColor:(v,y)=>l("homeAssistant:lightColor",{entityId:v,rgbColor:y}),homeAssistantSetLightWhite:v=>l("homeAssistant:lightWhite",{entityId:v}),neatoStart:()=>l("neato:start"),neatoSendHome:()=>l("neato:sendHome"),neatoLocate:()=>l("neato:locate"),neatoClearErrors:()=>l("neato:clearErrors"),setNickname:v=>l("nickname:set",{nickname:v}),requestVerification:()=>l("verification:request"),requestPrivateRoverAccess:v=>l("session:privateRover:requestAccess",{roverId:v}),triggerReplay:(v=[],y="")=>v&&typeof v=="object"&&!Array.isArray(v)?l("replay:trigger",v):l("replay:trigger",{sources:v,title:y}),setCommunityGoal:v=>l("communityGoal:set",{text:v}),setAdminReason:v=>l("adminReason:set",{text:v}),rebootRover:v=>l("command",{roverId:v,type:"reboot",data:{reboot:{}}}),rebootServer:()=>l("server:reboot"),playUploadedAudio:({roverId:v,name:y,mime:S,dataBase64:E})=>l("audio:uploadPlay",{roverId:v,name:y,mime:S,dataBase64:E}),stopUploadedAudio:v=>l("audio:uploadStop",{roverId:v}),startMicWhip:v=>l("audio:micWhipStart",{roverId:v}),readyMicWhip:v=>l("audio:micWhipReady",{roverId:v}),stopMicWhip:v=>l("audio:micWhipStop",{roverId:v}),setAudioLevels:(v={})=>l("audioLevels:set",v),setPrivateSafety:(v,y={})=>l("session:privateSafety:set",{roverId:v,safety:y}),llmControl:(v,y={})=>l("llm:control",{controls:{action:v,...y}}),pushAlert:v=>h(y=>({...y,alerts:[...y.alerts.slice(-49),{...v,receivedAt:Date.now(),id:v.id||Math.random().toString(36).slice(2)}]}))}),[l,h]),g=m.useMemo(()=>({getState:d,subscribe:p,actions:x}),[x,d,p]);return r.jsx(ed.Provider,{value:g,children:n})}function ft(n,s=Object.is){const l=m.useContext(ed);if(!l)throw new Error("useSessionSelector must be used within SessionProvider");const o=m.useRef(n);o.current=n;const f=m.useRef(s);f.current=s;const[d,h]=m.useState(()=>n(l.getState()));return m.useEffect(()=>(h(p=>{const x=o.current(l.getState());return f.current(p,x)?p:x}),l.subscribe(p=>o.current(p),p=>{h(x=>f.current(x,p)?x:p)},(p,x)=>f.current(p,x))),[l]),d}function wn(){const n=m.useContext(ed);if(!n)throw new Error("useSessionActions must be used within SessionProvider");return n.actions}function nn(){const n=ft(l=>l),s=wn();return m.useMemo(()=>({...n,...s}),[s,n])}const rg=m.createContext({frames:{}});function PS({children:n}){const s=tn(),[l,o]=m.useState({});m.useEffect(()=>{function d({roverId:h,sensors:p={},frame:x={}}){h&&o(g=>({...g,[h]:{roverId:h,sensors:p,raw:x?.data||null,receivedAt:Date.now()}}))}return s.on("sensorFrame",d),()=>{s.off("sensorFrame",d)}},[s]);const f=m.useMemo(()=>({frames:l}),[l]);return r.jsx(rg.Provider,{value:f,children:n})}function td(){return m.useContext(rg).frames}function ml(n){const s=td();return n?s[n]??null:null}const WS=650,ej={161:{red:!0},164:{green:!0},165:{force:!0},168:{red:!0,green:!0},169:{red:!0,force:!0},172:{green:!0,force:!0},173:{red:!0,green:!0,force:!0}};function af(n){if(typeof n!="number"||n<=0)return null;const s=ej[n];return s?{code:n,...s}:null}function tj(n,s={}){const l=s.holdMs||WS,[o,f]=m.useState({left:null,right:null,omni:null}),[d,h]=m.useState(0);return m.useEffect(()=>{const p=setInterval(()=>h(Date.now()),Math.max(l/2,100));return()=>clearInterval(p)},[l]),m.useEffect(()=>{const p=Date.now(),x=af(n?.infraredCharacterLeft),g=af(n?.infraredCharacterRight),v=af(n?.infraredCharacterOmni);!x&&!g&&!v||f(y=>({left:x?{...x,ts:p}:y.left,right:g?{...g,ts:p}:y.right,omni:v?{...v,ts:p}:y.omni}))},[n?.infraredCharacterLeft,n?.infraredCharacterRight,n?.infraredCharacterOmni]),m.useEffect(()=>{const{left:p,right:x,omni:g}=o;if(!(p?.ts||x?.ts||g?.ts))return;const y=new Date().toISOString();console.debug("[DockIR]",y,{left:p?.code??0,omni:g?.code??0,right:x?.code??0})},[o.left?.code,o.right?.code,o.omni?.code]),m.useMemo(()=>{const p=Date.now(),x=w=>{if(!w)return{active:!1,red:!1,green:!1,force:!1,age:null,code:null};const j=p-w.ts,N=j<=l;return{active:N,age:j,code:w.code,red:!!(w.red&&N),green:!!(w.green&&N),force:!!(w.force&&N)}},g=x(o.left),v=x(o.right),y=x(o.omni),S=g.force||v.force||y.force,E=g.active||v.active||y.active,C=g.active&&!v.active?"right":v.active&&!g.active?"left":"center",k=(v.active?1:0)-(g.active?1:0);return{visible:E,forceDetected:S,left:g,right:v,omni:y,bias:C,balance:Math.max(-1,Math.min(1,k))}},[o.left,o.right,o.omni,l,d])}function nj(){ft(S=>S.connected);const n=ft(S=>S.session),s=n?.assignment?.roverId,l=ml(s),o=l?.sensors||{},f=tj(o),d=o.voltageMv!=null?`${(o.voltageMv/1e3).toFixed(2)} V`:null,h=o.currentMa!=null?`${o.currentMa} mA`:null,p=o.batteryTemperatureC!=null?`${o.batteryTemperatureC} °C`:null,x=o.batteryChargeMah,g=o.batteryCapacityMah;l?.receivedAt&&new Date(l.receivedAt).toLocaleTimeString();const v=l?.raw?l.raw:null,y=s?n?.activeDrivers?.[s]:null;return m.useMemo(()=>s?y?y===n?.socketId?"You":(n?.users||[]).find(E=>E.socketId===y)?.nickname||y.slice(0,6):"Available":"n/a",[y,s,n?.socketId,n?.users]),r.jsxs("section",{className:"panel-section space-y-0.5 text-base text-slate-100",children:[s?l?r.jsxs(r.Fragment,{children:[r.jsx(aj,{sensors:o,voltage:d,current:h,batteryTemp:p,charge:x,capacity:g}),r.jsx(sj,{sensors:o,dockState:f})]}):r.jsx("p",{className:"text-sm text-slate-500",children:"Waiting for sensor frames…"}):r.jsx("p",{className:"text-sm text-slate-500",children:"Assign a rover to view sensors."}),v&&r.jsx("pre",{className:"surface whitespace-pre-wrap break-words text-xs text-lime-300",children:v})]})}function aj({sensors:n,voltage:s,current:l,batteryTemp:o,charge:f,capacity:d}){const h=f!=null&&d?`${Math.round(f/d*100)}`:"--",p=n?.oiMode?.label||"--",x=n?.chargingSources?.homeBase?"Yes":"No",g=n?.chargingState?.label||"--";return r.jsxs("div",{className:"grid grid-cols-2 gap-0.5 md:grid-cols-3",children:[r.jsx(aa,{label:"Voltage",value:s??"--"}),r.jsx(aa,{label:"Current",value:l??"--"}),r.jsx(aa,{label:"Battery temp",value:o??"--"}),r.jsx(aa,{label:"Charge",value:f!=null?`${f} mAh`:"--"}),r.jsx(aa,{label:"Capacity",value:d!=null?`${d} mAh`:"--"}),r.jsx(aa,{label:"Charge",value:h}),r.jsx(aa,{label:"OI mode",value:p}),r.jsx(aa,{label:"Docked",value:x}),r.jsx(aa,{label:"Charging state",value:g})]})}function aa({label:n,value:s}){return r.jsxs("div",{className:"surface flex items-center justify-between gap-0.5 px-1 py-0.5 text-sm",children:[r.jsx("span",{className:"text-slate-400",children:n}),r.jsx("span",{className:"text-slate-100",children:s})]})}function sj({sensors:n,dockState:s}){const l=n?.bumpsAndWheelDrops||{},o=n?.wheelOvercurrents||{},f=[{label:"Left",value:n?.lightBumpLeftSignal},{label:"Front Left",value:n?.lightBumpFrontLeftSignal},{label:"Center Left",value:n?.lightBumpCenterLeftSignal},{label:"Center Right",value:n?.lightBumpCenterRightSignal},{label:"Front Right",value:n?.lightBumpFrontRightSignal},{label:"Right",value:n?.lightBumpRightSignal}],d=[{label:"Left",value:n?.cliffLeftSignal,active:n?.cliffLeft},{label:"Front Left",value:n?.cliffFrontLeftSignal,active:n?.cliffFrontLeft},{label:"Front Right",value:n?.cliffFrontRightSignal,active:n?.cliffFrontRight},{label:"Right",value:n?.cliffRightSignal,active:n?.cliffRight}],h=[{label:"Wheel L",value:n?.wheelLeftCurrentMa,over:o.leftWheel},{label:"Wheel R",value:n?.wheelRightCurrentMa,over:o.rightWheel},{label:"Side brush",value:n?.sideBrushCurrentMa,over:o.sideBrush},{label:"Main brush",value:n?.mainBrushCurrentMa,over:o.mainBrush}];return r.jsxs("div",{className:"grid gap-0.5 md:grid-cols-2",children:[r.jsxs(el,{title:"Dock IR",children:[r.jsx(lj,{sensors:n}),r.jsx(ij,{state:s})]}),r.jsxs(el,{title:"Bumps & drops",children:[r.jsx(sa,{label:"Bump L",value:r.jsx(ui,{active:l.bumpLeft})}),r.jsx(sa,{label:"Bump R",value:r.jsx(ui,{active:l.bumpRight})}),r.jsx(sa,{label:"Wheel drop L",value:r.jsx(ui,{active:l.wheelDropLeft,tone:"amber"})}),r.jsx(sa,{label:"Wheel drop R",value:r.jsx(ui,{active:l.wheelDropRight,tone:"amber"})})]}),r.jsx(el,{title:"Light bumps (raw)",children:f.map(p=>r.jsx(sa,{label:p.label,value:fi(p.value)},p.label))}),r.jsx(el,{title:"Cliff sensors",children:d.map(p=>r.jsx(sa,{label:p.label,value:`${fi(p.value)} · ${p.active?"bool: true":"bool: false"}`},p.label))}),r.jsx(el,{title:"Currents",children:h.map(p=>r.jsx(sa,{label:p.label,value:r.jsxs("span",{className:"flex items-center gap-0.5",children:[r.jsx("span",{children:fi(p.value,"mA")}),p.over?r.jsx(ui,{active:!0,tone:"red",label:"over"}):null]})},p.label))}),r.jsxs(el,{title:"Dirt detect",children:[r.jsx(sa,{label:"Left",value:fi(n?.dirtDetectLeft)}),r.jsx(sa,{label:"Right",value:fi(n?.dirtDetect)})]})]})}function el({title:n,children:s}){return r.jsxs("div",{className:"surface space-y-0.5 p-1 text-sm",children:[r.jsx("div",{className:"text-[0.8rem] uppercase tracking-wide text-slate-400",children:n}),r.jsx("div",{className:"space-y-0.5",children:s})]})}function sa({label:n,value:s}){return r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{className:"text-slate-300",children:n}),r.jsx("span",{className:"text-slate-100",children:s})]})}function ui({active:n,tone:s="green",label:l}){const o="rounded px-1.5 py-0.5 text-[0.7rem] font-semibold",f=s==="red"?n?"bg-red-600 text-white":"bg-slate-700 text-slate-300":s==="amber"?n?"bg-amber-500 text-slate-900":"bg-slate-700 text-slate-300":n?"bg-emerald-600 text-white":"bg-slate-700 text-slate-300";return r.jsx("span",{className:`${o} ${f}`,children:l||(n?"true":"false")})}function fi(n,s){return n==null||Number.isNaN(n)?"--":s?`${n} ${s}`:n}function lj({sensors:n}){const s=n?.infraredCharacterLeft,l=n?.infraredCharacterRight,o=n?.infraredCharacterOmni,f=d=>r.jsx("span",{className:`rounded px-1 py-0.25 text-[0.7rem] font-semibold ${d?"bg-emerald-600 text-white":"bg-slate-700 text-slate-300"}`,children:d||"--"});return r.jsxs("div",{className:"flex items-center justify-between gap-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:"L"}),f(s)]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:"O"}),f(o)]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:"R"}),f(l)]})]})}function ij({state:n}){if(!n)return null;const s=o=>{const f=[];return o?.red&&f.push("R"),o?.green&&f.push("G"),o?.force&&f.push("F"),f.length?f.join(""):"none"},l=o=>o?.age!=null?`${o.age}ms`:"--";return r.jsxs("div",{className:"text-[0.7rem] text-slate-400",children:[r.jsx("div",{children:`Left: ${n.left.code??"--"} (${s(n.left)}) · age ${l(n.left)}`}),r.jsx("div",{children:`Omni: ${n.omni.code??"--"} (${s(n.omni)}) · age ${l(n.omni)}`}),r.jsx("div",{children:`Right: ${n.right.code??"--"} (${s(n.right)}) · age ${l(n.right)}`})]})}const og=m.createContext(null);function rj({children:n}){const[s,l]=m.useState(()=>({status:"loading",data:{}}));m.useEffect(()=>{const p=qf();l({status:"ready",data:p??{}})},[]);const o=m.useCallback(()=>{const p=qf();l({status:"ready",data:p??{}})},[]),f=m.useCallback(p=>{const x=B0(p??{});return l(x?{status:"ready",data:p??{}}:g=>({...g,status:"error"})),x},[]),d=m.useCallback((p,x)=>{l(g=>{const v=g.data[p]||{},y=typeof x=="function"?x(v):{...v,...x??{}},S={...g.data,[p]:y};return B0(S)?{status:"ready",data:S}:{...g,status:"error"}})},[]),h=m.useMemo(()=>({data:s.data,status:s.status,reload:o,saveAll:f,setNamespace:d}),[s,o,f,d]);return r.jsx(og.Provider,{value:h,children:n})}function oj(){const n=m.useContext(og);if(!n)throw new Error("useSettings must be used within SettingsProvider");return n}function He(n,s={}){const{data:l,status:o,setNamespace:f}=oj(),d=l[n]??s??{},h=m.useCallback(g=>{f(n,v=>{const y=v??{};return typeof g=="function"?g(y):{...y,...g??{}}})},[n,f]),p=m.useCallback(g=>{f(n,()=>g??{})},[n,f]),x=m.useCallback(()=>{const g=typeof s=="object"?{...s}:s;f(n,()=>g??{})},[s,n,f]);return{value:d,status:o,save:h,replace:p,reset:x}}const cj=/^#[0-9A-Fa-f]{6}$/;function nd(n){const s=typeof n=="string"?n.trim():"";return!s||!cj.test(s)?null:s.toUpperCase()}function ca(n,s=.2){const l=nd(n);if(!l)return;const o=Number.isFinite(s)?Math.max(0,Math.min(1,s)):.2,f=cg(l);if(f)return{borderColor:`rgba(${f.r}, ${f.g}, ${f.b}, 0.65)`,backgroundColor:`rgba(${f.r}, ${f.g}, ${f.b}, ${o})`}}function uj(n,s=.2){const l=nd(n);if(!l)return;const o=Number.isFinite(s)?Math.max(0,Math.min(1,s)):.2,f=cg(l);if(f)return{borderColor:`rgba(${f.r}, ${f.g}, ${f.b}, 0.55)`,backgroundColor:`rgba(${f.r}, ${f.g}, ${f.b}, ${o})`}}function cg(n){const s=nd(n);return s?{r:parseInt(s.slice(1,3),16),g:parseInt(s.slice(3,5),16),b:parseInt(s.slice(5,7),16)}:null}function fj(n=[]){return n.map(s=>!s?.type||!s?.id?null:{type:s.type,id:String(s.id),label:s.label||String(s.id),color:s.color||null,key:`${s.type}:${s.id}`}).filter(Boolean)}function ad({panelId:n="replay-sources",fillHeight:s=!1}){const{session:l,triggerReplay:o}=nn(),f=fj(l?.replaySources||[]),{value:d,save:h}=He("replaySources",{}),[p,x]=m.useState([]),[g,v]=m.useState(!1),[y,S]=m.useState(null),[E,C]=m.useState(null),[k,w]=m.useState(""),[j,N]=m.useState(!1),[T,M]=m.useState(!0),O=l?.replay||null,[K,_]=m.useState(0),U=m.useMemo(()=>{const q=l?.assignment?.roverId;return q?[`rover:${q}`]:[]},[l?.assignment?.roverId]),X=m.useMemo(()=>{const L=((Array.isArray(l?.users)?l.users.find(fe=>fe?.socketId===l?.socketId):null)?.nickname||"Someone").trim()||"Someone",Z=l?.assignment?.roverId||null,le=Z&&Array.isArray(l?.roster)?l.roster.find(fe=>String(fe?.id)===String(Z))?.name||Z:"a rover";return`${L} driving ${le}`},[l?.users,l?.socketId,l?.assignment?.roverId,l?.roster]);m.useEffect(()=>{const q=d?.[n];if(Array.isArray(q)&&q.length){x(q);return}x(U)},[d?.[n],U,n]),m.useEffect(()=>{const q=d?.[`${n}:includeSidebar`];if(typeof q=="boolean"){M(q);return}M(!0)},[d?.[`${n}:includeSidebar`],n]),m.useEffect(()=>{j||w(X)},[X,j]),m.useEffect(()=>{const q=new Set(f.map(L=>L.key));x(L=>L.filter(Z=>q.has(Z)))},[f]);const F=m.useMemo(()=>({rovers:f.filter(q=>q.type==="rover"),rooms:f.filter(q=>q.type==="room")}),[f]);m.useEffect(()=>{if(!O?.lastTriggeredAt||!O?.cooldownMs){_(0);return}const q=()=>{const Z=O.lastTriggeredAt+O.cooldownMs-Date.now();_(Math.max(0,Z))};q();const L=setInterval(q,250);return()=>clearInterval(L)},[O?.lastTriggeredAt,O?.cooldownMs,O?.remainingMs]);const H=g||l?.mode==="lockdown"||K>0||!p.length,te=q=>{x(L=>{const Z=L.includes(q)?L.filter(le=>le!==q):[...L,q];return h(le=>({...le||{},[n]:Z})),Z}),C(null)},ce=async()=>{if(!H){v(!0),S(null),C(null);try{const q=p.map(Z=>{const[le,fe]=Z.split(":");return{type:le,id:fe}}),L=String(k||"").trim()||X;await o({sources:q,title:L,includeSidebar:T}),C("Replay sent. Check the Discord replay channel.")}catch(q){S(q.message)}finally{v(!1)}}},oe=s?"h-full flex flex-col":"",V=s?"flex-1 min-h-0 overflow-y-auto":"";return r.jsxs("section",{className:`panel-section p-0.75 text-sm ${oe}`,children:[r.jsxs("header",{className:"panel-muted flex items-center justify-between text-xs",children:[r.jsx("span",{children:"Replay Sources"}),r.jsx("span",{children:f.length})]}),r.jsxs("div",{className:`grid gap-0.5 md:grid-cols-2 ${V}`,children:[r.jsx(O0,{title:"Rovers",items:F.rovers,selected:p,onToggle:te}),r.jsx(O0,{title:"Room Cams",items:F.rooms,selected:p,onToggle:te})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("label",{className:"panel-muted block text-xs",htmlFor:`${n}-title`,children:"Replay title"}),r.jsx("input",{id:`${n}-title`,type:"text",className:"field-input w-full text-xs",value:k,onChange:q=>{w(q.target.value),N(!0)},placeholder:X,maxLength:120}),r.jsxs("label",{className:"surface flex items-center gap-0.5 text-xs",children:[r.jsx("input",{type:"checkbox",checked:T,onChange:q=>{const L=!!q.target.checked;M(L),h(Z=>({...Z||{},[`${n}:includeSidebar`]:L}))},className:"accent-emerald-400"}),r.jsx("span",{children:"Include replay sidebar"})]}),r.jsx("button",{type:"button",className:"button-dark w-full text-xs disabled:opacity-40",onClick:ce,disabled:H,children:K>0?`Replay (${Math.ceil(K/1e3)}s)`:g?"Replay…":"Replay"}),y?r.jsx("div",{className:"text-xs text-amber-400",children:y}):null,E?r.jsx("div",{className:"text-xs text-emerald-300",children:E}):null]})]})}function O0({title:n,items:s,selected:l,onToggle:o}){return s.length?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs",children:n}),r.jsx("div",{className:"space-y-0.5",children:s.map(f=>r.jsxs("label",{className:"surface flex items-center gap-0.5 text-xs",children:[r.jsx("input",{type:"checkbox",checked:l.includes(f.key),onChange:()=>o(f.key),className:"accent-emerald-400"}),r.jsx("span",{className:`truncate ${f.type==="rover"?"rounded px-1 py-[1px] border border-transparent":""}`,style:f.type==="rover"?ca(f.color,.16):void 0,children:f.label})]},f.key))})]}):null}var ug={color:void 0,size:void 0,className:void 0,style:void 0,attr:void 0},L0=fs.createContext&&fs.createContext(ug),dj=["attr","size","title"];function mj(n,s){if(n==null)return{};var l=hj(n,s),o,f;if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(n);for(f=0;f=0)&&Object.prototype.propertyIsEnumerable.call(n,o)&&(l[o]=n[o])}return l}function hj(n,s){if(n==null)return{};var l={};for(var o in n)if(Object.prototype.hasOwnProperty.call(n,o)){if(s.indexOf(o)>=0)continue;l[o]=n[o]}return l}function ho(){return ho=Object.assign?Object.assign.bind():function(n){for(var s=1;sfs.createElement(s.tag,po({key:l},s.attr),fg(s.child)))}function Ti(n){return s=>fs.createElement(vj,ho({attr:po({},n.attr)},s),fg(n.child))}function vj(n){var s=l=>{var{attr:o,size:f,title:d}=n,h=mj(n,dj),p=f||l.size||"1em",x;return l.className&&(x=l.className),n.className&&(x=(x?x+" ":"")+n.className),fs.createElement("svg",ho({stroke:"currentColor",fill:"currentColor",strokeWidth:"0"},l.attr,o,h,{className:x,style:po(po({color:n.color||l.color},l.style),n.style),height:p,width:p,xmlns:"http://www.w3.org/2000/svg"}),d&&fs.createElement("title",null,d),n.children)};return L0!==void 0?fs.createElement(L0.Consumer,null,l=>s(l)):s(ug)}function dg(n){return Ti({attr:{viewBox:"0 0 640 512"},child:[{tag:"path",attr:{d:"M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z"},child:[]}]})(n)}function bj(n){return Ti({attr:{viewBox:"0 0 448 512"},child:[{tag:"path",attr:{d:"M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"},child:[]}]})(n)}function U0(n){return Ti({attr:{viewBox:"0 0 640 512"},child:[{tag:"path",attr:{d:"M192 384h192c53 0 96-43 96-96h32c70.6 0 128-57.4 128-128S582.6 32 512 32H120c-13.3 0-24 10.7-24 24v232c0 53 43 96 96 96zM512 96c35.3 0 64 28.7 64 64s-28.7 64-64 64h-32V96h32zm47.7 384H48.3c-47.6 0-61-64-36-64h583.3c25 0 11.8 64-35.9 64z"},child:[]}]})(n)}function yj(n){return Ti({attr:{viewBox:"0 0 640 512"},child:[{tag:"path",attr:{d:"M528 448H112c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h416c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm64-320c-26.5 0-48 21.5-48 48 0 7.1 1.6 13.7 4.4 19.8L476 239.2c-15.4 9.2-35.3 4-44.2-11.6L350.3 85C361 76.2 368 63 368 48c0-26.5-21.5-48-48-48s-48 21.5-48 48c0 15 7 28.2 17.7 37l-81.5 142.6c-8.9 15.6-28.9 20.8-44.2 11.6l-72.3-43.4c2.7-6 4.4-12.7 4.4-19.8 0-26.5-21.5-48-48-48S0 149.5 0 176s21.5 48 48 48c2.6 0 5.2-.4 7.7-.8L128 416h384l72.3-192.8c2.5.4 5.1.8 7.7.8 26.5 0 48-21.5 48-48s-21.5-48-48-48z"},child:[]}]})(n)}function Sj(n){return Ti({attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"},child:[]}]})(n)}function jj(n){switch(n){case"admin":case"lockdown":case"lockdown-admin":return"text-amber-300";case"spectator":return"text-slate-400";default:return"text-sky-300"}}function sd(n){return!!n?.system}function Aj(n){const s=new Date(n);return`${s.getHours().toString().padStart(2,"0")}:${s.getMinutes().toString().padStart(2,"0")}`}function H0(n){return n.nickname||n.socketId?.slice(0,6)||"unknown"}function Nj({guildIconUrl:n,userAvatarUrl:s,label:l}){return!n&&!s?null:r.jsxs("span",{className:"flex h-4 w-4 overflow-hidden rounded-full border border-slate-700/80",title:l,children:[r.jsx("span",{className:`h-full w-1/2 bg-slate-700/70 ${n?"bg-cover":""}`,style:n?{backgroundImage:`url(${n})`,backgroundPosition:"left center",backgroundSize:"200% 100%"}:void 0}),r.jsx("span",{className:`h-full w-1/2 bg-slate-700/70 ${s?"bg-cover":""}`,style:s?{backgroundImage:`url(${s})`,backgroundPosition:"right center",backgroundSize:"200% 100%"}:void 0})]})}function mg({message:n}){const s=n.fromDiscord?`${n.discordGuildName||"Discord"} · ${H0(n)}`:null,l=sd(n),o=l?"text-emerald-300":jj(n.role);return r.jsxs(r.Fragment,{children:[n.fromDiscord?r.jsxs(r.Fragment,{children:[r.jsx(dg,{className:"h-3.5 w-3.5 text-indigo-200"}),r.jsx(Nj,{guildIconUrl:n.discordGuildIconUrl,userAvatarUrl:n.discordUserAvatarUrl,label:s})]}):null,r.jsx("span",{className:`font-semibold text-[0.85rem] ${o}`,children:H0(n)}),l?r.jsx("span",{className:"rounded bg-emerald-900/60 px-1 text-[0.65rem] font-semibold uppercase tracking-wide text-white",children:"bot"}):null,n.roverId&&r.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem]",style:uj(n.roverColor,.14),children:n.roverId})]})}function hg(n){return sd(n)?"surface-muted relative flex flex-wrap items-start gap-0.5 border border-emerald-500/40 bg-emerald-900/15 text-sm":`surface-muted relative flex flex-wrap items-start gap-0.5 text-sm ${n.role==="admin"||n.role==="lockdown"||n.role==="lockdown-admin"?"border border-amber-400/30":n.fromDiscord?"border border-indigo-400/30 bg-indigo-900/20":""}`}function ld({message:n}){const s=sd(n);return r.jsxs("div",{className:hg(n),children:[r.jsx(mg,{message:n}),r.jsx("span",{className:`break-words leading-tight whitespace-pre-wrap ${s?"text-emerald-100":"text-slate-100"}`,children:n.text}),r.jsx("span",{className:"absolute bottom-0.5 right-1 text-[0.65rem] text-slate-400/60",children:Aj(n.ts)})]})}function pg({message:n}){return r.jsxs("div",{className:`${hg(n)} italic opacity-80 border-slate-600/40 bg-slate-900/40`,children:[r.jsx(mg,{message:n}),r.jsx("span",{className:"text-slate-300",children:"typing..."})]})}function xg({buttonId:n,count:s,goal:l,rewardNumber:o,rewardName:f,className:d=""}){return r.jsxs("article",{className:["surface px-0.5 py-0.5 text-center",d].filter(Boolean).join(" "),children:[r.jsxs("p",{className:"text-xs text-slate-400",children:["Button ",n]}),r.jsxs("p",{className:"text-sm font-semibold text-white",children:[s," / ",l]}),r.jsxs("p",{className:"truncate text-[0.7rem] text-slate-300",children:["#",o," ",f]})]})}const wj=3e3,Cj=3500,Ej="#2196f3";function kj(n){return n.id?n.id:n.timestamp?`${n.timestamp}-${n.message}`:`${n.title||"alert"}-${n.message}`}function id({scale:n=1}){const s=ft(S=>S.alerts),l=ft(S=>S.session),{pushAlert:o}=wn(),f=tn(),[d,h]=m.useState(()=>Date.now());m.useEffect(()=>{function S(E={}){const C=Number(E.buttonId);if(!Number.isFinite(C)||C<1||C>4)return;const w=(Array.isArray(l?.buttonBox?.buttons)?l.buttonBox.buttons:[]).find(O=>Number(O?.id)===C)||{},j=Number.isFinite(E.count)?E.count:Number(w.count)||0,N=Number.isFinite(w.goal)?w.goal:0,T=Number.isFinite(w.rewardNumber)?w.rewardNumber:"?",M=typeof w.rewardName=="string"&&w.rewardName.trim()?w.rewardName.trim():"Unassigned";o({id:`buttonbox-active-${C}`,kind:"buttonbox-active",lifetimeMs:Cj,payload:{buttonId:C,count:j,goal:N,rewardNumber:T,rewardName:M}})}return f.on("buttonBox:increment",S),()=>{f.off("buttonBox:increment",S)}},[o,l?.buttonBox?.buttons,f]);const p=m.useMemo(()=>s.slice(-12).map(S=>({alert:S,key:kj(S)})),[s]);m.useEffect(()=>{if(!p.length)return;const S=setInterval(()=>h(Date.now()),200);return()=>clearInterval(S)},[p.length]);const x=new Map;p.forEach(S=>{const E=d-(S.alert.receivedAt??S.alert.timestamp??0),C=Number.isFinite(S.alert.lifetimeMs)?S.alert.lifetimeMs:wj;E<=C&&x.set(S.key,{...S,age:E})});const g=Array.from(x.values()).slice(-3);if(!g.length)return null;const v=n===1?void 0:{transform:`translateX(-50%) scale(${n})`,transformOrigin:"top center"},y=n===1?"pointer-events-none fixed top-0.5 left-1/2 z-50 flex -translate-x-1/2 flex-col gap-0.5":"pointer-events-none fixed top-0.5 left-1/2 z-50 flex flex-col gap-0.5";return r.jsx("div",{className:y,style:v,children:g.map(S=>r.jsx(Mj,{alert:S.alert},S.key))})}function V0(n){const s=typeof n=="string"?n.trim():"",l=/^#?([0-9a-fA-F]{6})$/.exec(s);if(!l)return null;const o=l[1];return{r:parseInt(o.slice(0,2),16),g:parseInt(o.slice(2,4),16),b:parseInt(o.slice(4,6),16)}}function Mj({alert:n}){if(n.kind==="buttonbox-active"&&n.payload){const f=n.payload;return r.jsx("div",{className:"pointer-events-none w-[12.5rem]",children:r.jsx(xg,{buttonId:f.buttonId,count:f.count,goal:f.goal,rewardNumber:f.rewardNumber,rewardName:f.rewardName,className:"bg-cyan-900/45"})})}if(n.kind==="chat"&&n.payload)return r.jsx(ld,{message:n.payload});if(n.kind==="chat-typing"&&n.payload)return r.jsx(pg,{message:n.payload});const s=V0(n.color)||V0(Ej),l=s?`rgba(${s.r}, ${s.g}, ${s.b}, 0.18)`:"rgba(33, 150, 243, 0.18)",o=s?`rgba(${s.r}, ${s.g}, ${s.b}, 0.45)`:"rgba(33, 150, 243, 0.45)";return r.jsx("div",{className:"pointer-events-auto max-w-[80vw] rounded-full border px-2 py-0.5 text-[0.7rem] leading-tight text-slate-100 shadow-sm shadow-black/30",style:{backgroundColor:l,border:`1px solid ${o}`},children:r.jsxs("p",{className:"truncate text-slate-100",children:[r.jsx("span",{className:"text-slate-300",children:n.title||"Alert"}),r.jsx("span",{className:"text-slate-500",children:" · "}),r.jsx("span",{className:"text-white",children:n.message})]})})}const tl={main:[-127,127],side:[-127,127],vacuum:[0,127]},sf={maxSpeed:500,baseSpeed:250,boostSpeed:400},Tf=100,rd=[31,127],il=60,Df=8,Rj=250,qj=4e3,Zr=.4,$0=.2,G0=.8,Tj={start:[128],safe:[131],full:[132],passive:[128],dock:[143]},gi={driveForward:["w"],driveBackward:["s"],driveLeft:["a"],driveRight:["d"],boostModifier:["\\"],slowModifier:["shift"],auxMainForward:["i"],auxMainReverse:["k"],auxSideForward:["o"],auxSideReverse:["l"],auxVacuumFast:["p"],auxVacuumSlow:[";"],auxAllForward:[","],cameraUp:["u"],cameraDown:["j"],nightVisionToggle:["e"],hornHonk:["h"],micPtt:["m"],driveMacro:["f"],dockMacro:["g"],chatFocus:["enter"],songNoteUp:["ArrowUp"],songNoteDown:["ArrowDown"],homeAssistantOn:["ArrowRight"],homeAssistantOff:["ArrowLeft"]},gg=[{id:"drive-sequence",label:"Drive",description:"Start, undock, and full command sequence used by the drive button.",steps:[{type:"servo",angle:0},{type:"oi",command:"start"},{type:"pause",duration:Tf},{type:"oi",command:"dock"},{type:"pause",duration:Tf},{type:"oi",command:"full"},{type:"pause",duration:300},{type:"drive",speeds:{left:-300,right:-300}},{type:"pause",duration:600},{type:"drive",speeds:{left:0,right:0}}]},{id:"seek-dock",label:"Dock",description:"Send the seek dock command.",steps:[{type:"oi",command:"dock"}]}];function _f(){return{vector:{x:0,y:0,boost:!1},speeds:{left:0,right:0},source:null,lastUpdatedAt:0}}function Bf(){return{main:0,side:0,vacuum:0}}function Dj(){return{enabled:!1,angle:null,config:null}}function co(){return{note:il}}function pi(){return{active:!1,heat:0,overheated:!1}}function uo(){return{pttActive:!1}}const Y0={roverId:null,mode:"drive",drive:_f(),aux:Bf(),camera:Dj(),song:co(),horn:pi(),mic:uo(),lastControlIntentAt:0,macros:gg,keymap:gi,inputs:{}};function _j(n,s){switch(s.type){case"control/set-rover":return{...n,roverId:s.payload??null,drive:s.payload?n.drive:_f(),aux:s.payload?n.aux:Bf(),song:s.payload?n.song:co(),horn:s.payload?n.horn:pi(),mic:s.payload?n.mic:uo(),lastControlIntentAt:s.payload?n.lastControlIntentAt:0};case"control/set-mode":return n.mode===s.payload?n:{...n,mode:s.payload==="dock"?"dock":"drive"};case"control/update-drive":{const{vector:l,speeds:o,source:f}=s.payload;return{...n,drive:{vector:l??n.drive.vector,speeds:o??n.drive.speeds,source:f??n.drive.source,lastUpdatedAt:Date.now()}}}case"control/set-aux-motors":return{...n,aux:{...n.aux,...s.payload}};case"control/set-camera-config":return{...n,camera:{...n.camera,enabled:!!s.payload?.config,config:s.payload?.config??null,angle:typeof s.payload?.angle=="number"?s.payload.angle:s.payload?.config?s.payload.config.homeAngle??n.camera.angle:null}};case"control/set-camera-angle":return{...n,camera:{...n.camera,angle:s.payload}};case"control/register-input-state":{const l=s.payload?.source||"unknown";return{...n,inputs:{...n.inputs,[l]:{...n.inputs[l]??{},...s.payload?.state,updatedAt:Date.now()}}}}case"control/set-keymap":return{...n,keymap:{...n.keymap,...s.payload??{}}};case"control/set-macros":return{...n,macros:Array.isArray(s.payload)?s.payload:n.macros};case"control/reset":return{...n,drive:_f(),aux:Bf(),song:co(),horn:pi(),mic:uo(),lastControlIntentAt:0};case"control/set-horn-active":return{...n,horn:{...n.horn||pi(),active:!!s.payload}};case"control/set-horn-heat":return{...n,horn:{...n.horn||pi(),heat:typeof s.payload?.heat=="number"?s.payload.heat:0,overheated:!!s.payload?.overheated}};case"control/record-intent":return{...n,lastControlIntentAt:Date.now()};case"control/set-song-note":return{...n,song:{...n.song||co(),note:s.payload??il}};case"control/set-mic-ptt":return{...n,mic:{...n.mic||uo(),pttActive:!!s.payload}};default:return n}}function rl(n,s,l){return typeof n!="number"||Number.isNaN(n)?s:Math.max(s,Math.min(l,n))}function ol(n){return typeof n!="number"||Number.isNaN(n)?0:Math.max(-1,Math.min(1,n))}function pn(n,s){return!Array.isArray(s)||s.length!==2?n:rl(n,s[0],s[1])}function Bj(n={}){const s=ol(n.x??0),l=ol(n.y??0);return{x:s,y:l,boost:!!n.boost}}function Oj(n={},s={}){const l=Bj(n),o=typeof s.maxSpeed=="number"?s.maxSpeed:sf.maxSpeed,f=typeof s.baseSpeed=="number"?s.baseSpeed:sf.baseSpeed,d=typeof s.boostSpeed=="number"?s.boostSpeed:sf.boostSpeed,h=l.boost?d:f,p=l.y*h,x=l.x*h;return{vector:l,speeds:{left:rl(Math.round(p+x),-o,o),right:rl(Math.round(p-x),-o,o)}}}function Lj(n){const s=Array.isArray(n)?n:[],l=String.fromCharCode(...s);if(typeof btoa=="function")return btoa(l);if(typeof Buffer<"u")return Buffer.from(s).toString("base64");throw new Error("No base64 encoder available")}function F0(n){return new Promise(s=>setTimeout(s,n))}function zj(n={}){const{driveTransform:s,auxTransform:l}=n,o=tn(),f=ft(O=>O.session),d=f?.assignment?.roverId,h=m.useMemo(()=>!d||!Array.isArray(f?.roster)?null:f.roster.find(O=>String(O.id)===String(d))||null,[d,f?.roster]),p=m.useMemo(()=>!h?.cameraServo||!h.cameraServo.enabled?null:h.cameraServo,[h]),x=m.useMemo(()=>!h?.nightVision||!h.nightVision.enabled?null:h.nightVision,[h]),g=m.useMemo(()=>!h?.horn||!h.horn.enabled?null:h.horn,[h]),v=m.useMemo(()=>h?.nightVision?.state??null,[h]),y=m.useCallback((O,K)=>{d&&o.emit("command",{roverId:d,...O},K)},[o,d]),S=m.useCallback(()=>{d&&y({type:"sensorStream",data:{sensorStream:{enable:!0}}})},[y,d]),E=m.useCallback(O=>{if(!d)return null;const K={left:pn(O?.left??0,[-500,500]),right:pn(O?.right??0,[-500,500])},_=s?s(K):K,U={left:pn(_?.left??0,[-500,500]),right:pn(_?.right??0,[-500,500])};return y({type:"drive",data:{driveDirect:U}}),U},[s,y,d]),C=m.useCallback(({main:O=0,side:K=0,vacuum:_=0}={})=>{if(!d)return null;const U={main:pn(O,tl.main),side:pn(K,tl.side),vacuum:pn(_,tl.vacuum)},X=l?l(U):U,F={main:pn(X?.main??0,tl.main),side:pn(X?.side??0,tl.side),vacuum:pn(X?.vacuum??0,tl.vacuum)};return y({type:"motors",data:{motorPwm:F}}),F},[l,y,d]),k=m.useCallback(O=>!d||!p?null:(y({type:"servo",data:{servo:{angle:O}}}),O),[y,d,p]),w=m.useCallback(O=>{if(!d)return!1;const K=Array.isArray(O)?O:typeof O=="string"?Tj[O]:null;return K?(y({type:"raw",data:{raw:Lj(K)}}),S(),!0):!1},[y,S,d]),j=m.useCallback(async O=>{if(!(!O||!Array.isArray(O.steps)||!d))for(const K of O.steps){if(!d)break;switch(K.type){case"oi":w(K.command);break;case"drive":E(K.speeds??{left:0,right:0});break;case"motors":C(K.values??{});break;case"servo":k(K.angle);break;case"pause":await F0(K.duration??Tf);break}if(K.delay||K.delayMs){const _=K.delayMs??K.delay;typeof _=="number"&&_>0&&await F0(_)}}},[d,w,E,C,k]),N=m.useCallback((O="toggle")=>!d||!x?null:(y({type:"nightVision",data:{nightVision:{action:O}}}),O),[y,x,d]),T=m.useCallback(O=>d?(y({type:"horn",data:{horn:O}}),O):null,[y,d]),M=m.useCallback((O=[],K={})=>{if(!d)return null;const U=(Array.isArray(O)&&O.length>0?O:[{note:il,duration:Df}]).slice(0,16).map(X=>({note:pn(Math.round(X?.note??il),rd),duration:pn(Math.round(X?.duration??Df),[1,255])}));return y({type:"song",data:{song:{notes:U,slot:K.slot,loop:K.loop}}}),U},[y,d]);return m.useMemo(()=>({roverId:d,rosterEntry:h,servoConfig:p,nightVision:x,nightVisionState:v,horn:g,emitCommand:y,enableSensorStream:S,sendDriveDirect:E,sendAuxMotors:C,sendServoAngle:k,sendOiCommand:w,sendNightVision:N,sendHorn:T,sendSong:M,runMacroSteps:j}),[d,h,p,x,v,g,y,S,E,C,k,w,N,T,j])}const Uj={"{":"[","}":"]",":":";",'"':"'","<":",",">":".","?":"/","|":"\\",_:"-","+":"="},X0={"[":"BracketLeft","]":"BracketRight","\\":"Backslash",";":"Semicolon","'":"Quote",",":"Comma",".":"Period","/":"Slash","-":"Minus","=":"Equal","`":"Backquote"};function Di(n){if(typeof n!="string")return"";const s=n.toLowerCase();return Uj[s]??s}function Hj(n){const s=Di(n);if(!s)return null;if(X0[s])return X0[s];if(s.length===1){if(/[a-z]/.test(s))return`Key${s.toUpperCase()}`;if(/[0-9]/.test(s))return`Digit${s}`}return null}function vg(n){const s=Di(n);return s?`key:${s}`:null}function Vj(n){const s=Hj(n);return s?`code:${s}`:null}function Q0(n){const s=new Set,l=vg(n?.key??"");l&&s.add(l);const o=n?.code?`code:${n.code}`:null;return o&&s.add(o),Array.from(s)}function $j(n={}){return Object.fromEntries(Object.entries(n).map(([s,l])=>{const o=Array.isArray(l)?l:[l],f=new Set;return o.forEach(d=>{const h=vg(String(d));h&&f.add(h);const p=Vj(String(d));p&&f.add(p)}),[s,f]}))}function An(n){const s=Di(n);return s?s===" "?"Space":s==="\\"?"Backslash":s==="`"?"Backtick":s==="["?"[ or {":s==="]"?"] or }":s===";"?"; or :":s==="'"?`' or "`:s===","?", or <":s==="."?". or >":s==="/"?"/ or ?":s==="-"?"- or _":s==="="?"= or +":s==="arrowup"?"Arrow Up":s==="arrowdown"?"Arrow Down":s==="arrowleft"?"Arrow Left":s==="arrowright"?"Arrow Right":s.length===1?s.toUpperCase():s:"—"}const qn={keyboard:{baseSpeed:250,turboSpeed:400,precisionSpeed:125,tiltSpeed:100,tiltIntervalMs:110}},ia={label:"Default",calibration:{driveDeadzone:.18,cameraDeadzone:.08,auxDeadzone:.05,driveCurve:"linear",cameraCurve:"linear",auxCurve:"linear",cameraMode:"absolute",cameraSensitivity:60,auxSideScale:.55},bindings:{drive:{kind:"axisPair",sources:[{kind:"axisPair",x:0,y:1,invertX:!1,invertY:!0}]},cameraTilt:{kind:"axis",sources:[{kind:"axis",index:3,invert:!0},{kind:"axis",index:1,invert:!0}]},mainBrush:{kind:"axis",sources:[{kind:"buttonAxis",index:6},{kind:"axis",index:2,invert:!1}]},sideBrush:{kind:"axis",sources:[{kind:"buttonAxis",index:7},{kind:"axis",index:5,invert:!1}]},vacuum:{kind:"button",sources:[{kind:"button",index:0}]},allAux:{kind:"button",sources:[{kind:"button",index:1}]},mainReverse:{kind:"button",sources:[{kind:"button",index:4}]},sideReverse:{kind:"button",sources:[{kind:"button",index:5}]},driveMacro:{kind:"button",sources:[{kind:"button",index:2}]},dockMacro:{kind:"button",sources:[{kind:"button",index:3}]},nightVisionToggle:{kind:"button",sources:[{kind:"button",index:9}]}}},Ba={activeSignature:null,profiles:{},defaults:{profile:ia}},us={waveform:"saw",freqs:[440,550,660,0]},ct={masterVolume:1,alertVolume:.5,roverVolume:1,mainBrushDuckEnabled:!0,mainBrushDuckAmount:.75},os=[{key:"drive",motors:["leftWheel","rightWheel"]},{key:"aux",motors:["mainBrush","sideBrush"]}],Gj={downRatePerSec:.15,upRatePerSec:.7,releaseDelaySec:1,outputRateMs:250};function K0(){return os.reduce((n,s)=>(n[s.key]={cap:1,clearSec:0},n),{})}function Z0(n){return Number.isFinite(n)?Math.max(0,Math.min(1,n)):0}function Yj(n,s={}){const l=ft(j=>j.session),d=(ml(n)?.sensors||{})?.wheelOvercurrents||{},h=m.useMemo(()=>({...Gj,...s.config||{}}),[s.config]),[p,x]=m.useState(()=>K0()),g=m.useRef(0),v=m.useRef(d);m.useEffect(()=>{v.current=d||{}},[d]),m.useEffect(()=>{x(K0()),g.current=0},[n]);const y=m.useMemo(()=>os.some(j=>j.motors.some(N=>!!d?.[N])),[d]),S=m.useMemo(()=>Object.values(p||{}).some(j=>(Number.isFinite(j?.cap)?j.cap:1)<.999),[p]),E=!!n&&(y||S);m.useEffect(()=>{if(!E)return;g.current=typeof performance<"u"?performance.now():Date.now();const j=setInterval(()=>{const N=typeof performance<"u"?performance.now():Date.now(),T=Math.max(0,N-g.current);g.current=N;const M=Math.min(.25,T/1e3);M<=0||x(O=>{let K=!1;const _={},U=Number.isFinite(h.downRatePerSec)?Math.max(0,h.downRatePerSec):0,X=Number.isFinite(h.upRatePerSec)?Math.max(0,h.upRatePerSec):0,F=Number.isFinite(h.releaseDelaySec)?Math.max(0,h.releaseDelaySec):0;return os.forEach(H=>{const te=O[H.key]||{cap:1,clearSec:0},ce=Number.isFinite(te.cap)?te.cap:1,oe=Number.isFinite(te.clearSec)?te.clearSec:0,V=H.motors.some(le=>!!v.current?.[le]),q=V?0:oe+M,L=!V&&q>=F,Z=Z0(V?ce-U*M:L?ce+X*M:ce);(Math.abs(Z-ce)>1e-4||Math.abs(q-oe)>1e-4)&&(K=!0),_[H.key]={cap:Z,clearSec:q}}),K?_:O})},100);return()=>clearInterval(j)},[h.downRatePerSec,h.releaseDelaySec,h.upRatePerSec,n,E]);const C=m.useMemo(()=>{const j=os.reduce((N,T)=>{const M=p?.[T.key],O=Number.isFinite(M?.cap)?M.cap:1;return N[T.key]=Z0(O),N},{});return{perGroup:j,drive:{left:j.drive??1,right:j.drive??1},aux:{main:j.aux??1,side:j.aux??1,vacuum:1}}},[p]),k=m.useMemo(()=>{const j={};os.forEach(T=>{T.motors.forEach(M=>{j[M]=!!d?.[M]})});const N=os.reduce((T,M)=>(T[M.key]=M.motors.some(O=>!!d?.[O]),T),{});return{motors:j,groups:N}},[d]),w=l?.role==="admin"||l?.role==="lockdown"||l?.role==="lockdown-admin";return m.useMemo(()=>({caps:p,overcurrent:k,scales:C,isActive:(C?.drive?.left??1)<1||(C?.drive?.right??1)<1||(C?.aux?.main??1)<1||(C?.aux?.side??1)<1,config:h,adminImmune:w}),[p,k,C,h,w])}function Fj(n={},s,l=!1){if(l||!s?.drive)return n;const o=typeof s.drive.left=="number"?s.drive.left:1,f=typeof s.drive.right=="number"?s.drive.right:1;return o>=.999&&f>=.999?n:{left:Math.round((n.left??0)*o),right:Math.round((n.right??0)*f)}}function Xj(n={},s,l=!1){if(l||!s?.aux)return n;const o=typeof s.aux.main=="number"?s.aux.main:1,f=typeof s.aux.side=="number"?s.aux.side:1,d=typeof s.aux.vacuum=="number"?s.aux.vacuum:1;return o>=.999&&f>=.999&&d>=.999?n:{main:Math.round((n.main??0)*o),side:Math.round((n.side??0)*f),vacuum:Math.round((n.vacuum??0)*d)}}const bg=m.createContext(null);function I0(n){return Object.fromEntries(Object.entries(n||{}).map(([s,l])=>[s,Array.isArray(l)?[...l]:[]]))}function Qj(n,s){if(!n)return s;const l=typeof n.minAngle=="number"?n.minAngle:-45,o=typeof n.maxAngle=="number"?n.maxAngle:45;return rl(s,l,o)}function Kj(n=[]){if(!Array.isArray(n)||n.length<3)return n;const s=n.slice(-3),[l,o,f]=s,d=l?.type==="drive"&&Number(l?.speeds?.left)===-300&&Number(l?.speeds?.right)===-300,h=o?.type==="pause"&&Number(o?.duration)===600,p=f?.type==="drive"&&Number(f?.speeds?.left)===0&&Number(f?.speeds?.right)===0;return!d||!h||!p?n:n.slice(0,-3)}function Zj({children:n}){const[s,l]=m.useReducer(_j,Y0),o=m.useRef(null),f=m.useRef(!1),d=m.useRef(Y0.camera.angle),h=m.useRef(null),p=m.useRef(0),x=m.useRef(0),{value:g,save:v}=He("controls",{keymap:gi,macros:gg}),{value:y}=He("page",{driveMacroBackoffEnabled:!0}),{value:S}=He("horn",us),E=typeof y?.driveMacroBackoffEnabled=="boolean"?y.driveMacroBackoffEnabled:!0,C=ft(ie=>ie.session),{homeAssistantSetState:k}=wn(),w=C?.assignment?.roverId??null,j=Yj(w),N=m.useCallback(ie=>Fj(ie,j.scales,j.adminImmune),[j.adminImmune,j.scales]),T=m.useCallback(ie=>Xj(ie,j.scales,j.adminImmune),[j.adminImmune,j.scales]),M=zj({driveTransform:N,auxTransform:T}),O=m.useCallback(()=>{const me=(C?.homeAssistant?.entities||[]).filter(se=>(se.type==="light"||se.type==="switch")&&se.available!==!1&&se.state!=="on");if(me.length===0){f.current=!1;return}f.current=!0,me.forEach(se=>{k(se.id,"on").catch(()=>{})}),f.current=!1},[C?.homeAssistant?.entities,k]);m.useEffect(()=>{l({type:"control/set-rover",payload:M.roverId})},[M.roverId]),m.useEffect(()=>{const ie=o.current;o.current=s.mode,ie!=="drive"&&s.mode==="drive"&&C?.homeAssistant?.entities?O():ie!=="drive"&&s.mode==="drive"&&(f.current=!0)},[s.mode,C?.homeAssistant?.entities,O]),m.useEffect(()=>{f.current&&C?.homeAssistant?.entities&&O()},[C?.homeAssistant?.entities,O]),m.useEffect(()=>{const ie={...gi,...g?.keymap||{}};l({type:"control/set-keymap",payload:ie}),g?.macros&&l({type:"control/set-macros",payload:g.macros})},[g?.keymap,g?.macros]),m.useEffect(()=>{const ie=M.servoConfig;if(!ie){l({type:"control/set-camera-config",payload:{config:null}}),d.current=null;return}const me=typeof ie.minAngle=="number"?ie.minAngle:-45,se=typeof ie.maxAngle=="number"?ie.maxAngle:45,P=typeof ie.homeAngle=="number"?ie.homeAngle:(me+se)/2,de=typeof d.current=="number"?rl(d.current,me,se):null,Ne=de??rl(P,me,se);l({type:"control/set-camera-config",payload:{config:ie,angle:Ne}}),d.current=Ne},[M.servoConfig]),m.useEffect(()=>{d.current=typeof s.camera.angle=="number"?s.camera.angle:d.current},[s.camera.angle]),m.useEffect(()=>{M.roverId&&M.enableSensorStream()},[M.roverId,M.enableSensorStream]);const K=m.useCallback(ie=>{l({type:"control/set-mode",payload:ie})},[]),_=m.useCallback(()=>{l({type:"control/record-intent"})},[]),U=m.useRef(s.drive.speeds),X=m.useRef(s.aux),F=m.useMemo(()=>JSON.stringify(j.scales),[j.scales]),H=m.useRef(0),te=m.useRef(0);m.useEffect(()=>{U.current=s.drive.speeds},[s.drive.speeds]),m.useEffect(()=>{X.current=s.aux},[s.aux]),m.useEffect(()=>{if(!M.roverId||j.adminImmune||!j.isActive)return;const ie=Math.max(0,Number(j?.config?.outputRateMs)||0),me=typeof performance<"u"?performance.now():Date.now(),se=U.current||{left:0,right:0},P=X.current||{main:0,side:0,vacuum:0},de=!!(se.left||se.right),Ne=!!(P.main||P.side||P.vacuum);!de&&!Ne||(de&&me-H.current>=ie&&(H.current=me,M.sendDriveDirect(se)),Ne&&me-te.current>=ie&&(te.current=me,M.sendAuxMotors(P)))},[F,j.adminImmune,j.config,j.isActive,M]);const ce=m.useCallback((ie,me={})=>{const se=Oj(ie,me.speedOptions);l({type:"control/update-drive",payload:{...se,source:me.source??null}}),_(),M.sendDriveDirect(se.speeds)},[M,_]),oe=m.useCallback((ie={})=>{const me=M.sendAuxMotors(ie)??ie;l({type:"control/set-aux-motors",payload:me}),_()},[M,_]),V=m.useCallback((ie,me)=>{if(!ie)return!1;const se=Di(me);if(!se)return!1;const P=I0(s.keymap);return P[ie]=[se],l({type:"control/set-keymap",payload:P}),v(de=>({...de??{},keymap:P})),!0},[s.keymap,v]),q=m.useCallback(()=>{const ie=I0(gi);l({type:"control/set-keymap",payload:ie}),v(me=>({...me??{},keymap:ie}))},[v]),L=m.useCallback(ie=>{if(!M.servoConfig)return;const me=Qj(M.servoConfig,ie);l({type:"control/set-camera-angle",payload:me}),M.sendServoAngle(me),d.current=me,_()},[M,_]),Z=m.useCallback((ie=0)=>{const me=M.servoConfig;if(!me)return;const se=typeof ie=="number"&&ie!==0?ie:me.nudgeDegrees||1,P=typeof d.current=="number"?d.current:typeof me.homeAngle=="number"?me.homeAngle:0;L(P+se)},[M.servoConfig,L]),le=m.useCallback(()=>{const ie=M.servoConfig;if(!ie)return;const me=typeof ie.homeAngle=="number"?ie.homeAngle:typeof ie.minAngle=="number"&&typeof ie.maxAngle=="number"?(ie.minAngle+ie.maxAngle)/2:0;L(me)},[M.servoConfig,L]),fe=m.useCallback(async ie=>{const me=s.macros.find(P=>P.id===ie)||null;if(!me)return;let se=me;ie==="drive-sequence"?(O(),C?.homeAssistant?.entities||(f.current=!0),_(),E||(se={...me,steps:Kj(me.steps)})):ie==="seek-dock"&&_(),await M.runMacroSteps(se)},[E,M,_,C?.homeAssistant?.entities,s.macros,O]),R=m.useCallback(()=>{l({type:"control/update-drive",payload:{vector:{x:0,y:0,boost:!1},speeds:{left:0,right:0},source:"system-stop"}}),M.sendDriveDirect({left:0,right:0}),M.sendAuxMotors({main:0,side:0,vacuum:0})},[M]),$=m.useCallback(ie=>{M.sendOiCommand(ie)},[M]),ee=m.useCallback(ie=>{M.roverId&&M.emitCommand({type:"sensorStream",data:{sensorStream:{enable:ie}}})},[M]),ae=m.useCallback(ie=>{if(M.nightVision){if(typeof ie=="boolean"){const me=ie?"off":"on";M.sendNightVision(me)}else M.sendNightVision("toggle");_()}},[M,_]),pe=m.useCallback(()=>{ae()},[ae]),re=m.useCallback(ie=>{const me=typeof ie=="number"?ie:il;return l({type:"control/set-song-note",payload:me}),me},[]),ue=m.useCallback((ie,me)=>M.sendSong(ie,me),[M]),ve=m.useMemo(()=>{const ie=S??us,me=ie.waveform==="sine"?"sine":"saw",P=[...Array.isArray(ie.freqs)?ie.freqs:us.freqs,0,0,0,0].slice(0,4).map(de=>{const Ne=Number(de);return Number.isFinite(Ne)?Ne<=0?0:Math.min(5e3,Math.round(Ne)):0});return{waveform:me,freqs:P}},[S]),be=m.useCallback(()=>{if(!M.horn)return;if(s.horn?.overheated||(s.horn?.heat??0)>=1||s.horn?.active)return!1;const ie=Date.now();return M.sendHorn({action:"start",...ve}),l({type:"control/set-horn-active",payload:!0}),p.current=ie,x.current=ie,h.current&&(clearTimeout(h.current),h.current=null),h.current=setTimeout(()=>{xe()},qj),_(),!0},[l,ve,M,_,s.horn?.active,s.horn?.heat,s.horn?.overheated]),xe=m.useCallback(()=>{if(!M.horn)return;M.sendHorn({action:"stop"}),l({type:"control/set-horn-active",payload:!1}),h.current&&(clearTimeout(h.current),h.current=null);const ie=Date.now(),me=p.current||ie,se=Math.max(0,ie-me);if(p.current=0,se>0){const P=s.horn?.heat??0,de=se/1e3*Zr;let Ne=Math.max(0,Math.min(1,P+de)),pt=s.horn?.overheated??!1;Ne>=1&&(Ne=1,pt=!0),l({type:"control/set-horn-heat",payload:{heat:Ne,overheated:pt}})}},[l,M,s.horn?.heat,s.horn?.overheated,Zr]),Be=m.useRef({active:!!s.horn?.active,heat:s.horn?.heat??0,overheated:!!s.horn?.overheated}),ze=m.useRef(xe);m.useEffect(()=>{Be.current={active:!!s.horn?.active,heat:s.horn?.heat??0,overheated:!!s.horn?.overheated}},[s.horn?.active,s.horn?.heat,s.horn?.overheated]),m.useEffect(()=>{ze.current=xe},[xe]);const Ae=!!s.horn?.active||(s.horn?.heat??0)>0||!!s.horn?.overheated;m.useEffect(()=>{if(!Ae)return;const me=setInterval(()=>{const se=Date.now(),P=x.current||se;x.current=se;const de=Math.min(1e3,Math.max(0,se-P))/1e3,Ne=Be.current,pt=Ne.heat??0,Ve=!!Ne.active,st=!!Ne.overheated,lt=de*(Ve?Zr:-$0);let Ot=Math.max(0,Math.min(1,pt+lt)),it=st;Ot>=1?(Ot=1,it=!0,Ve&&ze.current()):it&&Ot<=G0&&(it=!1),(Ot!==pt||it!==st)&&l({type:"control/set-horn-heat",payload:{heat:Ot,overheated:it}})},100);return()=>clearInterval(me)},[l,Ae,$0,G0,Zr]);const tt=m.useCallback((ie,me)=>{l({type:"control/register-input-state",payload:{source:ie,state:me}})},[]),Je=m.useCallback(ie=>{l({type:"control/set-mic-ptt",payload:!!ie})},[]),vt=m.useMemo(()=>({state:s,dispatch:l,pipeline:M,overcurrentLimiter:j,actions:{setMode:K,setDriveVector:ce,setAuxMotors:oe,setServoAngle:L,nudgeServo:Z,goServoHome:le,runMacro:fe,stopAllMotion:R,sendOiCommand:$,setSensorStream:ee,setNightVision:ae,toggleNightVision:pe,updateKeyBinding:V,resetKeyBindings:q,registerInputState:tt,setSongNote:re,sendSong:ue,startHorn:be,stopHorn:xe,setMicPttActive:Je}}),[s,M,j,K,ce,oe,L,Z,le,fe,R,$,ee,ae,pe,V,q,tt,re,ue,be,xe,Je]);return r.jsx(bg.Provider,{value:vt,children:n})}function _t(){const n=m.useContext(bg);if(!n)throw new Error("useControlSystem must be used within ControlSystemProvider");return n}const Ij="data:audio/mpeg;base64,//uQxAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAANAAAIpQBKSkpKSkpKXFxcXFxcXFxra2tra2tra3p6enp6enqJiYmJiYmJiZiYmJiYmJiYpqampqamprW1tbW1tbW1xMTExMTExMTT09PT09PT4uLi4uLi4uLx8fHx8fHx8f////////8AAABQTEFNRTMuMTAwBLkAAAAAAAAAABUgJAUYQQAB4AAACKVpqtMZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//ugxAAAwqQPR8CIwCh0BCj5jDwlIAAjW87wAACcOsAKPMk8ARj8w9OAWwNlV/gCgQMHEhAOVnFaNzWWAPI2zyjHjd8FAoKqyAa88AAAAABNjEd9CQOglIY9dtC+a51bGZrZgTewD3c+AAYx5hxIMheIcudKAyaykG1/h5EsPB0iTEFNRTMuMTAwqqqqqqrIBZqvAAAAAC9JXFIAHrCgAp0D0hUYOInIluqg1TNdKCzMeAAFQCKKsxUmVfireKILLBgSVgb4qBVtPWpMQU1FMy4xMDCqqqqqqqqqqqqqqqqpApm/AAAAAC7QYaHPHoCjkCysmc+QY9NNWRbKE+mqowNobwAAoSQQMLGChDlOrKMqVMC/6xy/CXbFaL7AZUxBTUUzLjEwMFVVVVVVVVVVVacDqZ8AAAAAMgzaYFBPNgIOnVCQfFfwmBBhLVNJQSdxdQRofwAGxF9xAAYs4AZDuE87li0YCASIBwaCiXUj+2BqTEFNRTMuMTAwqqqqqqqqlwOonwAAAAAtkABQSEZ1INNDgx8HeaaLCXiu5dqSciylQNXjv8GdmACQ5ogYKbnsmxkoChog+w9IhU6GsgzCIQBSxFpMQQAAMBiHjgAAAAv6FQQILmJmGLltnax9HszIVEAoEq1p8olpcPLlGpXFastuWosKNFlmlqADJbwAEFRI4iJJy0oDumUW//sgxOEAw5wfU8fnAGBvg6n5nDxUh7QuwcEzkK5Ztz7AZUxBTUUzLjEwMFVVVVVVVZUAhd8AAAAALZAAamQMWKtC7Avib0WLplt2IAp0SKV0pFFxCADLX6AIPFrWJIBQqPGW/x0QDTRLGaQYCRAZzKeoU6uqTEFN6AB3n/7wAAAxq//7EMT0AMPUHU/MawJgc4PpuYy8VQZjocBw2OgQQyQyECnbABEUC/ZoM0J56Jm0tqzNJaq8KospqUAQ5/QBghnCqQAhR4Mz1D1gJPstYsI1sYIg079I5cYjY6pMQU1FMy4xMDCqqqqq//sQxPUAw+AdT8zvAih6hCk5nWBFqqqWAFOf4AAAAEAIQZPkMcwUzFVE51cSBjIHpJRIEIjWgGar9VhgCUvwAFAUMk0RCpMkwXjPQDcoLBU+n5RuR4ZrPQLPckxBTUUzLjEwMKqqqqr/+xDE9oDEAB1NzG8CKIGEKPmd5EWqxgBWn9AAAAAKIiC5GcLJIczCEvNbWsF31jo4Bw0rXktvJF5YRyABlj+ABIQ2RGsHgdc0XsPntoEDUzaQOjTBqblFPUE1TEFNRckAt68AAAAALv/7EMT4AMQIHU3M7wIojwUo+Y2MZfAgKcwITAQIYN1TosJeLtDA0ubWNrFSADJoln4AC0hVaLiIIUChs+4HST4BgCpQHITPMBQkEnj73ORZfylh+sRLEGUiNIpMQU1FMy4xMDCqqqqq//sQxP6AxlgtK+13Yih3hCj5neBNqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrIkT7UNAZ7NS7yMqcihSKLMn8DlKYq8ZdPCVEoJBuWqkxBTUUzLjEwMKqqqqr/+xDE+ADEXCVHzGjDIIQEqLm9PIWqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7EMT+AMWoL0XNcwJoiASoeY3gVaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sQxPgAxHAnRcxvAmiBBKj5jehEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+xDE+IDEmCVDzPMCKH6EqLmNYE2qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7EMT9gEPgI0vMZwQgvYWlPY5gFaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sQxOYDw+gpIIfgwWgAADSAAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=",yg=m.createContext({messages:[],typing:[],sendMessage:async()=>{},focusChat:()=>{},blurChat:()=>{},registerInputRef:()=>{},onInputFocus:()=>{},onInputBlur:()=>{},setTypingActive:()=>{},isChatFocused:!1});function Jj({children:n}){const s=tn(),l=ft(V=>V.session),{pushAlert:o}=wn(),{value:f}=He("audio",ct),[d,h]=m.useState([]),[p,x]=m.useState([]),[g,v]=m.useState(!1),y=m.useRef(null),S=m.useRef(null),E=m.useRef(null),C=m.useRef(new Map),k=m.useRef(new Map),w=m.useRef({isTyping:!1,lastSent:0}),j=Number.isFinite(f?.masterVolume)?f.masterVolume:ct.masterVolume,N=Number.isFinite(f?.alertVolume)?f.alertVolume:ct.alertVolume,T=Math.max(0,Math.min(1,j*N)),M=m.useCallback(()=>{const V=Array.from(C.current.values()).sort((q,L)=>q.lastUpdate-L.lastUpdate).map(q=>q.payload);x(V)},[]),O=m.useCallback(V=>!V||typeof V!="object"?null:V.typingId?V.typingId:V.fromDiscord?`discord:${V.discordUserId||V.discordUserName||V.nickname||"unknown"}`:`socket:${V.socketId||V.nickname||"unknown"}`,[]);m.useEffect(()=>{E.current=new Audio(Ij),E.current.volume=T,E.current.load()},[T]);const K=m.useCallback(()=>{const V=E.current;V&&(V.volume=T,V.currentTime=0,V.play().catch(()=>{}))},[T]);m.useEffect(()=>{function V(q={}){h(L=>[...L.slice(-99),q]),!(q?.socketId&&l?.socketId&&q.socketId===l.socketId)&&(K(),o?.({kind:"chat",payload:q,id:`chat-${q.id||Math.random().toString(36).slice(2)}`,receivedAt:Date.now()}))}return s.on("chat:message",V),()=>{s.off("chat:message",V)}},[K,l?.socketId,s]),m.useEffect(()=>{function V(q={}){const L=O(q);if(!L)return;const Z=Date.now();if(q?.socketId&&l?.socketId&&q.socketId===l.socketId){q.isTyping||(C.current.delete(L),M());return}if(q.isTyping){C.current.set(L,{payload:q,expiresAt:Z+6e3,lastUpdate:Z});const le=k.current.get(L)||0;Z-le>=2500&&(k.current.set(L,Z),o?.({kind:"chat-typing",payload:q,id:`chat-typing-${L}-${q.id||Math.random().toString(36).slice(2)}`,receivedAt:Z}))}else C.current.delete(L);M()}return s.on("chat:typing",V),()=>{s.off("chat:typing",V)}},[o,M,O,l?.socketId,s]),m.useEffect(()=>{const V=setInterval(()=>{const q=Date.now();let L=!1;C.current.forEach((Z,le)=>{Z.expiresAt<=q&&(C.current.delete(le),L=!0)}),L&&M()},2e3);return()=>clearInterval(V)},[M]),m.useEffect(()=>{function V(q=[]){Array.isArray(q)&&h(L=>{if(L.length===0)return q.slice(-100);const Z=new Set(q.map(fe=>fe?.id));return[...q,...L.filter(fe=>fe?.id&&!Z.has(fe.id))].slice(-100)})}return s.on("chat:init",V),()=>{s.off("chat:init",V)}},[s]);const _=m.useCallback(V=>{const q=!!V,L=Date.now(),Z=w.current,le=!q&&Z.isTyping;!(q&&(!Z.isTyping||L-Z.lastSent>=3500))&&!le||(w.current={isTyping:q,lastSent:L},s.emit("chat:typing",{isTyping:q}))},[s]),U=m.useCallback((V,q=null)=>new Promise((L,Z)=>{s.emit("chat:send",{text:V,tts:q},(le={})=>{le.error?Z(new Error(le.error)):L(le)})}),[s]),X=m.useCallback((V,q={})=>{(q?.target==="hud"?"hud":"panel")==="hud"?S.current=V:y.current=V},[]),F=m.useCallback(()=>{v(!0),(S.current||y.current)?.focus()},[]),H=m.useCallback(()=>{v(!1),S.current?.blur(),y.current?.blur()},[]),te=m.useCallback(()=>v(!0),[]),ce=m.useCallback(()=>v(!1),[]),oe=m.useMemo(()=>({messages:d,sendMessage:U,focusChat:F,blurChat:H,registerInputRef:X,onInputFocus:te,onInputBlur:ce,setTypingActive:_,typing:p,isChatFocused:g,selfSocketId:l?.socketId||null}),[H,F,g,d,ce,te,X,U,l?.socketId,_,p]);return r.jsx(yg.Provider,{value:oe,children:n})}function od(){const n=m.useContext(yg);if(!n)throw new Error("useChat must be used inside ChatProvider");return n}let Sg=!1;function lf(n){Sg=!!n}function J0(){return Sg}const Pj=new Set(["","text","search","email","password","url","tel","number","date","datetime-local","month","time","week"]);function jg(n){if(!n||n.nodeType!==1)return!1;const s=n.tagName;if(s==="TEXTAREA"||n.isContentEditable)return!0;if(s!=="INPUT")return!1;const l=n.type?n.type.toLowerCase():"";return Pj.has(l)}function Wj(){return typeof document>"u"?!1:jg(document.activeElement)}const rf="keyboard",of={x:0,y:0,boost:!1},cf={main:0,side:0,vacuum:0},P0=rd[0],W0=rd[1],cd=5,Si=500,ji=1,ud=100;function uf(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(0,Math.min(500,l)):s}function eA(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(cd,Math.min(Si,l)):s}function Ag(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(ji,Math.min(ud,l)):s}function tA(n){const l=(Ag(n,n)-ji)/(ud-ji),o=Si-l*(Si-cd);return Math.round(o)}function nA(n){const s=eA(n,n),l=(Si-s)/(Si-cd),o=ji+l*(ud-ji);return Math.round(o)}function aA(n){return jg(n?.target)}function ht(n,s){if(!n||n.size===0)return!1;for(const l of s)if(n.has(l))return!0;return!1}function sA(n,s){const l=ht(s.driveForward,n),o=ht(s.driveBackward,n),f=ht(s.driveLeft,n),d=ht(s.driveRight,n),h=ht(s.boostModifier,n),p=ht(s.slowModifier,n);let x=0;l&&!o?x=1:o&&!l&&(x=-1);let g=0;f&&!d?g=-1:d&&!f&&(g=1);const v=p?.4:1;return{x:g*v,y:x*v,boost:h&&!p}}function lA(n,s){if(ht(s.auxAllForward,n))return{main:127,side:127,vacuum:127};const o=ht(s.auxMainForward,n)?127:ht(s.auxMainReverse,n)?-127:0,f=ht(s.auxSideForward,n)?127:ht(s.auxSideReverse,n)?-70:0,d=ht(s.auxVacuumFast,n)?127:ht(s.auxVacuumSlow,n)?50:0;return{main:o,side:f,vacuum:d}}function iA(){const{state:n,actions:{setMode:s,setDriveVector:l,setAuxMotors:o,nudgeServo:f,runMacro:d,stopAllMotion:h,registerInputState:p,toggleNightVision:x,startHorn:g,stopHorn:v,setMicPttActive:y,setSongNote:S,sendSong:E}}=_t(),C=ft(re=>re.session),{homeAssistantSetState:k}=wn(),{focusChat:w,blurChat:j,isChatFocused:N}=od(),{value:T}=He("inputs",qn),M=m.useMemo(()=>$j(n.keymap),[n.keymap]),O=m.useMemo(()=>{const re=new Set;return Object.values(M).forEach(ue=>{ue&&ue.forEach(ve=>re.add(ve))}),re},[M]),K=m.useMemo(()=>{const re=qn.keyboard,ue=T?.keyboard??{};return{baseSpeed:uf(ue.baseSpeed,re.baseSpeed),turboSpeed:uf(ue.turboSpeed,re.turboSpeed),precisionSpeed:uf(ue.precisionSpeed,re.precisionSpeed)}},[T?.keyboard]),_=m.useMemo(()=>{const re=qn.keyboard,ue=T?.keyboard??{},ve=Ag(typeof ue.tiltSpeed=="number"?ue.tiltSpeed:typeof ue.tiltIntervalMs=="number"?nA(ue.tiltIntervalMs):re.tiltSpeed,re.tiltSpeed);return tA(ve)},[T?.keyboard]),U=m.useMemo(()=>Math.abs(n.camera?.config?.nudgeDegrees||1),[n.camera?.config?.nudgeDegrees]),X=m.useRef(new Set),F=m.useRef(of),H=m.useRef(cf),te=m.useRef(null),ce=m.useRef(null),oe=m.useRef(!1),V=m.useCallback(()=>{const re=new Set(X.current);ht(M.boostModifier,re);const ve=ht(M.slowModifier,re)?{baseSpeed:K.precisionSpeed,boostSpeed:K.precisionSpeed}:{baseSpeed:K.baseSpeed,boostSpeed:K.turboSpeed},be=sA(re,M),xe=lA(re,M);(be.x!==F.current.x||be.y!==F.current.y||be.boost!==F.current.boost)&&(F.current=be,l(be,{source:rf,speedOptions:ve})),(xe.main!==H.current.main||xe.side!==H.current.side||xe.vacuum!==H.current.vacuum)&&(H.current=xe,o(xe)),p(rf,{keys:Array.from(re),vector:be,aux:xe})},[M,K,p,o,l]),q=m.useCallback(()=>{te.current&&(clearTimeout(te.current),te.current=null)},[]),L=m.useCallback(()=>{const re=new Set(X.current),ue=ht(M.cameraUp,re),ve=ht(M.cameraDown,re);return(ue?1:0)-(ve?1:0)},[M]),Z=m.useCallback(()=>{if(L()===0){q();return}if(te.current)return;const ue=()=>{const ve=L();if(ve===0){q();return}f(ve*U),te.current=setTimeout(ue,_)};te.current=setTimeout(ue,0)},[L,f,_,U,q]),le=m.useCallback(()=>{ce.current&&(clearTimeout(ce.current),ce.current=null)},[]),fe=m.useCallback(()=>{const re=new Set(X.current),ue=ht(M.songNoteUp,re),ve=ht(M.songNoteDown,re);return(ue?1:0)-(ve?1:0)},[M]),R=m.useCallback(re=>{if(re===0)return;let ve=(typeof n.song?.note=="number"?n.song.note:il)+re;ve>W0?ve=P0:ve{if(fe()===0){le();return}if(ce.current)return;const ue=()=>{const ve=fe();if(ve===0){le();return}R(ve),ce.current=setTimeout(ue,Rj)};ce.current=setTimeout(ue,0)},[fe,le,R]),ee=m.useCallback(()=>{X.current.clear(),F.current=of,H.current=cf,q(),le(),oe.current&&(oe.current=!1,v()),y(!1),h(),p(rf,{keys:[],vector:of,aux:cf})},[p,y,h,v,q,le]),ae=m.useCallback(re=>{const ue=C?.homeAssistant;if(!ue?.enabled||!ue?.connected||ue?.lightPolicy?.locked||ue?.lightPolicy?.lockedOn)return;const be=(ue.entities||[]).filter(xe=>(xe.type==="light"||xe.type==="switch")&&xe.available!==!1&&xe.state!=="unavailable");if(be.length!==0){if(re==="on"){const xe=be.find(Be=>Be.state!=="on");xe&&k(xe.id,"on").catch(()=>{});return}if(re==="off")for(let xe=be.length-1;xe>=0;xe-=1){const Be=be[xe];if(Be.state==="on"){k(Be.id,"off").catch(()=>{});break}}}},[k,C?.homeAssistant]);m.useEffect(()=>{function re(be){if(J0()||aA(be))return;const xe=Q0(be);if(xe.length===0)return;const Be=new Set(xe);if(ht(M.chatFocus,Be)){be.preventDefault(),ee(),N||w();return}xe.some(Ae=>O.has(Ae))&&be.preventDefault();const ze=xe.filter(Ae=>!X.current.has(Ae));if(ze.forEach(Ae=>X.current.add(Ae)),ze.length>0)if(ze.some(Ae=>M.driveMacro?.has(Ae)))s("drive"),d("drive-sequence");else if(ze.some(Ae=>M.dockMacro?.has(Ae)))s("dock"),d("seek-dock");else if(ze.some(Ae=>M.nightVisionToggle?.has(Ae)))x();else if(ze.some(Ae=>M.hornHonk?.has(Ae))){if(!oe.current){const Ae=g();oe.current=!!Ae}}else ze.some(Ae=>M.micPtt?.has(Ae))?y(!0):ze.some(Ae=>M.homeAssistantOn?.has(Ae))?ae("on"):ze.some(Ae=>M.homeAssistantOff?.has(Ae))&&ae("off");Z(),$(),V()}function ue(be){if(J0())return;Q0(be).forEach(Be=>X.current.delete(Be)),oe.current&&!ht(M.hornHonk,X.current)&&(oe.current=!1,v()),ht(M.micPtt,X.current)||y(!1),Z(),$(),V()}function ve(){ee()}return window.addEventListener("keydown",re,{capture:!0}),window.addEventListener("keyup",ue,{capture:!0}),window.addEventListener("blur",ve),()=>{window.removeEventListener("keydown",re,{capture:!0}),window.removeEventListener("keyup",ue,{capture:!0}),window.removeEventListener("blur",ve)}},[O,j,V,Z,$,w,N,M.chatFocus,M.dockMacro,M.driveMacro,M.hornHonk,M.micPtt,ee,d,y,s,h,le,g,v,ae]);const pe=m.useRef(ee);return m.useEffect(()=>{pe.current=ee},[ee]),m.useEffect(()=>{pe.current()},[n.roverId]),m.useEffect(()=>{oe.current=!!n.horn?.active},[n.horn?.active]),m.useEffect(()=>()=>{q(),le()},[q,le]),null}const rA=1.6;function Ng(n){if(!n)return"unknown::none::0::0";const s=n.id||"unknown",l=n.mapping||"none",o=Array.isArray(n.axes)?n.axes.length:0,f=Array.isArray(n.buttons)?n.buttons.length:0;return`${s}::${l}::${o}::${f}`}function oA(n){return JSON.parse(JSON.stringify(n??{}))}function wg(n,s){const l=oA(s);return l.meta={id:n?.id??"Unknown",mapping:n?.mapping??"none",axes:n?.axes?.length??0,buttons:n?.buttons?.length??0},l}function cs(n){return Number.isFinite(n)?Math.max(-1,Math.min(1,n)):0}function di(n,s){if(!n)return 0;const l=Math.abs(n);return s==="expo"?Math.sign(n)*Math.pow(l,rA):n}function ff(n,s){const l=Math.abs(n);if(l<=s)return 0;const o=(l-s)/(1-s);return Math.sign(n)*o}function cA(n,s,l){const o=Math.hypot(n,s);if(o<=l)return{x:0,y:0};const d=(o-l)/(1-l)/o;return{x:n*d,y:s*d}}function xo(n,s){if(!n||!Array.isArray(n.axes))return null;const l=n.axes[s];return Number.isFinite(l)?cs(l):null}function Of(n,s){if(!n||!Array.isArray(n.buttons))return null;const l=n.buttons[s];if(!l)return null;const o=typeof l.value=="number"?l.value:l.pressed?1:0;return{pressed:!!(l.pressed||o>.5),value:Math.max(0,Math.min(1,o))}}function df(n,s=[]){for(const l of s)if(l){if(l.kind==="axis"){const o=xo(n,l.index);if(o===null)continue;return{value:l.invert?-o:o,source:l}}if(l.kind==="buttonAxis"){const o=Of(n,l.index);if(!o)continue;return{value:cs(o.value),source:l}}}return{value:0,source:null}}function uA(n,s=[]){for(const l of s){if(!l||l.kind!=="axisPair")continue;const o=xo(n,l.x),f=xo(n,l.y);if(o===null||f===null)continue;const d=l.invertX?-o:o,h=l.invertY?-f:f;return{x:d,y:h,source:l}}return{x:0,y:0,source:null}}function as(n,s=[]){for(const l of s)if(l){if(l.kind==="button"){const o=Of(n,l.index);if(!o)continue;return{pressed:o.pressed,source:l}}if(l.kind==="axisButton"){const o=xo(n,l.index);if(o===null)continue;const f=l.direction||1,d=typeof l.threshold=="number"?l.threshold:.6;return{pressed:o*f>d,source:l}}if(l.kind==="buttonAxis"){const o=Of(n,l.index);if(!o)continue;return{pressed:o.value>.5,source:l}}}return{pressed:!1,source:null}}function Cg(n,s){const l=s?.bindings??{},o=s?.calibration??{},f=l.drive??{},d=uA(n,f.sources);let h=cs(d.x),p=cs(d.y);const x=Math.min(Math.max(o.driveDeadzone??.18,0),.8),g=cA(h,p,x);h=di(g.x,o.driveCurve),p=di(g.y,o.driveCurve);const v=l.cameraTilt??{},y=df(n,v.sources),S=Math.min(Math.max(o.cameraDeadzone??.08,0),.8);let E=ff(cs(y.value),S);E=di(E,o.cameraCurve);const C=Math.min(Math.max(o.auxDeadzone??.05,0),.6),k=l.mainBrush??{},w=df(n,k.sources);let j=ff(cs(w.value),C);j=di(j,o.auxCurve);const N=l.sideBrush??{},T=df(n,N.sources);let M=ff(cs(T.value),C);M=di(M,o.auxCurve);const O=as(n,l.vacuum?.sources),K=as(n,l.allAux?.sources),_=as(n,l.mainReverse?.sources),U=as(n,l.sideReverse?.sources),X=as(n,l.driveMacro?.sources),F=as(n,l.dockMacro?.sources),H=as(n,l.nightVisionToggle?.sources);return{driveVector:{x:h,y:p,boost:!1},cameraAxis:E,auxAxis:{main:j,side:M},buttons:{vacuum:O.pressed,allAux:K.pressed,mainReverse:_.pressed,sideReverse:U.pressed,driveMacro:X.pressed,dockMacro:F.pressed,nightVisionToggle:H.pressed},sources:{drive:d.source,cameraTilt:y.source,mainBrush:w.source,sideBrush:T.source,vacuum:O.source,allAux:K.source,mainReverse:_.source,sideReverse:U.source,driveMacro:X.source,dockMacro:F.source,nightVisionToggle:H.source}}}const xi=new Set;let ll=null,cl={pads:[],timestamp:0},Ir=!1,Jr=null;function ex(){return Eg().some(n=>n?.connected!==!1)}function Eg(){if(typeof navigator>"u"||!navigator.getGamepads)return[];const n=navigator.getGamepads();return n?Array.from(n).filter(Boolean):[]}function fA(n){return{index:n.index,id:n.id,mapping:n.mapping,connected:n.connected!==!1,timestamp:n.timestamp,axes:Array.from(n.axes??[]),buttons:(n.buttons??[]).map(s=>({pressed:!!s?.pressed,value:typeof s?.value=="number"?s.value:s?.pressed?1:0})),signature:Ng(n)}}function go(){cl={pads:Eg().map(fA),timestamp:typeof performance<"u"?performance.now():Date.now()},xi.forEach(s=>s(cl))}function kg(){if(go(),cl.pads.length===0){Lf();return}ll=requestAnimationFrame(kg)}function tx(){ll||(go(),cl.pads.length!==0&&(ll=requestAnimationFrame(kg)))}function Lf(){ll&&(cancelAnimationFrame(ll),ll=null)}function Mg(n){if(xi.add(n),!Ir&&typeof window<"u"){const s=()=>{go(),xi.size!==0&&(ex()?tx():Lf())};window.addEventListener("gamepadconnected",s),window.addEventListener("gamepaddisconnected",s),Jr=s,Ir=!0}return ex()?tx():go(),n(cl),()=>{xi.delete(n),xi.size===0&&(Lf(),Ir&&typeof window<"u"&&(window.removeEventListener("gamepadconnected",Jr),window.removeEventListener("gamepaddisconnected",Jr),Jr=null,Ir=!1))}}function dA(){const[n,s]=m.useState(cl);return m.useEffect(()=>Mg(s),[]),n}const nl="gamepad",ss={x:0,y:0,boost:!1},ls={main:0,side:0,vacuum:0},mA=100,hA=100;function mf(n,s){return n&&s&&n.x===s.x&&n.y===s.y&&n.boost===s.boost}function hf(n,s){return n&&s&&n.main===s.main&&n.side===s.side&&n.vacuum===s.vacuum}function pA(n){return n?Math.hypot(n.x||0,n.y||0):0}function xA(n){return n?!n.main&&!n.side&&!n.vacuum:!0}function gA(n,s){if(!n||n.length===0)return null;if(s){const l=n.find(o=>o.signature===s);if(l)return l}return n[0]}function vA(){const{state:n,actions:{setMode:s,setDriveVector:l,setAuxMotors:o,setServoAngle:f,runMacro:d,toggleNightVision:h,registerInputState:p}}=_t(),{value:x,save:g}=He("gamepad",Ba),v=m.useRef(new Set),y=m.useRef(ss),S=m.useRef(ls),E=m.useRef({main:!1,side:!1}),C=m.useRef(new Map),k=m.useRef(0),w=m.useRef(0),j=m.useRef(0),N=m.useRef(null),T=m.useCallback(_=>{const U=_.signature??Ng(_);x?.profiles?.[U]||v.current.has(U)||(v.current.add(U),g(X=>{const F=X??Ba;if(F.profiles?.[U])return F;const H=F?.defaults?.profile??ia,te=wg(_,H);return{...F,profiles:{...F.profiles??{},[U]:te}}}))},[x?.profiles,g]),M=m.useCallback((_,U)=>{const X=C.current.get(_)||!1;return C.current.set(_,U),U&&!X},[]),O=m.useCallback((_,U)=>{const X=n.camera?.config;if(!X)return;const F=typeof performance<"u"?performance.now():Date.now(),H=U?.cameraMode??"absolute",te=Math.max(1,Math.min(180,U?.cameraSensitivity??60));if(H==="velocity"){const L=Math.min(50,F-j.current||16),Z=_*te*(L/1e3);if(Math.abs(Z)<.01)return;const fe=(typeof N.current=="number"?N.current:typeof n.camera?.angle=="number"?n.camera.angle:typeof X.homeAngle=="number"?X.homeAngle:0)+Z;f(fe),N.current=fe,j.current=F;return}const ce=typeof X.minAngle=="number"?X.minAngle:-45,oe=typeof X.maxAngle=="number"?X.maxAngle:45,V=typeof X.homeAngle=="number"?X.homeAngle:(ce+oe)/2,q=_<0?V+_*(V-ce):V+_*(oe-V);typeof N.current=="number"&&Math.abs(N.current-q)<.35&&F-j.current<80||(j.current=F,N.current=q,f(q))},[f,n.camera?.angle,n.camera?.config]),K=m.useMemo(()=>x?.activeSignature??null,[x?.activeSignature]);return m.useEffect(()=>Mg(_=>{const U=gA(_.pads,K);if(!U){mf(y.current,ss)||(y.current=ss,l(ss,{source:nl})),hf(S.current,ls)||(S.current=ls,o(ls)),C.current=new Map,E.current={main:!1,side:!1},k.current=0,w.current=0,p(nl,{connected:!1});return}if(Wj()){mf(y.current,ss)||(y.current=ss,l(ss,{source:nl})),hf(S.current,ls)||(S.current=ls,o(ls)),C.current=new Map,E.current={main:!1,side:!1},p(nl,{connected:!0,blocked:!0});return}T(U);const X=U.signature,F=x?.profiles?.[X]??x?.defaults?.profile??ia,H=Cg(U,F);if(!mf(H.driveVector,y.current)){const Z=typeof performance<"u"?performance.now():Date.now();(pA(H.driveVector)<.02||Z-k.current>=mA)&&(y.current=H.driveVector,k.current=Z,l(H.driveVector,{source:nl}))}const te=F.calibration?.auxSideScale??.55,ce=Math.round(Math.min(Math.abs(H.auxAxis.main),1)*127),oe=Math.round(Math.min(Math.abs(H.auxAxis.side),1)*127),V=E.current.main?-ce:ce,q=E.current.side?-Math.round(oe*te):Math.round(oe*te);let L={main:H.auxAxis.main!==0?V:0,side:H.auxAxis.side!==0?q:0,vacuum:H.buttons.vacuum?127:0};if(H.buttons.allAux&&(L={main:127,side:127,vacuum:127}),!hf(L,S.current)){const Z=typeof performance<"u"?performance.now():Date.now();(xA(L)||Z-w.current>=hA)&&(S.current=L,w.current=Z,o(L))}H.buttons.mainReverse&&M("mainReverse",!0)?E.current.main=!E.current.main:H.buttons.mainReverse||M("mainReverse",!1),H.buttons.sideReverse&&M("sideReverse",!0)?E.current.side=!E.current.side:H.buttons.sideReverse||M("sideReverse",!1),H.buttons.driveMacro&&M("driveMacro",!0)?(s("drive"),d("drive-sequence")):H.buttons.driveMacro||M("driveMacro",!1),H.buttons.dockMacro&&M("dockMacro",!0)?(s("dock"),d("seek-dock")):H.buttons.dockMacro||M("dockMacro",!1),H.buttons.nightVisionToggle&&M("nightVisionToggle",!0)?h():H.buttons.nightVisionToggle||M("nightVisionToggle",!1),Math.abs(H.cameraAxis)>.001&&O(H.cameraAxis,F.calibration),p(nl,{connected:!0,signature:X,id:U.id,index:U.index,axes:U.axes,buttons:U.buttons,drive:H.driveVector,aux:L,cameraAxis:H.cameraAxis,bindings:H.sources})}),[K,T,x?.defaults?.profile,x?.profiles,M,O,p,d,o,l,s,h]),null}function Rg(n){const s=n?.sensors||{},l=s.oiMode?.label||"Unknown",o=l.toLowerCase(),f=s.chargingState?.label||"",d=!!s.chargingSources?.homeBase,h=d&&f.toLowerCase()!=="not charging"&&f!=="";return{driving:o==="full",docked:d,charging:h,dockedNotCharging:d&&!h,dockingInProgress:!d&&!h&&o==="passive",oiLabel:l,chargingLabel:f}}function qg(n){const s=ml(n);return m.useMemo(()=>Rg(s),[s])}function al({label:n,value:s,tone:l="neutral"}){const o=l==="good"?"border-emerald-200 bg-emerald-600 text-white":l==="warn"?"border-amber-200 bg-amber-600 text-white":l==="bad"?"border-red-200 bg-red-600 text-white":"border-slate-200/30 bg-slate-700 text-slate-100";return r.jsx("div",{className:`flex flex-1 flex-col items-center justify-center rounded-lg border px-0.75 py-0.5 text-center ${o}`,children:r.jsx("span",{className:"text-base font-semibold md:text-lg",children:s})})}function nx({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function pf({label:n,tone:s}){const l=s==="emerald"?"border-emerald-200/70 bg-emerald-600/70 text-emerald-50":s==="amber"?"border-amber-200/70 bg-amber-600/70 text-amber-50":"border-indigo-200/70 bg-indigo-600/70 text-indigo-50";return r.jsx("span",{className:`rounded-full border px-0.5 py-0.15 text-[0.7rem] font-semibold ${l}`,children:n})}function bA({instructions:n,onConfirm:s,onCancel:l,pending:o}){return r.jsx("div",{className:"fixed inset-0 z-40 flex items-center justify-center bg-black/70 p-1",children:r.jsxs("div",{className:"surface w-full max-w-md space-y-0.5 border border-indigo-700 bg-indigo-950/90 p-1 text-slate-100 shadow-2xl",children:[r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-lg font-semibold text-indigo-50",children:"Dock Rover"}),r.jsx("p",{className:"text-sm text-slate-200",children:n.summary}),r.jsx(zf,{steps:n.steps,tone:"indigo"})]}),r.jsxs("div",{className:"grid grid-cols-2 gap-0.5 text-sm",children:[r.jsx("button",{type:"button",onClick:l,className:"bg-slate-700 px-0.5 py-1 font-semibold text-slate-100 transition hover:bg-slate-600",children:"Cancel"}),r.jsx("button",{type:"button",disabled:o,onClick:s,className:"bg-indigo-600 px-0.5 py-1 font-semibold text-indigo-50 transition hover:bg-indigo-500 disabled:opacity-50",children:o?"Docking…":"Confirm Dock"})]})]})})}function Tg({layout:n="desktop",expand:s=!1,fill:l=!1,driveDockState:o,compactHeightClass:f=""}){const d=n==="mobile",{state:{roverId:h,keymap:p},actions:x}=_t(),g=ml(h),v=o??Rg(g),{driving:y,docked:S,charging:E,dockingInProgress:C}=v,[k,w]=m.useState(null),[j,N]=m.useState(!1),[T,M]=m.useState(!1),O=!h||k!==null,K=!h||k!==null,_=An(p?.driveMacro?.[0]),U=An(p?.dockMacro?.[0]),X={summary:"You are about to trigger an automatic docking attempt! To have a successful dock:",steps:["Line up the rover straight in front of the dock","Make sure the rover is about one foot or half a meter away from the dock","Press Confirm Dock to begin the docking process"]},F="Click this button to initate auto-dock.",H={summary:"You must enable driving mode before you can move the rover.",steps:["Press the keybind or tap this button to enable driving mode","Once ready (should be instant), this dialog will change, and you will be able to move"]},te=S?"Docked":"Undocked",ce=S?"good":"bad",oe=E?"Charging":S?"Charging in 5s":"—",V=E?"good":S?"warn":"bad",q=async()=>{if(!(!h||k)){w("drive");try{x.setMode("drive"),await x.runMacro("drive-sequence")}catch(Je){alert(Je.message)}finally{w(null)}}},L=async()=>{if(!(!h||k)){N(!1),M(!1),w("drive");try{x.setMode("drive"),await x.runMacro("drive-sequence")}catch(Je){alert(Je.message)}finally{w(null)}}},Z=async()=>{if(!(!h||k)){w("dock");try{x.setMode("dock"),await x.runMacro("seek-dock")}catch(Je){alert(Je.message)}finally{w(null),N(!1),M(!1)}}},le=()=>{K||(M(!0),N(!0))},fe="flex w-full flex-col gap-0.5 overflow-hidden rounded-xl border-2 px-0.75 py-0.75 text-slate-100 shadow-md transition hover:-translate-y-0.5 hover:shadow-xl focus-visible:outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-60 select-none no-touch-select",R="text-center",$="items-center justify-between",ee="items-center justify-center",ae=d?"text-sm font-semibold":"",pe="border-emerald-300/70 bg-emerald-800 text-emerald-50 hover:bg-emerald-700 focus-visible:ring-emerald-300",re="border-amber-300/70 bg-amber-900 text-amber-50 hover:bg-amber-800 focus-visible:ring-amber-300",ue="border-indigo-300/70 bg-indigo-900 text-indigo-50 hover:bg-indigo-800 focus-visible:ring-indigo-300",ve="border-amber-300/70 bg-amber-900 text-amber-50 hover:bg-amber-800 focus-visible:ring-amber-300",xe=s||C,Be=xe?"h-full flex-1":l?"flex-1":"",ze=d&&!xe?f:"",Ae=d&&!xe?ee:$,tt=d&&!xe&&y&&S;if(!y&&!C)return r.jsxs("button",{type:"button",onClick:L,onContextMenu:Je=>Je.preventDefault(),disabled:O,className:`${fe} ${Be} ${ze} ${R} ${Ae} ${ae} ${pe}`,children:[r.jsxs("div",{className:"space-y-0.5 w-full",children:[r.jsxs("div",{className:"flex w-full flex-col items-center gap-0.25",children:[r.jsx("span",{className:"text-base font-semibold text-emerald-50 md:text-lg",children:"Start Driving"}),!d&&xe?r.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-0.5",children:[_?r.jsx(nx,{label:_}):null,r.jsx(pf,{label:"Click to start",tone:"emerald"})]}):null]}),xe?r.jsxs(r.Fragment,{children:[r.jsx("p",{className:"text-sm text-emerald-50/90",children:H.summary}),r.jsx(zf,{steps:H.steps,tone:"emerald"})]}):null]}),xe?r.jsxs("div",{className:"flex w-full flex-1 flex-col gap-0.5 self-stretch",children:[r.jsx(al,{label:"Dock",value:te,tone:ce}),r.jsx(al,{label:"Charge",value:oe,tone:V})]}):null]});if(C){const Je={summary:"If the rover is failing to dock, click to drive and try again.",steps:["The rover should be slowly wiggling towards the dock","If it is obviously not working, press this button to enter driving mode and try again"]};return r.jsxs("button",{type:"button",disabled:O,onClick:q,onContextMenu:vt=>vt.preventDefault(),className:`${fe} ${Be} ${ze} ${R} ${Ae} ${ae} ${re}`,children:[r.jsxs("div",{className:"space-y-0.5 w-full",children:[r.jsxs("div",{className:"flex w-full flex-col items-center gap-0.25",children:[r.jsx("span",{className:"text-base font-semibold text-amber-50 md:text-lg",children:"Docking in Progress"}),xe?r.jsx("div",{className:"flex flex-wrap items-center justify-center gap-0.5",children:r.jsx(pf,{label:"Return to driving mode",tone:"emerald"})}):null]}),xe?r.jsx("p",{className:"text-sm text-amber-50/90",children:Je.summary}):null]}),xe?r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"flex w-full flex-1 flex-col gap-0.5 self-stretch",children:[r.jsx(al,{label:"Dock",value:te,tone:ce}),r.jsx(al,{label:"Charge",value:oe,tone:V})]}),d?null:r.jsx(zf,{steps:Je.steps,tone:"amber"})]}):null]})}return r.jsxs(r.Fragment,{children:[r.jsxs("button",{type:"button",disabled:K,onClick:le,onContextMenu:Je=>Je.preventDefault(),className:d?`flex w-full ${fe} ${ze} ${R} ${Ae} ${ae} ${tt?ve:ue}`:`${fe} ${Be} ${R} ${$} ${ae} ${ue}`,children:[r.jsxs("div",{className:"flex w-full flex-col items-center gap-0.25",children:[r.jsx("span",{className:"text-base font-semibold text-indigo-50 md:text-lg",children:tt?"Docked!":"Dock and Charge"}),!d&&xe?r.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-0.5",children:[U?r.jsx(nx,{label:U}):null,r.jsx(pf,{label:"Click to begin docking",tone:"indigo"})]}):null]}),!d&&xe&&r.jsxs(r.Fragment,{children:[r.jsx("p",{className:"text-sm text-indigo-50/90",children:F}),r.jsxs("div",{className:"flex w-full flex-1 flex-col gap-0.5 self-stretch",children:[r.jsx(al,{label:"Dock",value:te,tone:ce}),r.jsx(al,{label:"Charge",value:oe,tone:V})]}),r.jsx("div",{className:"text-xs text-indigo-100/80",children:"Line up straight, about 1 foot away, before docking."})]})]}),T||!d&&j?r.jsx(bA,{instructions:X,pending:k==="dock",onCancel:()=>{M(!1),N(!1)},onConfirm:Z}):null]})}function zf({steps:n,tone:s="emerald"}){const l=s==="emerald"?"bg-emerald-900/60 text-emerald-50/90 border-emerald-700/60":s==="amber"?"bg-amber-900/60 text-amber-50/90 border-amber-700/60":"bg-indigo-900/60 text-indigo-50/90 border-indigo-700/60",o=s==="emerald"?"text-emerald-200":s==="amber"?"text-amber-200":"text-indigo-200";return r.jsx("div",{className:`space-y-0.5 rounded border px-0.5 py-0.35 text-left ${l}`,children:n.map((f,d)=>r.jsxs("div",{className:"text-[0.85rem] leading-snug break-words",children:[r.jsxs("div",{className:"flex items-start",children:[r.jsxs("span",{className:`mr-0 align-top text-[0.75rem] font-semibold ${o}`,children:[d+1,"."]}),r.jsx("span",{className:"align-top",children:f})]}),d{xf(n)&&p(n)},[n]);const x=xf(h),g=x?h:!1,v=x?g?"On":"Off":"—",y=g?"bg-emerald-500 text-emerald-950":"bg-slate-700 text-slate-200",S=()=>{if(s)return;const C=x?!g:!0;p(C),l?.(C)},E=m.useMemo(()=>["group flex w-full flex-col items-center justify-center gap-0.35 rounded-xl border-2 px-1 py-0.75 text-center select-none no-touch-select",g?"border-emerald-300/70 bg-emerald-800 text-emerald-50 hover:bg-emerald-700":"border-amber-300/70 bg-amber-900 text-amber-50 hover:bg-amber-800","disabled:opacity-50",d,f].filter(Boolean).join(" "),[f,g,d]);return r.jsxs("button",{type:"button",onClick:S,onContextMenu:C=>C.preventDefault(),disabled:s,"aria-pressed":g,className:E,children:[r.jsxs("span",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-sm font-semibold",children:"Night Vision"}),o?r.jsx("span",{className:"rounded bg-slate-800 px-1 py-0.5 text-[0.6rem] font-semibold text-slate-200",children:o}):null]}),r.jsx("span",{className:`rounded px-1 py-0.5 text-[0.7rem] font-semibold ${y}`,children:v})]})}function gf(n){const s=Number(n);return!Number.isFinite(s)||s<=0?0:Math.min(5e3,Math.round(s))}function _g({disabled:n,onStart:s,onStop:l,keyLabel:o,active:f,heat:d=0,className:h="",defaultShowSettings:p=!0,showSettingsToggle:x=!1,compactSettings:g=!1}){const[v,y]=m.useState(!1),[S,E]=m.useState(p),{value:C,save:k}=He("horn",us),[w,j]=m.useState(C?.waveform||us.waveform),[N,T]=m.useState(()=>[...Array.isArray(C?.freqs)?C.freqs:us.freqs,0,0,0,0].slice(0,4).map(q=>gf(q)));m.useEffect(()=>{j(C?.waveform||us.waveform),Array.isArray(C?.freqs)&&T([...C.freqs,0,0,0,0].slice(0,4).map(V=>gf(V)))},[C?.freqs,C?.waveform]);const M=!!f,O=Math.max(0,Math.min(1,Number(d)||0)),K=m.useMemo(()=>["group relative flex w-full flex-col gap-0.5 overflow-hidden rounded-xl border-2 px-1 py-1.5 text-xs font-semibold select-none no-touch-select",M?"border-fuchsia-300/70 bg-fuchsia-700 text-fuchsia-50":"border-cyan-300/70 bg-cyan-900 text-cyan-50 hover:bg-cyan-800","disabled:opacity-50",h].filter(Boolean).join(" "),[h,M]),_=()=>{n||v||(y(!0),s?.())},U=()=>{v&&(y(!1),l?.())};m.useEffect(()=>{!M&&v&&y(!1)},[M,v]);const X=w==="sine"?"sine":"saw",F=m.useCallback(V=>{const q=V.target.value==="sine"?"sine":"saw";j(q),k(L=>({...L??{},waveform:q}))},[k]),H=m.useCallback((V,q)=>{T(L=>{const Z=[...L];return Z[V]=gf(q),k(le=>({...le??{},freqs:Z})),Z})},[k]),te=V=>{if(n)return;const q=V.target?.tagName?.toLowerCase();q==="input"||q==="select"||q==="option"||q==="label"||q==="button"||(V.preventDefault(),_())},ce=V=>{const q=V.target?.tagName?.toLowerCase();q==="input"||q==="select"||q==="option"||q==="label"||q==="button"||(V.preventDefault(),U())},oe=x?r.jsx("button",{type:"button",onClick:V=>{V.preventDefault(),E(q=>!q)},className:"rounded bg-black/40 px-1 py-0.5 text-[0.6rem] font-semibold text-white/90 hover:text-white",children:S?"Hide":"Settings"}):null;return r.jsxs("div",{role:"button",tabIndex:0,"aria-pressed":v,onPointerDown:te,onPointerUp:ce,onPointerLeave:U,onPointerCancel:U,onContextMenu:V=>V.preventDefault(),onBlur:U,className:K,children:[r.jsx("div",{className:"pointer-events-none absolute inset-0 opacity-70",style:{background:`linear-gradient(90deg, rgba(14,116,144,0.7) ${O*100}%, rgba(0,0,0,0) ${O*100}%)`}}),r.jsx("div",{className:`pointer-events-none absolute inset-0 transition-opacity ${M?"opacity-40":"opacity-0"}`,style:{background:"linear-gradient(90deg, rgba(217,70,239,0.75), rgba(244,114,182,0.35))"}}),r.jsxs("div",{className:"relative z-10 flex items-center justify-between gap-0.5",children:[r.jsxs("span",{className:"flex items-center gap-0.5 text-sm font-semibold",children:[r.jsx("span",{children:"Horn"}),o?r.jsx("span",{className:"rounded bg-black/40 px-1 py-0.5 text-[0.6rem] font-semibold text-white",children:o}):null]}),oe,r.jsx("span",{className:`rounded px-1 py-0.5 text-[0.65rem] font-semibold ${M?"bg-fuchsia-200 text-fuchsia-900":"bg-slate-800 text-slate-200"}`,children:M?"Honk":"Hold"})]}),S?g?r.jsxs("div",{className:"relative z-10 flex flex-col gap-0.5 text-[0.65rem]",children:[r.jsxs("label",{className:"flex items-center justify-between gap-0.5 text-slate-200",children:[r.jsx("span",{className:"text-slate-300",children:"Wave"}),r.jsxs("select",{value:X,onChange:F,className:"rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.65rem] text-slate-100",children:[r.jsx("option",{value:"saw",children:"Saw"}),r.jsx("option",{value:"sine",children:"Sine"})]})]}),r.jsx("div",{className:"grid grid-cols-2 gap-0.5",children:N.map((V,q)=>r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("span",{className:"text-[0.6rem] text-slate-400",children:q+1}),r.jsx("input",{type:"number",min:0,max:5e3,step:1,value:V,onChange:L=>H(q,L.target.value),className:"w-full rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-right text-[0.65rem] font-mono text-slate-100"})]},`horn-freq-${q}`))})]}):r.jsxs("div",{className:"relative z-10 grid grid-cols-[minmax(0,1.2fr)_repeat(4,minmax(0,1fr))] items-center gap-0.5 text-[0.65rem]",children:[r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("span",{className:"text-slate-300",children:"Wave"}),r.jsxs("select",{value:X,onChange:F,className:"rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.65rem] text-slate-100",children:[r.jsx("option",{value:"saw",children:"Saw"}),r.jsx("option",{value:"sine",children:"Sine"})]})]}),N.map((V,q)=>r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("span",{className:"text-[0.6rem] text-slate-400",children:q+1}),r.jsx("input",{type:"number",min:0,max:5e3,step:1,value:V,onChange:L=>H(q,L.target.value),className:"w-full rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-right text-[0.65rem] font-mono text-slate-100"})]},`horn-freq-${q}`))]}):null]})}function Pr(n){return typeof n!="number"||Number.isNaN(n)?"—":`${n>0?"+":""}${n.toFixed(1)}°`}function ax({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function Bg({value:n,min:s,max:l,step:o=.5,label:f="Camera Tilt",orientation:d="horizontal",onChange:h,onCommit:p,throttleMs:x=0,disabled:g=!1,keyDownLabel:v,keyUpLabel:y,className:S="",labelRowClass:E="",labelClass:C="",valueClass:k="",sliderClass:w="",endpointClass:j="",endpointLabelClass:N="",accentClass:T="",showValue:M=!0,showEndpoints:O}){const K=d==="vertical",U=typeof O=="boolean"?O:!K,[X,F]=m.useState(n),H=m.useRef(!1),te=m.useRef(null);m.useEffect(()=>{H.current||F(n)},[n]),m.useEffect(()=>()=>{te.current&&clearTimeout(te.current)},[]);const ce=Z=>{if(h){if(x>0){te.current&&clearTimeout(te.current),te.current=setTimeout(()=>{h(Z)},x);return}h(Z)}},oe=Z=>{const le=Number.parseFloat(Z.target.value);Number.isNaN(le)||(H.current=!0,F(le),ce(le))},V=()=>{H.current=!1,te.current&&(clearTimeout(te.current),te.current=null),p?p(X):x>0&&h?.(X)};if(typeof s!="number"||typeof l!="number")return null;const q=[K?"h-28 w-5":"w-full",T,w].filter(Boolean).join(" "),L=r.jsx("input",{type:"range",orient:K?"vertical":void 0,min:s,max:l,step:o,value:Number.isFinite(X)?X:s,onChange:oe,onMouseUp:V,onTouchEnd:V,onPointerUp:V,disabled:g,className:q,style:K?{writingMode:"bt-lr",WebkitAppearance:"slider-vertical"}:void 0});return K?r.jsxs("div",{className:`flex h-full flex-col items-center gap-0.5 ${S}`.trim(),children:[M?r.jsx("div",{className:`flex flex-col items-center ${E}`.trim(),children:r.jsx("span",{className:k,children:Pr(n)})}):null,r.jsxs("div",{className:"flex min-h-0 flex-1 items-center gap-0.5",children:[r.jsx("span",{className:C,children:f}),L]})]}):r.jsxs("div",{className:`space-y-0.5 ${S}`.trim(),children:[r.jsxs("div",{className:`flex items-center justify-between ${E}`.trim(),children:[r.jsx("span",{className:C,children:f}),M?r.jsx("span",{className:k,children:Pr(n)}):null]}),r.jsxs("div",{children:[L,U?r.jsxs("div",{className:`mt-0 flex items-center justify-between ${j}`.trim(),children:[r.jsxs("span",{className:`flex items-center gap-0.5 ${N}`.trim(),children:[v?r.jsx(ax,{label:v}):null,Pr(s)]}),r.jsxs("span",{className:`flex items-center gap-0.5 ${N}`.trim(),children:[Pr(l),y?r.jsx(ax,{label:y}):null]})]}):null]})]})}const Wr="mobile-joystick",yA=80,SA=.15,jA={main:0,side:0,vacuum:0},AA={main:127,side:127,vacuum:127},NA={main:-127,side:-127,vacuum:-127};function wA({disabled:n,layout:s,radius:l,onMove:o,onStop:f}){const d=m.useRef(null),h=m.useRef(null),p=m.useRef({x:0,y:0}),[x,g]=m.useState({active:!1,base:{x:0,y:0},knob:{x:0,y:0}}),v=m.useCallback(()=>{h.current=null,g({active:!1,base:{x:0,y:0},knob:{x:0,y:0}}),f?.()},[f]),y=m.useCallback(k=>{if(n||h.current!==null)return;k.preventDefault();const w=d.current;if(!w)return;const j=w.getBoundingClientRect(),N=k.clientX-j.left,T=k.clientY-j.top;p.current={x:N,y:T},h.current=k.pointerId,w.setPointerCapture?.(k.pointerId),g({active:!0,base:{x:N,y:T},knob:{x:0,y:0}})},[n]),S=m.useCallback(k=>{if(n||h.current!==k.pointerId)return;k.preventDefault();const w=d.current;if(!w)return;const j=w.getBoundingClientRect(),N=k.clientX-j.left,T=k.clientY-j.top,M=N-p.current.x,O=T-p.current.y,K=Math.min(Math.hypot(M,O),l),_=Math.atan2(O,M),U=Math.cos(_)*K,X=Math.sin(_)*K,F={x:ol(U/l),y:ol(-X/l),boost:!1};g(H=>({...H,knob:{x:U,y:X}})),o?.(F)},[n,o]),E=m.useCallback(k=>{if(h.current!==k.pointerId)return;k.preventDefault(),d.current?.releasePointerCapture?.(k.pointerId),v()},[v]);return m.useEffect(()=>{n&&v()},[n,v]),r.jsxs("div",{ref:d,role:"presentation",className:"relative w-full h-full select-none overflow-hidden rounded-xl border-2 border-slate-700 bg-slate-900/70 text-slate-100 shadow-md",style:{touchAction:"none"},onPointerDown:y,onPointerMove:S,onPointerUp:E,onPointerLeave:E,onPointerCancel:E,onContextMenu:k=>k.preventDefault(),children:[!x.active&&r.jsxs("div",{className:"absolute inset-x-0 top-0 flex flex-col items-center gap-0 text-center pt-0.5",children:[r.jsx("span",{className:"font-semibold text-slate-200",children:"Joystick area"}),r.jsx("span",{className:"text-sm text-slate-300",children:"Touch and hold to use the joystick"})]}),x.active&&r.jsxs(r.Fragment,{children:[r.jsx("div",{className:"pointer-events-none absolute h-28 w-28 -translate-x-1/2 -translate-y-1/2 bg-cyan-400/10 outline outline-2 outline-cyan-400/60 [clip-path:circle(50%)]",style:{left:x.base.x,top:x.base.y}}),r.jsx("div",{className:"pointer-events-none absolute h-12 w-12 -translate-x-1/2 -translate-y-1/2 bg-cyan-300/80 shadow-lg [clip-path:circle(50%)]",style:{left:x.base.x+x.knob.x,top:x.base.y+x.knob.y}})]})]})}function CA({layout:n}){const{state:{roverId:s},actions:{setDriveVector:l,registerInputState:o}}=_t(),f=qg(s),d=f.docked&&!f.driving,h=d||f.dockingInProgress,p=!s,x=yA,g=SA,v=m.useRef({x:0,y:0,boost:!1});m.useEffect(()=>{p&&(v.current={x:0,y:0,boost:!1})},[p]);const y=m.useCallback((k={})=>{if(p)return;const w={x:ol(k.x??0),y:ol(k.y??0),boost:!!k.boost},j={x:v.current.x+(w.x-v.current.x)*(1-g),y:v.current.y+(w.y-v.current.y)*(1-g),boost:w.boost};v.current=j,l(j,{source:Wr}),o(Wr,{vector:j,lastEvent:"move"})},[p,o,l,g]),S=m.useCallback(()=>{if(p)return;const k={x:0,y:0,boost:!1};v.current=k,l(k,{source:Wr}),o(Wr,{vector:k,lastEvent:"stop"})},[p,o,l]),C=`flex h-full flex-col gap-0.5 text-slate-100 ${d?"max-h-screen self-start":""}`;return r.jsxs("div",{className:C,children:[r.jsx(Tg,{layout:"mobile",expand:h,driveDockState:f,compactHeightClass:"min-h-[5rem]"}),h?null:r.jsx("div",{className:"flex-1 min-h-0",children:r.jsx(wA,{disabled:p,layout:n,radius:x,onMove:y,onStop:S})})]})}function sx({id:n,label:s,values:l,color:o,disabled:f,onPress:d,onRelease:h}){return r.jsx("button",{type:"button",disabled:f,onPointerDown:p=>{p.preventDefault(),d(n,l)},onPointerUp:()=>h(n),onPointerLeave:()=>h(n),onPointerCancel:()=>h(n),onContextMenu:p=>p.preventDefault(),className:`flex h-full w-full items-center justify-center rounded-xl border-2 px-1 py-0.75 text-center text-sm font-semibold text-white transition select-none no-touch-select ${o} hover:brightness-110 active:brightness-125 active:scale-[0.99] disabled:opacity-30`,children:s})}function EA({layout:n}){const{state:{roverId:s,camera:l,horn:o},pipeline:f,actions:{setServoAngle:d,setNightVision:h,setAuxMotors:p,startHorn:x,stopHorn:g}}=_t(),v=!s,y=m.useRef(null),S=l?.config,E=!!(s&&l?.enabled&&S),C=!!(s&&f?.nightVision),k=f?.nightVisionState,w=!!(s&&f?.horn),j=o?.overheated,N=typeof S?.minAngle=="number"?S.minAngle:-45,T=typeof S?.maxAngle=="number"?S.maxAngle:45,M=typeof l?.angle=="number"?l.angle:typeof S?.homeAngle=="number"?S.homeAngle:(N+T)/2,O=m.useCallback(U=>{C&&h(U)},[C,h]),K=m.useCallback((U,X)=>{v||(y.current=U,p(X))},[v,p]),_=m.useCallback(U=>{v||y.current===U&&(y.current=null,p(jA))},[v,p]);return r.jsxs("div",{className:"grid h-full min-h-0 w-full grid-rows-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)] gap-0.5 text-slate-100",children:[r.jsxs("div",{className:"grid min-h-0 grid-rows-2 gap-0.5",children:[r.jsx(sx,{id:"aux-vac-forward",label:"Vacuum Forward",values:AA,color:"bg-fuchsia-600",disabled:v,onPress:K,onRelease:_}),r.jsx(sx,{id:"aux-vac-backward",label:"Vacuum Backward",values:NA,color:"bg-fuchsia-800",disabled:v,onPress:K,onRelease:_})]}),r.jsxs("div",{className:"flex min-h-0 items-stretch gap-0.5",children:[E?r.jsx("div",{className:"flex-1 min-h-0 rounded bg-zinc-950 p-0.25",children:r.jsx(Bg,{value:M,min:N,max:T,step:.5,onChange:d,orientation:"vertical",label:"Camera Tilt",labelClass:"text-sm font-semibold text-white [writing-mode:vertical-rl] rotate-180",labelRowClass:"text-[0.7rem] text-slate-300",valueClass:"font-mono text-slate-200",className:"h-full gap-0",sliderClass:"h-full w-7",accentClass:"accent-cyan-400",showEndpoints:!1,showValue:!1})}):null,C?r.jsx(Dg,{nightVisionOn:k?.nightVisionOn,disabled:v,onToggle:O,heightClass:"h-full"}):null]}),r.jsx("div",{className:"min-h-0",children:w?r.jsx(_g,{disabled:v||j,onStart:x,onStop:g,active:o?.active,heat:o?.heat,defaultShowSettings:!1,showSettingsToggle:!0,compactSettings:!0,className:"h-full"}):null})]})}function vo({layout:n,className:s=""}){return r.jsx("div",{className:`flex flex-col gap-0.5 ${s}`.trim(),children:r.jsx(EA,{layout:n})})}function bo({layout:n,className:s=""}){return r.jsx("div",{className:`flex flex-col gap-0.5 ${s}`.trim(),children:r.jsx(CA,{layout:n==="landscape"?"landscape":"portrait"})})}function kA({swapColumns:n=!1}){const s="h-[min(60svh,24rem)]",l=n?r.jsx(bo,{layout:"portrait",className:s}):r.jsx(vo,{layout:"portrait",className:s}),o=n?r.jsx(vo,{layout:"portrait",className:s}):r.jsx(bo,{layout:"portrait",className:s});return r.jsx("section",{className:"panel",children:r.jsxs("div",{className:"grid grid-cols-2 gap-0.5 items-stretch",children:[l,o]})})}function MA(n=[],s={}){const l=tn(),{enabled:o=!0,version:f=null}=s,[d,h]=m.useState({}),p=m.useRef(new Map),x=m.useMemo(()=>n.map(C=>typeof C=="string"?C:C.id),[n]),g=m.useMemo(()=>{const C=x.join("|");return f?`${C}|v:${f}`:C},[x,f]),v=m.useRef([]),[y,S]=m.useState(0),E=m.useRef(new Map);return m.useEffect(()=>{if(!l)return;const C=()=>S(k=>k+1);return l.on("connect",C),()=>l.off("connect",C)},[l]),m.useEffect(()=>{v.current=x},[g,x]),m.useEffect(()=>{p.current.forEach(C=>URL.revokeObjectURL(C)),p.current.clear(),h({})},[g]),m.useEffect(()=>{if(!o){p.current.forEach(N=>URL.revokeObjectURL(N)),p.current.clear(),h({});return}if(!v.current.length||!l)return;let C=!1;const k=v.current,w=(N={},T)=>{if(C||!N.id||!T)return;const M=T.byteLength??T.length??0,O=Date.now(),K=E.current.get(N.id)||{count:0,totalBytes:0,lastLogAt:0},_={count:K.count+1,totalBytes:K.totalBytes+M,lastLogAt:K.lastLogAt};if(!_.lastLogAt||O-_.lastLogAt>=1e4){const H=_.count?_.totalBytes/_.count:0;console.log("[roomCamera]",N.id,`frame=${M}B`,`avg=${Math.round(H)}B`,`count=${_.count}`),_.lastLogAt=O}E.current.set(N.id,_);const U=new Blob([T],{type:"image/jpeg"}),X=URL.createObjectURL(U),F=p.current.get(N.id);F&&URL.revokeObjectURL(F),p.current.set(N.id,X),h(H=>({...H,[N.id]:{status:"playing",ts:N.ts||Date.now(),error:null,objectUrl:X}}))},j=(N={})=>{C||!N.id||h(T=>({...T,[N.id]:{...T[N.id]||{},status:N.error?"error":T[N.id]?.status||"connecting",error:N.error||null,ts:N.ts||T[N.id]?.ts||null,objectUrl:T[N.id]?.objectUrl||null}}))};return l.on("roomCamera:frame",w),l.on("roomCamera:status",j),l.emit("roomCamera:subscribe",{ids:k},(N={})=>{N.error}),()=>{C=!0,l.emit("roomCamera:unsubscribe",{ids:k}),l.off("roomCamera:frame",w),l.off("roomCamera:status",j),p.current.forEach(N=>URL.revokeObjectURL(N)),p.current.clear()}},[l,g,o,y]),d}function RA({feed:n,label:s}){const[l,o]=m.useState(!1);m.useEffect(()=>{n&&(!n.ts&&!n.objectUrl||o(d=>!d))},[n?.ts,n?.objectUrl]);const f=m.useMemo(()=>n?n.error?`Error: ${n.error}`:n.status||"Connecting…":"Connecting…",[n]);return r.jsxs("div",{className:"relative w-full overflow-hidden rounded bg-black",style:{aspectRatio:"4 / 3"},children:[n?.objectUrl?r.jsx("img",{src:n.objectUrl,alt:s,className:"h-full w-full object-cover"}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-300",children:"Waiting for frame…"}),r.jsx("div",{className:"pointer-events-none absolute left-0 top-0 bg-black/70 px-0.5 py-0.5 text-xs font-semibold text-white",children:s}),r.jsxs("div",{className:"pointer-events-none absolute bottom-0 left-0 m-0 flex items-center gap-0.5 rounded bg-black/70 px-0.5 py-0.25 text-[0.7rem] text-slate-100",children:[r.jsx("span",{className:`h-2 w-2 rounded-full ${l?"bg-emerald-400":"bg-slate-500"}`}),r.jsx("span",{children:f})]})]})}function qA(){return r.jsxs("div",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-center text-slate-400",children:"No room cameras configured."}),r.jsx("p",{className:"text-center text-slate-500",children:"Add entries to server config to populate this list."})]})}const Og=["horizontal","vertical"];function vf(n,s){return Og.includes(n)?n:s}function fd({defaultOrientation:n="horizontal",orientation:s,hideLayoutToggle:l=!1,hideHeader:o=!1,panelId:f=null}){const{session:d}=nn(),h=d?.roomCameras||[],p=MA(h.map(w=>({id:w.id}))),{value:x,save:g}=He("roomCameraPanels",{}),[v,y]=m.useState(()=>vf(f?x?.[f]:n,"horizontal"));m.useEffect(()=>{if(!f)return;const w=x?.[f];w&&y(vf(w,"horizontal"))},[f,x?.[f]]);const S=s?vf(s,"horizontal"):v,E=S==="vertical"?"flex flex-col gap-0.5":"grid gap-0.5 md:grid-cols-2",C=!l&&!s&&h.length>0,k=w=>{y(w),f&&g(j=>({...j||{},[f]:w}))};return h.length===0?r.jsx(qA,{}):r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[!o&&r.jsxs("header",{className:"flex flex-wrap items-center justify-between gap-0.5 text-sm text-slate-400",children:[r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("p",{children:"Room cameras"}),r.jsx("span",{className:"text-xs text-slate-500",children:h.length})]}),r.jsx("div",{className:"flex flex-wrap items-center gap-0.5 text-xs",children:C&&r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-slate-500",children:"Layout:"}),r.jsx("div",{className:"inline-flex overflow-hidden rounded border border-slate-700",children:Og.map(w=>r.jsx("button",{type:"button",className:`px-1 py-0.5 ${S===w?"bg-slate-600 text-white":"bg-transparent text-slate-400 hover:text-white"}`,onClick:()=>k(w),children:w==="vertical"?"Vertical":"Grid"},w))})]})})]}),r.jsx("div",{className:E,children:h.map(w=>{const j=p[w.id]||null;return r.jsx("article",{className:"w-full space-y-0.5 rounded bg-zinc-950 p-0.5 shadow-inner shadow-black/40",children:r.jsx(RA,{feed:j,label:w.name||w.id})},w.id)})})]})}function dd(){const n=ft(s=>s.logs);return r.jsxs("div",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"flex items-center justify-between text-sm text-slate-400",children:[r.jsx("span",{children:"Server logs"}),r.jsx("span",{children:n.length})]}),r.jsx("div",{className:"surface h-64 overflow-y-auto font-mono text-xs",children:n.length===0?r.jsx("p",{children:"No logs yet."}):n.slice().reverse().map(s=>r.jsxs("div",{className:"surface",children:[r.jsx("span",{className:"text-amber-400",children:s.timestamp})," ",r.jsxs("span",{className:"text-lime-400",children:["[",s.level,"]"]})," ",s.label&&r.jsxs("span",{className:"text-teal-400",children:["[",s.label,"]"]})," ",r.jsx("span",{children:s.message})]},s.id))})]})}function TA(n){if(!n)return null;if(typeof n=="string"){const s=String(n).trim();return s?{type:"rover",id:s,key:s}:null}if(typeof n=="object"){if(n.type&&n.id){const s=String(n.id);let l=n.key;return l||(l=n.type==="room"?`room:${s}`:s),{type:n.type,id:s,key:l}}if(n.roverId){const s=String(n.roverId);return{type:"rover",id:s,key:n.key||s}}if(n.roomCameraId){const s=String(n.roomCameraId);return{type:"room",id:s,key:n.key||`room:${s}`}}}return null}function DA(n=[]){const s=new Set,l=[];return n.forEach(o=>{!o?.key||s.has(o.key)||(s.add(o.key),l.push(o))}),l.sort((o,f)=>o.key.localeCompare(f.key))}function Ai(n=[],s={}){const l=tn(),{enabled:o=!0,version:f=null}=s,[d,h]=m.useState({}),p=m.useMemo(()=>Array.isArray(n)?DA(n.map(TA).filter(Boolean)):[],[n]),x=m.useMemo(()=>{const E=p.map(C=>`${C.type}:${C.id}:${C.key}`).join("|");return f?`${E}|v:${f}`:E},[p,f]),g=m.useRef([]),[v,y]=m.useState(0);return m.useEffect(()=>{if(!l)return;const E=()=>y(C=>C+1);return l.on("connect",E),()=>{l.off("connect",E)}},[l]),m.useEffect(()=>{g.current=p},[p]),m.useEffect(()=>{if(!x||!o){h({});return}const E=g.current;let C=!1;function k(w){const j=w.type==="room"?{roomCameraId:w.id}:{roverId:w.id};l.emit("video:request",j,(N={})=>{C||h(T=>({...T,[w.key]:N}))})}return E.forEach(w=>{k(w)}),()=>{C=!0}},[l,x,o,v]),m.useMemo(()=>{if(!x||!o)return{};const E={};return p.forEach(C=>{d[C.key]&&(E[C.key]=d[C.key])}),E},[x,d,p])}function md(n=[],s={}){const l=tn(),{enabled:o=!0,version:f=null}=s,[d,h]=m.useState({}),p=m.useRef(new Map),x=m.useMemo(()=>n.map(C=>typeof C=="string"?C:C.id).filter(Boolean),[n]),g=m.useMemo(()=>{const C=x.join("|");return f?`${C}|v:${f}`:C},[x,f]),v=m.useRef([]),[y,S]=m.useState(0),E=m.useRef(new Map);return m.useEffect(()=>{if(!l)return;const C=()=>S(k=>k+1);return l.on("connect",C),()=>l.off("connect",C)},[l]),m.useEffect(()=>{v.current=x},[g,x]),m.useEffect(()=>{p.current.forEach(C=>URL.revokeObjectURL(C)),p.current.clear(),h({})},[g]),m.useEffect(()=>{if(!o){p.current.forEach(N=>URL.revokeObjectURL(N)),p.current.clear(),h({});return}if(!v.current.length||!l)return;let C=!1;const k=v.current,w=(N={},T)=>{if(C||!N.id||!T)return;const M=T.byteLength??T.length??0,O=Date.now(),K=E.current.get(N.id)||{count:0,totalBytes:0,lastLogAt:0},_={count:K.count+1,totalBytes:K.totalBytes+M,lastLogAt:K.lastLogAt};if(!_.lastLogAt||O-_.lastLogAt>=1e4){const H=_.count?_.totalBytes/_.count:0;console.log("[roverSnapshot]",N.id,`frame=${M}B`,`avg=${Math.round(H)}B`,`count=${_.count}`),_.lastLogAt=O}E.current.set(N.id,_);const U=new Blob([T],{type:"image/jpeg"}),X=URL.createObjectURL(U),F=p.current.get(N.id);F&&URL.revokeObjectURL(F),p.current.set(N.id,X),h(H=>({...H,[N.id]:{status:"playing",ts:N.ts||Date.now(),error:null,objectUrl:X}}))},j=(N={})=>{C||!N.id||h(T=>({...T,[N.id]:{...T[N.id]||{},status:N.error?"error":T[N.id]?.status||"connecting",error:N.error||null,ts:N.ts||T[N.id]?.ts||null,objectUrl:T[N.id]?.objectUrl||null}}))};return l.on("roverSnapshot:frame",w),l.on("roverSnapshot:status",j),l.emit("roverSnapshot:subscribe",{ids:k},(N={})=>{N.error}),()=>{C=!0,l.emit("roverSnapshot:unsubscribe",{ids:k}),l.off("roverSnapshot:frame",w),l.off("roverSnapshot:status",j),p.current.forEach(N=>URL.revokeObjectURL(N)),p.current.clear()}},[l,g,o,y]),d}const _A={iceServers:[{urls:"stun:stun.l.google.com:19302"},{urls:"turn:your.turn.server:3478",username:"user",credential:"pass"}],bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"};function BA(n){if(typeof btoa=="function")return btoa(n);if(typeof Buffer<"u")return Buffer.from(n).toString("base64");throw new Error("No base64 encoder available")}function OA(n){if(!n)return{};const s=`${n}:${n}`;return{Authorization:`Basic ${BA(s)}`}}class lx{constructor({url:s,token:l,video:o,onStatus:f,audioOnly:d=!1,receiveAudio:h=!0}){this.url=s,this.token=l,this.video=o,this.audioOnly=d,this.receiveAudio=h,this.pc=null,this.abortController=null,this.onStatus=f}notify(s,l){typeof this.onStatus=="function"&&this.onStatus(s,l)}configureVideoElement(){this.video&&(this.video.playsInline=!0,this.video.autoplay=!0,this.video.muted=!this.audioOnly,typeof this.video.disableRemotePlayback<"u"&&(this.video.disableRemotePlayback=!0),"latencyHint"in HTMLMediaElement.prototype&&(this.video.latencyHint="interactive"))}async start(){if(!this.url||!this.video)throw new Error("Media target missing");this.stop(),this.notify("connecting"),this.configureVideoElement(),this.abortController=new AbortController;const s=new RTCPeerConnection(_A);this.pc=s;const l=new MediaStream;s.ontrack=o=>{o.streams[0]?.getTracks().forEach(f=>l.addTrack(f)),this.video.srcObject=l,o.track?.kind==="video"&&"playoutDelayHint"in o.receiver&&(o.receiver.playoutDelayHint=0)},this.audioOnly?s.addTransceiver("audio",{direction:"recvonly"}):(s.addTransceiver("video",{direction:"recvonly"}),this.receiveAudio&&s.addTransceiver("audio",{direction:"recvonly"})),s.onconnectionstatechange=()=>{this.notify(s.connectionState)},s.oniceconnectionstatechange=()=>{const o=s.iceConnectionState;(o==="failed"||o==="disconnected")&&this.notify(o)};try{const o=await s.createOffer({offerToReceiveAudio:this.audioOnly?!0:this.receiveAudio,offerToReceiveVideo:!this.audioOnly});await s.setLocalDescription(o);const f=await fetch(this.url,{method:"POST",headers:{"Content-Type":"application/sdp",...OA(this.token)},body:o.sdp,signal:this.abortController.signal});if(!f.ok)throw new Error(`WHEP request failed: ${f.status}`);const d=await f.text();await s.setRemoteDescription({type:"answer",sdp:d}),s.getReceivers().forEach(h=>{"playoutDelayHint"in h&&(h.playoutDelayHint=0)}),await this.video.play().catch(()=>{}),this.notify("playing")}catch(o){throw this.notify("error",o.message),this.stop(),o}}stop(){this.abortController&&(this.abortController.abort(),this.abortController=null),this.pc&&(this.pc.getSenders().forEach(s=>s.track?.stop()),this.pc.getReceivers().forEach(s=>s.track?.stop()),this.pc.close(),this.pc=null),this.video&&(this.video.srcObject=null),this.notify("stopped")}}function Uf({sensors:n={},variant:s="full",size:l,overlay:o=!1}){const f=l||(s==="mini"?190:260),d=f/2,h=f*.07,p=d,x=d+h,g=d*.8,v=g-4,y=g+4,S=g-14,E=g-6,C=g*.65,k=n?.bumpsAndWheelDrops||{},w=n?.wheelOvercurrents||{},j=n?.wheelLeftCurrentMa??0,N=n?.wheelRightCurrentMa??0,T=n?.sideBrushCurrentMa??0,M=n?.mainBrushCurrentMa??0,O=6,K=k.bumpLeft?O:0,_=k.bumpRight?O:0,U=GA({count:6,totalSpan:140,gap:6,startAngle:-70}),X=["L","FL","CL","CR","FR","R"],F=[n?.lightBumpLeftSignal,n?.lightBumpFrontLeftSignal,n?.lightBumpCenterLeftSignal,n?.lightBumpCenterRightSignal,n?.lightBumpFrontRightSignal,n?.lightBumpRightSignal],H=U.map((V,q)=>({label:X[q],start:V.start,end:V.end,value:F[q]})),te=[{label:"Cliff L",start:-60,end:-46,value:n?.cliffLeftSignal,active:n?.cliffLeft},{label:"Cliff FL",start:-32,end:-16,value:n?.cliffFrontLeftSignal,active:n?.cliffFrontLeft},{label:"Cliff FR",start:16,end:32,value:n?.cliffFrontRightSignal,active:n?.cliffFrontRight},{label:"Cliff R",start:46,end:60,value:n?.cliffRightSignal,active:n?.cliffRight}],ce=F.filter(V=>V!=null),oe=ce.length?Math.max(...ce,1200):1200;return r.jsxs("div",{className:`${o?"relative":"surface relative p-1"}`,style:o?{width:`${f}px`,height:`${f}px`}:{height:"100%",width:"100%",aspectRatio:"1 / 1"},children:[o?null:r.jsxs(r.Fragment,{children:[r.jsx("div",{className:"absolute left-1 top-1 text-xs text-slate-400",children:"Top-down"}),r.jsxs("div",{className:"absolute right-1 top-1 text-[0.65rem] text-slate-500",children:["0–",oe]})]}),r.jsxs("svg",{width:"100%",height:"100%",viewBox:`0 0 ${f} ${f}`,preserveAspectRatio:"xMidYMid meet",className:"mx-auto block",children:[r.jsx("circle",{cx:p,cy:x,r:g,fill:"#0f172a",stroke:"#334155",strokeWidth:"2"}),r.jsx(ix,{cx:p-C,cy:x,current:j,drop:k.wheelDropLeft,overcurrent:w.leftWheel,label:"L"}),r.jsx(ix,{cx:p+C,cy:x,current:N,drop:k.wheelDropRight,overcurrent:w.rightWheel,label:"R"}),r.jsx(UA,{cx:p+g*.65,cy:x-g*.55,current:T,overcurrent:w.sideBrush}),r.jsx(HA,{cx:p,cy:x,current:M,overcurrent:w.mainBrush,variant:s,dirtLeft:n?.dirtDetectLeft,dirtRight:n?.dirtDetect}),H.map(V=>{const q=VA(V.value,oe),L=y+4,Z=L+28;return r.jsx(LA,{cx:p,cy:x,rBase:Z,rTip:L,startDeg:V.start,endDeg:V.end,color:q,value:V.value,max:oe},V.label)}),te.map(V=>{const q=$A(V.value,V.active);return r.jsx(bf,{cx:p,cy:x,rInner:S,rOuter:E,startDeg:V.start,endDeg:V.end,color:q,opacity:1,pulse:!!V.active},V.label)}),r.jsx(bf,{cx:p,cy:x,rInner:v-K,rOuter:y-K,startDeg:-70,endDeg:-6,color:k.bumpLeft?"#ef4444":"#475569",opacity:1,pulse:!!k.bumpLeft}),r.jsx(bf,{cx:p,cy:x,rInner:v-_,rOuter:y-_,startDeg:6,endDeg:70,color:k.bumpRight?"#ef4444":"#475569",opacity:1,pulse:!!k.bumpRight})]})]})}function bf({cx:n,cy:s,rInner:l,rOuter:o,startDeg:f,endDeg:d,color:h,pulse:p=!1,opacity:x=1}){const g=(l+o)/2,v=o-l,y=zA(n,s,g,f,d);return r.jsxs(r.Fragment,{children:[r.jsx("path",{d:y,stroke:h,strokeWidth:v,strokeLinecap:"round",fill:"none",opacity:x}),p?r.jsx("path",{d:y,stroke:"#ef4444",strokeWidth:v,strokeLinecap:"round",fill:"none",className:"animate-pulse",opacity:1}):null]})}function LA({cx:n,cy:s,rBase:l,rTip:o,startDeg:f,endDeg:d,color:h,value:p,max:x}){const g=(f+d)/2,v=vi(n,s,o,g),y=ko(p!=null?p/(x||1):0),S=Math.pow(y,.35),E=l-(l-o)*S,C=vi(n,s,E,f),k=vi(n,s,E,d),w=`M ${v.x} ${v.y} L ${C.x} ${C.y} L ${k.x} ${k.y} Z`;return r.jsx("path",{d:w,fill:h,opacity:1,stroke:"none"})}function zA(n,s,l,o,f){let d=o,h=f;h<=d&&(h+=360);const p=vi(n,s,l,d),x=vi(n,s,l,h);return["M",p.x,p.y,"A",l,l,0,0,1,x.x,x.y].join(" ")}function vi(n,s,l,o){const f=Lg(o);return{x:n+l*Math.cos(f),y:s+l*Math.sin(f)}}function Lg(n){return(n-90)*Math.PI/180}function hd(n,s){if(s)return"#ef4444";const l=Math.abs(n);return l>900?"#f59e0b":l>300?"#22c55e":"#64748b"}function ko(n){return Math.max(0,Math.min(1,n))}function ix({cx:n,cy:s,current:l,drop:o,overcurrent:f,label:d}){const h=Math.abs(l),p=ko(h/1200),x=hd(l,f),g=56,v=14,y=9,S=3,E=g*p,C=d==="L"?-1:1,k=C*(-y/2-S/2),w=C*(v/2+S/2),j=v+y+S+2,N=g+4;return r.jsxs("g",{transform:`translate(${n},${s})`,children:[r.jsx("rect",{x:-j/2,y:-N/2,width:j,height:N,rx:"4",fill:"none",stroke:"#64748b",strokeWidth:"1"}),r.jsx("rect",{x:k-v/2,y:-g/2,width:v,height:g,fill:"#0f172a",stroke:"#0f172a",strokeWidth:"1",rx:"2"}),r.jsx("rect",{x:k-v/2,y:g/2-E,width:v,height:E,fill:x,className:f?"animate-pulse":""}),r.jsx("rect",{x:w-y/2,y:-g/2,width:y,height:g,fill:o?"#ef4444":"#475569",className:o?"animate-pulse":"",rx:"2"}),r.jsx("text",{x:0,y:g/2+10,textAnchor:"middle",className:"fill-slate-200 text-[0.7rem]",children:d})]})}function UA({cx:n,cy:s,current:l,overcurrent:o}){var f=Math.abs(l);f<10&&(f=0);const d=hd(l*3,o),h=43,p=f>0?.65:null;return r.jsxs("g",{style:{transformOrigin:`${n}px ${s}px`,animation:p?`spin ${p}s linear infinite`:"none",animationDirection:p?"reverse":"normal"},children:[r.jsx("circle",{cx:n,cy:s,r:10,fill:"#64748b",stroke:"#64748b",strokeWidth:"1"}),[0,120,240].map(g=>{const v=Lg(g),y=n+h*Math.cos(v),S=s+h*Math.sin(v);return r.jsx("line",{x1:n,y1:s,x2:y,y2:S,stroke:d,strokeWidth:"4",strokeLinecap:"round"},g)}),o?r.jsx("circle",{cx:n,cy:s,r:h+8,stroke:"#ef4444",strokeWidth:"3",fill:"none",className:"animate-pulse"}):null]})}function HA({cx:n,cy:s,current:l,overcurrent:o,variant:f,dirtLeft:d,dirtRight:h}){const p=Math.abs(l),x=hd(l,o),g=1,v=96,y=12,S=`main-brush-pattern-a-${f}`,E=`main-brush-pattern-b-${f}`,C=p>0?.6:null,k=l>=0?1:-1;return r.jsxs("g",{children:[r.jsx("defs",{children:[S,E].map((w,j)=>r.jsxs("pattern",{id:w,patternUnits:"userSpaceOnUse",width:"6",height:"6",children:[r.jsx("rect",{width:"6",height:"6",fill:x,opacity:g}),r.jsx("path",{d:"M0 6 L6 0",stroke:"#0f172a",strokeWidth:"1"}),C?r.jsx("animateTransform",{attributeName:"patternTransform",type:"translate",from:"0 0",to:`0 ${k*(j===0?6:-6)}`,dur:`${C}s`,repeatCount:"indefinite"}):null]},w))}),r.jsx("rect",{x:n-v/2,y:s-14,width:v,height:y,rx:"3",fill:`url(#${S})`,stroke:"#64748b",strokeWidth:"1"}),r.jsx("rect",{x:n-v/2,y:s+4,width:v,height:y,rx:"3",fill:`url(#${E})`,stroke:"#64748b",strokeWidth:"1"}),r.jsx("circle",{cx:n-v/4,cy:s-8,r:3.5,fill:"#fbbf24"}),r.jsx("circle",{cx:n+v/4,cy:s+8,r:3.5,fill:"#fbbf24"}),o?r.jsx("rect",{x:n-v/2-4,y:s-16,width:v+8,height:y*2+16,rx:"6",stroke:"#ef4444",strokeWidth:"3",fill:"none",className:"animate-pulse"}):null]})}function VA(n,s){if(n==null||n<=0)return"hsl(200 60% 18%)";const o=ko(n/(s||1));return`hsl(${(200+Math.pow(o,.45)*360)%360} 100% 60%)`}function $A(n,s){if(s)return"#ef4444";const l=ko(n==null?0:n/4095),o=[47,55,69],f=[245,158,11],[d,h,p]=o.map((x,g)=>Math.round(x+(f[g]-x)*l));return`rgb(${d}, ${h}, ${p})`}function GA({count:n,totalSpan:s,gap:l,startAngle:o}){const d=(s-l*(n-1))/n,h=[];let p=o;for(let x=0;x{s({hudMapDesktop:!!f})}]}const YA={discord:dg,kofi:U0,"ko-fi":U0,wiki:bj,throne:yj},FA={discord:{backgroundImage:"linear-gradient(270deg,#5865F2,#404EED,#5865F2)",backgroundSize:"600% 600%",animation:"socialGradient 180s ease infinite"},kofi:{backgroundImage:"linear-gradient(270deg,#FF6433,#E04822,#FF6433)",backgroundSize:"600% 600%",animation:"socialGradient 170s ease infinite"},"ko-fi":{backgroundImage:"linear-gradient(270deg,#FF6433,#E04822,#FF6433)",backgroundSize:"600% 600%",animation:"socialGradient 170s ease infinite"},wiki:{backgroundImage:"linear-gradient(270deg,#EE8019,#C65C08,#EE8019)",backgroundSize:"600% 600%",animation:"socialGradient 180s ease infinite"},throne:{backgroundImage:"linear-gradient(270deg,#7C3AED,#5B21B6,#7C3AED)",backgroundSize:"600% 600%",animation:"socialGradient 180s ease infinite"}};function XA(){m.useEffect(()=>{if(typeof document>"u")return;const n="social-button-keyframes";if(document.getElementById(n))return;const s=document.createElement("style");s.id=n,s.textContent=` +Please change the parent to .`)}let S=ds(),E;if(s){let N=typeof s=="string"?ul(s):s;ut(v==="/"||N.pathname?.startsWith(v),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${v}" but pathname "${N.pathname}" was given in the \`location\` prop.`),E=N}else E=S;let C=E.pathname||"/",k=C;if(v!=="/"){let N=v.replace(/^\//,"").split("/");k="/"+C.replace(/^\//,"").split("/").slice(N.length).join("/")}let w=kx(n,{pathname:k});Nn(y||w!=null,`No routes matched location "${E.pathname}${E.search}${E.hash}" `),Nn(w==null||w[w.length-1].route.element!==void 0||w[w.length-1].route.Component!==void 0||w[w.length-1].route.lazy!==void 0,`Matched leaf route at location "${E.pathname}${E.search}${E.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let j=r1(w&&w.map(N=>Object.assign({},N,{params:Object.assign({},x,N.params),pathname:ra([v,d.encodeLocation?d.encodeLocation(N.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:N.pathname]),pathnameBase:N.pathnameBase==="/"?v:ra([v,d.encodeLocation?d.encodeLocation(N.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:N.pathnameBase])})),h,l,o,f);return s&&j?m.createElement(Mi.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...E},navigationType:"POP"}},j):j}function a1(){let n=d1(),s=Zy(n)?`${n.status} ${n.statusText}`:n instanceof Error?n.message:JSON.stringify(n),l=n instanceof Error?n.stack:null,o="rgba(200,200,200, 0.5)",f={padding:"0.5rem",backgroundColor:o},d={padding:"2px 4px",backgroundColor:o},h=null;return console.error("Error handled by React Router default ErrorBoundary:",n),h=m.createElement(m.Fragment,null,m.createElement("p",null,"💿 Hey developer 👋"),m.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",m.createElement("code",{style:d},"ErrorBoundary")," or"," ",m.createElement("code",{style:d},"errorElement")," prop on your route.")),m.createElement(m.Fragment,null,m.createElement("h2",null,"Unexpected Application Error!"),m.createElement("h3",{style:{fontStyle:"italic"}},s),l?m.createElement("pre",{style:f},l):null,h)}var s1=m.createElement(a1,null),l1=class extends m.Component{constructor(n){super(n),this.state={location:n.location,revalidation:n.revalidation,error:n.error}}static getDerivedStateFromError(n){return{error:n}}static getDerivedStateFromProps(n,s){return s.location!==n.location||s.revalidation!=="idle"&&n.revalidation==="idle"?{error:n.error,location:n.location,revalidation:n.revalidation}:{error:n.error!==void 0?n.error:s.error,location:s.location,revalidation:n.revalidation||s.revalidation}}componentDidCatch(n,s){this.props.onError?this.props.onError(n,s):console.error("React Router caught the following error during render",n)}render(){return this.state.error!==void 0?m.createElement(ua.Provider,{value:this.props.routeContext},m.createElement(Gf.Provider,{value:this.state.error,children:this.props.component})):this.props.children}};function i1({routeContext:n,match:s,children:l}){let o=m.useContext(fl);return o&&o.static&&o.staticContext&&(s.route.errorElement||s.route.ErrorBoundary)&&(o.staticContext._deepestRenderedBoundaryId=s.route.id),m.createElement(ua.Provider,{value:n},l)}function r1(n,s=[],l=null,o=null,f=null){if(n==null){if(!l)return null;if(l.errors)n=l.matches;else if(s.length===0&&!l.initialized&&l.matches.length>0)n=l.matches;else return null}let d=n,h=l?.errors;if(h!=null){let v=d.findIndex(y=>y.route.id&&h?.[y.route.id]!==void 0);ut(v>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(h).join(",")}`),d=d.slice(0,Math.min(d.length,v+1))}let p=!1,x=-1;if(l)for(let v=0;v=0?d=d.slice(0,x+1):d=[d[0]];break}}}let g=l&&o?(v,y)=>{o(v,{location:l.location,params:l.matches?.[0]?.params??{},errorInfo:y})}:void 0;return d.reduceRight((v,y,S)=>{let E,C=!1,k=null,w=null;l&&(E=h&&y.route.id?h[y.route.id]:void 0,k=y.route.errorElement||s1,p&&(x<0&&S===0?(zx("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),C=!0,w=null):x===S&&(C=!0,w=y.route.hydrateFallbackElement||null)));let j=s.concat(d.slice(0,S+1)),N=()=>{let T;return E?T=k:C?T=w:y.route.Component?T=m.createElement(y.route.Component,null):y.route.element?T=y.route.element:T=v,m.createElement(i1,{match:y,routeContext:{outlet:v,matches:j,isDataRoute:l!=null},children:T})};return l&&(y.route.ErrorBoundary||y.route.errorElement||S===0)?m.createElement(l1,{location:l.location,revalidation:l.revalidation,component:k,error:E,children:N(),routeContext:{outlet:null,matches:j,isDataRoute:!0},onError:g}):N()},null)}function Yf(n){return`${n} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function o1(n){let s=m.useContext(fl);return ut(s,Yf(n)),s}function c1(n){let s=m.useContext(No);return ut(s,Yf(n)),s}function u1(n){let s=m.useContext(ua);return ut(s,Yf(n)),s}function Ff(n){let s=u1(n),l=s.matches[s.matches.length-1];return ut(l.route.id,`${n} can only be used on routes that contain a unique "id"`),l.route.id}function f1(){return Ff("useRouteId")}function d1(){let n=m.useContext(Gf),s=c1("useRouteError"),l=Ff("useRouteError");return n!==void 0?n:s.errors?.[l]}function m1(){let{router:n}=o1("useNavigate"),s=Ff("useNavigate"),l=m.useRef(!1);return Ox(()=>{l.current=!0}),m.useCallback(async(f,d={})=>{Nn(l.current,Bx),l.current&&(typeof f=="number"?n.navigate(f):await n.navigate(f,{fromRouteId:s,...d}))},[n,s])}var k0={};function zx(n,s,l){!s&&!k0[n]&&(k0[n]=!0,Nn(!1,l))}m.memo(h1);function h1({routes:n,future:s,state:l,unstable_onError:o}){return Lx(n,void 0,l,o,s)}function no(n){ut(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function p1({basename:n="/",children:s=null,location:l,navigationType:o="POP",navigator:f,static:d=!1}){ut(!Ri(),"You cannot render a inside another . You should never have more than one in your app.");let h=n.replace(/^\/*/,"/"),p=m.useMemo(()=>({basename:h,navigator:f,static:d,future:{}}),[h,f,d]);typeof l=="string"&&(l=ul(l));let{pathname:x="/",search:g="",hash:v="",state:y=null,key:S="default"}=l,E=m.useMemo(()=>{let C=oa(x,h);return C==null?null:{location:{pathname:C,search:g,hash:v,state:y,key:S},navigationType:o}},[h,x,g,v,y,S,o]);return Nn(E!=null,` is not able to match the URL "${x}${g}${v}" because it does not start with the basename, so the won't render anything.`),E==null?null:m.createElement(_n.Provider,{value:p},m.createElement(Mi.Provider,{children:s,value:E}))}function x1({children:n,location:s}){return n1(Nf(n),s)}function Nf(n,s=[]){let l=[];return m.Children.forEach(n,(o,f)=>{if(!m.isValidElement(o))return;let d=[...s,f];if(o.type===m.Fragment){l.push.apply(l,Nf(o.props.children,d));return}ut(o.type===no,`[${typeof o.type=="string"?o.type:o.type.name}] is not a component. All component children of must be a or `),ut(!o.props.index||!o.props.children,"An index route cannot have child routes.");let h={id:o.props.id||d.join("-"),caseSensitive:o.props.caseSensitive,element:o.props.element,Component:o.props.Component,index:o.props.index,path:o.props.path,middleware:o.props.middleware,loader:o.props.loader,action:o.props.action,hydrateFallbackElement:o.props.hydrateFallbackElement,HydrateFallback:o.props.HydrateFallback,errorElement:o.props.errorElement,ErrorBoundary:o.props.ErrorBoundary,hasErrorBoundary:o.props.hasErrorBoundary===!0||o.props.ErrorBoundary!=null||o.props.errorElement!=null,shouldRevalidate:o.props.shouldRevalidate,handle:o.props.handle,lazy:o.props.lazy};o.props.children&&(h.children=Nf(o.props.children,d)),l.push(h)}),l}var ao="get",so="application/x-www-form-urlencoded";function wo(n){return n!=null&&typeof n.tagName=="string"}function g1(n){return wo(n)&&n.tagName.toLowerCase()==="button"}function v1(n){return wo(n)&&n.tagName.toLowerCase()==="form"}function b1(n){return wo(n)&&n.tagName.toLowerCase()==="input"}function y1(n){return!!(n.metaKey||n.altKey||n.ctrlKey||n.shiftKey)}function S1(n,s){return n.button===0&&(!s||s==="_self")&&!y1(n)}var Xr=null;function j1(){if(Xr===null)try{new FormData(document.createElement("form"),0),Xr=!1}catch{Xr=!0}return Xr}var A1=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Wu(n){return n!=null&&!A1.has(n)?(Nn(!1,`"${n}" is not a valid \`encType\` for \`\`/\`\` and will default to "${so}"`),null):n}function N1(n,s){let l,o,f,d,h;if(v1(n)){let p=n.getAttribute("action");o=p?oa(p,s):null,l=n.getAttribute("method")||ao,f=Wu(n.getAttribute("enctype"))||so,d=new FormData(n)}else if(g1(n)||b1(n)&&(n.type==="submit"||n.type==="image")){let p=n.form;if(p==null)throw new Error('Cannot submit a or without a ');let x=n.getAttribute("formaction")||p.getAttribute("action");if(o=x?oa(x,s):null,l=n.getAttribute("formmethod")||p.getAttribute("method")||ao,f=Wu(n.getAttribute("formenctype"))||Wu(p.getAttribute("enctype"))||so,d=new FormData(p,n),!j1()){let{name:g,type:v,value:y}=n;if(v==="image"){let S=g?`${g}.`:"";d.append(`${S}x`,"0"),d.append(`${S}y`,"0")}else g&&d.append(g,y)}}else{if(wo(n))throw new Error('Cannot submit element that is not , , or ');l=ao,o=null,f=so,h=n}return d&&f==="text/plain"&&(h=d,d=void 0),{action:o,method:l.toLowerCase(),encType:f,formData:d,body:h}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");function Xf(n,s){if(n===!1||n===null||typeof n>"u")throw new Error(s)}function w1(n,s,l){let o=typeof n=="string"?new URL(n,typeof window>"u"?"server://singlefetch/":window.location.origin):n;return o.pathname==="/"?o.pathname=`_root.${l}`:s&&oa(o.pathname,s)==="/"?o.pathname=`${s.replace(/\/$/,"")}/_root.${l}`:o.pathname=`${o.pathname.replace(/\/$/,"")}.${l}`,o}async function C1(n,s){if(n.id in s)return s[n.id];try{let l=await import(n.module);return s[n.id]=l,l}catch(l){return console.error(`Error loading route module \`${n.module}\`, reloading page...`),console.error(l),window.__reactRouterContext&&window.__reactRouterContext.isSpaMode,window.location.reload(),new Promise(()=>{})}}function E1(n){return n==null?!1:n.href==null?n.rel==="preload"&&typeof n.imageSrcSet=="string"&&typeof n.imageSizes=="string":typeof n.rel=="string"&&typeof n.href=="string"}async function k1(n,s,l){let o=await Promise.all(n.map(async f=>{let d=s.routes[f.route.id];if(d){let h=await C1(d,l);return h.links?h.links():[]}return[]}));return T1(o.flat(1).filter(E1).filter(f=>f.rel==="stylesheet"||f.rel==="preload").map(f=>f.rel==="stylesheet"?{...f,rel:"prefetch",as:"style"}:{...f,rel:"prefetch"}))}function M0(n,s,l,o,f,d){let h=(x,g)=>l[g]?x.route.id!==l[g].route.id:!0,p=(x,g)=>l[g].pathname!==x.pathname||l[g].route.path?.endsWith("*")&&l[g].params["*"]!==x.params["*"];return d==="assets"?s.filter((x,g)=>h(x,g)||p(x,g)):d==="data"?s.filter((x,g)=>{let v=o.routes[x.route.id];if(!v||!v.hasLoader)return!1;if(h(x,g)||p(x,g))return!0;if(x.route.shouldRevalidate){let y=x.route.shouldRevalidate({currentUrl:new URL(f.pathname+f.search+f.hash,window.origin),currentParams:l[0]?.params||{},nextUrl:new URL(n,window.origin),nextParams:x.params,defaultShouldRevalidate:!0});if(typeof y=="boolean")return y}return!0}):[]}function M1(n,s,{includeHydrateFallback:l}={}){return R1(n.map(o=>{let f=s.routes[o.route.id];if(!f)return[];let d=[f.module];return f.clientActionModule&&(d=d.concat(f.clientActionModule)),f.clientLoaderModule&&(d=d.concat(f.clientLoaderModule)),l&&f.hydrateFallbackModule&&(d=d.concat(f.hydrateFallbackModule)),f.imports&&(d=d.concat(f.imports)),d}).flat(1))}function R1(n){return[...new Set(n)]}function q1(n){let s={},l=Object.keys(n).sort();for(let o of l)s[o]=n[o];return s}function T1(n,s){let l=new Set;return new Set(s),n.reduce((o,f)=>{let d=JSON.stringify(q1(f));return l.has(d)||(l.add(d),o.push({key:d,link:f})),o},[])}function Ux(){let n=m.useContext(fl);return Xf(n,"You must render this element inside a element"),n}function D1(){let n=m.useContext(No);return Xf(n,"You must render this element inside a element"),n}var Qf=m.createContext(void 0);Qf.displayName="FrameworkContext";function Hx(){let n=m.useContext(Qf);return Xf(n,"You must render this element inside a element"),n}function _1(n,s){let l=m.useContext(Qf),[o,f]=m.useState(!1),[d,h]=m.useState(!1),{onFocus:p,onBlur:x,onMouseEnter:g,onMouseLeave:v,onTouchStart:y}=s,S=m.useRef(null);m.useEffect(()=>{if(n==="render"&&h(!0),n==="viewport"){let k=j=>{j.forEach(N=>{h(N.isIntersecting)})},w=new IntersectionObserver(k,{threshold:.5});return S.current&&w.observe(S.current),()=>{w.disconnect()}}},[n]),m.useEffect(()=>{if(o){let k=setTimeout(()=>{h(!0)},100);return()=>{clearTimeout(k)}}},[o]);let E=()=>{f(!0)},C=()=>{f(!1),h(!1)};return l?n!=="intent"?[d,S,{}]:[d,S,{onFocus:oi(p,E),onBlur:oi(x,C),onMouseEnter:oi(g,E),onMouseLeave:oi(v,C),onTouchStart:oi(y,E)}]:[!1,S,{}]}function oi(n,s){return l=>{n&&n(l),l.defaultPrevented||s(l)}}function B1({page:n,...s}){let{router:l}=Ux(),o=m.useMemo(()=>kx(l.routes,n,l.basename),[l.routes,n,l.basename]);return o?m.createElement(L1,{page:n,matches:o,...s}):null}function O1(n){let{manifest:s,routeModules:l}=Hx(),[o,f]=m.useState([]);return m.useEffect(()=>{let d=!1;return k1(n,s,l).then(h=>{d||f(h)}),()=>{d=!0}},[n,s,l]),o}function L1({page:n,matches:s,...l}){let o=ds(),{manifest:f,routeModules:d}=Hx(),{basename:h}=Ux(),{loaderData:p,matches:x}=D1(),g=m.useMemo(()=>M0(n,s,x,f,o,"data"),[n,s,x,f,o]),v=m.useMemo(()=>M0(n,s,x,f,o,"assets"),[n,s,x,f,o]),y=m.useMemo(()=>{if(n===o.pathname+o.search+o.hash)return[];let C=new Set,k=!1;if(s.forEach(j=>{let N=f.routes[j.route.id];!N||!N.hasLoader||(!g.some(T=>T.route.id===j.route.id)&&j.route.id in p&&d[j.route.id]?.shouldRevalidate||N.hasClientLoader?k=!0:C.add(j.route.id))}),C.size===0)return[];let w=w1(n,h,"data");return k&&C.size>0&&w.searchParams.set("_routes",s.filter(j=>C.has(j.route.id)).map(j=>j.route.id).join(",")),[w.pathname+w.search]},[h,p,o,f,g,s,n,d]),S=m.useMemo(()=>M1(v,f),[v,f]),E=O1(v);return m.createElement(m.Fragment,null,y.map(C=>m.createElement("link",{key:C,rel:"prefetch",as:"fetch",href:C,...l})),S.map(C=>m.createElement("link",{key:C,rel:"modulepreload",href:C,...l})),E.map(({key:C,link:k})=>m.createElement("link",{key:C,nonce:l.nonce,...k})))}function z1(...n){return s=>{n.forEach(l=>{typeof l=="function"?l(s):l!=null&&(l.current=s)})}}var Vx=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";try{Vx&&(window.__reactRouterVersion="7.9.6")}catch{}function U1({basename:n,children:s,window:l}){let o=m.useRef();o.current==null&&(o.current=wy({window:l,v5Compat:!0}));let f=o.current,[d,h]=m.useState({action:f.action,location:f.location}),p=m.useCallback(x=>{m.startTransition(()=>h(x))},[h]);return m.useLayoutEffect(()=>f.listen(p),[f,p]),m.createElement(p1,{basename:n,children:s,location:d.location,navigationType:d.action,navigator:f})}var $x=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Gx=m.forwardRef(function({onClick:s,discover:l="render",prefetch:o="none",relative:f,reloadDocument:d,replace:h,state:p,target:x,to:g,preventScrollReset:v,viewTransition:y,...S},E){let{basename:C}=m.useContext(_n),k=typeof g=="string"&&$x.test(g),w,j=!1;if(typeof g=="string"&&k&&(w=g,Vx))try{let X=new URL(window.location.href),F=g.startsWith("//")?new URL(X.protocol+g):new URL(g),H=oa(F.pathname,C);F.origin===X.origin&&H!=null?g=H+F.search+F.hash:j=!0}catch{Nn(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}let N=Wy(g,{relative:f}),[T,M,O]=_1(o,S),K=G1(g,{replace:h,state:p,target:x,preventScrollReset:v,relative:f,viewTransition:y});function _(X){s&&s(X),X.defaultPrevented||K(X)}let U=m.createElement("a",{...S,...O,href:w||N,onClick:j||d?s:_,ref:z1(E,M),target:x,"data-discover":!k&&l==="render"?"true":void 0});return T&&!k?m.createElement(m.Fragment,null,U,m.createElement(B1,{page:N})):U});Gx.displayName="Link";var H1=m.forwardRef(function({"aria-current":s="page",caseSensitive:l=!1,className:o="",end:f=!1,style:d,to:h,viewTransition:p,children:x,...g},v){let y=qi(h,{relative:g.relative}),S=ds(),E=m.useContext(No),{navigator:C,basename:k}=m.useContext(_n),w=E!=null&&K1(y)&&p===!0,j=C.encodeLocation?C.encodeLocation(y).pathname:y.pathname,N=S.pathname,T=E&&E.navigation&&E.navigation.location?E.navigation.location.pathname:null;l||(N=N.toLowerCase(),T=T?T.toLowerCase():null,j=j.toLowerCase()),T&&k&&(T=oa(T,k)||T);const M=j!=="/"&&j.endsWith("/")?j.length-1:j.length;let O=N===j||!f&&N.startsWith(j)&&N.charAt(M)==="/",K=T!=null&&(T===j||!f&&T.startsWith(j)&&T.charAt(j.length)==="/"),_={isActive:O,isPending:K,isTransitioning:w},U=O?s:void 0,X;typeof o=="function"?X=o(_):X=[o,O?"active":null,K?"pending":null,w?"transitioning":null].filter(Boolean).join(" ");let F=typeof d=="function"?d(_):d;return m.createElement(Gx,{...g,"aria-current":U,className:X,ref:v,style:F,to:h,viewTransition:p},typeof x=="function"?x(_):x)});H1.displayName="NavLink";var V1=m.forwardRef(({discover:n="render",fetcherKey:s,navigate:l,reloadDocument:o,replace:f,state:d,method:h=ao,action:p,onSubmit:x,relative:g,preventScrollReset:v,viewTransition:y,...S},E)=>{let C=X1(),k=Q1(p,{relative:g}),w=h.toLowerCase()==="get"?"get":"post",j=typeof p=="string"&&$x.test(p),N=T=>{if(x&&x(T),T.defaultPrevented)return;T.preventDefault();let M=T.nativeEvent.submitter,O=M?.getAttribute("formmethod")||h;C(M||T.currentTarget,{fetcherKey:s,method:O,navigate:l,replace:f,state:d,relative:g,preventScrollReset:v,viewTransition:y})};return m.createElement("form",{ref:E,method:w,action:k,onSubmit:o?x:N,...S,"data-discover":!j&&n==="render"?"true":void 0})});V1.displayName="Form";function $1(n){return`${n} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Yx(n){let s=m.useContext(fl);return ut(s,$1(n)),s}function G1(n,{target:s,replace:l,state:o,preventScrollReset:f,relative:d,viewTransition:h}={}){let p=e1(),x=ds(),g=qi(n,{relative:d});return m.useCallback(v=>{if(S1(v,s)){v.preventDefault();let y=l!==void 0?l:yi(x)===yi(g);p(n,{replace:y,state:o,preventScrollReset:f,relative:d,viewTransition:h})}},[x,p,g,l,o,s,n,f,d,h])}var Y1=0,F1=()=>`__${String(++Y1)}__`;function X1(){let{router:n}=Yx("useSubmit"),{basename:s}=m.useContext(_n),l=f1();return m.useCallback(async(o,f={})=>{let{action:d,method:h,encType:p,formData:x,body:g}=N1(o,s);if(f.navigate===!1){let v=f.fetcherKey||F1();await n.fetch(v,l,f.action||d,{preventScrollReset:f.preventScrollReset,formData:x,body:g,formMethod:f.method||h,formEncType:f.encType||p,flushSync:f.flushSync})}else await n.navigate(f.action||d,{preventScrollReset:f.preventScrollReset,formData:x,body:g,formMethod:f.method||h,formEncType:f.encType||p,replace:f.replace,state:f.state,fromRouteId:l,flushSync:f.flushSync,viewTransition:f.viewTransition})},[n,s,l])}function Q1(n,{relative:s}={}){let{basename:l}=m.useContext(_n),o=m.useContext(ua);ut(o,"useFormAction must be used inside a RouteContext");let[f]=o.matches.slice(-1),d={...qi(n||".",{relative:s})},h=ds();if(n==null){d.search=h.search;let p=new URLSearchParams(d.search),x=p.getAll("index");if(x.some(v=>v==="")){p.delete("index"),x.filter(y=>y).forEach(y=>p.append("index",y));let v=p.toString();d.search=v?`?${v}`:""}}return(!n||n===".")&&f.route.index&&(d.search=d.search?d.search.replace(/^\?/,"?index&"):"?index"),l!=="/"&&(d.pathname=d.pathname==="/"?l:ra([l,d.pathname])),yi(d)}function K1(n,{relative:s}={}){let l=m.useContext(_x);ut(l!=null,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:o}=Yx("useViewTransitionState"),f=qi(n,{relative:s});if(!l.isTransitioning)return!1;let d=oa(l.currentLocation.pathname,o)||l.currentLocation.pathname,h=oa(l.nextLocation.pathname,o)||l.nextLocation.pathname;return mo(f.pathname,h)!=null||mo(f.pathname,d)!=null}const Dn=Object.create(null);Dn.open="0";Dn.close="1";Dn.ping="2";Dn.pong="3";Dn.message="4";Dn.upgrade="5";Dn.noop="6";const lo=Object.create(null);Object.keys(Dn).forEach(n=>{lo[Dn[n]]=n});const wf={type:"error",data:"parser error"},Fx=typeof Blob=="function"||typeof Blob<"u"&&Object.prototype.toString.call(Blob)==="[object BlobConstructor]",Xx=typeof ArrayBuffer=="function",Qx=n=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(n):n&&n.buffer instanceof ArrayBuffer,Kf=({type:n,data:s},l,o)=>Fx&&s instanceof Blob?l?o(s):R0(s,o):Xx&&(s instanceof ArrayBuffer||Qx(s))?l?o(s):R0(new Blob([s]),o):o(Dn[n]+(s||"")),R0=(n,s)=>{const l=new FileReader;return l.onload=function(){const o=l.result.split(",")[1];s("b"+(o||""))},l.readAsDataURL(n)};function q0(n){return n instanceof Uint8Array?n:n instanceof ArrayBuffer?new Uint8Array(n):new Uint8Array(n.buffer,n.byteOffset,n.byteLength)}let ef;function Z1(n,s){if(Fx&&n.data instanceof Blob)return n.data.arrayBuffer().then(q0).then(s);if(Xx&&(n.data instanceof ArrayBuffer||Qx(n.data)))return s(q0(n.data));Kf(n,!1,l=>{ef||(ef=new TextEncoder),s(ef.encode(l))})}const T0="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",hi=typeof Uint8Array>"u"?[]:new Uint8Array(256);for(let n=0;n{let s=n.length*.75,l=n.length,o,f=0,d,h,p,x;n[n.length-1]==="="&&(s--,n[n.length-2]==="="&&s--);const g=new ArrayBuffer(s),v=new Uint8Array(g);for(o=0;o>4,v[f++]=(h&15)<<4|p>>2,v[f++]=(p&3)<<6|x&63;return g},J1=typeof ArrayBuffer=="function",Zf=(n,s)=>{if(typeof n!="string")return{type:"message",data:Kx(n,s)};const l=n.charAt(0);return l==="b"?{type:"message",data:P1(n.substring(1),s)}:lo[l]?n.length>1?{type:lo[l],data:n.substring(1)}:{type:lo[l]}:wf},P1=(n,s)=>{if(J1){const l=I1(n);return Kx(l,s)}else return{base64:!0,data:n}},Kx=(n,s)=>{switch(s){case"blob":return n instanceof Blob?n:new Blob([n]);case"arraybuffer":default:return n instanceof ArrayBuffer?n:n.buffer}},Zx="",W1=(n,s)=>{const l=n.length,o=new Array(l);let f=0;n.forEach((d,h)=>{Kf(d,!1,p=>{o[h]=p,++f===l&&s(o.join(Zx))})})},eS=(n,s)=>{const l=n.split(Zx),o=[];for(let f=0;f{const o=l.length;let f;if(o<126)f=new Uint8Array(1),new DataView(f.buffer).setUint8(0,o);else if(o<65536){f=new Uint8Array(3);const d=new DataView(f.buffer);d.setUint8(0,126),d.setUint16(1,o)}else{f=new Uint8Array(9);const d=new DataView(f.buffer);d.setUint8(0,127),d.setBigUint64(1,BigInt(o))}n.data&&typeof n.data!="string"&&(f[0]|=128),s.enqueue(f),s.enqueue(l)})}})}let tf;function Qr(n){return n.reduce((s,l)=>s+l.length,0)}function Kr(n,s){if(n[0].length===s)return n.shift();const l=new Uint8Array(s);let o=0;for(let f=0;fMath.pow(2,21)-1){p.enqueue(wf);break}f=v*Math.pow(2,32)+g.getUint32(4),o=3}else{if(Qr(l)n){p.enqueue(wf);break}}}})}const Ix=4;function At(n){if(n)return aS(n)}function aS(n){for(var s in At.prototype)n[s]=At.prototype[s];return n}At.prototype.on=At.prototype.addEventListener=function(n,s){return this._callbacks=this._callbacks||{},(this._callbacks["$"+n]=this._callbacks["$"+n]||[]).push(s),this};At.prototype.once=function(n,s){function l(){this.off(n,l),s.apply(this,arguments)}return l.fn=s,this.on(n,l),this};At.prototype.off=At.prototype.removeListener=At.prototype.removeAllListeners=At.prototype.removeEventListener=function(n,s){if(this._callbacks=this._callbacks||{},arguments.length==0)return this._callbacks={},this;var l=this._callbacks["$"+n];if(!l)return this;if(arguments.length==1)return delete this._callbacks["$"+n],this;for(var o,f=0;fPromise.resolve().then(s):(s,l)=>l(s,0),gn=typeof self<"u"?self:typeof window<"u"?window:Function("return this")(),sS="arraybuffer";function Jx(n,...s){return s.reduce((l,o)=>(n.hasOwnProperty(o)&&(l[o]=n[o]),l),{})}const lS=gn.setTimeout,iS=gn.clearTimeout;function Eo(n,s){s.useNativeTimers?(n.setTimeoutFn=lS.bind(gn),n.clearTimeoutFn=iS.bind(gn)):(n.setTimeoutFn=gn.setTimeout.bind(gn),n.clearTimeoutFn=gn.clearTimeout.bind(gn))}const rS=1.33;function oS(n){return typeof n=="string"?cS(n):Math.ceil((n.byteLength||n.size)*rS)}function cS(n){let s=0,l=0;for(let o=0,f=n.length;o=57344?l+=3:(o++,l+=4);return l}function Px(){return Date.now().toString(36).substring(3)+Math.random().toString(36).substring(2,5)}function uS(n){let s="";for(let l in n)n.hasOwnProperty(l)&&(s.length&&(s+="&"),s+=encodeURIComponent(l)+"="+encodeURIComponent(n[l]));return s}function fS(n){let s={},l=n.split("&");for(let o=0,f=l.length;o{this.readyState="paused",s()};if(this._polling||!this.writable){let o=0;this._polling&&(o++,this.once("pollComplete",function(){--o||l()})),this.writable||(o++,this.once("drain",function(){--o||l()}))}else l()}_poll(){this._polling=!0,this.doPoll(),this.emitReserved("poll")}onData(s){const l=o=>{if(this.readyState==="opening"&&o.type==="open"&&this.onOpen(),o.type==="close")return this.onClose({description:"transport closed by the server"}),!1;this.onPacket(o)};eS(s,this.socket.binaryType).forEach(l),this.readyState!=="closed"&&(this._polling=!1,this.emitReserved("pollComplete"),this.readyState==="open"&&this._poll())}doClose(){const s=()=>{this.write([{type:"close"}])};this.readyState==="open"?s():this.once("open",s)}write(s){this.writable=!1,W1(s,l=>{this.doWrite(l,()=>{this.writable=!0,this.emitReserved("drain")})})}uri(){const s=this.opts.secure?"https":"http",l=this.query||{};return this.opts.timestampRequests!==!1&&(l[this.opts.timestampParam]=Px()),!this.supportsBinary&&!l.sid&&(l.b64=1),this.createUri(s,l)}}let Wx=!1;try{Wx=typeof XMLHttpRequest<"u"&&"withCredentials"in new XMLHttpRequest}catch{}const hS=Wx;function pS(){}class xS extends mS{constructor(s){if(super(s),typeof location<"u"){const l=location.protocol==="https:";let o=location.port;o||(o=l?"443":"80"),this.xd=typeof location<"u"&&s.hostname!==location.hostname||o!==s.port}}doWrite(s,l){const o=this.request({method:"POST",data:s});o.on("success",l),o.on("error",(f,d)=>{this.onError("xhr post error",f,d)})}doPoll(){const s=this.request();s.on("data",this.onData.bind(this)),s.on("error",(l,o)=>{this.onError("xhr poll error",l,o)}),this.pollXhr=s}}class Tn extends At{constructor(s,l,o){super(),this.createRequest=s,Eo(this,o),this._opts=o,this._method=o.method||"GET",this._uri=l,this._data=o.data!==void 0?o.data:null,this._create()}_create(){var s;const l=Jx(this._opts,"agent","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","autoUnref");l.xdomain=!!this._opts.xd;const o=this._xhr=this.createRequest(l);try{o.open(this._method,this._uri,!0);try{if(this._opts.extraHeaders){o.setDisableHeaderCheck&&o.setDisableHeaderCheck(!0);for(let f in this._opts.extraHeaders)this._opts.extraHeaders.hasOwnProperty(f)&&o.setRequestHeader(f,this._opts.extraHeaders[f])}}catch{}if(this._method==="POST")try{o.setRequestHeader("Content-type","text/plain;charset=UTF-8")}catch{}try{o.setRequestHeader("Accept","*/*")}catch{}(s=this._opts.cookieJar)===null||s===void 0||s.addCookies(o),"withCredentials"in o&&(o.withCredentials=this._opts.withCredentials),this._opts.requestTimeout&&(o.timeout=this._opts.requestTimeout),o.onreadystatechange=()=>{var f;o.readyState===3&&((f=this._opts.cookieJar)===null||f===void 0||f.parseCookies(o.getResponseHeader("set-cookie"))),o.readyState===4&&(o.status===200||o.status===1223?this._onLoad():this.setTimeoutFn(()=>{this._onError(typeof o.status=="number"?o.status:0)},0))},o.send(this._data)}catch(f){this.setTimeoutFn(()=>{this._onError(f)},0);return}typeof document<"u"&&(this._index=Tn.requestsCount++,Tn.requests[this._index]=this)}_onError(s){this.emitReserved("error",s,this._xhr),this._cleanup(!0)}_cleanup(s){if(!(typeof this._xhr>"u"||this._xhr===null)){if(this._xhr.onreadystatechange=pS,s)try{this._xhr.abort()}catch{}typeof document<"u"&&delete Tn.requests[this._index],this._xhr=null}}_onLoad(){const s=this._xhr.responseText;s!==null&&(this.emitReserved("data",s),this.emitReserved("success"),this._cleanup())}abort(){this._cleanup()}}Tn.requestsCount=0;Tn.requests={};if(typeof document<"u"){if(typeof attachEvent=="function")attachEvent("onunload",D0);else if(typeof addEventListener=="function"){const n="onpagehide"in gn?"pagehide":"unload";addEventListener(n,D0,!1)}}function D0(){for(let n in Tn.requests)Tn.requests.hasOwnProperty(n)&&Tn.requests[n].abort()}const gS=(function(){const n=eg({xdomain:!1});return n&&n.responseType!==null})();class vS extends xS{constructor(s){super(s);const l=s&&s.forceBase64;this.supportsBinary=gS&&!l}request(s={}){return Object.assign(s,{xd:this.xd},this.opts),new Tn(eg,this.uri(),s)}}function eg(n){const s=n.xdomain;try{if(typeof XMLHttpRequest<"u"&&(!s||hS))return new XMLHttpRequest}catch{}if(!s)try{return new gn[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP")}catch{}}const tg=typeof navigator<"u"&&typeof navigator.product=="string"&&navigator.product.toLowerCase()==="reactnative";class bS extends If{get name(){return"websocket"}doOpen(){const s=this.uri(),l=this.opts.protocols,o=tg?{}:Jx(this.opts,"agent","perMessageDeflate","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","localAddress","protocolVersion","origin","maxPayload","family","checkServerIdentity");this.opts.extraHeaders&&(o.headers=this.opts.extraHeaders);try{this.ws=this.createSocket(s,l,o)}catch(f){return this.emitReserved("error",f)}this.ws.binaryType=this.socket.binaryType,this.addEventListeners()}addEventListeners(){this.ws.onopen=()=>{this.opts.autoUnref&&this.ws._socket.unref(),this.onOpen()},this.ws.onclose=s=>this.onClose({description:"websocket connection closed",context:s}),this.ws.onmessage=s=>this.onData(s.data),this.ws.onerror=s=>this.onError("websocket error",s)}write(s){this.writable=!1;for(let l=0;l{try{this.doWrite(o,d)}catch{}f&&Co(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){typeof this.ws<"u"&&(this.ws.onerror=()=>{},this.ws.close(),this.ws=null)}uri(){const s=this.opts.secure?"wss":"ws",l=this.query||{};return this.opts.timestampRequests&&(l[this.opts.timestampParam]=Px()),this.supportsBinary||(l.b64=1),this.createUri(s,l)}}const nf=gn.WebSocket||gn.MozWebSocket;class yS extends bS{createSocket(s,l,o){return tg?new nf(s,l,o):l?new nf(s,l):new nf(s)}doWrite(s,l){this.ws.send(l)}}class SS extends If{get name(){return"webtransport"}doOpen(){try{this._transport=new WebTransport(this.createUri("https"),this.opts.transportOptions[this.name])}catch(s){return this.emitReserved("error",s)}this._transport.closed.then(()=>{this.onClose()}).catch(s=>{this.onError("webtransport error",s)}),this._transport.ready.then(()=>{this._transport.createBidirectionalStream().then(s=>{const l=nS(Number.MAX_SAFE_INTEGER,this.socket.binaryType),o=s.readable.pipeThrough(l).getReader(),f=tS();f.readable.pipeTo(s.writable),this._writer=f.writable.getWriter();const d=()=>{o.read().then(({done:p,value:x})=>{p||(this.onPacket(x),d())}).catch(p=>{})};d();const h={type:"open"};this.query.sid&&(h.data=`{"sid":"${this.query.sid}"}`),this._writer.write(h).then(()=>this.onOpen())})})}write(s){this.writable=!1;for(let l=0;l{f&&Co(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){var s;(s=this._transport)===null||s===void 0||s.close()}}const jS={websocket:yS,webtransport:SS,polling:vS},AS=/^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,NS=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];function Cf(n){if(n.length>8e3)throw"URI too long";const s=n,l=n.indexOf("["),o=n.indexOf("]");l!=-1&&o!=-1&&(n=n.substring(0,l)+n.substring(l,o).replace(/:/g,";")+n.substring(o,n.length));let f=AS.exec(n||""),d={},h=14;for(;h--;)d[NS[h]]=f[h]||"";return l!=-1&&o!=-1&&(d.source=s,d.host=d.host.substring(1,d.host.length-1).replace(/;/g,":"),d.authority=d.authority.replace("[","").replace("]","").replace(/;/g,":"),d.ipv6uri=!0),d.pathNames=wS(d,d.path),d.queryKey=CS(d,d.query),d}function wS(n,s){const l=/\/{2,9}/g,o=s.replace(l,"/").split("/");return(s.slice(0,1)=="/"||s.length===0)&&o.splice(0,1),s.slice(-1)=="/"&&o.splice(o.length-1,1),o}function CS(n,s){const l={};return s.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,function(o,f,d){f&&(l[f]=d)}),l}const Ef=typeof addEventListener=="function"&&typeof removeEventListener=="function",io=[];Ef&&addEventListener("offline",()=>{io.forEach(n=>n())},!1);class Oa extends At{constructor(s,l){if(super(),this.binaryType=sS,this.writeBuffer=[],this._prevBufferLen=0,this._pingInterval=-1,this._pingTimeout=-1,this._maxPayload=-1,this._pingTimeoutTime=1/0,s&&typeof s=="object"&&(l=s,s=null),s){const o=Cf(s);l.hostname=o.host,l.secure=o.protocol==="https"||o.protocol==="wss",l.port=o.port,o.query&&(l.query=o.query)}else l.host&&(l.hostname=Cf(l.host).host);Eo(this,l),this.secure=l.secure!=null?l.secure:typeof location<"u"&&location.protocol==="https:",l.hostname&&!l.port&&(l.port=this.secure?"443":"80"),this.hostname=l.hostname||(typeof location<"u"?location.hostname:"localhost"),this.port=l.port||(typeof location<"u"&&location.port?location.port:this.secure?"443":"80"),this.transports=[],this._transportsByName={},l.transports.forEach(o=>{const f=o.prototype.name;this.transports.push(f),this._transportsByName[f]=o}),this.opts=Object.assign({path:"/engine.io",agent:!1,withCredentials:!1,upgrade:!0,timestampParam:"t",rememberUpgrade:!1,addTrailingSlash:!0,rejectUnauthorized:!0,perMessageDeflate:{threshold:1024},transportOptions:{},closeOnBeforeunload:!1},l),this.opts.path=this.opts.path.replace(/\/$/,"")+(this.opts.addTrailingSlash?"/":""),typeof this.opts.query=="string"&&(this.opts.query=fS(this.opts.query)),Ef&&(this.opts.closeOnBeforeunload&&(this._beforeunloadEventListener=()=>{this.transport&&(this.transport.removeAllListeners(),this.transport.close())},addEventListener("beforeunload",this._beforeunloadEventListener,!1)),this.hostname!=="localhost"&&(this._offlineEventListener=()=>{this._onClose("transport close",{description:"network connection lost"})},io.push(this._offlineEventListener))),this.opts.withCredentials&&(this._cookieJar=void 0),this._open()}createTransport(s){const l=Object.assign({},this.opts.query);l.EIO=Ix,l.transport=s,this.id&&(l.sid=this.id);const o=Object.assign({},this.opts,{query:l,socket:this,hostname:this.hostname,secure:this.secure,port:this.port},this.opts.transportOptions[s]);return new this._transportsByName[s](o)}_open(){if(this.transports.length===0){this.setTimeoutFn(()=>{this.emitReserved("error","No transports available")},0);return}const s=this.opts.rememberUpgrade&&Oa.priorWebsocketSuccess&&this.transports.indexOf("websocket")!==-1?"websocket":this.transports[0];this.readyState="opening";const l=this.createTransport(s);l.open(),this.setTransport(l)}setTransport(s){this.transport&&this.transport.removeAllListeners(),this.transport=s,s.on("drain",this._onDrain.bind(this)).on("packet",this._onPacket.bind(this)).on("error",this._onError.bind(this)).on("close",l=>this._onClose("transport close",l))}onOpen(){this.readyState="open",Oa.priorWebsocketSuccess=this.transport.name==="websocket",this.emitReserved("open"),this.flush()}_onPacket(s){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing")switch(this.emitReserved("packet",s),this.emitReserved("heartbeat"),s.type){case"open":this.onHandshake(JSON.parse(s.data));break;case"ping":this._sendPacket("pong"),this.emitReserved("ping"),this.emitReserved("pong"),this._resetPingTimeout();break;case"error":const l=new Error("server error");l.code=s.data,this._onError(l);break;case"message":this.emitReserved("data",s.data),this.emitReserved("message",s.data);break}}onHandshake(s){this.emitReserved("handshake",s),this.id=s.sid,this.transport.query.sid=s.sid,this._pingInterval=s.pingInterval,this._pingTimeout=s.pingTimeout,this._maxPayload=s.maxPayload,this.onOpen(),this.readyState!=="closed"&&this._resetPingTimeout()}_resetPingTimeout(){this.clearTimeoutFn(this._pingTimeoutTimer);const s=this._pingInterval+this._pingTimeout;this._pingTimeoutTime=Date.now()+s,this._pingTimeoutTimer=this.setTimeoutFn(()=>{this._onClose("ping timeout")},s),this.opts.autoUnref&&this._pingTimeoutTimer.unref()}_onDrain(){this.writeBuffer.splice(0,this._prevBufferLen),this._prevBufferLen=0,this.writeBuffer.length===0?this.emitReserved("drain"):this.flush()}flush(){if(this.readyState!=="closed"&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length){const s=this._getWritablePackets();this.transport.send(s),this._prevBufferLen=s.length,this.emitReserved("flush")}}_getWritablePackets(){if(!(this._maxPayload&&this.transport.name==="polling"&&this.writeBuffer.length>1))return this.writeBuffer;let l=1;for(let o=0;o0&&l>this._maxPayload)return this.writeBuffer.slice(0,o);l+=2}return this.writeBuffer}_hasPingExpired(){if(!this._pingTimeoutTime)return!0;const s=Date.now()>this._pingTimeoutTime;return s&&(this._pingTimeoutTime=0,Co(()=>{this._onClose("ping timeout")},this.setTimeoutFn)),s}write(s,l,o){return this._sendPacket("message",s,l,o),this}send(s,l,o){return this._sendPacket("message",s,l,o),this}_sendPacket(s,l,o,f){if(typeof l=="function"&&(f=l,l=void 0),typeof o=="function"&&(f=o,o=null),this.readyState==="closing"||this.readyState==="closed")return;o=o||{},o.compress=o.compress!==!1;const d={type:s,data:l,options:o};this.emitReserved("packetCreate",d),this.writeBuffer.push(d),f&&this.once("flush",f),this.flush()}close(){const s=()=>{this._onClose("forced close"),this.transport.close()},l=()=>{this.off("upgrade",l),this.off("upgradeError",l),s()},o=()=>{this.once("upgrade",l),this.once("upgradeError",l)};return(this.readyState==="opening"||this.readyState==="open")&&(this.readyState="closing",this.writeBuffer.length?this.once("drain",()=>{this.upgrading?o():s()}):this.upgrading?o():s()),this}_onError(s){if(Oa.priorWebsocketSuccess=!1,this.opts.tryAllTransports&&this.transports.length>1&&this.readyState==="opening")return this.transports.shift(),this._open();this.emitReserved("error",s),this._onClose("transport error",s)}_onClose(s,l){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing"){if(this.clearTimeoutFn(this._pingTimeoutTimer),this.transport.removeAllListeners("close"),this.transport.close(),this.transport.removeAllListeners(),Ef&&(this._beforeunloadEventListener&&removeEventListener("beforeunload",this._beforeunloadEventListener,!1),this._offlineEventListener)){const o=io.indexOf(this._offlineEventListener);o!==-1&&io.splice(o,1)}this.readyState="closed",this.id=null,this.emitReserved("close",s,l),this.writeBuffer=[],this._prevBufferLen=0}}}Oa.protocol=Ix;class ES extends Oa{constructor(){super(...arguments),this._upgrades=[]}onOpen(){if(super.onOpen(),this.readyState==="open"&&this.opts.upgrade)for(let s=0;s{o||(l.send([{type:"ping",data:"probe"}]),l.once("packet",y=>{if(!o)if(y.type==="pong"&&y.data==="probe"){if(this.upgrading=!0,this.emitReserved("upgrading",l),!l)return;Oa.priorWebsocketSuccess=l.name==="websocket",this.transport.pause(()=>{o||this.readyState!=="closed"&&(v(),this.setTransport(l),l.send([{type:"upgrade"}]),this.emitReserved("upgrade",l),l=null,this.upgrading=!1,this.flush())})}else{const S=new Error("probe error");S.transport=l.name,this.emitReserved("upgradeError",S)}}))};function d(){o||(o=!0,v(),l.close(),l=null)}const h=y=>{const S=new Error("probe error: "+y);S.transport=l.name,d(),this.emitReserved("upgradeError",S)};function p(){h("transport closed")}function x(){h("socket closed")}function g(y){l&&y.name!==l.name&&d()}const v=()=>{l.removeListener("open",f),l.removeListener("error",h),l.removeListener("close",p),this.off("close",x),this.off("upgrading",g)};l.once("open",f),l.once("error",h),l.once("close",p),this.once("close",x),this.once("upgrading",g),this._upgrades.indexOf("webtransport")!==-1&&s!=="webtransport"?this.setTimeoutFn(()=>{o||l.open()},200):l.open()}onHandshake(s){this._upgrades=this._filterUpgrades(s.upgrades),super.onHandshake(s)}_filterUpgrades(s){const l=[];for(let o=0;ojS[f]).filter(f=>!!f)),super(s,o)}};function MS(n,s="",l){let o=n;l=l||typeof location<"u"&&location,n==null&&(n=l.protocol+"//"+l.host),typeof n=="string"&&(n.charAt(0)==="/"&&(n.charAt(1)==="/"?n=l.protocol+n:n=l.host+n),/^(https?|wss?):\/\//.test(n)||(typeof l<"u"?n=l.protocol+"//"+n:n="https://"+n),o=Cf(n)),o.port||(/^(http|ws)$/.test(o.protocol)?o.port="80":/^(http|ws)s$/.test(o.protocol)&&(o.port="443")),o.path=o.path||"/";const d=o.host.indexOf(":")!==-1?"["+o.host+"]":o.host;return o.id=o.protocol+"://"+d+":"+o.port+s,o.href=o.protocol+"://"+d+(l&&l.port===o.port?"":":"+o.port),o}const RS=typeof ArrayBuffer=="function",qS=n=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(n):n.buffer instanceof ArrayBuffer,ng=Object.prototype.toString,TS=typeof Blob=="function"||typeof Blob<"u"&&ng.call(Blob)==="[object BlobConstructor]",DS=typeof File=="function"||typeof File<"u"&&ng.call(File)==="[object FileConstructor]";function Jf(n){return RS&&(n instanceof ArrayBuffer||qS(n))||TS&&n instanceof Blob||DS&&n instanceof File}function ro(n,s){if(!n||typeof n!="object")return!1;if(Array.isArray(n)){for(let l=0,o=n.length;l=0&&n.num{delete this.acks[s];for(let p=0;p{this.io.clearTimeoutFn(d),l.apply(this,p)};h.withError=!0,this.acks[s]=h}emitWithAck(s,...l){return new Promise((o,f)=>{const d=(h,p)=>h?f(h):o(p);d.withError=!0,l.push(d),this.emit(s,...l)})}_addToQueue(s){let l;typeof s[s.length-1]=="function"&&(l=s.pop());const o={id:this._queueSeq++,tryCount:0,pending:!1,args:s,flags:Object.assign({fromQueue:!0},this.flags)};s.push((f,...d)=>o!==this._queue[0]?void 0:(f!==null?o.tryCount>this._opts.retries&&(this._queue.shift(),l&&l(f)):(this._queue.shift(),l&&l(null,...d)),o.pending=!1,this._drainQueue())),this._queue.push(o),this._drainQueue()}_drainQueue(s=!1){if(!this.connected||this._queue.length===0)return;const l=this._queue[0];l.pending&&!s||(l.pending=!0,l.tryCount++,this.flags=l.flags,this.emit.apply(this,l.args))}packet(s){s.nsp=this.nsp,this.io._packet(s)}onopen(){typeof this.auth=="function"?this.auth(s=>{this._sendConnectPacket(s)}):this._sendConnectPacket(this.auth)}_sendConnectPacket(s){this.packet({type:_e.CONNECT,data:this._pid?Object.assign({pid:this._pid,offset:this._lastOffset},s):s})}onerror(s){this.connected||this.emitReserved("connect_error",s)}onclose(s,l){this.connected=!1,delete this.id,this.emitReserved("disconnect",s,l),this._clearAcks()}_clearAcks(){Object.keys(this.acks).forEach(s=>{if(!this.sendBuffer.some(o=>String(o.id)===s)){const o=this.acks[s];delete this.acks[s],o.withError&&o.call(this,new Error("socket has been disconnected"))}})}onpacket(s){if(s.nsp===this.nsp)switch(s.type){case _e.CONNECT:s.data&&s.data.sid?this.onconnect(s.data.sid,s.data.pid):this.emitReserved("connect_error",new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));break;case _e.EVENT:case _e.BINARY_EVENT:this.onevent(s);break;case _e.ACK:case _e.BINARY_ACK:this.onack(s);break;case _e.DISCONNECT:this.ondisconnect();break;case _e.CONNECT_ERROR:this.destroy();const o=new Error(s.data.message);o.data=s.data.data,this.emitReserved("connect_error",o);break}}onevent(s){const l=s.data||[];s.id!=null&&l.push(this.ack(s.id)),this.connected?this.emitEvent(l):this.receiveBuffer.push(Object.freeze(l))}emitEvent(s){if(this._anyListeners&&this._anyListeners.length){const l=this._anyListeners.slice();for(const o of l)o.apply(this,s)}super.emit.apply(this,s),this._pid&&s.length&&typeof s[s.length-1]=="string"&&(this._lastOffset=s[s.length-1])}ack(s){const l=this;let o=!1;return function(...f){o||(o=!0,l.packet({type:_e.ACK,id:s,data:f}))}}onack(s){const l=this.acks[s.id];typeof l=="function"&&(delete this.acks[s.id],l.withError&&s.data.unshift(null),l.apply(this,s.data))}onconnect(s,l){this.id=s,this.recovered=l&&this._pid===l,this._pid=l,this.connected=!0,this.emitBuffered(),this.emitReserved("connect"),this._drainQueue(!0)}emitBuffered(){this.receiveBuffer.forEach(s=>this.emitEvent(s)),this.receiveBuffer=[],this.sendBuffer.forEach(s=>{this.notifyOutgoingListeners(s),this.packet(s)}),this.sendBuffer=[]}ondisconnect(){this.destroy(),this.onclose("io server disconnect")}destroy(){this.subs&&(this.subs.forEach(s=>s()),this.subs=void 0),this.io._destroy(this)}disconnect(){return this.connected&&this.packet({type:_e.DISCONNECT}),this.destroy(),this.connected&&this.onclose("io client disconnect"),this}close(){return this.disconnect()}compress(s){return this.flags.compress=s,this}get volatile(){return this.flags.volatile=!0,this}timeout(s){return this.flags.timeout=s,this}onAny(s){return this._anyListeners=this._anyListeners||[],this._anyListeners.push(s),this}prependAny(s){return this._anyListeners=this._anyListeners||[],this._anyListeners.unshift(s),this}offAny(s){if(!this._anyListeners)return this;if(s){const l=this._anyListeners;for(let o=0;o0&&n.jitter<=1?n.jitter:0,this.attempts=0}dl.prototype.duration=function(){var n=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var s=Math.random(),l=Math.floor(s*this.jitter*n);n=(Math.floor(s*10)&1)==0?n-l:n+l}return Math.min(n,this.max)|0};dl.prototype.reset=function(){this.attempts=0};dl.prototype.setMin=function(n){this.ms=n};dl.prototype.setMax=function(n){this.max=n};dl.prototype.setJitter=function(n){this.jitter=n};class Rf extends At{constructor(s,l){var o;super(),this.nsps={},this.subs=[],s&&typeof s=="object"&&(l=s,s=void 0),l=l||{},l.path=l.path||"/socket.io",this.opts=l,Eo(this,l),this.reconnection(l.reconnection!==!1),this.reconnectionAttempts(l.reconnectionAttempts||1/0),this.reconnectionDelay(l.reconnectionDelay||1e3),this.reconnectionDelayMax(l.reconnectionDelayMax||5e3),this.randomizationFactor((o=l.randomizationFactor)!==null&&o!==void 0?o:.5),this.backoff=new dl({min:this.reconnectionDelay(),max:this.reconnectionDelayMax(),jitter:this.randomizationFactor()}),this.timeout(l.timeout==null?2e4:l.timeout),this._readyState="closed",this.uri=s;const f=l.parser||HS;this.encoder=new f.Encoder,this.decoder=new f.Decoder,this._autoConnect=l.autoConnect!==!1,this._autoConnect&&this.open()}reconnection(s){return arguments.length?(this._reconnection=!!s,s||(this.skipReconnect=!0),this):this._reconnection}reconnectionAttempts(s){return s===void 0?this._reconnectionAttempts:(this._reconnectionAttempts=s,this)}reconnectionDelay(s){var l;return s===void 0?this._reconnectionDelay:(this._reconnectionDelay=s,(l=this.backoff)===null||l===void 0||l.setMin(s),this)}randomizationFactor(s){var l;return s===void 0?this._randomizationFactor:(this._randomizationFactor=s,(l=this.backoff)===null||l===void 0||l.setJitter(s),this)}reconnectionDelayMax(s){var l;return s===void 0?this._reconnectionDelayMax:(this._reconnectionDelayMax=s,(l=this.backoff)===null||l===void 0||l.setMax(s),this)}timeout(s){return arguments.length?(this._timeout=s,this):this._timeout}maybeReconnectOnOpen(){!this._reconnecting&&this._reconnection&&this.backoff.attempts===0&&this.reconnect()}open(s){if(~this._readyState.indexOf("open"))return this;this.engine=new kS(this.uri,this.opts);const l=this.engine,o=this;this._readyState="opening",this.skipReconnect=!1;const f=jn(l,"open",function(){o.onopen(),s&&s()}),d=p=>{this.cleanup(),this._readyState="closed",this.emitReserved("error",p),s?s(p):this.maybeReconnectOnOpen()},h=jn(l,"error",d);if(this._timeout!==!1){const p=this._timeout,x=this.setTimeoutFn(()=>{f(),d(new Error("timeout")),l.close()},p);this.opts.autoUnref&&x.unref(),this.subs.push(()=>{this.clearTimeoutFn(x)})}return this.subs.push(f),this.subs.push(h),this}connect(s){return this.open(s)}onopen(){this.cleanup(),this._readyState="open",this.emitReserved("open");const s=this.engine;this.subs.push(jn(s,"ping",this.onping.bind(this)),jn(s,"data",this.ondata.bind(this)),jn(s,"error",this.onerror.bind(this)),jn(s,"close",this.onclose.bind(this)),jn(this.decoder,"decoded",this.ondecoded.bind(this)))}onping(){this.emitReserved("ping")}ondata(s){try{this.decoder.add(s)}catch(l){this.onclose("parse error",l)}}ondecoded(s){Co(()=>{this.emitReserved("packet",s)},this.setTimeoutFn)}onerror(s){this.emitReserved("error",s)}socket(s,l){let o=this.nsps[s];return o?this._autoConnect&&!o.active&&o.connect():(o=new ag(this,s,l),this.nsps[s]=o),o}_destroy(s){const l=Object.keys(this.nsps);for(const o of l)if(this.nsps[o].active)return;this._close()}_packet(s){const l=this.encoder.encode(s);for(let o=0;os()),this.subs.length=0,this.decoder.destroy()}_close(){this.skipReconnect=!0,this._reconnecting=!1,this.onclose("forced close")}disconnect(){return this._close()}onclose(s,l){var o;this.cleanup(),(o=this.engine)===null||o===void 0||o.close(),this.backoff.reset(),this._readyState="closed",this.emitReserved("close",s,l),this._reconnection&&!this.skipReconnect&&this.reconnect()}reconnect(){if(this._reconnecting||this.skipReconnect)return this;const s=this;if(this.backoff.attempts>=this._reconnectionAttempts)this.backoff.reset(),this.emitReserved("reconnect_failed"),this._reconnecting=!1;else{const l=this.backoff.duration();this._reconnecting=!0;const o=this.setTimeoutFn(()=>{s.skipReconnect||(this.emitReserved("reconnect_attempt",s.backoff.attempts),!s.skipReconnect&&s.open(f=>{f?(s._reconnecting=!1,s.reconnect(),this.emitReserved("reconnect_error",f)):s.onreconnect()}))},l);this.opts.autoUnref&&o.unref(),this.subs.push(()=>{this.clearTimeoutFn(o)})}}onreconnect(){const s=this.backoff.attempts;this._reconnecting=!1,this.backoff.reset(),this.emitReserved("reconnect",s)}}const ci={};function oo(n,s){typeof n=="object"&&(s=n,n=void 0),s=s||{};const l=MS(n,s.path||"/socket.io"),o=l.source,f=l.id,d=l.path,h=ci[f]&&d in ci[f].nsps,p=s.forceNew||s["force new connection"]||s.multiplex===!1||h;let x;return p?x=new Rf(o,s):(ci[f]||(ci[f]=new Rf(o,s)),x=ci[f]),l.query&&!s.query&&(s.query=l.queryKey),x.socket(l.path,s)}Object.assign(oo,{Manager:Rf,Socket:ag,io:oo,connect:oo});const sg="roverSettings",$S=3600*24*365;function GS(n){try{const s=decodeURIComponent(n??"");return JSON.parse(s)}catch(s){return console.warn("Failed to parse settings cookie",s),null}}function qf(){if(typeof document>"u")return{};const n=`${sg}=`,s=document.cookie.split(";").map(o=>o.trim()).find(o=>o.startsWith(n));if(!s)return{};const l=s.substring(n.length);return GS(l)??{}}function B0(n){if(typeof document>"u")return!1;try{const s=encodeURIComponent(JSON.stringify(n??{})),l=`${sg}=${s}; path=/; max-age=${$S}; samesite=strict`;return document.cookie=l,!0}catch(s){return console.warn("Failed to write settings cookie",s),!1}}const lg=window.location.origin;console.info("[socket] connecting to",lg);const YS=qf(),FS=YS?.page?.connectionTransport||"websocket",XS=FS==="polling"?["polling"]:["websocket","polling"],Wf=oo(lg,{transports:XS,timeout:15e3});Wf.on("connect_error",n=>console.error("connect_error",n.code,n.message,n.data));const ig=m.createContext(Wf),QS=({children:n})=>r.jsx(ig.Provider,{value:Wf,children:n}),tn=()=>m.useContext(ig),KS={connected:!1,session:null,logs:[],adminLogs:[],llmCommentaryState:null,llmCommentaryStatus:null,alerts:[]},ed=m.createContext(null);function ZS(n){return m.useCallback((s,l={})=>new Promise((o,f)=>{n.emit(s,l,(d={})=>{d.error?f(new Error(d.error)):o(d)})}),[n])}function IS(n){return typeof n=="function"?n:s=>s}function JS({children:n}){const s=tn(),l=ZS(s),o=m.useRef({...KS,connected:s.connected}),f=m.useRef(new Set),d=m.useCallback(()=>o.current,[]),h=m.useCallback(v=>{const y=o.current,S=typeof v=="function"?v(y):{...y,...v||{}};S!==y&&(o.current=S,f.current.forEach(E=>{const C=E.selector(S);E.equalityFn(E.current,C)||(E.current=C,E.listener(C))}))},[]),p=m.useCallback((v,y,S=Object.is)=>{const E=IS(v),C={selector:E,equalityFn:S,listener:y,current:E(o.current)};return f.current.add(C),()=>{f.current.delete(C)}},[]);m.useEffect(()=>{const v=()=>{h(S=>S.connected?S:{...S,connected:!0})},y=()=>{h(S=>S.connected?{...S,connected:!1}:S)};return s.on("connect",v),s.on("disconnect",y),()=>{s.off("connect",v),s.off("disconnect",y)}},[h,s]),m.useEffect(()=>{function v(j){h(N=>({...N,session:j}))}function y(j=[]){h(N=>({...N,logs:j}))}function S(j){h(N=>({...N,logs:[...N.logs.slice(-199),j]}))}function E(j=[]){h(N=>({...N,adminLogs:j}))}function C(j){h(N=>({...N,adminLogs:[...N.adminLogs.slice(-199),j]}))}function k(j=null){const N=j&&typeof j=="object"?j:null,T=N?.debug?.status&&typeof N.debug.status=="object"?N.debug.status:null;h(M=>({...M,llmCommentaryState:N,llmCommentaryStatus:T}))}function w(j={}){h(N=>({...N,alerts:[...N.alerts.slice(-49),{...j,receivedAt:Date.now()}]}))}return s.on("session:sync",v),s.on("log:init",y),s.on("log:entry",S),s.on("adminlog:init",E),s.on("adminlog:entry",C),s.on("llm:state",k),s.on("alert:new",w),()=>{s.off("session:sync",v),s.off("log:init",y),s.off("log:entry",S),s.off("adminlog:init",E),s.off("adminlog:entry",C),s.off("llm:state",k),s.off("alert:new",w)}},[h,s]);const x=m.useMemo(()=>({login:(v,y)=>l("auth:login",{username:v,password:y}),identifySession:({cookieUserId:v,nickname:y}={})=>l("session:identify",{cookieUserId:v,nickname:y}),setRole:v=>l("session:setRole",{role:v}),requestControl:(v,y={})=>l("session:requestControl",{roverId:v,...y}),releaseControl:v=>l("session:releaseControl",{roverId:v}),subscribeAll:()=>l("session:subscribeAll"),lockRover:(v,y)=>l("session:lockRover",{roverId:v,locked:y}),setMode:v=>l("setMode",{mode:v}),homeAssistantToggle:v=>l("homeAssistant:toggle",{entityId:v}),homeAssistantSetState:(v,y)=>l("homeAssistant:setState",{entityId:v,state:y}),homeAssistantSetLightColor:(v,y)=>l("homeAssistant:lightColor",{entityId:v,rgbColor:y}),homeAssistantSetLightWhite:v=>l("homeAssistant:lightWhite",{entityId:v}),neatoStart:()=>l("neato:start"),neatoSendHome:()=>l("neato:sendHome"),neatoLocate:()=>l("neato:locate"),neatoClearErrors:()=>l("neato:clearErrors"),setNickname:v=>l("nickname:set",{nickname:v}),requestVerification:()=>l("verification:request"),requestPrivateRoverAccess:v=>l("session:privateRover:requestAccess",{roverId:v}),triggerReplay:(v=[],y="")=>v&&typeof v=="object"&&!Array.isArray(v)?l("replay:trigger",v):l("replay:trigger",{sources:v,title:y}),setCommunityGoal:v=>l("communityGoal:set",{text:v}),setAdminReason:v=>l("adminReason:set",{text:v}),rebootRover:v=>l("command",{roverId:v,type:"reboot",data:{reboot:{}}}),rebootServer:()=>l("server:reboot"),playUploadedAudio:({roverId:v,name:y,mime:S,dataBase64:E})=>l("audio:uploadPlay",{roverId:v,name:y,mime:S,dataBase64:E}),stopUploadedAudio:v=>l("audio:uploadStop",{roverId:v}),startMicWhip:v=>l("audio:micWhipStart",{roverId:v}),readyMicWhip:v=>l("audio:micWhipReady",{roverId:v}),stopMicWhip:v=>l("audio:micWhipStop",{roverId:v}),setAudioLevels:(v={})=>l("audioLevels:set",v),setPrivateSafety:(v,y={})=>l("session:privateSafety:set",{roverId:v,safety:y}),llmControl:(v,y={})=>l("llm:control",{controls:{action:v,...y}}),pushAlert:v=>h(y=>({...y,alerts:[...y.alerts.slice(-49),{...v,receivedAt:Date.now(),id:v.id||Math.random().toString(36).slice(2)}]}))}),[l,h]),g=m.useMemo(()=>({getState:d,subscribe:p,actions:x}),[x,d,p]);return r.jsx(ed.Provider,{value:g,children:n})}function ft(n,s=Object.is){const l=m.useContext(ed);if(!l)throw new Error("useSessionSelector must be used within SessionProvider");const o=m.useRef(n);o.current=n;const f=m.useRef(s);f.current=s;const[d,h]=m.useState(()=>n(l.getState()));return m.useEffect(()=>(h(p=>{const x=o.current(l.getState());return f.current(p,x)?p:x}),l.subscribe(p=>o.current(p),p=>{h(x=>f.current(x,p)?x:p)},(p,x)=>f.current(p,x))),[l]),d}function wn(){const n=m.useContext(ed);if(!n)throw new Error("useSessionActions must be used within SessionProvider");return n.actions}function nn(){const n=ft(l=>l),s=wn();return m.useMemo(()=>({...n,...s}),[s,n])}const rg=m.createContext({frames:{}});function PS({children:n}){const s=tn(),[l,o]=m.useState({});m.useEffect(()=>{function d({roverId:h,sensors:p={},frame:x={}}){h&&o(g=>({...g,[h]:{roverId:h,sensors:p,raw:x?.data||null,receivedAt:Date.now()}}))}return s.on("sensorFrame",d),()=>{s.off("sensorFrame",d)}},[s]);const f=m.useMemo(()=>({frames:l}),[l]);return r.jsx(rg.Provider,{value:f,children:n})}function td(){return m.useContext(rg).frames}function ml(n){const s=td();return n?s[n]??null:null}const WS=650,ej={161:{red:!0},164:{green:!0},165:{force:!0},168:{red:!0,green:!0},169:{red:!0,force:!0},172:{green:!0,force:!0},173:{red:!0,green:!0,force:!0}};function af(n){if(typeof n!="number"||n<=0)return null;const s=ej[n];return s?{code:n,...s}:null}function tj(n,s={}){const l=s.holdMs||WS,[o,f]=m.useState({left:null,right:null,omni:null}),[d,h]=m.useState(0);return m.useEffect(()=>{const p=setInterval(()=>h(Date.now()),Math.max(l/2,100));return()=>clearInterval(p)},[l]),m.useEffect(()=>{const p=Date.now(),x=af(n?.infraredCharacterLeft),g=af(n?.infraredCharacterRight),v=af(n?.infraredCharacterOmni);!x&&!g&&!v||f(y=>({left:x?{...x,ts:p}:y.left,right:g?{...g,ts:p}:y.right,omni:v?{...v,ts:p}:y.omni}))},[n?.infraredCharacterLeft,n?.infraredCharacterRight,n?.infraredCharacterOmni]),m.useEffect(()=>{const{left:p,right:x,omni:g}=o;if(!(p?.ts||x?.ts||g?.ts))return;const y=new Date().toISOString();console.debug("[DockIR]",y,{left:p?.code??0,omni:g?.code??0,right:x?.code??0})},[o.left?.code,o.right?.code,o.omni?.code]),m.useMemo(()=>{const p=Date.now(),x=w=>{if(!w)return{active:!1,red:!1,green:!1,force:!1,age:null,code:null};const j=p-w.ts,N=j<=l;return{active:N,age:j,code:w.code,red:!!(w.red&&N),green:!!(w.green&&N),force:!!(w.force&&N)}},g=x(o.left),v=x(o.right),y=x(o.omni),S=g.force||v.force||y.force,E=g.active||v.active||y.active,C=g.active&&!v.active?"right":v.active&&!g.active?"left":"center",k=(v.active?1:0)-(g.active?1:0);return{visible:E,forceDetected:S,left:g,right:v,omni:y,bias:C,balance:Math.max(-1,Math.min(1,k))}},[o.left,o.right,o.omni,l,d])}function nj(){ft(S=>S.connected);const n=ft(S=>S.session),s=n?.assignment?.roverId,l=ml(s),o=l?.sensors||{},f=tj(o),d=o.voltageMv!=null?`${(o.voltageMv/1e3).toFixed(2)} V`:null,h=o.currentMa!=null?`${o.currentMa} mA`:null,p=o.batteryTemperatureC!=null?`${o.batteryTemperatureC} °C`:null,x=o.batteryChargeMah,g=o.batteryCapacityMah;l?.receivedAt&&new Date(l.receivedAt).toLocaleTimeString();const v=l?.raw?l.raw:null,y=s?n?.activeDrivers?.[s]:null;return m.useMemo(()=>s?y?y===n?.socketId?"You":(n?.users||[]).find(E=>E.socketId===y)?.nickname||y.slice(0,6):"Available":"n/a",[y,s,n?.socketId,n?.users]),r.jsxs("section",{className:"panel-section space-y-0.5 text-base text-slate-100",children:[s?l?r.jsxs(r.Fragment,{children:[r.jsx(aj,{sensors:o,voltage:d,current:h,batteryTemp:p,charge:x,capacity:g}),r.jsx(sj,{sensors:o,dockState:f})]}):r.jsx("p",{className:"text-sm text-slate-500",children:"Waiting for sensor frames…"}):r.jsx("p",{className:"text-sm text-slate-500",children:"Assign a rover to view sensors."}),v&&r.jsx("pre",{className:"surface whitespace-pre-wrap break-words text-xs text-lime-300",children:v})]})}function aj({sensors:n,voltage:s,current:l,batteryTemp:o,charge:f,capacity:d}){const h=f!=null&&d?`${Math.round(f/d*100)}`:"--",p=n?.oiMode?.label||"--",x=n?.chargingSources?.homeBase?"Yes":"No",g=n?.chargingState?.label||"--";return r.jsxs("div",{className:"grid grid-cols-2 gap-0.5 md:grid-cols-3",children:[r.jsx(aa,{label:"Voltage",value:s??"--"}),r.jsx(aa,{label:"Current",value:l??"--"}),r.jsx(aa,{label:"Battery temp",value:o??"--"}),r.jsx(aa,{label:"Charge",value:f!=null?`${f} mAh`:"--"}),r.jsx(aa,{label:"Capacity",value:d!=null?`${d} mAh`:"--"}),r.jsx(aa,{label:"Charge",value:h}),r.jsx(aa,{label:"OI mode",value:p}),r.jsx(aa,{label:"Docked",value:x}),r.jsx(aa,{label:"Charging state",value:g})]})}function aa({label:n,value:s}){return r.jsxs("div",{className:"surface flex items-center justify-between gap-0.5 px-1 py-0.5 text-sm",children:[r.jsx("span",{className:"text-slate-400",children:n}),r.jsx("span",{className:"text-slate-100",children:s})]})}function sj({sensors:n,dockState:s}){const l=n?.bumpsAndWheelDrops||{},o=n?.wheelOvercurrents||{},f=[{label:"Left",value:n?.lightBumpLeftSignal},{label:"Front Left",value:n?.lightBumpFrontLeftSignal},{label:"Center Left",value:n?.lightBumpCenterLeftSignal},{label:"Center Right",value:n?.lightBumpCenterRightSignal},{label:"Front Right",value:n?.lightBumpFrontRightSignal},{label:"Right",value:n?.lightBumpRightSignal}],d=[{label:"Left",value:n?.cliffLeftSignal,active:n?.cliffLeft},{label:"Front Left",value:n?.cliffFrontLeftSignal,active:n?.cliffFrontLeft},{label:"Front Right",value:n?.cliffFrontRightSignal,active:n?.cliffFrontRight},{label:"Right",value:n?.cliffRightSignal,active:n?.cliffRight}],h=[{label:"Wheel L",value:n?.wheelLeftCurrentMa,over:o.leftWheel},{label:"Wheel R",value:n?.wheelRightCurrentMa,over:o.rightWheel},{label:"Side brush",value:n?.sideBrushCurrentMa,over:o.sideBrush},{label:"Main brush",value:n?.mainBrushCurrentMa,over:o.mainBrush}];return r.jsxs("div",{className:"grid gap-0.5 md:grid-cols-2",children:[r.jsxs(el,{title:"Dock IR",children:[r.jsx(lj,{sensors:n}),r.jsx(ij,{state:s})]}),r.jsxs(el,{title:"Bumps & drops",children:[r.jsx(sa,{label:"Bump L",value:r.jsx(ui,{active:l.bumpLeft})}),r.jsx(sa,{label:"Bump R",value:r.jsx(ui,{active:l.bumpRight})}),r.jsx(sa,{label:"Wheel drop L",value:r.jsx(ui,{active:l.wheelDropLeft,tone:"amber"})}),r.jsx(sa,{label:"Wheel drop R",value:r.jsx(ui,{active:l.wheelDropRight,tone:"amber"})})]}),r.jsx(el,{title:"Light bumps (raw)",children:f.map(p=>r.jsx(sa,{label:p.label,value:fi(p.value)},p.label))}),r.jsx(el,{title:"Cliff sensors",children:d.map(p=>r.jsx(sa,{label:p.label,value:`${fi(p.value)} · ${p.active?"bool: true":"bool: false"}`},p.label))}),r.jsx(el,{title:"Currents",children:h.map(p=>r.jsx(sa,{label:p.label,value:r.jsxs("span",{className:"flex items-center gap-0.5",children:[r.jsx("span",{children:fi(p.value,"mA")}),p.over?r.jsx(ui,{active:!0,tone:"red",label:"over"}):null]})},p.label))}),r.jsxs(el,{title:"Dirt detect",children:[r.jsx(sa,{label:"Left",value:fi(n?.dirtDetectLeft)}),r.jsx(sa,{label:"Right",value:fi(n?.dirtDetect)})]})]})}function el({title:n,children:s}){return r.jsxs("div",{className:"surface space-y-0.5 p-1 text-sm",children:[r.jsx("div",{className:"text-[0.8rem] uppercase tracking-wide text-slate-400",children:n}),r.jsx("div",{className:"space-y-0.5",children:s})]})}function sa({label:n,value:s}){return r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{className:"text-slate-300",children:n}),r.jsx("span",{className:"text-slate-100",children:s})]})}function ui({active:n,tone:s="green",label:l}){const o="rounded px-1.5 py-0.5 text-[0.7rem] font-semibold",f=s==="red"?n?"bg-red-600 text-white":"bg-slate-700 text-slate-300":s==="amber"?n?"bg-amber-500 text-slate-900":"bg-slate-700 text-slate-300":n?"bg-emerald-600 text-white":"bg-slate-700 text-slate-300";return r.jsx("span",{className:`${o} ${f}`,children:l||(n?"true":"false")})}function fi(n,s){return n==null||Number.isNaN(n)?"--":s?`${n} ${s}`:n}function lj({sensors:n}){const s=n?.infraredCharacterLeft,l=n?.infraredCharacterRight,o=n?.infraredCharacterOmni,f=d=>r.jsx("span",{className:`rounded px-1 py-0.25 text-[0.7rem] font-semibold ${d?"bg-emerald-600 text-white":"bg-slate-700 text-slate-300"}`,children:d||"--"});return r.jsxs("div",{className:"flex items-center justify-between gap-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:"L"}),f(s)]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:"O"}),f(o)]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:"R"}),f(l)]})]})}function ij({state:n}){if(!n)return null;const s=o=>{const f=[];return o?.red&&f.push("R"),o?.green&&f.push("G"),o?.force&&f.push("F"),f.length?f.join(""):"none"},l=o=>o?.age!=null?`${o.age}ms`:"--";return r.jsxs("div",{className:"text-[0.7rem] text-slate-400",children:[r.jsx("div",{children:`Left: ${n.left.code??"--"} (${s(n.left)}) · age ${l(n.left)}`}),r.jsx("div",{children:`Omni: ${n.omni.code??"--"} (${s(n.omni)}) · age ${l(n.omni)}`}),r.jsx("div",{children:`Right: ${n.right.code??"--"} (${s(n.right)}) · age ${l(n.right)}`})]})}const og=m.createContext(null);function rj({children:n}){const[s,l]=m.useState(()=>({status:"loading",data:{}}));m.useEffect(()=>{const p=qf();l({status:"ready",data:p??{}})},[]);const o=m.useCallback(()=>{const p=qf();l({status:"ready",data:p??{}})},[]),f=m.useCallback(p=>{const x=B0(p??{});return l(x?{status:"ready",data:p??{}}:g=>({...g,status:"error"})),x},[]),d=m.useCallback((p,x)=>{l(g=>{const v=g.data[p]||{},y=typeof x=="function"?x(v):{...v,...x??{}},S={...g.data,[p]:y};return B0(S)?{status:"ready",data:S}:{...g,status:"error"}})},[]),h=m.useMemo(()=>({data:s.data,status:s.status,reload:o,saveAll:f,setNamespace:d}),[s,o,f,d]);return r.jsx(og.Provider,{value:h,children:n})}function oj(){const n=m.useContext(og);if(!n)throw new Error("useSettings must be used within SettingsProvider");return n}function He(n,s={}){const{data:l,status:o,setNamespace:f}=oj(),d=l[n]??s??{},h=m.useCallback(g=>{f(n,v=>{const y=v??{};return typeof g=="function"?g(y):{...y,...g??{}}})},[n,f]),p=m.useCallback(g=>{f(n,()=>g??{})},[n,f]),x=m.useCallback(()=>{const g=typeof s=="object"?{...s}:s;f(n,()=>g??{})},[s,n,f]);return{value:d,status:o,save:h,replace:p,reset:x}}const cj=/^#[0-9A-Fa-f]{6}$/;function nd(n){const s=typeof n=="string"?n.trim():"";return!s||!cj.test(s)?null:s.toUpperCase()}function ca(n,s=.2){const l=nd(n);if(!l)return;const o=Number.isFinite(s)?Math.max(0,Math.min(1,s)):.2,f=cg(l);if(f)return{borderColor:`rgba(${f.r}, ${f.g}, ${f.b}, 0.65)`,backgroundColor:`rgba(${f.r}, ${f.g}, ${f.b}, ${o})`}}function uj(n,s=.2){const l=nd(n);if(!l)return;const o=Number.isFinite(s)?Math.max(0,Math.min(1,s)):.2,f=cg(l);if(f)return{borderColor:`rgba(${f.r}, ${f.g}, ${f.b}, 0.55)`,backgroundColor:`rgba(${f.r}, ${f.g}, ${f.b}, ${o})`}}function cg(n){const s=nd(n);return s?{r:parseInt(s.slice(1,3),16),g:parseInt(s.slice(3,5),16),b:parseInt(s.slice(5,7),16)}:null}function fj(n=[]){return n.map(s=>!s?.type||!s?.id?null:{type:s.type,id:String(s.id),label:s.label||String(s.id),color:s.color||null,key:`${s.type}:${s.id}`}).filter(Boolean)}function ad({panelId:n="replay-sources",fillHeight:s=!1}){const{session:l,triggerReplay:o}=nn(),f=fj(l?.replaySources||[]),{value:d,save:h}=He("replaySources",{}),[p,x]=m.useState([]),[g,v]=m.useState(!1),[y,S]=m.useState(null),[E,C]=m.useState(null),[k,w]=m.useState(""),[j,N]=m.useState(!1),[T,M]=m.useState(!0),O=l?.replay||null,[K,_]=m.useState(0),U=m.useMemo(()=>{const q=l?.assignment?.roverId;return q?[`rover:${q}`]:[]},[l?.assignment?.roverId]),X=m.useMemo(()=>{const L=((Array.isArray(l?.users)?l.users.find(fe=>fe?.socketId===l?.socketId):null)?.nickname||"Someone").trim()||"Someone",Z=l?.assignment?.roverId||null,le=Z&&Array.isArray(l?.roster)?l.roster.find(fe=>String(fe?.id)===String(Z))?.name||Z:"a rover";return`${L} driving ${le}`},[l?.users,l?.socketId,l?.assignment?.roverId,l?.roster]);m.useEffect(()=>{const q=d?.[n];if(Array.isArray(q)&&q.length){x(q);return}x(U)},[d?.[n],U,n]),m.useEffect(()=>{const q=d?.[`${n}:includeSidebar`];if(typeof q=="boolean"){M(q);return}M(!0)},[d?.[`${n}:includeSidebar`],n]),m.useEffect(()=>{j||w(X)},[X,j]),m.useEffect(()=>{const q=new Set(f.map(L=>L.key));x(L=>L.filter(Z=>q.has(Z)))},[f]);const F=m.useMemo(()=>({rovers:f.filter(q=>q.type==="rover"),rooms:f.filter(q=>q.type==="room")}),[f]);m.useEffect(()=>{if(!O?.lastTriggeredAt||!O?.cooldownMs){_(0);return}const q=()=>{const Z=O.lastTriggeredAt+O.cooldownMs-Date.now();_(Math.max(0,Z))};q();const L=setInterval(q,250);return()=>clearInterval(L)},[O?.lastTriggeredAt,O?.cooldownMs,O?.remainingMs]);const H=g||l?.mode==="lockdown"||K>0||!p.length,te=q=>{x(L=>{const Z=L.includes(q)?L.filter(le=>le!==q):[...L,q];return h(le=>({...le||{},[n]:Z})),Z}),C(null)},ce=async()=>{if(!H){v(!0),S(null),C(null);try{const q=p.map(Z=>{const[le,fe]=Z.split(":");return{type:le,id:fe}}),L=String(k||"").trim()||X;await o({sources:q,title:L,includeSidebar:T}),C("Replay sent. Check the Discord replay channel.")}catch(q){S(q.message)}finally{v(!1)}}},oe=s?"h-full flex flex-col":"",V=s?"flex-1 min-h-0 overflow-y-auto":"";return r.jsxs("section",{className:`panel-section p-0.75 text-sm ${oe}`,children:[r.jsxs("header",{className:"panel-muted flex items-center justify-between text-xs",children:[r.jsx("span",{children:"Replay Sources"}),r.jsx("span",{children:f.length})]}),r.jsxs("div",{className:`grid gap-0.5 md:grid-cols-2 ${V}`,children:[r.jsx(O0,{title:"Rovers",items:F.rovers,selected:p,onToggle:te}),r.jsx(O0,{title:"Room Cams",items:F.rooms,selected:p,onToggle:te})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("label",{className:"panel-muted block text-xs",htmlFor:`${n}-title`,children:"Replay title"}),r.jsx("input",{id:`${n}-title`,type:"text",className:"field-input w-full text-xs",value:k,onChange:q=>{w(q.target.value),N(!0)},placeholder:X,maxLength:120}),r.jsxs("label",{className:"surface flex items-center gap-0.5 text-xs",children:[r.jsx("input",{type:"checkbox",checked:T,onChange:q=>{const L=!!q.target.checked;M(L),h(Z=>({...Z||{},[`${n}:includeSidebar`]:L}))},className:"accent-emerald-400"}),r.jsx("span",{children:"Include replay sidebar"})]}),r.jsx("button",{type:"button",className:"button-dark w-full text-xs disabled:opacity-40",onClick:ce,disabled:H,children:K>0?`Replay (${Math.ceil(K/1e3)}s)`:g?"Replay…":"Replay"}),y?r.jsx("div",{className:"text-xs text-amber-400",children:y}):null,E?r.jsx("div",{className:"text-xs text-emerald-300",children:E}):null]})]})}function O0({title:n,items:s,selected:l,onToggle:o}){return s.length?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs",children:n}),r.jsx("div",{className:"space-y-0.5",children:s.map(f=>r.jsxs("label",{className:"surface flex items-center gap-0.5 text-xs",children:[r.jsx("input",{type:"checkbox",checked:l.includes(f.key),onChange:()=>o(f.key),className:"accent-emerald-400"}),r.jsx("span",{className:`truncate ${f.type==="rover"?"rounded px-1 py-[1px] border border-transparent":""}`,style:f.type==="rover"?ca(f.color,.16):void 0,children:f.label})]},f.key))})]}):null}var ug={color:void 0,size:void 0,className:void 0,style:void 0,attr:void 0},L0=fs.createContext&&fs.createContext(ug),dj=["attr","size","title"];function mj(n,s){if(n==null)return{};var l=hj(n,s),o,f;if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(n);for(f=0;f=0)&&Object.prototype.propertyIsEnumerable.call(n,o)&&(l[o]=n[o])}return l}function hj(n,s){if(n==null)return{};var l={};for(var o in n)if(Object.prototype.hasOwnProperty.call(n,o)){if(s.indexOf(o)>=0)continue;l[o]=n[o]}return l}function ho(){return ho=Object.assign?Object.assign.bind():function(n){for(var s=1;sfs.createElement(s.tag,po({key:l},s.attr),fg(s.child)))}function Ti(n){return s=>fs.createElement(vj,ho({attr:po({},n.attr)},s),fg(n.child))}function vj(n){var s=l=>{var{attr:o,size:f,title:d}=n,h=mj(n,dj),p=f||l.size||"1em",x;return l.className&&(x=l.className),n.className&&(x=(x?x+" ":"")+n.className),fs.createElement("svg",ho({stroke:"currentColor",fill:"currentColor",strokeWidth:"0"},l.attr,o,h,{className:x,style:po(po({color:n.color||l.color},l.style),n.style),height:p,width:p,xmlns:"http://www.w3.org/2000/svg"}),d&&fs.createElement("title",null,d),n.children)};return L0!==void 0?fs.createElement(L0.Consumer,null,l=>s(l)):s(ug)}function dg(n){return Ti({attr:{viewBox:"0 0 640 512"},child:[{tag:"path",attr:{d:"M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z"},child:[]}]})(n)}function bj(n){return Ti({attr:{viewBox:"0 0 448 512"},child:[{tag:"path",attr:{d:"M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"},child:[]}]})(n)}function U0(n){return Ti({attr:{viewBox:"0 0 640 512"},child:[{tag:"path",attr:{d:"M192 384h192c53 0 96-43 96-96h32c70.6 0 128-57.4 128-128S582.6 32 512 32H120c-13.3 0-24 10.7-24 24v232c0 53 43 96 96 96zM512 96c35.3 0 64 28.7 64 64s-28.7 64-64 64h-32V96h32zm47.7 384H48.3c-47.6 0-61-64-36-64h583.3c25 0 11.8 64-35.9 64z"},child:[]}]})(n)}function yj(n){return Ti({attr:{viewBox:"0 0 640 512"},child:[{tag:"path",attr:{d:"M528 448H112c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h416c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm64-320c-26.5 0-48 21.5-48 48 0 7.1 1.6 13.7 4.4 19.8L476 239.2c-15.4 9.2-35.3 4-44.2-11.6L350.3 85C361 76.2 368 63 368 48c0-26.5-21.5-48-48-48s-48 21.5-48 48c0 15 7 28.2 17.7 37l-81.5 142.6c-8.9 15.6-28.9 20.8-44.2 11.6l-72.3-43.4c2.7-6 4.4-12.7 4.4-19.8 0-26.5-21.5-48-48-48S0 149.5 0 176s21.5 48 48 48c2.6 0 5.2-.4 7.7-.8L128 416h384l72.3-192.8c2.5.4 5.1.8 7.7.8 26.5 0 48-21.5 48-48s-21.5-48-48-48z"},child:[]}]})(n)}function Sj(n){return Ti({attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"},child:[]}]})(n)}function jj(n){switch(n){case"admin":case"lockdown":case"lockdown-admin":return"text-amber-300";case"spectator":return"text-slate-400";default:return"text-sky-300"}}function sd(n){return!!n?.system}function Aj(n){const s=new Date(n);return`${s.getHours().toString().padStart(2,"0")}:${s.getMinutes().toString().padStart(2,"0")}`}function H0(n){return n.nickname||n.socketId?.slice(0,6)||"unknown"}function Nj({guildIconUrl:n,userAvatarUrl:s,label:l}){return!n&&!s?null:r.jsxs("span",{className:"flex h-4 w-4 overflow-hidden rounded-full border border-slate-700/80",title:l,children:[r.jsx("span",{className:`h-full w-1/2 bg-slate-700/70 ${n?"bg-cover":""}`,style:n?{backgroundImage:`url(${n})`,backgroundPosition:"left center",backgroundSize:"200% 100%"}:void 0}),r.jsx("span",{className:`h-full w-1/2 bg-slate-700/70 ${s?"bg-cover":""}`,style:s?{backgroundImage:`url(${s})`,backgroundPosition:"right center",backgroundSize:"200% 100%"}:void 0})]})}function mg({message:n}){const s=n.fromDiscord?`${n.discordGuildName||"Discord"} · ${H0(n)}`:null,l=sd(n),o=l?"text-emerald-300":jj(n.role);return r.jsxs(r.Fragment,{children:[n.fromDiscord?r.jsxs(r.Fragment,{children:[r.jsx(dg,{className:"h-3.5 w-3.5 text-indigo-200"}),r.jsx(Nj,{guildIconUrl:n.discordGuildIconUrl,userAvatarUrl:n.discordUserAvatarUrl,label:s})]}):null,r.jsx("span",{className:`font-semibold text-[0.85rem] ${o}`,children:H0(n)}),l?r.jsx("span",{className:"rounded bg-emerald-900/60 px-1 text-[0.65rem] font-semibold uppercase tracking-wide text-white",children:"bot"}):null,n.roverId&&r.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem]",style:uj(n.roverColor,.14),children:n.roverId})]})}function hg(n){return sd(n)?"surface-muted relative flex flex-wrap items-start gap-0.5 border border-emerald-500/40 bg-emerald-900/15 text-sm":`surface-muted relative flex flex-wrap items-start gap-0.5 text-sm ${n.role==="admin"||n.role==="lockdown"||n.role==="lockdown-admin"?"border border-amber-400/30":n.fromDiscord?"border border-indigo-400/30 bg-indigo-900/20":""}`}function ld({message:n}){const s=sd(n);return r.jsxs("div",{className:hg(n),children:[r.jsx(mg,{message:n}),r.jsx("span",{className:`break-words leading-tight whitespace-pre-wrap ${s?"text-emerald-100":"text-slate-100"}`,children:n.text}),r.jsx("span",{className:"absolute bottom-0.5 right-1 text-[0.65rem] text-slate-400/60",children:Aj(n.ts)})]})}function pg({message:n}){return r.jsxs("div",{className:`${hg(n)} italic opacity-80 border-slate-600/40 bg-slate-900/40`,children:[r.jsx(mg,{message:n}),r.jsx("span",{className:"text-slate-300",children:"typing..."})]})}function xg({buttonId:n,count:s,goal:l,rewardNumber:o,rewardName:f,className:d=""}){return r.jsxs("article",{className:["surface px-0.5 py-0.5 text-center",d].filter(Boolean).join(" "),children:[r.jsxs("p",{className:"text-xs text-slate-400",children:["Button ",n]}),r.jsxs("p",{className:"text-sm font-semibold text-white",children:[s," / ",l]}),r.jsxs("p",{className:"truncate text-[0.7rem] text-slate-300",children:["#",o," ",f]})]})}const wj=3e3,Cj=3500,Ej="#2196f3";function kj(n){return n.id?n.id:n.timestamp?`${n.timestamp}-${n.message}`:`${n.title||"alert"}-${n.message}`}function id({scale:n=1}){const s=ft(S=>S.alerts),l=ft(S=>S.session),{pushAlert:o}=wn(),f=tn(),[d,h]=m.useState(()=>Date.now());m.useEffect(()=>{function S(E={}){const C=Number(E.buttonId);if(!Number.isFinite(C)||C<1||C>4)return;const w=(Array.isArray(l?.buttonBox?.buttons)?l.buttonBox.buttons:[]).find(O=>Number(O?.id)===C)||{},j=Number.isFinite(E.count)?E.count:Number(w.count)||0,N=Number.isFinite(w.goal)?w.goal:0,T=Number.isFinite(w.rewardNumber)?w.rewardNumber:"?",M=typeof w.rewardName=="string"&&w.rewardName.trim()?w.rewardName.trim():"Unassigned";o({id:`buttonbox-active-${C}`,kind:"buttonbox-active",lifetimeMs:Cj,payload:{buttonId:C,count:j,goal:N,rewardNumber:T,rewardName:M}})}return f.on("buttonBox:increment",S),()=>{f.off("buttonBox:increment",S)}},[o,l?.buttonBox?.buttons,f]);const p=m.useMemo(()=>s.slice(-12).map(S=>({alert:S,key:kj(S)})),[s]);m.useEffect(()=>{if(!p.length)return;const S=setInterval(()=>h(Date.now()),200);return()=>clearInterval(S)},[p.length]);const x=new Map;p.forEach(S=>{const E=d-(S.alert.receivedAt??S.alert.timestamp??0),C=Number.isFinite(S.alert.lifetimeMs)?S.alert.lifetimeMs:wj;E<=C&&x.set(S.key,{...S,age:E})});const g=Array.from(x.values()).slice(-3);if(!g.length)return null;const v=n===1?void 0:{transform:`translateX(-50%) scale(${n})`,transformOrigin:"top center"},y=n===1?"pointer-events-none fixed top-0.5 left-1/2 z-50 flex -translate-x-1/2 flex-col gap-0.5":"pointer-events-none fixed top-0.5 left-1/2 z-50 flex flex-col gap-0.5";return r.jsx("div",{className:y,style:v,children:g.map(S=>r.jsx(Mj,{alert:S.alert},S.key))})}function V0(n){const s=typeof n=="string"?n.trim():"",l=/^#?([0-9a-fA-F]{6})$/.exec(s);if(!l)return null;const o=l[1];return{r:parseInt(o.slice(0,2),16),g:parseInt(o.slice(2,4),16),b:parseInt(o.slice(4,6),16)}}function Mj({alert:n}){if(n.kind==="buttonbox-active"&&n.payload){const f=n.payload;return r.jsx("div",{className:"pointer-events-none w-[12.5rem]",children:r.jsx(xg,{buttonId:f.buttonId,count:f.count,goal:f.goal,rewardNumber:f.rewardNumber,rewardName:f.rewardName,className:"bg-cyan-900/45"})})}if(n.kind==="chat"&&n.payload)return r.jsx(ld,{message:n.payload});if(n.kind==="chat-typing"&&n.payload)return r.jsx(pg,{message:n.payload});const s=V0(n.color)||V0(Ej),l=s?`rgba(${s.r}, ${s.g}, ${s.b}, 0.18)`:"rgba(33, 150, 243, 0.18)",o=s?`rgba(${s.r}, ${s.g}, ${s.b}, 0.45)`:"rgba(33, 150, 243, 0.45)";return r.jsx("div",{className:"pointer-events-auto max-w-[80vw] rounded-full border px-2 py-0.5 text-[0.7rem] leading-tight text-slate-100 shadow-sm shadow-black/30",style:{backgroundColor:l,border:`1px solid ${o}`},children:r.jsxs("p",{className:"truncate text-slate-100",children:[r.jsx("span",{className:"text-slate-300",children:n.title||"Alert"}),r.jsx("span",{className:"text-slate-500",children:" · "}),r.jsx("span",{className:"text-white",children:n.message})]})})}const tl={main:[-127,127],side:[-127,127],vacuum:[0,127]},sf={maxSpeed:500,baseSpeed:250,boostSpeed:400},Tf=100,rd=[31,127],il=60,Df=8,Rj=250,qj=4e3,Zr=.4,$0=.2,G0=.8,Tj={start:[128],safe:[131],full:[132],passive:[128],dock:[143]},gi={driveForward:["w"],driveBackward:["s"],driveLeft:["a"],driveRight:["d"],boostModifier:["\\"],slowModifier:["shift"],auxMainForward:["i"],auxMainReverse:["k"],auxSideForward:["o"],auxSideReverse:["l"],auxVacuumFast:["p"],auxVacuumSlow:[";"],auxAllForward:[","],cameraUp:["u"],cameraDown:["j"],nightVisionToggle:["e"],hornHonk:["h"],micPtt:["m"],driveMacro:["f"],dockMacro:["g"],chatFocus:["enter"],songNoteUp:["ArrowUp"],songNoteDown:["ArrowDown"],homeAssistantOn:["ArrowRight"],homeAssistantOff:["ArrowLeft"]},gg=[{id:"drive-sequence",label:"Drive",description:"Start, undock, and full command sequence used by the drive button.",steps:[{type:"servo",angle:0},{type:"oi",command:"start"},{type:"pause",duration:Tf},{type:"oi",command:"dock"},{type:"pause",duration:Tf},{type:"oi",command:"full"},{type:"pause",duration:300},{type:"drive",speeds:{left:-300,right:-300}},{type:"pause",duration:600},{type:"drive",speeds:{left:0,right:0}}]},{id:"seek-dock",label:"Dock",description:"Send the seek dock command.",steps:[{type:"oi",command:"dock"}]}];function _f(){return{vector:{x:0,y:0,boost:!1},speeds:{left:0,right:0},source:null,lastUpdatedAt:0}}function Bf(){return{main:0,side:0,vacuum:0}}function Dj(){return{enabled:!1,angle:null,config:null}}function co(){return{note:il}}function pi(){return{active:!1,heat:0,overheated:!1}}function uo(){return{pttActive:!1}}const Y0={roverId:null,mode:"drive",drive:_f(),aux:Bf(),camera:Dj(),song:co(),horn:pi(),mic:uo(),lastControlIntentAt:0,macros:gg,keymap:gi,inputs:{}};function _j(n,s){switch(s.type){case"control/set-rover":return{...n,roverId:s.payload??null,drive:s.payload?n.drive:_f(),aux:s.payload?n.aux:Bf(),song:s.payload?n.song:co(),horn:s.payload?n.horn:pi(),mic:s.payload?n.mic:uo(),lastControlIntentAt:s.payload?n.lastControlIntentAt:0};case"control/set-mode":return n.mode===s.payload?n:{...n,mode:s.payload==="dock"?"dock":"drive"};case"control/update-drive":{const{vector:l,speeds:o,source:f}=s.payload;return{...n,drive:{vector:l??n.drive.vector,speeds:o??n.drive.speeds,source:f??n.drive.source,lastUpdatedAt:Date.now()}}}case"control/set-aux-motors":return{...n,aux:{...n.aux,...s.payload}};case"control/set-camera-config":return{...n,camera:{...n.camera,enabled:!!s.payload?.config,config:s.payload?.config??null,angle:typeof s.payload?.angle=="number"?s.payload.angle:s.payload?.config?s.payload.config.homeAngle??n.camera.angle:null}};case"control/set-camera-angle":return{...n,camera:{...n.camera,angle:s.payload}};case"control/register-input-state":{const l=s.payload?.source||"unknown";return{...n,inputs:{...n.inputs,[l]:{...n.inputs[l]??{},...s.payload?.state,updatedAt:Date.now()}}}}case"control/set-keymap":return{...n,keymap:{...n.keymap,...s.payload??{}}};case"control/set-macros":return{...n,macros:Array.isArray(s.payload)?s.payload:n.macros};case"control/reset":return{...n,drive:_f(),aux:Bf(),song:co(),horn:pi(),mic:uo(),lastControlIntentAt:0};case"control/set-horn-active":return{...n,horn:{...n.horn||pi(),active:!!s.payload}};case"control/set-horn-heat":return{...n,horn:{...n.horn||pi(),heat:typeof s.payload?.heat=="number"?s.payload.heat:0,overheated:!!s.payload?.overheated}};case"control/record-intent":return{...n,lastControlIntentAt:Date.now()};case"control/set-song-note":return{...n,song:{...n.song||co(),note:s.payload??il}};case"control/set-mic-ptt":return{...n,mic:{...n.mic||uo(),pttActive:!!s.payload}};default:return n}}function rl(n,s,l){return typeof n!="number"||Number.isNaN(n)?s:Math.max(s,Math.min(l,n))}function ol(n){return typeof n!="number"||Number.isNaN(n)?0:Math.max(-1,Math.min(1,n))}function pn(n,s){return!Array.isArray(s)||s.length!==2?n:rl(n,s[0],s[1])}function Bj(n={}){const s=ol(n.x??0),l=ol(n.y??0);return{x:s,y:l,boost:!!n.boost}}function Oj(n={},s={}){const l=Bj(n),o=typeof s.maxSpeed=="number"?s.maxSpeed:sf.maxSpeed,f=typeof s.baseSpeed=="number"?s.baseSpeed:sf.baseSpeed,d=typeof s.boostSpeed=="number"?s.boostSpeed:sf.boostSpeed,h=l.boost?d:f,p=l.y*h,x=l.x*h;return{vector:l,speeds:{left:rl(Math.round(p+x),-o,o),right:rl(Math.round(p-x),-o,o)}}}function Lj(n){const s=Array.isArray(n)?n:[],l=String.fromCharCode(...s);if(typeof btoa=="function")return btoa(l);if(typeof Buffer<"u")return Buffer.from(s).toString("base64");throw new Error("No base64 encoder available")}function F0(n){return new Promise(s=>setTimeout(s,n))}function zj(n={}){const{driveTransform:s,auxTransform:l}=n,o=tn(),f=ft(O=>O.session),d=f?.assignment?.roverId,h=m.useMemo(()=>!d||!Array.isArray(f?.roster)?null:f.roster.find(O=>String(O.id)===String(d))||null,[d,f?.roster]),p=m.useMemo(()=>!h?.cameraServo||!h.cameraServo.enabled?null:h.cameraServo,[h]),x=m.useMemo(()=>!h?.nightVision||!h.nightVision.enabled?null:h.nightVision,[h]),g=m.useMemo(()=>!h?.horn||!h.horn.enabled?null:h.horn,[h]),v=m.useMemo(()=>h?.nightVision?.state??null,[h]),y=m.useCallback((O,K)=>{d&&o.emit("command",{roverId:d,...O},K)},[o,d]),S=m.useCallback(()=>{d&&y({type:"sensorStream",data:{sensorStream:{enable:!0}}})},[y,d]),E=m.useCallback(O=>{if(!d)return null;const K={left:pn(O?.left??0,[-500,500]),right:pn(O?.right??0,[-500,500])},_=s?s(K):K,U={left:pn(_?.left??0,[-500,500]),right:pn(_?.right??0,[-500,500])};return y({type:"drive",data:{driveDirect:U}}),U},[s,y,d]),C=m.useCallback(({main:O=0,side:K=0,vacuum:_=0}={})=>{if(!d)return null;const U={main:pn(O,tl.main),side:pn(K,tl.side),vacuum:pn(_,tl.vacuum)},X=l?l(U):U,F={main:pn(X?.main??0,tl.main),side:pn(X?.side??0,tl.side),vacuum:pn(X?.vacuum??0,tl.vacuum)};return y({type:"motors",data:{motorPwm:F}}),F},[l,y,d]),k=m.useCallback(O=>!d||!p?null:(y({type:"servo",data:{servo:{angle:O}}}),O),[y,d,p]),w=m.useCallback(O=>{if(!d)return!1;const K=Array.isArray(O)?O:typeof O=="string"?Tj[O]:null;return K?(y({type:"raw",data:{raw:Lj(K)}}),S(),!0):!1},[y,S,d]),j=m.useCallback(async O=>{if(!(!O||!Array.isArray(O.steps)||!d))for(const K of O.steps){if(!d)break;switch(K.type){case"oi":w(K.command);break;case"drive":E(K.speeds??{left:0,right:0});break;case"motors":C(K.values??{});break;case"servo":k(K.angle);break;case"pause":await F0(K.duration??Tf);break}if(K.delay||K.delayMs){const _=K.delayMs??K.delay;typeof _=="number"&&_>0&&await F0(_)}}},[d,w,E,C,k]),N=m.useCallback((O="toggle")=>!d||!x?null:(y({type:"nightVision",data:{nightVision:{action:O}}}),O),[y,x,d]),T=m.useCallback(O=>d?(y({type:"horn",data:{horn:O}}),O):null,[y,d]),M=m.useCallback((O=[],K={})=>{if(!d)return null;const U=(Array.isArray(O)&&O.length>0?O:[{note:il,duration:Df}]).slice(0,16).map(X=>({note:pn(Math.round(X?.note??il),rd),duration:pn(Math.round(X?.duration??Df),[1,255])}));return y({type:"song",data:{song:{notes:U,slot:K.slot,loop:K.loop}}}),U},[y,d]);return m.useMemo(()=>({roverId:d,rosterEntry:h,servoConfig:p,nightVision:x,nightVisionState:v,horn:g,emitCommand:y,enableSensorStream:S,sendDriveDirect:E,sendAuxMotors:C,sendServoAngle:k,sendOiCommand:w,sendNightVision:N,sendHorn:T,sendSong:M,runMacroSteps:j}),[d,h,p,x,v,g,y,S,E,C,k,w,N,T,j])}const Uj={"{":"[","}":"]",":":";",'"':"'","<":",",">":".","?":"/","|":"\\",_:"-","+":"="},X0={"[":"BracketLeft","]":"BracketRight","\\":"Backslash",";":"Semicolon","'":"Quote",",":"Comma",".":"Period","/":"Slash","-":"Minus","=":"Equal","`":"Backquote"};function Di(n){if(typeof n!="string")return"";const s=n.toLowerCase();return Uj[s]??s}function Hj(n){const s=Di(n);if(!s)return null;if(X0[s])return X0[s];if(s.length===1){if(/[a-z]/.test(s))return`Key${s.toUpperCase()}`;if(/[0-9]/.test(s))return`Digit${s}`}return null}function vg(n){const s=Di(n);return s?`key:${s}`:null}function Vj(n){const s=Hj(n);return s?`code:${s}`:null}function Q0(n){const s=new Set,l=vg(n?.key??"");l&&s.add(l);const o=n?.code?`code:${n.code}`:null;return o&&s.add(o),Array.from(s)}function $j(n={}){return Object.fromEntries(Object.entries(n).map(([s,l])=>{const o=Array.isArray(l)?l:[l],f=new Set;return o.forEach(d=>{const h=vg(String(d));h&&f.add(h);const p=Vj(String(d));p&&f.add(p)}),[s,f]}))}function An(n){const s=Di(n);return s?s===" "?"Space":s==="\\"?"Backslash":s==="`"?"Backtick":s==="["?"[ or {":s==="]"?"] or }":s===";"?"; or :":s==="'"?`' or "`:s===","?", or <":s==="."?". or >":s==="/"?"/ or ?":s==="-"?"- or _":s==="="?"= or +":s==="arrowup"?"Arrow Up":s==="arrowdown"?"Arrow Down":s==="arrowleft"?"Arrow Left":s==="arrowright"?"Arrow Right":s.length===1?s.toUpperCase():s:"—"}const qn={keyboard:{baseSpeed:250,turboSpeed:400,precisionSpeed:125,tiltSpeed:100,tiltIntervalMs:110}},ia={label:"Default",calibration:{driveDeadzone:.18,cameraDeadzone:.08,auxDeadzone:.05,driveCurve:"linear",cameraCurve:"linear",auxCurve:"linear",cameraMode:"absolute",cameraSensitivity:60,auxSideScale:.55},bindings:{drive:{kind:"axisPair",sources:[{kind:"axisPair",x:0,y:1,invertX:!1,invertY:!0}]},cameraTilt:{kind:"axis",sources:[{kind:"axis",index:3,invert:!0},{kind:"axis",index:1,invert:!0}]},mainBrush:{kind:"axis",sources:[{kind:"buttonAxis",index:6},{kind:"axis",index:2,invert:!1}]},sideBrush:{kind:"axis",sources:[{kind:"buttonAxis",index:7},{kind:"axis",index:5,invert:!1}]},vacuum:{kind:"button",sources:[{kind:"button",index:0}]},allAux:{kind:"button",sources:[{kind:"button",index:1}]},mainReverse:{kind:"button",sources:[{kind:"button",index:4}]},sideReverse:{kind:"button",sources:[{kind:"button",index:5}]},driveMacro:{kind:"button",sources:[{kind:"button",index:2}]},dockMacro:{kind:"button",sources:[{kind:"button",index:3}]},nightVisionToggle:{kind:"button",sources:[{kind:"button",index:9}]}}},Ba={activeSignature:null,profiles:{},defaults:{profile:ia}},us={waveform:"saw",freqs:[440,550,660,0]},ct={masterVolume:1,alertVolume:.5,roverVolume:1,mainBrushDuckEnabled:!0,mainBrushDuckAmount:.75},os=[{key:"drive",motors:["leftWheel","rightWheel"]},{key:"aux",motors:["mainBrush","sideBrush"]}],Gj={downRatePerSec:.15,upRatePerSec:.7,releaseDelaySec:1,outputRateMs:250};function K0(){return os.reduce((n,s)=>(n[s.key]={cap:1,clearSec:0},n),{})}function Z0(n){return Number.isFinite(n)?Math.max(0,Math.min(1,n)):0}function Yj(n,s={}){const l=ft(j=>j.session),d=(ml(n)?.sensors||{})?.wheelOvercurrents||{},h=m.useMemo(()=>({...Gj,...s.config||{}}),[s.config]),[p,x]=m.useState(()=>K0()),g=m.useRef(0),v=m.useRef(d);m.useEffect(()=>{v.current=d||{}},[d]),m.useEffect(()=>{x(K0()),g.current=0},[n]);const y=m.useMemo(()=>os.some(j=>j.motors.some(N=>!!d?.[N])),[d]),S=m.useMemo(()=>Object.values(p||{}).some(j=>(Number.isFinite(j?.cap)?j.cap:1)<.999),[p]),E=!!n&&(y||S);m.useEffect(()=>{if(!E)return;g.current=typeof performance<"u"?performance.now():Date.now();const j=setInterval(()=>{const N=typeof performance<"u"?performance.now():Date.now(),T=Math.max(0,N-g.current);g.current=N;const M=Math.min(.25,T/1e3);M<=0||x(O=>{let K=!1;const _={},U=Number.isFinite(h.downRatePerSec)?Math.max(0,h.downRatePerSec):0,X=Number.isFinite(h.upRatePerSec)?Math.max(0,h.upRatePerSec):0,F=Number.isFinite(h.releaseDelaySec)?Math.max(0,h.releaseDelaySec):0;return os.forEach(H=>{const te=O[H.key]||{cap:1,clearSec:0},ce=Number.isFinite(te.cap)?te.cap:1,oe=Number.isFinite(te.clearSec)?te.clearSec:0,V=H.motors.some(le=>!!v.current?.[le]),q=V?0:oe+M,L=!V&&q>=F,Z=Z0(V?ce-U*M:L?ce+X*M:ce);(Math.abs(Z-ce)>1e-4||Math.abs(q-oe)>1e-4)&&(K=!0),_[H.key]={cap:Z,clearSec:q}}),K?_:O})},100);return()=>clearInterval(j)},[h.downRatePerSec,h.releaseDelaySec,h.upRatePerSec,n,E]);const C=m.useMemo(()=>{const j=os.reduce((N,T)=>{const M=p?.[T.key],O=Number.isFinite(M?.cap)?M.cap:1;return N[T.key]=Z0(O),N},{});return{perGroup:j,drive:{left:j.drive??1,right:j.drive??1},aux:{main:j.aux??1,side:j.aux??1,vacuum:1}}},[p]),k=m.useMemo(()=>{const j={};os.forEach(T=>{T.motors.forEach(M=>{j[M]=!!d?.[M]})});const N=os.reduce((T,M)=>(T[M.key]=M.motors.some(O=>!!d?.[O]),T),{});return{motors:j,groups:N}},[d]),w=l?.role==="admin"||l?.role==="lockdown"||l?.role==="lockdown-admin";return m.useMemo(()=>({caps:p,overcurrent:k,scales:C,isActive:(C?.drive?.left??1)<1||(C?.drive?.right??1)<1||(C?.aux?.main??1)<1||(C?.aux?.side??1)<1,config:h,adminImmune:w}),[p,k,C,h,w])}function Fj(n={},s,l=!1){if(l||!s?.drive)return n;const o=typeof s.drive.left=="number"?s.drive.left:1,f=typeof s.drive.right=="number"?s.drive.right:1;return o>=.999&&f>=.999?n:{left:Math.round((n.left??0)*o),right:Math.round((n.right??0)*f)}}function Xj(n={},s,l=!1){if(l||!s?.aux)return n;const o=typeof s.aux.main=="number"?s.aux.main:1,f=typeof s.aux.side=="number"?s.aux.side:1,d=typeof s.aux.vacuum=="number"?s.aux.vacuum:1;return o>=.999&&f>=.999&&d>=.999?n:{main:Math.round((n.main??0)*o),side:Math.round((n.side??0)*f),vacuum:Math.round((n.vacuum??0)*d)}}const bg=m.createContext(null);function I0(n){return Object.fromEntries(Object.entries(n||{}).map(([s,l])=>[s,Array.isArray(l)?[...l]:[]]))}function Qj(n,s){if(!n)return s;const l=typeof n.minAngle=="number"?n.minAngle:-45,o=typeof n.maxAngle=="number"?n.maxAngle:45;return rl(s,l,o)}function Kj(n=[]){if(!Array.isArray(n)||n.length<3)return n;const s=n.slice(-3),[l,o,f]=s,d=l?.type==="drive"&&Number(l?.speeds?.left)===-300&&Number(l?.speeds?.right)===-300,h=o?.type==="pause"&&Number(o?.duration)===600,p=f?.type==="drive"&&Number(f?.speeds?.left)===0&&Number(f?.speeds?.right)===0;return!d||!h||!p?n:n.slice(0,-3)}function Zj({children:n}){const[s,l]=m.useReducer(_j,Y0),o=m.useRef(null),f=m.useRef(!1),d=m.useRef(Y0.camera.angle),h=m.useRef(null),p=m.useRef(0),x=m.useRef(0),{value:g,save:v}=He("controls",{keymap:gi,macros:gg}),{value:y}=He("page",{driveMacroBackoffEnabled:!0}),{value:S}=He("horn",us),E=typeof y?.driveMacroBackoffEnabled=="boolean"?y.driveMacroBackoffEnabled:!0,C=ft(ie=>ie.session),{homeAssistantSetState:k}=wn(),w=C?.assignment?.roverId??null,j=Yj(w),N=m.useCallback(ie=>Fj(ie,j.scales,j.adminImmune),[j.adminImmune,j.scales]),T=m.useCallback(ie=>Xj(ie,j.scales,j.adminImmune),[j.adminImmune,j.scales]),M=zj({driveTransform:N,auxTransform:T}),O=m.useCallback(()=>{const me=(C?.homeAssistant?.entities||[]).filter(se=>(se.type==="light"||se.type==="switch")&&se.available!==!1&&se.state!=="on");if(me.length===0){f.current=!1;return}f.current=!0,me.forEach(se=>{k(se.id,"on").catch(()=>{})}),f.current=!1},[C?.homeAssistant?.entities,k]);m.useEffect(()=>{l({type:"control/set-rover",payload:M.roverId})},[M.roverId]),m.useEffect(()=>{const ie=o.current;o.current=s.mode,ie!=="drive"&&s.mode==="drive"&&C?.homeAssistant?.entities?O():ie!=="drive"&&s.mode==="drive"&&(f.current=!0)},[s.mode,C?.homeAssistant?.entities,O]),m.useEffect(()=>{f.current&&C?.homeAssistant?.entities&&O()},[C?.homeAssistant?.entities,O]),m.useEffect(()=>{const ie={...gi,...g?.keymap||{}};l({type:"control/set-keymap",payload:ie}),g?.macros&&l({type:"control/set-macros",payload:g.macros})},[g?.keymap,g?.macros]),m.useEffect(()=>{const ie=M.servoConfig;if(!ie){l({type:"control/set-camera-config",payload:{config:null}}),d.current=null;return}const me=typeof ie.minAngle=="number"?ie.minAngle:-45,se=typeof ie.maxAngle=="number"?ie.maxAngle:45,P=typeof ie.homeAngle=="number"?ie.homeAngle:(me+se)/2,de=typeof d.current=="number"?rl(d.current,me,se):null,Ne=de??rl(P,me,se);l({type:"control/set-camera-config",payload:{config:ie,angle:Ne}}),d.current=Ne},[M.servoConfig]),m.useEffect(()=>{d.current=typeof s.camera.angle=="number"?s.camera.angle:d.current},[s.camera.angle]),m.useEffect(()=>{M.roverId&&M.enableSensorStream()},[M.roverId,M.enableSensorStream]);const K=m.useCallback(ie=>{l({type:"control/set-mode",payload:ie})},[]),_=m.useCallback(()=>{l({type:"control/record-intent"})},[]),U=m.useRef(s.drive.speeds),X=m.useRef(s.aux),F=m.useMemo(()=>JSON.stringify(j.scales),[j.scales]),H=m.useRef(0),te=m.useRef(0);m.useEffect(()=>{U.current=s.drive.speeds},[s.drive.speeds]),m.useEffect(()=>{X.current=s.aux},[s.aux]),m.useEffect(()=>{if(!M.roverId||j.adminImmune||!j.isActive)return;const ie=Math.max(0,Number(j?.config?.outputRateMs)||0),me=typeof performance<"u"?performance.now():Date.now(),se=U.current||{left:0,right:0},P=X.current||{main:0,side:0,vacuum:0},de=!!(se.left||se.right),Ne=!!(P.main||P.side||P.vacuum);!de&&!Ne||(de&&me-H.current>=ie&&(H.current=me,M.sendDriveDirect(se)),Ne&&me-te.current>=ie&&(te.current=me,M.sendAuxMotors(P)))},[F,j.adminImmune,j.config,j.isActive,M]);const ce=m.useCallback((ie,me={})=>{const se=Oj(ie,me.speedOptions);l({type:"control/update-drive",payload:{...se,source:me.source??null}}),_(),M.sendDriveDirect(se.speeds)},[M,_]),oe=m.useCallback((ie={})=>{const me=M.sendAuxMotors(ie)??ie;l({type:"control/set-aux-motors",payload:me}),_()},[M,_]),V=m.useCallback((ie,me)=>{if(!ie)return!1;const se=Di(me);if(!se)return!1;const P=I0(s.keymap);return P[ie]=[se],l({type:"control/set-keymap",payload:P}),v(de=>({...de??{},keymap:P})),!0},[s.keymap,v]),q=m.useCallback(()=>{const ie=I0(gi);l({type:"control/set-keymap",payload:ie}),v(me=>({...me??{},keymap:ie}))},[v]),L=m.useCallback(ie=>{if(!M.servoConfig)return;const me=Qj(M.servoConfig,ie);l({type:"control/set-camera-angle",payload:me}),M.sendServoAngle(me),d.current=me,_()},[M,_]),Z=m.useCallback((ie=0)=>{const me=M.servoConfig;if(!me)return;const se=typeof ie=="number"&&ie!==0?ie:me.nudgeDegrees||1,P=typeof d.current=="number"?d.current:typeof me.homeAngle=="number"?me.homeAngle:0;L(P+se)},[M.servoConfig,L]),le=m.useCallback(()=>{const ie=M.servoConfig;if(!ie)return;const me=typeof ie.homeAngle=="number"?ie.homeAngle:typeof ie.minAngle=="number"&&typeof ie.maxAngle=="number"?(ie.minAngle+ie.maxAngle)/2:0;L(me)},[M.servoConfig,L]),fe=m.useCallback(async ie=>{const me=s.macros.find(P=>P.id===ie)||null;if(!me)return;let se=me;ie==="drive-sequence"?(O(),C?.homeAssistant?.entities||(f.current=!0),_(),E||(se={...me,steps:Kj(me.steps)})):ie==="seek-dock"&&_(),await M.runMacroSteps(se)},[E,M,_,C?.homeAssistant?.entities,s.macros,O]),R=m.useCallback(()=>{l({type:"control/update-drive",payload:{vector:{x:0,y:0,boost:!1},speeds:{left:0,right:0},source:"system-stop"}}),M.sendDriveDirect({left:0,right:0}),M.sendAuxMotors({main:0,side:0,vacuum:0})},[M]),$=m.useCallback(ie=>{M.sendOiCommand(ie)},[M]),ee=m.useCallback(ie=>{M.roverId&&M.emitCommand({type:"sensorStream",data:{sensorStream:{enable:ie}}})},[M]),ae=m.useCallback(ie=>{if(M.nightVision){if(typeof ie=="boolean"){const me=ie?"off":"on";M.sendNightVision(me)}else M.sendNightVision("toggle");_()}},[M,_]),pe=m.useCallback(()=>{ae()},[ae]),re=m.useCallback(ie=>{const me=typeof ie=="number"?ie:il;return l({type:"control/set-song-note",payload:me}),me},[]),ue=m.useCallback((ie,me)=>M.sendSong(ie,me),[M]),ve=m.useMemo(()=>{const ie=S??us,me=ie.waveform==="sine"?"sine":"saw",P=[...Array.isArray(ie.freqs)?ie.freqs:us.freqs,0,0,0,0].slice(0,4).map(de=>{const Ne=Number(de);return Number.isFinite(Ne)?Ne<=0?0:Math.min(5e3,Math.round(Ne)):0});return{waveform:me,freqs:P}},[S]),be=m.useCallback(()=>{if(!M.horn)return;if(s.horn?.overheated||(s.horn?.heat??0)>=1||s.horn?.active)return!1;const ie=Date.now();return M.sendHorn({action:"start",...ve}),l({type:"control/set-horn-active",payload:!0}),p.current=ie,x.current=ie,h.current&&(clearTimeout(h.current),h.current=null),h.current=setTimeout(()=>{xe()},qj),_(),!0},[l,ve,M,_,s.horn?.active,s.horn?.heat,s.horn?.overheated]),xe=m.useCallback(()=>{if(!M.horn)return;M.sendHorn({action:"stop"}),l({type:"control/set-horn-active",payload:!1}),h.current&&(clearTimeout(h.current),h.current=null);const ie=Date.now(),me=p.current||ie,se=Math.max(0,ie-me);if(p.current=0,se>0){const P=s.horn?.heat??0,de=se/1e3*Zr;let Ne=Math.max(0,Math.min(1,P+de)),pt=s.horn?.overheated??!1;Ne>=1&&(Ne=1,pt=!0),l({type:"control/set-horn-heat",payload:{heat:Ne,overheated:pt}})}},[l,M,s.horn?.heat,s.horn?.overheated,Zr]),Be=m.useRef({active:!!s.horn?.active,heat:s.horn?.heat??0,overheated:!!s.horn?.overheated}),ze=m.useRef(xe);m.useEffect(()=>{Be.current={active:!!s.horn?.active,heat:s.horn?.heat??0,overheated:!!s.horn?.overheated}},[s.horn?.active,s.horn?.heat,s.horn?.overheated]),m.useEffect(()=>{ze.current=xe},[xe]);const Ae=!!s.horn?.active||(s.horn?.heat??0)>0||!!s.horn?.overheated;m.useEffect(()=>{if(!Ae)return;const me=setInterval(()=>{const se=Date.now(),P=x.current||se;x.current=se;const de=Math.min(1e3,Math.max(0,se-P))/1e3,Ne=Be.current,pt=Ne.heat??0,Ve=!!Ne.active,st=!!Ne.overheated,lt=de*(Ve?Zr:-$0);let Ot=Math.max(0,Math.min(1,pt+lt)),it=st;Ot>=1?(Ot=1,it=!0,Ve&&ze.current()):it&&Ot<=G0&&(it=!1),(Ot!==pt||it!==st)&&l({type:"control/set-horn-heat",payload:{heat:Ot,overheated:it}})},100);return()=>clearInterval(me)},[l,Ae,$0,G0,Zr]);const tt=m.useCallback((ie,me)=>{l({type:"control/register-input-state",payload:{source:ie,state:me}})},[]),Je=m.useCallback(ie=>{l({type:"control/set-mic-ptt",payload:!!ie})},[]),vt=m.useMemo(()=>({state:s,dispatch:l,pipeline:M,overcurrentLimiter:j,actions:{setMode:K,setDriveVector:ce,setAuxMotors:oe,setServoAngle:L,nudgeServo:Z,goServoHome:le,runMacro:fe,stopAllMotion:R,sendOiCommand:$,setSensorStream:ee,setNightVision:ae,toggleNightVision:pe,updateKeyBinding:V,resetKeyBindings:q,registerInputState:tt,setSongNote:re,sendSong:ue,startHorn:be,stopHorn:xe,setMicPttActive:Je}}),[s,M,j,K,ce,oe,L,Z,le,fe,R,$,ee,ae,pe,V,q,tt,re,ue,be,xe,Je]);return r.jsx(bg.Provider,{value:vt,children:n})}function _t(){const n=m.useContext(bg);if(!n)throw new Error("useControlSystem must be used within ControlSystemProvider");return n}const Ij="data:audio/mpeg;base64,//uQxAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAANAAAIpQBKSkpKSkpKXFxcXFxcXFxra2tra2tra3p6enp6enqJiYmJiYmJiZiYmJiYmJiYpqampqamprW1tbW1tbW1xMTExMTExMTT09PT09PT4uLi4uLi4uLx8fHx8fHx8f////////8AAABQTEFNRTMuMTAwBLkAAAAAAAAAABUgJAUYQQAB4AAACKVpqtMZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//ugxAAAwqQPR8CIwCh0BCj5jDwlIAAjW87wAACcOsAKPMk8ARj8w9OAWwNlV/gCgQMHEhAOVnFaNzWWAPI2zyjHjd8FAoKqyAa88AAAAABNjEd9CQOglIY9dtC+a51bGZrZgTewD3c+AAYx5hxIMheIcudKAyaykG1/h5EsPB0iTEFNRTMuMTAwqqqqqqrIBZqvAAAAAC9JXFIAHrCgAp0D0hUYOInIluqg1TNdKCzMeAAFQCKKsxUmVfireKILLBgSVgb4qBVtPWpMQU1FMy4xMDCqqqqqqqqqqqqqqqqpApm/AAAAAC7QYaHPHoCjkCysmc+QY9NNWRbKE+mqowNobwAAoSQQMLGChDlOrKMqVMC/6xy/CXbFaL7AZUxBTUUzLjEwMFVVVVVVVVVVVacDqZ8AAAAAMgzaYFBPNgIOnVCQfFfwmBBhLVNJQSdxdQRofwAGxF9xAAYs4AZDuE87li0YCASIBwaCiXUj+2BqTEFNRTMuMTAwqqqqqqqqlwOonwAAAAAtkABQSEZ1INNDgx8HeaaLCXiu5dqSciylQNXjv8GdmACQ5ogYKbnsmxkoChog+w9IhU6GsgzCIQBSxFpMQQAAMBiHjgAAAAv6FQQILmJmGLltnax9HszIVEAoEq1p8olpcPLlGpXFastuWosKNFlmlqADJbwAEFRI4iJJy0oDumUW//sgxOEAw5wfU8fnAGBvg6n5nDxUh7QuwcEzkK5Ztz7AZUxBTUUzLjEwMFVVVVVVVZUAhd8AAAAALZAAamQMWKtC7Avib0WLplt2IAp0SKV0pFFxCADLX6AIPFrWJIBQqPGW/x0QDTRLGaQYCRAZzKeoU6uqTEFN6AB3n/7wAAAxq//7EMT0AMPUHU/MawJgc4PpuYy8VQZjocBw2OgQQyQyECnbABEUC/ZoM0J56Jm0tqzNJaq8KospqUAQ5/QBghnCqQAhR4Mz1D1gJPstYsI1sYIg079I5cYjY6pMQU1FMy4xMDCqqqqq//sQxPUAw+AdT8zvAih6hCk5nWBFqqqWAFOf4AAAAEAIQZPkMcwUzFVE51cSBjIHpJRIEIjWgGar9VhgCUvwAFAUMk0RCpMkwXjPQDcoLBU+n5RuR4ZrPQLPckxBTUUzLjEwMKqqqqr/+xDE9oDEAB1NzG8CKIGEKPmd5EWqxgBWn9AAAAAKIiC5GcLJIczCEvNbWsF31jo4Bw0rXktvJF5YRyABlj+ABIQ2RGsHgdc0XsPntoEDUzaQOjTBqblFPUE1TEFNRckAt68AAAAALv/7EMT4AMQIHU3M7wIojwUo+Y2MZfAgKcwITAQIYN1TosJeLtDA0ubWNrFSADJoln4AC0hVaLiIIUChs+4HST4BgCpQHITPMBQkEnj73ORZfylh+sRLEGUiNIpMQU1FMy4xMDCqqqqq//sQxP6AxlgtK+13Yih3hCj5neBNqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrIkT7UNAZ7NS7yMqcihSKLMn8DlKYq8ZdPCVEoJBuWqkxBTUUzLjEwMKqqqqr/+xDE+ADEXCVHzGjDIIQEqLm9PIWqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7EMT+AMWoL0XNcwJoiASoeY3gVaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sQxPgAxHAnRcxvAmiBBKj5jehEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+xDE+IDEmCVDzPMCKH6EqLmNYE2qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7EMT9gEPgI0vMZwQgvYWlPY5gFaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sQxOYDw+gpIIfgwWgAADSAAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=",yg=m.createContext({messages:[],typing:[],sendMessage:async()=>{},focusChat:()=>{},blurChat:()=>{},registerInputRef:()=>{},onInputFocus:()=>{},onInputBlur:()=>{},setTypingActive:()=>{},isChatFocused:!1});function Jj({children:n}){const s=tn(),l=ft(V=>V.session),{pushAlert:o}=wn(),{value:f}=He("audio",ct),[d,h]=m.useState([]),[p,x]=m.useState([]),[g,v]=m.useState(!1),y=m.useRef(null),S=m.useRef(null),E=m.useRef(null),C=m.useRef(new Map),k=m.useRef(new Map),w=m.useRef({isTyping:!1,lastSent:0}),j=Number.isFinite(f?.masterVolume)?f.masterVolume:ct.masterVolume,N=Number.isFinite(f?.alertVolume)?f.alertVolume:ct.alertVolume,T=Math.max(0,Math.min(1,j*N)),M=m.useCallback(()=>{const V=Array.from(C.current.values()).sort((q,L)=>q.lastUpdate-L.lastUpdate).map(q=>q.payload);x(V)},[]),O=m.useCallback(V=>!V||typeof V!="object"?null:V.typingId?V.typingId:V.fromDiscord?`discord:${V.discordUserId||V.discordUserName||V.nickname||"unknown"}`:`socket:${V.socketId||V.nickname||"unknown"}`,[]);m.useEffect(()=>{E.current=new Audio(Ij),E.current.volume=T,E.current.load()},[T]);const K=m.useCallback(()=>{const V=E.current;V&&(V.volume=T,V.currentTime=0,V.play().catch(()=>{}))},[T]);m.useEffect(()=>{function V(q={}){h(L=>[...L.slice(-99),q]),!(q?.socketId&&l?.socketId&&q.socketId===l.socketId)&&(K(),o?.({kind:"chat",payload:q,id:`chat-${q.id||Math.random().toString(36).slice(2)}`,receivedAt:Date.now()}))}return s.on("chat:message",V),()=>{s.off("chat:message",V)}},[K,l?.socketId,s]),m.useEffect(()=>{function V(q={}){const L=O(q);if(!L)return;const Z=Date.now();if(q?.socketId&&l?.socketId&&q.socketId===l.socketId){q.isTyping||(C.current.delete(L),M());return}if(q.isTyping){C.current.set(L,{payload:q,expiresAt:Z+6e3,lastUpdate:Z});const le=k.current.get(L)||0;Z-le>=2500&&(k.current.set(L,Z),o?.({kind:"chat-typing",payload:q,id:`chat-typing-${L}-${q.id||Math.random().toString(36).slice(2)}`,receivedAt:Z}))}else C.current.delete(L);M()}return s.on("chat:typing",V),()=>{s.off("chat:typing",V)}},[o,M,O,l?.socketId,s]),m.useEffect(()=>{const V=setInterval(()=>{const q=Date.now();let L=!1;C.current.forEach((Z,le)=>{Z.expiresAt<=q&&(C.current.delete(le),L=!0)}),L&&M()},2e3);return()=>clearInterval(V)},[M]),m.useEffect(()=>{function V(q=[]){Array.isArray(q)&&h(L=>{if(L.length===0)return q.slice(-100);const Z=new Set(q.map(fe=>fe?.id));return[...q,...L.filter(fe=>fe?.id&&!Z.has(fe.id))].slice(-100)})}return s.on("chat:init",V),()=>{s.off("chat:init",V)}},[s]);const _=m.useCallback(V=>{const q=!!V,L=Date.now(),Z=w.current,le=!q&&Z.isTyping;!(q&&(!Z.isTyping||L-Z.lastSent>=3500))&&!le||(w.current={isTyping:q,lastSent:L},s.emit("chat:typing",{isTyping:q}))},[s]),U=m.useCallback((V,q=null)=>new Promise((L,Z)=>{s.emit("chat:send",{text:V,tts:q},(le={})=>{le.error?Z(new Error(le.error)):L(le)})}),[s]),X=m.useCallback((V,q={})=>{(q?.target==="hud"?"hud":"panel")==="hud"?S.current=V:y.current=V},[]),F=m.useCallback(()=>{v(!0),(S.current||y.current)?.focus()},[]),H=m.useCallback(()=>{v(!1),S.current?.blur(),y.current?.blur()},[]),te=m.useCallback(()=>v(!0),[]),ce=m.useCallback(()=>v(!1),[]),oe=m.useMemo(()=>({messages:d,sendMessage:U,focusChat:F,blurChat:H,registerInputRef:X,onInputFocus:te,onInputBlur:ce,setTypingActive:_,typing:p,isChatFocused:g,selfSocketId:l?.socketId||null}),[H,F,g,d,ce,te,X,U,l?.socketId,_,p]);return r.jsx(yg.Provider,{value:oe,children:n})}function od(){const n=m.useContext(yg);if(!n)throw new Error("useChat must be used inside ChatProvider");return n}let Sg=!1;function lf(n){Sg=!!n}function J0(){return Sg}const Pj=new Set(["","text","search","email","password","url","tel","number","date","datetime-local","month","time","week"]);function jg(n){if(!n||n.nodeType!==1)return!1;const s=n.tagName;if(s==="TEXTAREA"||n.isContentEditable)return!0;if(s!=="INPUT")return!1;const l=n.type?n.type.toLowerCase():"";return Pj.has(l)}function Wj(){return typeof document>"u"?!1:jg(document.activeElement)}const rf="keyboard",of={x:0,y:0,boost:!1},cf={main:0,side:0,vacuum:0},P0=rd[0],W0=rd[1],cd=5,Si=500,ji=1,ud=100;function uf(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(0,Math.min(500,l)):s}function eA(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(cd,Math.min(Si,l)):s}function Ag(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(ji,Math.min(ud,l)):s}function tA(n){const l=(Ag(n,n)-ji)/(ud-ji),o=Si-l*(Si-cd);return Math.round(o)}function nA(n){const s=eA(n,n),l=(Si-s)/(Si-cd),o=ji+l*(ud-ji);return Math.round(o)}function aA(n){return jg(n?.target)}function ht(n,s){if(!n||n.size===0)return!1;for(const l of s)if(n.has(l))return!0;return!1}function sA(n,s){const l=ht(s.driveForward,n),o=ht(s.driveBackward,n),f=ht(s.driveLeft,n),d=ht(s.driveRight,n),h=ht(s.boostModifier,n),p=ht(s.slowModifier,n);let x=0;l&&!o?x=1:o&&!l&&(x=-1);let g=0;f&&!d?g=-1:d&&!f&&(g=1);const v=p?.4:1;return{x:g*v,y:x*v,boost:h&&!p}}function lA(n,s){if(ht(s.auxAllForward,n))return{main:127,side:127,vacuum:127};const o=ht(s.auxMainForward,n)?127:ht(s.auxMainReverse,n)?-127:0,f=ht(s.auxSideForward,n)?127:ht(s.auxSideReverse,n)?-70:0,d=ht(s.auxVacuumFast,n)?127:ht(s.auxVacuumSlow,n)?50:0;return{main:o,side:f,vacuum:d}}function iA(){const{state:n,actions:{setMode:s,setDriveVector:l,setAuxMotors:o,nudgeServo:f,runMacro:d,stopAllMotion:h,registerInputState:p,toggleNightVision:x,startHorn:g,stopHorn:v,setMicPttActive:y,setSongNote:S,sendSong:E}}=_t(),C=ft(re=>re.session),{homeAssistantSetState:k}=wn(),{focusChat:w,blurChat:j,isChatFocused:N}=od(),{value:T}=He("inputs",qn),M=m.useMemo(()=>$j(n.keymap),[n.keymap]),O=m.useMemo(()=>{const re=new Set;return Object.values(M).forEach(ue=>{ue&&ue.forEach(ve=>re.add(ve))}),re},[M]),K=m.useMemo(()=>{const re=qn.keyboard,ue=T?.keyboard??{};return{baseSpeed:uf(ue.baseSpeed,re.baseSpeed),turboSpeed:uf(ue.turboSpeed,re.turboSpeed),precisionSpeed:uf(ue.precisionSpeed,re.precisionSpeed)}},[T?.keyboard]),_=m.useMemo(()=>{const re=qn.keyboard,ue=T?.keyboard??{},ve=Ag(typeof ue.tiltSpeed=="number"?ue.tiltSpeed:typeof ue.tiltIntervalMs=="number"?nA(ue.tiltIntervalMs):re.tiltSpeed,re.tiltSpeed);return tA(ve)},[T?.keyboard]),U=m.useMemo(()=>Math.abs(n.camera?.config?.nudgeDegrees||1),[n.camera?.config?.nudgeDegrees]),X=m.useRef(new Set),F=m.useRef(of),H=m.useRef(cf),te=m.useRef(null),ce=m.useRef(null),oe=m.useRef(!1),V=m.useCallback(()=>{const re=new Set(X.current);ht(M.boostModifier,re);const ve=ht(M.slowModifier,re)?{baseSpeed:K.precisionSpeed,boostSpeed:K.precisionSpeed}:{baseSpeed:K.baseSpeed,boostSpeed:K.turboSpeed},be=sA(re,M),xe=lA(re,M);(be.x!==F.current.x||be.y!==F.current.y||be.boost!==F.current.boost)&&(F.current=be,l(be,{source:rf,speedOptions:ve})),(xe.main!==H.current.main||xe.side!==H.current.side||xe.vacuum!==H.current.vacuum)&&(H.current=xe,o(xe)),p(rf,{keys:Array.from(re),vector:be,aux:xe})},[M,K,p,o,l]),q=m.useCallback(()=>{te.current&&(clearTimeout(te.current),te.current=null)},[]),L=m.useCallback(()=>{const re=new Set(X.current),ue=ht(M.cameraUp,re),ve=ht(M.cameraDown,re);return(ue?1:0)-(ve?1:0)},[M]),Z=m.useCallback(()=>{if(L()===0){q();return}if(te.current)return;const ue=()=>{const ve=L();if(ve===0){q();return}f(ve*U),te.current=setTimeout(ue,_)};te.current=setTimeout(ue,0)},[L,f,_,U,q]),le=m.useCallback(()=>{ce.current&&(clearTimeout(ce.current),ce.current=null)},[]),fe=m.useCallback(()=>{const re=new Set(X.current),ue=ht(M.songNoteUp,re),ve=ht(M.songNoteDown,re);return(ue?1:0)-(ve?1:0)},[M]),R=m.useCallback(re=>{if(re===0)return;let ve=(typeof n.song?.note=="number"?n.song.note:il)+re;ve>W0?ve=P0:ve{if(fe()===0){le();return}if(ce.current)return;const ue=()=>{const ve=fe();if(ve===0){le();return}R(ve),ce.current=setTimeout(ue,Rj)};ce.current=setTimeout(ue,0)},[fe,le,R]),ee=m.useCallback(()=>{X.current.clear(),F.current=of,H.current=cf,q(),le(),oe.current&&(oe.current=!1,v()),y(!1),h(),p(rf,{keys:[],vector:of,aux:cf})},[p,y,h,v,q,le]),ae=m.useCallback(re=>{const ue=C?.homeAssistant;if(!ue?.enabled||!ue?.connected||ue?.lightPolicy?.locked||ue?.lightPolicy?.lockedOn)return;const be=(ue.entities||[]).filter(xe=>(xe.type==="light"||xe.type==="switch")&&xe.available!==!1&&xe.state!=="unavailable");if(be.length!==0){if(re==="on"){const xe=be.find(Be=>Be.state!=="on");xe&&k(xe.id,"on").catch(()=>{});return}if(re==="off")for(let xe=be.length-1;xe>=0;xe-=1){const Be=be[xe];if(Be.state==="on"){k(Be.id,"off").catch(()=>{});break}}}},[k,C?.homeAssistant]);m.useEffect(()=>{function re(be){if(J0()||aA(be))return;const xe=Q0(be);if(xe.length===0)return;const Be=new Set(xe);if(ht(M.chatFocus,Be)){be.preventDefault(),ee(),N||w();return}xe.some(Ae=>O.has(Ae))&&be.preventDefault();const ze=xe.filter(Ae=>!X.current.has(Ae));if(ze.forEach(Ae=>X.current.add(Ae)),ze.length>0)if(ze.some(Ae=>M.driveMacro?.has(Ae)))s("drive"),d("drive-sequence");else if(ze.some(Ae=>M.dockMacro?.has(Ae)))s("dock"),d("seek-dock");else if(ze.some(Ae=>M.nightVisionToggle?.has(Ae)))x();else if(ze.some(Ae=>M.hornHonk?.has(Ae))){if(!oe.current){const Ae=g();oe.current=!!Ae}}else ze.some(Ae=>M.micPtt?.has(Ae))?y(!0):ze.some(Ae=>M.homeAssistantOn?.has(Ae))?ae("on"):ze.some(Ae=>M.homeAssistantOff?.has(Ae))&&ae("off");Z(),$(),V()}function ue(be){if(J0())return;Q0(be).forEach(Be=>X.current.delete(Be)),oe.current&&!ht(M.hornHonk,X.current)&&(oe.current=!1,v()),ht(M.micPtt,X.current)||y(!1),Z(),$(),V()}function ve(){ee()}return window.addEventListener("keydown",re,{capture:!0}),window.addEventListener("keyup",ue,{capture:!0}),window.addEventListener("blur",ve),()=>{window.removeEventListener("keydown",re,{capture:!0}),window.removeEventListener("keyup",ue,{capture:!0}),window.removeEventListener("blur",ve)}},[O,j,V,Z,$,w,N,M.chatFocus,M.dockMacro,M.driveMacro,M.hornHonk,M.micPtt,ee,d,y,s,h,le,g,v,ae]);const pe=m.useRef(ee);return m.useEffect(()=>{pe.current=ee},[ee]),m.useEffect(()=>{pe.current()},[n.roverId]),m.useEffect(()=>{oe.current=!!n.horn?.active},[n.horn?.active]),m.useEffect(()=>()=>{q(),le()},[q,le]),null}const rA=1.6;function Ng(n){if(!n)return"unknown::none::0::0";const s=n.id||"unknown",l=n.mapping||"none",o=Array.isArray(n.axes)?n.axes.length:0,f=Array.isArray(n.buttons)?n.buttons.length:0;return`${s}::${l}::${o}::${f}`}function oA(n){return JSON.parse(JSON.stringify(n??{}))}function wg(n,s){const l=oA(s);return l.meta={id:n?.id??"Unknown",mapping:n?.mapping??"none",axes:n?.axes?.length??0,buttons:n?.buttons?.length??0},l}function cs(n){return Number.isFinite(n)?Math.max(-1,Math.min(1,n)):0}function di(n,s){if(!n)return 0;const l=Math.abs(n);return s==="expo"?Math.sign(n)*Math.pow(l,rA):n}function ff(n,s){const l=Math.abs(n);if(l<=s)return 0;const o=(l-s)/(1-s);return Math.sign(n)*o}function cA(n,s,l){const o=Math.hypot(n,s);if(o<=l)return{x:0,y:0};const d=(o-l)/(1-l)/o;return{x:n*d,y:s*d}}function xo(n,s){if(!n||!Array.isArray(n.axes))return null;const l=n.axes[s];return Number.isFinite(l)?cs(l):null}function Of(n,s){if(!n||!Array.isArray(n.buttons))return null;const l=n.buttons[s];if(!l)return null;const o=typeof l.value=="number"?l.value:l.pressed?1:0;return{pressed:!!(l.pressed||o>.5),value:Math.max(0,Math.min(1,o))}}function df(n,s=[]){for(const l of s)if(l){if(l.kind==="axis"){const o=xo(n,l.index);if(o===null)continue;return{value:l.invert?-o:o,source:l}}if(l.kind==="buttonAxis"){const o=Of(n,l.index);if(!o)continue;return{value:cs(o.value),source:l}}}return{value:0,source:null}}function uA(n,s=[]){for(const l of s){if(!l||l.kind!=="axisPair")continue;const o=xo(n,l.x),f=xo(n,l.y);if(o===null||f===null)continue;const d=l.invertX?-o:o,h=l.invertY?-f:f;return{x:d,y:h,source:l}}return{x:0,y:0,source:null}}function as(n,s=[]){for(const l of s)if(l){if(l.kind==="button"){const o=Of(n,l.index);if(!o)continue;return{pressed:o.pressed,source:l}}if(l.kind==="axisButton"){const o=xo(n,l.index);if(o===null)continue;const f=l.direction||1,d=typeof l.threshold=="number"?l.threshold:.6;return{pressed:o*f>d,source:l}}if(l.kind==="buttonAxis"){const o=Of(n,l.index);if(!o)continue;return{pressed:o.value>.5,source:l}}}return{pressed:!1,source:null}}function Cg(n,s){const l=s?.bindings??{},o=s?.calibration??{},f=l.drive??{},d=uA(n,f.sources);let h=cs(d.x),p=cs(d.y);const x=Math.min(Math.max(o.driveDeadzone??.18,0),.8),g=cA(h,p,x);h=di(g.x,o.driveCurve),p=di(g.y,o.driveCurve);const v=l.cameraTilt??{},y=df(n,v.sources),S=Math.min(Math.max(o.cameraDeadzone??.08,0),.8);let E=ff(cs(y.value),S);E=di(E,o.cameraCurve);const C=Math.min(Math.max(o.auxDeadzone??.05,0),.6),k=l.mainBrush??{},w=df(n,k.sources);let j=ff(cs(w.value),C);j=di(j,o.auxCurve);const N=l.sideBrush??{},T=df(n,N.sources);let M=ff(cs(T.value),C);M=di(M,o.auxCurve);const O=as(n,l.vacuum?.sources),K=as(n,l.allAux?.sources),_=as(n,l.mainReverse?.sources),U=as(n,l.sideReverse?.sources),X=as(n,l.driveMacro?.sources),F=as(n,l.dockMacro?.sources),H=as(n,l.nightVisionToggle?.sources);return{driveVector:{x:h,y:p,boost:!1},cameraAxis:E,auxAxis:{main:j,side:M},buttons:{vacuum:O.pressed,allAux:K.pressed,mainReverse:_.pressed,sideReverse:U.pressed,driveMacro:X.pressed,dockMacro:F.pressed,nightVisionToggle:H.pressed},sources:{drive:d.source,cameraTilt:y.source,mainBrush:w.source,sideBrush:T.source,vacuum:O.source,allAux:K.source,mainReverse:_.source,sideReverse:U.source,driveMacro:X.source,dockMacro:F.source,nightVisionToggle:H.source}}}const xi=new Set;let ll=null,cl={pads:[],timestamp:0},Ir=!1,Jr=null;function ex(){return Eg().some(n=>n?.connected!==!1)}function Eg(){if(typeof navigator>"u"||!navigator.getGamepads)return[];const n=navigator.getGamepads();return n?Array.from(n).filter(Boolean):[]}function fA(n){return{index:n.index,id:n.id,mapping:n.mapping,connected:n.connected!==!1,timestamp:n.timestamp,axes:Array.from(n.axes??[]),buttons:(n.buttons??[]).map(s=>({pressed:!!s?.pressed,value:typeof s?.value=="number"?s.value:s?.pressed?1:0})),signature:Ng(n)}}function go(){cl={pads:Eg().map(fA),timestamp:typeof performance<"u"?performance.now():Date.now()},xi.forEach(s=>s(cl))}function kg(){if(go(),cl.pads.length===0){Lf();return}ll=requestAnimationFrame(kg)}function tx(){ll||(go(),cl.pads.length!==0&&(ll=requestAnimationFrame(kg)))}function Lf(){ll&&(cancelAnimationFrame(ll),ll=null)}function Mg(n){if(xi.add(n),!Ir&&typeof window<"u"){const s=()=>{go(),xi.size!==0&&(ex()?tx():Lf())};window.addEventListener("gamepadconnected",s),window.addEventListener("gamepaddisconnected",s),Jr=s,Ir=!0}return ex()?tx():go(),n(cl),()=>{xi.delete(n),xi.size===0&&(Lf(),Ir&&typeof window<"u"&&(window.removeEventListener("gamepadconnected",Jr),window.removeEventListener("gamepaddisconnected",Jr),Jr=null,Ir=!1))}}function dA(){const[n,s]=m.useState(cl);return m.useEffect(()=>Mg(s),[]),n}const nl="gamepad",ss={x:0,y:0,boost:!1},ls={main:0,side:0,vacuum:0},mA=100,hA=100;function mf(n,s){return n&&s&&n.x===s.x&&n.y===s.y&&n.boost===s.boost}function hf(n,s){return n&&s&&n.main===s.main&&n.side===s.side&&n.vacuum===s.vacuum}function pA(n){return n?Math.hypot(n.x||0,n.y||0):0}function xA(n){return n?!n.main&&!n.side&&!n.vacuum:!0}function gA(n,s){if(!n||n.length===0)return null;if(s){const l=n.find(o=>o.signature===s);if(l)return l}return n[0]}function vA(){const{state:n,actions:{setMode:s,setDriveVector:l,setAuxMotors:o,setServoAngle:f,runMacro:d,toggleNightVision:h,registerInputState:p}}=_t(),{value:x,save:g}=He("gamepad",Ba),v=m.useRef(new Set),y=m.useRef(ss),S=m.useRef(ls),E=m.useRef({main:!1,side:!1}),C=m.useRef(new Map),k=m.useRef(0),w=m.useRef(0),j=m.useRef(0),N=m.useRef(null),T=m.useCallback(_=>{const U=_.signature??Ng(_);x?.profiles?.[U]||v.current.has(U)||(v.current.add(U),g(X=>{const F=X??Ba;if(F.profiles?.[U])return F;const H=F?.defaults?.profile??ia,te=wg(_,H);return{...F,profiles:{...F.profiles??{},[U]:te}}}))},[x?.profiles,g]),M=m.useCallback((_,U)=>{const X=C.current.get(_)||!1;return C.current.set(_,U),U&&!X},[]),O=m.useCallback((_,U)=>{const X=n.camera?.config;if(!X)return;const F=typeof performance<"u"?performance.now():Date.now(),H=U?.cameraMode??"absolute",te=Math.max(1,Math.min(180,U?.cameraSensitivity??60));if(H==="velocity"){const L=Math.min(50,F-j.current||16),Z=_*te*(L/1e3);if(Math.abs(Z)<.01)return;const fe=(typeof N.current=="number"?N.current:typeof n.camera?.angle=="number"?n.camera.angle:typeof X.homeAngle=="number"?X.homeAngle:0)+Z;f(fe),N.current=fe,j.current=F;return}const ce=typeof X.minAngle=="number"?X.minAngle:-45,oe=typeof X.maxAngle=="number"?X.maxAngle:45,V=typeof X.homeAngle=="number"?X.homeAngle:(ce+oe)/2,q=_<0?V+_*(V-ce):V+_*(oe-V);typeof N.current=="number"&&Math.abs(N.current-q)<.35&&F-j.current<80||(j.current=F,N.current=q,f(q))},[f,n.camera?.angle,n.camera?.config]),K=m.useMemo(()=>x?.activeSignature??null,[x?.activeSignature]);return m.useEffect(()=>Mg(_=>{const U=gA(_.pads,K);if(!U){mf(y.current,ss)||(y.current=ss,l(ss,{source:nl})),hf(S.current,ls)||(S.current=ls,o(ls)),C.current=new Map,E.current={main:!1,side:!1},k.current=0,w.current=0,p(nl,{connected:!1});return}if(Wj()){mf(y.current,ss)||(y.current=ss,l(ss,{source:nl})),hf(S.current,ls)||(S.current=ls,o(ls)),C.current=new Map,E.current={main:!1,side:!1},p(nl,{connected:!0,blocked:!0});return}T(U);const X=U.signature,F=x?.profiles?.[X]??x?.defaults?.profile??ia,H=Cg(U,F);if(!mf(H.driveVector,y.current)){const Z=typeof performance<"u"?performance.now():Date.now();(pA(H.driveVector)<.02||Z-k.current>=mA)&&(y.current=H.driveVector,k.current=Z,l(H.driveVector,{source:nl}))}const te=F.calibration?.auxSideScale??.55,ce=Math.round(Math.min(Math.abs(H.auxAxis.main),1)*127),oe=Math.round(Math.min(Math.abs(H.auxAxis.side),1)*127),V=E.current.main?-ce:ce,q=E.current.side?-Math.round(oe*te):Math.round(oe*te);let L={main:H.auxAxis.main!==0?V:0,side:H.auxAxis.side!==0?q:0,vacuum:H.buttons.vacuum?127:0};if(H.buttons.allAux&&(L={main:127,side:127,vacuum:127}),!hf(L,S.current)){const Z=typeof performance<"u"?performance.now():Date.now();(xA(L)||Z-w.current>=hA)&&(S.current=L,w.current=Z,o(L))}H.buttons.mainReverse&&M("mainReverse",!0)?E.current.main=!E.current.main:H.buttons.mainReverse||M("mainReverse",!1),H.buttons.sideReverse&&M("sideReverse",!0)?E.current.side=!E.current.side:H.buttons.sideReverse||M("sideReverse",!1),H.buttons.driveMacro&&M("driveMacro",!0)?(s("drive"),d("drive-sequence")):H.buttons.driveMacro||M("driveMacro",!1),H.buttons.dockMacro&&M("dockMacro",!0)?(s("dock"),d("seek-dock")):H.buttons.dockMacro||M("dockMacro",!1),H.buttons.nightVisionToggle&&M("nightVisionToggle",!0)?h():H.buttons.nightVisionToggle||M("nightVisionToggle",!1),Math.abs(H.cameraAxis)>.001&&O(H.cameraAxis,F.calibration),p(nl,{connected:!0,signature:X,id:U.id,index:U.index,axes:U.axes,buttons:U.buttons,drive:H.driveVector,aux:L,cameraAxis:H.cameraAxis,bindings:H.sources})}),[K,T,x?.defaults?.profile,x?.profiles,M,O,p,d,o,l,s,h]),null}function Rg(n){const s=n?.sensors||{},l=s.oiMode?.label||"Unknown",o=l.toLowerCase(),f=s.chargingState?.label||"",d=!!s.chargingSources?.homeBase,h=d&&f.toLowerCase()!=="not charging"&&f!=="";return{driving:o==="full",docked:d,charging:h,dockedNotCharging:d&&!h,dockingInProgress:!d&&!h&&o==="passive",oiLabel:l,chargingLabel:f}}function qg(n){const s=ml(n);return m.useMemo(()=>Rg(s),[s])}function al({label:n,value:s,tone:l="neutral"}){const o=l==="good"?"border-emerald-200 bg-emerald-600 text-white":l==="warn"?"border-amber-200 bg-amber-600 text-white":l==="bad"?"border-red-200 bg-red-600 text-white":"border-slate-200/30 bg-slate-700 text-slate-100";return r.jsx("div",{className:`flex flex-1 flex-col items-center justify-center rounded-lg border px-0.75 py-0.5 text-center ${o}`,children:r.jsx("span",{className:"text-base font-semibold md:text-lg",children:s})})}function nx({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function pf({label:n,tone:s}){const l=s==="emerald"?"border-emerald-200/70 bg-emerald-600/70 text-emerald-50":s==="amber"?"border-amber-200/70 bg-amber-600/70 text-amber-50":"border-indigo-200/70 bg-indigo-600/70 text-indigo-50";return r.jsx("span",{className:`rounded-full border px-0.5 py-0.15 text-[0.7rem] font-semibold ${l}`,children:n})}function bA({instructions:n,onConfirm:s,onCancel:l,pending:o}){return r.jsx("div",{className:"fixed inset-0 z-40 flex items-center justify-center bg-black/70 p-1",children:r.jsxs("div",{className:"surface w-full max-w-md space-y-0.5 border border-indigo-700 bg-indigo-950/90 p-1 text-slate-100 shadow-2xl",children:[r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-lg font-semibold text-indigo-50",children:"Dock Rover"}),r.jsx("p",{className:"text-sm text-slate-200",children:n.summary}),r.jsx(zf,{steps:n.steps,tone:"indigo"})]}),r.jsxs("div",{className:"grid grid-cols-2 gap-0.5 text-sm",children:[r.jsx("button",{type:"button",onClick:l,className:"bg-slate-700 px-0.5 py-1 font-semibold text-slate-100 transition hover:bg-slate-600",children:"Cancel"}),r.jsx("button",{type:"button",disabled:o,onClick:s,className:"bg-indigo-600 px-0.5 py-1 font-semibold text-indigo-50 transition hover:bg-indigo-500 disabled:opacity-50",children:o?"Docking…":"Confirm Dock"})]})]})})}function Tg({layout:n="desktop",expand:s=!1,fill:l=!1,driveDockState:o,compactHeightClass:f=""}){const d=n==="mobile",{state:{roverId:h,keymap:p},actions:x}=_t(),g=ml(h),v=o??Rg(g),{driving:y,docked:S,charging:E,dockingInProgress:C}=v,[k,w]=m.useState(null),[j,N]=m.useState(!1),[T,M]=m.useState(!1),O=!h||k!==null,K=!h||k!==null,_=An(p?.driveMacro?.[0]),U=An(p?.dockMacro?.[0]),X={summary:"You are about to trigger an automatic docking attempt! To have a successful dock:",steps:["Line up the rover straight in front of the dock","Make sure the rover is about one foot or half a meter away from the dock","Press Confirm Dock to begin the docking process"]},F="Click this button to initate auto-dock.",H={summary:"You must enable driving mode before you can move the rover.",steps:["Press the keybind or tap this button to enable driving mode","Once ready (should be instant), this dialog will change, and you will be able to move"]},te=S?"Docked":"Undocked",ce=S?"good":"bad",oe=E?"Charging":S?"Charging in 5s":"—",V=E?"good":S?"warn":"bad",q=async()=>{if(!(!h||k)){w("drive");try{x.setMode("drive"),await x.runMacro("drive-sequence")}catch(Je){alert(Je.message)}finally{w(null)}}},L=async()=>{if(!(!h||k)){N(!1),M(!1),w("drive");try{x.setMode("drive"),await x.runMacro("drive-sequence")}catch(Je){alert(Je.message)}finally{w(null)}}},Z=async()=>{if(!(!h||k)){w("dock");try{x.setMode("dock"),await x.runMacro("seek-dock")}catch(Je){alert(Je.message)}finally{w(null),N(!1),M(!1)}}},le=()=>{K||(M(!0),N(!0))},fe="flex w-full flex-col gap-0.5 overflow-hidden rounded-xl border-2 px-0.75 py-0.75 text-slate-100 shadow-md transition hover:-translate-y-0.5 hover:shadow-xl focus-visible:outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-60 select-none no-touch-select",R="text-center",$="items-center justify-between",ee="items-center justify-center",ae=d?"text-sm font-semibold":"",pe="border-emerald-300/70 bg-emerald-800 text-emerald-50 hover:bg-emerald-700 focus-visible:ring-emerald-300",re="border-amber-300/70 bg-amber-900 text-amber-50 hover:bg-amber-800 focus-visible:ring-amber-300",ue="border-indigo-300/70 bg-indigo-900 text-indigo-50 hover:bg-indigo-800 focus-visible:ring-indigo-300",ve="border-amber-300/70 bg-amber-900 text-amber-50 hover:bg-amber-800 focus-visible:ring-amber-300",xe=s||C,Be=xe?"h-full flex-1":l?"flex-1":"",ze=d&&!xe?f:"",Ae=d&&!xe?ee:$,tt=d&&!xe&&y&&S;if(!y&&!C)return r.jsxs("button",{type:"button",onClick:L,onContextMenu:Je=>Je.preventDefault(),disabled:O,className:`${fe} ${Be} ${ze} ${R} ${Ae} ${ae} ${pe}`,children:[r.jsxs("div",{className:"space-y-0.5 w-full",children:[r.jsxs("div",{className:"flex w-full flex-col items-center gap-0.25",children:[r.jsx("span",{className:"text-base font-semibold text-emerald-50 md:text-lg",children:"Start Driving"}),!d&&xe?r.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-0.5",children:[_?r.jsx(nx,{label:_}):null,r.jsx(pf,{label:"Click to start",tone:"emerald"})]}):null]}),xe?r.jsxs(r.Fragment,{children:[r.jsx("p",{className:"text-sm text-emerald-50/90",children:H.summary}),r.jsx(zf,{steps:H.steps,tone:"emerald"})]}):null]}),xe?r.jsxs("div",{className:"flex w-full flex-1 flex-col gap-0.5 self-stretch",children:[r.jsx(al,{label:"Dock",value:te,tone:ce}),r.jsx(al,{label:"Charge",value:oe,tone:V})]}):null]});if(C){const Je={summary:"If the rover is failing to dock, click to drive and try again.",steps:["The rover should be slowly wiggling towards the dock","If it is obviously not working, press this button to enter driving mode and try again"]};return r.jsxs("button",{type:"button",disabled:O,onClick:q,onContextMenu:vt=>vt.preventDefault(),className:`${fe} ${Be} ${ze} ${R} ${Ae} ${ae} ${re}`,children:[r.jsxs("div",{className:"space-y-0.5 w-full",children:[r.jsxs("div",{className:"flex w-full flex-col items-center gap-0.25",children:[r.jsx("span",{className:"text-base font-semibold text-amber-50 md:text-lg",children:"Docking in Progress"}),xe?r.jsx("div",{className:"flex flex-wrap items-center justify-center gap-0.5",children:r.jsx(pf,{label:"Return to driving mode",tone:"emerald"})}):null]}),xe?r.jsx("p",{className:"text-sm text-amber-50/90",children:Je.summary}):null]}),xe?r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"flex w-full flex-1 flex-col gap-0.5 self-stretch",children:[r.jsx(al,{label:"Dock",value:te,tone:ce}),r.jsx(al,{label:"Charge",value:oe,tone:V})]}),d?null:r.jsx(zf,{steps:Je.steps,tone:"amber"})]}):null]})}return r.jsxs(r.Fragment,{children:[r.jsxs("button",{type:"button",disabled:K,onClick:le,onContextMenu:Je=>Je.preventDefault(),className:d?`flex w-full ${fe} ${ze} ${R} ${Ae} ${ae} ${tt?ve:ue}`:`${fe} ${Be} ${R} ${$} ${ae} ${ue}`,children:[r.jsxs("div",{className:"flex w-full flex-col items-center gap-0.25",children:[r.jsx("span",{className:"text-base font-semibold text-indigo-50 md:text-lg",children:tt?"Docked!":"Dock and Charge"}),!d&&xe?r.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-0.5",children:[U?r.jsx(nx,{label:U}):null,r.jsx(pf,{label:"Click to begin docking",tone:"indigo"})]}):null]}),!d&&xe&&r.jsxs(r.Fragment,{children:[r.jsx("p",{className:"text-sm text-indigo-50/90",children:F}),r.jsxs("div",{className:"flex w-full flex-1 flex-col gap-0.5 self-stretch",children:[r.jsx(al,{label:"Dock",value:te,tone:ce}),r.jsx(al,{label:"Charge",value:oe,tone:V})]}),r.jsx("div",{className:"text-xs text-indigo-100/80",children:"Line up straight, about 1 foot away, before docking."})]})]}),T||!d&&j?r.jsx(bA,{instructions:X,pending:k==="dock",onCancel:()=>{M(!1),N(!1)},onConfirm:Z}):null]})}function zf({steps:n,tone:s="emerald"}){const l=s==="emerald"?"bg-emerald-900/60 text-emerald-50/90 border-emerald-700/60":s==="amber"?"bg-amber-900/60 text-amber-50/90 border-amber-700/60":"bg-indigo-900/60 text-indigo-50/90 border-indigo-700/60",o=s==="emerald"?"text-emerald-200":s==="amber"?"text-amber-200":"text-indigo-200";return r.jsx("div",{className:`space-y-0.5 rounded border px-0.5 py-0.35 text-left ${l}`,children:n.map((f,d)=>r.jsxs("div",{className:"text-[0.85rem] leading-snug break-words",children:[r.jsxs("div",{className:"flex items-start",children:[r.jsxs("span",{className:`mr-0 align-top text-[0.75rem] font-semibold ${o}`,children:[d+1,"."]}),r.jsx("span",{className:"align-top",children:f})]}),d{xf(n)&&p(n)},[n]);const x=xf(h),g=x?h:!1,v=x?g?"On":"Off":"—",y=g?"bg-emerald-500 text-emerald-950":"bg-slate-700 text-slate-200",S=()=>{if(s)return;const C=x?!g:!0;p(C),l?.(C)},E=m.useMemo(()=>["group flex w-full flex-col items-center justify-center gap-0.35 rounded-xl border-2 px-1 py-0.75 text-center select-none no-touch-select",g?"border-emerald-300/70 bg-emerald-800 text-emerald-50 hover:bg-emerald-700":"border-amber-300/70 bg-amber-900 text-amber-50 hover:bg-amber-800","disabled:opacity-50",d,f].filter(Boolean).join(" "),[f,g,d]);return r.jsxs("button",{type:"button",onClick:S,onContextMenu:C=>C.preventDefault(),disabled:s,"aria-pressed":g,className:E,children:[r.jsxs("span",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-sm font-semibold",children:"Night Vision"}),o?r.jsx("span",{className:"rounded bg-slate-800 px-1 py-0.5 text-[0.6rem] font-semibold text-slate-200",children:o}):null]}),r.jsx("span",{className:`rounded px-1 py-0.5 text-[0.7rem] font-semibold ${y}`,children:v})]})}function gf(n){const s=Number(n);return!Number.isFinite(s)||s<=0?0:Math.min(5e3,Math.round(s))}function _g({disabled:n,onStart:s,onStop:l,keyLabel:o,active:f,heat:d=0,className:h="",defaultShowSettings:p=!0,showSettingsToggle:x=!1,compactSettings:g=!1}){const[v,y]=m.useState(!1),[S,E]=m.useState(p),{value:C,save:k}=He("horn",us),[w,j]=m.useState(C?.waveform||us.waveform),[N,T]=m.useState(()=>[...Array.isArray(C?.freqs)?C.freqs:us.freqs,0,0,0,0].slice(0,4).map(q=>gf(q)));m.useEffect(()=>{j(C?.waveform||us.waveform),Array.isArray(C?.freqs)&&T([...C.freqs,0,0,0,0].slice(0,4).map(V=>gf(V)))},[C?.freqs,C?.waveform]);const M=!!f,O=Math.max(0,Math.min(1,Number(d)||0)),K=m.useMemo(()=>["group relative flex w-full flex-col gap-0.5 overflow-hidden rounded-xl border-2 px-1 py-1.5 text-xs font-semibold select-none no-touch-select",M?"border-fuchsia-300/70 bg-fuchsia-700 text-fuchsia-50":"border-cyan-300/70 bg-cyan-900 text-cyan-50 hover:bg-cyan-800","disabled:opacity-50",h].filter(Boolean).join(" "),[h,M]),_=()=>{n||v||(y(!0),s?.())},U=()=>{v&&(y(!1),l?.())};m.useEffect(()=>{!M&&v&&y(!1)},[M,v]);const X=w==="sine"?"sine":"saw",F=m.useCallback(V=>{const q=V.target.value==="sine"?"sine":"saw";j(q),k(L=>({...L??{},waveform:q}))},[k]),H=m.useCallback((V,q)=>{T(L=>{const Z=[...L];return Z[V]=gf(q),k(le=>({...le??{},freqs:Z})),Z})},[k]),te=V=>{if(n)return;const q=V.target?.tagName?.toLowerCase();q==="input"||q==="select"||q==="option"||q==="label"||q==="button"||(V.preventDefault(),_())},ce=V=>{const q=V.target?.tagName?.toLowerCase();q==="input"||q==="select"||q==="option"||q==="label"||q==="button"||(V.preventDefault(),U())},oe=x?r.jsx("button",{type:"button",onClick:V=>{V.preventDefault(),E(q=>!q)},className:"rounded bg-black/40 px-1 py-0.5 text-[0.6rem] font-semibold text-white/90 hover:text-white",children:S?"Hide":"Settings"}):null;return r.jsxs("div",{role:"button",tabIndex:0,"aria-pressed":v,onPointerDown:te,onPointerUp:ce,onPointerLeave:U,onPointerCancel:U,onContextMenu:V=>V.preventDefault(),onBlur:U,className:K,children:[r.jsx("div",{className:"pointer-events-none absolute inset-0 opacity-70",style:{background:`linear-gradient(90deg, rgba(14,116,144,0.7) ${O*100}%, rgba(0,0,0,0) ${O*100}%)`}}),r.jsx("div",{className:`pointer-events-none absolute inset-0 transition-opacity ${M?"opacity-40":"opacity-0"}`,style:{background:"linear-gradient(90deg, rgba(217,70,239,0.75), rgba(244,114,182,0.35))"}}),r.jsxs("div",{className:"relative z-10 flex items-center justify-between gap-0.5",children:[r.jsxs("span",{className:"flex items-center gap-0.5 text-sm font-semibold",children:[r.jsx("span",{children:"Horn"}),o?r.jsx("span",{className:"rounded bg-black/40 px-1 py-0.5 text-[0.6rem] font-semibold text-white",children:o}):null]}),oe,r.jsx("span",{className:`rounded px-1 py-0.5 text-[0.65rem] font-semibold ${M?"bg-fuchsia-200 text-fuchsia-900":"bg-slate-800 text-slate-200"}`,children:M?"Honk":"Hold"})]}),S?g?r.jsxs("div",{className:"relative z-10 flex flex-col gap-0.5 text-[0.65rem]",children:[r.jsxs("label",{className:"flex items-center justify-between gap-0.5 text-slate-200",children:[r.jsx("span",{className:"text-slate-300",children:"Wave"}),r.jsxs("select",{value:X,onChange:F,className:"rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.65rem] text-slate-100",children:[r.jsx("option",{value:"saw",children:"Saw"}),r.jsx("option",{value:"sine",children:"Sine"})]})]}),r.jsx("div",{className:"grid grid-cols-2 gap-0.5",children:N.map((V,q)=>r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("span",{className:"text-[0.6rem] text-slate-400",children:q+1}),r.jsx("input",{type:"number",min:0,max:5e3,step:1,value:V,onChange:L=>H(q,L.target.value),className:"w-full rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-right text-[0.65rem] font-mono text-slate-100"})]},`horn-freq-${q}`))})]}):r.jsxs("div",{className:"relative z-10 grid grid-cols-[minmax(0,1.2fr)_repeat(4,minmax(0,1fr))] items-center gap-0.5 text-[0.65rem]",children:[r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("span",{className:"text-slate-300",children:"Wave"}),r.jsxs("select",{value:X,onChange:F,className:"rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.65rem] text-slate-100",children:[r.jsx("option",{value:"saw",children:"Saw"}),r.jsx("option",{value:"sine",children:"Sine"})]})]}),N.map((V,q)=>r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("span",{className:"text-[0.6rem] text-slate-400",children:q+1}),r.jsx("input",{type:"number",min:0,max:5e3,step:1,value:V,onChange:L=>H(q,L.target.value),className:"w-full rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-right text-[0.65rem] font-mono text-slate-100"})]},`horn-freq-${q}`))]}):null]})}function Pr(n){return typeof n!="number"||Number.isNaN(n)?"—":`${n>0?"+":""}${n.toFixed(1)}°`}function ax({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function Bg({value:n,min:s,max:l,step:o=.5,label:f="Camera Tilt",orientation:d="horizontal",onChange:h,onCommit:p,throttleMs:x=0,disabled:g=!1,keyDownLabel:v,keyUpLabel:y,className:S="",labelRowClass:E="",labelClass:C="",valueClass:k="",sliderClass:w="",endpointClass:j="",endpointLabelClass:N="",accentClass:T="",showValue:M=!0,showEndpoints:O}){const K=d==="vertical",U=typeof O=="boolean"?O:!K,[X,F]=m.useState(n),H=m.useRef(!1),te=m.useRef(null);m.useEffect(()=>{H.current||F(n)},[n]),m.useEffect(()=>()=>{te.current&&clearTimeout(te.current)},[]);const ce=Z=>{if(h){if(x>0){te.current&&clearTimeout(te.current),te.current=setTimeout(()=>{h(Z)},x);return}h(Z)}},oe=Z=>{const le=Number.parseFloat(Z.target.value);Number.isNaN(le)||(H.current=!0,F(le),ce(le))},V=()=>{H.current=!1,te.current&&(clearTimeout(te.current),te.current=null),p?p(X):x>0&&h?.(X)};if(typeof s!="number"||typeof l!="number")return null;const q=[K?"h-28 w-5":"w-full",T,w].filter(Boolean).join(" "),L=r.jsx("input",{type:"range",orient:K?"vertical":void 0,min:s,max:l,step:o,value:Number.isFinite(X)?X:s,onChange:oe,onMouseUp:V,onTouchEnd:V,onPointerUp:V,disabled:g,className:q,style:K?{writingMode:"bt-lr",WebkitAppearance:"slider-vertical"}:void 0});return K?r.jsxs("div",{className:`flex h-full flex-col items-center gap-0.5 ${S}`.trim(),children:[M?r.jsx("div",{className:`flex flex-col items-center ${E}`.trim(),children:r.jsx("span",{className:k,children:Pr(n)})}):null,r.jsxs("div",{className:"flex min-h-0 flex-1 items-center gap-0.5",children:[r.jsx("span",{className:C,children:f}),L]})]}):r.jsxs("div",{className:`space-y-0.5 ${S}`.trim(),children:[r.jsxs("div",{className:`flex items-center justify-between ${E}`.trim(),children:[r.jsx("span",{className:C,children:f}),M?r.jsx("span",{className:k,children:Pr(n)}):null]}),r.jsxs("div",{children:[L,U?r.jsxs("div",{className:`mt-0 flex items-center justify-between ${j}`.trim(),children:[r.jsxs("span",{className:`flex items-center gap-0.5 ${N}`.trim(),children:[v?r.jsx(ax,{label:v}):null,Pr(s)]}),r.jsxs("span",{className:`flex items-center gap-0.5 ${N}`.trim(),children:[Pr(l),y?r.jsx(ax,{label:y}):null]})]}):null]})]})}const Wr="mobile-joystick",yA=80,SA=.15,jA={main:0,side:0,vacuum:0},AA={main:127,side:127,vacuum:127},NA={main:-127,side:-127,vacuum:-127};function wA({disabled:n,layout:s,radius:l,onMove:o,onStop:f}){const d=m.useRef(null),h=m.useRef(null),p=m.useRef({x:0,y:0}),[x,g]=m.useState({active:!1,base:{x:0,y:0},knob:{x:0,y:0}}),v=m.useCallback(()=>{h.current=null,g({active:!1,base:{x:0,y:0},knob:{x:0,y:0}}),f?.()},[f]),y=m.useCallback(k=>{if(n||h.current!==null)return;k.preventDefault();const w=d.current;if(!w)return;const j=w.getBoundingClientRect(),N=k.clientX-j.left,T=k.clientY-j.top;p.current={x:N,y:T},h.current=k.pointerId,w.setPointerCapture?.(k.pointerId),g({active:!0,base:{x:N,y:T},knob:{x:0,y:0}})},[n]),S=m.useCallback(k=>{if(n||h.current!==k.pointerId)return;k.preventDefault();const w=d.current;if(!w)return;const j=w.getBoundingClientRect(),N=k.clientX-j.left,T=k.clientY-j.top,M=N-p.current.x,O=T-p.current.y,K=Math.min(Math.hypot(M,O),l),_=Math.atan2(O,M),U=Math.cos(_)*K,X=Math.sin(_)*K,F={x:ol(U/l),y:ol(-X/l),boost:!1};g(H=>({...H,knob:{x:U,y:X}})),o?.(F)},[n,o]),E=m.useCallback(k=>{if(h.current!==k.pointerId)return;k.preventDefault(),d.current?.releasePointerCapture?.(k.pointerId),v()},[v]);return m.useEffect(()=>{n&&v()},[n,v]),r.jsxs("div",{ref:d,role:"presentation",className:"relative w-full h-full select-none overflow-hidden rounded-xl border-2 border-slate-700 bg-slate-900/70 text-slate-100 shadow-md",style:{touchAction:"none"},onPointerDown:y,onPointerMove:S,onPointerUp:E,onPointerLeave:E,onPointerCancel:E,onContextMenu:k=>k.preventDefault(),children:[!x.active&&r.jsxs("div",{className:"absolute inset-x-0 top-0 flex flex-col items-center gap-0 text-center pt-0.5",children:[r.jsx("span",{className:"font-semibold text-slate-200",children:"Joystick area"}),r.jsx("span",{className:"text-sm text-slate-300",children:"Touch and hold to use the joystick"})]}),x.active&&r.jsxs(r.Fragment,{children:[r.jsx("div",{className:"pointer-events-none absolute h-28 w-28 -translate-x-1/2 -translate-y-1/2 bg-cyan-400/10 outline outline-2 outline-cyan-400/60 [clip-path:circle(50%)]",style:{left:x.base.x,top:x.base.y}}),r.jsx("div",{className:"pointer-events-none absolute h-12 w-12 -translate-x-1/2 -translate-y-1/2 bg-cyan-300/80 shadow-lg [clip-path:circle(50%)]",style:{left:x.base.x+x.knob.x,top:x.base.y+x.knob.y}})]})]})}function CA({layout:n}){const{state:{roverId:s},actions:{setDriveVector:l,registerInputState:o}}=_t(),f=qg(s),d=f.docked&&!f.driving,h=d||f.dockingInProgress,p=!s,x=yA,g=SA,v=m.useRef({x:0,y:0,boost:!1});m.useEffect(()=>{p&&(v.current={x:0,y:0,boost:!1})},[p]);const y=m.useCallback((k={})=>{if(p)return;const w={x:ol(k.x??0),y:ol(k.y??0),boost:!!k.boost},j={x:v.current.x+(w.x-v.current.x)*(1-g),y:v.current.y+(w.y-v.current.y)*(1-g),boost:w.boost};v.current=j,l(j,{source:Wr}),o(Wr,{vector:j,lastEvent:"move"})},[p,o,l,g]),S=m.useCallback(()=>{if(p)return;const k={x:0,y:0,boost:!1};v.current=k,l(k,{source:Wr}),o(Wr,{vector:k,lastEvent:"stop"})},[p,o,l]),C=`flex h-full flex-col gap-0.5 text-slate-100 ${d?"max-h-screen self-start":""}`;return r.jsxs("div",{className:C,children:[r.jsx(Tg,{layout:"mobile",expand:h,driveDockState:f,compactHeightClass:"min-h-[5rem]"}),h?null:r.jsx("div",{className:"flex-1 min-h-0",children:r.jsx(wA,{disabled:p,layout:n,radius:x,onMove:y,onStop:S})})]})}function sx({id:n,label:s,values:l,color:o,disabled:f,onPress:d,onRelease:h}){return r.jsx("button",{type:"button",disabled:f,onPointerDown:p=>{p.preventDefault(),d(n,l)},onPointerUp:()=>h(n),onPointerLeave:()=>h(n),onPointerCancel:()=>h(n),onContextMenu:p=>p.preventDefault(),className:`flex h-full w-full items-center justify-center rounded-xl border-2 px-1 py-0.75 text-center text-sm font-semibold text-white transition select-none no-touch-select ${o} hover:brightness-110 active:brightness-125 active:scale-[0.99] disabled:opacity-30`,children:s})}function EA({layout:n}){const{state:{roverId:s,camera:l,horn:o},pipeline:f,actions:{setServoAngle:d,setNightVision:h,setAuxMotors:p,startHorn:x,stopHorn:g}}=_t(),v=!s,y=m.useRef(null),S=l?.config,E=!!(s&&l?.enabled&&S),C=!!(s&&f?.nightVision),k=f?.nightVisionState,w=!!(s&&f?.horn),j=o?.overheated,N=typeof S?.minAngle=="number"?S.minAngle:-45,T=typeof S?.maxAngle=="number"?S.maxAngle:45,M=typeof l?.angle=="number"?l.angle:typeof S?.homeAngle=="number"?S.homeAngle:(N+T)/2,O=m.useCallback(U=>{C&&h(U)},[C,h]),K=m.useCallback((U,X)=>{v||(y.current=U,p(X))},[v,p]),_=m.useCallback(U=>{v||y.current===U&&(y.current=null,p(jA))},[v,p]);return r.jsxs("div",{className:"grid h-full min-h-0 w-full grid-rows-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)] gap-0.5 text-slate-100",children:[r.jsxs("div",{className:"grid min-h-0 grid-rows-2 gap-0.5",children:[r.jsx(sx,{id:"aux-vac-forward",label:"Vacuum Forward",values:AA,color:"bg-fuchsia-600",disabled:v,onPress:K,onRelease:_}),r.jsx(sx,{id:"aux-vac-backward",label:"Vacuum Backward",values:NA,color:"bg-fuchsia-800",disabled:v,onPress:K,onRelease:_})]}),r.jsxs("div",{className:"flex min-h-0 items-stretch gap-0.5",children:[E?r.jsx("div",{className:"flex-1 min-h-0 rounded bg-zinc-950 p-0.25",children:r.jsx(Bg,{value:M,min:N,max:T,step:.5,onChange:d,orientation:"vertical",label:"Camera Tilt",labelClass:"text-sm font-semibold text-white [writing-mode:vertical-rl] rotate-180",labelRowClass:"text-[0.7rem] text-slate-300",valueClass:"font-mono text-slate-200",className:"h-full gap-0",sliderClass:"h-full w-7",accentClass:"accent-cyan-400",showEndpoints:!1,showValue:!1})}):null,C?r.jsx(Dg,{nightVisionOn:k?.nightVisionOn,disabled:v,onToggle:O,heightClass:"h-full"}):null]}),r.jsx("div",{className:"min-h-0",children:w?r.jsx(_g,{disabled:v||j,onStart:x,onStop:g,active:o?.active,heat:o?.heat,defaultShowSettings:!1,showSettingsToggle:!0,compactSettings:!0,className:"h-full"}):null})]})}function vo({layout:n,className:s=""}){return r.jsx("div",{className:`flex flex-col gap-0.5 ${s}`.trim(),children:r.jsx(EA,{layout:n})})}function bo({layout:n,className:s=""}){return r.jsx("div",{className:`flex flex-col gap-0.5 ${s}`.trim(),children:r.jsx(CA,{layout:n==="landscape"?"landscape":"portrait"})})}function kA({swapColumns:n=!1}){const s="h-[min(60svh,24rem)]",l=n?r.jsx(bo,{layout:"portrait",className:s}):r.jsx(vo,{layout:"portrait",className:s}),o=n?r.jsx(vo,{layout:"portrait",className:s}):r.jsx(bo,{layout:"portrait",className:s});return r.jsx("section",{className:"panel",children:r.jsxs("div",{className:"grid grid-cols-2 gap-0.5 items-stretch",children:[l,o]})})}function MA(n=[],s={}){const l=tn(),{enabled:o=!0,version:f=null}=s,[d,h]=m.useState({}),p=m.useRef(new Map),x=m.useMemo(()=>n.map(C=>typeof C=="string"?C:C.id),[n]),g=m.useMemo(()=>{const C=x.join("|");return f?`${C}|v:${f}`:C},[x,f]),v=m.useRef([]),[y,S]=m.useState(0),E=m.useRef(new Map);return m.useEffect(()=>{if(!l)return;const C=()=>S(k=>k+1);return l.on("connect",C),()=>l.off("connect",C)},[l]),m.useEffect(()=>{v.current=x},[g,x]),m.useEffect(()=>{p.current.forEach(C=>URL.revokeObjectURL(C)),p.current.clear(),h({})},[g]),m.useEffect(()=>{if(!o){p.current.forEach(N=>URL.revokeObjectURL(N)),p.current.clear(),h({});return}if(!v.current.length||!l)return;let C=!1;const k=v.current,w=(N={},T)=>{if(C||!N.id||!T)return;const M=T.byteLength??T.length??0,O=Date.now(),K=E.current.get(N.id)||{count:0,totalBytes:0,lastLogAt:0},_={count:K.count+1,totalBytes:K.totalBytes+M,lastLogAt:K.lastLogAt};if(!_.lastLogAt||O-_.lastLogAt>=1e4){const H=_.count?_.totalBytes/_.count:0;console.log("[roomCamera]",N.id,`frame=${M}B`,`avg=${Math.round(H)}B`,`count=${_.count}`),_.lastLogAt=O}E.current.set(N.id,_);const U=new Blob([T],{type:"image/jpeg"}),X=URL.createObjectURL(U),F=p.current.get(N.id);F&&URL.revokeObjectURL(F),p.current.set(N.id,X),h(H=>({...H,[N.id]:{status:"playing",ts:N.ts||Date.now(),error:null,objectUrl:X}}))},j=(N={})=>{C||!N.id||h(T=>({...T,[N.id]:{...T[N.id]||{},status:N.error?"error":T[N.id]?.status||"connecting",error:N.error||null,ts:N.ts||T[N.id]?.ts||null,objectUrl:T[N.id]?.objectUrl||null}}))};return l.on("roomCamera:frame",w),l.on("roomCamera:status",j),l.emit("roomCamera:subscribe",{ids:k},(N={})=>{N.error}),()=>{C=!0,l.emit("roomCamera:unsubscribe",{ids:k}),l.off("roomCamera:frame",w),l.off("roomCamera:status",j),p.current.forEach(N=>URL.revokeObjectURL(N)),p.current.clear()}},[l,g,o,y]),d}function RA({feed:n,label:s}){const[l,o]=m.useState(!1);m.useEffect(()=>{n&&(!n.ts&&!n.objectUrl||o(d=>!d))},[n?.ts,n?.objectUrl]);const f=m.useMemo(()=>n?n.error?`Error: ${n.error}`:n.status||"Connecting…":"Connecting…",[n]);return r.jsxs("div",{className:"relative w-full overflow-hidden rounded bg-black",style:{aspectRatio:"4 / 3"},children:[n?.objectUrl?r.jsx("img",{src:n.objectUrl,alt:s,className:"h-full w-full object-cover"}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-300",children:"Waiting for frame…"}),r.jsx("div",{className:"pointer-events-none absolute left-0 top-0 bg-black/70 px-0.5 py-0.5 text-xs font-semibold text-white",children:s}),r.jsxs("div",{className:"pointer-events-none absolute bottom-0 left-0 m-0 flex items-center gap-0.5 rounded bg-black/70 px-0.5 py-0.25 text-[0.7rem] text-slate-100",children:[r.jsx("span",{className:`h-2 w-2 rounded-full ${l?"bg-emerald-400":"bg-slate-500"}`}),r.jsx("span",{children:f})]})]})}function qA(){return r.jsxs("div",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-center text-slate-400",children:"No room cameras configured."}),r.jsx("p",{className:"text-center text-slate-500",children:"Add entries to server config to populate this list."})]})}const Og=["horizontal","vertical"];function vf(n,s){return Og.includes(n)?n:s}function fd({defaultOrientation:n="horizontal",orientation:s,hideLayoutToggle:l=!1,hideHeader:o=!1,panelId:f=null}){const{session:d}=nn(),h=d?.roomCameras||[],p=MA(h.map(w=>({id:w.id}))),{value:x,save:g}=He("roomCameraPanels",{}),[v,y]=m.useState(()=>vf(f?x?.[f]:n,"horizontal"));m.useEffect(()=>{if(!f)return;const w=x?.[f];w&&y(vf(w,"horizontal"))},[f,x?.[f]]);const S=s?vf(s,"horizontal"):v,E=S==="vertical"?"flex flex-col gap-0.5":"grid gap-0.5 md:grid-cols-2",C=!l&&!s&&h.length>0,k=w=>{y(w),f&&g(j=>({...j||{},[f]:w}))};return h.length===0?r.jsx(qA,{}):r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[!o&&r.jsxs("header",{className:"flex flex-wrap items-center justify-between gap-0.5 text-sm text-slate-400",children:[r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("p",{children:"Room cameras"}),r.jsx("span",{className:"text-xs text-slate-500",children:h.length})]}),r.jsx("div",{className:"flex flex-wrap items-center gap-0.5 text-xs",children:C&&r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("span",{className:"text-slate-500",children:"Layout:"}),r.jsx("div",{className:"inline-flex overflow-hidden rounded border border-slate-700",children:Og.map(w=>r.jsx("button",{type:"button",className:`px-1 py-0.5 ${S===w?"bg-slate-600 text-white":"bg-transparent text-slate-400 hover:text-white"}`,onClick:()=>k(w),children:w==="vertical"?"Vertical":"Grid"},w))})]})})]}),r.jsx("div",{className:E,children:h.map(w=>{const j=p[w.id]||null;return r.jsx("article",{className:"w-full space-y-0.5 rounded bg-zinc-950 p-0.5 shadow-inner shadow-black/40",children:r.jsx(RA,{feed:j,label:w.name||w.id})},w.id)})})]})}function dd(){const n=ft(s=>s.logs);return r.jsxs("div",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"flex items-center justify-between text-sm text-slate-400",children:[r.jsx("span",{children:"Server logs"}),r.jsx("span",{children:n.length})]}),r.jsx("div",{className:"surface h-64 overflow-y-auto font-mono text-xs",children:n.length===0?r.jsx("p",{children:"No logs yet."}):n.slice().reverse().map(s=>r.jsxs("div",{className:"surface",children:[r.jsx("span",{className:"text-amber-400",children:s.timestamp})," ",r.jsxs("span",{className:"text-lime-400",children:["[",s.level,"]"]})," ",s.label&&r.jsxs("span",{className:"text-teal-400",children:["[",s.label,"]"]})," ",r.jsx("span",{children:s.message})]},s.id))})]})}function TA(n){if(!n)return null;if(typeof n=="string"){const s=String(n).trim();return s?{type:"rover",id:s,key:s}:null}if(typeof n=="object"){if(n.type&&n.id){const s=String(n.id);let l=n.key;return l||(l=n.type==="room"?`room:${s}`:s),{type:n.type,id:s,key:l}}if(n.roverId){const s=String(n.roverId);return{type:"rover",id:s,key:n.key||s}}if(n.roomCameraId){const s=String(n.roomCameraId);return{type:"room",id:s,key:n.key||`room:${s}`}}}return null}function DA(n=[]){const s=new Set,l=[];return n.forEach(o=>{!o?.key||s.has(o.key)||(s.add(o.key),l.push(o))}),l.sort((o,f)=>o.key.localeCompare(f.key))}function Ai(n=[],s={}){const l=tn(),{enabled:o=!0,version:f=null}=s,[d,h]=m.useState({}),p=m.useMemo(()=>Array.isArray(n)?DA(n.map(TA).filter(Boolean)):[],[n]),x=m.useMemo(()=>{const E=p.map(C=>`${C.type}:${C.id}:${C.key}`).join("|");return f?`${E}|v:${f}`:E},[p,f]),g=m.useRef([]),[v,y]=m.useState(0);return m.useEffect(()=>{if(!l)return;const E=()=>y(C=>C+1);return l.on("connect",E),()=>{l.off("connect",E)}},[l]),m.useEffect(()=>{g.current=p},[p]),m.useEffect(()=>{if(!x||!o){h({});return}const E=g.current;let C=!1;function k(w){const j=w.type==="room"?{roomCameraId:w.id}:{roverId:w.id};l.emit("video:request",j,(N={})=>{C||h(T=>({...T,[w.key]:N}))})}return E.forEach(w=>{k(w)}),()=>{C=!0}},[l,x,o,v]),m.useMemo(()=>{if(!x||!o)return{};const E={};return p.forEach(C=>{d[C.key]&&(E[C.key]=d[C.key])}),E},[x,d,p])}function md(n=[],s={}){const l=tn(),{enabled:o=!0,version:f=null}=s,[d,h]=m.useState({}),p=m.useRef(new Map),x=m.useMemo(()=>n.map(C=>typeof C=="string"?C:C.id).filter(Boolean),[n]),g=m.useMemo(()=>{const C=x.join("|");return f?`${C}|v:${f}`:C},[x,f]),v=m.useRef([]),[y,S]=m.useState(0),E=m.useRef(new Map);return m.useEffect(()=>{if(!l)return;const C=()=>S(k=>k+1);return l.on("connect",C),()=>l.off("connect",C)},[l]),m.useEffect(()=>{v.current=x},[g,x]),m.useEffect(()=>{p.current.forEach(C=>URL.revokeObjectURL(C)),p.current.clear(),h({})},[g]),m.useEffect(()=>{if(!o){p.current.forEach(N=>URL.revokeObjectURL(N)),p.current.clear(),h({});return}if(!v.current.length||!l)return;let C=!1;const k=v.current,w=(N={},T)=>{if(C||!N.id||!T)return;const M=T.byteLength??T.length??0,O=Date.now(),K=E.current.get(N.id)||{count:0,totalBytes:0,lastLogAt:0},_={count:K.count+1,totalBytes:K.totalBytes+M,lastLogAt:K.lastLogAt};if(!_.lastLogAt||O-_.lastLogAt>=1e4){const H=_.count?_.totalBytes/_.count:0;console.log("[roverSnapshot]",N.id,`frame=${M}B`,`avg=${Math.round(H)}B`,`count=${_.count}`),_.lastLogAt=O}E.current.set(N.id,_);const U=new Blob([T],{type:"image/jpeg"}),X=URL.createObjectURL(U),F=p.current.get(N.id);F&&URL.revokeObjectURL(F),p.current.set(N.id,X),h(H=>({...H,[N.id]:{status:"playing",ts:N.ts||Date.now(),error:null,objectUrl:X}}))},j=(N={})=>{C||!N.id||h(T=>({...T,[N.id]:{...T[N.id]||{},status:N.error?"error":T[N.id]?.status||"connecting",error:N.error||null,ts:N.ts||T[N.id]?.ts||null,objectUrl:T[N.id]?.objectUrl||null}}))};return l.on("roverSnapshot:frame",w),l.on("roverSnapshot:status",j),l.emit("roverSnapshot:subscribe",{ids:k},(N={})=>{N.error}),()=>{C=!0,l.emit("roverSnapshot:unsubscribe",{ids:k}),l.off("roverSnapshot:frame",w),l.off("roverSnapshot:status",j),p.current.forEach(N=>URL.revokeObjectURL(N)),p.current.clear()}},[l,g,o,y]),d}const _A={iceServers:[{urls:"stun:stun.l.google.com:19302"},{urls:"turn:your.turn.server:3478",username:"user",credential:"pass"}],bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"};function BA(n){if(typeof btoa=="function")return btoa(n);if(typeof Buffer<"u")return Buffer.from(n).toString("base64");throw new Error("No base64 encoder available")}function OA(n){if(!n)return{};const s=`${n}:${n}`;return{Authorization:`Basic ${BA(s)}`}}class lx{constructor({url:s,token:l,video:o,onStatus:f,audioOnly:d=!1,receiveAudio:h=!0}){this.url=s,this.token=l,this.video=o,this.audioOnly=d,this.receiveAudio=h,this.pc=null,this.abortController=null,this.onStatus=f}notify(s,l){typeof this.onStatus=="function"&&this.onStatus(s,l)}configureVideoElement(){this.video&&(this.video.playsInline=!0,this.video.autoplay=!0,this.video.muted=!this.audioOnly,typeof this.video.disableRemotePlayback<"u"&&(this.video.disableRemotePlayback=!0),"latencyHint"in HTMLMediaElement.prototype&&(this.video.latencyHint="interactive"))}async start(){if(!this.url||!this.video)throw new Error("Media target missing");this.stop(),this.notify("connecting"),this.configureVideoElement(),this.abortController=new AbortController;const s=new RTCPeerConnection(_A);this.pc=s;const l=new MediaStream;s.ontrack=o=>{o.streams[0]?.getTracks().forEach(f=>l.addTrack(f)),this.video.srcObject=l,o.track?.kind==="video"&&"playoutDelayHint"in o.receiver&&(o.receiver.playoutDelayHint=0)},this.audioOnly?s.addTransceiver("audio",{direction:"recvonly"}):(s.addTransceiver("video",{direction:"recvonly"}),this.receiveAudio&&s.addTransceiver("audio",{direction:"recvonly"})),s.onconnectionstatechange=()=>{this.notify(s.connectionState)},s.oniceconnectionstatechange=()=>{const o=s.iceConnectionState;(o==="failed"||o==="disconnected")&&this.notify(o)};try{const o=await s.createOffer({offerToReceiveAudio:this.audioOnly?!0:this.receiveAudio,offerToReceiveVideo:!this.audioOnly});await s.setLocalDescription(o);const f=await fetch(this.url,{method:"POST",headers:{"Content-Type":"application/sdp",...OA(this.token)},body:o.sdp,signal:this.abortController.signal});if(!f.ok)throw new Error(`WHEP request failed: ${f.status}`);const d=await f.text();await s.setRemoteDescription({type:"answer",sdp:d}),s.getReceivers().forEach(h=>{"playoutDelayHint"in h&&(h.playoutDelayHint=0)}),await this.video.play().catch(()=>{}),this.notify("playing")}catch(o){throw this.notify("error",o.message),this.stop(),o}}stop(){this.abortController&&(this.abortController.abort(),this.abortController=null),this.pc&&(this.pc.getSenders().forEach(s=>s.track?.stop()),this.pc.getReceivers().forEach(s=>s.track?.stop()),this.pc.close(),this.pc=null),this.video&&(this.video.srcObject=null),this.notify("stopped")}}function Lg(){const{value:n,save:s}=He("page",{hudMapDesktop:!1});return[!!n?.hudMapDesktop,f=>{s({hudMapDesktop:!!f})}]}const LA={discord:dg,kofi:U0,"ko-fi":U0,wiki:bj,throne:yj},zA={discord:{backgroundImage:"linear-gradient(270deg,#5865F2,#404EED,#5865F2)",backgroundSize:"600% 600%",animation:"socialGradient 180s ease infinite"},kofi:{backgroundImage:"linear-gradient(270deg,#FF6433,#E04822,#FF6433)",backgroundSize:"600% 600%",animation:"socialGradient 170s ease infinite"},"ko-fi":{backgroundImage:"linear-gradient(270deg,#FF6433,#E04822,#FF6433)",backgroundSize:"600% 600%",animation:"socialGradient 170s ease infinite"},wiki:{backgroundImage:"linear-gradient(270deg,#EE8019,#C65C08,#EE8019)",backgroundSize:"600% 600%",animation:"socialGradient 180s ease infinite"},throne:{backgroundImage:"linear-gradient(270deg,#7C3AED,#5B21B6,#7C3AED)",backgroundSize:"600% 600%",animation:"socialGradient 180s ease infinite"}};function UA(){m.useEffect(()=>{if(typeof document>"u")return;const n="social-button-keyframes";if(document.getElementById(n))return;const s=document.createElement("style");s.id=n,s.textContent=` @keyframes socialGradient { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } - `,document.head.appendChild(s)},[])}function QA(n,s){return typeof n=="string"&&n.trim()?n.trim().toLowerCase():typeof s=="string"&&s.trim()?s.trim().toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,""):""}function pd({id:n,label:s,url:l,className:o=""}){if(!l)return null;XA();const f=QA(n,s),d=YA[f]||Sj,h=FA[f]||null,p=s||n||"Link";return r.jsxs("a",{href:l,target:"_blank",rel:"noopener noreferrer","aria-label":p,className:`inline-flex items-center w-full px-0.5 py-0.5 text-sm font-medium text-white transition justify-center gap-1 rounded-md ${h?"":"bg-slate-700 hover:bg-slate-600"} ${o}`,style:h||void 0,children:[r.jsx(d,{className:"mr-0"}),p]})}const Ni=10;function Ug({batteryState:n=null,charge:s=null,config:l=null}){const o=n?.percentDisplay!=null&&Number.isFinite(n.percentDisplay)?Math.round(n.percentDisplay):null,f=n?.warnActive??null,d=n?.urgentActive??null,h=l?.Full??null,p=l?.Warn??null,x=l?.Urgent??null,g=s??n?.charge??null;let v=o;if(v==null&&(v=KA({charge:g,full:h,warn:p,urgent:x})),v==null)return{available:!1};const y=Math.max(0,Math.min(1,v/100)),S=f??(p!=null&&g!=null&&g<=p),E=d??(x!=null&&g!=null&&g<=x);return{available:!0,percent:y,percentDisplay:v,warnActive:S,urgentActive:E,warnDisplayPercent:Ni}}function KA({charge:n,full:s,warn:l,urgent:o}){if(n!=null&&s!=null&&l!=null&&o!=null&&s>l&&l>o){const f=Ni/100,d=1-f;if(n<=o)return 0;if(n<=l){const p=(n-o)/(l-o);return Math.round(Math.max(0,Math.min(1,p))*Ni)}if(n>=s)return 100;const h=(n-l)/(s-l);return Math.round((f+Math.max(0,Math.min(1,h))*d)*100)}return null}const ZA=1600,IA=800;function Sn(...n){return n.filter(Boolean).join(" ")}function Hf({visual:n,orientation:s="horizontal",variant:l="inline",compact:o=!1,showLabel:f,className:d=""}){const h=l==="background",p=s==="vertical",x=f??!h;if(!n?.available){if(h){const te=Ni,ce=Sn("absolute z-10",p?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",E&&!S&&"battery-tick-warn"),oe=p?{bottom:`${te}%`}:{left:`${te}%`},V=Sn("absolute inset-0 pointer-events-none",d);return r.jsxs("div",{className:V,children:[r.jsx("div",{className:"absolute inset-0 bg-slate-900/35"}),r.jsx("div",{className:ce,style:oe})]})}return p?null:r.jsx("p",{className:"text-xs text-slate-500",children:"Battery telemetry unavailable"})}const g=n.percentDisplay??0,v=Math.max(0,Math.min(100,g)),y=n.warnDisplayPercent??Ni,S=!!n.urgentActive,E=!!n.warnActive,C=S?`${IA}ms`:E?`${ZA}ms`:void 0,w=h?S||E?"bg-red-500/45":"bg-emerald-500/45":S||E?"bg-red-500":"bg-emerald-500",j=S||E?"bg-red-900/35":"bg-slate-900/35",N=S||E?"bg-red-900/45":"bg-slate-900/35",T=Sn(h?"absolute inset-0 pointer-events-none":"relative pointer-events-auto",p&&!h?"flex flex-col items-center justify-center":"w-full",d);if(h){const te=p?{height:`${v}%`}:{width:`${v}%`},ce=Sn("absolute",p?"bottom-0 left-0 right-0":"left-0 top-0 bottom-0",w,"transition-[width,height]",S&&"battery-urgent-flash"),oe=Sn("absolute z-10",p?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",E&&!S&&"battery-tick-warn"),V=p?{bottom:`${y}%`}:{left:`${y}%`};return r.jsxs("div",{className:T,children:[r.jsx("div",{className:Sn("absolute inset-0",j,S&&"battery-urgent-flash")}),r.jsx("div",{className:ce,style:{...te,animationDuration:C}}),r.jsx("div",{className:oe,style:V})]})}const M=Sn("relative overflow-hidden rounded-sm border border-slate-800",S||E?N:"bg-zinc-900/90",S&&"battery-urgent-flash",p?"w-full flex-1":o?"h-4":"h-5"),O=p?{height:`${v}%`}:{width:`${v}%`},K=Sn("absolute",p?"bottom-0 left-0 right-0":"left-0 top-0 bottom-0",w,"transition-[width,height]",S&&"battery-urgent-flash"),_=Sn("absolute z-10",p?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",E&&!S&&"battery-tick-warn"),U=p?{bottom:`${y}%`}:{left:`${y}%`},X=`Battery ${g}%`,F=Sn("pointer-events-none absolute inset-0 flex items-center justify-center text-center font-semibold",p?o?"text-[0.55rem]":"text-[0.65rem]":"text-xs"),H=Sn("rounded px-1.5 py-0.5",h?"bg-black/30 text-slate-100":"bg-black/50 text-slate-100");return r.jsxs("div",{className:T,children:[r.jsxs("div",{className:M,children:[r.jsx("div",{className:K,style:{...O,animationDuration:C}}),r.jsx("div",{className:_,style:U})]}),x&&!p?r.jsx("div",{className:F,children:r.jsx("span",{className:H,children:X})}):null,x&&p?r.jsx("div",{className:"mt-0.5 text-[0.65rem] font-semibold text-slate-100",children:r.jsxs("span",{className:H,children:[g,"%"]})}):null]})}const rx=2e3,JA=3e3,PA=3e3,WA=40,eN=1e3;function wi({sessionInfo:n,audioSessionInfo:s,videoMode:l="whep",snapshotFeed:o=null,qualityNotice:f=null,label:d,roverColor:h=null,forceMute:p=!1,telemetryFrame:x,batteryConfig:g,layoutFormat:v="desktop",hudVariant:y="default",driverLabel:S=null,hudForceMap:E=!1,hudMapPosition:C="top-center",hudLabelScale:k=1,fitParent:w=!1,overcurrentLimiter:j=null,showTurnCue:N=!1,turnTimerText:T=null,turnSeconds:M=null,isActiveDriver:O=!1,idleSkipSeconds:K=null}){const _=ft(ye=>ye.session),U=m.useRef(null),X=m.useRef(null),F=m.useRef(null),H=m.useRef(null),te=m.useRef(null),ce=m.useRef(null),oe=m.useRef(null),V=m.useRef(null),[q,L]=m.useState("idle"),[Z,le]=m.useState(null),[fe,R]=m.useState("idle"),[$,ee]=m.useState(null),[ae,pe]=m.useState(0),[re,ue]=m.useState(0),[ve,be]=m.useState(!0),xe=!!s?.url,Be=l==="snapshot",ze=x?.sensors,{value:Ae}=He("audio",ct),tt=Number.isFinite(Ae?.masterVolume)?Ae.masterVolume:ct.masterVolume,Je=Number.isFinite(Ae?.roverVolume)?Ae.roverVolume:ct.roverVolume,vt=typeof Ae?.mainBrushDuckEnabled=="boolean"?Ae.mainBrushDuckEnabled:typeof Ae?.autoLevelEnabled=="boolean"?Ae.autoLevelEnabled:ct.mainBrushDuckEnabled,ie=Number.isFinite(Ae?.mainBrushDuckAmount)?Math.max(0,Math.min(1,Ae.mainBrushDuckAmount)):ct.mainBrushDuckAmount,me=Math.max(0,Math.min(1,tt*Je)),se=ze?.batteryChargeMah??null,P=v==="desktop",de=!P,Ne=de?"top-right":C,[pt]=zg(),Ve=E||de?!0:pt,st=Ug({charge:se,config:g}),lt=ze?.wheelOvercurrents||null,Ot=lt==null?[]:Object.entries(lt).filter(([,ye])=>!!ye).map(([ye])=>ye),it=j?.caps||null,ms=j?.overcurrent?.groups||null,Yt=typeof window<"u"&&new URLSearchParams(window.location.search).has("debugAudio"),La=typeof window<"u"&&new URLSearchParams(window.location.search).has("debugHud"),Bo=m.useMemo(()=>{if(!it)return null;const ye=Number.isFinite(it?.drive?.cap)?it.drive.cap:1,Fe=Number.isFinite(it?.aux?.cap)?it.aux.cap:1;return Math.max(0,Math.min(1,1-Math.min(ye,Fe)))},[it]),Bn=!!j?.isActive,Nt=Ot.length?Ot:Bn?["limiter"]:[],Ft=Bo??(Ot.length?1:0),Mt=!!Nt.length,fa=!!((Number(ze?.mainBrushCurrentMa)||0)>WA||ze?.wheelOvercurrents?.mainBrush),Oo=vt&&fa?1-ie:1,hs=Math.max(0,Math.min(1,me*Oo)),ps=vt&&fa&&ie>0?`Volume decreased ${Math.round(ie*1e3)/10}%`:null,za=m.useRef({hasDedicatedAudio:!1,audioUrl:null,mainBrushDuckEnabled:!1,mainBrushDuckAmount:0,mainBrushActive:!1,baseRoverGain:0,effectiveRoverGain:0});m.useEffect(()=>{za.current={hasDedicatedAudio:xe,audioUrl:s?.url||null,mainBrushDuckEnabled:vt,mainBrushDuckAmount:ie,mainBrushActive:fa,baseRoverGain:me,effectiveRoverGain:hs}},[xe,s?.url,vt,ie,fa,me,hs]);const Pe=m.useCallback((ye,Fe={})=>{if(!Yt)return;const Ze=X.current,ke=za.current,$e={event:ye,ts:Date.now(),roverLabel:d||null,hasDedicatedAudio:ke.hasDedicatedAudio,audioUrl:ke.audioUrl,mainBrushDuckEnabled:ke.mainBrushDuckEnabled,mainBrushDuckAmount:ke.mainBrushDuckAmount,mainBrushActive:ke.mainBrushActive,baseRoverGain:ke.baseRoverGain,effectiveRoverGain:ke.effectiveRoverGain,element:Ze?{muted:Ze.muted,volume:Ze.volume,paused:Ze.paused,ended:Ze.ended,readyState:Ze.readyState,networkState:Ze.networkState}:null,...Fe};try{console.log(`[AudioDebug] ${ye} ${JSON.stringify($e)}`)}catch{console.log("[AudioDebug]",ye,$e)}},[Yt,d]),On=_?.socials?.find(ye=>String(ye?.id||ye?.label||"").toLowerCase()==="discord")?.url||_?.discord?.invite||null;m.useEffect(()=>{La&&console.log("[OvercurrentHUD]",{overlayVisible:Mt,overlayMotors:Nt,overlayFill:Ft,limiterActive:Bn,limiterCaps:it,limiterGroups:ms,wheelOvercurrents:lt})},[La,Ft,Nt,Mt,Bn,it,ms,lt]),m.useEffect(()=>{Pe("settings/update")},[Pe]);const Cn=m.useCallback(()=>{clearTimeout(F.current),F.current=setTimeout(()=>pe(Date.now()),rx)},[]),Ln=m.useCallback(()=>{clearTimeout(H.current),H.current=setTimeout(()=>ue(Date.now()),rx)},[]),xs=m.useCallback(async()=>{const ye=U.current;if(ye)try{ye.muted=!0,await ye.play()}catch{}},[]),hl=m.useCallback((ye=0)=>{if(p||xe)return;clearTimeout(ce.current);const Fe=()=>{clearTimeout(ce.current),ce.current=setTimeout(()=>{p||Ze()},JA)},Ze=async()=>{const ke=U.current;if(ke)try{await xs(),ke.muted=!1,await ke.play(),be(!1)}catch{ke.muted=!0,be(!0),Fe()}};ce.current=setTimeout(Ze,ye)},[xs,p,xe]);m.useEffect(()=>()=>{clearTimeout(F.current),clearTimeout(H.current),clearTimeout(ce.current),clearInterval(te.current),oe.current&&(cancelAnimationFrame(oe.current),oe.current=null)},[]),m.useEffect(()=>{q==="playing"&&hl(0)},[q,hl]),m.useEffect(()=>{Be&&(L("snapshot"),le(null))},[Be]),m.useEffect(()=>{if(Be||!n?.url||!U.current)return;let ye=!0,Fe;const Ze=setTimeout(()=>be(!0),0),ke=($e,rt)=>{ye&&(Pe("video/status",{nextStatus:$e,info:rt||null}),L($e),le(rt||null),$e==="playing"&&xs(),["error","failed","disconnected","closed"].includes($e)&&Cn())};return Fe=new lx({url:n.url,token:n.token,video:U.current,receiveAudio:!xe,onStatus:ke}),Fe.start().catch($e=>{ye&&(L("error"),le($e.message),Cn())}),()=>{ye=!1,clearTimeout(Ze),Fe?.stop()}},[Be,n?.url,n?.token,ae,Cn,xs,xe,Pe]),m.useEffect(()=>{q==="stopped"&&n?.url&&Cn()},[q,n?.url,Cn]),m.useEffect(()=>{const ye=X.current;if(!ye||!s?.url){Pe("route/no-audio-url"),V.current=null;return}const Fe=Math.max(0,Math.min(1,hs)),Ze=V.current==null?Math.max(0,Math.min(1,ye.volume)):V.current;if(oe.current&&(cancelAnimationFrame(oe.current),oe.current=null),Fe>Ze){const ke=performance.now(),$e=Ze,rt=Fe-$e,ot=wt=>{const nt=Math.min(1,(wt-ke)/eN),zn=$e+rt*nt;ye.volume=zn,V.current=zn,nt<1?oe.current=requestAnimationFrame(ot):oe.current=null};oe.current=requestAnimationFrame(ot)}else ye.volume=Fe,V.current=Fe;Pe("route/direct",{elementVolume:Fe,duckEnabled:vt,mainBrushActive:fa,duckAmount:ie})},[s?.url,hs,vt,fa,ie,Pe]),m.useEffect(()=>{if(!s?.url||!X.current)return;let ye=!0,Fe;const Ze=(ke,$e)=>{ye&&(Pe("audio/status",{nextStatus:ke,info:$e||null}),ee($e||(ke==="connected"?"connected":null)),R(rt=>ke==="connected"&&(rt==="playing"||rt==="connecting")||ke==="new"?rt:ke),["error","failed"].includes(ke)&&Ln())};return Fe=new lx({url:s.url,token:s.token,video:X.current,audioOnly:!0,onStatus:Ze}),Fe.start().catch(ke=>{ye&&(R("error"),ee(ke.message),Ln())}),()=>{ye=!1,Fe?.stop()}},[s?.url,s?.token,re,Ln,Pe]),m.useEffect(()=>{const ye=X.current;if(!s?.url||!ye){clearInterval(te.current);return}if(!["connecting","connected","playing","paused"].includes(fe)){clearInterval(te.current);return}const Ze=async()=>{const ke=X.current;ke&&(ke.muted=!1,!(!ke.paused&&!ke.ended)&&(Pe("retry/play-attempt"),ke.play().then(()=>{Pe("retry/play-ok"),R($e=>$e==="connected"?"playing":$e),ee($e=>$e==="paused"?null:$e)}).catch($e=>{Pe("retry/play-fail",{error:$e?.message}),ee(rt=>rt||$e?.message||"autoplay blocked")})))};return Ze(),te.current=setInterval(Ze,PA),()=>clearInterval(te.current)},[s?.url,fe,Pe]),m.useEffect(()=>{const ye=X.current;if(!ye)return;const Fe=()=>{Pe("element/play"),R(nt=>nt==="error"?nt:"playing"),ee(null)},Ze=()=>{Pe("element/pause"),R(nt=>["error","failed","disconnected","closed","stopped"].includes(nt)?nt:"paused"),ee(nt=>nt||"paused")},ke=()=>{Pe("element/ended"),R(nt=>nt==="error"?nt:"stopped"),ee(nt=>nt||"ended")},$e=()=>{const{error:nt}=ye,zn=nt?.message||"audio error";Pe("element/error",{error:zn}),R("error"),ee(zn)},rt=()=>Pe("element/waiting"),ot=()=>Pe("element/canplay"),wt=()=>Pe("element/stalled");return ye.addEventListener("play",Fe),ye.addEventListener("pause",Ze),ye.addEventListener("ended",ke),ye.addEventListener("error",$e),ye.addEventListener("waiting",rt),ye.addEventListener("canplay",ot),ye.addEventListener("stalled",wt),()=>{ye.removeEventListener("play",Fe),ye.removeEventListener("pause",Ze),ye.removeEventListener("ended",ke),ye.removeEventListener("error",$e),ye.removeEventListener("waiting",rt),ye.removeEventListener("canplay",ot),ye.removeEventListener("stalled",wt)}},[s?.url,Pe]);const pl=o?.error?`Error: ${o.error}`:o?.objectUrl?"snapshot":o?.status||"waiting",Ua=Be?pl:n?.url?q==="error"?`Error: ${Z||"unknown"}`:Z?`${q} (${Z})`:q:"waiting",Lo=s?.error?`Error: ${s.error}`:s?.url?fe==="error"?`Error: ${$||"unknown"}`:$?`${fe} (${$})`:fe:null,xl=y==="spectator",an=y==="none";return r.jsxs("div",{className:`flex flex-col gap-0.5 ${w?"h-full":""}`,children:[r.jsxs("div",{className:`relative w-full overflow-hidden bg-black ${w?"h-full flex-1":"aspect-[4/3]"}`,children:[Be?o?.objectUrl?r.jsx("img",{src:o.objectUrl,alt:d,className:"h-full w-full object-contain",draggable:!1}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-300",children:"Waiting for frame…"}):r.jsx("video",{ref:U,muted:p||ve||xe,playsInline:!0,autoPlay:!0,controls:!1,className:"h-full w-full object-contain"}),r.jsx("audio",{ref:X,autoPlay:!0,hidden:!0}),!an&&N?r.jsx(aN,{mobileHud:de,turnSeconds:M,isActiveDriver:O,idleSkipSeconds:K}):null,an?null:r.jsx(nN,{frame:x,sensors:ze,label:d,roverColor:h,status:Ua,audioStatus:Lo,levelStatus:ps,desktopLayout:P,layoutFormat:v,variant:y,driverLabel:S,battery:st,showTopDown:Ve,mobileHud:de,mapPosition:Ne,turnTimerText:T,labelScale:k}),an?null:r.jsx(rN,{compact:de}),!an&&La?r.jsx("div",{className:"pointer-events-none absolute left-1 top-1 z-40 rounded bg-black/80 px-1 py-0.5 text-[0.6rem] text-lime-200",children:`OC vis:${Mt?1:0} motors:${Nt.length} fill:${Math.round(Ft*100)}%`}):null,an?null:r.jsx(lN,{motors:Nt,fill:Ft,compact:de}),an?null:r.jsx(iN,{battery:st,compact:de}),!an&&xl&&st.available?r.jsx("div",{className:"pointer-events-none absolute right-1 top-1/2 flex h-[70%] -translate-y-1/2 flex-col items-center justify-center rounded bg-black/60 px-0.5 pb-1 pt-1",children:r.jsx(Hf,{visual:st,orientation:"vertical",variant:"inline",compact:de,className:"h-full w-4"})}):null,!an&&f?r.jsx("div",{className:"pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2",children:r.jsxs("div",{className:`mx-auto w-fit rounded border border-amber-300/80 bg-black/75 text-amber-200 ${de?"px-2 py-1 text-[0.6rem]":"px-3 py-1.5 text-sm"}`,children:[r.jsx("div",{className:"text-center",children:f}),r.jsx("div",{className:"pointer-events-auto mt-0",children:r.jsx(pd,{id:"discord",label:"Join our Discord server while you wait!",url:On})})]})}):null]}),!an&&!xl&&r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(tN,{sensors:ze}),r.jsx("div",{className:"panel-section space-y-0.5 text-sm",children:r.jsx(Hf,{visual:st,compact:de})})]})]})}function tN({sensors:n}){const s=[n?.lightBumpLeftSignal,n?.lightBumpFrontLeftSignal,n?.lightBumpCenterLeftSignal,n?.lightBumpCenterRightSignal,n?.lightBumpFrontRightSignal,n?.lightBumpRightSignal],l=s.filter(p=>p!=null).reduce((p,x)=>Math.max(p,x),1200),o=p=>Math.pow(Math.max(0,Math.min(1,(p??0)/l)),.35),f=p=>p==null||p<=0?"hsl(200 60% 18%)":`hsl(${(200+o(p)*360)%360} 100% 60%)`,d=6,h=12;return r.jsx("div",{className:"flex w-full items-center justify-center gap-0.5",children:s.map((p,x)=>{const g=o(p),v=xr.jsxs("span",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:re}),r.jsx("span",{className:"font-semibold text-white",children:ue})]},re))]})}),r.jsx("div",{className:`absolute ${H} left-1/2`,style:te,children:r.jsxs("div",{className:`flex items-center gap-0.5 bg-black/80 text-slate-100 ${O} ${K}`,children:[r.jsx("span",{className:"font-semibold text-white rounded px-1 py-[1px] border border-transparent",style:ca(o,.18),children:l||"Unnamed Rover"}),v?r.jsxs("span",{className:"text-slate-300",children:["• ",v]}):null]})})]}),S?r.jsx("div",{className:"pointer-events-none absolute rounded",style:{...q},children:r.jsx(Uf,{sensors:s,size:240,overlay:!0})}):null]})}return r.jsxs("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:[r.jsx("div",{className:`absolute ${_} font-medium text-slate-100 ${T}`,children:r.jsxs("div",{className:"flex flex-col gap-0.5 leading-none",children:[r.jsxs("span",{children:["Status: ",f]}),d?r.jsxs("span",{children:["Audio: ",d]}):null,h?r.jsx("span",{className:"text-cyan-300",children:h}):null]})}),k?r.jsx("div",{className:`absolute left-1/2 top-0.5 -translate-x-1/2 rounded bg-black/70 text-slate-100 ${X} ${U}`,children:k}):null,r.jsx("div",{className:`absolute ${H} left-1/2`,style:te,children:r.jsx("div",{className:`flex gap-0.5 bg-black/80 text-slate-100 ${O} ${K}`,children:r.jsxs("span",{children:["Rover:"," ",r.jsxs("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ca(o,.18),children:['"',l||"Unnamed Rover",'"']})]})})}),S&&g!=="spectator"?r.jsx("div",{className:"pointer-events-none absolute rounded",style:{...q},children:r.jsx(Uf,{sensors:s,size:240,overlay:!0})}):null]})}function aN({mobileHud:n=!1,turnSeconds:s=null,isActiveDriver:l=!1,idleSkipSeconds:o=null}){const f=n?"text-3xl":"text-5xl",d=n?"text-xs":"text-sm",h=n?"text-[0.55rem]":"text-[0.75rem]",p=n?"px-4 py-3":"px-6 py-4",x=l&&typeof o=="number";return r.jsx("div",{className:"pointer-events-none absolute inset-0 z-30 flex items-center justify-center bg-black/55",children:r.jsxs("div",{className:`flex flex-col items-center gap-0.5 rounded border border-amber-300/80 bg-black/70 ${p}`,children:[r.jsx("div",{className:`font-semibold text-amber-200 ${f}`,children:"IT IS YOUR TURN!"}),r.jsx("div",{className:`text-amber-200/80 ${d}`,children:"Start driving!"}),x?r.jsxs("div",{className:`text-red-100/90 ${h}`,children:["Idle skip in ",o,"s"]}):null]})})}const sN={leftWheel:"Left wheel",rightWheel:"Right wheel",mainBrush:"Main brush",sideBrush:"Side brush",limiter:"Overcurrent limit"};function lN({motors:n,fill:s=0,compact:l=!1}){if(!n?.length)return null;const o=n.map(v=>sN[v]||v),f=l?"w-[12rem] h-[3.5rem]":"w-[20rem] h-[7rem]",d=l?"px-2 py-1":"px-4 py-2",h=l?"text-lg":"text-4xl",p=l?"text-xs":"text-xl",x=Math.max(0,Math.min(1,s)),g=`${Math.round(x*100)}%`;return r.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-red-900/50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 ${f}`,children:r.jsxs("div",{className:"relative h-full w-full",children:[r.jsx("div",{className:"absolute inset-0 overflow-hidden",children:r.jsx("div",{className:"h-full bg-red-700/60",style:{width:g}})}),r.jsxs("div",{className:`relative z-10 flex h-full w-full flex-col items-center justify-center text-center font-semibold text-white animate-pulse ${h} ${d}`,children:[r.jsx("div",{children:"OVERCURRENT"}),r.jsx("div",{className:`mt-0 font-medium text-white ${p}`,children:o.join(", ")})]})]})})}function iN({battery:n,compact:s=!1}){if(!n?.available||!n.warnActive&&!n.urgentActive)return null;const l=n.urgentActive?"BATTERY VERY LOW, DOCK THE ROVER AND CHARGE IMMEDIATELY!!":"Battery low! please dock and charge the rover soon.",o=s?"p-2 top-6":"p-4 top-10",f=s?"text-sm":"text-2xl";return r.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-amber-900/60 left-1/2 -translate-x-1/2 ${o}`,children:r.jsx("div",{className:`text-center font-semibold text-white animate-pulse ${f}`,children:r.jsx("div",{children:l})})})}function rN({compact:n=!1}){const s=ft(_=>_.session),{sendMessage:l,onInputFocus:o,onInputBlur:f,blurChat:d,registerInputRef:h,setTypingActive:p}=od(),{value:x}=He("tts",{engine:"flite",voice:"rms",pitch:50}),[g,v]=m.useState(""),[y,S]=m.useState(!1),E=s?.role!=="spectator",C=s?.role==="spectator",k=s?.assignment?.roverId||null,j=!!m.useMemo(()=>s?.roster?.find(_=>String(_.id)===String(k))||null,[k,s?.roster])?.audio?.ttsEnabled,N=m.useMemo(()=>{if(!j)return null;const _=x?.engine==="espeak"?"espeak":"flite";if(_==="espeak"){let X=Number.isFinite(x?.pitch)?Math.round(x.pitch):void 0;return typeof X=="number"&&(X=Math.max(0,Math.min(99,X))),{speak:!0,engine:_,pitch:X}}const U=typeof x?.voice=="string"?x.voice:void 0;return{speak:!0,engine:_,voice:U}},[x?.engine,x?.pitch,x?.voice,j]),T=n?"pointer-events-auto absolute bottom-0.5 right-0.5 flex w-[9rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.4 py-0.2":"pointer-events-auto absolute bottom-1 right-1 flex w-[12rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.5 py-0.25",M=n?"min-w-0 flex-1 bg-transparent text-[0.55rem] text-slate-100 placeholder:text-slate-400 focus:outline-none":"min-w-0 flex-1 bg-transparent text-[0.7rem] text-slate-100 placeholder:text-slate-400 focus:outline-none",O=n?"rounded bg-cyan-500/80 px-0.35 py-0.2 text-[0.55rem] font-semibold text-black disabled:opacity-50":"rounded bg-cyan-500/80 px-0.5 py-0.25 text-[0.7rem] font-semibold text-black disabled:opacity-50";async function K(_){if(_.preventDefault(),!E)return;const U=g.trim();if(U){S(!0);try{await l(U,N),v(""),d(),p(!1)}catch(X){alert(X.message)}finally{S(!1)}}}return C?null:r.jsxs("form",{onSubmit:K,className:T,children:[r.jsx("input",{className:M,value:g,onChange:_=>{const U=_.target.value;v(U),p(!!U.trim())},onFocus:_=>{o(_),p(!!g.trim())},onBlur:_=>{f(_),p(!1)},onKeyDown:_=>{_.key==="Enter"&&!g.trim()&&(_.preventDefault(),d(),p(!1))},ref:_=>h(_,{target:"hud"}),placeholder:E?"Chat (TTS)":"Spectator",disabled:!E}),r.jsx("button",{type:"submit",disabled:!E||y,className:O,children:"Speak"})]})}function xd({layoutFormat:n="desktop"}){const s=ft(ae=>ae.session),{state:{song:l,lastControlIntentAt:o},overcurrentLimiter:f}=_t(),[d,h]=m.useState(()=>Date.now()),[p,x]=m.useState(!1),[g,v]=m.useState(null),y=m.useRef({active:!1,roverId:null});m.useEffect(()=>{if(s?.mode!=="turns")return;const ae=setInterval(()=>h(Date.now()),250);return()=>clearInterval(ae)},[s?.mode]);const S=s?.assignment?.roverId,C=!!(S&&s?.roster?s.roster.find(ae=>String(ae.id)===String(S)):null)?.media?.audioPublishUrl,k=S?s?.turnQueues?.[S]:null,w=s?.socketId||null,j=S?s?.activeDrivers?.[S]:null,N=!!(w&&j===w),T=m.useMemo(()=>{const ae=k?.queue||[];if(!ae.length||!k?.current||ae.length<=1)return null;const pe=ae.findIndex(re=>re===k.current);return pe===-1?ae[0]||null:ae[(pe+1)%ae.length]||null},[k?.queue,k?.current]),M=!!(w&&T===w),O=k?.deadline||null,K=k?.idleDeadline||null,_=O?O-d:null,U=K?K-d:null,X=s?.mode==="turns"&&M&&_!=null&&_<=5e3&&_>0,F=s?.mode!=="turns"||N||X,H=_!=null&&Number.isFinite(_)?Math.max(0,Math.ceil(_/1e3)):null,te=U!=null&&Number.isFinite(U)?Math.max(0,Math.ceil(U/1e3)):null,ce=N?H!=null?`${H}s left`:null:M&&H!=null?`Your turn in ${H}s`:null,oe=S?[...F?[{type:"rover",id:S,key:S}]:[],...C?[{type:"rover",id:`${S}-audio`,key:`${S}-audio`}]:[]]:[],V=Ai(oe),q=S&&F?V[S]:null,L=S&&C?V[`${S}-audio`]:null,Z=md(S?[S]:[],{enabled:!!S,version:s?.mode}),le=S&&Z[S]||null,fe=ml(S),R=S&&s?.roster?s.roster.find(ae=>String(ae.id)===String(S)):null,$=R?.battery??null,ee=R?.name||(S?`Rover ${S}`:"");return m.useEffect(()=>{if(s?.mode!=="turns"){x(!1),v(null),y.current={active:!1,roverId:null};return}const ae=y.current,pe=N&&!ae.active,re=N&&S&&S!==ae.roverId;pe||re?(x(!0),v(Date.now())):!N&&ae.active&&(x(!1),v(null)),y.current={active:N,roverId:S}},[N,S,s?.mode]),m.useEffect(()=>{!p||!g||o>g&&x(!1)},[o,g,p]),r.jsx("section",{className:"panel",children:S?r.jsx(wi,{sessionInfo:q,videoMode:F?"whep":"snapshot",snapshotFeed:le,audioSessionInfo:L,label:ee,roverColor:R?.color||null,telemetryFrame:fe,batteryConfig:$,layoutFormat:n,overcurrentLimiter:f,songNote:l?.note,qualityNotice:F?null:"Preview feed (low FPS) until your turn.",showTurnCue:p,turnTimerText:ce,turnSeconds:H,isActiveDriver:N,idleSkipSeconds:te}):r.jsxs("div",{className:"panel-muted content-center text-center text-sm text-slate-400 aspect-[4/3]",children:[r.jsx("p",{children:"You are not assigned to a rover."}),r.jsx("p",{className:"mt-0",children:r.jsx("a",{href:"/spectate",className:"text-blue-400 underline hover:text-blue-500",children:"Click here to visit the spectator page."})})]})})}function yo({label:n,tone:s="muted"}){const l=s==="success"?"bg-emerald-900 text-emerald-100":s==="warn"?"bg-amber-900 text-amber-100":"bg-slate-800 text-slate-200";return r.jsx("span",{className:`rounded px-1 py-0.5 text-xs font-semibold leading-none ${l}`,children:n})}function Mo(n){if(!Number.isFinite(n))return 0;const s=n%360;return s<0?s+360:s}function oN(n){if(!Array.isArray(n)||n.length<3)return 0;const[s,l,o]=n,f=Math.max(0,Math.min(255,Number(s)))/255,d=Math.max(0,Math.min(255,Number(l)))/255,h=Math.max(0,Math.min(255,Number(o)))/255,p=Math.max(f,d,h),x=Math.min(f,d,h),g=p-x;if(g===0)return 0;let v=0;return p===f?v=(d-h)/g%6:p===d?v=(h-f)/g+2:v=(f-d)/g+4,Mo(Math.round(v*60))}function ox(n){const s=Mo(n),l=1,o=1-Math.abs(s/60%2-1);let f=0,d=0,h=0;return s<60?(f=l,d=o):s<120?(f=o,d=l):s<180?(d=l,h=o):s<240?(d=o,h=l):s<300?(f=o,h=l):(f=l,h=o),[Math.round(f*255),Math.round(d*255),Math.round(h*255)]}function cx(n){return n?Array.isArray(n.hsColor)?Mo(Number(n.hsColor[0])):Array.isArray(n.rgbColor)?oN(n.rgbColor):0:0}function cN({entity:n,connected:s,controlsLocked:l,onToggle:o,onSetColor:f,onSetWhite:d}){const h=n.state==="unavailable"||!n.available,p=n.state==="on",x=n.type==="light"&&n.supportsColor,g=h?"warn":p?"success":"muted",v=h?"Unavailable":p?"On":"Off",y=l||!s||h,S=y||!x,[E,C]=m.useState(()=>cx(n)),k=m.useRef(E),w=m.useRef(!1),j=h?"border-slate-800 bg-slate-900 text-slate-400 cursor-not-allowed":l?"border-slate-800 bg-slate-900 text-slate-300 cursor-not-allowed":p?"border-emerald-700 bg-emerald-900/80 text-emerald-50 hover:bg-emerald-800":"border-rose-800 bg-rose-900/80 text-rose-50 hover:bg-rose-800";m.useEffect(()=>{if(!x||w.current)return;const U=cx(n);k.current=U,C(U)},[n.rgbColor,n.hsColor,x]);const N=U=>{const X=Mo(Number(U.target.value));k.current=X,C(X)},T=()=>{S||!f||f(n.id,ox(k.current))},M=U=>{U.stopPropagation()},O=U=>{M(U),!(S||!d)&&d(n.id)},_=`rgb(${(x?ox(k.current):[255,255,255]).join(",")})`;return r.jsxs("button",{type:"button",onClick:()=>o(n.id),disabled:y,className:`relative flex min-w-[12rem] flex-[1_1_12rem] items-start justify-between gap-0.5 rounded px-1 py-0.5 text-left transition-colors ${j} disabled:opacity-60 disabled:hover:bg-inherit`,children:[r.jsxs("div",{className:"min-w-0 flex-1",children:[r.jsxs("div",{className:"flex items-center gap-0.5 text-sm leading-normal",children:[r.jsx("span",{className:"truncate font-semibold text-white",children:n.name||n.id}),x&&r.jsxs(r.Fragment,{children:[r.jsx(yo,{label:v,tone:g}),!s&&r.jsx("span",{className:"text-xs text-amber-200",children:"Offline"})]})]}),x?r.jsx("div",{className:"-mt-0.5 w-full",onClick:M,onPointerDown:U=>{M(U),w.current=!0},onPointerUp:U=>{M(U),w.current=!1,T()},onPointerCancel:U=>{M(U),w.current=!1,T()},onKeyUp:U=>{M(U),T()},onBlur:T,children:r.jsx("div",{className:"relative w-full",children:r.jsx("input",{type:"range",min:"0",max:"360",step:"1",value:E,onChange:N,disabled:S,"aria-label":`Set color for ${n.name||n.id}`,className:"ha-hue-slider w-full"})})}):r.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-400",children:[r.jsx(yo,{label:v,tone:g}),!s&&r.jsx("span",{className:"text-amber-200",children:" · Offline"})]})]}),x&&r.jsxs("div",{className:"absolute right-1 top-1 flex items-center gap-0.5",children:[r.jsx("span",{role:"button",tabIndex:S?-1:0,onClick:O,onPointerDown:M,onKeyDown:U=>{S||(U.key==="Enter"||U.key===" ")&&(U.preventDefault(),O(U))},title:"Set white color temperature","aria-label":`Set ${n.name||n.id} to white`,"aria-disabled":S,className:`inline-flex items-center justify-center rounded border border-slate-200 bg-white px-1 py-0.5 text-xs font-semibold leading-none text-slate-900 ${S?"cursor-not-allowed opacity-60":"cursor-pointer hover:bg-slate-100"}`,children:"white"}),r.jsx("span",{className:"pointer-events-none h-2.5 w-2.5 rounded-full border border-white/60",style:{backgroundColor:_}})]}),!x&&r.jsx("div",{className:"self-center text-xs font-semibold text-white/90",children:p?"Turn off":"Turn on"})]})}function Hg(){const{state:{keymap:n}}=_t(),s=ft(E=>E.session),{homeAssistantToggle:l,homeAssistantSetLightColor:o,homeAssistantSetLightWhite:f}=wn(),d=s?.homeAssistant,h=m.useMemo(()=>d?.entities||[],[d?.entities]),p=d?.lightPolicy||null,x=!!(p?.locked||p?.lockedOn),g=p?.lockState||(p?.lockedOn?"on":null),v=An(n?.homeAssistantOn?.[0]),y=An(n?.homeAssistantOff?.[0]);if(!d?.enabled)return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm text-slate-400",children:[r.jsx("p",{className:"text-slate-300",children:"Room Controls"}),r.jsx("p",{className:"text-slate-500",children:"Not configured on the server."})]});if(h.length===0)return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm text-slate-400",children:[r.jsx("p",{className:"text-slate-300",children:"Room Controls"}),r.jsx("p",{className:"text-slate-500",children:"No lights or switches configured."})]});const S=!!d?.connected;return r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("header",{className:"flex items-center justify-between gap-0.5 text-sm text-slate-400",children:[r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("p",{children:"Room Controls"}),r.jsx("span",{className:"text-xs text-slate-500",children:h.length}),x?r.jsx(yo,{label:g==="off"?"Locked Off":"Locked On",tone:"warn"}):null,r.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-300 background-black",children:[r.jsxs("span",{className:"flex items-center gap-0.5",children:[r.jsx("span",{children:"On"}),v?r.jsx(ux,{label:v}):null]}),r.jsxs("span",{className:"flex items-center gap-0.5",children:[r.jsx("span",{children:"Off"}),y?r.jsx(ux,{label:y}):null]})]})]}),r.jsx(yo,{label:S?"Connected":"Offline",tone:S?"success":"warn"})]}),x?r.jsx("p",{className:"rounded border border-amber-600/60 bg-amber-900/40 px-1 py-0.5 text-xs text-amber-100",children:g==="off"?"Lights are locked off. Room controls are disabled.":"Lights are locked on. Room controls are disabled."}):null,r.jsx("div",{className:"flex flex-wrap gap-0.5",children:h.map(E=>r.jsx(cN,{entity:E,connected:S,controlsLocked:x,onToggle:l,onSetColor:o,onSetWhite:f},E.id))})]})}function ux({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function Vg(){const{login:n,setRole:s}=wn(),[l,o]=m.useState(""),[f,d]=m.useState(""),[h,p]=m.useState(!1);async function x(g){g.preventDefault(),p(!0);try{await n(l,f),o(""),d("")}catch(v){alert(v.message)}finally{p(!1)}}return r.jsxs("div",{className:"panel-section space-y-0.5 text-base",children:[r.jsx("p",{className:"text-sm text-slate-400",children:"Admin login"}),r.jsxs("form",{className:"flex flex-col gap-0.5",onSubmit:x,children:[r.jsx("input",{className:"field-input",placeholder:"Username",value:l,onChange:g=>o(g.target.value)}),r.jsx("input",{className:"field-input",placeholder:"Password",type:"password",value:f,onChange:g=>d(g.target.value)}),r.jsx("button",{type:"submit",disabled:h,className:"button-dark w-full disabled:opacity-50",children:h?"Logging in…":"Login"})]})]})}function fx(...n){return n.filter(Boolean).join(" ")}function uN(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function fN(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function dN({title:n,roster:s=[],emptyText:l="No roster data.",renderActions:o=null}){return r.jsxs("div",{className:"space-y-0.5 text-sm",children:[n&&r.jsx("p",{className:"text-sm text-slate-400",children:n}),s.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:l}):r.jsx("ul",{className:"space-y-0.5 text-sm",children:s.map(f=>{const d=!!(f?.private?.enabled&&f?.private?.open),h=!!f?.locked;return r.jsxs("li",{className:fx("surface flex flex-wrap items-center justify-between gap-0.5",h?"bg-red-900/40":d?"bg-amber-700/35 border border-amber-200/30":null),children:[r.jsxs("div",{children:[r.jsx("p",{className:"text-slate-200",children:r.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ca(f.color,.16),children:f.name})}),r.jsxs("p",{className:"text-xs text-slate-500 flex flex-wrap items-center gap-0.5",children:[r.jsx("span",{children:f.locked?"locked":"free"}),f.lockReason&&r.jsx("span",{className:"rounded bg-black/30 px-1",children:f.lockReason}),r.jsxs("span",{className:fx("font-semibold",fN(f)),children:["Battery ",uN(f)]})]})]}),o?o(f):null]},f.id)})})]})}const mN=[{key:"open",label:"Open"},{key:"turns",label:"Turns"},{key:"admin",label:"Admin"},{key:"lockdown",label:"Lockdown"}];function hN(){const{session:n,lockRover:s,setMode:l,requestControl:o,setCommunityGoal:f,setAdminReason:d,rebootRover:h,rebootServer:p,setAudioLevels:x,setPrivateSafety:g,llmControl:v,adminLogs:y,llmCommentaryState:S}=nn(),E=m.useMemo(()=>n?.roster??[],[n?.roster]),[C,k]=m.useState({}),[w,j]=m.useState({}),[N,T]=m.useState(!1),[M,O]=m.useState(!1),K=n?.health||null,_=n?.communityGoal?.text||"",U=n?.communityGoal?.updatedAt||null,[X,F]=m.useState(_),H=n?.adminReason?.text||"",te=n?.adminReason?.updatedAt||null,[ce,oe]=m.useState(H),V=n?.audioLevels||{},[q,L]=m.useState({hornGain:Number.isFinite(V.hornGain)?V.hornGain:1,ttsGain:Number.isFinite(V.ttsGain)?V.ttsGain:1,forwardGain:Number.isFinite(V.forwardGain)?V.forwardGain:1}),[Z,le]=m.useState({}),fe=n?.role==="admin"||n?.role==="lockdown"||n?.role==="lockdown-admin",R=n?.role==="lockdown"||n?.role==="lockdown-admin",$=n?.mode??"open",ee=async(se,P)=>{try{await s(se,P),k(de=>({...de,[se]:P}))}catch(de){alert(de.message)}},ae=async se=>{const P=se.target.value;try{await l(P)}catch(de){alert(de.message)}},pe=async se=>{try{await o(se,{force:!0})}catch(P){alert(P.message)}},re=async se=>{if(!(!se?.id||!window.confirm(`Reboot rover "${se.name||se.id}" now?`))){j(de=>({...de,[se.id]:!0}));try{await h(se.id)}catch(de){alert(de.message)}finally{j(de=>({...de,[se.id]:!1}))}}},ue=async()=>{if(window.confirm("Reboot the server host now? This will disconnect all users.")){T(!0);try{await p()}catch(P){alert(P.message),T(!1)}}},ve=async()=>{if(window.confirm("Clear LLM commentary history now? This resets chat context, bot memory, and rover activity metrics for narration.")){O(!0);try{await v("clearHistory")}catch(P){alert(P.message)}finally{O(!1)}}},be=async()=>{try{await f(X)}catch(se){alert(se.message)}},xe=async()=>{try{await f(null)}catch(se){alert(se.message)}},Be=async()=>{try{await d(ce)}catch(se){alert(se.message)}},ze=async()=>{try{await d(null)}catch(se){alert(se.message)}},Ae=se=>P=>{const de=Number(P.target.value);L(Ne=>({...Ne||{},[se]:Number.isFinite(de)?de:1}))},tt=async()=>{try{await x(q)}catch(se){alert(se.message)}},Je=async()=>{window.dispatchEvent(new CustomEvent("buttonBox:rewardRunLocalTest",{detail:{rewardName:"Admin Mode",count:1e3,goal:1e3}}))};m.useEffect(()=>{F(_)},[_]),m.useEffect(()=>{oe(H)},[H]),m.useEffect(()=>{L({hornGain:Number.isFinite(V.hornGain)?V.hornGain:1,ttsGain:Number.isFinite(V.ttsGain)?V.ttsGain:1,forwardGain:Number.isFinite(V.forwardGain)?V.forwardGain:1})},[V.forwardGain,V.hornGain,V.ttsGain]),m.useEffect(()=>{const se={};(E||[]).forEach(P=>{P?.private?.enabled&&(se[P.id]={speedLimitEnabled:!!P?.private?.safety?.speedLimitEnabled,speedLimitMaxWheelSpeed:Number.isFinite(P?.private?.safety?.speedLimitMaxWheelSpeed)?P.private.safety.speedLimitMaxWheelSpeed:250,hardOvercurrentEnabled:!!P?.private?.safety?.hardOvercurrentEnabled,overcurrentStopMs:Number.isFinite(P?.private?.safety?.overcurrentStopMs)?P.private.safety.overcurrentStopMs:300,hardBumpEnabled:!!P?.private?.safety?.hardBumpEnabled,bumpBackoffSpeed:Number.isFinite(P?.private?.safety?.bumpBackoffSpeed)?P.private.safety.bumpBackoffSpeed:250,bumpBackoffMs:Number.isFinite(P?.private?.safety?.bumpBackoffMs)?P.private.safety.bumpBackoffMs:350,cliffEnabled:!!P?.private?.safety?.cliffEnabled,cliffBackoffSpeed:Number.isFinite(P?.private?.safety?.cliffBackoffSpeed)?P.private.safety.cliffBackoffSpeed:250,cliffBackoffMs:Number.isFinite(P?.private?.safety?.cliffBackoffMs)?P.private.safety.cliffBackoffMs:500,triggerCooldownMs:Number.isFinite(P?.private?.safety?.triggerCooldownMs)?P.private.safety.triggerCooldownMs:800})}),le(se)},[E]);const vt=m.useMemo(()=>{const se={};return E.forEach(P=>{se[P.id]=C[P.id]??P.locked}),se},[E,C]),ie=(se,P={})=>{le(de=>({...de||{},[se]:{...de?.[se]||{},...P||{}}}))},me=async se=>{try{const P=Z?.[se];if(!P)return;await g(se,P)}catch(P){alert(P.message)}};return fe?r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5 text-sm",children:[r.jsx("span",{children:"Admin controls"}),r.jsx("select",{value:$,onChange:ae,className:"field-input text-sm",children:mN.map(se=>r.jsx("option",{value:se.key,children:se.label},se.key))})]}),r.jsxs("div",{className:"flex gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:ue,disabled:N,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:N?"Server rebooting...":"Reboot Server"}),r.jsx("button",{type:"button",onClick:Je,className:"button-dark",children:"Test Reward Popup"})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Global audio levels"}),n?.audioLevels?.updatedAt?r.jsxs("span",{children:["Updated ",new Date(n.audioLevels.updatedAt).toLocaleString()]}):null]}),r.jsxs("label",{className:"grid gap-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Horn gain"}),r.jsxs("span",{children:[q.hornGain.toFixed(2),"x"]})]}),r.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:q.hornGain,onChange:Ae("hornGain"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"grid gap-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"TTS gain"}),r.jsxs("span",{children:[q.ttsGain.toFixed(2),"x"]})]}),r.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:q.ttsGain,onChange:Ae("ttsGain"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"grid gap-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Forward gain"}),r.jsxs("span",{children:[q.forwardGain.toFixed(2),"x"]})]}),r.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:q.forwardGain,onChange:Ae("forwardGain"),className:"w-full accent-emerald-500"})]}),r.jsx("div",{className:"flex gap-0.5 text-xs",children:r.jsx("button",{type:"button",onClick:tt,className:"button-dark",children:"Apply audio levels"})})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Community goal"}),U?r.jsxs("span",{children:["Updated ",new Date(U).toLocaleString()]}):null]}),r.jsx("input",{type:"text",value:X,onChange:se=>F(se.target.value),placeholder:"Set a community goal",className:"field-input text-sm"}),r.jsxs("div",{className:"flex gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:be,className:"button-dark",children:"Set goal"}),r.jsx("button",{type:"button",onClick:xe,className:"button-danger",children:"Clear"})]})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Admin mode reason"}),te?r.jsxs("span",{children:["Updated ",new Date(te).toLocaleString()]}):null]}),r.jsx("textarea",{value:ce,onChange:se=>oe(se.target.value),placeholder:"Set an admin mode reason",className:"field-input text-sm min-h-[3.5rem]"}),r.jsxs("div",{className:"flex gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:Be,className:"button-dark",children:"Set reason"}),r.jsx("button",{type:"button",onClick:ze,className:"button-danger",children:"Clear"})]})]}),r.jsx(dN,{roster:E,renderActions:se=>r.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:()=>ee(se.id,!vt[se.id]),className:"button-dark",children:vt[se.id]?"Unlock":"Lock"}),r.jsx("button",{type:"button",onClick:()=>pe(se.id),className:"button-dark",children:"Force"}),r.jsx("button",{type:"button",onClick:()=>re(se),disabled:!!w[se.id],className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:w[se.id]?"Rebooting...":"Reboot"}),se?.private?.enabled?r.jsxs("div",{className:"w-full rounded border border-slate-700/70 p-0.5 space-y-0.5 text-[0.7rem]",children:[r.jsx("div",{className:"text-slate-300",children:"Private safety"}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!Z?.[se.id]?.speedLimitEnabled,disabled:!R,onChange:P=>ie(se.id,{speedLimitEnabled:!!P.target.checked})}),r.jsx("span",{children:"Speed limit"})]}),r.jsx("input",{type:"number",min:"1",max:"500",className:"field-input text-xs w-20",disabled:!R,value:Z?.[se.id]?.speedLimitMaxWheelSpeed??250,onChange:P=>ie(se.id,{speedLimitMaxWheelSpeed:Number(P.target.value)||250})}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!Z?.[se.id]?.hardOvercurrentEnabled,disabled:!R,onChange:P=>ie(se.id,{hardOvercurrentEnabled:!!P.target.checked})}),r.jsx("span",{children:"Hard overcurrent"})]}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!Z?.[se.id]?.hardBumpEnabled,disabled:!R,onChange:P=>ie(se.id,{hardBumpEnabled:!!P.target.checked})}),r.jsx("span",{children:"Hard bump"})]}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!Z?.[se.id]?.cliffEnabled,disabled:!R,onChange:P=>ie(se.id,{cliffEnabled:!!P.target.checked})}),r.jsx("span",{children:"Cliff safety"})]}),r.jsx("button",{type:"button",disabled:!R,onClick:()=>me(se.id),className:"button-dark disabled:opacity-50",children:"Apply Safety"})]}):null]})}),r.jsx(vN,{health:K,roster:E}),r.jsx(pN,{state:S,onClearHistory:ve,clearingHistory:M}),r.jsx(bN,{entries:y})]}):null}function pN({state:n,onClearHistory:s,clearingHistory:l}){const[o,f]=m.useState(null);if(!n)return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"LLM Commentary"}),r.jsx("div",{className:"surface text-xs text-slate-300",children:"No status received yet."})]});const d=n.runtime||{},h=n.counters||{},p=n.timings||{},x=n.input||{},g=n.output||{},v=n.errors||{},y=Array.isArray(n.history)?n.history:[],S=y.find(w=>w.runId===o)||(y.length?y[y.length-1]:null),E=xN(n),C=gN(x.modelMessages,g.raw),k=[{label:"running",value:d.running?"yes":"no"},{label:"in flight",value:d.inFlight?"yes":"no"},{label:"phase",value:d.phase||"--"},{label:"run id",value:d.currentRunId??"--"},{label:"tick count",value:d.tickCount??0},{label:"last tick",value:d.lastTickAt?new Date(d.lastTickAt).toLocaleString():"never"},{label:"next run",value:d.nextRunAt?new Date(d.nextRunAt).toLocaleString():"n/a"},{label:"outcome",value:d.outcome||"--"},{label:"reason",value:d.reason||"--"},{label:"skip streak",value:h.skipStreak??0},{label:"clear count",value:h.clearCount??0},{label:"last gen",value:p.lastGenerationMs!=null?`${p.lastGenerationMs} ms`:"--"},{label:"avg gen",value:p.avgGenerationMs!=null?`${p.avgGenerationMs} ms`:"--"},{label:"gen count",value:p.generationCount??0},{label:"prompt chars",value:h.promptChars??0},{label:"active drivers",value:h.snapshotSummary?.activeDrivers??0},{label:"snapshot rovers",value:h.snapshotSummary?.rovers??0},{label:"snapshot chat",value:h.snapshotSummary?.chatMessages??0}];return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"LLM Commentary"}),r.jsx("div",{className:"flex gap-0.5 text-xs",children:r.jsx("button",{type:"button",onClick:s,disabled:!!l,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:l?"Clearing...":"Clear LLM History"})}),r.jsxs("div",{className:`surface border text-center ${E.className}`,children:[r.jsx("div",{className:"text-[1.1rem] font-bold tracking-wide",children:E.label}),r.jsx("div",{className:"text-xs text-slate-200",children:E.detail})]}),r.jsx("div",{className:"surface flex flex-wrap gap-0.5 text-xs",children:k.map(w=>r.jsxs("span",{className:"rounded border border-slate-600/60 bg-slate-800/70 px-0.5 py-0.25 text-[0.72rem] leading-tight text-slate-200",children:[w.label,": ",w.value]},w.label))}),v.message?r.jsxs("div",{className:"surface text-xs text-red-300 break-words",children:["Error: ",v.message]}):null,v.details?r.jsxs("details",{className:"surface text-xs text-red-200",children:[r.jsx("summary",{className:"cursor-pointer select-none text-red-300",children:"Failure details"}),r.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-red-200",children:JSON.stringify(v.details,null,2)})]}):null,g.generated?r.jsxs("div",{className:"surface text-xs text-slate-200 break-words",children:["Generated: ",g.generated]}):null,g.posted?r.jsxs("div",{className:"surface text-xs text-emerald-200 break-words",children:["Posted: ",g.posted]}):null,r.jsxs("div",{className:"grid gap-0.5 md:grid-cols-2",children:[r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"Live Input Conversation"}),r.jsx("div",{className:"surface max-h-72 space-y-0.5 overflow-y-auto",children:C.length?C.map(w=>r.jsx(ld,{message:w.message},w.id)):r.jsx("div",{className:"text-xs text-slate-300",children:"No model conversation captured yet."})})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"Output + Error"}),r.jsxs("div",{className:"surface space-y-0.5 text-xs text-slate-200",children:[r.jsxs("div",{children:["Raw output: ",g.raw?.trim()?g.raw:""]}),r.jsxs("div",{children:["Posted: ",g.posted||""]}),r.jsxs("div",{children:["Output at:"," ",g.modelOutputAt?new Date(g.modelOutputAt).toLocaleString():"n/a"]}),r.jsxs("div",{children:["Failed at: ",v.failedAt?new Date(v.failedAt).toLocaleString():"n/a"]})]})]})]}),r.jsxs("details",{className:"surface text-xs text-slate-200",children:[r.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Full Monitor Payload"}),r.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(n,null,2)})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"Recent Runs"}),r.jsx("div",{className:"surface max-h-52 space-y-0.5 overflow-y-auto text-xs",children:y.length?y.slice().reverse().map(w=>r.jsxs("button",{type:"button",onClick:()=>f(w.runId),className:`w-full text-left surface ${S?.runId===w.runId?"border border-sky-400/50":""}`,children:[r.jsxs("span",{className:"text-slate-300",children:["#",w.runId]})," ",r.jsx("span",{className:"text-slate-200",children:w.outcome||w.phase||"--"})," ",r.jsx("span",{className:"text-slate-400",children:w.durationMs!=null?`${w.durationMs}ms`:"--"})," ",r.jsx("span",{className:"text-slate-500",children:w.reason||""})]},w.runId)):r.jsx("div",{className:"text-slate-300",children:"No runs recorded yet."})})]}),S?r.jsxs("details",{className:"surface text-xs text-slate-200",open:!0,children:[r.jsxs("summary",{className:"cursor-pointer select-none text-slate-300",children:["Run #",S.runId," details"]}),r.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(S,null,2)})]}):null]})}function xN(n){const s=n?.runtime||{},l=n?.output||{},o=n?.errors||{};return s.inFlight?{label:"IN FLIGHT",detail:s.reason||"Generating commentary now",className:"border-amber-400/60 bg-amber-700/20 text-amber-200"}:s.outcome==="posted"?{label:"POSTED",detail:l.posted?`Last: ${l.posted}`:"Commentary posted",className:"border-emerald-400/60 bg-emerald-700/20 text-emerald-200"}:s.outcome==="skipped"?{label:"SKIPPED",detail:s.reason||"Model chose to skip",className:"border-slate-400/60 bg-slate-700/30 text-slate-200"}:s.outcome==="failed"?{label:"FAILED",detail:o.message||s.reason||"Tick failed",className:"border-red-400/60 bg-red-700/20 text-red-200"}:{label:s.running?"IDLE":"STOPPED",detail:s.reason||"Waiting for next tick",className:"border-sky-400/50 bg-sky-700/20 text-sky-200"}}function gN(n,s){const l=Date.now(),f=(Array.isArray(n)?n:[]).map((d,h)=>{const p=String(d?.role||"").toLowerCase(),x=typeof d?.content=="string"?d.content:JSON.stringify(d?.content??null,null,2),g=p==="system"?"LLM System":p==="assistant"?"LLM Context":p==="user"?"LLM Input":"LLM Message";return{id:`llm-msg-${h}`,message:{ts:l+h,nickname:g,text:x,role:"spectator",system:p==="system"}}});if(s!=null){const d=String(s);f.push({id:"llm-output",message:{ts:l+f.length+1,nickname:"LLM Output",text:d.trim()?d:"",role:"spectator",system:!0}})}return f}function vN({health:n,roster:s=[]}){if(!n)return null;const l=n.replay||{sources:[],readyCount:0,totalCount:0},o=n.snapshots||{rovers:[],rooms:[]},f=x=>s.find(g=>String(g.id)===String(x))?.color||null,d=`${l.readyCount}/${l.totalCount} sources ready`,h=o.rovers.filter(x=>x.stale).length,p=o.rooms.filter(x=>x.stale).length;return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"Health"}),r.jsxs("div",{className:"surface space-y-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:"Replay segments"}),r.jsx("span",{className:"text-slate-400",children:d})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:"Rover snapshots"}),r.jsxs("span",{className:h?"text-amber-300":"text-emerald-300",children:[o.rovers.length-h,"/",o.rovers.length," ok"]})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:"Room cameras"}),r.jsxs("span",{className:p?"text-amber-300":"text-emerald-300",children:[o.rooms.length-p,"/",o.rooms.length," ok"]})]})]}),r.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:l.sources.map(x=>r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{className:`${x.type==="rover"?"rounded px-1 py-[1px] border border-transparent":""}`,style:x.type==="rover"?ca(f(x.id),.16):void 0,children:x.label}),r.jsxs("span",{className:x.ready?"text-emerald-300":"text-amber-300",children:[x.recentCount,"/",x.neededCount]})]},`${x.type}:${x.id}`))}),r.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:o.rovers.map(x=>r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ca(f(x.id),.16),children:x.name}),r.jsx("span",{className:x.stale?"text-amber-300":"text-emerald-300",children:x.stale?"stale":"ok"})]},`rover:${x.id}`))}),r.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:o.rooms.map(x=>r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:x.name}),r.jsx("span",{className:x.stale?"text-amber-300":"text-emerald-300",children:x.error?"error":x.stale?"stale":"ok"})]},`room:${x.id}`))})]})}function bN({entries:n}){const s=n||[];return r.jsxs("div",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"flex items-center justify-between text-sm text-slate-400",children:[r.jsx("span",{children:"Admin IP log"}),r.jsx("span",{children:s.length})]}),r.jsx("div",{className:"surface h-64 overflow-y-auto font-mono text-xs",children:s.length===0?r.jsx("p",{children:"No admin log entries yet."}):s.slice().reverse().map(l=>r.jsxs("div",{className:"surface",children:[r.jsx("span",{className:"text-amber-400",children:l.ts?new Date(l.ts).toLocaleTimeString():"--"})," ",l.label&&r.jsxs("span",{className:"text-teal-400",children:["[",l.label,"]"]})," ",r.jsx("span",{className:"text-slate-200",children:l.message})," ",l.ip&&r.jsx("span",{className:"text-cyan-300",children:l.ip})," ",l.meta&&r.jsx("span",{className:"text-slate-500",children:JSON.stringify(l.meta)})]},l.id))}),r.jsx("p",{className:"text-xs text-slate-500",children:"Admin-only log stream; IPs never appear in user data."})]})}const yN=[{id:"driveForward",label:"Drive Forward",group:"Driving"},{id:"driveBackward",label:"Drive Backward",group:"Driving"},{id:"driveLeft",label:"Turn Left",group:"Driving"},{id:"driveRight",label:"Turn Right",group:"Driving"},{id:"boostModifier",label:"Boost Modifier",group:"Driving"},{id:"slowModifier",label:"Slow Modifier",group:"Driving"},{id:"auxMainForward",label:"Main Brush Forward",group:"Aux Motors"},{id:"auxMainReverse",label:"Main Brush Reverse",group:"Aux Motors"},{id:"auxSideForward",label:"Side Brush Forward",group:"Aux Motors"},{id:"auxSideReverse",label:"Side Brush Reverse",group:"Aux Motors"},{id:"auxVacuumFast",label:"Vacuum Max",group:"Aux Motors"},{id:"auxVacuumSlow",label:"Vacuum Low",group:"Aux Motors"},{id:"auxAllForward",label:"All Aux Forward",group:"Aux Motors"},{id:"cameraUp",label:"Camera Up",group:"Camera"},{id:"cameraDown",label:"Camera Down",group:"Camera"},{id:"nightVisionToggle",label:"Toggle Night Vision",group:"Camera"},{id:"hornHonk",label:"Horn (Hold)",group:"Audio"},{id:"micPtt",label:"Mic Push To Talk",group:"Audio"},{id:"driveMacro",label:"Drive Macro",group:"Macros"},{id:"dockMacro",label:"Dock Macro",group:"Macros"},{id:"chatFocus",label:"Toggle Chat",group:"Chat"},{id:"songNoteUp",label:"Song Note Up",group:"Audio"},{id:"songNoteDown",label:"Song Note Down",group:"Audio"},{id:"homeAssistantOn",label:"Room Controls On (Cycle)",group:"Room Controls"},{id:"homeAssistantOff",label:"Room Controls Off (Cycle)",group:"Room Controls"}];function SN(n){return n.reduce((s,l)=>((s[l.group]||(s[l.group]=[])).push(l),s),{})}function jN(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(0,Math.min(500,l)):s}const gd=5,Ci=500,Ei=1,vd=100;function AN(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(gd,Math.min(Ci,l)):s}function fo(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(Ei,Math.min(vd,l)):s}function NN(n){const l=(fo(n,n)-Ei)/(vd-Ei),o=Ci-l*(Ci-gd);return Math.round(o)}function wN(n){const s=AN(n,n),l=(Ci-s)/(Ci-gd),o=Ei+l*(vd-Ei);return Math.round(o)}function CN(n){const[s,l]=m.useState(null),o=m.useCallback(h=>{lf(!0),l(h)},[]),f=m.useCallback(()=>{lf(!1),l(null)},[]),d=m.useCallback((h,p)=>{if(p.preventDefault(),p.stopPropagation(),p.key==="Escape"){f();return}const x=Di(p.key??"");x&&(n(h,x,p),f())},[f,n]);return m.useEffect(()=>()=>lf(!1),[]),{active:s,startCapture:o,cancel:f,captureFromEvent:d}}function eo({label:n,description:s,value:l,onChange:o,min:f=0,max:d=500,step:h=5}){return r.jsxs("label",{className:"surface-muted block p-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-300",children:[r.jsx("span",{className:"font-semibold text-slate-100",children:n}),r.jsx("input",{type:"number",min:f,max:d,value:l,onChange:p=>o(p.target.value),className:"w-16 rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-right text-[0.75rem] font-mono text-slate-100"})]}),s&&r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:s}),r.jsxs("div",{className:"mt-0 flex items-center gap-0.5",children:[r.jsx("input",{type:"range",min:f,max:d,step:h,value:l,onChange:p=>o(p.target.value),className:"h-2 flex-1 accent-emerald-400"}),r.jsx("span",{className:"w-12 text-right text-[0.75rem] font-mono text-slate-400",children:l})]})]})}function EN(){const{state:{keymap:n},actions:{updateKeyBinding:s,resetKeyBindings:l}}=_t(),{value:o,save:f}=He("inputs",qn),d={...qn.keyboard,...o.keyboard??{}},h=m.useMemo(()=>typeof d.tiltSpeed=="number"?fo(d.tiltSpeed,qn.keyboard.tiltSpeed):typeof d.tiltIntervalMs=="number"?fo(wN(d.tiltIntervalMs),qn.keyboard.tiltSpeed):qn.keyboard.tiltSpeed,[d.tiltIntervalMs,d.tiltSpeed]),p=m.useMemo(()=>SN(yN),[]),{active:x,startCapture:g,cancel:v,captureFromEvent:y}=CN((k,w)=>{s(k,w)}),S=m.useCallback(k=>n?.[k]?.[0]||gi[k]?.[0]||"",[n]),E=m.useCallback((k,w)=>{const j=qn.keyboard,N=jN(w,j[k]);f(T=>({...T??{},keyboard:{...T?.keyboard??j,[k]:N}}))},[f]),C=m.useCallback(k=>{const w=qn.keyboard,j=fo(k,w.tiltSpeed),N=NN(j);f(T=>({...T??{},keyboard:{...T?.keyboard??w,tiltSpeed:j,tiltIntervalMs:N}}))},[f]);return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Keyboard layout"}),r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Per-browser · click to change a binding"})]}),r.jsx("button",{type:"button",onClick:()=>l(),className:"button-dark text-xs",children:"Reset defaults"})]}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Keyboard speeds"}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(eo,{label:"Base speed",description:"Normal driving speed",value:d.baseSpeed,onChange:k=>E("baseSpeed",k)}),r.jsx(eo,{label:"Turbo speed",description:"Used when holding the boost modifier",value:d.turboSpeed,onChange:k=>E("turboSpeed",k)}),r.jsx(eo,{label:"Precision speed",description:"Used when holding the precision modifier",value:d.precisionSpeed,onChange:k=>E("precisionSpeed",k)})]})]}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Camera tilt"}),r.jsx(eo,{label:"Tilt speed",description:"Higher = faster when holding tilt keys",value:h,onChange:C,min:1,max:100,step:1})]}),r.jsx("div",{className:"space-y-0.5",children:Object.entries(p).map(([k,w])=>r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.75rem] text-slate-400",children:k}),r.jsx("div",{className:"space-y-0.5",children:w.map(j=>{const N=S(j.id),T=x===j.id;return r.jsxs("div",{className:"surface-muted flex items-center justify-between text-xs",children:[r.jsxs("div",{children:[r.jsx("p",{className:"font-semibold text-slate-100",children:j.label}),r.jsx("p",{className:"text-[0.65rem] text-slate-400",children:An(N)})]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[T&&r.jsx("button",{type:"button",onClick:()=>v(),className:"button-danger text-[0.7rem]",children:"Cancel"}),r.jsx("button",{type:"button",onClick:()=>g(j.id),onKeyDown:T?M=>y(j.id,M):void 0,autoFocus:T,className:`${T?"px-0.5 py-0.5 bg-emerald-500 text-emerald-950 hover:bg-emerald-400":"button-dark"} text-[0.7rem] font-medium transition-colors`,children:T?"Press a key…":"Change"})]})]},j.id)})})]},k))})]})}const la=new Intl.NumberFormat(void 0,{maximumFractionDigits:2}),kN=[{id:"drive",label:"Drive stick",kind:"axisPair",section:"Driving",invertDefaults:{invertX:!1,invertY:!0}},{id:"cameraTilt",label:"Camera tilt",kind:"axis",section:"Camera",invertDefaults:{invert:!0}},{id:"mainBrush",label:"Main brush",kind:"axis",section:"Brushes",invertDefaults:{invert:!1}},{id:"sideBrush",label:"Side brush",kind:"axis",section:"Brushes",invertDefaults:{invert:!1}},{id:"vacuum",label:"Vacuum",kind:"button",section:"Aux buttons"},{id:"allAux",label:"All aux",kind:"button",section:"Aux buttons"},{id:"mainReverse",label:"Main reverse toggle",kind:"button",section:"Brush toggles"},{id:"sideReverse",label:"Side reverse toggle",kind:"button",section:"Brush toggles"},{id:"driveMacro",label:"Drive macro",kind:"button",section:"Mode macros"},{id:"dockMacro",label:"Dock macro",kind:"button",section:"Mode macros"},{id:"nightVisionToggle",label:"Night vision toggle",kind:"button",section:"Camera"}],dx=.45,MN=.6;function mi({label:n,description:s,min:l,max:o,step:f,value:d,onChange:h}){return r.jsxs("label",{className:"surface-muted block p-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-300",children:[r.jsx("span",{className:"font-semibold text-slate-100",children:n}),r.jsx("span",{className:"font-mono text-slate-400",children:la.format(d)})]}),s&&r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:s}),r.jsx("input",{type:"range",min:l,max:o,step:f,value:d,onChange:p=>h(Number(p.target.value)),className:"mt-0 w-full accent-emerald-400"})]})}function RN(n){if(!n)return"Unassigned";if(n.kind==="axisPair"){const s=`${n.invertX?"X inv ":""}${n.invertY?"Y inv":""}`.trim();return`Axes ${n.x}/${n.y}${s?` (${s})`:""}`}if(n.kind==="axis")return`Axis ${n.index}${n.invert?" (inv)":""}`;if(n.kind==="button")return`Button ${n.index}`;if(n.kind==="buttonAxis")return`Button ${n.index} (analog)`;if(n.kind==="axisButton"){const s=n.direction<0?"<":">";return`Axis ${n.index} ${s} ${la.format(n.threshold??.6)}`}return"Unassigned"}function qN(n){return n.reduce((s,l)=>((s[l.section]||(s[l.section]=[])).push(l),s),{})}function TN(n,s){if(!n||n.length===0)return null;if(s){const l=n.find(o=>o.signature===s);if(l)return l}return n[0]}function DN(n){return{axes:Array.from(n.axes??[]),buttons:(n.buttons??[]).map(s=>({pressed:!!s?.pressed,value:typeof s?.value=="number"?s.value:s?.pressed?1:0}))}}function _N(n,s,l){const o=(n.axes??[]).map((d,h)=>({index:h,delta:Math.abs((d??0)-(s.axes?.[h]??0)),value:d}));if(o.sort((d,h)=>h.delta-d.delta),l.kind==="axisPair"){const d=o.filter(h=>h.delta>dx).slice(0,2);return d.length<2?null:{kind:"axisPair",x:d[0].index,y:d[1].index,...l.invertDefaults??{}}}const f=o.find(d=>d.delta>dx);return f?{kind:"axis",index:f.index,...l.invertDefaults??{}}:null}function BN(n,s,l){const o=n.buttons??[];for(let d=0;dMN)return l.kind==="axis"?{kind:"buttonAxis",index:d}:{kind:"button",index:d}}const f=n.axes??[];for(let d=0;d.7&&p>.5)return l.kind==="axis"?{kind:"axis",index:d,...l.invertDefaults??{}}:{kind:"axisButton",index:d,direction:h>=0?1:-1,threshold:.6}}return null}function ON(n,s,l){if(!n)return null;if(l.kind==="axis"||l.kind==="axisPair"){const o=_N(n,s,l);if(o)return o}return BN(n,s,l)}function LN(){const n=dA(),{value:s,save:l}=He("gamepad",Ba),[o,f]=m.useState(null),d=m.useRef(null),h=m.useMemo(()=>qN(kN),[]),p=m.useMemo(()=>TN(n.pads,s.activeSignature),[n.pads,s.activeSignature]),x=p?.signature??null,g=m.useMemo(()=>x?s?.profiles?.[x]??s?.defaults?.profile??ia:s?.defaults?.profile??ia,[x,s?.defaults?.profile,s?.profiles]);m.useEffect(()=>{!p||!x||s?.profiles?.[x]||l(w=>{const j=w??Ba;if(j.profiles?.[x])return j;const N=j?.defaults?.profile??ia,T=wg(p,N);return{...j,profiles:{...j.profiles??{},[x]:T}}})},[p,x,s?.profiles,l]),m.useEffect(()=>{d.current=null},[o,x]),m.useEffect(()=>{if(!o||!p)return;if(!d.current){d.current=DN(p);return}const w=ON(p,d.current,o);w&&(l(j=>{const N=j??Ba,T=N.profiles?.[x]??N?.defaults?.profile??ia,M={...T,bindings:{...T.bindings??{},[o.id]:{...T.bindings?.[o.id]??{},kind:o.kind,sources:[w]}}};return{...N,profiles:{...N.profiles??{},[x]:M}}}),f(null))},[p,x,o,l]);const v=m.useCallback(w=>{l(j=>({...j??Ba,activeSignature:w||null}))},[l]),y=m.useCallback(w=>{l(j=>{const N=j??Ba,T=(x&&N.profiles?.[x])??N?.defaults?.profile??ia,M={...T,calibration:{...T.calibration??{},...w}};return x?{...N,profiles:{...N.profiles??{},[x]:M}}:{...N,defaults:{...N.defaults??{},profile:M}}})},[x,l]),S=m.useCallback((w,j)=>{l(N=>{const T=N??Ba,M=(x&&T.profiles?.[x])??T?.defaults?.profile??ia,O=j(M.bindings?.[w]??{}),K={...M,bindings:{...M.bindings??{},[w]:O}};return x?{...T,profiles:{...T.profiles??{},[x]:K}}:{...T,defaults:{...T.defaults??{},profile:K}}})},[x,l]),E=m.useCallback(w=>{S(w.id,j=>({...j,sources:[]}))},[S]),C=m.useCallback((w,j)=>{S(w.id,N=>{const T=Array.isArray(N.sources)?[...N.sources]:[];if(!T[0])return N;const M={...T[0]};return j==="invertX"?M.invertX=!M.invertX:j==="invertY"?M.invertY=!M.invertY:M.invert=!M.invert,T[0]=M,{...N,sources:T}})},[S]),k=m.useMemo(()=>p?{outputs:Cg(p,g)}:null,[p,g]);return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("div",{className:"flex items-center justify-between",children:r.jsxs("div",{children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Controller"}),r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:p?"Move sticks or press buttons to bind":"Connect a controller to configure."}),o&&r.jsxs("p",{className:"mt-0 text-[0.7rem] text-emerald-400",children:["Capturing ",o.label,"…"]})]})}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Connected controller"}),n.pads.length===0?r.jsx("p",{className:"text-[0.7rem] text-slate-400",children:"No controller detected."}):r.jsxs("div",{className:"flex items-center justify-between gap-0.5 text-xs",children:[r.jsx("select",{value:x??"",onChange:w=>v(w.target.value),className:"flex-1 rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.75rem] text-slate-100",children:n.pads.map(w=>r.jsx("option",{value:w.signature,children:w.id||"Unknown controller"},w.signature))}),r.jsx("span",{className:"text-[0.7rem] text-slate-400",children:p?.mapping??"unknown"})]})]}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Calibration"}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(mi,{label:"Drive deadzone",description:"Ignore small drive stick drift",min:0,max:.6,step:.01,value:g.calibration?.driveDeadzone??.18,onChange:w=>y({driveDeadzone:w})}),r.jsx(mi,{label:"Camera deadzone",description:"Ignore small camera tilt drift",min:0,max:.4,step:.01,value:g.calibration?.cameraDeadzone??.08,onChange:w=>y({cameraDeadzone:w})}),r.jsx(mi,{label:"Aux deadzone",description:"Ignore small trigger noise",min:0,max:.4,step:.01,value:g.calibration?.auxDeadzone??.05,onChange:w=>y({auxDeadzone:w})}),r.jsx(mi,{label:"Side brush scale",description:"Scale side brush output",min:.3,max:1,step:.05,value:g.calibration?.auxSideScale??.55,onChange:w=>y({auxSideScale:w})}),r.jsxs("label",{className:"surface-muted block p-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-300",children:[r.jsx("span",{className:"font-semibold text-slate-100",children:"Camera mode"}),r.jsxs("select",{value:g.calibration?.cameraMode??"absolute",onChange:w=>y({cameraMode:w.target.value}),className:"rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.75rem] text-slate-100",children:[r.jsx("option",{value:"absolute",children:"Absolute"}),r.jsx("option",{value:"velocity",children:"Velocity"})]})]}),r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:"Absolute maps stick to angle; velocity moves over time."})]}),r.jsx(mi,{label:"Camera sensitivity",description:"Velocity mode degrees per second",min:10,max:180,step:5,value:g.calibration?.cameraSensitivity??60,onChange:w=>y({cameraSensitivity:w})})]})]}),r.jsx("div",{className:"space-y-0.5",children:Object.entries(h).map(([w,j])=>r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:w}),r.jsx("div",{className:"space-y-0.5",children:j.map(N=>{const M=g.bindings?.[N.id]?.sources?.[0]??null;return r.jsxs("div",{className:"surface-muted flex items-center justify-between text-xs",children:[r.jsxs("div",{children:[r.jsx("p",{className:"font-semibold text-slate-100",children:N.label}),r.jsx("p",{className:"text-[0.65rem] text-slate-400",children:RN(M)})]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[N.kind==="axisPair"&&r.jsxs(r.Fragment,{children:[r.jsx("button",{type:"button",disabled:!M,onClick:()=>C(N,"invertX"),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert X"}),r.jsx("button",{type:"button",disabled:!M,onClick:()=>C(N,"invertY"),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert Y"})]}),N.kind==="axis"&&r.jsx("button",{type:"button",disabled:!M,onClick:()=>C(N),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert"}),r.jsx("button",{type:"button",onClick:()=>E(N),className:"button-dark text-[0.7rem]",children:"Clear"}),r.jsx("button",{type:"button",onClick:()=>f(N),className:`${o?.id===N.id?"px-0.5 py-0.5 bg-emerald-500 text-emerald-950 hover:bg-emerald-400":"button-dark"} text-[0.7rem] font-medium`,children:o?.id===N.id?"Waiting…":"Capture"})]})]},N.id)})})]},w))}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Diagnostics"}),p?r.jsxs("div",{className:"space-y-0.5 text-[0.7rem] text-slate-300",children:[r.jsx("p",{className:"text-slate-400",children:"Raw axes"}),r.jsx("div",{className:"grid grid-cols-2 gap-0.5",children:p.axes.map((w,j)=>r.jsxs("span",{className:"font-mono text-slate-300",children:["A",j,": ",la.format(w)]},`axis-${j}`))}),r.jsx("p",{className:"text-slate-400",children:"Raw buttons"}),r.jsx("div",{className:"grid grid-cols-2 gap-0.5",children:p.buttons.map((w,j)=>r.jsxs("span",{className:"font-mono text-slate-300",children:["B",j,": ",la.format(w.value)," ",w.pressed?"●":""]},`btn-${j}`))}),k?.outputs&&r.jsxs(r.Fragment,{children:[r.jsx("p",{className:"text-slate-400",children:"Mapped outputs"}),r.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[r.jsxs("span",{className:"font-mono text-slate-300",children:["Drive: ",la.format(k.outputs.driveVector.x),","," ",la.format(k.outputs.driveVector.y)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Camera: ",la.format(k.outputs.cameraAxis)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Main: ",la.format(k.outputs.auxAxis.main)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Side: ",la.format(k.outputs.auxAxis.side)]})]})]})]}):r.jsx("p",{className:"text-[0.7rem] text-slate-400",children:"No controller detected."})]})]})}const zN={drive:"Drive wheels",aux:"Aux motors"};function mx(n){return Number.isFinite(n)?`${Math.round(n*100)}%`:"--"}function UN({value:n,color:s="bg-emerald-500"}){const l=`${Math.round(Math.max(0,Math.min(1,n))*100)}%`;return r.jsx("div",{className:"h-2 w-full overflow-hidden rounded bg-slate-800",children:r.jsx("div",{className:`h-full ${s}`,style:{width:l}})})}function HN(){const{state:{roverId:n},overcurrentLimiter:s}=_t(),l=m.useMemo(()=>os.map(o=>o.key),[]);return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Overcurrent limiter"}),r.jsx("span",{children:s?.adminImmune?"Admin immune":"Active"})]}),n?r.jsxs("div",{className:"space-y-0.5",children:[l.map(o=>{const f=s?.caps?.[o]?.cap??0,d=s?.overcurrent?.groups?.[o]??!1,h=s?.scales?.perGroup?.[o]??1;return r.jsxs("div",{className:"surface space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs",children:[r.jsx("span",{className:"text-slate-200",children:zN[o]||o}),r.jsx("span",{className:d?"text-red-300":"text-slate-400",children:d?"overcurrent":"ok"})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-[0.7rem] text-slate-400",children:[r.jsx("span",{children:"Cap"}),r.jsx("span",{children:mx(f)})]}),r.jsx(UN,{value:f,color:"bg-amber-500"}),r.jsxs("div",{className:"flex items-center justify-between text-[0.7rem] text-slate-400",children:[r.jsx("span",{children:"Scale"}),r.jsx("span",{children:mx(h)})]})]})]},o)}),r.jsxs("div",{className:"surface text-[0.7rem] text-slate-400",children:[r.jsx("div",{children:`Down rate ${s?.config?.downRatePerSec}/s · Up rate ${s?.config?.upRatePerSec}/s`}),r.jsx("div",{children:`Release delay ${s?.config?.releaseDelaySec}s`}),r.jsx("div",{children:`Output rate ${s?.config?.outputRateMs}ms`})]})]}):r.jsx("p",{className:"text-xs text-slate-500",children:"Assign a rover to view limiter status."})]})}const $g=m.createContext(null);function Gg(){const n=m.useContext($g);if(!n)throw new Error("Tabs components must be used within a provider.");return n}const hx={primary:{base:"flex-1 px-0.5 py-0.5 text-sm font-medium focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-1 focus-visible:outline-slate-500 rounded-md border border-slate-800",active:"bg-sky-600 text-white border-white",inactive:"bg-zinc-900 text-slate-300 hover:bg-sky-500 hover:text-white"}},px={none:"",pink:"bg-pink-500 text-white border-pink-200 hover:bg-pink-400",green:"bg-emerald-500 text-white border-emerald-200 hover:bg-emerald-400"},Yg="primary";function bd(...n){return n.filter(Boolean).join(" ")}function yd({children:n,defaultTab:s,currentTab:l,onTabChange:o,variant:f=Yg}){const[d,h]=m.useState(s??null),[p,x]=m.useState([]),g=m.useCallback(E=>E?(x(C=>C.includes(E)?C:[...C,E]),()=>x(C=>C.includes(E)?C.filter(k=>k!==E):C)):()=>{},[]),v=l??d??p[0]??null;m.useEffect(()=>{s&&l===void 0&&h(s)},[s,l]);const y=m.useCallback(E=>{E&&(l===void 0&&h(E),o&&o(E))},[l,o]),S=m.useMemo(()=>({activeTab:v,setActiveTab:y,registerTab:g,variant:f}),[v,y,g,f]);return r.jsx($g.Provider,{value:S,children:n})}function Sd({children:n,className:s=""}){return r.jsx("div",{className:bd("flex gap-0.5",s),children:n})}function Wt({id:n,children:s,className:l="",disabled:o=!1,highlight:f="none"}){const{activeTab:d,setActiveTab:h,registerTab:p,variant:x}=Gg();m.useEffect(()=>p(n),[n,p]);const g=hx[x]??hx[Yg],v=d===n,y=px[f]||px.none,S=bd(g.base,y||(v?g.active:g.inactive),o?"cursor-not-allowed opacity-50":"",l);return r.jsx("button",{type:"button",className:S,onClick:()=>!o&&h(n),"aria-pressed":v,"aria-disabled":o,children:s})}function jd({children:n,className:s=""}){return r.jsx("div",{className:bd("mt-0 space-y-0.5",s),children:n})}function en({id:n,children:s,keepMounted:l=!1}){const{activeTab:o}=Gg(),f=o===n;return!f&&!l?null:!f&&l?r.jsx("div",{hidden:!0,"aria-hidden":"true",children:s}):r.jsx(r.Fragment,{children:s})}function VN(){const{session:n}=nn(),s=m.useMemo(()=>JSON.stringify(n??{},null,2),[n]);return r.jsxs("div",{className:"panel-section flex min-h-0 flex-col gap-0.5 text-xs",children:[r.jsx("p",{className:"text-sm text-slate-400",children:"Session snapshot"}),r.jsx("pre",{className:"surface min-h-0 flex-1 overflow-y-auto font-mono text-[0.7rem] text-lime-300",children:s})]})}const xx=300,gx=240;function $N(n,s){if(n===void 0)return"undefined";if(n===null)return"null";if(typeof n=="string")return n;if(typeof n=="number"||typeof n=="boolean")return String(n);if(typeof n=="function")return"[Function]";if(n instanceof Error)return`${n.name}: ${n.message}`;if(n instanceof Date)return n.toISOString();if(s||(s=new WeakSet),typeof n=="object"){if(s.has(n))return"[Circular]";s.add(n)}try{return JSON.stringify(n,(l,o)=>typeof o=="function"?"[Function]":o instanceof Error?`${o.name}: ${o.message}`:o,0)}catch{return String(n)}}function GN(n){const l=n.map(o=>$N(o)).join(" ");return l.length>gx?`${l.slice(0,gx)}…`:l}function YN(){const n=tn(),[s,l]=m.useState([]),o=m.useMemo(()=>s.reduce((f,d)=>(d.direction==="in"&&(f.in+=1),d.direction==="out"&&(f.out+=1),f),{in:0,out:0}),[s]);return m.useEffect(()=>{const f=(x,g,v)=>{l(y=>{const S=[...y,{id:`${Date.now()}-${Math.random().toString(16).slice(2)}`,direction:x,event:g,payload:GN(v),timestamp:new Date().toLocaleTimeString()}];return S.length>xx?S.slice(-xx):S})},d=(x,...g)=>f("in",x,g),h=(x,...g)=>f("out",x,g);n.onAny(d);let p=null;if(typeof n.onAnyOutgoing=="function")n.onAnyOutgoing(h),p=()=>n.offAnyOutgoing(h);else{const x=n.emit.bind(n);n.emit=(g,...v)=>(h(g,...v),x(g,...v)),p=()=>{n.emit=x}}return()=>{n.offAny(d),p&&p()}},[n]),r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"flex items-center justify-between text-sm text-slate-400",children:[r.jsx("span",{children:"Socket activity"}),r.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-400",children:[r.jsxs("span",{className:"surface-muted",children:["in ",o.in]}),r.jsxs("span",{className:"surface-muted",children:["out ",o.out]}),r.jsx("button",{type:"button",className:"button-dark text-xs",onClick:()=>l([]),children:"Clear"})]})]}),r.jsx("div",{className:"surface h-64 overflow-y-auto font-mono text-xs",children:s.length===0?r.jsx("p",{children:"No socket activity yet."}):s.slice().reverse().map(f=>r.jsxs("div",{className:"surface",children:[r.jsx("span",{className:"text-slate-400",children:f.timestamp})," ",r.jsxs("span",{className:f.direction==="in"?"text-emerald-400":"text-amber-400",children:["[",f.direction.toUpperCase(),"]"]})," ",r.jsx("span",{className:"text-cyan-300",children:f.event})," ",r.jsx("span",{className:"text-slate-200",children:f.payload})]},f.id))}),r.jsx("p",{className:"text-xs text-slate-500",children:"Logs are collected only while this panel is open."})]})}const FN=[{key:"start",label:"Start OI"},{key:"safe",label:"Safe"},{key:"full",label:"Full"},{key:"passive",label:"Passive"},{key:"dock",label:"Dock"}];function Fg(){const{state:{roverId:n},actions:{sendOiCommand:s,setSensorStream:l}}=_t(),o=!!n,[f,d]=zg(),h=tn(),{value:p,save:x}=He("page",{hudMapDesktop:!1,connectionTransport:"websocket",swapMobileControlColumns:!1,driveMacroBackoffEnabled:!0}),{value:g,save:v}=He("audio",ct),y=p?.connectionTransport||"websocket",S=!!p?.swapMobileControlColumns,E=typeof p?.driveMacroBackoffEnabled=="boolean"?p.driveMacroBackoffEnabled:!0,C=Number.isFinite(g?.masterVolume)?g.masterVolume:ct.masterVolume,k=Number.isFinite(g?.alertVolume)?g.alertVolume:ct.alertVolume,w=Number.isFinite(g?.roverVolume)?g.roverVolume:ct.roverVolume,j=typeof g?.mainBrushDuckEnabled=="boolean"?g.mainBrushDuckEnabled:typeof g?.autoLevelEnabled=="boolean"?g.autoLevelEnabled:ct.mainBrushDuckEnabled,N=Number.isFinite(g?.mainBrushDuckAmount)?Math.max(0,Math.min(1,g.mainBrushDuckAmount)):ct.mainBrushDuckAmount,T=m.useMemo(()=>[{key:"start",label:"Enable stream",enable:!0},{key:"stop",label:"Disable stream",enable:!1}],[]),M=F=>{n&&l(F)},O=F=>{const H=F.target.value;x(te=>({...te??{},connectionTransport:H})),h?.io?.opts&&(h.io.opts.transports=H==="polling"?["polling"]:["websocket","polling"],h.disconnect(),h.connect())},K=F=>H=>{const te=Number(H.target.value),ce=Number.isFinite(te)?Math.max(0,Math.min(1,te)):0;v(oe=>({...oe??{},[F]:ce}))},_=F=>{const H=!!F.target.checked;v(te=>({...te??{},mainBrushDuckEnabled:H}))},U=F=>{const H=!!F.target.checked;x(te=>({...te??{},swapMobileControlColumns:H}))},X=F=>{const H=!!F.target.checked;x(te=>({...te??{},driveMacroBackoffEnabled:H}))};return r.jsxs(yd,{defaultTab:"keybindings",children:[r.jsxs(Sd,{children:[r.jsx(Wt,{id:"keybindings",children:"Keybindings"}),r.jsx(Wt,{id:"controller",children:"Controller"}),r.jsx(Wt,{id:"page",children:"Page settings"}),r.jsx(Wt,{id:"admin",children:"Admin"})]}),r.jsxs(jd,{children:[r.jsx(en,{id:"keybindings",children:r.jsx("div",{className:"space-y-0.5",children:r.jsx(EN,{})})}),r.jsx(en,{id:"controller",children:r.jsx("div",{className:"space-y-0.5",children:r.jsx(LN,{})})}),r.jsx(en,{id:"page",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"HUD"}),r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:f,onChange:F=>d(F.target.checked)}),r.jsx("span",{children:"Show top-down map in HUD (desktop)"})]}),r.jsx("p",{className:"text-xs text-slate-500",children:"Mobile HUD keeps the map on by default."})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Mobile controls"}),r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:S,onChange:U}),r.jsx("span",{children:"Swap control columns (put joystick on the left)"})]})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Macros"}),r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:E,onChange:X}),r.jsx("span",{children:"Enable backward bump in drive macro"})]})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Audio"}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Master volume"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(C*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:C,onChange:K("masterVolume"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Alert/page sounds"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(k*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:k,onChange:K("alertVolume"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Rover audio"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(w*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:w,onChange:K("roverVolume"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"flex items-center justify-between gap-0.5 text-slate-200",children:[r.jsx("span",{children:"Main brush ducking"}),r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:j,onChange:_})]}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Main brush duck amount"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(N*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:N,onChange:K("mainBrushDuckAmount"),className:"w-full accent-emerald-500",disabled:!j})]}),r.jsx("p",{className:"text-xs text-slate-500",children:"Lowers rover audio only while the main brush is running."})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Connection"}),r.jsxs("label",{className:"flex items-center justify-between gap-0.5 text-slate-200",children:[r.jsx("span",{children:"Transport"}),r.jsxs("select",{value:y,onChange:O,className:"field-input text-sm",children:[r.jsx("option",{value:"websocket",children:"WebSocket"}),r.jsx("option",{value:"polling",children:"Polling"})]})]}),r.jsx("p",{className:"text-xs text-slate-500",children:"Switching reconnects your session."})]})]})}),r.jsx(en,{id:"admin",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Manual OI commands"}),r.jsx("div",{className:"surface flex flex-wrap gap-0.5",children:FN.map(F=>r.jsx("button",{type:"button",onClick:()=>s(F.key),disabled:!o,className:"button-dark text-xs disabled:opacity-30",children:F.label},F.key))})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Sensor stream"}),r.jsx("div",{className:"surface flex gap-0.5",children:T.map(F=>r.jsx("button",{type:"button",onClick:()=>M(F.enable),disabled:!o,className:"flex-1 button-dark text-xs disabled:opacity-30",children:F.label},F.key))}),!o&&r.jsx("p",{className:"text-xs text-slate-500",children:"Assign a rover to toggle streams."})]}),r.jsx(Vg,{}),r.jsx(HN,{}),r.jsx(hN,{}),r.jsx(VN,{}),r.jsx(YN,{})]})})]})]})}const vx={desktop:{main:[{type:"list",title:"Chat and nicknames",items:["Set a nickname in the user list panel, on the bottom left of the page below the rover video.",{segments:["Toggle chat focus with ",{action:"chatFocus"},". Press ",{action:"chatFocus"}," again to send."]}]},{type:"list",title:"Driving the rover",items:[{segments:['Press the "Start Driving" button onscreen, or press ',{action:"driveMacro"}," on your keyboard to put the rover into driving mode."]},"Refer to the controls for the controls for the rover."]},{type:"list",title:"Docking the rover",items:["Line up the rover to the dock, about a foot away, then:",{segments:['Press the "Dock and Charge" button onscreen, or press ',{action:"dockMacro"}," on your keyboard to start docking."]},"Wait for the rover to confirm it is docked and charging before leaving it unattended."]}],aside:[{type:"keyboard",title:"Keyboard controls",footnote:"Per-browser; adjust bindings and speeds in Settings → Keybindings.",groups:[{id:"movement",title:"Movement",items:[{action:"driveForward",label:"Forward"},{action:"driveBackward",label:"Backward"},{action:"driveLeft",label:"Turn left"},{action:"driveRight",label:"Turn right"},{action:"boostModifier",label:"Boost speed"},{action:"slowModifier",label:"Precision speed"}]},{id:"macros",title:"Rover modes & chat",items:[{action:"driveMacro",label:"Drive macro"},{action:"dockMacro",label:"Dock macro"},{action:"chatFocus",label:"Chat focus"}]},{id:"camera",title:"Camera",items:[{action:"cameraUp",label:"Tilt up"},{action:"cameraDown",label:"Tilt down"},{action:"nightVisionToggle",label:"Toggle night vision"}]},{id:"motors",title:"Rover Aux Motors",items:[{action:"auxMainForward",label:"Main brush forward"},{action:"auxMainReverse",label:"Main brush reverse"},{action:"auxSideForward",label:"Side brush forward"},{action:"auxSideReverse",label:"Side brush reverse"},{action:"auxVacuumFast",label:"Vacuum max"},{action:"auxVacuumSlow",label:"Vacuum low"},{action:"auxAllForward",label:"All motors forward"}]},{id:"audio",title:"Audio / Song",items:[{action:"songNoteUp",label:"Song note up"},{action:"songNoteDown",label:"Song note down"}]},{id:"room-controls",title:"Room Controls",items:[{action:"homeAssistantOn",label:"Next room control on"},{action:"homeAssistantOff",label:"Next room control off (reverse)"}]}]},{type:"gamepad",title:"Gamepad / joystick",items:["Gamepad controls are fully configurable to handle inconsistent browser mappings.","Use Settings → Controller to bind inputs, calibrate deadzones, and view diagnostics.","If inputs behave oddly, the diagnostics panel will show raw axis/button values."]}]},"mobile-portrait":{main:[{type:"list",title:"Chat and nicknames",items:["Set a nickname in the user list panel below.","Tap in the chat box to send messages in the chat."]},{type:"list",title:"Driving the rover",items:[{segments:['Press the "Start Driving" button onscreen to put the rover into driving mode.']},"Look below the rover video. Use the joystick column to move the rover, and hold the aux buttons in the other control column."]},{type:"list",title:"Docking the rover",items:["Line up the rover to the dock, about a foot away, then:",{segments:['Press the "Dock and Charge" button onscreen to start docking.']},"Wait for the rover to confirm it is docked and charging before leaving it unattended."]}]},"mobile-landscape":{main:[{type:"list",title:"Chat and nicknames",items:["Scroll down to see more of the page.","Set a nickname in the user list panel below.","Tap in the chat box to send messages in the chat."]},{type:"list",title:"Driving the rover",items:[{segments:['Press the "Start Driving" button, or the "Drive" button to put the rover into driving mode.']},"Use the joystick column beside the video feed to move the rover, and hold the aux buttons in the other control column."]},{type:"list",title:"Docking the rover",items:["Line up the rover to the dock, about a foot away, then:",{segments:['Press the "Dock and Charge" or the "Dock" button onscreen to start docking.']},"Wait for the rover to confirm it is docked and charging before leaving it unattended."]}]}};function XN(n){return vx[n]||vx.desktop}function Xg({actionId:n,keymap:s}){const l=s?.[n]?.[0]??"";return r.jsx("span",{className:"rounded border border-slate-600 bg-slate-900/40 px-1 text-[0.7rem] text-slate-200",children:An(l)})}function bx(n,s){return n.map((l,o)=>typeof l=="string"?r.jsx("span",{children:l},`text-${o}`):l?.action?r.jsx(Xg,{actionId:l.action,keymap:s},`pill-${l.action}-${o}`):l?.text?r.jsx("span",{children:l.text},`span-${o}`):null)}function Ro(n,s,l){if(typeof n=="string")return n;if(Array.isArray(n?.segments))return bx(n.segments,s);if(n&&typeof n=="object"){if(typeof n.text=="string")return n.text;if(Array.isArray(n))return bx(n,s)}return String(n??"")}function QN({hero:n,keymap:s}){return n?r.jsxs("div",{className:"surface space-y-0.5 px-0.5 py-0.5",children:[r.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-0.5",children:[r.jsxs("div",{children:[r.jsx("p",{className:"text-sm font-semibold text-white",children:n.title}),n.subtitle&&r.jsx("p",{className:"text-xs text-slate-300",children:n.subtitle})]}),n.chips&&r.jsx("div",{className:"flex flex-wrap gap-0.5 text-[0.7rem] text-slate-200",children:n.chips.map(l=>r.jsx("span",{className:"rounded border border-slate-700 px-1 py-[2px]",children:l},l))})]}),n.bullets&&r.jsx("ul",{className:"space-y-0.5 text-[0.85rem] text-slate-200",children:n.bullets.map((l,o)=>{const f=Array.isArray(l?.segments)?`hero-${o}`:`hero-${o}`;return r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:Ro(l,s)},f)})})]}):null}function KN({block:n,keymap:s}){return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs font-semibold text-slate-200",children:n.title}),r.jsx("ul",{className:"space-y-0.5 text-[0.8rem] text-slate-300",children:n.items.map((l,o)=>{const f=`item-${o}`;return r.jsx("li",{className:"surface-muted flex flex-wrap items-center gap-0.5 px-0.5 py-0.25",children:Ro(l,s)},f)})})]})}function ZN({block:n}){const s=n.tone==="info"?"border-cyan-500/40":"border-slate-700";return r.jsxs("div",{className:`surface space-y-0.5 border ${s} px-0.5 py-0.5`,children:[r.jsx("p",{className:"text-xs font-semibold text-slate-100",children:n.title}),n.body&&r.jsx("ul",{className:"space-y-0.5 text-[0.8rem] text-slate-300",children:n.body.map((l,o)=>r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:Ro(l,{})},`callout-${o}`))})]})}function IN({group:n,keymap:s}){return r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"px-0.5 py-0.25 text-[0.75rem] font-semibold text-slate-200",children:n.title}),r.jsx("div",{className:"space-y-0.5 px-0.5 pb-0.25",children:n.items.map(l=>r.jsxs("div",{className:"surface-muted flex items-center justify-between gap-0.5 px-0.5 py-0.25 text-[0.8rem]",children:[r.jsx("span",{className:"text-slate-200",children:l.label}),r.jsx(Xg,{actionId:l.action,keymap:s})]},l.action))})]})}function JN({block:n,keymap:s}){return n?r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-200",children:[r.jsx("span",{className:"font-semibold",children:n.title}),n.footnote&&r.jsx("span",{className:"text-[0.7rem] text-slate-400",children:n.footnote})]}),r.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-0.5",children:n.groups?.map(l=>r.jsx(IN,{group:l,keymap:s},l.id))})]}):null}function PN({block:n}){return n?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs font-semibold text-slate-200",children:n.title}),r.jsx("ul",{className:"space-y-0.5 text-[0.8rem] text-slate-300",children:n.items?.map((s,l)=>r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:Ro(s,{})},`gamepad-${l}`))})]}):null}function yx({block:n,keymap:s}){if(!n)return null;switch(n.type){case"list":return r.jsx(KN,{block:n,keymap:s});case"callout":return r.jsx(ZN,{block:n});case"keyboard":return r.jsx(JN,{block:n,keymap:s});case"gamepad":return r.jsx(PN,{block:n});default:return null}}function Qg({layout:n,keymap:s}){const l=m.useMemo(()=>XN(n),[n]),o=s||{},f=l.main||[],d=l.aside||[];return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(QN,{hero:l.hero,keymap:o}),r.jsxs("div",{className:"grid gap-0.5",style:{gridTemplateColumns:"repeat(auto-fit, minmax(360px, 1fr))"},children:[r.jsx("div",{className:"space-y-0.5",children:f.map((h,p)=>r.jsx(yx,{block:h,keymap:o},h.title||p))}),r.jsx("div",{className:"space-y-0.5",children:d.map((h,p)=>r.jsx(yx,{block:h,keymap:o},h.title||p))})]})]})}function Kg({layout:n,onOpenOverlay:s}){const{state:l}=_t();return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Help"}),r.jsx("button",{type:"button",onClick:s,className:"button-dark px-1 py-0.25 text-[0.75rem]",children:"Open full help"})]}),r.jsx(Qg,{layout:n,keymap:l?.keymap||{}})]})}const WN=["kal","rms","slt","ksp","bdl"],ew=Array.from({length:10},(n,s)=>s*10);function qo({hideInput:n=!1,hideSpectatorNotice:s=!1,fillHeight:l=!1,allowSpectatorInput:o=!1}){const f=ft(R=>R.session),{messages:d,typing:h,sendMessage:p,registerInputRef:x,onInputFocus:g,onInputBlur:v,blurChat:y,setTypingActive:S}=od(),{value:E,save:C}=He("tts",{engine:"flite",voice:"rms",pitch:50}),[k,w]=m.useState(""),[j,N]=m.useState(!1),[T,M]=m.useState(!1),[O,K]=m.useState(()=>E?.engine||"flite"),[_,U]=m.useState(()=>E?.voice||"rms"),[X,F]=m.useState(()=>Number.isFinite(E?.pitch)?E.pitch:50),H=f?.role!=="spectator"||o,te=m.useRef(null),ce=f?.assignment?.roverId||null,V=!!m.useMemo(()=>f?.roster?.find(R=>String(R.id)===String(ce))||null,[ce,f?.roster])?.audio?.ttsEnabled,q=m.useMemo(()=>d.slice(-200),[d]),L=m.useMemo(()=>h||[],[h]);m.useEffect(()=>{te.current&&(te.current.scrollTop=te.current.scrollHeight)},[q,L]),m.useEffect(()=>{const R=E?.engine||"flite",$=E?.voice||"rms",ee=Number.isFinite(E?.pitch)?E.pitch:50;O!==R&&K(R),_!==$&&U($),X!==ee&&F(ee)},[O,X,E?.engine,E?.pitch,E?.voice,_]),m.useEffect(()=>{M(!!V)},[V]);const Z=m.useMemo(()=>!V||!T?null:O==="espeak"?{speak:!0,engine:O,pitch:X}:{speak:!0,engine:O,voice:_},[O,X,T,V,_]);async function le(R){if(R.preventDefault(),!H||n)return;const ee=k.replace(/\\n/g,` -`).trim();if(ee){N(!0);try{await p(ee,Z),w(""),y(),S(!1)}catch(ae){alert(ae.message)}finally{N(!1)}}}const fe=l?"flex-1 min-h-0 overflow-y-auto":"h-48 overflow-y-auto";return r.jsxs("section",{className:`panel-section space-y-0.5 text-base ${l?"flex h-full flex-col overflow-hidden":""}`,children:[r.jsxs("div",{className:`surface overflow-y-auto space-y-0.5 px-0 ${fe}`,ref:te,children:[q.length===0&&L.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"No messages yet."}):q.map(R=>r.jsx(ld,{message:R},R.id)),L.map(R=>r.jsx(pg,{message:R},`typing-${R.typingId||R.id}`))]}),!n&&r.jsxs("form",{className:"flex flex-wrap items-stretch gap-0.5",onSubmit:le,children:[r.jsx("input",{className:"field-input flex-1 min-w-[10rem]",value:k,onChange:R=>{const $=R.target.value;w($),S(!!$.trim())},onFocus:R=>{g(R),S(!!k.trim())},onBlur:R=>{v(R),S(!1)},onKeyDown:R=>{R.key==="Enter"&&!k.trim()&&(R.preventDefault(),y(),S(!1))},ref:R=>x(R,{target:"panel"}),placeholder:H?"Type a message…":s?"":"Spectators cannot chat",disabled:!H}),V&&r.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 basis-full sm:basis-auto",children:[r.jsxs("label",{className:"flex items-center gap-0.5 text-xs text-slate-300",children:[r.jsx("input",{type:"checkbox",checked:T,onChange:R=>M(R.target.checked),className:"accent-cyan-500"}),r.jsx("span",{children:"Speak"})]}),r.jsxs("select",{value:O,onChange:R=>{const $=R.target.value;K($),C(ee=>({...ee||{},engine:$}))},className:"field-input text-xs",children:[r.jsx("option",{value:"flite",children:"flite"}),r.jsx("option",{value:"espeak",children:"espeak"})]}),O==="flite"?r.jsx("select",{value:_,onChange:R=>{const $=R.target.value;U($),C(ee=>({...ee||{},voice:$}))},className:"field-input text-xs",children:WN.map(R=>r.jsx("option",{value:R,children:R},R))}):r.jsx("select",{value:X,onChange:R=>{const $=Number(R.target.value);F($),C(ee=>({...ee||{},pitch:$}))},className:"field-input text-xs",children:ew.map(R=>r.jsxs("option",{value:R,children:["pitch ",R]},R))})]}),r.jsx("button",{type:"submit",disabled:!H||j,className:"button-dark h-full disabled:opacity-50 self-stretch",children:j?"...":"Send"})]})]})}function To({compact:n=!1}){const{session:s,setNickname:l}=nn(),{value:o,save:f}=He("profile",{nickname:""}),[d,h]=m.useState(o.nickname||""),[p,x]=m.useState(!1),g=s?.role!=="spectator";m.useEffect(()=>{h(o.nickname||"")},[o.nickname]);async function v(y){if(y.preventDefault(),!g)return;const S=(d||"").trim().slice(0,32);if(S){x(!0);try{await l(S),f({nickname:S})}catch(E){alert(E.message)}finally{x(!1)}}}return r.jsxs("form",{className:"grid w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-stretch gap-0.5",onSubmit:v,children:[r.jsx("input",{className:"field-input flex-1 min-w-0",value:d,onChange:y=>h(y.target.value),maxLength:32,placeholder:"Enter a nickname",disabled:!g}),r.jsx("button",{type:"submit",disabled:!g||p,className:"button-dark h-full shrink-0 whitespace-nowrap px-0.5 py-0 disabled:opacity-50",children:p?"Saving…":n?"Set":"Save"})]})}function tw(n){const s=Array.isArray(n?.socials)?n.socials:null;if(s&&s.length)return s;const l=[];return n?.discord?.invite&&l.push({id:"discord",label:"Discord",url:n.discord.invite}),n?.kofi?.link&&l.push({id:"kofi",label:"Ko-fi",url:n.kofi.link}),l}function nw(n){if(!n||typeof n!="object")return null;const s=n.id||n.service||n.key||n.name||null,l=n.label||n.title||n.name||s||"Link",o=n.url||n.link||n.href||null;return o?{id:s,label:l,url:o}:null}function Zg({className:n=""}){const{session:s}=nn(),l=tw(s).map(nw).filter(Boolean).slice(0,4);return l.length?r.jsx("div",{className:`grid grid-cols-2 grid-rows-2 gap-0.5 ${n}`,children:l.map(o=>r.jsx(pd,{...o},`${o.id||o.label}-${o.url}`))}):null}function aw({compact:n=!1}){return r.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:r.jsx("div",{className:"surface flex w-full items-center px-0 py-0",children:r.jsx(To,{compact:n})})})}function sw(){return r.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:r.jsx(Zg,{className:"flex-1 min-h-0"})})}function yf(...n){return n.filter(Boolean).join(" ")}function lw(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function iw(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function rw(n){switch(n){case"admin":case"lockdown":case"lockdown-admin":return"text-amber-300";case"spectator":return"text-slate-400";default:return"text-sky-300"}}function ow(n,s){if(!n)return"";const l=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${l} (you)`:l}function Do({title:n="Rovers"}){const s=ft(j=>j.session),{requestControl:l}=wn(),[o,f]=m.useState({}),[d,h]=m.useState(()=>Date.now()),p=m.useMemo(()=>s?.role&&s.role!=="spectator",[s?.role]),x=m.useMemo(()=>s?.role==="admin"||s?.role==="lockdown"||s?.role==="lockdown-admin",[s?.role]),g=s?.roster??[],v=s?.turnQueues??{},y=s?.users??[],S=s?.socketId||null,E=m.useMemo(()=>Object.values(v||{}).some(j=>j?.deadline||j?.idleDeadline),[v]);m.useEffect(()=>{if(!E)return;const j=setInterval(()=>{h(Date.now())},1e3);return()=>clearInterval(j)},[E]);const C=m.useMemo(()=>{const j=new Set(g.map(T=>String(T.id))),N=Object.keys(v||{}).filter(T=>!j.has(String(T))).map(T=>({id:T,name:T,locked:!1,batteryState:null}));return[...g,...N]},[g,v]);async function k(j){if(j){f(N=>({...N,[j]:!0}));try{await l(j)}catch(N){alert(N.message)}finally{f(N=>({...N,[j]:!1}))}}}const w=j=>y.find(N=>N.socketId===j)||{socketId:j,nickname:null,role:null};return r.jsxs("div",{className:"space-y-0.5 text-sm",children:[n&&r.jsx("p",{className:"text-sm text-slate-400",children:n}),C.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"No rovers registered."}):r.jsx("ul",{className:"space-y-0.5 text-sm",children:C.map(j=>{const N=String(j.id),T=v?.[N]||null,M=T?.queue||[],O=T?.idleDeadline||T?.deadline||null,K=O&&O>d?Math.ceil((O-d)/1e3):O?0:null,_=T?.current||null,U=_?M.findIndex(le=>le===_):-1,X=M.length>1?U>=0?M[(U+1)%M.length]:M[0]:null,F=!!(S&&_&&_===S),H=!!(S&&X&&X===S),te=K!=null&&(F||H),ce=!!j.locked,oe=ce&&!x,V=!!(j?.private?.enabled&&j?.private?.open),q=j.lockReason?`locked: ${j.lockReason}`:"locked",L=ce?q:o[N]?"...":"request",Z=p&&!oe&&!o[N];return r.jsxs("li",{className:yf("surface flex flex-wrap items-start justify-between gap-0.5",Z&&"cursor-pointer",ce?"bg-red-900/40":V?"bg-amber-700/35 border border-amber-200/30":null),onClick:()=>{Z&&k(j.id)},children:[r.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("p",{className:"text-slate-200",children:r.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ca(j.color,.16),children:j.name})}),te?r.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem] text-slate-200",children:F?`${K}s left`:`Your turn in ${K}s`}):null]}),r.jsx("span",{className:yf("text-[0.75rem] font-semibold",iw(j)),children:lw(j)})]}),M.length===0?r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"No queue."}):r.jsx("div",{className:"flex flex-wrap items-center gap-0.5",children:M.map((le,fe)=>{const R=w(le),$=le===_,ee=!!(X&&le===X&&!$),ae=$?"bg-sky-600 text-white ring-2 ring-amber-300":ee?"bg-emerald-700/60 text-emerald-100 ring-1 ring-emerald-300/70":"bg-slate-800 text-slate-200";return r.jsxs("span",{className:`flex items-center gap-0.5 rounded px-1 text-[0.7rem] ${ae}`,children:[r.jsx("span",{className:`${rw(R.role)} font-semibold`,children:ow(R,S)}),$&&r.jsx("span",{className:"text-[0.65rem] text-slate-200",children:"now"}),ee&&r.jsx("span",{className:"text-[0.65rem] text-emerald-100",children:"next"})]},`${N}-${le}-${fe}`)})})]}),p?r.jsx("button",{type:"button",onClick:le=>{le.stopPropagation(),k(j.id)},disabled:o[N]||oe,className:yf("button-dark disabled:opacity-40",ce&&"bg-red-600/70 text-white hover:bg-red-600"),children:L}):null]},j.id)})})]})}function cw(n){switch(n){case"admin":case"lockdown":case"lockdown-admin":return"text-amber-300";case"spectator":return"text-slate-400";default:return"text-sky-300"}}function uw(n,s){if(!n)return"";const l=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${l} (you)`:l}function So({hideNicknameForm:n=!1,hideHeader:s=!1,className:l="",fillHeight:o=!1,compact:f=!1}){const{session:d}=nn(),h=d?.role!=="spectator",p=d?.users??[],x=d?.socketId||null,g=m.useMemo(()=>[...p].sort((y,S)=>y.socketId===x?-1:S.socketId===x?1:(y.nickname||"").localeCompare(S.nickname||"")),[x,p]),v=o?"flex-1 min-h-0 overflow-y-auto":f?"h-28 overflow-y-auto":"h-48 overflow-y-auto";return r.jsxs("section",{className:`panel-section space-y-0.5 text-base ${o?"flex h-full min-h-0 flex-col overflow-hidden":""} ${l}`,children:[!n&&r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"grid gap-0.5 md:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]",children:[r.jsx("div",{className:"min-w-0",children:r.jsx("div",{className:"surface flex w-full items-center px-0 py-0",children:r.jsx(To,{compact:f})})}),r.jsx(Zg,{})]}),!h&&r.jsx("p",{className:"text-xs text-slate-500",children:"Spectators cannot set nicknames."})]}),r.jsxs("div",{className:`space-y-0.5 ${o?"flex flex-1 min-h-0 flex-col":""}`,children:[!s&&r.jsxs("div",{className:`flex items-center justify-between text-sm text-slate-400 ${f?"text-xs":""}`,children:[r.jsx("span",{children:"Users"}),r.jsx("span",{className:"text-xs text-slate-500",children:g.length})]}),r.jsx("div",{className:`surface flex flex-wrap content-start items-start gap-0.5 px-0 pb-0 ${v} ${f?"text-[0.8rem]":""}`,children:g.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"Waiting for users…"}):g.map(y=>r.jsx("span",{className:`rounded bg-slate-800/80 px-1 py-0.25 text-[0.7rem] ${cw(y.role)}`,children:uw(y,x)},y.socketId))})]})]})}const fw=/^cu_[a-f0-9]{32}$/,ki="field-input w-full max-w-sm text-left focus:ring-emerald-500",_o="mx-auto w-full max-w-xl flex justify-center",bi="mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center";function dw(n){const s=String(n||"").trim();return s?s.length<=10?`${s.slice(0,2)}***${s.slice(-2)}`:`${s.slice(0,6)}...${s.slice(-6)}`:""}const Sx=8*1024*1024,is=16e3,mw={iceServers:[{urls:"stun:stun.l.google.com:19302"}],bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"};function jx(n){let s="";for(let o=0;o{if(!n||n.iceGatheringState==="complete"){l();return}const o=setTimeout(()=>{n.removeEventListener("icegatheringstatechange",f),l()},s);function f(){n.iceGatheringState==="complete"&&(clearTimeout(o),n.removeEventListener("icegatheringstatechange",f),l())}n.addEventListener("icegatheringstatechange",f)})}function Ax(n){if(!n)return!1;const s=n.connectionState,l=n.iceConnectionState;return s==="connected"||l==="connected"||l==="completed"}function gw(n,s=1e4){return new Promise((l,o)=>{if(!n){o(new Error("Peer connection missing"));return}if(Ax(n)){l();return}const f=setTimeout(()=>{h(),o(new Error("Peer connection timeout"))},s),d=()=>{Ax(n)?(h(),l()):(n.connectionState==="failed"||n.connectionState==="closed"||n.iceConnectionState==="failed")&&(h(),o(new Error(`Peer connection ${n.connectionState||n.iceConnectionState}`)))};function h(){clearTimeout(f),n.removeEventListener("connectionstatechange",d),n.removeEventListener("iceconnectionstatechange",d)}n.addEventListener("connectionstatechange",d),n.addEventListener("iceconnectionstatechange",d)})}async function vw(n){if(!n?.getParameters||!n?.setParameters)return;const s=n.getParameters()||{},l=s.encodings&&s.encodings[0]||{};s.encodings=[{...l,maxBitrate:64e3,dtx:"disabled"}];try{await n.setParameters(s)}catch{}}function bw(n,s=6e3){return new Promise((l,o)=>{if(!n){o(new Error("Peer connection missing"));return}const f=Date.now();let d=-1;const h=setInterval(async()=>{if(Date.now()-f>s){clearInterval(h),o(new Error("WHIP connected but no outbound audio flow"));return}try{const p=n.getSenders().filter(x=>x.track?.kind==="audio");for(const x of p){const g=await x.getStats();for(const v of g.values()){if(v.type!=="outbound-rtp"||v.kind!=="audio")continue;const y=Number(v.bytesSent||0),S=Number(v.packetsSent||0);if(d<0)d=y;else if(y>d+200||S>5){clearInterval(h),l();return}}}}catch{}},250)})}function xn({label:n,active:s,detail:l=""}){return r.jsxs("div",{className:`rounded-md px-0.5 py-0.5 text-xs text-slate-100 ${s?"bg-emerald-500":"bg-slate-700"}`,children:[r.jsx("div",{className:"text-center font-medium",children:n}),r.jsx("div",{className:"text-center text-[0.72rem] opacity-90",children:l||(s?"active":"idle")})]})}function Nx({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function yw(n){const s=n.reduce((f,d)=>f+d.length,0),l=new Float32Array(s);let o=0;for(const f of n)l.set(f,o),o+=f.length;return l}function Sw(n){const s=new Int16Array(n.length);for(let l=0;l{for(let v=0;vv&&s?.[v]||null,[s,v]),ee=!!($&&$.state!=="offline"&&!$.error),ae=$?.source==="upload"&&$?.state==="playing",pe=$?.source==="mic-whip"&&($?.state==="starting"||$?.state==="playing"),re=!!(!j&&X.current&&(k||R)),ue=!j&&(N==="live"||N==="starting"),ve=j&&M==="recording",be=j&&M==="sending",xe=An(p?.keymap?.micPtt?.[0])||"M",Be=m.useCallback(P=>{const de=P==="clip"?"clip":"live";g(Ne=>({...Ne||{},pttMode:de}))},[g]),ze=async()=>{if(!v){_("Take control of your rover first.");return}if(!y){_("Select an audio file first.");return}if(y.size>Sx){_(`File too large (max ${Sx} bytes).`);return}C(!0),_("");try{const P=await y.arrayBuffer(),de=jx(new Uint8Array(P));await l?.({roverId:v,name:y.name,mime:y.type||"",dataBase64:de}),_("Upload playback started.")}catch(P){_(P?.message||"Failed to play upload.")}finally{C(!1)}},Ae=async()=>{if(!v){_("Take control of your rover first.");return}C(!0),_("");try{await o?.(v),_("Upload playback stopped.")}catch(P){_(P?.message||"Failed to stop upload.")}finally{C(!1)}},tt=m.useCallback(async P=>{const de=String(P||te.current||"").trim();if(H.current=!1,T("idle"),F.current){try{F.current.getSenders().forEach(Ne=>Ne.track?.stop())}catch{}try{F.current.close()}catch{}}if(F.current=null,U.current)try{U.current.getTracks().forEach(Ne=>Ne.stop())}catch{}if(U.current=null,X.current=null,de)try{await h?.(de)}catch{}te.current=""},[h]),Je=m.useCallback(async P=>{const de=await f?.(P),Ne=String(de?.whipUrl||"").trim(),pt=String(de?.token||"").trim();if(!Ne||!pt)throw new Error("WHIP endpoint unavailable");const Ve=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:is,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}});U.current=Ve;const st=Ve.getAudioTracks()?.[0];if(X.current=st||null,st&&(st.enabled=!!(k||R)),st?.applyConstraints)try{await st.applyConstraints({channelCount:1,sampleRate:is,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1})}catch{}const lt=new RTCPeerConnection(mw);F.current=lt,lt.onconnectionstatechange=()=>{if(!H.current)return;const Yt=lt.connectionState;if(Yt==="connected"){T("live");return}(Yt==="failed"||Yt==="disconnected"||Yt==="closed")&&(T("error"),_(`WHIP transport ${Yt}.`))},Ve.getAudioTracks().forEach(Yt=>{const La=lt.addTrack(Yt,Ve);vw(La)});const Ot=await lt.createOffer({offerToReceiveAudio:!1,offerToReceiveVideo:!1});await lt.setLocalDescription(Ot),await xw(lt,1800);const it=await fetch(Ne,{method:"POST",headers:{"Content-Type":"application/sdp",...pw(pt)},body:lt.localDescription?.sdp||Ot.sdp});if(!it.ok)throw new Error(`WHIP request failed: ${it.status}`);const ms=await it.text();await lt.setRemoteDescription({type:"answer",sdp:ms}),await gw(lt,1e4),await bw(lt,6e3),await d?.(P)},[k,R,d,f]),vt=m.useCallback(async()=>{if(le.current=!1,q.current){try{q.current.disconnect()}catch{}q.current.onaudioprocess=null}if(V.current)try{V.current.disconnect()}catch{}if(L.current)try{L.current.disconnect()}catch{}if(ce.current)try{ce.current.getTracks().forEach(P=>P.stop())}catch{}if(oe.current)try{await oe.current.close()}catch{}Z.current=[],q.current=null,V.current=null,L.current=null,ce.current=null,oe.current=null,fe.current=is},[]),ie=m.useCallback(async()=>{if(ce.current&&oe.current&&q.current)return;O(st=>st==="recording"?st:"arming");const P=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:is,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}}),de=new AudioContext({latencyHint:"interactive"}),Ne=de.createMediaStreamSource(P),pt=de.createScriptProcessor(1024,1,1),Ve=de.createGain();Ve.gain.value=0,pt.onaudioprocess=st=>{if(!le.current)return;const lt=st.inputBuffer.getChannelData(0);Z.current.push(new Float32Array(lt))},Ne.connect(pt),pt.connect(Ve),Ve.connect(de.destination),ce.current=P,oe.current=de,V.current=Ne,q.current=pt,L.current=Ve,fe.current=de.sampleRate||is},[]),me=m.useCallback(async({send:P})=>{const de=le.current;if(le.current=!1,!de){P||O("idle");return}const Ne=Z.current;if(Z.current=[],!P){O("idle");return}if(!v){O("idle");return}if(!Ne.length){O("idle");return}O("sending");try{const pt=yw(Ne),Ve=jw(pt,fe.current||is),st=jx(Ve);await l?.({roverId:v,name:`ptt-${Date.now()}.wav`,mime:"audio/wav",dataBase64:st}),O("idle")}catch(pt){O("error"),_(pt?.message||"Failed to send PTT clip.")}},[l,v]),se=m.useCallback(async()=>{if(!v){_("Take control of your rover first.");return}await ie(),Z.current=[],le.current=!0,O("recording")},[ie,v]);return m.useEffect(()=>{let P=!1;async function de(){if(j){await tt(te.current||v);return}if(!v){await tt(te.current);return}if(!(H.current&&te.current===v)&&!(!k&&!R))try{T("starting"),_(""),H.current=!0,te.current=v,await Je(v),P||T("live")}catch(Ne){P||(T("error"),_(Ne?.message||"Failed to start mic forwarding.")),await tt(v)}}return de(),()=>{P=!0}},[j,k,R,v,Je,tt]),m.useEffect(()=>{const P=X.current;P&&(P.enabled=!!(!j&&(k||R)))},[j,k,R]),m.useEffect(()=>{let P=!1;async function de(){if(!j||!v){le.current&&await me({send:!1}),O("idle");return}try{await ie(),!P&&!le.current&&O("idle")}catch(Ne){P||(O("error"),_(Ne?.message||"Microphone access failed for clip mode."))}}return de(),()=>{P=!0}},[j,ie,me,v]),m.useEffect(()=>{let P=!1;async function de(){if(j){if(!v){le.current&&await me({send:!1});return}if(R){if(!le.current)try{_(""),await se()}catch(Ne){P||(O("error"),_(Ne?.message||"Failed to start clip recording."))}}else le.current&&await me({send:!0})}}return de(),()=>{P=!0}},[j,me,R,v,se]),m.useEffect(()=>()=>{tt(te.current||v),vt()},[v,tt,vt]),r.jsx("section",{className:"surface",children:r.jsxs("div",{className:"grid gap-1",children:[r.jsx("p",{className:"text-sm text-slate-100 text-center",children:"Audio Controls"}),r.jsx("section",{className:"surface",children:r.jsxs("div",{className:"flex items-center justify-center gap-0.5 py-0.25 text-xs text-slate-300",children:[r.jsx("span",{children:"Push-to-Talk Key"}),r.jsx(Nx,{label:xe})]})}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-2",children:[r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"PTT Mode"}),r.jsx("p",{className:"text-xs text-slate-400 text-center",children:"Choose how holding your PTT key behaves: live mic stream, or record-and-send clip. If the live stream doesn't work, switch to clip mode."}),r.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[r.jsx("button",{type:"button",className:`button-dark w-full text-sm ${j?"":"bg-emerald-500 text-white hover:bg-emerald-500"}`,onClick:()=>Be("live"),children:"Live Mic (WHIP)"}),r.jsx("button",{type:"button",className:`button-dark w-full text-sm ${j?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,onClick:()=>Be("clip"),children:"Record Clip"})]})]})}),r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_1fr]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"PTT Clip Status"}),r.jsxs("div",{className:"grid gap-0.5 content-start",children:[r.jsx(xn,{label:"Mode",active:j,detail:j?"record clip":"live mic"}),r.jsx(xn,{label:"PTT hold",active:R,detail:R?"held":"released"}),r.jsx(xn,{label:"Recording",active:ve,detail:ve?"capturing":"idle"}),r.jsx(xn,{label:"Playback",active:j&&ae,detail:j&&ae?"playing":"idle"})]})]})})]}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-2",children:[r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr_auto]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Audio Upload"}),r.jsxs("label",{className:"mx-auto grid w-full max-w-sm gap-0.5 text-xs text-slate-300 text-center",children:[r.jsx("span",{children:"Audio file (mp3 / wav / ogg)"}),r.jsx("input",{className:`${ki} text-center`,type:"file",accept:".mp3,.wav,.ogg,audio/mpeg,audio/wav,audio/ogg",disabled:E||!v,onChange:P=>S(P.target.files?.[0]||null)})]}),r.jsx("div",{className:"mx-auto w-full max-w-sm text-center",children:y?r.jsxs("div",{className:"surface-muted text-xs text-slate-300",children:[y.name," (",y.size," bytes)"]}):r.jsx("div",{className:"surface-muted text-xs text-slate-500",children:"No file selected"})}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:E||!v,onClick:ze,children:E?"Working...":"Play Upload"}),r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:E||!v,onClick:Ae,children:"Stop"})]})]})}),r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Live Microphone"}),r.jsxs("label",{className:"surface-muted mx-auto flex w-full max-w-sm items-center justify-center gap-0.5 px-0.5 py-0.5 text-xs text-slate-300",children:[r.jsx("input",{type:"checkbox",checked:k,disabled:!v||j,onChange:P=>g(de=>({...de||{},openMicEnabled:!!P.target.checked}))}),r.jsx("span",{children:j?"Open mic (live mode only)":"Open mic"})]}),r.jsxs("div",{className:"grid gap-0.5 content-start",children:[r.jsx(xn,{label:"WHIP link",active:ue,detail:N}),r.jsx(xn,{label:"Mic hot",active:re,detail:re?"transmitting":"muted"}),r.jsxs("div",{className:"surface-muted text-center text-xs text-slate-400",children:["Hold ",r.jsx(Nx,{label:xe})," to talk"]})]})]})})]}),r.jsx("section",{className:"surface",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Audio Status"}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-6",children:[r.jsx(xn,{label:"Forward pipe",active:ee,detail:ee?"connected":"offline"}),r.jsx(xn,{label:"Upload playback",active:ae,detail:ae?"playing":"idle"}),r.jsx(xn,{label:"Mic relay",active:pe,detail:pe?"active":"idle"}),r.jsx(xn,{label:"WHIP transport",active:ue,detail:N}),r.jsx(xn,{label:"Clip recording",active:ve,detail:ve?"recording":"idle"}),r.jsx(xn,{label:"Clip sending",active:be,detail:be?"sending":"idle"})]}),K?r.jsx("div",{className:"text-xs text-slate-400 text-center",children:K}):null]})})]})})}function Nw({pendingRequestId:n,currentStoredKey:s,nickname:l,requestVerification:o,applyIdentityKey:f,onMessage:d,fullWidth:h=!1}){const[p,x]=m.useState(0),[g,v]=m.useState(""),[y,S]=m.useState(!1),[E,C]=m.useState(!1),k=()=>{x(1),v(s),S(!1),d?.("")},w=()=>{x(0),S(!1)},j=async T=>{if(T.preventDefault(),!y){d?.("Please confirm your nickname agreement before sending.");return}if(p<3){d?.("Complete all request steps before sending.");return}C(!0),d?.("");try{const M=await f(g);await o?.(),v(M),x(0),S(!1),d?.("Verification request sent to lockdown admins.")}catch(M){d?.(M.message||"Failed to submit request.")}finally{C(!1)}},N=h?"w-full":_o;return n?r.jsx("section",{className:`surface text-sm text-slate-300 ${N}`,children:r.jsxs("div",{className:bi,children:["Verification request pending: ",n]})}):p===0?r.jsx("section",{className:`surface ${N}`,children:r.jsxs("div",{className:bi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Verification"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:k,disabled:E,children:"Request Verification"})]})}):r.jsx("form",{className:`surface ${N}`,onSubmit:j,children:r.jsxs("div",{className:bi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Request verification"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Step ",p," of 3"]}),p===1?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Confirm your nickname, which is used as part of the verification process. You can edit it here before requesting."}),r.jsx("div",{className:"mx-auto w-full max-w-sm",children:r.jsx(To,{compact:!0})}),r.jsxs("div",{className:"surface-muted mx-auto w-full max-w-sm text-xs text-slate-300 text-center",children:["Current nickname: ",r.jsx("span",{className:"font-semibold",children:l||"(not set)"})]}),r.jsxs("label",{className:"flex items-center justify-center gap-0.5 text-xs text-slate-300 text-center",children:[r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:y,onChange:T=>S(T.target.checked)}),r.jsx("span",{children:"I understand this nickname is tied to my verification."})]}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!l||!y,onClick:()=>x(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:w,children:"Cancel"})]})]}):null,p===2?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Save your identity key in a safe place. You can use it to restore your identity in another browser."}),r.jsx("input",{className:ki,type:"password",name:"identity_key_request",autoComplete:"current-password",maxLength:35,value:g,onChange:T=>v(T.target.value.toLowerCase()),placeholder:"Identity key for this request"}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!g,onClick:()=>navigator.clipboard?.writeText(g),children:"Copy Key"}),r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!g,onClick:()=>x(3),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(1),children:"Back"})]})]}):null,p===3?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Final step: confirm and send your verification request."}),r.jsx("input",{className:ki,type:"password",name:"identity_key_request_final",autoComplete:"current-password",maxLength:35,value:g,onChange:T=>v(T.target.value.toLowerCase()),placeholder:"Identity key for this request"}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"submit",className:"button-dark text-sm",disabled:E||!g,children:"Confirm Request"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(2),children:"Back"})]})]}):null]})})}function ww({currentStoredKey:n,applyIdentityKey:s,onMessage:l,fullWidth:o=!1}){const[f,d]=m.useState(0),[h,p]=m.useState(""),[x,g]=m.useState(!1),v=()=>{d(1),p(""),l?.("")},y=()=>{d(0),p("")},S=async C=>{if(C.preventDefault(),!(f<2)){g(!0),l?.("");try{await s(h),d(0),p(""),l?.("Identity key restored.")}catch(k){l?.(k.message||"Failed to restore key.")}finally{g(!1)}}},E=o?"w-full":_o;return r.jsx("section",{className:`surface ${E}`,children:r.jsxs("div",{className:bi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Identity key"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Current: ",dw(n)||"not set yet"]}),r.jsx("input",{className:ki,type:"password",name:"identity_key_current",autoComplete:"current-password",maxLength:35,value:n,readOnly:!0,placeholder:"Identity key"}),f===0?r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!n,onClick:()=>navigator.clipboard?.writeText(n),children:"Copy Key"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:v,disabled:x,children:"Restore Key"})]}):null,f===1?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Restoring your key should only be done when needed. Use this to move your identity to another browser."}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>d(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:y,children:"Cancel"})]})]}):null,f===2?r.jsxs("form",{className:"space-y-0.5",onSubmit:S,children:[r.jsx("input",{className:ki,type:"password",name:"identity_key_restore",autoComplete:"current-password",maxLength:35,value:h,onChange:C=>p(C.target.value.toLowerCase()),placeholder:"Paste key to restore"}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"submit",className:"button-dark text-sm",disabled:x||!h,children:"Confirm Restore"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>d(1),children:"Back"})]})]}):null]})})}function Cw({requestableRovers:n=[],pendingRequests:s=[],requestPrivateRoverAccess:l,onMessage:o,fullWidth:f=!1}){const[d,h]=m.useState({}),p=m.useMemo(()=>{const v=new Map;return(s||[]).forEach(y=>{y?.roverId&&v.set(String(y.roverId),y)}),v},[s]),x=f?"w-full":_o,g=async v=>{if(v){h(y=>({...y,[v]:!0})),o?.("");try{(await l?.(v))?.existing?o?.("You already have a pending request for that rover."):o?.("Private rover access request sent to lockdown admins.")}catch(y){o?.(y.message||"Failed to send request.")}finally{h(y=>({...y,[v]:!1}))}}};return r.jsx("section",{className:`surface text-sm text-slate-300 ${x}`,children:r.jsxs("div",{className:bi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Private rover access requests"}),n.length===0?r.jsx("p",{className:"text-xs text-slate-500",children:"No closed private rovers are available to request right now."}):r.jsx("div",{className:"w-full space-y-0.5",children:n.map(v=>{const y=String(v.id),S=!!d[y],E=p.get(y);return r.jsxs("div",{className:"surface-muted flex items-center justify-between gap-0.5 px-1 py-0.5",children:[r.jsxs("div",{className:"min-w-0 text-left",children:[r.jsx("p",{className:"truncate text-xs font-semibold text-slate-100",children:v.name||y}),r.jsx("p",{className:"truncate text-[0.7rem] text-slate-500",children:y})]}),E?r.jsx("span",{className:"rounded bg-amber-700/30 px-1 py-0.5 text-[0.7rem] text-amber-200",children:"Pending"}):r.jsx("button",{type:"button",onClick:()=>g(y),disabled:S,className:"button-dark text-xs disabled:opacity-50",children:S?"Sending...":"Request"})]},y)})})]})})}function Vf(n){return String(n||"").trim()}function Ew(n){const s=Vf(n);return s?s.includes("DOCKINGRUNNING")?"Returning":s.includes("PAUSED")?"Paused":s.includes("HOUSECLEANINGRUNNING")?"Cleaning":s.includes("SPOTCLEANINGRUNNING")?"Spot cleaning":s.includes("STATE_START")?"Starting":s.includes("STATE_IDLE")||s.includes("STATE_STANDBY")?"Idle":s:"--"}function Ig(n){return n==="good"?"bg-emerald-600 text-white":n==="warn"?"bg-amber-500 text-slate-900":n==="danger"?"bg-rose-600 text-white":n==="info"?"bg-sky-600 text-white":"bg-slate-700 text-slate-100"}function rs({label:n,value:s,tone:l="muted",valueClass:o=""}){return r.jsxs("div",{className:`rounded-md px-1 py-0.75 text-center ${Ig(l)}`,children:[r.jsx("div",{className:"text-[0.72rem] opacity-90",children:n}),r.jsx("div",{className:`text-sm font-semibold ${o}`,title:String(s||""),children:s})]})}function kw({neato:n,onStart:s,onSendHome:l,onLocate:o,onClearErrors:f,fullWidth:d=!1}){const[h,p]=m.useState(""),x=d?"w-full":"w-full max-w-xl",g=!!n?.configured,v=!!(n?.enabled&&n?.connected),y=!!n?.telemetry?.extPowerPresent,S=!!n?.telemetry?.chargingActive,E=Ew(n?.telemetry?.uiState),C=n?.telemetry?.batteryPercent,k=Number.isFinite(C)?`${C}%`:"--",w=n?.telemetry?.batteryVoltage,j=Number.isFinite(w)?`${w.toFixed(2)} V`:"--",N=Vf(n?.telemetry?.robotError)||"--",T=Vf(n?.telemetry?.robotAlert)||"--",M=N!=="--"&&!/^no errors$/i.test(N)&&!/^200/.test(N),O=T!=="--"&&!/^200/.test(T),K=n?.controls||{},_=!!K?.start?.available,U=!!K?.sendHome?.available,X=!!K?.locate?.available,F=!!K?.clearErrors?.available,H=m.useMemo(()=>y?{key:"start",label:"Start cleaning",pending:"Starting...",toneClass:"bg-emerald-600 hover:bg-emerald-500 text-white",canRun:_,fn:s}:{key:"home",label:"Send to dock",pending:"Sending...",toneClass:"bg-sky-600 hover:bg-sky-500 text-white",canRun:U,fn:l},[y,_,s,U,l]),te=g&&v&&H.canRun,ce=g&&v&&X,oe=g&&v&&F,V=async(fe,R)=>{if(R){p(fe);try{await R()}catch{}finally{p("")}}},q=g?v?"Online":"Offline":"Not configured",L=g?v?"good":"danger":"warn",Z=C==null?"muted":C>=60?"good":C>=25?"warn":"danger",le=y?"Docked":E!=="--"?E:"Away from dock";return r.jsx("section",{className:`surface text-sm text-slate-200 ${x}`,children:r.jsxs("div",{className:"grid gap-0.5",children:[r.jsxs("div",{className:"relative flex items-center justify-center min-h-[1.5rem]",children:[r.jsxs("div",{className:"text-center",children:[r.jsx("p",{className:"text-sm text-slate-100",children:"Neato Controls"}),r.jsx("p",{className:"text-xs text-slate-400",children:"Control the autonomous Neato robovac"})]}),r.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${Ig(L)}`,children:q})]}),r.jsx("section",{className:"surface-muted px-0.5 py-0.5",children:r.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-0.5",children:[r.jsxs("div",{className:"grid gap-0.5",children:[r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.75 text-center",children:[r.jsx("div",{className:"text-xs text-slate-300",children:"State"}),r.jsx("div",{className:"text-base font-semibold text-slate-100",children:le})]}),r.jsx("button",{type:"button",disabled:!te||!!h,onClick:()=>V(H.key,H.fn),className:`rounded-md px-1 py-1 text-base font-semibold transition disabled:opacity-50 ${H.toneClass}`,children:h===H.key?H.pending:H.label})]}),r.jsx("button",{type:"button",disabled:!ce||!!h,onClick:()=>V("locate",o),className:"rounded-md bg-fuchsia-600 px-1 py-0.75 text-sm font-semibold text-white transition hover:bg-fuchsia-500 disabled:opacity-50",children:h==="locate"?"Playing...":"Play sound"}),r.jsx("button",{type:"button",disabled:!oe||!!h,onClick:()=>V("clearErrors",f),className:"rounded-md bg-amber-500 px-1 py-0.75 text-sm font-semibold text-slate-900 transition hover:bg-amber-400 disabled:opacity-50",children:h==="clearErrors"?"Clearing...":"Clear errors"})]})}),r.jsx("section",{className:"surface-muted px-0.5 py-0.5",children:r.jsxs("div",{className:"grid gap-0.5 grid-cols-2 sm:grid-cols-3 lg:grid-cols-7",children:[r.jsx(rs,{label:"Battery",value:k,tone:Z}),r.jsx(rs,{label:"Voltage",value:j,tone:w==null?"muted":"info"}),r.jsx(rs,{label:"Docked",value:y?"Yes":"No",tone:y?"info":"muted"}),r.jsx(rs,{label:"Charging",value:S?"Yes":"No",tone:S?"info":"muted"}),r.jsx(rs,{label:"UI state",value:E,tone:"muted",valueClass:"truncate"}),r.jsx(rs,{label:"Robot error",value:N,tone:M?"danger":"muted",valueClass:"truncate"}),r.jsx(rs,{label:"Robot alert",value:T,tone:O?"warn":"muted",valueClass:"truncate"})]})}),!g||!v||!H.canRun||!X||!F?r.jsx("p",{className:"text-xs text-slate-400 text-center",children:g?v?"Waiting for required Neato entities in Home Assistant.":"Home Assistant is offline.":"Set homeAssistant.neato.device in server config to enable Neato controls."}):null]})})}function Jg(){const{session:n,identifySession:s,requestVerification:l,requestPrivateRoverAccess:o,playUploadedAudio:f,stopUploadedAudio:d,startMicWhip:h,readyMicWhip:p,stopMicWhip:x,neatoStart:g,neatoSendHome:v,neatoLocate:y,neatoClearErrors:S}=nn(),{value:E,save:C}=He("identity",{cookieUserId:""}),{value:k}=He("profile",{nickname:""}),w=m.useMemo(()=>(E?.cookieUserId||"").trim(),[E?.cookieUserId]),j=(k?.nickname||"").trim(),N=!!n?.isVerified,T=n?.verification?.pendingRequestId||null,M=n?.privateRoverAccess?.requestableRovers||[],O=n?.privateRoverAccess?.pendingRequests||[],K=String(n?.assignment?.roverId||"").trim(),[_,U]=m.useState(""),X=async F=>{const H=String(F||"").trim().toLowerCase();if(!H)throw new Error("Identity key required.");if(!fw.test(H))throw new Error("Identity key must match format: cu_ + 32 lowercase hex chars.");return C(te=>({...te||{},cookieUserId:H})),await s({cookieUserId:H,nickname:j}),H};return r.jsxs("section",{className:"space-y-2 text-base",children:[r.jsxs("div",{className:"grid gap-2 grid-cols-1 lg:grid-cols-[minmax(0,1.25fr)_minmax(0,0.9fr)]",children:[N?null:r.jsx("div",{className:"lg:col-span-2",children:r.jsx(Nw,{pendingRequestId:T,currentStoredKey:w,nickname:j,requestVerification:l,applyIdentityKey:X,onMessage:U,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:N?r.jsxs("div",{className:"space-y-2",children:[r.jsx(kw,{neato:n?.neato||null,onStart:g,onSendHome:v,onLocate:y,onClearErrors:S,fullWidth:!0}),r.jsx(Aw,{ownRoverId:K,audioForwardByRover:n?.audioForward||{},playUploadedAudio:f,stopUploadedAudio:d,startMicWhip:h,readyMicWhip:p,stopMicWhip:x})]}):r.jsx("section",{className:"surface h-full",children:r.jsx("div",{className:"flex h-full flex-col items-center justify-center text-center text-xs text-slate-400",children:"Verify your account to unlock VIP controls."})})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(Cw,{requestableRovers:M,pendingRequests:O,requestPrivateRoverAccess:o,onMessage:U,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(ww,{currentStoredKey:w,applyIdentityKey:X,onMessage:U,fullWidth:!0})})]}),_?r.jsx("div",{className:_o,children:r.jsx("p",{className:"text-xs text-slate-400 text-center",children:_})}):null]})}const Mw=420,Rw=1200,qw={1:262,2:330,3:392,4:523};function jo(){const{session:n}=nn(),s=tn(),{value:l}=He("audio",ct),o=Number.isFinite(l?.masterVolume)?l.masterVolume:ct.masterVolume,f=Number.isFinite(l?.alertVolume)?l.alertVolume:ct.alertVolume,d=Math.max(0,Math.min(1,o*f)),h=m.useMemo(()=>{const k=Array.isArray(n?.buttonBox?.buttons)?n.buttonBox.buttons:[];return k.length===4?k:[1,2,3,4].map(w=>k.find(j=>Number(j?.id)===w)||{id:w,count:0,goal:0,rewardName:null,rewardId:null,rewardNumber:null,lastRewardAt:null})},[n?.buttonBox?.buttons]),[p,x]=m.useState({}),[g,v]=m.useState({}),y=m.useRef(new Map),S=m.useRef(new Map),E=m.useRef({}),C=m.useRef(null);return m.useEffect(()=>{const k={};h.forEach(j=>{k[j.id]=Number(j.lastRewardAt||0)});const w=E.current||{};h.forEach(j=>{const N=Number(j.id),T=k[N]||0,M=Number(w[N]||0);if(T>0&&T!==M){v(_=>({..._,[N]:!0}));const O=S.current.get(N);O&&clearTimeout(O);const K=setTimeout(()=>{v(_=>({..._,[N]:!1})),S.current.delete(N)},Rw);S.current.set(N,K)}}),E.current=k},[h]),m.useEffect(()=>{function k(j){const N=qw[j];if(!N||d<=0)return;let T=C.current;if(!T){const _=window.AudioContext||window.webkitAudioContext;if(!_)return;T=new _,C.current=T}const M=T.createOscillator(),O=T.createGain();M.type="square",M.frequency.value=N;const K=.14*d;O.gain.setValueAtTime(1e-4,T.currentTime),O.gain.exponentialRampToValueAtTime(Math.max(1e-4,K),T.currentTime+.01),O.gain.exponentialRampToValueAtTime(1e-4,T.currentTime+.2),M.connect(O),O.connect(T.destination),M.start(),M.stop(T.currentTime+.21)}function w(j={}){const N=Number(j.buttonId);if(!Number.isFinite(N)||N<1||N>4)return;x(O=>({...O,[N]:!0}));const T=y.current.get(N);T&&clearTimeout(T);const M=setTimeout(()=>{x(O=>({...O,[N]:!1})),y.current.delete(N)},Mw);y.current.set(N,M),k(N)}return s.on("buttonBox:increment",w),()=>{s.off("buttonBox:increment",w)}},[d,s]),r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsx("header",{className:"panel-muted text-center text-sm",children:r.jsx("p",{children:"Button Box"})}),r.jsx("div",{className:"grid grid-cols-4 gap-0.5",children:h.map(k=>{const w=Number(k.id),j=Number.isFinite(k.count)?k.count:0,N=Number.isFinite(k.goal)?k.goal:0,T=typeof k.rewardName=="string"&&k.rewardName.trim()?k.rewardName.trim():"Unassigned",M=Number.isFinite(k.rewardNumber)?k.rewardNumber:"?",O=!!p[w],K=!!g[w];return r.jsx(xg,{buttonId:w,count:j,goal:N,rewardNumber:M,rewardName:T,className:[O?"bg-cyan-900/45":"",K?"bg-fuchsia-900/45":""].filter(Boolean).join(" ")},w)})})]})}function Tw(){const{state:{roverId:n}}=_t(),l=ml(n)?.sensors||{};return r.jsx("section",{className:"panel-section",children:r.jsx("div",{className:"aspect-square w-full",children:r.jsx(Uf,{sensors:l})})})}function Dw(){const{state:{roverId:n,keymap:s,camera:l,horn:o},pipeline:f,actions:{setServoAngle:d,setNightVision:h,startHorn:p,stopHorn:x}}=_t(),g=qg(n),v=g.docked&&!g.driving,y=l?.config,S=!!(n&&l?.enabled&&y),E=!!(n&&f?.nightVision),C=f?.nightVisionState,k=!!(n&&f?.horn),w=o?.overheated,j=typeof y?.minAngle=="number"?y.minAngle:-30,N=typeof y?.maxAngle=="number"?y.maxAngle:30,T=typeof l?.angle=="number"?l.angle:typeof y?.homeAngle=="number"?y.homeAngle:(j+N)/2,M=An(s?.nightVisionToggle?.[0]),O=An(s?.hornHonk?.[0]),K=An(s?.cameraUp?.[0]),_=An(s?.cameraDown?.[0]);return r.jsxs("section",{className:"panel-section grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto] gap-0.5",children:[r.jsx(Tg,{layout:"desktop",expand:!0,driveDockState:g}),v?null:r.jsxs("div",{className:"surface space-y-0.5 p-0 text-sm text-slate-200",children:[E&&r.jsx(Dg,{nightVisionOn:C?.nightVisionOn,disabled:!n,onToggle:h,keyLabel:M}),k&&r.jsx(_g,{disabled:!n||w,onStart:p,onStop:x,keyLabel:O,active:o?.active,heat:o?.heat}),S&&r.jsx(Bg,{value:T,min:j,max:N,onChange:d,keyDownLabel:_,keyUpLabel:K,className:"space-y-0.5 px-1 py-1",labelRowClass:"text-xs text-slate-300",labelClass:"",valueClass:"font-mono text-slate-100",sliderClass:"w-full",accentClass:"accent-emerald-400",endpointClass:"text-[0.7rem] text-slate-400"})]})]})}function _w({layout:n,onOpenHelpOverlay:s}){const l=ft(E=>E.session),{state:o}=_t(),{value:f}=He("vipAudio",{openMicEnabled:!1,pttMode:"live"}),d=l?.isVerified?"bg-emerald-400":"bg-red-600",h=String(l?.assignment?.roverId||"").trim(),p=h?l?.audioForward?.[h]:null,x=!!o?.mic?.pttActive,g=!!f?.openMicEnabled,v=f?.pttMode==="clip"?"clip":"live",y=!!(h&&l?.isVerified&&(v==="clip"?x:g||x)),S=!!(h&&l?.isVerified&&v==="clip"&&p?.source==="upload"&&p?.state==="playing");return r.jsx("section",{className:"panel text-base",children:r.jsxs(yd,{defaultTab:"telemetry",children:[r.jsxs(Sd,{children:[r.jsx(Wt,{id:"telemetry",children:"Controls"}),r.jsx(Wt,{id:"vip",highlight:S?"green":y?"pink":"none",children:r.jsxs("span",{className:"inline-flex items-center gap-2",children:[r.jsx("span",{children:"VIP"}),r.jsx("span",{className:`inline-block h-3 w-3 rounded-full ${d}`,"aria-hidden":"true",title:l?.isVerified?"Verified":"Not verified"})]})}),r.jsx(Wt,{id:"help",children:"Help"}),r.jsx(Wt,{id:"settings",children:"Settings"})]}),r.jsxs(jd,{children:[r.jsx(en,{id:"telemetry",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"grid items-stretch gap-0.5 grid-cols-[minmax(0,1.35fr)_minmax(0,0.95fr)]",children:[r.jsx(Tw,{}),r.jsx(Dw,{})]}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.9fr)_minmax(0,0.75fr)]",children:[r.jsx(Do,{}),r.jsx(ad,{panelId:"replay-sources-desktop",fillHeight:!0}),r.jsx(sw,{})]}),r.jsxs("div",{className:"grid items-stretch gap-0.5 grid-cols-[minmax(0,1.3fr)_minmax(0,0.22fr)] h-[14rem]",children:[r.jsx(qo,{fillHeight:!0}),r.jsxs("div",{className:"grid min-h-0 gap-0.5 grid-rows-[minmax(0,1fr)_auto]",children:[r.jsx(So,{compact:!0,hideNicknameForm:!0,fillHeight:!0}),r.jsx(aw,{compact:!0})]})]}),r.jsx(Hg,{}),r.jsx(jo,{}),r.jsx(fd,{defaultOrientation:"horizontal",panelId:"rightpane-telemetry"})]})}),r.jsx(en,{id:"vip",keepMounted:!0,children:r.jsx(Jg,{})}),r.jsx(en,{id:"help",children:r.jsx(Kg,{layout:n,onOpenOverlay:s})}),r.jsx(en,{id:"settings",children:r.jsx(Fg,{})})]})]})})}const Bw=new Set(["admin","lockdown","lockdown-admin"]),Ow=new Set(["lockdown","lockdown-admin"]),Lw=new Set(["admin","lockdown"]);function zw(n="admin"){return n==="lockdown"?{title:"Lockdown mode active",description:"Only the server owners can access the interface at this time."}:{title:"Admin mode active"}}function Uw(){const n=ft(S=>S.session),s=n?.mode,l=n?.role,o=n?.adminReason?.text||"";n?.adminReason?.updatedAt;const f=n?.timezone||"UTC",d=n?.socials?.find(S=>String(S?.id||S?.label||"").toLowerCase()==="discord")?.url||n?.discord?.invite||null,h=Lw.has(s),p=s==="lockdown"?Ow.has(l):Bw.has(l),[x,g]=m.useState(()=>new Date),v=m.useMemo(()=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:f,hour:"numeric",minute:"2-digit",second:"2-digit"}).format(x)}catch{return x.toLocaleTimeString()}},[x,f]);if(m.useEffect(()=>{const S=setInterval(()=>g(new Date),1e3);return()=>clearInterval(S)},[]),!h||p)return null;const y=zw(s);return r.jsx("div",{className:"pointer-events-auto fixed inset-0 z-50 flex items-center justify-center bg-black/85 px-0.5 py-0.5",children:r.jsxs("div",{className:"surface w-full max-w-md space-y-0.5 text-slate-100 shadow-2xl",children:[r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-lg font-semibold",children:y.title}),r.jsx("p",{className:"text-sm text-slate-300",children:y.description})]}),r.jsxs("div",{className:"surface-muted space-y-0.5",children:[r.jsx("p",{className:"text-[0.7rem] tracking-wide text-slate-400",children:"Reason for locking:"}),r.jsx("p",{className:"text-lg font-semibold text-slate-100",children:o||"No reason set."}),r.jsxs("p",{className:"text-center text-sm text-slate-300",children:["Server time: ",v]})]}),r.jsx("div",{className:"surface-muted",children:r.jsx(Vg,{})}),r.jsx("div",{className:"w-full justify-center items-center",children:r.jsx(pd,{id:"discord",label:"Join our Discord server for updates!",url:d})}),"You can still use the chat while the server is locked:",r.jsxs("div",{className:"max-h-80 overflow-y-auto",children:[r.jsx(qo,{}),r.jsx(To,{})]})]})})}const Hw="/assets/turn_alert-DVO8EZJa.mp3";function Vw(n,s=1){const l=m.useRef(null);return m.useEffect(()=>{l.current=new Audio(n),l.current.volume=s,l.current.load()},[n,s]),()=>{l.current&&(l.current.volume=s,l.current.currentTime=0,l.current.play().catch(()=>{}))}}function $w(){const n=ft(v=>v.session),{pushAlert:s}=wn(),{value:l}=He("audio",ct),o=Number.isFinite(l?.masterVolume)?l.masterVolume:ct.masterVolume,f=Number.isFinite(l?.alertVolume)?l.alertVolume:ct.alertVolume,d=Math.max(0,Math.min(1,o*f)),h=Vw(Hw,d),p=m.useRef(new Set),x=m.useMemo(()=>n?.turnQueues||{},[n?.turnQueues]),g=n?.socketId||null;return m.useEffect(()=>{if(!g)return;const v=[];Object.entries(x).forEach(([y,S])=>{!S||!S.current||S.current!==g||p.current.has(y)||(v.push(y),p.current.add(y))}),Object.keys(x).forEach(y=>{(!x[y]||x[y].current!==g)&&p.current.delete(y)}),v.length!==0&&(v.forEach(y=>{const S=n?.roster?.find(E=>String(E.id)===String(y))?.name||y;s({title:"Your turn!",message:`You now control ${S}.`,color:"#ff5722"})}),h())},[x,h,s,n?.roster,g]),null}function Gw({visible:n,mode:s,onEnterFullscreen:l,onDismiss:o}){if(!n)return null;const f=s==="pwa-hint";return r.jsx("div",{className:"fixed inset-0 z-40 flex items-end justify-center p-2 pointer-events-none sm:items-center",children:r.jsx("div",{className:"pointer-events-auto w-full max-w-sm rounded-lg border border-cyan-500/40 bg-zinc-950/95 shadow-xl",children:r.jsxs("div",{className:"space-y-0.5 p-4 text-sm text-slate-100",children:[r.jsx("h2",{className:"text-base font-semibold text-white",children:"Better in fullscreen"}),f?r.jsxs("p",{className:"text-slate-300",children:["For fullscreen on iOS, open Safari's share menu and pick ",r.jsx("strong",{children:"Add to Home Screen"}),". Launching from the home screen removes the browser chrome."]}):r.jsx("p",{className:"text-slate-300",children:"Enable fullscreen to free up more space for the video feed and controls. You can exit fullscreen at any time via the system back or home gesture."}),r.jsxs("div",{className:"flex justify-end gap-0.5 pt-1 text-sm",children:[r.jsx("button",{type:"button",className:"rounded border border-slate-600 px-3 py-1 text-slate-200",onClick:o,children:f?"Got it":"Not now"}),!f&&r.jsx("button",{type:"button",className:"rounded bg-cyan-500 px-3 py-1 font-semibold text-black hover:bg-cyan-400",onClick:l,children:"Enter fullscreen"})]})]})})})}function Yw({side:n="right",onClick:s}){const l=n==="left"?"left-2":"right-2";return r.jsx("button",{type:"button",onClick:s,className:`fixed bottom-2 ${l} z-30 flex h-10 w-10 items-center justify-center rounded-full border border-cyan-200/50 bg-slate-900/70 text-cyan-100 shadow-lg backdrop-blur-sm transition hover:bg-slate-800/80 active:scale-95`,"aria-label":"Enter fullscreen",title:"Enter fullscreen",children:r.jsx("svg",{viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true",className:"pointer-events-none",children:r.jsx("path",{d:"M4 9V4h5M15 4h5v5M20 15v5h-5M9 20H4v-5",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})}const Pg="fullscreenPromptDismissed",Fw=new Set(["mobile-portrait","mobile-landscape"]),Wg=()=>{if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}},Xw=()=>{const n=Wg();if(!n)return!1;try{return n.getItem(Pg)==="1"}catch{return!1}},wx=()=>{const n=Wg();if(n)try{n.setItem(Pg,"1")}catch{}},Qw=()=>{if(typeof navigator>"u")return!1;const n=navigator.userAgent||navigator.platform||"";return/iphone|ipad|ipod/i.test(n)},Cx=()=>{if(typeof document>"u")return!1;const n=document;return!!(n.fullscreenEnabled||n.webkitFullscreenEnabled||n.mozFullScreenEnabled||n.msFullscreenEnabled)};function Kw(n){const s=Fw.has(n),[l,o]=m.useState(!1),[f,d]=m.useState("native"),[h,p]=m.useState(!1),x=m.useMemo(()=>Qw(),[]),g=m.useMemo(()=>Cx(),[]),v=m.useCallback(()=>{if(!s){o(!1),p(!1);return}if(!h&&Xw()){o(!1);return}if(x){d("pwa-hint"),o(!0);return}if(!Cx()){o(!1);return}if(typeof document<"u"&&document.fullscreenElement){o(!1);return}d("native"),o(!0)},[h,x,s]);m.useEffect(()=>{v()},[v]),m.useEffect(()=>{if(typeof document>"u")return;const C=()=>{if(document.fullscreenElement){p(!1),o(!1);return}v()};return document.addEventListener("fullscreenchange",C),document.addEventListener("webkitfullscreenchange",C),()=>{document.removeEventListener("fullscreenchange",C),document.removeEventListener("webkitfullscreenchange",C)}},[v]);const y=m.useCallback(()=>{wx(),p(!1),o(!1)},[]),S=m.useCallback(async()=>{if(!s||x||typeof document>"u")return!1;if(document.fullscreenElement)return!0;const C=document.documentElement;if(!C)return!1;const k=C.requestFullscreen||C.webkitRequestFullscreen||C.mozRequestFullScreen||C.msRequestFullscreen;if(!k)return!1;try{const w=k.call(C);return w&&typeof w.then=="function"&&await w,wx(),p(!1),o(!1),!0}catch(w){return console.warn("Failed to enter fullscreen",w),!1}},[x,s]),E=m.useCallback(()=>{s&&(p(!0),d(x?"pwa-hint":"native"),o(!0))},[x,s]);return m.useEffect(()=>{s||(p(!1),o(!1))},[s]),{visible:l,mode:f,isIOS:x,nativeSupported:g,enterFullscreen:S,dismiss:y,showPrompt:E}}function Zw({visible:n,layout:s,onClose:l,showOnLoad:o,onToggleShowOnLoad:f}){if(!n)return null;const{state:d}=_t(),h=p=>{const x=!p.target.checked;f?.(x)};return r.jsx("div",{className:"fixed inset-0 z-30 flex items-center justify-center bg-black/80 px-0.5 py-0.5",children:r.jsxs("div",{className:"pointer-events-auto surface w-full max-w-4xl max-h-[90vh] overflow-hidden shadow-2xl",children:[r.jsxs("div",{className:"flex items-center justify-between border-b border-slate-700 px-0.5 py-0.25 text-sm text-slate-200",children:[r.jsx("span",{className:"font-semibold",children:"Help & controls"}),r.jsxs("div",{className:"flex items-center gap-0.5 text-[0.8rem] text-slate-300",children:[r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!o,onChange:h,className:"accent-cyan-500"}),r.jsx("span",{children:"Don't show again"})]}),r.jsx("button",{type:"button",onClick:l,className:"button-dark px-2 py-0.25 text-[0.8rem]",children:"Close"})]})]}),r.jsx("div",{className:"max-h-[85vh] overflow-y-auto p-0.5",children:r.jsx(Qg,{layout:s,keymap:d?.keymap||{}})})]})})}const Iw=`aroma + `,document.head.appendChild(s)},[])}function HA(n,s){return typeof n=="string"&&n.trim()?n.trim().toLowerCase():typeof s=="string"&&s.trim()?s.trim().toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,""):""}function hd({id:n,label:s,url:l,className:o=""}){if(!l)return null;UA();const f=HA(n,s),d=LA[f]||Sj,h=zA[f]||null,p=s||n||"Link";return r.jsxs("a",{href:l,target:"_blank",rel:"noopener noreferrer","aria-label":p,className:`inline-flex items-center w-full px-0.5 py-0.5 text-sm font-medium text-white transition justify-center gap-1 rounded-md ${h?"":"bg-slate-700 hover:bg-slate-600"} ${o}`,style:h||void 0,children:[r.jsx(d,{className:"mr-0"}),p]})}const Ni=10;function zg({batteryState:n=null,charge:s=null,config:l=null}){const o=n?.percentDisplay!=null&&Number.isFinite(n.percentDisplay)?Math.round(n.percentDisplay):null,f=n?.warnActive??null,d=n?.urgentActive??null,h=l?.Full??null,p=l?.Warn??null,x=l?.Urgent??null,g=s??n?.charge??null;let v=o;if(v==null&&(v=VA({charge:g,full:h,warn:p,urgent:x})),v==null)return{available:!1};const y=Math.max(0,Math.min(1,v/100)),S=f??(p!=null&&g!=null&&g<=p),E=d??(x!=null&&g!=null&&g<=x);return{available:!0,percent:y,percentDisplay:v,warnActive:S,urgentActive:E,warnDisplayPercent:Ni}}function VA({charge:n,full:s,warn:l,urgent:o}){if(n!=null&&s!=null&&l!=null&&o!=null&&s>l&&l>o){const f=Ni/100,d=1-f;if(n<=o)return 0;if(n<=l){const p=(n-o)/(l-o);return Math.round(Math.max(0,Math.min(1,p))*Ni)}if(n>=s)return 100;const h=(n-l)/(s-l);return Math.round((f+Math.max(0,Math.min(1,h))*d)*100)}return null}const $A=1600,GA=800;function Sn(...n){return n.filter(Boolean).join(" ")}function Uf({visual:n,orientation:s="horizontal",variant:l="inline",compact:o=!1,showLabel:f,className:d=""}){const h=l==="background",p=s==="vertical",x=f??!h;if(!n?.available){if(h){const te=Ni,ce=Sn("absolute z-10",p?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",E&&!S&&"battery-tick-warn"),oe=p?{bottom:`${te}%`}:{left:`${te}%`},V=Sn("absolute inset-0 pointer-events-none",d);return r.jsxs("div",{className:V,children:[r.jsx("div",{className:"absolute inset-0 bg-slate-900/35"}),r.jsx("div",{className:ce,style:oe})]})}return p?null:r.jsx("p",{className:"text-xs text-slate-500",children:"Battery telemetry unavailable"})}const g=n.percentDisplay??0,v=Math.max(0,Math.min(100,g)),y=n.warnDisplayPercent??Ni,S=!!n.urgentActive,E=!!n.warnActive,C=S?`${GA}ms`:E?`${$A}ms`:void 0,w=h?S||E?"bg-red-500/45":"bg-emerald-500/45":S||E?"bg-red-500":"bg-emerald-500",j=S||E?"bg-red-900/35":"bg-slate-900/35",N=S||E?"bg-red-900/45":"bg-slate-900/35",T=Sn(h?"absolute inset-0 pointer-events-none":"relative pointer-events-auto",p&&!h?"flex flex-col items-center justify-center":"w-full",d);if(h){const te=p?{height:`${v}%`}:{width:`${v}%`},ce=Sn("absolute",p?"bottom-0 left-0 right-0":"left-0 top-0 bottom-0",w,"transition-[width,height]",S&&"battery-urgent-flash"),oe=Sn("absolute z-10",p?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",E&&!S&&"battery-tick-warn"),V=p?{bottom:`${y}%`}:{left:`${y}%`};return r.jsxs("div",{className:T,children:[r.jsx("div",{className:Sn("absolute inset-0",j,S&&"battery-urgent-flash")}),r.jsx("div",{className:ce,style:{...te,animationDuration:C}}),r.jsx("div",{className:oe,style:V})]})}const M=Sn("relative overflow-hidden rounded-sm border border-slate-800",S||E?N:"bg-zinc-900/90",S&&"battery-urgent-flash",p?"w-full flex-1":o?"h-4":"h-5"),O=p?{height:`${v}%`}:{width:`${v}%`},K=Sn("absolute",p?"bottom-0 left-0 right-0":"left-0 top-0 bottom-0",w,"transition-[width,height]",S&&"battery-urgent-flash"),_=Sn("absolute z-10",p?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",E&&!S&&"battery-tick-warn"),U=p?{bottom:`${y}%`}:{left:`${y}%`},X=`Battery ${g}%`,F=Sn("pointer-events-none absolute inset-0 flex items-center justify-center text-center font-semibold",p?o?"text-[0.55rem]":"text-[0.65rem]":"text-xs"),H=Sn("rounded px-1.5 py-0.5",h?"bg-black/30 text-slate-100":"bg-black/50 text-slate-100");return r.jsxs("div",{className:T,children:[r.jsxs("div",{className:M,children:[r.jsx("div",{className:K,style:{...O,animationDuration:C}}),r.jsx("div",{className:_,style:U})]}),x&&!p?r.jsx("div",{className:F,children:r.jsx("span",{className:H,children:X})}):null,x&&p?r.jsx("div",{className:"mt-0.5 text-[0.65rem] font-semibold text-slate-100",children:r.jsxs("span",{className:H,children:[g,"%"]})}):null]})}function YA({mobileHud:n=!1,turnSeconds:s=null,isActiveDriver:l=!1,idleSkipSeconds:o=null}){const f=n?"text-3xl":"text-5xl",d=n?"text-xs":"text-sm",h=n?"text-[0.55rem]":"text-[0.75rem]",p=n?"px-4 py-3":"px-6 py-4",x=l&&typeof o=="number";return r.jsx("div",{className:"pointer-events-none absolute inset-0 z-30 flex items-center justify-center bg-black/55",children:r.jsxs("div",{className:`flex flex-col items-center gap-0.5 rounded border border-amber-300/80 bg-black/70 ${p}`,children:[r.jsx("div",{className:`font-semibold text-amber-200 ${f}`,children:"IT IS YOUR TURN!"}),r.jsx("div",{className:`text-amber-200/80 ${d}`,children:"Start driving!"}),x?r.jsxs("div",{className:`text-red-100/90 ${h}`,children:["Idle skip in ",o,"s"]}):null]})})}function Hf({sensors:n={},variant:s="full",size:l,overlay:o=!1}){const f=l||(s==="mini"?190:260),d=f/2,h=f*.07,p=d,x=d+h,g=d*.8,v=g-4,y=g+4,S=g-14,E=g-6,C=g*.65,k=n?.bumpsAndWheelDrops||{},w=n?.wheelOvercurrents||{},j=n?.wheelLeftCurrentMa??0,N=n?.wheelRightCurrentMa??0,T=n?.sideBrushCurrentMa??0,M=n?.mainBrushCurrentMa??0,O=6,K=k.bumpLeft?O:0,_=k.bumpRight?O:0,U=JA({count:6,totalSpan:140,gap:6,startAngle:-70}),X=["L","FL","CL","CR","FR","R"],F=[n?.lightBumpLeftSignal,n?.lightBumpFrontLeftSignal,n?.lightBumpCenterLeftSignal,n?.lightBumpCenterRightSignal,n?.lightBumpFrontRightSignal,n?.lightBumpRightSignal],H=U.map((V,q)=>({label:X[q],start:V.start,end:V.end,value:F[q]})),te=[{label:"Cliff L",start:-60,end:-46,value:n?.cliffLeftSignal,active:n?.cliffLeft},{label:"Cliff FL",start:-32,end:-16,value:n?.cliffFrontLeftSignal,active:n?.cliffFrontLeft},{label:"Cliff FR",start:16,end:32,value:n?.cliffFrontRightSignal,active:n?.cliffFrontRight},{label:"Cliff R",start:46,end:60,value:n?.cliffRightSignal,active:n?.cliffRight}],ce=F.filter(V=>V!=null),oe=ce.length?Math.max(...ce,1200):1200;return r.jsxs("div",{className:`${o?"relative":"surface relative p-1"}`,style:o?{width:`${f}px`,height:`${f}px`}:{height:"100%",width:"100%",aspectRatio:"1 / 1"},children:[o?null:r.jsxs(r.Fragment,{children:[r.jsx("div",{className:"absolute left-1 top-1 text-xs text-slate-400",children:"Top-down"}),r.jsxs("div",{className:"absolute right-1 top-1 text-[0.65rem] text-slate-500",children:["0–",oe]})]}),r.jsxs("svg",{width:"100%",height:"100%",viewBox:`0 0 ${f} ${f}`,preserveAspectRatio:"xMidYMid meet",className:"mx-auto block",children:[r.jsx("circle",{cx:p,cy:x,r:g,fill:"#0f172a",stroke:"#334155",strokeWidth:"2"}),r.jsx(ix,{cx:p-C,cy:x,current:j,drop:k.wheelDropLeft,overcurrent:w.leftWheel,label:"L"}),r.jsx(ix,{cx:p+C,cy:x,current:N,drop:k.wheelDropRight,overcurrent:w.rightWheel,label:"R"}),r.jsx(QA,{cx:p+g*.65,cy:x-g*.55,current:T,overcurrent:w.sideBrush}),r.jsx(KA,{cx:p,cy:x,current:M,overcurrent:w.mainBrush,variant:s,dirtLeft:n?.dirtDetectLeft,dirtRight:n?.dirtDetect}),H.map(V=>{const q=ZA(V.value,oe),L=y+4,Z=L+28;return r.jsx(FA,{cx:p,cy:x,rBase:Z,rTip:L,startDeg:V.start,endDeg:V.end,color:q,value:V.value,max:oe},V.label)}),te.map(V=>{const q=IA(V.value,V.active);return r.jsx(bf,{cx:p,cy:x,rInner:S,rOuter:E,startDeg:V.start,endDeg:V.end,color:q,opacity:1,pulse:!!V.active},V.label)}),r.jsx(bf,{cx:p,cy:x,rInner:v-K,rOuter:y-K,startDeg:-70,endDeg:-6,color:k.bumpLeft?"#ef4444":"#475569",opacity:1,pulse:!!k.bumpLeft}),r.jsx(bf,{cx:p,cy:x,rInner:v-_,rOuter:y-_,startDeg:6,endDeg:70,color:k.bumpRight?"#ef4444":"#475569",opacity:1,pulse:!!k.bumpRight})]})]})}function bf({cx:n,cy:s,rInner:l,rOuter:o,startDeg:f,endDeg:d,color:h,pulse:p=!1,opacity:x=1}){const g=(l+o)/2,v=o-l,y=XA(n,s,g,f,d);return r.jsxs(r.Fragment,{children:[r.jsx("path",{d:y,stroke:h,strokeWidth:v,strokeLinecap:"round",fill:"none",opacity:x}),p?r.jsx("path",{d:y,stroke:"#ef4444",strokeWidth:v,strokeLinecap:"round",fill:"none",className:"animate-pulse",opacity:1}):null]})}function FA({cx:n,cy:s,rBase:l,rTip:o,startDeg:f,endDeg:d,color:h,value:p,max:x}){const g=(f+d)/2,v=vi(n,s,o,g),y=ko(p!=null?p/(x||1):0),S=Math.pow(y,.35),E=l-(l-o)*S,C=vi(n,s,E,f),k=vi(n,s,E,d),w=`M ${v.x} ${v.y} L ${C.x} ${C.y} L ${k.x} ${k.y} Z`;return r.jsx("path",{d:w,fill:h,opacity:1,stroke:"none"})}function XA(n,s,l,o,f){let d=o,h=f;h<=d&&(h+=360);const p=vi(n,s,l,d),x=vi(n,s,l,h);return["M",p.x,p.y,"A",l,l,0,0,1,x.x,x.y].join(" ")}function vi(n,s,l,o){const f=Ug(o);return{x:n+l*Math.cos(f),y:s+l*Math.sin(f)}}function Ug(n){return(n-90)*Math.PI/180}function pd(n,s){if(s)return"#ef4444";const l=Math.abs(n);return l>900?"#f59e0b":l>300?"#22c55e":"#64748b"}function ko(n){return Math.max(0,Math.min(1,n))}function ix({cx:n,cy:s,current:l,drop:o,overcurrent:f,label:d}){const h=Math.abs(l),p=ko(h/1200),x=pd(l,f),g=56,v=14,y=9,S=3,E=g*p,C=d==="L"?-1:1,k=C*(-y/2-S/2),w=C*(v/2+S/2),j=v+y+S+2,N=g+4;return r.jsxs("g",{transform:`translate(${n},${s})`,children:[r.jsx("rect",{x:-j/2,y:-N/2,width:j,height:N,rx:"4",fill:"none",stroke:"#64748b",strokeWidth:"1"}),r.jsx("rect",{x:k-v/2,y:-g/2,width:v,height:g,fill:"#0f172a",stroke:"#0f172a",strokeWidth:"1",rx:"2"}),r.jsx("rect",{x:k-v/2,y:g/2-E,width:v,height:E,fill:x,className:f?"animate-pulse":""}),r.jsx("rect",{x:w-y/2,y:-g/2,width:y,height:g,fill:o?"#ef4444":"#475569",className:o?"animate-pulse":"",rx:"2"}),r.jsx("text",{x:0,y:g/2+10,textAnchor:"middle",className:"fill-slate-200 text-[0.7rem]",children:d})]})}function QA({cx:n,cy:s,current:l,overcurrent:o}){var f=Math.abs(l);f<10&&(f=0);const d=pd(l*3,o),h=43,p=f>0?.65:null;return r.jsxs("g",{style:{transformOrigin:`${n}px ${s}px`,animation:p?`spin ${p}s linear infinite`:"none",animationDirection:p?"reverse":"normal"},children:[r.jsx("circle",{cx:n,cy:s,r:10,fill:"#64748b",stroke:"#64748b",strokeWidth:"1"}),[0,120,240].map(g=>{const v=Ug(g),y=n+h*Math.cos(v),S=s+h*Math.sin(v);return r.jsx("line",{x1:n,y1:s,x2:y,y2:S,stroke:d,strokeWidth:"4",strokeLinecap:"round"},g)}),o?r.jsx("circle",{cx:n,cy:s,r:h+8,stroke:"#ef4444",strokeWidth:"3",fill:"none",className:"animate-pulse"}):null]})}function KA({cx:n,cy:s,current:l,overcurrent:o,variant:f,dirtLeft:d,dirtRight:h}){const p=Math.abs(l),x=pd(l,o),g=1,v=96,y=12,S=`main-brush-pattern-a-${f}`,E=`main-brush-pattern-b-${f}`,C=p>0?.6:null,k=l>=0?1:-1;return r.jsxs("g",{children:[r.jsx("defs",{children:[S,E].map((w,j)=>r.jsxs("pattern",{id:w,patternUnits:"userSpaceOnUse",width:"6",height:"6",children:[r.jsx("rect",{width:"6",height:"6",fill:x,opacity:g}),r.jsx("path",{d:"M0 6 L6 0",stroke:"#0f172a",strokeWidth:"1"}),C?r.jsx("animateTransform",{attributeName:"patternTransform",type:"translate",from:"0 0",to:`0 ${k*(j===0?6:-6)}`,dur:`${C}s`,repeatCount:"indefinite"}):null]},w))}),r.jsx("rect",{x:n-v/2,y:s-14,width:v,height:y,rx:"3",fill:`url(#${S})`,stroke:"#64748b",strokeWidth:"1"}),r.jsx("rect",{x:n-v/2,y:s+4,width:v,height:y,rx:"3",fill:`url(#${E})`,stroke:"#64748b",strokeWidth:"1"}),r.jsx("circle",{cx:n-v/4,cy:s-8,r:3.5,fill:"#fbbf24"}),r.jsx("circle",{cx:n+v/4,cy:s+8,r:3.5,fill:"#fbbf24"}),o?r.jsx("rect",{x:n-v/2-4,y:s-16,width:v+8,height:y*2+16,rx:"6",stroke:"#ef4444",strokeWidth:"3",fill:"none",className:"animate-pulse"}):null]})}function ZA(n,s){if(n==null||n<=0)return"hsl(200 60% 18%)";const o=ko(n/(s||1));return`hsl(${(200+Math.pow(o,.45)*360)%360} 100% 60%)`}function IA(n,s){if(s)return"#ef4444";const l=ko(n==null?0:n/4095),o=[47,55,69],f=[245,158,11],[d,h,p]=o.map((x,g)=>Math.round(x+(f[g]-x)*l));return`rgb(${d}, ${h}, ${p})`}function JA({count:n,totalSpan:s,gap:l,startAngle:o}){const d=(s-l*(n-1))/n,h=[];let p=o;for(let x=0;xr.jsxs("span",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:re}),r.jsx("span",{className:"font-semibold text-white",children:ue})]},re))]})}),r.jsx("div",{className:`absolute ${H} left-1/2`,style:te,children:r.jsxs("div",{className:`flex items-center gap-0.5 bg-black/80 text-slate-100 ${O} ${K}`,children:[r.jsx("span",{className:"font-semibold text-white rounded px-1 py-[1px] border border-transparent",style:ca(o,.18),children:l||"Unnamed Rover"}),v?r.jsxs("span",{className:"text-slate-300",children:["• ",v]}):null]})})]}),S?r.jsx("div",{className:"pointer-events-none absolute rounded",style:{...q},children:r.jsx(Hf,{sensors:s,size:240,overlay:!0})}):null]})}return r.jsxs("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:[r.jsx("div",{className:`absolute ${_} font-medium text-slate-100 ${T}`,children:r.jsxs("div",{className:"flex flex-col gap-0.5 leading-none",children:[r.jsxs("span",{children:["Status: ",f]}),d?r.jsxs("span",{children:["Audio: ",d]}):null,h?r.jsx("span",{className:"text-cyan-300",children:h}):null]})}),k?r.jsx("div",{className:`absolute left-1/2 top-0.5 -translate-x-1/2 rounded bg-black/70 text-slate-100 ${X} ${U}`,children:k}):null,r.jsx("div",{className:`absolute ${H} left-1/2`,style:te,children:r.jsx("div",{className:`flex gap-0.5 bg-black/80 text-slate-100 ${O} ${K}`,children:r.jsxs("span",{children:["Rover:"," ",r.jsxs("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ca(o,.18),children:['"',l||"Unnamed Rover",'"']})]})})}),S&&g!=="spectator"?r.jsx("div",{className:"pointer-events-none absolute rounded",style:{...q},children:r.jsx(Hf,{sensors:s,size:240,overlay:!0})}):null]})}const rx=2e3,WA=3e3,eN=3e3,tN=40,nN=1e3,aN={leftWheel:"Left wheel",rightWheel:"Right wheel",mainBrush:"Main brush",sideBrush:"Side brush",limiter:"Overcurrent limit"};function sN({motors:n,fill:s=0,compact:l=!1}){if(!n?.length)return null;const o=n.map(v=>aN[v]||v),f=l?"w-[12rem] h-[3.5rem]":"w-[20rem] h-[7rem]",d=l?"px-2 py-1":"px-4 py-2",h=l?"text-lg":"text-4xl",p=l?"text-xs":"text-xl",x=Math.max(0,Math.min(1,s)),g=`${Math.round(x*100)}%`;return r.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-red-900/50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 ${f}`,children:r.jsxs("div",{className:"relative h-full w-full",children:[r.jsx("div",{className:"absolute inset-0 overflow-hidden",children:r.jsx("div",{className:"h-full bg-red-700/60",style:{width:g}})}),r.jsxs("div",{className:`relative z-10 flex h-full w-full flex-col items-center justify-center text-center font-semibold text-white animate-pulse ${h} ${d}`,children:[r.jsx("div",{children:"OVERCURRENT"}),r.jsx("div",{className:`mt-0 font-medium text-white ${p}`,children:o.join(", ")})]})]})})}function lN({battery:n,compact:s=!1}){if(!n?.available||!n.warnActive&&!n.urgentActive)return null;const l=n.urgentActive?"BATTERY VERY LOW, DOCK THE ROVER AND CHARGE IMMEDIATELY!!":"Battery low! please dock and charge the rover soon.",o=s?"p-2 top-6":"p-4 top-10",f=s?"text-sm":"text-2xl";return r.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-amber-900/60 left-1/2 -translate-x-1/2 ${o}`,children:r.jsx("div",{className:`text-center font-semibold text-white animate-pulse ${f}`,children:r.jsx("div",{children:l})})})}function iN({sensors:n}){const s=[n?.lightBumpLeftSignal,n?.lightBumpFrontLeftSignal,n?.lightBumpCenterLeftSignal,n?.lightBumpCenterRightSignal,n?.lightBumpFrontRightSignal,n?.lightBumpRightSignal],l=s.filter(p=>p!=null).reduce((p,x)=>Math.max(p,x),1200),o=p=>Math.pow(Math.max(0,Math.min(1,(p??0)/l)),.35),f=p=>p==null||p<=0?"hsl(200 60% 18%)":`hsl(${(200+o(p)*360)%360} 100% 60%)`,d=6,h=12;return r.jsx("div",{className:"flex w-full items-center justify-center gap-0.5",children:s.map((p,x)=>{const g=o(p),v=x_.session),{sendMessage:l,onInputFocus:o,onInputBlur:f,blurChat:d,registerInputRef:h,setTypingActive:p}=od(),{value:x}=He("tts",{engine:"flite",voice:"rms",pitch:50}),[g,v]=m.useState(""),[y,S]=m.useState(!1),E=s?.role!=="spectator",C=s?.role==="spectator",k=s?.assignment?.roverId||null,j=!!m.useMemo(()=>s?.roster?.find(_=>String(_.id)===String(k))||null,[k,s?.roster])?.audio?.ttsEnabled,N=m.useMemo(()=>{if(!j)return null;const _=x?.engine==="espeak"?"espeak":"flite";if(_==="espeak"){let X=Number.isFinite(x?.pitch)?Math.round(x.pitch):void 0;return typeof X=="number"&&(X=Math.max(0,Math.min(99,X))),{speak:!0,engine:_,pitch:X}}const U=typeof x?.voice=="string"?x.voice:void 0;return{speak:!0,engine:_,voice:U}},[x?.engine,x?.pitch,x?.voice,j]),T=n?"pointer-events-auto absolute bottom-0.5 right-0.5 flex w-[9rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.4 py-0.2":"pointer-events-auto absolute bottom-1 right-1 flex w-[12rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.5 py-0.25",M=n?"min-w-0 flex-1 bg-transparent text-[0.55rem] text-slate-100 placeholder:text-slate-400 focus:outline-none":"min-w-0 flex-1 bg-transparent text-[0.7rem] text-slate-100 placeholder:text-slate-400 focus:outline-none",O=n?"rounded bg-cyan-500/80 px-0.35 py-0.2 text-[0.55rem] font-semibold text-black disabled:opacity-50":"rounded bg-cyan-500/80 px-0.5 py-0.25 text-[0.7rem] font-semibold text-black disabled:opacity-50";async function K(_){if(_.preventDefault(),!E)return;const U=g.trim();if(U){S(!0);try{await l(U,N),v(""),d(),p(!1)}catch(X){alert(X.message)}finally{S(!1)}}}return C?null:r.jsxs("form",{onSubmit:K,className:T,children:[r.jsx("input",{className:M,value:g,onChange:_=>{const U=_.target.value;v(U),p(!!U.trim())},onFocus:_=>{o(_),p(!!g.trim())},onBlur:_=>{f(_),p(!1)},onKeyDown:_=>{_.key==="Enter"&&!g.trim()&&(_.preventDefault(),d(),p(!1))},ref:_=>h(_,{target:"hud"}),placeholder:E?"Chat (TTS)":"Spectator",disabled:!E}),r.jsx("button",{type:"submit",disabled:!E||y,className:O,children:"Speak"})]})}function wi({sessionInfo:n,audioSessionInfo:s,videoMode:l="whep",snapshotFeed:o=null,qualityNotice:f=null,label:d,roverColor:h=null,forceMute:p=!1,telemetryFrame:x,batteryConfig:g,layoutFormat:v="desktop",hudVariant:y="default",driverLabel:S=null,hudForceMap:E=!1,hudMapPosition:C="top-center",hudLabelScale:k=1,fitParent:w=!1,overcurrentLimiter:j=null,showTurnCue:N=!1,turnTimerText:T=null,turnSeconds:M=null,isActiveDriver:O=!1,idleSkipSeconds:K=null}){const _=ft(ye=>ye.session),U=m.useRef(null),X=m.useRef(null),F=m.useRef(null),H=m.useRef(null),te=m.useRef(null),ce=m.useRef(null),oe=m.useRef(null),V=m.useRef(null),[q,L]=m.useState("idle"),[Z,le]=m.useState(null),[fe,R]=m.useState("idle"),[$,ee]=m.useState(null),[ae,pe]=m.useState(0),[re,ue]=m.useState(0),[ve,be]=m.useState(!0),xe=!!s?.url,Be=l==="snapshot",ze=x?.sensors,{value:Ae}=He("audio",ct),tt=Number.isFinite(Ae?.masterVolume)?Ae.masterVolume:ct.masterVolume,Je=Number.isFinite(Ae?.roverVolume)?Ae.roverVolume:ct.roverVolume,vt=typeof Ae?.mainBrushDuckEnabled=="boolean"?Ae.mainBrushDuckEnabled:typeof Ae?.autoLevelEnabled=="boolean"?Ae.autoLevelEnabled:ct.mainBrushDuckEnabled,ie=Number.isFinite(Ae?.mainBrushDuckAmount)?Math.max(0,Math.min(1,Ae.mainBrushDuckAmount)):ct.mainBrushDuckAmount,me=Math.max(0,Math.min(1,tt*Je)),se=ze?.batteryChargeMah??null,P=v==="desktop",de=!P,Ne=de?"top-right":C,[pt]=Lg(),Ve=E||de?!0:pt,st=zg({charge:se,config:g}),lt=ze?.wheelOvercurrents||null,Ot=lt==null?[]:Object.entries(lt).filter(([,ye])=>!!ye).map(([ye])=>ye),it=j?.caps||null,ms=j?.overcurrent?.groups||null,Yt=typeof window<"u"&&new URLSearchParams(window.location.search).has("debugAudio"),La=typeof window<"u"&&new URLSearchParams(window.location.search).has("debugHud"),Bo=m.useMemo(()=>{if(!it)return null;const ye=Number.isFinite(it?.drive?.cap)?it.drive.cap:1,Fe=Number.isFinite(it?.aux?.cap)?it.aux.cap:1;return Math.max(0,Math.min(1,1-Math.min(ye,Fe)))},[it]),Bn=!!j?.isActive,Nt=Ot.length?Ot:Bn?["limiter"]:[],Ft=Bo??(Ot.length?1:0),Mt=!!Nt.length,fa=!!((Number(ze?.mainBrushCurrentMa)||0)>tN||ze?.wheelOvercurrents?.mainBrush),Oo=vt&&fa?1-ie:1,hs=Math.max(0,Math.min(1,me*Oo)),ps=vt&&fa&&ie>0?`Volume decreased ${Math.round(ie*1e3)/10}%`:null,za=m.useRef({hasDedicatedAudio:!1,audioUrl:null,mainBrushDuckEnabled:!1,mainBrushDuckAmount:0,mainBrushActive:!1,baseRoverGain:0,effectiveRoverGain:0});m.useEffect(()=>{za.current={hasDedicatedAudio:xe,audioUrl:s?.url||null,mainBrushDuckEnabled:vt,mainBrushDuckAmount:ie,mainBrushActive:fa,baseRoverGain:me,effectiveRoverGain:hs}},[xe,s?.url,vt,ie,fa,me,hs]);const Pe=m.useCallback((ye,Fe={})=>{if(!Yt)return;const Ze=X.current,ke=za.current,$e={event:ye,ts:Date.now(),roverLabel:d||null,hasDedicatedAudio:ke.hasDedicatedAudio,audioUrl:ke.audioUrl,mainBrushDuckEnabled:ke.mainBrushDuckEnabled,mainBrushDuckAmount:ke.mainBrushDuckAmount,mainBrushActive:ke.mainBrushActive,baseRoverGain:ke.baseRoverGain,effectiveRoverGain:ke.effectiveRoverGain,element:Ze?{muted:Ze.muted,volume:Ze.volume,paused:Ze.paused,ended:Ze.ended,readyState:Ze.readyState,networkState:Ze.networkState}:null,...Fe};try{console.log(`[AudioDebug] ${ye} ${JSON.stringify($e)}`)}catch{console.log("[AudioDebug]",ye,$e)}},[Yt,d]),On=_?.socials?.find(ye=>String(ye?.id||ye?.label||"").toLowerCase()==="discord")?.url||_?.discord?.invite||null;m.useEffect(()=>{La&&console.log("[OvercurrentHUD]",{overlayVisible:Mt,overlayMotors:Nt,overlayFill:Ft,limiterActive:Bn,limiterCaps:it,limiterGroups:ms,wheelOvercurrents:lt})},[La,Ft,Nt,Mt,Bn,it,ms,lt]),m.useEffect(()=>{Pe("settings/update")},[Pe]);const Cn=m.useCallback(()=>{clearTimeout(F.current),F.current=setTimeout(()=>pe(Date.now()),rx)},[]),Ln=m.useCallback(()=>{clearTimeout(H.current),H.current=setTimeout(()=>ue(Date.now()),rx)},[]),xs=m.useCallback(async()=>{const ye=U.current;if(ye)try{ye.muted=!0,await ye.play()}catch{}},[]),hl=m.useCallback((ye=0)=>{if(p||xe)return;clearTimeout(ce.current);const Fe=()=>{clearTimeout(ce.current),ce.current=setTimeout(()=>{p||Ze()},WA)},Ze=async()=>{const ke=U.current;if(ke)try{await xs(),ke.muted=!1,await ke.play(),be(!1)}catch{ke.muted=!0,be(!0),Fe()}};ce.current=setTimeout(Ze,ye)},[xs,p,xe]);m.useEffect(()=>()=>{clearTimeout(F.current),clearTimeout(H.current),clearTimeout(ce.current),clearInterval(te.current),oe.current&&(cancelAnimationFrame(oe.current),oe.current=null)},[]),m.useEffect(()=>{q==="playing"&&hl(0)},[q,hl]),m.useEffect(()=>{Be&&(L("snapshot"),le(null))},[Be]),m.useEffect(()=>{if(Be||!n?.url||!U.current)return;let ye=!0,Fe;const Ze=setTimeout(()=>be(!0),0),ke=($e,rt)=>{ye&&(Pe("video/status",{nextStatus:$e,info:rt||null}),L($e),le(rt||null),$e==="playing"&&xs(),["error","failed","disconnected","closed"].includes($e)&&Cn())};return Fe=new lx({url:n.url,token:n.token,video:U.current,receiveAudio:!xe,onStatus:ke}),Fe.start().catch($e=>{ye&&(L("error"),le($e.message),Cn())}),()=>{ye=!1,clearTimeout(Ze),Fe?.stop()}},[Be,n?.url,n?.token,ae,Cn,xs,xe,Pe]),m.useEffect(()=>{q==="stopped"&&n?.url&&Cn()},[q,n?.url,Cn]),m.useEffect(()=>{const ye=X.current;if(!ye||!s?.url){Pe("route/no-audio-url"),V.current=null;return}const Fe=Math.max(0,Math.min(1,hs)),Ze=V.current==null?Math.max(0,Math.min(1,ye.volume)):V.current;if(oe.current&&(cancelAnimationFrame(oe.current),oe.current=null),Fe>Ze){const ke=performance.now(),$e=Ze,rt=Fe-$e,ot=wt=>{const nt=Math.min(1,(wt-ke)/nN),zn=$e+rt*nt;ye.volume=zn,V.current=zn,nt<1?oe.current=requestAnimationFrame(ot):oe.current=null};oe.current=requestAnimationFrame(ot)}else ye.volume=Fe,V.current=Fe;Pe("route/direct",{elementVolume:Fe,duckEnabled:vt,mainBrushActive:fa,duckAmount:ie})},[s?.url,hs,vt,fa,ie,Pe]),m.useEffect(()=>{if(!s?.url||!X.current)return;let ye=!0,Fe;const Ze=(ke,$e)=>{ye&&(Pe("audio/status",{nextStatus:ke,info:$e||null}),ee($e||(ke==="connected"?"connected":null)),R(rt=>ke==="connected"&&(rt==="playing"||rt==="connecting")||ke==="new"?rt:ke),["error","failed"].includes(ke)&&Ln())};return Fe=new lx({url:s.url,token:s.token,video:X.current,audioOnly:!0,onStatus:Ze}),Fe.start().catch(ke=>{ye&&(R("error"),ee(ke.message),Ln())}),()=>{ye=!1,Fe?.stop()}},[s?.url,s?.token,re,Ln,Pe]),m.useEffect(()=>{const ye=X.current;if(!s?.url||!ye){clearInterval(te.current);return}if(!["connecting","connected","playing","paused"].includes(fe)){clearInterval(te.current);return}const Ze=async()=>{const ke=X.current;ke&&(ke.muted=!1,!(!ke.paused&&!ke.ended)&&(Pe("retry/play-attempt"),ke.play().then(()=>{Pe("retry/play-ok"),R($e=>$e==="connected"?"playing":$e),ee($e=>$e==="paused"?null:$e)}).catch($e=>{Pe("retry/play-fail",{error:$e?.message}),ee(rt=>rt||$e?.message||"autoplay blocked")})))};return Ze(),te.current=setInterval(Ze,eN),()=>clearInterval(te.current)},[s?.url,fe,Pe]),m.useEffect(()=>{const ye=X.current;if(!ye)return;const Fe=()=>{Pe("element/play"),R(nt=>nt==="error"?nt:"playing"),ee(null)},Ze=()=>{Pe("element/pause"),R(nt=>["error","failed","disconnected","closed","stopped"].includes(nt)?nt:"paused"),ee(nt=>nt||"paused")},ke=()=>{Pe("element/ended"),R(nt=>nt==="error"?nt:"stopped"),ee(nt=>nt||"ended")},$e=()=>{const{error:nt}=ye,zn=nt?.message||"audio error";Pe("element/error",{error:zn}),R("error"),ee(zn)},rt=()=>Pe("element/waiting"),ot=()=>Pe("element/canplay"),wt=()=>Pe("element/stalled");return ye.addEventListener("play",Fe),ye.addEventListener("pause",Ze),ye.addEventListener("ended",ke),ye.addEventListener("error",$e),ye.addEventListener("waiting",rt),ye.addEventListener("canplay",ot),ye.addEventListener("stalled",wt),()=>{ye.removeEventListener("play",Fe),ye.removeEventListener("pause",Ze),ye.removeEventListener("ended",ke),ye.removeEventListener("error",$e),ye.removeEventListener("waiting",rt),ye.removeEventListener("canplay",ot),ye.removeEventListener("stalled",wt)}},[s?.url,Pe]);const pl=o?.error?`Error: ${o.error}`:o?.objectUrl?"snapshot":o?.status||"waiting",Ua=Be?pl:n?.url?q==="error"?`Error: ${Z||"unknown"}`:Z?`${q} (${Z})`:q:"waiting",Lo=s?.error?`Error: ${s.error}`:s?.url?fe==="error"?`Error: ${$||"unknown"}`:$?`${fe} (${$})`:fe:null,xl=y==="spectator",an=y==="none";return r.jsxs("div",{className:`flex flex-col gap-0.5 ${w?"h-full":""}`,children:[r.jsxs("div",{className:`relative w-full overflow-hidden bg-black ${w?"h-full flex-1":"aspect-[4/3]"}`,children:[Be?o?.objectUrl?r.jsx("img",{src:o.objectUrl,alt:d,className:"h-full w-full object-contain",draggable:!1}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-300",children:"Waiting for frame…"}):r.jsx("video",{ref:U,muted:p||ve||xe,playsInline:!0,autoPlay:!0,controls:!1,className:"h-full w-full object-contain"}),r.jsx("audio",{ref:X,autoPlay:!0,hidden:!0}),!an&&N?r.jsx(YA,{mobileHud:de,turnSeconds:M,isActiveDriver:O,idleSkipSeconds:K}):null,an?null:r.jsx(PA,{frame:x,sensors:ze,label:d,roverColor:h,status:Ua,audioStatus:Lo,levelStatus:ps,desktopLayout:P,layoutFormat:v,variant:y,driverLabel:S,battery:st,showTopDown:Ve,mobileHud:de,mapPosition:Ne,turnTimerText:T,labelScale:k}),an?null:r.jsx(rN,{compact:de}),!an&&La?r.jsx("div",{className:"pointer-events-none absolute left-1 top-1 z-40 rounded bg-black/80 px-1 py-0.5 text-[0.6rem] text-lime-200",children:`OC vis:${Mt?1:0} motors:${Nt.length} fill:${Math.round(Ft*100)}%`}):null,an?null:r.jsx(sN,{motors:Nt,fill:Ft,compact:de}),an?null:r.jsx(lN,{battery:st,compact:de}),!an&&xl&&st.available?r.jsx("div",{className:"pointer-events-none absolute right-1 top-1/2 flex h-[70%] -translate-y-1/2 flex-col items-center justify-center rounded bg-black/60 px-0.5 pb-1 pt-1",children:r.jsx(Uf,{visual:st,orientation:"vertical",variant:"inline",compact:de,className:"h-full w-4"})}):null,!an&&f?r.jsx("div",{className:"pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2",children:r.jsxs("div",{className:`mx-auto w-fit rounded border border-amber-300/80 bg-black/75 text-amber-200 ${de?"px-2 py-1 text-[0.6rem]":"px-3 py-1.5 text-sm"}`,children:[r.jsx("div",{className:"text-center",children:f}),r.jsx("div",{className:"pointer-events-auto mt-0",children:r.jsx(hd,{id:"discord",label:"Join our Discord server while you wait!",url:On})})]})}):null]}),!an&&!xl&&r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(iN,{sensors:ze}),r.jsx("div",{className:"panel-section space-y-0.5 text-sm",children:r.jsx(Uf,{visual:st,compact:de})})]})]})}function xd({layoutFormat:n="desktop"}){const s=ft(ae=>ae.session),{state:{song:l,lastControlIntentAt:o},overcurrentLimiter:f}=_t(),[d,h]=m.useState(()=>Date.now()),[p,x]=m.useState(!1),[g,v]=m.useState(null),y=m.useRef({active:!1,roverId:null});m.useEffect(()=>{if(s?.mode!=="turns")return;const ae=setInterval(()=>h(Date.now()),250);return()=>clearInterval(ae)},[s?.mode]);const S=s?.assignment?.roverId,C=!!(S&&s?.roster?s.roster.find(ae=>String(ae.id)===String(S)):null)?.media?.audioPublishUrl,k=S?s?.turnQueues?.[S]:null,w=s?.socketId||null,j=S?s?.activeDrivers?.[S]:null,N=!!(w&&j===w),T=m.useMemo(()=>{const ae=k?.queue||[];if(!ae.length||!k?.current||ae.length<=1)return null;const pe=ae.findIndex(re=>re===k.current);return pe===-1?ae[0]||null:ae[(pe+1)%ae.length]||null},[k?.queue,k?.current]),M=!!(w&&T===w),O=k?.deadline||null,K=k?.idleDeadline||null,_=O?O-d:null,U=K?K-d:null,X=s?.mode==="turns"&&M&&_!=null&&_<=5e3&&_>0,F=s?.mode!=="turns"||N||X,H=_!=null&&Number.isFinite(_)?Math.max(0,Math.ceil(_/1e3)):null,te=U!=null&&Number.isFinite(U)?Math.max(0,Math.ceil(U/1e3)):null,ce=N?H!=null?`${H}s left`:null:M&&H!=null?`Your turn in ${H}s`:null,oe=S?[...F?[{type:"rover",id:S,key:S}]:[],...C?[{type:"rover",id:`${S}-audio`,key:`${S}-audio`}]:[]]:[],V=Ai(oe),q=S&&F?V[S]:null,L=S&&C?V[`${S}-audio`]:null,Z=md(S?[S]:[],{enabled:!!S,version:s?.mode}),le=S&&Z[S]||null,fe=ml(S),R=S&&s?.roster?s.roster.find(ae=>String(ae.id)===String(S)):null,$=R?.battery??null,ee=R?.name||(S?`Rover ${S}`:"");return m.useEffect(()=>{if(s?.mode!=="turns"){x(!1),v(null),y.current={active:!1,roverId:null};return}const ae=y.current,pe=N&&!ae.active,re=N&&S&&S!==ae.roverId;pe||re?(x(!0),v(Date.now())):!N&&ae.active&&(x(!1),v(null)),y.current={active:N,roverId:S}},[N,S,s?.mode]),m.useEffect(()=>{!p||!g||o>g&&x(!1)},[o,g,p]),r.jsx("section",{className:"panel",children:S?r.jsx(wi,{sessionInfo:q,videoMode:F?"whep":"snapshot",snapshotFeed:le,audioSessionInfo:L,label:ee,roverColor:R?.color||null,telemetryFrame:fe,batteryConfig:$,layoutFormat:n,overcurrentLimiter:f,songNote:l?.note,qualityNotice:F?null:"Preview feed (low FPS) until your turn.",showTurnCue:p,turnTimerText:ce,turnSeconds:H,isActiveDriver:N,idleSkipSeconds:te}):r.jsxs("div",{className:"panel-muted content-center text-center text-sm text-slate-400 aspect-[4/3]",children:[r.jsx("p",{children:"You are not assigned to a rover."}),r.jsx("p",{className:"mt-0",children:r.jsx("a",{href:"/spectate",className:"text-blue-400 underline hover:text-blue-500",children:"Click here to visit the spectator page."})})]})})}function yo({label:n,tone:s="muted"}){const l=s==="success"?"bg-emerald-900 text-emerald-100":s==="warn"?"bg-amber-900 text-amber-100":"bg-slate-800 text-slate-200";return r.jsx("span",{className:`rounded px-1 py-0.5 text-xs font-semibold leading-none ${l}`,children:n})}function Mo(n){if(!Number.isFinite(n))return 0;const s=n%360;return s<0?s+360:s}function oN(n){if(!Array.isArray(n)||n.length<3)return 0;const[s,l,o]=n,f=Math.max(0,Math.min(255,Number(s)))/255,d=Math.max(0,Math.min(255,Number(l)))/255,h=Math.max(0,Math.min(255,Number(o)))/255,p=Math.max(f,d,h),x=Math.min(f,d,h),g=p-x;if(g===0)return 0;let v=0;return p===f?v=(d-h)/g%6:p===d?v=(h-f)/g+2:v=(f-d)/g+4,Mo(Math.round(v*60))}function ox(n){const s=Mo(n),l=1,o=1-Math.abs(s/60%2-1);let f=0,d=0,h=0;return s<60?(f=l,d=o):s<120?(f=o,d=l):s<180?(d=l,h=o):s<240?(d=o,h=l):s<300?(f=o,h=l):(f=l,h=o),[Math.round(f*255),Math.round(d*255),Math.round(h*255)]}function cx(n){return n?Array.isArray(n.hsColor)?Mo(Number(n.hsColor[0])):Array.isArray(n.rgbColor)?oN(n.rgbColor):0:0}function cN({entity:n,connected:s,controlsLocked:l,onToggle:o,onSetColor:f,onSetWhite:d}){const h=n.state==="unavailable"||!n.available,p=n.state==="on",x=n.type==="light"&&n.supportsColor,g=h?"warn":p?"success":"muted",v=h?"Unavailable":p?"On":"Off",y=l||!s||h,S=y||!x,[E,C]=m.useState(()=>cx(n)),k=m.useRef(E),w=m.useRef(!1),j=h?"border-slate-800 bg-slate-900 text-slate-400 cursor-not-allowed":l?"border-slate-800 bg-slate-900 text-slate-300 cursor-not-allowed":p?"border-emerald-700 bg-emerald-900/80 text-emerald-50 hover:bg-emerald-800":"border-rose-800 bg-rose-900/80 text-rose-50 hover:bg-rose-800";m.useEffect(()=>{if(!x||w.current)return;const U=cx(n);k.current=U,C(U)},[n.rgbColor,n.hsColor,x]);const N=U=>{const X=Mo(Number(U.target.value));k.current=X,C(X)},T=()=>{S||!f||f(n.id,ox(k.current))},M=U=>{U.stopPropagation()},O=U=>{M(U),!(S||!d)&&d(n.id)},_=`rgb(${(x?ox(k.current):[255,255,255]).join(",")})`;return r.jsxs("button",{type:"button",onClick:()=>o(n.id),disabled:y,className:`relative flex min-w-[12rem] flex-[1_1_12rem] items-start justify-between gap-0.5 rounded px-1 py-0.5 text-left transition-colors ${j} disabled:opacity-60 disabled:hover:bg-inherit`,children:[r.jsxs("div",{className:"min-w-0 flex-1",children:[r.jsxs("div",{className:"flex items-center gap-0.5 text-sm leading-normal",children:[r.jsx("span",{className:"truncate font-semibold text-white",children:n.name||n.id}),x&&r.jsxs(r.Fragment,{children:[r.jsx(yo,{label:v,tone:g}),!s&&r.jsx("span",{className:"text-xs text-amber-200",children:"Offline"})]})]}),x?r.jsx("div",{className:"-mt-0.5 w-full",onClick:M,onPointerDown:U=>{M(U),w.current=!0},onPointerUp:U=>{M(U),w.current=!1,T()},onPointerCancel:U=>{M(U),w.current=!1,T()},onKeyUp:U=>{M(U),T()},onBlur:T,children:r.jsx("div",{className:"relative w-full",children:r.jsx("input",{type:"range",min:"0",max:"360",step:"1",value:E,onChange:N,disabled:S,"aria-label":`Set color for ${n.name||n.id}`,className:"ha-hue-slider w-full"})})}):r.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-400",children:[r.jsx(yo,{label:v,tone:g}),!s&&r.jsx("span",{className:"text-amber-200",children:" · Offline"})]})]}),x&&r.jsxs("div",{className:"absolute right-1 top-1 flex items-center gap-0.5",children:[r.jsx("span",{role:"button",tabIndex:S?-1:0,onClick:O,onPointerDown:M,onKeyDown:U=>{S||(U.key==="Enter"||U.key===" ")&&(U.preventDefault(),O(U))},title:"Set white color temperature","aria-label":`Set ${n.name||n.id} to white`,"aria-disabled":S,className:`inline-flex items-center justify-center rounded border border-slate-200 bg-white px-1 py-0.5 text-xs font-semibold leading-none text-slate-900 ${S?"cursor-not-allowed opacity-60":"cursor-pointer hover:bg-slate-100"}`,children:"white"}),r.jsx("span",{className:"pointer-events-none h-2.5 w-2.5 rounded-full border border-white/60",style:{backgroundColor:_}})]}),!x&&r.jsx("div",{className:"self-center text-xs font-semibold text-white/90",children:p?"Turn off":"Turn on"})]})}function Hg(){const{state:{keymap:n}}=_t(),s=ft(E=>E.session),{homeAssistantToggle:l,homeAssistantSetLightColor:o,homeAssistantSetLightWhite:f}=wn(),d=s?.homeAssistant,h=m.useMemo(()=>d?.entities||[],[d?.entities]),p=d?.lightPolicy||null,x=!!(p?.locked||p?.lockedOn),g=p?.lockState||(p?.lockedOn?"on":null),v=An(n?.homeAssistantOn?.[0]),y=An(n?.homeAssistantOff?.[0]);if(!d?.enabled)return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm text-slate-400",children:[r.jsx("p",{className:"text-slate-300",children:"Room Controls"}),r.jsx("p",{className:"text-slate-500",children:"Not configured on the server."})]});if(h.length===0)return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm text-slate-400",children:[r.jsx("p",{className:"text-slate-300",children:"Room Controls"}),r.jsx("p",{className:"text-slate-500",children:"No lights or switches configured."})]});const S=!!d?.connected;return r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("header",{className:"flex items-center justify-between gap-0.5 text-sm text-slate-400",children:[r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("p",{children:"Room Controls"}),r.jsx("span",{className:"text-xs text-slate-500",children:h.length}),x?r.jsx(yo,{label:g==="off"?"Locked Off":"Locked On",tone:"warn"}):null,r.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-300 background-black",children:[r.jsxs("span",{className:"flex items-center gap-0.5",children:[r.jsx("span",{children:"On"}),v?r.jsx(ux,{label:v}):null]}),r.jsxs("span",{className:"flex items-center gap-0.5",children:[r.jsx("span",{children:"Off"}),y?r.jsx(ux,{label:y}):null]})]})]}),r.jsx(yo,{label:S?"Connected":"Offline",tone:S?"success":"warn"})]}),x?r.jsx("p",{className:"rounded border border-amber-600/60 bg-amber-900/40 px-1 py-0.5 text-xs text-amber-100",children:g==="off"?"Lights are locked off. Room controls are disabled.":"Lights are locked on. Room controls are disabled."}):null,r.jsx("div",{className:"flex flex-wrap gap-0.5",children:h.map(E=>r.jsx(cN,{entity:E,connected:S,controlsLocked:x,onToggle:l,onSetColor:o,onSetWhite:f},E.id))})]})}function ux({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function Vg(){const{login:n,setRole:s}=wn(),[l,o]=m.useState(""),[f,d]=m.useState(""),[h,p]=m.useState(!1);async function x(g){g.preventDefault(),p(!0);try{await n(l,f),o(""),d("")}catch(v){alert(v.message)}finally{p(!1)}}return r.jsxs("div",{className:"panel-section space-y-0.5 text-base",children:[r.jsx("p",{className:"text-sm text-slate-400",children:"Admin login"}),r.jsxs("form",{className:"flex flex-col gap-0.5",onSubmit:x,children:[r.jsx("input",{className:"field-input",placeholder:"Username",value:l,onChange:g=>o(g.target.value)}),r.jsx("input",{className:"field-input",placeholder:"Password",type:"password",value:f,onChange:g=>d(g.target.value)}),r.jsx("button",{type:"submit",disabled:h,className:"button-dark w-full disabled:opacity-50",children:h?"Logging in…":"Login"})]})]})}function fx(...n){return n.filter(Boolean).join(" ")}function uN(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function fN(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function dN({title:n,roster:s=[],emptyText:l="No roster data.",renderActions:o=null}){return r.jsxs("div",{className:"space-y-0.5 text-sm",children:[n&&r.jsx("p",{className:"text-sm text-slate-400",children:n}),s.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:l}):r.jsx("ul",{className:"space-y-0.5 text-sm",children:s.map(f=>{const d=!!(f?.private?.enabled&&f?.private?.open),h=!!f?.locked;return r.jsxs("li",{className:fx("surface flex flex-wrap items-center justify-between gap-0.5",h?"bg-red-900/40":d?"bg-amber-700/35 border border-amber-200/30":null),children:[r.jsxs("div",{children:[r.jsx("p",{className:"text-slate-200",children:r.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ca(f.color,.16),children:f.name})}),r.jsxs("p",{className:"text-xs text-slate-500 flex flex-wrap items-center gap-0.5",children:[r.jsx("span",{children:f.locked?"locked":"free"}),f.lockReason&&r.jsx("span",{className:"rounded bg-black/30 px-1",children:f.lockReason}),r.jsxs("span",{className:fx("font-semibold",fN(f)),children:["Battery ",uN(f)]})]})]}),o?o(f):null]},f.id)})})]})}const mN=[{key:"open",label:"Open"},{key:"turns",label:"Turns"},{key:"admin",label:"Admin"},{key:"lockdown",label:"Lockdown"}];function hN(){const{session:n,lockRover:s,setMode:l,requestControl:o,setCommunityGoal:f,setAdminReason:d,rebootRover:h,rebootServer:p,setAudioLevels:x,setPrivateSafety:g,llmControl:v,adminLogs:y,llmCommentaryState:S}=nn(),E=m.useMemo(()=>n?.roster??[],[n?.roster]),[C,k]=m.useState({}),[w,j]=m.useState({}),[N,T]=m.useState(!1),[M,O]=m.useState(!1),K=n?.health||null,_=n?.communityGoal?.text||"",U=n?.communityGoal?.updatedAt||null,[X,F]=m.useState(_),H=n?.adminReason?.text||"",te=n?.adminReason?.updatedAt||null,[ce,oe]=m.useState(H),V=n?.audioLevels||{},[q,L]=m.useState({hornGain:Number.isFinite(V.hornGain)?V.hornGain:1,ttsGain:Number.isFinite(V.ttsGain)?V.ttsGain:1,forwardGain:Number.isFinite(V.forwardGain)?V.forwardGain:1}),[Z,le]=m.useState({}),fe=n?.role==="admin"||n?.role==="lockdown"||n?.role==="lockdown-admin",R=n?.role==="lockdown"||n?.role==="lockdown-admin",$=n?.mode??"open",ee=async(se,P)=>{try{await s(se,P),k(de=>({...de,[se]:P}))}catch(de){alert(de.message)}},ae=async se=>{const P=se.target.value;try{await l(P)}catch(de){alert(de.message)}},pe=async se=>{try{await o(se,{force:!0})}catch(P){alert(P.message)}},re=async se=>{if(!(!se?.id||!window.confirm(`Reboot rover "${se.name||se.id}" now?`))){j(de=>({...de,[se.id]:!0}));try{await h(se.id)}catch(de){alert(de.message)}finally{j(de=>({...de,[se.id]:!1}))}}},ue=async()=>{if(window.confirm("Reboot the server host now? This will disconnect all users.")){T(!0);try{await p()}catch(P){alert(P.message),T(!1)}}},ve=async()=>{if(window.confirm("Clear LLM commentary history now? This resets chat context, bot memory, and rover activity metrics for narration.")){O(!0);try{await v("clearHistory")}catch(P){alert(P.message)}finally{O(!1)}}},be=async()=>{try{await f(X)}catch(se){alert(se.message)}},xe=async()=>{try{await f(null)}catch(se){alert(se.message)}},Be=async()=>{try{await d(ce)}catch(se){alert(se.message)}},ze=async()=>{try{await d(null)}catch(se){alert(se.message)}},Ae=se=>P=>{const de=Number(P.target.value);L(Ne=>({...Ne||{},[se]:Number.isFinite(de)?de:1}))},tt=async()=>{try{await x(q)}catch(se){alert(se.message)}},Je=async()=>{window.dispatchEvent(new CustomEvent("buttonBox:rewardRunLocalTest",{detail:{rewardName:"Admin Mode",count:1e3,goal:1e3}}))};m.useEffect(()=>{F(_)},[_]),m.useEffect(()=>{oe(H)},[H]),m.useEffect(()=>{L({hornGain:Number.isFinite(V.hornGain)?V.hornGain:1,ttsGain:Number.isFinite(V.ttsGain)?V.ttsGain:1,forwardGain:Number.isFinite(V.forwardGain)?V.forwardGain:1})},[V.forwardGain,V.hornGain,V.ttsGain]),m.useEffect(()=>{const se={};(E||[]).forEach(P=>{P?.private?.enabled&&(se[P.id]={speedLimitEnabled:!!P?.private?.safety?.speedLimitEnabled,speedLimitMaxWheelSpeed:Number.isFinite(P?.private?.safety?.speedLimitMaxWheelSpeed)?P.private.safety.speedLimitMaxWheelSpeed:250,hardOvercurrentEnabled:!!P?.private?.safety?.hardOvercurrentEnabled,overcurrentStopMs:Number.isFinite(P?.private?.safety?.overcurrentStopMs)?P.private.safety.overcurrentStopMs:300,hardBumpEnabled:!!P?.private?.safety?.hardBumpEnabled,bumpBackoffSpeed:Number.isFinite(P?.private?.safety?.bumpBackoffSpeed)?P.private.safety.bumpBackoffSpeed:250,bumpBackoffMs:Number.isFinite(P?.private?.safety?.bumpBackoffMs)?P.private.safety.bumpBackoffMs:350,cliffEnabled:!!P?.private?.safety?.cliffEnabled,cliffBackoffSpeed:Number.isFinite(P?.private?.safety?.cliffBackoffSpeed)?P.private.safety.cliffBackoffSpeed:250,cliffBackoffMs:Number.isFinite(P?.private?.safety?.cliffBackoffMs)?P.private.safety.cliffBackoffMs:500,triggerCooldownMs:Number.isFinite(P?.private?.safety?.triggerCooldownMs)?P.private.safety.triggerCooldownMs:800})}),le(se)},[E]);const vt=m.useMemo(()=>{const se={};return E.forEach(P=>{se[P.id]=C[P.id]??P.locked}),se},[E,C]),ie=(se,P={})=>{le(de=>({...de||{},[se]:{...de?.[se]||{},...P||{}}}))},me=async se=>{try{const P=Z?.[se];if(!P)return;await g(se,P)}catch(P){alert(P.message)}};return fe?r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5 text-sm",children:[r.jsx("span",{children:"Admin controls"}),r.jsx("select",{value:$,onChange:ae,className:"field-input text-sm",children:mN.map(se=>r.jsx("option",{value:se.key,children:se.label},se.key))})]}),r.jsxs("div",{className:"flex gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:ue,disabled:N,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:N?"Server rebooting...":"Reboot Server"}),r.jsx("button",{type:"button",onClick:Je,className:"button-dark",children:"Test Reward Popup"})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Global audio levels"}),n?.audioLevels?.updatedAt?r.jsxs("span",{children:["Updated ",new Date(n.audioLevels.updatedAt).toLocaleString()]}):null]}),r.jsxs("label",{className:"grid gap-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Horn gain"}),r.jsxs("span",{children:[q.hornGain.toFixed(2),"x"]})]}),r.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:q.hornGain,onChange:Ae("hornGain"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"grid gap-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"TTS gain"}),r.jsxs("span",{children:[q.ttsGain.toFixed(2),"x"]})]}),r.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:q.ttsGain,onChange:Ae("ttsGain"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"grid gap-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Forward gain"}),r.jsxs("span",{children:[q.forwardGain.toFixed(2),"x"]})]}),r.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:q.forwardGain,onChange:Ae("forwardGain"),className:"w-full accent-emerald-500"})]}),r.jsx("div",{className:"flex gap-0.5 text-xs",children:r.jsx("button",{type:"button",onClick:tt,className:"button-dark",children:"Apply audio levels"})})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Community goal"}),U?r.jsxs("span",{children:["Updated ",new Date(U).toLocaleString()]}):null]}),r.jsx("input",{type:"text",value:X,onChange:se=>F(se.target.value),placeholder:"Set a community goal",className:"field-input text-sm"}),r.jsxs("div",{className:"flex gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:be,className:"button-dark",children:"Set goal"}),r.jsx("button",{type:"button",onClick:xe,className:"button-danger",children:"Clear"})]})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Admin mode reason"}),te?r.jsxs("span",{children:["Updated ",new Date(te).toLocaleString()]}):null]}),r.jsx("textarea",{value:ce,onChange:se=>oe(se.target.value),placeholder:"Set an admin mode reason",className:"field-input text-sm min-h-[3.5rem]"}),r.jsxs("div",{className:"flex gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:Be,className:"button-dark",children:"Set reason"}),r.jsx("button",{type:"button",onClick:ze,className:"button-danger",children:"Clear"})]})]}),r.jsx(dN,{roster:E,renderActions:se=>r.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:()=>ee(se.id,!vt[se.id]),className:"button-dark",children:vt[se.id]?"Unlock":"Lock"}),r.jsx("button",{type:"button",onClick:()=>pe(se.id),className:"button-dark",children:"Force"}),r.jsx("button",{type:"button",onClick:()=>re(se),disabled:!!w[se.id],className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:w[se.id]?"Rebooting...":"Reboot"}),se?.private?.enabled?r.jsxs("div",{className:"w-full rounded border border-slate-700/70 p-0.5 space-y-0.5 text-[0.7rem]",children:[r.jsx("div",{className:"text-slate-300",children:"Private safety"}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!Z?.[se.id]?.speedLimitEnabled,disabled:!R,onChange:P=>ie(se.id,{speedLimitEnabled:!!P.target.checked})}),r.jsx("span",{children:"Speed limit"})]}),r.jsx("input",{type:"number",min:"1",max:"500",className:"field-input text-xs w-20",disabled:!R,value:Z?.[se.id]?.speedLimitMaxWheelSpeed??250,onChange:P=>ie(se.id,{speedLimitMaxWheelSpeed:Number(P.target.value)||250})}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!Z?.[se.id]?.hardOvercurrentEnabled,disabled:!R,onChange:P=>ie(se.id,{hardOvercurrentEnabled:!!P.target.checked})}),r.jsx("span",{children:"Hard overcurrent"})]}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!Z?.[se.id]?.hardBumpEnabled,disabled:!R,onChange:P=>ie(se.id,{hardBumpEnabled:!!P.target.checked})}),r.jsx("span",{children:"Hard bump"})]}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!Z?.[se.id]?.cliffEnabled,disabled:!R,onChange:P=>ie(se.id,{cliffEnabled:!!P.target.checked})}),r.jsx("span",{children:"Cliff safety"})]}),r.jsx("button",{type:"button",disabled:!R,onClick:()=>me(se.id),className:"button-dark disabled:opacity-50",children:"Apply Safety"})]}):null]})}),r.jsx(vN,{health:K,roster:E}),r.jsx(pN,{state:S,onClearHistory:ve,clearingHistory:M}),r.jsx(bN,{entries:y})]}):null}function pN({state:n,onClearHistory:s,clearingHistory:l}){const[o,f]=m.useState(null);if(!n)return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"LLM Commentary"}),r.jsx("div",{className:"surface text-xs text-slate-300",children:"No status received yet."})]});const d=n.runtime||{},h=n.counters||{},p=n.timings||{},x=n.input||{},g=n.output||{},v=n.errors||{},y=Array.isArray(n.history)?n.history:[],S=y.find(w=>w.runId===o)||(y.length?y[y.length-1]:null),E=xN(n),C=gN(x.modelMessages,g.raw),k=[{label:"running",value:d.running?"yes":"no"},{label:"in flight",value:d.inFlight?"yes":"no"},{label:"phase",value:d.phase||"--"},{label:"run id",value:d.currentRunId??"--"},{label:"tick count",value:d.tickCount??0},{label:"last tick",value:d.lastTickAt?new Date(d.lastTickAt).toLocaleString():"never"},{label:"next run",value:d.nextRunAt?new Date(d.nextRunAt).toLocaleString():"n/a"},{label:"outcome",value:d.outcome||"--"},{label:"reason",value:d.reason||"--"},{label:"skip streak",value:h.skipStreak??0},{label:"clear count",value:h.clearCount??0},{label:"last gen",value:p.lastGenerationMs!=null?`${p.lastGenerationMs} ms`:"--"},{label:"avg gen",value:p.avgGenerationMs!=null?`${p.avgGenerationMs} ms`:"--"},{label:"gen count",value:p.generationCount??0},{label:"prompt chars",value:h.promptChars??0},{label:"active drivers",value:h.snapshotSummary?.activeDrivers??0},{label:"snapshot rovers",value:h.snapshotSummary?.rovers??0},{label:"snapshot chat",value:h.snapshotSummary?.chatMessages??0}];return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"LLM Commentary"}),r.jsx("div",{className:"flex gap-0.5 text-xs",children:r.jsx("button",{type:"button",onClick:s,disabled:!!l,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:l?"Clearing...":"Clear LLM History"})}),r.jsxs("div",{className:`surface border text-center ${E.className}`,children:[r.jsx("div",{className:"text-[1.1rem] font-bold tracking-wide",children:E.label}),r.jsx("div",{className:"text-xs text-slate-200",children:E.detail})]}),r.jsx("div",{className:"surface flex flex-wrap gap-0.5 text-xs",children:k.map(w=>r.jsxs("span",{className:"rounded border border-slate-600/60 bg-slate-800/70 px-0.5 py-0.25 text-[0.72rem] leading-tight text-slate-200",children:[w.label,": ",w.value]},w.label))}),v.message?r.jsxs("div",{className:"surface text-xs text-red-300 break-words",children:["Error: ",v.message]}):null,v.details?r.jsxs("details",{className:"surface text-xs text-red-200",children:[r.jsx("summary",{className:"cursor-pointer select-none text-red-300",children:"Failure details"}),r.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-red-200",children:JSON.stringify(v.details,null,2)})]}):null,g.generated?r.jsxs("div",{className:"surface text-xs text-slate-200 break-words",children:["Generated: ",g.generated]}):null,g.posted?r.jsxs("div",{className:"surface text-xs text-emerald-200 break-words",children:["Posted: ",g.posted]}):null,r.jsxs("div",{className:"grid gap-0.5 md:grid-cols-2",children:[r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"Live Input Conversation"}),r.jsx("div",{className:"surface max-h-72 space-y-0.5 overflow-y-auto",children:C.length?C.map(w=>r.jsx(ld,{message:w.message},w.id)):r.jsx("div",{className:"text-xs text-slate-300",children:"No model conversation captured yet."})})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"Output + Error"}),r.jsxs("div",{className:"surface space-y-0.5 text-xs text-slate-200",children:[r.jsxs("div",{children:["Raw output: ",g.raw?.trim()?g.raw:""]}),r.jsxs("div",{children:["Posted: ",g.posted||""]}),r.jsxs("div",{children:["Output at:"," ",g.modelOutputAt?new Date(g.modelOutputAt).toLocaleString():"n/a"]}),r.jsxs("div",{children:["Failed at: ",v.failedAt?new Date(v.failedAt).toLocaleString():"n/a"]})]})]})]}),r.jsxs("details",{className:"surface text-xs text-slate-200",children:[r.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Full Monitor Payload"}),r.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(n,null,2)})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"Recent Runs"}),r.jsx("div",{className:"surface max-h-52 space-y-0.5 overflow-y-auto text-xs",children:y.length?y.slice().reverse().map(w=>r.jsxs("button",{type:"button",onClick:()=>f(w.runId),className:`w-full text-left surface ${S?.runId===w.runId?"border border-sky-400/50":""}`,children:[r.jsxs("span",{className:"text-slate-300",children:["#",w.runId]})," ",r.jsx("span",{className:"text-slate-200",children:w.outcome||w.phase||"--"})," ",r.jsx("span",{className:"text-slate-400",children:w.durationMs!=null?`${w.durationMs}ms`:"--"})," ",r.jsx("span",{className:"text-slate-500",children:w.reason||""})]},w.runId)):r.jsx("div",{className:"text-slate-300",children:"No runs recorded yet."})})]}),S?r.jsxs("details",{className:"surface text-xs text-slate-200",open:!0,children:[r.jsxs("summary",{className:"cursor-pointer select-none text-slate-300",children:["Run #",S.runId," details"]}),r.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(S,null,2)})]}):null]})}function xN(n){const s=n?.runtime||{},l=n?.output||{},o=n?.errors||{};return s.inFlight?{label:"IN FLIGHT",detail:s.reason||"Generating commentary now",className:"border-amber-400/60 bg-amber-700/20 text-amber-200"}:s.outcome==="posted"?{label:"POSTED",detail:l.posted?`Last: ${l.posted}`:"Commentary posted",className:"border-emerald-400/60 bg-emerald-700/20 text-emerald-200"}:s.outcome==="skipped"?{label:"SKIPPED",detail:s.reason||"Model chose to skip",className:"border-slate-400/60 bg-slate-700/30 text-slate-200"}:s.outcome==="failed"?{label:"FAILED",detail:o.message||s.reason||"Tick failed",className:"border-red-400/60 bg-red-700/20 text-red-200"}:{label:s.running?"IDLE":"STOPPED",detail:s.reason||"Waiting for next tick",className:"border-sky-400/50 bg-sky-700/20 text-sky-200"}}function gN(n,s){const l=Date.now(),f=(Array.isArray(n)?n:[]).map((d,h)=>{const p=String(d?.role||"").toLowerCase(),x=typeof d?.content=="string"?d.content:JSON.stringify(d?.content??null,null,2),g=p==="system"?"LLM System":p==="assistant"?"LLM Context":p==="user"?"LLM Input":"LLM Message";return{id:`llm-msg-${h}`,message:{ts:l+h,nickname:g,text:x,role:"spectator",system:p==="system"}}});if(s!=null){const d=String(s);f.push({id:"llm-output",message:{ts:l+f.length+1,nickname:"LLM Output",text:d.trim()?d:"",role:"spectator",system:!0}})}return f}function vN({health:n,roster:s=[]}){if(!n)return null;const l=n.replay||{sources:[],readyCount:0,totalCount:0},o=n.snapshots||{rovers:[],rooms:[]},f=x=>s.find(g=>String(g.id)===String(x))?.color||null,d=`${l.readyCount}/${l.totalCount} sources ready`,h=o.rovers.filter(x=>x.stale).length,p=o.rooms.filter(x=>x.stale).length;return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"Health"}),r.jsxs("div",{className:"surface space-y-0.5 text-xs text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:"Replay segments"}),r.jsx("span",{className:"text-slate-400",children:d})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:"Rover snapshots"}),r.jsxs("span",{className:h?"text-amber-300":"text-emerald-300",children:[o.rovers.length-h,"/",o.rovers.length," ok"]})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:"Room cameras"}),r.jsxs("span",{className:p?"text-amber-300":"text-emerald-300",children:[o.rooms.length-p,"/",o.rooms.length," ok"]})]})]}),r.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:l.sources.map(x=>r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{className:`${x.type==="rover"?"rounded px-1 py-[1px] border border-transparent":""}`,style:x.type==="rover"?ca(f(x.id),.16):void 0,children:x.label}),r.jsxs("span",{className:x.ready?"text-emerald-300":"text-amber-300",children:[x.recentCount,"/",x.neededCount]})]},`${x.type}:${x.id}`))}),r.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:o.rovers.map(x=>r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ca(f(x.id),.16),children:x.name}),r.jsx("span",{className:x.stale?"text-amber-300":"text-emerald-300",children:x.stale?"stale":"ok"})]},`rover:${x.id}`))}),r.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:o.rooms.map(x=>r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:x.name}),r.jsx("span",{className:x.stale?"text-amber-300":"text-emerald-300",children:x.error?"error":x.stale?"stale":"ok"})]},`room:${x.id}`))})]})}function bN({entries:n}){const s=n||[];return r.jsxs("div",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"flex items-center justify-between text-sm text-slate-400",children:[r.jsx("span",{children:"Admin IP log"}),r.jsx("span",{children:s.length})]}),r.jsx("div",{className:"surface h-64 overflow-y-auto font-mono text-xs",children:s.length===0?r.jsx("p",{children:"No admin log entries yet."}):s.slice().reverse().map(l=>r.jsxs("div",{className:"surface",children:[r.jsx("span",{className:"text-amber-400",children:l.ts?new Date(l.ts).toLocaleTimeString():"--"})," ",l.label&&r.jsxs("span",{className:"text-teal-400",children:["[",l.label,"]"]})," ",r.jsx("span",{className:"text-slate-200",children:l.message})," ",l.ip&&r.jsx("span",{className:"text-cyan-300",children:l.ip})," ",l.meta&&r.jsx("span",{className:"text-slate-500",children:JSON.stringify(l.meta)})]},l.id))}),r.jsx("p",{className:"text-xs text-slate-500",children:"Admin-only log stream; IPs never appear in user data."})]})}const yN=[{id:"driveForward",label:"Drive Forward",group:"Driving"},{id:"driveBackward",label:"Drive Backward",group:"Driving"},{id:"driveLeft",label:"Turn Left",group:"Driving"},{id:"driveRight",label:"Turn Right",group:"Driving"},{id:"boostModifier",label:"Boost Modifier",group:"Driving"},{id:"slowModifier",label:"Slow Modifier",group:"Driving"},{id:"auxMainForward",label:"Main Brush Forward",group:"Aux Motors"},{id:"auxMainReverse",label:"Main Brush Reverse",group:"Aux Motors"},{id:"auxSideForward",label:"Side Brush Forward",group:"Aux Motors"},{id:"auxSideReverse",label:"Side Brush Reverse",group:"Aux Motors"},{id:"auxVacuumFast",label:"Vacuum Max",group:"Aux Motors"},{id:"auxVacuumSlow",label:"Vacuum Low",group:"Aux Motors"},{id:"auxAllForward",label:"All Aux Forward",group:"Aux Motors"},{id:"cameraUp",label:"Camera Up",group:"Camera"},{id:"cameraDown",label:"Camera Down",group:"Camera"},{id:"nightVisionToggle",label:"Toggle Night Vision",group:"Camera"},{id:"hornHonk",label:"Horn (Hold)",group:"Audio"},{id:"micPtt",label:"Mic Push To Talk",group:"Audio"},{id:"driveMacro",label:"Drive Macro",group:"Macros"},{id:"dockMacro",label:"Dock Macro",group:"Macros"},{id:"chatFocus",label:"Toggle Chat",group:"Chat"},{id:"songNoteUp",label:"Song Note Up",group:"Audio"},{id:"songNoteDown",label:"Song Note Down",group:"Audio"},{id:"homeAssistantOn",label:"Room Controls On (Cycle)",group:"Room Controls"},{id:"homeAssistantOff",label:"Room Controls Off (Cycle)",group:"Room Controls"}];function SN(n){return n.reduce((s,l)=>((s[l.group]||(s[l.group]=[])).push(l),s),{})}function jN(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(0,Math.min(500,l)):s}const gd=5,Ci=500,Ei=1,vd=100;function AN(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(gd,Math.min(Ci,l)):s}function fo(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(Ei,Math.min(vd,l)):s}function NN(n){const l=(fo(n,n)-Ei)/(vd-Ei),o=Ci-l*(Ci-gd);return Math.round(o)}function wN(n){const s=AN(n,n),l=(Ci-s)/(Ci-gd),o=Ei+l*(vd-Ei);return Math.round(o)}function CN(n){const[s,l]=m.useState(null),o=m.useCallback(h=>{lf(!0),l(h)},[]),f=m.useCallback(()=>{lf(!1),l(null)},[]),d=m.useCallback((h,p)=>{if(p.preventDefault(),p.stopPropagation(),p.key==="Escape"){f();return}const x=Di(p.key??"");x&&(n(h,x,p),f())},[f,n]);return m.useEffect(()=>()=>lf(!1),[]),{active:s,startCapture:o,cancel:f,captureFromEvent:d}}function eo({label:n,description:s,value:l,onChange:o,min:f=0,max:d=500,step:h=5}){return r.jsxs("label",{className:"surface-muted block p-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-300",children:[r.jsx("span",{className:"font-semibold text-slate-100",children:n}),r.jsx("input",{type:"number",min:f,max:d,value:l,onChange:p=>o(p.target.value),className:"w-16 rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-right text-[0.75rem] font-mono text-slate-100"})]}),s&&r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:s}),r.jsxs("div",{className:"mt-0 flex items-center gap-0.5",children:[r.jsx("input",{type:"range",min:f,max:d,step:h,value:l,onChange:p=>o(p.target.value),className:"h-2 flex-1 accent-emerald-400"}),r.jsx("span",{className:"w-12 text-right text-[0.75rem] font-mono text-slate-400",children:l})]})]})}function EN(){const{state:{keymap:n},actions:{updateKeyBinding:s,resetKeyBindings:l}}=_t(),{value:o,save:f}=He("inputs",qn),d={...qn.keyboard,...o.keyboard??{}},h=m.useMemo(()=>typeof d.tiltSpeed=="number"?fo(d.tiltSpeed,qn.keyboard.tiltSpeed):typeof d.tiltIntervalMs=="number"?fo(wN(d.tiltIntervalMs),qn.keyboard.tiltSpeed):qn.keyboard.tiltSpeed,[d.tiltIntervalMs,d.tiltSpeed]),p=m.useMemo(()=>SN(yN),[]),{active:x,startCapture:g,cancel:v,captureFromEvent:y}=CN((k,w)=>{s(k,w)}),S=m.useCallback(k=>n?.[k]?.[0]||gi[k]?.[0]||"",[n]),E=m.useCallback((k,w)=>{const j=qn.keyboard,N=jN(w,j[k]);f(T=>({...T??{},keyboard:{...T?.keyboard??j,[k]:N}}))},[f]),C=m.useCallback(k=>{const w=qn.keyboard,j=fo(k,w.tiltSpeed),N=NN(j);f(T=>({...T??{},keyboard:{...T?.keyboard??w,tiltSpeed:j,tiltIntervalMs:N}}))},[f]);return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Keyboard layout"}),r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Per-browser · click to change a binding"})]}),r.jsx("button",{type:"button",onClick:()=>l(),className:"button-dark text-xs",children:"Reset defaults"})]}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Keyboard speeds"}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(eo,{label:"Base speed",description:"Normal driving speed",value:d.baseSpeed,onChange:k=>E("baseSpeed",k)}),r.jsx(eo,{label:"Turbo speed",description:"Used when holding the boost modifier",value:d.turboSpeed,onChange:k=>E("turboSpeed",k)}),r.jsx(eo,{label:"Precision speed",description:"Used when holding the precision modifier",value:d.precisionSpeed,onChange:k=>E("precisionSpeed",k)})]})]}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Camera tilt"}),r.jsx(eo,{label:"Tilt speed",description:"Higher = faster when holding tilt keys",value:h,onChange:C,min:1,max:100,step:1})]}),r.jsx("div",{className:"space-y-0.5",children:Object.entries(p).map(([k,w])=>r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.75rem] text-slate-400",children:k}),r.jsx("div",{className:"space-y-0.5",children:w.map(j=>{const N=S(j.id),T=x===j.id;return r.jsxs("div",{className:"surface-muted flex items-center justify-between text-xs",children:[r.jsxs("div",{children:[r.jsx("p",{className:"font-semibold text-slate-100",children:j.label}),r.jsx("p",{className:"text-[0.65rem] text-slate-400",children:An(N)})]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[T&&r.jsx("button",{type:"button",onClick:()=>v(),className:"button-danger text-[0.7rem]",children:"Cancel"}),r.jsx("button",{type:"button",onClick:()=>g(j.id),onKeyDown:T?M=>y(j.id,M):void 0,autoFocus:T,className:`${T?"px-0.5 py-0.5 bg-emerald-500 text-emerald-950 hover:bg-emerald-400":"button-dark"} text-[0.7rem] font-medium transition-colors`,children:T?"Press a key…":"Change"})]})]},j.id)})})]},k))})]})}const la=new Intl.NumberFormat(void 0,{maximumFractionDigits:2}),kN=[{id:"drive",label:"Drive stick",kind:"axisPair",section:"Driving",invertDefaults:{invertX:!1,invertY:!0}},{id:"cameraTilt",label:"Camera tilt",kind:"axis",section:"Camera",invertDefaults:{invert:!0}},{id:"mainBrush",label:"Main brush",kind:"axis",section:"Brushes",invertDefaults:{invert:!1}},{id:"sideBrush",label:"Side brush",kind:"axis",section:"Brushes",invertDefaults:{invert:!1}},{id:"vacuum",label:"Vacuum",kind:"button",section:"Aux buttons"},{id:"allAux",label:"All aux",kind:"button",section:"Aux buttons"},{id:"mainReverse",label:"Main reverse toggle",kind:"button",section:"Brush toggles"},{id:"sideReverse",label:"Side reverse toggle",kind:"button",section:"Brush toggles"},{id:"driveMacro",label:"Drive macro",kind:"button",section:"Mode macros"},{id:"dockMacro",label:"Dock macro",kind:"button",section:"Mode macros"},{id:"nightVisionToggle",label:"Night vision toggle",kind:"button",section:"Camera"}],dx=.45,MN=.6;function mi({label:n,description:s,min:l,max:o,step:f,value:d,onChange:h}){return r.jsxs("label",{className:"surface-muted block p-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-300",children:[r.jsx("span",{className:"font-semibold text-slate-100",children:n}),r.jsx("span",{className:"font-mono text-slate-400",children:la.format(d)})]}),s&&r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:s}),r.jsx("input",{type:"range",min:l,max:o,step:f,value:d,onChange:p=>h(Number(p.target.value)),className:"mt-0 w-full accent-emerald-400"})]})}function RN(n){if(!n)return"Unassigned";if(n.kind==="axisPair"){const s=`${n.invertX?"X inv ":""}${n.invertY?"Y inv":""}`.trim();return`Axes ${n.x}/${n.y}${s?` (${s})`:""}`}if(n.kind==="axis")return`Axis ${n.index}${n.invert?" (inv)":""}`;if(n.kind==="button")return`Button ${n.index}`;if(n.kind==="buttonAxis")return`Button ${n.index} (analog)`;if(n.kind==="axisButton"){const s=n.direction<0?"<":">";return`Axis ${n.index} ${s} ${la.format(n.threshold??.6)}`}return"Unassigned"}function qN(n){return n.reduce((s,l)=>((s[l.section]||(s[l.section]=[])).push(l),s),{})}function TN(n,s){if(!n||n.length===0)return null;if(s){const l=n.find(o=>o.signature===s);if(l)return l}return n[0]}function DN(n){return{axes:Array.from(n.axes??[]),buttons:(n.buttons??[]).map(s=>({pressed:!!s?.pressed,value:typeof s?.value=="number"?s.value:s?.pressed?1:0}))}}function _N(n,s,l){const o=(n.axes??[]).map((d,h)=>({index:h,delta:Math.abs((d??0)-(s.axes?.[h]??0)),value:d}));if(o.sort((d,h)=>h.delta-d.delta),l.kind==="axisPair"){const d=o.filter(h=>h.delta>dx).slice(0,2);return d.length<2?null:{kind:"axisPair",x:d[0].index,y:d[1].index,...l.invertDefaults??{}}}const f=o.find(d=>d.delta>dx);return f?{kind:"axis",index:f.index,...l.invertDefaults??{}}:null}function BN(n,s,l){const o=n.buttons??[];for(let d=0;dMN)return l.kind==="axis"?{kind:"buttonAxis",index:d}:{kind:"button",index:d}}const f=n.axes??[];for(let d=0;d.7&&p>.5)return l.kind==="axis"?{kind:"axis",index:d,...l.invertDefaults??{}}:{kind:"axisButton",index:d,direction:h>=0?1:-1,threshold:.6}}return null}function ON(n,s,l){if(!n)return null;if(l.kind==="axis"||l.kind==="axisPair"){const o=_N(n,s,l);if(o)return o}return BN(n,s,l)}function LN(){const n=dA(),{value:s,save:l}=He("gamepad",Ba),[o,f]=m.useState(null),d=m.useRef(null),h=m.useMemo(()=>qN(kN),[]),p=m.useMemo(()=>TN(n.pads,s.activeSignature),[n.pads,s.activeSignature]),x=p?.signature??null,g=m.useMemo(()=>x?s?.profiles?.[x]??s?.defaults?.profile??ia:s?.defaults?.profile??ia,[x,s?.defaults?.profile,s?.profiles]);m.useEffect(()=>{!p||!x||s?.profiles?.[x]||l(w=>{const j=w??Ba;if(j.profiles?.[x])return j;const N=j?.defaults?.profile??ia,T=wg(p,N);return{...j,profiles:{...j.profiles??{},[x]:T}}})},[p,x,s?.profiles,l]),m.useEffect(()=>{d.current=null},[o,x]),m.useEffect(()=>{if(!o||!p)return;if(!d.current){d.current=DN(p);return}const w=ON(p,d.current,o);w&&(l(j=>{const N=j??Ba,T=N.profiles?.[x]??N?.defaults?.profile??ia,M={...T,bindings:{...T.bindings??{},[o.id]:{...T.bindings?.[o.id]??{},kind:o.kind,sources:[w]}}};return{...N,profiles:{...N.profiles??{},[x]:M}}}),f(null))},[p,x,o,l]);const v=m.useCallback(w=>{l(j=>({...j??Ba,activeSignature:w||null}))},[l]),y=m.useCallback(w=>{l(j=>{const N=j??Ba,T=(x&&N.profiles?.[x])??N?.defaults?.profile??ia,M={...T,calibration:{...T.calibration??{},...w}};return x?{...N,profiles:{...N.profiles??{},[x]:M}}:{...N,defaults:{...N.defaults??{},profile:M}}})},[x,l]),S=m.useCallback((w,j)=>{l(N=>{const T=N??Ba,M=(x&&T.profiles?.[x])??T?.defaults?.profile??ia,O=j(M.bindings?.[w]??{}),K={...M,bindings:{...M.bindings??{},[w]:O}};return x?{...T,profiles:{...T.profiles??{},[x]:K}}:{...T,defaults:{...T.defaults??{},profile:K}}})},[x,l]),E=m.useCallback(w=>{S(w.id,j=>({...j,sources:[]}))},[S]),C=m.useCallback((w,j)=>{S(w.id,N=>{const T=Array.isArray(N.sources)?[...N.sources]:[];if(!T[0])return N;const M={...T[0]};return j==="invertX"?M.invertX=!M.invertX:j==="invertY"?M.invertY=!M.invertY:M.invert=!M.invert,T[0]=M,{...N,sources:T}})},[S]),k=m.useMemo(()=>p?{outputs:Cg(p,g)}:null,[p,g]);return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("div",{className:"flex items-center justify-between",children:r.jsxs("div",{children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Controller"}),r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:p?"Move sticks or press buttons to bind":"Connect a controller to configure."}),o&&r.jsxs("p",{className:"mt-0 text-[0.7rem] text-emerald-400",children:["Capturing ",o.label,"…"]})]})}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Connected controller"}),n.pads.length===0?r.jsx("p",{className:"text-[0.7rem] text-slate-400",children:"No controller detected."}):r.jsxs("div",{className:"flex items-center justify-between gap-0.5 text-xs",children:[r.jsx("select",{value:x??"",onChange:w=>v(w.target.value),className:"flex-1 rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.75rem] text-slate-100",children:n.pads.map(w=>r.jsx("option",{value:w.signature,children:w.id||"Unknown controller"},w.signature))}),r.jsx("span",{className:"text-[0.7rem] text-slate-400",children:p?.mapping??"unknown"})]})]}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Calibration"}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(mi,{label:"Drive deadzone",description:"Ignore small drive stick drift",min:0,max:.6,step:.01,value:g.calibration?.driveDeadzone??.18,onChange:w=>y({driveDeadzone:w})}),r.jsx(mi,{label:"Camera deadzone",description:"Ignore small camera tilt drift",min:0,max:.4,step:.01,value:g.calibration?.cameraDeadzone??.08,onChange:w=>y({cameraDeadzone:w})}),r.jsx(mi,{label:"Aux deadzone",description:"Ignore small trigger noise",min:0,max:.4,step:.01,value:g.calibration?.auxDeadzone??.05,onChange:w=>y({auxDeadzone:w})}),r.jsx(mi,{label:"Side brush scale",description:"Scale side brush output",min:.3,max:1,step:.05,value:g.calibration?.auxSideScale??.55,onChange:w=>y({auxSideScale:w})}),r.jsxs("label",{className:"surface-muted block p-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-300",children:[r.jsx("span",{className:"font-semibold text-slate-100",children:"Camera mode"}),r.jsxs("select",{value:g.calibration?.cameraMode??"absolute",onChange:w=>y({cameraMode:w.target.value}),className:"rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.75rem] text-slate-100",children:[r.jsx("option",{value:"absolute",children:"Absolute"}),r.jsx("option",{value:"velocity",children:"Velocity"})]})]}),r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:"Absolute maps stick to angle; velocity moves over time."})]}),r.jsx(mi,{label:"Camera sensitivity",description:"Velocity mode degrees per second",min:10,max:180,step:5,value:g.calibration?.cameraSensitivity??60,onChange:w=>y({cameraSensitivity:w})})]})]}),r.jsx("div",{className:"space-y-0.5",children:Object.entries(h).map(([w,j])=>r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:w}),r.jsx("div",{className:"space-y-0.5",children:j.map(N=>{const M=g.bindings?.[N.id]?.sources?.[0]??null;return r.jsxs("div",{className:"surface-muted flex items-center justify-between text-xs",children:[r.jsxs("div",{children:[r.jsx("p",{className:"font-semibold text-slate-100",children:N.label}),r.jsx("p",{className:"text-[0.65rem] text-slate-400",children:RN(M)})]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[N.kind==="axisPair"&&r.jsxs(r.Fragment,{children:[r.jsx("button",{type:"button",disabled:!M,onClick:()=>C(N,"invertX"),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert X"}),r.jsx("button",{type:"button",disabled:!M,onClick:()=>C(N,"invertY"),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert Y"})]}),N.kind==="axis"&&r.jsx("button",{type:"button",disabled:!M,onClick:()=>C(N),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert"}),r.jsx("button",{type:"button",onClick:()=>E(N),className:"button-dark text-[0.7rem]",children:"Clear"}),r.jsx("button",{type:"button",onClick:()=>f(N),className:`${o?.id===N.id?"px-0.5 py-0.5 bg-emerald-500 text-emerald-950 hover:bg-emerald-400":"button-dark"} text-[0.7rem] font-medium`,children:o?.id===N.id?"Waiting…":"Capture"})]})]},N.id)})})]},w))}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Diagnostics"}),p?r.jsxs("div",{className:"space-y-0.5 text-[0.7rem] text-slate-300",children:[r.jsx("p",{className:"text-slate-400",children:"Raw axes"}),r.jsx("div",{className:"grid grid-cols-2 gap-0.5",children:p.axes.map((w,j)=>r.jsxs("span",{className:"font-mono text-slate-300",children:["A",j,": ",la.format(w)]},`axis-${j}`))}),r.jsx("p",{className:"text-slate-400",children:"Raw buttons"}),r.jsx("div",{className:"grid grid-cols-2 gap-0.5",children:p.buttons.map((w,j)=>r.jsxs("span",{className:"font-mono text-slate-300",children:["B",j,": ",la.format(w.value)," ",w.pressed?"●":""]},`btn-${j}`))}),k?.outputs&&r.jsxs(r.Fragment,{children:[r.jsx("p",{className:"text-slate-400",children:"Mapped outputs"}),r.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[r.jsxs("span",{className:"font-mono text-slate-300",children:["Drive: ",la.format(k.outputs.driveVector.x),","," ",la.format(k.outputs.driveVector.y)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Camera: ",la.format(k.outputs.cameraAxis)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Main: ",la.format(k.outputs.auxAxis.main)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Side: ",la.format(k.outputs.auxAxis.side)]})]})]})]}):r.jsx("p",{className:"text-[0.7rem] text-slate-400",children:"No controller detected."})]})]})}const zN={drive:"Drive wheels",aux:"Aux motors"};function mx(n){return Number.isFinite(n)?`${Math.round(n*100)}%`:"--"}function UN({value:n,color:s="bg-emerald-500"}){const l=`${Math.round(Math.max(0,Math.min(1,n))*100)}%`;return r.jsx("div",{className:"h-2 w-full overflow-hidden rounded bg-slate-800",children:r.jsx("div",{className:`h-full ${s}`,style:{width:l}})})}function HN(){const{state:{roverId:n},overcurrentLimiter:s}=_t(),l=m.useMemo(()=>os.map(o=>o.key),[]);return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Overcurrent limiter"}),r.jsx("span",{children:s?.adminImmune?"Admin immune":"Active"})]}),n?r.jsxs("div",{className:"space-y-0.5",children:[l.map(o=>{const f=s?.caps?.[o]?.cap??0,d=s?.overcurrent?.groups?.[o]??!1,h=s?.scales?.perGroup?.[o]??1;return r.jsxs("div",{className:"surface space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs",children:[r.jsx("span",{className:"text-slate-200",children:zN[o]||o}),r.jsx("span",{className:d?"text-red-300":"text-slate-400",children:d?"overcurrent":"ok"})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-[0.7rem] text-slate-400",children:[r.jsx("span",{children:"Cap"}),r.jsx("span",{children:mx(f)})]}),r.jsx(UN,{value:f,color:"bg-amber-500"}),r.jsxs("div",{className:"flex items-center justify-between text-[0.7rem] text-slate-400",children:[r.jsx("span",{children:"Scale"}),r.jsx("span",{children:mx(h)})]})]})]},o)}),r.jsxs("div",{className:"surface text-[0.7rem] text-slate-400",children:[r.jsx("div",{children:`Down rate ${s?.config?.downRatePerSec}/s · Up rate ${s?.config?.upRatePerSec}/s`}),r.jsx("div",{children:`Release delay ${s?.config?.releaseDelaySec}s`}),r.jsx("div",{children:`Output rate ${s?.config?.outputRateMs}ms`})]})]}):r.jsx("p",{className:"text-xs text-slate-500",children:"Assign a rover to view limiter status."})]})}const $g=m.createContext(null);function Gg(){const n=m.useContext($g);if(!n)throw new Error("Tabs components must be used within a provider.");return n}const hx={primary:{base:"flex-1 px-0.5 py-0.5 text-sm font-medium focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-1 focus-visible:outline-slate-500 rounded-md border border-slate-800",active:"bg-sky-600 text-white border-white",inactive:"bg-zinc-900 text-slate-300 hover:bg-sky-500 hover:text-white"}},px={none:"",pink:"bg-pink-500 text-white border-pink-200 hover:bg-pink-400",green:"bg-emerald-500 text-white border-emerald-200 hover:bg-emerald-400"},Yg="primary";function bd(...n){return n.filter(Boolean).join(" ")}function yd({children:n,defaultTab:s,currentTab:l,onTabChange:o,variant:f=Yg}){const[d,h]=m.useState(s??null),[p,x]=m.useState([]),g=m.useCallback(E=>E?(x(C=>C.includes(E)?C:[...C,E]),()=>x(C=>C.includes(E)?C.filter(k=>k!==E):C)):()=>{},[]),v=l??d??p[0]??null;m.useEffect(()=>{s&&l===void 0&&h(s)},[s,l]);const y=m.useCallback(E=>{E&&(l===void 0&&h(E),o&&o(E))},[l,o]),S=m.useMemo(()=>({activeTab:v,setActiveTab:y,registerTab:g,variant:f}),[v,y,g,f]);return r.jsx($g.Provider,{value:S,children:n})}function Sd({children:n,className:s=""}){return r.jsx("div",{className:bd("flex gap-0.5",s),children:n})}function Wt({id:n,children:s,className:l="",disabled:o=!1,highlight:f="none"}){const{activeTab:d,setActiveTab:h,registerTab:p,variant:x}=Gg();m.useEffect(()=>p(n),[n,p]);const g=hx[x]??hx[Yg],v=d===n,y=px[f]||px.none,S=bd(g.base,y||(v?g.active:g.inactive),o?"cursor-not-allowed opacity-50":"",l);return r.jsx("button",{type:"button",className:S,onClick:()=>!o&&h(n),"aria-pressed":v,"aria-disabled":o,children:s})}function jd({children:n,className:s=""}){return r.jsx("div",{className:bd("mt-0 space-y-0.5",s),children:n})}function en({id:n,children:s,keepMounted:l=!1}){const{activeTab:o}=Gg(),f=o===n;return!f&&!l?null:!f&&l?r.jsx("div",{hidden:!0,"aria-hidden":"true",children:s}):r.jsx(r.Fragment,{children:s})}function VN(){const{session:n}=nn(),s=m.useMemo(()=>JSON.stringify(n??{},null,2),[n]);return r.jsxs("div",{className:"panel-section flex min-h-0 flex-col gap-0.5 text-xs",children:[r.jsx("p",{className:"text-sm text-slate-400",children:"Session snapshot"}),r.jsx("pre",{className:"surface min-h-0 flex-1 overflow-y-auto font-mono text-[0.7rem] text-lime-300",children:s})]})}const xx=300,gx=240;function $N(n,s){if(n===void 0)return"undefined";if(n===null)return"null";if(typeof n=="string")return n;if(typeof n=="number"||typeof n=="boolean")return String(n);if(typeof n=="function")return"[Function]";if(n instanceof Error)return`${n.name}: ${n.message}`;if(n instanceof Date)return n.toISOString();if(s||(s=new WeakSet),typeof n=="object"){if(s.has(n))return"[Circular]";s.add(n)}try{return JSON.stringify(n,(l,o)=>typeof o=="function"?"[Function]":o instanceof Error?`${o.name}: ${o.message}`:o,0)}catch{return String(n)}}function GN(n){const l=n.map(o=>$N(o)).join(" ");return l.length>gx?`${l.slice(0,gx)}…`:l}function YN(){const n=tn(),[s,l]=m.useState([]),o=m.useMemo(()=>s.reduce((f,d)=>(d.direction==="in"&&(f.in+=1),d.direction==="out"&&(f.out+=1),f),{in:0,out:0}),[s]);return m.useEffect(()=>{const f=(x,g,v)=>{l(y=>{const S=[...y,{id:`${Date.now()}-${Math.random().toString(16).slice(2)}`,direction:x,event:g,payload:GN(v),timestamp:new Date().toLocaleTimeString()}];return S.length>xx?S.slice(-xx):S})},d=(x,...g)=>f("in",x,g),h=(x,...g)=>f("out",x,g);n.onAny(d);let p=null;if(typeof n.onAnyOutgoing=="function")n.onAnyOutgoing(h),p=()=>n.offAnyOutgoing(h);else{const x=n.emit.bind(n);n.emit=(g,...v)=>(h(g,...v),x(g,...v)),p=()=>{n.emit=x}}return()=>{n.offAny(d),p&&p()}},[n]),r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"flex items-center justify-between text-sm text-slate-400",children:[r.jsx("span",{children:"Socket activity"}),r.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-400",children:[r.jsxs("span",{className:"surface-muted",children:["in ",o.in]}),r.jsxs("span",{className:"surface-muted",children:["out ",o.out]}),r.jsx("button",{type:"button",className:"button-dark text-xs",onClick:()=>l([]),children:"Clear"})]})]}),r.jsx("div",{className:"surface h-64 overflow-y-auto font-mono text-xs",children:s.length===0?r.jsx("p",{children:"No socket activity yet."}):s.slice().reverse().map(f=>r.jsxs("div",{className:"surface",children:[r.jsx("span",{className:"text-slate-400",children:f.timestamp})," ",r.jsxs("span",{className:f.direction==="in"?"text-emerald-400":"text-amber-400",children:["[",f.direction.toUpperCase(),"]"]})," ",r.jsx("span",{className:"text-cyan-300",children:f.event})," ",r.jsx("span",{className:"text-slate-200",children:f.payload})]},f.id))}),r.jsx("p",{className:"text-xs text-slate-500",children:"Logs are collected only while this panel is open."})]})}const FN=[{key:"start",label:"Start OI"},{key:"safe",label:"Safe"},{key:"full",label:"Full"},{key:"passive",label:"Passive"},{key:"dock",label:"Dock"}];function Fg(){const{state:{roverId:n},actions:{sendOiCommand:s,setSensorStream:l}}=_t(),o=!!n,[f,d]=Lg(),h=tn(),{value:p,save:x}=He("page",{hudMapDesktop:!1,connectionTransport:"websocket",swapMobileControlColumns:!1,driveMacroBackoffEnabled:!0}),{value:g,save:v}=He("audio",ct),y=p?.connectionTransport||"websocket",S=!!p?.swapMobileControlColumns,E=typeof p?.driveMacroBackoffEnabled=="boolean"?p.driveMacroBackoffEnabled:!0,C=Number.isFinite(g?.masterVolume)?g.masterVolume:ct.masterVolume,k=Number.isFinite(g?.alertVolume)?g.alertVolume:ct.alertVolume,w=Number.isFinite(g?.roverVolume)?g.roverVolume:ct.roverVolume,j=typeof g?.mainBrushDuckEnabled=="boolean"?g.mainBrushDuckEnabled:typeof g?.autoLevelEnabled=="boolean"?g.autoLevelEnabled:ct.mainBrushDuckEnabled,N=Number.isFinite(g?.mainBrushDuckAmount)?Math.max(0,Math.min(1,g.mainBrushDuckAmount)):ct.mainBrushDuckAmount,T=m.useMemo(()=>[{key:"start",label:"Enable stream",enable:!0},{key:"stop",label:"Disable stream",enable:!1}],[]),M=F=>{n&&l(F)},O=F=>{const H=F.target.value;x(te=>({...te??{},connectionTransport:H})),h?.io?.opts&&(h.io.opts.transports=H==="polling"?["polling"]:["websocket","polling"],h.disconnect(),h.connect())},K=F=>H=>{const te=Number(H.target.value),ce=Number.isFinite(te)?Math.max(0,Math.min(1,te)):0;v(oe=>({...oe??{},[F]:ce}))},_=F=>{const H=!!F.target.checked;v(te=>({...te??{},mainBrushDuckEnabled:H}))},U=F=>{const H=!!F.target.checked;x(te=>({...te??{},swapMobileControlColumns:H}))},X=F=>{const H=!!F.target.checked;x(te=>({...te??{},driveMacroBackoffEnabled:H}))};return r.jsxs(yd,{defaultTab:"keybindings",children:[r.jsxs(Sd,{children:[r.jsx(Wt,{id:"keybindings",children:"Keybindings"}),r.jsx(Wt,{id:"controller",children:"Controller"}),r.jsx(Wt,{id:"page",children:"Page settings"}),r.jsx(Wt,{id:"admin",children:"Admin"})]}),r.jsxs(jd,{children:[r.jsx(en,{id:"keybindings",children:r.jsx("div",{className:"space-y-0.5",children:r.jsx(EN,{})})}),r.jsx(en,{id:"controller",children:r.jsx("div",{className:"space-y-0.5",children:r.jsx(LN,{})})}),r.jsx(en,{id:"page",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"HUD"}),r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:f,onChange:F=>d(F.target.checked)}),r.jsx("span",{children:"Show top-down map in HUD (desktop)"})]}),r.jsx("p",{className:"text-xs text-slate-500",children:"Mobile HUD keeps the map on by default."})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Mobile controls"}),r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:S,onChange:U}),r.jsx("span",{children:"Swap control columns (put joystick on the left)"})]})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Macros"}),r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:E,onChange:X}),r.jsx("span",{children:"Enable backward bump in drive macro"})]})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Audio"}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Master volume"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(C*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:C,onChange:K("masterVolume"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Alert/page sounds"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(k*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:k,onChange:K("alertVolume"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Rover audio"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(w*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:w,onChange:K("roverVolume"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"flex items-center justify-between gap-0.5 text-slate-200",children:[r.jsx("span",{children:"Main brush ducking"}),r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:j,onChange:_})]}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Main brush duck amount"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(N*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:N,onChange:K("mainBrushDuckAmount"),className:"w-full accent-emerald-500",disabled:!j})]}),r.jsx("p",{className:"text-xs text-slate-500",children:"Lowers rover audio only while the main brush is running."})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Connection"}),r.jsxs("label",{className:"flex items-center justify-between gap-0.5 text-slate-200",children:[r.jsx("span",{children:"Transport"}),r.jsxs("select",{value:y,onChange:O,className:"field-input text-sm",children:[r.jsx("option",{value:"websocket",children:"WebSocket"}),r.jsx("option",{value:"polling",children:"Polling"})]})]}),r.jsx("p",{className:"text-xs text-slate-500",children:"Switching reconnects your session."})]})]})}),r.jsx(en,{id:"admin",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Manual OI commands"}),r.jsx("div",{className:"surface flex flex-wrap gap-0.5",children:FN.map(F=>r.jsx("button",{type:"button",onClick:()=>s(F.key),disabled:!o,className:"button-dark text-xs disabled:opacity-30",children:F.label},F.key))})]}),r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"Sensor stream"}),r.jsx("div",{className:"surface flex gap-0.5",children:T.map(F=>r.jsx("button",{type:"button",onClick:()=>M(F.enable),disabled:!o,className:"flex-1 button-dark text-xs disabled:opacity-30",children:F.label},F.key))}),!o&&r.jsx("p",{className:"text-xs text-slate-500",children:"Assign a rover to toggle streams."})]}),r.jsx(Vg,{}),r.jsx(HN,{}),r.jsx(hN,{}),r.jsx(VN,{}),r.jsx(YN,{})]})})]})]})}const vx={desktop:{main:[{type:"list",title:"Chat and nicknames",items:["Set a nickname in the user list panel, on the bottom left of the page below the rover video.",{segments:["Toggle chat focus with ",{action:"chatFocus"},". Press ",{action:"chatFocus"}," again to send."]}]},{type:"list",title:"Driving the rover",items:[{segments:['Press the "Start Driving" button onscreen, or press ',{action:"driveMacro"}," on your keyboard to put the rover into driving mode."]},"Refer to the controls for the controls for the rover."]},{type:"list",title:"Docking the rover",items:["Line up the rover to the dock, about a foot away, then:",{segments:['Press the "Dock and Charge" button onscreen, or press ',{action:"dockMacro"}," on your keyboard to start docking."]},"Wait for the rover to confirm it is docked and charging before leaving it unattended."]}],aside:[{type:"keyboard",title:"Keyboard controls",footnote:"Per-browser; adjust bindings and speeds in Settings → Keybindings.",groups:[{id:"movement",title:"Movement",items:[{action:"driveForward",label:"Forward"},{action:"driveBackward",label:"Backward"},{action:"driveLeft",label:"Turn left"},{action:"driveRight",label:"Turn right"},{action:"boostModifier",label:"Boost speed"},{action:"slowModifier",label:"Precision speed"}]},{id:"macros",title:"Rover modes & chat",items:[{action:"driveMacro",label:"Drive macro"},{action:"dockMacro",label:"Dock macro"},{action:"chatFocus",label:"Chat focus"}]},{id:"camera",title:"Camera",items:[{action:"cameraUp",label:"Tilt up"},{action:"cameraDown",label:"Tilt down"},{action:"nightVisionToggle",label:"Toggle night vision"}]},{id:"motors",title:"Rover Aux Motors",items:[{action:"auxMainForward",label:"Main brush forward"},{action:"auxMainReverse",label:"Main brush reverse"},{action:"auxSideForward",label:"Side brush forward"},{action:"auxSideReverse",label:"Side brush reverse"},{action:"auxVacuumFast",label:"Vacuum max"},{action:"auxVacuumSlow",label:"Vacuum low"},{action:"auxAllForward",label:"All motors forward"}]},{id:"audio",title:"Audio / Song",items:[{action:"songNoteUp",label:"Song note up"},{action:"songNoteDown",label:"Song note down"}]},{id:"room-controls",title:"Room Controls",items:[{action:"homeAssistantOn",label:"Next room control on"},{action:"homeAssistantOff",label:"Next room control off (reverse)"}]}]},{type:"gamepad",title:"Gamepad / joystick",items:["Gamepad controls are fully configurable to handle inconsistent browser mappings.","Use Settings → Controller to bind inputs, calibrate deadzones, and view diagnostics.","If inputs behave oddly, the diagnostics panel will show raw axis/button values."]}]},"mobile-portrait":{main:[{type:"list",title:"Chat and nicknames",items:["Set a nickname in the user list panel below.","Tap in the chat box to send messages in the chat."]},{type:"list",title:"Driving the rover",items:[{segments:['Press the "Start Driving" button onscreen to put the rover into driving mode.']},"Look below the rover video. Use the joystick column to move the rover, and hold the aux buttons in the other control column."]},{type:"list",title:"Docking the rover",items:["Line up the rover to the dock, about a foot away, then:",{segments:['Press the "Dock and Charge" button onscreen to start docking.']},"Wait for the rover to confirm it is docked and charging before leaving it unattended."]}]},"mobile-landscape":{main:[{type:"list",title:"Chat and nicknames",items:["Scroll down to see more of the page.","Set a nickname in the user list panel below.","Tap in the chat box to send messages in the chat."]},{type:"list",title:"Driving the rover",items:[{segments:['Press the "Start Driving" button, or the "Drive" button to put the rover into driving mode.']},"Use the joystick column beside the video feed to move the rover, and hold the aux buttons in the other control column."]},{type:"list",title:"Docking the rover",items:["Line up the rover to the dock, about a foot away, then:",{segments:['Press the "Dock and Charge" or the "Dock" button onscreen to start docking.']},"Wait for the rover to confirm it is docked and charging before leaving it unattended."]}]}};function XN(n){return vx[n]||vx.desktop}function Xg({actionId:n,keymap:s}){const l=s?.[n]?.[0]??"";return r.jsx("span",{className:"rounded border border-slate-600 bg-slate-900/40 px-1 text-[0.7rem] text-slate-200",children:An(l)})}function bx(n,s){return n.map((l,o)=>typeof l=="string"?r.jsx("span",{children:l},`text-${o}`):l?.action?r.jsx(Xg,{actionId:l.action,keymap:s},`pill-${l.action}-${o}`):l?.text?r.jsx("span",{children:l.text},`span-${o}`):null)}function Ro(n,s,l){if(typeof n=="string")return n;if(Array.isArray(n?.segments))return bx(n.segments,s);if(n&&typeof n=="object"){if(typeof n.text=="string")return n.text;if(Array.isArray(n))return bx(n,s)}return String(n??"")}function QN({hero:n,keymap:s}){return n?r.jsxs("div",{className:"surface space-y-0.5 px-0.5 py-0.5",children:[r.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-0.5",children:[r.jsxs("div",{children:[r.jsx("p",{className:"text-sm font-semibold text-white",children:n.title}),n.subtitle&&r.jsx("p",{className:"text-xs text-slate-300",children:n.subtitle})]}),n.chips&&r.jsx("div",{className:"flex flex-wrap gap-0.5 text-[0.7rem] text-slate-200",children:n.chips.map(l=>r.jsx("span",{className:"rounded border border-slate-700 px-1 py-[2px]",children:l},l))})]}),n.bullets&&r.jsx("ul",{className:"space-y-0.5 text-[0.85rem] text-slate-200",children:n.bullets.map((l,o)=>{const f=Array.isArray(l?.segments)?`hero-${o}`:`hero-${o}`;return r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:Ro(l,s)},f)})})]}):null}function KN({block:n,keymap:s}){return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs font-semibold text-slate-200",children:n.title}),r.jsx("ul",{className:"space-y-0.5 text-[0.8rem] text-slate-300",children:n.items.map((l,o)=>{const f=`item-${o}`;return r.jsx("li",{className:"surface-muted flex flex-wrap items-center gap-0.5 px-0.5 py-0.25",children:Ro(l,s)},f)})})]})}function ZN({block:n}){const s=n.tone==="info"?"border-cyan-500/40":"border-slate-700";return r.jsxs("div",{className:`surface space-y-0.5 border ${s} px-0.5 py-0.5`,children:[r.jsx("p",{className:"text-xs font-semibold text-slate-100",children:n.title}),n.body&&r.jsx("ul",{className:"space-y-0.5 text-[0.8rem] text-slate-300",children:n.body.map((l,o)=>r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:Ro(l,{})},`callout-${o}`))})]})}function IN({group:n,keymap:s}){return r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"px-0.5 py-0.25 text-[0.75rem] font-semibold text-slate-200",children:n.title}),r.jsx("div",{className:"space-y-0.5 px-0.5 pb-0.25",children:n.items.map(l=>r.jsxs("div",{className:"surface-muted flex items-center justify-between gap-0.5 px-0.5 py-0.25 text-[0.8rem]",children:[r.jsx("span",{className:"text-slate-200",children:l.label}),r.jsx(Xg,{actionId:l.action,keymap:s})]},l.action))})]})}function JN({block:n,keymap:s}){return n?r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-200",children:[r.jsx("span",{className:"font-semibold",children:n.title}),n.footnote&&r.jsx("span",{className:"text-[0.7rem] text-slate-400",children:n.footnote})]}),r.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-0.5",children:n.groups?.map(l=>r.jsx(IN,{group:l,keymap:s},l.id))})]}):null}function PN({block:n}){return n?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs font-semibold text-slate-200",children:n.title}),r.jsx("ul",{className:"space-y-0.5 text-[0.8rem] text-slate-300",children:n.items?.map((s,l)=>r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:Ro(s,{})},`gamepad-${l}`))})]}):null}function yx({block:n,keymap:s}){if(!n)return null;switch(n.type){case"list":return r.jsx(KN,{block:n,keymap:s});case"callout":return r.jsx(ZN,{block:n});case"keyboard":return r.jsx(JN,{block:n,keymap:s});case"gamepad":return r.jsx(PN,{block:n});default:return null}}function Qg({layout:n,keymap:s}){const l=m.useMemo(()=>XN(n),[n]),o=s||{},f=l.main||[],d=l.aside||[];return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(QN,{hero:l.hero,keymap:o}),r.jsxs("div",{className:"grid gap-0.5",style:{gridTemplateColumns:"repeat(auto-fit, minmax(360px, 1fr))"},children:[r.jsx("div",{className:"space-y-0.5",children:f.map((h,p)=>r.jsx(yx,{block:h,keymap:o},h.title||p))}),r.jsx("div",{className:"space-y-0.5",children:d.map((h,p)=>r.jsx(yx,{block:h,keymap:o},h.title||p))})]})]})}function Kg({layout:n,onOpenOverlay:s}){const{state:l}=_t();return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Help"}),r.jsx("button",{type:"button",onClick:s,className:"button-dark px-1 py-0.25 text-[0.75rem]",children:"Open full help"})]}),r.jsx(Qg,{layout:n,keymap:l?.keymap||{}})]})}const WN=["kal","rms","slt","ksp","bdl"],ew=Array.from({length:10},(n,s)=>s*10);function qo({hideInput:n=!1,hideSpectatorNotice:s=!1,fillHeight:l=!1,allowSpectatorInput:o=!1}){const f=ft(R=>R.session),{messages:d,typing:h,sendMessage:p,registerInputRef:x,onInputFocus:g,onInputBlur:v,blurChat:y,setTypingActive:S}=od(),{value:E,save:C}=He("tts",{engine:"flite",voice:"rms",pitch:50}),[k,w]=m.useState(""),[j,N]=m.useState(!1),[T,M]=m.useState(!1),[O,K]=m.useState(()=>E?.engine||"flite"),[_,U]=m.useState(()=>E?.voice||"rms"),[X,F]=m.useState(()=>Number.isFinite(E?.pitch)?E.pitch:50),H=f?.role!=="spectator"||o,te=m.useRef(null),ce=f?.assignment?.roverId||null,V=!!m.useMemo(()=>f?.roster?.find(R=>String(R.id)===String(ce))||null,[ce,f?.roster])?.audio?.ttsEnabled,q=m.useMemo(()=>d.slice(-200),[d]),L=m.useMemo(()=>h||[],[h]);m.useEffect(()=>{te.current&&(te.current.scrollTop=te.current.scrollHeight)},[q,L]),m.useEffect(()=>{const R=E?.engine||"flite",$=E?.voice||"rms",ee=Number.isFinite(E?.pitch)?E.pitch:50;O!==R&&K(R),_!==$&&U($),X!==ee&&F(ee)},[O,X,E?.engine,E?.pitch,E?.voice,_]),m.useEffect(()=>{M(!!V)},[V]);const Z=m.useMemo(()=>!V||!T?null:O==="espeak"?{speak:!0,engine:O,pitch:X}:{speak:!0,engine:O,voice:_},[O,X,T,V,_]);async function le(R){if(R.preventDefault(),!H||n)return;const ee=k.replace(/\\n/g,` +`).trim();if(ee){N(!0);try{await p(ee,Z),w(""),y(),S(!1)}catch(ae){alert(ae.message)}finally{N(!1)}}}const fe=l?"flex-1 min-h-0 overflow-y-auto":"h-48 overflow-y-auto";return r.jsxs("section",{className:`panel-section space-y-0.5 text-base ${l?"flex h-full flex-col overflow-hidden":""}`,children:[r.jsxs("div",{className:`surface overflow-y-auto space-y-0.5 px-0 ${fe}`,ref:te,children:[q.length===0&&L.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"No messages yet."}):q.map(R=>r.jsx(ld,{message:R},R.id)),L.map(R=>r.jsx(pg,{message:R},`typing-${R.typingId||R.id}`))]}),!n&&r.jsxs("form",{className:"flex flex-wrap items-stretch gap-0.5",onSubmit:le,children:[r.jsx("input",{className:"field-input flex-1 min-w-[10rem]",value:k,onChange:R=>{const $=R.target.value;w($),S(!!$.trim())},onFocus:R=>{g(R),S(!!k.trim())},onBlur:R=>{v(R),S(!1)},onKeyDown:R=>{R.key==="Enter"&&!k.trim()&&(R.preventDefault(),y(),S(!1))},ref:R=>x(R,{target:"panel"}),placeholder:H?"Type a message…":s?"":"Spectators cannot chat",disabled:!H}),V&&r.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 basis-full sm:basis-auto",children:[r.jsxs("label",{className:"flex items-center gap-0.5 text-xs text-slate-300",children:[r.jsx("input",{type:"checkbox",checked:T,onChange:R=>M(R.target.checked),className:"accent-cyan-500"}),r.jsx("span",{children:"Speak"})]}),r.jsxs("select",{value:O,onChange:R=>{const $=R.target.value;K($),C(ee=>({...ee||{},engine:$}))},className:"field-input text-xs",children:[r.jsx("option",{value:"flite",children:"flite"}),r.jsx("option",{value:"espeak",children:"espeak"})]}),O==="flite"?r.jsx("select",{value:_,onChange:R=>{const $=R.target.value;U($),C(ee=>({...ee||{},voice:$}))},className:"field-input text-xs",children:WN.map(R=>r.jsx("option",{value:R,children:R},R))}):r.jsx("select",{value:X,onChange:R=>{const $=Number(R.target.value);F($),C(ee=>({...ee||{},pitch:$}))},className:"field-input text-xs",children:ew.map(R=>r.jsxs("option",{value:R,children:["pitch ",R]},R))})]}),r.jsx("button",{type:"submit",disabled:!H||j,className:"button-dark h-full disabled:opacity-50 self-stretch",children:j?"...":"Send"})]})]})}function To({compact:n=!1}){const{session:s,setNickname:l}=nn(),{value:o,save:f}=He("profile",{nickname:""}),[d,h]=m.useState(o.nickname||""),[p,x]=m.useState(!1),g=s?.role!=="spectator";m.useEffect(()=>{h(o.nickname||"")},[o.nickname]);async function v(y){if(y.preventDefault(),!g)return;const S=(d||"").trim().slice(0,32);if(S){x(!0);try{await l(S),f({nickname:S})}catch(E){alert(E.message)}finally{x(!1)}}}return r.jsxs("form",{className:"grid w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-stretch gap-0.5",onSubmit:v,children:[r.jsx("input",{className:"field-input flex-1 min-w-0",value:d,onChange:y=>h(y.target.value),maxLength:32,placeholder:"Enter a nickname",disabled:!g}),r.jsx("button",{type:"submit",disabled:!g||p,className:"button-dark h-full shrink-0 whitespace-nowrap px-0.5 py-0 disabled:opacity-50",children:p?"Saving…":n?"Set":"Save"})]})}function tw(n){const s=Array.isArray(n?.socials)?n.socials:null;if(s&&s.length)return s;const l=[];return n?.discord?.invite&&l.push({id:"discord",label:"Discord",url:n.discord.invite}),n?.kofi?.link&&l.push({id:"kofi",label:"Ko-fi",url:n.kofi.link}),l}function nw(n){if(!n||typeof n!="object")return null;const s=n.id||n.service||n.key||n.name||null,l=n.label||n.title||n.name||s||"Link",o=n.url||n.link||n.href||null;return o?{id:s,label:l,url:o}:null}function Zg({className:n=""}){const{session:s}=nn(),l=tw(s).map(nw).filter(Boolean).slice(0,4);return l.length?r.jsx("div",{className:`grid grid-cols-2 grid-rows-2 gap-0.5 ${n}`,children:l.map(o=>r.jsx(hd,{...o},`${o.id||o.label}-${o.url}`))}):null}function aw({compact:n=!1}){return r.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:r.jsx("div",{className:"surface flex w-full items-center px-0 py-0",children:r.jsx(To,{compact:n})})})}function sw(){return r.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:r.jsx(Zg,{className:"flex-1 min-h-0"})})}function yf(...n){return n.filter(Boolean).join(" ")}function lw(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function iw(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function rw(n){switch(n){case"admin":case"lockdown":case"lockdown-admin":return"text-amber-300";case"spectator":return"text-slate-400";default:return"text-sky-300"}}function ow(n,s){if(!n)return"";const l=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${l} (you)`:l}function Do({title:n="Rovers"}){const s=ft(j=>j.session),{requestControl:l}=wn(),[o,f]=m.useState({}),[d,h]=m.useState(()=>Date.now()),p=m.useMemo(()=>s?.role&&s.role!=="spectator",[s?.role]),x=m.useMemo(()=>s?.role==="admin"||s?.role==="lockdown"||s?.role==="lockdown-admin",[s?.role]),g=s?.roster??[],v=s?.turnQueues??{},y=s?.users??[],S=s?.socketId||null,E=m.useMemo(()=>Object.values(v||{}).some(j=>j?.deadline||j?.idleDeadline),[v]);m.useEffect(()=>{if(!E)return;const j=setInterval(()=>{h(Date.now())},1e3);return()=>clearInterval(j)},[E]);const C=m.useMemo(()=>{const j=new Set(g.map(T=>String(T.id))),N=Object.keys(v||{}).filter(T=>!j.has(String(T))).map(T=>({id:T,name:T,locked:!1,batteryState:null}));return[...g,...N]},[g,v]);async function k(j){if(j){f(N=>({...N,[j]:!0}));try{await l(j)}catch(N){alert(N.message)}finally{f(N=>({...N,[j]:!1}))}}}const w=j=>y.find(N=>N.socketId===j)||{socketId:j,nickname:null,role:null};return r.jsxs("div",{className:"space-y-0.5 text-sm",children:[n&&r.jsx("p",{className:"text-sm text-slate-400",children:n}),C.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"No rovers registered."}):r.jsx("ul",{className:"space-y-0.5 text-sm",children:C.map(j=>{const N=String(j.id),T=v?.[N]||null,M=T?.queue||[],O=T?.idleDeadline||T?.deadline||null,K=O&&O>d?Math.ceil((O-d)/1e3):O?0:null,_=T?.current||null,U=_?M.findIndex(le=>le===_):-1,X=M.length>1?U>=0?M[(U+1)%M.length]:M[0]:null,F=!!(S&&_&&_===S),H=!!(S&&X&&X===S),te=K!=null&&(F||H),ce=!!j.locked,oe=ce&&!x,V=!!(j?.private?.enabled&&j?.private?.open),q=j.lockReason?`locked: ${j.lockReason}`:"locked",L=ce?q:o[N]?"...":"request",Z=p&&!oe&&!o[N];return r.jsxs("li",{className:yf("surface flex flex-wrap items-start justify-between gap-0.5",Z&&"cursor-pointer",ce?"bg-red-900/40":V?"bg-amber-700/35 border border-amber-200/30":null),onClick:()=>{Z&&k(j.id)},children:[r.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsxs("div",{className:"flex items-center gap-0.5",children:[r.jsx("p",{className:"text-slate-200",children:r.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ca(j.color,.16),children:j.name})}),te?r.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem] text-slate-200",children:F?`${K}s left`:`Your turn in ${K}s`}):null]}),r.jsx("span",{className:yf("text-[0.75rem] font-semibold",iw(j)),children:lw(j)})]}),M.length===0?r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"No queue."}):r.jsx("div",{className:"flex flex-wrap items-center gap-0.5",children:M.map((le,fe)=>{const R=w(le),$=le===_,ee=!!(X&&le===X&&!$),ae=$?"bg-sky-600 text-white ring-2 ring-amber-300":ee?"bg-emerald-700/60 text-emerald-100 ring-1 ring-emerald-300/70":"bg-slate-800 text-slate-200";return r.jsxs("span",{className:`flex items-center gap-0.5 rounded px-1 text-[0.7rem] ${ae}`,children:[r.jsx("span",{className:`${rw(R.role)} font-semibold`,children:ow(R,S)}),$&&r.jsx("span",{className:"text-[0.65rem] text-slate-200",children:"now"}),ee&&r.jsx("span",{className:"text-[0.65rem] text-emerald-100",children:"next"})]},`${N}-${le}-${fe}`)})})]}),p?r.jsx("button",{type:"button",onClick:le=>{le.stopPropagation(),k(j.id)},disabled:o[N]||oe,className:yf("button-dark disabled:opacity-40",ce&&"bg-red-600/70 text-white hover:bg-red-600"),children:L}):null]},j.id)})})]})}function cw(n){switch(n){case"admin":case"lockdown":case"lockdown-admin":return"text-amber-300";case"spectator":return"text-slate-400";default:return"text-sky-300"}}function uw(n,s){if(!n)return"";const l=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${l} (you)`:l}function So({hideNicknameForm:n=!1,hideHeader:s=!1,className:l="",fillHeight:o=!1,compact:f=!1}){const{session:d}=nn(),h=d?.role!=="spectator",p=d?.users??[],x=d?.socketId||null,g=m.useMemo(()=>[...p].sort((y,S)=>y.socketId===x?-1:S.socketId===x?1:(y.nickname||"").localeCompare(S.nickname||"")),[x,p]),v=o?"flex-1 min-h-0 overflow-y-auto":f?"h-28 overflow-y-auto":"h-48 overflow-y-auto";return r.jsxs("section",{className:`panel-section space-y-0.5 text-base ${o?"flex h-full min-h-0 flex-col overflow-hidden":""} ${l}`,children:[!n&&r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"grid gap-0.5 md:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]",children:[r.jsx("div",{className:"min-w-0",children:r.jsx("div",{className:"surface flex w-full items-center px-0 py-0",children:r.jsx(To,{compact:f})})}),r.jsx(Zg,{})]}),!h&&r.jsx("p",{className:"text-xs text-slate-500",children:"Spectators cannot set nicknames."})]}),r.jsxs("div",{className:`space-y-0.5 ${o?"flex flex-1 min-h-0 flex-col":""}`,children:[!s&&r.jsxs("div",{className:`flex items-center justify-between text-sm text-slate-400 ${f?"text-xs":""}`,children:[r.jsx("span",{children:"Users"}),r.jsx("span",{className:"text-xs text-slate-500",children:g.length})]}),r.jsx("div",{className:`surface flex flex-wrap content-start items-start gap-0.5 px-0 pb-0 ${v} ${f?"text-[0.8rem]":""}`,children:g.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"Waiting for users…"}):g.map(y=>r.jsx("span",{className:`rounded bg-slate-800/80 px-1 py-0.25 text-[0.7rem] ${cw(y.role)}`,children:uw(y,x)},y.socketId))})]})]})}const fw=/^cu_[a-f0-9]{32}$/,ki="field-input w-full max-w-sm text-left focus:ring-emerald-500",_o="mx-auto w-full max-w-xl flex justify-center",bi="mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center";function dw(n){const s=String(n||"").trim();return s?s.length<=10?`${s.slice(0,2)}***${s.slice(-2)}`:`${s.slice(0,6)}...${s.slice(-6)}`:""}const Sx=8*1024*1024,is=16e3,mw={iceServers:[{urls:"stun:stun.l.google.com:19302"}],bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"};function jx(n){let s="";for(let o=0;o{if(!n||n.iceGatheringState==="complete"){l();return}const o=setTimeout(()=>{n.removeEventListener("icegatheringstatechange",f),l()},s);function f(){n.iceGatheringState==="complete"&&(clearTimeout(o),n.removeEventListener("icegatheringstatechange",f),l())}n.addEventListener("icegatheringstatechange",f)})}function Ax(n){if(!n)return!1;const s=n.connectionState,l=n.iceConnectionState;return s==="connected"||l==="connected"||l==="completed"}function gw(n,s=1e4){return new Promise((l,o)=>{if(!n){o(new Error("Peer connection missing"));return}if(Ax(n)){l();return}const f=setTimeout(()=>{h(),o(new Error("Peer connection timeout"))},s),d=()=>{Ax(n)?(h(),l()):(n.connectionState==="failed"||n.connectionState==="closed"||n.iceConnectionState==="failed")&&(h(),o(new Error(`Peer connection ${n.connectionState||n.iceConnectionState}`)))};function h(){clearTimeout(f),n.removeEventListener("connectionstatechange",d),n.removeEventListener("iceconnectionstatechange",d)}n.addEventListener("connectionstatechange",d),n.addEventListener("iceconnectionstatechange",d)})}async function vw(n){if(!n?.getParameters||!n?.setParameters)return;const s=n.getParameters()||{},l=s.encodings&&s.encodings[0]||{};s.encodings=[{...l,maxBitrate:64e3,dtx:"disabled"}];try{await n.setParameters(s)}catch{}}function bw(n,s=6e3){return new Promise((l,o)=>{if(!n){o(new Error("Peer connection missing"));return}const f=Date.now();let d=-1;const h=setInterval(async()=>{if(Date.now()-f>s){clearInterval(h),o(new Error("WHIP connected but no outbound audio flow"));return}try{const p=n.getSenders().filter(x=>x.track?.kind==="audio");for(const x of p){const g=await x.getStats();for(const v of g.values()){if(v.type!=="outbound-rtp"||v.kind!=="audio")continue;const y=Number(v.bytesSent||0),S=Number(v.packetsSent||0);if(d<0)d=y;else if(y>d+200||S>5){clearInterval(h),l();return}}}}catch{}},250)})}function xn({label:n,active:s,detail:l=""}){return r.jsxs("div",{className:`rounded-md px-0.5 py-0.5 text-xs text-slate-100 ${s?"bg-emerald-500":"bg-slate-700"}`,children:[r.jsx("div",{className:"text-center font-medium",children:n}),r.jsx("div",{className:"text-center text-[0.72rem] opacity-90",children:l||(s?"active":"idle")})]})}function Nx({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function yw(n){const s=n.reduce((f,d)=>f+d.length,0),l=new Float32Array(s);let o=0;for(const f of n)l.set(f,o),o+=f.length;return l}function Sw(n){const s=new Int16Array(n.length);for(let l=0;l{for(let v=0;vv&&s?.[v]||null,[s,v]),ee=!!($&&$.state!=="offline"&&!$.error),ae=$?.source==="upload"&&$?.state==="playing",pe=$?.source==="mic-whip"&&($?.state==="starting"||$?.state==="playing"),re=!!(!j&&X.current&&(k||R)),ue=!j&&(N==="live"||N==="starting"),ve=j&&M==="recording",be=j&&M==="sending",xe=An(p?.keymap?.micPtt?.[0])||"M",Be=m.useCallback(P=>{const de=P==="clip"?"clip":"live";g(Ne=>({...Ne||{},pttMode:de}))},[g]),ze=async()=>{if(!v){_("Take control of your rover first.");return}if(!y){_("Select an audio file first.");return}if(y.size>Sx){_(`File too large (max ${Sx} bytes).`);return}C(!0),_("");try{const P=await y.arrayBuffer(),de=jx(new Uint8Array(P));await l?.({roverId:v,name:y.name,mime:y.type||"",dataBase64:de}),_("Upload playback started.")}catch(P){_(P?.message||"Failed to play upload.")}finally{C(!1)}},Ae=async()=>{if(!v){_("Take control of your rover first.");return}C(!0),_("");try{await o?.(v),_("Upload playback stopped.")}catch(P){_(P?.message||"Failed to stop upload.")}finally{C(!1)}},tt=m.useCallback(async P=>{const de=String(P||te.current||"").trim();if(H.current=!1,T("idle"),F.current){try{F.current.getSenders().forEach(Ne=>Ne.track?.stop())}catch{}try{F.current.close()}catch{}}if(F.current=null,U.current)try{U.current.getTracks().forEach(Ne=>Ne.stop())}catch{}if(U.current=null,X.current=null,de)try{await h?.(de)}catch{}te.current=""},[h]),Je=m.useCallback(async P=>{const de=await f?.(P),Ne=String(de?.whipUrl||"").trim(),pt=String(de?.token||"").trim();if(!Ne||!pt)throw new Error("WHIP endpoint unavailable");const Ve=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:is,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}});U.current=Ve;const st=Ve.getAudioTracks()?.[0];if(X.current=st||null,st&&(st.enabled=!!(k||R)),st?.applyConstraints)try{await st.applyConstraints({channelCount:1,sampleRate:is,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1})}catch{}const lt=new RTCPeerConnection(mw);F.current=lt,lt.onconnectionstatechange=()=>{if(!H.current)return;const Yt=lt.connectionState;if(Yt==="connected"){T("live");return}(Yt==="failed"||Yt==="disconnected"||Yt==="closed")&&(T("error"),_(`WHIP transport ${Yt}.`))},Ve.getAudioTracks().forEach(Yt=>{const La=lt.addTrack(Yt,Ve);vw(La)});const Ot=await lt.createOffer({offerToReceiveAudio:!1,offerToReceiveVideo:!1});await lt.setLocalDescription(Ot),await xw(lt,1800);const it=await fetch(Ne,{method:"POST",headers:{"Content-Type":"application/sdp",...pw(pt)},body:lt.localDescription?.sdp||Ot.sdp});if(!it.ok)throw new Error(`WHIP request failed: ${it.status}`);const ms=await it.text();await lt.setRemoteDescription({type:"answer",sdp:ms}),await gw(lt,1e4),await bw(lt,6e3),await d?.(P)},[k,R,d,f]),vt=m.useCallback(async()=>{if(le.current=!1,q.current){try{q.current.disconnect()}catch{}q.current.onaudioprocess=null}if(V.current)try{V.current.disconnect()}catch{}if(L.current)try{L.current.disconnect()}catch{}if(ce.current)try{ce.current.getTracks().forEach(P=>P.stop())}catch{}if(oe.current)try{await oe.current.close()}catch{}Z.current=[],q.current=null,V.current=null,L.current=null,ce.current=null,oe.current=null,fe.current=is},[]),ie=m.useCallback(async()=>{if(ce.current&&oe.current&&q.current)return;O(st=>st==="recording"?st:"arming");const P=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:is,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}}),de=new AudioContext({latencyHint:"interactive"}),Ne=de.createMediaStreamSource(P),pt=de.createScriptProcessor(1024,1,1),Ve=de.createGain();Ve.gain.value=0,pt.onaudioprocess=st=>{if(!le.current)return;const lt=st.inputBuffer.getChannelData(0);Z.current.push(new Float32Array(lt))},Ne.connect(pt),pt.connect(Ve),Ve.connect(de.destination),ce.current=P,oe.current=de,V.current=Ne,q.current=pt,L.current=Ve,fe.current=de.sampleRate||is},[]),me=m.useCallback(async({send:P})=>{const de=le.current;if(le.current=!1,!de){P||O("idle");return}const Ne=Z.current;if(Z.current=[],!P){O("idle");return}if(!v){O("idle");return}if(!Ne.length){O("idle");return}O("sending");try{const pt=yw(Ne),Ve=jw(pt,fe.current||is),st=jx(Ve);await l?.({roverId:v,name:`ptt-${Date.now()}.wav`,mime:"audio/wav",dataBase64:st}),O("idle")}catch(pt){O("error"),_(pt?.message||"Failed to send PTT clip.")}},[l,v]),se=m.useCallback(async()=>{if(!v){_("Take control of your rover first.");return}await ie(),Z.current=[],le.current=!0,O("recording")},[ie,v]);return m.useEffect(()=>{let P=!1;async function de(){if(j){await tt(te.current||v);return}if(!v){await tt(te.current);return}if(!(H.current&&te.current===v)&&!(!k&&!R))try{T("starting"),_(""),H.current=!0,te.current=v,await Je(v),P||T("live")}catch(Ne){P||(T("error"),_(Ne?.message||"Failed to start mic forwarding.")),await tt(v)}}return de(),()=>{P=!0}},[j,k,R,v,Je,tt]),m.useEffect(()=>{const P=X.current;P&&(P.enabled=!!(!j&&(k||R)))},[j,k,R]),m.useEffect(()=>{let P=!1;async function de(){if(!j||!v){le.current&&await me({send:!1}),O("idle");return}try{await ie(),!P&&!le.current&&O("idle")}catch(Ne){P||(O("error"),_(Ne?.message||"Microphone access failed for clip mode."))}}return de(),()=>{P=!0}},[j,ie,me,v]),m.useEffect(()=>{let P=!1;async function de(){if(j){if(!v){le.current&&await me({send:!1});return}if(R){if(!le.current)try{_(""),await se()}catch(Ne){P||(O("error"),_(Ne?.message||"Failed to start clip recording."))}}else le.current&&await me({send:!0})}}return de(),()=>{P=!0}},[j,me,R,v,se]),m.useEffect(()=>()=>{tt(te.current||v),vt()},[v,tt,vt]),r.jsx("section",{className:"surface",children:r.jsxs("div",{className:"grid gap-1",children:[r.jsx("p",{className:"text-sm text-slate-100 text-center",children:"Audio Controls"}),r.jsx("section",{className:"surface",children:r.jsxs("div",{className:"flex items-center justify-center gap-0.5 py-0.25 text-xs text-slate-300",children:[r.jsx("span",{children:"Push-to-Talk Key"}),r.jsx(Nx,{label:xe})]})}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-2",children:[r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"PTT Mode"}),r.jsx("p",{className:"text-xs text-slate-400 text-center",children:"Choose how holding your PTT key behaves: live mic stream, or record-and-send clip. If the live stream doesn't work, switch to clip mode."}),r.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[r.jsx("button",{type:"button",className:`button-dark w-full text-sm ${j?"":"bg-emerald-500 text-white hover:bg-emerald-500"}`,onClick:()=>Be("live"),children:"Live Mic (WHIP)"}),r.jsx("button",{type:"button",className:`button-dark w-full text-sm ${j?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,onClick:()=>Be("clip"),children:"Record Clip"})]})]})}),r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_1fr]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"PTT Clip Status"}),r.jsxs("div",{className:"grid gap-0.5 content-start",children:[r.jsx(xn,{label:"Mode",active:j,detail:j?"record clip":"live mic"}),r.jsx(xn,{label:"PTT hold",active:R,detail:R?"held":"released"}),r.jsx(xn,{label:"Recording",active:ve,detail:ve?"capturing":"idle"}),r.jsx(xn,{label:"Playback",active:j&&ae,detail:j&&ae?"playing":"idle"})]})]})})]}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-2",children:[r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr_auto]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Audio Upload"}),r.jsxs("label",{className:"mx-auto grid w-full max-w-sm gap-0.5 text-xs text-slate-300 text-center",children:[r.jsx("span",{children:"Audio file (mp3 / wav / ogg)"}),r.jsx("input",{className:`${ki} text-center`,type:"file",accept:".mp3,.wav,.ogg,audio/mpeg,audio/wav,audio/ogg",disabled:E||!v,onChange:P=>S(P.target.files?.[0]||null)})]}),r.jsx("div",{className:"mx-auto w-full max-w-sm text-center",children:y?r.jsxs("div",{className:"surface-muted text-xs text-slate-300",children:[y.name," (",y.size," bytes)"]}):r.jsx("div",{className:"surface-muted text-xs text-slate-500",children:"No file selected"})}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:E||!v,onClick:ze,children:E?"Working...":"Play Upload"}),r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:E||!v,onClick:Ae,children:"Stop"})]})]})}),r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Live Microphone"}),r.jsxs("label",{className:"surface-muted mx-auto flex w-full max-w-sm items-center justify-center gap-0.5 px-0.5 py-0.5 text-xs text-slate-300",children:[r.jsx("input",{type:"checkbox",checked:k,disabled:!v||j,onChange:P=>g(de=>({...de||{},openMicEnabled:!!P.target.checked}))}),r.jsx("span",{children:j?"Open mic (live mode only)":"Open mic"})]}),r.jsxs("div",{className:"grid gap-0.5 content-start",children:[r.jsx(xn,{label:"WHIP link",active:ue,detail:N}),r.jsx(xn,{label:"Mic hot",active:re,detail:re?"transmitting":"muted"}),r.jsxs("div",{className:"surface-muted text-center text-xs text-slate-400",children:["Hold ",r.jsx(Nx,{label:xe})," to talk"]})]})]})})]}),r.jsx("section",{className:"surface",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Audio Status"}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-6",children:[r.jsx(xn,{label:"Forward pipe",active:ee,detail:ee?"connected":"offline"}),r.jsx(xn,{label:"Upload playback",active:ae,detail:ae?"playing":"idle"}),r.jsx(xn,{label:"Mic relay",active:pe,detail:pe?"active":"idle"}),r.jsx(xn,{label:"WHIP transport",active:ue,detail:N}),r.jsx(xn,{label:"Clip recording",active:ve,detail:ve?"recording":"idle"}),r.jsx(xn,{label:"Clip sending",active:be,detail:be?"sending":"idle"})]}),K?r.jsx("div",{className:"text-xs text-slate-400 text-center",children:K}):null]})})]})})}function Nw({pendingRequestId:n,currentStoredKey:s,nickname:l,requestVerification:o,applyIdentityKey:f,onMessage:d,fullWidth:h=!1}){const[p,x]=m.useState(0),[g,v]=m.useState(""),[y,S]=m.useState(!1),[E,C]=m.useState(!1),k=()=>{x(1),v(s),S(!1),d?.("")},w=()=>{x(0),S(!1)},j=async T=>{if(T.preventDefault(),!y){d?.("Please confirm your nickname agreement before sending.");return}if(p<3){d?.("Complete all request steps before sending.");return}C(!0),d?.("");try{const M=await f(g);await o?.(),v(M),x(0),S(!1),d?.("Verification request sent to lockdown admins.")}catch(M){d?.(M.message||"Failed to submit request.")}finally{C(!1)}},N=h?"w-full":_o;return n?r.jsx("section",{className:`surface text-sm text-slate-300 ${N}`,children:r.jsxs("div",{className:bi,children:["Verification request pending: ",n]})}):p===0?r.jsx("section",{className:`surface ${N}`,children:r.jsxs("div",{className:bi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Verification"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:k,disabled:E,children:"Request Verification"})]})}):r.jsx("form",{className:`surface ${N}`,onSubmit:j,children:r.jsxs("div",{className:bi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Request verification"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Step ",p," of 3"]}),p===1?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Confirm your nickname, which is used as part of the verification process. You can edit it here before requesting."}),r.jsx("div",{className:"mx-auto w-full max-w-sm",children:r.jsx(To,{compact:!0})}),r.jsxs("div",{className:"surface-muted mx-auto w-full max-w-sm text-xs text-slate-300 text-center",children:["Current nickname: ",r.jsx("span",{className:"font-semibold",children:l||"(not set)"})]}),r.jsxs("label",{className:"flex items-center justify-center gap-0.5 text-xs text-slate-300 text-center",children:[r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:y,onChange:T=>S(T.target.checked)}),r.jsx("span",{children:"I understand this nickname is tied to my verification."})]}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!l||!y,onClick:()=>x(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:w,children:"Cancel"})]})]}):null,p===2?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Save your identity key in a safe place. You can use it to restore your identity in another browser."}),r.jsx("input",{className:ki,type:"password",name:"identity_key_request",autoComplete:"current-password",maxLength:35,value:g,onChange:T=>v(T.target.value.toLowerCase()),placeholder:"Identity key for this request"}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!g,onClick:()=>navigator.clipboard?.writeText(g),children:"Copy Key"}),r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!g,onClick:()=>x(3),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(1),children:"Back"})]})]}):null,p===3?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Final step: confirm and send your verification request."}),r.jsx("input",{className:ki,type:"password",name:"identity_key_request_final",autoComplete:"current-password",maxLength:35,value:g,onChange:T=>v(T.target.value.toLowerCase()),placeholder:"Identity key for this request"}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"submit",className:"button-dark text-sm",disabled:E||!g,children:"Confirm Request"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(2),children:"Back"})]})]}):null]})})}function ww({currentStoredKey:n,applyIdentityKey:s,onMessage:l,fullWidth:o=!1}){const[f,d]=m.useState(0),[h,p]=m.useState(""),[x,g]=m.useState(!1),v=()=>{d(1),p(""),l?.("")},y=()=>{d(0),p("")},S=async C=>{if(C.preventDefault(),!(f<2)){g(!0),l?.("");try{await s(h),d(0),p(""),l?.("Identity key restored.")}catch(k){l?.(k.message||"Failed to restore key.")}finally{g(!1)}}},E=o?"w-full":_o;return r.jsx("section",{className:`surface ${E}`,children:r.jsxs("div",{className:bi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Identity key"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Current: ",dw(n)||"not set yet"]}),r.jsx("input",{className:ki,type:"password",name:"identity_key_current",autoComplete:"current-password",maxLength:35,value:n,readOnly:!0,placeholder:"Identity key"}),f===0?r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!n,onClick:()=>navigator.clipboard?.writeText(n),children:"Copy Key"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:v,disabled:x,children:"Restore Key"})]}):null,f===1?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Restoring your key should only be done when needed. Use this to move your identity to another browser."}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>d(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:y,children:"Cancel"})]})]}):null,f===2?r.jsxs("form",{className:"space-y-0.5",onSubmit:S,children:[r.jsx("input",{className:ki,type:"password",name:"identity_key_restore",autoComplete:"current-password",maxLength:35,value:h,onChange:C=>p(C.target.value.toLowerCase()),placeholder:"Paste key to restore"}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"submit",className:"button-dark text-sm",disabled:x||!h,children:"Confirm Restore"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>d(1),children:"Back"})]})]}):null]})})}function Cw({requestableRovers:n=[],pendingRequests:s=[],requestPrivateRoverAccess:l,onMessage:o,fullWidth:f=!1}){const[d,h]=m.useState({}),p=m.useMemo(()=>{const v=new Map;return(s||[]).forEach(y=>{y?.roverId&&v.set(String(y.roverId),y)}),v},[s]),x=f?"w-full":_o,g=async v=>{if(v){h(y=>({...y,[v]:!0})),o?.("");try{(await l?.(v))?.existing?o?.("You already have a pending request for that rover."):o?.("Private rover access request sent to lockdown admins.")}catch(y){o?.(y.message||"Failed to send request.")}finally{h(y=>({...y,[v]:!1}))}}};return r.jsx("section",{className:`surface text-sm text-slate-300 ${x}`,children:r.jsxs("div",{className:bi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Private rover access requests"}),n.length===0?r.jsx("p",{className:"text-xs text-slate-500",children:"No closed private rovers are available to request right now."}):r.jsx("div",{className:"w-full space-y-0.5",children:n.map(v=>{const y=String(v.id),S=!!d[y],E=p.get(y);return r.jsxs("div",{className:"surface-muted flex items-center justify-between gap-0.5 px-1 py-0.5",children:[r.jsxs("div",{className:"min-w-0 text-left",children:[r.jsx("p",{className:"truncate text-xs font-semibold text-slate-100",children:v.name||y}),r.jsx("p",{className:"truncate text-[0.7rem] text-slate-500",children:y})]}),E?r.jsx("span",{className:"rounded bg-amber-700/30 px-1 py-0.5 text-[0.7rem] text-amber-200",children:"Pending"}):r.jsx("button",{type:"button",onClick:()=>g(y),disabled:S,className:"button-dark text-xs disabled:opacity-50",children:S?"Sending...":"Request"})]},y)})})]})})}function Vf(n){return String(n||"").trim()}function Ew(n){const s=Vf(n);return s?s.includes("DOCKINGRUNNING")?"Returning":s.includes("PAUSED")?"Paused":s.includes("HOUSECLEANINGRUNNING")?"Cleaning":s.includes("SPOTCLEANINGRUNNING")?"Spot cleaning":s.includes("STATE_START")?"Starting":s.includes("STATE_IDLE")||s.includes("STATE_STANDBY")?"Idle":s:"--"}function Ig(n){return n==="good"?"bg-emerald-600 text-white":n==="warn"?"bg-amber-500 text-slate-900":n==="danger"?"bg-rose-600 text-white":n==="info"?"bg-sky-600 text-white":"bg-slate-700 text-slate-100"}function rs({label:n,value:s,tone:l="muted",valueClass:o=""}){return r.jsxs("div",{className:`rounded-md px-1 py-0.75 text-center ${Ig(l)}`,children:[r.jsx("div",{className:"text-[0.72rem] opacity-90",children:n}),r.jsx("div",{className:`text-sm font-semibold ${o}`,title:String(s||""),children:s})]})}function kw({neato:n,onStart:s,onSendHome:l,onLocate:o,onClearErrors:f,fullWidth:d=!1}){const[h,p]=m.useState(""),x=d?"w-full":"w-full max-w-xl",g=!!n?.configured,v=!!(n?.enabled&&n?.connected),y=!!n?.telemetry?.extPowerPresent,S=!!n?.telemetry?.chargingActive,E=Ew(n?.telemetry?.uiState),C=n?.telemetry?.batteryPercent,k=Number.isFinite(C)?`${C}%`:"--",w=n?.telemetry?.batteryVoltage,j=Number.isFinite(w)?`${w.toFixed(2)} V`:"--",N=Vf(n?.telemetry?.robotError)||"--",T=Vf(n?.telemetry?.robotAlert)||"--",M=N!=="--"&&!/^no errors$/i.test(N)&&!/^200/.test(N),O=T!=="--"&&!/^200/.test(T),K=n?.controls||{},_=!!K?.start?.available,U=!!K?.sendHome?.available,X=!!K?.locate?.available,F=!!K?.clearErrors?.available,H=m.useMemo(()=>y?{key:"start",label:"Start cleaning",pending:"Starting...",toneClass:"bg-emerald-600 hover:bg-emerald-500 text-white",canRun:_,fn:s}:{key:"home",label:"Send to dock",pending:"Sending...",toneClass:"bg-sky-600 hover:bg-sky-500 text-white",canRun:U,fn:l},[y,_,s,U,l]),te=g&&v&&H.canRun,ce=g&&v&&X,oe=g&&v&&F,V=async(fe,R)=>{if(R){p(fe);try{await R()}catch{}finally{p("")}}},q=g?v?"Online":"Offline":"Not configured",L=g?v?"good":"danger":"warn",Z=C==null?"muted":C>=60?"good":C>=25?"warn":"danger",le=y?"Docked":E!=="--"?E:"Away from dock";return r.jsx("section",{className:`surface text-sm text-slate-200 ${x}`,children:r.jsxs("div",{className:"grid gap-0.5",children:[r.jsxs("div",{className:"relative flex items-center justify-center min-h-[1.5rem]",children:[r.jsxs("div",{className:"text-center",children:[r.jsx("p",{className:"text-sm text-slate-100",children:"Neato Controls"}),r.jsx("p",{className:"text-xs text-slate-400",children:"Control the autonomous Neato robovac"})]}),r.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${Ig(L)}`,children:q})]}),r.jsx("section",{className:"surface-muted px-0.5 py-0.5",children:r.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-0.5",children:[r.jsxs("div",{className:"grid gap-0.5",children:[r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.75 text-center",children:[r.jsx("div",{className:"text-xs text-slate-300",children:"State"}),r.jsx("div",{className:"text-base font-semibold text-slate-100",children:le})]}),r.jsx("button",{type:"button",disabled:!te||!!h,onClick:()=>V(H.key,H.fn),className:`rounded-md px-1 py-1 text-base font-semibold transition disabled:opacity-50 ${H.toneClass}`,children:h===H.key?H.pending:H.label})]}),r.jsx("button",{type:"button",disabled:!ce||!!h,onClick:()=>V("locate",o),className:"rounded-md bg-fuchsia-600 px-1 py-0.75 text-sm font-semibold text-white transition hover:bg-fuchsia-500 disabled:opacity-50",children:h==="locate"?"Playing...":"Play sound"}),r.jsx("button",{type:"button",disabled:!oe||!!h,onClick:()=>V("clearErrors",f),className:"rounded-md bg-amber-500 px-1 py-0.75 text-sm font-semibold text-slate-900 transition hover:bg-amber-400 disabled:opacity-50",children:h==="clearErrors"?"Clearing...":"Clear errors"})]})}),r.jsx("section",{className:"surface-muted px-0.5 py-0.5",children:r.jsxs("div",{className:"grid gap-0.5 grid-cols-2 sm:grid-cols-3 lg:grid-cols-7",children:[r.jsx(rs,{label:"Battery",value:k,tone:Z}),r.jsx(rs,{label:"Voltage",value:j,tone:w==null?"muted":"info"}),r.jsx(rs,{label:"Docked",value:y?"Yes":"No",tone:y?"info":"muted"}),r.jsx(rs,{label:"Charging",value:S?"Yes":"No",tone:S?"info":"muted"}),r.jsx(rs,{label:"UI state",value:E,tone:"muted",valueClass:"truncate"}),r.jsx(rs,{label:"Robot error",value:N,tone:M?"danger":"muted",valueClass:"truncate"}),r.jsx(rs,{label:"Robot alert",value:T,tone:O?"warn":"muted",valueClass:"truncate"})]})}),!g||!v||!H.canRun||!X||!F?r.jsx("p",{className:"text-xs text-slate-400 text-center",children:g?v?"Waiting for required Neato entities in Home Assistant.":"Home Assistant is offline.":"Set homeAssistant.neato.device in server config to enable Neato controls."}):null]})})}function Jg(){const{session:n,identifySession:s,requestVerification:l,requestPrivateRoverAccess:o,playUploadedAudio:f,stopUploadedAudio:d,startMicWhip:h,readyMicWhip:p,stopMicWhip:x,neatoStart:g,neatoSendHome:v,neatoLocate:y,neatoClearErrors:S}=nn(),{value:E,save:C}=He("identity",{cookieUserId:""}),{value:k}=He("profile",{nickname:""}),w=m.useMemo(()=>(E?.cookieUserId||"").trim(),[E?.cookieUserId]),j=(k?.nickname||"").trim(),N=!!n?.isVerified,T=n?.verification?.pendingRequestId||null,M=n?.privateRoverAccess?.requestableRovers||[],O=n?.privateRoverAccess?.pendingRequests||[],K=String(n?.assignment?.roverId||"").trim(),[_,U]=m.useState(""),X=async F=>{const H=String(F||"").trim().toLowerCase();if(!H)throw new Error("Identity key required.");if(!fw.test(H))throw new Error("Identity key must match format: cu_ + 32 lowercase hex chars.");return C(te=>({...te||{},cookieUserId:H})),await s({cookieUserId:H,nickname:j}),H};return r.jsxs("section",{className:"space-y-2 text-base",children:[r.jsxs("div",{className:"grid gap-2 grid-cols-1 lg:grid-cols-[minmax(0,1.25fr)_minmax(0,0.9fr)]",children:[N?null:r.jsx("div",{className:"lg:col-span-2",children:r.jsx(Nw,{pendingRequestId:T,currentStoredKey:w,nickname:j,requestVerification:l,applyIdentityKey:X,onMessage:U,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:N?r.jsxs("div",{className:"space-y-2",children:[r.jsx(kw,{neato:n?.neato||null,onStart:g,onSendHome:v,onLocate:y,onClearErrors:S,fullWidth:!0}),r.jsx(Aw,{ownRoverId:K,audioForwardByRover:n?.audioForward||{},playUploadedAudio:f,stopUploadedAudio:d,startMicWhip:h,readyMicWhip:p,stopMicWhip:x})]}):r.jsx("section",{className:"surface h-full",children:r.jsx("div",{className:"flex h-full flex-col items-center justify-center text-center text-xs text-slate-400",children:"Verify your account to unlock VIP controls."})})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(Cw,{requestableRovers:M,pendingRequests:O,requestPrivateRoverAccess:o,onMessage:U,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(ww,{currentStoredKey:w,applyIdentityKey:X,onMessage:U,fullWidth:!0})})]}),_?r.jsx("div",{className:_o,children:r.jsx("p",{className:"text-xs text-slate-400 text-center",children:_})}):null]})}const Mw=420,Rw=1200,qw={1:262,2:330,3:392,4:523};function jo(){const{session:n}=nn(),s=tn(),{value:l}=He("audio",ct),o=Number.isFinite(l?.masterVolume)?l.masterVolume:ct.masterVolume,f=Number.isFinite(l?.alertVolume)?l.alertVolume:ct.alertVolume,d=Math.max(0,Math.min(1,o*f)),h=m.useMemo(()=>{const k=Array.isArray(n?.buttonBox?.buttons)?n.buttonBox.buttons:[];return k.length===4?k:[1,2,3,4].map(w=>k.find(j=>Number(j?.id)===w)||{id:w,count:0,goal:0,rewardName:null,rewardId:null,rewardNumber:null,lastRewardAt:null})},[n?.buttonBox?.buttons]),[p,x]=m.useState({}),[g,v]=m.useState({}),y=m.useRef(new Map),S=m.useRef(new Map),E=m.useRef({}),C=m.useRef(null);return m.useEffect(()=>{const k={};h.forEach(j=>{k[j.id]=Number(j.lastRewardAt||0)});const w=E.current||{};h.forEach(j=>{const N=Number(j.id),T=k[N]||0,M=Number(w[N]||0);if(T>0&&T!==M){v(_=>({..._,[N]:!0}));const O=S.current.get(N);O&&clearTimeout(O);const K=setTimeout(()=>{v(_=>({..._,[N]:!1})),S.current.delete(N)},Rw);S.current.set(N,K)}}),E.current=k},[h]),m.useEffect(()=>{function k(j){const N=qw[j];if(!N||d<=0)return;let T=C.current;if(!T){const _=window.AudioContext||window.webkitAudioContext;if(!_)return;T=new _,C.current=T}const M=T.createOscillator(),O=T.createGain();M.type="square",M.frequency.value=N;const K=.14*d;O.gain.setValueAtTime(1e-4,T.currentTime),O.gain.exponentialRampToValueAtTime(Math.max(1e-4,K),T.currentTime+.01),O.gain.exponentialRampToValueAtTime(1e-4,T.currentTime+.2),M.connect(O),O.connect(T.destination),M.start(),M.stop(T.currentTime+.21)}function w(j={}){const N=Number(j.buttonId);if(!Number.isFinite(N)||N<1||N>4)return;x(O=>({...O,[N]:!0}));const T=y.current.get(N);T&&clearTimeout(T);const M=setTimeout(()=>{x(O=>({...O,[N]:!1})),y.current.delete(N)},Mw);y.current.set(N,M),k(N)}return s.on("buttonBox:increment",w),()=>{s.off("buttonBox:increment",w)}},[d,s]),r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsx("header",{className:"panel-muted text-center text-sm",children:r.jsx("p",{children:"Button Box"})}),r.jsx("div",{className:"grid grid-cols-4 gap-0.5",children:h.map(k=>{const w=Number(k.id),j=Number.isFinite(k.count)?k.count:0,N=Number.isFinite(k.goal)?k.goal:0,T=typeof k.rewardName=="string"&&k.rewardName.trim()?k.rewardName.trim():"Unassigned",M=Number.isFinite(k.rewardNumber)?k.rewardNumber:"?",O=!!p[w],K=!!g[w];return r.jsx(xg,{buttonId:w,count:j,goal:N,rewardNumber:M,rewardName:T,className:[O?"bg-cyan-900/45":"",K?"bg-fuchsia-900/45":""].filter(Boolean).join(" ")},w)})})]})}function Tw(){const{state:{roverId:n}}=_t(),l=ml(n)?.sensors||{};return r.jsx("section",{className:"panel-section",children:r.jsx("div",{className:"aspect-square w-full",children:r.jsx(Hf,{sensors:l})})})}function Dw(){const{state:{roverId:n,keymap:s,camera:l,horn:o},pipeline:f,actions:{setServoAngle:d,setNightVision:h,startHorn:p,stopHorn:x}}=_t(),g=qg(n),v=g.docked&&!g.driving,y=l?.config,S=!!(n&&l?.enabled&&y),E=!!(n&&f?.nightVision),C=f?.nightVisionState,k=!!(n&&f?.horn),w=o?.overheated,j=typeof y?.minAngle=="number"?y.minAngle:-30,N=typeof y?.maxAngle=="number"?y.maxAngle:30,T=typeof l?.angle=="number"?l.angle:typeof y?.homeAngle=="number"?y.homeAngle:(j+N)/2,M=An(s?.nightVisionToggle?.[0]),O=An(s?.hornHonk?.[0]),K=An(s?.cameraUp?.[0]),_=An(s?.cameraDown?.[0]);return r.jsxs("section",{className:"panel-section grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto] gap-0.5",children:[r.jsx(Tg,{layout:"desktop",expand:!0,driveDockState:g}),v?null:r.jsxs("div",{className:"surface space-y-0.5 p-0 text-sm text-slate-200",children:[E&&r.jsx(Dg,{nightVisionOn:C?.nightVisionOn,disabled:!n,onToggle:h,keyLabel:M}),k&&r.jsx(_g,{disabled:!n||w,onStart:p,onStop:x,keyLabel:O,active:o?.active,heat:o?.heat}),S&&r.jsx(Bg,{value:T,min:j,max:N,onChange:d,keyDownLabel:_,keyUpLabel:K,className:"space-y-0.5 px-1 py-1",labelRowClass:"text-xs text-slate-300",labelClass:"",valueClass:"font-mono text-slate-100",sliderClass:"w-full",accentClass:"accent-emerald-400",endpointClass:"text-[0.7rem] text-slate-400"})]})]})}function _w({layout:n,onOpenHelpOverlay:s}){const l=ft(E=>E.session),{state:o}=_t(),{value:f}=He("vipAudio",{openMicEnabled:!1,pttMode:"live"}),d=l?.isVerified?"bg-emerald-400":"bg-red-600",h=String(l?.assignment?.roverId||"").trim(),p=h?l?.audioForward?.[h]:null,x=!!o?.mic?.pttActive,g=!!f?.openMicEnabled,v=f?.pttMode==="clip"?"clip":"live",y=!!(h&&l?.isVerified&&(v==="clip"?x:g||x)),S=!!(h&&l?.isVerified&&v==="clip"&&p?.source==="upload"&&p?.state==="playing");return r.jsx("section",{className:"panel text-base",children:r.jsxs(yd,{defaultTab:"telemetry",children:[r.jsxs(Sd,{children:[r.jsx(Wt,{id:"telemetry",children:"Controls"}),r.jsx(Wt,{id:"vip",highlight:S?"green":y?"pink":"none",children:r.jsxs("span",{className:"inline-flex items-center gap-2",children:[r.jsx("span",{children:"VIP"}),r.jsx("span",{className:`inline-block h-3 w-3 rounded-full ${d}`,"aria-hidden":"true",title:l?.isVerified?"Verified":"Not verified"})]})}),r.jsx(Wt,{id:"help",children:"Help"}),r.jsx(Wt,{id:"settings",children:"Settings"})]}),r.jsxs(jd,{children:[r.jsx(en,{id:"telemetry",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"grid items-stretch gap-0.5 grid-cols-[minmax(0,1.35fr)_minmax(0,0.95fr)]",children:[r.jsx(Tw,{}),r.jsx(Dw,{})]}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.9fr)_minmax(0,0.75fr)]",children:[r.jsx(Do,{}),r.jsx(ad,{panelId:"replay-sources-desktop",fillHeight:!0}),r.jsx(sw,{})]}),r.jsxs("div",{className:"grid items-stretch gap-0.5 grid-cols-[minmax(0,1.3fr)_minmax(0,0.22fr)] h-[14rem]",children:[r.jsx(qo,{fillHeight:!0}),r.jsxs("div",{className:"grid min-h-0 gap-0.5 grid-rows-[minmax(0,1fr)_auto]",children:[r.jsx(So,{compact:!0,hideNicknameForm:!0,fillHeight:!0}),r.jsx(aw,{compact:!0})]})]}),r.jsx(Hg,{}),r.jsx(jo,{}),r.jsx(fd,{defaultOrientation:"horizontal",panelId:"rightpane-telemetry"})]})}),r.jsx(en,{id:"vip",keepMounted:!0,children:r.jsx(Jg,{})}),r.jsx(en,{id:"help",children:r.jsx(Kg,{layout:n,onOpenOverlay:s})}),r.jsx(en,{id:"settings",children:r.jsx(Fg,{})})]})]})})}const Bw=new Set(["admin","lockdown","lockdown-admin"]),Ow=new Set(["lockdown","lockdown-admin"]),Lw=new Set(["admin","lockdown"]);function zw(n="admin"){return n==="lockdown"?{title:"Lockdown mode active",description:"Only the server owners can access the interface at this time."}:{title:"Admin mode active"}}function Uw(){const n=ft(S=>S.session),s=n?.mode,l=n?.role,o=n?.adminReason?.text||"";n?.adminReason?.updatedAt;const f=n?.timezone||"UTC",d=n?.socials?.find(S=>String(S?.id||S?.label||"").toLowerCase()==="discord")?.url||n?.discord?.invite||null,h=Lw.has(s),p=s==="lockdown"?Ow.has(l):Bw.has(l),[x,g]=m.useState(()=>new Date),v=m.useMemo(()=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:f,hour:"numeric",minute:"2-digit",second:"2-digit"}).format(x)}catch{return x.toLocaleTimeString()}},[x,f]);if(m.useEffect(()=>{const S=setInterval(()=>g(new Date),1e3);return()=>clearInterval(S)},[]),!h||p)return null;const y=zw(s);return r.jsx("div",{className:"pointer-events-auto fixed inset-0 z-50 flex items-center justify-center bg-black/85 px-0.5 py-0.5",children:r.jsxs("div",{className:"surface w-full max-w-md space-y-0.5 text-slate-100 shadow-2xl",children:[r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-lg font-semibold",children:y.title}),r.jsx("p",{className:"text-sm text-slate-300",children:y.description})]}),r.jsxs("div",{className:"surface-muted space-y-0.5",children:[r.jsx("p",{className:"text-[0.7rem] tracking-wide text-slate-400",children:"Reason for locking:"}),r.jsx("p",{className:"text-lg font-semibold text-slate-100",children:o||"No reason set."}),r.jsxs("p",{className:"text-center text-sm text-slate-300",children:["Server time: ",v]})]}),r.jsx("div",{className:"surface-muted",children:r.jsx(Vg,{})}),r.jsx("div",{className:"w-full justify-center items-center",children:r.jsx(hd,{id:"discord",label:"Join our Discord server for updates!",url:d})}),"You can still use the chat while the server is locked:",r.jsxs("div",{className:"max-h-80 overflow-y-auto",children:[r.jsx(qo,{}),r.jsx(To,{})]})]})})}const Hw="/assets/turn_alert-DVO8EZJa.mp3";function Vw(n,s=1){const l=m.useRef(null);return m.useEffect(()=>{l.current=new Audio(n),l.current.volume=s,l.current.load()},[n,s]),()=>{l.current&&(l.current.volume=s,l.current.currentTime=0,l.current.play().catch(()=>{}))}}function $w(){const n=ft(v=>v.session),{pushAlert:s}=wn(),{value:l}=He("audio",ct),o=Number.isFinite(l?.masterVolume)?l.masterVolume:ct.masterVolume,f=Number.isFinite(l?.alertVolume)?l.alertVolume:ct.alertVolume,d=Math.max(0,Math.min(1,o*f)),h=Vw(Hw,d),p=m.useRef(new Set),x=m.useMemo(()=>n?.turnQueues||{},[n?.turnQueues]),g=n?.socketId||null;return m.useEffect(()=>{if(!g)return;const v=[];Object.entries(x).forEach(([y,S])=>{!S||!S.current||S.current!==g||p.current.has(y)||(v.push(y),p.current.add(y))}),Object.keys(x).forEach(y=>{(!x[y]||x[y].current!==g)&&p.current.delete(y)}),v.length!==0&&(v.forEach(y=>{const S=n?.roster?.find(E=>String(E.id)===String(y))?.name||y;s({title:"Your turn!",message:`You now control ${S}.`,color:"#ff5722"})}),h())},[x,h,s,n?.roster,g]),null}function Gw({visible:n,mode:s,onEnterFullscreen:l,onDismiss:o}){if(!n)return null;const f=s==="pwa-hint";return r.jsx("div",{className:"fixed inset-0 z-40 flex items-end justify-center p-2 pointer-events-none sm:items-center",children:r.jsx("div",{className:"pointer-events-auto w-full max-w-sm rounded-lg border border-cyan-500/40 bg-zinc-950/95 shadow-xl",children:r.jsxs("div",{className:"space-y-0.5 p-4 text-sm text-slate-100",children:[r.jsx("h2",{className:"text-base font-semibold text-white",children:"Better in fullscreen"}),f?r.jsxs("p",{className:"text-slate-300",children:["For fullscreen on iOS, open Safari's share menu and pick ",r.jsx("strong",{children:"Add to Home Screen"}),". Launching from the home screen removes the browser chrome."]}):r.jsx("p",{className:"text-slate-300",children:"Enable fullscreen to free up more space for the video feed and controls. You can exit fullscreen at any time via the system back or home gesture."}),r.jsxs("div",{className:"flex justify-end gap-0.5 pt-1 text-sm",children:[r.jsx("button",{type:"button",className:"rounded border border-slate-600 px-3 py-1 text-slate-200",onClick:o,children:f?"Got it":"Not now"}),!f&&r.jsx("button",{type:"button",className:"rounded bg-cyan-500 px-3 py-1 font-semibold text-black hover:bg-cyan-400",onClick:l,children:"Enter fullscreen"})]})]})})})}function Yw({side:n="right",onClick:s}){const l=n==="left"?"left-2":"right-2";return r.jsx("button",{type:"button",onClick:s,className:`fixed bottom-2 ${l} z-30 flex h-10 w-10 items-center justify-center rounded-full border border-cyan-200/50 bg-slate-900/70 text-cyan-100 shadow-lg backdrop-blur-sm transition hover:bg-slate-800/80 active:scale-95`,"aria-label":"Enter fullscreen",title:"Enter fullscreen",children:r.jsx("svg",{viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true",className:"pointer-events-none",children:r.jsx("path",{d:"M4 9V4h5M15 4h5v5M20 15v5h-5M9 20H4v-5",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})}const Pg="fullscreenPromptDismissed",Fw=new Set(["mobile-portrait","mobile-landscape"]),Wg=()=>{if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}},Xw=()=>{const n=Wg();if(!n)return!1;try{return n.getItem(Pg)==="1"}catch{return!1}},wx=()=>{const n=Wg();if(n)try{n.setItem(Pg,"1")}catch{}},Qw=()=>{if(typeof navigator>"u")return!1;const n=navigator.userAgent||navigator.platform||"";return/iphone|ipad|ipod/i.test(n)},Cx=()=>{if(typeof document>"u")return!1;const n=document;return!!(n.fullscreenEnabled||n.webkitFullscreenEnabled||n.mozFullScreenEnabled||n.msFullscreenEnabled)};function Kw(n){const s=Fw.has(n),[l,o]=m.useState(!1),[f,d]=m.useState("native"),[h,p]=m.useState(!1),x=m.useMemo(()=>Qw(),[]),g=m.useMemo(()=>Cx(),[]),v=m.useCallback(()=>{if(!s){o(!1),p(!1);return}if(!h&&Xw()){o(!1);return}if(x){d("pwa-hint"),o(!0);return}if(!Cx()){o(!1);return}if(typeof document<"u"&&document.fullscreenElement){o(!1);return}d("native"),o(!0)},[h,x,s]);m.useEffect(()=>{v()},[v]),m.useEffect(()=>{if(typeof document>"u")return;const C=()=>{if(document.fullscreenElement){p(!1),o(!1);return}v()};return document.addEventListener("fullscreenchange",C),document.addEventListener("webkitfullscreenchange",C),()=>{document.removeEventListener("fullscreenchange",C),document.removeEventListener("webkitfullscreenchange",C)}},[v]);const y=m.useCallback(()=>{wx(),p(!1),o(!1)},[]),S=m.useCallback(async()=>{if(!s||x||typeof document>"u")return!1;if(document.fullscreenElement)return!0;const C=document.documentElement;if(!C)return!1;const k=C.requestFullscreen||C.webkitRequestFullscreen||C.mozRequestFullScreen||C.msRequestFullscreen;if(!k)return!1;try{const w=k.call(C);return w&&typeof w.then=="function"&&await w,wx(),p(!1),o(!1),!0}catch(w){return console.warn("Failed to enter fullscreen",w),!1}},[x,s]),E=m.useCallback(()=>{s&&(p(!0),d(x?"pwa-hint":"native"),o(!0))},[x,s]);return m.useEffect(()=>{s||(p(!1),o(!1))},[s]),{visible:l,mode:f,isIOS:x,nativeSupported:g,enterFullscreen:S,dismiss:y,showPrompt:E}}function Zw({visible:n,layout:s,onClose:l,showOnLoad:o,onToggleShowOnLoad:f}){if(!n)return null;const{state:d}=_t(),h=p=>{const x=!p.target.checked;f?.(x)};return r.jsx("div",{className:"fixed inset-0 z-30 flex items-center justify-center bg-black/80 px-0.5 py-0.5",children:r.jsxs("div",{className:"pointer-events-auto surface w-full max-w-4xl max-h-[90vh] overflow-hidden shadow-2xl",children:[r.jsxs("div",{className:"flex items-center justify-between border-b border-slate-700 px-0.5 py-0.25 text-sm text-slate-200",children:[r.jsx("span",{className:"font-semibold",children:"Help & controls"}),r.jsxs("div",{className:"flex items-center gap-0.5 text-[0.8rem] text-slate-300",children:[r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!o,onChange:h,className:"accent-cyan-500"}),r.jsx("span",{children:"Don't show again"})]}),r.jsx("button",{type:"button",onClick:l,className:"button-dark px-2 py-0.25 text-[0.8rem]",children:"Close"})]})]}),r.jsx("div",{className:"max-h-[85vh] overflow-y-auto p-0.5",children:r.jsx(Qg,{layout:s,keymap:d?.keymap||{}})})]})})}const Iw=`aroma bagel batter beans @@ -123,4 +123,4 @@ wok yeast yogurt shrimp -fling`;function Jw(n){return n?n.charAt(0).toUpperCase()+n.slice(1):""}function Pw(){const n=String(Iw).split(/\r?\n/).map(l=>l.trim()).filter(Boolean);return n.length?(n[Math.floor(Math.random()*n.length)]||"").trim():""}function Ad(){const{setNickname:n}=wn(),{value:s,status:l,save:o}=He("profile",{nickname:""}),f=m.useRef(!1);m.useEffect(()=>{if(l!=="ready"||f.current||(s.nickname||"").trim())return;f.current=!0;const h=Jw(Pw()).slice(0,32);if(!h)return;(async()=>{try{await n(h)}catch{}finally{o({nickname:h})}})()},[o,n,l,s.nickname])}function Ww(){const n=tn(),s=ft(w=>w.connected),{identifySession:l}=wn(),{value:o,status:f,save:d}=He("identity",{cookieUserId:""}),{value:h,status:p}=He("profile",{nickname:""}),x=m.useRef(!1),g=m.useRef(null),v=m.useRef(null),y=f==="ready"&&p==="ready",S=(o?.cookieUserId||"").trim(),E=(h?.nickname||"").trim(),C=m.useCallback(()=>{v.current&&(clearTimeout(v.current),v.current=null)},[]),k=m.useCallback(async()=>{if(!(!y||!s||!n?.id||x.current)){x.current=!0;try{const j=((await l({cookieUserId:S,nickname:E}))?.cookieUserId||"").trim();j&&j!==S&&d(N=>({...N||{},cookieUserId:j})),g.current=n.id,C()}catch{C(),v.current=setTimeout(()=>{k()},2e3)}finally{x.current=!1}}},[C,s,S,l,E,y,d,n?.id]);m.useEffect(()=>{!y||!s||!n?.id||g.current!==n.id&&k()},[s,y,k,n?.id]),m.useEffect(()=>{!y||!s||!n?.id||k()},[y,s,n?.id,S,E,k]),m.useEffect(()=>{const w=()=>{n?.connected&&k()},j=()=>{typeof document>"u"||document.visibilityState!=="visible"||n?.connected&&k()};return window.addEventListener("online",w),document.addEventListener("visibilitychange",j),()=>{window.removeEventListener("online",w),document.removeEventListener("visibilitychange",j)}},[k,n?.connected]),m.useEffect(()=>()=>C(),[C])}const Sf=1e4,jf=28,e2=14;function Ao({layout:n="desktop",className:s="",dismissable:l=!0}){const{session:o}=nn(),f=o?.communityGoal?.text?String(o.communityGoal.text).trim():"",d=n==="mobile-portrait"||n==="mobile-landscape"||n==="mobile",[h,p]=m.useState(!1),[x,g]=m.useState(jf),[v,y]=m.useState(0),S=m.useRef(null),E=m.useRef(null),C=m.useRef(null);m.useEffect(()=>{if(!f){p(!1);return}if(p(!0),!d||!l)return;const N=Date.now();y(Sf);const T=setTimeout(()=>p(!1),Sf),M=setInterval(()=>{const O=Date.now()-N;y(Math.max(0,Sf-O))},250);return()=>{clearTimeout(T),clearInterval(M)}},[f,d]),m.useEffect(()=>{if(!f)return;g(jf);let N=0;const T=()=>{const O=C.current,K=E.current;if(!O||!K)return;const _=O.clientWidth;if(!_)return;const U=K.scrollWidth;if(!U)return;const X=Math.min(1,_/U),F=Math.max(e2,Math.floor(jf*X));g(F)};N=window.requestAnimationFrame(T);const M=new ResizeObserver(()=>{window.cancelAnimationFrame(N),N=window.requestAnimationFrame(T)});return S.current&&M.observe(S.current),()=>{window.cancelAnimationFrame(N),M.disconnect()}},[f]);const k=m.useMemo(()=>["panel-section flex w-full items-center justify-center",d?"rounded-none":"rounded","px-1 py-1 text-center font-semibold tracking-tight",s].filter(Boolean).join(" "),[s,d]);if(!f||!h)return null;const w=d?Math.ceil(v/1e3):null,j=l?{onClick:()=>p(!1),role:"button",tabIndex:0}:{};return r.jsx("div",{ref:S,className:k,style:{fontSize:`${x}px`,lineHeight:1.1},...j,children:r.jsxs("span",{className:"flex w-full items-stretch gap-0.5 whitespace-nowrap rounded-md",children:[r.jsxs("span",{className:"flex flex-col justify-center border-r border-slate-700/60 px-0.5 text-[0.55em] font-semibold leading-tight text-slate-400",children:[r.jsx("span",{children:"Community"}),r.jsx("span",{children:"Goal"})]}),r.jsx("span",{ref:C,className:"flex-1 overflow-hidden text-slate-100",children:r.jsx("span",{ref:E,className:"block",children:f})}),d?r.jsxs("span",{className:"flex items-center border-l border-slate-700/60 px-0.5 text-[0.55em] font-semibold uppercase tracking-wide text-slate-400",children:[w,"s"]}):null]})})}const t2=3200;function n2(n={}){const s=typeof n.rewardName=="string"&&n.rewardName.trim()?n.rewardName.trim():"Unknown Event",l=Number.isFinite(Number(n.goal))?Math.max(1,Math.floor(Number(n.goal))):0,o=Number.isFinite(Number(n.count))?Math.max(0,Math.floor(Number(n.count))):l;return{rewardName:s,goal:l,count:o,ts:Date.now()}}function ev(){const n=tn(),{value:s}=He("audio",ct),l=Number.isFinite(s?.masterVolume)?s.masterVolume:ct.masterVolume,o=Number.isFinite(s?.alertVolume)?s.alertVolume:ct.alertVolume,f=Math.max(0,Math.min(1,l*o)),[d,h]=m.useState(null),p=m.useRef(null);return m.useEffect(()=>{p.current=new Audio("/tada.mp3"),p.current.volume=f,p.current.load()},[f]),m.useEffect(()=>{let x=null;function g(){const S=p.current;S&&(S.volume=f,S.currentTime=0,S.play().catch(()=>{}))}function v(S={}){const E=n2(S);h(E),g(),x&&clearTimeout(x),x=setTimeout(()=>{h(null)},t2)}function y(S){v(S?.detail||{})}return n.on("buttonBox:rewardRun",v),window.addEventListener("buttonBox:rewardRunLocalTest",y),()=>{x&&clearTimeout(x),n.off("buttonBox:rewardRun",v),window.removeEventListener("buttonBox:rewardRunLocalTest",y)}},[f,n]),d?r.jsx("div",{className:"pointer-events-none fixed inset-0 z-[120] flex items-center justify-center bg-black/75 px-1 py-1",children:r.jsx("div",{className:"pointer-events-auto w-full max-w-2xl",children:r.jsx("div",{className:"surface rounded-none border-2 border-cyan-300 bg-amber-100/95 px-1 py-1 text-center text-black shadow-2xl",children:r.jsxs("div",{className:"flex items-center justify-center gap-1 border-2 border-blue-600 bg-yellow-100 px-0.5 py-1",children:[r.jsx("img",{src:"/party1.gif",alt:"",className:"hidden shrink-0 sm:block"}),r.jsxs("div",{children:[r.jsxs("p",{className:"font-mono text-2xl font-bold text-red-700 sm:text-3xl",children:["Running event: ",d.rewardName,"!"]}),r.jsxs("p",{className:"font-mono text-xl font-bold text-blue-800 sm:text-2xl",children:[d.count,"/",d.goal]})]}),r.jsx("img",{src:"/party2.gif",alt:"",className:"hidden shrink-0 sm:block"})]})})})}):null}function a2(){const[n,s]=m.useState(()=>typeof window>"u"||window.innerWidth>=1024?"desktop":window.innerWidth>window.innerHeight?"mobile-landscape":"mobile-portrait");return m.useEffect(()=>{function l(){if(typeof window>"u")return;const{innerWidth:o,innerHeight:f}=window;o>=1024?s("desktop"):o>f?s("mobile-landscape"):s("mobile-portrait")}return l(),window.addEventListener("resize",l),()=>window.removeEventListener("resize",l)},[]),n}function s2({layout:n,onOpenHelpOverlay:s}){return r.jsxs("div",{className:"flex h-full gap-0.5 overflow-hidden",children:[r.jsxs("div",{className:"flex min-w-0 flex-[1.22] flex-col gap-0.5 overflow-y-auto pr-0",children:[r.jsx(xd,{}),r.jsx(nj,{}),r.jsx(dd,{})]}),r.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-0.5 overflow-y-auto",children:[r.jsx(Ao,{layout:n}),r.jsx(_w,{layout:n,onOpenHelpOverlay:s})]})]})}function tv({layout:n,onOpenHelpOverlay:s,roomPanelId:l,showTelemetry:o=!0}){const f=ft(k=>k.session),{state:d}=_t(),{value:h}=He("vipAudio",{openMicEnabled:!1,pttMode:"live"}),p=f?.isVerified?"bg-emerald-400":"bg-amber-400",x=String(f?.assignment?.roverId||"").trim(),g=x?f?.audioForward?.[x]:null,v=!!d?.mic?.pttActive,y=!!h?.openMicEnabled,S=h?.pttMode==="clip"?"clip":"live",E=!!(x&&f?.isVerified&&(S==="clip"?v:y||v)),C=!!(x&&f?.isVerified&&S==="clip"&&g?.source==="upload"&&g?.state==="playing");return r.jsx("section",{className:"panel text-base",children:r.jsxs(yd,{defaultTab:"chat",children:[r.jsxs(Sd,{children:[r.jsx(Wt,{id:"chat",children:"Chat"}),r.jsx(Wt,{id:"vip",highlight:C?"green":E?"pink":"none",children:r.jsxs("span",{className:"inline-flex items-center gap-0.5",children:[r.jsx("span",{children:"VIP"}),r.jsx("span",{className:`inline-block h-1.5 w-1.5 rounded-full ${p}`,"aria-hidden":"true",title:f?.isVerified?"Verified":"Not verified"})]})}),r.jsx(Wt,{id:"roomcontrols",children:"Room Controls"}),r.jsx(Wt,{id:"help",children:"Help"}),r.jsx(Wt,{id:"settings",children:"Settings"})]}),r.jsxs(jd,{children:[r.jsx(en,{id:"chat",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(qo,{}),r.jsx(So,{})]})}),r.jsx(en,{id:"vip",keepMounted:!0,children:r.jsx(Jg,{})}),r.jsx(en,{id:"roomcontrols",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(Hg,{}),r.jsx(jo,{}),r.jsx(fd,{panelId:l})]})}),r.jsx(en,{id:"help",children:r.jsx(Kg,{layout:n,onOpenOverlay:s})}),r.jsx(en,{id:"settings",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(Fg,{}),r.jsx(dd,{})]})})]})]})})}function l2({onOpenHelpOverlay:n,swapMobileControlColumns:s=!1}){return r.jsxs("div",{className:"flex flex-col gap-0.5",children:[r.jsx(xd,{layoutFormat:"mobile-portrait"}),r.jsx(kA,{swapColumns:s}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",children:[r.jsx(ad,{panelId:"replay-sources-mobile-portrait"}),r.jsx(Do,{})]}),r.jsx(tv,{layout:"mobile-portrait",onOpenHelpOverlay:n,roomPanelId:"mobile-portrait-room"})]})}function i2({onOpenHelpOverlay:n,swapMobileControlColumns:s=!1}){const l="self-start h-[min(100svh,32rem)]",o=s?r.jsx(bo,{layout:"landscape",className:l}):r.jsx(vo,{layout:"landscape",className:l}),f=s?r.jsx(vo,{layout:"landscape",className:l}):r.jsx(bo,{layout:"landscape",className:l});return r.jsxs("div",{className:"flex flex-col gap-0.5",children:[r.jsxs("section",{className:"grid min-h-screen grid-cols-[minmax(0,0.7fr)_minmax(0,2.1fr)_minmax(0,0.7fr)] gap-0.5",children:[o,r.jsxs("div",{children:[r.jsx(xd,{layoutFormat:"mobile-landscape"}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",children:[r.jsx(ad,{panelId:"replay-sources-mobile-landscape"}),r.jsx(Do,{})]})]}),f]}),r.jsx("div",{className:"flex flex-col gap-0.5 pb-0",children:r.jsx(tv,{layout:"mobile-landscape",onOpenHelpOverlay:n,roomPanelId:"mobile-landscape-room",showTelemetry:!1})})]})}function r2(){const n=a2(),s=n==="desktop",l=Kw(n);return r.jsx("div",{className:`bg-black text-slate-100 ${s?"h-screen overflow-hidden":"min-h-screen"}`,children:r.jsx(o2,{layout:n,isDesktop:s,fullscreen:l})})}function o2({layout:n,isDesktop:s,fullscreen:l}){Ad(),Ww();const{visible:o,mode:f,isIOS:d,nativeSupported:h,enterFullscreen:p,dismiss:x,showPrompt:g}=l,{value:v,status:y,save:S}=He("help",{showOnLoad:!0}),{value:E}=He("page",{swapMobileControlColumns:!1}),C=!!E?.swapMobileControlColumns,k=C?"left":"right",w=!s&&(d||h),[j,N]=m.useState(!1);m.useEffect(()=>{y==="ready"&&N(v?.showOnLoad!==!1)},[y,v?.showOnLoad]);const T=m.useCallback(()=>N(!0),[]),M=m.useCallback(()=>N(!1),[]),O=m.useCallback(async()=>{if(d){g();return}await p()||g()},[p,d,g]),K=m.useCallback(U=>{const X=!!U;S(F=>({...F??{},showOnLoad:X})),X||N(!1)},[S]),_=m.useMemo(()=>s?r.jsx(s2,{layout:n,onOpenHelpOverlay:T}):n==="mobile-landscape"?r.jsx(i2,{onOpenHelpOverlay:T,swapMobileControlColumns:C}):r.jsx(l2,{onOpenHelpOverlay:T,swapMobileControlColumns:C}),[s,n,T,C]);return r.jsxs(Zj,{children:[r.jsx(iA,{}),r.jsx(vA,{}),r.jsxs("main",{className:`flex w-full flex-col gap-0.5 text-base ${s?"h-full overflow-hidden":""}`,children:[s?null:r.jsx(Ao,{layout:n}),_]}),r.jsx(id,{}),r.jsx(ev,{}),r.jsx($w,{}),r.jsx(Uw,{}),r.jsx(Zw,{visible:j,layout:n,onClose:M,showOnLoad:v?.showOnLoad!==!1,onToggleShowOnLoad:K}),r.jsx(Gw,{visible:o,mode:f,onEnterFullscreen:p,onDismiss:x}),w?r.jsx(Yw,{side:k,onClick:O}):null]})}function nv(){const{session:n,setRole:s,subscribeAll:l,connected:o}=nn(),[f,d]=m.useState(!1);return m.useEffect(()=>{let h=!1;async function p(){if(n?.mode==="lockdown"){d(!1);return}try{n?.role!=="spectator"&&await s("spectator"),await l(),h||d(!0)}catch(x){console.error("Failed to enter spectator mode",x),h||d(!1)}}return p(),()=>{h=!0}},[o,n?.mode,n?.role,s,l]),f}function c2(){const[n,s]=m.useState(()=>typeof window>"u"?!1:window.matchMedia("(max-aspect-ratio: 4/3)").matches);return m.useEffect(()=>{if(typeof window>"u")return;const l=window.matchMedia("(max-aspect-ratio: 4/3)"),o=f=>s(f.matches);return l.addEventListener?l.addEventListener("change",o):l.addListener(o),()=>{l.removeEventListener?l.removeEventListener("change",o):l.removeListener(o)}},[]),n}function u2({roverId:n,session:s}){const l=s?.activeDrivers?.[n]||null,f=(s?.users||[]).find(x=>x.socketId===l)?.nickname||(l?l.slice(0,6):"No driver"),d=s?.mode,h=s?.turnQueues?.[n];return d==="turns"&&h?.current?`${f} (turns)`:f}function f2({rover:n,frame:s,sessionInfo:l,videoMode:o,snapshotFeed:f,audioInfo:d,session:h}){const p=u2({roverId:n.id,session:h});return r.jsx("article",{className:"min-h-[16rem] rounded bg-zinc-900 p-0 sm:min-h-[18rem]",children:r.jsx("div",{className:"min-h-0 overflow-hidden rounded bg-black/20",children:r.jsx(wi,{sessionInfo:l,videoMode:o,snapshotFeed:f,audioSessionInfo:d,label:n.name,roverColor:n.color||null,telemetryFrame:s,batteryConfig:n.battery,hudVariant:"spectator",driverLabel:p,hudForceMap:!0,hudMapPosition:"top-center"})})})}function d2({roster:n,frames:s,videoSources:l,snapshotFeeds:o,audioSources:f,session:d,canSpectateVideo:h}){return n.length===0?r.jsx("p",{className:"col-span-full text-slate-400",children:"No rovers registered."}):r.jsx("section",{className:"grid grid-cols-1 gap-0.5 md:grid-cols-2",children:n.map(p=>r.jsx(f2,{rover:p,frame:s[p.id],sessionInfo:h&&l[p.id]||null,videoMode:h?"whep":"snapshot",snapshotFeed:h?null:o[p.id],audioInfo:f[`${p.id}-audio`],session:d,showHudMap:!0,hudMapPosition:"bottom-left"},p.id))})}function m2(){return r.jsx("section",{className:"min-h-0",children:r.jsx("div",{className:"surface min-h-[14rem] overflow-hidden",children:r.jsx(fd,{defaultOrientation:"horizontal",hideLayoutToggle:!0,hideHeader:!0,panelId:"spectator-secondary"})})})}function h2({className:n=""}){return r.jsx("div",{className:`panel ${n}`,children:r.jsx(dd,{})})}function p2(){const{session:n}=nn(),s=n?.mode==="lockdown",l=!!n?.isLocalNetwork;Ad(),nv();const o=c2(),f=td(),d=n?.roster??[],h=md(d.map(w=>w.id),{enabled:!s&&!l,version:n?.mode}),p=l?d.map(w=>({type:"rover",id:w.id,key:w.id})):[],x=Ai(p,{enabled:!s&&l,version:n?.mode}),g=d.flatMap(w=>w.media?.audioPublishUrl?[{type:"rover",id:`${w.id}-audio`,key:`${w.id}-audio`}]:[]),v=Ai(g,{enabled:!s,version:n?.mode});if(s)return r.jsx("div",{className:"flex min-h-screen items-center justify-center bg-black text-slate-200",children:r.jsxs("div",{className:"surface max-w-md space-y-0.5 p-1 text-center text-sm",children:[r.jsx("p",{className:"text-lg font-semibold text-white",children:"Spectate disabled during lockdown."}),r.jsx("p",{className:"text-slate-300",children:"Please wait until the server leaves lockdown to view streams."})]})});const y=o?"flex min-h-screen flex-col bg-black text-slate-100 md:h-screen md:overflow-hidden":"grid min-h-screen grid-cols-1 gap-0.5 bg-black text-slate-100 md:h-full md:min-h-0 md:grid-cols-[minmax(0,1fr)_18rem] lg:grid-cols-[minmax(0,1fr)_20rem]",S=o?"order-2 flex min-h-0 min-w-0 flex-1 flex-col gap-0.5 overflow-y-auto":"order-1 flex min-h-0 min-w-0 flex-col gap-0.5 md:overflow-y-auto",E=o?"order-1 grid w-full min-h-0 items-stretch gap-0.5 border-b border-slate-800/60 bg-slate-950/90 p-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.7fr)_minmax(0,1.9fr)_minmax(0,0.7fr)]":"order-2 flex min-h-0 min-w-0 flex-col gap-0.5 border-l border-slate-800/60 bg-slate-950/90 md:h-full md:overflow-y-auto",C="",k=o?"h-64":"";return r.jsxs("div",{className:"min-h-screen bg-black text-slate-100 md:h-screen md:overflow-hidden",children:[r.jsxs("main",{className:y,children:[r.jsxs("section",{className:E,children:[o?r.jsxs("div",{className:`${C} ${k} flex flex-col gap-0.5`,children:[r.jsx(Ao,{layout:"desktop",dismissable:!1,className:"text-sm"}),r.jsx(jo,{}),r.jsx("div",{className:"min-h-0 flex-1",children:r.jsx(So,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})})]}):r.jsxs("div",{className:C,children:[r.jsx(Ao,{layout:"desktop",dismissable:!1,className:"text-sm"}),r.jsx(jo,{})]}),r.jsx("div",{className:`${C} ${o?`${k} overflow-y-auto`:""}`,children:r.jsx("div",{className:"panel h-full",children:r.jsx(Do,{title:"Rovers"})})}),o?null:r.jsx("div",{className:`${C} flex-1 min-h-0`,children:r.jsx(So,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})}),r.jsx("div",{className:`${C} ${o?k:"flex-[1.1] min-h-0"}`,children:r.jsx(qo,{allowSpectatorInput:!0,hideSpectatorNotice:!0,fillHeight:!0})}),r.jsx("div",{className:`${C} ${o?k:""}`,children:r.jsx(h2,{className:`${o?"h-full":"h-40"} overflow-hidden`})})]}),r.jsxs("section",{className:S,children:[r.jsx(d2,{roster:d,frames:f,videoSources:x,snapshotFeeds:h,audioSources:v,session:n,canSpectateVideo:l}),r.jsx(m2,{})]})]}),r.jsx(id,{}),r.jsx(ev,{})]})}function x2(){return r.jsx(p2,{})}function g2({children:n}){return r.jsx("div",{className:"flex h-full w-full items-center justify-start overflow-hidden bg-black",children:r.jsx("div",{className:"relative flex items-center justify-center overflow-hidden bg-black",style:{width:"min(100%, calc(100vh * 4 / 3))",height:"min(100%, calc(100vw * 3 / 4))",maxWidth:"100%",maxHeight:"100%",aspectRatio:"4 / 3"},children:r.jsx("div",{className:"flex h-full w-full items-center justify-center overflow-hidden",children:n})})})}function v2({roverId:n,session:s}){const l=s?.activeDrivers?.[n]||null,f=(s?.users||[]).find(p=>p.socketId===l)?.nickname||(l?l.slice(0,6):"No driver"),d=s?.mode,h=s?.turnQueues?.[n];return d==="turns"&&h?.current?`${f}`:f}function b2({rover:n,frame:s}){const l=s?.sensors?.batteryChargeMah??null,o=n?.battery??null;return Ug({batteryState:n?.batteryState??null,charge:l,config:o})}function sl({children:n,className:s="",maxSize:l=1e3,minSize:o=14,style:f=void 0}){const d=m.useRef(null),h=m.useRef(null),[p,x]=m.useState(l);return m.useLayoutEffect(()=>{const g=d.current,v=h.current;if(!g||!v)return;let y=null;const S=()=>{const k=g.clientWidth;if(!k){E();return}let w=o,j=l,N=o;for(;w<=j;){const T=Math.floor((w+j)/2);v.style.fontSize=`${T}px`,v.scrollWidth<=k?(N=T,w=T+1):j=T-1}x(N)},E=()=>{y&&cancelAnimationFrame(y),y=requestAnimationFrame(S)};E();const C=new ResizeObserver(E);return C.observe(g),()=>{y&&cancelAnimationFrame(y),C.disconnect()}},[n,l,o]),r.jsx("div",{ref:d,className:"w-full min-w-0",children:r.jsx("div",{ref:h,className:`whitespace-nowrap ${s}`,style:{fontSize:`${p}px`,lineHeight:1.1,...f||{}},children:n})})}function Ex({rover:n,frame:s,driverLabel:l,sessionInfo:o,videoMode:f="snapshot",snapshotFeed:d,withDivider:h=!1,showPreview:p=!0,variant:x="stacked"}){const g=b2({rover:n,frame:s}),v=g?.available?g.percentDisplay:null,y=x==="active";return r.jsxs("div",{className:`relative flex min-w-0 flex-1 flex-col gap-4 overflow-hidden bg-black px-0 py-0 ${h?"border-r border-slate-700/60":""}`,children:[r.jsx(Hf,{visual:g,orientation:y?"vertical":"horizontal",variant:"background"}),y?r.jsxs("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col justify-between text-center",children:[r.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:r.jsx(sl,{className:"font-semibold leading-none text-white rounded border border-transparent px-1 py-[1px]",maxSize:1e3,minSize:18,style:ca(n.color,.18),children:n.name||n.id})}),l?r.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:r.jsx(sl,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:l})}):r.jsx("div",{}),r.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:r.jsx("div",{className:"relative",children:r.jsx(sl,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:v==null?"--%":`${v}%`})})})]}):r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"relative z-10 flex min-w-0 flex-col gap-1 text-center",children:[r.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:r.jsx(sl,{className:"font-semibold leading-none text-white rounded border border-transparent px-1 py-[1px]",maxSize:1e3,minSize:18,style:ca(n.color,.18),children:n.name||n.id})}),l?r.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:r.jsx(sl,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:l})}):null,r.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:r.jsx("div",{className:"relative",children:r.jsx(sl,{className:"font-semibold leading-none text-white",maxSize:80,minSize:16,children:v==null?"--%":`${v}%`})})})]}),r.jsx("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col gap-4",children:r.jsx("div",{className:"flex w-full min-w-0 flex-1 flex-col items-center gap-4",children:p?r.jsx("div",{className:"mt-auto w-full",children:r.jsx("div",{className:"w-full aspect-[4/3]",children:r.jsx(wi,{sessionInfo:o,videoMode:f,snapshotFeed:d,audioSessionInfo:null,label:n.name||n.id,roverColor:n.color||null,telemetryFrame:s,batteryConfig:n.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})})}):null})})]})]})}const y2=2e4,S2=3600*1e3;function j2(){const{session:n}=nn(),s=nv();Ad();const l=n?.mode==="lockdown",o=!!n?.isLocalNetwork,f=td(),d=n?.roster??[],[h,p]=m.useState(0),x=n?.activeDrivers||{},g=m.useMemo(()=>d.filter(F=>x[F.id]),[d,x]),v=g.length?g:d,y=md(v.map(F=>F.id),{enabled:!l&&!o,version:n?.mode}),S=m.useMemo(()=>o?v.map(F=>({type:"rover",id:F.id,key:F.id})):[],[o,v]),E=Ai(S,{enabled:!l&&o,version:n?.mode}),C=m.useMemo(()=>g.flatMap(F=>{if(!F?.id||!F.media?.audioPublishUrl)return[];const H=String(F.id);return[{type:"rover",id:`${H}-audio`,key:`${H}-audio`}]}),[g]),k=Ai(C,{enabled:!l,version:n?.mode}),w=m.useMemo(()=>{if(!g.length)return[];if(!o){const H=g.filter(te=>y[te.id]?.objectUrl);return H.length?H:g}const F=g.filter(H=>{const te=E[H.id];return te?.url&&!te?.error});return F.length?F:g},[g,y,E,o]),j=m.useMemo(()=>w.map(F=>({type:"rover",rover:F})),[w]),N=m.useMemo(()=>j.map(F=>`r:${F.rover.id}`).join("|"),[j]);m.useEffect(()=>{p(0)},[N]),m.useEffect(()=>{if(!j.length)return;const F=setInterval(()=>{p(H=>(H+1)%j.length)},y2);return()=>clearInterval(F)},[j.length,N]);const T=j.length?j[h%j.length]:null,M=T?.type==="rover"?T.rover:null,O=!o&&M&&y[M.id]||null,K=o&&M&&E[M.id]||null,_=M&&k[`${M.id}-audio`]||null,U=M&&f[M.id]||null,X=M?v2({roverId:M.id,session:n}):null;return l?r.jsx("div",{className:"relative flex h-screen w-screen items-center justify-center bg-black text-slate-200",children:r.jsxs("div",{className:"surface max-w-sm space-y-0.5 p-1 text-center text-sm",children:[r.jsx("p",{className:"text-lg font-semibold text-white",children:"Mini spectator is disabled in lockdown."}),r.jsx("p",{className:"text-slate-300",children:"It will automatically resume once lockdown ends."})]})}):g.length?r.jsxs("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:[r.jsx("section",{className:"relative flex h-full shrink-0 items-center justify-start overflow-hidden bg-black",style:{width:"min(100vw, calc(100vh * 4 / 3))"},children:s?M?r.jsx(g2,{children:o?r.jsx("div",{className:"relative h-full w-full",children:j.map(F=>{const H=F.rover,te=M?.id===H.id;return r.jsx("div",{className:`absolute inset-0 ${te?"opacity-100":"opacity-0 pointer-events-none"}`,children:r.jsx(wi,{sessionInfo:E[H.id]||null,videoMode:"whep",snapshotFeed:null,audioSessionInfo:te?_:null,forceMute:!te,label:H.name||H.id,roverColor:H.color||null,telemetryFrame:f[H.id]||null,batteryConfig:H.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})},H.id)})}):r.jsx(wi,{sessionInfo:null,videoMode:"snapshot",snapshotFeed:O,audioSessionInfo:_,label:M.name||M.id,roverColor:M.color||null,telemetryFrame:U,batteryConfig:M.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:g.length?"No sources available.":"No active drivers."}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"Switching to spectator…"})}),r.jsx("aside",{className:"flex h-full min-w-0 flex-1 flex-col border-l border-slate-800/60 bg-black",children:M?r.jsx(Ex,{rover:M,frame:U,driverLabel:X,sessionInfo:o?K:null,videoMode:o?"whep":"snapshot",snapshotFeed:o?null:y[M.id]||null,showPreview:!1,variant:"active"}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No active rover."})})]}):r.jsx("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:r.jsx("section",{className:"flex h-full w-full gap-x-3 bg-slate-900 px-0",children:d.length?d.map(F=>r.jsx(Ex,{rover:F,frame:f[F.id]||null,driverLabel:null,sessionInfo:o&&E[F.id]||null,videoMode:o?"whep":"snapshot",snapshotFeed:o?null:y[F.id]||null,showPreview:!0,withDivider:!1},F.id)):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No rovers available."})})})}function A2(){return m.useEffect(()=>{if(typeof window>"u")return;const n=setTimeout(()=>{const s=new URL(window.location.href);s.searchParams.set("refresh",Date.now().toString()),window.location.replace(s.toString())},S2);return()=>clearTimeout(n)},[]),r.jsxs(r.Fragment,{children:[r.jsx(j2,{}),r.jsx(id,{scale:3})]})}function to(n){if(!n||!n.length)return null;const s=Math.floor(Math.random()*n.length);return n[s]||null}function N2(){if(typeof document>"u"||!document.body)return;const n=document.body.getElementsByTagName("*");if(!n||n.length<2)return;const s=to(n),l=to(n),o=s?.classList?.[0]||null;if(o&&l?.classList)try{l.classList.add(o)}catch{}const f=to(n),d=to(n),h=f?.classList?.[1]||null;if(h&&d?.classList)try{d.classList.add(h)}catch{}}function w2(){const n=ft(s=>!!s.session?.moderation?.isDeterred);return m.useEffect(()=>{if(!n)return;const s=window.setInterval(()=>{N2()},1);return()=>{window.clearInterval(s)}},[n]),null}Ny.createRoot(document.getElementById("root")).render(r.jsx(m.StrictMode,{children:r.jsx(QS,{children:r.jsx(JS,{children:r.jsx(PS,{children:r.jsx(rj,{children:r.jsxs(Jj,{children:[r.jsx(w2,{}),r.jsx(U1,{children:r.jsxs(x1,{children:[r.jsx(no,{path:"/",element:r.jsx(r2,{})}),r.jsx(no,{path:"/spectate",element:r.jsx(x2,{})}),r.jsx(no,{path:"/mini",element:r.jsx(A2,{})})]})})]})})})})})})); +fling`;function Jw(n){return n?n.charAt(0).toUpperCase()+n.slice(1):""}function Pw(){const n=String(Iw).split(/\r?\n/).map(l=>l.trim()).filter(Boolean);return n.length?(n[Math.floor(Math.random()*n.length)]||"").trim():""}function Ad(){const{setNickname:n}=wn(),{value:s,status:l,save:o}=He("profile",{nickname:""}),f=m.useRef(!1);m.useEffect(()=>{if(l!=="ready"||f.current||(s.nickname||"").trim())return;f.current=!0;const h=Jw(Pw()).slice(0,32);if(!h)return;(async()=>{try{await n(h)}catch{}finally{o({nickname:h})}})()},[o,n,l,s.nickname])}function Ww(){const n=tn(),s=ft(w=>w.connected),{identifySession:l}=wn(),{value:o,status:f,save:d}=He("identity",{cookieUserId:""}),{value:h,status:p}=He("profile",{nickname:""}),x=m.useRef(!1),g=m.useRef(null),v=m.useRef(null),y=f==="ready"&&p==="ready",S=(o?.cookieUserId||"").trim(),E=(h?.nickname||"").trim(),C=m.useCallback(()=>{v.current&&(clearTimeout(v.current),v.current=null)},[]),k=m.useCallback(async()=>{if(!(!y||!s||!n?.id||x.current)){x.current=!0;try{const j=((await l({cookieUserId:S,nickname:E}))?.cookieUserId||"").trim();j&&j!==S&&d(N=>({...N||{},cookieUserId:j})),g.current=n.id,C()}catch{C(),v.current=setTimeout(()=>{k()},2e3)}finally{x.current=!1}}},[C,s,S,l,E,y,d,n?.id]);m.useEffect(()=>{!y||!s||!n?.id||g.current!==n.id&&k()},[s,y,k,n?.id]),m.useEffect(()=>{!y||!s||!n?.id||k()},[y,s,n?.id,S,E,k]),m.useEffect(()=>{const w=()=>{n?.connected&&k()},j=()=>{typeof document>"u"||document.visibilityState!=="visible"||n?.connected&&k()};return window.addEventListener("online",w),document.addEventListener("visibilitychange",j),()=>{window.removeEventListener("online",w),document.removeEventListener("visibilitychange",j)}},[k,n?.connected]),m.useEffect(()=>()=>C(),[C])}const Sf=1e4,jf=28,e2=14;function Ao({layout:n="desktop",className:s="",dismissable:l=!0}){const{session:o}=nn(),f=o?.communityGoal?.text?String(o.communityGoal.text).trim():"",d=n==="mobile-portrait"||n==="mobile-landscape"||n==="mobile",[h,p]=m.useState(!1),[x,g]=m.useState(jf),[v,y]=m.useState(0),S=m.useRef(null),E=m.useRef(null),C=m.useRef(null);m.useEffect(()=>{if(!f){p(!1);return}if(p(!0),!d||!l)return;const N=Date.now();y(Sf);const T=setTimeout(()=>p(!1),Sf),M=setInterval(()=>{const O=Date.now()-N;y(Math.max(0,Sf-O))},250);return()=>{clearTimeout(T),clearInterval(M)}},[f,d]),m.useEffect(()=>{if(!f)return;g(jf);let N=0;const T=()=>{const O=C.current,K=E.current;if(!O||!K)return;const _=O.clientWidth;if(!_)return;const U=K.scrollWidth;if(!U)return;const X=Math.min(1,_/U),F=Math.max(e2,Math.floor(jf*X));g(F)};N=window.requestAnimationFrame(T);const M=new ResizeObserver(()=>{window.cancelAnimationFrame(N),N=window.requestAnimationFrame(T)});return S.current&&M.observe(S.current),()=>{window.cancelAnimationFrame(N),M.disconnect()}},[f]);const k=m.useMemo(()=>["panel-section flex w-full items-center justify-center",d?"rounded-none":"rounded","px-1 py-1 text-center font-semibold tracking-tight",s].filter(Boolean).join(" "),[s,d]);if(!f||!h)return null;const w=d?Math.ceil(v/1e3):null,j=l?{onClick:()=>p(!1),role:"button",tabIndex:0}:{};return r.jsx("div",{ref:S,className:k,style:{fontSize:`${x}px`,lineHeight:1.1},...j,children:r.jsxs("span",{className:"flex w-full items-stretch gap-0.5 whitespace-nowrap rounded-md",children:[r.jsxs("span",{className:"flex flex-col justify-center border-r border-slate-700/60 px-0.5 text-[0.55em] font-semibold leading-tight text-slate-400",children:[r.jsx("span",{children:"Community"}),r.jsx("span",{children:"Goal"})]}),r.jsx("span",{ref:C,className:"flex-1 overflow-hidden text-slate-100",children:r.jsx("span",{ref:E,className:"block",children:f})}),d?r.jsxs("span",{className:"flex items-center border-l border-slate-700/60 px-0.5 text-[0.55em] font-semibold uppercase tracking-wide text-slate-400",children:[w,"s"]}):null]})})}const t2=3200;function n2(n={}){const s=typeof n.rewardName=="string"&&n.rewardName.trim()?n.rewardName.trim():"Unknown Event",l=Number.isFinite(Number(n.goal))?Math.max(1,Math.floor(Number(n.goal))):0,o=Number.isFinite(Number(n.count))?Math.max(0,Math.floor(Number(n.count))):l;return{rewardName:s,goal:l,count:o,ts:Date.now()}}function ev(){const n=tn(),{value:s}=He("audio",ct),l=Number.isFinite(s?.masterVolume)?s.masterVolume:ct.masterVolume,o=Number.isFinite(s?.alertVolume)?s.alertVolume:ct.alertVolume,f=Math.max(0,Math.min(1,l*o)),[d,h]=m.useState(null),p=m.useRef(null);return m.useEffect(()=>{p.current=new Audio("/tada.mp3"),p.current.volume=f,p.current.load()},[f]),m.useEffect(()=>{let x=null;function g(){const S=p.current;S&&(S.volume=f,S.currentTime=0,S.play().catch(()=>{}))}function v(S={}){const E=n2(S);h(E),g(),x&&clearTimeout(x),x=setTimeout(()=>{h(null)},t2)}function y(S){v(S?.detail||{})}return n.on("buttonBox:rewardRun",v),window.addEventListener("buttonBox:rewardRunLocalTest",y),()=>{x&&clearTimeout(x),n.off("buttonBox:rewardRun",v),window.removeEventListener("buttonBox:rewardRunLocalTest",y)}},[f,n]),d?r.jsx("div",{className:"pointer-events-none fixed inset-0 z-[120] flex items-center justify-center bg-black/75 px-1 py-1",children:r.jsx("div",{className:"pointer-events-auto w-full max-w-2xl",children:r.jsx("div",{className:"surface rounded-none border-2 border-cyan-300 bg-amber-100/95 px-1 py-1 text-center text-black shadow-2xl",children:r.jsxs("div",{className:"flex items-center justify-center gap-1 border-2 border-blue-600 bg-yellow-100 px-0.5 py-1",children:[r.jsx("img",{src:"/party1.gif",alt:"",className:"hidden shrink-0 sm:block"}),r.jsxs("div",{children:[r.jsxs("p",{className:"font-mono text-2xl font-bold text-red-700 sm:text-3xl",children:["Running event: ",d.rewardName,"!"]}),r.jsxs("p",{className:"font-mono text-xl font-bold text-blue-800 sm:text-2xl",children:[d.count,"/",d.goal]})]}),r.jsx("img",{src:"/party2.gif",alt:"",className:"hidden shrink-0 sm:block"})]})})})}):null}function a2(){const[n,s]=m.useState(()=>typeof window>"u"||window.innerWidth>=1024?"desktop":window.innerWidth>window.innerHeight?"mobile-landscape":"mobile-portrait");return m.useEffect(()=>{function l(){if(typeof window>"u")return;const{innerWidth:o,innerHeight:f}=window;o>=1024?s("desktop"):o>f?s("mobile-landscape"):s("mobile-portrait")}return l(),window.addEventListener("resize",l),()=>window.removeEventListener("resize",l)},[]),n}function s2({layout:n,onOpenHelpOverlay:s}){return r.jsxs("div",{className:"flex h-full gap-0.5 overflow-hidden",children:[r.jsxs("div",{className:"flex min-w-0 flex-[1.22] flex-col gap-0.5 overflow-y-auto pr-0",children:[r.jsx(xd,{}),r.jsx(nj,{}),r.jsx(dd,{})]}),r.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-0.5 overflow-y-auto",children:[r.jsx(Ao,{layout:n}),r.jsx(_w,{layout:n,onOpenHelpOverlay:s})]})]})}function tv({layout:n,onOpenHelpOverlay:s,roomPanelId:l,showTelemetry:o=!0}){const f=ft(k=>k.session),{state:d}=_t(),{value:h}=He("vipAudio",{openMicEnabled:!1,pttMode:"live"}),p=f?.isVerified?"bg-emerald-400":"bg-amber-400",x=String(f?.assignment?.roverId||"").trim(),g=x?f?.audioForward?.[x]:null,v=!!d?.mic?.pttActive,y=!!h?.openMicEnabled,S=h?.pttMode==="clip"?"clip":"live",E=!!(x&&f?.isVerified&&(S==="clip"?v:y||v)),C=!!(x&&f?.isVerified&&S==="clip"&&g?.source==="upload"&&g?.state==="playing");return r.jsx("section",{className:"panel text-base",children:r.jsxs(yd,{defaultTab:"chat",children:[r.jsxs(Sd,{children:[r.jsx(Wt,{id:"chat",children:"Chat"}),r.jsx(Wt,{id:"vip",highlight:C?"green":E?"pink":"none",children:r.jsxs("span",{className:"inline-flex items-center gap-0.5",children:[r.jsx("span",{children:"VIP"}),r.jsx("span",{className:`inline-block h-1.5 w-1.5 rounded-full ${p}`,"aria-hidden":"true",title:f?.isVerified?"Verified":"Not verified"})]})}),r.jsx(Wt,{id:"roomcontrols",children:"Room Controls"}),r.jsx(Wt,{id:"help",children:"Help"}),r.jsx(Wt,{id:"settings",children:"Settings"})]}),r.jsxs(jd,{children:[r.jsx(en,{id:"chat",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(qo,{}),r.jsx(So,{})]})}),r.jsx(en,{id:"vip",keepMounted:!0,children:r.jsx(Jg,{})}),r.jsx(en,{id:"roomcontrols",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(Hg,{}),r.jsx(jo,{}),r.jsx(fd,{panelId:l})]})}),r.jsx(en,{id:"help",children:r.jsx(Kg,{layout:n,onOpenOverlay:s})}),r.jsx(en,{id:"settings",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(Fg,{}),r.jsx(dd,{})]})})]})]})})}function l2({onOpenHelpOverlay:n,swapMobileControlColumns:s=!1}){return r.jsxs("div",{className:"flex flex-col gap-0.5",children:[r.jsx(xd,{layoutFormat:"mobile-portrait"}),r.jsx(kA,{swapColumns:s}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",children:[r.jsx(ad,{panelId:"replay-sources-mobile-portrait"}),r.jsx(Do,{})]}),r.jsx(tv,{layout:"mobile-portrait",onOpenHelpOverlay:n,roomPanelId:"mobile-portrait-room"})]})}function i2({onOpenHelpOverlay:n,swapMobileControlColumns:s=!1}){const l="self-start h-[min(100svh,32rem)]",o=s?r.jsx(bo,{layout:"landscape",className:l}):r.jsx(vo,{layout:"landscape",className:l}),f=s?r.jsx(vo,{layout:"landscape",className:l}):r.jsx(bo,{layout:"landscape",className:l});return r.jsxs("div",{className:"flex flex-col gap-0.5",children:[r.jsxs("section",{className:"grid min-h-screen grid-cols-[minmax(0,0.7fr)_minmax(0,2.1fr)_minmax(0,0.7fr)] gap-0.5",children:[o,r.jsxs("div",{children:[r.jsx(xd,{layoutFormat:"mobile-landscape"}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",children:[r.jsx(ad,{panelId:"replay-sources-mobile-landscape"}),r.jsx(Do,{})]})]}),f]}),r.jsx("div",{className:"flex flex-col gap-0.5 pb-0",children:r.jsx(tv,{layout:"mobile-landscape",onOpenHelpOverlay:n,roomPanelId:"mobile-landscape-room",showTelemetry:!1})})]})}function r2(){const n=a2(),s=n==="desktop",l=Kw(n);return r.jsx("div",{className:`bg-black text-slate-100 ${s?"h-screen overflow-hidden":"min-h-screen"}`,children:r.jsx(o2,{layout:n,isDesktop:s,fullscreen:l})})}function o2({layout:n,isDesktop:s,fullscreen:l}){Ad(),Ww();const{visible:o,mode:f,isIOS:d,nativeSupported:h,enterFullscreen:p,dismiss:x,showPrompt:g}=l,{value:v,status:y,save:S}=He("help",{showOnLoad:!0}),{value:E}=He("page",{swapMobileControlColumns:!1}),C=!!E?.swapMobileControlColumns,k=C?"left":"right",w=!s&&(d||h),[j,N]=m.useState(!1);m.useEffect(()=>{y==="ready"&&N(v?.showOnLoad!==!1)},[y,v?.showOnLoad]);const T=m.useCallback(()=>N(!0),[]),M=m.useCallback(()=>N(!1),[]),O=m.useCallback(async()=>{if(d){g();return}await p()||g()},[p,d,g]),K=m.useCallback(U=>{const X=!!U;S(F=>({...F??{},showOnLoad:X})),X||N(!1)},[S]),_=m.useMemo(()=>s?r.jsx(s2,{layout:n,onOpenHelpOverlay:T}):n==="mobile-landscape"?r.jsx(i2,{onOpenHelpOverlay:T,swapMobileControlColumns:C}):r.jsx(l2,{onOpenHelpOverlay:T,swapMobileControlColumns:C}),[s,n,T,C]);return r.jsxs(Zj,{children:[r.jsx(iA,{}),r.jsx(vA,{}),r.jsxs("main",{className:`flex w-full flex-col gap-0.5 text-base ${s?"h-full overflow-hidden":""}`,children:[s?null:r.jsx(Ao,{layout:n}),_]}),r.jsx(id,{}),r.jsx(ev,{}),r.jsx($w,{}),r.jsx(Uw,{}),r.jsx(Zw,{visible:j,layout:n,onClose:M,showOnLoad:v?.showOnLoad!==!1,onToggleShowOnLoad:K}),r.jsx(Gw,{visible:o,mode:f,onEnterFullscreen:p,onDismiss:x}),w?r.jsx(Yw,{side:k,onClick:O}):null]})}function nv(){const{session:n,setRole:s,subscribeAll:l,connected:o}=nn(),[f,d]=m.useState(!1);return m.useEffect(()=>{let h=!1;async function p(){if(n?.mode==="lockdown"){d(!1);return}try{n?.role!=="spectator"&&await s("spectator"),await l(),h||d(!0)}catch(x){console.error("Failed to enter spectator mode",x),h||d(!1)}}return p(),()=>{h=!0}},[o,n?.mode,n?.role,s,l]),f}function c2(){const[n,s]=m.useState(()=>typeof window>"u"?!1:window.matchMedia("(max-aspect-ratio: 4/3)").matches);return m.useEffect(()=>{if(typeof window>"u")return;const l=window.matchMedia("(max-aspect-ratio: 4/3)"),o=f=>s(f.matches);return l.addEventListener?l.addEventListener("change",o):l.addListener(o),()=>{l.removeEventListener?l.removeEventListener("change",o):l.removeListener(o)}},[]),n}function u2({roverId:n,session:s}){const l=s?.activeDrivers?.[n]||null,f=(s?.users||[]).find(x=>x.socketId===l)?.nickname||(l?l.slice(0,6):"No driver"),d=s?.mode,h=s?.turnQueues?.[n];return d==="turns"&&h?.current?`${f} (turns)`:f}function f2({rover:n,frame:s,sessionInfo:l,videoMode:o,snapshotFeed:f,audioInfo:d,session:h}){const p=u2({roverId:n.id,session:h});return r.jsx("article",{className:"min-h-[16rem] rounded bg-zinc-900 p-0 sm:min-h-[18rem]",children:r.jsx("div",{className:"min-h-0 overflow-hidden rounded bg-black/20",children:r.jsx(wi,{sessionInfo:l,videoMode:o,snapshotFeed:f,audioSessionInfo:d,label:n.name,roverColor:n.color||null,telemetryFrame:s,batteryConfig:n.battery,hudVariant:"spectator",driverLabel:p,hudForceMap:!0,hudMapPosition:"top-center"})})})}function d2({roster:n,frames:s,videoSources:l,snapshotFeeds:o,audioSources:f,session:d,canSpectateVideo:h}){return n.length===0?r.jsx("p",{className:"col-span-full text-slate-400",children:"No rovers registered."}):r.jsx("section",{className:"grid grid-cols-1 gap-0.5 md:grid-cols-2",children:n.map(p=>r.jsx(f2,{rover:p,frame:s[p.id],sessionInfo:h&&l[p.id]||null,videoMode:h?"whep":"snapshot",snapshotFeed:h?null:o[p.id],audioInfo:f[`${p.id}-audio`],session:d,showHudMap:!0,hudMapPosition:"bottom-left"},p.id))})}function m2(){return r.jsx("section",{className:"min-h-0",children:r.jsx("div",{className:"surface min-h-[14rem] overflow-hidden",children:r.jsx(fd,{defaultOrientation:"horizontal",hideLayoutToggle:!0,hideHeader:!0,panelId:"spectator-secondary"})})})}function h2({className:n=""}){return r.jsx("div",{className:`panel ${n}`,children:r.jsx(dd,{})})}function p2(){const{session:n}=nn(),s=n?.mode==="lockdown",l=!!n?.isLocalNetwork;Ad(),nv();const o=c2(),f=td(),d=n?.roster??[],h=md(d.map(w=>w.id),{enabled:!s&&!l,version:n?.mode}),p=l?d.map(w=>({type:"rover",id:w.id,key:w.id})):[],x=Ai(p,{enabled:!s&&l,version:n?.mode}),g=d.flatMap(w=>w.media?.audioPublishUrl?[{type:"rover",id:`${w.id}-audio`,key:`${w.id}-audio`}]:[]),v=Ai(g,{enabled:!s,version:n?.mode});if(s)return r.jsx("div",{className:"flex min-h-screen items-center justify-center bg-black text-slate-200",children:r.jsxs("div",{className:"surface max-w-md space-y-0.5 p-1 text-center text-sm",children:[r.jsx("p",{className:"text-lg font-semibold text-white",children:"Spectate disabled during lockdown."}),r.jsx("p",{className:"text-slate-300",children:"Please wait until the server leaves lockdown to view streams."})]})});const y=o?"flex min-h-screen flex-col bg-black text-slate-100 md:h-screen md:overflow-hidden":"grid min-h-screen grid-cols-1 gap-0.5 bg-black text-slate-100 md:h-full md:min-h-0 md:grid-cols-[minmax(0,1fr)_18rem] lg:grid-cols-[minmax(0,1fr)_20rem]",S=o?"order-2 flex min-h-0 min-w-0 flex-1 flex-col gap-0.5 overflow-y-auto":"order-1 flex min-h-0 min-w-0 flex-col gap-0.5 md:overflow-y-auto",E=o?"order-1 grid w-full min-h-0 items-stretch gap-0.5 border-b border-slate-800/60 bg-slate-950/90 p-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.7fr)_minmax(0,1.9fr)_minmax(0,0.7fr)]":"order-2 flex min-h-0 min-w-0 flex-col gap-0.5 border-l border-slate-800/60 bg-slate-950/90 md:h-full md:overflow-y-auto",C="",k=o?"h-64":"";return r.jsxs("div",{className:"min-h-screen bg-black text-slate-100 md:h-screen md:overflow-hidden",children:[r.jsxs("main",{className:y,children:[r.jsxs("section",{className:E,children:[o?r.jsxs("div",{className:`${C} ${k} flex flex-col gap-0.5`,children:[r.jsx(Ao,{layout:"desktop",dismissable:!1,className:"text-sm"}),r.jsx(jo,{}),r.jsx("div",{className:"min-h-0 flex-1",children:r.jsx(So,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})})]}):r.jsxs("div",{className:C,children:[r.jsx(Ao,{layout:"desktop",dismissable:!1,className:"text-sm"}),r.jsx(jo,{})]}),r.jsx("div",{className:`${C} ${o?`${k} overflow-y-auto`:""}`,children:r.jsx("div",{className:"panel h-full",children:r.jsx(Do,{title:"Rovers"})})}),o?null:r.jsx("div",{className:`${C} flex-1 min-h-0`,children:r.jsx(So,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})}),r.jsx("div",{className:`${C} ${o?k:"flex-[1.1] min-h-0"}`,children:r.jsx(qo,{allowSpectatorInput:!0,hideSpectatorNotice:!0,fillHeight:!0})}),r.jsx("div",{className:`${C} ${o?k:""}`,children:r.jsx(h2,{className:`${o?"h-full":"h-40"} overflow-hidden`})})]}),r.jsxs("section",{className:S,children:[r.jsx(d2,{roster:d,frames:f,videoSources:x,snapshotFeeds:h,audioSources:v,session:n,canSpectateVideo:l}),r.jsx(m2,{})]})]}),r.jsx(id,{}),r.jsx(ev,{})]})}function x2(){return r.jsx(p2,{})}function g2({children:n}){return r.jsx("div",{className:"flex h-full w-full items-center justify-start overflow-hidden bg-black",children:r.jsx("div",{className:"relative flex items-center justify-center overflow-hidden bg-black",style:{width:"min(100%, calc(100vh * 4 / 3))",height:"min(100%, calc(100vw * 3 / 4))",maxWidth:"100%",maxHeight:"100%",aspectRatio:"4 / 3"},children:r.jsx("div",{className:"flex h-full w-full items-center justify-center overflow-hidden",children:n})})})}function v2({roverId:n,session:s}){const l=s?.activeDrivers?.[n]||null,f=(s?.users||[]).find(p=>p.socketId===l)?.nickname||(l?l.slice(0,6):"No driver"),d=s?.mode,h=s?.turnQueues?.[n];return d==="turns"&&h?.current?`${f}`:f}function b2({rover:n,frame:s}){const l=s?.sensors?.batteryChargeMah??null,o=n?.battery??null;return zg({batteryState:n?.batteryState??null,charge:l,config:o})}function sl({children:n,className:s="",maxSize:l=1e3,minSize:o=14,style:f=void 0}){const d=m.useRef(null),h=m.useRef(null),[p,x]=m.useState(l);return m.useLayoutEffect(()=>{const g=d.current,v=h.current;if(!g||!v)return;let y=null;const S=()=>{const k=g.clientWidth;if(!k){E();return}let w=o,j=l,N=o;for(;w<=j;){const T=Math.floor((w+j)/2);v.style.fontSize=`${T}px`,v.scrollWidth<=k?(N=T,w=T+1):j=T-1}x(N)},E=()=>{y&&cancelAnimationFrame(y),y=requestAnimationFrame(S)};E();const C=new ResizeObserver(E);return C.observe(g),()=>{y&&cancelAnimationFrame(y),C.disconnect()}},[n,l,o]),r.jsx("div",{ref:d,className:"w-full min-w-0",children:r.jsx("div",{ref:h,className:`whitespace-nowrap ${s}`,style:{fontSize:`${p}px`,lineHeight:1.1,...f||{}},children:n})})}function Ex({rover:n,frame:s,driverLabel:l,sessionInfo:o,videoMode:f="snapshot",snapshotFeed:d,withDivider:h=!1,showPreview:p=!0,variant:x="stacked"}){const g=b2({rover:n,frame:s}),v=g?.available?g.percentDisplay:null,y=x==="active";return r.jsxs("div",{className:`relative flex min-w-0 flex-1 flex-col gap-4 overflow-hidden bg-black px-0 py-0 ${h?"border-r border-slate-700/60":""}`,children:[r.jsx(Uf,{visual:g,orientation:y?"vertical":"horizontal",variant:"background"}),y?r.jsxs("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col justify-between text-center",children:[r.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:r.jsx(sl,{className:"font-semibold leading-none text-white rounded border border-transparent px-1 py-[1px]",maxSize:1e3,minSize:18,style:ca(n.color,.18),children:n.name||n.id})}),l?r.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:r.jsx(sl,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:l})}):r.jsx("div",{}),r.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:r.jsx("div",{className:"relative",children:r.jsx(sl,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:v==null?"--%":`${v}%`})})})]}):r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"relative z-10 flex min-w-0 flex-col gap-1 text-center",children:[r.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:r.jsx(sl,{className:"font-semibold leading-none text-white rounded border border-transparent px-1 py-[1px]",maxSize:1e3,minSize:18,style:ca(n.color,.18),children:n.name||n.id})}),l?r.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:r.jsx(sl,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:l})}):null,r.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:r.jsx("div",{className:"relative",children:r.jsx(sl,{className:"font-semibold leading-none text-white",maxSize:80,minSize:16,children:v==null?"--%":`${v}%`})})})]}),r.jsx("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col gap-4",children:r.jsx("div",{className:"flex w-full min-w-0 flex-1 flex-col items-center gap-4",children:p?r.jsx("div",{className:"mt-auto w-full",children:r.jsx("div",{className:"w-full aspect-[4/3]",children:r.jsx(wi,{sessionInfo:o,videoMode:f,snapshotFeed:d,audioSessionInfo:null,label:n.name||n.id,roverColor:n.color||null,telemetryFrame:s,batteryConfig:n.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})})}):null})})]})]})}const y2=2e4,S2=3600*1e3;function j2(){const{session:n}=nn(),s=nv();Ad();const l=n?.mode==="lockdown",o=!!n?.isLocalNetwork,f=td(),d=n?.roster??[],[h,p]=m.useState(0),x=n?.activeDrivers||{},g=m.useMemo(()=>d.filter(F=>x[F.id]),[d,x]),v=g.length?g:d,y=md(v.map(F=>F.id),{enabled:!l&&!o,version:n?.mode}),S=m.useMemo(()=>o?v.map(F=>({type:"rover",id:F.id,key:F.id})):[],[o,v]),E=Ai(S,{enabled:!l&&o,version:n?.mode}),C=m.useMemo(()=>g.flatMap(F=>{if(!F?.id||!F.media?.audioPublishUrl)return[];const H=String(F.id);return[{type:"rover",id:`${H}-audio`,key:`${H}-audio`}]}),[g]),k=Ai(C,{enabled:!l,version:n?.mode}),w=m.useMemo(()=>{if(!g.length)return[];if(!o){const H=g.filter(te=>y[te.id]?.objectUrl);return H.length?H:g}const F=g.filter(H=>{const te=E[H.id];return te?.url&&!te?.error});return F.length?F:g},[g,y,E,o]),j=m.useMemo(()=>w.map(F=>({type:"rover",rover:F})),[w]),N=m.useMemo(()=>j.map(F=>`r:${F.rover.id}`).join("|"),[j]);m.useEffect(()=>{p(0)},[N]),m.useEffect(()=>{if(!j.length)return;const F=setInterval(()=>{p(H=>(H+1)%j.length)},y2);return()=>clearInterval(F)},[j.length,N]);const T=j.length?j[h%j.length]:null,M=T?.type==="rover"?T.rover:null,O=!o&&M&&y[M.id]||null,K=o&&M&&E[M.id]||null,_=M&&k[`${M.id}-audio`]||null,U=M&&f[M.id]||null,X=M?v2({roverId:M.id,session:n}):null;return l?r.jsx("div",{className:"relative flex h-screen w-screen items-center justify-center bg-black text-slate-200",children:r.jsxs("div",{className:"surface max-w-sm space-y-0.5 p-1 text-center text-sm",children:[r.jsx("p",{className:"text-lg font-semibold text-white",children:"Mini spectator is disabled in lockdown."}),r.jsx("p",{className:"text-slate-300",children:"It will automatically resume once lockdown ends."})]})}):g.length?r.jsxs("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:[r.jsx("section",{className:"relative flex h-full shrink-0 items-center justify-start overflow-hidden bg-black",style:{width:"min(100vw, calc(100vh * 4 / 3))"},children:s?M?r.jsx(g2,{children:o?r.jsx("div",{className:"relative h-full w-full",children:j.map(F=>{const H=F.rover,te=M?.id===H.id;return r.jsx("div",{className:`absolute inset-0 ${te?"opacity-100":"opacity-0 pointer-events-none"}`,children:r.jsx(wi,{sessionInfo:E[H.id]||null,videoMode:"whep",snapshotFeed:null,audioSessionInfo:te?_:null,forceMute:!te,label:H.name||H.id,roverColor:H.color||null,telemetryFrame:f[H.id]||null,batteryConfig:H.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})},H.id)})}):r.jsx(wi,{sessionInfo:null,videoMode:"snapshot",snapshotFeed:O,audioSessionInfo:_,label:M.name||M.id,roverColor:M.color||null,telemetryFrame:U,batteryConfig:M.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:g.length?"No sources available.":"No active drivers."}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"Switching to spectator…"})}),r.jsx("aside",{className:"flex h-full min-w-0 flex-1 flex-col border-l border-slate-800/60 bg-black",children:M?r.jsx(Ex,{rover:M,frame:U,driverLabel:X,sessionInfo:o?K:null,videoMode:o?"whep":"snapshot",snapshotFeed:o?null:y[M.id]||null,showPreview:!1,variant:"active"}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No active rover."})})]}):r.jsx("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:r.jsx("section",{className:"flex h-full w-full gap-x-3 bg-slate-900 px-0",children:d.length?d.map(F=>r.jsx(Ex,{rover:F,frame:f[F.id]||null,driverLabel:null,sessionInfo:o&&E[F.id]||null,videoMode:o?"whep":"snapshot",snapshotFeed:o?null:y[F.id]||null,showPreview:!0,withDivider:!1},F.id)):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No rovers available."})})})}function A2(){return m.useEffect(()=>{if(typeof window>"u")return;const n=setTimeout(()=>{const s=new URL(window.location.href);s.searchParams.set("refresh",Date.now().toString()),window.location.replace(s.toString())},S2);return()=>clearTimeout(n)},[]),r.jsxs(r.Fragment,{children:[r.jsx(j2,{}),r.jsx(id,{scale:3})]})}function to(n){if(!n||!n.length)return null;const s=Math.floor(Math.random()*n.length);return n[s]||null}function N2(){if(typeof document>"u"||!document.body)return;const n=document.body.getElementsByTagName("*");if(!n||n.length<2)return;const s=to(n),l=to(n),o=s?.classList?.[0]||null;if(o&&l?.classList)try{l.classList.add(o)}catch{}const f=to(n),d=to(n),h=f?.classList?.[1]||null;if(h&&d?.classList)try{d.classList.add(h)}catch{}}function w2(){const n=ft(s=>!!s.session?.moderation?.isDeterred);return m.useEffect(()=>{if(!n)return;const s=window.setInterval(()=>{N2()},1);return()=>{window.clearInterval(s)}},[n]),null}Ny.createRoot(document.getElementById("root")).render(r.jsx(m.StrictMode,{children:r.jsx(QS,{children:r.jsx(JS,{children:r.jsx(PS,{children:r.jsx(rj,{children:r.jsxs(Jj,{children:[r.jsx(w2,{}),r.jsx(U1,{children:r.jsxs(x1,{children:[r.jsx(no,{path:"/",element:r.jsx(r2,{})}),r.jsx(no,{path:"/spectate",element:r.jsx(x2,{})}),r.jsx(no,{path:"/mini",element:r.jsx(A2,{})})]})})]})})})})})})); diff --git a/server/public/index.html b/server/public/index.html index 0c3a6a49..635ab842 100644 --- a/server/public/index.html +++ b/server/public/index.html @@ -11,7 +11,7 @@ Multi Roomba Rover - + diff --git a/webui/src/components/VideoTile.jsx b/webui/src/components/VideoTile.jsx index 47ecf907..ac8130da 100644 --- a/webui/src/components/VideoTile.jsx +++ b/webui/src/components/VideoTile.jsx @@ -1,21 +1,25 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { WhepPlayer } from '../lib/whepPlayer.js'; -import TopDownMap from './TopDownMap.jsx'; import { useHudMapSetting } from '../hooks/useHudMapSetting.js'; -import { useChat } from '../context/ChatContext.jsx'; import { useSessionSelector } from '../context/SessionContext.jsx'; import { useSettingsNamespace } from '../settings/index.js'; import { AUDIO_SETTINGS_DEFAULTS } from '../settings/namespaces.js'; import SocialButton from './SocialButton.jsx'; import BatteryBar from './BatteryBar.jsx'; import { buildBatteryVisual } from '../lib/battery.js'; -import { roverNameChromeStyle } from '../lib/roverColor.js'; - -const RESTART_DELAY_MS = 2000; -const UNMUTE_RETRY_MS = 3000; -const AUDIO_RETRY_MS = 3000; -const BRUSH_CURRENT_THRESHOLD_MA = 40; -const DUCK_RELEASE_FADE_MS = 1000; +import TurnCueOverlay from './VideoTile/TurnCueOverlay.jsx'; +import HudOverlay from './VideoTile/HudOverlay.jsx'; +import OvercurrentOverlay from './VideoTile/OvercurrentOverlay.jsx'; +import LowBatteryOverlay from './VideoTile/LowBatteryOverlay.jsx'; +import LightBumpBars from './VideoTile/LightBumpBars.jsx'; +import HudChatInput from './VideoTile/HudChatInput.jsx'; +import { + RESTART_DELAY_MS, + UNMUTE_RETRY_MS, + AUDIO_RETRY_MS, + BRUSH_CURRENT_THRESHOLD_MA, + DUCK_RELEASE_FADE_MS, +} from './VideoTile/constants.js'; export default function VideoTile({ sessionInfo, @@ -674,420 +678,3 @@ export default function VideoTile({ ); } -function LightBumpBars({ sensors }) { - const values = [ - sensors?.lightBumpLeftSignal, - sensors?.lightBumpFrontLeftSignal, - sensors?.lightBumpCenterLeftSignal, - sensors?.lightBumpCenterRightSignal, - sensors?.lightBumpFrontRightSignal, - sensors?.lightBumpRightSignal, - ]; - const max = values.filter((v) => v != null).reduce((acc, v) => Math.max(acc, v), 1200); - const eased = (v) => Math.pow(Math.max(0, Math.min(1, (v ?? 0) / max)), 0.35); - const hueFor = (v) => { - if (v == null || v <= 0) return 'hsl(200 60% 18%)'; - const h = (200 + eased(v) * 360) % 360; - return `hsl(${h} 100% 60%)`; - }; - const segments = 6; - const gap = 2; - const barHeight = 12; - - return ( - - {values.map((v, idx) => { - const t = eased(v); - const dir = idx < segments / 2 ? -1 : 1; // left bars fill left, right bars fill right - const fill = `${t * 100}%`; - const color = hueFor(v); - return ( - - - - - - ); - })} - - ); -} - -function HudOverlay({ - frame, - sensors, - label, - roverColor = null, - status, - audioStatus, - levelStatus, - desktopLayout = true, - layoutFormat = 'desktop', - variant = 'default', - driverLabel = null, - battery, - showTopDown = false, - mobileHud = false, - mapPosition = 'top-center', - turnTimerText = null, - labelScale = 1, -}) { - const bumps = sensors?.bumpsAndWheelDrops || {}; - const isMobile = mobileHud; - const portraitMobile = layoutFormat === 'mobile-portrait'; - const statusTextClass = isMobile ? 'text-[0.45rem]' : 'text-[0.65rem]'; - const statusPadClass = isMobile ? 'px-0.25 py-0.25' : 'px-1 py-0.5'; - const labelPadClass = isMobile ? 'px-0.25 py-0.25' : 'px-0.5 py-0.5'; - const labelTextClass = isMobile ? 'text-[0.55rem]' : 'text-[0.8rem]'; - const statusPosClass = isMobile ? 'left-0.5 top-0.5' : 'left-1 top-1'; - const timerTextClass = isMobile ? 'text-[0.5rem]' : 'text-[0.7rem]'; - const timerPadClass = isMobile ? 'px-0.5 py-0.25' : 'px-1 py-0.5'; - const telemetryPosClass = isMobile ? 'left-0.5 top-1/2' : 'left-1 top-1/2'; - const labelPosClass = isMobile ? 'bottom-0.5' : 'bottom-0.5'; - const labelWrapperStyle = { - transform: `translateX(-50%) scale(${labelScale})`, - transformOrigin: 'center bottom', - }; - const mapSize = '240px'; - const mapScale = portraitMobile ? 0.3 : isMobile ? 0.33 : 0.7; - const mapOpacity = isMobile ? 0.6 : 0.7; - const mapStyle = { - width: mapSize, - height: mapSize, - opacity: mapOpacity, - transform: mapPosition === 'top-center' ? `translateX(-50%) scale(${mapScale})` : `scale(${mapScale})`, - transformOrigin: - mapPosition === 'bottom-left' ? 'bottom left' : mapPosition === 'top-center' ? 'top center' : 'top right', - ...(mapPosition === 'bottom-left' - ? { left: '0.25rem', bottom: '0.25rem' } - : mapPosition === 'top-center' - ? { left: '50%', top: '0.25rem' } - : { right: '0.25rem', top: '0.25rem' }), - }; - - if (variant === 'none') { - return null; - } - - if (variant === 'spectator') { - const telemetryEntries = [ - ['Voltage', sensors?.voltageMv != null ? `${(sensors.voltageMv / 1000).toFixed(2)} V` : '--'], - ['Current', sensors?.currentMa != null ? `${sensors.currentMa} mA` : '--'], - ['Charge', sensors?.batteryChargeMah != null ? `${sensors.batteryChargeMah}` : '--'], - ['OI', sensors?.oiMode?.label || '--'], - ]; - const docked = Boolean(sensors?.chargingSources?.homeBase); - const chargingLabel = sensors?.chargingState?.label || ''; - const charging = Boolean(chargingLabel && chargingLabel.toLowerCase() !== 'not charging'); - const oiLabel = sensors?.oiMode?.label || 'Unknown'; - const oiNormalized = oiLabel.toLowerCase(); - const oiTone = - oiNormalized === 'full' - ? 'bg-emerald-500/80 text-emerald-50' - : oiNormalized === 'safe' - ? 'bg-amber-400/80 text-amber-950' - : oiNormalized === 'passive' - ? 'bg-slate-700/80 text-slate-100' - : 'bg-slate-700/60 text-slate-200'; - const dockTone = docked ? 'bg-emerald-500/80 text-emerald-50' : 'bg-slate-700/70 text-slate-200'; - const chargingTone = charging - ? 'bg-emerald-500/80 text-emerald-50' - : docked - ? 'bg-amber-400/80 text-amber-950' - : 'bg-slate-700/70 text-slate-200'; - return ( - <> - - - - Status: {status} - {audioStatus ? Audio: {audioStatus} : null} - {levelStatus ? {levelStatus} : null} - - - - - - {docked ? 'Docked' : 'Undocked'} - - {charging ? 'Charging' : docked ? 'Not charging' : 'Not charging'} - - OI: {oiLabel} - - {/* - Telemetry - */} - {telemetryEntries.map(([labelText, value]) => ( - - {labelText} - {value} - - ))} - - - - - - - {label || 'Unnamed Rover'} - - {driverLabel ? • {driverLabel} : null} - - - - {showTopDown ? ( - - - - ) : null} - > - ); - } - - return ( - - - - Status: {status} - {audioStatus ? Audio: {audioStatus} : null} - {levelStatus ? {levelStatus} : null} - - - {turnTimerText ? ( - - {turnTimerText} - - ) : null} - - - - Rover:{' '} - - "{label || 'Unnamed Rover'}" - - - {/* {pulse ? 'Sensors active' : 'No recent sensors'} */} - - - - {showTopDown && variant !== 'spectator' ? ( - - - - ) : null} - - ); -} - -function TurnCueOverlay({ - mobileHud = false, - turnSeconds = null, - isActiveDriver = false, - idleSkipSeconds = null, -}) { - const titleClass = mobileHud ? 'text-3xl' : 'text-5xl'; - const subClass = mobileHud ? 'text-xs' : 'text-sm'; - const timerClass = mobileHud ? 'text-[0.55rem]' : 'text-[0.75rem]'; - const padClass = mobileHud ? 'px-4 py-3' : 'px-6 py-4'; - const showCountdown = isActiveDriver && typeof idleSkipSeconds === 'number'; - return ( - - - IT IS YOUR TURN! - Start driving! - {showCountdown ? ( - - Idle skip in {idleSkipSeconds}s - - ) : null} - - - ); -} - -const OVERCURRENT_LABELS = { - leftWheel: 'Left wheel', - rightWheel: 'Right wheel', - mainBrush: 'Main brush', - sideBrush: 'Side brush', - limiter: 'Overcurrent limit', -}; - -function OvercurrentOverlay({ motors, fill = 0, compact = false }) { - if (!motors?.length) return null; - const safeLabels = motors.map((name) => OVERCURRENT_LABELS[name] || name); - const containerClass = compact ? 'w-[12rem] h-[3.5rem]' : 'w-[20rem] h-[7rem]'; - const padClass = compact ? 'px-2 py-1' : 'px-4 py-2'; - const textClass = compact ? 'text-lg' : 'text-4xl'; - const subTextClass = compact ? 'text-xs' : 'text-xl'; - const safeFill = Math.max(0, Math.min(1, fill)); - const fillWidth = `${Math.round(safeFill * 100)}%`; - return ( - - - - - - - OVERCURRENT - {safeLabels.join(', ')} - - - - ); -} - -// low battery overlay, change text based on warn / urgent. use percentage calculated same as BatteryBar. change text based on warn or urgent. -function LowBatteryOverlay({ battery, compact = false }) { - if (!battery?.available) return null; - if (!battery.warnActive && !battery.urgentActive) return null; - - const message = battery.urgentActive - ? 'BATTERY VERY LOW, DOCK THE ROVER AND CHARGE IMMEDIATELY!!' - : 'Battery low! please dock and charge the rover soon.'; - - const containerClass = compact ? 'p-2 top-6' : 'p-4 top-10'; - const textClass = compact ? 'text-sm' : 'text-2xl'; - - return ( - - - {message} - - - ); -} - -function HudChatInput({ compact = false }) { - const session = useSessionSelector((state) => state.session); - const { sendMessage, onInputFocus, onInputBlur, blurChat, registerInputRef, setTypingActive } = useChat(); - const { value: ttsSettings } = useSettingsNamespace('tts', { engine: 'flite', voice: 'rms', pitch: 50 }); - const [draft, setDraft] = useState(''); - const [sending, setSending] = useState(false); - const canChat = session?.role !== 'spectator'; - const hideHudChat = session?.role === 'spectator'; - const currentRoverId = session?.assignment?.roverId || null; - const rover = useMemo( - () => session?.roster?.find((entry) => String(entry.id) === String(currentRoverId)) || null, - [currentRoverId, session?.roster], - ); - const ttsSupported = Boolean(rover?.audio?.ttsEnabled); - const ttsPayload = useMemo(() => { - if (!ttsSupported) return null; - const engine = ttsSettings?.engine === 'espeak' ? 'espeak' : 'flite'; - if (engine === 'espeak') { - let pitch = Number.isFinite(ttsSettings?.pitch) ? Math.round(ttsSettings.pitch) : undefined; - if (typeof pitch === 'number') { - pitch = Math.max(0, Math.min(99, pitch)); - } - return { speak: true, engine, pitch }; - } - const voice = typeof ttsSettings?.voice === 'string' ? ttsSettings.voice : undefined; - return { speak: true, engine, voice }; - }, [ttsSettings?.engine, ttsSettings?.pitch, ttsSettings?.voice, ttsSupported]); - const containerClass = compact - ? 'pointer-events-auto absolute bottom-0.5 right-0.5 flex w-[9rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.4 py-0.2' - : 'pointer-events-auto absolute bottom-1 right-1 flex w-[12rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.5 py-0.25'; - const inputClass = compact - ? 'min-w-0 flex-1 bg-transparent text-[0.55rem] text-slate-100 placeholder:text-slate-400 focus:outline-none' - : 'min-w-0 flex-1 bg-transparent text-[0.7rem] text-slate-100 placeholder:text-slate-400 focus:outline-none'; - const buttonClass = compact - ? 'rounded bg-cyan-500/80 px-0.35 py-0.2 text-[0.55rem] font-semibold text-black disabled:opacity-50' - : 'rounded bg-cyan-500/80 px-0.5 py-0.25 text-[0.7rem] font-semibold text-black disabled:opacity-50'; - - async function handleSend(event) { - event.preventDefault(); - if (!canChat) return; - const clean = draft.trim(); - if (!clean) return; - setSending(true); - try { - await sendMessage(clean, ttsPayload); - setDraft(''); - blurChat(); - setTypingActive(false); - } catch (err) { - alert(err.message); - } finally { - setSending(false); - } - } - - if (hideHudChat) return null; - - return ( - - { - const next = event.target.value; - setDraft(next); - setTypingActive(Boolean(next.trim())); - }} - onFocus={(event) => { - onInputFocus(event); - setTypingActive(Boolean(draft.trim())); - }} - onBlur={(event) => { - onInputBlur(event); - setTypingActive(false); - }} - onKeyDown={(event) => { - if (event.key === 'Enter' && !draft.trim()) { - event.preventDefault(); - blurChat(); - setTypingActive(false); - } - }} - ref={(el) => registerInputRef(el, { target: 'hud' })} - placeholder={canChat ? 'Chat (TTS)' : 'Spectator'} - disabled={!canChat} - /> - - Speak - - - ); -} diff --git a/webui/src/components/VideoTile/HudChatInput.jsx b/webui/src/components/VideoTile/HudChatInput.jsx new file mode 100644 index 00000000..8a7762fa --- /dev/null +++ b/webui/src/components/VideoTile/HudChatInput.jsx @@ -0,0 +1,98 @@ +// Inline HUD chat input for driver speech messages. +import { useMemo, useState } from 'react'; +import { useChat } from '../../context/ChatContext.jsx'; +import { useSessionSelector } from '../../context/SessionContext.jsx'; +import { useSettingsNamespace } from '../../settings/index.js'; + +export default function HudChatInput({ compact = false }) { + const session = useSessionSelector((state) => state.session); + const { sendMessage, onInputFocus, onInputBlur, blurChat, registerInputRef, setTypingActive } = useChat(); + const { value: ttsSettings } = useSettingsNamespace('tts', { engine: 'flite', voice: 'rms', pitch: 50 }); + const [draft, setDraft] = useState(''); + const [sending, setSending] = useState(false); + const canChat = session?.role !== 'spectator'; + const hideHudChat = session?.role === 'spectator'; + const currentRoverId = session?.assignment?.roverId || null; + const rover = useMemo( + () => session?.roster?.find((entry) => String(entry.id) === String(currentRoverId)) || null, + [currentRoverId, session?.roster], + ); + const ttsSupported = Boolean(rover?.audio?.ttsEnabled); + const ttsPayload = useMemo(() => { + if (!ttsSupported) return null; + const engine = ttsSettings?.engine === 'espeak' ? 'espeak' : 'flite'; + if (engine === 'espeak') { + let pitch = Number.isFinite(ttsSettings?.pitch) ? Math.round(ttsSettings.pitch) : undefined; + if (typeof pitch === 'number') { + pitch = Math.max(0, Math.min(99, pitch)); + } + return { speak: true, engine, pitch }; + } + const voice = typeof ttsSettings?.voice === 'string' ? ttsSettings.voice : undefined; + return { speak: true, engine, voice }; + }, [ttsSettings?.engine, ttsSettings?.pitch, ttsSettings?.voice, ttsSupported]); + const containerClass = compact + ? 'pointer-events-auto absolute bottom-0.5 right-0.5 flex w-[9rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.4 py-0.2' + : 'pointer-events-auto absolute bottom-1 right-1 flex w-[12rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.5 py-0.25'; + const inputClass = compact + ? 'min-w-0 flex-1 bg-transparent text-[0.55rem] text-slate-100 placeholder:text-slate-400 focus:outline-none' + : 'min-w-0 flex-1 bg-transparent text-[0.7rem] text-slate-100 placeholder:text-slate-400 focus:outline-none'; + const buttonClass = compact + ? 'rounded bg-cyan-500/80 px-0.35 py-0.2 text-[0.55rem] font-semibold text-black disabled:opacity-50' + : 'rounded bg-cyan-500/80 px-0.5 py-0.25 text-[0.7rem] font-semibold text-black disabled:opacity-50'; + + async function handleSend(event) { + event.preventDefault(); + if (!canChat) return; + const clean = draft.trim(); + if (!clean) return; + setSending(true); + try { + await sendMessage(clean, ttsPayload); + setDraft(''); + blurChat(); + setTypingActive(false); + } catch (err) { + alert(err.message); + } finally { + setSending(false); + } + } + + if (hideHudChat) return null; + + return ( + + { + const next = event.target.value; + setDraft(next); + setTypingActive(Boolean(next.trim())); + }} + onFocus={(event) => { + onInputFocus(event); + setTypingActive(Boolean(draft.trim())); + }} + onBlur={(event) => { + onInputBlur(event); + setTypingActive(false); + }} + onKeyDown={(event) => { + if (event.key === 'Enter' && !draft.trim()) { + event.preventDefault(); + blurChat(); + setTypingActive(false); + } + }} + ref={(el) => registerInputRef(el, { target: 'hud' })} + placeholder={canChat ? 'Chat (TTS)' : 'Spectator'} + disabled={!canChat} + /> + + Speak + + + ); +} diff --git a/webui/src/components/VideoTile/HudOverlay.jsx b/webui/src/components/VideoTile/HudOverlay.jsx new file mode 100644 index 00000000..9ef6a46a --- /dev/null +++ b/webui/src/components/VideoTile/HudOverlay.jsx @@ -0,0 +1,177 @@ +// Telemetry HUD and map overlay for VideoTile. +import React from 'react'; +import TopDownMap from '../TopDownMap.jsx'; +import { roverNameChromeStyle } from '../../lib/roverColor.js'; + +export default function HudOverlay({ + frame, + sensors, + label, + roverColor = null, + status, + audioStatus, + levelStatus, + desktopLayout = true, + layoutFormat = 'desktop', + variant = 'default', + driverLabel = null, + battery, + showTopDown = false, + mobileHud = false, + mapPosition = 'top-center', + turnTimerText = null, + labelScale = 1, +}) { + const isMobile = mobileHud; + const portraitMobile = layoutFormat === 'mobile-portrait'; + const statusTextClass = isMobile ? 'text-[0.45rem]' : 'text-[0.65rem]'; + const statusPadClass = isMobile ? 'px-0.25 py-0.25' : 'px-1 py-0.5'; + const labelPadClass = isMobile ? 'px-0.25 py-0.25' : 'px-0.5 py-0.5'; + const labelTextClass = isMobile ? 'text-[0.55rem]' : 'text-[0.8rem]'; + const statusPosClass = isMobile ? 'left-0.5 top-0.5' : 'left-1 top-1'; + const timerTextClass = isMobile ? 'text-[0.5rem]' : 'text-[0.7rem]'; + const timerPadClass = isMobile ? 'px-0.5 py-0.25' : 'px-1 py-0.5'; + const telemetryPosClass = isMobile ? 'left-0.5 top-1/2' : 'left-1 top-1/2'; + const labelPosClass = isMobile ? 'bottom-0.5' : 'bottom-0.5'; + const labelWrapperStyle = { + transform: `translateX(-50%) scale(${labelScale})`, + transformOrigin: 'center bottom', + }; + const mapSize = '240px'; + const mapScale = portraitMobile ? 0.3 : isMobile ? 0.33 : 0.7; + const mapOpacity = isMobile ? 0.6 : 0.7; + const mapStyle = { + width: mapSize, + height: mapSize, + opacity: mapOpacity, + transform: mapPosition === 'top-center' ? `translateX(-50%) scale(${mapScale})` : `scale(${mapScale})`, + transformOrigin: + mapPosition === 'bottom-left' ? 'bottom left' : mapPosition === 'top-center' ? 'top center' : 'top right', + ...(mapPosition === 'bottom-left' + ? { left: '0.25rem', bottom: '0.25rem' } + : mapPosition === 'top-center' + ? { left: '50%', top: '0.25rem' } + : { right: '0.25rem', top: '0.25rem' }), + }; + + if (variant === 'none') { + return null; + } + + if (variant === 'spectator') { + const telemetryEntries = [ + ['Voltage', sensors?.voltageMv != null ? `${(sensors.voltageMv / 1000).toFixed(2)} V` : '--'], + ['Current', sensors?.currentMa != null ? `${sensors.currentMa} mA` : '--'], + ['Charge', sensors?.batteryChargeMah != null ? `${sensors.batteryChargeMah}` : '--'], + ['OI', sensors?.oiMode?.label || '--'], + ]; + const docked = Boolean(sensors?.chargingSources?.homeBase); + const chargingLabel = sensors?.chargingState?.label || ''; + const charging = Boolean(chargingLabel && chargingLabel.toLowerCase() !== 'not charging'); + const oiLabel = sensors?.oiMode?.label || 'Unknown'; + const oiNormalized = oiLabel.toLowerCase(); + const oiTone = + oiNormalized === 'full' + ? 'bg-emerald-500/80 text-emerald-50' + : oiNormalized === 'safe' + ? 'bg-amber-400/80 text-amber-950' + : oiNormalized === 'passive' + ? 'bg-slate-700/80 text-slate-100' + : 'bg-slate-700/60 text-slate-200'; + const dockTone = docked ? 'bg-emerald-500/80 text-emerald-50' : 'bg-slate-700/70 text-slate-200'; + const chargingTone = charging + ? 'bg-emerald-500/80 text-emerald-50' + : docked + ? 'bg-amber-400/80 text-amber-950' + : 'bg-slate-700/70 text-slate-200'; + return ( + <> + + + + Status: {status} + {audioStatus ? Audio: {audioStatus} : null} + {levelStatus ? {levelStatus} : null} + + + + + + {docked ? 'Docked' : 'Undocked'} + + {charging ? 'Charging' : docked ? 'Not charging' : 'Not charging'} + + OI: {oiLabel} + + {telemetryEntries.map(([labelText, value]) => ( + + {labelText} + {value} + + ))} + + + + + + + {label || 'Unnamed Rover'} + + {driverLabel ? • {driverLabel} : null} + + + + {showTopDown ? ( + + + + ) : null} + > + ); + } + + return ( + + + + Status: {status} + {audioStatus ? Audio: {audioStatus} : null} + {levelStatus ? {levelStatus} : null} + + + {turnTimerText ? ( + + {turnTimerText} + + ) : null} + + + + Rover:{' '} + + "{label || 'Unnamed Rover'}" + + + + + + {showTopDown && variant !== 'spectator' ? ( + + + + ) : null} + + ); +} diff --git a/webui/src/components/VideoTile/LightBumpBars.jsx b/webui/src/components/VideoTile/LightBumpBars.jsx new file mode 100644 index 00000000..971abd39 --- /dev/null +++ b/webui/src/components/VideoTile/LightBumpBars.jsx @@ -0,0 +1,47 @@ +// Light bump signal bars used under the tile HUD. +import React from 'react'; + +export default function LightBumpBars({ sensors }) { + const values = [ + sensors?.lightBumpLeftSignal, + sensors?.lightBumpFrontLeftSignal, + sensors?.lightBumpCenterLeftSignal, + sensors?.lightBumpCenterRightSignal, + sensors?.lightBumpFrontRightSignal, + sensors?.lightBumpRightSignal, + ]; + const max = values.filter((v) => v != null).reduce((acc, v) => Math.max(acc, v), 1200); + const eased = (v) => Math.pow(Math.max(0, Math.min(1, (v ?? 0) / max)), 0.35); + const hueFor = (v) => { + if (v == null || v <= 0) return 'hsl(200 60% 18%)'; + const h = (200 + eased(v) * 360) % 360; + return `hsl(${h} 100% 60%)`; + }; + const segments = 6; + const barHeight = 12; + + return ( + + {values.map((v, idx) => { + const t = eased(v); + const dir = idx < segments / 2 ? -1 : 1; + const fill = `${t * 100}%`; + const color = hueFor(v); + return ( + + + + + + ); + })} + + ); +} diff --git a/webui/src/components/VideoTile/LowBatteryOverlay.jsx b/webui/src/components/VideoTile/LowBatteryOverlay.jsx new file mode 100644 index 00000000..ec90e7a2 --- /dev/null +++ b/webui/src/components/VideoTile/LowBatteryOverlay.jsx @@ -0,0 +1,24 @@ +// Low battery warning overlay. +import React from 'react'; + +export default function LowBatteryOverlay({ battery, compact = false }) { + if (!battery?.available) return null; + if (!battery.warnActive && !battery.urgentActive) return null; + + const message = battery.urgentActive + ? 'BATTERY VERY LOW, DOCK THE ROVER AND CHARGE IMMEDIATELY!!' + : 'Battery low! please dock and charge the rover soon.'; + + const containerClass = compact ? 'p-2 top-6' : 'p-4 top-10'; + const textClass = compact ? 'text-sm' : 'text-2xl'; + + return ( + + + {message} + + + ); +} diff --git a/webui/src/components/VideoTile/OvercurrentOverlay.jsx b/webui/src/components/VideoTile/OvercurrentOverlay.jsx new file mode 100644 index 00000000..9b4a918a --- /dev/null +++ b/webui/src/components/VideoTile/OvercurrentOverlay.jsx @@ -0,0 +1,29 @@ +// Overcurrent warning overlay. +import React from 'react'; +import { OVERCURRENT_LABELS } from './constants.js'; + +export default function OvercurrentOverlay({ motors, fill = 0, compact = false }) { + if (!motors?.length) return null; + const safeLabels = motors.map((name) => OVERCURRENT_LABELS[name] || name); + const containerClass = compact ? 'w-[12rem] h-[3.5rem]' : 'w-[20rem] h-[7rem]'; + const padClass = compact ? 'px-2 py-1' : 'px-4 py-2'; + const textClass = compact ? 'text-lg' : 'text-4xl'; + const subTextClass = compact ? 'text-xs' : 'text-xl'; + const safeFill = Math.max(0, Math.min(1, fill)); + const fillWidth = `${Math.round(safeFill * 100)}%`; + return ( + + + + + + + OVERCURRENT + {safeLabels.join(', ')} + + + + ); +} diff --git a/webui/src/components/VideoTile/TurnCueOverlay.jsx b/webui/src/components/VideoTile/TurnCueOverlay.jsx new file mode 100644 index 00000000..70377f44 --- /dev/null +++ b/webui/src/components/VideoTile/TurnCueOverlay.jsx @@ -0,0 +1,28 @@ +// Turn cue overlay shown to active drivers. +import React from 'react'; + +export default function TurnCueOverlay({ + mobileHud = false, + turnSeconds = null, + isActiveDriver = false, + idleSkipSeconds = null, +}) { + const titleClass = mobileHud ? 'text-3xl' : 'text-5xl'; + const subClass = mobileHud ? 'text-xs' : 'text-sm'; + const timerClass = mobileHud ? 'text-[0.55rem]' : 'text-[0.75rem]'; + const padClass = mobileHud ? 'px-4 py-3' : 'px-6 py-4'; + const showCountdown = isActiveDriver && typeof idleSkipSeconds === 'number'; + return ( + + + IT IS YOUR TURN! + Start driving! + {showCountdown ? ( + + Idle skip in {idleSkipSeconds}s + + ) : null} + + + ); +} diff --git a/webui/src/components/VideoTile/constants.js b/webui/src/components/VideoTile/constants.js new file mode 100644 index 00000000..1cacdd7b --- /dev/null +++ b/webui/src/components/VideoTile/constants.js @@ -0,0 +1,14 @@ +// VideoTile timing and threshold constants. +export const RESTART_DELAY_MS = 2000; +export const UNMUTE_RETRY_MS = 3000; +export const AUDIO_RETRY_MS = 3000; +export const BRUSH_CURRENT_THRESHOLD_MA = 40; +export const DUCK_RELEASE_FADE_MS = 1000; + +export const OVERCURRENT_LABELS = { + leftWheel: 'Left wheel', + rightWheel: 'Right wheel', + mainBrush: 'Main brush', + sideBrush: 'Side brush', + limiter: 'Overcurrent limit', +};