From b76c5010b4a23029b9b8daefca3a12de65b5b84b Mon Sep 17 00:00:00 2001 From: legop3 Date: Sat, 18 Apr 2026 19:23:27 -0400 Subject: [PATCH] upped the spams --- server/public/assets/index-BTc7ve5w.css | 1 - .../{index-Dpm2R3OA.js => index-BaS9tmKz.js} | 2 +- server/public/assets/index-DTYY_hd_.css | 1 + server/public/index.html | 4 ++-- server/src/rewards/definitions/chatSpam.js | 2 +- .../src/rewards/definitions/ghostTypingSpam.js | 4 ++-- server/src/rewards/definitions/modeJam.js | 2 +- server/src/rewards/definitions/rogueEventSpam.js | 2 +- webui/src/components/ButtonBoxPanel.jsx | 16 ++++++++-------- 9 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 server/public/assets/index-BTc7ve5w.css rename server/public/assets/{index-Dpm2R3OA.js => index-BaS9tmKz.js} (97%) create mode 100644 server/public/assets/index-DTYY_hd_.css diff --git a/server/public/assets/index-BTc7ve5w.css b/server/public/assets/index-BTc7ve5w.css deleted file mode 100644 index 6b204b64..00000000 --- a/server/public/assets/index-BTc7ve5w.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-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.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-\[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-\[12rem\]{width:12rem}.w-\[20rem\]{width:20rem}.w-\[2px\]{width:2px}.w-\[9rem\]{width:9rem}.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-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-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-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * 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}.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-cyan-200\/50{border-color:#a5f3fc80}.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-800{--tw-border-opacity: 1;border-color:rgb(159 18 57 / var(--tw-border-opacity))}.border-sky-400\/50{border-color:#38bdf880}.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-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\/70{background-color:#164e63b3}.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\/70{background-color:#701a75b3}.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-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\/90{background-color:#020617e6}.bg-transparent{background-color:transparent}.bg-white\/10{background-color:#ffffff1a}.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-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-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-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-cyan-400\/70{--tw-ring-color: rgb(34 211 238 / .7)}.ring-emerald-300\/70{--tw-ring-color: rgb(110 231 183 / .7)}.ring-fuchsia-400\/80{--tw-ring-color: rgb(232 121 249 / .8)}.ring-white\/10{--tw-ring-color: rgb(255 255 255 / .1)}.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}.duration-200{transition-duration:.2s}@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\: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-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-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-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\: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}}@media(min-width:768px){.md\:h-full{height:100%}.md\:h-screen{height:100vh}.md\:min-h-0{min-height:0px}.md\:min-h-\[18rem\]{min-height:18rem}.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\.1fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.1fr) 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-Dpm2R3OA.js b/server/public/assets/index-BaS9tmKz.js similarity index 97% rename from server/public/assets/index-Dpm2R3OA.js rename to server/public/assets/index-BaS9tmKz.js index f66cf69e..2e9e3a10 100644 --- a/server/public/assets/index-Dpm2R3OA.js +++ b/server/public/assets/index-BaS9tmKz.js @@ -15,7 +15,7 @@ Please change the parent to i&&i>o){const f=yi/100,d=1-f;if(n<=o)return 0;if(n<=i){const h=(n-o)/(i-o);return Math.round(Math.max(0,Math.min(1,h))*yi)}if(n>=s)return 100;const p=(n-i)/(s-i);return Math.round((f+Math.max(0,Math.min(1,p))*d)*100)}return null}const _j=1600,Oj=800;function vn(...n){return n.filter(Boolean).join(" ")}function Rf({visual:n,orientation:s="horizontal",variant:i="inline",compact:o=!1,showLabel:f,className:d=""}){const p=i==="background",h=s==="vertical",x=f??!p;if(!n?.available){if(p){const te=yi,fe=vn("absolute z-10",h?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",R&&!A&&"battery-tick-warn"),ce=h?{bottom:`${te}%`}:{left:`${te}%`},Y=vn("absolute inset-0 pointer-events-none",d);return r.jsxs("div",{className:Y,children:[r.jsx("div",{className:"absolute inset-0 bg-slate-900/35"}),r.jsx("div",{className:fe,style:ce})]})}return h?null:r.jsx("p",{className:"text-xs text-slate-500",children:"Battery telemetry unavailable"})}const g=n.percentDisplay??0,y=Math.max(0,Math.min(100,g)),b=n.warnDisplayPercent??yi,A=!!n.urgentActive,R=!!n.warnActive,E=A?`${Oj}ms`:R?`${_j}ms`:void 0,j=p?A||R?"bg-red-500/45":"bg-emerald-500/45":A||R?"bg-red-500":"bg-emerald-500",N=A||R?"bg-red-900/35":"bg-slate-900/35",C=A||R?"bg-red-900/45":"bg-slate-900/35",w=vn(p?"absolute inset-0 pointer-events-none":"relative pointer-events-auto",h&&!p?"flex flex-col items-center justify-center":"w-full",d);if(p){const te=h?{height:`${y}%`}:{width:`${y}%`},fe=vn("absolute",h?"bottom-0 left-0 right-0":"left-0 top-0 bottom-0",j,"transition-[width,height]",A&&"battery-urgent-flash"),ce=vn("absolute z-10",h?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",R&&!A&&"battery-tick-warn"),Y=h?{bottom:`${b}%`}:{left:`${b}%`};return r.jsxs("div",{className:w,children:[r.jsx("div",{className:vn("absolute inset-0",N,A&&"battery-urgent-flash")}),r.jsx("div",{className:fe,style:{...te,animationDuration:E}}),r.jsx("div",{className:ce,style:Y})]})}const M=vn("relative overflow-hidden rounded-sm border border-slate-800",A||R?C:"bg-zinc-900/90",A&&"battery-urgent-flash",h?"w-full flex-1":o?"h-4":"h-5"),B=h?{height:`${y}%`}:{width:`${y}%`},H=vn("absolute",h?"bottom-0 left-0 right-0":"left-0 top-0 bottom-0",j,"transition-[width,height]",A&&"battery-urgent-flash"),_=vn("absolute z-10",h?"left-0 right-0 h-[2px]":"top-0 bottom-0 w-[2px]","bg-black/70",R&&!A&&"battery-tick-warn"),K=h?{bottom:`${b}%`}:{left:`${b}%`},L=`Battery ${g}%`,U=vn("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"),F=vn("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:w,children:[r.jsxs("div",{className:M,children:[r.jsx("div",{className:H,style:{...B,animationDuration:E}}),r.jsx("div",{className:_,style:K})]}),x&&!h?r.jsx("div",{className:U,children:r.jsx("span",{className:F,children:L})}):null,x&&h?r.jsx("div",{className:"mt-0.5 text-[0.65rem] font-semibold text-slate-100",children:r.jsxs("span",{className:F,children:[g,"%"]})}):null]})}const X0=2e3,Bj=3e3,Lj=3e3,zj=40,Uj=1e3;function bi({sessionInfo:n,audioSessionInfo:s,videoMode:i="whep",snapshotFeed:o=null,qualityNotice:f=null,label:d,roverColor:p=null,forceMute:h=!1,telemetryFrame:x,batteryConfig:g,layoutFormat:y="desktop",hudVariant:b="default",driverLabel:A=null,hudForceMap:R=!1,hudMapPosition:E="top-center",hudLabelScale:k=1,fitParent:j=!1,overcurrentLimiter:N=null,showTurnCue:C=!1,turnTimerText:w=null,turnSeconds:M=null,isActiveDriver:B=!1,idleSkipSeconds:H=null}){const{session:_}=Le(),K=m.useRef(null),L=m.useRef(null),U=m.useRef(null),F=m.useRef(null),te=m.useRef(null),fe=m.useRef(null),ce=m.useRef(null),Y=m.useRef(null),[T,X]=m.useState("idle"),[J,se]=m.useState(null),[de,q]=m.useState("idle"),[V,P]=m.useState(null),[ne,pe]=m.useState(0),[ie,oe]=m.useState(0),[ve,ye]=m.useState(!0),xe=!!s?.url,Ue=i==="snapshot",$e=x?.sensors,{value:Ne}=Fe("audio",St),ae=Number.isFinite(Ne?.masterVolume)?Ne.masterVolume:St.masterVolume,ue=Number.isFinite(Ne?.roverVolume)?Ne.roverVolume:St.roverVolume,be=typeof Ne?.mainBrushDuckEnabled=="boolean"?Ne.mainBrushDuckEnabled:typeof Ne?.autoLevelEnabled=="boolean"?Ne.autoLevelEnabled:St.mainBrushDuckEnabled,Me=Number.isFinite(Ne?.mainBrushDuckAmount)?Math.max(0,Math.min(1,Ne.mainBrushDuckAmount)):St.mainBrushDuckAmount,le=Math.max(0,Math.min(1,ae*ue)),re=$e?.batteryChargeMah??null,me=y==="desktop",we=!me,et=we?"top-right":E,[dt]=Ag(),ze=R||we?!0:dt,xt=jg({charge:re,config:g}),mt=$e?.wheelOvercurrents||null,Tn=mt==null?[]:Object.entries(mt).filter(([,Ae])=>!!Ae).map(([Ae])=>Ae),kt=N?.caps||null,cs=N?.overcurrent?.groups||null,Gt=typeof window<"u"&&new URLSearchParams(window.location.search).has("debugAudio"),Oa=typeof window<"u"&&new URLSearchParams(window.location.search).has("debugHud"),Co=m.useMemo(()=>{if(!kt)return null;const Ae=Number.isFinite(kt?.drive?.cap)?kt.drive.cap:1,Ke=Number.isFinite(kt?.aux?.cap)?kt.aux.cap:1;return Math.max(0,Math.min(1,1-Math.min(Ae,Ke)))},[kt]),Dn=!!N?.isActive,jt=Tn.length?Tn:Dn?["limiter"]:[],Yt=Co??(Tn.length?1:0),Mt=!!jt.length,ca=!!((Number($e?.mainBrushCurrentMa)||0)>zj||$e?.wheelOvercurrents?.mainBrush),Eo=be&&ca?1-Me:1,us=Math.max(0,Math.min(1,le*Eo)),fs=be&&ca&&Me>0?`Volume decreased ${Math.round(Me*1e3)/10}%`:null,Ba=m.useRef({hasDedicatedAudio:!1,audioUrl:null,mainBrushDuckEnabled:!1,mainBrushDuckAmount:0,mainBrushActive:!1,baseRoverGain:0,effectiveRoverGain:0});m.useEffect(()=>{Ba.current={hasDedicatedAudio:xe,audioUrl:s?.url||null,mainBrushDuckEnabled:be,mainBrushDuckAmount:Me,mainBrushActive:ca,baseRoverGain:le,effectiveRoverGain:us}},[xe,s?.url,be,Me,ca,le,us]);const tt=m.useCallback((Ae,Ke={})=>{if(!Gt)return;const Pe=L.current,qe=Ba.current,Ye={event:Ae,ts:Date.now(),roverLabel:d||null,hasDedicatedAudio:qe.hasDedicatedAudio,audioUrl:qe.audioUrl,mainBrushDuckEnabled:qe.mainBrushDuckEnabled,mainBrushDuckAmount:qe.mainBrushDuckAmount,mainBrushActive:qe.mainBrushActive,baseRoverGain:qe.baseRoverGain,effectiveRoverGain:qe.effectiveRoverGain,element:Pe?{muted:Pe.muted,volume:Pe.volume,paused:Pe.paused,ended:Pe.ended,readyState:Pe.readyState,networkState:Pe.networkState}:null,...Ke};try{console.log(`[AudioDebug] ${Ae} ${JSON.stringify(Ye)}`)}catch{console.log("[AudioDebug]",Ae,Ye)}},[Gt,d]),_n=_?.socials?.find(Ae=>String(Ae?.id||Ae?.label||"").toLowerCase()==="discord")?.url||_?.discord?.invite||null;m.useEffect(()=>{Oa&&console.log("[OvercurrentHUD]",{overlayVisible:Mt,overlayMotors:jt,overlayFill:Yt,limiterActive:Dn,limiterCaps:kt,limiterGroups:cs,wheelOvercurrents:mt})},[Oa,Yt,jt,Mt,Dn,kt,cs,mt]),m.useEffect(()=>{tt("settings/update")},[tt]);const jn=m.useCallback(()=>{clearTimeout(U.current),U.current=setTimeout(()=>pe(Date.now()),X0)},[]),On=m.useCallback(()=>{clearTimeout(F.current),F.current=setTimeout(()=>oe(Date.now()),X0)},[]),ds=m.useCallback(async()=>{const Ae=K.current;if(Ae)try{Ae.muted=!0,await Ae.play()}catch{}},[]),ul=m.useCallback((Ae=0)=>{if(h||xe)return;clearTimeout(fe.current);const Ke=()=>{clearTimeout(fe.current),fe.current=setTimeout(()=>{h||Pe()},Bj)},Pe=async()=>{const qe=K.current;if(qe)try{await ds(),qe.muted=!1,await qe.play(),ye(!1)}catch{qe.muted=!0,ye(!0),Ke()}};fe.current=setTimeout(Pe,Ae)},[ds,h,xe]);m.useEffect(()=>()=>{clearTimeout(U.current),clearTimeout(F.current),clearTimeout(fe.current),clearInterval(te.current),ce.current&&(cancelAnimationFrame(ce.current),ce.current=null)},[]),m.useEffect(()=>{T==="playing"&&ul(0)},[T,ul]),m.useEffect(()=>{Ue&&(X("snapshot"),se(null))},[Ue]),m.useEffect(()=>{if(Ue||!n?.url||!K.current)return;let Ae=!0,Ke;const Pe=setTimeout(()=>ye(!0),0),qe=(Ye,it)=>{Ae&&(tt("video/status",{nextStatus:Ye,info:it||null}),X(Ye),se(it||null),Ye==="playing"&&ds(),["error","failed","disconnected","closed"].includes(Ye)&&jn())};return Ke=new Y0({url:n.url,token:n.token,video:K.current,receiveAudio:!xe,onStatus:qe}),Ke.start().catch(Ye=>{Ae&&(X("error"),se(Ye.message),jn())}),()=>{Ae=!1,clearTimeout(Pe),Ke?.stop()}},[Ue,n?.url,n?.token,ne,jn,ds,xe,tt]),m.useEffect(()=>{T==="stopped"&&n?.url&&jn()},[T,n?.url,jn]),m.useEffect(()=>{const Ae=L.current;if(!Ae||!s?.url){tt("route/no-audio-url"),Y.current=null;return}const Ke=Math.max(0,Math.min(1,us)),Pe=Y.current==null?Math.max(0,Math.min(1,Ae.volume)):Y.current;if(ce.current&&(cancelAnimationFrame(ce.current),ce.current=null),Ke>Pe){const qe=performance.now(),Ye=Pe,it=Ke-Ye,rt=Nt=>{const st=Math.min(1,(Nt-qe)/Uj),Bn=Ye+it*st;Ae.volume=Bn,Y.current=Bn,st<1?ce.current=requestAnimationFrame(rt):ce.current=null};ce.current=requestAnimationFrame(rt)}else Ae.volume=Ke,Y.current=Ke;tt("route/direct",{elementVolume:Ke,duckEnabled:be,mainBrushActive:ca,duckAmount:Me})},[s?.url,us,be,ca,Me,tt]),m.useEffect(()=>{if(!s?.url||!L.current)return;let Ae=!0,Ke;const Pe=(qe,Ye)=>{Ae&&(tt("audio/status",{nextStatus:qe,info:Ye||null}),P(Ye||(qe==="connected"?"connected":null)),q(it=>qe==="connected"&&(it==="playing"||it==="connecting")||qe==="new"?it:qe),["error","failed"].includes(qe)&&On())};return Ke=new Y0({url:s.url,token:s.token,video:L.current,audioOnly:!0,onStatus:Pe}),Ke.start().catch(qe=>{Ae&&(q("error"),P(qe.message),On())}),()=>{Ae=!1,Ke?.stop()}},[s?.url,s?.token,ie,On,tt]),m.useEffect(()=>{const Ae=L.current;if(!s?.url||!Ae){clearInterval(te.current);return}if(!["connecting","connected","playing","paused"].includes(de)){clearInterval(te.current);return}const Pe=async()=>{const qe=L.current;qe&&(qe.muted=!1,!(!qe.paused&&!qe.ended)&&(tt("retry/play-attempt"),qe.play().then(()=>{tt("retry/play-ok"),q(Ye=>Ye==="connected"?"playing":Ye),P(Ye=>Ye==="paused"?null:Ye)}).catch(Ye=>{tt("retry/play-fail",{error:Ye?.message}),P(it=>it||Ye?.message||"autoplay blocked")})))};return Pe(),te.current=setInterval(Pe,Lj),()=>clearInterval(te.current)},[s?.url,de,tt]),m.useEffect(()=>{const Ae=L.current;if(!Ae)return;const Ke=()=>{tt("element/play"),q(st=>st==="error"?st:"playing"),P(null)},Pe=()=>{tt("element/pause"),q(st=>["error","failed","disconnected","closed","stopped"].includes(st)?st:"paused"),P(st=>st||"paused")},qe=()=>{tt("element/ended"),q(st=>st==="error"?st:"stopped"),P(st=>st||"ended")},Ye=()=>{const{error:st}=Ae,Bn=st?.message||"audio error";tt("element/error",{error:Bn}),q("error"),P(Bn)},it=()=>tt("element/waiting"),rt=()=>tt("element/canplay"),Nt=()=>tt("element/stalled");return Ae.addEventListener("play",Ke),Ae.addEventListener("pause",Pe),Ae.addEventListener("ended",qe),Ae.addEventListener("error",Ye),Ae.addEventListener("waiting",it),Ae.addEventListener("canplay",rt),Ae.addEventListener("stalled",Nt),()=>{Ae.removeEventListener("play",Ke),Ae.removeEventListener("pause",Pe),Ae.removeEventListener("ended",qe),Ae.removeEventListener("error",Ye),Ae.removeEventListener("waiting",it),Ae.removeEventListener("canplay",rt),Ae.removeEventListener("stalled",Nt)}},[s?.url,tt]);const fl=o?.error?`Error: ${o.error}`:o?.objectUrl?"snapshot":o?.status||"waiting",La=Ue?fl:n?.url?T==="error"?`Error: ${J||"unknown"}`:J?`${T} (${J})`:T:"waiting",ko=s?.error?`Error: ${s.error}`:s?.url?de==="error"?`Error: ${V||"unknown"}`:V?`${de} (${V})`:de:null,dl=b==="spectator",en=b==="none";return r.jsxs("div",{className:`flex flex-col gap-0.5 ${j?"h-full":""}`,children:[r.jsxs("div",{className:`relative w-full overflow-hidden bg-black ${j?"h-full flex-1":"aspect-[4/3]"}`,children:[Ue?o?.objectUrl?r.jsx("img",{src:o.objectUrl,alt:d,className:"h-full w-full object-contain",draggable:!1}):r.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-300",children:"Waiting for frame…"}):r.jsx("video",{ref:K,muted:h||ve||xe,playsInline:!0,autoPlay:!0,controls:!1,className:"h-full w-full object-contain"}),r.jsx("audio",{ref:L,autoPlay:!0,hidden:!0}),!en&&C?r.jsx($j,{mobileHud:we,turnSeconds:M,isActiveDriver:B,idleSkipSeconds:H}):null,en?null:r.jsx(Vj,{frame:x,sensors:$e,label:d,roverColor:p,status:La,audioStatus:ko,levelStatus:fs,desktopLayout:me,layoutFormat:y,variant:b,driverLabel:A,battery:xt,showTopDown:ze,mobileHud:we,mapPosition:et,turnTimerText:w,labelScale:k}),en?null:r.jsx(Xj,{compact:we}),!en&&Oa?r.jsx("div",{className:"pointer-events-none absolute left-1 top-1 z-40 rounded bg-black/80 px-1 py-0.5 text-[0.6rem] text-lime-200",children:`OC vis:${Mt?1:0} motors:${jt.length} fill:${Math.round(Yt*100)}%`}):null,en?null:r.jsx(Yj,{motors:jt,fill:Yt,compact:we}),en?null:r.jsx(Fj,{battery:xt,compact:we}),!en&&dl&&xt.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(Rf,{visual:xt,orientation:"vertical",variant:"inline",compact:we,className:"h-full w-4"})}):null,!en&&f?r.jsx("div",{className:"pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2",children:r.jsxs("div",{className:`mx-auto w-fit rounded border border-amber-300/80 bg-black/75 text-amber-200 ${we?"px-2 py-1 text-[0.6rem]":"px-3 py-1.5 text-sm"}`,children:[r.jsx("div",{className:"text-center",children:f}),r.jsx("div",{className:"pointer-events-auto mt-0",children:r.jsx(sd,{id:"discord",label:"Join our Discord server while you wait!",url:_n})})]})}):null]}),!en&&!dl&&r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(Hj,{sensors:$e}),r.jsx("div",{className:"panel-section space-y-0.5 text-sm",children:r.jsx(Rf,{visual:xt,compact:we})})]})]})}function Hj({sensors:n}){const s=[n?.lightBumpLeftSignal,n?.lightBumpFrontLeftSignal,n?.lightBumpCenterLeftSignal,n?.lightBumpCenterRightSignal,n?.lightBumpFrontRightSignal,n?.lightBumpRightSignal],i=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)/i)),.35),f=h=>h==null||h<=0?"hsl(200 60% 18%)":`hsl(${(200+o(h)*360)%360} 100% 60%)`,d=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),y=xDate.now());m.useEffect(()=>{const se=setInterval(()=>C(Date.now()),150);return()=>clearInterval(se)},[]),n?.receivedAt&&N-n.receivedAt<200;const w=R,M=x==="mobile-portrait",B=w?"text-[0.45rem]":"text-[0.65rem]",H=w?"px-0.25 py-0.25":"px-1 py-0.5",_=w?"px-0.25 py-0.25":"px-0.5 py-0.5",K=w?"text-[0.55rem]":"text-[0.8rem]",L=w?"left-0.5 top-0.5":"left-1 top-1",U=w?"text-[0.5rem]":"text-[0.7rem]",F=w?"px-0.5 py-0.25":"px-1 py-0.5",te=w?"left-0.5 top-1/2":"left-1 top-1/2",fe="bottom-0.5",ce={transform:`translateX(-50%) scale(${j})`,transformOrigin:"center bottom"},Y="240px",T=M?.3:w?.33:.7,J={width:Y,height:Y,opacity:w?.6:.7,transform:E==="top-center"?`translateX(-50%) scale(${T})`:`scale(${T})`,transformOrigin:E==="bottom-left"?"bottom left":E==="top-center"?"top center":"top right",...E==="bottom-left"?{left:"0.25rem",bottom:"0.25rem"}:E==="top-center"?{left:"50%",top:"0.25rem"}:{right:"0.25rem",top:"0.25rem"}};if(g==="none")return null;if(g==="spectator"){const se=[["Voltage",s?.voltageMv!=null?`${(s.voltageMv/1e3).toFixed(2)} V`:"--"],["Current",s?.currentMa!=null?`${s.currentMa} mA`:"--"],["Charge",s?.batteryChargeMah!=null?`${s.batteryChargeMah}`:"--"],["OI",s?.oiMode?.label||"--"]],de=!!s?.chargingSources?.homeBase,q=s?.chargingState?.label||"",V=!!(q&&q.toLowerCase()!=="not charging"),P=s?.oiMode?.label||"Unknown",ne=P.toLowerCase(),pe=ne==="full"?"bg-emerald-500/80 text-emerald-50":ne==="safe"?"bg-amber-400/80 text-amber-950":ne==="passive"?"bg-slate-700/80 text-slate-100":"bg-slate-700/60 text-slate-200",ie=de?"bg-emerald-500/80 text-emerald-50":"bg-slate-700/70 text-slate-200",oe=V?"bg-emerald-500/80 text-emerald-50":de?"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 ${L} font-medium text-slate-100 ${B}`,children:r.jsxs("div",{className:"flex flex-col gap-0.5 leading-none",children:[r.jsxs("span",{children:["Status: ",f]}),d?r.jsxs("span",{children:["Audio: ",d]}):null,p?r.jsx("span",{className:"text-cyan-300",children:p}):null]})}),r.jsx("div",{className:`absolute ${te} flex -translate-y-1/2 flex-col gap-0.5 bg-black/70 text-slate-100 ${B} ${H}`,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 ${ie}`,children:de?"Docked":"Undocked"}),r.jsx("span",{className:`rounded px-1.5 py-0.5 ${oe}`,children:V?"Charging":"Not charging"}),r.jsxs("span",{className:`rounded px-1.5 py-0.5 ${pe}`,children:["OI: ",P]})]}),se.map(([ve,ye])=>r.jsxs("span",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{className:"text-slate-400",children:ve}),r.jsx("span",{className:"font-semibold text-white",children:ye})]},ve))]})}),r.jsx("div",{className:`absolute ${fe} left-1/2`,style:ce,children:r.jsxs("div",{className:`flex items-center gap-0.5 bg-black/80 text-slate-100 ${_} ${K}`,children:[r.jsx("span",{className:"font-semibold text-white rounded px-1 py-[1px] border border-transparent",style:ra(o,.18),children:i||"Unnamed Rover"}),y?r.jsxs("span",{className:"text-slate-300",children:["• ",y]}):null]})})]}),A?r.jsx("div",{className:"pointer-events-none absolute rounded",style:{...J},children:r.jsx(qf,{sensors:s,size:240,overlay:!0})}):null]})}return r.jsxs("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:[r.jsx("div",{className:`absolute ${L} font-medium text-slate-100 ${B}`,children:r.jsxs("div",{className:"flex flex-col gap-0.5 leading-none",children:[r.jsxs("span",{children:["Status: ",f]}),d?r.jsxs("span",{children:["Audio: ",d]}):null,p?r.jsx("span",{className:"text-cyan-300",children:p}):null]})}),k?r.jsx("div",{className:`absolute left-1/2 top-0.5 -translate-x-1/2 rounded bg-black/70 text-slate-100 ${F} ${U}`,children:k}):null,r.jsx("div",{className:`absolute ${fe} left-1/2`,style:ce,children:r.jsx("div",{className:`flex gap-0.5 bg-black/80 text-slate-100 ${_} ${K}`,children:r.jsxs("span",{children:["Rover:"," ",r.jsxs("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ra(o,.18),children:['"',i||"Unnamed Rover",'"']})]})})}),A&&g!=="spectator"?r.jsx("div",{className:"pointer-events-none absolute rounded",style:{...J},children:r.jsx(qf,{sensors:s,size:240,overlay:!0})}):null]})}function $j({mobileHud:n=!1,turnSeconds:s=null,isActiveDriver:i=!1,idleSkipSeconds:o=null}){const f=n?"text-3xl":"text-5xl",d=n?"text-xs":"text-sm",p=n?"text-[0.55rem]":"text-[0.75rem]",h=n?"px-4 py-3":"px-6 py-4",x=i&&typeof o=="number";return r.jsx("div",{className:"pointer-events-none absolute inset-0 z-30 flex items-center justify-center bg-black/55",children:r.jsxs("div",{className:`flex flex-col items-center gap-0.5 rounded border border-amber-300/80 bg-black/70 ${h}`,children:[r.jsx("div",{className:`font-semibold text-amber-200 ${f}`,children:"IT IS YOUR TURN!"}),r.jsx("div",{className:`text-amber-200/80 ${d}`,children:"Start driving!"}),x?r.jsxs("div",{className:`text-red-100/90 ${p}`,children:["Idle skip in ",o,"s"]}):null]})})}const Gj={leftWheel:"Left wheel",rightWheel:"Right wheel",mainBrush:"Main brush",sideBrush:"Side brush",limiter:"Overcurrent limit"};function Yj({motors:n,fill:s=0,compact:i=!1}){if(!n?.length)return null;const o=n.map(y=>Gj[y]||y),f=i?"w-[12rem] h-[3.5rem]":"w-[20rem] h-[7rem]",d=i?"px-2 py-1":"px-4 py-2",p=i?"text-lg":"text-4xl",h=i?"text-xs":"text-xl",x=Math.max(0,Math.min(1,s)),g=`${Math.round(x*100)}%`;return r.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-red-900/50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 ${f}`,children:r.jsxs("div",{className:"relative h-full w-full",children:[r.jsx("div",{className:"absolute inset-0 overflow-hidden",children:r.jsx("div",{className:"h-full bg-red-700/60",style:{width:g}})}),r.jsxs("div",{className:`relative z-10 flex h-full w-full flex-col items-center justify-center text-center font-semibold text-white animate-pulse ${p} ${d}`,children:[r.jsx("div",{children:"OVERCURRENT"}),r.jsx("div",{className:`mt-0 font-medium text-white ${h}`,children:o.join(", ")})]})]})})}function Fj({battery:n,compact:s=!1}){if(!n?.available||!n.warnActive&&!n.urgentActive)return null;const i=n.urgentActive?"BATTERY VERY LOW, DOCK THE ROVER AND CHARGE IMMEDIATELY!!":"Battery low! please dock and charge the rover soon.",o=s?"p-2 top-6":"p-4 top-10",f=s?"text-sm":"text-2xl";return r.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-amber-900/60 left-1/2 -translate-x-1/2 ${o}`,children:r.jsx("div",{className:`text-center font-semibold text-white animate-pulse ${f}`,children:r.jsx("div",{children:i})})})}function Xj({compact:n=!1}){const{session:s}=Le(),{sendMessage:i,onInputFocus:o,onInputBlur:f,blurChat:d,registerInputRef:p,setTypingActive:h}=Jf(),{value:x}=Fe("tts",{engine:"flite",voice:"rms",pitch:50}),[g,y]=m.useState(""),[b,A]=m.useState(!1),R=s?.role!=="spectator",E=s?.role==="spectator",k=s?.assignment?.roverId||null,N=!!m.useMemo(()=>s?.roster?.find(_=>String(_.id)===String(k))||null,[k,s?.roster])?.audio?.ttsEnabled,C=m.useMemo(()=>{if(!N)return null;const _=x?.engine==="espeak"?"espeak":"flite";if(_==="espeak"){let L=Number.isFinite(x?.pitch)?Math.round(x.pitch):void 0;return typeof L=="number"&&(L=Math.max(0,Math.min(99,L))),{speak:!0,engine:_,pitch:L}}const K=typeof x?.voice=="string"?x.voice:void 0;return{speak:!0,engine:_,voice:K}},[x?.engine,x?.pitch,x?.voice,N]),w=n?"pointer-events-auto absolute bottom-0.5 right-0.5 flex w-[9rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.4 py-0.2":"pointer-events-auto absolute bottom-1 right-1 flex w-[12rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.5 py-0.25",M=n?"min-w-0 flex-1 bg-transparent text-[0.55rem] text-slate-100 placeholder:text-slate-400 focus:outline-none":"min-w-0 flex-1 bg-transparent text-[0.7rem] text-slate-100 placeholder:text-slate-400 focus:outline-none",B=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 H(_){if(_.preventDefault(),!R)return;const K=g.trim();if(K){A(!0);try{await i(K,C),y(""),d(),h(!1)}catch(L){alert(L.message)}finally{A(!1)}}}return E?null:r.jsxs("form",{onSubmit:H,className:w,children:[r.jsx("input",{className:M,value:g,onChange:_=>{const K=_.target.value;y(K),h(!!K.trim())},onFocus:_=>{o(_),h(!!g.trim())},onBlur:_=>{f(_),h(!1)},onKeyDown:_=>{_.key==="Enter"&&!g.trim()&&(_.preventDefault(),d(),h(!1))},ref:_=>p(_,{target:"hud"}),placeholder:R?"Chat (TTS)":"Spectator",disabled:!R}),r.jsx("button",{type:"submit",disabled:!R||b,className:B,children:"Speak"})]})}function ld({layoutFormat:n="desktop"}){const{session:s}=Le(),{state:{song:i,lastControlIntentAt:o},overcurrentLimiter:f}=_t(),[d,p]=m.useState(()=>Date.now()),[h,x]=m.useState(!1),[g,y]=m.useState(null),b=m.useRef({active:!1,roverId:null});m.useEffect(()=>{if(s?.mode!=="turns")return;const ne=setInterval(()=>p(Date.now()),250);return()=>clearInterval(ne)},[s?.mode]);const A=s?.assignment?.roverId,E=!!(A&&s?.roster?s.roster.find(ne=>String(ne.id)===String(A)):null)?.media?.audioPublishUrl,k=A?s?.turnQueues?.[A]:null,j=s?.socketId||null,N=A?s?.activeDrivers?.[A]:null,C=!!(j&&N===j),w=m.useMemo(()=>{const ne=k?.queue||[];if(!ne.length||!k?.current||ne.length<=1)return null;const pe=ne.findIndex(ie=>ie===k.current);return pe===-1?ne[0]||null:ne[(pe+1)%ne.length]||null},[k?.queue,k?.current]),M=!!(j&&w===j),B=k?.deadline||null,H=k?.idleDeadline||null,_=B?B-d:null,K=H?H-d:null,L=s?.mode==="turns"&&M&&_!=null&&_<=5e3&&_>0,U=s?.mode!=="turns"||C||L,F=_!=null&&Number.isFinite(_)?Math.max(0,Math.ceil(_/1e3)):null,te=K!=null&&Number.isFinite(K)?Math.max(0,Math.ceil(K/1e3)):null,fe=C?F!=null?`${F}s left`:null:M&&F!=null?`Your turn in ${F}s`:null,ce=A?[...U?[{type:"rover",id:A,key:A}]:[],...E?[{type:"rover",id:`${A}-audio`,key:`${A}-audio`}]:[]]:[],Y=vi(ce),T=A&&U?Y[A]:null,X=A&&E?Y[`${A}-audio`]:null,J=nd(A?[A]:[],{enabled:!!A,version:s?.mode}),se=A&&J[A]||null,de=cl(A),q=A&&s?.roster?s.roster.find(ne=>String(ne.id)===String(A)):null,V=q?.battery??null,P=q?.name||(A?`Rover ${A}`:"");return m.useEffect(()=>{if(s?.mode!=="turns"){x(!1),y(null),b.current={active:!1,roverId:null};return}const ne=b.current,pe=C&&!ne.active,ie=C&&A&&A!==ne.roverId;pe||ie?(x(!0),y(Date.now())):!C&&ne.active&&(x(!1),y(null)),b.current={active:C,roverId:A}},[C,A,s?.mode]),m.useEffect(()=>{!h||!g||o>g&&x(!1)},[o,g,h]),r.jsx("section",{className:"panel",children:A?r.jsx(bi,{sessionInfo:T,videoMode:U?"whep":"snapshot",snapshotFeed:se,audioSessionInfo:X,label:P,roverColor:q?.color||null,telemetryFrame:de,batteryConfig:V,layoutFormat:n,overcurrentLimiter:f,songNote:i?.note,qualityNotice:U?null:"Preview feed (low FPS) until your turn.",showTurnCue:h,turnTimerText:fe,turnSeconds:F,isActiveDriver:C,idleSkipSeconds:te}):r.jsxs("div",{className:"panel-muted content-center text-center text-sm text-slate-400 aspect-[4/3]",children:[r.jsx("p",{children:"You are not assigned to a rover."}),r.jsx("p",{className:"mt-0",children:r.jsx("a",{href:"/spectate",className:"text-blue-400 underline hover:text-blue-500",children:"Click here to visit the spectator page."})})]})})}function fo({label:n,tone:s="muted"}){const i=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 ${i}`,children:n})}function bo(n){if(!Number.isFinite(n))return 0;const s=n%360;return s<0?s+360:s}function Qj(n){if(!Array.isArray(n)||n.length<3)return 0;const[s,i,o]=n,f=Math.max(0,Math.min(255,Number(s)))/255,d=Math.max(0,Math.min(255,Number(i)))/255,p=Math.max(0,Math.min(255,Number(o)))/255,h=Math.max(f,d,p),x=Math.min(f,d,p),g=h-x;if(g===0)return 0;let y=0;return h===f?y=(d-p)/g%6:h===d?y=(p-f)/g+2:y=(f-d)/g+4,bo(Math.round(y*60))}function Q0(n){const s=bo(n),i=1,o=1-Math.abs(s/60%2-1);let f=0,d=0,p=0;return s<60?(f=i,d=o):s<120?(f=o,d=i):s<180?(d=i,p=o):s<240?(d=o,p=i):s<300?(f=o,p=i):(f=i,p=o),[Math.round(f*255),Math.round(d*255),Math.round(p*255)]}function K0(n){return n?Array.isArray(n.hsColor)?bo(Number(n.hsColor[0])):Array.isArray(n.rgbColor)?Qj(n.rgbColor):0:0}function Kj({entity:n,connected:s,controlsLocked:i,onToggle:o,onSetColor:f}){const d=n.state==="unavailable"||!n.available,p=n.state==="on",h=n.type==="light"&&n.supportsColor,x=d?"warn":p?"success":"muted",g=d?"Unavailable":p?"On":"Off",y=i||!s||d,b=y||!h,[A,R]=m.useState(()=>K0(n)),E=m.useRef(A),k=m.useRef(!1),j=d?"border-slate-800 bg-slate-900 text-slate-400 cursor-not-allowed":i?"border-slate-800 bg-slate-900 text-slate-300 cursor-not-allowed":p?"border-emerald-700 bg-emerald-900/80 text-emerald-50 hover:bg-emerald-800":"border-rose-800 bg-rose-900/80 text-rose-50 hover:bg-rose-800";m.useEffect(()=>{if(!h||k.current)return;const H=K0(n);E.current=H,R(H)},[n.rgbColor,n.hsColor,h]);const N=H=>{const _=bo(Number(H.target.value));E.current=_,R(_)},C=()=>{b||!f||f(n.id,Q0(E.current))},w=H=>{H.stopPropagation()},B=`rgb(${(h?Q0(E.current):[255,255,255]).join(",")})`;return r.jsxs("button",{type:"button",onClick:()=>o(n.id),disabled:y,className:`relative flex min-w-[12rem] flex-[1_1_12rem] items-start justify-between gap-0.5 rounded px-1 py-0.5 text-left transition-colors ${j} disabled:opacity-60 disabled:hover:bg-inherit`,children:[r.jsxs("div",{className:"min-w-0 flex-1",children:[r.jsxs("div",{className:"flex items-center gap-0.5 text-sm leading-normal",children:[r.jsx("span",{className:"truncate font-semibold text-white",children:n.name||n.id}),h&&r.jsxs(r.Fragment,{children:[r.jsx(fo,{label:g,tone:x}),!s&&r.jsx("span",{className:"text-xs text-amber-200",children:"Offline"})]})]}),h?r.jsx("div",{className:"-mt-0.5 w-full",onClick:w,onPointerDown:H=>{w(H),k.current=!0},onPointerUp:H=>{w(H),k.current=!1,C()},onPointerCancel:H=>{w(H),k.current=!1,C()},onKeyUp:H=>{w(H),C()},onBlur:C,children:r.jsx("div",{className:"relative w-full",children:r.jsx("input",{type:"range",min:"0",max:"360",step:"1",value:A,onChange:N,disabled:b,"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(fo,{label:g,tone:x}),!s&&r.jsx("span",{className:"text-amber-200",children:" · Offline"})]})]}),h&&r.jsx("span",{className:"pointer-events-none absolute right-1 top-1 h-2.5 w-2.5 rounded-full border border-white/60",style:{backgroundColor:B}}),!h&&r.jsx("div",{className:"self-center text-xs font-semibold text-white/90",children:p?"Turn off":"Turn on"})]})}function Ng(){const{state:{keymap:n}}=_t(),{session:s,homeAssistantToggle:i,homeAssistantSetLightColor:o}=Le(),f=s?.homeAssistant,d=m.useMemo(()=>f?.entities||[],[f?.entities]),h=!!(f?.lightPolicy||null)?.lockedOn,x=bn(n?.homeAssistantOn?.[0]),g=bn(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(d.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 y=!!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:d.length}),h?r.jsx(fo,{label:"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"}),x?r.jsx(Z0,{label:x}):null]}),r.jsxs("span",{className:"flex items-center gap-0.5",children:[r.jsx("span",{children:"Off"}),g?r.jsx(Z0,{label:g}):null]})]})]}),r.jsx(fo,{label:y?"Connected":"Offline",tone:y?"success":"warn"})]}),h?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:"Lights are locked on. Room controls are disabled."}):null,r.jsx("div",{className:"flex flex-wrap gap-0.5",children:d.map(b=>r.jsx(Kj,{entity:b,connected:y,controlsLocked:h,onToggle:i,onSetColor:o},b.id))})]})}function Z0({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function wg(){const{login:n,setRole:s}=Le(),[i,o]=m.useState(""),[f,d]=m.useState(""),[p,h]=m.useState(!1);async function x(g){g.preventDefault(),h(!0);try{await n(i,f),o(""),d("")}catch(y){alert(y.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:i,onChange:g=>o(g.target.value)}),r.jsx("input",{className:"field-input",placeholder:"Password",type:"password",value:f,onChange:g=>d(g.target.value)}),r.jsx("button",{type:"submit",disabled:p,className:"button-dark w-full disabled:opacity-50",children:p?"Logging in…":"Login"})]})]})}function I0(...n){return n.filter(Boolean).join(" ")}function Zj(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function Ij(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function Jj({title:n,roster:s=[],emptyText:i="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:i}):r.jsx("ul",{className:"space-y-0.5 text-sm",children:s.map(f=>{const d=!!(f?.private?.enabled&&f?.private?.open),p=!!f?.locked;return r.jsxs("li",{className:I0("surface flex flex-wrap items-center justify-between gap-0.5",p?"bg-red-900/40":d?"bg-amber-700/35 border border-amber-200/30":null),children:[r.jsxs("div",{children:[r.jsx("p",{className:"text-slate-200",children:r.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ra(f.color,.16),children:f.name})}),r.jsxs("p",{className:"text-xs text-slate-500 flex flex-wrap items-center gap-0.5",children:[r.jsx("span",{children:f.locked?"locked":"free"}),f.lockReason&&r.jsx("span",{className:"rounded bg-black/30 px-1",children:f.lockReason}),r.jsxs("span",{className:I0("font-semibold",Ij(f)),children:["Battery ",Zj(f)]})]})]}),o?o(f):null]},f.id)})})]})}const Pj=[{key:"open",label:"Open"},{key:"turns",label:"Turns"},{key:"admin",label:"Admin"},{key:"lockdown",label:"Lockdown"}];function Wj(){const{session:n,lockRover:s,setMode:i,requestControl:o,setCommunityGoal:f,setAdminReason:d,rebootRover:p,rebootServer:h,setAudioLevels:x,setPrivateSafety:g,llmControl:y,adminLogs:b,llmCommentaryState:A}=Le(),R=m.useMemo(()=>n?.roster??[],[n?.roster]),[E,k]=m.useState({}),[j,N]=m.useState({}),[C,w]=m.useState(!1),[M,B]=m.useState(!1),H=n?.health||null,_=n?.communityGoal?.text||"",K=n?.communityGoal?.updatedAt||null,[L,U]=m.useState(_),F=n?.adminReason?.text||"",te=n?.adminReason?.updatedAt||null,[fe,ce]=m.useState(F),Y=n?.audioLevels||{},[T,X]=m.useState({hornGain:Number.isFinite(Y.hornGain)?Y.hornGain:1,ttsGain:Number.isFinite(Y.ttsGain)?Y.ttsGain:1,forwardGain:Number.isFinite(Y.forwardGain)?Y.forwardGain:1}),[J,se]=m.useState({}),de=n?.role==="admin"||n?.role==="lockdown"||n?.role==="lockdown-admin",q=n?.role==="lockdown"||n?.role==="lockdown-admin",V=n?.mode??"open",P=async(le,re)=>{try{await s(le,re),k(me=>({...me,[le]:re}))}catch(me){alert(me.message)}},ne=async le=>{const re=le.target.value;try{await i(re)}catch(me){alert(me.message)}},pe=async le=>{try{await o(le,{force:!0})}catch(re){alert(re.message)}},ie=async le=>{if(!(!le?.id||!window.confirm(`Reboot rover "${le.name||le.id}" now?`))){N(me=>({...me,[le.id]:!0}));try{await p(le.id)}catch(me){alert(me.message)}finally{N(me=>({...me,[le.id]:!1}))}}},oe=async()=>{if(window.confirm("Reboot the server host now? This will disconnect all users.")){w(!0);try{await h()}catch(re){alert(re.message),w(!1)}}},ve=async()=>{if(window.confirm("Clear LLM commentary history now? This resets chat context, bot memory, and rover activity metrics for narration.")){B(!0);try{await y("clearHistory")}catch(re){alert(re.message)}finally{B(!1)}}},ye=async()=>{try{await f(L)}catch(le){alert(le.message)}},xe=async()=>{try{await f(null)}catch(le){alert(le.message)}},Ue=async()=>{try{await d(fe)}catch(le){alert(le.message)}},$e=async()=>{try{await d(null)}catch(le){alert(le.message)}},Ne=le=>re=>{const me=Number(re.target.value);X(we=>({...we||{},[le]:Number.isFinite(me)?me:1}))},ae=async()=>{try{await x(T)}catch(le){alert(le.message)}};m.useEffect(()=>{U(_)},[_]),m.useEffect(()=>{ce(F)},[F]),m.useEffect(()=>{X({hornGain:Number.isFinite(Y.hornGain)?Y.hornGain:1,ttsGain:Number.isFinite(Y.ttsGain)?Y.ttsGain:1,forwardGain:Number.isFinite(Y.forwardGain)?Y.forwardGain:1})},[Y.forwardGain,Y.hornGain,Y.ttsGain]),m.useEffect(()=>{const le={};(R||[]).forEach(re=>{re?.private?.enabled&&(le[re.id]={speedLimitEnabled:!!re?.private?.safety?.speedLimitEnabled,speedLimitMaxWheelSpeed:Number.isFinite(re?.private?.safety?.speedLimitMaxWheelSpeed)?re.private.safety.speedLimitMaxWheelSpeed:250,hardOvercurrentEnabled:!!re?.private?.safety?.hardOvercurrentEnabled,overcurrentStopMs:Number.isFinite(re?.private?.safety?.overcurrentStopMs)?re.private.safety.overcurrentStopMs:300,hardBumpEnabled:!!re?.private?.safety?.hardBumpEnabled,bumpBackoffSpeed:Number.isFinite(re?.private?.safety?.bumpBackoffSpeed)?re.private.safety.bumpBackoffSpeed:250,bumpBackoffMs:Number.isFinite(re?.private?.safety?.bumpBackoffMs)?re.private.safety.bumpBackoffMs:350,cliffEnabled:!!re?.private?.safety?.cliffEnabled,cliffBackoffSpeed:Number.isFinite(re?.private?.safety?.cliffBackoffSpeed)?re.private.safety.cliffBackoffSpeed:250,cliffBackoffMs:Number.isFinite(re?.private?.safety?.cliffBackoffMs)?re.private.safety.cliffBackoffMs:500,triggerCooldownMs:Number.isFinite(re?.private?.safety?.triggerCooldownMs)?re.private.safety.triggerCooldownMs:800})}),se(le)},[R]);const ue=m.useMemo(()=>{const le={};return R.forEach(re=>{le[re.id]=E[re.id]??re.locked}),le},[R,E]),be=(le,re={})=>{se(me=>({...me||{},[le]:{...me?.[le]||{},...re||{}}}))},Me=async le=>{try{const re=J?.[le];if(!re)return;await g(le,re)}catch(re){alert(re.message)}};return de?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:ne,className:"field-input text-sm",children:Pj.map(le=>r.jsx("option",{value:le.key,children:le.label},le.key))})]}),r.jsx("div",{className:"flex gap-0.5 text-xs",children:r.jsx("button",{type:"button",onClick:oe,disabled:C,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:C?"Server rebooting...":"Reboot Server"})}),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:[T.hornGain.toFixed(2),"x"]})]}),r.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:T.hornGain,onChange:Ne("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:[T.ttsGain.toFixed(2),"x"]})]}),r.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:T.ttsGain,onChange:Ne("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:[T.forwardGain.toFixed(2),"x"]})]}),r.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:T.forwardGain,onChange:Ne("forwardGain"),className:"w-full accent-emerald-500"})]}),r.jsx("div",{className:"flex gap-0.5 text-xs",children:r.jsx("button",{type:"button",onClick:ae,className:"button-dark",children:"Apply audio levels"})})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Community goal"}),K?r.jsxs("span",{children:["Updated ",new Date(K).toLocaleString()]}):null]}),r.jsx("input",{type:"text",value:L,onChange:le=>U(le.target.value),placeholder:"Set a community goal",className:"field-input text-sm"}),r.jsxs("div",{className:"flex gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:ye,className:"button-dark",children:"Set goal"}),r.jsx("button",{type:"button",onClick:xe,className:"button-danger",children:"Clear"})]})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[r.jsx("span",{children:"Admin mode reason"}),te?r.jsxs("span",{children:["Updated ",new Date(te).toLocaleString()]}):null]}),r.jsx("textarea",{value:fe,onChange:le=>ce(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:Ue,className:"button-dark",children:"Set reason"}),r.jsx("button",{type:"button",onClick:$e,className:"button-danger",children:"Clear"})]})]}),r.jsx(Jj,{roster:R,renderActions:le=>r.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 text-xs",children:[r.jsx("button",{type:"button",onClick:()=>P(le.id,!ue[le.id]),className:"button-dark",children:ue[le.id]?"Unlock":"Lock"}),r.jsx("button",{type:"button",onClick:()=>pe(le.id),className:"button-dark",children:"Force"}),r.jsx("button",{type:"button",onClick:()=>ie(le),disabled:!!j[le.id],className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:j[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:!!J?.[le.id]?.speedLimitEnabled,disabled:!q,onChange:re=>be(le.id,{speedLimitEnabled:!!re.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:!q,value:J?.[le.id]?.speedLimitMaxWheelSpeed??250,onChange:re=>be(le.id,{speedLimitMaxWheelSpeed:Number(re.target.value)||250})}),r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!!J?.[le.id]?.hardOvercurrentEnabled,disabled:!q,onChange:re=>be(le.id,{hardOvercurrentEnabled:!!re.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:!!J?.[le.id]?.hardBumpEnabled,disabled:!q,onChange:re=>be(le.id,{hardBumpEnabled:!!re.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:!!J?.[le.id]?.cliffEnabled,disabled:!q,onChange:re=>be(le.id,{cliffEnabled:!!re.target.checked})}),r.jsx("span",{children:"Cliff safety"})]}),r.jsx("button",{type:"button",disabled:!q,onClick:()=>Me(le.id),className:"button-dark disabled:opacity-50",children:"Apply Safety"})]}):null]})}),r.jsx(aN,{health:H,roster:R}),r.jsx(eN,{state:A,onClearHistory:ve,clearingHistory:M}),r.jsx(sN,{entries:b})]}):null}function eN({state:n,onClearHistory:s,clearingHistory:i}){const[o,f]=m.useState(null);if(!n)return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("div",{className:"panel-muted text-xs uppercase",children:"LLM Commentary"}),r.jsx("div",{className:"surface text-xs text-slate-300",children:"No status received yet."})]});const d=n.runtime||{},p=n.counters||{},h=n.timings||{},x=n.input||{},g=n.output||{},y=n.errors||{},b=Array.isArray(n.history)?n.history:[],A=b.find(j=>j.runId===o)||(b.length?b[b.length-1]:null),R=tN(n),E=nN(x.modelMessages,g.raw),k=[{label:"running",value:d.running?"yes":"no"},{label:"in flight",value:d.inFlight?"yes":"no"},{label:"phase",value:d.phase||"--"},{label:"run id",value:d.currentRunId??"--"},{label:"tick count",value:d.tickCount??0},{label:"last tick",value:d.lastTickAt?new Date(d.lastTickAt).toLocaleString():"never"},{label:"next run",value:d.nextRunAt?new Date(d.nextRunAt).toLocaleString():"n/a"},{label:"outcome",value:d.outcome||"--"},{label:"reason",value:d.reason||"--"},{label:"skip streak",value: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:!!i,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:i?"Clearing...":"Clear LLM History"})}),r.jsxs("div",{className:`surface border text-center ${R.className}`,children:[r.jsx("div",{className:"text-[1.1rem] font-bold tracking-wide",children:R.label}),r.jsx("div",{className:"text-xs text-slate-200",children:R.detail})]}),r.jsx("div",{className:"surface flex flex-wrap gap-0.5 text-xs",children:k.map(j=>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:[j.label,": ",j.value]},j.label))}),y.message?r.jsxs("div",{className:"surface text-xs text-red-300 break-words",children:["Error: ",y.message]}):null,y.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(y.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:E.length?E.map(j=>r.jsx(Kf,{message:j.message},j.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: ",y.failedAt?new Date(y.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:b.length?b.slice().reverse().map(j=>r.jsxs("button",{type:"button",onClick:()=>f(j.runId),className:`w-full text-left surface ${A?.runId===j.runId?"border border-sky-400/50":""}`,children:[r.jsxs("span",{className:"text-slate-300",children:["#",j.runId]})," ",r.jsx("span",{className:"text-slate-200",children:j.outcome||j.phase||"--"})," ",r.jsx("span",{className:"text-slate-400",children:j.durationMs!=null?`${j.durationMs}ms`:"--"})," ",r.jsx("span",{className:"text-slate-500",children:j.reason||""})]},j.runId)):r.jsx("div",{className:"text-slate-300",children:"No runs recorded yet."})})]}),A?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 #",A.runId," details"]}),r.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(A,null,2)})]}):null]})}function tN(n){const s=n?.runtime||{},i=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:i.posted?`Last: ${i.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 nN(n,s){const i=Date.now(),f=(Array.isArray(n)?n:[]).map((d,p)=>{const h=String(d?.role||"").toLowerCase(),x=typeof d?.content=="string"?d.content:JSON.stringify(d?.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:i+p,nickname:g,text:x,role:"spectator",system:h==="system"}}});if(s!=null){const d=String(s);f.push({id:"llm-output",message:{ts:i+f.length+1,nickname:"LLM Output",text:d.trim()?d:"",role:"spectator",system:!0}})}return f}function aN({health:n,roster:s=[]}){if(!n)return null;const i=n.replay||{sources:[],readyCount:0,totalCount:0},o=n.snapshots||{rovers:[],rooms:[]},f=x=>s.find(g=>String(g.id)===String(x))?.color||null,d=`${i.readyCount}/${i.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:d})]}),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:i.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"?ra(f(x.id),.16):void 0,children:x.label}),r.jsxs("span",{className:x.ready?"text-emerald-300":"text-amber-300",children:[x.recentCount,"/",x.neededCount]})]},`${x.type}:${x.id}`))}),r.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:o.rovers.map(x=>r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ra(f(x.id),.16),children:x.name}),r.jsx("span",{className:x.stale?"text-amber-300":"text-emerald-300",children:x.stale?"stale":"ok"})]},`rover:${x.id}`))}),r.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:o.rooms.map(x=>r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{children:x.name}),r.jsx("span",{className:x.stale?"text-amber-300":"text-emerald-300",children:x.error?"error":x.stale?"stale":"ok"})]},`room:${x.id}`))})]})}function sN({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(i=>r.jsxs("div",{className:"surface",children:[r.jsx("span",{className:"text-amber-400",children:i.ts?new Date(i.ts).toLocaleTimeString():"--"})," ",i.label&&r.jsxs("span",{className:"text-teal-400",children:["[",i.label,"]"]})," ",r.jsx("span",{className:"text-slate-200",children:i.message})," ",i.ip&&r.jsx("span",{className:"text-cyan-300",children:i.ip})," ",i.meta&&r.jsx("span",{className:"text-slate-500",children:JSON.stringify(i.meta)})]},i.id))}),r.jsx("p",{className:"text-xs text-slate-500",children:"Admin-only log stream; IPs never appear in user data."})]})}const lN=[{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 iN(n){return n.reduce((s,i)=>((s[i.group]||(s[i.group]=[])).push(i),s),{})}function rN(n,s){const i=Number(n);return Number.isFinite(i)?Math.max(0,Math.min(500,i)):s}const id=5,Si=500,Ai=1,rd=100;function oN(n,s){const i=Number(n);return Number.isFinite(i)?Math.max(id,Math.min(Si,i)):s}function ao(n,s){const i=Number(n);return Number.isFinite(i)?Math.max(Ai,Math.min(rd,i)):s}function cN(n){const i=(ao(n,n)-Ai)/(rd-Ai),o=Si-i*(Si-id);return Math.round(o)}function uN(n){const s=oN(n,n),i=(Si-s)/(Si-id),o=Ai+i*(rd-Ai);return Math.round(o)}function fN(n){const[s,i]=m.useState(null),o=m.useCallback(p=>{Ju(!0),i(p)},[]),f=m.useCallback(()=>{Ju(!1),i(null)},[]),d=m.useCallback((p,h)=>{if(h.preventDefault(),h.stopPropagation(),h.key==="Escape"){f();return}const x=ki(h.key??"");x&&(n(p,x,h),f())},[f,n]);return m.useEffect(()=>()=>Ju(!1),[]),{active:s,startCapture:o,cancel:f,captureFromEvent:d}}function Xr({label:n,description:s,value:i,onChange:o,min:f=0,max:d=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:f,max:d,value:i,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:f,max:d,step:p,value:i,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:i})]})]})}function dN(){const{state:{keymap:n},actions:{updateKeyBinding:s,resetKeyBindings:i}}=_t(),{value:o,save:f}=Fe("inputs",kn),d={...kn.keyboard,...o.keyboard??{}},p=m.useMemo(()=>typeof d.tiltSpeed=="number"?ao(d.tiltSpeed,kn.keyboard.tiltSpeed):typeof d.tiltIntervalMs=="number"?ao(uN(d.tiltIntervalMs),kn.keyboard.tiltSpeed):kn.keyboard.tiltSpeed,[d.tiltIntervalMs,d.tiltSpeed]),h=m.useMemo(()=>iN(lN),[]),{active:x,startCapture:g,cancel:y,captureFromEvent:b}=fN((k,j)=>{s(k,j)}),A=m.useCallback(k=>n?.[k]?.[0]||di[k]?.[0]||"",[n]),R=m.useCallback((k,j)=>{const N=kn.keyboard,C=rN(j,N[k]);f(w=>({...w??{},keyboard:{...w?.keyboard??N,[k]:C}}))},[f]),E=m.useCallback(k=>{const j=kn.keyboard,N=ao(k,j.tiltSpeed),C=cN(N);f(w=>({...w??{},keyboard:{...w?.keyboard??j,tiltSpeed:N,tiltIntervalMs:C}}))},[f]);return r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Keyboard layout"}),r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Per-browser · click to change a binding"})]}),r.jsx("button",{type:"button",onClick:()=>i(),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(Xr,{label:"Base speed",description:"Normal driving speed",value:d.baseSpeed,onChange:k=>R("baseSpeed",k)}),r.jsx(Xr,{label:"Turbo speed",description:"Used when holding the boost modifier",value:d.turboSpeed,onChange:k=>R("turboSpeed",k)}),r.jsx(Xr,{label:"Precision speed",description:"Used when holding the precision modifier",value:d.precisionSpeed,onChange:k=>R("precisionSpeed",k)})]})]}),r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Camera tilt"}),r.jsx(Xr,{label:"Tilt speed",description:"Higher = faster when holding tilt keys",value:p,onChange:E,min:1,max:100,step:1})]}),r.jsx("div",{className:"space-y-0.5",children:Object.entries(h).map(([k,j])=>r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.75rem] text-slate-400",children:k}),r.jsx("div",{className:"space-y-0.5",children:j.map(N=>{const C=A(N.id),w=x===N.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:N.label}),r.jsx("p",{className:"text-[0.65rem] text-slate-400",children:bn(C)})]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[w&&r.jsx("button",{type:"button",onClick:()=>y(),className:"button-danger text-[0.7rem]",children:"Cancel"}),r.jsx("button",{type:"button",onClick:()=>g(N.id),onKeyDown:w?M=>b(N.id,M):void 0,autoFocus:w,className:`${w?"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:w?"Press a key…":"Change"})]})]},N.id)})})]},k))})]})}const aa=new Intl.NumberFormat(void 0,{maximumFractionDigits:2}),mN=[{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"}],J0=.45,hN=.6;function ci({label:n,description:s,min:i,max:o,step:f,value:d,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:aa.format(d)})]}),s&&r.jsx("p",{className:"text-[0.65rem] text-slate-500",children:s}),r.jsx("input",{type:"range",min:i,max:o,step:f,value:d,onChange:h=>p(Number(h.target.value)),className:"mt-0 w-full accent-emerald-400"})]})}function pN(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} ${aa.format(n.threshold??.6)}`}return"Unassigned"}function xN(n){return n.reduce((s,i)=>((s[i.section]||(s[i.section]=[])).push(i),s),{})}function gN(n,s){if(!n||n.length===0)return null;if(s){const i=n.find(o=>o.signature===s);if(i)return i}return n[0]}function vN(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 yN(n,s,i){const o=(n.axes??[]).map((d,p)=>({index:p,delta:Math.abs((d??0)-(s.axes?.[p]??0)),value:d}));if(o.sort((d,p)=>p.delta-d.delta),i.kind==="axisPair"){const d=o.filter(p=>p.delta>J0).slice(0,2);return d.length<2?null:{kind:"axisPair",x:d[0].index,y:d[1].index,...i.invertDefaults??{}}}const f=o.find(d=>d.delta>J0);return f?{kind:"axis",index:f.index,...i.invertDefaults??{}}:null}function bN(n,s,i){const o=n.buttons??[];for(let d=0;dhN)return i.kind==="axis"?{kind:"buttonAxis",index:d}:{kind:"button",index:d}}const f=n.axes??[];for(let d=0;d.7&&h>.5)return i.kind==="axis"?{kind:"axis",index:d,...i.invertDefaults??{}}:{kind:"axisButton",index:d,direction:p>=0?1:-1,threshold:.6}}return null}function SN(n,s,i){if(!n)return null;if(i.kind==="axis"||i.kind==="axisPair"){const o=yN(n,s,i);if(o)return o}return bN(n,s,i)}function AN(){const n=JA(),{value:s,save:i}=Fe("gamepad",Da),[o,f]=m.useState(null),d=m.useRef(null),p=m.useMemo(()=>xN(mN),[]),h=m.useMemo(()=>gN(n.pads,s.activeSignature),[n.pads,s.activeSignature]),x=h?.signature??null,g=m.useMemo(()=>x?s?.profiles?.[x]??s?.defaults?.profile??sa:s?.defaults?.profile??sa,[x,s?.defaults?.profile,s?.profiles]);m.useEffect(()=>{!h||!x||s?.profiles?.[x]||i(j=>{const N=j??Da;if(N.profiles?.[x])return N;const C=N?.defaults?.profile??sa,w=ug(h,C);return{...N,profiles:{...N.profiles??{},[x]:w}}})},[h,x,s?.profiles,i]),m.useEffect(()=>{d.current=null},[o,x]),m.useEffect(()=>{if(!o||!h)return;if(!d.current){d.current=vN(h);return}const j=SN(h,d.current,o);j&&(i(N=>{const C=N??Da,w=C.profiles?.[x]??C?.defaults?.profile??sa,M={...w,bindings:{...w.bindings??{},[o.id]:{...w.bindings?.[o.id]??{},kind:o.kind,sources:[j]}}};return{...C,profiles:{...C.profiles??{},[x]:M}}}),f(null))},[h,x,o,i]);const y=m.useCallback(j=>{i(N=>({...N??Da,activeSignature:j||null}))},[i]),b=m.useCallback(j=>{i(N=>{const C=N??Da,w=(x&&C.profiles?.[x])??C?.defaults?.profile??sa,M={...w,calibration:{...w.calibration??{},...j}};return x?{...C,profiles:{...C.profiles??{},[x]:M}}:{...C,defaults:{...C.defaults??{},profile:M}}})},[x,i]),A=m.useCallback((j,N)=>{i(C=>{const w=C??Da,M=(x&&w.profiles?.[x])??w?.defaults?.profile??sa,B=N(M.bindings?.[j]??{}),H={...M,bindings:{...M.bindings??{},[j]:B}};return x?{...w,profiles:{...w.profiles??{},[x]:H}}:{...w,defaults:{...w.defaults??{},profile:H}}})},[x,i]),R=m.useCallback(j=>{A(j.id,N=>({...N,sources:[]}))},[A]),E=m.useCallback((j,N)=>{A(j.id,C=>{const w=Array.isArray(C.sources)?[...C.sources]:[];if(!w[0])return C;const M={...w[0]};return N==="invertX"?M.invertX=!M.invertX:N==="invertY"?M.invertY=!M.invertY:M.invert=!M.invert,w[0]=M,{...C,sources:w}})},[A]),k=m.useMemo(()=>h?{outputs:fg(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:j=>y(j.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(j=>r.jsx("option",{value:j.signature,children:j.id||"Unknown controller"},j.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:j=>b({driveDeadzone:j})}),r.jsx(ci,{label:"Camera deadzone",description:"Ignore small camera tilt drift",min:0,max:.4,step:.01,value:g.calibration?.cameraDeadzone??.08,onChange:j=>b({cameraDeadzone:j})}),r.jsx(ci,{label:"Aux deadzone",description:"Ignore small trigger noise",min:0,max:.4,step:.01,value:g.calibration?.auxDeadzone??.05,onChange:j=>b({auxDeadzone:j})}),r.jsx(ci,{label:"Side brush scale",description:"Scale side brush output",min:.3,max:1,step:.05,value:g.calibration?.auxSideScale??.55,onChange:j=>b({auxSideScale:j})}),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:j=>b({cameraMode:j.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:j=>b({cameraSensitivity:j})})]})]}),r.jsx("div",{className:"space-y-0.5",children:Object.entries(p).map(([j,N])=>r.jsxs("div",{className:"space-y-0.5 surface",children:[r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:j}),r.jsx("div",{className:"space-y-0.5",children:N.map(C=>{const M=g.bindings?.[C.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:C.label}),r.jsx("p",{className:"text-[0.65rem] text-slate-400",children:pN(M)})]}),r.jsxs("div",{className:"flex items-center gap-0.5",children:[C.kind==="axisPair"&&r.jsxs(r.Fragment,{children:[r.jsx("button",{type:"button",disabled:!M,onClick:()=>E(C,"invertX"),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert X"}),r.jsx("button",{type:"button",disabled:!M,onClick:()=>E(C,"invertY"),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert Y"})]}),C.kind==="axis"&&r.jsx("button",{type:"button",disabled:!M,onClick:()=>E(C),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert"}),r.jsx("button",{type:"button",onClick:()=>R(C),className:"button-dark text-[0.7rem]",children:"Clear"}),r.jsx("button",{type:"button",onClick:()=>f(C),className:`${o?.id===C.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===C.id?"Waiting…":"Capture"})]})]},C.id)})})]},j))}),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((j,N)=>r.jsxs("span",{className:"font-mono text-slate-300",children:["A",N,": ",aa.format(j)]},`axis-${N}`))}),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((j,N)=>r.jsxs("span",{className:"font-mono text-slate-300",children:["B",N,": ",aa.format(j.value)," ",j.pressed?"●":""]},`btn-${N}`))}),k?.outputs&&r.jsxs(r.Fragment,{children:[r.jsx("p",{className:"text-slate-400",children:"Mapped outputs"}),r.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[r.jsxs("span",{className:"font-mono text-slate-300",children:["Drive: ",aa.format(k.outputs.driveVector.x),","," ",aa.format(k.outputs.driveVector.y)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Camera: ",aa.format(k.outputs.cameraAxis)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Main: ",aa.format(k.outputs.auxAxis.main)]}),r.jsxs("span",{className:"font-mono text-slate-300",children:["Side: ",aa.format(k.outputs.auxAxis.side)]})]})]})]}):r.jsx("p",{className:"text-[0.7rem] text-slate-400",children:"No controller detected."})]})]})}const jN={drive:"Drive wheels",aux:"Aux motors"};function P0(n){return Number.isFinite(n)?`${Math.round(n*100)}%`:"--"}function NN({value:n,color:s="bg-emerald-500"}){const i=`${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:i}})})}function wN(){const{state:{roverId:n},overcurrentLimiter:s}=_t(),i=m.useMemo(()=>tl.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:[i.map(o=>{const f=s?.caps?.[o]?.cap??0,d=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:jN[o]||o}),r.jsx("span",{className:d?"text-red-300":"text-slate-400",children:d?"overcurrent":"ok"})]}),r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("div",{className:"flex items-center justify-between text-[0.7rem] text-slate-400",children:[r.jsx("span",{children:"Cap"}),r.jsx("span",{children:P0(f)})]}),r.jsx(NN,{value:f,color:"bg-amber-500"}),r.jsxs("div",{className:"flex items-center justify-between text-[0.7rem] text-slate-400",children:[r.jsx("span",{children:"Scale"}),r.jsx("span",{children:P0(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 Cg=m.createContext(null);function Eg(){const n=m.useContext(Cg);if(!n)throw new Error("Tabs components must be used within a provider.");return n}const W0={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"}},ex={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"},kg="primary";function od(...n){return n.filter(Boolean).join(" ")}function cd({children:n,defaultTab:s,currentTab:i,onTabChange:o,variant:f=kg}){const[d,p]=m.useState(s??null),[h,x]=m.useState([]),g=m.useCallback(R=>R?(x(E=>E.includes(R)?E:[...E,R]),()=>x(E=>E.includes(R)?E.filter(k=>k!==R):E)):()=>{},[]),y=i??d??h[0]??null;m.useEffect(()=>{s&&i===void 0&&p(s)},[s,i]);const b=m.useCallback(R=>{R&&(i===void 0&&p(R),o&&o(R))},[i,o]),A=m.useMemo(()=>({activeTab:y,setActiveTab:b,registerTab:g,variant:f}),[y,b,g,f]);return r.jsx(Cg.Provider,{value:A,children:n})}function ud({children:n,className:s=""}){return r.jsx("div",{className:od("flex gap-0.5",s),children:n})}function Pt({id:n,children:s,className:i="",disabled:o=!1,highlight:f="none"}){const{activeTab:d,setActiveTab:p,registerTab:h,variant:x}=Eg();m.useEffect(()=>h(n),[n,h]);const g=W0[x]??W0[kg],y=d===n,b=ex[f]||ex.none,A=od(g.base,b||(y?g.active:g.inactive),o?"cursor-not-allowed opacity-50":"",i);return r.jsx("button",{type:"button",className:A,onClick:()=>!o&&p(n),"aria-pressed":y,"aria-disabled":o,children:s})}function fd({children:n,className:s=""}){return r.jsx("div",{className:od("mt-0 space-y-0.5",s),children:n})}function Wt({id:n,children:s,keepMounted:i=!1}){const{activeTab:o}=Eg(),f=o===n;return!f&&!i?null:!f&&i?r.jsx("div",{hidden:!0,"aria-hidden":"true",children:s}):r.jsx(r.Fragment,{children:s})}function CN(){const{session:n}=Le(),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 tx=300,nx=240;function EN(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,(i,o)=>typeof o=="function"?"[Function]":o instanceof Error?`${o.name}: ${o.message}`:o,0)}catch{return String(n)}}function kN(n){const i=n.map(o=>EN(o)).join(" ");return i.length>nx?`${i.slice(0,nx)}…`:i}function MN(){const n=An(),[s,i]=m.useState([]),o=m.useMemo(()=>s.reduce((f,d)=>(d.direction==="in"&&(f.in+=1),d.direction==="out"&&(f.out+=1),f),{in:0,out:0}),[s]);return m.useEffect(()=>{const f=(x,g,y)=>{i(b=>{const A=[...b,{id:`${Date.now()}-${Math.random().toString(16).slice(2)}`,direction:x,event:g,payload:kN(y),timestamp:new Date().toLocaleTimeString()}];return A.length>tx?A.slice(-tx):A})},d=(x,...g)=>f("in",x,g),p=(x,...g)=>f("out",x,g);n.onAny(d);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,...y)=>(p(g,...y),x(g,...y)),h=()=>{n.emit=x}}return()=>{n.offAny(d),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:()=>i([]),children:"Clear"})]})]}),r.jsx("div",{className:"surface h-64 overflow-y-auto font-mono text-xs",children:s.length===0?r.jsx("p",{children:"No socket activity yet."}):s.slice().reverse().map(f=>r.jsxs("div",{className:"surface",children:[r.jsx("span",{className:"text-slate-400",children:f.timestamp})," ",r.jsxs("span",{className:f.direction==="in"?"text-emerald-400":"text-amber-400",children:["[",f.direction.toUpperCase(),"]"]})," ",r.jsx("span",{className:"text-cyan-300",children:f.event})," ",r.jsx("span",{className:"text-slate-200",children:f.payload})]},f.id))}),r.jsx("p",{className:"text-xs text-slate-500",children:"Logs are collected only while this panel is open."})]})}const qN=[{key:"start",label:"Start OI"},{key:"safe",label:"Safe"},{key:"full",label:"Full"},{key:"passive",label:"Passive"},{key:"dock",label:"Dock"}];function Mg(){const{state:{roverId:n},actions:{sendOiCommand:s,setSensorStream:i}}=_t(),o=!!n,[f,d]=Ag(),p=An(),{value:h,save:x}=Fe("page",{hudMapDesktop:!1,connectionTransport:"websocket",swapMobileControlColumns:!1,driveMacroBackoffEnabled:!0}),{value:g,save:y}=Fe("audio",St),b=h?.connectionTransport||"websocket",A=!!h?.swapMobileControlColumns,R=typeof h?.driveMacroBackoffEnabled=="boolean"?h.driveMacroBackoffEnabled:!0,E=Number.isFinite(g?.masterVolume)?g.masterVolume:St.masterVolume,k=Number.isFinite(g?.alertVolume)?g.alertVolume:St.alertVolume,j=Number.isFinite(g?.roverVolume)?g.roverVolume:St.roverVolume,N=typeof g?.mainBrushDuckEnabled=="boolean"?g.mainBrushDuckEnabled:typeof g?.autoLevelEnabled=="boolean"?g.autoLevelEnabled:St.mainBrushDuckEnabled,C=Number.isFinite(g?.mainBrushDuckAmount)?Math.max(0,Math.min(1,g.mainBrushDuckAmount)):St.mainBrushDuckAmount,w=m.useMemo(()=>[{key:"start",label:"Enable stream",enable:!0},{key:"stop",label:"Disable stream",enable:!1}],[]),M=U=>{n&&i(U)},B=U=>{const F=U.target.value;x(te=>({...te??{},connectionTransport:F})),p?.io?.opts&&(p.io.opts.transports=F==="polling"?["polling"]:["websocket","polling"],p.disconnect(),p.connect())},H=U=>F=>{const te=Number(F.target.value),fe=Number.isFinite(te)?Math.max(0,Math.min(1,te)):0;y(ce=>({...ce??{},[U]:fe}))},_=U=>{const F=!!U.target.checked;y(te=>({...te??{},mainBrushDuckEnabled:F}))},K=U=>{const F=!!U.target.checked;x(te=>({...te??{},swapMobileControlColumns:F}))},L=U=>{const F=!!U.target.checked;x(te=>({...te??{},driveMacroBackoffEnabled:F}))};return r.jsxs(cd,{defaultTab:"keybindings",children:[r.jsxs(ud,{children:[r.jsx(Pt,{id:"keybindings",children:"Keybindings"}),r.jsx(Pt,{id:"controller",children:"Controller"}),r.jsx(Pt,{id:"page",children:"Page settings"}),r.jsx(Pt,{id:"admin",children:"Admin"})]}),r.jsxs(fd,{children:[r.jsx(Wt,{id:"keybindings",children:r.jsx("div",{className:"space-y-0.5",children:r.jsx(dN,{})})}),r.jsx(Wt,{id:"controller",children:r.jsx("div",{className:"space-y-0.5",children:r.jsx(AN,{})})}),r.jsx(Wt,{id:"page",children:r.jsxs("div",{className:"space-y-0.5",children:[r.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[r.jsx("p",{className:"text-slate-400",children:"HUD"}),r.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[r.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:f,onChange:U=>d(U.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:A,onChange:K}),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:R,onChange:L}),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(E*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:E,onChange:H("masterVolume"),className:"w-full accent-emerald-500"})]}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Alert/page sounds"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(k*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:k,onChange:H("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(j*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:j,onChange:H("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:N,onChange:_})]}),r.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[r.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[r.jsx("span",{children:"Main brush duck amount"}),r.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(C*100),"%"]})]}),r.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:C,onChange:H("mainBrushDuckAmount"),className:"w-full accent-emerald-500",disabled:!N})]}),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:b,onChange:B,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(Wt,{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:qN.map(U=>r.jsx("button",{type:"button",onClick:()=>s(U.key),disabled:!o,className:"button-dark text-xs disabled:opacity-30",children:U.label},U.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:w.map(U=>r.jsx("button",{type:"button",onClick:()=>M(U.enable),disabled:!o,className:"flex-1 button-dark text-xs disabled:opacity-30",children:U.label},U.key))}),!o&&r.jsx("p",{className:"text-xs text-slate-500",children:"Assign a rover to toggle streams."})]}),r.jsx(wg,{}),r.jsx(wN,{}),r.jsx(Wj,{}),r.jsx(CN,{}),r.jsx(MN,{})]})})]})]})}const ax={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 RN(n){return ax[n]||ax.desktop}function qg({actionId:n,keymap:s}){const i=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:bn(i)})}function sx(n,s){return n.map((i,o)=>typeof i=="string"?r.jsx("span",{children:i},`text-${o}`):i?.action?r.jsx(qg,{actionId:i.action,keymap:s},`pill-${i.action}-${o}`):i?.text?r.jsx("span",{children:i.text},`span-${o}`):null)}function So(n,s,i){if(typeof n=="string")return n;if(Array.isArray(n?.segments))return sx(n.segments,s);if(n&&typeof n=="object"){if(typeof n.text=="string")return n.text;if(Array.isArray(n))return sx(n,s)}return String(n??"")}function TN({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(i=>r.jsx("span",{className:"rounded border border-slate-700 px-1 py-[2px]",children:i},i))})]}),n.bullets&&r.jsx("ul",{className:"space-y-0.5 text-[0.85rem] text-slate-200",children:n.bullets.map((i,o)=>{const f=Array.isArray(i?.segments)?`hero-${o}`:`hero-${o}`;return r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:So(i,s)},f)})})]}):null}function DN({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((i,o)=>{const f=`item-${o}`;return r.jsx("li",{className:"surface-muted flex flex-wrap items-center gap-0.5 px-0.5 py-0.25",children:So(i,s)},f)})})]})}function _N({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((i,o)=>r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:So(i,{})},`callout-${o}`))})]})}function ON({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(i=>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:i.label}),r.jsx(qg,{actionId:i.action,keymap:s})]},i.action))})]})}function BN({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(i=>r.jsx(ON,{group:i,keymap:s},i.id))})]}):null}function LN({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,i)=>r.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:So(s,{})},`gamepad-${i}`))})]}):null}function lx({block:n,keymap:s}){if(!n)return null;switch(n.type){case"list":return r.jsx(DN,{block:n,keymap:s});case"callout":return r.jsx(_N,{block:n});case"keyboard":return r.jsx(BN,{block:n,keymap:s});case"gamepad":return r.jsx(LN,{block:n});default:return null}}function Rg({layout:n,keymap:s}){const i=m.useMemo(()=>RN(n),[n]),o=s||{},f=i.main||[],d=i.aside||[];return r.jsxs("div",{className:"space-y-0.5",children:[r.jsx(TN,{hero:i.hero,keymap:o}),r.jsxs("div",{className:"grid gap-0.5",style:{gridTemplateColumns:"repeat(auto-fit, minmax(360px, 1fr))"},children:[r.jsx("div",{className:"space-y-0.5",children:f.map((p,h)=>r.jsx(lx,{block:p,keymap:o},p.title||h))}),r.jsx("div",{className:"space-y-0.5",children:d.map((p,h)=>r.jsx(lx,{block:p,keymap:o},p.title||h))})]})]})}function Tg({layout:n,onOpenOverlay:s}){const{state:i}=_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(Rg,{layout:n,keymap:i?.keymap||{}})]})}const zN=["kal","rms","slt","ksp","bdl"],UN=Array.from({length:10},(n,s)=>s*10);function Ao({hideInput:n=!1,hideSpectatorNotice:s=!1,fillHeight:i=!1,allowSpectatorInput:o=!1}){const{session:f}=Le(),{messages:d,typing:p,sendMessage:h,registerInputRef:x,onInputFocus:g,onInputBlur:y,blurChat:b,setTypingActive:A}=Jf(),{value:R,save:E}=Fe("tts",{engine:"flite",voice:"rms",pitch:50}),[k,j]=m.useState(""),[N,C]=m.useState(!1),[w,M]=m.useState(!1),[B,H]=m.useState(()=>R?.engine||"flite"),[_,K]=m.useState(()=>R?.voice||"rms"),[L,U]=m.useState(()=>Number.isFinite(R?.pitch)?R.pitch:50),F=f?.role!=="spectator"||o,te=m.useRef(null),fe=f?.assignment?.roverId||null,Y=!!m.useMemo(()=>f?.roster?.find(q=>String(q.id)===String(fe))||null,[fe,f?.roster])?.audio?.ttsEnabled,T=m.useMemo(()=>d.slice(-200),[d]),X=m.useMemo(()=>p||[],[p]);m.useEffect(()=>{te.current&&(te.current.scrollTop=te.current.scrollHeight)},[T,X]),m.useEffect(()=>{const q=R?.engine||"flite",V=R?.voice||"rms",P=Number.isFinite(R?.pitch)?R.pitch:50;B!==q&&H(q),_!==V&&K(V),L!==P&&U(P)},[B,L,R?.engine,R?.pitch,R?.voice,_]),m.useEffect(()=>{M(!!Y)},[Y]);const J=m.useMemo(()=>!Y||!w?null:B==="espeak"?{speak:!0,engine:B,pitch:L}:{speak:!0,engine:B,voice:_},[B,L,w,Y,_]);async function se(q){if(q.preventDefault(),!F||n)return;const P=k.replace(/\\n/g,` -`).trim();if(P){C(!0);try{await h(P,J),j(""),b(),A(!1)}catch(ne){alert(ne.message)}finally{C(!1)}}}const de=i?"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 ${i?"flex h-full flex-col overflow-hidden":""}`,children:[r.jsxs("div",{className:`surface overflow-y-auto space-y-0.5 px-0 ${de}`,ref:te,children:[T.length===0&&X.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"No messages yet."}):T.map(q=>r.jsx(Kf,{message:q},q.id)),X.map(q=>r.jsx(tg,{message:q},`typing-${q.typingId||q.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:k,onChange:q=>{const V=q.target.value;j(V),A(!!V.trim())},onFocus:q=>{g(q),A(!!k.trim())},onBlur:q=>{y(q),A(!1)},onKeyDown:q=>{q.key==="Enter"&&!k.trim()&&(q.preventDefault(),b(),A(!1))},ref:q=>x(q,{target:"panel"}),placeholder:F?"Type a message…":s?"":"Spectators cannot chat",disabled:!F}),Y&&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:w,onChange:q=>M(q.target.checked),className:"accent-cyan-500"}),r.jsx("span",{children:"Speak"})]}),r.jsxs("select",{value:B,onChange:q=>{const V=q.target.value;H(V),E(P=>({...P||{},engine:V}))},className:"field-input text-xs",children:[r.jsx("option",{value:"flite",children:"flite"}),r.jsx("option",{value:"espeak",children:"espeak"})]}),B==="flite"?r.jsx("select",{value:_,onChange:q=>{const V=q.target.value;K(V),E(P=>({...P||{},voice:V}))},className:"field-input text-xs",children:zN.map(q=>r.jsx("option",{value:q,children:q},q))}):r.jsx("select",{value:L,onChange:q=>{const V=Number(q.target.value);U(V),E(P=>({...P||{},pitch:V}))},className:"field-input text-xs",children:UN.map(q=>r.jsxs("option",{value:q,children:["pitch ",q]},q))})]}),r.jsx("button",{type:"submit",disabled:!F||N,className:"button-dark h-full disabled:opacity-50 self-stretch",children:N?"...":"Send"})]})]})}function jo({compact:n=!1}){const{session:s,setNickname:i}=Le(),{value:o,save:f}=Fe("profile",{nickname:""}),[d,p]=m.useState(o.nickname||""),[h,x]=m.useState(!1),g=s?.role!=="spectator";m.useEffect(()=>{p(o.nickname||"")},[o.nickname]);async function y(b){if(b.preventDefault(),!g)return;const A=(d||"").trim().slice(0,32);if(A){x(!0);try{await i(A),f({nickname:A})}catch(R){alert(R.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:y,children:[r.jsx("input",{className:"field-input flex-1 min-w-0",value:d,onChange:b=>p(b.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 HN(n){const s=Array.isArray(n?.socials)?n.socials:null;if(s&&s.length)return s;const i=[];return n?.discord?.invite&&i.push({id:"discord",label:"Discord",url:n.discord.invite}),n?.kofi?.link&&i.push({id:"kofi",label:"Ko-fi",url:n.kofi.link}),i}function VN(n){if(!n||typeof n!="object")return null;const s=n.id||n.service||n.key||n.name||null,i=n.label||n.title||n.name||s||"Link",o=n.url||n.link||n.href||null;return o?{id:s,label:i,url:o}:null}function Dg({className:n=""}){const{session:s}=Le(),i=HN(s).map(VN).filter(Boolean).slice(0,4);return i.length?r.jsx("div",{className:`grid grid-cols-2 grid-rows-2 gap-0.5 ${n}`,children:i.map(o=>r.jsx(sd,{...o},`${o.id||o.label}-${o.url}`))}):null}function $N({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(jo,{compact:n})})})}function GN(){return r.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:r.jsx(Dg,{className:"flex-1 min-h-0"})})}function df(...n){return n.filter(Boolean).join(" ")}function YN(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function FN(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function XN(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 QN(n,s){if(!n)return"";const i=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${i} (you)`:i}function No({title:n="Rovers"}){const{session:s,requestControl:i}=Le(),[o,f]=m.useState({}),[d,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??[],y=s?.turnQueues??{},b=s?.users??[],A=s?.socketId||null,R=m.useMemo(()=>Object.values(y||{}).some(N=>N?.deadline||N?.idleDeadline),[y]);m.useEffect(()=>{if(!R)return;const N=setInterval(()=>{p(Date.now())},1e3);return()=>clearInterval(N)},[R]);const E=m.useMemo(()=>{const N=new Set(g.map(w=>String(w.id))),C=Object.keys(y||{}).filter(w=>!N.has(String(w))).map(w=>({id:w,name:w,locked:!1,batteryState:null}));return[...g,...C]},[g,y]);async function k(N){if(N){f(C=>({...C,[N]:!0}));try{await i(N)}catch(C){alert(C.message)}finally{f(C=>({...C,[N]:!1}))}}}const j=N=>b.find(C=>C.socketId===N)||{socketId:N,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}),E.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:E.map(N=>{const C=String(N.id),w=y?.[C]||null,M=w?.queue||[],B=w?.idleDeadline||w?.deadline||null,H=B&&B>d?Math.ceil((B-d)/1e3):B?0:null,_=w?.current||null,K=_?M.findIndex(se=>se===_):-1,L=M.length>1?K>=0?M[(K+1)%M.length]:M[0]:null,U=!!(A&&_&&_===A),F=!!(A&&L&&L===A),te=H!=null&&(U||F),fe=!!N.locked,ce=fe&&!x,Y=!!(N?.private?.enabled&&N?.private?.open),T=N.lockReason?`locked: ${N.lockReason}`:"locked",X=fe?T:o[C]?"...":"request",J=h&&!ce&&!o[C];return r.jsxs("li",{className:df("surface flex flex-wrap items-start justify-between gap-0.5",J&&"cursor-pointer",fe?"bg-red-900/40":Y?"bg-amber-700/35 border border-amber-200/30":null),onClick:()=>{J&&k(N.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:ra(N.color,.16),children:N.name})}),te?r.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem] text-slate-200",children:U?`${H}s left`:`Your turn in ${H}s`}):null]}),r.jsx("span",{className:df("text-[0.75rem] font-semibold",FN(N)),children:YN(N)})]}),M.length===0?r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"No queue."}):r.jsx("div",{className:"flex flex-wrap items-center gap-0.5",children:M.map((se,de)=>{const q=j(se),V=se===_,P=!!(L&&se===L&&!V),ne=V?"bg-sky-600 text-white ring-2 ring-amber-300":P?"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] ${ne}`,children:[r.jsx("span",{className:`${XN(q.role)} font-semibold`,children:QN(q,A)}),V&&r.jsx("span",{className:"text-[0.65rem] text-slate-200",children:"now"}),P&&r.jsx("span",{className:"text-[0.65rem] text-emerald-100",children:"next"})]},`${C}-${se}-${de}`)})})]}),h?r.jsx("button",{type:"button",onClick:se=>{se.stopPropagation(),k(N.id)},disabled:o[C]||ce,className:df("button-dark disabled:opacity-40",fe&&"bg-red-600/70 text-white hover:bg-red-600"),children:X}):null]},N.id)})})]})}function KN(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 ZN(n,s){if(!n)return"";const i=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${i} (you)`:i}function mo({hideNicknameForm:n=!1,hideHeader:s=!1,className:i="",fillHeight:o=!1,compact:f=!1}){const{session:d}=Le(),p=d?.role!=="spectator",h=d?.users??[],x=d?.socketId||null,g=m.useMemo(()=>[...h].sort((b,A)=>b.socketId===x?-1:A.socketId===x?1:(b.nickname||"").localeCompare(A.nickname||"")),[x,h]),y=o?"flex-1 min-h-0 overflow-y-auto":f?"h-28 overflow-y-auto":"h-48 overflow-y-auto";return r.jsxs("section",{className:`panel-section space-y-0.5 text-base ${o?"flex h-full min-h-0 flex-col overflow-hidden":""} ${i}`,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(jo,{compact:f})})}),r.jsx(Dg,{})]}),!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 ${f?"text-xs":""}`,children:[r.jsx("span",{children:"Users"}),r.jsx("span",{className:"text-xs text-slate-500",children:g.length})]}),r.jsx("div",{className:`surface flex flex-wrap content-start items-start gap-0.5 px-0 pb-0 ${y} ${f?"text-[0.8rem]":""}`,children:g.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"Waiting for users…"}):g.map(b=>r.jsx("span",{className:`rounded bg-slate-800/80 px-1 py-0.25 text-[0.7rem] ${KN(b.role)}`,children:ZN(b,x)},b.socketId))})]})]})}const IN=/^cu_[a-f0-9]{32}$/,ji="field-input w-full max-w-sm text-left focus:ring-emerald-500",wo="mx-auto w-full max-w-xl flex justify-center",hi="mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center";function JN(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 ix=8*1024*1024,ss=16e3,PN={iceServers:[{urls:"stun:stun.l.google.com:19302"}],bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"};function rx(n){let s="";for(let o=0;o{if(!n||n.iceGatheringState==="complete"){i();return}const o=setTimeout(()=>{n.removeEventListener("icegatheringstatechange",f),i()},s);function f(){n.iceGatheringState==="complete"&&(clearTimeout(o),n.removeEventListener("icegatheringstatechange",f),i())}n.addEventListener("icegatheringstatechange",f)})}function ox(n){if(!n)return!1;const s=n.connectionState,i=n.iceConnectionState;return s==="connected"||i==="connected"||i==="completed"}function nw(n,s=1e4){return new Promise((i,o)=>{if(!n){o(new Error("Peer connection missing"));return}if(ox(n)){i();return}const f=setTimeout(()=>{p(),o(new Error("Peer connection timeout"))},s),d=()=>{ox(n)?(p(),i()):(n.connectionState==="failed"||n.connectionState==="closed"||n.iceConnectionState==="failed")&&(p(),o(new Error(`Peer connection ${n.connectionState||n.iceConnectionState}`)))};function p(){clearTimeout(f),n.removeEventListener("connectionstatechange",d),n.removeEventListener("iceconnectionstatechange",d)}n.addEventListener("connectionstatechange",d),n.addEventListener("iceconnectionstatechange",d)})}async function aw(n){if(!n?.getParameters||!n?.setParameters)return;const s=n.getParameters()||{},i=s.encodings&&s.encodings[0]||{};s.encodings=[{...i,maxBitrate:64e3,dtx:"disabled"}];try{await n.setParameters(s)}catch{}}function sw(n,s=6e3){return new Promise((i,o)=>{if(!n){o(new Error("Peer connection missing"));return}const f=Date.now();let d=-1;const p=setInterval(async()=>{if(Date.now()-f>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 y of g.values()){if(y.type!=="outbound-rtp"||y.kind!=="audio")continue;const b=Number(y.bytesSent||0),A=Number(y.packetsSent||0);if(d<0)d=b;else if(b>d+200||A>5){clearInterval(p),i();return}}}}catch{}},250)})}function mn({label:n,active:s,detail:i=""}){return r.jsxs("div",{className:`rounded-md px-0.5 py-0.5 text-xs text-slate-100 ${s?"bg-emerald-500":"bg-slate-700"}`,children:[r.jsx("div",{className:"text-center font-medium",children:n}),r.jsx("div",{className:"text-center text-[0.72rem] opacity-90",children:i||(s?"active":"idle")})]})}function cx({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function lw(n){const s=n.reduce((f,d)=>f+d.length,0),i=new Float32Array(s);let o=0;for(const f of n)i.set(f,o),o+=f.length;return i}function iw(n){const s=new Int16Array(n.length);for(let i=0;i{for(let y=0;yy&&s?.[y]||null,[s,y]),P=!!(V&&V.state!=="offline"&&!V.error),ne=V?.source==="upload"&&V?.state==="playing",pe=V?.source==="mic-whip"&&(V?.state==="starting"||V?.state==="playing"),ie=!!(!N&&L.current&&(k||q)),oe=!N&&(C==="live"||C==="starting"),ve=N&&M==="recording",ye=N&&M==="sending",xe=bn(h?.keymap?.micPtt?.[0])||"M",Ue=m.useCallback(me=>{const we=me==="clip"?"clip":"live";g(et=>({...et||{},pttMode:we}))},[g]),$e=async()=>{if(!y){_("Take control of your rover first.");return}if(!b){_("Select an audio file first.");return}if(b.size>ix){_(`File too large (max ${ix} bytes).`);return}E(!0),_("");try{const me=await b.arrayBuffer(),we=rx(new Uint8Array(me));await i?.({roverId:y,name:b.name,mime:b.type||"",dataBase64:we}),_("Upload playback started.")}catch(me){_(me?.message||"Failed to play upload.")}finally{E(!1)}},Ne=async()=>{if(!y){_("Take control of your rover first.");return}E(!0),_("");try{await o?.(y),_("Upload playback stopped.")}catch(me){_(me?.message||"Failed to stop upload.")}finally{E(!1)}},ae=m.useCallback(async me=>{const we=String(me||te.current||"").trim();if(F.current=!1,w("idle"),U.current){try{U.current.getSenders().forEach(et=>et.track?.stop())}catch{}try{U.current.close()}catch{}}if(U.current=null,K.current)try{K.current.getTracks().forEach(et=>et.stop())}catch{}if(K.current=null,L.current=null,we)try{await p?.(we)}catch{}te.current=""},[p]),ue=m.useCallback(async me=>{const we=await f?.(me),et=String(we?.whipUrl||"").trim(),dt=String(we?.token||"").trim();if(!et||!dt)throw new Error("WHIP endpoint unavailable");const ze=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}});K.current=ze;const xt=ze.getAudioTracks()?.[0];if(L.current=xt||null,xt&&(xt.enabled=!!(k||q)),xt?.applyConstraints)try{await xt.applyConstraints({channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1})}catch{}const mt=new RTCPeerConnection(PN);U.current=mt,mt.onconnectionstatechange=()=>{if(!F.current)return;const Gt=mt.connectionState;if(Gt==="connected"){w("live");return}(Gt==="failed"||Gt==="disconnected"||Gt==="closed")&&(w("error"),_(`WHIP transport ${Gt}.`))},ze.getAudioTracks().forEach(Gt=>{const Oa=mt.addTrack(Gt,ze);aw(Oa)});const Tn=await mt.createOffer({offerToReceiveAudio:!1,offerToReceiveVideo:!1});await mt.setLocalDescription(Tn),await tw(mt,1800);const kt=await fetch(et,{method:"POST",headers:{"Content-Type":"application/sdp",...ew(dt)},body:mt.localDescription?.sdp||Tn.sdp});if(!kt.ok)throw new Error(`WHIP request failed: ${kt.status}`);const cs=await kt.text();await mt.setRemoteDescription({type:"answer",sdp:cs}),await nw(mt,1e4),await sw(mt,6e3),await d?.(me)},[k,q,d,f]),be=m.useCallback(async()=>{if(se.current=!1,T.current){try{T.current.disconnect()}catch{}T.current.onaudioprocess=null}if(Y.current)try{Y.current.disconnect()}catch{}if(X.current)try{X.current.disconnect()}catch{}if(fe.current)try{fe.current.getTracks().forEach(me=>me.stop())}catch{}if(ce.current)try{await ce.current.close()}catch{}J.current=[],T.current=null,Y.current=null,X.current=null,fe.current=null,ce.current=null,de.current=ss},[]),Me=m.useCallback(async()=>{if(fe.current&&ce.current&&T.current)return;B(xt=>xt==="recording"?xt:"arming");const me=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}}),we=new AudioContext({latencyHint:"interactive"}),et=we.createMediaStreamSource(me),dt=we.createScriptProcessor(1024,1,1),ze=we.createGain();ze.gain.value=0,dt.onaudioprocess=xt=>{if(!se.current)return;const mt=xt.inputBuffer.getChannelData(0);J.current.push(new Float32Array(mt))},et.connect(dt),dt.connect(ze),ze.connect(we.destination),fe.current=me,ce.current=we,Y.current=et,T.current=dt,X.current=ze,de.current=we.sampleRate||ss},[]),le=m.useCallback(async({send:me})=>{const we=se.current;if(se.current=!1,!we){me||B("idle");return}const et=J.current;if(J.current=[],!me){B("idle");return}if(!y){B("idle");return}if(!et.length){B("idle");return}B("sending");try{const dt=lw(et),ze=rw(dt,de.current||ss),xt=rx(ze);await i?.({roverId:y,name:`ptt-${Date.now()}.wav`,mime:"audio/wav",dataBase64:xt}),B("idle")}catch(dt){B("error"),_(dt?.message||"Failed to send PTT clip.")}},[i,y]),re=m.useCallback(async()=>{if(!y){_("Take control of your rover first.");return}await Me(),J.current=[],se.current=!0,B("recording")},[Me,y]);return m.useEffect(()=>{let me=!1;async function we(){if(N){await ae(te.current||y);return}if(!y){await ae(te.current);return}if(!(F.current&&te.current===y)&&!(!k&&!q))try{w("starting"),_(""),F.current=!0,te.current=y,await ue(y),me||w("live")}catch(et){me||(w("error"),_(et?.message||"Failed to start mic forwarding.")),await ae(y)}}return we(),()=>{me=!0}},[N,k,q,y,ue,ae]),m.useEffect(()=>{const me=L.current;me&&(me.enabled=!!(!N&&(k||q)))},[N,k,q]),m.useEffect(()=>{let me=!1;async function we(){if(!N||!y){se.current&&await le({send:!1}),B("idle");return}try{await Me(),!me&&!se.current&&B("idle")}catch(et){me||(B("error"),_(et?.message||"Microphone access failed for clip mode."))}}return we(),()=>{me=!0}},[N,Me,le,y]),m.useEffect(()=>{let me=!1;async function we(){if(N){if(!y){se.current&&await le({send:!1});return}if(q){if(!se.current)try{_(""),await re()}catch(et){me||(B("error"),_(et?.message||"Failed to start clip recording."))}}else se.current&&await le({send:!0})}}return we(),()=>{me=!0}},[N,le,q,y,re]),m.useEffect(()=>()=>{ae(te.current||y),be()},[y,ae,be]),r.jsxs("div",{className:"grid gap-0.5",children:[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(cx,{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 ${N?"":"bg-emerald-500 text-white hover:bg-emerald-500"}`,onClick:()=>Ue("live"),children:"Live Mic (WHIP)"}),r.jsx("button",{type:"button",className:`button-dark w-full text-sm ${N?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,onClick:()=>Ue("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(mn,{label:"Mode",active:N,detail:N?"record clip":"live mic"}),r.jsx(mn,{label:"PTT hold",active:q,detail:q?"held":"released"}),r.jsx(mn,{label:"Recording",active:ve,detail:ve?"capturing":"idle"}),r.jsx(mn,{label:"Playback",active:N&&ne,detail:N&&ne?"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:`${ji} text-center`,type:"file",accept:".mp3,.wav,.ogg,audio/mpeg,audio/wav,audio/ogg",disabled:R||!y,onChange:me=>A(me.target.files?.[0]||null)})]}),r.jsx("div",{className:"mx-auto w-full max-w-sm text-center",children:b?r.jsxs("div",{className:"surface-muted text-xs text-slate-300",children:[b.name," (",b.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:R||!y,onClick:$e,children:R?"Working...":"Play Upload"}),r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:R||!y,onClick:Ne,children:"Stop"})]})]})}),r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Live Microphone"}),r.jsxs("label",{className:"surface-muted mx-auto flex w-full max-w-sm items-center justify-center gap-0.5 px-0.5 py-0.5 text-xs text-slate-300",children:[r.jsx("input",{type:"checkbox",checked:k,disabled:!y||N,onChange:me=>g(we=>({...we||{},openMicEnabled:!!me.target.checked}))}),r.jsx("span",{children:N?"Open mic (live mode only)":"Open mic"})]}),r.jsxs("div",{className:"grid gap-0.5 content-start",children:[r.jsx(mn,{label:"WHIP link",active:oe,detail:C}),r.jsx(mn,{label:"Mic hot",active:ie,detail:ie?"transmitting":"muted"}),r.jsxs("div",{className:"surface-muted text-center text-xs text-slate-400",children:["Hold ",r.jsx(cx,{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(mn,{label:"Forward pipe",active:P,detail:P?"connected":"offline"}),r.jsx(mn,{label:"Upload playback",active:ne,detail:ne?"playing":"idle"}),r.jsx(mn,{label:"Mic relay",active:pe,detail:pe?"active":"idle"}),r.jsx(mn,{label:"WHIP transport",active:oe,detail:C}),r.jsx(mn,{label:"Clip recording",active:ve,detail:ve?"recording":"idle"}),r.jsx(mn,{label:"Clip sending",active:ye,detail:ye?"sending":"idle"})]}),H?r.jsx("div",{className:"text-xs text-slate-400 text-center",children:H}):null]})})]})}function cw({pendingRequestId:n,currentStoredKey:s,nickname:i,requestVerification:o,applyIdentityKey:f,onMessage:d,fullWidth:p=!1}){const[h,x]=m.useState(0),[g,y]=m.useState(""),[b,A]=m.useState(!1),[R,E]=m.useState(!1),k=()=>{x(1),y(s),A(!1),d?.("")},j=()=>{x(0),A(!1)},N=async w=>{if(w.preventDefault(),!b){d?.("Please confirm your nickname agreement before sending.");return}if(h<3){d?.("Complete all request steps before sending.");return}E(!0),d?.("");try{const M=await f(g);await o?.(),y(M),x(0),A(!1),d?.("Verification request sent to lockdown admins.")}catch(M){d?.(M.message||"Failed to submit request.")}finally{E(!1)}},C=p?"w-full":wo;return n?r.jsx("section",{className:`surface text-sm text-slate-300 ${C}`,children:r.jsxs("div",{className:hi,children:["Verification request pending: ",n]})}):h===0?r.jsx("section",{className:`surface ${C}`,children:r.jsxs("div",{className:hi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Verification"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:k,disabled:R,children:"Request Verification"})]})}):r.jsx("form",{className:`surface ${C}`,onSubmit:N,children:r.jsxs("div",{className:hi,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(jo,{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:i||"(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:b,onChange:w=>A(w.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:!i||!b,onClick:()=>x(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:j,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:ji,type:"password",name:"identity_key_request",autoComplete:"current-password",maxLength:35,value:g,onChange:w=>y(w.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:ji,type:"password",name:"identity_key_request_final",autoComplete:"current-password",maxLength:35,value:g,onChange:w=>y(w.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:R||!g,children:"Confirm Request"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(2),children:"Back"})]})]}):null]})})}function uw({currentStoredKey:n,applyIdentityKey:s,onMessage:i,fullWidth:o=!1}){const[f,d]=m.useState(0),[p,h]=m.useState(""),[x,g]=m.useState(!1),y=()=>{d(1),h(""),i?.("")},b=()=>{d(0),h("")},A=async E=>{if(E.preventDefault(),!(f<2)){g(!0),i?.("");try{await s(p),d(0),h(""),i?.("Identity key restored.")}catch(k){i?.(k.message||"Failed to restore key.")}finally{g(!1)}}},R=o?"w-full":wo;return r.jsx("section",{className:`surface ${R}`,children:r.jsxs("div",{className:hi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Identity key"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Current: ",JN(n)||"not set yet"]}),r.jsx("input",{className:ji,type:"password",name:"identity_key_current",autoComplete:"current-password",maxLength:35,value:n,readOnly:!0,placeholder:"Identity key"}),f===0?r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!n,onClick:()=>navigator.clipboard?.writeText(n),children:"Copy Key"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:y,disabled:x,children:"Restore Key"})]}):null,f===1?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Restoring your key should only be done when needed. Use this to move your identity to another browser."}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>d(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:b,children:"Cancel"})]})]}):null,f===2?r.jsxs("form",{className:"space-y-0.5",onSubmit:A,children:[r.jsx("input",{className:ji,type:"password",name:"identity_key_restore",autoComplete:"current-password",maxLength:35,value:p,onChange:E=>h(E.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:()=>d(1),children:"Back"})]})]}):null]})})}function fw({requestableRovers:n=[],pendingRequests:s=[],requestPrivateRoverAccess:i,onMessage:o,fullWidth:f=!1}){const[d,p]=m.useState({}),h=m.useMemo(()=>{const y=new Map;return(s||[]).forEach(b=>{b?.roverId&&y.set(String(b.roverId),b)}),y},[s]),x=f?"w-full":wo,g=async y=>{if(y){p(b=>({...b,[y]:!0})),o?.("");try{(await i?.(y))?.existing?o?.("You already have a pending request for that rover."):o?.("Private rover access request sent to lockdown admins.")}catch(b){o?.(b.message||"Failed to send request.")}finally{p(b=>({...b,[y]:!1}))}}};return r.jsx("section",{className:`surface text-sm text-slate-300 ${x}`,children:r.jsxs("div",{className:hi,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(y=>{const b=String(y.id),A=!!d[b],R=h.get(b);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:y.name||b}),r.jsx("p",{className:"truncate text-[0.7rem] text-slate-500",children:b})]}),R?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(b),disabled:A,className:"button-dark text-xs disabled:opacity-50",children:A?"Sending...":"Request"})]},b)})})]})})}function _g(){const{session:n,identifySession:s,requestVerification:i,requestPrivateRoverAccess:o,playUploadedAudio:f,stopUploadedAudio:d,startMicWhip:p,readyMicWhip:h,stopMicWhip:x}=Le(),{value:g,save:y}=Fe("identity",{cookieUserId:""}),{value:b}=Fe("profile",{nickname:""}),A=m.useMemo(()=>(g?.cookieUserId||"").trim(),[g?.cookieUserId]),R=(b?.nickname||"").trim(),E=!!n?.isVerified,k=n?.verification?.pendingRequestId||null,j=n?.privateRoverAccess?.requestableRovers||[],N=n?.privateRoverAccess?.pendingRequests||[],C=String(n?.assignment?.roverId||"").trim(),[w,M]=m.useState(""),B=async H=>{const _=String(H||"").trim().toLowerCase();if(!_)throw new Error("Identity key required.");if(!IN.test(_))throw new Error("Identity key must match format: cu_ + 32 lowercase hex chars.");return y(K=>({...K||{},cookieUserId:_})),await s({cookieUserId:_,nickname:R}),_};return r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-[minmax(0,1.25fr)_minmax(0,0.9fr)]",children:[r.jsx("div",{className:"lg:col-span-2",children:E?r.jsx("section",{className:"surface w-full",children:r.jsxs("div",{className:"mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center",children:[r.jsx("p",{className:"text-sm text-emerald-300",children:"Verification complete"}),r.jsx("p",{className:"text-xs text-slate-400",children:"VIP controls are unlocked for your assigned rover."})]})}):r.jsx(cw,{pendingRequestId:k,currentStoredKey:A,nickname:R,requestVerification:i,applyIdentityKey:B,onMessage:M,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:E?r.jsx(ow,{ownRoverId:C,audioForwardByRover:n?.audioForward||{},playUploadedAudio:f,stopUploadedAudio:d,startMicWhip:p,readyMicWhip:h,stopMicWhip:x}):r.jsx("section",{className:"surface h-full",children:r.jsx("div",{className:"flex h-full flex-col items-center justify-center text-center text-xs text-slate-400",children:"Verify your account to unlock VIP controls."})})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(fw,{requestableRovers:j,pendingRequests:N,requestPrivateRoverAccess:o,onMessage:M,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(uw,{currentStoredKey:A,applyIdentityKey:B,onMessage:M,fullWidth:!0})})]}),w?r.jsx("div",{className:wo,children:r.jsx("p",{className:"text-xs text-slate-400 text-center",children:w})}):null]})}const dw=420,mw=1200,hw={1:262,2:330,3:392,4:523};function Og(){const{session:n}=Le(),s=An(),{value:i}=Fe("audio",St),o=Number.isFinite(i?.masterVolume)?i.masterVolume:St.masterVolume,f=Number.isFinite(i?.alertVolume)?i.alertVolume:St.alertVolume,d=Math.max(0,Math.min(1,o*f)),p=m.useMemo(()=>{const k=Array.isArray(n?.buttonBox?.buttons)?n.buttonBox.buttons:[];return k.length===4?k:[1,2,3,4].map(j=>k.find(N=>Number(N?.id)===j)||{id:j,count:0,goal:0,rewardName:null,rewardId:null,rewardNumber:null,lastRewardAt:null})},[n?.buttonBox?.buttons]),[h,x]=m.useState({}),[g,y]=m.useState({}),b=m.useRef(new Map),A=m.useRef(new Map),R=m.useRef({}),E=m.useRef(null);return m.useEffect(()=>{const k={};p.forEach(N=>{k[N.id]=Number(N.lastRewardAt||0)});const j=R.current||{};p.forEach(N=>{const C=Number(N.id),w=k[C]||0,M=Number(j[C]||0);if(w>0&&w!==M){y(_=>({..._,[C]:!0}));const B=A.current.get(C);B&&clearTimeout(B);const H=setTimeout(()=>{y(_=>({..._,[C]:!1})),A.current.delete(C)},mw);A.current.set(C,H)}}),R.current=k},[p]),m.useEffect(()=>{function k(N){const C=hw[N];if(!C||d<=0)return;let w=E.current;if(!w){const _=window.AudioContext||window.webkitAudioContext;if(!_)return;w=new _,E.current=w}const M=w.createOscillator(),B=w.createGain();M.type="square",M.frequency.value=C;const H=.08*d;B.gain.setValueAtTime(1e-4,w.currentTime),B.gain.exponentialRampToValueAtTime(Math.max(1e-4,H),w.currentTime+.01),B.gain.exponentialRampToValueAtTime(1e-4,w.currentTime+.11),M.connect(B),B.connect(w.destination),M.start(),M.stop(w.currentTime+.12)}function j(N={}){const C=Number(N.buttonId);if(!Number.isFinite(C)||C<1||C>4)return;x(B=>({...B,[C]:!0}));const w=b.current.get(C);w&&clearTimeout(w);const M=setTimeout(()=>{x(B=>({...B,[C]:!1})),b.current.delete(C)},dw);b.current.set(C,M),k(C)}return s.on("buttonBox:increment",j),()=>{s.off("buttonBox:increment",j)}},[d,s]),r.jsxs("section",{className:"panel-section space-y-1 text-base",children:[r.jsx("header",{className:"text-center text-sm text-slate-300",children:r.jsx("p",{children:"Button Box"})}),r.jsx("div",{className:"grid grid-cols-4 gap-1",children:p.map(k=>{const j=Number(k.id),N=Number.isFinite(k.count)?k.count:0,C=Number.isFinite(k.goal)?k.goal:0,w=typeof k.rewardName=="string"&&k.rewardName.trim()?k.rewardName.trim():"Unassigned",M=Number.isFinite(k.rewardNumber)?k.rewardNumber:"?",B=!!h[j],H=!!g[j];return r.jsxs("article",{className:["rounded bg-slate-800/70 p-1 text-center shadow-sm ring-1 ring-white/10 transition-colors duration-200",B?"bg-cyan-900/70 ring-1 ring-cyan-400/70":"",H?"bg-fuchsia-900/70 ring-1 ring-fuchsia-400/80":""].filter(Boolean).join(" "),children:[r.jsxs("p",{className:"text-xs text-slate-300",children:["Button ",j]}),r.jsxs("p",{className:"text-sm font-semibold text-white",children:[N," / ",C]}),r.jsxs("p",{className:"truncate text-[0.7rem] text-slate-200",children:["#",M," ",w]})]},j)})})]})}function pw(){const{state:{roverId:n}}=_t(),i=cl(n)?.sensors||{};return r.jsx("section",{className:"panel-section",children:r.jsx("div",{className:"aspect-square w-full",children:r.jsx(qf,{sensors:i})})})}function xw(){const{state:{roverId:n,keymap:s,camera:i,horn:o},pipeline:f,actions:{setServoAngle:d,setNightVision:p,startHorn:h,stopHorn:x}}=_t(),g=pg(n),y=g.docked&&!g.driving,b=i?.config,A=!!(n&&i?.enabled&&b),R=!!(n&&f?.nightVision),E=f?.nightVisionState,k=!!(n&&f?.horn),j=o?.overheated,N=typeof b?.minAngle=="number"?b.minAngle:-30,C=typeof b?.maxAngle=="number"?b.maxAngle:30,w=typeof i?.angle=="number"?i.angle:typeof b?.homeAngle=="number"?b.homeAngle:(N+C)/2,M=bn(s?.nightVisionToggle?.[0]),B=bn(s?.hornHonk?.[0]),H=bn(s?.cameraUp?.[0]),_=bn(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(xg,{layout:"desktop",expand:!0,driveDockState:g}),y?null:r.jsxs("div",{className:"surface space-y-0.5 p-0 text-sm text-slate-200",children:[R&&r.jsx(gg,{nightVisionOn:E?.nightVisionOn,disabled:!n,onToggle:p,keyLabel:M}),k&&r.jsx(vg,{disabled:!n||j,onStart:h,onStop:x,keyLabel:B,active:o?.active,heat:o?.heat}),A&&r.jsx(yg,{value:w,min:N,max:C,onChange:d,keyDownLabel:_,keyUpLabel:H,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 gw({layout:n,onOpenHelpOverlay:s}){const{session:i}=Le(),{state:o}=_t(),{value:f}=Fe("vipAudio",{openMicEnabled:!1,pttMode:"live"}),d=i?.isVerified?"bg-emerald-400":"bg-red-600",p=String(i?.assignment?.roverId||"").trim(),h=p?i?.audioForward?.[p]:null,x=!!o?.mic?.pttActive,g=!!f?.openMicEnabled,y=f?.pttMode==="clip"?"clip":"live",b=!!(p&&i?.isVerified&&(y==="clip"?x:g||x)),A=!!(p&&i?.isVerified&&y==="clip"&&h?.source==="upload"&&h?.state==="playing");return r.jsx("section",{className:"panel text-base",children:r.jsxs(cd,{defaultTab:"telemetry",children:[r.jsxs(ud,{children:[r.jsx(Pt,{id:"telemetry",children:"Controls"}),r.jsx(Pt,{id:"vip",highlight:A?"green":b?"pink":"none",children:r.jsxs("span",{className:"inline-flex items-center gap-2",children:[r.jsx("span",{children:"VIP"}),r.jsx("span",{className:`inline-block h-3 w-3 rounded-full ${d}`,"aria-hidden":"true",title:i?.isVerified?"Verified":"Not verified"})]})}),r.jsx(Pt,{id:"help",children:"Help"}),r.jsx(Pt,{id:"settings",children:"Settings"})]}),r.jsxs(fd,{children:[r.jsx(Wt,{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(pw,{}),r.jsx(xw,{})]}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.9fr)_minmax(0,0.75fr)]",children:[r.jsx(No,{}),r.jsx(Xf,{panelId:"replay-sources-desktop",fillHeight:!0}),r.jsx(GN,{})]}),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(Ao,{fillHeight:!0}),r.jsxs("div",{className:"grid min-h-0 gap-0.5 grid-rows-[minmax(0,1fr)_auto]",children:[r.jsx(mo,{compact:!0,hideNicknameForm:!0,fillHeight:!0}),r.jsx($N,{compact:!0})]})]}),r.jsx(Ng,{}),r.jsx(Og,{}),r.jsx(ed,{defaultOrientation:"horizontal",panelId:"rightpane-telemetry"})]})}),r.jsx(Wt,{id:"vip",keepMounted:!0,children:r.jsx(_g,{})}),r.jsx(Wt,{id:"help",children:r.jsx(Tg,{layout:n,onOpenOverlay:s})}),r.jsx(Wt,{id:"settings",children:r.jsx(Mg,{})})]})]})})}const vw=new Set(["admin","lockdown","lockdown-admin"]),yw=new Set(["lockdown","lockdown-admin"]),bw=new Set(["admin","lockdown"]);function Sw(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 Aw(){const{session:n}=Le(),s=n?.mode,i=n?.role,o=n?.adminReason?.text||"";n?.adminReason?.updatedAt;const f=n?.timezone||"UTC",d=n?.socials?.find(A=>String(A?.id||A?.label||"").toLowerCase()==="discord")?.url||n?.discord?.invite||null,p=bw.has(s),h=s==="lockdown"?yw.has(i):vw.has(i),[x,g]=m.useState(()=>new Date),y=m.useMemo(()=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:f,hour:"numeric",minute:"2-digit",second:"2-digit"}).format(x)}catch{return x.toLocaleTimeString()}},[x,f]);if(m.useEffect(()=>{const A=setInterval(()=>g(new Date),1e3);return()=>clearInterval(A)},[]),!p||h)return null;const b=Sw(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:b.title}),r.jsx("p",{className:"text-sm text-slate-300",children:b.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: ",y]})]}),r.jsx("div",{className:"surface-muted",children:r.jsx(wg,{})}),r.jsx("div",{className:"w-full justify-center items-center",children:r.jsx(sd,{id:"discord",label:"Join our Discord server for updates!",url:d})}),"You can still use the chat while the server is locked:",r.jsxs("div",{className:"max-h-80 overflow-y-auto",children:[r.jsx(Ao,{}),r.jsx(jo,{})]})]})})}const jw="/assets/turn_alert-DVO8EZJa.mp3";function Nw(n,s=1){const i=m.useRef(null);return m.useEffect(()=>{i.current=new Audio(n),i.current.volume=s,i.current.load()},[n,s]),()=>{i.current&&(i.current.volume=s,i.current.currentTime=0,i.current.play().catch(()=>{}))}}function ww(){const{session:n,pushAlert:s}=Le(),{value:i}=Fe("audio",St),o=Number.isFinite(i?.masterVolume)?i.masterVolume:St.masterVolume,f=Number.isFinite(i?.alertVolume)?i.alertVolume:St.alertVolume,d=Math.max(0,Math.min(1,o*f)),p=Nw(jw,d),h=m.useRef(new Set),x=m.useMemo(()=>n?.turnQueues||{},[n?.turnQueues]),g=n?.socketId||null;return m.useEffect(()=>{if(!g)return;const y=[];Object.entries(x).forEach(([b,A])=>{!A||!A.current||A.current!==g||h.current.has(b)||(y.push(b),h.current.add(b))}),Object.keys(x).forEach(b=>{(!x[b]||x[b].current!==g)&&h.current.delete(b)}),y.length!==0&&(y.forEach(b=>{const A=n?.roster?.find(R=>String(R.id)===String(b))?.name||b;s({title:"Your turn!",message:`You now control ${A}.`,color:"#ff5722"})}),p())},[x,p,s,n?.roster,g]),null}function Cw({visible:n,mode:s,onEnterFullscreen:i,onDismiss:o}){if(!n)return null;const f=s==="pwa-hint";return r.jsx("div",{className:"fixed inset-0 z-40 flex items-end justify-center p-2 pointer-events-none sm:items-center",children:r.jsx("div",{className:"pointer-events-auto w-full max-w-sm rounded-lg border border-cyan-500/40 bg-zinc-950/95 shadow-xl",children:r.jsxs("div",{className:"space-y-0.5 p-4 text-sm text-slate-100",children:[r.jsx("h2",{className:"text-base font-semibold text-white",children:"Better in fullscreen"}),f?r.jsxs("p",{className:"text-slate-300",children:["For fullscreen on iOS, open Safari's share menu and pick ",r.jsx("strong",{children:"Add to Home Screen"}),". Launching from the home screen removes the browser chrome."]}):r.jsx("p",{className:"text-slate-300",children:"Enable fullscreen to free up more space for the video feed and controls. You can exit fullscreen at any time via the system back or home gesture."}),r.jsxs("div",{className:"flex justify-end gap-0.5 pt-1 text-sm",children:[r.jsx("button",{type:"button",className:"rounded border border-slate-600 px-3 py-1 text-slate-200",onClick:o,children:f?"Got it":"Not now"}),!f&&r.jsx("button",{type:"button",className:"rounded bg-cyan-500 px-3 py-1 font-semibold text-black hover:bg-cyan-400",onClick:i,children:"Enter fullscreen"})]})]})})})}function Ew({side:n="right",onClick:s}){const i=n==="left"?"left-2":"right-2";return r.jsx("button",{type:"button",onClick:s,className:`fixed bottom-2 ${i} 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 Bg="fullscreenPromptDismissed",kw=new Set(["mobile-portrait","mobile-landscape"]),Lg=()=>{if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}},Mw=()=>{const n=Lg();if(!n)return!1;try{return n.getItem(Bg)==="1"}catch{return!1}},ux=()=>{const n=Lg();if(n)try{n.setItem(Bg,"1")}catch{}},qw=()=>{if(typeof navigator>"u")return!1;const n=navigator.userAgent||navigator.platform||"";return/iphone|ipad|ipod/i.test(n)},fx=()=>{if(typeof document>"u")return!1;const n=document;return!!(n.fullscreenEnabled||n.webkitFullscreenEnabled||n.mozFullScreenEnabled||n.msFullscreenEnabled)};function Rw(n){const s=kw.has(n),[i,o]=m.useState(!1),[f,d]=m.useState("native"),[p,h]=m.useState(!1),x=m.useMemo(()=>qw(),[]),g=m.useMemo(()=>fx(),[]),y=m.useCallback(()=>{if(!s){o(!1),h(!1);return}if(!p&&Mw()){o(!1);return}if(x){d("pwa-hint"),o(!0);return}if(!fx()){o(!1);return}if(typeof document<"u"&&document.fullscreenElement){o(!1);return}d("native"),o(!0)},[p,x,s]);m.useEffect(()=>{y()},[y]),m.useEffect(()=>{if(typeof document>"u")return;const E=()=>{if(document.fullscreenElement){h(!1),o(!1);return}y()};return document.addEventListener("fullscreenchange",E),document.addEventListener("webkitfullscreenchange",E),()=>{document.removeEventListener("fullscreenchange",E),document.removeEventListener("webkitfullscreenchange",E)}},[y]);const b=m.useCallback(()=>{ux(),h(!1),o(!1)},[]),A=m.useCallback(async()=>{if(!s||x||typeof document>"u")return!1;if(document.fullscreenElement)return!0;const E=document.documentElement;if(!E)return!1;const k=E.requestFullscreen||E.webkitRequestFullscreen||E.mozRequestFullScreen||E.msRequestFullscreen;if(!k)return!1;try{const j=k.call(E);return j&&typeof j.then=="function"&&await j,ux(),h(!1),o(!1),!0}catch(j){return console.warn("Failed to enter fullscreen",j),!1}},[x,s]),R=m.useCallback(()=>{s&&(h(!0),d(x?"pwa-hint":"native"),o(!0))},[x,s]);return m.useEffect(()=>{s||(h(!1),o(!1))},[s]),{visible:i,mode:f,isIOS:x,nativeSupported:g,enterFullscreen:A,dismiss:b,showPrompt:R}}function Tw({visible:n,layout:s,onClose:i,showOnLoad:o,onToggleShowOnLoad:f}){if(!n)return null;const{state:d}=_t(),p=h=>{const x=!h.target.checked;f?.(x)};return r.jsx("div",{className:"fixed inset-0 z-30 flex items-center justify-center bg-black/80 px-0.5 py-0.5",children:r.jsxs("div",{className:"pointer-events-auto surface w-full max-w-4xl max-h-[90vh] overflow-hidden shadow-2xl",children:[r.jsxs("div",{className:"flex items-center justify-between border-b border-slate-700 px-0.5 py-0.25 text-sm text-slate-200",children:[r.jsx("span",{className:"font-semibold",children:"Help & controls"}),r.jsxs("div",{className:"flex items-center gap-0.5 text-[0.8rem] text-slate-300",children:[r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!o,onChange:p,className:"accent-cyan-500"}),r.jsx("span",{children:"Don't show again"})]}),r.jsx("button",{type:"button",onClick:i,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(Rg,{layout:s,keymap:d?.keymap||{}})})]})})}const Dw=`aroma +`).trim();if(P){C(!0);try{await h(P,J),j(""),b(),A(!1)}catch(ne){alert(ne.message)}finally{C(!1)}}}const de=i?"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 ${i?"flex h-full flex-col overflow-hidden":""}`,children:[r.jsxs("div",{className:`surface overflow-y-auto space-y-0.5 px-0 ${de}`,ref:te,children:[T.length===0&&X.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"No messages yet."}):T.map(q=>r.jsx(Kf,{message:q},q.id)),X.map(q=>r.jsx(tg,{message:q},`typing-${q.typingId||q.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:k,onChange:q=>{const V=q.target.value;j(V),A(!!V.trim())},onFocus:q=>{g(q),A(!!k.trim())},onBlur:q=>{y(q),A(!1)},onKeyDown:q=>{q.key==="Enter"&&!k.trim()&&(q.preventDefault(),b(),A(!1))},ref:q=>x(q,{target:"panel"}),placeholder:F?"Type a message…":s?"":"Spectators cannot chat",disabled:!F}),Y&&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:w,onChange:q=>M(q.target.checked),className:"accent-cyan-500"}),r.jsx("span",{children:"Speak"})]}),r.jsxs("select",{value:B,onChange:q=>{const V=q.target.value;H(V),E(P=>({...P||{},engine:V}))},className:"field-input text-xs",children:[r.jsx("option",{value:"flite",children:"flite"}),r.jsx("option",{value:"espeak",children:"espeak"})]}),B==="flite"?r.jsx("select",{value:_,onChange:q=>{const V=q.target.value;K(V),E(P=>({...P||{},voice:V}))},className:"field-input text-xs",children:zN.map(q=>r.jsx("option",{value:q,children:q},q))}):r.jsx("select",{value:L,onChange:q=>{const V=Number(q.target.value);U(V),E(P=>({...P||{},pitch:V}))},className:"field-input text-xs",children:UN.map(q=>r.jsxs("option",{value:q,children:["pitch ",q]},q))})]}),r.jsx("button",{type:"submit",disabled:!F||N,className:"button-dark h-full disabled:opacity-50 self-stretch",children:N?"...":"Send"})]})]})}function jo({compact:n=!1}){const{session:s,setNickname:i}=Le(),{value:o,save:f}=Fe("profile",{nickname:""}),[d,p]=m.useState(o.nickname||""),[h,x]=m.useState(!1),g=s?.role!=="spectator";m.useEffect(()=>{p(o.nickname||"")},[o.nickname]);async function y(b){if(b.preventDefault(),!g)return;const A=(d||"").trim().slice(0,32);if(A){x(!0);try{await i(A),f({nickname:A})}catch(R){alert(R.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:y,children:[r.jsx("input",{className:"field-input flex-1 min-w-0",value:d,onChange:b=>p(b.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 HN(n){const s=Array.isArray(n?.socials)?n.socials:null;if(s&&s.length)return s;const i=[];return n?.discord?.invite&&i.push({id:"discord",label:"Discord",url:n.discord.invite}),n?.kofi?.link&&i.push({id:"kofi",label:"Ko-fi",url:n.kofi.link}),i}function VN(n){if(!n||typeof n!="object")return null;const s=n.id||n.service||n.key||n.name||null,i=n.label||n.title||n.name||s||"Link",o=n.url||n.link||n.href||null;return o?{id:s,label:i,url:o}:null}function Dg({className:n=""}){const{session:s}=Le(),i=HN(s).map(VN).filter(Boolean).slice(0,4);return i.length?r.jsx("div",{className:`grid grid-cols-2 grid-rows-2 gap-0.5 ${n}`,children:i.map(o=>r.jsx(sd,{...o},`${o.id||o.label}-${o.url}`))}):null}function $N({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(jo,{compact:n})})})}function GN(){return r.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:r.jsx(Dg,{className:"flex-1 min-h-0"})})}function df(...n){return n.filter(Boolean).join(" ")}function YN(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function FN(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function XN(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 QN(n,s){if(!n)return"";const i=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${i} (you)`:i}function No({title:n="Rovers"}){const{session:s,requestControl:i}=Le(),[o,f]=m.useState({}),[d,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??[],y=s?.turnQueues??{},b=s?.users??[],A=s?.socketId||null,R=m.useMemo(()=>Object.values(y||{}).some(N=>N?.deadline||N?.idleDeadline),[y]);m.useEffect(()=>{if(!R)return;const N=setInterval(()=>{p(Date.now())},1e3);return()=>clearInterval(N)},[R]);const E=m.useMemo(()=>{const N=new Set(g.map(w=>String(w.id))),C=Object.keys(y||{}).filter(w=>!N.has(String(w))).map(w=>({id:w,name:w,locked:!1,batteryState:null}));return[...g,...C]},[g,y]);async function k(N){if(N){f(C=>({...C,[N]:!0}));try{await i(N)}catch(C){alert(C.message)}finally{f(C=>({...C,[N]:!1}))}}}const j=N=>b.find(C=>C.socketId===N)||{socketId:N,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}),E.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:E.map(N=>{const C=String(N.id),w=y?.[C]||null,M=w?.queue||[],B=w?.idleDeadline||w?.deadline||null,H=B&&B>d?Math.ceil((B-d)/1e3):B?0:null,_=w?.current||null,K=_?M.findIndex(se=>se===_):-1,L=M.length>1?K>=0?M[(K+1)%M.length]:M[0]:null,U=!!(A&&_&&_===A),F=!!(A&&L&&L===A),te=H!=null&&(U||F),fe=!!N.locked,ce=fe&&!x,Y=!!(N?.private?.enabled&&N?.private?.open),T=N.lockReason?`locked: ${N.lockReason}`:"locked",X=fe?T:o[C]?"...":"request",J=h&&!ce&&!o[C];return r.jsxs("li",{className:df("surface flex flex-wrap items-start justify-between gap-0.5",J&&"cursor-pointer",fe?"bg-red-900/40":Y?"bg-amber-700/35 border border-amber-200/30":null),onClick:()=>{J&&k(N.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:ra(N.color,.16),children:N.name})}),te?r.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem] text-slate-200",children:U?`${H}s left`:`Your turn in ${H}s`}):null]}),r.jsx("span",{className:df("text-[0.75rem] font-semibold",FN(N)),children:YN(N)})]}),M.length===0?r.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"No queue."}):r.jsx("div",{className:"flex flex-wrap items-center gap-0.5",children:M.map((se,de)=>{const q=j(se),V=se===_,P=!!(L&&se===L&&!V),ne=V?"bg-sky-600 text-white ring-2 ring-amber-300":P?"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] ${ne}`,children:[r.jsx("span",{className:`${XN(q.role)} font-semibold`,children:QN(q,A)}),V&&r.jsx("span",{className:"text-[0.65rem] text-slate-200",children:"now"}),P&&r.jsx("span",{className:"text-[0.65rem] text-emerald-100",children:"next"})]},`${C}-${se}-${de}`)})})]}),h?r.jsx("button",{type:"button",onClick:se=>{se.stopPropagation(),k(N.id)},disabled:o[C]||ce,className:df("button-dark disabled:opacity-40",fe&&"bg-red-600/70 text-white hover:bg-red-600"),children:X}):null]},N.id)})})]})}function KN(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 ZN(n,s){if(!n)return"";const i=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${i} (you)`:i}function mo({hideNicknameForm:n=!1,hideHeader:s=!1,className:i="",fillHeight:o=!1,compact:f=!1}){const{session:d}=Le(),p=d?.role!=="spectator",h=d?.users??[],x=d?.socketId||null,g=m.useMemo(()=>[...h].sort((b,A)=>b.socketId===x?-1:A.socketId===x?1:(b.nickname||"").localeCompare(A.nickname||"")),[x,h]),y=o?"flex-1 min-h-0 overflow-y-auto":f?"h-28 overflow-y-auto":"h-48 overflow-y-auto";return r.jsxs("section",{className:`panel-section space-y-0.5 text-base ${o?"flex h-full min-h-0 flex-col overflow-hidden":""} ${i}`,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(jo,{compact:f})})}),r.jsx(Dg,{})]}),!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 ${f?"text-xs":""}`,children:[r.jsx("span",{children:"Users"}),r.jsx("span",{className:"text-xs text-slate-500",children:g.length})]}),r.jsx("div",{className:`surface flex flex-wrap content-start items-start gap-0.5 px-0 pb-0 ${y} ${f?"text-[0.8rem]":""}`,children:g.length===0?r.jsx("p",{className:"text-sm text-slate-500",children:"Waiting for users…"}):g.map(b=>r.jsx("span",{className:`rounded bg-slate-800/80 px-1 py-0.25 text-[0.7rem] ${KN(b.role)}`,children:ZN(b,x)},b.socketId))})]})]})}const IN=/^cu_[a-f0-9]{32}$/,ji="field-input w-full max-w-sm text-left focus:ring-emerald-500",wo="mx-auto w-full max-w-xl flex justify-center",hi="mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center";function JN(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 ix=8*1024*1024,ss=16e3,PN={iceServers:[{urls:"stun:stun.l.google.com:19302"}],bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"};function rx(n){let s="";for(let o=0;o{if(!n||n.iceGatheringState==="complete"){i();return}const o=setTimeout(()=>{n.removeEventListener("icegatheringstatechange",f),i()},s);function f(){n.iceGatheringState==="complete"&&(clearTimeout(o),n.removeEventListener("icegatheringstatechange",f),i())}n.addEventListener("icegatheringstatechange",f)})}function ox(n){if(!n)return!1;const s=n.connectionState,i=n.iceConnectionState;return s==="connected"||i==="connected"||i==="completed"}function nw(n,s=1e4){return new Promise((i,o)=>{if(!n){o(new Error("Peer connection missing"));return}if(ox(n)){i();return}const f=setTimeout(()=>{p(),o(new Error("Peer connection timeout"))},s),d=()=>{ox(n)?(p(),i()):(n.connectionState==="failed"||n.connectionState==="closed"||n.iceConnectionState==="failed")&&(p(),o(new Error(`Peer connection ${n.connectionState||n.iceConnectionState}`)))};function p(){clearTimeout(f),n.removeEventListener("connectionstatechange",d),n.removeEventListener("iceconnectionstatechange",d)}n.addEventListener("connectionstatechange",d),n.addEventListener("iceconnectionstatechange",d)})}async function aw(n){if(!n?.getParameters||!n?.setParameters)return;const s=n.getParameters()||{},i=s.encodings&&s.encodings[0]||{};s.encodings=[{...i,maxBitrate:64e3,dtx:"disabled"}];try{await n.setParameters(s)}catch{}}function sw(n,s=6e3){return new Promise((i,o)=>{if(!n){o(new Error("Peer connection missing"));return}const f=Date.now();let d=-1;const p=setInterval(async()=>{if(Date.now()-f>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 y of g.values()){if(y.type!=="outbound-rtp"||y.kind!=="audio")continue;const b=Number(y.bytesSent||0),A=Number(y.packetsSent||0);if(d<0)d=b;else if(b>d+200||A>5){clearInterval(p),i();return}}}}catch{}},250)})}function mn({label:n,active:s,detail:i=""}){return r.jsxs("div",{className:`rounded-md px-0.5 py-0.5 text-xs text-slate-100 ${s?"bg-emerald-500":"bg-slate-700"}`,children:[r.jsx("div",{className:"text-center font-medium",children:n}),r.jsx("div",{className:"text-center text-[0.72rem] opacity-90",children:i||(s?"active":"idle")})]})}function cx({label:n}){return n?r.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function lw(n){const s=n.reduce((f,d)=>f+d.length,0),i=new Float32Array(s);let o=0;for(const f of n)i.set(f,o),o+=f.length;return i}function iw(n){const s=new Int16Array(n.length);for(let i=0;i{for(let y=0;yy&&s?.[y]||null,[s,y]),P=!!(V&&V.state!=="offline"&&!V.error),ne=V?.source==="upload"&&V?.state==="playing",pe=V?.source==="mic-whip"&&(V?.state==="starting"||V?.state==="playing"),ie=!!(!N&&L.current&&(k||q)),oe=!N&&(C==="live"||C==="starting"),ve=N&&M==="recording",ye=N&&M==="sending",xe=bn(h?.keymap?.micPtt?.[0])||"M",Ue=m.useCallback(me=>{const we=me==="clip"?"clip":"live";g(et=>({...et||{},pttMode:we}))},[g]),$e=async()=>{if(!y){_("Take control of your rover first.");return}if(!b){_("Select an audio file first.");return}if(b.size>ix){_(`File too large (max ${ix} bytes).`);return}E(!0),_("");try{const me=await b.arrayBuffer(),we=rx(new Uint8Array(me));await i?.({roverId:y,name:b.name,mime:b.type||"",dataBase64:we}),_("Upload playback started.")}catch(me){_(me?.message||"Failed to play upload.")}finally{E(!1)}},Ne=async()=>{if(!y){_("Take control of your rover first.");return}E(!0),_("");try{await o?.(y),_("Upload playback stopped.")}catch(me){_(me?.message||"Failed to stop upload.")}finally{E(!1)}},ae=m.useCallback(async me=>{const we=String(me||te.current||"").trim();if(F.current=!1,w("idle"),U.current){try{U.current.getSenders().forEach(et=>et.track?.stop())}catch{}try{U.current.close()}catch{}}if(U.current=null,K.current)try{K.current.getTracks().forEach(et=>et.stop())}catch{}if(K.current=null,L.current=null,we)try{await p?.(we)}catch{}te.current=""},[p]),ue=m.useCallback(async me=>{const we=await f?.(me),et=String(we?.whipUrl||"").trim(),dt=String(we?.token||"").trim();if(!et||!dt)throw new Error("WHIP endpoint unavailable");const ze=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}});K.current=ze;const xt=ze.getAudioTracks()?.[0];if(L.current=xt||null,xt&&(xt.enabled=!!(k||q)),xt?.applyConstraints)try{await xt.applyConstraints({channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1})}catch{}const mt=new RTCPeerConnection(PN);U.current=mt,mt.onconnectionstatechange=()=>{if(!F.current)return;const Gt=mt.connectionState;if(Gt==="connected"){w("live");return}(Gt==="failed"||Gt==="disconnected"||Gt==="closed")&&(w("error"),_(`WHIP transport ${Gt}.`))},ze.getAudioTracks().forEach(Gt=>{const Oa=mt.addTrack(Gt,ze);aw(Oa)});const Tn=await mt.createOffer({offerToReceiveAudio:!1,offerToReceiveVideo:!1});await mt.setLocalDescription(Tn),await tw(mt,1800);const kt=await fetch(et,{method:"POST",headers:{"Content-Type":"application/sdp",...ew(dt)},body:mt.localDescription?.sdp||Tn.sdp});if(!kt.ok)throw new Error(`WHIP request failed: ${kt.status}`);const cs=await kt.text();await mt.setRemoteDescription({type:"answer",sdp:cs}),await nw(mt,1e4),await sw(mt,6e3),await d?.(me)},[k,q,d,f]),be=m.useCallback(async()=>{if(se.current=!1,T.current){try{T.current.disconnect()}catch{}T.current.onaudioprocess=null}if(Y.current)try{Y.current.disconnect()}catch{}if(X.current)try{X.current.disconnect()}catch{}if(fe.current)try{fe.current.getTracks().forEach(me=>me.stop())}catch{}if(ce.current)try{await ce.current.close()}catch{}J.current=[],T.current=null,Y.current=null,X.current=null,fe.current=null,ce.current=null,de.current=ss},[]),Me=m.useCallback(async()=>{if(fe.current&&ce.current&&T.current)return;B(xt=>xt==="recording"?xt:"arming");const me=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:ss,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}}),we=new AudioContext({latencyHint:"interactive"}),et=we.createMediaStreamSource(me),dt=we.createScriptProcessor(1024,1,1),ze=we.createGain();ze.gain.value=0,dt.onaudioprocess=xt=>{if(!se.current)return;const mt=xt.inputBuffer.getChannelData(0);J.current.push(new Float32Array(mt))},et.connect(dt),dt.connect(ze),ze.connect(we.destination),fe.current=me,ce.current=we,Y.current=et,T.current=dt,X.current=ze,de.current=we.sampleRate||ss},[]),le=m.useCallback(async({send:me})=>{const we=se.current;if(se.current=!1,!we){me||B("idle");return}const et=J.current;if(J.current=[],!me){B("idle");return}if(!y){B("idle");return}if(!et.length){B("idle");return}B("sending");try{const dt=lw(et),ze=rw(dt,de.current||ss),xt=rx(ze);await i?.({roverId:y,name:`ptt-${Date.now()}.wav`,mime:"audio/wav",dataBase64:xt}),B("idle")}catch(dt){B("error"),_(dt?.message||"Failed to send PTT clip.")}},[i,y]),re=m.useCallback(async()=>{if(!y){_("Take control of your rover first.");return}await Me(),J.current=[],se.current=!0,B("recording")},[Me,y]);return m.useEffect(()=>{let me=!1;async function we(){if(N){await ae(te.current||y);return}if(!y){await ae(te.current);return}if(!(F.current&&te.current===y)&&!(!k&&!q))try{w("starting"),_(""),F.current=!0,te.current=y,await ue(y),me||w("live")}catch(et){me||(w("error"),_(et?.message||"Failed to start mic forwarding.")),await ae(y)}}return we(),()=>{me=!0}},[N,k,q,y,ue,ae]),m.useEffect(()=>{const me=L.current;me&&(me.enabled=!!(!N&&(k||q)))},[N,k,q]),m.useEffect(()=>{let me=!1;async function we(){if(!N||!y){se.current&&await le({send:!1}),B("idle");return}try{await Me(),!me&&!se.current&&B("idle")}catch(et){me||(B("error"),_(et?.message||"Microphone access failed for clip mode."))}}return we(),()=>{me=!0}},[N,Me,le,y]),m.useEffect(()=>{let me=!1;async function we(){if(N){if(!y){se.current&&await le({send:!1});return}if(q){if(!se.current)try{_(""),await re()}catch(et){me||(B("error"),_(et?.message||"Failed to start clip recording."))}}else se.current&&await le({send:!0})}}return we(),()=>{me=!0}},[N,le,q,y,re]),m.useEffect(()=>()=>{ae(te.current||y),be()},[y,ae,be]),r.jsxs("div",{className:"grid gap-0.5",children:[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(cx,{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 ${N?"":"bg-emerald-500 text-white hover:bg-emerald-500"}`,onClick:()=>Ue("live"),children:"Live Mic (WHIP)"}),r.jsx("button",{type:"button",className:`button-dark w-full text-sm ${N?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,onClick:()=>Ue("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(mn,{label:"Mode",active:N,detail:N?"record clip":"live mic"}),r.jsx(mn,{label:"PTT hold",active:q,detail:q?"held":"released"}),r.jsx(mn,{label:"Recording",active:ve,detail:ve?"capturing":"idle"}),r.jsx(mn,{label:"Playback",active:N&&ne,detail:N&&ne?"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:`${ji} text-center`,type:"file",accept:".mp3,.wav,.ogg,audio/mpeg,audio/wav,audio/ogg",disabled:R||!y,onChange:me=>A(me.target.files?.[0]||null)})]}),r.jsx("div",{className:"mx-auto w-full max-w-sm text-center",children:b?r.jsxs("div",{className:"surface-muted text-xs text-slate-300",children:[b.name," (",b.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:R||!y,onClick:$e,children:R?"Working...":"Play Upload"}),r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:R||!y,onClick:Ne,children:"Stop"})]})]})}),r.jsx("section",{className:"surface h-full",children:r.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[r.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Live Microphone"}),r.jsxs("label",{className:"surface-muted mx-auto flex w-full max-w-sm items-center justify-center gap-0.5 px-0.5 py-0.5 text-xs text-slate-300",children:[r.jsx("input",{type:"checkbox",checked:k,disabled:!y||N,onChange:me=>g(we=>({...we||{},openMicEnabled:!!me.target.checked}))}),r.jsx("span",{children:N?"Open mic (live mode only)":"Open mic"})]}),r.jsxs("div",{className:"grid gap-0.5 content-start",children:[r.jsx(mn,{label:"WHIP link",active:oe,detail:C}),r.jsx(mn,{label:"Mic hot",active:ie,detail:ie?"transmitting":"muted"}),r.jsxs("div",{className:"surface-muted text-center text-xs text-slate-400",children:["Hold ",r.jsx(cx,{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(mn,{label:"Forward pipe",active:P,detail:P?"connected":"offline"}),r.jsx(mn,{label:"Upload playback",active:ne,detail:ne?"playing":"idle"}),r.jsx(mn,{label:"Mic relay",active:pe,detail:pe?"active":"idle"}),r.jsx(mn,{label:"WHIP transport",active:oe,detail:C}),r.jsx(mn,{label:"Clip recording",active:ve,detail:ve?"recording":"idle"}),r.jsx(mn,{label:"Clip sending",active:ye,detail:ye?"sending":"idle"})]}),H?r.jsx("div",{className:"text-xs text-slate-400 text-center",children:H}):null]})})]})}function cw({pendingRequestId:n,currentStoredKey:s,nickname:i,requestVerification:o,applyIdentityKey:f,onMessage:d,fullWidth:p=!1}){const[h,x]=m.useState(0),[g,y]=m.useState(""),[b,A]=m.useState(!1),[R,E]=m.useState(!1),k=()=>{x(1),y(s),A(!1),d?.("")},j=()=>{x(0),A(!1)},N=async w=>{if(w.preventDefault(),!b){d?.("Please confirm your nickname agreement before sending.");return}if(h<3){d?.("Complete all request steps before sending.");return}E(!0),d?.("");try{const M=await f(g);await o?.(),y(M),x(0),A(!1),d?.("Verification request sent to lockdown admins.")}catch(M){d?.(M.message||"Failed to submit request.")}finally{E(!1)}},C=p?"w-full":wo;return n?r.jsx("section",{className:`surface text-sm text-slate-300 ${C}`,children:r.jsxs("div",{className:hi,children:["Verification request pending: ",n]})}):h===0?r.jsx("section",{className:`surface ${C}`,children:r.jsxs("div",{className:hi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Verification"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:k,disabled:R,children:"Request Verification"})]})}):r.jsx("form",{className:`surface ${C}`,onSubmit:N,children:r.jsxs("div",{className:hi,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(jo,{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:i||"(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:b,onChange:w=>A(w.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:!i||!b,onClick:()=>x(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:j,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:ji,type:"password",name:"identity_key_request",autoComplete:"current-password",maxLength:35,value:g,onChange:w=>y(w.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:ji,type:"password",name:"identity_key_request_final",autoComplete:"current-password",maxLength:35,value:g,onChange:w=>y(w.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:R||!g,children:"Confirm Request"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(2),children:"Back"})]})]}):null]})})}function uw({currentStoredKey:n,applyIdentityKey:s,onMessage:i,fullWidth:o=!1}){const[f,d]=m.useState(0),[p,h]=m.useState(""),[x,g]=m.useState(!1),y=()=>{d(1),h(""),i?.("")},b=()=>{d(0),h("")},A=async E=>{if(E.preventDefault(),!(f<2)){g(!0),i?.("");try{await s(p),d(0),h(""),i?.("Identity key restored.")}catch(k){i?.(k.message||"Failed to restore key.")}finally{g(!1)}}},R=o?"w-full":wo;return r.jsx("section",{className:`surface ${R}`,children:r.jsxs("div",{className:hi,children:[r.jsx("p",{className:"text-sm text-slate-300",children:"Identity key"}),r.jsxs("p",{className:"text-xs text-slate-500",children:["Current: ",JN(n)||"not set yet"]}),r.jsx("input",{className:ji,type:"password",name:"identity_key_current",autoComplete:"current-password",maxLength:35,value:n,readOnly:!0,placeholder:"Identity key"}),f===0?r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!n,onClick:()=>navigator.clipboard?.writeText(n),children:"Copy Key"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:y,disabled:x,children:"Restore Key"})]}):null,f===1?r.jsxs("div",{className:"space-y-0.5",children:[r.jsx("p",{className:"text-xs text-slate-400",children:"Restoring your key should only be done when needed. Use this to move your identity to another browser."}),r.jsxs("div",{className:"flex justify-center gap-0.5",children:[r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>d(2),children:"Continue"}),r.jsx("button",{type:"button",className:"button-dark text-sm",onClick:b,children:"Cancel"})]})]}):null,f===2?r.jsxs("form",{className:"space-y-0.5",onSubmit:A,children:[r.jsx("input",{className:ji,type:"password",name:"identity_key_restore",autoComplete:"current-password",maxLength:35,value:p,onChange:E=>h(E.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:()=>d(1),children:"Back"})]})]}):null]})})}function fw({requestableRovers:n=[],pendingRequests:s=[],requestPrivateRoverAccess:i,onMessage:o,fullWidth:f=!1}){const[d,p]=m.useState({}),h=m.useMemo(()=>{const y=new Map;return(s||[]).forEach(b=>{b?.roverId&&y.set(String(b.roverId),b)}),y},[s]),x=f?"w-full":wo,g=async y=>{if(y){p(b=>({...b,[y]:!0})),o?.("");try{(await i?.(y))?.existing?o?.("You already have a pending request for that rover."):o?.("Private rover access request sent to lockdown admins.")}catch(b){o?.(b.message||"Failed to send request.")}finally{p(b=>({...b,[y]:!1}))}}};return r.jsx("section",{className:`surface text-sm text-slate-300 ${x}`,children:r.jsxs("div",{className:hi,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(y=>{const b=String(y.id),A=!!d[b],R=h.get(b);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:y.name||b}),r.jsx("p",{className:"truncate text-[0.7rem] text-slate-500",children:b})]}),R?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(b),disabled:A,className:"button-dark text-xs disabled:opacity-50",children:A?"Sending...":"Request"})]},b)})})]})})}function _g(){const{session:n,identifySession:s,requestVerification:i,requestPrivateRoverAccess:o,playUploadedAudio:f,stopUploadedAudio:d,startMicWhip:p,readyMicWhip:h,stopMicWhip:x}=Le(),{value:g,save:y}=Fe("identity",{cookieUserId:""}),{value:b}=Fe("profile",{nickname:""}),A=m.useMemo(()=>(g?.cookieUserId||"").trim(),[g?.cookieUserId]),R=(b?.nickname||"").trim(),E=!!n?.isVerified,k=n?.verification?.pendingRequestId||null,j=n?.privateRoverAccess?.requestableRovers||[],N=n?.privateRoverAccess?.pendingRequests||[],C=String(n?.assignment?.roverId||"").trim(),[w,M]=m.useState(""),B=async H=>{const _=String(H||"").trim().toLowerCase();if(!_)throw new Error("Identity key required.");if(!IN.test(_))throw new Error("Identity key must match format: cu_ + 32 lowercase hex chars.");return y(K=>({...K||{},cookieUserId:_})),await s({cookieUserId:_,nickname:R}),_};return r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-[minmax(0,1.25fr)_minmax(0,0.9fr)]",children:[r.jsx("div",{className:"lg:col-span-2",children:E?r.jsx("section",{className:"surface w-full",children:r.jsxs("div",{className:"mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center",children:[r.jsx("p",{className:"text-sm text-emerald-300",children:"Verification complete"}),r.jsx("p",{className:"text-xs text-slate-400",children:"VIP controls are unlocked for your assigned rover."})]})}):r.jsx(cw,{pendingRequestId:k,currentStoredKey:A,nickname:R,requestVerification:i,applyIdentityKey:B,onMessage:M,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:E?r.jsx(ow,{ownRoverId:C,audioForwardByRover:n?.audioForward||{},playUploadedAudio:f,stopUploadedAudio:d,startMicWhip:p,readyMicWhip:h,stopMicWhip:x}):r.jsx("section",{className:"surface h-full",children:r.jsx("div",{className:"flex h-full flex-col items-center justify-center text-center text-xs text-slate-400",children:"Verify your account to unlock VIP controls."})})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(fw,{requestableRovers:j,pendingRequests:N,requestPrivateRoverAccess:o,onMessage:M,fullWidth:!0})}),r.jsx("div",{className:"lg:col-span-2",children:r.jsx(uw,{currentStoredKey:A,applyIdentityKey:B,onMessage:M,fullWidth:!0})})]}),w?r.jsx("div",{className:wo,children:r.jsx("p",{className:"text-xs text-slate-400 text-center",children:w})}):null]})}const dw=420,mw=1200,hw={1:262,2:330,3:392,4:523};function Og(){const{session:n}=Le(),s=An(),{value:i}=Fe("audio",St),o=Number.isFinite(i?.masterVolume)?i.masterVolume:St.masterVolume,f=Number.isFinite(i?.alertVolume)?i.alertVolume:St.alertVolume,d=Math.max(0,Math.min(1,o*f)),p=m.useMemo(()=>{const k=Array.isArray(n?.buttonBox?.buttons)?n.buttonBox.buttons:[];return k.length===4?k:[1,2,3,4].map(j=>k.find(N=>Number(N?.id)===j)||{id:j,count:0,goal:0,rewardName:null,rewardId:null,rewardNumber:null,lastRewardAt:null})},[n?.buttonBox?.buttons]),[h,x]=m.useState({}),[g,y]=m.useState({}),b=m.useRef(new Map),A=m.useRef(new Map),R=m.useRef({}),E=m.useRef(null);return m.useEffect(()=>{const k={};p.forEach(N=>{k[N.id]=Number(N.lastRewardAt||0)});const j=R.current||{};p.forEach(N=>{const C=Number(N.id),w=k[C]||0,M=Number(j[C]||0);if(w>0&&w!==M){y(_=>({..._,[C]:!0}));const B=A.current.get(C);B&&clearTimeout(B);const H=setTimeout(()=>{y(_=>({..._,[C]:!1})),A.current.delete(C)},mw);A.current.set(C,H)}}),R.current=k},[p]),m.useEffect(()=>{function k(N){const C=hw[N];if(!C||d<=0)return;let w=E.current;if(!w){const _=window.AudioContext||window.webkitAudioContext;if(!_)return;w=new _,E.current=w}const M=w.createOscillator(),B=w.createGain();M.type="square",M.frequency.value=C;const H=.08*d;B.gain.setValueAtTime(1e-4,w.currentTime),B.gain.exponentialRampToValueAtTime(Math.max(1e-4,H),w.currentTime+.01),B.gain.exponentialRampToValueAtTime(1e-4,w.currentTime+.11),M.connect(B),B.connect(w.destination),M.start(),M.stop(w.currentTime+.12)}function j(N={}){const C=Number(N.buttonId);if(!Number.isFinite(C)||C<1||C>4)return;x(B=>({...B,[C]:!0}));const w=b.current.get(C);w&&clearTimeout(w);const M=setTimeout(()=>{x(B=>({...B,[C]:!1})),b.current.delete(C)},dw);b.current.set(C,M),k(C)}return s.on("buttonBox:increment",j),()=>{s.off("buttonBox:increment",j)}},[d,s]),r.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[r.jsx("header",{className:"panel-muted text-center text-sm",children:r.jsx("p",{children:"Button Box"})}),r.jsx("div",{className:"grid grid-cols-4 gap-0.5",children:p.map(k=>{const j=Number(k.id),N=Number.isFinite(k.count)?k.count:0,C=Number.isFinite(k.goal)?k.goal:0,w=typeof k.rewardName=="string"&&k.rewardName.trim()?k.rewardName.trim():"Unassigned",M=Number.isFinite(k.rewardNumber)?k.rewardNumber:"?",B=!!h[j],H=!!g[j];return r.jsxs("article",{className:["surface px-0.5 py-0.5 text-center transition-colors duration-200",B?"border border-cyan-400/70 bg-cyan-900/40":"",H?"border border-fuchsia-400/80 bg-fuchsia-900/40":""].filter(Boolean).join(" "),children:[r.jsxs("p",{className:"text-xs text-slate-400",children:["Button ",j]}),r.jsxs("p",{className:"text-sm font-semibold text-white",children:[N," / ",C]}),r.jsxs("p",{className:"truncate text-[0.7rem] text-slate-300",children:["#",M," ",w]})]},j)})})]})}function pw(){const{state:{roverId:n}}=_t(),i=cl(n)?.sensors||{};return r.jsx("section",{className:"panel-section",children:r.jsx("div",{className:"aspect-square w-full",children:r.jsx(qf,{sensors:i})})})}function xw(){const{state:{roverId:n,keymap:s,camera:i,horn:o},pipeline:f,actions:{setServoAngle:d,setNightVision:p,startHorn:h,stopHorn:x}}=_t(),g=pg(n),y=g.docked&&!g.driving,b=i?.config,A=!!(n&&i?.enabled&&b),R=!!(n&&f?.nightVision),E=f?.nightVisionState,k=!!(n&&f?.horn),j=o?.overheated,N=typeof b?.minAngle=="number"?b.minAngle:-30,C=typeof b?.maxAngle=="number"?b.maxAngle:30,w=typeof i?.angle=="number"?i.angle:typeof b?.homeAngle=="number"?b.homeAngle:(N+C)/2,M=bn(s?.nightVisionToggle?.[0]),B=bn(s?.hornHonk?.[0]),H=bn(s?.cameraUp?.[0]),_=bn(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(xg,{layout:"desktop",expand:!0,driveDockState:g}),y?null:r.jsxs("div",{className:"surface space-y-0.5 p-0 text-sm text-slate-200",children:[R&&r.jsx(gg,{nightVisionOn:E?.nightVisionOn,disabled:!n,onToggle:p,keyLabel:M}),k&&r.jsx(vg,{disabled:!n||j,onStart:h,onStop:x,keyLabel:B,active:o?.active,heat:o?.heat}),A&&r.jsx(yg,{value:w,min:N,max:C,onChange:d,keyDownLabel:_,keyUpLabel:H,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 gw({layout:n,onOpenHelpOverlay:s}){const{session:i}=Le(),{state:o}=_t(),{value:f}=Fe("vipAudio",{openMicEnabled:!1,pttMode:"live"}),d=i?.isVerified?"bg-emerald-400":"bg-red-600",p=String(i?.assignment?.roverId||"").trim(),h=p?i?.audioForward?.[p]:null,x=!!o?.mic?.pttActive,g=!!f?.openMicEnabled,y=f?.pttMode==="clip"?"clip":"live",b=!!(p&&i?.isVerified&&(y==="clip"?x:g||x)),A=!!(p&&i?.isVerified&&y==="clip"&&h?.source==="upload"&&h?.state==="playing");return r.jsx("section",{className:"panel text-base",children:r.jsxs(cd,{defaultTab:"telemetry",children:[r.jsxs(ud,{children:[r.jsx(Pt,{id:"telemetry",children:"Controls"}),r.jsx(Pt,{id:"vip",highlight:A?"green":b?"pink":"none",children:r.jsxs("span",{className:"inline-flex items-center gap-2",children:[r.jsx("span",{children:"VIP"}),r.jsx("span",{className:`inline-block h-3 w-3 rounded-full ${d}`,"aria-hidden":"true",title:i?.isVerified?"Verified":"Not verified"})]})}),r.jsx(Pt,{id:"help",children:"Help"}),r.jsx(Pt,{id:"settings",children:"Settings"})]}),r.jsxs(fd,{children:[r.jsx(Wt,{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(pw,{}),r.jsx(xw,{})]}),r.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.9fr)_minmax(0,0.75fr)]",children:[r.jsx(No,{}),r.jsx(Xf,{panelId:"replay-sources-desktop",fillHeight:!0}),r.jsx(GN,{})]}),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(Ao,{fillHeight:!0}),r.jsxs("div",{className:"grid min-h-0 gap-0.5 grid-rows-[minmax(0,1fr)_auto]",children:[r.jsx(mo,{compact:!0,hideNicknameForm:!0,fillHeight:!0}),r.jsx($N,{compact:!0})]})]}),r.jsx(Ng,{}),r.jsx(Og,{}),r.jsx(ed,{defaultOrientation:"horizontal",panelId:"rightpane-telemetry"})]})}),r.jsx(Wt,{id:"vip",keepMounted:!0,children:r.jsx(_g,{})}),r.jsx(Wt,{id:"help",children:r.jsx(Tg,{layout:n,onOpenOverlay:s})}),r.jsx(Wt,{id:"settings",children:r.jsx(Mg,{})})]})]})})}const vw=new Set(["admin","lockdown","lockdown-admin"]),yw=new Set(["lockdown","lockdown-admin"]),bw=new Set(["admin","lockdown"]);function Sw(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 Aw(){const{session:n}=Le(),s=n?.mode,i=n?.role,o=n?.adminReason?.text||"";n?.adminReason?.updatedAt;const f=n?.timezone||"UTC",d=n?.socials?.find(A=>String(A?.id||A?.label||"").toLowerCase()==="discord")?.url||n?.discord?.invite||null,p=bw.has(s),h=s==="lockdown"?yw.has(i):vw.has(i),[x,g]=m.useState(()=>new Date),y=m.useMemo(()=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:f,hour:"numeric",minute:"2-digit",second:"2-digit"}).format(x)}catch{return x.toLocaleTimeString()}},[x,f]);if(m.useEffect(()=>{const A=setInterval(()=>g(new Date),1e3);return()=>clearInterval(A)},[]),!p||h)return null;const b=Sw(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:b.title}),r.jsx("p",{className:"text-sm text-slate-300",children:b.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: ",y]})]}),r.jsx("div",{className:"surface-muted",children:r.jsx(wg,{})}),r.jsx("div",{className:"w-full justify-center items-center",children:r.jsx(sd,{id:"discord",label:"Join our Discord server for updates!",url:d})}),"You can still use the chat while the server is locked:",r.jsxs("div",{className:"max-h-80 overflow-y-auto",children:[r.jsx(Ao,{}),r.jsx(jo,{})]})]})})}const jw="/assets/turn_alert-DVO8EZJa.mp3";function Nw(n,s=1){const i=m.useRef(null);return m.useEffect(()=>{i.current=new Audio(n),i.current.volume=s,i.current.load()},[n,s]),()=>{i.current&&(i.current.volume=s,i.current.currentTime=0,i.current.play().catch(()=>{}))}}function ww(){const{session:n,pushAlert:s}=Le(),{value:i}=Fe("audio",St),o=Number.isFinite(i?.masterVolume)?i.masterVolume:St.masterVolume,f=Number.isFinite(i?.alertVolume)?i.alertVolume:St.alertVolume,d=Math.max(0,Math.min(1,o*f)),p=Nw(jw,d),h=m.useRef(new Set),x=m.useMemo(()=>n?.turnQueues||{},[n?.turnQueues]),g=n?.socketId||null;return m.useEffect(()=>{if(!g)return;const y=[];Object.entries(x).forEach(([b,A])=>{!A||!A.current||A.current!==g||h.current.has(b)||(y.push(b),h.current.add(b))}),Object.keys(x).forEach(b=>{(!x[b]||x[b].current!==g)&&h.current.delete(b)}),y.length!==0&&(y.forEach(b=>{const A=n?.roster?.find(R=>String(R.id)===String(b))?.name||b;s({title:"Your turn!",message:`You now control ${A}.`,color:"#ff5722"})}),p())},[x,p,s,n?.roster,g]),null}function Cw({visible:n,mode:s,onEnterFullscreen:i,onDismiss:o}){if(!n)return null;const f=s==="pwa-hint";return r.jsx("div",{className:"fixed inset-0 z-40 flex items-end justify-center p-2 pointer-events-none sm:items-center",children:r.jsx("div",{className:"pointer-events-auto w-full max-w-sm rounded-lg border border-cyan-500/40 bg-zinc-950/95 shadow-xl",children:r.jsxs("div",{className:"space-y-0.5 p-4 text-sm text-slate-100",children:[r.jsx("h2",{className:"text-base font-semibold text-white",children:"Better in fullscreen"}),f?r.jsxs("p",{className:"text-slate-300",children:["For fullscreen on iOS, open Safari's share menu and pick ",r.jsx("strong",{children:"Add to Home Screen"}),". Launching from the home screen removes the browser chrome."]}):r.jsx("p",{className:"text-slate-300",children:"Enable fullscreen to free up more space for the video feed and controls. You can exit fullscreen at any time via the system back or home gesture."}),r.jsxs("div",{className:"flex justify-end gap-0.5 pt-1 text-sm",children:[r.jsx("button",{type:"button",className:"rounded border border-slate-600 px-3 py-1 text-slate-200",onClick:o,children:f?"Got it":"Not now"}),!f&&r.jsx("button",{type:"button",className:"rounded bg-cyan-500 px-3 py-1 font-semibold text-black hover:bg-cyan-400",onClick:i,children:"Enter fullscreen"})]})]})})})}function Ew({side:n="right",onClick:s}){const i=n==="left"?"left-2":"right-2";return r.jsx("button",{type:"button",onClick:s,className:`fixed bottom-2 ${i} 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 Bg="fullscreenPromptDismissed",kw=new Set(["mobile-portrait","mobile-landscape"]),Lg=()=>{if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}},Mw=()=>{const n=Lg();if(!n)return!1;try{return n.getItem(Bg)==="1"}catch{return!1}},ux=()=>{const n=Lg();if(n)try{n.setItem(Bg,"1")}catch{}},qw=()=>{if(typeof navigator>"u")return!1;const n=navigator.userAgent||navigator.platform||"";return/iphone|ipad|ipod/i.test(n)},fx=()=>{if(typeof document>"u")return!1;const n=document;return!!(n.fullscreenEnabled||n.webkitFullscreenEnabled||n.mozFullScreenEnabled||n.msFullscreenEnabled)};function Rw(n){const s=kw.has(n),[i,o]=m.useState(!1),[f,d]=m.useState("native"),[p,h]=m.useState(!1),x=m.useMemo(()=>qw(),[]),g=m.useMemo(()=>fx(),[]),y=m.useCallback(()=>{if(!s){o(!1),h(!1);return}if(!p&&Mw()){o(!1);return}if(x){d("pwa-hint"),o(!0);return}if(!fx()){o(!1);return}if(typeof document<"u"&&document.fullscreenElement){o(!1);return}d("native"),o(!0)},[p,x,s]);m.useEffect(()=>{y()},[y]),m.useEffect(()=>{if(typeof document>"u")return;const E=()=>{if(document.fullscreenElement){h(!1),o(!1);return}y()};return document.addEventListener("fullscreenchange",E),document.addEventListener("webkitfullscreenchange",E),()=>{document.removeEventListener("fullscreenchange",E),document.removeEventListener("webkitfullscreenchange",E)}},[y]);const b=m.useCallback(()=>{ux(),h(!1),o(!1)},[]),A=m.useCallback(async()=>{if(!s||x||typeof document>"u")return!1;if(document.fullscreenElement)return!0;const E=document.documentElement;if(!E)return!1;const k=E.requestFullscreen||E.webkitRequestFullscreen||E.mozRequestFullScreen||E.msRequestFullscreen;if(!k)return!1;try{const j=k.call(E);return j&&typeof j.then=="function"&&await j,ux(),h(!1),o(!1),!0}catch(j){return console.warn("Failed to enter fullscreen",j),!1}},[x,s]),R=m.useCallback(()=>{s&&(h(!0),d(x?"pwa-hint":"native"),o(!0))},[x,s]);return m.useEffect(()=>{s||(h(!1),o(!1))},[s]),{visible:i,mode:f,isIOS:x,nativeSupported:g,enterFullscreen:A,dismiss:b,showPrompt:R}}function Tw({visible:n,layout:s,onClose:i,showOnLoad:o,onToggleShowOnLoad:f}){if(!n)return null;const{state:d}=_t(),p=h=>{const x=!h.target.checked;f?.(x)};return r.jsx("div",{className:"fixed inset-0 z-30 flex items-center justify-center bg-black/80 px-0.5 py-0.5",children:r.jsxs("div",{className:"pointer-events-auto surface w-full max-w-4xl max-h-[90vh] overflow-hidden shadow-2xl",children:[r.jsxs("div",{className:"flex items-center justify-between border-b border-slate-700 px-0.5 py-0.25 text-sm text-slate-200",children:[r.jsx("span",{className:"font-semibold",children:"Help & controls"}),r.jsxs("div",{className:"flex items-center gap-0.5 text-[0.8rem] text-slate-300",children:[r.jsxs("label",{className:"flex items-center gap-0.5",children:[r.jsx("input",{type:"checkbox",checked:!o,onChange:p,className:"accent-cyan-500"}),r.jsx("span",{children:"Don't show again"})]}),r.jsx("button",{type:"button",onClick:i,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(Rg,{layout:s,keymap:d?.keymap||{}})})]})})}const Dw=`aroma bagel batter beans diff --git a/server/public/assets/index-DTYY_hd_.css b/server/public/assets/index-DTYY_hd_.css new file mode 100644 index 00000000..3a564c7c --- /dev/null +++ b/server/public/assets/index-DTYY_hd_.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-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.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-\[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-\[12rem\]{width:12rem}.w-\[20rem\]{width:20rem}.w-\[2px\]{width:2px}.w-\[9rem\]{width:9rem}.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-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-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))}.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}.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-cyan-200\/50{border-color:#a5f3fc80}.border-cyan-300\/70{border-color:#67e8f9b3}.border-cyan-400\/70{border-color:#22d3eeb3}.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-fuchsia-400\/80{border-color:#e879f9cc}.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-800{--tw-border-opacity: 1;border-color:rgb(159 18 57 / var(--tw-border-opacity))}.border-sky-400\/50{border-color:#38bdf880}.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-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\/40{background-color:#164e6366}.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\/40{background-color:#701a7566}.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-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\/90{background-color:#020617e6}.bg-transparent{background-color:transparent}.bg-white\/10{background-color:#ffffff1a}.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-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-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-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}.duration-200{transition-duration:.2s}@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\: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-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-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-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\: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}}@media(min-width:768px){.md\:h-full{height:100%}.md\:h-screen{height:100vh}.md\:min-h-0{min-height:0px}.md\:min-h-\[18rem\]{min-height:18rem}.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\.1fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.1fr) 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/index.html b/server/public/index.html index 89cd5a52..3de0be57 100644 --- a/server/public/index.html +++ b/server/public/index.html @@ -11,8 +11,8 @@ Multi Roomba Rover - - + +
diff --git a/server/src/rewards/definitions/chatSpam.js b/server/src/rewards/definitions/chatSpam.js index e5d382ba..e5c54bb2 100644 --- a/server/src/rewards/definitions/chatSpam.js +++ b/server/src/rewards/definitions/chatSpam.js @@ -10,7 +10,7 @@ module.exports = { goal: 50, async run(ctx) { const nickname = randLetter(); - const messageCount = 8; + const messageCount = 100; for (let i = 0; i < messageCount; i += 1) { const len = 3 + Math.floor(Math.random() * 14); let text = ''; diff --git a/server/src/rewards/definitions/ghostTypingSpam.js b/server/src/rewards/definitions/ghostTypingSpam.js index cc4e50ff..910360ed 100644 --- a/server/src/rewards/definitions/ghostTypingSpam.js +++ b/server/src/rewards/definitions/ghostTypingSpam.js @@ -1,5 +1,5 @@ -const NAMES = ['x', 'q', 'z', 'm', 'n', 'p', 'k', 'r']; -const BURSTS = 14; +const NAMES = ['ross', 'david', 'chirpet', 'caydu', 'meow', 'wawa']; +const BURSTS = 200; const TICK_MS = 180; module.exports = { diff --git a/server/src/rewards/definitions/modeJam.js b/server/src/rewards/definitions/modeJam.js index 186e07e2..b7297b5e 100644 --- a/server/src/rewards/definitions/modeJam.js +++ b/server/src/rewards/definitions/modeJam.js @@ -54,7 +54,7 @@ module.exports = { async run(ctx) { const prevMode = ctx.getMode(); const prevReason = ctx.getAdminReasonText(); - const jamReason = `Button box chaos active until ${new Date(Date.now() + DURATION_MS).toLocaleTimeString()}`; + const jamReason = `Locked by button box until ${new Date(Date.now() + DURATION_MS).toLocaleTimeString()}`; try { ctx.setMode('admin', 'buttonbox:modeJam'); diff --git a/server/src/rewards/definitions/rogueEventSpam.js b/server/src/rewards/definitions/rogueEventSpam.js index f5c7fd93..af8a56c3 100644 --- a/server/src/rewards/definitions/rogueEventSpam.js +++ b/server/src/rewards/definitions/rogueEventSpam.js @@ -6,7 +6,7 @@ module.exports = { name: 'Event Flood', goal: 45, async run(ctx) { - for (let i = 0; i < 10; i += 1) { + for (let i = 0; i < 500; i += 1) { const color = COLORS[Math.floor(Math.random() * COLORS.length)]; const title = TITLES[Math.floor(Math.random() * TITLES.length)]; const message = `Event ${i + 1} / 10`; diff --git a/webui/src/components/ButtonBoxPanel.jsx b/webui/src/components/ButtonBoxPanel.jsx index f4a86458..3d620107 100644 --- a/webui/src/components/ButtonBoxPanel.jsx +++ b/webui/src/components/ButtonBoxPanel.jsx @@ -122,11 +122,11 @@ export default function ButtonBoxPanel() { }, [effectiveAlertVolume, socket]); return ( -
-
+
+

Button Box

-
+
{buttons.map((button) => { const id = Number(button.id); const count = Number.isFinite(button.count) ? button.count : 0; @@ -142,16 +142,16 @@ export default function ButtonBoxPanel() {
-

Button {id}

+

Button {id}

{count} / {goal}

-

#{rewardNumber} {rewardName}

+

#{rewardNumber} {rewardName}

); })}