diff --git a/plans/to-do.md b/plans/to-do.md index 2767547b..f01722b8 100644 --- a/plans/to-do.md +++ b/plans/to-do.md @@ -17,6 +17,7 @@ 13. add tool call embeds or something for the llm bot in discord, probably not in web ui 14. add discord bot typing thing for when someone requests a replay 15. change replay title for ones requested from discord, something other than "requester driving rover" +16. better quickstart guide, something better than just a big list of controls. help overlay sucks i think. # relative pipe dreams: diff --git a/server/public/assets/index-D8G6mAM9.js b/server/public/assets/index-Dt4-1xEp.js similarity index 99% rename from server/public/assets/index-D8G6mAM9.js rename to server/public/assets/index-Dt4-1xEp.js index ec5b0055..43e93794 100644 --- a/server/public/assets/index-D8G6mAM9.js +++ b/server/public/assets/index-Dt4-1xEp.js @@ -20,7 +20,7 @@ ${w}`}).join(` ---------------------------------------- `):""};return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Overseer Control"}),l.jsx("div",{className:"flex gap-0.5 text-xs",children:l.jsx("button",{type:"button",onClick:s,disabled:!!r,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:r?"Clearing...":"Clear Overseer History"})}),l.jsxs("div",{className:"surface flex flex-wrap gap-0.5 text-xs",children:[l.jsxs("span",{className:"surface-muted",children:["running: ",f.running?"yes":"no"]}),l.jsxs("span",{className:"surface-muted",children:["phase: ",f.phase||"--"]}),l.jsxs("span",{className:"surface-muted",children:["tick: ",f.tickCount??0]}),l.jsxs("span",{className:"surface-muted",children:["trigger: ",f.lastTriggerReason||"--"]}),l.jsxs("span",{className:"surface-muted",children:["name: ",p.name||"--"]}),l.jsxs("span",{className:"surface-muted",children:["model: ",p.model||"--"]}),l.jsxs("span",{className:"surface-muted",children:["observeOnly: ",p.observeOnly?"yes":"no"]}),l.jsxs("span",{className:"surface-muted",children:["decision: ",h.normalized||"--"]}),l.jsxs("span",{className:"surface-muted",children:["outcome: ",h.outcome||"--"]}),l.jsxs("span",{className:"surface-muted",children:["reason: ",h.reason||"--"]}),l.jsxs("span",{className:"surface-muted",children:["last gen: ",x.lastGenerationMs!=null?`${x.lastGenerationMs}ms`:"--"]})]}),l.jsxs("details",{className:"surface text-xs text-slate-200",open:!0,children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Latest Context"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:g.stateUpdate||""})]}),l.jsxs("details",{className:"surface text-xs text-slate-200",open:!0,children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Exact Model Input (messages[])"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:y()})]}),l.jsxs("details",{className:"surface text-xs text-slate-200",children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Exact System Prompt"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:g.systemPrompt||""})]}),l.jsxs("details",{className:"surface text-xs text-slate-200",children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Exact Transcript Rows"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(g.transcript||[],null,2)})]}),l.jsxs("details",{className:"surface text-xs text-slate-200",children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Tool Availability"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify({available:g.availableTools,blocked:g.blockedTools},null,2)})]}),l.jsxs("details",{className:"surface text-xs text-slate-200",open:!0,children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Exact Model Output"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:h.raw||""})]}),l.jsxs("details",{className:"surface text-xs text-slate-200",open:!0,children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Live Tool Calls"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(h.liveToolCalls||[],null,2)})]}),l.jsxs("div",{className:"surface text-xs text-slate-200",children:[l.jsxs("div",{children:["Normalized decision: ",h.normalized||"--"]}),l.jsxs("div",{children:["Model input at: ",g.modelInputAt?new Date(g.modelInputAt).toLocaleString():"n/a"]}),l.jsxs("div",{children:["Model output at: ",h.outputAt?new Date(h.outputAt).toLocaleString():"n/a"]})]}),v.message?l.jsxs("div",{className:"surface text-xs text-red-300",children:["Error: ",v.message]}):null,l.jsxs("details",{className:"surface text-xs text-slate-200",children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Recent Runs"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(n.history||[],null,2)})]}),l.jsx("button",{type:"button",className:"button-dark text-xs",onClick:()=>u(N=>!N),children:o?"Hide Full Payload":"Show Full Payload"}),o?l.jsx("pre",{className:"surface whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(n,null,2)}):null]})}function Cw({health:n,roster:s=[]}){if(!n)return null;const r=n.replay||{sources:[],readyCount:0,totalCount:0},o=n.snapshots||{rovers:[],rooms:[]},u=x=>s.find(g=>String(g.id)===String(x))?.color||null,f=`${r.readyCount}/${r.totalCount} sources ready`,p=o.rovers.filter(x=>x.stale).length,h=o.rooms.filter(x=>x.stale).length;return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Health"}),l.jsxs("div",{className:"surface space-y-0.5 text-xs text-slate-200",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{children:"Replay segments"}),l.jsx("span",{className:"text-slate-400",children:f})]}),l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{children:"Rover snapshots"}),l.jsxs("span",{className:p?"text-amber-300":"text-emerald-300",children:[o.rovers.length-p,"/",o.rovers.length," ok"]})]}),l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{children:"Room cameras"}),l.jsxs("span",{className:h?"text-amber-300":"text-emerald-300",children:[o.rooms.length-h,"/",o.rooms.length," ok"]})]})]}),l.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:r.sources.map(x=>l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{className:`${x.type==="rover"?"rounded px-1 py-[1px] border border-transparent":""}`,style:x.type==="rover"?ia(u(x.id),.16):void 0,children:x.label}),l.jsxs("span",{className:x.ready?"text-emerald-300":"text-amber-300",children:[x.recentCount,"/",x.neededCount]})]},`${x.type}:${x.id}`))}),l.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:o.rovers.map(x=>l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ia(u(x.id),.16),children:x.name}),l.jsx("span",{className:x.stale?"text-amber-300":"text-emerald-300",children:x.stale?"stale":"ok"})]},`rover:${x.id}`))}),l.jsx("div",{className:"space-y-0.5 text-xs text-slate-300",children:o.rooms.map(x=>l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{children:x.name}),l.jsx("span",{className:x.stale?"text-amber-300":"text-emerald-300",children:x.error?"error":x.stale?"stale":"ok"})]},`room:${x.id}`))})]})}function Ew({entries:n}){const s=n||[];return l.jsxs("div",{className:"panel-section space-y-0.5 text-base",children:[l.jsxs("div",{className:"flex items-center justify-between text-sm text-slate-400",children:[l.jsx("span",{children:"Admin IP log"}),l.jsx("span",{children:s.length})]}),l.jsx("div",{className:"surface h-64 overflow-y-auto font-mono text-xs",children:s.length===0?l.jsx("p",{children:"No admin log entries yet."}):s.slice().reverse().map(r=>l.jsxs("div",{className:"surface",children:[l.jsx("span",{className:"text-amber-400",children:r.ts?new Date(r.ts).toLocaleTimeString():"--"})," ",r.label&&l.jsxs("span",{className:"text-teal-400",children:["[",r.label,"]"]})," ",l.jsx("span",{className:"text-slate-200",children:r.message})," ",r.ip&&l.jsx("span",{className:"text-cyan-300",children:r.ip})," ",r.meta&&l.jsx("span",{className:"text-slate-500",children:JSON.stringify(r.meta)})]},r.id))}),l.jsx("p",{className:"text-xs text-slate-500",children:"Admin-only log stream; IPs never appear in user data."})]})}const kw=[{key:"open",label:"Open"},{key:"turns",label:"Turns"},{key:"admin",label:"Admin"},{key:"lockdown",label:"Lockdown"}];function Mw(){const{session:n,lockRover:s,setMode:r,requestControl:o,setGlobalObjective:u,setAdminReason:f,rebootRover:p,rebootServer:h,setAudioLevels:x,setPrivateSafety:g,llmControl:v,overseerControl:y,adminLogs:N,llmCommentaryState:M,overseerControlState:C}=kr(),S=m.useMemo(()=>n?.roster??[],[n?.roster]),[w,j]=m.useState({}),[R,k]=m.useState({}),[E,B]=m.useState(!1),[X,L]=m.useState(!1),[z,K]=m.useState(!1),V=n?.health||null,F=n?.globalObjective?.text||"",W=n?.globalObjective?.updatedAt||null,[ie,oe]=m.useState(F),$=n?.adminReason?.text||"",T=n?.adminReason?.updatedAt||null,[H,J]=m.useState($),te=n?.audioLevels||{},[ue,q]=m.useState({hornGain:Number.isFinite(te.hornGain)?te.hornGain:1,ttsGain:Number.isFinite(te.ttsGain)?te.ttsGain:1,forwardGain:Number.isFinite(te.forwardGain)?te.forwardGain:1}),[_,I]=m.useState({}),ne=n?.role==="admin"||n?.role==="lockdown"||n?.role==="lockdown-admin",me=n?.role==="lockdown"||n?.role==="lockdown-admin",ce=n?.mode??"open",se=async(le,de)=>{try{await s(le,de),j(Me=>({...Me,[le]:de}))}catch(Me){alert(Me.message)}},ve=async le=>{const de=le.target.value;try{await r(de)}catch(Me){alert(Me.message)}},he=async le=>{try{await o(le,{force:!0})}catch(de){alert(de.message)}},be=async le=>{if(!(!le?.id||!window.confirm(`Reboot rover "${le.name||le.id}" now?`))){k(Me=>({...Me,[le.id]:!0}));try{await p(le.id)}catch(Me){alert(Me.message)}finally{k(Me=>({...Me,[le.id]:!1}))}}},Ve=async()=>{if(window.confirm("Reboot the server host now? This will disconnect all users.")){B(!0);try{await h()}catch(de){alert(de.message),B(!1)}}},De=async()=>{if(window.confirm("Clear LLM commentary history now? This resets chat context, bot memory, and rover activity metrics for narration.")){L(!0);try{await v("clearHistory")}catch(de){alert(de.message)}finally{L(!1)}}},Te=async()=>{if(window.confirm("Clear Overseer Control history now?")){K(!0);try{await y("clearHistory")}catch(de){alert(de.message)}finally{K(!1)}}},ze=async()=>{try{await u(ie)}catch(le){alert(le.message)}},$e=async()=>{try{await u(null)}catch(le){alert(le.message)}},vt=async()=>{try{await f(H)}catch(le){alert(le.message)}},re=async()=>{try{await f(null)}catch(le){alert(le.message)}},xe=le=>de=>{const Me=Number(de.target.value);q(ft=>({...ft||{},[le]:Number.isFinite(Me)?Me:1}))},Ee=async()=>{try{await x(ue)}catch(le){alert(le.message)}},fe=async()=>{window.dispatchEvent(new CustomEvent("buttonBox:rewardRunLocalTest",{detail:{rewardName:"Admin Mode",count:1e3,goal:1e3}}))};m.useEffect(()=>{oe(F)},[F]),m.useEffect(()=>{J($)},[$]),m.useEffect(()=>{q({hornGain:Number.isFinite(te.hornGain)?te.hornGain:1,ttsGain:Number.isFinite(te.ttsGain)?te.ttsGain:1,forwardGain:Number.isFinite(te.forwardGain)?te.forwardGain:1})},[te.forwardGain,te.hornGain,te.ttsGain]),m.useEffect(()=>{const le={};(S||[]).forEach(de=>{de?.private?.enabled&&(le[de.id]={speedLimitEnabled:!!de?.private?.safety?.speedLimitEnabled,speedLimitMaxWheelSpeed:Number.isFinite(de?.private?.safety?.speedLimitMaxWheelSpeed)?de.private.safety.speedLimitMaxWheelSpeed:250,hardOvercurrentEnabled:!!de?.private?.safety?.hardOvercurrentEnabled,overcurrentStopMs:Number.isFinite(de?.private?.safety?.overcurrentStopMs)?de.private.safety.overcurrentStopMs:300,hardBumpEnabled:!!de?.private?.safety?.hardBumpEnabled,bumpBackoffSpeed:Number.isFinite(de?.private?.safety?.bumpBackoffSpeed)?de.private.safety.bumpBackoffSpeed:250,bumpBackoffMs:Number.isFinite(de?.private?.safety?.bumpBackoffMs)?de.private.safety.bumpBackoffMs:350,cliffEnabled:!!de?.private?.safety?.cliffEnabled,cliffBackoffSpeed:Number.isFinite(de?.private?.safety?.cliffBackoffSpeed)?de.private.safety.cliffBackoffSpeed:250,cliffBackoffMs:Number.isFinite(de?.private?.safety?.cliffBackoffMs)?de.private.safety.cliffBackoffMs:500,triggerCooldownMs:Number.isFinite(de?.private?.safety?.triggerCooldownMs)?de.private.safety.triggerCooldownMs:800})}),I(le)},[S]);const we=m.useMemo(()=>{const le={};return S.forEach(de=>{le[de.id]=w[de.id]??de.locked}),le},[S,w]),Ae=(le,de={})=>{I(Me=>({...Me||{},[le]:{...Me?.[le]||{},...de||{}}}))},it=async le=>{try{const de=_?.[le];if(!de)return;await g(le,de)}catch(de){alert(de.message)}};return ne?l.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5 text-sm",children:[l.jsx("span",{children:"Admin controls"}),l.jsx("select",{value:ce,onChange:ve,className:"field-input text-sm",children:kw.map(le=>l.jsx("option",{value:le.key,children:le.label},le.key))})]}),l.jsxs("div",{className:"flex gap-0.5 text-xs",children:[l.jsx("button",{type:"button",onClick:Ve,disabled:E,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:E?"Server rebooting...":"Reboot Server"}),l.jsx("button",{type:"button",onClick:fe,className:"button-dark",children:"Test Reward Popup"})]}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[l.jsx("span",{children:"Global audio levels"}),n?.audioLevels?.updatedAt?l.jsxs("span",{children:["Updated ",new Date(n.audioLevels.updatedAt).toLocaleString()]}):null]}),l.jsxs("label",{className:"grid gap-0.5 text-xs text-slate-200",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[l.jsx("span",{children:"Horn gain"}),l.jsxs("span",{children:[ue.hornGain.toFixed(2),"x"]})]}),l.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:ue.hornGain,onChange:xe("hornGain"),className:"w-full accent-emerald-500"})]}),l.jsxs("label",{className:"grid gap-0.5 text-xs text-slate-200",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[l.jsx("span",{children:"TTS gain"}),l.jsxs("span",{children:[ue.ttsGain.toFixed(2),"x"]})]}),l.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:ue.ttsGain,onChange:xe("ttsGain"),className:"w-full accent-emerald-500"})]}),l.jsxs("label",{className:"grid gap-0.5 text-xs text-slate-200",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[l.jsx("span",{children:"Forward gain"}),l.jsxs("span",{children:[ue.forwardGain.toFixed(2),"x"]})]}),l.jsx("input",{type:"range",min:"0",max:"4",step:"0.01",value:ue.forwardGain,onChange:xe("forwardGain"),className:"w-full accent-emerald-500"})]}),l.jsx("div",{className:"flex gap-0.5 text-xs",children:l.jsx("button",{type:"button",onClick:Ee,className:"button-dark",children:"Apply audio levels"})})]}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[l.jsx("span",{children:"Global objective"}),W?l.jsxs("span",{children:["Updated ",new Date(W).toLocaleString()]}):null]}),l.jsx("input",{type:"text",value:ie,onChange:le=>oe(le.target.value),placeholder:"Set a global objective",className:"field-input text-sm"}),l.jsxs("div",{className:"flex gap-0.5 text-xs",children:[l.jsx("button",{type:"button",onClick:ze,className:"button-dark",children:"Set objective"}),l.jsx("button",{type:"button",onClick:$e,className:"button-danger",children:"Clear"})]})]}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[l.jsx("span",{children:"Admin mode reason"}),T?l.jsxs("span",{children:["Updated ",new Date(T).toLocaleString()]}):null]}),l.jsx("textarea",{value:H,onChange:le=>J(le.target.value),placeholder:"Set an admin mode reason",className:"field-input text-sm min-h-[3.5rem]"}),l.jsxs("div",{className:"flex gap-0.5 text-xs",children:[l.jsx("button",{type:"button",onClick:vt,className:"button-dark",children:"Set reason"}),l.jsx("button",{type:"button",onClick:re,className:"button-danger",children:"Clear"})]})]}),l.jsx(Sw,{roster:S,renderActions:le=>l.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 text-xs",children:[l.jsx("button",{type:"button",onClick:()=>se(le.id,!we[le.id]),className:"button-dark",children:we[le.id]?"Unlock":"Lock"}),l.jsx("button",{type:"button",onClick:()=>he(le.id),className:"button-dark",children:"Force"}),l.jsx("button",{type:"button",onClick:()=>be(le),disabled:!!R[le.id],className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:R[le.id]?"Rebooting...":"Reboot"}),le?.private?.enabled?l.jsxs("div",{className:"w-full rounded border border-slate-700/70 p-0.5 space-y-0.5 text-[0.7rem]",children:[l.jsx("div",{className:"text-slate-300",children:"Private safety"}),l.jsxs("label",{className:"flex items-center gap-0.5",children:[l.jsx("input",{type:"checkbox",checked:!!_?.[le.id]?.speedLimitEnabled,disabled:!me,onChange:de=>Ae(le.id,{speedLimitEnabled:!!de.target.checked})}),l.jsx("span",{children:"Speed limit"})]}),l.jsx("input",{type:"number",min:"1",max:"500",className:"field-input text-xs w-20",disabled:!me,value:_?.[le.id]?.speedLimitMaxWheelSpeed??250,onChange:de=>Ae(le.id,{speedLimitMaxWheelSpeed:Number(de.target.value)||250})}),l.jsxs("label",{className:"flex items-center gap-0.5",children:[l.jsx("input",{type:"checkbox",checked:!!_?.[le.id]?.hardOvercurrentEnabled,disabled:!me,onChange:de=>Ae(le.id,{hardOvercurrentEnabled:!!de.target.checked})}),l.jsx("span",{children:"Hard overcurrent"})]}),l.jsxs("label",{className:"flex items-center gap-0.5",children:[l.jsx("input",{type:"checkbox",checked:!!_?.[le.id]?.hardBumpEnabled,disabled:!me,onChange:de=>Ae(le.id,{hardBumpEnabled:!!de.target.checked})}),l.jsx("span",{children:"Hard bump"})]}),l.jsxs("label",{className:"flex items-center gap-0.5",children:[l.jsx("input",{type:"checkbox",checked:!!_?.[le.id]?.cliffEnabled,disabled:!me,onChange:de=>Ae(le.id,{cliffEnabled:!!de.target.checked})}),l.jsx("span",{children:"Cliff safety"})]}),l.jsx("button",{type:"button",disabled:!me,onClick:()=>it(le.id),className:"button-dark disabled:opacity-50",children:"Apply Safety"})]}):null]})}),l.jsx(Cw,{health:V,roster:S}),l.jsx(ww,{state:M,onClearHistory:De,clearingHistory:X}),l.jsx(Aw,{state:C,onClearHistory:Te,clearingHistory:z}),l.jsx(Ew,{entries:N})]}):null}const Rw=[{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 qw(n){return n.reduce((s,r)=>((s[r.group]||(s[r.group]=[])).push(r),s),{})}function Tw(n,s){const r=Number(n);return Number.isFinite(r)?Math.max(0,Math.min(500,r)):s}const vf=5,jr=500,Nr=1,bf=100;function Dw(n,s){const r=Number(n);return Number.isFinite(r)?Math.max(vf,Math.min(jr,r)):s}function mo(n,s){const r=Number(n);return Number.isFinite(r)?Math.max(Nr,Math.min(bf,r)):s}function _w(n){const r=(mo(n,n)-Nr)/(bf-Nr),o=jr-r*(jr-vf);return Math.round(o)}function Ow(n){const s=Dw(n,n),r=(jr-s)/(jr-vf),o=Nr+r*(bf-Nr);return Math.round(o)}function Bw(n){const[s,r]=m.useState(null),o=m.useCallback(p=>{rd(!0),r(p)},[]),u=m.useCallback(()=>{rd(!1),r(null)},[]),f=m.useCallback((p,h)=>{if(h.preventDefault(),h.stopPropagation(),h.key==="Escape"){u();return}const x=Rr(h.key??"");x&&(n(p,x,h),u())},[u,n]);return m.useEffect(()=>()=>rd(!1),[]),{active:s,startCapture:o,cancel:u,captureFromEvent:f}}function eo({label:n,description:s,value:r,onChange:o,min:u=0,max:f=500,step:p=5}){return l.jsxs("label",{className:"surface-muted block p-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-300",children:[l.jsx("span",{className:"font-semibold text-slate-100",children:n}),l.jsx("input",{type:"number",min:u,max:f,value:r,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&&l.jsx("p",{className:"text-[0.65rem] text-slate-500",children:s}),l.jsxs("div",{className:"mt-0 flex items-center gap-0.5",children:[l.jsx("input",{type:"range",min:u,max:f,step:p,value:r,onChange:h=>o(h.target.value),className:"h-2 flex-1 accent-emerald-400"}),l.jsx("span",{className:"w-12 text-right text-[0.75rem] font-mono text-slate-400",children:r})]})]})}function Lw(){const{state:{keymap:n},actions:{updateKeyBinding:s,resetKeyBindings:r}}=Dt(),{value:o,save:u}=Qe("inputs",Dn),f={...Dn.keyboard,...o.keyboard??{}},p=m.useMemo(()=>typeof f.tiltSpeed=="number"?mo(f.tiltSpeed,Dn.keyboard.tiltSpeed):typeof f.tiltIntervalMs=="number"?mo(Ow(f.tiltIntervalMs),Dn.keyboard.tiltSpeed):Dn.keyboard.tiltSpeed,[f.tiltIntervalMs,f.tiltSpeed]),h=m.useMemo(()=>qw(Rw),[]),{active:x,startCapture:g,cancel:v,captureFromEvent:y}=Bw((S,w)=>{s(S,w)}),N=m.useCallback(S=>n?.[S]?.[0]||mr[S]?.[0]||"",[n]),M=m.useCallback((S,w)=>{const j=Dn.keyboard,R=Tw(w,j[S]);u(k=>({...k??{},keyboard:{...k?.keyboard??j,[S]:R}}))},[u]),C=m.useCallback(S=>{const w=Dn.keyboard,j=mo(S,w.tiltSpeed),R=_w(j);u(k=>({...k??{},keyboard:{...k?.keyboard??w,tiltSpeed:j,tiltIntervalMs:R}}))},[u]);return l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsxs("div",{children:[l.jsx("p",{className:"text-xs text-slate-400",children:"Keyboard layout"}),l.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Per-browser · click to change a binding"})]}),l.jsx("button",{type:"button",onClick:()=>r(),className:"button-dark text-xs",children:"Reset defaults"})]}),l.jsxs("div",{className:"space-y-0.5 surface",children:[l.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Keyboard speeds"}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsx(eo,{label:"Base speed",description:"Normal driving speed",value:f.baseSpeed,onChange:S=>M("baseSpeed",S)}),l.jsx(eo,{label:"Turbo speed",description:"Used when holding the boost modifier",value:f.turboSpeed,onChange:S=>M("turboSpeed",S)}),l.jsx(eo,{label:"Precision speed",description:"Used when holding the precision modifier",value:f.precisionSpeed,onChange:S=>M("precisionSpeed",S)})]})]}),l.jsxs("div",{className:"space-y-0.5 surface",children:[l.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Camera tilt"}),l.jsx(eo,{label:"Tilt speed",description:"Higher = faster when holding tilt keys",value:p,onChange:C,min:1,max:100,step:1})]}),l.jsx("div",{className:"space-y-0.5",children:Object.entries(h).map(([S,w])=>l.jsxs("div",{className:"space-y-0.5 surface",children:[l.jsx("p",{className:"text-[0.75rem] text-slate-400",children:S}),l.jsx("div",{className:"space-y-0.5",children:w.map(j=>{const R=N(j.id),k=x===j.id;return l.jsxs("div",{className:"surface-muted flex items-center justify-between text-xs",children:[l.jsxs("div",{children:[l.jsx("p",{className:"font-semibold text-slate-100",children:j.label}),l.jsx("p",{className:"text-[0.65rem] text-slate-400",children:An(R)})]}),l.jsxs("div",{className:"flex items-center gap-0.5",children:[k&&l.jsx("button",{type:"button",onClick:()=>v(),className:"button-danger text-[0.7rem]",children:"Cancel"}),l.jsx("button",{type:"button",onClick:()=>g(j.id),onKeyDown:k?E=>y(j.id,E):void 0,autoFocus:k,className:`${k?"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:k?"Press a key…":"Change"})]})]},j.id)})})]},S))})]})}const aa=new Intl.NumberFormat(void 0,{maximumFractionDigits:2}),zw=[{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"}],mx=.45,Uw=.6;function cr({label:n,description:s,min:r,max:o,step:u,value:f,onChange:p}){return l.jsxs("label",{className:"surface-muted block p-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-300",children:[l.jsx("span",{className:"font-semibold text-slate-100",children:n}),l.jsx("span",{className:"font-mono text-slate-400",children:aa.format(f)})]}),s&&l.jsx("p",{className:"text-[0.65rem] text-slate-500",children:s}),l.jsx("input",{type:"range",min:r,max:o,step:u,value:f,onChange:h=>p(Number(h.target.value)),className:"mt-0 w-full accent-emerald-400"})]})}function Hw(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 Vw(n){return n.reduce((s,r)=>((s[r.section]||(s[r.section]=[])).push(r),s),{})}function $w(n,s){if(!n||n.length===0)return null;if(s){const r=n.find(o=>o.signature===s);if(r)return r}return n[0]}function Gw(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 Yw(n,s,r){const o=(n.axes??[]).map((f,p)=>({index:p,delta:Math.abs((f??0)-(s.axes?.[p]??0)),value:f}));if(o.sort((f,p)=>p.delta-f.delta),r.kind==="axisPair"){const f=o.filter(p=>p.delta>mx).slice(0,2);return f.length<2?null:{kind:"axisPair",x:f[0].index,y:f[1].index,...r.invertDefaults??{}}}const u=o.find(f=>f.delta>mx);return u?{kind:"axis",index:u.index,...r.invertDefaults??{}}:null}function Fw(n,s,r){const o=n.buttons??[];for(let f=0;fUw)return r.kind==="axis"?{kind:"buttonAxis",index:f}:{kind:"button",index:f}}const u=n.axes??[];for(let f=0;f.7&&h>.5)return r.kind==="axis"?{kind:"axis",index:f,...r.invertDefaults??{}}:{kind:"axisButton",index:f,direction:p>=0?1:-1,threshold:.6}}return null}function Xw(n,s,r){if(!n)return null;if(r.kind==="axis"||r.kind==="axisPair"){const o=Yw(n,s,r);if(o)return o}return Fw(n,s,r)}function Qw(){const n=hN(),{value:s,save:r}=Qe("gamepad",_a),[o,u]=m.useState(null),f=m.useRef(null),p=m.useMemo(()=>Vw(zw),[]),h=m.useMemo(()=>$w(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]||r(w=>{const j=w??_a;if(j.profiles?.[x])return j;const R=j?.defaults?.profile??sa,k=Cg(h,R);return{...j,profiles:{...j.profiles??{},[x]:k}}})},[h,x,s?.profiles,r]),m.useEffect(()=>{f.current=null},[o,x]),m.useEffect(()=>{if(!o||!h)return;if(!f.current){f.current=Gw(h);return}const w=Xw(h,f.current,o);w&&(r(j=>{const R=j??_a,k=R.profiles?.[x]??R?.defaults?.profile??sa,E={...k,bindings:{...k.bindings??{},[o.id]:{...k.bindings?.[o.id]??{},kind:o.kind,sources:[w]}}};return{...R,profiles:{...R.profiles??{},[x]:E}}}),u(null))},[h,x,o,r]);const v=m.useCallback(w=>{r(j=>({...j??_a,activeSignature:w||null}))},[r]),y=m.useCallback(w=>{r(j=>{const R=j??_a,k=(x&&R.profiles?.[x])??R?.defaults?.profile??sa,E={...k,calibration:{...k.calibration??{},...w}};return x?{...R,profiles:{...R.profiles??{},[x]:E}}:{...R,defaults:{...R.defaults??{},profile:E}}})},[x,r]),N=m.useCallback((w,j)=>{r(R=>{const k=R??_a,E=(x&&k.profiles?.[x])??k?.defaults?.profile??sa,B=j(E.bindings?.[w]??{}),X={...E,bindings:{...E.bindings??{},[w]:B}};return x?{...k,profiles:{...k.profiles??{},[x]:X}}:{...k,defaults:{...k.defaults??{},profile:X}}})},[x,r]),M=m.useCallback(w=>{N(w.id,j=>({...j,sources:[]}))},[N]),C=m.useCallback((w,j)=>{N(w.id,R=>{const k=Array.isArray(R.sources)?[...R.sources]:[];if(!k[0])return R;const E={...k[0]};return j==="invertX"?E.invertX=!E.invertX:j==="invertY"?E.invertY=!E.invertY:E.invert=!E.invert,k[0]=E,{...R,sources:k}})},[N]),S=m.useMemo(()=>h?{outputs:Eg(h,g)}:null,[h,g]);return l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsx("div",{className:"flex items-center justify-between",children:l.jsxs("div",{children:[l.jsx("p",{className:"text-xs text-slate-400",children:"Controller"}),l.jsx("p",{className:"text-[0.65rem] text-slate-500",children:h?"Move sticks or press buttons to bind":"Connect a controller to configure."}),o&&l.jsxs("p",{className:"mt-0 text-[0.7rem] text-emerald-400",children:["Capturing ",o.label,"…"]})]})}),l.jsxs("div",{className:"space-y-0.5 surface",children:[l.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Connected controller"}),n.pads.length===0?l.jsx("p",{className:"text-[0.7rem] text-slate-400",children:"No controller detected."}):l.jsxs("div",{className:"flex items-center justify-between gap-0.5 text-xs",children:[l.jsx("select",{value:x??"",onChange:w=>v(w.target.value),className:"flex-1 rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.75rem] text-slate-100",children:n.pads.map(w=>l.jsx("option",{value:w.signature,children:w.id||"Unknown controller"},w.signature))}),l.jsx("span",{className:"text-[0.7rem] text-slate-400",children:h?.mapping??"unknown"})]})]}),l.jsxs("div",{className:"space-y-0.5 surface",children:[l.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Calibration"}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsx(cr,{label:"Drive deadzone",description:"Ignore small drive stick drift",min:0,max:.6,step:.01,value:g.calibration?.driveDeadzone??.18,onChange:w=>y({driveDeadzone:w})}),l.jsx(cr,{label:"Camera deadzone",description:"Ignore small camera tilt drift",min:0,max:.4,step:.01,value:g.calibration?.cameraDeadzone??.08,onChange:w=>y({cameraDeadzone:w})}),l.jsx(cr,{label:"Aux deadzone",description:"Ignore small trigger noise",min:0,max:.4,step:.01,value:g.calibration?.auxDeadzone??.05,onChange:w=>y({auxDeadzone:w})}),l.jsx(cr,{label:"Side brush scale",description:"Scale side brush output",min:.3,max:1,step:.05,value:g.calibration?.auxSideScale??.55,onChange:w=>y({auxSideScale:w})}),l.jsxs("label",{className:"surface-muted block p-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-300",children:[l.jsx("span",{className:"font-semibold text-slate-100",children:"Camera mode"}),l.jsxs("select",{value:g.calibration?.cameraMode??"absolute",onChange:w=>y({cameraMode:w.target.value}),className:"rounded border border-slate-700 bg-slate-900 px-1 py-[2px] text-[0.75rem] text-slate-100",children:[l.jsx("option",{value:"absolute",children:"Absolute"}),l.jsx("option",{value:"velocity",children:"Velocity"})]})]}),l.jsx("p",{className:"text-[0.65rem] text-slate-500",children:"Absolute maps stick to angle; velocity moves over time."})]}),l.jsx(cr,{label:"Camera sensitivity",description:"Velocity mode degrees per second",min:10,max:180,step:5,value:g.calibration?.cameraSensitivity??60,onChange:w=>y({cameraSensitivity:w})})]})]}),l.jsx("div",{className:"space-y-0.5",children:Object.entries(p).map(([w,j])=>l.jsxs("div",{className:"space-y-0.5 surface",children:[l.jsx("p",{className:"text-[0.7rem] text-slate-500",children:w}),l.jsx("div",{className:"space-y-0.5",children:j.map(R=>{const E=g.bindings?.[R.id]?.sources?.[0]??null;return l.jsxs("div",{className:"surface-muted flex items-center justify-between text-xs",children:[l.jsxs("div",{children:[l.jsx("p",{className:"font-semibold text-slate-100",children:R.label}),l.jsx("p",{className:"text-[0.65rem] text-slate-400",children:Hw(E)})]}),l.jsxs("div",{className:"flex items-center gap-0.5",children:[R.kind==="axisPair"&&l.jsxs(l.Fragment,{children:[l.jsx("button",{type:"button",disabled:!E,onClick:()=>C(R,"invertX"),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert X"}),l.jsx("button",{type:"button",disabled:!E,onClick:()=>C(R,"invertY"),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert Y"})]}),R.kind==="axis"&&l.jsx("button",{type:"button",disabled:!E,onClick:()=>C(R),className:"button-dark text-[0.7rem] font-medium disabled:opacity-50",children:"Invert"}),l.jsx("button",{type:"button",onClick:()=>M(R),className:"button-dark text-[0.7rem]",children:"Clear"}),l.jsx("button",{type:"button",onClick:()=>u(R),className:`${o?.id===R.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===R.id?"Waiting…":"Capture"})]})]},R.id)})})]},w))}),l.jsxs("div",{className:"space-y-0.5 surface",children:[l.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"Diagnostics"}),h?l.jsxs("div",{className:"space-y-0.5 text-[0.7rem] text-slate-300",children:[l.jsx("p",{className:"text-slate-400",children:"Raw axes"}),l.jsx("div",{className:"grid grid-cols-2 gap-0.5",children:h.axes.map((w,j)=>l.jsxs("span",{className:"font-mono text-slate-300",children:["A",j,": ",aa.format(w)]},`axis-${j}`))}),l.jsx("p",{className:"text-slate-400",children:"Raw buttons"}),l.jsx("div",{className:"grid grid-cols-2 gap-0.5",children:h.buttons.map((w,j)=>l.jsxs("span",{className:"font-mono text-slate-300",children:["B",j,": ",aa.format(w.value)," ",w.pressed?"●":""]},`btn-${j}`))}),S?.outputs&&l.jsxs(l.Fragment,{children:[l.jsx("p",{className:"text-slate-400",children:"Mapped outputs"}),l.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[l.jsxs("span",{className:"font-mono text-slate-300",children:["Drive: ",aa.format(S.outputs.driveVector.x),","," ",aa.format(S.outputs.driveVector.y)]}),l.jsxs("span",{className:"font-mono text-slate-300",children:["Camera: ",aa.format(S.outputs.cameraAxis)]}),l.jsxs("span",{className:"font-mono text-slate-300",children:["Main: ",aa.format(S.outputs.auxAxis.main)]}),l.jsxs("span",{className:"font-mono text-slate-300",children:["Side: ",aa.format(S.outputs.auxAxis.side)]})]})]})]}):l.jsx("p",{className:"text-[0.7rem] text-slate-400",children:"No controller detected."})]})]})}const Kw={drive:"Drive wheels",aux:"Aux motors"};function hx(n){return Number.isFinite(n)?`${Math.round(n*100)}%`:"--"}function Zw({value:n,color:s="bg-emerald-500"}){const r=`${Math.round(Math.max(0,Math.min(1,n))*100)}%`;return l.jsx("div",{className:"h-2 w-full overflow-hidden rounded bg-slate-800",children:l.jsx("div",{className:`h-full ${s}`,style:{width:r}})})}function Iw(){const{state:{roverId:n},overcurrentLimiter:s}=Dt(),r=m.useMemo(()=>is.map(o=>o.key),[]);return l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[l.jsx("span",{children:"Overcurrent limiter"}),l.jsx("span",{children:s?.adminImmune?"Admin immune":"Active"})]}),n?l.jsxs("div",{className:"space-y-0.5",children:[r.map(o=>{const u=s?.caps?.[o]?.cap??0,f=s?.overcurrent?.groups?.[o]??!1,p=s?.scales?.perGroup?.[o]??1;return l.jsxs("div",{className:"surface space-y-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs",children:[l.jsx("span",{className:"text-slate-200",children:Kw[o]||o}),l.jsx("span",{className:f?"text-red-300":"text-slate-400",children:f?"overcurrent":"ok"})]}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between text-[0.7rem] text-slate-400",children:[l.jsx("span",{children:"Cap"}),l.jsx("span",{children:hx(u)})]}),l.jsx(Zw,{value:u,color:"bg-amber-500"}),l.jsxs("div",{className:"flex items-center justify-between text-[0.7rem] text-slate-400",children:[l.jsx("span",{children:"Scale"}),l.jsx("span",{children:hx(p)})]})]})]},o)}),l.jsxs("div",{className:"surface text-[0.7rem] text-slate-400",children:[l.jsx("div",{children:`Down rate ${s?.config?.downRatePerSec}/s · Up rate ${s?.config?.upRatePerSec}/s`}),l.jsx("div",{children:`Release delay ${s?.config?.releaseDelaySec}s`}),l.jsx("div",{children:`Output rate ${s?.config?.outputRateMs}ms`})]})]}):l.jsx("p",{className:"text-xs text-slate-500",children:"Assign a rover to view limiter status."})]})}const Gg=m.createContext(null);function Yg(){const n=m.useContext(Gg);if(!n)throw new Error("Tabs components must be used within a provider.");return n}const px={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"}},xx={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"},Fg="primary";function yf(...n){return n.filter(Boolean).join(" ")}function Sf({children:n,defaultTab:s,currentTab:r,onTabChange:o,variant:u=Fg}){const[f,p]=m.useState(s??null),[h,x]=m.useState([]),g=m.useCallback(M=>M?(x(C=>C.includes(M)?C:[...C,M]),()=>x(C=>C.includes(M)?C.filter(S=>S!==M):C)):()=>{},[]),v=r??f??h[0]??null;m.useEffect(()=>{s&&r===void 0&&p(s)},[s,r]);const y=m.useCallback(M=>{M&&(r===void 0&&p(M),o&&o(M))},[r,o]),N=m.useMemo(()=>({activeTab:v,setActiveTab:y,registerTab:g,variant:u}),[v,y,g,u]);return l.jsx(Gg.Provider,{value:N,children:n})}function jf({children:n,className:s=""}){return l.jsx("div",{className:yf("flex gap-0.5",s),children:n})}function tn({id:n,children:s,className:r="",disabled:o=!1,highlight:u="none"}){const{activeTab:f,setActiveTab:p,registerTab:h,variant:x}=Yg();m.useEffect(()=>h(n),[n,h]);const g=px[x]??px[Fg],v=f===n,y=xx[u]||xx.none,N=yf(g.base,y||(v?g.active:g.inactive),o?"cursor-not-allowed opacity-50":"",r);return l.jsx("button",{type:"button",className:N,onClick:()=>!o&&p(n),"aria-pressed":v,"aria-disabled":o,children:s})}function Nf({children:n,className:s=""}){return l.jsx("div",{className:yf("mt-0 space-y-0.5",s),children:n})}function nn({id:n,children:s,keepMounted:r=!1}){const{activeTab:o}=Yg(),u=o===n;return!u&&!r?null:!u&&r?l.jsx("div",{hidden:!0,"aria-hidden":"true",children:s}):l.jsx(l.Fragment,{children:s})}function Jw(){const{session:n}=kr(),s=m.useMemo(()=>JSON.stringify(n??{},null,2),[n]);return l.jsxs("div",{className:"panel-section flex min-h-0 flex-col gap-0.5 text-xs",children:[l.jsx("p",{className:"text-sm text-slate-400",children:"Session snapshot"}),l.jsx("pre",{className:"surface min-h-0 flex-1 overflow-y-auto font-mono text-[0.7rem] text-lime-300",children:s})]})}const gx=300,vx=240;function Pw(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,(r,o)=>typeof o=="function"?"[Function]":o instanceof Error?`${o.name}: ${o.message}`:o,0)}catch{return String(n)}}function Ww(n){const r=n.map(o=>Pw(o)).join(" ");return r.length>vx?`${r.slice(0,vx)}…`:r}function eA(){const n=sn(),[s,r]=m.useState([]),o=m.useMemo(()=>s.reduce((u,f)=>(f.direction==="in"&&(u.in+=1),f.direction==="out"&&(u.out+=1),u),{in:0,out:0}),[s]);return m.useEffect(()=>{const u=(x,g,v)=>{r(y=>{const N=[...y,{id:`${Date.now()}-${Math.random().toString(16).slice(2)}`,direction:x,event:g,payload:Ww(v),timestamp:new Date().toLocaleTimeString()}];return N.length>gx?N.slice(-gx):N})},f=(x,...g)=>u("in",x,g),p=(x,...g)=>u("out",x,g);n.onAny(f);let h=null;if(typeof n.onAnyOutgoing=="function")n.onAnyOutgoing(p),h=()=>n.offAnyOutgoing(p);else{const x=n.emit.bind(n);n.emit=(g,...v)=>(p(g,...v),x(g,...v)),h=()=>{n.emit=x}}return()=>{n.offAny(f),h&&h()}},[n]),l.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[l.jsxs("div",{className:"flex items-center justify-between text-sm text-slate-400",children:[l.jsx("span",{children:"Socket activity"}),l.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-400",children:[l.jsxs("span",{className:"surface-muted",children:["in ",o.in]}),l.jsxs("span",{className:"surface-muted",children:["out ",o.out]}),l.jsx("button",{type:"button",className:"button-dark text-xs",onClick:()=>r([]),children:"Clear"})]})]}),l.jsx("div",{className:"surface h-64 overflow-y-auto font-mono text-xs",children:s.length===0?l.jsx("p",{children:"No socket activity yet."}):s.slice().reverse().map(u=>l.jsxs("div",{className:"surface",children:[l.jsx("span",{className:"text-slate-400",children:u.timestamp})," ",l.jsxs("span",{className:u.direction==="in"?"text-emerald-400":"text-amber-400",children:["[",u.direction.toUpperCase(),"]"]})," ",l.jsx("span",{className:"text-cyan-300",children:u.event})," ",l.jsx("span",{className:"text-slate-200",children:u.payload})]},u.id))}),l.jsx("p",{className:"text-xs text-slate-500",children:"Logs are collected only while this panel is open."})]})}const tA=[{key:"start",label:"Start OI"},{key:"safe",label:"Safe"},{key:"full",label:"Full"},{key:"passive",label:"Passive"},{key:"dock",label:"Dock"}];function Xg(){const{state:{roverId:n},actions:{sendOiCommand:s,setSensorStream:r}}=Dt(),o=!!n,[u,f]=zg(),p=sn(),{value:h,save:x}=Qe("page",{hudMapDesktop:!1,connectionTransport:"websocket",swapMobileControlColumns:!1,driveMacroBackoffEnabled:!0}),{value:g,save:v}=Qe("audio",ut),y=h?.connectionTransport||"websocket",N=!!h?.swapMobileControlColumns,M=typeof h?.driveMacroBackoffEnabled=="boolean"?h.driveMacroBackoffEnabled:!0,C=Number.isFinite(g?.masterVolume)?g.masterVolume:ut.masterVolume,S=Number.isFinite(g?.alertVolume)?g.alertVolume:ut.alertVolume,w=Number.isFinite(g?.roverVolume)?g.roverVolume:ut.roverVolume,j=typeof g?.mainBrushDuckEnabled=="boolean"?g.mainBrushDuckEnabled:typeof g?.autoLevelEnabled=="boolean"?g.autoLevelEnabled:ut.mainBrushDuckEnabled,R=Number.isFinite(g?.mainBrushDuckAmount)?Math.max(0,Math.min(1,g.mainBrushDuckAmount)):ut.mainBrushDuckAmount,k=m.useMemo(()=>[{key:"start",label:"Enable stream",enable:!0},{key:"stop",label:"Disable stream",enable:!1}],[]),E=V=>{n&&r(V)},B=V=>{const F=V.target.value;x(W=>({...W??{},connectionTransport:F})),p?.io?.opts&&(p.io.opts.transports=F==="polling"?["polling"]:["websocket","polling"],p.disconnect(),p.connect())},X=V=>F=>{const W=Number(F.target.value),ie=Number.isFinite(W)?Math.max(0,Math.min(1,W)):0;v(oe=>({...oe??{},[V]:ie}))},L=V=>{const F=!!V.target.checked;v(W=>({...W??{},mainBrushDuckEnabled:F}))},z=V=>{const F=!!V.target.checked;x(W=>({...W??{},swapMobileControlColumns:F}))},K=V=>{const F=!!V.target.checked;x(W=>({...W??{},driveMacroBackoffEnabled:F}))};return l.jsxs(Sf,{defaultTab:"keybindings",children:[l.jsxs(jf,{children:[l.jsx(tn,{id:"keybindings",children:"Keybindings"}),l.jsx(tn,{id:"controller",children:"Controller"}),l.jsx(tn,{id:"page",children:"Page settings"}),l.jsx(tn,{id:"admin",children:"Admin"})]}),l.jsxs(Nf,{children:[l.jsx(nn,{id:"keybindings",children:l.jsx("div",{className:"space-y-0.5",children:l.jsx(Lw,{})})}),l.jsx(nn,{id:"controller",children:l.jsx("div",{className:"space-y-0.5",children:l.jsx(Qw,{})})}),l.jsx(nn,{id:"page",children:l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsx("p",{className:"text-slate-400",children:"HUD"}),l.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[l.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:u,onChange:V=>f(V.target.checked)}),l.jsx("span",{children:"Show top-down map in HUD (desktop)"})]}),l.jsx("p",{className:"text-xs text-slate-500",children:"Mobile HUD keeps the map on by default."})]}),l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsx("p",{className:"text-slate-400",children:"Mobile controls"}),l.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[l.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:N,onChange:z}),l.jsx("span",{children:"Swap control columns (put joystick on the left)"})]})]}),l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsx("p",{className:"text-slate-400",children:"Macros"}),l.jsxs("label",{className:"flex items-center gap-0.5 text-slate-200",children:[l.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:M,onChange:K}),l.jsx("span",{children:"Enable backward bump in drive macro"})]})]}),l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsx("p",{className:"text-slate-400",children:"Audio"}),l.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[l.jsx("span",{children:"Master volume"}),l.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(C*100),"%"]})]}),l.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:C,onChange:X("masterVolume"),className:"w-full accent-emerald-500"})]}),l.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[l.jsx("span",{children:"Alert/page sounds"}),l.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(S*100),"%"]})]}),l.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:S,onChange:X("alertVolume"),className:"w-full accent-emerald-500"})]}),l.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[l.jsx("span",{children:"Rover audio"}),l.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(w*100),"%"]})]}),l.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:w,onChange:X("roverVolume"),className:"w-full accent-emerald-500"})]}),l.jsxs("label",{className:"flex items-center justify-between gap-0.5 text-slate-200",children:[l.jsx("span",{children:"Main brush ducking"}),l.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:j,onChange:L})]}),l.jsxs("label",{className:"grid gap-0.5 text-slate-200",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[l.jsx("span",{children:"Main brush duck amount"}),l.jsxs("span",{className:"text-xs text-slate-400",children:[Math.round(R*100),"%"]})]}),l.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:R,onChange:X("mainBrushDuckAmount"),className:"w-full accent-emerald-500",disabled:!j})]}),l.jsx("p",{className:"text-xs text-slate-500",children:"Lowers rover audio only while the main brush is running."})]}),l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsx("p",{className:"text-slate-400",children:"Connection"}),l.jsxs("label",{className:"flex items-center justify-between gap-0.5 text-slate-200",children:[l.jsx("span",{children:"Transport"}),l.jsxs("select",{value:y,onChange:B,className:"field-input text-sm",children:[l.jsx("option",{value:"websocket",children:"WebSocket"}),l.jsx("option",{value:"polling",children:"Polling"})]})]}),l.jsx("p",{className:"text-xs text-slate-500",children:"Switching reconnects your session."})]})]})}),l.jsx(nn,{id:"admin",children:l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsx("p",{className:"text-slate-400",children:"Manual OI commands"}),l.jsx("div",{className:"surface flex flex-wrap gap-0.5",children:tA.map(V=>l.jsx("button",{type:"button",onClick:()=>s(V.key),disabled:!o,className:"button-dark text-xs disabled:opacity-30",children:V.label},V.key))})]}),l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsx("p",{className:"text-slate-400",children:"Sensor stream"}),l.jsx("div",{className:"surface flex gap-0.5",children:k.map(V=>l.jsx("button",{type:"button",onClick:()=>E(V.enable),disabled:!o,className:"flex-1 button-dark text-xs disabled:opacity-30",children:V.label},V.key))}),!o&&l.jsx("p",{className:"text-xs text-slate-500",children:"Assign a rover to toggle streams."})]}),l.jsx($g,{}),l.jsx(Iw,{}),l.jsx(Mw,{}),l.jsx(Jw,{}),l.jsx(eA,{})]})})]})]})}const bx={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 nA(n){return bx[n]||bx.desktop}function Qg({actionId:n,keymap:s}){const r=s?.[n]?.[0]??"";return l.jsx("span",{className:"rounded border border-slate-600 bg-slate-900/40 px-1 text-[0.7rem] text-slate-200",children:An(r)})}function yx(n,s){return n.map((r,o)=>typeof r=="string"?l.jsx("span",{children:r},`text-${o}`):r?.action?l.jsx(Qg,{actionId:r.action,keymap:s},`pill-${r.action}-${o}`):r?.text?l.jsx("span",{children:r.text},`span-${o}`):null)}function qo(n,s,r){if(typeof n=="string")return n;if(Array.isArray(n?.segments))return yx(n.segments,s);if(n&&typeof n=="object"){if(typeof n.text=="string")return n.text;if(Array.isArray(n))return yx(n,s)}return String(n??"")}function aA({hero:n,keymap:s}){return n?l.jsxs("div",{className:"surface space-y-0.5 px-0.5 py-0.5",children:[l.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-0.5",children:[l.jsxs("div",{children:[l.jsx("p",{className:"text-sm font-semibold text-white",children:n.title}),n.subtitle&&l.jsx("p",{className:"text-xs text-slate-300",children:n.subtitle})]}),n.chips&&l.jsx("div",{className:"flex flex-wrap gap-0.5 text-[0.7rem] text-slate-200",children:n.chips.map(r=>l.jsx("span",{className:"rounded border border-slate-700 px-1 py-[2px]",children:r},r))})]}),n.bullets&&l.jsx("ul",{className:"space-y-0.5 text-[0.85rem] text-slate-200",children:n.bullets.map((r,o)=>{const u=Array.isArray(r?.segments)?`hero-${o}`:`hero-${o}`;return l.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:qo(r,s)},u)})})]}):null}function sA({block:n,keymap:s}){return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("p",{className:"text-xs font-semibold text-slate-200",children:n.title}),l.jsx("ul",{className:"space-y-0.5 text-[0.8rem] text-slate-300",children:n.items.map((r,o)=>{const u=`item-${o}`;return l.jsx("li",{className:"surface-muted flex flex-wrap items-center gap-0.5 px-0.5 py-0.25",children:qo(r,s)},u)})})]})}function lA({block:n}){const s=n.tone==="info"?"border-cyan-500/40":"border-slate-700";return l.jsxs("div",{className:`surface space-y-0.5 border ${s} px-0.5 py-0.5`,children:[l.jsx("p",{className:"text-xs font-semibold text-slate-100",children:n.title}),n.body&&l.jsx("ul",{className:"space-y-0.5 text-[0.8rem] text-slate-300",children:n.body.map((r,o)=>l.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:qo(r,{})},`callout-${o}`))})]})}function rA({group:n,keymap:s}){return l.jsxs("div",{className:"space-y-0.5 surface",children:[l.jsx("p",{className:"px-0.5 py-0.25 text-[0.75rem] font-semibold text-slate-200",children:n.title}),l.jsx("div",{className:"space-y-0.5 px-0.5 pb-0.25",children:n.items.map(r=>l.jsxs("div",{className:"surface-muted flex items-center justify-between gap-0.5 px-0.5 py-0.25 text-[0.8rem]",children:[l.jsx("span",{className:"text-slate-200",children:r.label}),l.jsx(Qg,{actionId:r.action,keymap:s})]},r.action))})]})}function iA({block:n,keymap:s}){return n?l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-200",children:[l.jsx("span",{className:"font-semibold",children:n.title}),n.footnote&&l.jsx("span",{className:"text-[0.7rem] text-slate-400",children:n.footnote})]}),l.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-0.5",children:n.groups?.map(r=>l.jsx(rA,{group:r,keymap:s},r.id))})]}):null}function oA({block:n}){return n?l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("p",{className:"text-xs font-semibold text-slate-200",children:n.title}),l.jsx("ul",{className:"space-y-0.5 text-[0.8rem] text-slate-300",children:n.items?.map((s,r)=>l.jsx("li",{className:"surface-muted px-0.5 py-0.25",children:qo(s,{})},`gamepad-${r}`))})]}):null}function Sx({block:n,keymap:s}){if(!n)return null;switch(n.type){case"list":return l.jsx(sA,{block:n,keymap:s});case"callout":return l.jsx(lA,{block:n});case"keyboard":return l.jsx(iA,{block:n,keymap:s});case"gamepad":return l.jsx(oA,{block:n});default:return null}}function Kg({layout:n,keymap:s}){const r=m.useMemo(()=>nA(n),[n]),o=s||{},u=r.main||[],f=r.aside||[];return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx(aA,{hero:r.hero,keymap:o}),l.jsxs("div",{className:"grid gap-0.5",style:{gridTemplateColumns:"repeat(auto-fit, minmax(360px, 1fr))"},children:[l.jsx("div",{className:"space-y-0.5",children:u.map((p,h)=>l.jsx(Sx,{block:p,keymap:o},p.title||h))}),l.jsx("div",{className:"space-y-0.5",children:f.map((p,h)=>l.jsx(Sx,{block:p,keymap:o},p.title||h))})]})]})}function Zg({layout:n,onOpenOverlay:s}){const{state:r}=Dt();return l.jsxs("section",{className:"panel-section space-y-0.5 text-sm",children:[l.jsxs("div",{className:"flex items-center justify-between text-xs text-slate-400",children:[l.jsx("span",{children:"Help"}),l.jsx("button",{type:"button",onClick:s,className:"button-dark px-1 py-0.25 text-[0.75rem]",children:"Open full help"})]}),l.jsx(Kg,{layout:n,keymap:r?.keymap||{}})]})}const cA=["kal","rms","slt","ksp","bdl"],uA=Array.from({length:10},(n,s)=>s*10);function To({hideInput:n=!1,hideSpectatorNotice:s=!1,fillHeight:r=!1,allowSpectatorInput:o=!1}){const u=pe(_=>_.session?.role||null),f=pe(_=>_.session?.assignment?.roverId||null),p=pe(_=>_.session?.roster??[]),{messages:h,typing:x,sendMessage:g,registerInputRef:v,onInputFocus:y,onInputBlur:N,blurChat:M,setTypingActive:C}=cf(),{value:S,save:w}=Qe("tts",{engine:"flite",voice:"rms",pitch:50}),[j,R]=m.useState(""),[k,E]=m.useState(!1),[B,X]=m.useState(!1),[L,z]=m.useState(()=>S?.engine||"flite"),[K,V]=m.useState(()=>S?.voice||"rms"),[F,W]=m.useState(()=>Number.isFinite(S?.pitch)?S.pitch:50),ie=u!=="spectator"||o,oe=m.useRef(null),T=!!m.useMemo(()=>p.find(_=>String(_.id)===String(f))||null,[f,p])?.audio?.ttsEnabled,H=m.useMemo(()=>h.slice(-200),[h]),J=m.useMemo(()=>x||[],[x]);m.useEffect(()=>{oe.current&&(oe.current.scrollTop=oe.current.scrollHeight)},[H,J]),m.useEffect(()=>{const _=S?.engine||"flite",I=S?.voice||"rms",ne=Number.isFinite(S?.pitch)?S.pitch:50;L!==_&&z(_),K!==I&&V(I),F!==ne&&W(ne)},[L,F,S?.engine,S?.pitch,S?.voice,K]),m.useEffect(()=>{X(!!T)},[T]);const te=m.useMemo(()=>!T||!B?null:L==="espeak"?{speak:!0,engine:L,pitch:F}:{speak:!0,engine:L,voice:K},[L,F,B,T,K]);async function ue(_){if(_.preventDefault(),!ie||n)return;const ne=j.replace(/\\n/g,` -`).trim();if(ne){E(!0);try{await g(ne,te),R(""),M(),C(!1)}catch(me){alert(me.message)}finally{E(!1)}}}const q=r?"flex-1 min-h-0 overflow-y-auto":"h-48 overflow-y-auto";return l.jsxs("section",{className:`panel-section space-y-0.5 text-base ${r?"flex h-full flex-col overflow-hidden":""}`,children:[l.jsxs("div",{className:`surface overflow-y-auto space-y-0.5 px-0 ${q}`,ref:oe,children:[H.length===0&&J.length===0?l.jsx("p",{className:"text-sm text-slate-500",children:"No messages yet."}):H.map(_=>l.jsx(lf,{message:_},_.id)),J.map(_=>l.jsx(xg,{message:_},`typing-${_.typingId||_.id}`))]}),!n&&l.jsxs("form",{className:"flex flex-wrap items-stretch gap-0.5",onSubmit:ue,children:[l.jsx("input",{className:"field-input flex-1 min-w-[10rem]",value:j,onChange:_=>{const I=_.target.value;R(I),C(!!I.trim())},onFocus:_=>{y(_),C(!!j.trim())},onBlur:_=>{N(_),C(!1)},onKeyDown:_=>{_.key==="Enter"&&!j.trim()&&(_.preventDefault(),M(),C(!1))},ref:_=>v(_,{target:"panel"}),placeholder:ie?"Type a message…":s?"":"Spectators cannot chat",disabled:!ie}),T&&l.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 basis-full sm:basis-auto",children:[l.jsxs("label",{className:"flex items-center gap-0.5 text-xs text-slate-300",children:[l.jsx("input",{type:"checkbox",checked:B,onChange:_=>X(_.target.checked),className:"accent-cyan-500"}),l.jsx("span",{children:"Speak"})]}),l.jsxs("select",{value:L,onChange:_=>{const I=_.target.value;z(I),w(ne=>({...ne||{},engine:I}))},className:"field-input text-xs",children:[l.jsx("option",{value:"flite",children:"flite"}),l.jsx("option",{value:"espeak",children:"espeak"})]}),L==="flite"?l.jsx("select",{value:K,onChange:_=>{const I=_.target.value;V(I),w(ne=>({...ne||{},voice:I}))},className:"field-input text-xs",children:cA.map(_=>l.jsx("option",{value:_,children:_},_))}):l.jsx("select",{value:F,onChange:_=>{const I=Number(_.target.value);W(I),w(ne=>({...ne||{},pitch:I}))},className:"field-input text-xs",children:uA.map(_=>l.jsxs("option",{value:_,children:["pitch ",_]},_))})]}),l.jsx("button",{type:"submit",disabled:!ie||k,className:"button-dark h-full disabled:opacity-50 self-stretch",children:k?"...":"Send"})]})]})}function Do({compact:n=!1}){const s=pe(y=>y.session?.role||null),{setNickname:r}=Xt(),{value:o,save:u}=Qe("profile",{nickname:""}),[f,p]=m.useState(o.nickname||""),[h,x]=m.useState(!1),g=s!=="spectator";m.useEffect(()=>{p(o.nickname||"")},[o.nickname]);async function v(y){if(y.preventDefault(),!g)return;const N=(f||"").trim().slice(0,32);if(N){x(!0);try{await r(N),u({nickname:N})}catch(M){alert(M.message)}finally{x(!1)}}}return l.jsxs("form",{className:"grid w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-stretch gap-0.5",onSubmit:v,children:[l.jsx("input",{className:"field-input flex-1 min-w-0",value:f,onChange:y=>p(y.target.value),maxLength:32,placeholder:"Enter a nickname",disabled:!g}),l.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 dA({socials:n,discordInvite:s,kofiLink:r}){const o=Array.isArray(n)?n:null;if(o&&o.length)return o;const u=[];return s&&u.push({id:"discord",label:"Discord",url:s}),r&&u.push({id:"kofi",label:"Ko-fi",url:r}),u}function fA(n){if(!n||typeof n!="object")return null;const s=n.id||n.service||n.key||n.name||null,r=n.label||n.title||n.name||s||"Link",o=n.url||n.link||n.href||null;return o?{id:s,label:r,url:o}:null}function Ig({className:n=""}){const s=pe(o=>({socials:o.session?.socials??[],discordInvite:o.session?.discord?.invite||null,kofiLink:o.session?.kofi?.link||null})),r=dA(s).map(fA).filter(Boolean).slice(0,4);return r.length?l.jsx("div",{className:`grid grid-cols-2 grid-rows-2 gap-0.5 ${n}`,children:r.map(o=>l.jsx(pf,{...o},`${o.id||o.label}-${o.url}`))}):null}function mA({compact:n=!1}){return l.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:l.jsx("div",{className:"surface flex w-full items-center px-0 py-0",children:l.jsx(Do,{compact:n})})})}function hA(){return l.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:l.jsx(Ig,{className:"flex-1 min-h-0"})})}function yd(...n){return n.filter(Boolean).join(" ")}function pA(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function xA(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function gA(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 vA(n,s){if(!n)return"";const r=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${r} (you)`:r}function _o({title:n="Rovers"}){const s=pe(j=>j.session?.role||null),r=pe(j=>j.session?.roster??[]),o=pe(j=>j.session?.turnQueues??{}),u=pe(j=>j.session?.users??[]),f=pe(j=>j.session?.socketId||null),{requestControl:p}=Xt(),[h,x]=m.useState({}),[g,v]=m.useState(()=>Date.now()),y=m.useMemo(()=>s&&s!=="spectator",[s]),N=m.useMemo(()=>s==="admin"||s==="lockdown"||s==="lockdown-admin",[s]),M=m.useMemo(()=>Object.values(o||{}).some(j=>j?.deadline||j?.idleDeadline),[o]);m.useEffect(()=>{if(!M)return;const j=setInterval(()=>{v(Date.now())},1e3);return()=>clearInterval(j)},[M]);const C=m.useMemo(()=>{const j=new Set(r.map(k=>String(k.id))),R=Object.keys(o||{}).filter(k=>!j.has(String(k))).map(k=>({id:k,name:k,locked:!1,batteryState:null}));return[...r,...R]},[r,o]);async function S(j){if(j){x(R=>({...R,[j]:!0}));try{await p(j)}catch(R){alert(R.message)}finally{x(R=>({...R,[j]:!1}))}}}const w=j=>u.find(R=>R.socketId===j)||{socketId:j,nickname:null,role:null};return l.jsxs("div",{className:"space-y-0.5 text-sm",children:[n&&l.jsx("p",{className:"text-sm text-slate-400",children:n}),C.length===0?l.jsx("p",{className:"text-sm text-slate-500",children:"No rovers registered."}):l.jsx("ul",{className:"space-y-0.5 text-sm",children:C.map(j=>{const R=String(j.id),k=o?.[R]||null,E=k?.queue||[],B=k?.idleDeadline||k?.deadline||null,X=B&&B>g?Math.ceil((B-g)/1e3):B?0:null,L=k?.current||null,z=L?E.findIndex(te=>te===L):-1,K=E.length>1?z>=0?E[(z+1)%E.length]:E[0]:null,V=!!(f&&L&&L===f),F=!!(f&&K&&K===f),W=X!=null&&(V||F),ie=!!j.locked,oe=ie&&!N,$=!!(j?.private?.enabled&&j?.private?.open),T=j.lockReason?`locked: ${j.lockReason}`:"locked",H=ie?T:h[R]?"...":"request",J=y&&!oe&&!h[R];return l.jsxs("li",{className:yd("surface flex flex-wrap items-start justify-between gap-0.5",J&&"cursor-pointer",ie?"bg-red-900/40":$?"bg-amber-700/35 border border-amber-200/30":null),onClick:()=>{J&&S(j.id)},children:[l.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[l.jsxs("div",{className:"flex items-center gap-0.5",children:[l.jsx("p",{className:"text-slate-200",children:l.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ia(j.color,.16),children:j.name})}),W?l.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem] text-slate-200",children:V?`${X}s left`:`Your turn in ${X}s`}):null]}),l.jsx("span",{className:yd("text-[0.75rem] font-semibold",xA(j)),children:pA(j)})]}),E.length===0?l.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"No queue."}):l.jsx("div",{className:"flex flex-wrap items-center gap-0.5",children:E.map((te,ue)=>{const q=w(te),_=te===L,I=!!(K&&te===K&&!_),ne=_?"bg-sky-600 text-white ring-2 ring-amber-300":I?"bg-emerald-700/60 text-emerald-100 ring-1 ring-emerald-300/70":"bg-slate-800 text-slate-200";return l.jsxs("span",{className:`flex items-center gap-0.5 rounded px-1 text-[0.7rem] ${ne}`,children:[l.jsx("span",{className:`${gA(q.role)} font-semibold`,children:vA(q,f)}),_&&l.jsx("span",{className:"text-[0.65rem] text-slate-200",children:"now"}),I&&l.jsx("span",{className:"text-[0.65rem] text-emerald-100",children:"next"})]},`${R}-${te}-${ue}`)})})]}),y?l.jsx("button",{type:"button",onClick:te=>{te.stopPropagation(),S(j.id)},disabled:h[R]||oe,className:yd("button-dark disabled:opacity-40",ie&&"bg-red-600/70 text-white hover:bg-red-600"),children:H}):null]},j.id)})})]})}function bA(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 yA(n,s){if(!n)return"";const r=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${r} (you)`:r}function jo({hideNicknameForm:n=!1,hideHeader:s=!1,className:r="",fillHeight:o=!1,compact:u=!1}){const f=pe(y=>y.session?.role||null),p=pe(y=>y.session?.users??[]),h=pe(y=>y.session?.socketId||null),x=f!=="spectator",g=m.useMemo(()=>[...p].sort((y,N)=>y.socketId===h?-1:N.socketId===h?1:(y.nickname||"").localeCompare(N.nickname||"")),[h,p]),v=o?"flex-1 min-h-0 overflow-y-auto":u?"h-28 overflow-y-auto":"h-48 overflow-y-auto";return l.jsxs("section",{className:`panel-section space-y-0.5 text-base ${o?"flex h-full min-h-0 flex-col overflow-hidden":""} ${r}`,children:[!n&&l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("div",{className:"grid gap-0.5 md:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]",children:[l.jsx("div",{className:"min-w-0",children:l.jsx("div",{className:"surface flex w-full items-center px-0 py-0",children:l.jsx(Do,{compact:u})})}),l.jsx(Ig,{})]}),!x&&l.jsx("p",{className:"text-xs text-slate-500",children:"Spectators cannot set nicknames."})]}),l.jsxs("div",{className:`space-y-0.5 ${o?"flex flex-1 min-h-0 flex-col":""}`,children:[!s&&l.jsxs("div",{className:`flex items-center justify-between text-sm text-slate-400 ${u?"text-xs":""}`,children:[l.jsx("span",{children:"Users"}),l.jsx("span",{className:"text-xs text-slate-500",children:g.length})]}),l.jsx("div",{className:`surface flex flex-wrap content-start items-start gap-0.5 px-0 pb-0 ${v} ${u?"text-[0.8rem]":""}`,children:g.length===0?l.jsx("p",{className:"text-sm text-slate-500",children:"Waiting for users…"}):g.map(y=>l.jsx("span",{className:`rounded bg-slate-800/80 px-1 py-0.25 text-[0.7rem] ${bA(y.role)}`,children:yA(y,h)},y.socketId))})]})]})}const SA=/^cu_[a-f0-9]{32}$/,wr="field-input w-full max-w-sm text-left focus:ring-emerald-500",Oo="mx-auto w-full max-w-xl flex justify-center",pr="mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center";function jA(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 jx=8*1024*1024,rs=16e3,NA={iceServers:[{urls:"stun:stun.l.google.com:19302"}],bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"};function Nx(n){let s="";for(let o=0;o{if(!n||n.iceGatheringState==="complete"){r();return}const o=setTimeout(()=>{n.removeEventListener("icegatheringstatechange",u),r()},s);function u(){n.iceGatheringState==="complete"&&(clearTimeout(o),n.removeEventListener("icegatheringstatechange",u),r())}n.addEventListener("icegatheringstatechange",u)})}function wx(n){if(!n)return!1;const s=n.connectionState,r=n.iceConnectionState;return s==="connected"||r==="connected"||r==="completed"}function EA(n,s=1e4){return new Promise((r,o)=>{if(!n){o(new Error("Peer connection missing"));return}if(wx(n)){r();return}const u=setTimeout(()=>{p(),o(new Error("Peer connection timeout"))},s),f=()=>{wx(n)?(p(),r()):(n.connectionState==="failed"||n.connectionState==="closed"||n.iceConnectionState==="failed")&&(p(),o(new Error(`Peer connection ${n.connectionState||n.iceConnectionState}`)))};function p(){clearTimeout(u),n.removeEventListener("connectionstatechange",f),n.removeEventListener("iceconnectionstatechange",f)}n.addEventListener("connectionstatechange",f),n.addEventListener("iceconnectionstatechange",f)})}async function kA(n){if(!n?.getParameters||!n?.setParameters)return;const s=n.getParameters()||{},r=s.encodings&&s.encodings[0]||{};s.encodings=[{...r,maxBitrate:64e3,dtx:"disabled"}];try{await n.setParameters(s)}catch{}}function MA(n,s=6e3){return new Promise((r,o)=>{if(!n){o(new Error("Peer connection missing"));return}const u=Date.now();let f=-1;const p=setInterval(async()=>{if(Date.now()-u>s){clearInterval(p),o(new Error("WHIP connected but no outbound audio flow"));return}try{const h=n.getSenders().filter(x=>x.track?.kind==="audio");for(const x of h){const g=await x.getStats();for(const v of g.values()){if(v.type!=="outbound-rtp"||v.kind!=="audio")continue;const y=Number(v.bytesSent||0),N=Number(v.packetsSent||0);if(f<0)f=y;else if(y>f+200||N>5){clearInterval(p),r();return}}}}catch{}},250)})}function RA(n){const s=n.reduce((u,f)=>u+f.length,0),r=new Float32Array(s);let o=0;for(const u of n)r.set(u,o),o+=u.length;return r}function qA(n){const s=new Int16Array(n.length);for(let r=0;r{for(let v=0;vv&&s?.[v]||null,[s,v]),I=!!(_&&_.state!=="offline"&&!_.error),ne=_?.source==="upload"&&_?.state==="playing",me=_?.source==="mic-whip"&&(_?.state==="starting"||_?.state==="playing"),ce=!!(!j&&K.current&&(S||q)),se=!j&&(R==="live"||R==="starting"),ve=j&&E==="recording",he=j&&E==="sending",be=An(h?.keymap?.micPtt?.[0])||"M",Ve=m.useCallback(fe=>{const we=fe==="clip"?"clip":"live";g(Ae=>({...Ae||{},pttMode:we}))},[g]),De=async()=>{if(!v){L("Take control of your rover first.");return}if(!y){L("Select an audio file first.");return}if(y.size>jx){L(`File too large (max ${jx} bytes).`);return}C(!0),L("");try{const fe=await y.arrayBuffer(),we=Nx(new Uint8Array(fe));await r?.({roverId:v,name:y.name,mime:y.type||"",dataBase64:we}),L("Upload playback started.")}catch(fe){L(fe?.message||"Failed to play upload.")}finally{C(!1)}},Te=async()=>{if(!v){L("Take control of your rover first.");return}C(!0),L("");try{await o?.(v),L("Upload playback stopped.")}catch(fe){L(fe?.message||"Failed to stop upload.")}finally{C(!1)}},ze=m.useCallback(async fe=>{const we=String(fe||W.current||"").trim();if(F.current=!1,k("idle"),V.current){try{V.current.getSenders().forEach(Ae=>Ae.track?.stop())}catch{}try{V.current.close()}catch{}}if(V.current=null,z.current)try{z.current.getTracks().forEach(Ae=>Ae.stop())}catch{}if(z.current=null,K.current=null,we)try{await p?.(we)}catch{}W.current=""},[p]),$e=m.useCallback(async fe=>{const we=await u?.(fe),Ae=String(we?.whipUrl||"").trim(),it=String(we?.token||"").trim();if(!Ae||!it)throw new Error("WHIP endpoint unavailable");const le=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:rs,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}});z.current=le;const de=le.getAudioTracks()?.[0];if(K.current=de||null,de&&(de.enabled=!!(S||q)),de?.applyConstraints)try{await de.applyConstraints({channelCount:1,sampleRate:rs,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1})}catch{}const Me=new RTCPeerConnection(NA);V.current=Me,Me.onconnectionstatechange=()=>{if(!F.current)return;const Qt=Me.connectionState;if(Qt==="connected"){k("live");return}(Qt==="failed"||Qt==="disconnected"||Qt==="closed")&&(k("error"),L(`WHIP transport ${Qt}.`))},le.getAudioTracks().forEach(Qt=>{const Ba=Me.addTrack(Qt,le);kA(Ba)});const ft=await Me.createOffer({offerToReceiveAudio:!1,offerToReceiveVideo:!1});await Me.setLocalDescription(ft),await CA(Me,1800);const kt=await fetch(Ae,{method:"POST",headers:{"Content-Type":"application/sdp",...AA(it)},body:Me.localDescription?.sdp||ft.sdp});if(!kt.ok)throw new Error(`WHIP request failed: ${kt.status}`);const ds=await kt.text();await Me.setRemoteDescription({type:"answer",sdp:ds}),await EA(Me,1e4),await MA(Me,6e3),await f?.(fe)},[S,q,f,u]),vt=m.useCallback(async()=>{if(te.current=!1,T.current){try{T.current.disconnect()}catch{}T.current.onaudioprocess=null}if($.current)try{$.current.disconnect()}catch{}if(H.current)try{H.current.disconnect()}catch{}if(ie.current)try{ie.current.getTracks().forEach(fe=>fe.stop())}catch{}if(oe.current)try{await oe.current.close()}catch{}J.current=[],T.current=null,$.current=null,H.current=null,ie.current=null,oe.current=null,ue.current=rs},[]),re=m.useCallback(async()=>{if(ie.current&&oe.current&&T.current)return;B(de=>de==="recording"?de:"arming");const fe=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:rs,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}}),we=new AudioContext({latencyHint:"interactive"}),Ae=we.createMediaStreamSource(fe),it=we.createScriptProcessor(1024,1,1),le=we.createGain();le.gain.value=0,it.onaudioprocess=de=>{if(!te.current)return;const Me=de.inputBuffer.getChannelData(0);J.current.push(new Float32Array(Me))},Ae.connect(it),it.connect(le),le.connect(we.destination),ie.current=fe,oe.current=we,$.current=Ae,T.current=it,H.current=le,ue.current=we.sampleRate||rs},[]),xe=m.useCallback(async({send:fe})=>{const we=te.current;if(te.current=!1,!we){fe||B("idle");return}const Ae=J.current;if(J.current=[],!fe){B("idle");return}if(!v){B("idle");return}if(!Ae.length){B("idle");return}B("sending");try{const it=RA(Ae),le=TA(it,ue.current||rs),de=Nx(le);await r?.({roverId:v,name:`ptt-${Date.now()}.wav`,mime:"audio/wav",dataBase64:de}),B("idle")}catch(it){B("error"),L(it?.message||"Failed to send PTT clip.")}},[r,v]),Ee=m.useCallback(async()=>{if(!v){L("Take control of your rover first.");return}await re(),J.current=[],te.current=!0,B("recording")},[re,v]);return m.useEffect(()=>{let fe=!1;async function we(){if(j){await ze(W.current||v);return}if(!v){await ze(W.current);return}if(!(F.current&&W.current===v)&&!(!S&&!q))try{k("starting"),L(""),F.current=!0,W.current=v,await $e(v),fe||k("live")}catch(Ae){fe||(k("error"),L(Ae?.message||"Failed to start mic forwarding.")),await ze(v)}}return we(),()=>{fe=!0}},[j,S,q,v,$e,ze]),m.useEffect(()=>{const fe=K.current;fe&&(fe.enabled=!!(!j&&(S||q)))},[j,S,q]),m.useEffect(()=>{let fe=!1;async function we(){if(!j||!v){te.current&&await xe({send:!1}),B("idle");return}try{await re(),!fe&&!te.current&&B("idle")}catch(Ae){fe||(B("error"),L(Ae?.message||"Microphone access failed for clip mode."))}}return we(),()=>{fe=!0}},[j,re,xe,v]),m.useEffect(()=>{let fe=!1;async function we(){if(j){if(!v){te.current&&await xe({send:!1});return}if(q){if(!te.current)try{L(""),await Ee()}catch(Ae){fe||(B("error"),L(Ae?.message||"Failed to start clip recording."))}}else te.current&&await xe({send:!0})}}return we(),()=>{fe=!0}},[j,xe,q,v,Ee]),m.useEffect(()=>()=>{ze(W.current||v),vt()},[v,ze,vt]),l.jsx("section",{className:"surface",children:l.jsxs("div",{className:"grid gap-1",children:[l.jsx("p",{className:"text-sm text-slate-100 text-center",children:"Audio Controls"}),l.jsx("section",{className:"surface",children:l.jsxs("div",{className:"flex items-center justify-center gap-0.5 py-0.25 text-xs text-slate-300",children:[l.jsx("span",{children:"Push-to-Talk Key"}),l.jsx(Ax,{label:be})]})}),l.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-2",children:[l.jsx("section",{className:"surface h-full",children:l.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"PTT Mode"}),l.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."}),l.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[l.jsx("button",{type:"button",className:`button-dark w-full text-sm ${j?"":"bg-emerald-500 text-white hover:bg-emerald-500"}`,onClick:()=>Ve("live"),children:"Live Mic (WHIP)"}),l.jsx("button",{type:"button",className:`button-dark w-full text-sm ${j?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,onClick:()=>Ve("clip"),children:"Record Clip"})]})]})}),l.jsx("section",{className:"surface h-full",children:l.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_1fr]",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"PTT Clip Status"}),l.jsxs("div",{className:"grid gap-0.5 content-start",children:[l.jsx(vn,{label:"Mode",active:j,detail:j?"record clip":"live mic"}),l.jsx(vn,{label:"PTT hold",active:q,detail:q?"held":"released"}),l.jsx(vn,{label:"Recording",active:ve,detail:ve?"capturing":"idle"}),l.jsx(vn,{label:"Playback",active:j&&ne,detail:j&&ne?"playing":"idle"})]})]})})]}),l.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-2",children:[l.jsx("section",{className:"surface h-full",children:l.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr_auto]",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Audio Upload"}),l.jsxs("label",{className:"mx-auto grid w-full max-w-sm gap-0.5 text-xs text-slate-300 text-center",children:[l.jsx("span",{children:"Audio file (mp3 / wav / ogg)"}),l.jsx("input",{className:`${wr} text-center`,type:"file",accept:".mp3,.wav,.ogg,audio/mpeg,audio/wav,audio/ogg",disabled:M||!v,onChange:fe=>N(fe.target.files?.[0]||null)})]}),l.jsx("div",{className:"mx-auto w-full max-w-sm text-center",children:y?l.jsxs("div",{className:"surface-muted text-xs text-slate-300",children:[y.name," (",y.size," bytes)"]}):l.jsx("div",{className:"surface-muted text-xs text-slate-500",children:"No file selected"})}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:M||!v,onClick:De,children:M?"Working...":"Play Upload"}),l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:M||!v,onClick:Te,children:"Stop"})]})]})}),l.jsx("section",{className:"surface h-full",children:l.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Live Microphone"}),l.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:[l.jsx("input",{type:"checkbox",checked:S,disabled:!v||j,onChange:fe=>g(we=>({...we||{},openMicEnabled:!!fe.target.checked}))}),l.jsx("span",{children:j?"Open mic (live mode only)":"Open mic"})]}),l.jsxs("div",{className:"grid gap-0.5 content-start",children:[l.jsx(vn,{label:"WHIP link",active:se,detail:R}),l.jsx(vn,{label:"Mic hot",active:ce,detail:ce?"transmitting":"muted"}),l.jsxs("div",{className:"surface-muted text-center text-xs text-slate-400",children:["Hold ",l.jsx(Ax,{label:be})," to talk"]})]})]})})]}),l.jsx("section",{className:"surface",children:l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Audio Status"}),l.jsxs("div",{className:"grid gap-0.5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-6",children:[l.jsx(vn,{label:"Forward pipe",active:I,detail:I?"connected":"offline"}),l.jsx(vn,{label:"Upload playback",active:ne,detail:ne?"playing":"idle"}),l.jsx(vn,{label:"Mic relay",active:me,detail:me?"active":"idle"}),l.jsx(vn,{label:"WHIP transport",active:se,detail:R}),l.jsx(vn,{label:"Clip recording",active:ve,detail:ve?"recording":"idle"}),l.jsx(vn,{label:"Clip sending",active:he,detail:he?"sending":"idle"})]}),X?l.jsx("div",{className:"text-xs text-slate-400 text-center",children:X}):null]})})]})})}function _A({pendingRequestId:n,currentStoredKey:s,nickname:r,requestVerification:o,applyIdentityKey:u,onMessage:f,fullWidth:p=!1}){const[h,x]=m.useState(0),[g,v]=m.useState(""),[y,N]=m.useState(!1),[M,C]=m.useState(!1),S=()=>{x(1),v(s),N(!1),f?.("")},w=()=>{x(0),N(!1)},j=async k=>{if(k.preventDefault(),!y){f?.("Please confirm your nickname agreement before sending.");return}if(h<3){f?.("Complete all request steps before sending.");return}C(!0),f?.("");try{const E=await u(g);await o?.(),v(E),x(0),N(!1),f?.("Verification request sent to lockdown admins.")}catch(E){f?.(E.message||"Failed to submit request.")}finally{C(!1)}},R=p?"w-full":Oo;return n?l.jsx("section",{className:`surface text-sm text-slate-300 ${R}`,children:l.jsxs("div",{className:pr,children:["Verification request pending: ",n]})}):h===0?l.jsx("section",{className:`surface ${R}`,children:l.jsxs("div",{className:pr,children:[l.jsx("p",{className:"text-sm text-slate-300",children:"Verification"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:S,disabled:M,children:"Request Verification"})]})}):l.jsx("form",{className:`surface ${R}`,onSubmit:j,children:l.jsxs("div",{className:pr,children:[l.jsx("p",{className:"text-sm text-slate-300",children:"Request verification"}),l.jsxs("p",{className:"text-xs text-slate-500",children:["Step ",h," of 3"]}),h===1?l.jsxs("div",{className:"space-y-0.5",children:[l.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."}),l.jsx("div",{className:"mx-auto w-full max-w-sm",children:l.jsx(Do,{compact:!0})}),l.jsxs("div",{className:"surface-muted mx-auto w-full max-w-sm text-xs text-slate-300 text-center",children:["Current nickname: ",l.jsx("span",{className:"font-semibold",children:r||"(not set)"})]}),l.jsxs("label",{className:"flex items-center justify-center gap-0.5 text-xs text-slate-300 text-center",children:[l.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:y,onChange:k=>N(k.target.checked)}),l.jsx("span",{children:"I understand this nickname is tied to my verification."})]}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!r||!y,onClick:()=>x(2),children:"Continue"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:w,children:"Cancel"})]})]}):null,h===2?l.jsxs("div",{className:"space-y-0.5",children:[l.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."}),l.jsx("input",{className:wr,type:"password",name:"identity_key_request",autoComplete:"current-password",maxLength:35,value:g,onChange:k=>v(k.target.value.toLowerCase()),placeholder:"Identity key for this request"}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!g,onClick:()=>navigator.clipboard?.writeText(g),children:"Copy Key"}),l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!g,onClick:()=>x(3),children:"Continue"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(1),children:"Back"})]})]}):null,h===3?l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("p",{className:"text-xs text-slate-400",children:"Final step: confirm and send your verification request."}),l.jsx("input",{className:wr,type:"password",name:"identity_key_request_final",autoComplete:"current-password",maxLength:35,value:g,onChange:k=>v(k.target.value.toLowerCase()),placeholder:"Identity key for this request"}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"submit",className:"button-dark text-sm",disabled:M||!g,children:"Confirm Request"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(2),children:"Back"})]})]}):null]})})}function OA({currentStoredKey:n,applyIdentityKey:s,onMessage:r,fullWidth:o=!1}){const[u,f]=m.useState(0),[p,h]=m.useState(""),[x,g]=m.useState(!1),v=()=>{f(1),h(""),r?.("")},y=()=>{f(0),h("")},N=async C=>{if(C.preventDefault(),!(u<2)){g(!0),r?.("");try{await s(p),f(0),h(""),r?.("Identity key restored.")}catch(S){r?.(S.message||"Failed to restore key.")}finally{g(!1)}}},M=o?"w-full":Oo;return l.jsx("section",{className:`surface ${M}`,children:l.jsxs("div",{className:pr,children:[l.jsx("p",{className:"text-sm text-slate-300",children:"Identity key"}),l.jsxs("p",{className:"text-xs text-slate-500",children:["Current: ",jA(n)||"not set yet"]}),l.jsx("input",{className:wr,type:"password",name:"identity_key_current",autoComplete:"current-password",maxLength:35,value:n,readOnly:!0,placeholder:"Identity key"}),u===0?l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!n,onClick:()=>navigator.clipboard?.writeText(n),children:"Copy Key"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:v,disabled:x,children:"Restore Key"})]}):null,u===1?l.jsxs("div",{className:"space-y-0.5",children:[l.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."}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>f(2),children:"Continue"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:y,children:"Cancel"})]})]}):null,u===2?l.jsxs("form",{className:"space-y-0.5",onSubmit:N,children:[l.jsx("input",{className:wr,type:"password",name:"identity_key_restore",autoComplete:"current-password",maxLength:35,value:p,onChange:C=>h(C.target.value.toLowerCase()),placeholder:"Paste key to restore"}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"submit",className:"button-dark text-sm",disabled:x||!p,children:"Confirm Restore"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>f(1),children:"Back"})]})]}):null]})})}function BA({requestableRovers:n=[],pendingRequests:s=[],requestPrivateRoverAccess:r,onMessage:o,fullWidth:u=!1}){const[f,p]=m.useState({}),h=m.useMemo(()=>{const v=new Map;return(s||[]).forEach(y=>{y?.roverId&&v.set(String(y.roverId),y)}),v},[s]),x=u?"w-full":Oo,g=async v=>{if(v){p(y=>({...y,[v]:!0})),o?.("");try{(await r?.(v))?.existing?o?.("You already have a pending request for that rover."):o?.("Private rover access request sent to lockdown admins.")}catch(y){o?.(y.message||"Failed to send request.")}finally{p(y=>({...y,[v]:!1}))}}};return l.jsx("section",{className:`surface text-sm text-slate-300 ${x}`,children:l.jsxs("div",{className:pr,children:[l.jsx("p",{className:"text-sm text-slate-300",children:"Private rover access requests"}),n.length===0?l.jsx("p",{className:"text-xs text-slate-500",children:"No closed private rovers are available to request right now."}):l.jsx("div",{className:"w-full space-y-0.5",children:n.map(v=>{const y=String(v.id),N=!!f[y],M=h.get(y);return l.jsxs("div",{className:"surface-muted flex items-center justify-between gap-0.5 px-1 py-0.5",children:[l.jsxs("div",{className:"min-w-0 text-left",children:[l.jsx("p",{className:"truncate text-xs font-semibold text-slate-100",children:v.name||y}),l.jsx("p",{className:"truncate text-[0.7rem] text-slate-500",children:y})]}),M?l.jsx("span",{className:"rounded bg-amber-700/30 px-1 py-0.5 text-[0.7rem] text-amber-200",children:"Pending"}):l.jsx("button",{type:"button",onClick:()=>g(y),disabled:N,className:"button-dark text-xs disabled:opacity-50",children:N?"Sending...":"Request"})]},y)})})]})})}function al(n){return String(n||"").trim()}function LA(n){const s=al(n);return s?s.includes("DOCKINGRUNNING")?"Returning":s.includes("PAUSED")?"Paused":s.includes("HOUSECLEANINGRUNNING")?"Cleaning":s.includes("SPOTCLEANINGRUNNING")?"Spot cleaning":s.includes("STATE_START")?"Starting":s.includes("STATE_IDLE")||s.includes("STATE_STANDBY")?"Idle":s:"--"}function Jg(n){return n==="good"?"bg-emerald-600 text-white":n==="warn"?"bg-amber-500 text-slate-900":n==="danger"?"bg-rose-600 text-white":"bg-slate-700 text-slate-100"}function to({label:n,value:s,tone:r="muted",valueClass:o="",hideLabel:u=!1}){return l.jsxs("div",{className:`rounded-md px-1 py-0.75 text-center ${Jg(r)}`,children:[u?null:l.jsx("div",{className:"text-[0.72rem] opacity-90",children:n}),l.jsx("div",{className:`text-sm font-semibold ${o}`,title:String(s||""),children:s})]})}function zA(n=[]){const u=[...n.filter(C=>C&&C.valid&&Number.isFinite(C.angleDeg)&&Number.isFinite(C.distanceMm))].sort((C,S)=>Number(C.angleDeg)-Number(S.angleDeg)),f=[];let p=[];for(const C of u){if(!p.length){p.push(C);continue}const S=p[p.length-1],w=Math.abs(Number(C.angleDeg)-Number(S.angleDeg)),j=Math.max(0,Number(S.distanceMm)),R=Math.max(0,Number(C.distanceMm)),k=Math.abs(R-j);if(w<=2&&k<=900){p.push(C);continue}f.push(p),p=[C]}p.length&&f.push(p);const h=f.map(C=>{const S=C.map(j=>Math.max(0,Number(j.distanceMm))),w=S.reduce((j,R)=>j+R,0)/Math.max(1,S.length);return{points:C,size:C.length,avgDistanceMm:w}}),g=h.reduce((C,S)=>S.size>(C?.size||0)?S:C,null)?.avgDistanceMm||1e3,v=h.filter(C=>{const S=C.size<=3,w=C.avgDistanceMm>g*1.8&&C.avgDistanceMm-g>1400;return!(S&&w)}).flatMap(C=>C.points),y=v.map(C=>Math.max(0,Number(C.distanceMm))).sort((C,S)=>C-S),N=Math.max(0,Math.floor((y.length-1)*.95)),M=Math.max(1e3,y[N]||1e3);return v.map(C=>{const S=(Number(C.angleDeg)-90)*Math.PI/180,w=Math.max(0,Number(C.distanceMm)),R=Math.max(0,Math.min(1,w/M))*102,k=110+Math.cos(S)*R,E=110+Math.sin(S)*R,X=38+Math.max(0,Math.min(255,Number(C.intensity)||0))/255*38;return{key:`${C.angleDeg}-${C.distanceMm}-${C.intensity}`,x:k,y:E,fill:`hsl(198 100% ${X}%)`}})}function UA({neato:n,lidar:s,lidarActive:r=!0,onStart:o,onSendHome:u,onLocate:f,onClearErrors:p,onPowerCycle:h,fullWidth:x=!1}){const[g,v]=m.useState(""),[y,N]=m.useState(!1),[M,C]=m.useState(!1),S=x?"w-full":"w-full max-w-xl",w=!!n?.configured,j=!!(n?.enabled&&n?.connected),R=!!n?.telemetry?.extPowerPresent,k=!!n?.telemetry?.chargingActive,E=LA(n?.telemetry?.uiState),B=al(n?.telemetry?.robotState)||"--",X=n?.telemetry?.batteryPercent,L=Number.isFinite(X)?`${X}%`:"--",z=n?.telemetry?.batteryVoltage,K=Number.isFinite(z)?`${z.toFixed(2)} V`:"--",V=al(n?.telemetry?.robotError)||"--",F=al(n?.telemetry?.robotAlert)||"--",W=Array.isArray(s?.points)?s.points:[],ie=m.useMemo(()=>r?zA(W):[],[r,W]),oe=al(s?.status)||"--",$=s?.debug&&typeof s.debug=="object"?s.debug:null,T=al($?.reason)||"--",H=$?.stats&&typeof $.stats=="object"?$.stats:null,J=n?.controls||{},te=!!J?.start?.available,ue=!!J?.sendHome?.available,q=!!J?.locate?.available,_=!!J?.clearErrors?.available,I=!!J?.powerCycle?.available,ne=w&&j&&te,me=w&&j&&ue,ce=w&&j&&q,se=w&&j&&_,ve=w&&j&&I,he=async(ze,$e)=>{if($e){v(ze);try{await $e()}catch{}finally{v("")}}},be=w?j?"Online":"Offline":"Not configured",Ve=w?j?"good":"danger":"warn",De=X==null?"muted":X>=60?"good":X>=25?"warn":"danger",Te=R?"Docked":E!=="--"?E:"Away from dock";return m.useEffect(()=>{if(!r||!s||!Array.isArray(s.points))return;N(!0);const ze=setTimeout(()=>{N(!1)},120);return()=>clearTimeout(ze)},[s,r]),l.jsx("section",{className:`surface text-sm text-slate-200 ${S}`,children:l.jsxs("div",{className:"grid gap-0.5",children:[l.jsxs("div",{className:"relative flex items-center justify-center min-h-[1.5rem]",children:[l.jsxs("div",{className:"text-center",children:[l.jsx("p",{className:"text-sm text-slate-100",children:"Neato Controls"}),l.jsx("p",{className:"text-xs text-slate-400",children:"Control the autonomous Neato robovac. Be nice to him."})]}),l.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${Jg(Ve)}`,children:be})]}),l.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-[minmax(0,0.95fr)_minmax(0,1.05fr)] gap-0.5",children:[l.jsxs("div",{className:"surface-muted grid gap-0.5",children:[l.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Controls"}),l.jsx("button",{type:"button",disabled:!ne||!!g,onClick:()=>he("start",o),className:"rounded-md border border-sky-300 bg-emerald-600 px-1 py-1 text-base font-semibold text-white transition hover:border-sky-500 hover:bg-emerald-500 disabled:opacity-50",children:g==="start"?"Starting...":"Start cleaning"}),l.jsx("button",{type:"button",disabled:!me||!!g,onClick:()=>he("sendHome",u),className:"rounded-md border border-sky-300 bg-sky-600 px-1 py-1 text-base font-semibold text-white transition hover:border-sky-500 hover:bg-sky-500 disabled:opacity-50",children:g==="sendHome"?"Sending...":"Send to dock"}),l.jsxs("div",{className:"grid grid-cols-3 gap-0.5",children:[l.jsx("button",{type:"button",disabled:!ce||!!g,onClick:()=>he("locate",f),className:"w-full rounded-md border border-sky-300 bg-fuchsia-600 px-1 py-0.5 text-xs font-semibold text-white transition hover:border-sky-500 hover:bg-fuchsia-500 disabled:opacity-50",children:g==="locate"?"Playing...":"Play sound"}),l.jsx("button",{type:"button",disabled:!se||!!g,onClick:()=>he("clearErrors",p),className:"w-full rounded-md border border-sky-300 bg-amber-500 px-1 py-0.5 text-xs font-semibold text-slate-900 transition hover:border-sky-500 hover:bg-amber-400 disabled:opacity-50",children:g==="clearErrors"?"Clearing...":"Clear errors"}),l.jsx("button",{type:"button",disabled:!ve||!!g,onClick:()=>he("powerCycle",h),className:"w-full rounded-md border border-rose-300 bg-rose-600 px-1 py-0.5 text-xs font-semibold text-white transition hover:border-rose-500 hover:bg-rose-500 disabled:opacity-50",children:g==="powerCycle"?"Cycling...":"Power cycle"})]}),l.jsxs("div",{className:"surface-muted grid gap-0.5 pt-0.25",children:[l.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Power status"}),l.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[l.jsx(to,{label:"Battery",value:L,tone:De}),l.jsx(to,{label:"Voltage",value:K,tone:"muted"}),l.jsx(to,{label:"Docked",value:R?"Docked":"Not docked",tone:R?"good":"muted",hideLabel:!0}),l.jsx(to,{label:"Charging",value:k?"charging":"not charging",tone:k?"good":"muted",hideLabel:!0})]})]})]}),l.jsx("div",{className:"grid gap-0.5",children:l.jsxs("div",{className:"surface-muted grid gap-0.5",children:[l.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Robot Status"}),l.jsxs("div",{className:"grid grid-cols-1 xl:grid-cols-[minmax(0,1fr)_minmax(13rem,15rem)] gap-0.5 items-start",children:[l.jsxs("div",{className:"grid gap-0.5",children:[l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot state (raw)"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:B})]}),l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Basic state"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:Te})]}),l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"UI state"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:E})]}),l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot error"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:V})]}),l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot alert"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:F})]})]}),l.jsxs("div",{className:`rounded-md px-1 py-0.5 ${y?"bg-emerald-900":"bg-slate-800"}`,children:[l.jsx("button",{type:"button",onClick:()=>C(ze=>!ze),className:"w-full text-left text-[0.72rem] text-slate-300",children:"Lidar"}),l.jsx("div",{className:"mt-0.25 text-center text-[0.68rem] text-slate-400",children:"Front of robot"}),l.jsx("div",{className:"mt-0.25 aspect-square rounded-md bg-slate-800 p-0",children:ie.length?l.jsxs("svg",{viewBox:"0 0 220 220",className:"h-full w-full",children:[l.jsx("rect",{x:"0",y:"0",width:"220",height:"220",fill:"#1e293b"}),l.jsx("rect",{x:"7",y:"7",width:"206",height:"206",fill:"none",stroke:"#64748b",strokeWidth:"1"}),l.jsx("rect",{x:"33",y:"33",width:"154",height:"154",fill:"none",stroke:"#475569",strokeWidth:"1"}),l.jsx("rect",{x:"59",y:"59",width:"102",height:"102",fill:"none",stroke:"#475569",strokeWidth:"1"}),l.jsx("rect",{x:"85",y:"85",width:"50",height:"50",fill:"none",stroke:"#334155",strokeWidth:"1"}),l.jsx("line",{x1:"110",y1:"7",x2:"110",y2:"213",stroke:"#475569",strokeWidth:"1"}),l.jsx("line",{x1:"7",y1:"110",x2:"213",y2:"110",stroke:"#475569",strokeWidth:"1"}),l.jsx("circle",{cx:"110",cy:"110",r:"4",fill:"#e2e8f0"}),ie.map(ze=>l.jsx("circle",{cx:ze.x,cy:ze.y,r:"1.8",fill:ze.fill},ze.key))]}):l.jsx("div",{className:"flex h-full items-center justify-center text-center text-xs text-slate-400",children:"Waiting for scan"})}),M?l.jsxs("div",{className:"mt-0.5 rounded-md bg-slate-900 px-0.75 py-0.5 font-mono text-[0.68rem] text-slate-300",children:[l.jsxs("div",{children:["Status: ",oe]}),l.jsxs("div",{children:["Reason: ",T]}),l.jsxs("div",{children:["Points: ",W.length]}),l.jsxs("div",{children:["Rotation: ",Number.isFinite(s?.rotationSpeed)?s.rotationSpeed.toFixed(2):"--"]}),l.jsxs("div",{children:["Request in flight: ",$?.requestInFlight?"yes":"no"]}),l.jsxs("div",{children:["Started at: ",$?.requestStartedAt||"--"]}),l.jsxs("div",{children:["Headers: ",H?.headersSeen??"--"]}),l.jsxs("div",{children:["Rotations: ",H?.rotationsSeen??"--"]}),l.jsxs("div",{children:["Scans ok: ",H?.scansOk??"--"]}),l.jsxs("div",{children:["Timeouts: ",H?.scansTimedOut??"--"]}),l.jsxs("div",{children:["Restarts: ",H?.scansRestarted??"--"]}),l.jsxs("div",{children:["Rotation no scan: ",H?.rotationsWithoutScan??"--"]}),l.jsxs("div",{children:["Parseable payloads: ",H?.parseablePayloads??"--"]}),l.jsxs("div",{children:["Point payloads: ",H?.pointPayloads??"--"]})]}):null]})]})]})})]}),!w||!j||!te||!ue||!q||!_||!I?l.jsx("p",{className:"text-xs text-slate-400 text-center",children:w?j?"Waiting for required Neato entities in Home Assistant.":"Home Assistant is offline.":"Set homeAssistant.neato.device in server config to enable Neato controls."}):null]})})}function HA(n){return n==="good"?"bg-emerald-600 text-white":n==="warn"?"bg-amber-500 text-slate-900":n==="danger"?"bg-rose-600 text-white":"bg-slate-700 text-slate-100"}function VA(n){return n==="up"?"Up":n==="down"?"Down":n==="stopped"?"Transitioning...":n==="conflict"?"Conflict":"--"}function $A({lift:n,onUp:s,onDown:r,fullWidth:o=!1}){const[u,f]=m.useState(""),[p,h]=m.useState(()=>Date.now()),x=o?"w-full":"w-full max-w-xl",g=!!n?.configured,v=!!(n?.enabled&&n?.connected),y=!!n?.busy,N=String(n?.target||"").toLowerCase(),M=String(n?.position||"").toLowerCase(),C=!!n?.availability?.upSwitch,S=!!n?.availability?.downSwitch,w=Number(n?.lastActionAt||0),j=Math.max(0,Number(n?.commandCooldownMs||0)),R=Math.max(0,w+j-p),k=!y&&R>0,E=y||k;m.useEffect(()=>{if(!E)return;const V=setInterval(()=>{h(Date.now())},100);return()=>clearInterval(V)},[E]),m.useEffect(()=>{h(Date.now())},[w,j,y]);const B=g?v?E?"Busy":"Ready":"Offline":"Not configured",X=g?v?E?"warn":"good":"danger":"warn",L=g&&v&&!E&&!u&&C&&S,z=m.useMemo(()=>Math.ceil(R/1e3),[R]),K=async(V,F)=>{if(F){f(V);try{await F()}catch{}finally{f("")}}};return l.jsxs("section",{className:`surface relative text-sm text-slate-200 ${x}`,children:[E?l.jsx("div",{className:"absolute inset-0 z-20 flex items-center justify-center rounded-md bg-slate-950/80 px-1.5 text-center",children:l.jsxs("div",{className:"space-y-0.25",children:[l.jsx("p",{className:"text-sm font-semibold text-slate-100",children:y?"Motion in progress":"Motion cooldown active"}),l.jsx("p",{className:"text-xs text-slate-300",children:"Controls are disabled while the lift is moving, otherwise it's tiny brain would get confused."}),!y&&k?l.jsxs("p",{className:"text-xs text-slate-400",children:["About ",z,"s remaining."]}):null]})}):null,l.jsxs("div",{className:"grid gap-0.5",children:[l.jsxs("div",{className:"relative flex items-center justify-center min-h-[1.5rem]",children:[l.jsxs("div",{className:"text-center",children:[l.jsx("p",{className:"text-sm text-slate-100",children:"Lift Controls"}),l.jsx("p",{className:"text-xs text-slate-400",children:"Move the lift up and down. Please don't break anything..."})]}),l.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${HA(X)}`,children:B})]}),l.jsx("section",{className:"surface-muted px-0.5 py-0.5",children:l.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-0.5",children:[l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.75 text-center",children:[l.jsx("div",{className:"text-xs text-slate-300",children:"Position"}),l.jsx("div",{className:"text-base font-semibold text-slate-100",children:VA(M)})]}),l.jsx("button",{type:"button",disabled:!L,onClick:()=>K("down",r),className:`button-dark w-full text-sm disabled:opacity-50 ${M==="down"||N==="down"?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,children:u==="down"||N==="down"?"Lowering...":"Down"}),l.jsx("button",{type:"button",disabled:!L,onClick:()=>K("up",s),className:`button-dark w-full text-sm disabled:opacity-50 ${M==="up"||N==="up"?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,children:u==="up"||N==="up"?"Raising...":"Up"})]})}),!g||!v||!C||!S?l.jsx("p",{className:"text-xs text-slate-400 text-center",children:g?v?"Waiting for required lift switch entities in Home Assistant.":"Home Assistant is offline.":"Set homeAssistant.lift.upSwitch and homeAssistant.lift.downSwitch in server config."}):null,n?.lastError?l.jsxs("p",{className:"text-xs text-rose-300 text-center",children:["Last error: ",n.lastError]}):null]})]})}function Pg({isActive:n=!0}){const s=pe($=>$.session),r=pe($=>$.neatoLidar),{identifySession:o,requestVerification:u,requestPrivateRoverAccess:f,playUploadedAudio:p,stopUploadedAudio:h,startMicWhip:x,readyMicWhip:g,stopMicWhip:v,neatoStart:y,neatoSendHome:N,neatoLocate:M,neatoClearErrors:C,neatoPowerCycle:S,liftUp:w,liftDown:j}=Xt(),{value:R,save:k}=Qe("identity",{cookieUserId:""}),{value:E}=Qe("profile",{nickname:""}),B=m.useMemo(()=>(R?.cookieUserId||"").trim(),[R?.cookieUserId]),X=(E?.nickname||"").trim(),L=!!s?.isVerified,z=s?.verification?.pendingRequestId||null,K=s?.privateRoverAccess?.requestableRovers||[],V=s?.privateRoverAccess?.pendingRequests||[],F=String(s?.assignment?.roverId||"").trim(),[W,ie]=m.useState(""),oe=async $=>{const T=String($||"").trim().toLowerCase();if(!T)throw new Error("Identity key required.");if(!SA.test(T))throw new Error("Identity key must match format: cu_ + 32 lowercase hex chars.");return k(H=>({...H||{},cookieUserId:T})),await o({cookieUserId:T,nickname:X}),T};return l.jsxs("section",{className:"space-y-2 text-base",children:[l.jsxs("div",{className:"grid gap-2 grid-cols-1 lg:grid-cols-[minmax(0,1.25fr)_minmax(0,0.9fr)]",children:[L?null:l.jsx("div",{className:"lg:col-span-2",children:l.jsx(_A,{pendingRequestId:z,currentStoredKey:B,nickname:X,requestVerification:u,applyIdentityKey:oe,onMessage:ie,fullWidth:!0})}),l.jsx("div",{className:"lg:col-span-2",children:L?l.jsxs("div",{className:"space-y-2",children:[l.jsx(UA,{neato:s?.neato||null,lidar:r,lidarActive:n,onStart:y,onSendHome:N,onLocate:M,onClearErrors:C,onPowerCycle:S,fullWidth:!0}),l.jsx($A,{lift:s?.lift||null,onUp:w,onDown:j,fullWidth:!0}),l.jsx(DA,{ownRoverId:F,audioForwardByRover:s?.audioForward||{},playUploadedAudio:p,stopUploadedAudio:h,startMicWhip:x,readyMicWhip:g,stopMicWhip:v})]}):l.jsx("section",{className:"surface h-full",children:l.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."})})}),l.jsx("div",{className:"lg:col-span-2",children:l.jsx(BA,{requestableRovers:K,pendingRequests:V,requestPrivateRoverAccess:f,onMessage:ie,fullWidth:!0})}),l.jsx("div",{className:"lg:col-span-2",children:l.jsx(OA,{currentStoredKey:B,applyIdentityKey:oe,onMessage:ie,fullWidth:!0})})]}),W?l.jsx("div",{className:Oo,children:l.jsx("p",{className:"text-xs text-slate-400 text-center",children:W})}):null]})}const GA=420,YA=1200,FA={1:262,2:330,3:392,4:523};function No(){const n=pe(S=>S.session?.buttonBox?.buttons??[]),s=sn(),{value:r}=Qe("audio",ut),o=Number.isFinite(r?.masterVolume)?r.masterVolume:ut.masterVolume,u=Number.isFinite(r?.alertVolume)?r.alertVolume:ut.alertVolume,f=Math.max(0,Math.min(1,o*u)),p=m.useMemo(()=>{const S=Array.isArray(n)?n:[];return S.length===4?S:[1,2,3,4].map(w=>S.find(j=>Number(j?.id)===w)||{id:w,count:0,goal:0,rewardName:null,rewardId:null,rewardNumber:null,lastRewardAt:null})},[n]),[h,x]=m.useState({}),[g,v]=m.useState({}),y=m.useRef(new Map),N=m.useRef(new Map),M=m.useRef({}),C=m.useRef(null);return m.useEffect(()=>{const S={};p.forEach(j=>{S[j.id]=Number(j.lastRewardAt||0)});const w=M.current||{};p.forEach(j=>{const R=Number(j.id),k=S[R]||0,E=Number(w[R]||0);if(k>0&&k!==E){v(L=>({...L,[R]:!0}));const B=N.current.get(R);B&&clearTimeout(B);const X=setTimeout(()=>{v(L=>({...L,[R]:!1})),N.current.delete(R)},YA);N.current.set(R,X)}}),M.current=S},[p]),m.useEffect(()=>{function S(j){const R=FA[j];if(!R||f<=0)return;let k=C.current;if(!k){const L=window.AudioContext||window.webkitAudioContext;if(!L)return;k=new L,C.current=k}const E=k.createOscillator(),B=k.createGain();E.type="square",E.frequency.value=R;const X=.14*f;B.gain.setValueAtTime(1e-4,k.currentTime),B.gain.exponentialRampToValueAtTime(Math.max(1e-4,X),k.currentTime+.01),B.gain.exponentialRampToValueAtTime(1e-4,k.currentTime+.2),E.connect(B),B.connect(k.destination),E.start(),E.stop(k.currentTime+.21)}function w(j={}){const R=Number(j.buttonId);if(!Number.isFinite(R)||R<1||R>4)return;x(B=>({...B,[R]:!0}));const k=y.current.get(R);k&&clearTimeout(k);const E=setTimeout(()=>{x(B=>({...B,[R]:!1})),y.current.delete(R)},GA);y.current.set(R,E),S(R)}return s.on("buttonBox:increment",w),()=>{s.off("buttonBox:increment",w)}},[f,s]),l.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[l.jsx("header",{className:"panel-muted text-center text-sm",children:l.jsx("p",{children:"Button Box"})}),l.jsx("div",{className:"grid grid-cols-4 gap-0.5",children:p.map(S=>{const w=Number(S.id),j=Number.isFinite(S.count)?S.count:0,R=Number.isFinite(S.goal)?S.goal:0,k=typeof S.rewardName=="string"&&S.rewardName.trim()?S.rewardName.trim():"Unassigned",E=Number.isFinite(S.rewardNumber)?S.rewardNumber:"?",B=!!h[w],X=!!g[w];return l.jsx(gg,{buttonId:w,count:j,goal:R,rewardNumber:E,rewardName:k,className:[B?"bg-cyan-900/45":"",X?"bg-fuchsia-900/45":""].filter(Boolean).join(" ")},w)})})]})}function XA(){const{state:{roverId:n}}=Dt(),r=fl(n)?.sensors||{};return l.jsx("section",{className:"panel-section",children:l.jsx("div",{className:"aspect-square w-full",children:l.jsx(Vd,{sensors:r})})})}function QA(){const{state:{roverId:n,keymap:s,camera:r,horn:o},pipeline:u,actions:{setServoAngle:f,setNightVision:p,startHorn:h,stopHorn:x}}=Dt(),g=Tg(n),v=g.docked&&!g.driving,y=r?.config,N=!!(n&&r?.enabled&&y),M=!!(n&&u?.nightVision),C=u?.nightVisionState,S=!!(n&&u?.horn),w=o?.overheated,j=typeof y?.minAngle=="number"?y.minAngle:-30,R=typeof y?.maxAngle=="number"?y.maxAngle:30,k=typeof r?.angle=="number"?r.angle:typeof y?.homeAngle=="number"?y.homeAngle:(j+R)/2,E=An(s?.nightVisionToggle?.[0]),B=An(s?.hornHonk?.[0]),X=An(s?.cameraUp?.[0]),L=An(s?.cameraDown?.[0]);return l.jsxs("section",{className:"panel-section grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto] gap-0.5",children:[l.jsx(Dg,{layout:"desktop",expand:!0,driveDockState:g}),v?null:l.jsxs("div",{className:"surface space-y-0.5 p-0 text-sm text-slate-200",children:[M&&l.jsx(_g,{nightVisionOn:C?.nightVisionOn,disabled:!n,onToggle:p,keyLabel:E}),S&&l.jsx(Og,{disabled:!n||w,onStart:h,onStop:x,keyLabel:B,active:o?.active,heat:o?.heat}),N&&l.jsx(Bg,{value:k,min:j,max:R,onChange:f,keyDownLabel:L,keyUpLabel:X,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 KA({layout:n,onOpenHelpOverlay:s}){const[r,o]=m.useState("telemetry"),u=pe(S=>!!S.session?.isVerified),f=pe(S=>String(S.session?.assignment?.roverId||"").trim()),p=pe(S=>{const w=String(S.session?.assignment?.roverId||"").trim();return w&&S.session?.audioForward?.[w]||null}),{state:h}=Dt(),{value:x}=Qe("vipAudio",{openMicEnabled:!1,pttMode:"live"}),g=u?"bg-emerald-400":"bg-red-600",v=!!h?.mic?.pttActive,y=!!x?.openMicEnabled,N=x?.pttMode==="clip"?"clip":"live",M=!!(f&&u&&(N==="clip"?v:y||v)),C=!!(f&&u&&N==="clip"&&p?.source==="upload"&&p?.state==="playing");return l.jsx("section",{className:"panel text-base",children:l.jsxs(Sf,{defaultTab:"telemetry",currentTab:r,onTabChange:o,children:[l.jsxs(jf,{children:[l.jsx(tn,{id:"telemetry",children:"Controls"}),l.jsx(tn,{id:"vip",highlight:C?"green":M?"pink":"none",children:l.jsxs("span",{className:"inline-flex items-center gap-2",children:[l.jsx("span",{children:"VIP"}),l.jsx("span",{className:`inline-block h-3 w-3 rounded-full ${g}`,"aria-hidden":"true",title:u?"Verified":"Not verified"})]})}),l.jsx(tn,{id:"help",children:"Help"}),l.jsx(tn,{id:"settings",children:"Settings"})]}),l.jsxs(Nf,{children:[l.jsx(nn,{id:"telemetry",children:l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("div",{className:"grid items-stretch gap-0.5 grid-cols-[minmax(0,1.35fr)_minmax(0,0.95fr)]",children:[l.jsx(XA,{}),l.jsx(QA,{})]}),l.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.9fr)_minmax(0,0.75fr)]",children:[l.jsx(_o,{}),l.jsx(af,{panelId:"replay-sources-desktop",fillHeight:!0}),l.jsx(hA,{})]}),l.jsxs("div",{className:"grid items-stretch gap-0.5 grid-cols-[minmax(0,1.3fr)_minmax(0,0.22fr)] h-[14rem]",children:[l.jsx(To,{fillHeight:!0}),l.jsxs("div",{className:"grid min-h-0 gap-0.5 grid-rows-[minmax(0,1fr)_auto]",children:[l.jsx(jo,{compact:!0,hideNicknameForm:!0,fillHeight:!0}),l.jsx(mA,{compact:!0})]})]}),l.jsx(Vg,{}),l.jsx(No,{}),l.jsx(ff,{defaultOrientation:"horizontal",panelId:"rightpane-telemetry"})]})}),l.jsx(nn,{id:"vip",keepMounted:!0,children:l.jsx(Pg,{isActive:r==="vip"})}),l.jsx(nn,{id:"help",children:l.jsx(Zg,{layout:n,onOpenOverlay:s})}),l.jsx(nn,{id:"settings",children:l.jsx(Xg,{})})]})]})})}const ZA=new Set(["admin","lockdown","lockdown-admin"]),IA=new Set(["lockdown","lockdown-admin"]),JA=new Set(["admin","lockdown"]);function PA(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 WA(){const n=pe(y=>y.session?.mode||null),s=pe(y=>y.session?.role||null),r=pe(y=>y.session?.adminReason?.text||"");pe(y=>y.session?.adminReason?.updatedAt||null);const o=pe(y=>y.session?.timezone||"UTC"),u=pe(y=>(y.session?.socials||[]).find(C=>String(C?.id||C?.label||"").toLowerCase()==="discord")?.url||y.session?.discord?.invite||null),f=JA.has(n),p=n==="lockdown"?IA.has(s):ZA.has(s),[h,x]=m.useState(()=>new Date),g=m.useMemo(()=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:o,hour:"numeric",minute:"2-digit",second:"2-digit"}).format(h)}catch{return h.toLocaleTimeString()}},[h,o]);if(m.useEffect(()=>{const y=setInterval(()=>x(new Date),1e3);return()=>clearInterval(y)},[]),!f||p)return null;const v=PA(n);return l.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:l.jsxs("div",{className:"surface w-full max-w-md space-y-0.5 text-slate-100 shadow-2xl",children:[l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("p",{className:"text-lg font-semibold",children:v.title}),l.jsx("p",{className:"text-sm text-slate-300",children:v.description})]}),l.jsxs("div",{className:"surface-muted space-y-0.5",children:[l.jsx("p",{className:"text-[0.7rem] tracking-wide text-slate-400",children:"Reason for locking:"}),l.jsx("p",{className:"text-lg font-semibold text-slate-100",children:r||"No reason set."}),l.jsxs("p",{className:"text-center text-sm text-slate-300",children:["Server time: ",g]})]}),l.jsx("div",{className:"surface-muted",children:l.jsx($g,{})}),l.jsx("div",{className:"w-full justify-center items-center",children:l.jsx(pf,{id:"discord",label:"Join our Discord server for updates!",url:u})}),"You can still use the chat while the server is locked:",l.jsxs("div",{className:"max-h-80 overflow-y-auto",children:[l.jsx(To,{}),l.jsx(Do,{})]})]})})}const e2="/assets/turn_alert-DVO8EZJa.mp3";function t2(n,s=1){const r=m.useRef(null);return m.useEffect(()=>{r.current=new Audio(n),r.current.volume=s,r.current.load()},[n,s]),()=>{r.current&&(r.current.volume=s,r.current.currentTime=0,r.current.play().catch(()=>{}))}}function n2(){const n=pe(v=>v.session?.socketId||null),s=pe(v=>v.session?.turnQueues||{}),r=pe(v=>v.session?.roster||[]),{pushAlert:o}=Xt(),{value:u}=Qe("audio",ut),f=Number.isFinite(u?.masterVolume)?u.masterVolume:ut.masterVolume,p=Number.isFinite(u?.alertVolume)?u.alertVolume:ut.alertVolume,h=Math.max(0,Math.min(1,f*p)),x=t2(e2,h),g=m.useRef(new Set);return m.useEffect(()=>{if(!n)return;const v=[];Object.entries(s).forEach(([y,N])=>{!N||!N.current||N.current!==n||g.current.has(y)||(v.push(y),g.current.add(y))}),Object.keys(s).forEach(y=>{(!s[y]||s[y].current!==n)&&g.current.delete(y)}),v.length!==0&&(v.forEach(y=>{const N=r.find(M=>String(M.id)===String(y))?.name||y;o({title:"Your turn!",message:`You now control ${N}.`,color:"#ff5722"})}),x())},[s,x,o,r,n]),null}function a2({visible:n,mode:s,onEnterFullscreen:r,onDismiss:o}){if(!n)return null;const u=s==="pwa-hint";return l.jsx("div",{className:"fixed inset-0 z-40 flex items-end justify-center p-2 pointer-events-none sm:items-center",children:l.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:l.jsxs("div",{className:"space-y-0.5 p-4 text-sm text-slate-100",children:[l.jsx("h2",{className:"text-base font-semibold text-white",children:"Better in fullscreen"}),u?l.jsxs("p",{className:"text-slate-300",children:["For fullscreen on iOS, open Safari's share menu and pick ",l.jsx("strong",{children:"Add to Home Screen"}),". Launching from the home screen removes the browser chrome."]}):l.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."}),l.jsxs("div",{className:"flex justify-end gap-0.5 pt-1 text-sm",children:[l.jsx("button",{type:"button",className:"rounded border border-slate-600 px-3 py-1 text-slate-200",onClick:o,children:u?"Got it":"Not now"}),!u&&l.jsx("button",{type:"button",className:"rounded bg-cyan-500 px-3 py-1 font-semibold text-black hover:bg-cyan-400",onClick:r,children:"Enter fullscreen"})]})]})})})}function s2({side:n="right",onClick:s}){const r=n==="left"?"left-2":"right-2";return l.jsx("button",{type:"button",onClick:s,className:`fixed bottom-2 ${r} 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:l.jsx("svg",{viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true",className:"pointer-events-none",children:l.jsx("path",{d:"M4 9V4h5M15 4h5v5M20 15v5h-5M9 20H4v-5",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})}const Wg="fullscreenPromptDismissed",l2=new Set(["mobile-portrait","mobile-landscape"]),ev=()=>{if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}},r2=()=>{const n=ev();if(!n)return!1;try{return n.getItem(Wg)==="1"}catch{return!1}},Cx=()=>{const n=ev();if(n)try{n.setItem(Wg,"1")}catch{}},i2=()=>{if(typeof navigator>"u")return!1;const n=navigator.userAgent||navigator.platform||"";return/iphone|ipad|ipod/i.test(n)},Ex=()=>{if(typeof document>"u")return!1;const n=document;return!!(n.fullscreenEnabled||n.webkitFullscreenEnabled||n.mozFullScreenEnabled||n.msFullscreenEnabled)};function o2(n){const s=l2.has(n),[r,o]=m.useState(!1),[u,f]=m.useState("native"),[p,h]=m.useState(!1),x=m.useMemo(()=>i2(),[]),g=m.useMemo(()=>Ex(),[]),v=m.useCallback(()=>{if(!s){o(!1),h(!1);return}if(!p&&r2()){o(!1);return}if(x){f("pwa-hint"),o(!0);return}if(!Ex()){o(!1);return}if(typeof document<"u"&&document.fullscreenElement){o(!1);return}f("native"),o(!0)},[p,x,s]);m.useEffect(()=>{v()},[v]),m.useEffect(()=>{if(typeof document>"u")return;const C=()=>{if(document.fullscreenElement){h(!1),o(!1);return}v()};return document.addEventListener("fullscreenchange",C),document.addEventListener("webkitfullscreenchange",C),()=>{document.removeEventListener("fullscreenchange",C),document.removeEventListener("webkitfullscreenchange",C)}},[v]);const y=m.useCallback(()=>{Cx(),h(!1),o(!1)},[]),N=m.useCallback(async()=>{if(!s||x||typeof document>"u")return!1;if(document.fullscreenElement)return!0;const C=document.documentElement;if(!C)return!1;const S=C.requestFullscreen||C.webkitRequestFullscreen||C.mozRequestFullScreen||C.msRequestFullscreen;if(!S)return!1;try{const w=S.call(C);return w&&typeof w.then=="function"&&await w,Cx(),h(!1),o(!1),!0}catch(w){return console.warn("Failed to enter fullscreen",w),!1}},[x,s]),M=m.useCallback(()=>{s&&(h(!0),f(x?"pwa-hint":"native"),o(!0))},[x,s]);return m.useEffect(()=>{s||(h(!1),o(!1))},[s]),{visible:r,mode:u,isIOS:x,nativeSupported:g,enterFullscreen:N,dismiss:y,showPrompt:M}}function c2({visible:n,layout:s,onClose:r,showOnLoad:o,onToggleShowOnLoad:u}){if(!n)return null;const{state:f}=Dt(),p=h=>{const x=!h.target.checked;u?.(x)};return l.jsx("div",{className:"fixed inset-0 z-30 flex items-center justify-center bg-black/80 px-0.5 py-0.5",children:l.jsxs("div",{className:"pointer-events-auto surface w-full max-w-4xl max-h-[90vh] overflow-hidden shadow-2xl",children:[l.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:[l.jsx("span",{className:"font-semibold",children:"Help & controls"}),l.jsxs("div",{className:"flex items-center gap-0.5 text-[0.8rem] text-slate-300",children:[l.jsxs("label",{className:"flex items-center gap-0.5",children:[l.jsx("input",{type:"checkbox",checked:!o,onChange:p,className:"accent-cyan-500"}),l.jsx("span",{children:"Don't show again"})]}),l.jsx("button",{type:"button",onClick:r,className:"button-dark px-2 py-0.25 text-[0.8rem]",children:"Close"})]})]}),l.jsx("div",{className:"max-h-[85vh] overflow-y-auto p-0.5",children:l.jsx(Kg,{layout:s,keymap:f?.keymap||{}})})]})})}const u2=`aroma +`).trim();if(ne){E(!0);try{await g(ne,te),R(""),M(),C(!1)}catch(me){alert(me.message)}finally{E(!1)}}}const q=r?"flex-1 min-h-0 overflow-y-auto":"h-48 overflow-y-auto";return l.jsxs("section",{className:`panel-section space-y-0.5 text-base ${r?"flex h-full flex-col overflow-hidden":""}`,children:[l.jsxs("div",{className:`surface overflow-y-auto space-y-0.5 px-0 ${q}`,ref:oe,children:[H.length===0&&J.length===0?l.jsx("p",{className:"text-sm text-slate-500",children:"No messages yet."}):H.map(_=>l.jsx(lf,{message:_},_.id)),J.map(_=>l.jsx(xg,{message:_},`typing-${_.typingId||_.id}`))]}),!n&&l.jsxs("form",{className:"flex flex-wrap items-stretch gap-0.5",onSubmit:ue,children:[l.jsx("input",{className:"field-input flex-1 min-w-[10rem]",value:j,onChange:_=>{const I=_.target.value;R(I),C(!!I.trim())},onFocus:_=>{y(_),C(!!j.trim())},onBlur:_=>{N(_),C(!1)},onKeyDown:_=>{_.key==="Enter"&&!j.trim()&&(_.preventDefault(),M(),C(!1))},ref:_=>v(_,{target:"panel"}),placeholder:ie?"Type a message…":s?"":"Spectators cannot chat",disabled:!ie}),T&&l.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 basis-full sm:basis-auto",children:[l.jsxs("label",{className:"flex items-center gap-0.5 text-xs text-slate-300",children:[l.jsx("input",{type:"checkbox",checked:B,onChange:_=>X(_.target.checked),className:"accent-cyan-500"}),l.jsx("span",{children:"Speak"})]}),l.jsxs("select",{value:L,onChange:_=>{const I=_.target.value;z(I),w(ne=>({...ne||{},engine:I}))},className:"field-input text-xs",children:[l.jsx("option",{value:"flite",children:"flite"}),l.jsx("option",{value:"espeak",children:"espeak"})]}),L==="flite"?l.jsx("select",{value:K,onChange:_=>{const I=_.target.value;V(I),w(ne=>({...ne||{},voice:I}))},className:"field-input text-xs",children:cA.map(_=>l.jsx("option",{value:_,children:_},_))}):l.jsx("select",{value:F,onChange:_=>{const I=Number(_.target.value);W(I),w(ne=>({...ne||{},pitch:I}))},className:"field-input text-xs",children:uA.map(_=>l.jsxs("option",{value:_,children:["pitch ",_]},_))})]}),l.jsx("button",{type:"submit",disabled:!ie||k,className:"button-dark h-full disabled:opacity-50 self-stretch",children:k?"...":"Send"})]})]})}function Do({compact:n=!1}){const s=pe(y=>y.session?.role||null),{setNickname:r}=Xt(),{value:o,save:u}=Qe("profile",{nickname:""}),[f,p]=m.useState(o.nickname||""),[h,x]=m.useState(!1),g=s!=="spectator";m.useEffect(()=>{p(o.nickname||"")},[o.nickname]);async function v(y){if(y.preventDefault(),!g)return;const N=(f||"").trim().slice(0,32);if(N){x(!0);try{await r(N),u({nickname:N})}catch(M){alert(M.message)}finally{x(!1)}}}return l.jsxs("form",{className:"grid w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-stretch gap-0.5",onSubmit:v,children:[l.jsx("input",{className:"field-input flex-1 min-w-0",value:f,onChange:y=>p(y.target.value),maxLength:32,placeholder:"Enter a nickname",disabled:!g}),l.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 dA({socials:n,discordInvite:s,kofiLink:r}){const o=Array.isArray(n)?n:null;if(o&&o.length)return o;const u=[];return s&&u.push({id:"discord",label:"Discord",url:s}),r&&u.push({id:"kofi",label:"Ko-fi",url:r}),u}function fA(n){if(!n||typeof n!="object")return null;const s=n.id||n.service||n.key||n.name||null,r=n.label||n.title||n.name||s||"Link",o=n.url||n.link||n.href||null;return o?{id:s,label:r,url:o}:null}function Ig({className:n=""}){const s=pe(o=>({socials:o.session?.socials??[],discordInvite:o.session?.discord?.invite||null,kofiLink:o.session?.kofi?.link||null})),r=dA(s).map(fA).filter(Boolean).slice(0,4);return r.length?l.jsx("div",{className:`grid grid-cols-2 grid-rows-2 gap-0.5 ${n}`,children:r.map(o=>l.jsx(pf,{...o},`${o.id||o.label}-${o.url}`))}):null}function mA({compact:n=!1}){return l.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:l.jsx("div",{className:"surface flex w-full items-center px-0 py-0",children:l.jsx(Do,{compact:n})})})}function hA(){return l.jsx("section",{className:"panel-section flex h-full min-h-0 flex-col gap-0.5 text-base",children:l.jsx(Ig,{className:"flex-1 min-h-0"})})}function yd(...n){return n.filter(Boolean).join(" ")}function pA(n){const s=n?.batteryState?.percentDisplay;return s==null?"--":`${s}%`}function xA(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function gA(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 vA(n,s){if(!n)return"";const r=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${r} (you)`:r}function _o({title:n="Rovers"}){const s=pe(j=>j.session?.role||null),r=pe(j=>j.session?.roster??[]),o=pe(j=>j.session?.turnQueues??{}),u=pe(j=>j.session?.users??[]),f=pe(j=>j.session?.socketId||null),{requestControl:p}=Xt(),[h,x]=m.useState({}),[g,v]=m.useState(()=>Date.now()),y=m.useMemo(()=>s&&s!=="spectator",[s]),N=m.useMemo(()=>s==="admin"||s==="lockdown"||s==="lockdown-admin",[s]),M=m.useMemo(()=>Object.values(o||{}).some(j=>j?.deadline||j?.idleDeadline),[o]);m.useEffect(()=>{if(!M)return;const j=setInterval(()=>{v(Date.now())},1e3);return()=>clearInterval(j)},[M]);const C=m.useMemo(()=>{const j=new Set(r.map(k=>String(k.id))),R=Object.keys(o||{}).filter(k=>!j.has(String(k))).map(k=>({id:k,name:k,locked:!1,batteryState:null}));return[...r,...R]},[r,o]);async function S(j){if(j){x(R=>({...R,[j]:!0}));try{await p(j)}catch(R){alert(R.message)}finally{x(R=>({...R,[j]:!1}))}}}const w=j=>u.find(R=>R.socketId===j)||{socketId:j,nickname:null,role:null};return l.jsxs("div",{className:"space-y-0.5 text-sm",children:[n&&l.jsx("p",{className:"text-sm text-slate-400",children:n}),C.length===0?l.jsx("p",{className:"text-sm text-slate-500",children:"No rovers registered."}):l.jsx("ul",{className:"space-y-0.5 text-sm",children:C.map(j=>{const R=String(j.id),k=o?.[R]||null,E=k?.queue||[],B=k?.idleDeadline||k?.deadline||null,X=B&&B>g?Math.ceil((B-g)/1e3):B?0:null,L=k?.current||null,z=L?E.findIndex(te=>te===L):-1,K=E.length>1?z>=0?E[(z+1)%E.length]:E[0]:null,V=!!(f&&L&&L===f),F=!!(f&&K&&K===f),W=X!=null&&(V||F),ie=!!j.locked,oe=ie&&!N,$=!!(j?.private?.enabled&&j?.private?.open),T=j.lockReason?`locked: ${j.lockReason}`:"locked",H=ie?T:h[R]?"...":"request",J=y&&!oe&&!h[R];return l.jsxs("li",{className:yd("surface flex flex-wrap items-start justify-between gap-0.5",J&&"cursor-pointer",ie?"bg-red-900/40":$?"bg-amber-700/35 border border-amber-200/30":null),onClick:()=>{J&&S(j.id)},children:[l.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-0.5",children:[l.jsxs("div",{className:"flex items-center justify-between gap-0.5",children:[l.jsxs("div",{className:"flex items-center gap-0.5",children:[l.jsx("p",{className:"text-slate-200",children:l.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ia(j.color,.16),children:j.name})}),W?l.jsx("span",{className:"rounded bg-slate-800 px-1 text-[0.7rem] text-slate-200",children:V?`${X}s left`:`Your turn in ${X}s`}):null]}),l.jsx("span",{className:yd("text-[0.75rem] font-semibold",xA(j)),children:pA(j)})]}),E.length===0?l.jsx("p",{className:"text-[0.7rem] text-slate-500",children:"No queue."}):l.jsx("div",{className:"flex flex-wrap items-center gap-0.5",children:E.map((te,ue)=>{const q=w(te),_=te===L,I=!!(K&&te===K&&!_),ne=_?"bg-sky-600 text-white ring-2 ring-amber-300":I?"bg-emerald-700/60 text-emerald-100 ring-1 ring-emerald-300/70":"bg-slate-800 text-slate-200";return l.jsxs("span",{className:`flex items-center gap-0.5 rounded px-1 text-[0.7rem] ${ne}`,children:[l.jsx("span",{className:`${gA(q.role)} font-semibold`,children:vA(q,f)}),_&&l.jsx("span",{className:"text-[0.65rem] text-slate-200",children:"now"}),I&&l.jsx("span",{className:"text-[0.65rem] text-emerald-100",children:"next"})]},`${R}-${te}-${ue}`)})})]}),y?l.jsx("button",{type:"button",onClick:te=>{te.stopPropagation(),S(j.id)},disabled:h[R]||oe,className:yd("button-dark disabled:opacity-40",ie&&"bg-red-600/70 text-white hover:bg-red-600"),children:H}):null]},j.id)})})]})}function bA(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 yA(n,s){if(!n)return"";const r=n.nickname||n.socketId?.slice(0,6)||"unknown";return n.socketId&&n.socketId===s?`${r} (you)`:r}function jo({hideNicknameForm:n=!1,hideHeader:s=!1,className:r="",fillHeight:o=!1,compact:u=!1}){const f=pe(y=>y.session?.role||null),p=pe(y=>y.session?.users??[]),h=pe(y=>y.session?.socketId||null),x=f!=="spectator",g=m.useMemo(()=>[...p].sort((y,N)=>y.socketId===h?-1:N.socketId===h?1:(y.nickname||"").localeCompare(N.nickname||"")),[h,p]),v=o?"flex-1 min-h-0 overflow-y-auto":u?"h-28 overflow-y-auto":"h-48 overflow-y-auto";return l.jsxs("section",{className:`panel-section space-y-0.5 text-base ${o?"flex h-full min-h-0 flex-col overflow-hidden":""} ${r}`,children:[!n&&l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("div",{className:"grid gap-0.5 md:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]",children:[l.jsx("div",{className:"min-w-0",children:l.jsx("div",{className:"surface flex w-full items-center px-0 py-0",children:l.jsx(Do,{compact:u})})}),l.jsx(Ig,{})]}),!x&&l.jsx("p",{className:"text-xs text-slate-500",children:"Spectators cannot set nicknames."})]}),l.jsxs("div",{className:`space-y-0.5 ${o?"flex flex-1 min-h-0 flex-col":""}`,children:[!s&&l.jsxs("div",{className:`flex items-center justify-between text-sm text-slate-400 ${u?"text-xs":""}`,children:[l.jsx("span",{children:"Users"}),l.jsx("span",{className:"text-xs text-slate-500",children:g.length})]}),l.jsx("div",{className:`surface flex flex-wrap content-start items-start gap-0.5 px-0 pb-0 ${v} ${u?"text-[0.8rem]":""}`,children:g.length===0?l.jsx("p",{className:"text-sm text-slate-500",children:"Waiting for users…"}):g.map(y=>l.jsx("span",{className:`rounded bg-slate-800/80 px-1 py-0.25 text-[0.7rem] ${bA(y.role)}`,children:yA(y,h)},y.socketId))})]})]})}const SA=/^cu_[a-f0-9]{32}$/,wr="field-input w-full max-w-sm text-left focus:ring-emerald-500",Oo="mx-auto w-full max-w-xl flex justify-center",pr="mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center";function jA(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 jx=8*1024*1024,rs=16e3,NA={iceServers:[{urls:"stun:stun.l.google.com:19302"}],bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"};function Nx(n){let s="";for(let o=0;o{if(!n||n.iceGatheringState==="complete"){r();return}const o=setTimeout(()=>{n.removeEventListener("icegatheringstatechange",u),r()},s);function u(){n.iceGatheringState==="complete"&&(clearTimeout(o),n.removeEventListener("icegatheringstatechange",u),r())}n.addEventListener("icegatheringstatechange",u)})}function wx(n){if(!n)return!1;const s=n.connectionState,r=n.iceConnectionState;return s==="connected"||r==="connected"||r==="completed"}function EA(n,s=1e4){return new Promise((r,o)=>{if(!n){o(new Error("Peer connection missing"));return}if(wx(n)){r();return}const u=setTimeout(()=>{p(),o(new Error("Peer connection timeout"))},s),f=()=>{wx(n)?(p(),r()):(n.connectionState==="failed"||n.connectionState==="closed"||n.iceConnectionState==="failed")&&(p(),o(new Error(`Peer connection ${n.connectionState||n.iceConnectionState}`)))};function p(){clearTimeout(u),n.removeEventListener("connectionstatechange",f),n.removeEventListener("iceconnectionstatechange",f)}n.addEventListener("connectionstatechange",f),n.addEventListener("iceconnectionstatechange",f)})}async function kA(n){if(!n?.getParameters||!n?.setParameters)return;const s=n.getParameters()||{},r=s.encodings&&s.encodings[0]||{};s.encodings=[{...r,maxBitrate:64e3,dtx:"disabled"}];try{await n.setParameters(s)}catch{}}function MA(n,s=6e3){return new Promise((r,o)=>{if(!n){o(new Error("Peer connection missing"));return}const u=Date.now();let f=-1;const p=setInterval(async()=>{if(Date.now()-u>s){clearInterval(p),o(new Error("WHIP connected but no outbound audio flow"));return}try{const h=n.getSenders().filter(x=>x.track?.kind==="audio");for(const x of h){const g=await x.getStats();for(const v of g.values()){if(v.type!=="outbound-rtp"||v.kind!=="audio")continue;const y=Number(v.bytesSent||0),N=Number(v.packetsSent||0);if(f<0)f=y;else if(y>f+200||N>5){clearInterval(p),r();return}}}}catch{}},250)})}function RA(n){const s=n.reduce((u,f)=>u+f.length,0),r=new Float32Array(s);let o=0;for(const u of n)r.set(u,o),o+=u.length;return r}function qA(n){const s=new Int16Array(n.length);for(let r=0;r{for(let v=0;vv&&s?.[v]||null,[s,v]),I=!!(_&&_.state!=="offline"&&!_.error),ne=_?.source==="upload"&&_?.state==="playing",me=_?.source==="mic-whip"&&(_?.state==="starting"||_?.state==="playing"),ce=!!(!j&&K.current&&(S||q)),se=!j&&(R==="live"||R==="starting"),ve=j&&E==="recording",he=j&&E==="sending",be=An(h?.keymap?.micPtt?.[0])||"M",Ve=m.useCallback(fe=>{const we=fe==="clip"?"clip":"live";g(Ae=>({...Ae||{},pttMode:we}))},[g]),De=async()=>{if(!v){L("Take control of your rover first.");return}if(!y){L("Select an audio file first.");return}if(y.size>jx){L(`File too large (max ${jx} bytes).`);return}C(!0),L("");try{const fe=await y.arrayBuffer(),we=Nx(new Uint8Array(fe));await r?.({roverId:v,name:y.name,mime:y.type||"",dataBase64:we}),L("Upload playback started.")}catch(fe){L(fe?.message||"Failed to play upload.")}finally{C(!1)}},Te=async()=>{if(!v){L("Take control of your rover first.");return}C(!0),L("");try{await o?.(v),L("Upload playback stopped.")}catch(fe){L(fe?.message||"Failed to stop upload.")}finally{C(!1)}},ze=m.useCallback(async fe=>{const we=String(fe||W.current||"").trim();if(F.current=!1,k("idle"),V.current){try{V.current.getSenders().forEach(Ae=>Ae.track?.stop())}catch{}try{V.current.close()}catch{}}if(V.current=null,z.current)try{z.current.getTracks().forEach(Ae=>Ae.stop())}catch{}if(z.current=null,K.current=null,we)try{await p?.(we)}catch{}W.current=""},[p]),$e=m.useCallback(async fe=>{const we=await u?.(fe),Ae=String(we?.whipUrl||"").trim(),it=String(we?.token||"").trim();if(!Ae||!it)throw new Error("WHIP endpoint unavailable");const le=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:rs,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}});z.current=le;const de=le.getAudioTracks()?.[0];if(K.current=de||null,de&&(de.enabled=!!(S||q)),de?.applyConstraints)try{await de.applyConstraints({channelCount:1,sampleRate:rs,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1})}catch{}const Me=new RTCPeerConnection(NA);V.current=Me,Me.onconnectionstatechange=()=>{if(!F.current)return;const Qt=Me.connectionState;if(Qt==="connected"){k("live");return}(Qt==="failed"||Qt==="disconnected"||Qt==="closed")&&(k("error"),L(`WHIP transport ${Qt}.`))},le.getAudioTracks().forEach(Qt=>{const Ba=Me.addTrack(Qt,le);kA(Ba)});const ft=await Me.createOffer({offerToReceiveAudio:!1,offerToReceiveVideo:!1});await Me.setLocalDescription(ft),await CA(Me,1800);const kt=await fetch(Ae,{method:"POST",headers:{"Content-Type":"application/sdp",...AA(it)},body:Me.localDescription?.sdp||ft.sdp});if(!kt.ok)throw new Error(`WHIP request failed: ${kt.status}`);const ds=await kt.text();await Me.setRemoteDescription({type:"answer",sdp:ds}),await EA(Me,1e4),await MA(Me,6e3),await f?.(fe)},[S,q,f,u]),vt=m.useCallback(async()=>{if(te.current=!1,T.current){try{T.current.disconnect()}catch{}T.current.onaudioprocess=null}if($.current)try{$.current.disconnect()}catch{}if(H.current)try{H.current.disconnect()}catch{}if(ie.current)try{ie.current.getTracks().forEach(fe=>fe.stop())}catch{}if(oe.current)try{await oe.current.close()}catch{}J.current=[],T.current=null,$.current=null,H.current=null,ie.current=null,oe.current=null,ue.current=rs},[]),re=m.useCallback(async()=>{if(ie.current&&oe.current&&T.current)return;B(de=>de==="recording"?de:"arming");const fe=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,sampleRate:rs,echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}}),we=new AudioContext({latencyHint:"interactive"}),Ae=we.createMediaStreamSource(fe),it=we.createScriptProcessor(1024,1,1),le=we.createGain();le.gain.value=0,it.onaudioprocess=de=>{if(!te.current)return;const Me=de.inputBuffer.getChannelData(0);J.current.push(new Float32Array(Me))},Ae.connect(it),it.connect(le),le.connect(we.destination),ie.current=fe,oe.current=we,$.current=Ae,T.current=it,H.current=le,ue.current=we.sampleRate||rs},[]),xe=m.useCallback(async({send:fe})=>{const we=te.current;if(te.current=!1,!we){fe||B("idle");return}const Ae=J.current;if(J.current=[],!fe){B("idle");return}if(!v){B("idle");return}if(!Ae.length){B("idle");return}B("sending");try{const it=RA(Ae),le=TA(it,ue.current||rs),de=Nx(le);await r?.({roverId:v,name:`ptt-${Date.now()}.wav`,mime:"audio/wav",dataBase64:de}),B("idle")}catch(it){B("error"),L(it?.message||"Failed to send PTT clip.")}},[r,v]),Ee=m.useCallback(async()=>{if(!v){L("Take control of your rover first.");return}await re(),J.current=[],te.current=!0,B("recording")},[re,v]);return m.useEffect(()=>{let fe=!1;async function we(){if(j){await ze(W.current||v);return}if(!v){await ze(W.current);return}if(!(F.current&&W.current===v)&&!(!S&&!q))try{k("starting"),L(""),F.current=!0,W.current=v,await $e(v),fe||k("live")}catch(Ae){fe||(k("error"),L(Ae?.message||"Failed to start mic forwarding.")),await ze(v)}}return we(),()=>{fe=!0}},[j,S,q,v,$e,ze]),m.useEffect(()=>{const fe=K.current;fe&&(fe.enabled=!!(!j&&(S||q)))},[j,S,q]),m.useEffect(()=>{let fe=!1;async function we(){if(!j||!v){te.current&&await xe({send:!1}),B("idle");return}try{await re(),!fe&&!te.current&&B("idle")}catch(Ae){fe||(B("error"),L(Ae?.message||"Microphone access failed for clip mode."))}}return we(),()=>{fe=!0}},[j,re,xe,v]),m.useEffect(()=>{let fe=!1;async function we(){if(j){if(!v){te.current&&await xe({send:!1});return}if(q){if(!te.current)try{L(""),await Ee()}catch(Ae){fe||(B("error"),L(Ae?.message||"Failed to start clip recording."))}}else te.current&&await xe({send:!0})}}return we(),()=>{fe=!0}},[j,xe,q,v,Ee]),m.useEffect(()=>()=>{ze(W.current||v),vt()},[v,ze,vt]),l.jsx("section",{className:"surface",children:l.jsxs("div",{className:"grid gap-1",children:[l.jsx("p",{className:"text-sm text-slate-100 text-center",children:"Audio Controls"}),l.jsx("section",{className:"surface",children:l.jsxs("div",{className:"flex items-center justify-center gap-0.5 py-0.25 text-xs text-slate-300",children:[l.jsx("span",{children:"Push-to-Talk Key"}),l.jsx(Ax,{label:be})]})}),l.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-2",children:[l.jsx("section",{className:"surface h-full",children:l.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"PTT Mode"}),l.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."}),l.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[l.jsx("button",{type:"button",className:`button-dark w-full text-sm ${j?"":"bg-emerald-500 text-white hover:bg-emerald-500"}`,onClick:()=>Ve("live"),children:"Live Mic (WHIP)"}),l.jsx("button",{type:"button",className:`button-dark w-full text-sm ${j?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,onClick:()=>Ve("clip"),children:"Record Clip"})]})]})}),l.jsx("section",{className:"surface h-full",children:l.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_1fr]",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"PTT Clip Status"}),l.jsxs("div",{className:"grid gap-0.5 content-start",children:[l.jsx(vn,{label:"Mode",active:j,detail:j?"record clip":"live mic"}),l.jsx(vn,{label:"PTT hold",active:q,detail:q?"held":"released"}),l.jsx(vn,{label:"Recording",active:ve,detail:ve?"capturing":"idle"}),l.jsx(vn,{label:"Playback",active:j&&ne,detail:j&&ne?"playing":"idle"})]})]})})]}),l.jsxs("div",{className:"grid gap-0.5 grid-cols-1 lg:grid-cols-2",children:[l.jsx("section",{className:"surface h-full",children:l.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr_auto]",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Audio Upload"}),l.jsxs("label",{className:"mx-auto grid w-full max-w-sm gap-0.5 text-xs text-slate-300 text-center",children:[l.jsx("span",{children:"Audio file (mp3 / wav / ogg)"}),l.jsx("input",{className:`${wr} text-center`,type:"file",accept:".mp3,.wav,.ogg,audio/mpeg,audio/wav,audio/ogg",disabled:M||!v,onChange:fe=>N(fe.target.files?.[0]||null)})]}),l.jsx("div",{className:"mx-auto w-full max-w-sm text-center",children:y?l.jsxs("div",{className:"surface-muted text-xs text-slate-300",children:[y.name," (",y.size," bytes)"]}):l.jsx("div",{className:"surface-muted text-xs text-slate-500",children:"No file selected"})}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:M||!v,onClick:De,children:M?"Working...":"Play Upload"}),l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:M||!v,onClick:Te,children:"Stop"})]})]})}),l.jsx("section",{className:"surface h-full",children:l.jsxs("div",{className:"grid h-full gap-0.5 grid-rows-[auto_auto_1fr]",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Live Microphone"}),l.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:[l.jsx("input",{type:"checkbox",checked:S,disabled:!v||j,onChange:fe=>g(we=>({...we||{},openMicEnabled:!!fe.target.checked}))}),l.jsx("span",{children:j?"Open mic (live mode only)":"Open mic"})]}),l.jsxs("div",{className:"grid gap-0.5 content-start",children:[l.jsx(vn,{label:"WHIP link",active:se,detail:R}),l.jsx(vn,{label:"Mic hot",active:ce,detail:ce?"transmitting":"muted"}),l.jsxs("div",{className:"surface-muted text-center text-xs text-slate-400",children:["Hold ",l.jsx(Ax,{label:be})," to talk"]})]})]})})]}),l.jsx("section",{className:"surface",children:l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("p",{className:"text-sm text-slate-200 text-center",children:"Audio Status"}),l.jsxs("div",{className:"grid gap-0.5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-6",children:[l.jsx(vn,{label:"Forward pipe",active:I,detail:I?"connected":"offline"}),l.jsx(vn,{label:"Upload playback",active:ne,detail:ne?"playing":"idle"}),l.jsx(vn,{label:"Mic relay",active:me,detail:me?"active":"idle"}),l.jsx(vn,{label:"WHIP transport",active:se,detail:R}),l.jsx(vn,{label:"Clip recording",active:ve,detail:ve?"recording":"idle"}),l.jsx(vn,{label:"Clip sending",active:he,detail:he?"sending":"idle"})]}),X?l.jsx("div",{className:"text-xs text-slate-400 text-center",children:X}):null]})})]})})}function _A({pendingRequestId:n,currentStoredKey:s,nickname:r,requestVerification:o,applyIdentityKey:u,onMessage:f,fullWidth:p=!1}){const[h,x]=m.useState(0),[g,v]=m.useState(""),[y,N]=m.useState(!1),[M,C]=m.useState(!1),S=()=>{x(1),v(s),N(!1),f?.("")},w=()=>{x(0),N(!1)},j=async k=>{if(k.preventDefault(),!y){f?.("Please confirm your nickname agreement before sending.");return}if(h<3){f?.("Complete all request steps before sending.");return}C(!0),f?.("");try{const E=await u(g);await o?.(),v(E),x(0),N(!1),f?.("Verification request sent to lockdown admins.")}catch(E){f?.(E.message||"Failed to submit request.")}finally{C(!1)}},R=p?"w-full":Oo;return n?l.jsx("section",{className:`surface text-sm text-slate-300 ${R}`,children:l.jsxs("div",{className:pr,children:["Verification request pending: ",n]})}):h===0?l.jsx("section",{className:`surface ${R}`,children:l.jsxs("div",{className:pr,children:[l.jsx("p",{className:"text-sm text-slate-300",children:"Verification"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:S,disabled:M,children:"Request Verification"})]})}):l.jsx("form",{className:`surface ${R}`,onSubmit:j,children:l.jsxs("div",{className:pr,children:[l.jsx("p",{className:"text-sm text-slate-300",children:"Request verification"}),l.jsxs("p",{className:"text-xs text-slate-500",children:["Step ",h," of 3"]}),h===1?l.jsxs("div",{className:"space-y-0.5",children:[l.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."}),l.jsx("div",{className:"mx-auto w-full max-w-sm",children:l.jsx(Do,{compact:!0})}),l.jsxs("div",{className:"surface-muted mx-auto w-full max-w-sm text-xs text-slate-300 text-center",children:["Current nickname: ",l.jsx("span",{className:"font-semibold",children:r||"(not set)"})]}),l.jsxs("label",{className:"flex items-center justify-center gap-0.5 text-xs text-slate-300 text-center",children:[l.jsx("input",{type:"checkbox",className:"accent-emerald-500",checked:y,onChange:k=>N(k.target.checked)}),l.jsx("span",{children:"I understand this nickname is tied to my verification."})]}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!r||!y,onClick:()=>x(2),children:"Continue"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:w,children:"Cancel"})]})]}):null,h===2?l.jsxs("div",{className:"space-y-0.5",children:[l.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."}),l.jsx("input",{className:wr,type:"password",name:"identity_key_request",autoComplete:"current-password",maxLength:35,value:g,onChange:k=>v(k.target.value.toLowerCase()),placeholder:"Identity key for this request"}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!g,onClick:()=>navigator.clipboard?.writeText(g),children:"Copy Key"}),l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!g,onClick:()=>x(3),children:"Continue"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(1),children:"Back"})]})]}):null,h===3?l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("p",{className:"text-xs text-slate-400",children:"Final step: confirm and send your verification request."}),l.jsx("input",{className:wr,type:"password",name:"identity_key_request_final",autoComplete:"current-password",maxLength:35,value:g,onChange:k=>v(k.target.value.toLowerCase()),placeholder:"Identity key for this request"}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"submit",className:"button-dark text-sm",disabled:M||!g,children:"Confirm Request"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>x(2),children:"Back"})]})]}):null]})})}function OA({currentStoredKey:n,applyIdentityKey:s,onMessage:r,fullWidth:o=!1}){const[u,f]=m.useState(0),[p,h]=m.useState(""),[x,g]=m.useState(!1),v=()=>{f(1),h(""),r?.("")},y=()=>{f(0),h("")},N=async C=>{if(C.preventDefault(),!(u<2)){g(!0),r?.("");try{await s(p),f(0),h(""),r?.("Identity key restored.")}catch(S){r?.(S.message||"Failed to restore key.")}finally{g(!1)}}},M=o?"w-full":Oo;return l.jsx("section",{className:`surface ${M}`,children:l.jsxs("div",{className:pr,children:[l.jsx("p",{className:"text-sm text-slate-300",children:"Identity key"}),l.jsxs("p",{className:"text-xs text-slate-500",children:["Current: ",jA(n)||"not set yet"]}),l.jsx("input",{className:wr,type:"password",name:"identity_key_current",autoComplete:"current-password",maxLength:35,value:n,readOnly:!0,placeholder:"Identity key"}),u===0?l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",disabled:!n,onClick:()=>navigator.clipboard?.writeText(n),children:"Copy Key"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:v,disabled:x,children:"Restore Key"})]}):null,u===1?l.jsxs("div",{className:"space-y-0.5",children:[l.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."}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>f(2),children:"Continue"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:y,children:"Cancel"})]})]}):null,u===2?l.jsxs("form",{className:"space-y-0.5",onSubmit:N,children:[l.jsx("input",{className:wr,type:"password",name:"identity_key_restore",autoComplete:"current-password",maxLength:35,value:p,onChange:C=>h(C.target.value.toLowerCase()),placeholder:"Paste key to restore"}),l.jsxs("div",{className:"flex justify-center gap-0.5",children:[l.jsx("button",{type:"submit",className:"button-dark text-sm",disabled:x||!p,children:"Confirm Restore"}),l.jsx("button",{type:"button",className:"button-dark text-sm",onClick:()=>f(1),children:"Back"})]})]}):null]})})}function BA({requestableRovers:n=[],pendingRequests:s=[],requestPrivateRoverAccess:r,onMessage:o,fullWidth:u=!1}){const[f,p]=m.useState({}),h=m.useMemo(()=>{const v=new Map;return(s||[]).forEach(y=>{y?.roverId&&v.set(String(y.roverId),y)}),v},[s]),x=u?"w-full":Oo,g=async v=>{if(v){p(y=>({...y,[v]:!0})),o?.("");try{(await r?.(v))?.existing?o?.("You already have a pending request for that rover."):o?.("Private rover access request sent to lockdown admins.")}catch(y){o?.(y.message||"Failed to send request.")}finally{p(y=>({...y,[v]:!1}))}}};return l.jsx("section",{className:`surface text-sm text-slate-300 ${x}`,children:l.jsxs("div",{className:pr,children:[l.jsx("p",{className:"text-sm text-slate-300",children:"Private rover access requests"}),n.length===0?l.jsx("p",{className:"text-xs text-slate-500",children:"No closed private rovers are available to request right now."}):l.jsx("div",{className:"w-full space-y-0.5",children:n.map(v=>{const y=String(v.id),N=!!f[y],M=h.get(y);return l.jsxs("div",{className:"surface-muted flex items-center justify-between gap-0.5 px-1 py-0.5",children:[l.jsxs("div",{className:"min-w-0 text-left",children:[l.jsx("p",{className:"truncate text-xs font-semibold text-slate-100",children:v.name||y}),l.jsx("p",{className:"truncate text-[0.7rem] text-slate-500",children:y})]}),M?l.jsx("span",{className:"rounded bg-amber-700/30 px-1 py-0.5 text-[0.7rem] text-amber-200",children:"Pending"}):l.jsx("button",{type:"button",onClick:()=>g(y),disabled:N,className:"button-dark text-xs disabled:opacity-50",children:N?"Sending...":"Request"})]},y)})})]})})}function al(n){return String(n||"").trim()}function LA(n){const s=al(n);return s?s.includes("DOCKINGRUNNING")?"Returning":s.includes("PAUSED")?"Paused":s.includes("HOUSECLEANINGRUNNING")?"Cleaning":s.includes("SPOTCLEANINGRUNNING")?"Spot cleaning":s.includes("STATE_START")?"Starting":s.includes("STATE_IDLE")||s.includes("STATE_STANDBY")?"Idle":s:"--"}function Jg(n){return n==="good"?"bg-emerald-600 text-white":n==="warn"?"bg-amber-500 text-slate-900":n==="danger"?"bg-rose-600 text-white":"bg-slate-700 text-slate-100"}function to({label:n,value:s,tone:r="muted",valueClass:o="",hideLabel:u=!1}){return l.jsxs("div",{className:`rounded-md px-1 py-0.75 text-center ${Jg(r)}`,children:[u?null:l.jsx("div",{className:"text-[0.72rem] opacity-90",children:n}),l.jsx("div",{className:`text-sm font-semibold ${o}`,title:String(s||""),children:s})]})}function zA(n=[]){const u=[...n.filter(C=>C&&C.valid&&Number.isFinite(C.angleDeg)&&Number.isFinite(C.distanceMm))].sort((C,S)=>Number(C.angleDeg)-Number(S.angleDeg)),f=[];let p=[];for(const C of u){if(!p.length){p.push(C);continue}const S=p[p.length-1],w=Math.abs(Number(C.angleDeg)-Number(S.angleDeg)),j=Math.max(0,Number(S.distanceMm)),R=Math.max(0,Number(C.distanceMm)),k=Math.abs(R-j);if(w<=2&&k<=900){p.push(C);continue}f.push(p),p=[C]}p.length&&f.push(p);const h=f.map(C=>{const S=C.map(j=>Math.max(0,Number(j.distanceMm))),w=S.reduce((j,R)=>j+R,0)/Math.max(1,S.length);return{points:C,size:C.length,avgDistanceMm:w}}),g=h.reduce((C,S)=>S.size>(C?.size||0)?S:C,null)?.avgDistanceMm||1e3,v=h.filter(C=>{const S=C.size<=3,w=C.avgDistanceMm>g*1.8&&C.avgDistanceMm-g>1400;return!(S&&w)}).flatMap(C=>C.points),y=v.map(C=>Math.max(0,Number(C.distanceMm))).sort((C,S)=>C-S),N=Math.max(0,Math.floor((y.length-1)*.95)),M=Math.max(1e3,y[N]||1e3);return v.map(C=>{const S=(Number(C.angleDeg)-90)*Math.PI/180,w=Math.max(0,Number(C.distanceMm)),R=Math.max(0,Math.min(1,w/M))*102,k=110+Math.cos(S)*R,E=110+Math.sin(S)*R,X=38+Math.max(0,Math.min(255,Number(C.intensity)||0))/255*38;return{key:`${C.angleDeg}-${C.distanceMm}-${C.intensity}`,x:k,y:E,fill:`hsl(198 100% ${X}%)`}})}function UA({neato:n,lidar:s,lidarActive:r=!0,onStart:o,onSendHome:u,onLocate:f,onClearErrors:p,onPowerCycle:h,fullWidth:x=!1}){const[g,v]=m.useState(""),[y,N]=m.useState(!1),[M,C]=m.useState(!1),S=x?"w-full":"w-full max-w-xl",w=!!n?.configured,j=!!(n?.enabled&&n?.connected),R=!!n?.telemetry?.extPowerPresent,k=!!n?.telemetry?.chargingActive,E=LA(n?.telemetry?.uiState),B=al(n?.telemetry?.robotState)||"--",X=n?.telemetry?.batteryPercent,L=Number.isFinite(X)?`${X}%`:"--",z=n?.telemetry?.batteryVoltage,K=Number.isFinite(z)?`${z.toFixed(2)} V`:"--",V=al(n?.telemetry?.robotError)||"--",F=al(n?.telemetry?.robotAlert)||"--",W=Array.isArray(s?.points)?s.points:[],ie=m.useMemo(()=>r?zA(W):[],[r,W]),oe=al(s?.status)||"--",$=s?.debug&&typeof s.debug=="object"?s.debug:null,T=al($?.reason)||"--",H=$?.stats&&typeof $.stats=="object"?$.stats:null,J=n?.controls||{},te=!!J?.start?.available,ue=!!J?.sendHome?.available,q=!!J?.locate?.available,_=!!J?.clearErrors?.available,I=!!J?.powerCycle?.available,ne=w&&j&&te,me=w&&j&&ue,ce=w&&j&&q,se=w&&j&&_,ve=w&&j&&I,he=async(ze,$e)=>{if($e){v(ze);try{await $e()}catch{}finally{v("")}}},be=w?j?"Online":"Offline":"Not configured",Ve=w?j?"good":"danger":"warn",De=X==null?"muted":X>=60?"good":X>=25?"warn":"danger",Te=R?"Docked":E!=="--"?E:"Away from dock";return m.useEffect(()=>{if(!r||!s||!Array.isArray(s.points))return;N(!0);const ze=setTimeout(()=>{N(!1)},120);return()=>clearTimeout(ze)},[s,r]),l.jsx("section",{className:`surface text-sm text-slate-200 ${S}`,children:l.jsxs("div",{className:"grid gap-0.5",children:[l.jsxs("div",{className:"relative flex items-center justify-center min-h-[1.5rem]",children:[l.jsxs("div",{className:"text-center",children:[l.jsx("p",{className:"text-sm text-slate-100",children:"Neato Controls"}),l.jsx("p",{className:"text-xs text-slate-400",children:"Control the autonomous Neato robovac. Be nice to him."})]}),l.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${Jg(Ve)}`,children:be})]}),l.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-[minmax(0,0.95fr)_minmax(0,1.05fr)] gap-0.5",children:[l.jsxs("div",{className:"surface-muted grid gap-0.5",children:[l.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Controls"}),l.jsx("button",{type:"button",disabled:!ne||!!g,onClick:()=>he("start",o),className:"rounded-md border border-sky-300 bg-emerald-600 px-1 py-1 text-base font-semibold text-white transition hover:border-sky-500 hover:bg-emerald-500 disabled:opacity-50",children:g==="start"?"Starting...":"Start cleaning"}),l.jsx("button",{type:"button",disabled:!me||!!g,onClick:()=>he("sendHome",u),className:"rounded-md border border-sky-300 bg-sky-600 px-1 py-1 text-base font-semibold text-white transition hover:border-sky-500 hover:bg-sky-500 disabled:opacity-50",children:g==="sendHome"?"Sending...":"Send to dock"}),l.jsxs("div",{className:"grid grid-cols-3 gap-0.5",children:[l.jsx("button",{type:"button",disabled:!ce||!!g,onClick:()=>he("locate",f),className:"w-full rounded-md border border-sky-300 bg-fuchsia-600 px-1 py-0.5 text-xs font-semibold text-white transition hover:border-sky-500 hover:bg-fuchsia-500 disabled:opacity-50",children:g==="locate"?"Playing...":"Play sound"}),l.jsx("button",{type:"button",disabled:!se||!!g,onClick:()=>he("clearErrors",p),className:"w-full rounded-md border border-sky-300 bg-amber-500 px-1 py-0.5 text-xs font-semibold text-slate-900 transition hover:border-sky-500 hover:bg-amber-400 disabled:opacity-50",children:g==="clearErrors"?"Clearing...":"Clear errors"}),l.jsx("button",{type:"button",disabled:!ve||!!g,onClick:()=>he("powerCycle",h),className:"w-full rounded-md border border-rose-300 bg-rose-600 px-1 py-0.5 text-xs font-semibold text-white transition hover:border-rose-500 hover:bg-rose-500 disabled:opacity-50",children:g==="powerCycle"?"Cycling...":"Power cycle"})]}),l.jsxs("div",{className:"surface-muted grid gap-0.5 pt-0.25",children:[l.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Power status"}),l.jsxs("div",{className:"grid grid-cols-2 gap-0.5",children:[l.jsx(to,{label:"Battery",value:L,tone:De}),l.jsx(to,{label:"Voltage",value:K,tone:"muted"}),l.jsx(to,{label:"Docked",value:R?"Docked":"Not docked",tone:R?"good":"muted",hideLabel:!0}),l.jsx(to,{label:"Charging",value:k?"charging":"not charging",tone:k?"good":"muted",hideLabel:!0})]})]})]}),l.jsx("div",{className:"grid gap-0.5",children:l.jsxs("div",{className:"surface-muted grid gap-0.5",children:[l.jsx("p",{className:"text-xs text-slate-300 text-center",children:"Robot Status"}),l.jsxs("div",{className:"grid grid-cols-1 xl:grid-cols-[minmax(0,1fr)_minmax(13rem,15rem)] gap-0.5 items-start",children:[l.jsxs("div",{className:"grid gap-0.5",children:[l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot state (raw)"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:B})]}),l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Basic state"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:Te})]}),l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"UI state"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:E})]}),l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot error"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:V})]}),l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.5",children:[l.jsx("div",{className:"text-[0.72rem] text-slate-300",children:"Robot alert"}),l.jsx("div",{className:"font-mono text-sm text-slate-100 break-all",children:F})]})]}),l.jsxs("div",{className:`rounded-md px-1 py-0.5 ${y?"bg-emerald-900":"bg-slate-800"}`,children:[l.jsx("button",{type:"button",onClick:()=>C(ze=>!ze),className:"w-full text-left text-[0.72rem] text-slate-300",children:"Lidar"}),l.jsx("div",{className:"mt-0.25 text-center text-[0.68rem] text-slate-400",children:"Front of robot"}),l.jsx("div",{className:"mt-0.25 aspect-square rounded-md bg-slate-800 p-0",children:ie.length?l.jsxs("svg",{viewBox:"0 0 220 220",className:"h-full w-full",children:[l.jsx("rect",{x:"0",y:"0",width:"220",height:"220",fill:"#1e293b"}),l.jsx("rect",{x:"7",y:"7",width:"206",height:"206",fill:"none",stroke:"#64748b",strokeWidth:"1"}),l.jsx("rect",{x:"33",y:"33",width:"154",height:"154",fill:"none",stroke:"#475569",strokeWidth:"1"}),l.jsx("rect",{x:"59",y:"59",width:"102",height:"102",fill:"none",stroke:"#475569",strokeWidth:"1"}),l.jsx("rect",{x:"85",y:"85",width:"50",height:"50",fill:"none",stroke:"#334155",strokeWidth:"1"}),l.jsx("line",{x1:"110",y1:"7",x2:"110",y2:"213",stroke:"#475569",strokeWidth:"1"}),l.jsx("line",{x1:"7",y1:"110",x2:"213",y2:"110",stroke:"#475569",strokeWidth:"1"}),l.jsx("circle",{cx:"110",cy:"110",r:"4",fill:"#e2e8f0"}),ie.map(ze=>l.jsx("circle",{cx:ze.x,cy:ze.y,r:"1.8",fill:ze.fill},ze.key))]}):l.jsx("div",{className:"flex h-full items-center justify-center text-center text-xs text-slate-400",children:"Waiting for scan"})}),M?l.jsxs("div",{className:"mt-0.5 rounded-md bg-slate-900 px-0.75 py-0.5 font-mono text-[0.68rem] text-slate-300",children:[l.jsxs("div",{children:["Status: ",oe]}),l.jsxs("div",{children:["Reason: ",T]}),l.jsxs("div",{children:["Points: ",W.length]}),l.jsxs("div",{children:["Rotation: ",Number.isFinite(s?.rotationSpeed)?s.rotationSpeed.toFixed(2):"--"]}),l.jsxs("div",{children:["Request in flight: ",$?.requestInFlight?"yes":"no"]}),l.jsxs("div",{children:["Started at: ",$?.requestStartedAt||"--"]}),l.jsxs("div",{children:["Headers: ",H?.headersSeen??"--"]}),l.jsxs("div",{children:["Rotations: ",H?.rotationsSeen??"--"]}),l.jsxs("div",{children:["Scans ok: ",H?.scansOk??"--"]}),l.jsxs("div",{children:["Timeouts: ",H?.scansTimedOut??"--"]}),l.jsxs("div",{children:["Restarts: ",H?.scansRestarted??"--"]}),l.jsxs("div",{children:["Rotation no scan: ",H?.rotationsWithoutScan??"--"]}),l.jsxs("div",{children:["Parseable payloads: ",H?.parseablePayloads??"--"]}),l.jsxs("div",{children:["Point payloads: ",H?.pointPayloads??"--"]})]}):null]})]})]})})]}),!w||!j||!te||!ue||!q||!_||!I?l.jsx("p",{className:"text-xs text-slate-400 text-center",children:w?j?"Waiting for required Neato entities in Home Assistant.":"Home Assistant is offline.":"Set homeAssistant.neato.device in server config to enable Neato controls."}):null]})})}function HA(n){return n==="good"?"bg-emerald-600 text-white":n==="warn"?"bg-amber-500 text-slate-900":n==="danger"?"bg-rose-600 text-white":"bg-slate-700 text-slate-100"}function VA(n){return n==="up"?"Up":n==="down"?"Down":n==="stopped"?"Transitioning...":n==="conflict"?"Conflict":"--"}function $A({lift:n,onUp:s,onDown:r,fullWidth:o=!1}){const[u,f]=m.useState(""),[p,h]=m.useState(()=>Date.now()),x=o?"w-full":"w-full max-w-xl",g=!!n?.configured,v=!!(n?.enabled&&n?.connected),y=!!n?.busy,N=String(n?.target||"").toLowerCase(),M=String(n?.position||"").toLowerCase(),C=!!n?.availability?.upSwitch,S=!!n?.availability?.downSwitch,w=Number(n?.lastActionAt||0),j=Math.max(0,Number(n?.commandCooldownMs||0)),R=Math.max(0,w+j-p),k=!y&&R>0,E=y||k;m.useEffect(()=>{if(!E)return;const V=setInterval(()=>{h(Date.now())},100);return()=>clearInterval(V)},[E]),m.useEffect(()=>{h(Date.now())},[w,j,y]);const B=g?v?E?"Busy":"Ready":"Offline":"Not configured",X=g?v?E?"warn":"good":"danger":"warn",L=g&&v&&!E&&!u&&C&&S,z=m.useMemo(()=>Math.ceil(R/1e3),[R]),K=async(V,F)=>{if(F){f(V);try{await F()}catch{}finally{f("")}}};return l.jsxs("section",{className:`surface relative text-sm text-slate-200 ${x}`,children:[E?l.jsx("div",{className:"absolute inset-0 z-20 flex items-center justify-center rounded-md bg-slate-950/80 px-1.5 text-center",children:l.jsxs("div",{className:"space-y-0.25",children:[l.jsx("p",{className:"text-sm font-semibold text-slate-100",children:y?"Motion in progress":"Motion cooldown active"}),l.jsx("p",{className:"text-xs text-slate-300",children:"Controls are disabled while the lift is moving, otherwise it's tiny brain would get confused."}),!y&&k?l.jsxs("p",{className:"text-xs text-slate-400",children:["About ",z,"s remaining."]}):null]})}):null,l.jsxs("div",{className:"grid gap-0.5",children:[l.jsxs("div",{className:"relative flex items-center justify-center min-h-[1.5rem]",children:[l.jsxs("div",{className:"text-center",children:[l.jsx("p",{className:"text-sm text-slate-100",children:"Lift Controls"}),l.jsx("p",{className:"text-xs text-slate-400",children:"Move the lift up and down. Please don't break anything..."})]}),l.jsx("span",{className:`absolute right-0 inline-flex w-auto rounded px-1 py-0.25 text-xs font-semibold ${HA(X)}`,children:B})]}),l.jsx("section",{className:"surface-muted px-0.5 py-0.5",children:l.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-0.5",children:[l.jsxs("div",{className:"rounded-md bg-slate-800 px-1 py-0.75 text-center",children:[l.jsx("div",{className:"text-xs text-slate-300",children:"Position"}),l.jsx("div",{className:"text-base font-semibold text-slate-100",children:VA(M)})]}),l.jsx("button",{type:"button",disabled:!L,onClick:()=>K("down",r),className:`button-dark w-full text-sm disabled:opacity-50 ${M==="down"||N==="down"?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,children:u==="down"||N==="down"?"Lowering...":"Down"}),l.jsx("button",{type:"button",disabled:!L,onClick:()=>K("up",s),className:`button-dark w-full text-sm disabled:opacity-50 ${M==="up"||N==="up"?"bg-emerald-500 text-white hover:bg-emerald-500":""}`,children:u==="up"||N==="up"?"Raising...":"Up"})]})}),!g||!v||!C||!S?l.jsx("p",{className:"text-xs text-slate-400 text-center",children:g?v?"Waiting for required lift switch entities in Home Assistant.":"Home Assistant is offline.":"Set homeAssistant.lift.upSwitch and homeAssistant.lift.downSwitch in server config."}):null,n?.lastError?l.jsxs("p",{className:"text-xs text-rose-300 text-center",children:["Last error: ",n.lastError]}):null]})]})}function Pg({isActive:n=!0}){const s=pe($=>$.session),r=pe($=>$.neatoLidar),{identifySession:o,requestVerification:u,requestPrivateRoverAccess:f,playUploadedAudio:p,stopUploadedAudio:h,startMicWhip:x,readyMicWhip:g,stopMicWhip:v,neatoStart:y,neatoSendHome:N,neatoLocate:M,neatoClearErrors:C,neatoPowerCycle:S,liftUp:w,liftDown:j}=Xt(),{value:R,save:k}=Qe("identity",{cookieUserId:""}),{value:E}=Qe("profile",{nickname:""}),B=m.useMemo(()=>(R?.cookieUserId||"").trim(),[R?.cookieUserId]),X=(E?.nickname||"").trim(),L=!!s?.isVerified,z=s?.verification?.pendingRequestId||null,K=s?.privateRoverAccess?.requestableRovers||[],V=s?.privateRoverAccess?.pendingRequests||[],F=String(s?.assignment?.roverId||"").trim(),[W,ie]=m.useState(""),oe=async $=>{const T=String($||"").trim().toLowerCase();if(!T)throw new Error("Identity key required.");if(!SA.test(T))throw new Error("Identity key must match format: cu_ + 32 lowercase hex chars.");return k(H=>({...H||{},cookieUserId:T})),await o({cookieUserId:T,nickname:X}),T};return l.jsxs("section",{className:"space-y-2 text-base",children:[l.jsxs("div",{className:"grid gap-2 grid-cols-1 lg:grid-cols-[minmax(0,1.25fr)_minmax(0,0.9fr)]",children:[L?null:l.jsx("div",{className:"lg:col-span-2",children:l.jsx(_A,{pendingRequestId:z,currentStoredKey:B,nickname:X,requestVerification:u,applyIdentityKey:oe,onMessage:ie,fullWidth:!0})}),l.jsx("div",{className:"lg:col-span-2",children:L?l.jsxs("div",{className:"space-y-2",children:[l.jsx(UA,{neato:s?.neato||null,lidar:r,lidarActive:n,onStart:y,onSendHome:N,onLocate:M,onClearErrors:C,onPowerCycle:S,fullWidth:!0}),l.jsx($A,{lift:s?.lift||null,onUp:w,onDown:j,fullWidth:!0}),l.jsx(DA,{ownRoverId:F,audioForwardByRover:s?.audioForward||{},playUploadedAudio:p,stopUploadedAudio:h,startMicWhip:x,readyMicWhip:g,stopMicWhip:v})]}):l.jsx("section",{className:"surface h-full",children:l.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."})})}),l.jsx("div",{className:"lg:col-span-2",children:l.jsx(BA,{requestableRovers:K,pendingRequests:V,requestPrivateRoverAccess:f,onMessage:ie,fullWidth:!0})}),l.jsx("div",{className:"lg:col-span-2",children:l.jsx(OA,{currentStoredKey:B,applyIdentityKey:oe,onMessage:ie,fullWidth:!0})})]}),W?l.jsx("div",{className:Oo,children:l.jsx("p",{className:"text-xs text-slate-400 text-center",children:W})}):null]})}const GA=420,YA=1200,FA={1:262,2:330,3:392,4:523};function No(){const n=pe(S=>S.session?.buttonBox?.buttons??[]),s=sn(),{value:r}=Qe("audio",ut),o=Number.isFinite(r?.masterVolume)?r.masterVolume:ut.masterVolume,u=Number.isFinite(r?.alertVolume)?r.alertVolume:ut.alertVolume,f=Math.max(0,Math.min(1,o*u)),p=m.useMemo(()=>{const S=Array.isArray(n)?n:[];return S.length===4?S:[1,2,3,4].map(w=>S.find(j=>Number(j?.id)===w)||{id:w,count:0,goal:0,rewardName:null,rewardId:null,rewardNumber:null,lastRewardAt:null})},[n]),[h,x]=m.useState({}),[g,v]=m.useState({}),y=m.useRef(new Map),N=m.useRef(new Map),M=m.useRef({}),C=m.useRef(null);return m.useEffect(()=>{const S={};p.forEach(j=>{S[j.id]=Number(j.lastRewardAt||0)});const w=M.current||{};p.forEach(j=>{const R=Number(j.id),k=S[R]||0,E=Number(w[R]||0);if(k>0&&k!==E){v(L=>({...L,[R]:!0}));const B=N.current.get(R);B&&clearTimeout(B);const X=setTimeout(()=>{v(L=>({...L,[R]:!1})),N.current.delete(R)},YA);N.current.set(R,X)}}),M.current=S},[p]),m.useEffect(()=>{function S(j){const R=FA[j];if(!R||f<=0)return;let k=C.current;if(!k){const L=window.AudioContext||window.webkitAudioContext;if(!L)return;k=new L,C.current=k}const E=k.createOscillator(),B=k.createGain();E.type="square",E.frequency.value=R;const X=.14*f;B.gain.setValueAtTime(1e-4,k.currentTime),B.gain.exponentialRampToValueAtTime(Math.max(1e-4,X),k.currentTime+.01),B.gain.exponentialRampToValueAtTime(1e-4,k.currentTime+.2),E.connect(B),B.connect(k.destination),E.start(),E.stop(k.currentTime+.21)}function w(j={}){const R=Number(j.buttonId);if(!Number.isFinite(R)||R<1||R>4)return;x(B=>({...B,[R]:!0}));const k=y.current.get(R);k&&clearTimeout(k);const E=setTimeout(()=>{x(B=>({...B,[R]:!1})),y.current.delete(R)},GA);y.current.set(R,E),S(R)}return s.on("buttonBox:increment",w),()=>{s.off("buttonBox:increment",w)}},[f,s]),l.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[l.jsx("header",{className:"panel-muted text-center text-sm",children:l.jsx("p",{children:"Button Box"})}),l.jsx("div",{className:"grid grid-cols-4 gap-0.5",children:p.map(S=>{const w=Number(S.id),j=Number.isFinite(S.count)?S.count:0,R=Number.isFinite(S.goal)?S.goal:0,k=typeof S.rewardName=="string"&&S.rewardName.trim()?S.rewardName.trim():"Unassigned",E=Number.isFinite(S.rewardNumber)?S.rewardNumber:"?",B=!!h[w],X=!!g[w];return l.jsx(gg,{buttonId:w,count:j,goal:R,rewardNumber:E,rewardName:k,className:[B?"bg-cyan-900/45":"",X?"bg-fuchsia-900/45":""].filter(Boolean).join(" ")},w)})})]})}function XA(){const{state:{roverId:n}}=Dt(),r=fl(n)?.sensors||{};return l.jsx("section",{className:"panel-section",children:l.jsx("div",{className:"aspect-square w-full",children:l.jsx(Vd,{sensors:r})})})}function QA(){const{state:{roverId:n,keymap:s,camera:r,horn:o},pipeline:u,actions:{setServoAngle:f,setNightVision:p,startHorn:h,stopHorn:x}}=Dt(),g=Tg(n),v=g.docked&&!g.driving,y=r?.config,N=!!(n&&r?.enabled&&y),M=!!(n&&u?.nightVision),C=u?.nightVisionState,S=!!(n&&u?.horn),w=o?.overheated,j=typeof y?.minAngle=="number"?y.minAngle:-30,R=typeof y?.maxAngle=="number"?y.maxAngle:30,k=typeof r?.angle=="number"?r.angle:typeof y?.homeAngle=="number"?y.homeAngle:(j+R)/2,E=An(s?.nightVisionToggle?.[0]),B=An(s?.hornHonk?.[0]),X=An(s?.cameraUp?.[0]),L=An(s?.cameraDown?.[0]);return l.jsxs("section",{className:"panel-section grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto] gap-0.5",children:[l.jsx(Dg,{layout:"desktop",expand:!0,driveDockState:g}),v?null:l.jsxs("div",{className:"surface space-y-0.5 p-0 text-sm text-slate-200",children:[M&&l.jsx(_g,{nightVisionOn:C?.nightVisionOn,disabled:!n,onToggle:p,keyLabel:E}),S&&l.jsx(Og,{disabled:!n||w,onStart:h,onStop:x,keyLabel:B,active:o?.active,heat:o?.heat}),N&&l.jsx(Bg,{value:k,min:j,max:R,onChange:f,keyDownLabel:L,keyUpLabel:X,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 KA({layout:n,onOpenHelpOverlay:s}){const[r,o]=m.useState("telemetry"),u=pe(S=>!!S.session?.isVerified),f=pe(S=>String(S.session?.assignment?.roverId||"").trim()),p=pe(S=>{const w=String(S.session?.assignment?.roverId||"").trim();return w&&S.session?.audioForward?.[w]||null}),{state:h}=Dt(),{value:x}=Qe("vipAudio",{openMicEnabled:!1,pttMode:"live"}),g=u?"bg-emerald-400":"bg-red-600",v=!!h?.mic?.pttActive,y=!!x?.openMicEnabled,N=x?.pttMode==="clip"?"clip":"live",M=!!(f&&u&&(N==="clip"?v:y||v)),C=!!(f&&u&&N==="clip"&&p?.source==="upload"&&p?.state==="playing");return l.jsx("section",{className:"panel text-base",children:l.jsxs(Sf,{defaultTab:"telemetry",currentTab:r,onTabChange:o,children:[l.jsxs(jf,{children:[l.jsx(tn,{id:"telemetry",children:"Controls"}),l.jsx(tn,{id:"vip",highlight:C?"green":M?"pink":"none",children:l.jsxs("span",{className:"inline-flex items-center gap-2",children:[l.jsx("span",{children:"VIP"}),l.jsx("span",{className:`inline-block h-3 w-3 rounded-full ${g}`,"aria-hidden":"true",title:u?"Verified":"Not verified"})]})}),l.jsx(tn,{id:"help",children:"Help"}),l.jsx(tn,{id:"settings",children:"Settings"})]}),l.jsxs(Nf,{children:[l.jsx(nn,{id:"telemetry",children:l.jsxs("div",{className:"space-y-0.5",children:[l.jsxs("div",{className:"grid items-stretch gap-0.5 grid-cols-[minmax(0,1.35fr)_minmax(0,0.95fr)]",children:[l.jsx(XA,{}),l.jsx(QA,{})]}),l.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.9fr)_minmax(0,0.75fr)]",children:[l.jsx(_o,{}),l.jsx(af,{panelId:"replay-sources-desktop",fillHeight:!0}),l.jsx(hA,{})]}),l.jsxs("div",{className:"grid items-stretch gap-0.5 grid-cols-[minmax(0,1.3fr)_minmax(0,0.22fr)] h-[14rem]",children:[l.jsx(To,{fillHeight:!0}),l.jsxs("div",{className:"grid min-h-0 gap-0.5 grid-rows-[minmax(0,1fr)_auto]",children:[l.jsx(jo,{compact:!0,hideNicknameForm:!0,fillHeight:!0}),l.jsx(mA,{compact:!0})]})]}),l.jsx(Vg,{}),l.jsx(No,{}),l.jsx(ff,{defaultOrientation:"horizontal",panelId:"rightpane-telemetry"})]})}),l.jsx(nn,{id:"vip",keepMounted:!0,children:l.jsx(Pg,{isActive:r==="vip"})}),l.jsx(nn,{id:"help",children:l.jsx(Zg,{layout:n,onOpenOverlay:s})}),l.jsx(nn,{id:"settings",children:l.jsx(Xg,{})})]})]})})}const ZA=new Set(["admin","lockdown","lockdown-admin"]),IA=new Set(["lockdown","lockdown-admin"]),JA=new Set(["admin","lockdown"]);function PA(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 WA(){const n=pe(y=>y.session?.mode||null),s=pe(y=>y.session?.role||null),r=pe(y=>y.session?.adminReason?.text||"");pe(y=>y.session?.adminReason?.updatedAt||null);const o=pe(y=>y.session?.timezone||"UTC"),u=pe(y=>(y.session?.socials||[]).find(C=>String(C?.id||C?.label||"").toLowerCase()==="discord")?.url||y.session?.discord?.invite||null),f=JA.has(n),p=n==="lockdown"?IA.has(s):ZA.has(s),[h,x]=m.useState(()=>new Date),g=m.useMemo(()=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:o,hour:"numeric",minute:"2-digit",second:"2-digit"}).format(h)}catch{return h.toLocaleTimeString()}},[h,o]);if(m.useEffect(()=>{const y=setInterval(()=>x(new Date),1e3);return()=>clearInterval(y)},[]),!f||p)return null;const v=PA(n);return l.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:l.jsxs("div",{className:"surface w-full max-w-md space-y-0.5 text-slate-100 shadow-2xl",children:[l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("p",{className:"text-lg font-semibold",children:v.title}),l.jsx("p",{className:"text-sm text-slate-300",children:v.description})]}),l.jsxs("div",{className:"surface-muted space-y-0.5",children:[l.jsx("p",{className:"text-[0.7rem] tracking-wide text-slate-400",children:"Reason for locking:"}),l.jsx("p",{className:"text-lg font-semibold text-slate-100",children:r||"No reason set."}),l.jsxs("p",{className:"text-center text-sm text-slate-300",children:["Server time: ",g]})]}),l.jsx("div",{className:"surface-muted",children:l.jsx($g,{})}),l.jsx("div",{className:"w-full justify-center items-center",children:l.jsx(pf,{id:"discord",label:"Join our Discord server for updates!",url:u})}),"You can still use the chat while the server is locked:",l.jsxs("div",{className:"max-h-80 overflow-y-auto",children:[l.jsx(To,{}),l.jsx(Do,{})]})]})})}const e2="/assets/turn_alert-DVO8EZJa.mp3";function t2(n,s=1){const r=m.useRef(null);return m.useEffect(()=>{r.current=new Audio(n),r.current.volume=s,r.current.load()},[n,s]),()=>{r.current&&(r.current.volume=s,r.current.currentTime=0,r.current.play().catch(()=>{}))}}function n2(){const n=pe(v=>v.session?.socketId||null),s=pe(v=>v.session?.turnQueues||{}),r=pe(v=>v.session?.roster||[]),{pushAlert:o}=Xt(),{value:u}=Qe("audio",ut),f=Number.isFinite(u?.masterVolume)?u.masterVolume:ut.masterVolume,p=Number.isFinite(u?.alertVolume)?u.alertVolume:ut.alertVolume,h=Math.max(0,Math.min(1,f*p)),x=t2(e2,h),g=m.useRef(new Set);return m.useEffect(()=>{if(!n)return;const v=[];Object.entries(s).forEach(([y,N])=>{!N||!N.current||N.current!==n||g.current.has(y)||(v.push(y),g.current.add(y))}),Object.keys(s).forEach(y=>{(!s[y]||s[y].current!==n)&&g.current.delete(y)}),v.length!==0&&(v.forEach(y=>{const N=r.find(M=>String(M.id)===String(y))?.name||y;o({title:"Your turn!",message:`You now control ${N}.`,color:"#ff5722"})}),x())},[s,x,o,r,n]),null}function a2({visible:n,mode:s,onEnterFullscreen:r,onDismiss:o}){if(!n)return null;const u=s==="pwa-hint";return l.jsx("div",{className:"fixed inset-0 z-40 flex items-end justify-center p-2 pointer-events-none sm:items-center",children:l.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:l.jsxs("div",{className:"space-y-0.5 p-4 text-sm text-slate-100",children:[l.jsx("h2",{className:"text-base font-semibold text-white",children:"Better in fullscreen"}),u?l.jsxs("p",{className:"text-slate-300",children:["For fullscreen on iOS, open Safari's share menu and pick ",l.jsx("strong",{children:"Add to Home Screen"}),". Launching from the home screen removes the browser chrome."]}):l.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."}),l.jsxs("div",{className:"flex justify-end gap-0.5 pt-1 text-sm",children:[l.jsx("button",{type:"button",className:"rounded border border-slate-600 px-3 py-1 text-slate-200",onClick:o,children:u?"Got it":"Not now"}),!u&&l.jsx("button",{type:"button",className:"rounded bg-cyan-500 px-3 py-1 font-semibold text-black hover:bg-cyan-400",onClick:r,children:"Enter fullscreen"})]})]})})})}function s2({side:n="right",onClick:s}){const r=n==="left"?"left-2":"right-2";return l.jsx("button",{type:"button",onClick:s,className:`fixed bottom-2 ${r} z-30 flex h-10 w-10 items-center justify-center rounded-full border border-slate-700 bg-black text-slate-200 transition hover:bg-zinc-900 active:scale-95`,"aria-label":"Enter fullscreen",title:"Enter fullscreen",children:l.jsx("svg",{viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true",className:"pointer-events-none",children:l.jsx("path",{d:"M4 9V4h5M15 4h5v5M20 15v5h-5M9 20H4v-5",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})}const Wg="fullscreenPromptDismissed",l2=new Set(["mobile-portrait","mobile-landscape"]),ev=()=>{if(typeof window>"u")return null;try{return window.sessionStorage}catch{return null}},r2=()=>{const n=ev();if(!n)return!1;try{return n.getItem(Wg)==="1"}catch{return!1}},Cx=()=>{const n=ev();if(n)try{n.setItem(Wg,"1")}catch{}},i2=()=>{if(typeof navigator>"u")return!1;const n=navigator.userAgent||navigator.platform||"";return/iphone|ipad|ipod/i.test(n)},Ex=()=>{if(typeof document>"u")return!1;const n=document;return!!(n.fullscreenEnabled||n.webkitFullscreenEnabled||n.mozFullScreenEnabled||n.msFullscreenEnabled)};function o2(n){const s=l2.has(n),[r,o]=m.useState(!1),[u,f]=m.useState("native"),[p,h]=m.useState(!1),x=m.useMemo(()=>i2(),[]),g=m.useMemo(()=>Ex(),[]),v=m.useCallback(()=>{if(!s){o(!1),h(!1);return}if(!p&&r2()){o(!1);return}if(x){f("pwa-hint"),o(!0);return}if(!Ex()){o(!1);return}if(typeof document<"u"&&document.fullscreenElement){o(!1);return}f("native"),o(!0)},[p,x,s]);m.useEffect(()=>{v()},[v]),m.useEffect(()=>{if(typeof document>"u")return;const C=()=>{if(document.fullscreenElement){h(!1),o(!1);return}v()};return document.addEventListener("fullscreenchange",C),document.addEventListener("webkitfullscreenchange",C),()=>{document.removeEventListener("fullscreenchange",C),document.removeEventListener("webkitfullscreenchange",C)}},[v]);const y=m.useCallback(()=>{Cx(),h(!1),o(!1)},[]),N=m.useCallback(async()=>{if(!s||x||typeof document>"u")return!1;if(document.fullscreenElement)return!0;const C=document.documentElement;if(!C)return!1;const S=C.requestFullscreen||C.webkitRequestFullscreen||C.mozRequestFullScreen||C.msRequestFullscreen;if(!S)return!1;try{const w=S.call(C);return w&&typeof w.then=="function"&&await w,Cx(),h(!1),o(!1),!0}catch(w){return console.warn("Failed to enter fullscreen",w),!1}},[x,s]),M=m.useCallback(()=>{s&&(h(!0),f(x?"pwa-hint":"native"),o(!0))},[x,s]);return m.useEffect(()=>{s||(h(!1),o(!1))},[s]),{visible:r,mode:u,isIOS:x,nativeSupported:g,enterFullscreen:N,dismiss:y,showPrompt:M}}function c2({visible:n,layout:s,onClose:r,showOnLoad:o,onToggleShowOnLoad:u}){if(!n)return null;const{state:f}=Dt(),p=h=>{const x=!h.target.checked;u?.(x)};return l.jsx("div",{className:"fixed inset-0 z-30 flex items-center justify-center bg-black/80 px-0.5 py-0.5",children:l.jsxs("div",{className:"pointer-events-auto surface w-full max-w-4xl max-h-[90vh] overflow-hidden shadow-2xl",children:[l.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:[l.jsx("span",{className:"font-semibold",children:"Help & controls"}),l.jsxs("div",{className:"flex items-center gap-0.5 text-[0.8rem] text-slate-300",children:[l.jsxs("label",{className:"flex items-center gap-0.5",children:[l.jsx("input",{type:"checkbox",checked:!o,onChange:p,className:"accent-cyan-500"}),l.jsx("span",{children:"Don't show again"})]}),l.jsx("button",{type:"button",onClick:r,className:"button-dark px-2 py-0.25 text-[0.8rem]",children:"Close"})]})]}),l.jsx("div",{className:"max-h-[85vh] overflow-y-auto p-0.5",children:l.jsx(Kg,{layout:s,keymap:f?.keymap||{}})})]})})}const u2=`aroma bagel batter beans diff --git a/server/public/assets/index-CGvUXLso.css b/server/public/assets/index-G6nhQ4vQ.css similarity index 50% rename from server/public/assets/index-CGvUXLso.css rename to server/public/assets/index-G6nhQ4vQ.css index 9402149f..528407cb 100644 --- a/server/public/assets/index-CGvUXLso.css +++ b/server/public/assets/index-G6nhQ4vQ.css @@ -1 +1 @@ -*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.panel{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));padding:0;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.panel-section{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(23 23 23 / var(--tw-bg-opacity));padding:0;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.panel-muted{border-radius:.375rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.surface{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(38 38 38 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.surface-muted{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(245 245 245 / var(--tw-text-opacity))}.field-input{border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(82 82 82 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.field-input::-moz-placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.field-input::placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.field-input:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(14 165 233 / var(--tw-ring-opacity))}.button-dark{border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(125 211 252 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity));padding:.125rem;font-size:.875rem;line-height:1.25rem;font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.button-dark:hover{--tw-border-opacity: 1;border-color:rgb(14 165 233 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity))}.button-danger{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity));padding:.125rem;font-size:.875rem;line-height:1.25rem;font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.button-danger:hover{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity))}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-x-0{left:0;right:0}.bottom-0{bottom:0}.bottom-0\.5{bottom:.125rem}.bottom-1{bottom:.25rem}.bottom-2{bottom:.5rem}.left-0{left:0}.left-0\.5{left:.125rem}.left-1{left:.25rem}.left-1\/2{left:50%}.left-2{left:.5rem}.right-0{right:0}.right-0\.5{right:.125rem}.right-1{right:.25rem}.right-2{right:.5rem}.top-0{top:0}.top-0\.5{top:.125rem}.top-1{top:.25rem}.top-1\/2{top:50%}.top-10{top:2.5rem}.top-6{top:1.5rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[120\]{z-index:120}.order-1{order:1}.order-2{order:2}.col-span-full{grid-column:1 / -1}.m-0{margin:0}.mx-auto{margin-left:auto;margin-right:auto}.-mt-0\.5{margin-top:-.125rem}.mr-0{margin-right:0}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-auto{margin-top:auto}.\!block{display:block!important}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.aspect-\[4\/3\]{aspect-ratio:4/3}.aspect-square{aspect-ratio:1 / 1}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-28{height:7rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-40{height:10rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-64{height:16rem}.h-\[14rem\]{height:14rem}.h-\[2px\]{height:2px}.h-\[3\.5rem\]{height:3.5rem}.h-\[70\%\]{height:70%}.h-\[7rem\]{height:7rem}.h-\[min\(100svh\,32rem\)\]{height:min(100svh,32rem)}.h-\[min\(60svh\,24rem\)\]{height:min(60svh,24rem)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-32{max-height:8rem}.max-h-40{max-height:10rem}.max-h-52{max-height:13rem}.max-h-72{max-height:18rem}.max-h-80{max-height:20rem}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-screen{max-height:100vh}.min-h-0{min-height:0px}.min-h-\[1\.5rem\]{min-height:1.5rem}.min-h-\[14rem\]{min-height:14rem}.min-h-\[16rem\]{min-height:16rem}.min-h-\[3\.5rem\]{min-height:3.5rem}.min-h-\[5rem\]{min-height:5rem}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-1\/2{width:50%}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-\[12\.5rem\]{width:12.5rem}.w-\[12rem\]{width:12rem}.w-\[20rem\]{width:20rem}.w-\[2px\]{width:2px}.w-\[9rem\]{width:9rem}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-\[0\]{min-width:0}.min-w-\[10rem\]{min-width:10rem}.min-w-\[12rem\]{min-width:12rem}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-\[70vw\]{max-width:70vw}.max-w-\[80vw\]{max-width:80vw}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-\[1\.1\]{flex:1.1}.flex-\[1\.22\]{flex:1.22}.flex-\[1_1_12rem\]{flex:1 1 12rem}.shrink-0{flex-shrink:0}.basis-full{flex-basis:100%}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\[minmax\(0\,0\.7fr\)_minmax\(0\,2\.1fr\)_minmax\(0\,0\.7fr\)\]{grid-template-columns:minmax(0,.7fr) minmax(0,2.1fr) minmax(0,.7fr)}.grid-cols-\[minmax\(0\,1\.2fr\)_repeat\(4\,minmax\(0\,1fr\)\)\]{grid-template-columns:minmax(0,1.2fr) repeat(4,minmax(0,1fr))}.grid-cols-\[minmax\(0\,1\.35fr\)_minmax\(0\,0\.95fr\)\]{grid-template-columns:minmax(0,1.35fr) minmax(0,.95fr)}.grid-cols-\[minmax\(0\,1\.3fr\)_minmax\(0\,0\.22fr\)\]{grid-template-columns:minmax(0,1.3fr) minmax(0,.22fr)}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,0\.7fr\)_minmax\(0\,1\.9fr\)_minmax\(0\,0\.7fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,.7fr) minmax(0,1.9fr) minmax(0,.7fr)}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,0\.9fr\)_minmax\(0\,0\.75fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,.9fr) minmax(0,.75fr)}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1\.4fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,1.4fr)}.grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}.grid-rows-\[auto_1fr\]{grid-template-rows:auto 1fr}.grid-rows-\[auto_auto_1fr\]{grid-template-rows:auto auto 1fr}.grid-rows-\[auto_auto_1fr_auto\]{grid-template-rows:auto auto 1fr auto}.grid-rows-\[minmax\(0\,1fr\)_auto\]{grid-template-rows:minmax(0,1fr) auto}.grid-rows-\[minmax\(0\,1fr\)_minmax\(0\,1fr\)_minmax\(0\,1fr\)\]{grid-template-rows:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.content-center{align-content:center}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0px}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.self-start{align-self:flex-start}.self-center{align-self:center}.self-stretch{align-self:stretch}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity))}.border-amber-200\/30{border-color:#fde68a4d}.border-amber-200\/70{border-color:#fde68ab3}.border-amber-300\/70{border-color:#fcd34db3}.border-amber-300\/80{border-color:#fcd34dcc}.border-amber-400\/30{border-color:#fbbf244d}.border-amber-400\/60{border-color:#fbbf2499}.border-amber-600\/60{border-color:#d9770699}.border-amber-700\/60{border-color:#b4530999}.border-blue-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity))}.border-cyan-200\/50{border-color:#a5f3fc80}.border-cyan-300{--tw-border-opacity: 1;border-color:rgb(103 232 249 / var(--tw-border-opacity))}.border-cyan-300\/70{border-color:#67e8f9b3}.border-cyan-500\/40{border-color:#06b6d466}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity))}.border-emerald-200\/70{border-color:#a7f3d0b3}.border-emerald-300\/70{border-color:#6ee7b7b3}.border-emerald-400\/60{border-color:#34d39999}.border-emerald-500\/40{border-color:#10b98166}.border-emerald-700{--tw-border-opacity: 1;border-color:rgb(4 120 87 / var(--tw-border-opacity))}.border-emerald-700\/60{border-color:#04785799}.border-fuchsia-300\/70{border-color:#f0abfcb3}.border-indigo-200\/70{border-color:#c7d2feb3}.border-indigo-300\/70{border-color:#a5b4fcb3}.border-indigo-400\/30{border-color:#818cf84d}.border-indigo-700{--tw-border-opacity: 1;border-color:rgb(67 56 202 / var(--tw-border-opacity))}.border-indigo-700\/60{border-color:#4338ca99}.border-pink-200{--tw-border-opacity: 1;border-color:rgb(251 207 232 / var(--tw-border-opacity))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity))}.border-red-400\/60{border-color:#f8717199}.border-rose-300{--tw-border-opacity: 1;border-color:rgb(253 164 175 / var(--tw-border-opacity))}.border-rose-800{--tw-border-opacity: 1;border-color:rgb(159 18 57 / var(--tw-border-opacity))}.border-sky-300{--tw-border-opacity: 1;border-color:rgb(125 211 252 / var(--tw-border-opacity))}.border-sky-400\/50{border-color:#38bdf880}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity))}.border-slate-200\/30{border-color:#e2e8f04d}.border-slate-400\/60{border-color:#94a3b899}.border-slate-600{--tw-border-opacity: 1;border-color:rgb(71 85 105 / var(--tw-border-opacity))}.border-slate-600\/40{border-color:#47556966}.border-slate-600\/60{border-color:#47556999}.border-slate-700{--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity))}.border-slate-700\/60{border-color:#33415599}.border-slate-700\/70{border-color:#334155b3}.border-slate-700\/80{border-color:#334155cc}.border-slate-800{--tw-border-opacity: 1;border-color:rgb(30 41 59 / var(--tw-border-opacity))}.border-slate-800\/60{border-color:#1e293b99}.border-transparent{border-color:transparent}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity))}.border-white\/40{border-color:#fff6}.border-white\/60{border-color:#fff9}.bg-amber-100\/95{background-color:#fef3c7f2}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity))}.bg-amber-400\/80{background-color:#fbbf24cc}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity))}.bg-amber-500\/30{background-color:#f59e0b4d}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity))}.bg-amber-600\/70{background-color:#d97706b3}.bg-amber-700\/20{background-color:#b4530933}.bg-amber-700\/30{background-color:#b453094d}.bg-amber-700\/35{background-color:#b4530959}.bg-amber-900{--tw-bg-opacity: 1;background-color:rgb(120 53 15 / var(--tw-bg-opacity))}.bg-amber-900\/40{background-color:#78350f66}.bg-amber-900\/60{background-color:#78350f99}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity))}.bg-black\/20{background-color:#0003}.bg-black\/30{background-color:#0000004d}.bg-black\/40{background-color:#0006}.bg-black\/50{background-color:#00000080}.bg-black\/55{background-color:#0000008c}.bg-black\/60{background-color:#0009}.bg-black\/70{background-color:#000000b3}.bg-black\/75{background-color:#000000bf}.bg-black\/80{background-color:#000c}.bg-black\/85{background-color:#000000d9}.bg-cyan-300\/80{background-color:#67e8f9cc}.bg-cyan-400\/10{background-color:#22d3ee1a}.bg-cyan-500{--tw-bg-opacity: 1;background-color:rgb(6 182 212 / var(--tw-bg-opacity))}.bg-cyan-500\/80{background-color:#06b6d4cc}.bg-cyan-900{--tw-bg-opacity: 1;background-color:rgb(22 78 99 / var(--tw-bg-opacity))}.bg-cyan-900\/45{background-color:#164e6373}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity))}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity))}.bg-emerald-500\/45{background-color:#10b98173}.bg-emerald-500\/80{background-color:#10b981cc}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity))}.bg-emerald-600\/70{background-color:#059669b3}.bg-emerald-700\/20{background-color:#04785733}.bg-emerald-700\/60{background-color:#04785799}.bg-emerald-800{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity))}.bg-emerald-900{--tw-bg-opacity: 1;background-color:rgb(6 78 59 / var(--tw-bg-opacity))}.bg-emerald-900\/15{background-color:#064e3b26}.bg-emerald-900\/60{background-color:#064e3b99}.bg-emerald-900\/80{background-color:#064e3bcc}.bg-fuchsia-200{--tw-bg-opacity: 1;background-color:rgb(245 208 254 / var(--tw-bg-opacity))}.bg-fuchsia-600{--tw-bg-opacity: 1;background-color:rgb(192 38 211 / var(--tw-bg-opacity))}.bg-fuchsia-700{--tw-bg-opacity: 1;background-color:rgb(162 28 175 / var(--tw-bg-opacity))}.bg-fuchsia-800{--tw-bg-opacity: 1;background-color:rgb(134 25 143 / var(--tw-bg-opacity))}.bg-fuchsia-900\/45{background-color:#701a7573}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity))}.bg-indigo-600\/70{background-color:#4f46e5b3}.bg-indigo-900{--tw-bg-opacity: 1;background-color:rgb(49 46 129 / var(--tw-bg-opacity))}.bg-indigo-900\/20{background-color:#312e8133}.bg-indigo-900\/60{background-color:#312e8199}.bg-indigo-950\/90{background-color:#1e1b4be6}.bg-pink-500{--tw-bg-opacity: 1;background-color:rgb(236 72 153 / var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity))}.bg-red-500\/45{background-color:#ef444473}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity))}.bg-red-600\/70{background-color:#dc2626b3}.bg-red-700\/20{background-color:#b91c1c33}.bg-red-700\/60{background-color:#b91c1c99}.bg-red-900\/35{background-color:#7f1d1d59}.bg-red-900\/40{background-color:#7f1d1d66}.bg-red-900\/45{background-color:#7f1d1d73}.bg-red-900\/50{background-color:#7f1d1d80}.bg-rose-600{--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity))}.bg-rose-900\/80{background-color:#881337cc}.bg-sky-600{--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity))}.bg-sky-700\/20{background-color:#0369a133}.bg-slate-500{--tw-bg-opacity: 1;background-color:rgb(100 116 139 / var(--tw-bg-opacity))}.bg-slate-600{--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity))}.bg-slate-700{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}.bg-slate-700\/30{background-color:#3341554d}.bg-slate-700\/60{background-color:#33415599}.bg-slate-700\/70{background-color:#334155b3}.bg-slate-700\/80{background-color:#334155cc}.bg-slate-800{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}.bg-slate-800\/70{background-color:#1e293bb3}.bg-slate-800\/80{background-color:#1e293bcc}.bg-slate-900{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity))}.bg-slate-900\/35{background-color:#0f172a59}.bg-slate-900\/40{background-color:#0f172a66}.bg-slate-900\/70{background-color:#0f172ab3}.bg-slate-950\/80{background-color:#020617cc}.bg-slate-950\/90{background-color:#020617e6}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-white\/10{background-color:#ffffff1a}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity))}.bg-zinc-900{--tw-bg-opacity: 1;background-color:rgb(24 24 27 / var(--tw-bg-opacity))}.bg-zinc-900\/90{background-color:#18181be6}.bg-zinc-950{--tw-bg-opacity: 1;background-color:rgb(9 9 11 / var(--tw-bg-opacity))}.bg-zinc-950\/95{background-color:#09090bf2}.bg-cover{background-size:cover}.fill-slate-200{fill:#e2e8f0}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-4{padding:1rem}.px-0{padding-left:0;padding-right:0}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-\[1px\]{padding-top:1px;padding-bottom:1px}.py-\[2px\]{padding-top:2px;padding-bottom:2px}.pb-0{padding-bottom:0}.pb-1{padding-bottom:.25rem}.pr-0{padding-right:0}.pt-0\.5{padding-top:.125rem}.pt-1{padding-top:.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-\[0\.45rem\]{font-size:.45rem}.text-\[0\.55em\]{font-size:.55em}.text-\[0\.55rem\]{font-size:.55rem}.text-\[0\.5rem\]{font-size:.5rem}.text-\[0\.65rem\]{font-size:.65rem}.text-\[0\.68rem\]{font-size:.68rem}.text-\[0\.6rem\]{font-size:.6rem}.text-\[0\.72rem\]{font-size:.72rem}.text-\[0\.75rem\]{font-size:.75rem}.text-\[0\.7rem\]{font-size:.7rem}.text-\[0\.85rem\]{font-size:.85rem}.text-\[0\.8rem\]{font-size:.8rem}.text-\[1\.1rem\]{font-size:1.1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-none{line-height:1}.leading-normal{line-height:1.5}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-amber-100{--tw-text-opacity: 1;color:rgb(254 243 199 / var(--tw-text-opacity))}.text-amber-200{--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity))}.text-amber-200\/80{color:#fde68acc}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity))}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity))}.text-amber-50{--tw-text-opacity: 1;color:rgb(255 251 235 / var(--tw-text-opacity))}.text-amber-50\/90{color:#fffbebe6}.text-amber-950{--tw-text-opacity: 1;color:rgb(69 26 3 / var(--tw-text-opacity))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity))}.text-cyan-100{--tw-text-opacity: 1;color:rgb(207 250 254 / var(--tw-text-opacity))}.text-cyan-300{--tw-text-opacity: 1;color:rgb(103 232 249 / var(--tw-text-opacity))}.text-cyan-50{--tw-text-opacity: 1;color:rgb(236 254 255 / var(--tw-text-opacity))}.text-emerald-100{--tw-text-opacity: 1;color:rgb(209 250 229 / var(--tw-text-opacity))}.text-emerald-200{--tw-text-opacity: 1;color:rgb(167 243 208 / var(--tw-text-opacity))}.text-emerald-300{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity))}.text-emerald-50{--tw-text-opacity: 1;color:rgb(236 253 245 / var(--tw-text-opacity))}.text-emerald-50\/90{color:#ecfdf5e6}.text-emerald-950{--tw-text-opacity: 1;color:rgb(2 44 34 / var(--tw-text-opacity))}.text-fuchsia-50{--tw-text-opacity: 1;color:rgb(253 244 255 / var(--tw-text-opacity))}.text-fuchsia-900{--tw-text-opacity: 1;color:rgb(112 26 117 / var(--tw-text-opacity))}.text-indigo-100\/80{color:#e0e7ffcc}.text-indigo-200{--tw-text-opacity: 1;color:rgb(199 210 254 / var(--tw-text-opacity))}.text-indigo-50{--tw-text-opacity: 1;color:rgb(238 242 255 / var(--tw-text-opacity))}.text-indigo-50\/90{color:#eef2ffe6}.text-lime-200{--tw-text-opacity: 1;color:rgb(217 249 157 / var(--tw-text-opacity))}.text-lime-300{--tw-text-opacity: 1;color:rgb(190 242 100 / var(--tw-text-opacity))}.text-lime-400{--tw-text-opacity: 1;color:rgb(163 230 53 / var(--tw-text-opacity))}.text-red-100\/90{color:#fee2e2e6}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity))}.text-rose-300{--tw-text-opacity: 1;color:rgb(253 164 175 / var(--tw-text-opacity))}.text-rose-50{--tw-text-opacity: 1;color:rgb(255 241 242 / var(--tw-text-opacity))}.text-sky-200{--tw-text-opacity: 1;color:rgb(186 230 253 / var(--tw-text-opacity))}.text-sky-300{--tw-text-opacity: 1;color:rgb(125 211 252 / var(--tw-text-opacity))}.text-slate-100{--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}.text-slate-200{--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity))}.text-slate-300{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.text-slate-400\/60{color:#94a3b899}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity))}.text-teal-400{--tw-text-opacity: 1;color:rgb(45 212 191 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.text-white\/90{color:#ffffffe6}.underline{text-decoration-line:underline}.accent-cyan-400{accent-color:#22d3ee}.accent-cyan-500{accent-color:#06b6d4}.accent-emerald-400{accent-color:#34d399}.accent-emerald-500{accent-color:#10b981}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-black\/30{--tw-shadow-color: rgb(0 0 0 / .3);--tw-shadow: var(--tw-shadow-colored)}.shadow-black\/40{--tw-shadow-color: rgb(0 0 0 / .4);--tw-shadow: var(--tw-shadow-colored)}.outline{outline-style:solid}.outline-2{outline-width:2px}.outline-cyan-400\/60{outline-color:#22d3ee99}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-amber-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(252 211 77 / var(--tw-ring-opacity))}.ring-emerald-300\/70{--tw-ring-color: rgb(110 231 183 / .7)}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert: invert(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[width\,height\]{transition-property:width,height;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@keyframes batteryTickWarn{0%,49%{background-color:#fffffff2}50%,to{background-color:#ef4444f2}}.battery-tick-warn{animation:batteryTickWarn .4s steps(2,end) infinite}@keyframes batteryUrgentFlash{0%,49%{opacity:1}50%,to{opacity:.25}}.battery-urgent-flash{animation:batteryUrgentFlash .4s steps(2,end) infinite}.no-touch-select{-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none;-webkit-touch-callout:none}.\[clip-path\:circle\(50\%\)\]{clip-path:circle(50%)}.\[writing-mode\:vertical-rl\]{writing-mode:vertical-rl}:root{font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}body{margin:0;min-height:100vh;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}*{scrollbar-width:thin;scrollbar-color:#3b82f6 rgba(255,255,255,.08)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}*::-webkit-scrollbar{width:1px;height:1px}*::-webkit-scrollbar-track{background:#ffffff14}*::-webkit-scrollbar-thumb{background-color:#3b82f6;border-radius:9999px}.ha-hue-slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red);cursor:pointer}.ha-hue-slider:disabled{opacity:.6;cursor:not-allowed}.ha-hue-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:.75rem;height:.75rem;border-radius:9999px;border:1px solid rgba(255,255,255,.7);background:#fff}.ha-hue-slider::-webkit-slider-runnable-track{height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.ha-hue-slider::-moz-range-thumb{width:.75rem;height:.75rem;border-radius:9999px;border:1px solid rgba(255,255,255,.7);background:#fff}.ha-hue-slider::-moz-range-track{height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.placeholder\:text-slate-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.placeholder\:text-slate-400::placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.hover\:-translate-y-0\.5:hover{--tw-translate-y: -.125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-rose-500:hover{--tw-border-opacity: 1;border-color:rgb(244 63 94 / var(--tw-border-opacity))}.hover\:border-sky-500:hover{--tw-border-opacity: 1;border-color:rgb(14 165 233 / var(--tw-border-opacity))}.hover\:bg-amber-400:hover{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity))}.hover\:bg-amber-800:hover{--tw-bg-opacity: 1;background-color:rgb(146 64 14 / var(--tw-bg-opacity))}.hover\:bg-cyan-400:hover{--tw-bg-opacity: 1;background-color:rgb(34 211 238 / var(--tw-bg-opacity))}.hover\:bg-cyan-800:hover{--tw-bg-opacity: 1;background-color:rgb(21 94 117 / var(--tw-bg-opacity))}.hover\:bg-emerald-400:hover{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity))}.hover\:bg-emerald-500:hover{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity))}.hover\:bg-emerald-700:hover{--tw-bg-opacity: 1;background-color:rgb(4 120 87 / var(--tw-bg-opacity))}.hover\:bg-emerald-800:hover{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity))}.hover\:bg-fuchsia-500:hover{--tw-bg-opacity: 1;background-color:rgb(217 70 239 / var(--tw-bg-opacity))}.hover\:bg-indigo-500:hover{--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity))}.hover\:bg-indigo-800:hover{--tw-bg-opacity: 1;background-color:rgb(55 48 163 / var(--tw-bg-opacity))}.hover\:bg-pink-400:hover{--tw-bg-opacity: 1;background-color:rgb(244 114 182 / var(--tw-bg-opacity))}.hover\:bg-red-600:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity))}.hover\:bg-rose-500:hover{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity))}.hover\:bg-rose-800:hover{--tw-bg-opacity: 1;background-color:rgb(159 18 57 / var(--tw-bg-opacity))}.hover\:bg-sky-500:hover{--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity))}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity))}.hover\:bg-slate-600:hover{--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity))}.hover\:bg-slate-800\/80:hover{background-color:#1e293bcc}.hover\:text-blue-500:hover{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.hover\:shadow-xl:hover{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:brightness-110:hover{--tw-brightness: brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-emerald-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(16 185 129 / var(--tw-ring-opacity))}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:outline:focus-visible{outline-style:solid}.focus-visible\:outline-1:focus-visible{outline-width:1px}.focus-visible\:outline-offset-1:focus-visible{outline-offset:1px}.focus-visible\:outline-slate-500:focus-visible{outline-color:#64748b}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-amber-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(252 211 77 / var(--tw-ring-opacity))}.focus-visible\:ring-emerald-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(110 231 183 / var(--tw-ring-opacity))}.focus-visible\:ring-indigo-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(165 180 252 / var(--tw-ring-opacity))}.active\:scale-95:active{--tw-scale-x: .95;--tw-scale-y: .95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:scale-\[0\.99\]:active{--tw-scale-x: .99;--tw-scale-y: .99;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:brightness-125:active{--tw-brightness: brightness(1.25);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.disabled\:hover\:bg-inherit:hover:disabled{background-color:inherit}@media(min-width:640px){.sm\:block{display:block}.sm\:min-h-\[18rem\]{min-height:18rem}.sm\:basis-auto{flex-basis:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:items-center{align-items:center}.sm\:text-2xl{font-size:1.5rem;line-height:2rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}}@media(min-width:768px){.md\:h-full{height:100%}.md\:h-screen{height:100vh}.md\:min-h-0{min-height:0px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-\[minmax\(0\,1\.4fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}.md\:grid-cols-\[minmax\(0\,1fr\)_18rem\]{grid-template-columns:minmax(0,1fr) 18rem}.md\:overflow-hidden{overflow:hidden}.md\:overflow-y-auto{overflow-y:auto}.md\:text-lg{font-size:1.125rem;line-height:1.75rem}}@media(min-width:1024px){.lg\:col-span-2{grid-column:span 2 / span 2}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:grid-cols-\[minmax\(0\,0\.95fr\)_minmax\(0\,1\.05fr\)\]{grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr)}.lg\:grid-cols-\[minmax\(0\,1\.25fr\)_minmax\(0\,0\.9fr\)\]{grid-template-columns:minmax(0,1.25fr) minmax(0,.9fr)}.lg\:grid-cols-\[minmax\(0\,1fr\)_20rem\]{grid-template-columns:minmax(0,1fr) 20rem}}@media(min-width:1280px){.xl\:grid-cols-\[minmax\(0\,1fr\)_minmax\(13rem\,15rem\)\]{grid-template-columns:minmax(0,1fr) minmax(13rem,15rem)}} +*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.panel{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));padding:0;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.panel-section{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(23 23 23 / var(--tw-bg-opacity));padding:0;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.panel-muted{border-radius:.375rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.surface{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(38 38 38 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.surface-muted{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(245 245 245 / var(--tw-text-opacity))}.field-input{border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(82 82 82 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity));padding:.125rem;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.field-input::-moz-placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.field-input::placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.field-input:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(14 165 233 / var(--tw-ring-opacity))}.button-dark{border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(125 211 252 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity));padding:.125rem;font-size:.875rem;line-height:1.25rem;font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.button-dark:hover{--tw-border-opacity: 1;border-color:rgb(14 165 233 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity))}.button-danger{border-radius:.375rem;--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity));padding:.125rem;font-size:.875rem;line-height:1.25rem;font-weight:500;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.button-danger:hover{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity))}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-x-0{left:0;right:0}.bottom-0{bottom:0}.bottom-0\.5{bottom:.125rem}.bottom-1{bottom:.25rem}.bottom-2{bottom:.5rem}.left-0{left:0}.left-0\.5{left:.125rem}.left-1{left:.25rem}.left-1\/2{left:50%}.left-2{left:.5rem}.right-0{right:0}.right-0\.5{right:.125rem}.right-1{right:.25rem}.right-2{right:.5rem}.top-0{top:0}.top-0\.5{top:.125rem}.top-1{top:.25rem}.top-1\/2{top:50%}.top-10{top:2.5rem}.top-6{top:1.5rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[120\]{z-index:120}.order-1{order:1}.order-2{order:2}.col-span-full{grid-column:1 / -1}.m-0{margin:0}.mx-auto{margin-left:auto;margin-right:auto}.-mt-0\.5{margin-top:-.125rem}.mr-0{margin-right:0}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-auto{margin-top:auto}.\!block{display:block!important}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.aspect-\[4\/3\]{aspect-ratio:4/3}.aspect-square{aspect-ratio:1 / 1}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-28{height:7rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-40{height:10rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-64{height:16rem}.h-\[14rem\]{height:14rem}.h-\[2px\]{height:2px}.h-\[3\.5rem\]{height:3.5rem}.h-\[70\%\]{height:70%}.h-\[7rem\]{height:7rem}.h-\[min\(100svh\,32rem\)\]{height:min(100svh,32rem)}.h-\[min\(60svh\,24rem\)\]{height:min(60svh,24rem)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-32{max-height:8rem}.max-h-40{max-height:10rem}.max-h-52{max-height:13rem}.max-h-72{max-height:18rem}.max-h-80{max-height:20rem}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-screen{max-height:100vh}.min-h-0{min-height:0px}.min-h-\[1\.5rem\]{min-height:1.5rem}.min-h-\[14rem\]{min-height:14rem}.min-h-\[16rem\]{min-height:16rem}.min-h-\[3\.5rem\]{min-height:3.5rem}.min-h-\[5rem\]{min-height:5rem}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-1\/2{width:50%}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-\[12\.5rem\]{width:12.5rem}.w-\[12rem\]{width:12rem}.w-\[20rem\]{width:20rem}.w-\[2px\]{width:2px}.w-\[9rem\]{width:9rem}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-\[0\]{min-width:0}.min-w-\[10rem\]{min-width:10rem}.min-w-\[12rem\]{min-width:12rem}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-\[70vw\]{max-width:70vw}.max-w-\[80vw\]{max-width:80vw}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-\[1\.1\]{flex:1.1}.flex-\[1\.22\]{flex:1.22}.flex-\[1_1_12rem\]{flex:1 1 12rem}.shrink-0{flex-shrink:0}.basis-full{flex-basis:100%}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\[minmax\(0\,0\.7fr\)_minmax\(0\,2\.1fr\)_minmax\(0\,0\.7fr\)\]{grid-template-columns:minmax(0,.7fr) minmax(0,2.1fr) minmax(0,.7fr)}.grid-cols-\[minmax\(0\,1\.2fr\)_repeat\(4\,minmax\(0\,1fr\)\)\]{grid-template-columns:minmax(0,1.2fr) repeat(4,minmax(0,1fr))}.grid-cols-\[minmax\(0\,1\.35fr\)_minmax\(0\,0\.95fr\)\]{grid-template-columns:minmax(0,1.35fr) minmax(0,.95fr)}.grid-cols-\[minmax\(0\,1\.3fr\)_minmax\(0\,0\.22fr\)\]{grid-template-columns:minmax(0,1.3fr) minmax(0,.22fr)}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,0\.7fr\)_minmax\(0\,1\.9fr\)_minmax\(0\,0\.7fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,.7fr) minmax(0,1.9fr) minmax(0,.7fr)}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,0\.9fr\)_minmax\(0\,0\.75fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,.9fr) minmax(0,.75fr)}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1\.4fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,1.4fr)}.grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}.grid-rows-\[auto_1fr\]{grid-template-rows:auto 1fr}.grid-rows-\[auto_auto_1fr\]{grid-template-rows:auto auto 1fr}.grid-rows-\[auto_auto_1fr_auto\]{grid-template-rows:auto auto 1fr auto}.grid-rows-\[minmax\(0\,1fr\)_auto\]{grid-template-rows:minmax(0,1fr) auto}.grid-rows-\[minmax\(0\,1fr\)_minmax\(0\,1fr\)_minmax\(0\,1fr\)\]{grid-template-rows:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.content-center{align-content:center}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0px}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.self-start{align-self:flex-start}.self-center{align-self:center}.self-stretch{align-self:stretch}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity))}.border-amber-200\/30{border-color:#fde68a4d}.border-amber-200\/70{border-color:#fde68ab3}.border-amber-300\/70{border-color:#fcd34db3}.border-amber-300\/80{border-color:#fcd34dcc}.border-amber-400\/30{border-color:#fbbf244d}.border-amber-400\/60{border-color:#fbbf2499}.border-amber-600\/60{border-color:#d9770699}.border-amber-700\/60{border-color:#b4530999}.border-blue-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity))}.border-cyan-300{--tw-border-opacity: 1;border-color:rgb(103 232 249 / var(--tw-border-opacity))}.border-cyan-300\/70{border-color:#67e8f9b3}.border-cyan-500\/40{border-color:#06b6d466}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity))}.border-emerald-200\/70{border-color:#a7f3d0b3}.border-emerald-300\/70{border-color:#6ee7b7b3}.border-emerald-400\/60{border-color:#34d39999}.border-emerald-500\/40{border-color:#10b98166}.border-emerald-700{--tw-border-opacity: 1;border-color:rgb(4 120 87 / var(--tw-border-opacity))}.border-emerald-700\/60{border-color:#04785799}.border-fuchsia-300\/70{border-color:#f0abfcb3}.border-indigo-200\/70{border-color:#c7d2feb3}.border-indigo-300\/70{border-color:#a5b4fcb3}.border-indigo-400\/30{border-color:#818cf84d}.border-indigo-700{--tw-border-opacity: 1;border-color:rgb(67 56 202 / var(--tw-border-opacity))}.border-indigo-700\/60{border-color:#4338ca99}.border-pink-200{--tw-border-opacity: 1;border-color:rgb(251 207 232 / var(--tw-border-opacity))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity))}.border-red-400\/60{border-color:#f8717199}.border-rose-300{--tw-border-opacity: 1;border-color:rgb(253 164 175 / var(--tw-border-opacity))}.border-rose-800{--tw-border-opacity: 1;border-color:rgb(159 18 57 / var(--tw-border-opacity))}.border-sky-300{--tw-border-opacity: 1;border-color:rgb(125 211 252 / var(--tw-border-opacity))}.border-sky-400\/50{border-color:#38bdf880}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity))}.border-slate-200\/30{border-color:#e2e8f04d}.border-slate-400\/60{border-color:#94a3b899}.border-slate-600{--tw-border-opacity: 1;border-color:rgb(71 85 105 / var(--tw-border-opacity))}.border-slate-600\/40{border-color:#47556966}.border-slate-600\/60{border-color:#47556999}.border-slate-700{--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity))}.border-slate-700\/60{border-color:#33415599}.border-slate-700\/70{border-color:#334155b3}.border-slate-700\/80{border-color:#334155cc}.border-slate-800{--tw-border-opacity: 1;border-color:rgb(30 41 59 / var(--tw-border-opacity))}.border-slate-800\/60{border-color:#1e293b99}.border-transparent{border-color:transparent}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity))}.border-white\/40{border-color:#fff6}.border-white\/60{border-color:#fff9}.bg-amber-100\/95{background-color:#fef3c7f2}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity))}.bg-amber-400\/80{background-color:#fbbf24cc}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity))}.bg-amber-500\/30{background-color:#f59e0b4d}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity))}.bg-amber-600\/70{background-color:#d97706b3}.bg-amber-700\/20{background-color:#b4530933}.bg-amber-700\/30{background-color:#b453094d}.bg-amber-700\/35{background-color:#b4530959}.bg-amber-900{--tw-bg-opacity: 1;background-color:rgb(120 53 15 / var(--tw-bg-opacity))}.bg-amber-900\/40{background-color:#78350f66}.bg-amber-900\/60{background-color:#78350f99}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity))}.bg-black\/20{background-color:#0003}.bg-black\/30{background-color:#0000004d}.bg-black\/40{background-color:#0006}.bg-black\/50{background-color:#00000080}.bg-black\/55{background-color:#0000008c}.bg-black\/60{background-color:#0009}.bg-black\/70{background-color:#000000b3}.bg-black\/75{background-color:#000000bf}.bg-black\/80{background-color:#000c}.bg-black\/85{background-color:#000000d9}.bg-cyan-300\/80{background-color:#67e8f9cc}.bg-cyan-400\/10{background-color:#22d3ee1a}.bg-cyan-500{--tw-bg-opacity: 1;background-color:rgb(6 182 212 / var(--tw-bg-opacity))}.bg-cyan-500\/80{background-color:#06b6d4cc}.bg-cyan-900{--tw-bg-opacity: 1;background-color:rgb(22 78 99 / var(--tw-bg-opacity))}.bg-cyan-900\/45{background-color:#164e6373}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity))}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity))}.bg-emerald-500\/45{background-color:#10b98173}.bg-emerald-500\/80{background-color:#10b981cc}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity))}.bg-emerald-600\/70{background-color:#059669b3}.bg-emerald-700\/20{background-color:#04785733}.bg-emerald-700\/60{background-color:#04785799}.bg-emerald-800{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity))}.bg-emerald-900{--tw-bg-opacity: 1;background-color:rgb(6 78 59 / var(--tw-bg-opacity))}.bg-emerald-900\/15{background-color:#064e3b26}.bg-emerald-900\/60{background-color:#064e3b99}.bg-emerald-900\/80{background-color:#064e3bcc}.bg-fuchsia-200{--tw-bg-opacity: 1;background-color:rgb(245 208 254 / var(--tw-bg-opacity))}.bg-fuchsia-600{--tw-bg-opacity: 1;background-color:rgb(192 38 211 / var(--tw-bg-opacity))}.bg-fuchsia-700{--tw-bg-opacity: 1;background-color:rgb(162 28 175 / var(--tw-bg-opacity))}.bg-fuchsia-800{--tw-bg-opacity: 1;background-color:rgb(134 25 143 / var(--tw-bg-opacity))}.bg-fuchsia-900\/45{background-color:#701a7573}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity))}.bg-indigo-600\/70{background-color:#4f46e5b3}.bg-indigo-900{--tw-bg-opacity: 1;background-color:rgb(49 46 129 / var(--tw-bg-opacity))}.bg-indigo-900\/20{background-color:#312e8133}.bg-indigo-900\/60{background-color:#312e8199}.bg-indigo-950\/90{background-color:#1e1b4be6}.bg-pink-500{--tw-bg-opacity: 1;background-color:rgb(236 72 153 / var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity))}.bg-red-500\/45{background-color:#ef444473}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity))}.bg-red-600\/70{background-color:#dc2626b3}.bg-red-700\/20{background-color:#b91c1c33}.bg-red-700\/60{background-color:#b91c1c99}.bg-red-900\/35{background-color:#7f1d1d59}.bg-red-900\/40{background-color:#7f1d1d66}.bg-red-900\/45{background-color:#7f1d1d73}.bg-red-900\/50{background-color:#7f1d1d80}.bg-rose-600{--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity))}.bg-rose-900\/80{background-color:#881337cc}.bg-sky-600{--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity))}.bg-sky-700\/20{background-color:#0369a133}.bg-slate-500{--tw-bg-opacity: 1;background-color:rgb(100 116 139 / var(--tw-bg-opacity))}.bg-slate-600{--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity))}.bg-slate-700{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}.bg-slate-700\/30{background-color:#3341554d}.bg-slate-700\/60{background-color:#33415599}.bg-slate-700\/70{background-color:#334155b3}.bg-slate-700\/80{background-color:#334155cc}.bg-slate-800{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}.bg-slate-800\/70{background-color:#1e293bb3}.bg-slate-800\/80{background-color:#1e293bcc}.bg-slate-900{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity))}.bg-slate-900\/35{background-color:#0f172a59}.bg-slate-900\/40{background-color:#0f172a66}.bg-slate-900\/70{background-color:#0f172ab3}.bg-slate-950\/80{background-color:#020617cc}.bg-slate-950\/90{background-color:#020617e6}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-white\/10{background-color:#ffffff1a}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity))}.bg-zinc-900{--tw-bg-opacity: 1;background-color:rgb(24 24 27 / var(--tw-bg-opacity))}.bg-zinc-900\/90{background-color:#18181be6}.bg-zinc-950{--tw-bg-opacity: 1;background-color:rgb(9 9 11 / var(--tw-bg-opacity))}.bg-zinc-950\/95{background-color:#09090bf2}.bg-cover{background-size:cover}.fill-slate-200{fill:#e2e8f0}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-4{padding:1rem}.px-0{padding-left:0;padding-right:0}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-\[1px\]{padding-top:1px;padding-bottom:1px}.py-\[2px\]{padding-top:2px;padding-bottom:2px}.pb-0{padding-bottom:0}.pb-1{padding-bottom:.25rem}.pr-0{padding-right:0}.pt-0\.5{padding-top:.125rem}.pt-1{padding-top:.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-\[0\.45rem\]{font-size:.45rem}.text-\[0\.55em\]{font-size:.55em}.text-\[0\.55rem\]{font-size:.55rem}.text-\[0\.5rem\]{font-size:.5rem}.text-\[0\.65rem\]{font-size:.65rem}.text-\[0\.68rem\]{font-size:.68rem}.text-\[0\.6rem\]{font-size:.6rem}.text-\[0\.72rem\]{font-size:.72rem}.text-\[0\.75rem\]{font-size:.75rem}.text-\[0\.7rem\]{font-size:.7rem}.text-\[0\.85rem\]{font-size:.85rem}.text-\[0\.8rem\]{font-size:.8rem}.text-\[1\.1rem\]{font-size:1.1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-none{line-height:1}.leading-normal{line-height:1.5}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-amber-100{--tw-text-opacity: 1;color:rgb(254 243 199 / var(--tw-text-opacity))}.text-amber-200{--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity))}.text-amber-200\/80{color:#fde68acc}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity))}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity))}.text-amber-50{--tw-text-opacity: 1;color:rgb(255 251 235 / var(--tw-text-opacity))}.text-amber-50\/90{color:#fffbebe6}.text-amber-950{--tw-text-opacity: 1;color:rgb(69 26 3 / var(--tw-text-opacity))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity))}.text-cyan-300{--tw-text-opacity: 1;color:rgb(103 232 249 / var(--tw-text-opacity))}.text-cyan-50{--tw-text-opacity: 1;color:rgb(236 254 255 / var(--tw-text-opacity))}.text-emerald-100{--tw-text-opacity: 1;color:rgb(209 250 229 / var(--tw-text-opacity))}.text-emerald-200{--tw-text-opacity: 1;color:rgb(167 243 208 / var(--tw-text-opacity))}.text-emerald-300{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity))}.text-emerald-50{--tw-text-opacity: 1;color:rgb(236 253 245 / var(--tw-text-opacity))}.text-emerald-50\/90{color:#ecfdf5e6}.text-emerald-950{--tw-text-opacity: 1;color:rgb(2 44 34 / var(--tw-text-opacity))}.text-fuchsia-50{--tw-text-opacity: 1;color:rgb(253 244 255 / var(--tw-text-opacity))}.text-fuchsia-900{--tw-text-opacity: 1;color:rgb(112 26 117 / var(--tw-text-opacity))}.text-indigo-100\/80{color:#e0e7ffcc}.text-indigo-200{--tw-text-opacity: 1;color:rgb(199 210 254 / var(--tw-text-opacity))}.text-indigo-50{--tw-text-opacity: 1;color:rgb(238 242 255 / var(--tw-text-opacity))}.text-indigo-50\/90{color:#eef2ffe6}.text-lime-200{--tw-text-opacity: 1;color:rgb(217 249 157 / var(--tw-text-opacity))}.text-lime-300{--tw-text-opacity: 1;color:rgb(190 242 100 / var(--tw-text-opacity))}.text-lime-400{--tw-text-opacity: 1;color:rgb(163 230 53 / var(--tw-text-opacity))}.text-red-100\/90{color:#fee2e2e6}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity))}.text-rose-300{--tw-text-opacity: 1;color:rgb(253 164 175 / var(--tw-text-opacity))}.text-rose-50{--tw-text-opacity: 1;color:rgb(255 241 242 / var(--tw-text-opacity))}.text-sky-200{--tw-text-opacity: 1;color:rgb(186 230 253 / var(--tw-text-opacity))}.text-sky-300{--tw-text-opacity: 1;color:rgb(125 211 252 / var(--tw-text-opacity))}.text-slate-100{--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}.text-slate-200{--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity))}.text-slate-300{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.text-slate-400\/60{color:#94a3b899}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity))}.text-teal-400{--tw-text-opacity: 1;color:rgb(45 212 191 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.text-white\/90{color:#ffffffe6}.underline{text-decoration-line:underline}.accent-cyan-400{accent-color:#22d3ee}.accent-cyan-500{accent-color:#06b6d4}.accent-emerald-400{accent-color:#34d399}.accent-emerald-500{accent-color:#10b981}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-black\/30{--tw-shadow-color: rgb(0 0 0 / .3);--tw-shadow: var(--tw-shadow-colored)}.shadow-black\/40{--tw-shadow-color: rgb(0 0 0 / .4);--tw-shadow: var(--tw-shadow-colored)}.outline{outline-style:solid}.outline-2{outline-width:2px}.outline-cyan-400\/60{outline-color:#22d3ee99}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-amber-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(252 211 77 / var(--tw-ring-opacity))}.ring-emerald-300\/70{--tw-ring-color: rgb(110 231 183 / .7)}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert: invert(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[width\,height\]{transition-property:width,height;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@keyframes batteryTickWarn{0%,49%{background-color:#fffffff2}50%,to{background-color:#ef4444f2}}.battery-tick-warn{animation:batteryTickWarn .4s steps(2,end) infinite}@keyframes batteryUrgentFlash{0%,49%{opacity:1}50%,to{opacity:.25}}.battery-urgent-flash{animation:batteryUrgentFlash .4s steps(2,end) infinite}.no-touch-select{-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none;-webkit-touch-callout:none}.\[clip-path\:circle\(50\%\)\]{clip-path:circle(50%)}.\[writing-mode\:vertical-rl\]{writing-mode:vertical-rl}:root{font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}body{margin:0;min-height:100vh;--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity))}*{scrollbar-width:thin;scrollbar-color:#3b82f6 rgba(255,255,255,.08)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}*::-webkit-scrollbar{width:1px;height:1px}*::-webkit-scrollbar-track{background:#ffffff14}*::-webkit-scrollbar-thumb{background-color:#3b82f6;border-radius:9999px}.ha-hue-slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red);cursor:pointer}.ha-hue-slider:disabled{opacity:.6;cursor:not-allowed}.ha-hue-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:.75rem;height:.75rem;border-radius:9999px;border:1px solid rgba(255,255,255,.7);background:#fff}.ha-hue-slider::-webkit-slider-runnable-track{height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.ha-hue-slider::-moz-range-thumb{width:.75rem;height:.75rem;border-radius:9999px;border:1px solid rgba(255,255,255,.7);background:#fff}.ha-hue-slider::-moz-range-track{height:.45rem;border-radius:9999px;background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.placeholder\:text-slate-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.placeholder\:text-slate-400::placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity))}.hover\:-translate-y-0\.5:hover{--tw-translate-y: -.125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-rose-500:hover{--tw-border-opacity: 1;border-color:rgb(244 63 94 / var(--tw-border-opacity))}.hover\:border-sky-500:hover{--tw-border-opacity: 1;border-color:rgb(14 165 233 / var(--tw-border-opacity))}.hover\:bg-amber-400:hover{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity))}.hover\:bg-amber-800:hover{--tw-bg-opacity: 1;background-color:rgb(146 64 14 / var(--tw-bg-opacity))}.hover\:bg-cyan-400:hover{--tw-bg-opacity: 1;background-color:rgb(34 211 238 / var(--tw-bg-opacity))}.hover\:bg-cyan-800:hover{--tw-bg-opacity: 1;background-color:rgb(21 94 117 / var(--tw-bg-opacity))}.hover\:bg-emerald-400:hover{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity))}.hover\:bg-emerald-500:hover{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity))}.hover\:bg-emerald-700:hover{--tw-bg-opacity: 1;background-color:rgb(4 120 87 / var(--tw-bg-opacity))}.hover\:bg-emerald-800:hover{--tw-bg-opacity: 1;background-color:rgb(6 95 70 / var(--tw-bg-opacity))}.hover\:bg-fuchsia-500:hover{--tw-bg-opacity: 1;background-color:rgb(217 70 239 / var(--tw-bg-opacity))}.hover\:bg-indigo-500:hover{--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity))}.hover\:bg-indigo-800:hover{--tw-bg-opacity: 1;background-color:rgb(55 48 163 / var(--tw-bg-opacity))}.hover\:bg-pink-400:hover{--tw-bg-opacity: 1;background-color:rgb(244 114 182 / var(--tw-bg-opacity))}.hover\:bg-red-600:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity))}.hover\:bg-rose-500:hover{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity))}.hover\:bg-rose-800:hover{--tw-bg-opacity: 1;background-color:rgb(159 18 57 / var(--tw-bg-opacity))}.hover\:bg-sky-500:hover{--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity))}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity))}.hover\:bg-slate-600:hover{--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity))}.hover\:bg-zinc-900:hover{--tw-bg-opacity: 1;background-color:rgb(24 24 27 / var(--tw-bg-opacity))}.hover\:text-blue-500:hover{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.hover\:shadow-xl:hover{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:brightness-110:hover{--tw-brightness: brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-emerald-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(16 185 129 / var(--tw-ring-opacity))}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:outline:focus-visible{outline-style:solid}.focus-visible\:outline-1:focus-visible{outline-width:1px}.focus-visible\:outline-offset-1:focus-visible{outline-offset:1px}.focus-visible\:outline-slate-500:focus-visible{outline-color:#64748b}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-amber-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(252 211 77 / var(--tw-ring-opacity))}.focus-visible\:ring-emerald-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(110 231 183 / var(--tw-ring-opacity))}.focus-visible\:ring-indigo-300:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(165 180 252 / var(--tw-ring-opacity))}.active\:scale-95:active{--tw-scale-x: .95;--tw-scale-y: .95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:scale-\[0\.99\]:active{--tw-scale-x: .99;--tw-scale-y: .99;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:brightness-125:active{--tw-brightness: brightness(1.25);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.disabled\:hover\:bg-inherit:hover:disabled{background-color:inherit}@media(min-width:640px){.sm\:block{display:block}.sm\:min-h-\[18rem\]{min-height:18rem}.sm\:basis-auto{flex-basis:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:items-center{align-items:center}.sm\:text-2xl{font-size:1.5rem;line-height:2rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}}@media(min-width:768px){.md\:h-full{height:100%}.md\:h-screen{height:100vh}.md\:min-h-0{min-height:0px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-\[minmax\(0\,1\.4fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}.md\:grid-cols-\[minmax\(0\,1fr\)_18rem\]{grid-template-columns:minmax(0,1fr) 18rem}.md\:overflow-hidden{overflow:hidden}.md\:overflow-y-auto{overflow-y:auto}.md\:text-lg{font-size:1.125rem;line-height:1.75rem}}@media(min-width:1024px){.lg\:col-span-2{grid-column:span 2 / span 2}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:grid-cols-\[minmax\(0\,0\.95fr\)_minmax\(0\,1\.05fr\)\]{grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr)}.lg\:grid-cols-\[minmax\(0\,1\.25fr\)_minmax\(0\,0\.9fr\)\]{grid-template-columns:minmax(0,1.25fr) minmax(0,.9fr)}.lg\:grid-cols-\[minmax\(0\,1fr\)_20rem\]{grid-template-columns:minmax(0,1fr) 20rem}}@media(min-width:1280px){.xl\:grid-cols-\[minmax\(0\,1fr\)_minmax\(13rem\,15rem\)\]{grid-template-columns:minmax(0,1fr) minmax(13rem,15rem)}} diff --git a/server/public/index.html b/server/public/index.html index bdea1018..6f54ceee 100644 --- a/server/public/index.html +++ b/server/public/index.html @@ -11,8 +11,8 @@ Multi Roomba Rover - - + +
diff --git a/webui/src/components/FloatingFullscreenButton/index.jsx b/webui/src/components/FloatingFullscreenButton/index.jsx index 7e504213..425b2c13 100644 --- a/webui/src/components/FloatingFullscreenButton/index.jsx +++ b/webui/src/components/FloatingFullscreenButton/index.jsx @@ -7,7 +7,7 @@ export default function FloatingFullscreenButton({ side = 'right', onClick }) {