From a8dd71193ae33f5087e967552533ea8cabf23f62 Mon Sep 17 00:00:00 2001 From: legop3 Date: Fri, 1 May 2026 17:25:45 -0400 Subject: [PATCH] lidar adjustmentses --- server/public/assets/index-BNzmusoM.css | 1 - server/public/assets/index-DmVJMLH1.css | 1 + .../{index-CZ7Wc8AL.js => index-zn-QfvQ7.js} | 2 +- server/public/index.html | 4 +- .../src/services/neatoService/lidarRuntime.js | 4 +- webui/src/components/vip/VipNeatoCard.jsx | 108 ++++++++++-------- 6 files changed, 66 insertions(+), 54 deletions(-) delete mode 100644 server/public/assets/index-BNzmusoM.css create mode 100644 server/public/assets/index-DmVJMLH1.css rename server/public/assets/{index-CZ7Wc8AL.js => index-zn-QfvQ7.js} (95%) diff --git a/server/public/assets/index-BNzmusoM.css b/server/public/assets/index-BNzmusoM.css deleted file mode 100644 index b7b4f06a..00000000 --- a/server/public/assets/index-BNzmusoM.css +++ /dev/null @@ -1 +0,0 @@ -*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.panel{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));padding:0;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.panel-section{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(23 23 23 / var(--tw-bg-opacity));padding:0;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.panel-muted{border-radius:.375rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.surface{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(38 38 38 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.surface-muted{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(245 245 245 / var(--tw-text-opacity))}.field-input{border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(82 82 82 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.field-input::-moz-placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.field-input::placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.field-input:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(14 165 233 / var(--tw-ring-opacity))}.button-dark{border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(125 211 252 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity));padding:.125rem;font-size:.875rem;line-height:1.25rem;font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.button-dark:hover{--tw-border-opacity: 1;border-color:rgb(14 165 233 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity))}.button-danger{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity));padding:.125rem;font-size:.875rem;line-height:1.25rem;font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.button-danger:hover{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity))}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-x-0{left:0;right:0}.bottom-0{bottom:0}.bottom-0\.5{bottom:.125rem}.bottom-1{bottom:.25rem}.bottom-2{bottom:.5rem}.left-0{left:0}.left-0\.5{left:.125rem}.left-1{left:.25rem}.left-1\/2{left:50%}.left-2{left:.5rem}.right-0{right:0}.right-0\.5{right:.125rem}.right-1{right:.25rem}.right-2{right:.5rem}.top-0{top:0}.top-0\.5{top:.125rem}.top-1{top:.25rem}.top-1\/2{top:50%}.top-10{top:2.5rem}.top-6{top:1.5rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[120\]{z-index:120}.order-1{order:1}.order-2{order:2}.col-span-full{grid-column:1 / -1}.m-0{margin:0}.mx-auto{margin-left:auto;margin-right:auto}.-mt-0\.5{margin-top:-.125rem}.mr-0{margin-right:0}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-auto{margin-top:auto}.\!block{display:block!important}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.aspect-\[4\/3\]{aspect-ratio:4/3}.aspect-square{aspect-ratio:1 / 1}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-28{height:7rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-40{height:10rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-64{height:16rem}.h-\[14rem\]{height:14rem}.h-\[2px\]{height:2px}.h-\[3\.5rem\]{height:3.5rem}.h-\[70\%\]{height:70%}.h-\[7rem\]{height:7rem}.h-\[min\(100svh\,32rem\)\]{height:min(100svh,32rem)}.h-\[min\(60svh\,24rem\)\]{height:min(60svh,24rem)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-32{max-height:8rem}.max-h-40{max-height:10rem}.max-h-52{max-height:13rem}.max-h-72{max-height:18rem}.max-h-80{max-height:20rem}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-screen{max-height:100vh}.min-h-0{min-height:0px}.min-h-\[1\.5rem\]{min-height:1.5rem}.min-h-\[14rem\]{min-height:14rem}.min-h-\[16rem\]{min-height:16rem}.min-h-\[3\.5rem\]{min-height:3.5rem}.min-h-\[5rem\]{min-height:5rem}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-1\/2{width:50%}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-\[12\.5rem\]{width:12.5rem}.w-\[12rem\]{width:12rem}.w-\[20rem\]{width:20rem}.w-\[2px\]{width:2px}.w-\[9rem\]{width:9rem}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-\[0\]{min-width:0}.min-w-\[10rem\]{min-width:10rem}.min-w-\[12rem\]{min-width:12rem}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-\[26rem\]{max-width:26rem}.max-w-\[70vw\]{max-width:70vw}.max-w-\[80vw\]{max-width:80vw}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-\[1\.1\]{flex:1.1}.flex-\[1\.22\]{flex:1.22}.flex-\[1_1_12rem\]{flex:1 1 12rem}.shrink-0{flex-shrink:0}.basis-full{flex-basis:100%}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\[minmax\(0\,0\.7fr\)_minmax\(0\,2\.1fr\)_minmax\(0\,0\.7fr\)\]{grid-template-columns:minmax(0,.7fr) minmax(0,2.1fr) minmax(0,.7fr)}.grid-cols-\[minmax\(0\,1\.2fr\)_repeat\(4\,minmax\(0\,1fr\)\)\]{grid-template-columns:minmax(0,1.2fr) repeat(4,minmax(0,1fr))}.grid-cols-\[minmax\(0\,1\.35fr\)_minmax\(0\,0\.95fr\)\]{grid-template-columns:minmax(0,1.35fr) minmax(0,.95fr)}.grid-cols-\[minmax\(0\,1\.3fr\)_minmax\(0\,0\.22fr\)\]{grid-template-columns:minmax(0,1.3fr) minmax(0,.22fr)}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,0\.7fr\)_minmax\(0\,1\.9fr\)_minmax\(0\,0\.7fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,.7fr) minmax(0,1.9fr) minmax(0,.7fr)}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,0\.9fr\)_minmax\(0\,0\.75fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,.9fr) minmax(0,.75fr)}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1\.4fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,1.4fr)}.grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}.grid-rows-\[auto_1fr\]{grid-template-rows:auto 1fr}.grid-rows-\[auto_auto_1fr\]{grid-template-rows:auto auto 1fr}.grid-rows-\[auto_auto_1fr_auto\]{grid-template-rows:auto auto 1fr auto}.grid-rows-\[minmax\(0\,1fr\)_auto\]{grid-template-rows:minmax(0,1fr) auto}.grid-rows-\[minmax\(0\,1fr\)_minmax\(0\,1fr\)_minmax\(0\,1fr\)\]{grid-template-rows:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.content-center{align-content:center}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0px}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.self-start{align-self:flex-start}.self-center{align-self:center}.self-stretch{align-self:stretch}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity))}.border-amber-200\/30{border-color:#fde68a4d}.border-amber-200\/70{border-color:#fde68ab3}.border-amber-300\/70{border-color:#fcd34db3}.border-amber-300\/80{border-color:#fcd34dcc}.border-amber-400\/30{border-color:#fbbf244d}.border-amber-400\/60{border-color:#fbbf2499}.border-amber-600\/60{border-color:#d9770699}.border-amber-700\/60{border-color:#b4530999}.border-blue-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity))}.border-cyan-200\/50{border-color:#a5f3fc80}.border-cyan-300{--tw-border-opacity: 1;border-color:rgb(103 232 249 / var(--tw-border-opacity))}.border-cyan-300\/70{border-color:#67e8f9b3}.border-cyan-500\/40{border-color:#06b6d466}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity))}.border-emerald-200\/70{border-color:#a7f3d0b3}.border-emerald-300\/70{border-color:#6ee7b7b3}.border-emerald-400\/60{border-color:#34d39999}.border-emerald-500\/40{border-color:#10b98166}.border-emerald-700{--tw-border-opacity: 1;border-color:rgb(4 120 87 / var(--tw-border-opacity))}.border-emerald-700\/60{border-color:#04785799}.border-fuchsia-300\/70{border-color:#f0abfcb3}.border-indigo-200\/70{border-color:#c7d2feb3}.border-indigo-300\/70{border-color:#a5b4fcb3}.border-indigo-400\/30{border-color:#818cf84d}.border-indigo-700{--tw-border-opacity: 1;border-color:rgb(67 56 202 / var(--tw-border-opacity))}.border-indigo-700\/60{border-color:#4338ca99}.border-pink-200{--tw-border-opacity: 1;border-color:rgb(251 207 232 / var(--tw-border-opacity))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity))}.border-red-400\/60{border-color:#f8717199}.border-rose-300{--tw-border-opacity: 1;border-color:rgb(253 164 175 / var(--tw-border-opacity))}.border-rose-800{--tw-border-opacity: 1;border-color:rgb(159 18 57 / var(--tw-border-opacity))}.border-sky-300{--tw-border-opacity: 1;border-color:rgb(125 211 252 / var(--tw-border-opacity))}.border-sky-400\/50{border-color:#38bdf880}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity))}.border-slate-200\/30{border-color:#e2e8f04d}.border-slate-400\/60{border-color:#94a3b899}.border-slate-600{--tw-border-opacity: 1;border-color:rgb(71 85 105 / var(--tw-border-opacity))}.border-slate-600\/40{border-color:#47556966}.border-slate-600\/60{border-color:#47556999}.border-slate-700{--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity))}.border-slate-700\/60{border-color:#33415599}.border-slate-700\/70{border-color:#334155b3}.border-slate-700\/80{border-color:#334155cc}.border-slate-800{--tw-border-opacity: 1;border-color:rgb(30 41 59 / var(--tw-border-opacity))}.border-slate-800\/60{border-color:#1e293b99}.border-transparent{border-color:transparent}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity))}.border-white\/40{border-color:#fff6}.border-white\/60{border-color:#fff9}.bg-amber-100\/95{background-color:#fef3c7f2}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity))}.bg-amber-400\/80{background-color:#fbbf24cc}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity))}.bg-amber-500\/30{background-color:#f59e0b4d}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity))}.bg-amber-600\/70{background-color:#d97706b3}.bg-amber-700\/20{background-color:#b4530933}.bg-amber-700\/30{background-color:#b453094d}.bg-amber-700\/35{background-color:#b4530959}.bg-amber-900{--tw-bg-opacity: 1;background-color:rgb(120 53 15 / var(--tw-bg-opacity))}.bg-amber-900\/40{background-color:#78350f66}.bg-amber-900\/60{background-color:#78350f99}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity))}.bg-black\/20{background-color:#0003}.bg-black\/30{background-color:#0000004d}.bg-black\/40{background-color:#0006}.bg-black\/50{background-color:#00000080}.bg-black\/55{background-color:#0000008c}.bg-black\/60{background-color:#0009}.bg-black\/70{background-color:#000000b3}.bg-black\/75{background-color:#000000bf}.bg-black\/80{background-color:#000c}.bg-black\/85{background-color:#000000d9}.bg-cyan-300\/80{background-color:#67e8f9cc}.bg-cyan-400\/10{background-color:#22d3ee1a}.bg-cyan-500{--tw-bg-opacity: 1;background-color:rgb(6 182 212 / var(--tw-bg-opacity))}.bg-cyan-500\/80{background-color:#06b6d4cc}.bg-cyan-900{--tw-bg-opacity: 1;background-color:rgb(22 78 99 / var(--tw-bg-opacity))}.bg-cyan-900\/45{background-color:#164e6373}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity))}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity))}.bg-emerald-500\/45{background-color:#10b98173}.bg-emerald-500\/80{background-color:#10b981cc}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity))}.bg-emerald-600\/70{background-color:#059669b3}.bg-emerald-700\/20{background-color:#04785733}.bg-emerald-700\/60{background-color:#04785799}.bg-emerald-800{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity))}.bg-emerald-900{--tw-bg-opacity: 1;background-color:rgb(6 78 59 / var(--tw-bg-opacity))}.bg-emerald-900\/15{background-color:#064e3b26}.bg-emerald-900\/60{background-color:#064e3b99}.bg-emerald-900\/80{background-color:#064e3bcc}.bg-fuchsia-200{--tw-bg-opacity: 1;background-color:rgb(245 208 254 / var(--tw-bg-opacity))}.bg-fuchsia-600{--tw-bg-opacity: 1;background-color:rgb(192 38 211 / var(--tw-bg-opacity))}.bg-fuchsia-700{--tw-bg-opacity: 1;background-color:rgb(162 28 175 / var(--tw-bg-opacity))}.bg-fuchsia-800{--tw-bg-opacity: 1;background-color:rgb(134 25 143 / var(--tw-bg-opacity))}.bg-fuchsia-900\/45{background-color:#701a7573}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity))}.bg-indigo-600\/70{background-color:#4f46e5b3}.bg-indigo-900{--tw-bg-opacity: 1;background-color:rgb(49 46 129 / var(--tw-bg-opacity))}.bg-indigo-900\/20{background-color:#312e8133}.bg-indigo-900\/60{background-color:#312e8199}.bg-indigo-950\/90{background-color:#1e1b4be6}.bg-pink-500{--tw-bg-opacity: 1;background-color:rgb(236 72 153 / var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity))}.bg-red-500\/45{background-color:#ef444473}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity))}.bg-red-600\/70{background-color:#dc2626b3}.bg-red-700\/20{background-color:#b91c1c33}.bg-red-700\/60{background-color:#b91c1c99}.bg-red-900\/35{background-color:#7f1d1d59}.bg-red-900\/40{background-color:#7f1d1d66}.bg-red-900\/45{background-color:#7f1d1d73}.bg-red-900\/50{background-color:#7f1d1d80}.bg-rose-600{--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity))}.bg-rose-900\/80{background-color:#881337cc}.bg-sky-600{--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity))}.bg-sky-700\/20{background-color:#0369a133}.bg-slate-500{--tw-bg-opacity: 1;background-color:rgb(100 116 139 / var(--tw-bg-opacity))}.bg-slate-600{--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity))}.bg-slate-700{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}.bg-slate-700\/30{background-color:#3341554d}.bg-slate-700\/60{background-color:#33415599}.bg-slate-700\/70{background-color:#334155b3}.bg-slate-700\/80{background-color:#334155cc}.bg-slate-800{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}.bg-slate-800\/70{background-color:#1e293bb3}.bg-slate-800\/80{background-color:#1e293bcc}.bg-slate-900{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity))}.bg-slate-900\/35{background-color:#0f172a59}.bg-slate-900\/40{background-color:#0f172a66}.bg-slate-900\/70{background-color:#0f172ab3}.bg-slate-950\/80{background-color:#020617cc}.bg-slate-950\/90{background-color:#020617e6}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-white\/10{background-color:#ffffff1a}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity))}.bg-zinc-900{--tw-bg-opacity: 1;background-color:rgb(24 24 27 / var(--tw-bg-opacity))}.bg-zinc-900\/90{background-color:#18181be6}.bg-zinc-950{--tw-bg-opacity: 1;background-color:rgb(9 9 11 / var(--tw-bg-opacity))}.bg-zinc-950\/95{background-color:#09090bf2}.bg-cover{background-size:cover}.fill-slate-200{fill:#e2e8f0}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-4{padding:1rem}.px-0{padding-left:0;padding-right:0}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-\[1px\]{padding-top:1px;padding-bottom:1px}.py-\[2px\]{padding-top:2px;padding-bottom:2px}.pb-0{padding-bottom:0}.pb-1{padding-bottom:.25rem}.pr-0{padding-right:0}.pt-0\.5{padding-top:.125rem}.pt-1{padding-top:.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-\[0\.45rem\]{font-size:.45rem}.text-\[0\.55em\]{font-size:.55em}.text-\[0\.55rem\]{font-size:.55rem}.text-\[0\.5rem\]{font-size:.5rem}.text-\[0\.65rem\]{font-size:.65rem}.text-\[0\.6rem\]{font-size:.6rem}.text-\[0\.72rem\]{font-size:.72rem}.text-\[0\.75rem\]{font-size:.75rem}.text-\[0\.7rem\]{font-size:.7rem}.text-\[0\.85rem\]{font-size:.85rem}.text-\[0\.8rem\]{font-size:.8rem}.text-\[1\.1rem\]{font-size:1.1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-none{line-height:1}.leading-normal{line-height:1.5}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-amber-100{--tw-text-opacity: 1;color:rgb(254 243 199 / var(--tw-text-opacity))}.text-amber-200{--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity))}.text-amber-200\/80{color:#fde68acc}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity))}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity))}.text-amber-50{--tw-text-opacity: 1;color:rgb(255 251 235 / var(--tw-text-opacity))}.text-amber-50\/90{color:#fffbebe6}.text-amber-950{--tw-text-opacity: 1;color:rgb(69 26 3 / var(--tw-text-opacity))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity))}.text-cyan-100{--tw-text-opacity: 1;color:rgb(207 250 254 / var(--tw-text-opacity))}.text-cyan-300{--tw-text-opacity: 1;color:rgb(103 232 249 / var(--tw-text-opacity))}.text-cyan-50{--tw-text-opacity: 1;color:rgb(236 254 255 / var(--tw-text-opacity))}.text-emerald-100{--tw-text-opacity: 1;color:rgb(209 250 229 / var(--tw-text-opacity))}.text-emerald-200{--tw-text-opacity: 1;color:rgb(167 243 208 / var(--tw-text-opacity))}.text-emerald-300{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity))}.text-emerald-50{--tw-text-opacity: 1;color:rgb(236 253 245 / var(--tw-text-opacity))}.text-emerald-50\/90{color:#ecfdf5e6}.text-emerald-950{--tw-text-opacity: 1;color:rgb(2 44 34 / var(--tw-text-opacity))}.text-fuchsia-50{--tw-text-opacity: 1;color:rgb(253 244 255 / var(--tw-text-opacity))}.text-fuchsia-900{--tw-text-opacity: 1;color:rgb(112 26 117 / var(--tw-text-opacity))}.text-indigo-100\/80{color:#e0e7ffcc}.text-indigo-200{--tw-text-opacity: 1;color:rgb(199 210 254 / var(--tw-text-opacity))}.text-indigo-50{--tw-text-opacity: 1;color:rgb(238 242 255 / var(--tw-text-opacity))}.text-indigo-50\/90{color:#eef2ffe6}.text-lime-200{--tw-text-opacity: 1;color:rgb(217 249 157 / var(--tw-text-opacity))}.text-lime-300{--tw-text-opacity: 1;color:rgb(190 242 100 / var(--tw-text-opacity))}.text-lime-400{--tw-text-opacity: 1;color:rgb(163 230 53 / var(--tw-text-opacity))}.text-red-100\/90{color:#fee2e2e6}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity))}.text-rose-300{--tw-text-opacity: 1;color:rgb(253 164 175 / var(--tw-text-opacity))}.text-rose-50{--tw-text-opacity: 1;color:rgb(255 241 242 / var(--tw-text-opacity))}.text-sky-200{--tw-text-opacity: 1;color:rgb(186 230 253 / var(--tw-text-opacity))}.text-sky-300{--tw-text-opacity: 1;color:rgb(125 211 252 / var(--tw-text-opacity))}.text-slate-100{--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}.text-slate-200{--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity))}.text-slate-300{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.text-slate-400\/60{color:#94a3b899}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity))}.text-teal-400{--tw-text-opacity: 1;color:rgb(45 212 191 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.text-white\/90{color:#ffffffe6}.underline{text-decoration-line:underline}.accent-cyan-400{accent-color:#22d3ee}.accent-cyan-500{accent-color:#06b6d4}.accent-emerald-400{accent-color:#34d399}.accent-emerald-500{accent-color:#10b981}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-black\/30{--tw-shadow-color: rgb(0 0 0 / .3);--tw-shadow: var(--tw-shadow-colored)}.shadow-black\/40{--tw-shadow-color: rgb(0 0 0 / .4);--tw-shadow: var(--tw-shadow-colored)}.outline{outline-style:solid}.outline-2{outline-width:2px}.outline-cyan-400\/60{outline-color:#22d3ee99}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-amber-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(252 211 77 / var(--tw-ring-opacity))}.ring-emerald-300\/70{--tw-ring-color: rgb(110 231 183 / .7)}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert: invert(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[width\,height\]{transition-property:width,height;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@keyframes batteryTickWarn{0%,49%{background-color:#fffffff2}50%,to{background-color:#ef4444f2}}.battery-tick-warn{animation:batteryTickWarn .4s steps(2,end) infinite}@keyframes batteryUrgentFlash{0%,49%{opacity:1}50%,to{opacity:.25}}.battery-urgent-flash{animation:batteryUrgentFlash .4s steps(2,end) infinite}.no-touch-select{-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none;-webkit-touch-callout:none}.\[clip-path\:circle\(50\%\)\]{clip-path:circle(50%)}.\[writing-mode\:vertical-rl\]{writing-mode:vertical-rl}:root{font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}body{margin:0;min-height:100vh;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}*{scrollbar-width:thin;scrollbar-color:#3b82f6 rgba(255,255,255,.08)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}*::-webkit-scrollbar{width:1px;height:1px}*::-webkit-scrollbar-track{background:#ffffff14}*::-webkit-scrollbar-thumb{background-color:#3b82f6;border-radius:9999px}.ha-hue-slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red);cursor:pointer}.ha-hue-slider:disabled{opacity:.6;cursor:not-allowed}.ha-hue-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:.75rem;height:.75rem;border-radius:9999px;border:1px solid rgba(255,255,255,.7);background:#fff}.ha-hue-slider::-webkit-slider-runnable-track{height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.ha-hue-slider::-moz-range-thumb{width:.75rem;height:.75rem;border-radius:9999px;border:1px solid rgba(255,255,255,.7);background:#fff}.ha-hue-slider::-moz-range-track{height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.placeholder\:text-slate-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.placeholder\:text-slate-400::placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.hover\:-translate-y-0\.5:hover{--tw-translate-y: -.125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-rose-500:hover{--tw-border-opacity: 1;border-color:rgb(244 63 94 / var(--tw-border-opacity))}.hover\:border-sky-500:hover{--tw-border-opacity: 1;border-color:rgb(14 165 233 / var(--tw-border-opacity))}.hover\:bg-amber-400:hover{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity))}.hover\:bg-amber-800:hover{--tw-bg-opacity: 1;background-color:rgb(146 64 14 / var(--tw-bg-opacity))}.hover\:bg-cyan-400:hover{--tw-bg-opacity: 1;background-color:rgb(34 211 238 / var(--tw-bg-opacity))}.hover\:bg-cyan-800:hover{--tw-bg-opacity: 1;background-color:rgb(21 94 117 / var(--tw-bg-opacity))}.hover\:bg-emerald-400:hover{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity))}.hover\:bg-emerald-500:hover{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity))}.hover\:bg-emerald-700:hover{--tw-bg-opacity: 1;background-color:rgb(4 120 87 / var(--tw-bg-opacity))}.hover\:bg-emerald-800:hover{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity))}.hover\:bg-fuchsia-500:hover{--tw-bg-opacity: 1;background-color:rgb(217 70 239 / var(--tw-bg-opacity))}.hover\:bg-indigo-500:hover{--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity))}.hover\:bg-indigo-800:hover{--tw-bg-opacity: 1;background-color:rgb(55 48 163 / var(--tw-bg-opacity))}.hover\:bg-pink-400:hover{--tw-bg-opacity: 1;background-color:rgb(244 114 182 / var(--tw-bg-opacity))}.hover\:bg-red-600:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity))}.hover\:bg-rose-500:hover{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity))}.hover\:bg-rose-800:hover{--tw-bg-opacity: 1;background-color:rgb(159 18 57 / var(--tw-bg-opacity))}.hover\:bg-sky-500:hover{--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity))}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity))}.hover\:bg-slate-600:hover{--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity))}.hover\:bg-slate-800\/80:hover{background-color:#1e293bcc}.hover\:text-blue-500:hover{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.hover\:shadow-xl:hover{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:brightness-110:hover{--tw-brightness: brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-emerald-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(16 185 129 / var(--tw-ring-opacity))}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:outline:focus-visible{outline-style:solid}.focus-visible\:outline-1:focus-visible{outline-width:1px}.focus-visible\:outline-offset-1:focus-visible{outline-offset:1px}.focus-visible\:outline-slate-500:focus-visible{outline-color:#64748b}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-amber-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(252 211 77 / var(--tw-ring-opacity))}.focus-visible\:ring-emerald-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(110 231 183 / var(--tw-ring-opacity))}.focus-visible\:ring-indigo-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(165 180 252 / var(--tw-ring-opacity))}.active\:scale-95:active{--tw-scale-x: .95;--tw-scale-y: .95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:scale-\[0\.99\]:active{--tw-scale-x: .99;--tw-scale-y: .99;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:brightness-125:active{--tw-brightness: brightness(1.25);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.disabled\:hover\:bg-inherit:hover:disabled{background-color:inherit}@media(min-width:640px){.sm\:block{display:block}.sm\:min-h-\[18rem\]{min-height:18rem}.sm\:basis-auto{flex-basis:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:items-center{align-items:center}.sm\:text-2xl{font-size:1.5rem;line-height:2rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}}@media(min-width:768px){.md\:h-full{height:100%}.md\:h-screen{height:100vh}.md\:min-h-0{min-height:0px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-\[minmax\(0\,1\.4fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}.md\:grid-cols-\[minmax\(0\,1fr\)_18rem\]{grid-template-columns:minmax(0,1fr) 18rem}.md\:overflow-hidden{overflow:hidden}.md\:overflow-y-auto{overflow-y:auto}.md\:text-lg{font-size:1.125rem;line-height:1.75rem}}@media(min-width:1024px){.lg\:col-span-2{grid-column:span 2 / span 2}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:grid-cols-\[minmax\(0\,1\.25fr\)_minmax\(0\,0\.9fr\)\]{grid-template-columns:minmax(0,1.25fr) minmax(0,.9fr)}.lg\:grid-cols-\[minmax\(0\,1fr\)_20rem\]{grid-template-columns:minmax(0,1fr) 20rem}} diff --git a/server/public/assets/index-DmVJMLH1.css b/server/public/assets/index-DmVJMLH1.css new file mode 100644 index 00000000..b6194974 --- /dev/null +++ b/server/public/assets/index-DmVJMLH1.css @@ -0,0 +1 @@ +*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.panel{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));padding:0;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.panel-section{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(23 23 23 / var(--tw-bg-opacity));padding:0;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.panel-muted{border-radius:.375rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.surface{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(38 38 38 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.surface-muted{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(245 245 245 / var(--tw-text-opacity))}.field-input{border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(82 82 82 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.field-input::-moz-placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.field-input::placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.field-input:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(14 165 233 / var(--tw-ring-opacity))}.button-dark{border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(125 211 252 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity));padding:.125rem;font-size:.875rem;line-height:1.25rem;font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.button-dark:hover{--tw-border-opacity: 1;border-color:rgb(14 165 233 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity))}.button-danger{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity));padding:.125rem;font-size:.875rem;line-height:1.25rem;font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.button-danger:hover{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity))}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-x-0{left:0;right:0}.bottom-0{bottom:0}.bottom-0\.5{bottom:.125rem}.bottom-1{bottom:.25rem}.bottom-2{bottom:.5rem}.left-0{left:0}.left-0\.5{left:.125rem}.left-1{left:.25rem}.left-1\/2{left:50%}.left-2{left:.5rem}.right-0{right:0}.right-0\.5{right:.125rem}.right-1{right:.25rem}.right-2{right:.5rem}.top-0{top:0}.top-0\.5{top:.125rem}.top-1{top:.25rem}.top-1\/2{top:50%}.top-10{top:2.5rem}.top-6{top:1.5rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[120\]{z-index:120}.order-1{order:1}.order-2{order:2}.col-span-full{grid-column:1 / -1}.m-0{margin:0}.mx-auto{margin-left:auto;margin-right:auto}.-mt-0\.5{margin-top:-.125rem}.mr-0{margin-right:0}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-auto{margin-top:auto}.\!block{display:block!important}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.aspect-\[4\/3\]{aspect-ratio:4/3}.aspect-square{aspect-ratio:1 / 1}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-28{height:7rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-40{height:10rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-64{height:16rem}.h-\[14rem\]{height:14rem}.h-\[2px\]{height:2px}.h-\[3\.5rem\]{height:3.5rem}.h-\[70\%\]{height:70%}.h-\[7rem\]{height:7rem}.h-\[min\(100svh\,32rem\)\]{height:min(100svh,32rem)}.h-\[min\(60svh\,24rem\)\]{height:min(60svh,24rem)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-32{max-height:8rem}.max-h-40{max-height:10rem}.max-h-52{max-height:13rem}.max-h-72{max-height:18rem}.max-h-80{max-height:20rem}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-screen{max-height:100vh}.min-h-0{min-height:0px}.min-h-\[1\.5rem\]{min-height:1.5rem}.min-h-\[14rem\]{min-height:14rem}.min-h-\[16rem\]{min-height:16rem}.min-h-\[3\.5rem\]{min-height:3.5rem}.min-h-\[5rem\]{min-height:5rem}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-1\/2{width:50%}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-\[12\.5rem\]{width:12.5rem}.w-\[12rem\]{width:12rem}.w-\[20rem\]{width:20rem}.w-\[2px\]{width:2px}.w-\[9rem\]{width:9rem}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-\[0\]{min-width:0}.min-w-\[10rem\]{min-width:10rem}.min-w-\[12rem\]{min-width:12rem}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-\[70vw\]{max-width:70vw}.max-w-\[80vw\]{max-width:80vw}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-\[1\.1\]{flex:1.1}.flex-\[1\.22\]{flex:1.22}.flex-\[1_1_12rem\]{flex:1 1 12rem}.shrink-0{flex-shrink:0}.basis-full{flex-basis:100%}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\[minmax\(0\,0\.7fr\)_minmax\(0\,2\.1fr\)_minmax\(0\,0\.7fr\)\]{grid-template-columns:minmax(0,.7fr) minmax(0,2.1fr) minmax(0,.7fr)}.grid-cols-\[minmax\(0\,1\.2fr\)_repeat\(4\,minmax\(0\,1fr\)\)\]{grid-template-columns:minmax(0,1.2fr) repeat(4,minmax(0,1fr))}.grid-cols-\[minmax\(0\,1\.35fr\)_minmax\(0\,0\.95fr\)\]{grid-template-columns:minmax(0,1.35fr) minmax(0,.95fr)}.grid-cols-\[minmax\(0\,1\.3fr\)_minmax\(0\,0\.22fr\)\]{grid-template-columns:minmax(0,1.3fr) minmax(0,.22fr)}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,0\.7fr\)_minmax\(0\,1\.9fr\)_minmax\(0\,0\.7fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,.7fr) minmax(0,1.9fr) minmax(0,.7fr)}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,0\.9fr\)_minmax\(0\,0\.75fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,.9fr) minmax(0,.75fr)}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1\.4fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,1.4fr)}.grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}.grid-rows-\[auto_1fr\]{grid-template-rows:auto 1fr}.grid-rows-\[auto_auto_1fr\]{grid-template-rows:auto auto 1fr}.grid-rows-\[auto_auto_1fr_auto\]{grid-template-rows:auto auto 1fr auto}.grid-rows-\[minmax\(0\,1fr\)_auto\]{grid-template-rows:minmax(0,1fr) auto}.grid-rows-\[minmax\(0\,1fr\)_minmax\(0\,1fr\)_minmax\(0\,1fr\)\]{grid-template-rows:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.content-center{align-content:center}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0px}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.self-start{align-self:flex-start}.self-center{align-self:center}.self-stretch{align-self:stretch}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity))}.border-amber-200\/30{border-color:#fde68a4d}.border-amber-200\/70{border-color:#fde68ab3}.border-amber-300\/70{border-color:#fcd34db3}.border-amber-300\/80{border-color:#fcd34dcc}.border-amber-400\/30{border-color:#fbbf244d}.border-amber-400\/60{border-color:#fbbf2499}.border-amber-600\/60{border-color:#d9770699}.border-amber-700\/60{border-color:#b4530999}.border-blue-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity))}.border-cyan-200\/50{border-color:#a5f3fc80}.border-cyan-300{--tw-border-opacity: 1;border-color:rgb(103 232 249 / var(--tw-border-opacity))}.border-cyan-300\/70{border-color:#67e8f9b3}.border-cyan-500\/40{border-color:#06b6d466}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity))}.border-emerald-200\/70{border-color:#a7f3d0b3}.border-emerald-300\/70{border-color:#6ee7b7b3}.border-emerald-400\/60{border-color:#34d39999}.border-emerald-500\/40{border-color:#10b98166}.border-emerald-700{--tw-border-opacity: 1;border-color:rgb(4 120 87 / var(--tw-border-opacity))}.border-emerald-700\/60{border-color:#04785799}.border-emerald-900{--tw-border-opacity: 1;border-color:rgb(6 78 59 / var(--tw-border-opacity))}.border-emerald-950{--tw-border-opacity: 1;border-color:rgb(2 44 34 / var(--tw-border-opacity))}.border-fuchsia-300\/70{border-color:#f0abfcb3}.border-indigo-200\/70{border-color:#c7d2feb3}.border-indigo-300\/70{border-color:#a5b4fcb3}.border-indigo-400\/30{border-color:#818cf84d}.border-indigo-700{--tw-border-opacity: 1;border-color:rgb(67 56 202 / var(--tw-border-opacity))}.border-indigo-700\/60{border-color:#4338ca99}.border-pink-200{--tw-border-opacity: 1;border-color:rgb(251 207 232 / var(--tw-border-opacity))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity))}.border-red-400\/60{border-color:#f8717199}.border-rose-300{--tw-border-opacity: 1;border-color:rgb(253 164 175 / var(--tw-border-opacity))}.border-rose-800{--tw-border-opacity: 1;border-color:rgb(159 18 57 / var(--tw-border-opacity))}.border-sky-300{--tw-border-opacity: 1;border-color:rgb(125 211 252 / var(--tw-border-opacity))}.border-sky-400\/50{border-color:#38bdf880}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity))}.border-slate-200\/30{border-color:#e2e8f04d}.border-slate-400\/60{border-color:#94a3b899}.border-slate-600{--tw-border-opacity: 1;border-color:rgb(71 85 105 / var(--tw-border-opacity))}.border-slate-600\/40{border-color:#47556966}.border-slate-600\/60{border-color:#47556999}.border-slate-700{--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity))}.border-slate-700\/60{border-color:#33415599}.border-slate-700\/70{border-color:#334155b3}.border-slate-700\/80{border-color:#334155cc}.border-slate-800{--tw-border-opacity: 1;border-color:rgb(30 41 59 / var(--tw-border-opacity))}.border-slate-800\/60{border-color:#1e293b99}.border-transparent{border-color:transparent}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity))}.border-white\/40{border-color:#fff6}.border-white\/60{border-color:#fff9}.bg-amber-100\/95{background-color:#fef3c7f2}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity))}.bg-amber-400\/80{background-color:#fbbf24cc}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity))}.bg-amber-500\/30{background-color:#f59e0b4d}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity))}.bg-amber-600\/70{background-color:#d97706b3}.bg-amber-700\/20{background-color:#b4530933}.bg-amber-700\/30{background-color:#b453094d}.bg-amber-700\/35{background-color:#b4530959}.bg-amber-900{--tw-bg-opacity: 1;background-color:rgb(120 53 15 / var(--tw-bg-opacity))}.bg-amber-900\/40{background-color:#78350f66}.bg-amber-900\/60{background-color:#78350f99}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity))}.bg-black\/20{background-color:#0003}.bg-black\/30{background-color:#0000004d}.bg-black\/40{background-color:#0006}.bg-black\/50{background-color:#00000080}.bg-black\/55{background-color:#0000008c}.bg-black\/60{background-color:#0009}.bg-black\/70{background-color:#000000b3}.bg-black\/75{background-color:#000000bf}.bg-black\/80{background-color:#000c}.bg-black\/85{background-color:#000000d9}.bg-cyan-300\/80{background-color:#67e8f9cc}.bg-cyan-400\/10{background-color:#22d3ee1a}.bg-cyan-500{--tw-bg-opacity: 1;background-color:rgb(6 182 212 / var(--tw-bg-opacity))}.bg-cyan-500\/80{background-color:#06b6d4cc}.bg-cyan-900{--tw-bg-opacity: 1;background-color:rgb(22 78 99 / var(--tw-bg-opacity))}.bg-cyan-900\/45{background-color:#164e6373}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity))}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity))}.bg-emerald-500\/45{background-color:#10b98173}.bg-emerald-500\/80{background-color:#10b981cc}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity))}.bg-emerald-600\/70{background-color:#059669b3}.bg-emerald-700\/20{background-color:#04785733}.bg-emerald-700\/60{background-color:#04785799}.bg-emerald-800{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity))}.bg-emerald-900{--tw-bg-opacity: 1;background-color:rgb(6 78 59 / var(--tw-bg-opacity))}.bg-emerald-900\/15{background-color:#064e3b26}.bg-emerald-900\/60{background-color:#064e3b99}.bg-emerald-900\/80{background-color:#064e3bcc}.bg-fuchsia-200{--tw-bg-opacity: 1;background-color:rgb(245 208 254 / var(--tw-bg-opacity))}.bg-fuchsia-600{--tw-bg-opacity: 1;background-color:rgb(192 38 211 / var(--tw-bg-opacity))}.bg-fuchsia-700{--tw-bg-opacity: 1;background-color:rgb(162 28 175 / var(--tw-bg-opacity))}.bg-fuchsia-800{--tw-bg-opacity: 1;background-color:rgb(134 25 143 / var(--tw-bg-opacity))}.bg-fuchsia-900\/45{background-color:#701a7573}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity))}.bg-indigo-600\/70{background-color:#4f46e5b3}.bg-indigo-900{--tw-bg-opacity: 1;background-color:rgb(49 46 129 / var(--tw-bg-opacity))}.bg-indigo-900\/20{background-color:#312e8133}.bg-indigo-900\/60{background-color:#312e8199}.bg-indigo-950\/90{background-color:#1e1b4be6}.bg-pink-500{--tw-bg-opacity: 1;background-color:rgb(236 72 153 / var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity))}.bg-red-500\/45{background-color:#ef444473}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity))}.bg-red-600\/70{background-color:#dc2626b3}.bg-red-700\/20{background-color:#b91c1c33}.bg-red-700\/60{background-color:#b91c1c99}.bg-red-900\/35{background-color:#7f1d1d59}.bg-red-900\/40{background-color:#7f1d1d66}.bg-red-900\/45{background-color:#7f1d1d73}.bg-red-900\/50{background-color:#7f1d1d80}.bg-rose-600{--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity))}.bg-rose-900\/80{background-color:#881337cc}.bg-sky-600{--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity))}.bg-sky-700\/20{background-color:#0369a133}.bg-slate-500{--tw-bg-opacity: 1;background-color:rgb(100 116 139 / var(--tw-bg-opacity))}.bg-slate-600{--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity))}.bg-slate-700{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}.bg-slate-700\/30{background-color:#3341554d}.bg-slate-700\/60{background-color:#33415599}.bg-slate-700\/70{background-color:#334155b3}.bg-slate-700\/80{background-color:#334155cc}.bg-slate-800{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}.bg-slate-800\/70{background-color:#1e293bb3}.bg-slate-800\/80{background-color:#1e293bcc}.bg-slate-900{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity))}.bg-slate-900\/35{background-color:#0f172a59}.bg-slate-900\/40{background-color:#0f172a66}.bg-slate-900\/70{background-color:#0f172ab3}.bg-slate-950\/80{background-color:#020617cc}.bg-slate-950\/90{background-color:#020617e6}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-white\/10{background-color:#ffffff1a}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity))}.bg-zinc-900{--tw-bg-opacity: 1;background-color:rgb(24 24 27 / var(--tw-bg-opacity))}.bg-zinc-900\/90{background-color:#18181be6}.bg-zinc-950{--tw-bg-opacity: 1;background-color:rgb(9 9 11 / var(--tw-bg-opacity))}.bg-zinc-950\/95{background-color:#09090bf2}.bg-\[radial-gradient\(circle_at_center\,rgba\(34\,197\,94\,0\.14\)\,rgba\(0\,0\,0\,0\.96\)_68\%\)\]{background-image:radial-gradient(circle at center,#22c55e24,#000000f5 68%)}.bg-cover{background-size:cover}.fill-slate-200{fill:#e2e8f0}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-4{padding:1rem}.px-0{padding-left:0;padding-right:0}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-\[1px\]{padding-top:1px;padding-bottom:1px}.py-\[2px\]{padding-top:2px;padding-bottom:2px}.pb-0{padding-bottom:0}.pb-1{padding-bottom:.25rem}.pr-0{padding-right:0}.pt-0\.5{padding-top:.125rem}.pt-1{padding-top:.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-\[0\.45rem\]{font-size:.45rem}.text-\[0\.55em\]{font-size:.55em}.text-\[0\.55rem\]{font-size:.55rem}.text-\[0\.5rem\]{font-size:.5rem}.text-\[0\.65rem\]{font-size:.65rem}.text-\[0\.6rem\]{font-size:.6rem}.text-\[0\.72rem\]{font-size:.72rem}.text-\[0\.75rem\]{font-size:.75rem}.text-\[0\.7rem\]{font-size:.7rem}.text-\[0\.85rem\]{font-size:.85rem}.text-\[0\.8rem\]{font-size:.8rem}.text-\[1\.1rem\]{font-size:1.1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-none{line-height:1}.leading-normal{line-height:1.5}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-\[0\.18em\]{letter-spacing:.18em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-amber-100{--tw-text-opacity: 1;color:rgb(254 243 199 / var(--tw-text-opacity))}.text-amber-200{--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity))}.text-amber-200\/80{color:#fde68acc}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity))}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity))}.text-amber-50{--tw-text-opacity: 1;color:rgb(255 251 235 / var(--tw-text-opacity))}.text-amber-50\/90{color:#fffbebe6}.text-amber-950{--tw-text-opacity: 1;color:rgb(69 26 3 / var(--tw-text-opacity))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity))}.text-cyan-100{--tw-text-opacity: 1;color:rgb(207 250 254 / var(--tw-text-opacity))}.text-cyan-300{--tw-text-opacity: 1;color:rgb(103 232 249 / var(--tw-text-opacity))}.text-cyan-50{--tw-text-opacity: 1;color:rgb(236 254 255 / var(--tw-text-opacity))}.text-emerald-100{--tw-text-opacity: 1;color:rgb(209 250 229 / var(--tw-text-opacity))}.text-emerald-200{--tw-text-opacity: 1;color:rgb(167 243 208 / var(--tw-text-opacity))}.text-emerald-300{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity))}.text-emerald-50{--tw-text-opacity: 1;color:rgb(236 253 245 / var(--tw-text-opacity))}.text-emerald-50\/90{color:#ecfdf5e6}.text-emerald-500\/80{color:#10b981cc}.text-emerald-950{--tw-text-opacity: 1;color:rgb(2 44 34 / var(--tw-text-opacity))}.text-fuchsia-50{--tw-text-opacity: 1;color:rgb(253 244 255 / var(--tw-text-opacity))}.text-fuchsia-900{--tw-text-opacity: 1;color:rgb(112 26 117 / var(--tw-text-opacity))}.text-indigo-100\/80{color:#e0e7ffcc}.text-indigo-200{--tw-text-opacity: 1;color:rgb(199 210 254 / var(--tw-text-opacity))}.text-indigo-50{--tw-text-opacity: 1;color:rgb(238 242 255 / var(--tw-text-opacity))}.text-indigo-50\/90{color:#eef2ffe6}.text-lime-200{--tw-text-opacity: 1;color:rgb(217 249 157 / var(--tw-text-opacity))}.text-lime-300{--tw-text-opacity: 1;color:rgb(190 242 100 / var(--tw-text-opacity))}.text-lime-400{--tw-text-opacity: 1;color:rgb(163 230 53 / var(--tw-text-opacity))}.text-red-100\/90{color:#fee2e2e6}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity))}.text-rose-300{--tw-text-opacity: 1;color:rgb(253 164 175 / var(--tw-text-opacity))}.text-rose-50{--tw-text-opacity: 1;color:rgb(255 241 242 / var(--tw-text-opacity))}.text-sky-200{--tw-text-opacity: 1;color:rgb(186 230 253 / var(--tw-text-opacity))}.text-sky-300{--tw-text-opacity: 1;color:rgb(125 211 252 / var(--tw-text-opacity))}.text-slate-100{--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}.text-slate-200{--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity))}.text-slate-300{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.text-slate-400\/60{color:#94a3b899}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity))}.text-teal-400{--tw-text-opacity: 1;color:rgb(45 212 191 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.text-white\/90{color:#ffffffe6}.underline{text-decoration-line:underline}.accent-cyan-400{accent-color:#22d3ee}.accent-cyan-500{accent-color:#06b6d4}.accent-emerald-400{accent-color:#34d399}.accent-emerald-500{accent-color:#10b981}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-black\/30{--tw-shadow-color: rgb(0 0 0 / .3);--tw-shadow: var(--tw-shadow-colored)}.shadow-black\/40{--tw-shadow-color: rgb(0 0 0 / .4);--tw-shadow: var(--tw-shadow-colored)}.outline{outline-style:solid}.outline-2{outline-width:2px}.outline-cyan-400\/60{outline-color:#22d3ee99}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-amber-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(252 211 77 / var(--tw-ring-opacity))}.ring-emerald-300\/70{--tw-ring-color: rgb(110 231 183 / .7)}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert: invert(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[width\,height\]{transition-property:width,height;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@keyframes batteryTickWarn{0%,49%{background-color:#fffffff2}50%,to{background-color:#ef4444f2}}.battery-tick-warn{animation:batteryTickWarn .4s steps(2,end) infinite}@keyframes batteryUrgentFlash{0%,49%{opacity:1}50%,to{opacity:.25}}.battery-urgent-flash{animation:batteryUrgentFlash .4s steps(2,end) infinite}.no-touch-select{-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none;-webkit-touch-callout:none}.\[clip-path\:circle\(50\%\)\]{clip-path:circle(50%)}.\[writing-mode\:vertical-rl\]{writing-mode:vertical-rl}:root{font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}body{margin:0;min-height:100vh;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}*{scrollbar-width:thin;scrollbar-color:#3b82f6 rgba(255,255,255,.08)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}*::-webkit-scrollbar{width:1px;height:1px}*::-webkit-scrollbar-track{background:#ffffff14}*::-webkit-scrollbar-thumb{background-color:#3b82f6;border-radius:9999px}.ha-hue-slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red);cursor:pointer}.ha-hue-slider:disabled{opacity:.6;cursor:not-allowed}.ha-hue-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:.75rem;height:.75rem;border-radius:9999px;border:1px solid rgba(255,255,255,.7);background:#fff}.ha-hue-slider::-webkit-slider-runnable-track{height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.ha-hue-slider::-moz-range-thumb{width:.75rem;height:.75rem;border-radius:9999px;border:1px solid rgba(255,255,255,.7);background:#fff}.ha-hue-slider::-moz-range-track{height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.placeholder\:text-slate-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.placeholder\:text-slate-400::placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.hover\:-translate-y-0\.5:hover{--tw-translate-y: -.125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-rose-500:hover{--tw-border-opacity: 1;border-color:rgb(244 63 94 / var(--tw-border-opacity))}.hover\:border-sky-500:hover{--tw-border-opacity: 1;border-color:rgb(14 165 233 / var(--tw-border-opacity))}.hover\:bg-amber-400:hover{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity))}.hover\:bg-amber-800:hover{--tw-bg-opacity: 1;background-color:rgb(146 64 14 / var(--tw-bg-opacity))}.hover\:bg-cyan-400:hover{--tw-bg-opacity: 1;background-color:rgb(34 211 238 / var(--tw-bg-opacity))}.hover\:bg-cyan-800:hover{--tw-bg-opacity: 1;background-color:rgb(21 94 117 / var(--tw-bg-opacity))}.hover\:bg-emerald-400:hover{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity))}.hover\:bg-emerald-500:hover{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity))}.hover\:bg-emerald-700:hover{--tw-bg-opacity: 1;background-color:rgb(4 120 87 / var(--tw-bg-opacity))}.hover\:bg-emerald-800:hover{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity))}.hover\:bg-fuchsia-500:hover{--tw-bg-opacity: 1;background-color:rgb(217 70 239 / var(--tw-bg-opacity))}.hover\:bg-indigo-500:hover{--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity))}.hover\:bg-indigo-800:hover{--tw-bg-opacity: 1;background-color:rgb(55 48 163 / var(--tw-bg-opacity))}.hover\:bg-pink-400:hover{--tw-bg-opacity: 1;background-color:rgb(244 114 182 / var(--tw-bg-opacity))}.hover\:bg-red-600:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity))}.hover\:bg-rose-500:hover{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity))}.hover\:bg-rose-800:hover{--tw-bg-opacity: 1;background-color:rgb(159 18 57 / var(--tw-bg-opacity))}.hover\:bg-sky-500:hover{--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity))}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity))}.hover\:bg-slate-600:hover{--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity))}.hover\:bg-slate-800\/80:hover{background-color:#1e293bcc}.hover\:text-blue-500:hover{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.hover\:shadow-xl:hover{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:brightness-110:hover{--tw-brightness: brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-emerald-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(16 185 129 / var(--tw-ring-opacity))}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:outline:focus-visible{outline-style:solid}.focus-visible\:outline-1:focus-visible{outline-width:1px}.focus-visible\:outline-offset-1:focus-visible{outline-offset:1px}.focus-visible\:outline-slate-500:focus-visible{outline-color:#64748b}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-amber-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(252 211 77 / var(--tw-ring-opacity))}.focus-visible\:ring-emerald-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(110 231 183 / var(--tw-ring-opacity))}.focus-visible\:ring-indigo-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(165 180 252 / var(--tw-ring-opacity))}.active\:scale-95:active{--tw-scale-x: .95;--tw-scale-y: .95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:scale-\[0\.99\]:active{--tw-scale-x: .99;--tw-scale-y: .99;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:brightness-125:active{--tw-brightness: brightness(1.25);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.disabled\:hover\:bg-inherit:hover:disabled{background-color:inherit}@media(min-width:640px){.sm\:block{display:block}.sm\:min-h-\[18rem\]{min-height:18rem}.sm\:basis-auto{flex-basis:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:items-center{align-items:center}.sm\:text-2xl{font-size:1.5rem;line-height:2rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}}@media(min-width:768px){.md\:h-full{height:100%}.md\:h-screen{height:100vh}.md\:min-h-0{min-height:0px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-\[minmax\(0\,1\.4fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}.md\:grid-cols-\[minmax\(0\,1fr\)_18rem\]{grid-template-columns:minmax(0,1fr) 18rem}.md\:overflow-hidden{overflow:hidden}.md\:overflow-y-auto{overflow-y:auto}.md\:text-lg{font-size:1.125rem;line-height:1.75rem}}@media(min-width:1024px){.lg\:col-span-2{grid-column:span 2 / span 2}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:grid-cols-\[minmax\(0\,0\.95fr\)_minmax\(0\,1\.05fr\)\]{grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr)}.lg\:grid-cols-\[minmax\(0\,1\.25fr\)_minmax\(0\,0\.9fr\)\]{grid-template-columns:minmax(0,1.25fr) minmax(0,.9fr)}.lg\:grid-cols-\[minmax\(0\,1fr\)_20rem\]{grid-template-columns:minmax(0,1fr) 20rem}}@media(min-width:1280px){.xl\:grid-cols-\[minmax\(0\,1fr\)_minmax\(13rem\,15rem\)\]{grid-template-columns:minmax(0,1fr) minmax(13rem,15rem)}} diff --git a/server/public/assets/index-CZ7Wc8AL.js b/server/public/assets/index-zn-QfvQ7.js similarity index 95% rename from server/public/assets/index-CZ7Wc8AL.js rename to server/public/assets/index-zn-QfvQ7.js index 48164dca..f5c7a5ee 100644 --- a/server/public/assets/index-CZ7Wc8AL.js +++ b/server/public/assets/index-zn-QfvQ7.js @@ -15,7 +15,7 @@ Please change the parent to l&&l>o){const u=yi/100,f=1-u;if(n<=o)return 0;if(n<=l){const h=(n-o)/(l-o);return Math.round(Math.max(0,Math.min(1,h))*yi)}if(n>=s)return 100;const p=(n-l)/(s-l);return Math.round((u+Math.max(0,Math.min(1,p))*f)*100)}return null}const $N=1600,GN=800;function An(...n){return n.filter(Boolean).join(" ")}function Ud({visual:n,orientation:s="horizontal",variant:l="inline",compact:o=!1,showLabel:u,className:f=""}){const p=l==="background",h=s==="vertical",x=u??!p;if(!n?.available){if(p){const ee=yi,oe=An("absolute z-10",h?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",k&&!S&&"battery-tick-warn"),ue=h?{bottom:`${ee}%`}:{left:`${ee}%`},U=An("absolute inset-0 pointer-events-none",f);return r.jsxs("div",{className:U,children:[r.jsx("div",{className:"absolute inset-0 bg-slate-900/35"}),r.jsx("div",{className:oe,style:ue})]})}return h?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??yi,S=!!n.urgentActive,k=!!n.warnActive,C=S?`${GN}ms`:k?`${$N}ms`:void 0,w=p?S||k?"bg-red-500/45":"bg-emerald-500/45":S||k?"bg-red-500":"bg-emerald-500",A=S||k?"bg-red-900/35":"bg-slate-900/35",N=S||k?"bg-red-900/45":"bg-slate-900/35",R=An(p?"absolute inset-0 pointer-events-none":"relative pointer-events-auto",h&&!p?"flex flex-col items-center justify-center":"w-full",f);if(p){const ee=h?{height:`${v}%`}:{width:`${v}%`},oe=An("absolute",h?"bottom-0 left-0 right-0":"left-0 top-0 bottom-0",w,"transition-[width,height]",S&&"battery-urgent-flash"),ue=An("absolute z-10",h?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",k&&!S&&"battery-tick-warn"),U=h?{bottom:`${y}%`}:{left:`${y}%`};return r.jsxs("div",{className:R,children:[r.jsx("div",{className:An("absolute inset-0",A,S&&"battery-urgent-flash")}),r.jsx("div",{className:oe,style:{...ee,animationDuration:C}}),r.jsx("div",{className:ue,style:U})]})}const E=An("relative overflow-hidden rounded-sm border border-slate-800",S||k?N:"bg-zinc-900/90",S&&"battery-urgent-flash",h?"w-full flex-1":o?"h-4":"h-5"),O=h?{height:`${v}%`}:{width:`${v}%`},K=An("absolute",h?"bottom-0 left-0 right-0":"left-0 top-0 bottom-0",w,"transition-[width,height]",S&&"battery-urgent-flash"),D=An("absolute z-10",h?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",k&&!S&&"battery-tick-warn"),H=h?{bottom:`${y}%`}:{left:`${y}%`},X=`Battery ${g}%`,$=An("pointer-events-none absolute inset-0 flex items-center justify-center text-center font-semibold",h?o?"text-[0.55rem]":"text-[0.65rem]":"text-xs"),G=An("rounded px-1.5 py-0.5",p?"bg-black/30 text-slate-100":"bg-black/50 text-slate-100");return r.jsxs("div",{className:R,children:[r.jsxs("div",{className:E,children:[r.jsx("div",{className:K,style:{...O,animationDuration:C}}),r.jsx("div",{className:D,style:H})]}),x&&!h?r.jsx("div",{className:$,children:r.jsx("span",{className:G,children:X})}):null,x&&h?r.jsx("div",{className:"mt-0.5 text-[0.65rem] font-semibold text-slate-100",children:r.jsxs("span",{className:G,children:[g,"%"]})}):null]})}function YN({mobileHud:n=!1,isActiveDriver:s=!1,idleSkipSeconds:l=null}){const o=n?"text-3xl":"text-5xl",u=n?"text-xs":"text-sm",f=n?"text-[0.55rem]":"text-[0.75rem]",p=n?"px-4 py-3":"px-6 py-4",h=s&&typeof l=="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 ${o}`,children:"IT IS YOUR TURN!"}),r.jsx("div",{className:`text-amber-200/80 ${u}`,children:"Start driving!"}),h?r.jsxs("div",{className:`text-red-100/90 ${f}`,children:["Idle skip in ",l,"s"]}):null]})})}function Mo(n){return Math.max(0,Math.min(1,n))}function Ug(n){return(n-90)*Math.PI/180}function hi(n,s,l,o){const u=Ug(o);return{x:n+l*Math.cos(u),y:s+l*Math.sin(u)}}function FN(n,s,l,o,u){let f=o,p=u;p<=f&&(p+=360);const h=hi(n,s,l,f),x=hi(n,s,l,p);return["M",h.x,h.y,"A",l,l,0,0,1,x.x,x.y].join(" ")}function pf(n,s){if(s)return"#ef4444";const l=Math.abs(n);return l>900?"#f59e0b":l>300?"#22c55e":"#64748b"}function XN(n,s){if(n==null||n<=0)return"hsl(200 60% 18%)";const o=Mo(n/(s||1));return`hsl(${(200+Math.pow(o,.45)*360)%360} 100% 60%)`}function QN(n,s){if(s)return"#ef4444";const l=Mo(n==null?0:n/4095),o=[47,55,69],u=[245,158,11],[f,p,h]=o.map((x,g)=>Math.round(x+(u[g]-x)*l));return`rgb(${f}, ${p}, ${h})`}function KN({count:n,totalSpan:s,gap:l,startAngle:o}){const f=(s-l*(n-1))/n,p=[];let h=o;for(let x=0;x0?.65:null;return r.jsxs("g",{style:{transformOrigin:`${n}px ${s}px`,animation:h?`spin ${h}s linear infinite`:"none",animationDirection:h?"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+p*Math.cos(v),S=s+p*Math.sin(v);return r.jsx("line",{x1:n,y1:s,x2:y,y2:S,stroke:f,strokeWidth:"4",strokeLinecap:"round"},g)}),o?r.jsx("circle",{cx:n,cy:s,r:p+8,stroke:"#ef4444",strokeWidth:"3",fill:"none",className:"animate-pulse"}):null]})}function JN({cx:n,cy:s,current:l,overcurrent:o,variant:u,dirtLeft:f,dirtRight:p}){const h=Math.abs(l),x=pf(l,o),g=1,v=96,y=12,S=`main-brush-pattern-a-${u}`,k=`main-brush-pattern-b-${u}`,C=h>0?.6:null,M=l>=0?1:-1;return r.jsxs("g",{children:[r.jsx("defs",{children:[S,k].map((w,A)=>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 ${M*(A===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(#${k})`,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 Hd({sensors:n={},variant:s="full",size:l,overlay:o=!1}){const u=l||(s==="mini"?190:260),f=u/2,p=u*.07,h=f,x=f+p,g=f*.8,v=g-4,y=g+4,S=g-14,k=g-6,C=g*.65,M=n?.bumpsAndWheelDrops||{},w=n?.wheelOvercurrents||{},A=n?.wheelLeftCurrentMa??0,N=n?.wheelRightCurrentMa??0,R=n?.sideBrushCurrentMa??0,E=n?.mainBrushCurrentMa??0,O=6,K=M.bumpLeft?O:0,D=M.bumpRight?O:0,H=KN({count:6,totalSpan:140,gap:6,startAngle:-70}),X=["L","FL","CL","CR","FR","R"],$=[n?.lightBumpLeftSignal,n?.lightBumpFrontLeftSignal,n?.lightBumpCenterLeftSignal,n?.lightBumpCenterRightSignal,n?.lightBumpFrontRightSignal,n?.lightBumpRightSignal],G=H.map((U,q)=>({label:X[q],start:U.start,end:U.end,value:$[q]})),ee=[{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}],oe=$.filter(U=>U!=null),ue=oe.length?Math.max(...oe,1200):1200;return r.jsxs("div",{className:`${o?"relative":"surface relative p-1"}`,style:o?{width:`${u}px`,height:`${u}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–",ue]})]}),r.jsxs("svg",{width:"100%",height:"100%",viewBox:`0 0 ${u} ${u}`,preserveAspectRatio:"xMidYMid meet",className:"mx-auto block",children:[r.jsx("circle",{cx:h,cy:x,r:g,fill:"#0f172a",stroke:"#334155",strokeWidth:"2"}),r.jsx(ix,{cx:h-C,cy:x,current:A,drop:M.wheelDropLeft,overcurrent:w.leftWheel,label:"L"}),r.jsx(ix,{cx:h+C,cy:x,current:N,drop:M.wheelDropRight,overcurrent:w.rightWheel,label:"R"}),r.jsx(IN,{cx:h+g*.65,cy:x-g*.55,current:R,overcurrent:w.sideBrush}),r.jsx(JN,{cx:h,cy:x,current:E,overcurrent:w.mainBrush,variant:s,dirtLeft:n?.dirtDetectLeft,dirtRight:n?.dirtDetect}),G.map(U=>{const q=XN(U.value,ue),L=y+4,Z=L+28;return r.jsx(ZN,{cx:h,cy:x,rBase:Z,rTip:L,startDeg:U.start,endDeg:U.end,color:q,value:U.value,max:ue},U.label)}),ee.map(U=>r.jsx(bd,{cx:h,cy:x,rInner:S,rOuter:k,startDeg:U.start,endDeg:U.end,color:QN(U.value,U.active),opacity:1,pulse:!!U.active},U.label)),r.jsx(bd,{cx:h,cy:x,rInner:v-K,rOuter:y-K,startDeg:-70,endDeg:-6,color:M.bumpLeft?"#ef4444":"#475569",opacity:1,pulse:!!M.bumpLeft}),r.jsx(bd,{cx:h,cy:x,rInner:v-D,rOuter:y-D,startDeg:6,endDeg:70,color:M.bumpRight?"#ef4444":"#475569",opacity:1,pulse:!!M.bumpRight})]})]})}function PN({sensors:n,label:s,roverColor:l=null,status:o,audioStatus:u,levelStatus:f,layoutFormat:p="desktop",variant:h="default",driverLabel:x=null,showTopDown:g=!1,mobileHud:v=!1,mapPosition:y="top-center",turnTimerText:S=null,labelScale:k=1}){const C=v,M=p==="mobile-portrait",w=C?"text-[0.45rem]":"text-[0.65rem]",A=C?"px-0.25 py-0.25":"px-1 py-0.5",N=C?"px-0.25 py-0.25":"px-0.5 py-0.5",R=C?"text-[0.55rem]":"text-[0.8rem]",E=C?"left-0.5 top-0.5":"left-1 top-1",O=C?"text-[0.5rem]":"text-[0.7rem]",K=C?"px-0.5 py-0.25":"px-1 py-0.5",D=C?"left-0.5 top-1/2":"left-1 top-1/2",H="bottom-0.5",X={transform:`translateX(-50%) scale(${k})`,transformOrigin:"center bottom"},$="240px",G=M?.3:C?.33:.7,oe={width:$,height:$,opacity:C?.6:.7,transform:y==="top-center"?`translateX(-50%) scale(${G})`:`scale(${G})`,transformOrigin:y==="bottom-left"?"bottom left":y==="top-center"?"top center":"top right",...y==="bottom-left"?{left:"0.25rem",bottom:"0.25rem"}:y==="top-center"?{left:"50%",top:"0.25rem"}:{right:"0.25rem",top:"0.25rem"}};if(h==="none")return null;if(h==="spectator"){const ue=[["Voltage",n?.voltageMv!=null?`${(n.voltageMv/1e3).toFixed(2)} V`:"--"],["Current",n?.currentMa!=null?`${n.currentMa} mA`:"--"],["Charge",n?.batteryChargeMah!=null?`${n.batteryChargeMah}`:"--"],["OI",n?.oiMode?.label||"--"]],U=!!n?.chargingSources?.homeBase,q=n?.chargingState?.label||"",L=!!(q&&q.toLowerCase()!=="not charging"),Z=n?.oiMode?.label||"Unknown",se=Z.toLowerCase(),ce=se==="full"?"bg-emerald-500/80 text-emerald-50":se==="safe"?"bg-amber-400/80 text-amber-950":se==="passive"?"bg-slate-700/80 text-slate-100":"bg-slate-700/60 text-slate-200",T=U?"bg-emerald-500/80 text-emerald-50":"bg-slate-700/70 text-slate-200",V=L?"bg-emerald-500/80 text-emerald-50":U?"bg-amber-400/80 text-amber-950":"bg-slate-700/70 text-slate-200";return r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:[r.jsx("div",{className:`absolute ${E} font-medium text-slate-100 ${w}`,children:r.jsxs("div",{className:"flex flex-col gap-0.5 leading-none",children:[r.jsxs("span",{children:["Status: ",o]}),u?r.jsxs("span",{children:["Audio: ",u]}):null,f?r.jsx("span",{className:"text-cyan-300",children:f}):null]})}),r.jsx("div",{className:`absolute ${D} flex -translate-y-1/2 flex-col gap-0.5 bg-black/70 text-slate-100 ${w} ${A}`,children:r.jsxs("div",{className:"space-y-0.5 leading-tight",children:[r.jsxs("div",{className:"flex flex-col gap-0.5 text-[0.75rem] font-semibold uppercase tracking-wide",children:[r.jsx("span",{className:`rounded px-1.5 py-0.5 ${T}`,children:U?"Docked":"Undocked"}),r.jsx("span",{className:`rounded px-1.5 py-0.5 ${V}`,children:L?"Charging":"Not charging"}),r.jsxs("span",{className:`rounded px-1.5 py-0.5 ${ce}`,children:["OI: ",Z]})]}),ue.map(([ne,ae])=>r.jsxs("span",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:ne}),r.jsx("span",{className:"font-semibold text-white",children:ae})]},ne))]})}),r.jsx("div",{className:`absolute ${H} left-1/2`,style:X,children:r.jsxs("div",{className:`flex items-center gap-0.5 bg-black/80 text-slate-100 ${N} ${R}`,children:[r.jsx("span",{className:"font-semibold text-white rounded px-1 py-[1px] border border-transparent",style:oa(l,.18),children:s||"Unnamed Rover"}),x?r.jsxs("span",{className:"text-slate-300",children:["• ",x]}):null]})})]}),g?r.jsx("div",{className:"pointer-events-none absolute rounded",style:{...oe},children:r.jsx(Hd,{sensors:n,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 ${E} font-medium text-slate-100 ${w}`,children:r.jsxs("div",{className:"flex flex-col gap-0.5 leading-none",children:[r.jsxs("span",{children:["Status: ",o]}),u?r.jsxs("span",{children:["Audio: ",u]}):null,f?r.jsx("span",{className:"text-cyan-300",children:f}):null]})}),S?r.jsx("div",{className:`absolute left-1/2 top-0.5 -translate-x-1/2 rounded bg-black/70 text-slate-100 ${K} ${O}`,children:S}):null,r.jsx("div",{className:`absolute ${H} left-1/2`,style:X,children:r.jsx("div",{className:`flex gap-0.5 bg-black/80 text-slate-100 ${N} ${R}`,children:r.jsxs("span",{children:["Rover:"," ",r.jsxs("span",{className:"rounded px-1 py-[1px] border border-transparent",style:oa(l,.18),children:['"',s||"Unnamed Rover",'"']})]})})}),g&&h!=="spectator"?r.jsx("div",{className:"pointer-events-none absolute rounded",style:{...oe},children:r.jsx(Hd,{sensors:n,size:240,overlay:!0})}):null]})}const rx=2e3,WN=3e3,eA=3e3,tA=40,nA=1e3,aA={leftWheel:"Left wheel",rightWheel:"Right wheel",mainBrush:"Main brush",sideBrush:"Side brush",limiter:"Overcurrent limit"};function sA({motors:n,fill:s=0,compact:l=!1}){if(!n?.length)return null;const o=n.map(v=>aA[v]||v),u=l?"w-[12rem] h-[3.5rem]":"w-[20rem] h-[7rem]",f=l?"px-2 py-1":"px-4 py-2",p=l?"text-lg":"text-4xl",h=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 ${u}`,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 ${p} ${f}`,children:[r.jsx("div",{children:"OVERCURRENT"}),r.jsx("div",{className:`mt-0 font-medium text-white ${h}`,children:o.join(", ")})]})]})})}function lA({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",u=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 ${u}`,children:r.jsx("div",{children:l})})})}function iA({sensors:n}){const s=[n?.lightBumpLeftSignal,n?.lightBumpFrontLeftSignal,n?.lightBumpCenterLeftSignal,n?.lightBumpCenterRightSignal,n?.lightBumpFrontRightSignal,n?.lightBumpRightSignal],l=s.filter(h=>h!=null).reduce((h,x)=>Math.max(h,x),1200),o=h=>Math.pow(Math.max(0,Math.min(1,(h??0)/l)),.35),u=h=>h==null||h<=0?"hsl(200 60% 18%)":`hsl(${(200+o(h)*360)%360} 100% 60%)`,f=6,p=12;return r.jsx("div",{className:"flex w-full items-center justify-center gap-0.5",children:s.map((h,x)=>{const g=o(h),v=xD.session),{sendMessage:l,onInputFocus:o,onInputBlur:u,blurChat:f,registerInputRef:p,setTypingActive:h}=of(),{value:x}=Ge("tts",{engine:"flite",voice:"rms",pitch:50}),[g,v]=m.useState(""),[y,S]=m.useState(!1),k=s?.role!=="spectator",C=s?.role==="spectator",M=s?.assignment?.roverId||null,A=!!m.useMemo(()=>s?.roster?.find(D=>String(D.id)===String(M))||null,[M,s?.roster])?.audio?.ttsEnabled,N=m.useMemo(()=>{if(!A)return null;const D=x?.engine==="espeak"?"espeak":"flite";if(D==="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:D,pitch:X}}const H=typeof x?.voice=="string"?x.voice:void 0;return{speak:!0,engine:D,voice:H}},[x?.engine,x?.pitch,x?.voice,A]),R=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",E=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(D){if(D.preventDefault(),!k)return;const H=g.trim();if(H){S(!0);try{await l(H,N),v(""),f(),h(!1)}catch(X){alert(X.message)}finally{S(!1)}}}return C?null:r.jsxs("form",{onSubmit:K,className:R,children:[r.jsx("input",{className:E,value:g,onChange:D=>{const H=D.target.value;v(H),h(!!H.trim())},onFocus:D=>{o(D),h(!!g.trim())},onBlur:D=>{u(D),h(!1)},onKeyDown:D=>{D.key==="Enter"&&!g.trim()&&(D.preventDefault(),f(),h(!1))},ref:D=>p(D,{target:"hud"}),placeholder:k?"Chat (TTS)":"Spectator",disabled:!k}),r.jsx("button",{type:"submit",disabled:!k||y,className:O,children:"Speak"})]})}function Si({sessionInfo:n,audioSessionInfo:s,videoMode:l="whep",snapshotFeed:o=null,qualityNotice:u=null,label:f,roverColor:p=null,forceMute:h=!1,telemetryFrame:x,batteryConfig:g,layoutFormat:v="desktop",hudVariant:y="default",driverLabel:S=null,hudForceMap:k=!1,hudMapPosition:C="top-center",hudLabelScale:M=1,fitParent:w=!1,overcurrentLimiter:A=null,showTurnCue:N=!1,turnTimerText:R=null,isActiveDriver:E=!1,idleSkipSeconds:O=null}){const K=it(ye=>ye.session),D=m.useRef(null),H=m.useRef(null),X=m.useRef(null),$=m.useRef(null),G=m.useRef(null),ee=m.useRef(null),oe=m.useRef(null),ue=m.useRef(null),[U,q]=m.useState("idle"),[L,Z]=m.useState(null),[se,ce]=m.useState("idle"),[T,V]=m.useState(null),[ne,ae]=m.useState(0),[me,re]=m.useState(0),[de,be]=m.useState(!0),ve=!!s?.url,xe=l==="snapshot",Le=x?.sensors,{value:De}=Ge("audio",st),Ee=Number.isFinite(De?.masterVolume)?De.masterVolume:st.masterVolume,nt=Number.isFinite(De?.roverVolume)?De.roverVolume:st.roverVolume,Ve=typeof De?.mainBrushDuckEnabled=="boolean"?De.mainBrushDuckEnabled:typeof De?.autoLevelEnabled=="boolean"?De.autoLevelEnabled:st.mainBrushDuckEnabled,mt=Number.isFinite(De?.mainBrushDuckAmount)?Math.max(0,Math.min(1,De.mainBrushDuckAmount)):st.mainBrushDuckAmount,ie=Math.max(0,Math.min(1,Ee*nt)),he=Le?.batteryChargeMah??null,J=!(v==="desktop"),pe=J?"top-right":C,[Ne]=Lg(),ht=k||J?!0:Ne,Oe=zg({charge:he,config:g}),rt=Le?.wheelOvercurrents||null,ot=rt==null?[]:Object.entries(rt).filter(([,ye])=>!!ye).map(([ye])=>ye),gt=A?.caps||null,kt=A?.overcurrent?.groups||null,us=typeof window<"u"&&new URLSearchParams(window.location.search).has("debugAudio"),Lt=typeof window<"u"&&new URLSearchParams(window.location.search).has("debugHud"),ul=m.useMemo(()=>{if(!gt)return null;const ye=Number.isFinite(gt?.drive?.cap)?gt.drive.cap:1,Ie=Number.isFinite(gt?.aux?.cap)?gt.aux.cap:1;return Math.max(0,Math.min(1,1-Math.min(ye,Ie)))},[gt]),dl=!!A?.isActive,yn=ot.length?ot:dl?["limiter"]:[],wt=ul??(ot.length?1:0),an=!!yn.length,vt=!!((Number(Le?.mainBrushCurrentMa)||0)>tA||Le?.wheelOvercurrents?.mainBrush),Oo=Ve&&vt?1-mt:1,ds=Math.max(0,Math.min(1,ie*Oo)),Lo=Ve&&vt&&mt>0?`Volume decreased ${Math.round(mt*1e3)/10}%`:null,Oa=m.useRef({hasDedicatedAudio:!1,audioUrl:null,mainBrushDuckEnabled:!1,mainBrushDuckAmount:0,mainBrushActive:!1,baseRoverGain:0,effectiveRoverGain:0});m.useEffect(()=>{Oa.current={hasDedicatedAudio:ve,audioUrl:s?.url||null,mainBrushDuckEnabled:Ve,mainBrushDuckAmount:mt,mainBrushActive:vt,baseRoverGain:ie,effectiveRoverGain:ds}},[ve,s?.url,Ve,mt,vt,ie,ds]);const We=m.useCallback((ye,Ie={})=>{if(!us)return;const Je=H.current,ke=Oa.current,Ye={event:ye,ts:Date.now(),roverLabel:f||null,hasDedicatedAudio:ke.hasDedicatedAudio,audioUrl:ke.audioUrl,mainBrushDuckEnabled:ke.mainBrushDuckEnabled,mainBrushDuckAmount:ke.mainBrushDuckAmount,mainBrushActive:ke.mainBrushActive,baseRoverGain:ke.baseRoverGain,effectiveRoverGain:ke.effectiveRoverGain,element:Je?{muted:Je.muted,volume:Je.volume,paused:Je.paused,ended:Je.ended,readyState:Je.readyState,networkState:Je.networkState}:null,...Ie};try{console.log(`[AudioDebug] ${ye} ${JSON.stringify(Ye)}`)}catch{console.log("[AudioDebug]",ye,Ye)}},[us,f]),fs=K?.socials?.find(ye=>String(ye?.id||ye?.label||"").toLowerCase()==="discord")?.url||K?.discord?.invite||null;m.useEffect(()=>{Lt&&console.log("[OvercurrentHUD]",{overlayVisible:an,overlayMotors:yn,overlayFill:wt,limiterActive:dl,limiterCaps:gt,limiterGroups:kt,wheelOvercurrents:rt})},[Lt,wt,yn,an,dl,gt,kt,rt]),m.useEffect(()=>{We("settings/update")},[We]);const Ft=m.useCallback(()=>{clearTimeout(X.current),X.current=setTimeout(()=>ae(Date.now()),rx)},[]),ua=m.useCallback(()=>{clearTimeout($.current),$.current=setTimeout(()=>re(Date.now()),rx)},[]),Mn=m.useCallback(async()=>{const ye=D.current;if(ye)try{ye.muted=!0,await ye.play()}catch{}},[]),Ri=m.useCallback((ye=0)=>{if(h||ve)return;clearTimeout(ee.current);const Ie=()=>{clearTimeout(ee.current),ee.current=setTimeout(()=>{h||Je()},WN)},Je=async()=>{const ke=D.current;if(ke)try{await Mn(),ke.muted=!1,await ke.play(),be(!1)}catch{ke.muted=!0,be(!0),Ie()}};ee.current=setTimeout(Je,ye)},[Mn,h,ve]);m.useEffect(()=>()=>{clearTimeout(X.current),clearTimeout($.current),clearTimeout(ee.current),clearInterval(G.current),oe.current&&(cancelAnimationFrame(oe.current),oe.current=null)},[]),m.useEffect(()=>{U==="playing"&&Ri(0)},[U,Ri]),m.useEffect(()=>{xe&&(q("snapshot"),Z(null))},[xe]),m.useEffect(()=>{if(xe||!n?.url||!D.current)return;let ye=!0,Ie;const Je=setTimeout(()=>be(!0),0),ke=(Ye,Mt)=>{ye&&(We("video/status",{nextStatus:Ye,info:Mt||null}),q(Ye),Z(Mt||null),Ye==="playing"&&Mn(),["error","failed","disconnected","closed"].includes(Ye)&&Ft())};return Ie=new lx({url:n.url,token:n.token,video:D.current,receiveAudio:!ve,onStatus:ke}),Ie.start().catch(Ye=>{ye&&(q("error"),Z(Ye.message),Ft())}),()=>{ye=!1,clearTimeout(Je),Ie?.stop()}},[xe,n?.url,n?.token,ne,Ft,Mn,ve,We]),m.useEffect(()=>{U==="stopped"&&n?.url&&Ft()},[U,n?.url,Ft]),m.useEffect(()=>{const ye=H.current;if(!ye||!s?.url){We("route/no-audio-url"),ue.current=null;return}const Ie=Math.max(0,Math.min(1,ds)),Je=ue.current==null?Math.max(0,Math.min(1,ye.volume)):ue.current;if(oe.current&&(cancelAnimationFrame(oe.current),oe.current=null),Ie>Je){const ke=performance.now(),Ye=Je,Mt=Ie-Ye,zt=ct=>{const ze=Math.min(1,(ct-ke)/nA),ln=Ye+Mt*ze;ye.volume=ln,ue.current=ln,ze<1?oe.current=requestAnimationFrame(zt):oe.current=null};oe.current=requestAnimationFrame(zt)}else ye.volume=Ie,ue.current=Ie;We("route/direct",{elementVolume:Ie,duckEnabled:Ve,mainBrushActive:vt,duckAmount:mt})},[s?.url,ds,Ve,vt,mt,We]),m.useEffect(()=>{if(!s?.url||!H.current)return;let ye=!0,Ie;const Je=(ke,Ye)=>{ye&&(We("audio/status",{nextStatus:ke,info:Ye||null}),V(Ye||(ke==="connected"?"connected":null)),ce(Mt=>ke==="connected"&&(Mt==="playing"||Mt==="connecting")||ke==="new"?Mt:ke),["error","failed"].includes(ke)&&ua())};return Ie=new lx({url:s.url,token:s.token,video:H.current,audioOnly:!0,onStatus:Je}),Ie.start().catch(ke=>{ye&&(ce("error"),V(ke.message),ua())}),()=>{ye=!1,Ie?.stop()}},[s?.url,s?.token,me,ua,We]),m.useEffect(()=>{const ye=H.current;if(!s?.url||!ye){clearInterval(G.current);return}if(!["connecting","connected","playing","paused"].includes(se)){clearInterval(G.current);return}const Je=async()=>{const ke=H.current;ke&&(ke.muted=!1,!(!ke.paused&&!ke.ended)&&(We("retry/play-attempt"),ke.play().then(()=>{We("retry/play-ok"),ce(Ye=>Ye==="connected"?"playing":Ye),V(Ye=>Ye==="paused"?null:Ye)}).catch(Ye=>{We("retry/play-fail",{error:Ye?.message}),V(Mt=>Mt||Ye?.message||"autoplay blocked")})))};return Je(),G.current=setInterval(Je,eA),()=>clearInterval(G.current)},[s?.url,se,We]),m.useEffect(()=>{const ye=H.current;if(!ye)return;const Ie=()=>{We("element/play"),ce(ze=>ze==="error"?ze:"playing"),V(null)},Je=()=>{We("element/pause"),ce(ze=>["error","failed","disconnected","closed","stopped"].includes(ze)?ze:"paused"),V(ze=>ze||"paused")},ke=()=>{We("element/ended"),ce(ze=>ze==="error"?ze:"stopped"),V(ze=>ze||"ended")},Ye=()=>{const{error:ze}=ye,ln=ze?.message||"audio error";We("element/error",{error:ln}),ce("error"),V(ln)},Mt=()=>We("element/waiting"),zt=()=>We("element/canplay"),ct=()=>We("element/stalled");return ye.addEventListener("play",Ie),ye.addEventListener("pause",Je),ye.addEventListener("ended",ke),ye.addEventListener("error",Ye),ye.addEventListener("waiting",Mt),ye.addEventListener("canplay",zt),ye.addEventListener("stalled",ct),()=>{ye.removeEventListener("play",Ie),ye.removeEventListener("pause",Je),ye.removeEventListener("ended",ke),ye.removeEventListener("error",Ye),ye.removeEventListener("waiting",Mt),ye.removeEventListener("canplay",zt),ye.removeEventListener("stalled",ct)}},[s?.url,We]);const qi=o?.error?`Error: ${o.error}`:o?.objectUrl?"snapshot":o?.status||"waiting",fl=xe?qi:n?.url?U==="error"?`Error: ${L||"unknown"}`:L?`${U} (${L})`:U:"waiting",La=s?.error?`Error: ${s.error}`:s?.url?se==="error"?`Error: ${T||"unknown"}`:T?`${se} (${T})`:se:null,Ti=y==="spectator",sn=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:[xe?o?.objectUrl?r.jsx("img",{src:o.objectUrl,alt:f,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:D,muted:h||de||ve,playsInline:!0,autoPlay:!0,controls:!1,className:"h-full w-full object-contain"}),r.jsx("audio",{ref:H,autoPlay:!0,hidden:!0}),!sn&&N?r.jsx(YN,{mobileHud:J,isActiveDriver:E,idleSkipSeconds:O}):null,sn?null:r.jsx(PN,{sensors:Le,label:f,roverColor:p,status:fl,audioStatus:La,levelStatus:Lo,layoutFormat:v,variant:y,driverLabel:S,showTopDown:ht,mobileHud:J,mapPosition:pe,turnTimerText:R,labelScale:M}),sn?null:r.jsx(rA,{compact:J}),!sn&&Lt?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:${an?1:0} motors:${yn.length} fill:${Math.round(wt*100)}%`}):null,sn?null:r.jsx(sA,{motors:yn,fill:wt,compact:J}),sn?null:r.jsx(lA,{battery:Oe,compact:J}),!sn&&Ti&&Oe.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(Ud,{visual:Oe,orientation:"vertical",variant:"inline",compact:J,className:"h-full w-4"})}):null,!sn&&u?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 ${J?"px-2 py-1 text-[0.6rem]":"px-3 py-1.5 text-sm"}`,children:[r.jsx("div",{className:"text-center",children:u}),r.jsx("div",{className:"pointer-events-auto mt-0",children:r.jsx(hf,{id:"discord",label:"Join our Discord server while you wait!",url:fs})})]})}):null]}),!sn&&!Ti&&r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(iA,{sensors:Le}),r.jsx("div",{className:"panel-section space-y-0.5 text-sm",children:r.jsx(Ud,{visual:Oe,compact:J})})]})]})}function xf({layoutFormat:n="desktop"}){const s=it(ae=>ae.session),{state:{song:l,lastControlIntentAt:o},overcurrentLimiter:u}=_t(),[f,p]=m.useState(()=>Date.now()),[h,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(()=>p(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,M=S?s?.turnQueues?.[S]:null,w=s?.socketId||null,A=S?s?.activeDrivers?.[S]:null,N=!!(w&&A===w),R=m.useMemo(()=>{const ae=M?.queue||[];if(!ae.length||!M?.current||ae.length<=1)return null;const me=ae.findIndex(re=>re===M.current);return me===-1?ae[0]||null:ae[(me+1)%ae.length]||null},[M?.queue,M?.current]),E=!!(w&&R===w),O=M?.deadline||null,K=M?.idleDeadline||null,D=O?O-f:null,H=K?K-f:null,X=s?.mode==="turns"&&E&&D!=null&&D<=5e3&&D>0,$=s?.mode!=="turns"||N||X,G=D!=null&&Number.isFinite(D)?Math.max(0,Math.ceil(D/1e3)):null,ee=H!=null&&Number.isFinite(H)?Math.max(0,Math.ceil(H/1e3)):null,oe=N?G!=null?`${G}s left`:null:E&&G!=null?`Your turn in ${G}s`:null,ue=S?[...$?[{type:"rover",id:S,key:S}]:[],...C?[{type:"rover",id:`${S}-audio`,key:`${S}-audio`}]:[]]:[],U=bi(ue),q=S&&$?U[S]:null,L=S&&C?U[`${S}-audio`]:null,Z=mf(S?[S]:[],{enabled:!!S,version:s?.mode}),se=S&&Z[S]||null,ce=cl(S),T=S&&s?.roster?s.roster.find(ae=>String(ae.id)===String(S)):null,V=T?.battery??null,ne=T?.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,me=N&&!ae.active,re=N&&S&&S!==ae.roverId;me||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(()=>{!h||!g||o>g&&x(!1)},[o,g,h]),r.jsx("section",{className:"panel",children:S?r.jsx(Si,{sessionInfo:q,videoMode:$?"whep":"snapshot",snapshotFeed:se,audioSessionInfo:L,label:ne,roverColor:T?.color||null,telemetryFrame:ce,batteryConfig:V,layoutFormat:n,overcurrentLimiter:u,songNote:l?.note,qualityNotice:$?null:"Preview feed (low FPS) until your turn.",showTurnCue:h,turnTimerText:oe,turnSeconds:G,isActiveDriver:N,idleSkipSeconds:ee}):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 So({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 Ro(n){if(!Number.isFinite(n))return 0;const s=n%360;return s<0?s+360:s}function oA(n){if(!Array.isArray(n)||n.length<3)return 0;const[s,l,o]=n,u=Math.max(0,Math.min(255,Number(s)))/255,f=Math.max(0,Math.min(255,Number(l)))/255,p=Math.max(0,Math.min(255,Number(o)))/255,h=Math.max(u,f,p),x=Math.min(u,f,p),g=h-x;if(g===0)return 0;let v=0;return h===u?v=(f-p)/g%6:h===f?v=(p-u)/g+2:v=(u-f)/g+4,Ro(Math.round(v*60))}function ox(n){const s=Ro(n),l=1,o=1-Math.abs(s/60%2-1);let u=0,f=0,p=0;return s<60?(u=l,f=o):s<120?(u=o,f=l):s<180?(f=l,p=o):s<240?(f=o,p=l):s<300?(u=o,p=l):(u=l,p=o),[Math.round(u*255),Math.round(f*255),Math.round(p*255)]}function cx(n){return n?Array.isArray(n.hsColor)?Ro(Number(n.hsColor[0])):Array.isArray(n.rgbColor)?oA(n.rgbColor):0:0}function cA({entity:n,connected:s,controlsLocked:l,onToggle:o,onSetColor:u,onSetWhite:f}){const p=n.state==="unavailable"||!n.available,h=n.state==="on",x=n.type==="light"&&n.supportsColor,g=p?"warn":h?"success":"muted",v=p?"Unavailable":h?"On":"Off",y=l||!s||p,S=y||!x,[k,C]=m.useState(()=>cx(n)),M=m.useRef(k),w=m.useRef(!1),A=p?"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":h?"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 H=cx(n);M.current=H,C(H)},[n.rgbColor,n.hsColor,x]);const N=H=>{const X=Ro(Number(H.target.value));M.current=X,C(X)},R=()=>{S||!u||u(n.id,ox(M.current))},E=H=>{H.stopPropagation()},O=H=>{E(H),!(S||!f)&&f(n.id)},D=`rgb(${(x?ox(M.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 ${A} 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(So,{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:E,onPointerDown:H=>{E(H),w.current=!0},onPointerUp:H=>{E(H),w.current=!1,R()},onPointerCancel:H=>{E(H),w.current=!1,R()},onKeyUp:H=>{E(H),R()},onBlur:R,children:r.jsx("div",{className:"relative w-full",children:r.jsx("input",{type:"range",min:"0",max:"360",step:"1",value:k,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(So,{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:E,onKeyDown:H=>{S||(H.key==="Enter"||H.key===" ")&&(H.preventDefault(),O(H))},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:D}})]}),!x&&r.jsx("div",{className:"self-center text-xs font-semibold text-white/90",children:h?"Turn off":"Turn on"})]})}function Hg(){const{state:{keymap:n}}=_t(),s=it(k=>k.session),{homeAssistantToggle:l,homeAssistantSetLightColor:o,homeAssistantSetLightWhite:u}=kn(),f=s?.homeAssistant,p=m.useMemo(()=>f?.entities||[],[f?.entities]),h=f?.lightPolicy||null,x=!!(h?.locked||h?.lockedOn),g=h?.lockState||(h?.lockedOn?"on":null),v=Cn(n?.homeAssistantOn?.[0]),y=Cn(n?.homeAssistantOff?.[0]);if(!f?.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(p.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=!!f?.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:p.length}),x?r.jsx(So,{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(So,{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:p.map(k=>r.jsx(cA,{entity:k,connected:S,controlsLocked:x,onToggle:l,onSetColor:o,onSetWhite:u},k.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}=kn(),[l,o]=m.useState(""),[u,f]=m.useState(""),[p,h]=m.useState(!1);async function x(g){g.preventDefault(),h(!0);try{await n(l,u),o(""),f("")}catch(v){alert(v.message)}finally{h(!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:u,onChange:g=>f(g.target.value)}),r.jsx("button",{type:"submit",disabled:p,className:"button-dark w-full disabled:opacity-50",children:p?"Logging in…":"Login"})]})]})}function dx(...n){return n.filter(Boolean).join(" ")}function uA(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function dA(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function fA({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(u=>{const f=!!(u?.private?.enabled&&u?.private?.open),p=!!u?.locked;return r.jsxs("li",{className:dx("surface flex flex-wrap items-center justify-between gap-0.5",p?"bg-red-900/40":f?"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:oa(u.color,.16),children:u.name})}),r.jsxs("p",{className:"text-xs text-slate-500 flex flex-wrap items-center gap-0.5",children:[r.jsx("span",{children:u.locked?"locked":"free"}),u.lockReason&&r.jsx("span",{className:"rounded bg-black/30 px-1",children:u.lockReason}),r.jsxs("span",{className:dx("font-semibold",dA(u)),children:["Battery ",uA(u)]})]})]}),o?o(u):null]},u.id)})})]})}function mA(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 hA(n,s){const l=Date.now(),u=(Array.isArray(n)?n:[]).map((f,p)=>{const h=String(f?.role||"").toLowerCase(),x=typeof f?.content=="string"?f.content:JSON.stringify(f?.content??null,null,2),g=h==="system"?"LLM System":h==="assistant"?"LLM Context":h==="user"?"LLM Input":"LLM Message";return{id:`llm-msg-${p}`,message:{ts:l+p,nickname:g,text:x,role:"spectator",system:h==="system"}}});if(s!=null){const f=String(s);u.push({id:"llm-output",message:{ts:l+u.length+1,nickname:"LLM Output",text:f.trim()?f:"",role:"spectator",system:!0}})}return u}function pA({state:n,onClearHistory:s,clearingHistory:l}){const[o,u]=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 f=n.runtime||{},p=n.counters||{},h=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),k=mA(n),C=hA(x.modelMessages,g.raw),M=[{label:"running",value:f.running?"yes":"no"},{label:"in flight",value:f.inFlight?"yes":"no"},{label:"phase",value:f.phase||"--"},{label:"run id",value:f.currentRunId??"--"},{label:"tick count",value:f.tickCount??0},{label:"last tick",value:f.lastTickAt?new Date(f.lastTickAt).toLocaleString():"never"},{label:"next run",value:f.nextRunAt?new Date(f.nextRunAt).toLocaleString():"n/a"},{label:"outcome",value:f.outcome||"--"},{label:"reason",value:f.reason||"--"},{label:"skip streak",value:p.skipStreak??0},{label:"clear count",value:p.clearCount??0},{label:"last gen",value:h.lastGenerationMs!=null?`${h.lastGenerationMs} ms`:"--"},{label:"avg gen",value:h.avgGenerationMs!=null?`${h.avgGenerationMs} ms`:"--"},{label:"gen count",value:h.generationCount??0},{label:"prompt chars",value:p.promptChars??0},{label:"active drivers",value:p.snapshotSummary?.activeDrivers??0},{label:"snapshot rovers",value:p.snapshotSummary?.rovers??0},{label:"snapshot chat",value:p.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 ${k.className}`,children:[r.jsx("div",{className:"text-[1.1rem] font-bold tracking-wide",children:k.label}),r.jsx("div",{className:"text-xs text-slate-200",children:k.detail})]}),r.jsx("div",{className:"surface flex flex-wrap gap-0.5 text-xs",children:M.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(sf,{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:()=>u(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 xA({health:n,roster:s=[]}){if(!n)return null;const l=n.replay||{sources:[],readyCount:0,totalCount:0},o=n.snapshots||{rovers:[],rooms:[]},u=x=>s.find(g=>String(g.id)===String(x))?.color||null,f=`${l.readyCount}/${l.totalCount} sources ready`,p=o.rovers.filter(x=>x.stale).length,h=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:f})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:"Rover snapshots"}),r.jsxs("span",{className:p?"text-amber-300":"text-emerald-300",children:[o.rovers.length-p,"/",o.rovers.length," ok"]})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:"Room cameras"}),r.jsxs("span",{className:h?"text-amber-300":"text-emerald-300",children:[o.rooms.length-h,"/",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"?oa(u(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:oa(u(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 gA({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 vA=[{key:"open",label:"Open"},{key:"turns",label:"Turns"},{key:"admin",label:"Admin"},{key:"lockdown",label:"Lockdown"}];function bA(){const{session:n,lockRover:s,setMode:l,requestControl:o,setGlobalObjective:u,setAdminReason:f,rebootRover:p,rebootServer:h,setAudioLevels:x,setPrivateSafety:g,llmControl:v,adminLogs:y,llmCommentaryState:S}=nn(),k=m.useMemo(()=>n?.roster??[],[n?.roster]),[C,M]=m.useState({}),[w,A]=m.useState({}),[N,R]=m.useState(!1),[E,O]=m.useState(!1),K=n?.health||null,D=n?.globalObjective?.text||"",H=n?.globalObjective?.updatedAt||null,[X,$]=m.useState(D),G=n?.adminReason?.text||"",ee=n?.adminReason?.updatedAt||null,[oe,ue]=m.useState(G),U=n?.audioLevels||{},[q,L]=m.useState({hornGain:Number.isFinite(U.hornGain)?U.hornGain:1,ttsGain:Number.isFinite(U.ttsGain)?U.ttsGain:1,forwardGain:Number.isFinite(U.forwardGain)?U.forwardGain:1}),[Z,se]=m.useState({}),ce=n?.role==="admin"||n?.role==="lockdown"||n?.role==="lockdown-admin",T=n?.role==="lockdown"||n?.role==="lockdown-admin",V=n?.mode??"open",ne=async(le,J)=>{try{await s(le,J),M(pe=>({...pe,[le]:J}))}catch(pe){alert(pe.message)}},ae=async le=>{const J=le.target.value;try{await l(J)}catch(pe){alert(pe.message)}},me=async le=>{try{await o(le,{force:!0})}catch(J){alert(J.message)}},re=async le=>{if(!(!le?.id||!window.confirm(`Reboot rover "${le.name||le.id}" now?`))){A(pe=>({...pe,[le.id]:!0}));try{await p(le.id)}catch(pe){alert(pe.message)}finally{A(pe=>({...pe,[le.id]:!1}))}}},de=async()=>{if(window.confirm("Reboot the server host now? This will disconnect all users.")){R(!0);try{await h()}catch(J){alert(J.message),R(!1)}}},be=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(J){alert(J.message)}finally{O(!1)}}},ve=async()=>{try{await u(X)}catch(le){alert(le.message)}},xe=async()=>{try{await u(null)}catch(le){alert(le.message)}},Le=async()=>{try{await f(oe)}catch(le){alert(le.message)}},De=async()=>{try{await f(null)}catch(le){alert(le.message)}},Ee=le=>J=>{const pe=Number(J.target.value);L(Ne=>({...Ne||{},[le]:Number.isFinite(pe)?pe:1}))},nt=async()=>{try{await x(q)}catch(le){alert(le.message)}},Ve=async()=>{window.dispatchEvent(new CustomEvent("buttonBox:rewardRunLocalTest",{detail:{rewardName:"Admin Mode",count:1e3,goal:1e3}}))};m.useEffect(()=>{$(D)},[D]),m.useEffect(()=>{ue(G)},[G]),m.useEffect(()=>{L({hornGain:Number.isFinite(U.hornGain)?U.hornGain:1,ttsGain:Number.isFinite(U.ttsGain)?U.ttsGain:1,forwardGain:Number.isFinite(U.forwardGain)?U.forwardGain:1})},[U.forwardGain,U.hornGain,U.ttsGain]),m.useEffect(()=>{const le={};(k||[]).forEach(J=>{J?.private?.enabled&&(le[J.id]={speedLimitEnabled:!!J?.private?.safety?.speedLimitEnabled,speedLimitMaxWheelSpeed:Number.isFinite(J?.private?.safety?.speedLimitMaxWheelSpeed)?J.private.safety.speedLimitMaxWheelSpeed:250,hardOvercurrentEnabled:!!J?.private?.safety?.hardOvercurrentEnabled,overcurrentStopMs:Number.isFinite(J?.private?.safety?.overcurrentStopMs)?J.private.safety.overcurrentStopMs:300,hardBumpEnabled:!!J?.private?.safety?.hardBumpEnabled,bumpBackoffSpeed:Number.isFinite(J?.private?.safety?.bumpBackoffSpeed)?J.private.safety.bumpBackoffSpeed:250,bumpBackoffMs:Number.isFinite(J?.private?.safety?.bumpBackoffMs)?J.private.safety.bumpBackoffMs:350,cliffEnabled:!!J?.private?.safety?.cliffEnabled,cliffBackoffSpeed:Number.isFinite(J?.private?.safety?.cliffBackoffSpeed)?J.private.safety.cliffBackoffSpeed:250,cliffBackoffMs:Number.isFinite(J?.private?.safety?.cliffBackoffMs)?J.private.safety.cliffBackoffMs:500,triggerCooldownMs:Number.isFinite(J?.private?.safety?.triggerCooldownMs)?J.private.safety.triggerCooldownMs:800})}),se(le)},[k]);const mt=m.useMemo(()=>{const le={};return k.forEach(J=>{le[J.id]=C[J.id]??J.locked}),le},[k,C]),ie=(le,J={})=>{se(pe=>({...pe||{},[le]:{...pe?.[le]||{},...J||{}}}))},he=async le=>{try{const J=Z?.[le];if(!J)return;await g(le,J)}catch(J){alert(J.message)}};return ce?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:V,onChange:ae,className:"field-input text-sm",children:vA.map(le=>r.jsx("option",{value:le.key,children:le.label},le.key))})]}),r.jsxs("div",{className:"flex gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:de,disabled:N,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:N?"Server rebooting...":"Reboot Server"}),r.jsx("button",{type:"button",onClick:Ve,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:Ee("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:Ee("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:Ee("forwardGain"),className:"w-full accent-emerald-500"})]}),r.jsx("div",{className:"flex gap-0.5 text-xs",children:r.jsx("button",{type:"button",onClick:nt,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:"Global objective"}),H?r.jsxs("span",{children:["Updated ",new Date(H).toLocaleString()]}):null]}),r.jsx("input",{type:"text",value:X,onChange:le=>$(le.target.value),placeholder:"Set a global objective",className:"field-input text-sm"}),r.jsxs("div",{className:"flex gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:ve,className:"button-dark",children:"Set objective"}),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"}),ee?r.jsxs("span",{children:["Updated ",new Date(ee).toLocaleString()]}):null]}),r.jsx("textarea",{value:oe,onChange:le=>ue(le.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:Le,className:"button-dark",children:"Set reason"}),r.jsx("button",{type:"button",onClick:De,className:"button-danger",children:"Clear"})]})]}),r.jsx(fA,{roster:k,renderActions:le=>r.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:()=>ne(le.id,!mt[le.id]),className:"button-dark",children:mt[le.id]?"Unlock":"Lock"}),r.jsx("button",{type:"button",onClick:()=>me(le.id),className:"button-dark",children:"Force"}),r.jsx("button",{type:"button",onClick:()=>re(le),disabled:!!w[le.id],className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:w[le.id]?"Rebooting...":"Reboot"}),le?.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?.[le.id]?.speedLimitEnabled,disabled:!T,onChange:J=>ie(le.id,{speedLimitEnabled:!!J.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:!T,value:Z?.[le.id]?.speedLimitMaxWheelSpeed??250,onChange:J=>ie(le.id,{speedLimitMaxWheelSpeed:Number(J.target.value)||250})}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!Z?.[le.id]?.hardOvercurrentEnabled,disabled:!T,onChange:J=>ie(le.id,{hardOvercurrentEnabled:!!J.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?.[le.id]?.hardBumpEnabled,disabled:!T,onChange:J=>ie(le.id,{hardBumpEnabled:!!J.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?.[le.id]?.cliffEnabled,disabled:!T,onChange:J=>ie(le.id,{cliffEnabled:!!J.target.checked})}),r.jsx("span",{children:"Cliff safety"})]}),r.jsx("button",{type:"button",disabled:!T,onClick:()=>he(le.id),className:"button-dark disabled:opacity-50",children:"Apply Safety"})]}):null]})}),r.jsx(xA,{health:K,roster:k}),r.jsx(pA,{state:S,onClearHistory:be,clearingHistory:E}),r.jsx(gA,{entries:y})]}):null}const yA=[{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 SA(n){return n.reduce((s,l)=>((s[l.group]||(s[l.group]=[])).push(l),s),{})}function jA(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(0,Math.min(500,l)):s}const gf=5,ji=500,Ni=1,vf=100;function NA(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(gf,Math.min(ji,l)):s}function fo(n,s){const l=Number(n);return Number.isFinite(l)?Math.max(Ni,Math.min(vf,l)):s}function AA(n){const l=(fo(n,n)-Ni)/(vf-Ni),o=ji-l*(ji-gf);return Math.round(o)}function wA(n){const s=NA(n,n),l=(ji-s)/(ji-gf),o=Ni+l*(vf-Ni);return Math.round(o)}function CA(n){const[s,l]=m.useState(null),o=m.useCallback(p=>{id(!0),l(p)},[]),u=m.useCallback(()=>{id(!1),l(null)},[]),f=m.useCallback((p,h)=>{if(h.preventDefault(),h.stopPropagation(),h.key==="Escape"){u();return}const x=Mi(h.key??"");x&&(n(p,x,h),u())},[u,n]);return m.useEffect(()=>()=>id(!1),[]),{active:s,startCapture:o,cancel:u,captureFromEvent:f}}function Wr({label:n,description:s,value:l,onChange:o,min:u=0,max:f=500,step:p=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:u,max:f,value:l,onChange:h=>o(h.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:u,max:f,step:p,value:l,onChange:h=>o(h.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 EA(){const{state:{keymap:n},actions:{updateKeyBinding:s,resetKeyBindings:l}}=_t(),{value:o,save:u}=Ge("inputs",_n),f={..._n.keyboard,...o.keyboard??{}},p=m.useMemo(()=>typeof f.tiltSpeed=="number"?fo(f.tiltSpeed,_n.keyboard.tiltSpeed):typeof f.tiltIntervalMs=="number"?fo(wA(f.tiltIntervalMs),_n.keyboard.tiltSpeed):_n.keyboard.tiltSpeed,[f.tiltIntervalMs,f.tiltSpeed]),h=m.useMemo(()=>SA(yA),[]),{active:x,startCapture:g,cancel:v,captureFromEvent:y}=CA((M,w)=>{s(M,w)}),S=m.useCallback(M=>n?.[M]?.[0]||mi[M]?.[0]||"",[n]),k=m.useCallback((M,w)=>{const A=_n.keyboard,N=jA(w,A[M]);u(R=>({...R??{},keyboard:{...R?.keyboard??A,[M]:N}}))},[u]),C=m.useCallback(M=>{const w=_n.keyboard,A=fo(M,w.tiltSpeed),N=AA(A);u(R=>({...R??{},keyboard:{...R?.keyboard??w,tiltSpeed:A,tiltIntervalMs:N}}))},[u]);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(Wr,{label:"Base speed",description:"Normal driving speed",value:f.baseSpeed,onChange:M=>k("baseSpeed",M)}),r.jsx(Wr,{label:"Turbo speed",description:"Used when holding the boost modifier",value:f.turboSpeed,onChange:M=>k("turboSpeed",M)}),r.jsx(Wr,{label:"Precision speed",description:"Used when holding the precision modifier",value:f.precisionSpeed,onChange:M=>k("precisionSpeed",M)})]})]}),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(Wr,{label:"Tilt speed",description:"Higher = faster when holding tilt keys",value:p,onChange:C,min:1,max:100,step:1})]}),r.jsx("div",{className:"space-y-0.5",children:Object.entries(h).map(([M,w])=>r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.75rem] text-slate-400",children:M}),r.jsx("div",{className:"space-y-0.5",children:w.map(A=>{const N=S(A.id),R=x===A.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:A.label}),r.jsx("p",{className:"text-[0.65rem] text-slate-400",children:Cn(N)})]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[R&&r.jsx("button",{type:"button",onClick:()=>v(),className:"button-danger text-[0.7rem]",children:"Cancel"}),r.jsx("button",{type:"button",onClick:()=>g(A.id),onKeyDown:R?E=>y(A.id,E):void 0,autoFocus:R,className:`${R?"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:R?"Press a key…":"Change"})]})]},A.id)})})]},M))})]})}const sa=new Intl.NumberFormat(void 0,{maximumFractionDigits:2}),kA=[{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"}],fx=.45,MA=.6;function ci({label:n,description:s,min:l,max:o,step:u,value:f,onChange:p}){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:sa.format(f)})]}),s&&r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:s}),r.jsx("input",{type:"range",min:l,max:o,step:u,value:f,onChange:h=>p(Number(h.target.value)),className:"mt-0 w-full accent-emerald-400"})]})}function RA(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} ${sa.format(n.threshold??.6)}`}return"Unassigned"}function qA(n){return n.reduce((s,l)=>((s[l.section]||(s[l.section]=[])).push(l),s),{})}function TA(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 DA(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 _A(n,s,l){const o=(n.axes??[]).map((f,p)=>({index:p,delta:Math.abs((f??0)-(s.axes?.[p]??0)),value:f}));if(o.sort((f,p)=>p.delta-f.delta),l.kind==="axisPair"){const f=o.filter(p=>p.delta>fx).slice(0,2);return f.length<2?null:{kind:"axisPair",x:f[0].index,y:f[1].index,...l.invertDefaults??{}}}const u=o.find(f=>f.delta>fx);return u?{kind:"axis",index:u.index,...l.invertDefaults??{}}:null}function BA(n,s,l){const o=n.buttons??[];for(let f=0;fMA)return l.kind==="axis"?{kind:"buttonAxis",index:f}:{kind:"button",index:f}}const u=n.axes??[];for(let f=0;f.7&&h>.5)return l.kind==="axis"?{kind:"axis",index:f,...l.invertDefaults??{}}:{kind:"axisButton",index:f,direction:p>=0?1:-1,threshold:.6}}return null}function OA(n,s,l){if(!n)return null;if(l.kind==="axis"||l.kind==="axisPair"){const o=_A(n,s,l);if(o)return o}return BA(n,s,l)}function LA(){const n=fN(),{value:s,save:l}=Ge("gamepad",_a),[o,u]=m.useState(null),f=m.useRef(null),p=m.useMemo(()=>qA(kA),[]),h=m.useMemo(()=>TA(n.pads,s.activeSignature),[n.pads,s.activeSignature]),x=h?.signature??null,g=m.useMemo(()=>x?s?.profiles?.[x]??s?.defaults?.profile??la:s?.defaults?.profile??la,[x,s?.defaults?.profile,s?.profiles]);m.useEffect(()=>{!h||!x||s?.profiles?.[x]||l(w=>{const A=w??_a;if(A.profiles?.[x])return A;const N=A?.defaults?.profile??la,R=wg(h,N);return{...A,profiles:{...A.profiles??{},[x]:R}}})},[h,x,s?.profiles,l]),m.useEffect(()=>{f.current=null},[o,x]),m.useEffect(()=>{if(!o||!h)return;if(!f.current){f.current=DA(h);return}const w=OA(h,f.current,o);w&&(l(A=>{const N=A??_a,R=N.profiles?.[x]??N?.defaults?.profile??la,E={...R,bindings:{...R.bindings??{},[o.id]:{...R.bindings?.[o.id]??{},kind:o.kind,sources:[w]}}};return{...N,profiles:{...N.profiles??{},[x]:E}}}),u(null))},[h,x,o,l]);const v=m.useCallback(w=>{l(A=>({...A??_a,activeSignature:w||null}))},[l]),y=m.useCallback(w=>{l(A=>{const N=A??_a,R=(x&&N.profiles?.[x])??N?.defaults?.profile??la,E={...R,calibration:{...R.calibration??{},...w}};return x?{...N,profiles:{...N.profiles??{},[x]:E}}:{...N,defaults:{...N.defaults??{},profile:E}}})},[x,l]),S=m.useCallback((w,A)=>{l(N=>{const R=N??_a,E=(x&&R.profiles?.[x])??R?.defaults?.profile??la,O=A(E.bindings?.[w]??{}),K={...E,bindings:{...E.bindings??{},[w]:O}};return x?{...R,profiles:{...R.profiles??{},[x]:K}}:{...R,defaults:{...R.defaults??{},profile:K}}})},[x,l]),k=m.useCallback(w=>{S(w.id,A=>({...A,sources:[]}))},[S]),C=m.useCallback((w,A)=>{S(w.id,N=>{const R=Array.isArray(N.sources)?[...N.sources]:[];if(!R[0])return N;const E={...R[0]};return A==="invertX"?E.invertX=!E.invertX:A==="invertY"?E.invertY=!E.invertY:E.invert=!E.invert,R[0]=E,{...N,sources:R}})},[S]),M=m.useMemo(()=>h?{outputs:Cg(h,g)}:null,[h,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:h?"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:h?.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(ci,{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(ci,{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(ci,{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(ci,{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(ci,{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(p).map(([w,A])=>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:A.map(N=>{const E=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:RA(E)})]}),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:!E,onClick:()=>C(N,"invertX"),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert X"}),r.jsx("button",{type:"button",disabled:!E,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:!E,onClick:()=>C(N),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert"}),r.jsx("button",{type:"button",onClick:()=>k(N),className:"button-dark text-[0.7rem]",children:"Clear"}),r.jsx("button",{type:"button",onClick:()=>u(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"}),h?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:h.axes.map((w,A)=>r.jsxs("span",{className:"font-mono text-slate-300",children:["A",A,": ",sa.format(w)]},`axis-${A}`))}),r.jsx("p",{className:"text-slate-400",children:"Raw buttons"}),r.jsx("div",{className:"grid grid-cols-2 gap-0.5",children:h.buttons.map((w,A)=>r.jsxs("span",{className:"font-mono text-slate-300",children:["B",A,": ",sa.format(w.value)," ",w.pressed?"●":""]},`btn-${A}`))}),M?.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: ",sa.format(M.outputs.driveVector.x),","," ",sa.format(M.outputs.driveVector.y)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Camera: ",sa.format(M.outputs.cameraAxis)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Main: ",sa.format(M.outputs.auxAxis.main)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Side: ",sa.format(M.outputs.auxAxis.side)]})]})]})]}):r.jsx("p",{className:"text-[0.7rem] text-slate-400",children:"No controller detected."})]})]})}const zA={drive:"Drive wheels",aux:"Aux motors"};function mx(n){return Number.isFinite(n)?`${Math.round(n*100)}%`:"--"}function UA({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 HA(){const{state:{roverId:n},overcurrentLimiter:s}=_t(),l=m.useMemo(()=>ls.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 u=s?.caps?.[o]?.cap??0,f=s?.overcurrent?.groups?.[o]??!1,p=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:zA[o]||o}),r.jsx("span",{className:f?"text-red-300":"text-slate-400",children:f?"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(u)})]}),r.jsx(UA,{value:u,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(p)})]})]})]},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 bf(...n){return n.filter(Boolean).join(" ")}function yf({children:n,defaultTab:s,currentTab:l,onTabChange:o,variant:u=Yg}){const[f,p]=m.useState(s??null),[h,x]=m.useState([]),g=m.useCallback(k=>k?(x(C=>C.includes(k)?C:[...C,k]),()=>x(C=>C.includes(k)?C.filter(M=>M!==k):C)):()=>{},[]),v=l??f??h[0]??null;m.useEffect(()=>{s&&l===void 0&&p(s)},[s,l]);const y=m.useCallback(k=>{k&&(l===void 0&&p(k),o&&o(k))},[l,o]),S=m.useMemo(()=>({activeTab:v,setActiveTab:y,registerTab:g,variant:u}),[v,y,g,u]);return r.jsx($g.Provider,{value:S,children:n})}function Sf({children:n,className:s=""}){return r.jsx("div",{className:bf("flex gap-0.5",s),children:n})}function Wt({id:n,children:s,className:l="",disabled:o=!1,highlight:u="none"}){const{activeTab:f,setActiveTab:p,registerTab:h,variant:x}=Gg();m.useEffect(()=>h(n),[n,h]);const g=hx[x]??hx[Yg],v=f===n,y=px[u]||px.none,S=bf(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&&p(n),"aria-pressed":v,"aria-disabled":o,children:s})}function jf({children:n,className:s=""}){return r.jsx("div",{className:bf("mt-0 space-y-0.5",s),children:n})}function en({id:n,children:s,keepMounted:l=!1}){const{activeTab:o}=Gg(),u=o===n;return!u&&!l?null:!u&&l?r.jsx("div",{hidden:!0,"aria-hidden":"true",children:s}):r.jsx(r.Fragment,{children:s})}function VA(){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 $A(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 GA(n){const l=n.map(o=>$A(o)).join(" ");return l.length>gx?`${l.slice(0,gx)}…`:l}function YA(){const n=tn(),[s,l]=m.useState([]),o=m.useMemo(()=>s.reduce((u,f)=>(f.direction==="in"&&(u.in+=1),f.direction==="out"&&(u.out+=1),u),{in:0,out:0}),[s]);return m.useEffect(()=>{const u=(x,g,v)=>{l(y=>{const S=[...y,{id:`${Date.now()}-${Math.random().toString(16).slice(2)}`,direction:x,event:g,payload:GA(v),timestamp:new Date().toLocaleTimeString()}];return S.length>xx?S.slice(-xx):S})},f=(x,...g)=>u("in",x,g),p=(x,...g)=>u("out",x,g);n.onAny(f);let h=null;if(typeof n.onAnyOutgoing=="function")n.onAnyOutgoing(p),h=()=>n.offAnyOutgoing(p);else{const x=n.emit.bind(n);n.emit=(g,...v)=>(p(g,...v),x(g,...v)),h=()=>{n.emit=x}}return()=>{n.offAny(f),h&&h()}},[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(u=>r.jsxs("div",{className:"surface",children:[r.jsx("span",{className:"text-slate-400",children:u.timestamp})," ",r.jsxs("span",{className:u.direction==="in"?"text-emerald-400":"text-amber-400",children:["[",u.direction.toUpperCase(),"]"]})," ",r.jsx("span",{className:"text-cyan-300",children:u.event})," ",r.jsx("span",{className:"text-slate-200",children:u.payload})]},u.id))}),r.jsx("p",{className:"text-xs text-slate-500",children:"Logs are collected only while this panel is open."})]})}const FA=[{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,[u,f]=Lg(),p=tn(),{value:h,save:x}=Ge("page",{hudMapDesktop:!1,connectionTransport:"websocket",swapMobileControlColumns:!1,driveMacroBackoffEnabled:!0}),{value:g,save:v}=Ge("audio",st),y=h?.connectionTransport||"websocket",S=!!h?.swapMobileControlColumns,k=typeof h?.driveMacroBackoffEnabled=="boolean"?h.driveMacroBackoffEnabled:!0,C=Number.isFinite(g?.masterVolume)?g.masterVolume:st.masterVolume,M=Number.isFinite(g?.alertVolume)?g.alertVolume:st.alertVolume,w=Number.isFinite(g?.roverVolume)?g.roverVolume:st.roverVolume,A=typeof g?.mainBrushDuckEnabled=="boolean"?g.mainBrushDuckEnabled:typeof g?.autoLevelEnabled=="boolean"?g.autoLevelEnabled:st.mainBrushDuckEnabled,N=Number.isFinite(g?.mainBrushDuckAmount)?Math.max(0,Math.min(1,g.mainBrushDuckAmount)):st.mainBrushDuckAmount,R=m.useMemo(()=>[{key:"start",label:"Enable stream",enable:!0},{key:"stop",label:"Disable stream",enable:!1}],[]),E=$=>{n&&l($)},O=$=>{const G=$.target.value;x(ee=>({...ee??{},connectionTransport:G})),p?.io?.opts&&(p.io.opts.transports=G==="polling"?["polling"]:["websocket","polling"],p.disconnect(),p.connect())},K=$=>G=>{const ee=Number(G.target.value),oe=Number.isFinite(ee)?Math.max(0,Math.min(1,ee)):0;v(ue=>({...ue??{},[$]:oe}))},D=$=>{const G=!!$.target.checked;v(ee=>({...ee??{},mainBrushDuckEnabled:G}))},H=$=>{const G=!!$.target.checked;x(ee=>({...ee??{},swapMobileControlColumns:G}))},X=$=>{const G=!!$.target.checked;x(ee=>({...ee??{},driveMacroBackoffEnabled:G}))};return r.jsxs(yf,{defaultTab:"keybindings",children:[r.jsxs(Sf,{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(jf,{children:[r.jsx(en,{id:"keybindings",children:r.jsx("div",{className:"space-y-0.5",children:r.jsx(EA,{})})}),r.jsx(en,{id:"controller",children:r.jsx("div",{className:"space-y-0.5",children:r.jsx(LA,{})})}),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:u,onChange:$=>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:H}),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:k,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(M*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:M,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:A,onChange:D})]}),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:!A})]}),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:FA.map($=>r.jsx("button",{type:"button",onClick:()=>s($.key),disabled:!o,className:"button-dark text-xs disabled:opacity-30",children:$.label},$.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:R.map($=>r.jsx("button",{type:"button",onClick:()=>E($.enable),disabled:!o,className:"flex-1 button-dark text-xs disabled:opacity-30",children:$.label},$.key))}),!o&&r.jsx("p",{className:"text-xs text-slate-500",children:"Assign a rover to toggle streams."})]}),r.jsx(Vg,{}),r.jsx(HA,{}),r.jsx(bA,{}),r.jsx(VA,{}),r.jsx(YA,{})]})})]})]})}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 XA(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:Cn(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 qo(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 QA({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 u=Array.isArray(l?.segments)?`hero-${o}`:`hero-${o}`;return r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:qo(l,s)},u)})})]}):null}function KA({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 u=`item-${o}`;return r.jsx("li",{className:"surface-muted flex flex-wrap items-center gap-0.5 px-0.5 py-0.25",children:qo(l,s)},u)})})]})}function ZA({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:qo(l,{})},`callout-${o}`))})]})}function IA({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 JA({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(IA,{group:l,keymap:s},l.id))})]}):null}function PA({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:qo(s,{})},`gamepad-${l}`))})]}):null}function yx({block:n,keymap:s}){if(!n)return null;switch(n.type){case"list":return r.jsx(KA,{block:n,keymap:s});case"callout":return r.jsx(ZA,{block:n});case"keyboard":return r.jsx(JA,{block:n,keymap:s});case"gamepad":return r.jsx(PA,{block:n});default:return null}}function Qg({layout:n,keymap:s}){const l=m.useMemo(()=>XA(n),[n]),o=s||{},u=l.main||[],f=l.aside||[];return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(QA,{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:u.map((p,h)=>r.jsx(yx,{block:p,keymap:o},p.title||h))}),r.jsx("div",{className:"space-y-0.5",children:f.map((p,h)=>r.jsx(yx,{block:p,keymap:o},p.title||h))})]})]})}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 WA=["kal","rms","slt","ksp","bdl"],ew=Array.from({length:10},(n,s)=>s*10);function To({hideInput:n=!1,hideSpectatorNotice:s=!1,fillHeight:l=!1,allowSpectatorInput:o=!1}){const u=it(T=>T.session),{messages:f,typing:p,sendMessage:h,registerInputRef:x,onInputFocus:g,onInputBlur:v,blurChat:y,setTypingActive:S}=of(),{value:k,save:C}=Ge("tts",{engine:"flite",voice:"rms",pitch:50}),[M,w]=m.useState(""),[A,N]=m.useState(!1),[R,E]=m.useState(!1),[O,K]=m.useState(()=>k?.engine||"flite"),[D,H]=m.useState(()=>k?.voice||"rms"),[X,$]=m.useState(()=>Number.isFinite(k?.pitch)?k.pitch:50),G=u?.role!=="spectator"||o,ee=m.useRef(null),oe=u?.assignment?.roverId||null,U=!!m.useMemo(()=>u?.roster?.find(T=>String(T.id)===String(oe))||null,[oe,u?.roster])?.audio?.ttsEnabled,q=m.useMemo(()=>f.slice(-200),[f]),L=m.useMemo(()=>p||[],[p]);m.useEffect(()=>{ee.current&&(ee.current.scrollTop=ee.current.scrollHeight)},[q,L]),m.useEffect(()=>{const T=k?.engine||"flite",V=k?.voice||"rms",ne=Number.isFinite(k?.pitch)?k.pitch:50;O!==T&&K(T),D!==V&&H(V),X!==ne&&$(ne)},[O,X,k?.engine,k?.pitch,k?.voice,D]),m.useEffect(()=>{E(!!U)},[U]);const Z=m.useMemo(()=>!U||!R?null:O==="espeak"?{speak:!0,engine:O,pitch:X}:{speak:!0,engine:O,voice:D},[O,X,R,U,D]);async function se(T){if(T.preventDefault(),!G||n)return;const ne=M.replace(/\\n/g,` -`).trim();if(ne){N(!0);try{await h(ne,Z),w(""),y(),S(!1)}catch(ae){alert(ae.message)}finally{N(!1)}}}const ce=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 ${ce}`,ref:ee,children:[q.length===0&&L.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"No messages yet."}):q.map(T=>r.jsx(sf,{message:T},T.id)),L.map(T=>r.jsx(pg,{message:T},`typing-${T.typingId||T.id}`))]}),!n&&r.jsxs("form",{className:"flex flex-wrap items-stretch gap-0.5",onSubmit:se,children:[r.jsx("input",{className:"field-input flex-1 min-w-[10rem]",value:M,onChange:T=>{const V=T.target.value;w(V),S(!!V.trim())},onFocus:T=>{g(T),S(!!M.trim())},onBlur:T=>{v(T),S(!1)},onKeyDown:T=>{T.key==="Enter"&&!M.trim()&&(T.preventDefault(),y(),S(!1))},ref:T=>x(T,{target:"panel"}),placeholder:G?"Type a message…":s?"":"Spectators cannot chat",disabled:!G}),U&&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:R,onChange:T=>E(T.target.checked),className:"accent-cyan-500"}),r.jsx("span",{children:"Speak"})]}),r.jsxs("select",{value:O,onChange:T=>{const V=T.target.value;K(V),C(ne=>({...ne||{},engine:V}))},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:D,onChange:T=>{const V=T.target.value;H(V),C(ne=>({...ne||{},voice:V}))},className:"field-input text-xs",children:WA.map(T=>r.jsx("option",{value:T,children:T},T))}):r.jsx("select",{value:X,onChange:T=>{const V=Number(T.target.value);$(V),C(ne=>({...ne||{},pitch:V}))},className:"field-input text-xs",children:ew.map(T=>r.jsxs("option",{value:T,children:["pitch ",T]},T))})]}),r.jsx("button",{type:"submit",disabled:!G||A,className:"button-dark h-full disabled:opacity-50 self-stretch",children:A?"...":"Send"})]})]})}function Do({compact:n=!1}){const{session:s,setNickname:l}=nn(),{value:o,save:u}=Ge("profile",{nickname:""}),[f,p]=m.useState(o.nickname||""),[h,x]=m.useState(!1),g=s?.role!=="spectator";m.useEffect(()=>{p(o.nickname||"")},[o.nickname]);async function v(y){if(y.preventDefault(),!g)return;const S=(f||"").trim().slice(0,32);if(S){x(!0);try{await l(S),u({nickname:S})}catch(k){alert(k.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:f,onChange:y=>p(y.target.value),maxLength:32,placeholder:"Enter a nickname",disabled:!g}),r.jsx("button",{type:"submit",disabled:!g||h,className:"button-dark h-full shrink-0 whitespace-nowrap px-0.5 py-0 disabled:opacity-50",children:h?"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(hf,{...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(Do,{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 yd(...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 _o({title:n="Rovers"}){const s=it(A=>A.session),{requestControl:l}=kn(),[o,u]=m.useState({}),[f,p]=m.useState(()=>Date.now()),h=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,k=m.useMemo(()=>Object.values(v||{}).some(A=>A?.deadline||A?.idleDeadline),[v]);m.useEffect(()=>{if(!k)return;const A=setInterval(()=>{p(Date.now())},1e3);return()=>clearInterval(A)},[k]);const C=m.useMemo(()=>{const A=new Set(g.map(R=>String(R.id))),N=Object.keys(v||{}).filter(R=>!A.has(String(R))).map(R=>({id:R,name:R,locked:!1,batteryState:null}));return[...g,...N]},[g,v]);async function M(A){if(A){u(N=>({...N,[A]:!0}));try{await l(A)}catch(N){alert(N.message)}finally{u(N=>({...N,[A]:!1}))}}}const w=A=>y.find(N=>N.socketId===A)||{socketId:A,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(A=>{const N=String(A.id),R=v?.[N]||null,E=R?.queue||[],O=R?.idleDeadline||R?.deadline||null,K=O&&O>f?Math.ceil((O-f)/1e3):O?0:null,D=R?.current||null,H=D?E.findIndex(se=>se===D):-1,X=E.length>1?H>=0?E[(H+1)%E.length]:E[0]:null,$=!!(S&&D&&D===S),G=!!(S&&X&&X===S),ee=K!=null&&($||G),oe=!!A.locked,ue=oe&&!x,U=!!(A?.private?.enabled&&A?.private?.open),q=A.lockReason?`locked: ${A.lockReason}`:"locked",L=oe?q:o[N]?"...":"request",Z=h&&!ue&&!o[N];return r.jsxs("li",{className:yd("surface flex flex-wrap items-start justify-between gap-0.5",Z&&"cursor-pointer",oe?"bg-red-900/40":U?"bg-amber-700/35 border border-amber-200/30":null),onClick:()=>{Z&&M(A.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:oa(A.color,.16),children:A.name})}),ee?r.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem] text-slate-200",children:$?`${K}s left`:`Your turn in ${K}s`}):null]}),r.jsx("span",{className:yd("text-[0.75rem] font-semibold",iw(A)),children:lw(A)})]}),E.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:E.map((se,ce)=>{const T=w(se),V=se===D,ne=!!(X&&se===X&&!V),ae=V?"bg-sky-600 text-white ring-2 ring-amber-300":ne?"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(T.role)} font-semibold`,children:ow(T,S)}),V&&r.jsx("span",{className:"text-[0.65rem] text-slate-200",children:"now"}),ne&&r.jsx("span",{className:"text-[0.65rem] text-emerald-100",children:"next"})]},`${N}-${se}-${ce}`)})})]}),h?r.jsx("button",{type:"button",onClick:se=>{se.stopPropagation(),M(A.id)},disabled:o[N]||ue,className:yd("button-dark disabled:opacity-40",oe&&"bg-red-600/70 text-white hover:bg-red-600"),children:L}):null]},A.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 jo({hideNicknameForm:n=!1,hideHeader:s=!1,className:l="",fillHeight:o=!1,compact:u=!1}){const{session:f}=nn(),p=f?.role!=="spectator",h=f?.users??[],x=f?.socketId||null,g=m.useMemo(()=>[...h].sort((y,S)=>y.socketId===x?-1:S.socketId===x?1:(y.nickname||"").localeCompare(S.nickname||"")),[x,h]),v=o?"flex-1 min-h-0 overflow-y-auto":u?"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(Do,{compact:u})})}),r.jsx(Zg,{})]}),!p&&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 ${u?"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} ${u?"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 dw=/^cu_[a-f0-9]{32}$/,Ai="field-input w-full max-w-sm text-left focus:ring-emerald-500",Bo="mx-auto w-full max-w-xl flex justify-center",pi="mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center";function fw(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,ss=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",u),l()},s);function u(){n.iceGatheringState==="complete"&&(clearTimeout(o),n.removeEventListener("icegatheringstatechange",u),l())}n.addEventListener("icegatheringstatechange",u)})}function Nx(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(Nx(n)){l();return}const u=setTimeout(()=>{p(),o(new Error("Peer connection timeout"))},s),f=()=>{Nx(n)?(p(),l()):(n.connectionState==="failed"||n.connectionState==="closed"||n.iceConnectionState==="failed")&&(p(),o(new Error(`Peer connection ${n.connectionState||n.iceConnectionState}`)))};function p(){clearTimeout(u),n.removeEventListener("connectionstatechange",f),n.removeEventListener("iceconnectionstatechange",f)}n.addEventListener("connectionstatechange",f),n.addEventListener("iceconnectionstatechange",f)})}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 u=Date.now();let f=-1;const p=setInterval(async()=>{if(Date.now()-u>s){clearInterval(p),o(new Error("WHIP connected but no outbound audio flow"));return}try{const h=n.getSenders().filter(x=>x.track?.kind==="audio");for(const x of h){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(f<0)f=y;else if(y>f+200||S>5){clearInterval(p),l();return}}}}catch{}},250)})}function yw(n){const s=n.reduce((u,f)=>u+f.length,0),l=new Float32Array(s);let o=0;for(const u of n)l.set(u,o),o+=u.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]),ne=!!(V&&V.state!=="offline"&&!V.error),ae=V?.source==="upload"&&V?.state==="playing",me=V?.source==="mic-whip"&&(V?.state==="starting"||V?.state==="playing"),re=!!(!A&&X.current&&(M||T)),de=!A&&(N==="live"||N==="starting"),be=A&&E==="recording",ve=A&&E==="sending",xe=Cn(h?.keymap?.micPtt?.[0])||"M",Le=m.useCallback(J=>{const pe=J==="clip"?"clip":"live";g(Ne=>({...Ne||{},pttMode:pe}))},[g]),De=async()=>{if(!v){D("Take control of your rover first.");return}if(!y){D("Select an audio file first.");return}if(y.size>Sx){D(`File too large (max ${Sx} bytes).`);return}C(!0),D("");try{const J=await y.arrayBuffer(),pe=jx(new Uint8Array(J));await l?.({roverId:v,name:y.name,mime:y.type||"",dataBase64:pe}),D("Upload playback started.")}catch(J){D(J?.message||"Failed to play upload.")}finally{C(!1)}},Ee=async()=>{if(!v){D("Take control of your rover first.");return}C(!0),D("");try{await o?.(v),D("Upload playback stopped.")}catch(J){D(J?.message||"Failed to stop upload.")}finally{C(!1)}},nt=m.useCallback(async J=>{const pe=String(J||ee.current||"").trim();if(G.current=!1,R("idle"),$.current){try{$.current.getSenders().forEach(Ne=>Ne.track?.stop())}catch{}try{$.current.close()}catch{}}if($.current=null,H.current)try{H.current.getTracks().forEach(Ne=>Ne.stop())}catch{}if(H.current=null,X.current=null,pe)try{await p?.(pe)}catch{}ee.current=""},[p]),Ve=m.useCallback(async J=>{const pe=await u?.(J),Ne=String(pe?.whipUrl||"").trim(),ht=String(pe?.token||"").trim();if(!Ne||!ht)throw new Error("WHIP endpoint unavailable");const Oe=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}});H.current=Oe;const rt=Oe.getAudioTracks()?.[0];if(X.current=rt||null,rt&&(rt.enabled=!!(M||T)),rt?.applyConstraints)try{await rt.applyConstraints({channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1})}catch{}const ot=new RTCPeerConnection(mw);$.current=ot,ot.onconnectionstatechange=()=>{if(!G.current)return;const Lt=ot.connectionState;if(Lt==="connected"){R("live");return}(Lt==="failed"||Lt==="disconnected"||Lt==="closed")&&(R("error"),D(`WHIP transport ${Lt}.`))},Oe.getAudioTracks().forEach(Lt=>{const ul=ot.addTrack(Lt,Oe);vw(ul)});const gt=await ot.createOffer({offerToReceiveAudio:!1,offerToReceiveVideo:!1});await ot.setLocalDescription(gt),await xw(ot,1800);const kt=await fetch(Ne,{method:"POST",headers:{"Content-Type":"application/sdp",...pw(ht)},body:ot.localDescription?.sdp||gt.sdp});if(!kt.ok)throw new Error(`WHIP request failed: ${kt.status}`);const us=await kt.text();await ot.setRemoteDescription({type:"answer",sdp:us}),await gw(ot,1e4),await bw(ot,6e3),await f?.(J)},[M,T,f,u]),mt=m.useCallback(async()=>{if(se.current=!1,q.current){try{q.current.disconnect()}catch{}q.current.onaudioprocess=null}if(U.current)try{U.current.disconnect()}catch{}if(L.current)try{L.current.disconnect()}catch{}if(oe.current)try{oe.current.getTracks().forEach(J=>J.stop())}catch{}if(ue.current)try{await ue.current.close()}catch{}Z.current=[],q.current=null,U.current=null,L.current=null,oe.current=null,ue.current=null,ce.current=ss},[]),ie=m.useCallback(async()=>{if(oe.current&&ue.current&&q.current)return;O(rt=>rt==="recording"?rt:"arming");const J=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}}),pe=new AudioContext({latencyHint:"interactive"}),Ne=pe.createMediaStreamSource(J),ht=pe.createScriptProcessor(1024,1,1),Oe=pe.createGain();Oe.gain.value=0,ht.onaudioprocess=rt=>{if(!se.current)return;const ot=rt.inputBuffer.getChannelData(0);Z.current.push(new Float32Array(ot))},Ne.connect(ht),ht.connect(Oe),Oe.connect(pe.destination),oe.current=J,ue.current=pe,U.current=Ne,q.current=ht,L.current=Oe,ce.current=pe.sampleRate||ss},[]),he=m.useCallback(async({send:J})=>{const pe=se.current;if(se.current=!1,!pe){J||O("idle");return}const Ne=Z.current;if(Z.current=[],!J){O("idle");return}if(!v){O("idle");return}if(!Ne.length){O("idle");return}O("sending");try{const ht=yw(Ne),Oe=jw(ht,ce.current||ss),rt=jx(Oe);await l?.({roverId:v,name:`ptt-${Date.now()}.wav`,mime:"audio/wav",dataBase64:rt}),O("idle")}catch(ht){O("error"),D(ht?.message||"Failed to send PTT clip.")}},[l,v]),le=m.useCallback(async()=>{if(!v){D("Take control of your rover first.");return}await ie(),Z.current=[],se.current=!0,O("recording")},[ie,v]);return m.useEffect(()=>{let J=!1;async function pe(){if(A){await nt(ee.current||v);return}if(!v){await nt(ee.current);return}if(!(G.current&&ee.current===v)&&!(!M&&!T))try{R("starting"),D(""),G.current=!0,ee.current=v,await Ve(v),J||R("live")}catch(Ne){J||(R("error"),D(Ne?.message||"Failed to start mic forwarding.")),await nt(v)}}return pe(),()=>{J=!0}},[A,M,T,v,Ve,nt]),m.useEffect(()=>{const J=X.current;J&&(J.enabled=!!(!A&&(M||T)))},[A,M,T]),m.useEffect(()=>{let J=!1;async function pe(){if(!A||!v){se.current&&await he({send:!1}),O("idle");return}try{await ie(),!J&&!se.current&&O("idle")}catch(Ne){J||(O("error"),D(Ne?.message||"Microphone access failed for clip mode."))}}return pe(),()=>{J=!0}},[A,ie,he,v]),m.useEffect(()=>{let J=!1;async function pe(){if(A){if(!v){se.current&&await he({send:!1});return}if(T){if(!se.current)try{D(""),await le()}catch(Ne){J||(O("error"),D(Ne?.message||"Failed to start clip recording."))}}else se.current&&await he({send:!0})}}return pe(),()=>{J=!0}},[A,he,T,v,le]),m.useEffect(()=>()=>{nt(ee.current||v),mt()},[v,nt,mt]),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(Ax,{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 ${A?"":"bg-emerald-500 text-white hover:bg-emerald-500"}`,onClick:()=>Le("live"),children:"Live Mic (WHIP)"}),r.jsx("button",{type:"button",className:`button-dark w-full text-sm ${A?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,onClick:()=>Le("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(vn,{label:"Mode",active:A,detail:A?"record clip":"live mic"}),r.jsx(vn,{label:"PTT hold",active:T,detail:T?"held":"released"}),r.jsx(vn,{label:"Recording",active:be,detail:be?"capturing":"idle"}),r.jsx(vn,{label:"Playback",active:A&&ae,detail:A&&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:`${Ai} text-center`,type:"file",accept:".mp3,.wav,.ogg,audio/mpeg,audio/wav,audio/ogg",disabled:k||!v,onChange:J=>S(J.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:k||!v,onClick:De,children:k?"Working...":"Play Upload"}),r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:k||!v,onClick:Ee,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:M,disabled:!v||A,onChange:J=>g(pe=>({...pe||{},openMicEnabled:!!J.target.checked}))}),r.jsx("span",{children:A?"Open mic (live mode only)":"Open mic"})]}),r.jsxs("div",{className:"grid gap-0.5 content-start",children:[r.jsx(vn,{label:"WHIP link",active:de,detail:N}),r.jsx(vn,{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(Ax,{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(vn,{label:"Forward pipe",active:ne,detail:ne?"connected":"offline"}),r.jsx(vn,{label:"Upload playback",active:ae,detail:ae?"playing":"idle"}),r.jsx(vn,{label:"Mic relay",active:me,detail:me?"active":"idle"}),r.jsx(vn,{label:"WHIP transport",active:de,detail:N}),r.jsx(vn,{label:"Clip recording",active:be,detail:be?"recording":"idle"}),r.jsx(vn,{label:"Clip sending",active:ve,detail:ve?"sending":"idle"})]}),K?r.jsx("div",{className:"text-xs text-slate-400 text-center",children:K}):null]})})]})})}function Aw({pendingRequestId:n,currentStoredKey:s,nickname:l,requestVerification:o,applyIdentityKey:u,onMessage:f,fullWidth:p=!1}){const[h,x]=m.useState(0),[g,v]=m.useState(""),[y,S]=m.useState(!1),[k,C]=m.useState(!1),M=()=>{x(1),v(s),S(!1),f?.("")},w=()=>{x(0),S(!1)},A=async R=>{if(R.preventDefault(),!y){f?.("Please confirm your nickname agreement before sending.");return}if(h<3){f?.("Complete all request steps before sending.");return}C(!0),f?.("");try{const E=await u(g);await o?.(),v(E),x(0),S(!1),f?.("Verification request sent to lockdown admins.")}catch(E){f?.(E.message||"Failed to submit request.")}finally{C(!1)}},N=p?"w-full":Bo;return n?r.jsx("section",{className:`surface text-sm text-slate-300 ${N}`,children:r.jsxs("div",{className:pi,children:["Verification request pending: ",n]})}):h===0?r.jsx("section",{className:`surface ${N}`,children:r.jsxs("div",{className:pi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Verification"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:M,disabled:k,children:"Request Verification"})]})}):r.jsx("form",{className:`surface ${N}`,onSubmit:A,children:r.jsxs("div",{className:pi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Request verification"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Step ",h," of 3"]}),h===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(Do,{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:R=>S(R.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,h===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:Ai,type:"password",name:"identity_key_request",autoComplete:"current-password",maxLength:35,value:g,onChange:R=>v(R.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,h===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:Ai,type:"password",name:"identity_key_request_final",autoComplete:"current-password",maxLength:35,value:g,onChange:R=>v(R.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:k||!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[u,f]=m.useState(0),[p,h]=m.useState(""),[x,g]=m.useState(!1),v=()=>{f(1),h(""),l?.("")},y=()=>{f(0),h("")},S=async C=>{if(C.preventDefault(),!(u<2)){g(!0),l?.("");try{await s(p),f(0),h(""),l?.("Identity key restored.")}catch(M){l?.(M.message||"Failed to restore key.")}finally{g(!1)}}},k=o?"w-full":Bo;return r.jsx("section",{className:`surface ${k}`,children:r.jsxs("div",{className:pi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Identity key"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Current: ",fw(n)||"not set yet"]}),r.jsx("input",{className:Ai,type:"password",name:"identity_key_current",autoComplete:"current-password",maxLength:35,value:n,readOnly:!0,placeholder:"Identity key"}),u===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,u===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:()=>f(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:y,children:"Cancel"})]})]}):null,u===2?r.jsxs("form",{className:"space-y-0.5",onSubmit:S,children:[r.jsx("input",{className:Ai,type:"password",name:"identity_key_restore",autoComplete:"current-password",maxLength:35,value:p,onChange:C=>h(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||!p,children:"Confirm Restore"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>f(1),children:"Back"})]})]}):null]})})}function Cw({requestableRovers:n=[],pendingRequests:s=[],requestPrivateRoverAccess:l,onMessage:o,fullWidth:u=!1}){const[f,p]=m.useState({}),h=m.useMemo(()=>{const v=new Map;return(s||[]).forEach(y=>{y?.roverId&&v.set(String(y.roverId),y)}),v},[s]),x=u?"w-full":Bo,g=async v=>{if(v){p(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{p(y=>({...y,[v]:!1}))}}};return r.jsx("section",{className:`surface text-sm text-slate-300 ${x}`,children:r.jsxs("div",{className:pi,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=!!f[y],k=h.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})]}),k?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 mo(n){return String(n||"").trim()}function Ew(n){const s=mo(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":"bg-slate-700 text-slate-100"}function eo({label:n,value:s,tone:l="muted",valueClass:o="",hideLabel:u=!1}){return r.jsxs("div",{className:`rounded-md px-1 py-0.75 text-center ${Ig(l)}`,children:[u?null: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(n=[]){return n.filter(u=>u&&u.valid&&Number.isFinite(u.angleDeg)&&Number.isFinite(u.distanceMm)).map(u=>{const f=(Number(u.angleDeg)-90)*Math.PI/180,h=Math.max(0,Math.min(1,Number(u.distanceMm)/4e3))*92,x=110+Math.cos(f)*h,g=110+Math.sin(f)*h;return`${x},${g}`}).join(" ")}function Mw({neato:n,lidar:s,onStart:l,onSendHome:o,onLocate:u,onClearErrors:f,onPowerCycle:p,fullWidth:h=!1}){const[x,g]=m.useState(""),v=h?"w-full":"w-full max-w-xl",y=!!n?.configured,S=!!(n?.enabled&&n?.connected),k=!!n?.telemetry?.extPowerPresent,C=!!n?.telemetry?.chargingActive,M=Ew(n?.telemetry?.uiState),w=mo(n?.telemetry?.robotState)||"--",A=n?.telemetry?.batteryPercent,N=Number.isFinite(A)?`${A}%`:"--",R=n?.telemetry?.batteryVoltage,E=Number.isFinite(R)?`${R.toFixed(2)} V`:"--",O=mo(n?.telemetry?.robotError)||"--",K=mo(n?.telemetry?.robotAlert)||"--",D=Array.isArray(s?.points)?s.points:[],H=kw(D),X=n?.controls||{},$=!!X?.start?.available,G=!!X?.sendHome?.available,ee=!!X?.locate?.available,oe=!!X?.clearErrors?.available,ue=!!X?.powerCycle?.available,U=y&&S&&$,q=y&&S&&G,L=y&&S&&ee,Z=y&&S&&oe,se=y&&S&&ue,ce=async(me,re)=>{if(re){g(me);try{await re()}catch{}finally{g("")}}},T=y?S?"Online":"Offline":"Not configured",V=y?S?"good":"danger":"warn",ne=A==null?"muted":A>=60?"good":A>=25?"warn":"danger",ae=k?"Docked":M!=="--"?M:"Away from dock";return r.jsx("section",{className:`surface text-sm text-slate-200 ${v}`,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. Be nice to him."})]}),r.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${Ig(V)}`,children:T})]}),r.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-0.5",children:[r.jsxs("div",{className:"surface-muted grid gap-0.5",children:[r.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Controls"}),r.jsx("button",{type:"button",disabled:!U||!!x,onClick:()=>ce("start",l),className:"rounded-md border border-sky-300 bg-emerald-600 px-1 py-1 text-base font-semibold text-white transition hover:border-sky-500 hover:bg-emerald-500 disabled:opacity-50",children:x==="start"?"Starting...":"Start cleaning"}),r.jsx("button",{type:"button",disabled:!q||!!x,onClick:()=>ce("sendHome",o),className:"rounded-md border border-sky-300 bg-sky-600 px-1 py-1 text-base font-semibold text-white transition hover:border-sky-500 hover:bg-sky-500 disabled:opacity-50",children:x==="sendHome"?"Sending...":"Send to dock"}),r.jsxs("div",{className:"grid grid-cols-3 gap-0.5",children:[r.jsx("button",{type:"button",disabled:!L||!!x,onClick:()=>ce("locate",u),className:"w-full rounded-md border border-sky-300 bg-fuchsia-600 px-1 py-0.5 text-xs font-semibold text-white transition hover:border-sky-500 hover:bg-fuchsia-500 disabled:opacity-50",children:x==="locate"?"Playing...":"Play sound"}),r.jsx("button",{type:"button",disabled:!Z||!!x,onClick:()=>ce("clearErrors",f),className:"w-full rounded-md border border-sky-300 bg-amber-500 px-1 py-0.5 text-xs font-semibold text-slate-900 transition hover:border-sky-500 hover:bg-amber-400 disabled:opacity-50",children:x==="clearErrors"?"Clearing...":"Clear errors"}),r.jsx("button",{type:"button",disabled:!se||!!x,onClick:()=>ce("powerCycle",p),className:"w-full rounded-md border border-rose-300 bg-rose-600 px-1 py-0.5 text-xs font-semibold text-white transition hover:border-rose-500 hover:bg-rose-500 disabled:opacity-50",children:x==="powerCycle"?"Cycling...":"Power cycle"})]}),r.jsxs("div",{className:"surface-muted grid gap-0.5 pt-0.25",children:[r.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Power status"}),r.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[r.jsx(eo,{label:"Battery",value:N,tone:ne}),r.jsx(eo,{label:"Voltage",value:E,tone:"muted"}),r.jsx(eo,{label:"Docked",value:k?"Docked":"Not docked",tone:k?"good":"muted",hideLabel:!0}),r.jsx(eo,{label:"Charging",value:C?"charging":"not charging",tone:C?"good":"muted",hideLabel:!0})]})]})]}),r.jsxs("div",{className:"surface-muted grid gap-0.5",children:[r.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Robot Status"}),r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot state (raw)"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:w})]}),r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Basic state"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:ae})]}),r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"UI state"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:M})]}),r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot error"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:O})]}),r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot alert"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:K})]})]})]}),r.jsxs("div",{className:"surface-muted grid gap-0.5",children:[r.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Lidar"}),r.jsx("div",{className:"rounded-md bg-slate-800 p-0.5",children:H?r.jsxs("svg",{viewBox:"0 0 220 220",className:"w-full max-w-[26rem] mx-auto",children:[r.jsx("circle",{cx:"110",cy:"110",r:"92",fill:"none",stroke:"#475569",strokeWidth:"1"}),r.jsx("circle",{cx:"110",cy:"110",r:"61",fill:"none",stroke:"#334155",strokeWidth:"1"}),r.jsx("circle",{cx:"110",cy:"110",r:"31",fill:"none",stroke:"#1e293b",strokeWidth:"1"}),r.jsx("line",{x1:"110",y1:"18",x2:"110",y2:"202",stroke:"#334155",strokeWidth:"1"}),r.jsx("line",{x1:"18",y1:"110",x2:"202",y2:"110",stroke:"#334155",strokeWidth:"1"}),r.jsx("circle",{cx:"110",cy:"110",r:"4",fill:"#e2e8f0"}),r.jsx("polyline",{points:H,fill:"none",stroke:"#38bdf8",strokeWidth:"1.5",strokeLinejoin:"round",strokeLinecap:"round"})]}):r.jsx("div",{className:"py-3 text-center text-xs text-slate-400",children:"Waiting for lidar scan..."})})]}),!y||!S||!$||!G||!ee||!oe||!ue?r.jsx("p",{className:"text-xs text-slate-400 text-center",children:y?S?"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 Rw(n){return n==="good"?"bg-emerald-600 text-white":n==="warn"?"bg-amber-500 text-slate-900":n==="danger"?"bg-rose-600 text-white":"bg-slate-700 text-slate-100"}function qw(n){return n==="up"?"Up":n==="down"?"Down":n==="stopped"?"Transitioning...":n==="conflict"?"Conflict":"--"}function Tw({lift:n,onUp:s,onDown:l,fullWidth:o=!1}){const[u,f]=m.useState(""),[p,h]=m.useState(()=>Date.now()),x=o?"w-full":"w-full max-w-xl",g=!!n?.configured,v=!!(n?.enabled&&n?.connected),y=!!n?.busy,S=String(n?.target||"").toLowerCase(),k=String(n?.position||"").toLowerCase(),C=!!n?.availability?.upSwitch,M=!!n?.availability?.downSwitch,w=Number(n?.lastActionAt||0),A=Math.max(0,Number(n?.commandCooldownMs||0)),N=Math.max(0,w+A-p),R=!y&&N>0,E=y||R;m.useEffect(()=>{if(!E)return;const $=setInterval(()=>{h(Date.now())},100);return()=>clearInterval($)},[E]),m.useEffect(()=>{h(Date.now())},[w,A,y]);const O=g?v?E?"Busy":"Ready":"Offline":"Not configured",K=g?v?E?"warn":"good":"danger":"warn",D=g&&v&&!E&&!u&&C&&M,H=m.useMemo(()=>Math.ceil(N/1e3),[N]),X=async($,G)=>{if(G){f($);try{await G()}catch{}finally{f("")}}};return r.jsxs("section",{className:`surface relative text-sm text-slate-200 ${x}`,children:[E?r.jsx("div",{className:"absolute inset-0 z-20 flex items-center justify-center rounded-md bg-slate-950/80 px-1.5 text-center",children:r.jsxs("div",{className:"space-y-0.25",children:[r.jsx("p",{className:"text-sm font-semibold text-slate-100",children:y?"Motion in progress":"Motion cooldown active"}),r.jsx("p",{className:"text-xs text-slate-300",children:"Controls are disabled while the lift is moving, otherwise it's tiny brain would get confused."}),!y&&R?r.jsxs("p",{className:"text-xs text-slate-400",children:["About ",H,"s remaining."]}):null]})}):null,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:"Lift Controls"}),r.jsx("p",{className:"text-xs text-slate-400",children:"Move the lift up and down. Please don't break anything..."})]}),r.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${Rw(K)}`,children:O})]}),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:"rounded-md bg-slate-800 px-1 py-0.75 text-center",children:[r.jsx("div",{className:"text-xs text-slate-300",children:"Position"}),r.jsx("div",{className:"text-base font-semibold text-slate-100",children:qw(k)})]}),r.jsx("button",{type:"button",disabled:!D,onClick:()=>X("down",l),className:`button-dark w-full text-sm disabled:opacity-50 ${k==="down"||S==="down"?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,children:u==="down"||S==="down"?"Lowering...":"Down"}),r.jsx("button",{type:"button",disabled:!D,onClick:()=>X("up",s),className:`button-dark w-full text-sm disabled:opacity-50 ${k==="up"||S==="up"?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,children:u==="up"||S==="up"?"Raising...":"Up"})]})}),!g||!v||!C||!M?r.jsx("p",{className:"text-xs text-slate-400 text-center",children:g?v?"Waiting for required lift switch entities in Home Assistant.":"Home Assistant is offline.":"Set homeAssistant.lift.upSwitch and homeAssistant.lift.downSwitch in server config."}):null,n?.lastError?r.jsxs("p",{className:"text-xs text-rose-300 text-center",children:["Last error: ",n.lastError]}):null]})]})}function Jg(){const{session:n,neatoLidar:s,identifySession:l,requestVerification:o,requestPrivateRoverAccess:u,playUploadedAudio:f,stopUploadedAudio:p,startMicWhip:h,readyMicWhip:x,stopMicWhip:g,neatoStart:v,neatoSendHome:y,neatoLocate:S,neatoClearErrors:k,neatoPowerCycle:C,liftUp:M,liftDown:w}=nn(),{value:A,save:N}=Ge("identity",{cookieUserId:""}),{value:R}=Ge("profile",{nickname:""}),E=m.useMemo(()=>(A?.cookieUserId||"").trim(),[A?.cookieUserId]),O=(R?.nickname||"").trim(),K=!!n?.isVerified,D=n?.verification?.pendingRequestId||null,H=n?.privateRoverAccess?.requestableRovers||[],X=n?.privateRoverAccess?.pendingRequests||[],$=String(n?.assignment?.roverId||"").trim(),[G,ee]=m.useState(""),oe=async ue=>{const U=String(ue||"").trim().toLowerCase();if(!U)throw new Error("Identity key required.");if(!dw.test(U))throw new Error("Identity key must match format: cu_ + 32 lowercase hex chars.");return N(q=>({...q||{},cookieUserId:U})),await l({cookieUserId:U,nickname:O}),U};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:[K?null:r.jsx("div",{className:"lg:col-span-2",children:r.jsx(Aw,{pendingRequestId:D,currentStoredKey:E,nickname:O,requestVerification:o,applyIdentityKey:oe,onMessage:ee,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:K?r.jsxs("div",{className:"space-y-2",children:[r.jsx(Mw,{neato:n?.neato||null,lidar:s,onStart:v,onSendHome:y,onLocate:S,onClearErrors:k,onPowerCycle:C,fullWidth:!0}),r.jsx(Tw,{lift:n?.lift||null,onUp:M,onDown:w,fullWidth:!0}),r.jsx(Nw,{ownRoverId:$,audioForwardByRover:n?.audioForward||{},playUploadedAudio:f,stopUploadedAudio:p,startMicWhip:h,readyMicWhip:x,stopMicWhip:g})]}):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:H,pendingRequests:X,requestPrivateRoverAccess:u,onMessage:ee,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(ww,{currentStoredKey:E,applyIdentityKey:oe,onMessage:ee,fullWidth:!0})})]}),G?r.jsx("div",{className:Bo,children:r.jsx("p",{className:"text-xs text-slate-400 text-center",children:G})}):null]})}const Dw=420,_w=1200,Bw={1:262,2:330,3:392,4:523};function No(){const{session:n}=nn(),s=tn(),{value:l}=Ge("audio",st),o=Number.isFinite(l?.masterVolume)?l.masterVolume:st.masterVolume,u=Number.isFinite(l?.alertVolume)?l.alertVolume:st.alertVolume,f=Math.max(0,Math.min(1,o*u)),p=m.useMemo(()=>{const M=Array.isArray(n?.buttonBox?.buttons)?n.buttonBox.buttons:[];return M.length===4?M:[1,2,3,4].map(w=>M.find(A=>Number(A?.id)===w)||{id:w,count:0,goal:0,rewardName:null,rewardId:null,rewardNumber:null,lastRewardAt:null})},[n?.buttonBox?.buttons]),[h,x]=m.useState({}),[g,v]=m.useState({}),y=m.useRef(new Map),S=m.useRef(new Map),k=m.useRef({}),C=m.useRef(null);return m.useEffect(()=>{const M={};p.forEach(A=>{M[A.id]=Number(A.lastRewardAt||0)});const w=k.current||{};p.forEach(A=>{const N=Number(A.id),R=M[N]||0,E=Number(w[N]||0);if(R>0&&R!==E){v(D=>({...D,[N]:!0}));const O=S.current.get(N);O&&clearTimeout(O);const K=setTimeout(()=>{v(D=>({...D,[N]:!1})),S.current.delete(N)},_w);S.current.set(N,K)}}),k.current=M},[p]),m.useEffect(()=>{function M(A){const N=Bw[A];if(!N||f<=0)return;let R=C.current;if(!R){const D=window.AudioContext||window.webkitAudioContext;if(!D)return;R=new D,C.current=R}const E=R.createOscillator(),O=R.createGain();E.type="square",E.frequency.value=N;const K=.14*f;O.gain.setValueAtTime(1e-4,R.currentTime),O.gain.exponentialRampToValueAtTime(Math.max(1e-4,K),R.currentTime+.01),O.gain.exponentialRampToValueAtTime(1e-4,R.currentTime+.2),E.connect(O),O.connect(R.destination),E.start(),E.stop(R.currentTime+.21)}function w(A={}){const N=Number(A.buttonId);if(!Number.isFinite(N)||N<1||N>4)return;x(O=>({...O,[N]:!0}));const R=y.current.get(N);R&&clearTimeout(R);const E=setTimeout(()=>{x(O=>({...O,[N]:!1})),y.current.delete(N)},Dw);y.current.set(N,E),M(N)}return s.on("buttonBox:increment",w),()=>{s.off("buttonBox:increment",w)}},[f,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:p.map(M=>{const w=Number(M.id),A=Number.isFinite(M.count)?M.count:0,N=Number.isFinite(M.goal)?M.goal:0,R=typeof M.rewardName=="string"&&M.rewardName.trim()?M.rewardName.trim():"Unassigned",E=Number.isFinite(M.rewardNumber)?M.rewardNumber:"?",O=!!h[w],K=!!g[w];return r.jsx(xg,{buttonId:w,count:A,goal:N,rewardNumber:E,rewardName:R,className:[O?"bg-cyan-900/45":"",K?"bg-fuchsia-900/45":""].filter(Boolean).join(" ")},w)})})]})}function Ow(){const{state:{roverId:n}}=_t(),l=cl(n)?.sensors||{};return r.jsx("section",{className:"panel-section",children:r.jsx("div",{className:"aspect-square w-full",children:r.jsx(Hd,{sensors:l})})})}function Lw(){const{state:{roverId:n,keymap:s,camera:l,horn:o},pipeline:u,actions:{setServoAngle:f,setNightVision:p,startHorn:h,stopHorn:x}}=_t(),g=qg(n),v=g.docked&&!g.driving,y=l?.config,S=!!(n&&l?.enabled&&y),k=!!(n&&u?.nightVision),C=u?.nightVisionState,M=!!(n&&u?.horn),w=o?.overheated,A=typeof y?.minAngle=="number"?y.minAngle:-30,N=typeof y?.maxAngle=="number"?y.maxAngle:30,R=typeof l?.angle=="number"?l.angle:typeof y?.homeAngle=="number"?y.homeAngle:(A+N)/2,E=Cn(s?.nightVisionToggle?.[0]),O=Cn(s?.hornHonk?.[0]),K=Cn(s?.cameraUp?.[0]),D=Cn(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:[k&&r.jsx(Dg,{nightVisionOn:C?.nightVisionOn,disabled:!n,onToggle:p,keyLabel:E}),M&&r.jsx(_g,{disabled:!n||w,onStart:h,onStop:x,keyLabel:O,active:o?.active,heat:o?.heat}),S&&r.jsx(Bg,{value:R,min:A,max:N,onChange:f,keyDownLabel:D,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 zw({layout:n,onOpenHelpOverlay:s}){const l=it(k=>k.session),{state:o}=_t(),{value:u}=Ge("vipAudio",{openMicEnabled:!1,pttMode:"live"}),f=l?.isVerified?"bg-emerald-400":"bg-red-600",p=String(l?.assignment?.roverId||"").trim(),h=p?l?.audioForward?.[p]:null,x=!!o?.mic?.pttActive,g=!!u?.openMicEnabled,v=u?.pttMode==="clip"?"clip":"live",y=!!(p&&l?.isVerified&&(v==="clip"?x:g||x)),S=!!(p&&l?.isVerified&&v==="clip"&&h?.source==="upload"&&h?.state==="playing");return r.jsx("section",{className:"panel text-base",children:r.jsxs(yf,{defaultTab:"telemetry",children:[r.jsxs(Sf,{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 ${f}`,"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(jf,{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(Ow,{}),r.jsx(Lw,{})]}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.9fr)_minmax(0,0.75fr)]",children:[r.jsx(_o,{}),r.jsx(nf,{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(To,{fillHeight:!0}),r.jsxs("div",{className:"grid min-h-0 gap-0.5 grid-rows-[minmax(0,1fr)_auto]",children:[r.jsx(jo,{compact:!0,hideNicknameForm:!0,fillHeight:!0}),r.jsx(aw,{compact:!0})]})]}),r.jsx(Hg,{}),r.jsx(No,{}),r.jsx(df,{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 Uw=new Set(["admin","lockdown","lockdown-admin"]),Hw=new Set(["lockdown","lockdown-admin"]),Vw=new Set(["admin","lockdown"]);function $w(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 Gw(){const n=it(S=>S.session),s=n?.mode,l=n?.role,o=n?.adminReason?.text||"";n?.adminReason?.updatedAt;const u=n?.timezone||"UTC",f=n?.socials?.find(S=>String(S?.id||S?.label||"").toLowerCase()==="discord")?.url||n?.discord?.invite||null,p=Vw.has(s),h=s==="lockdown"?Hw.has(l):Uw.has(l),[x,g]=m.useState(()=>new Date),v=m.useMemo(()=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:u,hour:"numeric",minute:"2-digit",second:"2-digit"}).format(x)}catch{return x.toLocaleTimeString()}},[x,u]);if(m.useEffect(()=>{const S=setInterval(()=>g(new Date),1e3);return()=>clearInterval(S)},[]),!p||h)return null;const y=$w(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(hf,{id:"discord",label:"Join our Discord server for updates!",url:f})}),"You can still use the chat while the server is locked:",r.jsxs("div",{className:"max-h-80 overflow-y-auto",children:[r.jsx(To,{}),r.jsx(Do,{})]})]})})}const Yw="/assets/turn_alert-DVO8EZJa.mp3";function Fw(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 Xw(){const n=it(v=>v.session),{pushAlert:s}=kn(),{value:l}=Ge("audio",st),o=Number.isFinite(l?.masterVolume)?l.masterVolume:st.masterVolume,u=Number.isFinite(l?.alertVolume)?l.alertVolume:st.alertVolume,f=Math.max(0,Math.min(1,o*u)),p=Fw(Yw,f),h=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||h.current.has(y)||(v.push(y),h.current.add(y))}),Object.keys(x).forEach(y=>{(!x[y]||x[y].current!==g)&&h.current.delete(y)}),v.length!==0&&(v.forEach(y=>{const S=n?.roster?.find(k=>String(k.id)===String(y))?.name||y;s({title:"Your turn!",message:`You now control ${S}.`,color:"#ff5722"})}),p())},[x,p,s,n?.roster,g]),null}function Qw({visible:n,mode:s,onEnterFullscreen:l,onDismiss:o}){if(!n)return null;const u=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"}),u?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:u?"Got it":"Not now"}),!u&&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 Kw({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",Zw=new Set(["mobile-portrait","mobile-landscape"]),Wg=()=>{if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}},Iw=()=>{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{}},Jw=()=>{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 Pw(n){const s=Zw.has(n),[l,o]=m.useState(!1),[u,f]=m.useState("native"),[p,h]=m.useState(!1),x=m.useMemo(()=>Jw(),[]),g=m.useMemo(()=>Cx(),[]),v=m.useCallback(()=>{if(!s){o(!1),h(!1);return}if(!p&&Iw()){o(!1);return}if(x){f("pwa-hint"),o(!0);return}if(!Cx()){o(!1);return}if(typeof document<"u"&&document.fullscreenElement){o(!1);return}f("native"),o(!0)},[p,x,s]);m.useEffect(()=>{v()},[v]),m.useEffect(()=>{if(typeof document>"u")return;const C=()=>{if(document.fullscreenElement){h(!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(),h(!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 M=C.requestFullscreen||C.webkitRequestFullscreen||C.mozRequestFullScreen||C.msRequestFullscreen;if(!M)return!1;try{const w=M.call(C);return w&&typeof w.then=="function"&&await w,wx(),h(!1),o(!1),!0}catch(w){return console.warn("Failed to enter fullscreen",w),!1}},[x,s]),k=m.useCallback(()=>{s&&(h(!0),f(x?"pwa-hint":"native"),o(!0))},[x,s]);return m.useEffect(()=>{s||(h(!1),o(!1))},[s]),{visible:l,mode:u,isIOS:x,nativeSupported:g,enterFullscreen:S,dismiss:y,showPrompt:k}}function Ww({visible:n,layout:s,onClose:l,showOnLoad:o,onToggleShowOnLoad:u}){if(!n)return null;const{state:f}=_t(),p=h=>{const x=!h.target.checked;u?.(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:p,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:f?.keymap||{}})})]})})}const e2=`aroma +`).trim();if(ne){N(!0);try{await h(ne,Z),w(""),y(),S(!1)}catch(ae){alert(ae.message)}finally{N(!1)}}}const ce=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 ${ce}`,ref:ee,children:[q.length===0&&L.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"No messages yet."}):q.map(T=>r.jsx(sf,{message:T},T.id)),L.map(T=>r.jsx(pg,{message:T},`typing-${T.typingId||T.id}`))]}),!n&&r.jsxs("form",{className:"flex flex-wrap items-stretch gap-0.5",onSubmit:se,children:[r.jsx("input",{className:"field-input flex-1 min-w-[10rem]",value:M,onChange:T=>{const V=T.target.value;w(V),S(!!V.trim())},onFocus:T=>{g(T),S(!!M.trim())},onBlur:T=>{v(T),S(!1)},onKeyDown:T=>{T.key==="Enter"&&!M.trim()&&(T.preventDefault(),y(),S(!1))},ref:T=>x(T,{target:"panel"}),placeholder:G?"Type a message…":s?"":"Spectators cannot chat",disabled:!G}),U&&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:R,onChange:T=>E(T.target.checked),className:"accent-cyan-500"}),r.jsx("span",{children:"Speak"})]}),r.jsxs("select",{value:O,onChange:T=>{const V=T.target.value;K(V),C(ne=>({...ne||{},engine:V}))},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:D,onChange:T=>{const V=T.target.value;H(V),C(ne=>({...ne||{},voice:V}))},className:"field-input text-xs",children:WA.map(T=>r.jsx("option",{value:T,children:T},T))}):r.jsx("select",{value:X,onChange:T=>{const V=Number(T.target.value);$(V),C(ne=>({...ne||{},pitch:V}))},className:"field-input text-xs",children:ew.map(T=>r.jsxs("option",{value:T,children:["pitch ",T]},T))})]}),r.jsx("button",{type:"submit",disabled:!G||A,className:"button-dark h-full disabled:opacity-50 self-stretch",children:A?"...":"Send"})]})]})}function Do({compact:n=!1}){const{session:s,setNickname:l}=nn(),{value:o,save:u}=Ge("profile",{nickname:""}),[f,p]=m.useState(o.nickname||""),[h,x]=m.useState(!1),g=s?.role!=="spectator";m.useEffect(()=>{p(o.nickname||"")},[o.nickname]);async function v(y){if(y.preventDefault(),!g)return;const S=(f||"").trim().slice(0,32);if(S){x(!0);try{await l(S),u({nickname:S})}catch(k){alert(k.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:f,onChange:y=>p(y.target.value),maxLength:32,placeholder:"Enter a nickname",disabled:!g}),r.jsx("button",{type:"submit",disabled:!g||h,className:"button-dark h-full shrink-0 whitespace-nowrap px-0.5 py-0 disabled:opacity-50",children:h?"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(hf,{...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(Do,{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 yd(...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 _o({title:n="Rovers"}){const s=it(A=>A.session),{requestControl:l}=kn(),[o,u]=m.useState({}),[f,p]=m.useState(()=>Date.now()),h=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,k=m.useMemo(()=>Object.values(v||{}).some(A=>A?.deadline||A?.idleDeadline),[v]);m.useEffect(()=>{if(!k)return;const A=setInterval(()=>{p(Date.now())},1e3);return()=>clearInterval(A)},[k]);const C=m.useMemo(()=>{const A=new Set(g.map(R=>String(R.id))),N=Object.keys(v||{}).filter(R=>!A.has(String(R))).map(R=>({id:R,name:R,locked:!1,batteryState:null}));return[...g,...N]},[g,v]);async function M(A){if(A){u(N=>({...N,[A]:!0}));try{await l(A)}catch(N){alert(N.message)}finally{u(N=>({...N,[A]:!1}))}}}const w=A=>y.find(N=>N.socketId===A)||{socketId:A,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(A=>{const N=String(A.id),R=v?.[N]||null,E=R?.queue||[],O=R?.idleDeadline||R?.deadline||null,K=O&&O>f?Math.ceil((O-f)/1e3):O?0:null,D=R?.current||null,H=D?E.findIndex(se=>se===D):-1,X=E.length>1?H>=0?E[(H+1)%E.length]:E[0]:null,$=!!(S&&D&&D===S),G=!!(S&&X&&X===S),ee=K!=null&&($||G),oe=!!A.locked,ue=oe&&!x,U=!!(A?.private?.enabled&&A?.private?.open),q=A.lockReason?`locked: ${A.lockReason}`:"locked",L=oe?q:o[N]?"...":"request",Z=h&&!ue&&!o[N];return r.jsxs("li",{className:yd("surface flex flex-wrap items-start justify-between gap-0.5",Z&&"cursor-pointer",oe?"bg-red-900/40":U?"bg-amber-700/35 border border-amber-200/30":null),onClick:()=>{Z&&M(A.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:oa(A.color,.16),children:A.name})}),ee?r.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem] text-slate-200",children:$?`${K}s left`:`Your turn in ${K}s`}):null]}),r.jsx("span",{className:yd("text-[0.75rem] font-semibold",iw(A)),children:lw(A)})]}),E.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:E.map((se,ce)=>{const T=w(se),V=se===D,ne=!!(X&&se===X&&!V),ae=V?"bg-sky-600 text-white ring-2 ring-amber-300":ne?"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(T.role)} font-semibold`,children:ow(T,S)}),V&&r.jsx("span",{className:"text-[0.65rem] text-slate-200",children:"now"}),ne&&r.jsx("span",{className:"text-[0.65rem] text-emerald-100",children:"next"})]},`${N}-${se}-${ce}`)})})]}),h?r.jsx("button",{type:"button",onClick:se=>{se.stopPropagation(),M(A.id)},disabled:o[N]||ue,className:yd("button-dark disabled:opacity-40",oe&&"bg-red-600/70 text-white hover:bg-red-600"),children:L}):null]},A.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 jo({hideNicknameForm:n=!1,hideHeader:s=!1,className:l="",fillHeight:o=!1,compact:u=!1}){const{session:f}=nn(),p=f?.role!=="spectator",h=f?.users??[],x=f?.socketId||null,g=m.useMemo(()=>[...h].sort((y,S)=>y.socketId===x?-1:S.socketId===x?1:(y.nickname||"").localeCompare(S.nickname||"")),[x,h]),v=o?"flex-1 min-h-0 overflow-y-auto":u?"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(Do,{compact:u})})}),r.jsx(Zg,{})]}),!p&&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 ${u?"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} ${u?"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 dw=/^cu_[a-f0-9]{32}$/,Ai="field-input w-full max-w-sm text-left focus:ring-emerald-500",Bo="mx-auto w-full max-w-xl flex justify-center",pi="mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center";function fw(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,ss=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",u),l()},s);function u(){n.iceGatheringState==="complete"&&(clearTimeout(o),n.removeEventListener("icegatheringstatechange",u),l())}n.addEventListener("icegatheringstatechange",u)})}function Nx(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(Nx(n)){l();return}const u=setTimeout(()=>{p(),o(new Error("Peer connection timeout"))},s),f=()=>{Nx(n)?(p(),l()):(n.connectionState==="failed"||n.connectionState==="closed"||n.iceConnectionState==="failed")&&(p(),o(new Error(`Peer connection ${n.connectionState||n.iceConnectionState}`)))};function p(){clearTimeout(u),n.removeEventListener("connectionstatechange",f),n.removeEventListener("iceconnectionstatechange",f)}n.addEventListener("connectionstatechange",f),n.addEventListener("iceconnectionstatechange",f)})}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 u=Date.now();let f=-1;const p=setInterval(async()=>{if(Date.now()-u>s){clearInterval(p),o(new Error("WHIP connected but no outbound audio flow"));return}try{const h=n.getSenders().filter(x=>x.track?.kind==="audio");for(const x of h){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(f<0)f=y;else if(y>f+200||S>5){clearInterval(p),l();return}}}}catch{}},250)})}function yw(n){const s=n.reduce((u,f)=>u+f.length,0),l=new Float32Array(s);let o=0;for(const u of n)l.set(u,o),o+=u.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]),ne=!!(V&&V.state!=="offline"&&!V.error),ae=V?.source==="upload"&&V?.state==="playing",me=V?.source==="mic-whip"&&(V?.state==="starting"||V?.state==="playing"),re=!!(!A&&X.current&&(M||T)),de=!A&&(N==="live"||N==="starting"),be=A&&E==="recording",ve=A&&E==="sending",xe=Cn(h?.keymap?.micPtt?.[0])||"M",Le=m.useCallback(J=>{const pe=J==="clip"?"clip":"live";g(Ne=>({...Ne||{},pttMode:pe}))},[g]),De=async()=>{if(!v){D("Take control of your rover first.");return}if(!y){D("Select an audio file first.");return}if(y.size>Sx){D(`File too large (max ${Sx} bytes).`);return}C(!0),D("");try{const J=await y.arrayBuffer(),pe=jx(new Uint8Array(J));await l?.({roverId:v,name:y.name,mime:y.type||"",dataBase64:pe}),D("Upload playback started.")}catch(J){D(J?.message||"Failed to play upload.")}finally{C(!1)}},Ee=async()=>{if(!v){D("Take control of your rover first.");return}C(!0),D("");try{await o?.(v),D("Upload playback stopped.")}catch(J){D(J?.message||"Failed to stop upload.")}finally{C(!1)}},nt=m.useCallback(async J=>{const pe=String(J||ee.current||"").trim();if(G.current=!1,R("idle"),$.current){try{$.current.getSenders().forEach(Ne=>Ne.track?.stop())}catch{}try{$.current.close()}catch{}}if($.current=null,H.current)try{H.current.getTracks().forEach(Ne=>Ne.stop())}catch{}if(H.current=null,X.current=null,pe)try{await p?.(pe)}catch{}ee.current=""},[p]),Ve=m.useCallback(async J=>{const pe=await u?.(J),Ne=String(pe?.whipUrl||"").trim(),ht=String(pe?.token||"").trim();if(!Ne||!ht)throw new Error("WHIP endpoint unavailable");const Oe=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}});H.current=Oe;const rt=Oe.getAudioTracks()?.[0];if(X.current=rt||null,rt&&(rt.enabled=!!(M||T)),rt?.applyConstraints)try{await rt.applyConstraints({channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1})}catch{}const ot=new RTCPeerConnection(mw);$.current=ot,ot.onconnectionstatechange=()=>{if(!G.current)return;const Lt=ot.connectionState;if(Lt==="connected"){R("live");return}(Lt==="failed"||Lt==="disconnected"||Lt==="closed")&&(R("error"),D(`WHIP transport ${Lt}.`))},Oe.getAudioTracks().forEach(Lt=>{const ul=ot.addTrack(Lt,Oe);vw(ul)});const gt=await ot.createOffer({offerToReceiveAudio:!1,offerToReceiveVideo:!1});await ot.setLocalDescription(gt),await xw(ot,1800);const kt=await fetch(Ne,{method:"POST",headers:{"Content-Type":"application/sdp",...pw(ht)},body:ot.localDescription?.sdp||gt.sdp});if(!kt.ok)throw new Error(`WHIP request failed: ${kt.status}`);const us=await kt.text();await ot.setRemoteDescription({type:"answer",sdp:us}),await gw(ot,1e4),await bw(ot,6e3),await f?.(J)},[M,T,f,u]),mt=m.useCallback(async()=>{if(se.current=!1,q.current){try{q.current.disconnect()}catch{}q.current.onaudioprocess=null}if(U.current)try{U.current.disconnect()}catch{}if(L.current)try{L.current.disconnect()}catch{}if(oe.current)try{oe.current.getTracks().forEach(J=>J.stop())}catch{}if(ue.current)try{await ue.current.close()}catch{}Z.current=[],q.current=null,U.current=null,L.current=null,oe.current=null,ue.current=null,ce.current=ss},[]),ie=m.useCallback(async()=>{if(oe.current&&ue.current&&q.current)return;O(rt=>rt==="recording"?rt:"arming");const J=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}}),pe=new AudioContext({latencyHint:"interactive"}),Ne=pe.createMediaStreamSource(J),ht=pe.createScriptProcessor(1024,1,1),Oe=pe.createGain();Oe.gain.value=0,ht.onaudioprocess=rt=>{if(!se.current)return;const ot=rt.inputBuffer.getChannelData(0);Z.current.push(new Float32Array(ot))},Ne.connect(ht),ht.connect(Oe),Oe.connect(pe.destination),oe.current=J,ue.current=pe,U.current=Ne,q.current=ht,L.current=Oe,ce.current=pe.sampleRate||ss},[]),he=m.useCallback(async({send:J})=>{const pe=se.current;if(se.current=!1,!pe){J||O("idle");return}const Ne=Z.current;if(Z.current=[],!J){O("idle");return}if(!v){O("idle");return}if(!Ne.length){O("idle");return}O("sending");try{const ht=yw(Ne),Oe=jw(ht,ce.current||ss),rt=jx(Oe);await l?.({roverId:v,name:`ptt-${Date.now()}.wav`,mime:"audio/wav",dataBase64:rt}),O("idle")}catch(ht){O("error"),D(ht?.message||"Failed to send PTT clip.")}},[l,v]),le=m.useCallback(async()=>{if(!v){D("Take control of your rover first.");return}await ie(),Z.current=[],se.current=!0,O("recording")},[ie,v]);return m.useEffect(()=>{let J=!1;async function pe(){if(A){await nt(ee.current||v);return}if(!v){await nt(ee.current);return}if(!(G.current&&ee.current===v)&&!(!M&&!T))try{R("starting"),D(""),G.current=!0,ee.current=v,await Ve(v),J||R("live")}catch(Ne){J||(R("error"),D(Ne?.message||"Failed to start mic forwarding.")),await nt(v)}}return pe(),()=>{J=!0}},[A,M,T,v,Ve,nt]),m.useEffect(()=>{const J=X.current;J&&(J.enabled=!!(!A&&(M||T)))},[A,M,T]),m.useEffect(()=>{let J=!1;async function pe(){if(!A||!v){se.current&&await he({send:!1}),O("idle");return}try{await ie(),!J&&!se.current&&O("idle")}catch(Ne){J||(O("error"),D(Ne?.message||"Microphone access failed for clip mode."))}}return pe(),()=>{J=!0}},[A,ie,he,v]),m.useEffect(()=>{let J=!1;async function pe(){if(A){if(!v){se.current&&await he({send:!1});return}if(T){if(!se.current)try{D(""),await le()}catch(Ne){J||(O("error"),D(Ne?.message||"Failed to start clip recording."))}}else se.current&&await he({send:!0})}}return pe(),()=>{J=!0}},[A,he,T,v,le]),m.useEffect(()=>()=>{nt(ee.current||v),mt()},[v,nt,mt]),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(Ax,{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 ${A?"":"bg-emerald-500 text-white hover:bg-emerald-500"}`,onClick:()=>Le("live"),children:"Live Mic (WHIP)"}),r.jsx("button",{type:"button",className:`button-dark w-full text-sm ${A?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,onClick:()=>Le("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(vn,{label:"Mode",active:A,detail:A?"record clip":"live mic"}),r.jsx(vn,{label:"PTT hold",active:T,detail:T?"held":"released"}),r.jsx(vn,{label:"Recording",active:be,detail:be?"capturing":"idle"}),r.jsx(vn,{label:"Playback",active:A&&ae,detail:A&&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:`${Ai} text-center`,type:"file",accept:".mp3,.wav,.ogg,audio/mpeg,audio/wav,audio/ogg",disabled:k||!v,onChange:J=>S(J.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:k||!v,onClick:De,children:k?"Working...":"Play Upload"}),r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:k||!v,onClick:Ee,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:M,disabled:!v||A,onChange:J=>g(pe=>({...pe||{},openMicEnabled:!!J.target.checked}))}),r.jsx("span",{children:A?"Open mic (live mode only)":"Open mic"})]}),r.jsxs("div",{className:"grid gap-0.5 content-start",children:[r.jsx(vn,{label:"WHIP link",active:de,detail:N}),r.jsx(vn,{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(Ax,{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(vn,{label:"Forward pipe",active:ne,detail:ne?"connected":"offline"}),r.jsx(vn,{label:"Upload playback",active:ae,detail:ae?"playing":"idle"}),r.jsx(vn,{label:"Mic relay",active:me,detail:me?"active":"idle"}),r.jsx(vn,{label:"WHIP transport",active:de,detail:N}),r.jsx(vn,{label:"Clip recording",active:be,detail:be?"recording":"idle"}),r.jsx(vn,{label:"Clip sending",active:ve,detail:ve?"sending":"idle"})]}),K?r.jsx("div",{className:"text-xs text-slate-400 text-center",children:K}):null]})})]})})}function Aw({pendingRequestId:n,currentStoredKey:s,nickname:l,requestVerification:o,applyIdentityKey:u,onMessage:f,fullWidth:p=!1}){const[h,x]=m.useState(0),[g,v]=m.useState(""),[y,S]=m.useState(!1),[k,C]=m.useState(!1),M=()=>{x(1),v(s),S(!1),f?.("")},w=()=>{x(0),S(!1)},A=async R=>{if(R.preventDefault(),!y){f?.("Please confirm your nickname agreement before sending.");return}if(h<3){f?.("Complete all request steps before sending.");return}C(!0),f?.("");try{const E=await u(g);await o?.(),v(E),x(0),S(!1),f?.("Verification request sent to lockdown admins.")}catch(E){f?.(E.message||"Failed to submit request.")}finally{C(!1)}},N=p?"w-full":Bo;return n?r.jsx("section",{className:`surface text-sm text-slate-300 ${N}`,children:r.jsxs("div",{className:pi,children:["Verification request pending: ",n]})}):h===0?r.jsx("section",{className:`surface ${N}`,children:r.jsxs("div",{className:pi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Verification"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:M,disabled:k,children:"Request Verification"})]})}):r.jsx("form",{className:`surface ${N}`,onSubmit:A,children:r.jsxs("div",{className:pi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Request verification"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Step ",h," of 3"]}),h===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(Do,{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:R=>S(R.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,h===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:Ai,type:"password",name:"identity_key_request",autoComplete:"current-password",maxLength:35,value:g,onChange:R=>v(R.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,h===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:Ai,type:"password",name:"identity_key_request_final",autoComplete:"current-password",maxLength:35,value:g,onChange:R=>v(R.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:k||!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[u,f]=m.useState(0),[p,h]=m.useState(""),[x,g]=m.useState(!1),v=()=>{f(1),h(""),l?.("")},y=()=>{f(0),h("")},S=async C=>{if(C.preventDefault(),!(u<2)){g(!0),l?.("");try{await s(p),f(0),h(""),l?.("Identity key restored.")}catch(M){l?.(M.message||"Failed to restore key.")}finally{g(!1)}}},k=o?"w-full":Bo;return r.jsx("section",{className:`surface ${k}`,children:r.jsxs("div",{className:pi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Identity key"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Current: ",fw(n)||"not set yet"]}),r.jsx("input",{className:Ai,type:"password",name:"identity_key_current",autoComplete:"current-password",maxLength:35,value:n,readOnly:!0,placeholder:"Identity key"}),u===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,u===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:()=>f(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:y,children:"Cancel"})]})]}):null,u===2?r.jsxs("form",{className:"space-y-0.5",onSubmit:S,children:[r.jsx("input",{className:Ai,type:"password",name:"identity_key_restore",autoComplete:"current-password",maxLength:35,value:p,onChange:C=>h(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||!p,children:"Confirm Restore"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>f(1),children:"Back"})]})]}):null]})})}function Cw({requestableRovers:n=[],pendingRequests:s=[],requestPrivateRoverAccess:l,onMessage:o,fullWidth:u=!1}){const[f,p]=m.useState({}),h=m.useMemo(()=>{const v=new Map;return(s||[]).forEach(y=>{y?.roverId&&v.set(String(y.roverId),y)}),v},[s]),x=u?"w-full":Bo,g=async v=>{if(v){p(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{p(y=>({...y,[v]:!1}))}}};return r.jsx("section",{className:`surface text-sm text-slate-300 ${x}`,children:r.jsxs("div",{className:pi,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=!!f[y],k=h.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})]}),k?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 mo(n){return String(n||"").trim()}function Ew(n){const s=mo(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":"bg-slate-700 text-slate-100"}function eo({label:n,value:s,tone:l="muted",valueClass:o="",hideLabel:u=!1}){return r.jsxs("div",{className:`rounded-md px-1 py-0.75 text-center ${Ig(l)}`,children:[u?null: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(n=[]){return n.filter(u=>u&&u.valid&&Number.isFinite(u.angleDeg)&&Number.isFinite(u.distanceMm)).map(u=>{const f=(Number(u.angleDeg)-90)*Math.PI/180,h=Math.max(0,Math.min(1,Number(u.distanceMm)/4e3))*92,x=110+Math.cos(f)*h,g=110+Math.sin(f)*h;return`${x},${g}`}).join(" ")}function Mw({neato:n,lidar:s,onStart:l,onSendHome:o,onLocate:u,onClearErrors:f,onPowerCycle:p,fullWidth:h=!1}){const[x,g]=m.useState(""),v=h?"w-full":"w-full max-w-xl",y=!!n?.configured,S=!!(n?.enabled&&n?.connected),k=!!n?.telemetry?.extPowerPresent,C=!!n?.telemetry?.chargingActive,M=Ew(n?.telemetry?.uiState),w=mo(n?.telemetry?.robotState)||"--",A=n?.telemetry?.batteryPercent,N=Number.isFinite(A)?`${A}%`:"--",R=n?.telemetry?.batteryVoltage,E=Number.isFinite(R)?`${R.toFixed(2)} V`:"--",O=mo(n?.telemetry?.robotError)||"--",K=mo(n?.telemetry?.robotAlert)||"--",D=Array.isArray(s?.points)?s.points:[],H=kw(D),X=n?.controls||{},$=!!X?.start?.available,G=!!X?.sendHome?.available,ee=!!X?.locate?.available,oe=!!X?.clearErrors?.available,ue=!!X?.powerCycle?.available,U=y&&S&&$,q=y&&S&&G,L=y&&S&&ee,Z=y&&S&&oe,se=y&&S&&ue,ce=async(me,re)=>{if(re){g(me);try{await re()}catch{}finally{g("")}}},T=y?S?"Online":"Offline":"Not configured",V=y?S?"good":"danger":"warn",ne=A==null?"muted":A>=60?"good":A>=25?"warn":"danger",ae=k?"Docked":M!=="--"?M:"Away from dock";return r.jsx("section",{className:`surface text-sm text-slate-200 ${v}`,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. Be nice to him."})]}),r.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${Ig(V)}`,children:T})]}),r.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-[minmax(0,0.95fr)_minmax(0,1.05fr)] gap-0.5",children:[r.jsxs("div",{className:"surface-muted grid gap-0.5",children:[r.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Controls"}),r.jsx("button",{type:"button",disabled:!U||!!x,onClick:()=>ce("start",l),className:"rounded-md border border-sky-300 bg-emerald-600 px-1 py-1 text-base font-semibold text-white transition hover:border-sky-500 hover:bg-emerald-500 disabled:opacity-50",children:x==="start"?"Starting...":"Start cleaning"}),r.jsx("button",{type:"button",disabled:!q||!!x,onClick:()=>ce("sendHome",o),className:"rounded-md border border-sky-300 bg-sky-600 px-1 py-1 text-base font-semibold text-white transition hover:border-sky-500 hover:bg-sky-500 disabled:opacity-50",children:x==="sendHome"?"Sending...":"Send to dock"}),r.jsxs("div",{className:"grid grid-cols-3 gap-0.5",children:[r.jsx("button",{type:"button",disabled:!L||!!x,onClick:()=>ce("locate",u),className:"w-full rounded-md border border-sky-300 bg-fuchsia-600 px-1 py-0.5 text-xs font-semibold text-white transition hover:border-sky-500 hover:bg-fuchsia-500 disabled:opacity-50",children:x==="locate"?"Playing...":"Play sound"}),r.jsx("button",{type:"button",disabled:!Z||!!x,onClick:()=>ce("clearErrors",f),className:"w-full rounded-md border border-sky-300 bg-amber-500 px-1 py-0.5 text-xs font-semibold text-slate-900 transition hover:border-sky-500 hover:bg-amber-400 disabled:opacity-50",children:x==="clearErrors"?"Clearing...":"Clear errors"}),r.jsx("button",{type:"button",disabled:!se||!!x,onClick:()=>ce("powerCycle",p),className:"w-full rounded-md border border-rose-300 bg-rose-600 px-1 py-0.5 text-xs font-semibold text-white transition hover:border-rose-500 hover:bg-rose-500 disabled:opacity-50",children:x==="powerCycle"?"Cycling...":"Power cycle"})]}),r.jsxs("div",{className:"surface-muted grid gap-0.5 pt-0.25",children:[r.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Power status"}),r.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[r.jsx(eo,{label:"Battery",value:N,tone:ne}),r.jsx(eo,{label:"Voltage",value:E,tone:"muted"}),r.jsx(eo,{label:"Docked",value:k?"Docked":"Not docked",tone:k?"good":"muted",hideLabel:!0}),r.jsx(eo,{label:"Charging",value:C?"charging":"not charging",tone:C?"good":"muted",hideLabel:!0})]})]})]}),r.jsx("div",{className:"grid gap-0.5",children:r.jsxs("div",{className:"surface-muted grid gap-0.5",children:[r.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Robot Status"}),r.jsxs("div",{className:"grid grid-cols-1 xl:grid-cols-[minmax(0,1fr)_minmax(13rem,15rem)] gap-0.5 items-start",children:[r.jsxs("div",{className:"grid gap-0.5",children:[r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot state (raw)"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:w})]}),r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Basic state"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:ae})]}),r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"UI state"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:M})]}),r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot error"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:O})]}),r.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[r.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot alert"}),r.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:K})]})]}),r.jsxs("div",{className:"rounded-md border border-emerald-900 bg-black p-0.5",children:[r.jsx("div",{className:"mb-0.25 text-center text-[0.72rem] uppercase tracking-[0.18em] text-emerald-400",children:"Lidar"}),r.jsx("div",{className:"aspect-square rounded-md border border-emerald-950 bg-[radial-gradient(circle_at_center,rgba(34,197,94,0.14),rgba(0,0,0,0.96)_68%)] p-0.25",children:H?r.jsxs("svg",{viewBox:"0 0 220 220",className:"h-full w-full",children:[r.jsx("circle",{cx:"110",cy:"110",r:"92",fill:"none",stroke:"#14532d",strokeWidth:"1.2"}),r.jsx("circle",{cx:"110",cy:"110",r:"61",fill:"none",stroke:"#166534",strokeWidth:"1"}),r.jsx("circle",{cx:"110",cy:"110",r:"31",fill:"none",stroke:"#15803d",strokeWidth:"0.9"}),r.jsx("line",{x1:"110",y1:"18",x2:"110",y2:"202",stroke:"#14532d",strokeWidth:"1"}),r.jsx("line",{x1:"18",y1:"110",x2:"202",y2:"110",stroke:"#14532d",strokeWidth:"1"}),r.jsx("line",{x1:"45",y1:"45",x2:"175",y2:"175",stroke:"#0f3d22",strokeWidth:"0.8"}),r.jsx("line",{x1:"175",y1:"45",x2:"45",y2:"175",stroke:"#0f3d22",strokeWidth:"0.8"}),r.jsx("circle",{cx:"110",cy:"110",r:"4",fill:"#86efac"}),r.jsx("polyline",{points:H,fill:"none",stroke:"#22c55e",strokeWidth:"1.4",strokeLinejoin:"round",strokeLinecap:"round"})]}):r.jsx("div",{className:"flex h-full items-center justify-center text-center text-xs text-emerald-500/80",children:"Waiting for scan"})})]})]})]})})]}),!y||!S||!$||!G||!ee||!oe||!ue?r.jsx("p",{className:"text-xs text-slate-400 text-center",children:y?S?"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 Rw(n){return n==="good"?"bg-emerald-600 text-white":n==="warn"?"bg-amber-500 text-slate-900":n==="danger"?"bg-rose-600 text-white":"bg-slate-700 text-slate-100"}function qw(n){return n==="up"?"Up":n==="down"?"Down":n==="stopped"?"Transitioning...":n==="conflict"?"Conflict":"--"}function Tw({lift:n,onUp:s,onDown:l,fullWidth:o=!1}){const[u,f]=m.useState(""),[p,h]=m.useState(()=>Date.now()),x=o?"w-full":"w-full max-w-xl",g=!!n?.configured,v=!!(n?.enabled&&n?.connected),y=!!n?.busy,S=String(n?.target||"").toLowerCase(),k=String(n?.position||"").toLowerCase(),C=!!n?.availability?.upSwitch,M=!!n?.availability?.downSwitch,w=Number(n?.lastActionAt||0),A=Math.max(0,Number(n?.commandCooldownMs||0)),N=Math.max(0,w+A-p),R=!y&&N>0,E=y||R;m.useEffect(()=>{if(!E)return;const $=setInterval(()=>{h(Date.now())},100);return()=>clearInterval($)},[E]),m.useEffect(()=>{h(Date.now())},[w,A,y]);const O=g?v?E?"Busy":"Ready":"Offline":"Not configured",K=g?v?E?"warn":"good":"danger":"warn",D=g&&v&&!E&&!u&&C&&M,H=m.useMemo(()=>Math.ceil(N/1e3),[N]),X=async($,G)=>{if(G){f($);try{await G()}catch{}finally{f("")}}};return r.jsxs("section",{className:`surface relative text-sm text-slate-200 ${x}`,children:[E?r.jsx("div",{className:"absolute inset-0 z-20 flex items-center justify-center rounded-md bg-slate-950/80 px-1.5 text-center",children:r.jsxs("div",{className:"space-y-0.25",children:[r.jsx("p",{className:"text-sm font-semibold text-slate-100",children:y?"Motion in progress":"Motion cooldown active"}),r.jsx("p",{className:"text-xs text-slate-300",children:"Controls are disabled while the lift is moving, otherwise it's tiny brain would get confused."}),!y&&R?r.jsxs("p",{className:"text-xs text-slate-400",children:["About ",H,"s remaining."]}):null]})}):null,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:"Lift Controls"}),r.jsx("p",{className:"text-xs text-slate-400",children:"Move the lift up and down. Please don't break anything..."})]}),r.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${Rw(K)}`,children:O})]}),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:"rounded-md bg-slate-800 px-1 py-0.75 text-center",children:[r.jsx("div",{className:"text-xs text-slate-300",children:"Position"}),r.jsx("div",{className:"text-base font-semibold text-slate-100",children:qw(k)})]}),r.jsx("button",{type:"button",disabled:!D,onClick:()=>X("down",l),className:`button-dark w-full text-sm disabled:opacity-50 ${k==="down"||S==="down"?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,children:u==="down"||S==="down"?"Lowering...":"Down"}),r.jsx("button",{type:"button",disabled:!D,onClick:()=>X("up",s),className:`button-dark w-full text-sm disabled:opacity-50 ${k==="up"||S==="up"?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,children:u==="up"||S==="up"?"Raising...":"Up"})]})}),!g||!v||!C||!M?r.jsx("p",{className:"text-xs text-slate-400 text-center",children:g?v?"Waiting for required lift switch entities in Home Assistant.":"Home Assistant is offline.":"Set homeAssistant.lift.upSwitch and homeAssistant.lift.downSwitch in server config."}):null,n?.lastError?r.jsxs("p",{className:"text-xs text-rose-300 text-center",children:["Last error: ",n.lastError]}):null]})]})}function Jg(){const{session:n,neatoLidar:s,identifySession:l,requestVerification:o,requestPrivateRoverAccess:u,playUploadedAudio:f,stopUploadedAudio:p,startMicWhip:h,readyMicWhip:x,stopMicWhip:g,neatoStart:v,neatoSendHome:y,neatoLocate:S,neatoClearErrors:k,neatoPowerCycle:C,liftUp:M,liftDown:w}=nn(),{value:A,save:N}=Ge("identity",{cookieUserId:""}),{value:R}=Ge("profile",{nickname:""}),E=m.useMemo(()=>(A?.cookieUserId||"").trim(),[A?.cookieUserId]),O=(R?.nickname||"").trim(),K=!!n?.isVerified,D=n?.verification?.pendingRequestId||null,H=n?.privateRoverAccess?.requestableRovers||[],X=n?.privateRoverAccess?.pendingRequests||[],$=String(n?.assignment?.roverId||"").trim(),[G,ee]=m.useState(""),oe=async ue=>{const U=String(ue||"").trim().toLowerCase();if(!U)throw new Error("Identity key required.");if(!dw.test(U))throw new Error("Identity key must match format: cu_ + 32 lowercase hex chars.");return N(q=>({...q||{},cookieUserId:U})),await l({cookieUserId:U,nickname:O}),U};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:[K?null:r.jsx("div",{className:"lg:col-span-2",children:r.jsx(Aw,{pendingRequestId:D,currentStoredKey:E,nickname:O,requestVerification:o,applyIdentityKey:oe,onMessage:ee,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:K?r.jsxs("div",{className:"space-y-2",children:[r.jsx(Mw,{neato:n?.neato||null,lidar:s,onStart:v,onSendHome:y,onLocate:S,onClearErrors:k,onPowerCycle:C,fullWidth:!0}),r.jsx(Tw,{lift:n?.lift||null,onUp:M,onDown:w,fullWidth:!0}),r.jsx(Nw,{ownRoverId:$,audioForwardByRover:n?.audioForward||{},playUploadedAudio:f,stopUploadedAudio:p,startMicWhip:h,readyMicWhip:x,stopMicWhip:g})]}):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:H,pendingRequests:X,requestPrivateRoverAccess:u,onMessage:ee,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(ww,{currentStoredKey:E,applyIdentityKey:oe,onMessage:ee,fullWidth:!0})})]}),G?r.jsx("div",{className:Bo,children:r.jsx("p",{className:"text-xs text-slate-400 text-center",children:G})}):null]})}const Dw=420,_w=1200,Bw={1:262,2:330,3:392,4:523};function No(){const{session:n}=nn(),s=tn(),{value:l}=Ge("audio",st),o=Number.isFinite(l?.masterVolume)?l.masterVolume:st.masterVolume,u=Number.isFinite(l?.alertVolume)?l.alertVolume:st.alertVolume,f=Math.max(0,Math.min(1,o*u)),p=m.useMemo(()=>{const M=Array.isArray(n?.buttonBox?.buttons)?n.buttonBox.buttons:[];return M.length===4?M:[1,2,3,4].map(w=>M.find(A=>Number(A?.id)===w)||{id:w,count:0,goal:0,rewardName:null,rewardId:null,rewardNumber:null,lastRewardAt:null})},[n?.buttonBox?.buttons]),[h,x]=m.useState({}),[g,v]=m.useState({}),y=m.useRef(new Map),S=m.useRef(new Map),k=m.useRef({}),C=m.useRef(null);return m.useEffect(()=>{const M={};p.forEach(A=>{M[A.id]=Number(A.lastRewardAt||0)});const w=k.current||{};p.forEach(A=>{const N=Number(A.id),R=M[N]||0,E=Number(w[N]||0);if(R>0&&R!==E){v(D=>({...D,[N]:!0}));const O=S.current.get(N);O&&clearTimeout(O);const K=setTimeout(()=>{v(D=>({...D,[N]:!1})),S.current.delete(N)},_w);S.current.set(N,K)}}),k.current=M},[p]),m.useEffect(()=>{function M(A){const N=Bw[A];if(!N||f<=0)return;let R=C.current;if(!R){const D=window.AudioContext||window.webkitAudioContext;if(!D)return;R=new D,C.current=R}const E=R.createOscillator(),O=R.createGain();E.type="square",E.frequency.value=N;const K=.14*f;O.gain.setValueAtTime(1e-4,R.currentTime),O.gain.exponentialRampToValueAtTime(Math.max(1e-4,K),R.currentTime+.01),O.gain.exponentialRampToValueAtTime(1e-4,R.currentTime+.2),E.connect(O),O.connect(R.destination),E.start(),E.stop(R.currentTime+.21)}function w(A={}){const N=Number(A.buttonId);if(!Number.isFinite(N)||N<1||N>4)return;x(O=>({...O,[N]:!0}));const R=y.current.get(N);R&&clearTimeout(R);const E=setTimeout(()=>{x(O=>({...O,[N]:!1})),y.current.delete(N)},Dw);y.current.set(N,E),M(N)}return s.on("buttonBox:increment",w),()=>{s.off("buttonBox:increment",w)}},[f,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:p.map(M=>{const w=Number(M.id),A=Number.isFinite(M.count)?M.count:0,N=Number.isFinite(M.goal)?M.goal:0,R=typeof M.rewardName=="string"&&M.rewardName.trim()?M.rewardName.trim():"Unassigned",E=Number.isFinite(M.rewardNumber)?M.rewardNumber:"?",O=!!h[w],K=!!g[w];return r.jsx(xg,{buttonId:w,count:A,goal:N,rewardNumber:E,rewardName:R,className:[O?"bg-cyan-900/45":"",K?"bg-fuchsia-900/45":""].filter(Boolean).join(" ")},w)})})]})}function Ow(){const{state:{roverId:n}}=_t(),l=cl(n)?.sensors||{};return r.jsx("section",{className:"panel-section",children:r.jsx("div",{className:"aspect-square w-full",children:r.jsx(Hd,{sensors:l})})})}function Lw(){const{state:{roverId:n,keymap:s,camera:l,horn:o},pipeline:u,actions:{setServoAngle:f,setNightVision:p,startHorn:h,stopHorn:x}}=_t(),g=qg(n),v=g.docked&&!g.driving,y=l?.config,S=!!(n&&l?.enabled&&y),k=!!(n&&u?.nightVision),C=u?.nightVisionState,M=!!(n&&u?.horn),w=o?.overheated,A=typeof y?.minAngle=="number"?y.minAngle:-30,N=typeof y?.maxAngle=="number"?y.maxAngle:30,R=typeof l?.angle=="number"?l.angle:typeof y?.homeAngle=="number"?y.homeAngle:(A+N)/2,E=Cn(s?.nightVisionToggle?.[0]),O=Cn(s?.hornHonk?.[0]),K=Cn(s?.cameraUp?.[0]),D=Cn(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:[k&&r.jsx(Dg,{nightVisionOn:C?.nightVisionOn,disabled:!n,onToggle:p,keyLabel:E}),M&&r.jsx(_g,{disabled:!n||w,onStart:h,onStop:x,keyLabel:O,active:o?.active,heat:o?.heat}),S&&r.jsx(Bg,{value:R,min:A,max:N,onChange:f,keyDownLabel:D,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 zw({layout:n,onOpenHelpOverlay:s}){const l=it(k=>k.session),{state:o}=_t(),{value:u}=Ge("vipAudio",{openMicEnabled:!1,pttMode:"live"}),f=l?.isVerified?"bg-emerald-400":"bg-red-600",p=String(l?.assignment?.roverId||"").trim(),h=p?l?.audioForward?.[p]:null,x=!!o?.mic?.pttActive,g=!!u?.openMicEnabled,v=u?.pttMode==="clip"?"clip":"live",y=!!(p&&l?.isVerified&&(v==="clip"?x:g||x)),S=!!(p&&l?.isVerified&&v==="clip"&&h?.source==="upload"&&h?.state==="playing");return r.jsx("section",{className:"panel text-base",children:r.jsxs(yf,{defaultTab:"telemetry",children:[r.jsxs(Sf,{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 ${f}`,"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(jf,{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(Ow,{}),r.jsx(Lw,{})]}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.9fr)_minmax(0,0.75fr)]",children:[r.jsx(_o,{}),r.jsx(nf,{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(To,{fillHeight:!0}),r.jsxs("div",{className:"grid min-h-0 gap-0.5 grid-rows-[minmax(0,1fr)_auto]",children:[r.jsx(jo,{compact:!0,hideNicknameForm:!0,fillHeight:!0}),r.jsx(aw,{compact:!0})]})]}),r.jsx(Hg,{}),r.jsx(No,{}),r.jsx(df,{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 Uw=new Set(["admin","lockdown","lockdown-admin"]),Hw=new Set(["lockdown","lockdown-admin"]),Vw=new Set(["admin","lockdown"]);function $w(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 Gw(){const n=it(S=>S.session),s=n?.mode,l=n?.role,o=n?.adminReason?.text||"";n?.adminReason?.updatedAt;const u=n?.timezone||"UTC",f=n?.socials?.find(S=>String(S?.id||S?.label||"").toLowerCase()==="discord")?.url||n?.discord?.invite||null,p=Vw.has(s),h=s==="lockdown"?Hw.has(l):Uw.has(l),[x,g]=m.useState(()=>new Date),v=m.useMemo(()=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:u,hour:"numeric",minute:"2-digit",second:"2-digit"}).format(x)}catch{return x.toLocaleTimeString()}},[x,u]);if(m.useEffect(()=>{const S=setInterval(()=>g(new Date),1e3);return()=>clearInterval(S)},[]),!p||h)return null;const y=$w(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(hf,{id:"discord",label:"Join our Discord server for updates!",url:f})}),"You can still use the chat while the server is locked:",r.jsxs("div",{className:"max-h-80 overflow-y-auto",children:[r.jsx(To,{}),r.jsx(Do,{})]})]})})}const Yw="/assets/turn_alert-DVO8EZJa.mp3";function Fw(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 Xw(){const n=it(v=>v.session),{pushAlert:s}=kn(),{value:l}=Ge("audio",st),o=Number.isFinite(l?.masterVolume)?l.masterVolume:st.masterVolume,u=Number.isFinite(l?.alertVolume)?l.alertVolume:st.alertVolume,f=Math.max(0,Math.min(1,o*u)),p=Fw(Yw,f),h=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||h.current.has(y)||(v.push(y),h.current.add(y))}),Object.keys(x).forEach(y=>{(!x[y]||x[y].current!==g)&&h.current.delete(y)}),v.length!==0&&(v.forEach(y=>{const S=n?.roster?.find(k=>String(k.id)===String(y))?.name||y;s({title:"Your turn!",message:`You now control ${S}.`,color:"#ff5722"})}),p())},[x,p,s,n?.roster,g]),null}function Qw({visible:n,mode:s,onEnterFullscreen:l,onDismiss:o}){if(!n)return null;const u=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"}),u?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:u?"Got it":"Not now"}),!u&&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 Kw({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",Zw=new Set(["mobile-portrait","mobile-landscape"]),Wg=()=>{if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}},Iw=()=>{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{}},Jw=()=>{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 Pw(n){const s=Zw.has(n),[l,o]=m.useState(!1),[u,f]=m.useState("native"),[p,h]=m.useState(!1),x=m.useMemo(()=>Jw(),[]),g=m.useMemo(()=>Cx(),[]),v=m.useCallback(()=>{if(!s){o(!1),h(!1);return}if(!p&&Iw()){o(!1);return}if(x){f("pwa-hint"),o(!0);return}if(!Cx()){o(!1);return}if(typeof document<"u"&&document.fullscreenElement){o(!1);return}f("native"),o(!0)},[p,x,s]);m.useEffect(()=>{v()},[v]),m.useEffect(()=>{if(typeof document>"u")return;const C=()=>{if(document.fullscreenElement){h(!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(),h(!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 M=C.requestFullscreen||C.webkitRequestFullscreen||C.mozRequestFullScreen||C.msRequestFullscreen;if(!M)return!1;try{const w=M.call(C);return w&&typeof w.then=="function"&&await w,wx(),h(!1),o(!1),!0}catch(w){return console.warn("Failed to enter fullscreen",w),!1}},[x,s]),k=m.useCallback(()=>{s&&(h(!0),f(x?"pwa-hint":"native"),o(!0))},[x,s]);return m.useEffect(()=>{s||(h(!1),o(!1))},[s]),{visible:l,mode:u,isIOS:x,nativeSupported:g,enterFullscreen:S,dismiss:y,showPrompt:k}}function Ww({visible:n,layout:s,onClose:l,showOnLoad:o,onToggleShowOnLoad:u}){if(!n)return null;const{state:f}=_t(),p=h=>{const x=!h.target.checked;u?.(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:p,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:f?.keymap||{}})})]})})}const e2=`aroma bagel batter beans diff --git a/server/public/index.html b/server/public/index.html index 58410109..6fd56c4d 100644 --- a/server/public/index.html +++ b/server/public/index.html @@ -11,8 +11,8 @@ Multi Roomba Rover - - + +
diff --git a/server/src/services/neatoService/lidarRuntime.js b/server/src/services/neatoService/lidarRuntime.js index c4fa789a..cf40d81c 100644 --- a/server/src/services/neatoService/lidarRuntime.js +++ b/server/src/services/neatoService/lidarRuntime.js @@ -1,8 +1,8 @@ const { spawn } = require('child_process'); const EventEmitter = require('events'); -const POLL_INTERVAL_MS = 10000; -const SCAN_TIMEOUT_MS = 6000; +const POLL_INTERVAL_MS = 1000; +const SCAN_TIMEOUT_MS = 2000; const RECONNECT_DELAY_MS = 5000; function parsePayloadLine(line) { diff --git a/webui/src/components/vip/VipNeatoCard.jsx b/webui/src/components/vip/VipNeatoCard.jsx index 74b9e286..f4f5f8e0 100644 --- a/webui/src/components/vip/VipNeatoCard.jsx +++ b/webui/src/components/vip/VipNeatoCard.jsx @@ -132,7 +132,7 @@ export default function VipNeatoCard({ -
+

Controls

-
-

Robot Status

-
-
Robot state (raw)
-
{robotStateRaw}
-
-
-
Basic state
-
{primaryState}
-
-
-
UI state
-
{uiStateLabel}
-
-
-
Robot error
-
{robotError}
-
-
-
Robot alert
-
{robotAlert}
-
-
-
+
+
+

Robot Status

+
+
+
+
Robot state (raw)
+
{robotStateRaw}
+
+
+
Basic state
+
{primaryState}
+
+
+
UI state
+
{uiStateLabel}
+
+
+
Robot error
+
{robotError}
+
+
+
Robot alert
+
{robotAlert}
+
+
-
-

Lidar

-
- {lidarDots ? ( - - - - - - - - - - ) : ( -
Waiting for lidar scan...
- )} +
+
+ Lidar +
+
+ {lidarDots ? ( + + + + + + + + + + + + ) : ( +
+ Waiting for scan +
+ )} +
+
+
+