cubefarm 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,91 +1,94 @@
1
- # ✻ cubefarm
2
-
3
- A cartoon 3D office where a team of Claude Code agents works through your GitHub issues. You walk the floors, look over their shoulders and watch their pull requests get tested and merged.
4
-
5
- ## Get started
6
-
7
- ```bash
8
- npx cubefarm
9
- ```
10
-
11
- That's it. cubefarm checks your machine, starts the office and opens it in your browser. The first time, `npx` asks whether to install cubefarm: say yes.
12
-
13
- ### What you need
14
-
15
- - **Node.js 22 or newer**: [nodejs.org](https://nodejs.org)
16
- - **git**
17
- - **The GitHub CLI**, signed in: install it from [cli.github.com](https://cli.github.com), then run `gh auth login`
18
- - **A Claude subscription**: sign in once with `npx cubefarm login`. Your agents use this login. You don't need to install Claude Code, because cubefarm brings its own.
19
-
20
- Not sure you're ready? `npx cubefarm doctor` checks all four.
21
-
22
- ### Just want to look around?
23
-
24
- ```bash
25
- npx cubefarm --demo
26
- ```
27
-
28
- Demo mode fakes GitHub and the agents, so it costs nothing and changes nothing.
29
-
30
- ## Your first five minutes
31
-
32
- 1. **Set up your company.** A short wizard asks your name, names your company and introduces your CEO.
33
- 2. **Move in a project.** Pick one of your project folders or a GitHub repo, or start a new one. It gets its own floor. Every project needs to be on GitHub, because issues and pull requests are how the team works.
34
- 3. **Let the CEO plan.** The CEO studies the project, writes its QA checklist, plans the work as GitHub issues and proposes who to hire. Press `P` for your phone to chat with them and approve hires.
35
- 4. **Watch the work.** Developers pick up issues and open pull requests. QA testers review and test each one in a real browser, then post a report with screenshots. With auto-merge on, a pull request merges itself once QA passes and GitHub's checks are green.
36
-
37
- ## What's in the office
38
-
39
- - **Floors**: one per project. Ride the elevator between them.
40
- - **Desks**: walk up behind an agent to watch their monitor. It streams their real terminal, and shows a live browser when they test the UI.
41
- - **The QA lab**: every floor has at least one QA tester.
42
- - **The whiteboard**: the Kanban board, from backlog to merged.
43
- - **The lobby**: the manager's office, where you connect projects, hire, file issues and change settings, and the CEO's corner office.
44
-
45
- ## Controls
46
-
47
- | Key | Action |
48
- | --- | --- |
49
- | `W A S D` / arrows | walk |
50
- | `Shift` | run |
51
- | mouse | look around (click the view first) |
52
- | `E` | use what you're looking at: a desk, the whiteboard, the elevator, the manager's computer |
53
- | `P` | your phone |
54
- | `H` | help |
55
- | `Esc` | let go of the mouse, or close a panel |
56
-
57
- ## Commands
58
-
59
- | Command | What it does |
60
- | --- | --- |
61
- | `npx cubefarm` | start the office and open it in your browser |
62
- | `npx cubefarm login` | sign in to Claude |
63
- | `npx cubefarm doctor` | check that your machine is ready |
64
- | `npx cubefarm --demo` | fake GitHub and fake agents |
65
- | `npx cubefarm --port 4400` | use another port (the default is 4317) |
66
- | `npx cubefarm --no-open` | don't open the browser |
67
-
68
- ## Updating
69
-
70
- `npx` keeps using the version it downloaded first. When a newer one is out, cubefarm tells you as it starts. To update:
71
-
72
- ```bash
73
- npx cubefarm@latest
74
- ```
75
-
76
- Prefer a permanent install? Run `npm install -g cubefarm`, then start it with `cubefarm`.
77
-
78
- ## Good to know
79
-
80
- - **It runs on your Claude subscription.** Every agent draws on the same usage limits. To cap how many work at once, set a session limit in the manager's console.
81
- - **Agents work on your machine.** By default they can only edit files in their own copy of the repo, can't push to your main branch and can't merge. The office merges, after QA.
82
- - **Your office lives in `~/.cubefarm`**: settings, clones of your repos and one working copy per agent. Set `SWARM_HOME` to use another folder.
83
-
84
- ## Learn more
85
-
86
- - [How it works](docs/how-it-works.md): the life of an issue, QA, auto-merge, models and usage, the safety model and floor previews
87
- - [Contributing](CONTRIBUTING.md): run it from source, tests, architecture and publishing
88
-
89
- ## License
90
-
91
- [MIT](LICENSE)
1
+ # ✻ cubefarm
2
+
3
+ A cartoon 3D office where a team of AI coding agents works through your GitHub issues. You walk the floors, look over their shoulders and watch their pull requests get tested and merged.
4
+
5
+ ## Get started
6
+
7
+ ```bash
8
+ npx cubefarm
9
+ ```
10
+
11
+ That's it. cubefarm checks your machine, starts the office and opens it in your browser. The first time, `npx` asks whether to install cubefarm: say yes.
12
+
13
+ ### What you need
14
+
15
+ - **Node.js 22 or newer**: [nodejs.org](https://nodejs.org)
16
+ - **git**
17
+ - **The GitHub CLI**, signed in: install it from [cli.github.com](https://cli.github.com), then run `gh auth login`
18
+ - **A coding agent subscription**: cubefarm brings Claude Code, the default agent and the one your CEO runs: sign in once with `npx cubefarm login`. You don't need to install it. Agents can also run Codex or OpenCode, if you have them installed and signed in.
19
+ - **Google Chrome**, for agents that test your app in a browser.
20
+
21
+ It runs on Windows, macOS and Linux. Not sure you're ready? `npx cubefarm doctor` checks all of it.
22
+
23
+ ### Just want to look around?
24
+
25
+ ```bash
26
+ npx cubefarm --demo
27
+ ```
28
+
29
+ Demo mode fakes GitHub and the agents, so it costs nothing and changes nothing.
30
+
31
+ ## Your first five minutes
32
+
33
+ 1. **Set up your company.** A short wizard asks your name, names your company and introduces your CEO.
34
+ 2. **Move in a project.** Pick one of your project folders or a GitHub repo, or start a new one. It gets its own floor. Every project needs to be on GitHub, because issues and pull requests are how the team works.
35
+ 3. **Let the CEO plan.** The CEO studies the project, writes its QA checklist, plans the work as GitHub issues and proposes who to hire. Press `P` for your phone to chat with them and approve hires.
36
+ 4. **Watch the work.** Developers pick up issues and open pull requests. QA testers review and test each one in a real browser, then post a report with screenshots. With auto-merge on, a pull request merges itself once QA passes and GitHub's checks are green.
37
+
38
+ ## What's in the office
39
+
40
+ - **Floors**: one per project. Ride the elevator between them.
41
+ - **Desks**: walk up behind an agent to watch their monitor. Open it to see their real terminal: every agent is an actual coding agent running on your machine, and you can type into it. It also shows a live browser when they test the UI. Pick the coding agent, model and effort for the whole team or per agent.
42
+ - **The QA lab**: every floor has at least one QA tester.
43
+ - **The whiteboard**: the Kanban board, from backlog to merged.
44
+ - **The lobby**: the manager's office, where you connect projects, hire, file issues and change settings, and the CEO's corner office.
45
+
46
+ ## Controls
47
+
48
+ | Key | Action |
49
+ | --- | --- |
50
+ | `W A S D` / arrows | walk |
51
+ | `Shift` | run |
52
+ | mouse | look around (click the view first) |
53
+ | `E` | use what you're looking at: a desk, the whiteboard, the elevator, the manager's computer |
54
+ | `P` | your phone |
55
+ | `H` | help |
56
+ | `Esc` | let go of the mouse, or close a panel |
57
+
58
+ ## Commands
59
+
60
+ | Command | What it does |
61
+ | --- | --- |
62
+ | `npx cubefarm` | start the office and open it in your browser |
63
+ | `npx cubefarm login` | sign in to Claude Code, the built-in coding agent |
64
+ | `npx cubefarm doctor` | check that your machine is ready |
65
+ | `npx cubefarm --demo` | fake GitHub and fake agents |
66
+ | `npx cubefarm --port 4400` | use another port (the default is 4317) |
67
+ | `npx cubefarm --no-open` | don't open the browser |
68
+
69
+ ## Updating
70
+
71
+ `npx` keeps using the version it downloaded first. When a newer one is out, cubefarm tells you as it starts. To update:
72
+
73
+ ```bash
74
+ npx cubefarm@latest
75
+ ```
76
+
77
+ Prefer a permanent install? Run `npm install -g cubefarm`, then start it with `cubefarm`.
78
+
79
+ Running it from a clone of this repo (`npm start`)? Then the office updates itself from GitHub once its agents are done: see [Updating the office](docs/how-it-works.md#updating-the-office).
80
+
81
+ ## Good to know
82
+
83
+ - **It runs on your coding agents' subscriptions.** Agents on the same coding agent draw on the same usage limits. To cap how many work at once, set a session limit in the manager's console.
84
+ - **Agents work on your machine, like your own coding agents**: with your skills, MCP servers and settings, each in its own copy of the repo. They can't push to your main branch or merge: the office merges, after QA.
85
+ - **Your office lives in `~/.cubefarm`**: settings, clones of your repos and one working copy per agent. Set `SWARM_HOME` to use another folder.
86
+
87
+ ## Learn more
88
+
89
+ - [How it works](docs/how-it-works.md): the life of an issue, QA, auto-merge, models and usage, the safety model and floor previews
90
+ - [Contributing](CONTRIBUTING.md): run it from source, tests, architecture and publishing
91
+
92
+ ## License
93
+
94
+ [MIT](LICENSE)
package/bin/cubefarm.js CHANGED
@@ -4,6 +4,7 @@ import { spawn, spawnSync } from 'node:child_process';
4
4
  import fs from 'node:fs';
5
5
  import { createRequire } from 'node:module';
6
6
  import net from 'node:net';
7
+ import os from 'node:os';
7
8
  import path from 'node:path';
8
9
  import { fileURLToPath, pathToFileURL } from 'node:url';
9
10
  import { parseArgs } from 'node:util';
@@ -13,11 +14,11 @@ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
13
14
  const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
14
15
 
15
16
  const HELP = `
16
- cubefarm ${pkg.version}: a cartoon 3D office where a team of Claude Code agents works through your GitHub issues.
17
+ cubefarm ${pkg.version}: a cartoon 3D office where a team of AI coding agents works through your GitHub issues.
17
18
 
18
19
  Usage
19
20
  npx cubefarm start the office and open it in your browser
20
- npx cubefarm login sign in to Claude with your subscription
21
+ npx cubefarm login sign in to Claude Code, the built-in coding agent
21
22
  npx cubefarm doctor check that this machine is ready
22
23
 
23
24
  Options
@@ -132,9 +133,22 @@ function checks() {
132
133
  const ok = status?.loggedIn === true;
133
134
  out.push({ name: 'Claude', ok, detail: ok ? `signed in${status.subscriptionType ? ` (${status.subscriptionType})` : ''}` : 'not signed in', fix: 'run: npx cubefarm login' });
134
135
  }
136
+
137
+ // Agents test in a browser through Playwright, which drives Google Chrome by default.
138
+ const chrome = chromePaths().some((p) => fs.existsSync(p));
139
+ out.push({ name: 'Chrome', ok: chrome, detail: chrome ? 'for browser testing' : 'not found', fix: 'install Google Chrome so agents can test in a browser' });
135
140
  return out;
136
141
  }
137
142
 
143
+ function chromePaths() {
144
+ const env = process.env;
145
+ if (process.platform === 'win32') {
146
+ return [env.PROGRAMFILES, env['PROGRAMFILES(X86)'], env.LOCALAPPDATA].filter(Boolean).map((d) => path.join(d, 'Google', 'Chrome', 'Application', 'chrome.exe'));
147
+ }
148
+ if (process.platform === 'darwin') return ['/Applications/Google Chrome.app', path.join(os.homedir(), 'Applications', 'Google Chrome.app')];
149
+ return ['/opt/google/chrome/chrome', '/usr/bin/google-chrome', '/usr/bin/google-chrome-stable'];
150
+ }
151
+
138
152
  const printCheck = (c) => console.log(` ${c.ok ? green('✓') : red('✗')} ${c.name.padEnd(12)} ${c.detail ? dim(c.detail) : ''}${c.ok ? '' : ` → ${c.fix}`}`);
139
153
 
140
154
  // ---------- helpers ----------
@@ -185,7 +199,8 @@ const newer = (a, b) => {
185
199
  };
186
200
 
187
201
  async function checkForUpdate() {
188
- if (process.env.CI) return;
202
+ // A checkout's `npm start` runs this under scripts/office.mjs, which updates the office from its origin instead.
203
+ if (process.env.CI || process.env.SWARM_LAUNCHER === '1') return;
189
204
  try {
190
205
  const res = await fetch(`https://registry.npmjs.org/${pkg.name}/latest`, { signal: AbortSignal.timeout(4000) });
191
206
  const { version } = await res.json();
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/rapier-CEtMYVKP.js","assets/index-CDs_MaRq.js","assets/index-BU33ZUhQ.css"])))=>i.map(i=>d[i]);
2
+ import{$ as e,A as t,B as n,C as r,Ct as i,D as a,E as o,Et as s,F as c,G as l,H as u,I as d,J as f,K as p,L as m,M as h,N as g,O as _,P as v,Q as y,R as b,S as x,St as S,T as C,U as w,V as T,W as E,X as ee,Y as te,Z as ne,_ as D,_t as re,a as ie,at as ae,b as O,bt as oe,c as se,ct as k,d as ce,dt as le,et as ue,f as de,ft as fe,g as pe,gt as me,h as he,ht as ge,i as _e,it as ve,j as ye,k as be,l as xe,lt as Se,m as Ce,mt as we,n as Te,nt as Ee,o as De,ot as Oe,p as ke,pt as Ae,q as je,r as Me,rt as Ne,s as Pe,st as Fe,t as Ie,tt as A,u as Le,ut as Re,v as ze,vt as Be,w as Ve,wt as He,x as Ue,xt as We,y as Ge,yt as Ke,z as qe}from"./index-CDs_MaRq.js";import{a as Je,i as Ye,n as Xe,r as Ze,t as Qe}from"./rapier-CEtMYVKP.js";var j=s(He());function $e(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function et(e){var t=$e(e,`string`);return typeof t==`symbol`?t:t+``}function tt(e,t,n){return(t=et(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function nt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function M(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?nt(Object(n),!0).forEach(function(t){tt(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):nt(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}var rt=new Ke;new fe;var it=new i;new Be;var N=new ge,P=new i,F=new Ke,at=new i,ot=e=>{let[t,n,r]=e;return new i(t,n,r)},st=({x:e,y:t,z:n,w:r})=>rt.set(e,t,n,r),ct=e=>{if(Array.isArray(e))return new Ye(e[0],e[1],e[2]);if(typeof e==`number`)return new Ye(e,e,e);{let t=e;return new Ye(t.x,t.y,t.z)}},lt={fixed:1,dynamic:0,kinematicPosition:2,kinematicVelocity:3},ut=e=>lt[e],dt=(e,t)=>{let n=Array.from(e);for(let r=0;r<e.length/3;r++)n[r*3]*=t.x,n[r*3+1]*=t.y,n[r*3+2]*=t.z;return n},ft=e=>e?e instanceof Ke?[e.x,e.y,e.z,e.w]:e instanceof i||e instanceof fe?[e.x,e.y,e.z]:Array.isArray(e)?e:[e]:[0];function I(e){let t=(0,j.useRef)(void 0);return t.current===void 0&&(t.current={value:typeof e==`function`?e():e}),t.current.value}var pt=e=>{let t=(0,j.useRef)(e),n=(0,j.useRef)(0),r=(0,j.useRef)(0);(0,j.useEffect)(()=>{t.current=e},[e]),(0,j.useEffect)(()=>{let e=()=>{let i=performance.now(),a=i-r.current;n.current=requestAnimationFrame(e),t.current(a/1e3),r.current=i};return n.current=requestAnimationFrame(e),()=>cancelAnimationFrame(n.current)},[])},mt=({onStep:e,updatePriority:t})=>(A((t,n)=>{e(n)},t),null),ht=({onStep:e})=>(pt(t=>{e(t)}),null),gt=(0,j.memo)(({onStep:e,type:t,updatePriority:n})=>t===`independent`?j.createElement(ht,{onStep:e}):j.createElement(mt,{onStep:e,updatePriority:n}));function _t(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function vt(e,t){if(e==null)return{};var n,r,i=_t(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var yt=[`mass`,`linearDamping`,`angularDamping`,`type`,`onCollisionEnter`,`onCollisionExit`,`onIntersectionEnter`,`onIntersectionExit`,`onContactForce`,`children`,`canSleep`,`ccd`,`gravityScale`,`softCcdPrediction`,`ref`],bt=(e,t,n)=>{let r=t.slice();if(e===`heightfield`){let e=r[3];return e.x*=n.x,e.x*=n.y,e.x*=n.z,r}if(e===`trimesh`||e===`convexHull`)return r[0]=dt(r[0],n),r;let i=[n.x,n.y,n.z,n.x,n.x];return r.map((e,t)=>i[t]*e)},xt=(e,t,n,r)=>{let i=bt(e.shape,e.args,n),a=Ze[e.shape](...i);return t.createCollider(a,r?.())},St=[`shape`,`args`],Ct="Please pick ONLY ONE of the `density`, `mass` and `massProperties` options.",wt=(e,t)=>{if(t.density!==void 0){if(t.mass!==void 0||t.massProperties!==void 0)throw Error(Ct);e.setDensity(t.density);return}if(t.mass!==void 0){if(t.massProperties!==void 0)throw Error(Ct);e.setMass(t.mass);return}t.massProperties!==void 0&&e.setMassProperties(t.massProperties.mass,t.massProperties.centerOfMass,t.massProperties.principalAngularInertia,t.massProperties.angularInertiaLocalFrame)},Tt={sensor:(e,t)=>{e.setSensor(t)},collisionGroups:(e,t)=>{e.setCollisionGroups(t)},solverGroups:(e,t)=>{e.setSolverGroups(t)},friction:(e,t)=>{e.setFriction(t)},frictionCombineRule:(e,t)=>{e.setFrictionCombineRule(t)},restitution:(e,t)=>{e.setRestitution(t)},restitutionCombineRule:(e,t)=>{e.setRestitutionCombineRule(t)},activeCollisionTypes:(e,t)=>{e.setActiveCollisionTypes(t)},contactSkin:(e,t)=>{e.setContactSkin(t)},quaternion:()=>{},position:()=>{},rotation:()=>{},scale:()=>{}},Et=Object.keys(Tt),Dt=(e,t,n)=>{let r=n.get(e.handle);if(r){let n=r.object.parent.getWorldScale(it),i=r.worldParent?.matrixWorld.clone().invert();r.object.updateWorldMatrix(!0,!1),N.copy(r.object.matrixWorld),i&&N.premultiply(i),N.decompose(P,F,at),e.parent()?(e.setTranslationWrtParent({x:P.x*n.x,y:P.y*n.y,z:P.z*n.z}),e.setRotationWrtParent(F)):(e.setTranslation({x:P.x*n.x,y:P.y*n.y,z:P.z*n.z}),e.setRotation(F)),Et.forEach(n=>{if(n in t){let r=t[n];Tt[n](e,r,t)}}),wt(e,t)}},Ot=(e,t,n)=>{let r=(0,j.useMemo)(()=>Et.flatMap(e=>ft(t[e])),[t]);(0,j.useEffect)(()=>{Dt(e(),t,n)},[...r,e])},kt=e=>{let t=!1;return e.traverseAncestors(e=>{e.userData.r3RapierType===`MeshCollider`&&(t=!0)}),t},At=(e,t,n)=>({collider:e,worldParent:n||void 0,object:t}),jt={cuboid:`cuboid`,ball:`ball`,hull:`convexHull`,trimesh:`trimesh`},Mt=({object:e,ignoreMeshColliders:t=!0,options:n})=>{let r=[];e.updateWorldMatrix(!0,!1);let i=e.matrixWorld.clone().invert(),a=e=>{if(`isMesh`in e){if(t&&kt(e))return;let a=e.getWorldScale(at),o=jt[n.colliders||`cuboid`];e.updateWorldMatrix(!0,!1),N.copy(e.matrixWorld).premultiply(i).decompose(P,F,at);let s=new fe().setFromQuaternion(F,`XYZ`),{geometry:c}=e,{args:l,offset:u}=Nt(c,n.colliders||`cuboid`),d=M(M({},It(n)),{},{args:l,shape:o,rotation:[s.x,s.y,s.z],position:[P.x+u.x*a.x,P.y+u.y*a.y,P.z+u.z*a.z],scale:[a.x,a.y,a.z]});r.push(d)}};return n.includeInvisible?e.traverse(a):e.traverseVisible(a),r},Nt=(e,t)=>{switch(t){case`cuboid`:{e.computeBoundingBox();let{boundingBox:t}=e,n=t.getSize(new i);return{args:[n.x/2,n.y/2,n.z/2],offset:t.getCenter(new i)}}case`ball`:{e.computeBoundingSphere();let{boundingSphere:t}=e;return{args:[t.radius],offset:t.center}}case`trimesh`:{let t=e.index?e.clone():ue(e);return{args:[t.attributes.position.array,t.index?.array],offset:new i}}case`hull`:return{args:[e.clone().attributes.position.array],offset:new i}}return{args:[],offset:new i}},Pt=e=>({collision:!!(e!=null&&e.onCollisionEnter||e!=null&&e.onCollisionExit||e!=null&&e.onIntersectionEnter||e!=null&&e.onIntersectionExit),contactForce:!!(e!=null&&e.onContactForce)}),Ft=(e,t,n,r={})=>{let{onCollisionEnter:i,onCollisionExit:a,onIntersectionEnter:o,onIntersectionExit:s,onContactForce:c}=t;(0,j.useEffect)(()=>{let l=e();if(l){let{collision:e,contactForce:u}=Pt(t),d=e||r.collision,f=u||r.contactForce;d&&f?l.setActiveEvents(Qe.COLLISION_EVENTS|Qe.CONTACT_FORCE_EVENTS):d?l.setActiveEvents(Qe.COLLISION_EVENTS):f&&l.setActiveEvents(Qe.CONTACT_FORCE_EVENTS),n.set(l.handle,{onCollisionEnter:i,onCollisionExit:a,onIntersectionEnter:o,onIntersectionExit:s,onContactForce:c})}return()=>{l&&n.delete(l.handle)}},[i,a,o,s,c,r])},It=(e={})=>vt(e,yt),Lt=e=>{let t=(0,j.useRef)(e);return(0,j.useEffect)(()=>{t.current=e},[e]),t},L=()=>{let e=(0,j.useContext)(Ut);if(!e)throw Error(`react-three-rapier: useRapier must be used within <Physics />!`);return e},Rt=e=>{let{beforeStepCallbacks:t}=L(),n=Lt(e);(0,j.useEffect)(()=>(t.add(n),()=>{t.delete(n)}),[])},zt=e=>{let{afterStepCallbacks:t}=L(),n=Lt(e);(0,j.useEffect)(()=>(t.add(n),()=>{t.delete(n)}),[])},Bt=(e,t,n=!0)=>{let[r,i]=(0,j.useState)([]);return(0,j.useEffect)(()=>{e.current&&t.colliders!==!1&&i(Mt({object:e.current,options:t,ignoreMeshColliders:n}))},[t.colliders]),r},Vt=(0,j.memo)(()=>{let{world:e}=L(),t=(0,j.useRef)(null);return A(()=>{let n=t.current;if(!n)return;let r=e.debugRender(),i=new Oe;i.setAttribute(`position`,new ae(r.vertices,3)),i.setAttribute(`color`,new ae(r.colors,4)),n.geometry.dispose(),n.geometry=i}),j.createElement(`group`,null,j.createElement(`lineSegments`,{ref:t,frustumCulled:!1},j.createElement(`lineBasicMaterial`,{color:16777215,vertexColors:!0}),j.createElement(`bufferGeometry`,null)))}),Ht=e=>{let t;return{proxy:new Proxy({},{get(n,r){return t||=e(),Reflect.get(t,r)},set(n,r,i){return t||=e(),Reflect.set(t,r,i)}}),reset:()=>{t=void 0},set:e=>{t=e}}},Ut=(0,j.createContext)(void 0),Wt=(e,t)=>({target:{rigidBody:e.rigidBody.object,collider:e.collider.object,colliderObject:e.collider.state?.object,rigidBodyObject:e.rigidBody.state?.object},other:{rigidBody:t.rigidBody.object,collider:t.collider.object,colliderObject:t.collider.state?.object,rigidBodyObject:t.rigidBody.state?.object},rigidBody:t.rigidBody.object,collider:t.collider.object,colliderObject:t.collider.state?.object,rigidBodyObject:t.rigidBody.state?.object}),Gt=async()=>{let e=await y(()=>import(`./rapier-CEtMYVKP.js`).then(e=>e.o),__vite__mapDeps([0,1,2]));return await e.init(),e},Kt=e=>{let{colliders:t=`cuboid`,children:n,timeStep:r=1/60,paused:i=!1,interpolate:a=!0,updatePriority:o,updateLoop:s=`follow`,debug:c=!1,gravity:l=[0,-9.81,0],allowedLinearError:u=.001,predictionDistance:d=.002,numSolverIterations:f=4,numInternalPgsIterations:p=1,minIslandSize:m=128,maxCcdSubsteps:h=1,contactNaturalFrequency:g=30,lengthUnit:_=1}=e,v=Ne(Gt,[`@react-thee/rapier`,Gt]),{invalidate:y}=Ee(),b=I(()=>new Map),x=I(()=>new Map),S=I(()=>new Map),C=I(()=>new Map),w=I(()=>new Xe(!1)),T=I(()=>new Set),E=I(()=>new Set),ee=I(()=>({filterContactPair:(...e)=>{for(let t of T){let n=t.current(...e);if(n!==null)return n}return null},filterIntersectionPair:(...e)=>{for(let t of E)if(t.current(...e)===!1)return!1;return!0}})),te=I(()=>new Set),ne=I(()=>new Set),{proxy:D,reset:re,set:ie}=I(()=>Ht(()=>new v.World(ot(l))));(0,j.useEffect)(()=>()=>{D.free(),re()},[]),(0,j.useEffect)(()=>{D.gravity=ct(l),D.integrationParameters.numSolverIterations=f,D.integrationParameters.numInternalPgsIterations=p,D.integrationParameters.normalizedAllowedLinearError=u,D.integrationParameters.minIslandSize=m,D.integrationParameters.maxCcdSubsteps=h,D.integrationParameters.normalizedPredictionDistance=d,D.lengthUnit=_,D.integrationParameters.contact_natural_frequency=g},[D,...l,f,p,u,m,h,d,_,g]);let ae=(0,j.useCallback)(e=>{let t=D.getCollider(e),n=C.get(e),r=x.get(e),i=t?.parent()?.handle,a=i===void 0?void 0:D.getRigidBody(i),o=a&&i!==void 0?S.get(i):void 0,s=i===void 0?void 0:b.get(i);return{collider:{object:t,events:n,state:r},rigidBody:{object:a,events:o,state:s}}},[]),[O]=(0,j.useState)({previousState:{},accumulator:0}),oe=(0,j.useCallback)(e=>{let t=D,n=r===`vary`,o=we.clamp(e,0,.5),s=e=>{te.forEach(e=>{e.current(t)}),t.timestep=e;let n=T.size>0||E.size>0;t.step(w,n?ee:void 0),ne.forEach(e=>{e.current(t)})};if(n)s(o);else for(O.accumulator+=o;O.accumulator>=r;)a&&(O.previousState={},t.forEachRigidBody(e=>{O.previousState[e.handle]={position:e.translation(),rotation:e.rotation()}})),s(r),O.accumulator-=r;let c=n||!a||i?1:O.accumulator/r;b.forEach((e,n)=>{let r=t.getRigidBody(n),i=S.get(n);if(i!=null&&i.onSleep||i!=null&&i.onWake){if(r.isSleeping()&&!e.isSleeping){var a;i==null||(a=i.onSleep)==null||a.call(i)}if(!r.isSleeping()&&e.isSleeping){var o;i==null||(o=i.onWake)==null||o.call(i)}e.isSleeping=r.isSleeping()}if(!r||r.isSleeping()&&!(`isInstancedMesh`in e.object)||!e.setMatrix)return;let s=r.translation(),l=r.rotation(),u=O.previousState[n];u&&(N.compose(u.position,st(u.rotation),e.scale).premultiply(e.invertedWorldMatrix).decompose(P,F,at),e.meshType==`mesh`&&(e.object.position.copy(P),e.object.quaternion.copy(F))),N.compose(s,st(l),e.scale).premultiply(e.invertedWorldMatrix).decompose(P,F,at),e.meshType==`instancedMesh`?e.setMatrix(N):(e.object.position.lerp(P,c),e.object.quaternion.slerp(F,c))}),w.drainCollisionEvents((e,n,r)=>{let i=ae(e),a=ae(n);if(!(i!=null&&i.collider.object)||!(a!=null&&a.collider.object))return;let o=Wt(i,a),s=Wt(a,i);if(r)t.contactPair(i.collider.object,a.collider.object,(e,t)=>{var n,r,c,l,u,d,f,p;(n=i.rigidBody.events)==null||(r=n.onCollisionEnter)==null||r.call(n,M(M({},o),{},{manifold:e,flipped:t})),(c=a.rigidBody.events)==null||(l=c.onCollisionEnter)==null||l.call(c,M(M({},s),{},{manifold:e,flipped:t})),(u=i.collider.events)==null||(d=u.onCollisionEnter)==null||d.call(u,M(M({},o),{},{manifold:e,flipped:t})),(f=a.collider.events)==null||(p=f.onCollisionEnter)==null||p.call(f,M(M({},s),{},{manifold:e,flipped:t}))});else{var c,l,u,d,f,p,m,h;(c=i.rigidBody.events)==null||(l=c.onCollisionExit)==null||l.call(c,o),(u=a.rigidBody.events)==null||(d=u.onCollisionExit)==null||d.call(u,s),(f=i.collider.events)==null||(p=f.onCollisionExit)==null||p.call(f,o),(m=a.collider.events)==null||(h=m.onCollisionExit)==null||h.call(m,s)}if(r){if(t.intersectionPair(i.collider.object,a.collider.object)){var g,_,v,y,b,x,S,C;(g=i.rigidBody.events)==null||(_=g.onIntersectionEnter)==null||_.call(g,o),(v=a.rigidBody.events)==null||(y=v.onIntersectionEnter)==null||y.call(v,s),(b=i.collider.events)==null||(x=b.onIntersectionEnter)==null||x.call(b,o),(S=a.collider.events)==null||(C=S.onIntersectionEnter)==null||C.call(S,s)}}else{var w,T,E,ee,te,ne,D,re;(w=i.rigidBody.events)==null||(T=w.onIntersectionExit)==null||T.call(w,o),(E=a.rigidBody.events)==null||(ee=E.onIntersectionExit)==null||ee.call(E,s),(te=i.collider.events)==null||(ne=te.onIntersectionExit)==null||ne.call(te,o),(D=a.collider.events)==null||(re=D.onIntersectionExit)==null||re.call(D,s)}}),w.drainContactForceEvents(e=>{var t,n,r,i,a,o,s,c;let l=ae(e.collider1()),u=ae(e.collider2());if(!(l!=null&&l.collider.object)||!(u!=null&&u.collider.object))return;let d=Wt(l,u),f=Wt(u,l);(t=l.rigidBody.events)==null||(n=t.onContactForce)==null||n.call(t,M(M({},d),{},{totalForce:e.totalForce(),totalForceMagnitude:e.totalForceMagnitude(),maxForceDirection:e.maxForceDirection(),maxForceMagnitude:e.maxForceMagnitude()})),(r=u.rigidBody.events)==null||(i=r.onContactForce)==null||i.call(r,M(M({},f),{},{totalForce:e.totalForce(),totalForceMagnitude:e.totalForceMagnitude(),maxForceDirection:e.maxForceDirection(),maxForceMagnitude:e.maxForceMagnitude()})),(a=l.collider.events)==null||(o=a.onContactForce)==null||o.call(a,M(M({},d),{},{totalForce:e.totalForce(),totalForceMagnitude:e.totalForceMagnitude(),maxForceDirection:e.maxForceDirection(),maxForceMagnitude:e.maxForceMagnitude()})),(s=u.collider.events)==null||(c=s.onContactForce)==null||c.call(s,M(M({},f),{},{totalForce:e.totalForce(),totalForceMagnitude:e.totalForceMagnitude(),maxForceDirection:e.maxForceDirection(),maxForceMagnitude:e.maxForceMagnitude()}))}),t.forEachActiveRigidBody(()=>{y()})},[i,r,a,D]),se=(0,j.useMemo)(()=>({rapier:v,world:D,setWorld:e=>{ie(e)},physicsOptions:{colliders:t,gravity:l},rigidBodyStates:b,colliderStates:x,rigidBodyEvents:S,colliderEvents:C,beforeStepCallbacks:te,afterStepCallbacks:ne,isPaused:i,isDebug:c,step:oe,filterContactPairHooks:T,filterIntersectionPairHooks:E}),[i,oe,c,t,l]),k=(0,j.useCallback)(e=>{i||oe(e)},[i,oe]);return j.createElement(Ut.Provider,{value:se},j.createElement(gt,{onStep:k,type:s,updatePriority:o}),c&&j.createElement(Vt,null),n)};function R(){return R=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},R.apply(null,arguments)}var qt=(e,t=null)=>{let n=(0,j.useRef)(t);return e&&typeof e!=`function`?(e.current||=n.current,e):n},Jt=(e,t,n)=>{let r=(0,j.useRef)(void 0),i=(0,j.useCallback)(()=>(r.current||=e(),r.current),n);return(0,j.useEffect)(()=>{let e=i(),n=()=>t(e);return()=>{n(),r.current=void 0}},[i]),i},Yt=e=>{let t=ut(e?.type||`dynamic`),n=new Je(t);return n.canSleep=e?.canSleep??!0,n},Xt=({rigidBody:e,object:t,setMatrix:n,getMatrix:r,worldScale:i,meshType:a=`mesh`})=>(t.updateWorldMatrix(!0,!1),{object:t,rigidBody:e,invertedWorldMatrix:t.parent.matrixWorld.clone().invert(),setMatrix:n||(e=>{t.matrix.copy(e)}),getMatrix:r||(e=>e.copy(t.matrix)),scale:i||t.getWorldScale(at).clone(),isSleeping:!1,meshType:a}),Zt=[`args`,`colliders`,`canSleep`],Qt={gravityScale:(e,t)=>{e.setGravityScale(t,!0)},additionalSolverIterations(e,t){e.setAdditionalSolverIterations(t)},linearDamping:(e,t)=>{e.setLinearDamping(t)},angularDamping:(e,t)=>{e.setAngularDamping(t)},dominanceGroup:(e,t)=>{e.setDominanceGroup(t)},enabledRotations:(e,[t,n,r])=>{e.setEnabledRotations(t,n,r,!0)},enabledTranslations:(e,[t,n,r])=>{e.setEnabledTranslations(t,n,r,!0)},lockRotations:(e,t)=>{e.lockRotations(t,!0)},lockTranslations:(e,t)=>{e.lockTranslations(t,!0)},angularVelocity:(e,[t,n,r])=>{e.setAngvel({x:t,y:n,z:r},!0)},linearVelocity:(e,[t,n,r])=>{e.setLinvel({x:t,y:n,z:r},!0)},ccd:(e,t)=>{e.enableCcd(t)},softCcdPrediction:(e,t)=>{e.setSoftCcdPrediction(t)},userData:(e,t)=>{e.userData=t},type(e,t){e.setBodyType(ut(t),!0)},position:()=>{},rotation:()=>{},quaternion:()=>{},scale:()=>{}},$t=Object.keys(Qt),en=(e,t,n,r=!0)=>{if(!e)return;let i=n.get(e.handle);i&&(r&&(i.object.updateWorldMatrix(!0,!1),N.copy(i.object.matrixWorld).decompose(P,F,at),e.setTranslation(P,!1),e.setRotation(F,!1)),$t.forEach(n=>{n in t&&Qt[n](e,t[n])}))},tn=(e,t,n,r=!0)=>{let i=(0,j.useMemo)(()=>$t.flatMap(e=>ft(t[e])),[t]);(0,j.useEffect)(()=>{en(e(),t,n,r)},i)},nn=(e,t,n)=>{let{onWake:r,onSleep:i,onCollisionEnter:a,onCollisionExit:o,onIntersectionEnter:s,onIntersectionExit:c,onContactForce:l}=t,u={onWake:r,onSleep:i,onCollisionEnter:a,onCollisionExit:o,onIntersectionEnter:s,onIntersectionExit:c,onContactForce:l};(0,j.useEffect)(()=>{let t=e();return n.set(t.handle,u),()=>{n.delete(t.handle)}},[r,i,a,o,s,c,l])},rn=({x:e,y:t,z:n}={x:0,y:0,z:0})=>new i(e,t,n),z=(0,j.memo)(e=>{let{children:t,position:n,rotation:r,quaternion:i,scale:a,name:o}=e,{world:s,colliderEvents:c,colliderStates:l}=L(),u=gn(),d=qt(e.ref),f=(0,j.useRef)(null),p=Jt(()=>{let t=f.current.getWorldScale(rn()),n=xt(e,s,t,u?.getRigidBody);return typeof e.ref==`function`&&e.ref(n),d.current=n,n},e=>{s.getCollider(e.handle)&&s.removeCollider(e,!0)},[...St.flatMap(t=>Array.isArray(e[t])?e[t]:[e[t]]),u]);(0,j.useEffect)(()=>{let e=p();return l.set(e.handle,At(e,f.current,u?.ref.current)),()=>{l.delete(e.handle)}},[p]);let m=(0,j.useMemo)(()=>M(M({},It(u?.options)),e),[e,u?.options]);return Ot(p,m,l),Ft(p,m,c,Pt(u?.options)),j.createElement(`object3D`,{position:n,rotation:r,quaternion:i,scale:a,ref:f,name:o},t)}),B=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`cuboid`,ref:t})));B.displayName=`CuboidCollider`;var an=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`roundCuboid`,ref:t})));an.displayName=`RoundCuboidCollider`;var on=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`ball`,ref:t})));on.displayName=`BallCollider`;var sn=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`capsule`,ref:t})));sn.displayName=`CapsuleCollider`;var cn=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`heightfield`,ref:t})));cn.displayName=`HeightfieldCollider`;var ln=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`trimesh`,ref:t})));ln.displayName=`TrimeshCollider`;var un=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`cone`,ref:t})));un.displayName=`ConeCollider`;var dn=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`roundCone`,ref:t})));dn.displayName=`RoundConeCollider`;var fn=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`cylinder`,ref:t})));fn.displayName=`CylinderCollider`,fn.displayName=`RoundCylinderCollider`;var pn=j.forwardRef((e,t)=>j.createElement(z,R({},e,{shape:`convexHull`,ref:t})));pn.displayName=`ConvexHullCollider`;var mn=[`ref`,`children`,`type`,`position`,`rotation`,`scale`,`quaternion`,`transformState`],hn=(0,j.createContext)(void 0),gn=()=>(0,j.useContext)(hn),V=(0,j.memo)(e=>{let{ref:t,children:n,type:r,position:i,rotation:a,scale:o,quaternion:s,transformState:c}=e,l=vt(e,mn),u=(0,j.useRef)(null),d=qt(t),{world:f,rigidBodyStates:p,physicsOptions:m,rigidBodyEvents:h}=L(),g=(0,j.useMemo)(()=>M(M(M({},m),e),{},{children:void 0}),[m,e]),_=Zt.flatMap(e=>Array.isArray(g[e])?[...g[e]]:g[e]),v=Bt(u,g),y=Jt(()=>{let e=Yt(g),n=f.createRigidBody(e);return typeof t==`function`&&t(n),d.current=n,n},e=>{f.getRigidBody(e.handle)&&f.removeRigidBody(e)},_);(0,j.useEffect)(()=>{let t=y(),n=Xt({rigidBody:t,object:u.current});return p.set(t.handle,e.transformState?e.transformState(n):n),()=>{p.delete(t.handle)}},[y]),tn(y,g,p),nn(y,g,h);let b=(0,j.useMemo)(()=>({ref:u,getRigidBody:y,options:g}),[y]);return j.createElement(hn.Provider,{value:b},j.createElement(`object3D`,R({ref:u},l,{position:i,rotation:a,quaternion:s,scale:o}),n,v.map((e,t)=>j.createElement(z,R({key:t},e)))))});V.displayName=`RigidBody`;var _n=(0,j.memo)(e=>{let{children:t,type:n}=e,{physicsOptions:r}=L(),i=(0,j.useRef)(null),{options:a}=gn(),o=Bt(i,(0,j.useMemo)(()=>M(M(M({},r),a),{},{children:void 0,colliders:n}),[r,a]),!1);return j.createElement(`object3D`,{ref:i,userData:{r3RapierType:`MeshCollider`}},t,o.map((e,t)=>j.createElement(z,R({key:t},e))))});_n.displayName=`MeshCollider`;var vn=[`ref`],yn=[`children`,`instances`,`colliderNodes`,`position`,`rotation`,`quaternion`,`scale`],bn=(0,j.memo)(e=>{let{ref:t}=e,n=vt(e,vn),r=qt(t,[]),i=(0,j.useRef)(null),a=(0,j.useRef)(null),{children:o,instances:s,colliderNodes:c=[],position:l,rotation:u,quaternion:d,scale:f}=n,p=vt(n,yn),m=Bt(i,M(M({},n),{},{children:void 0})),h=()=>{let e=a.current.children[0];if(e&&`isInstancedMesh`in e)return e};(0,j.useEffect)(()=>{let e=h();e?e.instanceMatrix.setUsage(le):console.warn(`InstancedRigidBodies expects exactly one child, which must be an InstancedMesh`)},[]);let g=(e,t)=>{let n=h();return n?M(M({},e),{},{getMatrix:e=>(n.getMatrixAt(t,e),e),setMatrix:e=>{n.setMatrixAt(t,e),n.instanceMatrix.needsUpdate=!0},meshType:`instancedMesh`}):e};return j.createElement(`object3D`,R({ref:i},p,{position:l,rotation:u,quaternion:d,scale:f}),j.createElement(`object3D`,{ref:a},o),s?.map((e,t)=>j.createElement(V,R({},p,e,{ref:e=>{r.current[t]=e},transformState:e=>g(e,t)}),j.createElement(j.Fragment,null,c.map((e,t)=>j.createElement(j.Fragment,{key:t},e)),m.map((e,t)=>j.createElement(z,R({key:t},e)))))))});bn.displayName=`InstancedRigidBodies`;var xn=(e,t)=>(Sn(e)<<16)+(t===void 0?65535:Sn(t)),Sn=e=>[e].flat().reduce((e,t)=>e|1<<t,0),H={standoff:.32,board:{w:1.2,h:.62,t:.05,bottom:2.56},square:{w:.48,h:.36},rim:{y:2.7,r:.23,tube:.018,gap:.15},net:{h:.42,bottomR:.14},score:{w:1.24,h:.36,bottom:3.2},ball:{r:.12}},Cn={office:10.5,lobby:-9},wn=H.standoff+H.board.t+H.rim.gap+H.rim.r,Tn=e=>({x:Cn[e],y:H.rim.y,z:12-wn,r:H.rim.r}),En=()=>({prev:null,armed:!0}),Dn=1.5;function On(e,t,n){let r=(e.y-n.y)/(e.y-t.y),i=e.x+(t.x-e.x)*r,a=e.z+(t.z-e.z)*r;return Math.hypot(i-n.x,a-n.z)<n.r}function kn(e,t,n){let r=e.prev;if(e.prev={x:t.x,y:t.y,z:t.z},!r)return!1;if(Math.hypot(t.x-r.x,t.y-r.y,t.z-r.z)>Dn)return e.armed=!0,!1;let i=r.y>n.y&&t.y<=n.y,a=r.y<=n.y&&t.y>n.y;if((i||a)&&On(r,t,n)){let t=i&&e.armed;return e.armed=!1,t}return!e.armed&&Math.hypot(t.x-n.x,t.z-n.z)>n.r&&(e.armed=!0),!1}var U=ve(),An=`#1f1d2b`,jn=`#ff7b00`,Mn=`#e63946`,Nn=`cubefarm:hoop-best`,Pn=new Map;function Fn(){try{let e=JSON.parse(localStorage.getItem(Nn)??`{}`);return e&&typeof e==`object`?e:{}}catch{return{}}}function In(e){let t=Number(Fn()[e]);return Number.isFinite(t)&&t>0?Math.floor(t):0}function Ln(e,t){try{localStorage.setItem(Nn,JSON.stringify({...Fn(),[e]:t}))}catch{}}function Rn(e,t,n,{score:r,best:i}){v(e,0,0,t,n,22),e.fillStyle=`#15151f`,e.fill();let a=`Score ${r} · Best ${i}`,o=88;for(e.font=`700 ${o}px ${h}`;o>30&&e.measureText(a).width>t-48;)o-=4,e.font=`700 ${o}px ${h}`;e.textAlign=`center`,e.textBaseline=`middle`,e.fillStyle=`#ffd166`,e.fillText(a,t/2,n/2+4),e.textAlign=`left`}function zn({r:t}){let n=d(An),r=t*.05;return(0,U.jsxs)(`group`,{children:[(0,U.jsxs)(`mesh`,{castShadow:!0,material:d(`#f3722c`),children:[(0,U.jsx)(`sphereGeometry`,{args:[t,24,16]}),(0,U.jsx)(e,{thickness:.012,color:An})]}),(0,U.jsx)(`mesh`,{rotation:[Math.PI/2,0,0],material:n,children:(0,U.jsx)(`torusGeometry`,{args:[t*1.004,r,6,40]})}),(0,U.jsx)(`mesh`,{material:n,children:(0,U.jsx)(`torusGeometry`,{args:[t*1.004,r,6,40]})}),[-1,1].map(e=>(0,U.jsx)(`mesh`,{position:[e*t*.6,0,0],rotation:[0,Math.PI/2,0],material:n,children:(0,U.jsx)(`torusGeometry`,{args:[t*.8*1.006,r,6,32]})},e))]})}var Bn=null;function Vn(){if(Bn)return Bn;let e=document.createElement(`canvas`);e.width=e.height=64;let t=e.getContext(`2d`);t.strokeStyle=`#ffffff`,t.lineWidth=7,t.beginPath(),t.moveTo(0,0),t.lineTo(64,64),t.moveTo(64,0),t.lineTo(0,64),t.stroke();let n=new Fe(e);return n.colorSpace=S,n.wrapS=n.wrapT=We,n.repeat.set(12,3),Bn=new me({map:n,color:`#f1f3f5`,alphaTest:.5,side:2}),Bn}var Hn=e=>e.current<0?1/0:(performance.now()-e.current)/1e3;function Un({burst:e}){let t=(0,j.useRef)(null);A(()=>{let n=t.current;if(!n)return;let r=Hn(e);if(r>2.5){n.scale.y!==1&&(n.scale.set(1,1,1),n.rotation.set(0,0,0));return}let i=Math.exp(-3*r),a=Math.sin(r*12)*i;n.scale.set(1-.16*a,1+.4*a,1-.16*a),n.rotation.set(.2*i*Math.sin(r*9),0,.12*i*Math.sin(r*7))});let{h:n,bottomR:r}=H.net;return(0,U.jsx)(`group`,{ref:t,position:[0,H.rim.y,-wn],children:(0,U.jsx)(`mesh`,{position:[0,-n/2,0],material:Vn(),children:(0,U.jsx)(`cylinderGeometry`,{args:[H.rim.r,r,n,24,1,!0]})})})}var Wn=42,Gn=1.8,Kn=[`#ef476f`,`#ffd166`,`#06d6a0`,`#118ab2`,`#ff9f1c`,`#9b5de5`];function qn({burst:e}){let t=(0,j.useRef)(null),n=(0,j.useMemo)(()=>Array.from({length:Wn},()=>({v:new i,spin:new i})),[]),r=(0,j.useMemo)(()=>new Be,[]),a=(0,j.useRef)(-1);return(0,j.useLayoutEffect)(()=>{let e=t.current;if(!e)return;let n=new k;for(let t=0;t<Wn;t++)e.setColorAt(t,n.set(Kn[t%Kn.length]));e.instanceColor&&(e.instanceColor.needsUpdate=!0)},[]),A(()=>{let i=t.current;if(!i)return;let o=Hn(e);if(o>Gn){i.visible&&=!1;return}if(a.current!==e.current){a.current=e.current;for(let e of n){let t=Math.random()*Math.PI*2,n=.6+Math.random()*1.6;e.v.set(Math.cos(t)*n,1.2+Math.random()*2,Math.sin(t)*n-.8),e.spin.set(Math.random()*12,Math.random()*12,Math.random()*12)}}i.visible=!0;let s=Math.min(1,(Gn-o)/.4);for(let e=0;e<Wn;e++){let t=n[e];r.position.set(t.v.x*o,Math.max(.02-H.rim.y,t.v.y*o-2.2*o*o),t.v.z*o),r.rotation.set(t.spin.x*o,t.spin.y*o,t.spin.z*o),r.scale.setScalar(s),r.updateMatrix(),i.setMatrixAt(e,r.matrix)}i.instanceMatrix.needsUpdate=!0}),(0,U.jsxs)(`instancedMesh`,{ref:t,args:[void 0,void 0,Wn],position:[0,H.rim.y-.05,-wn],visible:!1,frustumCulled:!1,children:[(0,U.jsx)(`planeGeometry`,{args:[.06,.035]}),(0,U.jsx)(`meshBasicMaterial`,{side:2,toneMapped:!1})]})}function Jn({tally:n}){let{w:r,h:i,bottom:a}=H.score,o=t(640,186,e=>Rn(e,640,186,n),[n.score,n.best]);return(0,U.jsxs)(`group`,{position:[0,a+i/2,-(H.standoff+H.board.t/2)],children:[(0,U.jsxs)(`mesh`,{material:d(`#2b2d42`),children:[(0,U.jsx)(`boxGeometry`,{args:[r,i,.06]}),(0,U.jsx)(e,{thickness:.015,color:An})]}),(0,U.jsxs)(`mesh`,{position:[0,0,-.031],rotation:[0,Math.PI,0],children:[(0,U.jsx)(`planeGeometry`,{args:[r-.05,i-.05]}),(0,U.jsx)(`meshBasicMaterial`,{map:o,toneMapped:!1})]})]})}var Yn=(0,j.memo)(function(){let{standoff:t,board:n,square:r,rim:i}=H,a=-(t+n.t)-.003,o=.035,s={cy:i.y+r.h/2,w:r.w,h:r.h};return(0,U.jsxs)(`group`,{children:[[-.4,.4].flatMap(e=>[2.72,3.05].map(n=>(0,U.jsx)(`mesh`,{position:[e,n,-t/2],material:d(`#8d99ae`),children:(0,U.jsx)(`boxGeometry`,{args:[.05,.05,t]})},`${e}${n}`))),(0,U.jsxs)(`mesh`,{position:[0,n.bottom+n.h/2,-(t+n.t/2)],material:d(`#fdfdfd`),castShadow:!0,children:[(0,U.jsx)(`boxGeometry`,{args:[n.w,n.h,n.t]}),(0,U.jsx)(e,{thickness:.015,color:An})]}),[[0,n.bottom+n.h-o/2,n.w-.04,o],[0,n.bottom+o/2,n.w-.04,o],[-(n.w/2-.02-o/2),n.bottom+n.h/2,o,n.h-.04],[n.w/2-.02-o/2,n.bottom+n.h/2,o,n.h-.04],[0,s.cy+s.h/2-o/2,s.w,o],[0,s.cy-s.h/2+o/2,s.w,o],[-(s.w/2-o/2),s.cy,o,s.h],[s.w/2-o/2,s.cy,o,s.h]].map(([e,t,n,r],i)=>(0,U.jsx)(`mesh`,{position:[e,t,a],material:d(Mn),children:(0,U.jsx)(`boxGeometry`,{args:[n,r,.004]})},i)),(0,U.jsx)(`mesh`,{position:[0,i.y,-(t+n.t+i.gap/2)],material:d(jn),children:(0,U.jsx)(`boxGeometry`,{args:[.14,.025,i.gap+.02]})}),(0,U.jsxs)(`mesh`,{position:[0,i.y,-wn],rotation:[Math.PI/2,0,0],material:d(jn),castShadow:!0,children:[(0,U.jsx)(`torusGeometry`,{args:[i.r,i.tube,8,40]}),(0,U.jsx)(e,{thickness:.008,color:An})]})]})}),Xn=24,Zn=(0,j.memo)(function({groups:e}){let{standoff:t,board:n,rim:r,score:i}=H,a=t+n.t,o=i.bottom+i.h,s=(0,j.useMemo)(()=>Array.from({length:Xn},(e,t)=>[Math.cos(t/Xn*Math.PI*2)*r.r,r.y,-wn+Math.sin(t/Xn*Math.PI*2)*r.r]),[r]);return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(B,{args:[Math.max(n.w,i.w)/2,(o-n.bottom)/2,a/2],position:[0,(n.bottom+o)/2,-a/2],restitution:.6,friction:.5,collisionGroups:e}),(0,U.jsx)(B,{args:[.07,.013,r.gap/2],position:[0,r.y,-(a+r.gap/2)],restitution:.45,collisionGroups:e}),s.map((t,n)=>(0,U.jsx)(on,{args:[r.tube+.004],position:t,restitution:.45,friction:.4,collisionGroups:e},n))]})}),Qn=(0,j.memo)(function({floor:e,groups:t}){let n=(0,j.useMemo)(()=>Tn(e),[e]),r=(0,j.useMemo)(()=>{let t=je.getState();return e===`lobby`?`lobby`:p(t.repos,t.floor)?.id??`floor-${t.floor}`},[e]),[i,a]=(0,j.useState)(()=>({score:Pn.get(r)??0,best:In(r)})),o=(0,j.useRef)(i),s=(0,j.useRef)(-1);(0,j.useEffect)(()=>(Le(()=>({...o.current})),()=>Le(null)),[]);let c=(0,j.useCallback)(()=>{let e=o.current,t={score:e.score+1,best:Math.max(e.best,e.score+1)};o.current=t,Pn.set(r,t.score),t.best>e.best&&Ln(r,t.best),a(t),s.current=performance.now(),ne()},[r]),l=(0,j.useRef)(new Map);zt((0,j.useCallback)(e=>{e.bodies.forEach(e=>{if(e.userData?.toy!==`basketball`||e.isSleeping())return;let t=l.current.get(e.handle);t||l.current.set(e.handle,t=En()),kn(t,e.translation(),n)&&c()})},[c,n]));let u=[Cn[e],0,12];return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(V,{type:`fixed`,colliders:!1,position:u,children:(0,U.jsx)(Zn,{groups:t})}),(0,U.jsxs)(`group`,{position:u,children:[(0,U.jsx)(Yn,{}),(0,U.jsx)(Un,{burst:s}),(0,U.jsx)(qn,{burst:s}),(0,U.jsx)(Jn,{tally:i})]})]})}),$n=`#1f1d2b`,er={beach:{kind:`beach`,r:.4,restitution:.8,density:1.2,damping:.9},exercise:{kind:`exercise`,r:.45,restitution:.7,density:1.6,damping:.9},yarn:{kind:`yarn`,r:.33,restitution:.35,density:2.5,damping:1.3},basketball:{kind:`basketball`,r:H.ball.r,restitution:.75,density:60,damping:.5,throwSpeed:8.5}},tr=(e,t,n,r)=>({id:e,...er[t],start:{x:n,y:er[t].r+.02,z:r}}),nr=e=>tr(`basketball`,`basketball`,Tn(e).x,Tn(e).z-.35),rr={office:[tr(`beach-ball`,`beach`,6.6,6.8),tr(`exercise-ball`,`exercise`,9.8,8.6),tr(`yarn-ball`,`yarn`,12.2,6.2),nr(`office`)],lobby:[tr(`beach-ball`,`beach`,-11,5.6),tr(`exercise-ball`,`exercise`,-7.6,8.2),tr(`yarn-ball`,`yarn`,-5.4,4.4),nr(`lobby`)]},ir=e=>Math.abs(e.x)>16||Math.abs(e.z)>12||e.y<-.5||e.y>6,ar=[`#ef476f`,`#ffffff`,`#ffd166`,`#ffffff`,`#118ab2`,`#ffffff`],W=null;function or(){if(W)return W;let e=new Uint8Array(ar.length*10*4);for(let t=0;t<10;t++)for(let n=0;n<ar.length;n++){let r=parseInt((t===0||t===9?`#ffffff`:ar[n]).slice(1),16),i=(t*ar.length+n)*4;e[i]=r>>16&255,e[i+1]=r>>8&255,e[i+2]=r&255,e[i+3]=255}return W=new Re(e,ar.length,10,oe),W.colorSpace=S,W.minFilter=re,W.magFilter=re,W.generateMipmaps=!1,W.needsUpdate=!0,W}var sr=`#8338ec`,cr=`#ff70a6`,lr=[[0,0,0],[Math.PI/2,0,0],[.6,0,1.1],[-.7,.3,-1],[1.2,.9,.4]];function ur({def:t}){let{r:n}=t;return t.kind===`basketball`?(0,U.jsx)(zn,{r:n}):t.kind===`beach`?(0,U.jsxs)(`mesh`,{castShadow:!0,material:m(`beach-ball`,or()),children:[(0,U.jsx)(`sphereGeometry`,{args:[n,24,16]}),(0,U.jsx)(e,{thickness:.02,color:$n})]}):t.kind===`exercise`?(0,U.jsxs)(`group`,{children:[(0,U.jsxs)(`mesh`,{castShadow:!0,material:d(sr),children:[(0,U.jsx)(`sphereGeometry`,{args:[n,24,16]}),(0,U.jsx)(e,{thickness:.02,color:$n})]}),(0,U.jsx)(`mesh`,{rotation:[Math.PI/2,0,0],material:d(c(sr,-.14)),children:(0,U.jsx)(`torusGeometry`,{args:[n*1.002,.018,6,40]})}),(0,U.jsx)(`mesh`,{position:[0,0,n],rotation:[Math.PI/2,0,0],material:d(`#f8f9fa`),children:(0,U.jsx)(`cylinderGeometry`,{args:[.045,.05,.04,12]})})]}):(0,U.jsxs)(`group`,{children:[(0,U.jsxs)(`mesh`,{castShadow:!0,material:d(cr),children:[(0,U.jsx)(`sphereGeometry`,{args:[n,20,14]}),(0,U.jsx)(e,{thickness:.02,color:$n})]}),lr.map((e,t)=>(0,U.jsx)(`mesh`,{rotation:e,material:d(c(cr,t%2?-.12:.08)),children:(0,U.jsx)(`torusGeometry`,{args:[n*1.005,.022,6,36]})},t)),(0,U.jsx)(`mesh`,{position:[n*.55,-n*.62,n*.45],rotation:[.4,0,.9],material:d(c(cr,-.12)),children:(0,U.jsx)(`capsuleGeometry`,{args:[.022,.3,3,6]})})]})}var dr=1/60,fr=`#2b2d42`,pr=2.8;function mr({def:e,shadow:t=!0,mag:n}){let{body:i,trim:a}=e;return(0,U.jsxs)(`group`,{children:[(0,U.jsx)(r,{size:[.1,.12,.3],position:[0,.02,-.02],color:i,outline:!0,shadow:t}),(0,U.jsx)(r,{size:[.104,.03,.2],position:[0,-.01,-.04],color:`#ffffff`,shadow:!1}),(0,U.jsx)(r,{size:[.05,.035,.22],position:[0,.095,-.03],color:a,outline:!0,shadow:t}),(0,U.jsx)(Ve,{r:.038,h:.14,position:[0,.03,-.23],rotation:[Math.PI/2,0,0],color:a,outline:!0,shadow:t}),(0,U.jsx)(Ve,{r:.046,h:.04,position:[0,.03,-.31],rotation:[Math.PI/2,0,0],color:`#ffd166`,outline:!0,shadow:t}),(0,U.jsx)(r,{size:[.11,.07,.08],position:[0,.03,.16],color:a,outline:!0,shadow:t}),(0,U.jsx)(r,{size:[.065,.15,.075],position:[0,-.1,.09],rotation:[.3,0,0],color:fr,outline:!0,shadow:t}),(0,U.jsx)(r,{size:[.02,.05,.07],position:[0,-.065,.01],color:fr,shadow:!1}),(0,U.jsx)(`group`,{ref:n,position:[0,-.08,-.1],children:(0,U.jsx)(r,{size:[.055,.12,.08],color:c(i,-.2),outline:!0,shadow:t})})]})}var G={x:.17,y:-.155,z:-.3,scale:.5},hr=new i(G.x,G.y+.03*G.scale,G.z-.33*G.scale);function gr({def:e}){let t=(0,j.useRef)(null),n=(0,j.useRef)(null),r=(0,j.useRef)(null);return A(({camera:e})=>{let i=t.current,a=n.current;if(!i||!a)return;i.position.copy(e.position),i.quaternion.copy(e.quaternion);let o=performance.now(),s=(o-De.at)/160,c=s<1?Math.min(1,s*4)*(1-s):0,l=je.getState().held,u=l?.kind===`blaster`?ze(l,o):null,d=u===null?0:Math.sin(u*Math.PI);a.position.set(G.x,G.y-d*.06,G.z+c*.05),a.rotation.set(c*.25+d*.45,0,d*.5),r.current&&(r.current.position.y=-.08-d*.14)}),(0,U.jsx)(`group`,{ref:t,children:(0,U.jsx)(`group`,{ref:n,scale:G.scale,children:(0,U.jsx)(mr,{def:e,shadow:!1,mag:r})})})}var _r=[1.4,1.06];function vr({x:e,onRack:t}){let n=t[0],i=ye(n?{id:`toy:rack:${n.id}`,label:`Take a blaster`,action:{kind:`pickup`,toyId:n.id}}:null,pr),{w:a,d:o,h:s}=b;return(0,U.jsxs)(`group`,{position:[e,0,12],rotation:[0,Math.PI,0],children:[(0,U.jsxs)(`group`,{ref:i,children:[(0,U.jsx)(r,{size:[a,.8,o],position:[0,.4,o/2],color:`#ffd166`,outline:!0}),(0,U.jsx)(r,{size:[a-.2,.08,.01],position:[0,.62,o+.005],color:`#ff8c1a`,shadow:!1}),(0,U.jsx)(r,{size:[a-.1,s-.85,.04],position:[0,.8+(s-.8)/2,.03],color:`#f4e1c1`,outline:!0}),_r.flatMap(e=>[-.16,.16].map(t=>(0,U.jsx)(Ve,{r:.012,h:.1,position:[t,e-.1,.09],rotation:[Math.PI/2,0,0],color:fr,shadow:!1},`${e}${t}`))),pe.map((e,n)=>t.includes(e)?(0,U.jsx)(`group`,{position:[0,_r[n],.13],rotation:[0,Math.PI/2,0],children:(0,U.jsx)(mr,{def:e})},e.id):null),(0,U.jsx)(r,{size:[.34,.1,.2],position:[.36,.85,.16],color:`#3a86ff`,outline:!0}),[0,1,2,3].map(e=>(0,U.jsxs)(`group`,{position:[.26+e*.065,.92,.16],rotation:[Math.PI/2,0,.2*(e-1.5)],children:[(0,U.jsx)(Ve,{r:.02,h:.13,color:e%2?`#ff8c1a`:`#3a86ff`,shadow:!1}),(0,U.jsx)(Ve,{r:.026,rTop:.02,h:.025,position:[0,-.075,0],color:`#ffd166`,shadow:!1})]},e))]}),(0,U.jsx)(xe,{position:[0,s-.14,.055],rotationY:0,size:[a-.2,.22],px:[512,96],draw:e=>g(e,512,96,[{text:`🎯 FOAM ZONE`,size:54}],`#ef476f`),deps:[]})]})}function yr({def:e,spot:t,groups:n,onLost:r}){let i=ye({id:`toy:${e.id}`,label:`Pick up blaster`,action:{kind:`pickup`,toyId:e.id}},pr),a=(0,j.useRef)(null),o=(0,j.useRef)(0);return zt(()=>{let e=a.current;++o.current%15||!e||e.isSleeping()||ir(e.translation())&&r()}),(0,U.jsxs)(V,{ref:a,colliders:!1,position:t.at,rotation:[0,t.yaw,0],linearVelocity:t.vel,linearDamping:.3,angularDamping:.6,ccd:!0,userData:{toy:e.id},children:[(0,U.jsx)(B,{args:[.055,.15,.27],position:[0,-.03,-.07],density:260,friction:.8,restitution:.25,collisionGroups:n}),(0,U.jsxs)(`group`,{ref:i,children:[(0,U.jsx)(mr,{def:e}),(0,U.jsx)(`mesh`,{visible:!1,position:[0,-.03,-.07],children:(0,U.jsx)(`boxGeometry`,{args:[.36,.36,.6]})})]})]})}var K={r:.026,half:.064,tip:.105,speed:19,flightGravity:.35,density:35,embed:.012,slow:4},br=new i(0,1,0),xr=new i(1,1,1),Sr={x:0,y:0,z:0},Cr=u();function wr(e){e.state=`loose`,e.body.setGravityScale(1,!0),e.body.setLinearDamping(.3)}function Tr({groups:e}){let{world:t,rapier:n}=L(),r=Ee(e=>e.camera),a=(0,j.useRef)([]),o=(0,j.useRef)(1),s=(0,j.useRef)(0),c=(0,j.useMemo)(()=>({fwd:new i,muzzle:new i,aim:new i,v:new i,n:new i,q:new Ke,m:new ge,p:new i}),[]),l=(0,j.useMemo)(()=>new n.Ray({x:0,y:0,z:0},{x:0,y:0,z:-1}),[n]),u=(0,j.useMemo)(()=>{let e=new Ae(new Se(K.r,K.r,.15,8),d(`#ffffff`),48),t=new Ae(new Se(.035,K.r,.03,10).translate(0,.09,0),d(`#ffd166`),48);for(let n of[e,t])n.count=0,n.frustumCulled=!1,n.instanceMatrix.setUsage(le);return e.setColorAt(0,new k(`#ffffff`)),{foam:e,tip:t}},[]);(0,j.useEffect)(()=>()=>{for(let e of[u.foam,u.tip])e.geometry.dispose(),e.dispose()},[u]);let p=(0,j.useCallback)(e=>{let n=a.current.indexOf(e);n<0||(a.current.splice(n,1),t.removeRigidBody(e.body))},[t]);(0,j.useEffect)(()=>(O({count:()=>a.current.length,stuck:()=>a.current.filter(e=>e.state===`stuck`).length,loose:()=>a.current.filter(e=>e.state===`loose`).map(e=>{let t=e.body.translation();return{id:e.id,x:t.x,y:t.y,z:t.z,color:`#${e.color.getHexString()}`,q:e.body.rotation()}}),remove:e=>{let t=a.current.find(t=>t.id===e);return t&&p(t),!!t}}),()=>{O(null),a.current=[]}),[p]);let m=(0,j.useCallback)((n,r,i)=>(l.origin=n,l.dir=r,t.castRay(l,i,!0,void 0,e)),[l,t,e]),h=(0,j.useCallback)(i=>{let s=pe.find(e=>e.id===i)??pe[0],{fwd:l,muzzle:u,aim:d,v:f,q:h}=c;l.set(0,0,-1).applyQuaternion(r.quaternion),u.copy(hr).applyQuaternion(r.quaternion).add(r.position),f.subVectors(u,r.position);let g=f.length();f.divideScalar(g);let _=m(r.position,f,g+K.tip);_&&u.copy(r.position).addScaledVector(f,Math.max(0,_.timeOfImpact-K.tip-.02));let v=m(r.position,l,60),y=v?v.timeOfImpact:40;y>1.2?d.copy(r.position).addScaledVector(l,y):d.copy(u).add(l),f.subVectors(d,u).normalize(),h.setFromUnitVectors(br,f);for(let e of x(a.current,40))p(e);let b=t.createRigidBody(n.RigidBodyDesc.dynamic().setTranslation(u.x,u.y,u.z).setRotation(h).setLinvel(f.x*K.speed,f.y*K.speed,f.z*K.speed).setGravityScale(K.flightGravity).setLinearDamping(.05).setAngularDamping(1.5).setCcdEnabled(!0).setUserData({toy:`dart`}));t.createCollider(n.ColliderDesc.capsule(K.half,K.r).setDensity(K.density).setRestitution(.35).setFriction(.9).setCollisionGroups(e),b),a.current.push({id:o.current++,born:performance.now(),body:b,color:new k(s.foam),state:`flying`,dir:f.clone()})},[r,m,e,n,p,c,t]),g=(0,j.useCallback)((e,r,i)=>{let a=e.body;a.setBodyType(n.RigidBodyType.Fixed,!1),t.removeCollider(a.collider(0),!1),a.setTranslation(r.addScaledVector(i,K.tip-K.embed),!1),a.setRotation(c.q.setFromUnitVectors(br,i.negate()),!1),e.state=`stuck`,f({dur:.05,peak:.05,filter:`bandpass`,freq:700,q:1.5})},[n,c,t]);return Rt((0,j.useCallback)(()=>{for(let e=se();e;e=se())h(e);let{v:n,n:r,p:i,q:o}=c;for(let s of[...a.current]){if(s.state!==`flying`)continue;let a=s.body,c=a.linvel(),u=Math.hypot(c.x,c.y,c.z);if(n.set(c.x,c.y,c.z).divideScalar(u||1),u<K.slow||n.dot(s.dir)<.97){wr(s);continue}s.dir.copy(n),a.setRotation(o.setFromUnitVectors(br,n),!0),a.setAngvel(Sr,!0);let d=a.translation();l.origin=d,l.dir=n;let f=t.castRayAndGetNormal(l,u*dr+K.tip,!0,void 0,e,void 0,a);if(!f||!f.collider.parent()?.isFixed())continue;i.set(d.x,d.y,d.z).addScaledVector(n,f.timeOfImpact);let p=i.x>Cr.minX&&i.x<Cr.maxX&&i.z>Cr.minZ-.05;r.set(f.normal.x,f.normal.y,f.normal.z),!p&&Ue(c,r)&&g(s,i,r)}if(!(++s.current%15))for(let e of[...a.current])e.state!==`stuck`&&ir(e.body.translation())&&p(e)},[e,l,p,h,g,c,t])),A(()=>{let{foam:e,tip:t}=u,{m:n,p:r,q:i}=c,o=a.current;for(let a=0;a<o.length;a++){let s=o[a].body,c=s.translation(),l=s.rotation();n.compose(r.set(c.x,c.y,c.z),i.set(l.x,l.y,l.z,l.w),xr),e.setMatrixAt(a,n),t.setMatrixAt(a,n),e.setColorAt(a,o[a].color)}(e.count!==o.length||o.length)&&(e.count=t.count=o.length,e.instanceMatrix.needsUpdate=!0,t.instanceMatrix.needsUpdate=!0,e.instanceColor&&(e.instanceColor.needsUpdate=!0))}),(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`primitive`,{object:u.foam}),(0,U.jsx)(`primitive`,{object:u.tip})]})}var Er=()=>Object.fromEntries(pe.map(e=>[e.id,{where:`rack`}]));function Dr({floor:e,groups:t}){let n=je(e=>e.held?.kind===`blaster`?e.held.id:null),r=Ee(e=>e.camera),{world:a,rapier:o}=L(),[s,c]=(0,j.useState)(Er),l=(0,j.useRef)(null),u=(0,j.useRef)(0);(0,j.useEffect)(()=>Pe(),[]);let d=(0,j.useCallback)(()=>{let e=new i(0,0,-1).applyQuaternion(r.quaternion);e.y=0,e.lengthSq()<1e-6&&e.set(0,0,-1),e.normalize();let n={x:r.position.x,y:1.1,z:r.position.z},s=a.castRay(new o.Ray(n,e),1,!0,void 0,t),c=s?Math.max(0,Math.min(.45,s.timeOfImpact-.3)):.45;return{where:`loose`,key:++u.current,at:[n.x+e.x*c,n.y,n.z+e.z*c],vel:[ie.x*.5,0,ie.z*.5],yaw:r.rotation.y}},[r,t,o,a]);(0,j.useEffect)(()=>{let e=l.current;if(l.current=n,e===n)return;let t=e?d():null;c(r=>{let i={...r};return e&&t&&(i[e]=t),n&&(i[n]={where:`held`}),i})},[n,d]);let f=(0,j.useCallback)(e=>c(t=>({...t,[e]:{where:`rack`}})),[]),p=pe.find(e=>e.id===n),m=e===`office`?b.officeX:b.lobbyX;return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(vr,{x:m,onRack:pe.filter(e=>s[e.id]?.where===`rack`)}),pe.map(e=>{let n=s[e.id];return n?.where===`loose`?(0,U.jsx)(yr,{def:e,spot:n,groups:t,onLost:()=>f(e.id)},`${e.id}:${n.key}`):null}),p&&(0,U.jsx)(gr,{def:p}),(0,U.jsx)(Tr,{groups:t})]})}var Or={half:[.43,.5,.43],y:1},kr=(0,j.memo)(function({floor:e,groups:t}){let n=(0,j.useSyncExternalStore)(_,a),r=(0,j.useMemo)(()=>rr[e].map(e=>e.id),[e]),s=(0,j.useRef)(new Map),c=(0,j.useRef)(new Map),l=(0,j.useMemo)(()=>new Map,[]),u=(0,j.useMemo)(()=>({p:new i,q:new Ke,found:[]}),[]);return A(()=>{let{p:e,q:t}=u;for(let[n,r]of s.current){n.obj.getWorldPosition(e),n.obj.getWorldQuaternion(t);let i=r.translation(),a=r.rotation(),o=Math.abs(i.x-e.x)+Math.abs(i.y-e.y)+Math.abs(i.z-e.z)>.005,s=Math.abs(a.x*t.x+a.y*t.y+a.z*t.z+a.w*t.w)<.99999;(o||s)&&(r.setTranslation(e,!0),r.setRotation(t,!0))}}),Rt(e=>{l.clear(),s.current.size&&e.forEachActiveRigidBody(e=>{if(!e.isDynamic())return;let t=e.linvel();l.set(e.handle,Math.hypot(t.x,t.y,t.z))})}),zt(e=>{let t=je.getState().held,n=t?.kind===`ball`?t.id:null,i=u.found;for(let[t,a]of s.current){if(!a.numColliders())continue;let s=a.collider(0);i.length=0,e.intersectionPairsWith(s,e=>void i.push(e));let u=c.current.get(t),d=null;for(let a of i){let i=a.parent();if(!i||!e.intersectionPair(s,a)||((d??=new Set).add(i.handle),u?.has(i.handle)))continue;let c=i.userData,f=o(c,r);C(f,l.get(i.handle)??0,f===`ball`&&c?.toy===n)&&be(t.id)}d?c.current.set(t,d):c.current.delete(t)}}),n.map(e=>(0,U.jsx)(V,{ref:t=>{t?s.current.set(e,t):(s.current.delete(e),c.current.delete(e))},type:`kinematicPosition`,colliders:!1,position:e.obj.getWorldPosition(new i).toArray(),userData:{seat:e.id},children:(0,U.jsx)(B,{sensor:!0,args:Or.half,position:[0,Or.y,0],collisionGroups:t})},e.key))}),q={r:.17,h:.09,speed:.3,turnRate:1.8,backSpeed:.2,cleanMin:120,cleanMax:180,charge:30,firstCharge:6,stuckAfter:5,spin:1.3},Ar={w:.44,d:.14,h:.26},jr=q.r+.03,Mr=jr+.1,Nr=.2,Pr=.8/(q.cleanMax+90),Fr=.6,Ir=.6,Lr=.45,Rr={office:12.8,lobby:-3.5},zr={office:[[-7.1,-11.3,1],[7.1,-11.3,1],[-15.3,11.2,1.2],[-11,-11.3,1.1],[15.3,11.3,.9]],lobby:[[-7.1,-11.4,1.1],[-15.4,-4.1,.9],[15.3,-4.2,1.1],[7.1,-4.1,.9],[15.3,11.3,1.2],[-15.3,11.3,1.2],[-3,11.4,1],[3,-11.3,.8]]};function Br(e){let t=Rr[e];return{x:t,z:-12+Ar.d+jr+.01,heading:-Math.PI/2,rect:{minX:t-Ar.w/2,maxX:t+Ar.w/2,minZ:-12,maxZ:-12+Ar.d,h:Ar.h}}}function Vr(e){let t=e===`office`?E():w();t.push(u());for(let[n,r,i]of zr[e])t.push(l(n,r,.6*i,.6*i));return t.push(Br(e).rect),t}function Hr(e,t,n,r=jr){if(Math.abs(t)>16-r||Math.abs(n)>12-r)return!1;let i=T(t,n,e,r);return i.x===t&&i.z===n}function Ur(e){let t=Math.round(32/Nr),n=Math.round(24/Nr),r=new Uint8Array(t*n);for(let i=0;i<n;i++)for(let n=0;n<t;n++)r[i*t+n]=+!Hr(e,Wr(n),Gr(i),Mr);return{rects:e,cols:t,rows:n,blocked:r}}var Wr=e=>-16+(e+.5)*Nr,Gr=e=>-12+(e+.5)*Nr,Kr=(e,t)=>Math.min(t-1,Math.max(0,Math.floor((e+16)/Nr))),qr=(e,t)=>Math.min(t-1,Math.max(0,Math.floor((e+12)/Nr)));function Jr(e,t,n,r=jr+.04){let i=Math.max(1,Math.ceil(Math.hypot(n.x-t.x,n.z-t.z)/.08));for(let a=1;a<=i;a++)if(!Hr(e,t.x+(n.x-t.x)*a/i,t.z+(n.z-t.z)*a/i,r))return!1;return!0}function Yr(e,t,n,r){let{cols:i,rows:a,blocked:o}=e;for(let e=0;e<12;e++){let s=-1,c=1/0;for(let l=-e;l<=e;l++)for(let u=-e;u<=e;u++){if(Math.max(Math.abs(u),Math.abs(l))!==e)continue;let d=t+u,f=n+l;if(d<0||f<0||d>=i||f>=a)continue;let p=f*i+d;if(o[p]||r(p))continue;let m=u*u+l*l;m<c&&(c=m,s=p)}if(s>=0)return s}return-1}function Xr(e,t,n,r=null){let{cols:i,rows:a,blocked:o}=e,s=r?r.r+Mr:0,c=e=>!!r&&Math.hypot(Wr(e%i)-r.x,Gr(Math.floor(e/i))-r.z)<s,l=Yr(e,Kr(t.x,i),qr(t.z,a),c),u=Yr(e,Kr(n.x,i),qr(n.z,a),()=>!1);if(l<0||u<0)return null;let d=i*a,f=new Float32Array(d).fill(1/0),p=new Int32Array(d).fill(-1),m=new Uint8Array(d),h=u%i,g=Math.floor(u/i),_=e=>{let t=Math.abs(e%i-h),n=Math.abs(Math.floor(e/i)-g);return Math.max(t,n)+(Math.SQRT2-1)*Math.min(t,n)},v=[],y=(e,t)=>{v.push([e,t]);let n=v.length-1;for(;n>0;){let e=n-1>>1;if(v[e][0]<=v[n][0])break;[v[e],v[n]]=[v[n],v[e]],n=e}},b=()=>{let e=v[0],t=v.pop();if(v.length){v[0]=t;let e=0;for(;;){let t=2*e+1,n=t+1,r=e;if(t<v.length&&v[t][0]<v[r][0]&&(r=t),n<v.length&&v[n][0]<v[r][0]&&(r=n),r===e)break;[v[r],v[e]]=[v[e],v[r]],e=r}}return e[1]},x=(e,t)=>e>=0&&t>=0&&e<i&&t<a&&!o[t*i+e]&&!c(t*i+e);f[l]=0,y(_(l),l);let S=!1;for(;v.length;){let e=b();if(m[e])continue;if(m[e]=1,e===u){S=!0;break}let t=e%i,n=Math.floor(e/i);for(let r=-1;r<=1;r++)for(let a=-1;a<=1;a++){if(!a&&!r||!x(t+a,n+r)||a&&r&&(!x(t+a,n)||!x(t,n+r)))continue;let o=(n+r)*i+t+a,s=f[e]+(a&&r?Math.SQRT2:1);s<f[o]&&(f[o]=s,p[o]=e,y(s+_(o),o))}}if(!S)return null;let C=[];for(let e=u;e>=0;e=p[e])C.push({x:Wr(e%i),z:Gr(Math.floor(e/i))});C.reverse(),C.push({x:n.x,z:n.z});let w=[],T=t,E=0;for(;E<C.length;){let t=E;for(let n=C.length-1;n>E;n--)if(Jr(e.rects,T,C[n])){t=n;break}T=C[t],w.push(T),E=t+1}return w}function Zr(e,t=1){let n=q.charge-q.firstCharge,r=.9;return{x:e.x,z:e.z,heading:e.heading,state:`charging`,move:`idle`,battery:r+.09999999999999998*n/q.charge,stateTime:n,moveTime:0,turnLeft:0,spiralR:0,path:[],cleanFor:q.cleanMin,chargeFrom:r,stuck:0,mark:{x:e.x,z:e.z},waited:0,spinFrom:0,resume:{move:`idle`,moveTime:0},speed:0,seed:t>>>0||1}}function Qr(e){e.seed=e.seed+1831565813>>>0;let t=e.seed;return t=Math.imul(t^t>>>15,t|1),t^=t+Math.imul(t^t>>>7,t|61),((t^t>>>14)>>>0)/4294967296}var $r=(e,t,n)=>t+(n-t)*Qr(e),J=e=>Math.atan2(Math.sin(e),Math.cos(e));function ei(e){return e.state===`charging`?e.battery<.995?`charging`:`docked`:e.state===`returning`||e.state===`docking`?`heading home`:`cleaning`}function ti(e){e.move!==`spin`&&(e.resume={move:e.move,moveTime:e.moveTime},e.spinFrom=e.heading,e.move=`spin`,e.moveTime=q.spin)}var ni=e=>({x:e.x-Math.cos(e.heading)*Ir,z:e.z-Math.sin(e.heading)*Ir});function ri(e,t,n){if(e.speed=0,e.stateTime+=t,e.move===`spin`){e.moveTime-=t;let n=Math.min(1,1-e.moveTime/q.spin);e.heading=e.spinFrom+4*Math.PI*(n*n*(3-2*n)),e.moveTime<=0&&(e.heading=e.spinFrom,e.move=e.resume.move,e.moveTime=e.resume.moveTime),e.state===`charging`&&ai(e);return}if(e.state===`charging`){ai(e),e.stateTime>=q.charge&&(ii(e,`leaving`),e.cleanFor=$r(e,q.cleanMin,q.cleanMax),e.move=`back`,e.moveTime=Fr/q.backSpeed);return}e.battery=Math.max(0,e.battery-Pr*t),e.state===`cleaning`&&(e.stateTime>=e.cleanFor||e.battery<.1)&&hi(e,n);let r=n.player;if(r){let i=r.x-e.x,a=r.z-e.z,o=Math.hypot(i,a);if(o<q.r+.3+.02){let r=o>1e-6?-i/o:-Math.cos(e.heading),s=o>1e-6?-a/o:-Math.sin(e.heading);ci(e,r*q.speed*1.5*t,s*q.speed*1.5*t,t,n),e.stuck=0;return}}switch(e.move){case`wait`:{if(e.stuck=0,e.moveTime-=t,e.moveTime>0)break;let i=r!==null&&oi(e,r);if(e.state===`cleaning`||e.state===`leaving`){i?fi(e,Math.atan2(e.z-r.z,e.x-r.x)+$r(e,-.7,.7)):e.move=`drive`;break}i?(e.waited+=.8,e.moveTime=.8,e.waited>=4&&(e.waited=0,gi(e,n,r))):(e.waited=0,e.move=e.state===`docking`?`park`:`path`);break}case`turn`:{let n=Math.sign(e.turnLeft)*Math.min(Math.abs(e.turnLeft),q.turnRate*t);e.heading=J(e.heading+n),e.turnLeft-=n,Math.abs(e.turnLeft)<1e-4&&pi(e);break}case`back`:if(e.moveTime-=t,ci(e,-Math.cos(e.heading)*q.backSpeed*t,-Math.sin(e.heading)*q.backSpeed*t,t,n)&&e.moveTime>0)break;e.stuck=0,e.state===`leaving`?(ii(e,`cleaning`),fi(e,n.dock.heading+Math.PI+$r(e,-.8,.8))):e.state===`cleaning`?di(e,(Qr(e)<.5?1:-1)*$r(e,2,3.6)):gi(e,n,null);break;case`drive`:if(si(e,r))break;li(e,q.speed,t,n)?Qr(e)<.02*t&&(e.move=`spiral`,e.spiralR=.15,e.moveTime=25):ui(e);break;case`spiral`:if(e.moveTime-=t,e.heading=J(e.heading+q.speed/e.spiralR*t),e.spiralR+=q.speed*.32/(2*Math.PI*e.spiralR)*t,si(e,r))break;li(e,q.speed,t,n)?(e.spiralR>1.4||e.moveTime<=0)&&(e.move=`drive`):ui(e);break;case`follow`:{if(e.moveTime-=t,e.moveTime<=0){di(e,-$r(e,.6,1.4));break}let i=q.speed*t,a=Math.cos(e.heading),o=Math.sin(e.heading);if(!Hr(n.nav.rects,e.x+a*(i+.02),e.z+o*(i+.02))){e.heading=J(e.heading-q.turnRate*t);break}if(Hr(n.nav.rects,e.x-o*.12+a*.05,e.z+a*.12+o*.05)&&(e.heading=J(e.heading+q.speed/.3*t)),si(e,r))break;li(e,q.speed,t,n)||(e.heading=J(e.heading-q.turnRate*t));break}case`path`:{let i=e.path[0];if(!i){ii(e,`docking`),fi(e,n.dock.heading);break}let a=i.x-e.x,o=i.z-e.z,s=Math.hypot(a,o);if(s<.04){e.path.shift();break}let c=J(Math.atan2(o,a)-e.heading);if(Math.abs(c)>.3){e.heading=J(e.heading+Math.sign(c)*Math.min(Math.abs(c),q.turnRate*t));break}if(e.heading=J(e.heading+Math.sign(c)*Math.min(Math.abs(c),q.turnRate*t)),si(e,r))break;li(e,Math.min(q.speed,s/t),t,n)||mi(e,.5);break}case`park`:{let i=Math.hypot(n.dock.x-e.x,n.dock.z-e.z);if(i<.005){e.x=n.dock.x,e.z=n.dock.z,e.heading=n.dock.heading,ii(e,`charging`),e.move=`idle`,e.chargeFrom=e.battery;break}if(e.heading=Math.atan2(n.dock.z-e.z,n.dock.x-e.x),si(e,r))break;li(e,Math.min(.15,i/t),t,n)||mi(e,.8);break}}Math.hypot(e.x-e.mark.x,e.z-e.mark.z)>.2?(e.mark={x:e.x,z:e.z},e.stuck=0):e.move!==`wait`&&(e.stuck+=t,e.stuck>=q.stuckAfter&&(e.stuck=0,e.state===`docking`&&ii(e,`returning`),mi(e,.8)))}function ii(e,t){e.state=t,e.stateTime=0}function ai(e){e.battery=e.chargeFrom+(1-e.chargeFrom)*Math.min(1,e.stateTime/q.charge)}function oi(e,t){let n=t.x-e.x,r=t.z-e.z,i=Math.hypot(n,r);return i<q.r+.3+Lr&&(n*Math.cos(e.heading)+r*Math.sin(e.heading))/i>.35}function si(e,t){return!t||!oi(e,t)?!1:(e.move=`wait`,e.moveTime=.8,!0)}function ci(e,t,n,r,i){let a=e.x+t,o=e.z+n;if(!Hr(i.nav.rects,a,o))return!1;let s=i.player;if(s){let t=q.r+qe+.08,n=Math.hypot(s.x-e.x,s.z-e.z),r=Math.hypot(s.x-a,s.z-o);if(r<t&&r<n)return!1}return e.x=a,e.z=o,e.speed=Math.hypot(t,n)/r,!0}function li(e,t,n,r){return ci(e,Math.cos(e.heading)*t*n,Math.sin(e.heading)*t*n,n,r)}function ui(e){if(Qr(e)<.3){e.move=`follow`,e.moveTime=$r(e,6,14);return}di(e,(Qr(e)<.5?1:-1)*$r(e,Math.PI/2,Math.PI))}function di(e,t){e.move=`turn`,e.turnLeft=t}function fi(e,t){di(e,J(t-e.heading))}function pi(e){e.move=e.state===`docking`?`park`:e.state===`returning`?`path`:`drive`}function mi(e,t){e.move=`back`,e.moveTime=t}function hi(e,t){let n=Xr(t.nav,e,ni(t.dock));if(!n){e.cleanFor+=15;return}ii(e,`returning`),e.path=n,e.move=`path`,e.waited=0}function gi(e,t,n){e.state===`docking`&&ii(e,`returning`);let r=Xr(t.nav,e,ni(t.dock),n?{...n,r:.3}:null)??Xr(t.nav,e,ni(t.dock));e.path=r??[],e.move=r?`path`:`wait`,e.moveTime=.8}var _i=8,vi=.05;function yi({brain:e}){let t=(0,j.useRef)(0),n=(0,j.useRef)([]),r=(0,j.useRef)([]),a=(0,j.useRef)([]),o=(0,j.useMemo)(()=>({foam:new Se(.026,.026,.15,8),tip:new Se(.035,.026,.03,10).translate(0,.09,0)}),[]);(0,j.useEffect)(()=>()=>{o.foam.dispose(),o.tip.dispose()},[o]),Rt(()=>{if(++t.current%4)return;let r=he(e.state,e.x,e.z,D(),q.r),a=0;for(let e of r)Ge(e.id)&&(a++,n.current.push({from:new i(e.x,e.y,e.z),q:new Ke(e.q.x,e.q.y,e.q.z,e.q.w),color:e.color,since:performance.now()}));a&&(Ce(a),n.current.length>_i&&n.current.splice(0,n.current.length-_i),ee())});let s=(0,j.useMemo)(()=>new i,[]);return A(()=>{let t=performance.now();n.current=n.current.filter(e=>t-e.since<ke.animMs),s.set(e.x,vi,e.z);for(let e=0;e<_i;e++){let i=r.current[e];if(!i)continue;let o=n.current[e];if(i.visible=!!o,!o)continue;let c=(t-o.since)/ke.animMs;i.position.lerpVectors(o.from,s,c*c),i.quaternion.copy(o.q),i.scale.setScalar(Math.max(.01,1-c));let l=a.current[e];l&&(l.material=d(o.color))}}),Array.from({length:_i},(e,t)=>(0,U.jsxs)(`group`,{ref:e=>void(r.current[t]=e),visible:!1,children:[(0,U.jsx)(`mesh`,{ref:e=>void(a.current[t]=e),geometry:o.foam,material:d(`#ffffff`)}),(0,U.jsx)(`mesh`,{geometry:o.tip,material:d(`#ffd166`)})]},t))}var bi=`#1f1d2b`,xi=new i(0,1,0),Y={clean:new k(`#4cc9f0`),home:new k(`#ffd166`),charge:new k(`#ff9f1c`),full:new k(`#06d6a0`),off:new k(`#3a3f4b`)},Si=e=>`Roomba · ${ei(e)} (battery ${Math.round(e.battery*100)}%)`;function Ci({brain:e}){let[t,n]=(0,j.useState)(()=>Si(e)),r=ye({id:`toy:roomba`,label:t,action:{kind:`poke`,toyId:`roomba`}},3);return A(()=>{let r=Si(e);r!==t&&n(r)}),(0,U.jsxs)(`mesh`,{ref:r,position:[0,.08,0],children:[(0,U.jsx)(`cylinderGeometry`,{args:[.25,.25,.16,12]}),(0,U.jsx)(`meshBasicMaterial`,{visible:!1})]})}function wi({brain:t,light:n}){let r=(0,j.useRef)(null);A((e,n)=>{let i=r.current;i&&(t.speed>0||t.move===`turn`||t.move===`follow`)&&(i.rotation.y+=Math.min(n,.1)*14)});let{r:i}=q;return(0,U.jsxs)(`group`,{children:[(0,U.jsxs)(`mesh`,{position:[0,.045,0],castShadow:!0,material:d(`#f1f3f5`),children:[(0,U.jsx)(`cylinderGeometry`,{args:[i,i,.07,32]}),(0,U.jsx)(e,{thickness:.01,color:bi})]}),(0,U.jsx)(`mesh`,{position:[0,.04,0],material:d(`#495057`),children:(0,U.jsx)(`cylinderGeometry`,{args:[i+.008,i+.008,.045,24,1,!1,0,Math.PI]})}),(0,U.jsx)(`mesh`,{position:[0,.084,0],material:d(`#ced4da`),children:(0,U.jsx)(`cylinderGeometry`,{args:[.12,.12,.012,28]})}),(0,U.jsx)(`mesh`,{position:[-.02,.092,0],material:d(`#868e96`),children:(0,U.jsx)(`cylinderGeometry`,{args:[.035,.035,.008,16]})}),(0,U.jsx)(`mesh`,{position:[.085,.09,0],material:n,children:(0,U.jsx)(`sphereGeometry`,{args:[.016,10,8]})}),(0,U.jsxs)(`group`,{ref:r,position:[.115,.012,.095],children:[[0,1,2].map(e=>(0,U.jsx)(`mesh`,{rotation:[0,e*2*Math.PI/3,0],position:[0,0,0],material:d(`#adb5bd`),children:(0,U.jsx)(`boxGeometry`,{args:[.13,.006,.008]})},e)),(0,U.jsx)(`mesh`,{material:d(`#495057`),children:(0,U.jsx)(`cylinderGeometry`,{args:[.018,.018,.012,10]})})]})]})}function Ti({dock:t,led:n,groups:r}){let{w:i,d:a,h:o}=Ar,s=(t.rect.minX+t.rect.maxX)/2,c=(t.rect.minZ+t.rect.maxZ)/2,l=Math.atan2(t.x-s,t.z-c);return(0,U.jsxs)(`group`,{position:[s,0,c],rotation:[0,l,0],children:[(0,U.jsx)(V,{type:`fixed`,colliders:!1,children:(0,U.jsx)(B,{args:[i/2,o/2,a/2],position:[0,o/2,0],collisionGroups:r})}),(0,U.jsxs)(`mesh`,{position:[0,o/2,0],castShadow:!0,material:d(`#343a40`),children:[(0,U.jsx)(`boxGeometry`,{args:[i,o,a]}),(0,U.jsx)(e,{thickness:.012,color:bi})]}),(0,U.jsx)(`mesh`,{position:[0,o-.02,0],material:d(`#495057`),children:(0,U.jsx)(`boxGeometry`,{args:[i+.02,.04,a+.02]})}),(0,U.jsx)(`mesh`,{position:[0,o*.62,a/2+.004],material:n,children:(0,U.jsx)(`circleGeometry`,{args:[.022,14]})}),(0,U.jsx)(`mesh`,{position:[0,.004,a/2+.09],material:d(`#2b2d42`),children:(0,U.jsx)(`boxGeometry`,{args:[.3,.008,.18]})}),[-.07,.07].map(e=>(0,U.jsx)(`mesh`,{position:[e,.009,a/2+.06],material:d(`#ced4da`),children:(0,U.jsx)(`boxGeometry`,{args:[.05,.004,.08]})},e))]})}var Ei=(0,j.memo)(function({floor:e,groups:t,dockGroups:n}){let r=Ee(e=>e.camera),i=(0,j.useMemo)(()=>Br(e),[e]),a=(0,j.useMemo)(()=>Zr(i,Math.random()*2**32>>>0),[i]),o=(0,j.useMemo)(()=>({nav:Ur(Vr(e)),dock:i,player:{x:0,z:0}}),[e,i]),s=(0,j.useRef)(null),c=(0,j.useMemo)(()=>({x:0,y:0,z:0}),[]),l=(0,j.useMemo)(()=>new Ke,[]),u=(0,j.useMemo)(()=>new me({color:Y.clean,toneMapped:!1}),[]),d=(0,j.useMemo)(()=>new me({color:Y.off,toneMapped:!1}),[]);return(0,j.useEffect)(()=>()=>{u.dispose(),d.dispose()},[u,d]),(0,j.useEffect)(()=>{let e=0;ce(()=>({x:a.x,z:a.z,state:a.state,battery:Math.round(a.battery*100),spinning:a.move===`spin`,spins:e}));let t=Ie(`roomba`,()=>{a.move!==`spin`&&e++,ti(a),te()});return()=>{ce(null),t()}},[a]),Rt(e=>{let t=s.current;if(!t)return;let n=o.player;n.x=r.position.x,n.z=r.position.z,ri(a,e.timestep,o),c.x=a.x,c.z=a.z,t.setNextKinematicTranslation(c),t.setNextKinematicRotation(l.setFromAxisAngle(xi,-a.heading))}),A(({clock:e})=>{let t=e.elapsedTime,n=a.state===`charging`;a.move===`spin`?u.color.setHSL(t*2%1,.9,.6):n?u.color.copy(a.battery>=.995?Y.full:Y.charge).multiplyScalar(.45+.55*(.5+.5*Math.sin(t*3))):a.state===`returning`||a.state===`docking`?u.color.copy(Math.sin(t*8)>0?Y.home:Y.off):u.color.copy(Y.clean),d.color.copy(n?u.color:Y.off)}),(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(Ti,{dock:i,led:d,groups:n}),(0,U.jsxs)(V,{ref:s,type:`kinematicPosition`,colliders:!1,position:[i.x,0,i.z],rotation:[0,-i.heading,0],userData:{toy:`roomba`},children:[(0,U.jsx)(fn,{args:[q.h/2,q.r],position:[0,q.h/2+.005,0],friction:.3,restitution:.3,collisionGroups:t}),(0,U.jsx)(wi,{brain:a,light:u}),(0,U.jsx)(Ci,{brain:a})]}),(0,U.jsx)(yi,{brain:a})]})}),Di=1/60,X={building:0,doorway:1,pusher:2,toys:3},Oi=xn(X.doorway,[X.toys]),ki=xn(X.pusher,[X.building,X.toys]),Ai=xn(X.toys,[X.building,X.doorway,X.pusher,X.toys]),ji=xn(X.toys,[X.building,X.doorway,X.toys]),Mi=xn(X.building,[X.pusher,X.toys]),Ni=xn(X.toys,[X.toys]),Pi=xn(X.toys,[X.toys]),Fi=u();function Ii({floor:e}){let t=(0,j.useMemo)(()=>e===`office`?E():w(),[e]);return(0,U.jsxs)(V,{type:`fixed`,colliders:!1,children:[(0,U.jsx)(B,{args:[17,.5,16],position:[0,-.5,2],friction:.8,restitution:.5,collisionGroups:Mi}),(0,U.jsx)(B,{args:[17,.5,16],position:[0,n+.5,2],collisionGroups:Mi}),(0,U.jsx)(B,{args:[(Fi.maxX-Fi.minX)/2,n/2,(Fi.maxZ-Fi.minZ)/2],position:[(Fi.minX+Fi.maxX)/2,n/2,(Fi.minZ+Fi.maxZ)/2],collisionGroups:Oi}),t.map((e,t)=>{let n=e.h??3.6;return(0,U.jsx)(B,{args:[(e.maxX-e.minX)/2,n/2,(e.maxZ-e.minZ)/2],position:[(e.minX+e.maxX)/2,n/2,(e.minZ+e.maxZ)/2],friction:.6,restitution:.5,collisionGroups:Mi},t)})]})}var Li={x:0,y:0,z:0},Z={half:.62,y:.95,mass:4,maxSpeed:12,maxImpulse:600*Di,teleport:1.5};function Ri(){let e=Ee(e=>e.camera),t=(0,j.useRef)(null),n=(0,j.useMemo)(()=>({x:0,y:Z.y,z:0}),[]),r=(0,j.useMemo)(()=>({x:0,y:0,z:0}),[]),i=(0,j.useRef)({x:NaN,z:NaN});return Rt(()=>{let a=t.current;if(!a)return;let{x:o,z:s}=e.position,c=i.current,l=o===c.x&&s===c.z;if(c.x=o,c.z=s,l&&a.isSleeping())return;let u=a.translation(),d=o-u.x,f=s-u.z,p=Math.hypot(d,f);if(p>Z.teleport){n.x=o,n.z=s,a.setTranslation(n,!0),a.setLinvel(Li,!0);return}if(l&&p<.002){a.setLinvel(Li,!1);return}let m=Z.maxImpulse*Math.min(1,Math.max(.1,(.7-p)/.4)),h=p>0?Math.min(1/Di,Z.maxSpeed/p):0,g=a.linvel();r.x=Z.mass*(d*h-g.x),r.z=Z.mass*(f*h-g.z);let _=Math.hypot(r.x,r.z);_>m&&(r.x*=m/_,r.z*=m/_),a.applyImpulse(r,!0)}),(0,U.jsx)(V,{ref:t,colliders:!1,position:[e.position.x,Z.y,e.position.z],gravityScale:0,enabledTranslations:[!0,!1,!0],lockRotations:!0,children:(0,U.jsx)(sn,{args:[Z.half,qe],mass:Z.mass,restitution:0,friction:.2,collisionGroups:ki})})}var zi={x:0,y:0,z:0,w:1};function Bi(e,t){e.setTranslation(t.start,!0),e.setRotation(zi,!0),e.setLinvel(Li,!0),e.setAngvel(Li,!0)}var Q={ahead:1,drop:.5,dropPerR:.9,pitch:.55,minPitch:-.7,maxPitch:.4,follow:14,maxSpeed:18,lost:2.2,lostFor:.35,windUp:.25},$={lob:3.2,hard:14,lift:1.6,hardLift:.9,aim:12,flightDamping:.05,walk:1},Vi=1500,Hi=2.5,Ui=new i;function Wi({def:e}){let t=je(t=>t.held?.kind===`ball`&&t.held.id===e.id),n=ye(t?null:{id:`toy:${e.id}`,label:`Pick up ball`,action:{kind:`pickup`,toyId:e.id}},Hi);return A(({camera:r})=>{let i=n.current;if(!i)return;let a=t&&i.getWorldPosition(Ui).distanceTo(r.position)<e.r+.12;i.visible===a&&(i.visible=!a)}),(0,U.jsx)(`group`,{ref:n,children:(0,U.jsx)(ur,{def:e})})}function Gi({floor:e}){let t=rr[e],{world:n}=L(),r=Ee(e=>e.camera),i=(0,j.useRef)([]),a=(0,j.useMemo)(()=>t.map((e,t)=>e=>void(i.current[t]=e)),[t]);(0,j.useEffect)(()=>(de(()=>({bodies:n.bodies.len(),balls:t.map((e,t)=>{let n=i.current[t],r=n?n.translation():e.start;return{id:e.id,x:r.x,y:r.y,z:r.z,sleeping:!n||n.isSleeping()}})})),()=>{de(null),Me()}),[n,t]);let o=(0,j.useRef)(0);zt((0,j.useCallback)(()=>{if(!(++o.current%15))for(let e=0;e<t.length;e++){let n=i.current[e];n&&!n.isSleeping()&&ir(n.translation())&&Bi(n,t[e])}},[t]));let s=(0,j.useRef)(-1),c=(0,j.useRef)(0),l=(0,j.useRef)([]),u=(0,j.useRef)([]),d=(0,j.useMemo)(()=>({x:0,y:0,z:0}),[]),f=(0,j.useCallback)(e=>{e.setGravityScale(0,!0),e.setLinearDamping(0),e.setAngularDamping(3),e.collider(0).setCollisionGroups(ji)},[]),p=(0,j.useCallback)((e,n)=>{let a=i.current[e];if(!a)return;let o=t[e];if(a.setGravityScale(1,!0),a.setAngularDamping(o.damping),l.current[e]=performance.now()+Vi,n===null){a.setLinearDamping(o.damping),d.x=ie.x*.5,d.y=0,d.z=ie.z*.5,a.setLinvel(d,!0);return}r.getWorldDirection(Ui);let s=a.translation();d.x=r.position.x+Ui.x*$.aim-s.x,d.y=r.position.y+Ui.y*$.aim-s.y,d.z=r.position.z+Ui.z*$.aim-s.z;let c=Math.hypot(d.x,d.y,d.z)||1,f=$.lob+((o.throwSpeed??$.hard)-$.lob)*n;d.x=d.x/c*f+ie.x*$.walk,d.y=d.y/c*f+$.lift+($.hardLift-$.lift)*n,d.z=d.z/c*f+ie.z*$.walk,a.setLinearDamping($.flightDamping),a.setLinvel(d,!0),u.current[e]=!0},[r,t,d]),m=(0,j.useMemo)(()=>t.map((e,t)=>()=>{u.current[t]&&(u.current[t]=!1,i.current[t]?.setLinearDamping(e.damping))}),[t]),h=(0,j.useCallback)((e,t,n)=>{let i=Math.min(Q.maxPitch,Math.max(Q.minPitch,r.rotation.x*Q.pitch)),a=r.rotation.y,o=n===null?0:Te(performance.now()-n)*Q.windUp,s=Q.ahead+t-o,c=s*Math.sin(i)-Q.drop-t*Q.dropPerR-o*.4,l=-s*Math.cos(i),u=e.translation(),f=r.position.x+l*Math.sin(a)-u.x,p=r.position.y+c-u.y,m=r.position.z+l*Math.cos(a)-u.z,h=Math.hypot(f,p,m),g=h>0?Math.min(Q.follow,Q.maxSpeed/h):0;return d.x=f*g,d.y=p*g,d.z=m*g,e.setLinvel(d,!0),h},[r,d]);return Rt((0,j.useCallback)(()=>{let e=je.getState(),n=-1;if(e.held?.kind===`ball`)for(let r=0;r<t.length;r++)t[r].id===e.held.id&&(n=r);let a=s.current;if(n!==a){a>=0&&p(a,_e(t[a].id));let e=n>=0?i.current[n]:null;e&&(f(e),u.current[n]=!1,l.current[n]=0),s.current=e?n:-1,c.current=0}let o=s.current;if(o>=0){let n=i.current[o];n&&h(n,t[o].r,e.chargeAt)>Q.lost?(c.current+=Di,c.current>Q.lostFor&&Me()):c.current=0}let d=performance.now();for(let e=0;e<t.length;e++){let n=l.current[e];if(!n)continue;let a=i.current[e];if(!a)continue;let o=a.translation();(d>n||Math.hypot(o.x-r.position.x,o.z-r.position.z)>t[e].r+.3+.15)&&(l.current[e]=0,a.collider(0).setCollisionGroups(Ai))}},[r,t,f,p,h])),t.map((e,t)=>(0,U.jsxs)(V,{ref:a[t],colliders:!1,position:[e.start.x,e.start.y,e.start.z],linearDamping:e.damping,angularDamping:e.damping,ccd:!0,userData:{toy:e.id},onCollisionEnter:m[t],children:[(0,U.jsx)(on,{args:[e.r],restitution:e.restitution,friction:.7,density:e.density,collisionGroups:Ai}),(0,U.jsx)(Wi,{def:e})]},e.id))}function Ki({floor:e}){let t=je(e=>e.travel!==null);return(0,U.jsxs)(Kt,{timeStep:Di,paused:t,numSolverIterations:8,children:[(0,U.jsx)(Ii,{floor:e}),(0,U.jsx)(Ri,{}),(0,U.jsx)(Gi,{floor:e}),(0,U.jsx)(Qn,{floor:e,groups:Mi}),(0,U.jsx)(Ei,{floor:e,groups:Ni,dockGroups:Mi}),(0,U.jsx)(Dr,{floor:e,groups:ji}),(0,U.jsx)(kr,{floor:e,groups:Pi})]})}var qi=(0,j.memo)(Ki);export{qi as default};
@@ -0,0 +1 @@
1
+ .xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}.games-list .game-card:first-of-type{margin-top:4px}.games-blurb{margin:0 2px 12px;line-height:1.45}.games-blurb kbd{font-size:.72rem}.game-card{width:100%;font-family:var(--font);color:var(--ink);text-align:left;border:2.5px solid var(--ink);box-shadow:0 3px 0 var(--ink);cursor:pointer;background:#fff;border-radius:16px;align-items:center;gap:12px;margin-bottom:12px;padding:10px 12px 10px 10px;transition:transform 60ms,box-shadow 60ms;display:flex}.game-card:hover{box-shadow:0 4px 0 var(--ink);transform:translateY(-1px)}.game-card:active{box-shadow:0 1px 0 var(--ink);transform:translateY(2px)}.game-thumb{border:2px solid var(--ink);background:color-mix(in srgb, var(--game) 22%, #fff);border-radius:12px;flex:none}.game-card-text{flex-direction:column;flex:1;gap:1px;min-width:0;display:flex}.game-card-text b{font-size:1.05rem}.game-card-what{color:var(--muted);font-size:.78rem;font-weight:500}.game-card-status{text-overflow:ellipsis;white-space:nowrap;font-size:.78rem;font-weight:600;overflow:hidden}.game-card-go{color:#fff;background:var(--game);border:2px solid var(--ink);text-shadow:0 1px #00000040;border-radius:50%;flex:none;place-items:center;width:30px;height:30px;font-size:.8rem;display:grid}.game{-webkit-user-select:none;user-select:none;flex-direction:column;flex:1;min-height:0;display:flex}.game-head{background:#fff;border-bottom:2px solid #1f1d2b14;align-items:center;gap:8px;padding:8px 10px;display:flex}.game-back{font-family:var(--font);color:var(--ink);cursor:pointer;background:0 0;border:2px solid #1f1d2b4d;border-radius:9px;padding:3px 9px 3px 6px;font-size:.82rem;font-weight:600}.game-back:hover{border-color:var(--ink)}.game-title{color:var(--ink);background:color-mix(in srgb, var(--game) 45%, #fff);border:2px solid var(--ink);border-radius:999px;padding:2px 10px;font-size:.95rem}.game-head-right{align-items:center;min-width:0;margin-left:auto;display:flex}.game-mini{width:32px;height:28px;color:var(--ink);border:2px solid var(--ink);box-shadow:0 2px 0 var(--ink);cursor:pointer;background:#fff;border-radius:9px;font-size:.85rem;line-height:1}.game-mini:active{box-shadow:none;transform:translateY(2px)}.game-chip{text-overflow:ellipsis;white-space:nowrap;border:2px solid var(--ink);background:#fff3b0;border-radius:999px;padding:2px 9px;font-size:.78rem;font-weight:600;overflow:hidden}.game-canvas-wrap{flex:1;justify-content:center;align-items:center;min-height:0;padding:6px 8px;display:flex;overflow:hidden}.game-canvas{touch-action:none;cursor:pointer}.game-keys{text-align:center;color:var(--muted);padding:2px 10px 8px;font-size:.7rem;line-height:1.7}.game-keys kbd{font-size:.66rem}.game-pads{justify-content:center;align-items:center;gap:7px;padding:2px 10px 8px;display:flex}.game-pad-gap{width:10px}.game-pad{width:46px;height:42px;font-family:var(--font);color:var(--ink);border:2.5px solid var(--ink);box-shadow:0 3px 0 var(--ink);cursor:pointer;touch-action:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;background:#fff;border-radius:12px;place-items:center;padding:0;font-size:1.15rem;line-height:1;display:grid}.game-pad:active{box-shadow:0 1px 0 var(--ink);background:#f3f0ff;transform:translateY(2px)}.game-pad-round{background:#eadcff;border-radius:50%;width:46px;height:46px}.game-pad-hot{background:#ffc93c}.game-dpad{grid-template-columns:repeat(3,46px);grid-template-areas:".up.""left down right";justify-content:center;gap:5px 7px;padding:0 10px 6px;display:grid}.game-dpad .game-pad{height:38px}.game-pad-up{grid-area:up}.game-pad-left{grid-area:left}.game-pad-right{grid-area:right}.game-pad-down{grid-area:down}.pet-say{border:2.5px solid var(--ink);min-height:2.3em;box-shadow:0 3px 0 var(--ink);background:#fff;border-radius:14px;align-items:center;margin:10px 14px 2px;padding:7px 12px;font-size:.85rem;font-weight:600;line-height:1.3;display:flex;position:relative}.pet-say:after{content:"";border-right:2.5px solid var(--ink);border-bottom:2.5px solid var(--ink);background:#fff;width:12px;height:12px;position:absolute;bottom:-9px;left:50%;transform:translate(-50%)rotate(45deg)}.pet .game-canvas-wrap{padding-top:10px}.pet-bars{gap:5px;padding:2px 16px 6px;display:grid}.pet-bar{grid-template-columns:82px 1fr;align-items:center;font-size:.8rem;font-weight:600;display:grid}.pet-meter{border:2px solid var(--ink);background:#eef0f6;border-radius:999px;height:13px;overflow:hidden}.pet-meter i{border-right:2px solid var(--ink);border-radius:999px;height:100%;transition:width .5s ease-out;display:block}.pet-bar-low .pet-meter{animation:1s ease-in-out infinite pet-low}@keyframes pet-low{50%{border-color:var(--bad);box-shadow:0 0 0 2px #ef476f59}}.pet-actions{grid-template-columns:repeat(4,1fr);gap:6px;padding:4px 12px 6px;display:grid}.pet-act{flex-direction:column;align-items:center;gap:1px;padding:5px 2px;display:flex}.pet-act-icon{font-size:1.25rem;line-height:1.2}.pet-unbox{grid-column:1/-1;margin:4px 0 12px}:root{--ink:#1f1d2b;--paper:#fffdf6;--muted:#6c7086;--good:#2dc653;--bad:#ef476f;--warn:#ffb703;--accent:#ff8a5b;--font:Fredoka, "Segoe UI", system-ui, sans-serif;--mono:"JetBrains Mono", Consolas, monospace;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}*{box-sizing:border-box}html,body,#root{height:100%;font-family:var(--font);color:var(--ink);background:#bfe3ff;margin:0;overflow:hidden}canvas{display:block}a{color:#3a56d4}kbd{border:2px solid var(--ink);min-width:1.6em;font-family:var(--font);text-align:center;background:#fff;border-bottom-width:4px;border-radius:6px;margin:0 .1em;padding:0 .4em;font-size:.85em;font-weight:600;line-height:1.5;display:inline-block}code{font-family:var(--mono);background:#0000000f;border-radius:5px;padding:1px 5px;font-size:.85em}.muted{color:var(--muted)}.small{font-size:.85rem}.spacer{flex:1}.grow{flex:1;min-width:0}.nowrap{white-space:nowrap}.btn{font-family:var(--font);border:2.5px solid var(--ink);color:var(--ink);box-shadow:0 3px 0 var(--ink);cursor:pointer;white-space:nowrap;background:#fff;border-radius:12px;padding:8px 14px;font-size:.95rem;font-weight:600;transition:transform 60ms,box-shadow 60ms}.btn:hover:not(:disabled){box-shadow:0 4px 0 var(--ink);transform:translateY(-1px)}.btn:active:not(:disabled){box-shadow:0 1px 0 var(--ink);transform:translateY(2px)}.btn:disabled{opacity:.45;cursor:not-allowed}.btn-good{background:#80ed99}.btn-bad{background:#ff8fa3}.btn-ghost{box-shadow:none;background:0 0;border-color:#1f1d2b59}.btn-small{box-shadow:0 2px 0 var(--ink);border-width:2px;border-radius:9px;padding:4px 10px;font-size:.82rem}.btn-ghost.btn-small{box-shadow:none}.btn-big{background:var(--accent);color:#fff;text-shadow:0 2px #0003;box-shadow:0 5px 0 var(--ink);border-radius:18px;padding:14px 32px;font-size:1.3rem}a.btn{text-decoration:none;display:inline-block}input,textarea,select{font-family:var(--font);color:var(--ink);background:#fff;border:2px solid #1f1d2b40;border-radius:10px;outline:none;width:100%;padding:8px 10px;font-size:.95rem}input:focus,textarea:focus,select:focus{border-color:var(--accent)}input[type=checkbox],input[type=radio]{width:auto;accent-color:var(--accent)}input[type=color]{width:42px;height:34px;padding:2px}textarea{resize:vertical}textarea.msg-box{resize:none;flex:1;min-width:0;max-height:calc(8.1em + 20px);line-height:1.35;overflow-y:auto}input.inline{background:0 0;border-color:#0000;padding:4px 6px}input.inline:hover,input.inline:focus{background:#fff;border-color:#1f1d2b40}.row{align-items:center;gap:8px;margin:6px 0;display:flex}.row.wrap{flex-wrap:wrap}.toggle{cursor:pointer;align-items:center;gap:6px;font-size:.92rem;display:inline-flex}.toggle.block{align-items:flex-start;margin:8px 0;display:flex}.pill,.chip{border:2px solid var(--ink);background:#fff;border-radius:999px;align-items:center;gap:4px;padding:3px 10px;font-size:.8rem;font-weight:600;display:inline-flex}.chip{color:var(--ink);border-width:1.5px;padding:1px 8px;font-size:.72rem;text-decoration:none}.chip-good,.pill-ok{background:#b9fbc0}.pill-bad{background:#ffc2d1}.pill-demo{background:#ffd166}.dot{border:2px solid var(--ink);border-radius:50%;width:12px;height:12px;display:inline-block}.agent-chip{align-items:center;gap:5px;font-size:.85rem;font-weight:600;display:inline-flex}.status{border:2px solid var(--ink);text-transform:uppercase;letter-spacing:.03em;border-radius:999px;padding:1px 9px;font-size:.75rem;font-weight:600;display:inline-block}.status-idle{background:#e9ecef}.status-preparing{background:#ffe066}.status-working{background:#74c0fc}.status-done{background:#8ce99a}.status-error{background:#ffa8a8}.status-stopped{background:#dee2e6}.status-installing,.status-starting{background:#ffe066}.status-running{background:#8ce99a}.status-unconfigured{background:#e9ecef}.hud{pointer-events:none;z-index:10;position:fixed;inset:0}.hud>*{pointer-events:auto}.hud-floor{background:var(--paper);border:3px solid var(--ink);box-shadow:0 4px 0 var(--ink);border-radius:18px;align-items:center;gap:12px;max-width:min(520px,100vw - 32px);padding:8px 16px 8px 8px;display:flex;position:absolute;top:16px;left:16px}.floor-num{background:var(--accent);border:3px solid var(--ink);color:#fff;text-shadow:0 2px #00000040;border-radius:12px;flex:none;place-items:center;width:46px;height:46px;font-size:1.5rem;font-weight:700;display:grid}.floor-name{text-overflow:ellipsis;white-space:nowrap;font-size:1.1rem;font-weight:700;overflow:hidden}.floor-sub{color:var(--muted);font-size:.85rem}.hud-status{flex-wrap:wrap;justify-content:flex-end;gap:6px;max-width:50vw;display:flex;position:absolute;top:16px;right:16px}.hud-banner{border:3px solid var(--ink);background:#ffe066;border-radius:14px;max-width:90vw;padding:8px 16px;font-weight:600;position:absolute;top:84px;left:50%;transform:translate(-50%)}.office-chip{max-width:min(420px,100vw - 32px);font-family:var(--font);color:var(--ink);border:2px solid var(--ink);box-shadow:0 3px 0 var(--ink);cursor:pointer;text-align:left;background:#ffe8a3;border-radius:999px;padding:5px 12px;font-size:.8rem;font-weight:600;position:absolute;top:100px;left:16px}.office-chip:hover{transform:translateY(-1px)}.office-chip:focus-visible{outline:3px solid var(--accent,#ff8a5b);outline-offset:2px}.crosshair{border:2px solid var(--ink);pointer-events:none;background:#fff;border-radius:50%;width:8px;height:8px;margin:-4px 0 0 -4px;transition:transform .15s;position:absolute;top:50%;left:50%}.crosshair-hot{background:var(--accent);transform:scale(1.8)}.hud-hint{background:var(--paper);border:3px solid var(--ink);box-shadow:0 4px 0 var(--ink);white-space:nowrap;pointer-events:none;border-radius:14px;padding:8px 16px;font-size:1.05rem;font-weight:600;position:absolute;bottom:22%;left:50%;transform:translate(-50%)}.hud-held{font-size:.95rem;bottom:calc(22% - 56px)}.charge{border:2px solid var(--ink);background:var(--paper);opacity:0;pointer-events:none;border-radius:6px;width:56px;height:9px;margin-left:-28px;transition:opacity .1s;position:absolute;top:calc(50% + 14px);left:50%;overflow:hidden}.charge-on{opacity:1}.charge-fill{transform-origin:0;background:#ffd166;height:100%;transform:scaleX(0)}.charge-full .charge-fill{background:#ff8a5b}.hud-ammo{background:var(--paper);border:3px solid var(--ink);box-shadow:0 4px 0 var(--ink);pointer-events:none;border-radius:14px;flex-direction:column;align-items:flex-end;gap:4px;padding:8px 14px;font-weight:700;display:flex;position:absolute;bottom:72px;right:16px}.hud-ammo-count{font-variant-numeric:tabular-nums;font-size:1.15rem}.hud-ammo-empty .hud-ammo-count{color:#ef476f}.hud-ammo-note{opacity:.75;font-size:.8rem;font-weight:600}.hud-ammo-bar{border:2px solid var(--ink);border-radius:6px;width:100%;min-width:110px;height:8px;overflow:hidden}.hud-ammo-fill{transform-origin:0;background:#ffd166;height:100%;transform:scaleX(0)}.hud-resume{color:#fff;text-shadow:0 2px 0 var(--ink), 0 0 6px var(--ink);pointer-events:none;font-weight:600;position:absolute;top:calc(50% + 26px);left:50%;transform:translate(-50%)}.workers{background:var(--paper);border:3px solid var(--ink);width:min(360px,100vw - 32px);max-height:calc(100vh - 180px);box-shadow:0 4px 0 var(--ink);border-radius:18px;flex-direction:column;display:flex;position:absolute;top:60px;right:16px;overflow:hidden}.workers-closed{width:auto}.wk-head{font-family:var(--font);letter-spacing:.08em;text-transform:uppercase;color:var(--ink);cursor:pointer;text-align:left;background:0 0;border:0;justify-content:space-between;align-items:center;gap:12px;padding:8px 14px;font-size:.8rem;font-weight:600;display:flex}.wk-head b{color:#1e9e45}.wk-chevron{color:var(--muted);letter-spacing:0;text-transform:none}.wk-list{padding:0 6px 6px;overflow-y:auto}.wk-empty{color:var(--muted);padding:4px 10px 8px;font-size:.85rem}.wk-row{width:100%;font-family:var(--font);color:var(--ink);text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:10px;padding:5px 8px 5px 26px;display:grid}.wk-row:hover{background:#1f1d2b0f}.wk-dot{border:2px solid var(--ink);border-radius:50%;width:12px;height:12px}.wk-main{flex-direction:column;min-width:0;display:flex}.wk-name{white-space:nowrap;text-overflow:ellipsis;font-size:.95rem;font-weight:600;overflow:hidden}.wk-task{color:var(--muted);margin-left:6px;font-size:.78rem;font-weight:500}.wk-line{gap:6px;min-width:0;display:flex}.wk-last{min-width:0;font-family:var(--mono);color:var(--muted);white-space:nowrap;text-overflow:ellipsis;flex:auto;font-size:.72rem;overflow:hidden}.wk-last-text{font-family:var(--font);color:var(--ink);font-size:.8rem}.wk-last-thinking{font-style:italic}.wk-last-error{color:var(--bad)}.wk-ago{color:var(--muted);flex:none;font-size:.72rem}.wk-group+.wk-group{margin-top:4px}.wk-group-head{width:100%;font-family:var(--font);letter-spacing:.05em;text-transform:uppercase;color:var(--muted);text-align:left;cursor:pointer;background:0 0;border:0;border-radius:10px;align-items:center;gap:8px;padding:6px 8px 2px;font-size:.75rem;font-weight:600;display:flex}.wk-group-head:hover{color:var(--ink)}.wk-group-arrow{width:10px}.wk-swatch{border:2px solid var(--ink);border-radius:4px;flex:none;width:12px;height:12px}.wk-group-name{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--ink);overflow:hidden}.wk-group-count{color:var(--ink);background:#1f1d2b14;border-radius:999px;margin-left:auto;padding:0 7px}@media (width<=700px){.workers{display:none}}.hud-help{pointer-events:none;background:#fffdf6d9;border-radius:12px;padding:6px 10px;font-size:.85rem;position:absolute;bottom:14px;left:16px}.stats{z-index:60;font:10px/1.2 var(--mono);color:#7cffb2;white-space:nowrap;pointer-events:none;background:#15151fcc;border-bottom-right-radius:8px;padding:1px 8px;position:fixed;top:0;left:0}.fade{opacity:0;pointer-events:none;background:#15151f;place-items:center;transition:opacity .6s;display:grid;position:absolute;inset:0}.fade-in{opacity:1}.fade-label{color:#7cffb2;font-size:3rem;font-weight:700}.toasts{z-index:40;flex-direction:column;align-items:flex-end;gap:8px;max-width:min(420px,100vw - 32px);display:flex;position:absolute;bottom:16px;right:16px}.toast{background:var(--paper);border:3px solid var(--ink);box-shadow:0 4px 0 var(--ink);cursor:pointer;border-radius:14px;padding:10px 14px;font-weight:500;animation:.25s ease-out pop}.toast-success{background:#d8f9df}.toast-error{background:#ffd6de}@keyframes pop{0%{opacity:0;transform:translateY(12px)scale(.95)}}.start{z-index:50;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:radial-gradient(circle at 30% 20%,#ffd6a5bf,#74c0fccc);place-items:center;padding:16px;display:grid;position:fixed;inset:0}.start-card{background:var(--paper);border:4px solid var(--ink);width:min(640px,100%);box-shadow:0 8px 0 var(--ink);text-align:center;border-radius:28px;max-height:calc(100vh - 32px);padding:28px 32px;overflow:auto}.start-logo{color:var(--accent);font-size:4rem;line-height:1;animation:12s linear infinite spin;display:inline-block}@keyframes spin{to{transform:rotate(360deg)}}.start h1{margin:6px 0 4px;font-size:2.6rem}.start-tag{color:var(--muted);margin:0 0 16px;font-size:1.1rem}.start-list{text-align:left;gap:8px;margin:0 0 22px;padding:0;list-style:none;display:grid}.start-meta{color:var(--muted);flex-wrap:wrap;justify-content:center;align-items:center;gap:10px;margin-top:16px;display:flex}.overlay{z-index:30;background:#15151f59;place-items:center;padding:16px;animation:.15s ease-out fadein;display:grid;position:fixed;inset:0}@keyframes fadein{0%{opacity:0}}.panel{background:var(--paper);border:4px solid var(--ink);width:min(640px,100%);max-height:calc(100vh - 32px);box-shadow:0 8px 0 var(--ink);border-radius:24px;flex-direction:column;animation:.2s ease-out pop;display:flex;overflow:hidden}.panel-wide{width:min(1320px,100%);height:calc(100vh - 32px)}.panel-head{background:var(--accent);border-bottom:4px solid var(--ink);align-items:center;gap:10px;padding:12px 16px;display:flex}.panel-title{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:1.25rem;font-weight:700;overflow:hidden}.panel-title a{color:var(--ink)}.panel-x{border:3px solid var(--ink);cursor:pointer;background:#fff;border-radius:12px;flex:none;width:36px;height:36px;font-weight:700}.panel-body{flex-direction:column;flex:1;min-height:0;padding:16px;display:flex;overflow:auto}.help h3{margin:14px 0 4px}.help p{margin:0;line-height:1.55}.mouse-settings{border:2px solid var(--ink);background:#fff8ef;border-radius:12px;flex-direction:column;gap:8px;margin-top:10px;padding:10px 12px;display:flex}.mouse-sens{align-items:center;gap:10px;font-size:.92rem;display:flex}.mouse-sens input[type=range]{max-width:260px;accent-color:var(--accent,#ff8a5b);flex:1}.mouse-sens b{font-variant-numeric:tabular-nums;min-width:3.4em}.sound{gap:10px 18px}.sound-volume{flex:200px;align-items:center;gap:8px;max-width:340px;display:flex}.sound-volume input[type=range]{accent-color:var(--accent);background:0 0;border:0;flex:1;padding:0}.sound-pct{text-align:right;font-variant-numeric:tabular-nums;min-width:3.2em}.elevator{flex-direction:column;gap:10px;display:flex}.floor-btn{text-align:left;border:3px solid var(--ink);box-shadow:0 4px 0 var(--ink);cursor:pointer;font-family:var(--font);background:#fff;border-radius:16px;grid-template-rows:auto auto;grid-template-columns:54px 1fr;align-items:center;column-gap:12px;padding:10px;display:grid}.floor-btn:hover{transform:translateY(-1px)}.floor-btn-here{outline:3px dashed var(--accent);outline-offset:3px;background:#fff4e6}.floor-btn-num{border:3px solid var(--ink);background:var(--accent);color:#fff;text-shadow:0 2px #00000040;border-radius:50%;grid-row:span 2;place-items:center;width:54px;height:54px;font-size:1.5rem;font-weight:700;display:grid}.floor-btn-name{text-overflow:ellipsis;white-space:nowrap;font-size:1.1rem;font-weight:700;overflow:hidden}.floor-btn-meta{color:var(--muted);font-size:.85rem}.term-title{align-items:center;gap:10px;display:flex}.avatar{border:3px solid var(--ink);color:#fff;text-shadow:0 1px #0000004d;border-radius:50%;flex:none;place-items:center;width:34px;height:34px;font-weight:700;display:grid}.term-meta{flex-wrap:wrap;align-items:center;gap:6px 14px;margin-bottom:10px;font-size:.92rem;display:flex}.term-error{word-break:break-word;background:#ffe3e3;border:2px solid #ff8787;border-radius:10px;margin-bottom:8px;padding:6px 10px;font-size:.88rem}.term-split{flex:1;grid-template-columns:1fr;gap:12px;min-height:0;display:grid}.term-split-2{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}.term{color:#e8e8f2;border:3px solid var(--ink);font-family:var(--mono);background:#1b1b29;border-radius:14px;min-height:200px;padding:12px 14px;font-size:13px;line-height:1.5;overflow:auto}.term-line{white-space:pre-wrap;word-break:break-word}.term-tool{color:#8be9fd}.term-result{color:#8d8da8}.term-system{color:#bd93f9}.term-error.term-line,.term-line.term-error{color:#ff6b6b;font-size:inherit;background:0 0;border:none;margin:0;padding:0}.term-manager{color:#ffb86c;font-weight:600}.term-done{color:#50fa7b;font-weight:600}.term-thinking{color:#f1fa8c;font-style:italic}.term-spin{color:#ff9e64;animation:1.4s ease-in-out infinite blink}.live-term{border:3px solid var(--ink);background:#1b1b29;border-radius:14px;flex-direction:column;min-width:0;min-height:200px;display:flex;overflow:hidden}.live-term-screen{flex:1;min-width:0;min-height:0;overflow:hidden}.live-term-screen .xterm{box-sizing:border-box;height:100%;padding:8px 4px 4px 10px}.live-term-foot{color:#8d8da8;border-top:1px solid #2c2c42;align-items:center;gap:8px;padding:4px 12px 6px;font-size:.78rem;display:flex}.live-dot{background:#55566e;border-radius:50%;flex:none;width:8px;height:8px}.live-dot-on{background:#50fa7b;box-shadow:0 0 6px #50fa7b}@keyframes blink{50%{opacity:.55}}.browser{flex-direction:column;gap:6px;min-height:0;display:flex}.browser-bar{border:3px solid var(--ink);text-overflow:ellipsis;white-space:nowrap;background:#e9ecf2;border-bottom:none;border-radius:14px 14px 0 0;padding:6px 12px;font-size:.85rem;overflow:hidden}.browser-view{border:3px solid var(--ink);background:#fff;border-radius:0 0 14px 14px;flex:1;min-height:0;margin-top:-6px;overflow:auto}.browser-view img{width:100%;display:block}.term-input{align-items:flex-end;gap:8px;margin-top:12px;display:flex}.term-actions{flex-wrap:wrap;align-items:center;gap:8px;margin-top:10px;display:flex}.term-actions select{width:auto;max-width:420px}.kanban-toolbar{flex-wrap:wrap;align-items:center;gap:12px;margin-bottom:12px;display:flex}.issue-form{background:#fff;border:3px dashed #1f1d2b4d;border-radius:16px;flex-direction:column;gap:8px;margin-bottom:12px;padding:12px;display:flex}.issue-form .row select{flex:1}.kanban{flex:1;grid-template-columns:repeat(4,minmax(220px,1fr));gap:12px;min-height:0;display:grid;overflow-x:auto}.kcol{border:3px solid var(--ink);background:#f4f1ea;border-radius:18px;flex-direction:column;min-height:0;display:flex;overflow:hidden}.kcol-head{border-bottom:3px solid var(--ink);padding:10px 12px;font-weight:700}.kcol-backlog .kcol-head{background:#ffd166}.kcol-progress .kcol-head{background:#4cc9f0}.kcol-review .kcol-head{background:#80ed99}.kcol-qa .kcol-head{background:#ff9f68}.kanban-5{grid-template-columns:repeat(5,minmax(210px,1fr))}.kcol-merged .kcol-head{background:#c77dff}.count{border:2px solid var(--ink);text-align:center;background:#fff;border-radius:999px;min-width:24px;padding:0 6px;font-size:.8rem;display:inline-block}.kcol-body{flex-direction:column;gap:8px;padding:10px;display:flex;overflow:auto}.kempty{padding:8px}.kcard{border:2.5px solid var(--ink);background:#fff;border-radius:12px;padding:8px 10px;box-shadow:0 3px #1f1d2bcc}.kcard-warn{background:#fff3d6}.kcard-bad{background:#ffe0e6}.kcard-good{background:#e3fbe7}.kcard-title{font-size:.92rem;font-weight:500;line-height:1.35}.kcard-title a{font-weight:700}.kcard-foot{align-items:center;gap:6px;margin-top:6px;display:flex}.kcard-foot select{width:auto;margin-left:auto;padding:3px 6px;font-size:.82rem}.kcard-foot-wrap{flex-wrap:wrap}.panel-app{width:100%;max-width:1600px}.panel-app .panel-body{padding:12px 16px}.app-title{align-items:center;gap:10px;min-width:0;display:flex}.app-title-name,.app-title-ref{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.app-title-name{flex:0 auto}.app-title-ref{color:var(--ink);opacity:.75;flex:0 2 auto;font-weight:500}.app-title .status{flex:none}.app-toolbar{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:10px;display:flex}.app-ref{flex:0 auto;width:260px;min-width:0;padding:5px 8px;font-size:.88rem}.seg{border:2px solid var(--ink);box-shadow:0 2px 0 var(--ink);border-radius:9px;display:inline-flex;overflow:hidden}.seg-btn{font-family:var(--font);color:var(--ink);cursor:pointer;white-space:nowrap;background:#fff;border:0;padding:4px 10px;font-size:.82rem;font-weight:600}.seg-btn+.seg-btn{border-left:2px solid var(--ink)}.seg-btn.seg-on{background:var(--accent)}.seg-btn:focus-visible{outline-offset:-3px;outline:3px solid #3a56d4}.app-stage{border:3px solid var(--ink);background:repeating-linear-gradient(45deg,#efeadf 0 12px,#f6f2e9 12px 24px);border-radius:14px;flex:1;justify-content:center;min-height:280px;display:flex;position:relative;overflow:hidden}.app-frame{background:#fff;border:0;width:100%;height:100%;display:block}.app-stage-phone .app-frame{border-left:3px solid var(--ink);border-right:3px solid var(--ink);width:396px;max-width:100%}.app-frame-hint{border:2.5px solid var(--ink);width:min(560px,100% - 24px);box-shadow:0 3px 0 var(--ink);background:#fff3d6;border-radius:12px;padding:10px 14px;font-size:.9rem;line-height:1.4;position:absolute;bottom:16px;left:50%;transform:translate(-50%)}.app-foot{margin:8px 0 0;line-height:1.4}.app-state{text-align:center;background:#fff;border:3px dashed #1f1d2b4d;border-radius:14px;flex-direction:column;flex:1;align-items:center;gap:10px;min-height:0;padding:24px 16px;display:flex;overflow:auto}.app-state h3{margin:0}.app-state p{max-width:560px;margin:0}.app-state-left{text-align:left;align-items:stretch}.app-state-left p{max-width:none}.app-state-icon{font-size:2.6rem;line-height:1}.app-spin{animation:2.4s linear infinite spin}.app-steps{text-align:left;color:var(--muted);margin:0;padding:0;font-weight:500;list-style:none}.app-steps li{padding:2px 0}.app-step-done{color:#1b873a}.app-step-now{color:var(--ink);font-weight:700}.app-log{text-align:left;white-space:pre-wrap;word-break:break-word;width:100%;max-width:900px;min-height:0;max-height:320px;margin:0;font-size:12px}.app-state-left .app-log{flex:0 auto;max-width:none}.app-settings{width:min(640px,100%)}.preview-form{flex-direction:column;gap:2px;display:flex}.preview-form input,.preview-form textarea{font-family:var(--mono);font-size:.85rem}.preview-form p{margin:2px 0 4px}.preview-details summary{cursor:pointer;font-weight:600}.preview-details summary code{word-break:break-all;font-weight:400}.preview-details[open] summary{margin-bottom:6px}.preview-details .status{font-size:.68rem}@media (width<=520px){.panel-app .panel-body{padding:10px}.app-ref{flex:100%;max-width:none}.app-toolbar .spacer,.app-title-ref{display:none}}.tabs{flex-wrap:wrap;gap:6px;margin-bottom:12px;display:flex}.tab{font-family:var(--font);border:2.5px solid var(--ink);cursor:pointer;background:#fff;border-radius:12px;padding:8px 14px;font-size:.95rem;font-weight:600}.tab-on{background:var(--accent);color:#fff;text-shadow:0 1px #00000040;box-shadow:0 3px 0 var(--ink)}.tab-body{flex:1;min-height:0;overflow:auto}.tab-grid{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr);align-items:start;gap:16px;display:grid}@media (width<=900px){.tab-grid{grid-template-columns:1fr}.kanban,.kanban-5{grid-template-columns:repeat(5,250px)}.term-split-2{grid-template-rows:minmax(200px,1fr) auto;grid-template-columns:1fr}}.section{margin:0 0 10px}.card{border:3px solid var(--ink);background:#fff;border-radius:18px;flex-direction:column;gap:6px;margin-bottom:12px;padding:12px 14px;display:flex}.card h3{margin:0 0 4px}.floor-card{border-left:12px solid var(--accent)}.floor-badge{background:var(--accent);border:2.5px solid var(--ink);color:#fff;text-shadow:0 1px #00000040;border-radius:10px;flex:none;place-items:center;width:36px;height:36px;font-weight:700;display:grid}.office-card{border-left:12px solid var(--ink)}.office-badge{text-shadow:none;background:#fff3c4}.office-card .grow{min-width:190px}.office-state{overflow-wrap:anywhere;font-weight:600}.office-state-ok{color:#1b873a}.office-state-busy{color:#9a5b00}.office-state-bad{color:#c0223b}.office-actions{flex:none;gap:6px;margin-left:auto;display:flex}.repo-list{border:2px solid #1f1d2b1f;border-radius:12px;flex-direction:column;gap:4px;max-height:260px;padding:6px;display:flex;overflow:auto}.repo-list.tall{max-height:520px}.repo-row{border-radius:10px;justify-content:space-between;align-items:center;gap:10px;padding:6px 8px;display:flex}.repo-row:hover{background:#fff4e6}.repo-row select{width:auto}.links{font-size:.85rem}.team{border-collapse:collapse;width:100%}.team td{vertical-align:middle;border-top:1.5px solid #1f1d2b14;padding:4px 6px}.team select{width:auto;padding:4px 6px}.field{flex-direction:column;gap:4px;margin:6px 0;font-size:.9rem;font-weight:600;display:flex}.wizard{text-align:left;width:min(680px,100%)}.wizard h1,.wizard .start-logo,.wizard .start-tag,.wizard h2,.wizard-icon{text-align:center}.wizard h2{margin:4px 0 6px;font-size:1.9rem}.wizard-icon{font-size:3rem;line-height:1.1}.wizard .start-logo{width:fit-content;margin:0 auto;display:block}.wizard .btn-big{margin:0 auto;display:block}.wizard-steps{justify-content:center;gap:8px;margin-bottom:10px;display:flex}.wizard-dot{border:2px solid var(--ink);background:#fff;border-radius:50%;width:12px;height:12px}.wizard-dot-done{background:#80ed99}.wizard-dot-on{background:var(--accent);transform:scale(1.25)}.wizard-nav{align-items:center;gap:10px;margin-top:18px;display:flex}.wizard-done{text-align:center;padding:10px 0}.wizard-done p{margin:6px 0}.ceo-setup{align-items:center;gap:18px;display:flex}.ceo-portrait{flex:none;width:120px;height:120px}.swatch{border:2.5px solid var(--ink);cursor:pointer;border-radius:50%;width:24px;height:24px;padding:0}.swatch-on{box-shadow:0 0 0 3px #fff, 0 0 0 5px var(--ink)}.picker{flex-direction:column;gap:8px;display:flex}.picker-tabs{flex-wrap:wrap;gap:6px;display:flex}.picker-tab{font-family:var(--font);border:2.5px solid var(--ink);cursor:pointer;white-space:nowrap;background:#fff;border-radius:12px;flex:1;padding:8px 10px;font-size:.88rem;font-weight:600}.picker-tab-on{background:var(--accent);color:#fff;text-shadow:0 1px #00000040;box-shadow:0 3px 0 var(--ink)}.picker-mode{flex-direction:column;gap:6px;display:flex}.picker-mode .row{margin:0}.folder-list{max-height:240px}.chip-warn{background:#fff3bf}.tour{z-index:45;background:var(--paper);border:3px solid var(--ink);border-left:10px solid var(--accent);width:min(390px,100vw - 32px);box-shadow:0 5px 0 var(--ink);border-radius:18px;padding:10px 14px;animation:.25s ease-out pop;position:fixed;bottom:16px;left:16px}.tour-cheer{border-left-color:var(--good);background:#eafbee}.tour-head{align-items:center;display:flex}.tour-count{color:var(--muted);font-size:.78rem;font-weight:700}.tour-title{margin:2px 0 4px;font-size:1.1rem;font-weight:700}.tour-body{font-size:.9rem;line-height:1.5}.tour-nav{align-items:center;margin-top:8px;display:flex}.ceo-term{flex:none;height:340px}.job-brief{margin:0 0 8px}.job-brief summary{cursor:pointer;font-weight:600}.job-brief .md{margin-top:4px;line-height:1.45}.confirm-overlay{z-index:60;background:#15151f73;place-items:center;padding:16px;animation:.12s ease-out fadein;display:grid;position:fixed;inset:0}.confirm{background:var(--paper);border:4px solid var(--ink);width:min(440px,100%);box-shadow:0 8px 0 var(--ink);text-align:center;border-radius:24px;padding:20px 22px 14px;animation:.18s ease-out pop}.confirm-danger{border-top:12px solid var(--bad)}.confirm-warn{border-top:12px solid var(--warn)}.confirm-good{border-top:12px solid var(--good)}.confirm-icon{font-size:2.4rem;line-height:1}.confirm h3{margin:8px 0 6px;font-size:1.25rem}.confirm-body{color:#4a4e69;margin-bottom:4px;line-height:1.5}.confirm-actions{justify-content:center;gap:10px;margin-top:14px;display:flex}.confirm-keys{margin-top:10px}.btn-warn{background:#ffd166}.badge{background:var(--bad);color:#fff;border:2px solid var(--ink);border-radius:999px;place-items:center;min-width:20px;height:20px;padding:0 6px;font-size:.72rem;font-weight:700;line-height:1;display:inline-grid}.toasts{bottom:88px}.phone-btn{font-family:var(--font);color:var(--ink);background:var(--paper);border:3px solid var(--ink);box-shadow:0 4px 0 var(--ink);cursor:pointer;border-radius:18px;align-items:center;gap:8px;padding:6px 14px 6px 8px;font-size:.9rem;font-weight:600;display:flex;position:absolute;bottom:16px;right:16px}.phone-btn:hover{transform:translateY(-1px)}.phone-btn-icon{font-size:1.7rem;line-height:1;display:inline-block}.phone-btn-ring .phone-btn-icon{animation:2.4s ease-in-out infinite ring}@keyframes ring{0%,72%,to{transform:rotate(0)}76%{transform:rotate(-16deg)}80%{transform:rotate(14deg)}84%{transform:rotate(-10deg)}88%{transform:rotate(8deg)}}.phone-btn-badge{position:absolute;top:-8px;left:26px}.phone-overlay{background:#15151f47;place-items:end;padding:16px 24px}.phone{border:4px solid var(--ink);width:min(400px,100%);height:min(760px,100vh - 32px);box-shadow:0 10px 0 var(--ink), inset 0 0 0 3px #3b3f5c;background:#23263a;border-radius:38px;flex-direction:column;padding:10px 10px 8px;animation:.22s ease-out slideup;display:flex}@keyframes slideup{0%{opacity:0;transform:translateY(40px)}}.phone-status{color:#e9e9f5;justify-content:space-between;align-items:center;padding:2px 16px 8px;font-size:.8rem;font-weight:600;display:flex}.phone-notch{background:#15151f;border-radius:999px;width:90px;height:18px}.phone-screen{background:var(--paper);border-radius:26px 26px 12px 12px;flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.phone-tabs{gap:4px;padding:8px 4px 2px;display:flex}.phone-tab{color:#b8bbd6;font-family:var(--font);cursor:pointer;background:0 0;border:none;border-radius:14px;flex-direction:column;flex:1;align-items:center;gap:2px;padding:6px 4px;font-size:.78rem;font-weight:600;display:flex}.phone-tab-on{color:#fff;background:#3b3f5c}.phone-tab-icon{font-size:1.3rem;position:relative}.badge-dot{min-width:18px;height:18px;font-size:.65rem;position:absolute;top:-6px;right:-14px}.phone-hint{text-align:center;color:#8e92b3;padding-top:4px;font-size:.72rem}.phone-hint kbd{font-size:.7rem}.phone-scroll{flex:1;padding:12px;overflow:auto}.phone-h{align-items:center;gap:6px;margin:10px 2px 8px;font-size:1rem;display:flex}.phone-h:first-child{margin-top:0}.phone-empty{padding:10px 6px;line-height:1.5}.linkish{color:#3a56d4;font-family:var(--font);cursor:pointer;text-align:left;background:0 0;border:none;padding:0;font-weight:600}.phone-chat{flex-direction:column;flex:1;min-height:0;display:flex}.chat-head{background:#fff;border-bottom:2px solid #1f1d2b14;align-items:center;gap:10px;padding:10px 12px;display:flex}.presence-busy{color:#d9480f;font-weight:600}.chat-log{background:#f4f1ea;flex-direction:column;flex:1;gap:8px;padding:10px;display:flex;overflow:auto}.bubble-row{display:flex}.bubble-row-me{justify-content:flex-end}.bubble{border:2px solid var(--ink);border-radius:16px;max-width:86%;padding:8px 11px 5px;font-size:.9rem;line-height:1.4}.bubble-them{background:#fff;border-bottom-left-radius:4px}.bubble-me{background:#ffd6a5;border-bottom-right-radius:4px}.bubble-from{color:var(--muted);font-size:.72rem;font-weight:700}.bubble-text{white-space:pre-wrap;overflow-wrap:anywhere}.bubble:has(.md pre,.md-table){width:86%}.md{overflow-wrap:anywhere;min-width:0}.md>:first-child{margin-top:0}.md>:last-child{margin-bottom:0}.md p,.md ul,.md ol,.md pre,.md blockquote,.md .md-table{margin:0 0 .55em}.md ul,.md ol{padding-left:1.3em}.md li>ul,.md li>ol{margin:.15em 0 .2em}.md li+li{margin-top:.15em}.md li>p{margin:0}.md h1,.md h2,.md h3,.md h4,.md h5,.md h6{margin:.7em 0 .3em;font-size:1em;line-height:1.25}.md h1{font-size:1.15em}.md h2{font-size:1.08em}.md h5,.md h6{color:var(--muted)}.md a{color:#3a56d4;overflow-wrap:anywhere;font-weight:600}.md a:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-radius:3px}.md-deadlink{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.md code{font-family:var(--mono);background:#1f1d2b14;border-radius:5px;padding:.1em .3em;font-size:.86em}.md pre,.md-table{contain:inline-size;overflow-x:auto}.md pre{background:#1f1d2b14;border-radius:8px;padding:7px 9px;line-height:1.35}.md pre code{white-space:pre;overflow-wrap:normal;background:0 0;padding:0}.md blockquote{color:#4a4e69;border-left:3px solid #1f1d2b40;padding:0 0 0 9px}.md hr{border:none;border-top:1.5px solid #1f1d2b26;margin:.6em 0}.md table{border-collapse:collapse;font-size:.9em}.md th,.md td{text-align:left;overflow-wrap:normal;border:1px solid #1f1d2b33;padding:3px 7px}.md th{background:#1f1d2b0f}.md td code{white-space:nowrap}.md input[type=checkbox]{vertical-align:middle;margin:0 4px 0 0}.md li:has(>input[type=checkbox]){margin-left:-1.1em;list-style:none}.bubble-time{text-align:right;color:var(--muted);margin-top:2px;font-size:.65rem}.bubble-office{text-align:center;color:#4a4e69;background:#1f1d2b12;border-radius:999px;align-self:center;max-width:92%;padding:3px 10px;font-size:.76rem}.bubble-typing{gap:4px;padding:10px 12px;display:flex}.bubble-typing span{background:var(--muted);border-radius:50%;width:7px;height:7px;animation:1.2s infinite typing}.bubble-typing span:nth-child(2){animation-delay:.15s}.bubble-typing span:nth-child(3){animation-delay:.3s}@keyframes typing{0%,60%,to{opacity:.5;transform:translateY(0)}30%{opacity:1;transform:translateY(-4px)}}.quick{background:#fff;gap:6px;padding:6px 10px 0;display:flex;overflow-x:auto}.quick-chip{font-family:var(--font);cursor:pointer;background:#fff;border:1.5px solid #1f1d2b4d;border-radius:999px;flex:none;padding:4px 10px;font-size:.75rem;font-weight:600}.quick-chip:hover{border-color:var(--accent)}.chat-input{background:#fff;align-items:flex-end;gap:6px;padding:8px 10px 10px;display:flex}.resume{border:3px solid var(--ink);color:var(--ink);background:#fff;border-radius:16px;flex-direction:column;gap:6px;margin-bottom:10px;padding:10px 12px;display:flex}.bubble .resume{border-width:2px;margin:6px 0 2px}.resume-letgo{background:#fff4f2}.resume-hot{box-shadow:0 0 0 4px var(--accent)}.resume-done{opacity:.75}.resume-head{align-items:center;gap:10px;display:flex}.resume-name{font-size:1.05rem;font-weight:700}.resume-title{color:var(--muted);font-size:.85rem;font-weight:600}.resume-meta{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.resume-reason{border-left:3px solid #1f1d2b33;padding-left:9px;font-size:.88rem;line-height:1.45}.resume-brief{background:#f6f3ec;border-radius:10px;margin:0;padding:8px;font-size:.82rem;line-height:1.45}.tiles{grid-template-columns:repeat(3,1fr);gap:8px;display:grid}.tile{border:2.5px solid var(--ink);text-align:center;background:#fff;border-radius:14px;padding:8px}.tile-value{white-space:nowrap;font-size:1.15rem;font-weight:700}.tile-label{color:var(--muted);font-size:.7rem;font-weight:600}.report{flex-direction:column;gap:6px;margin:0;padding:0;list-style:none;display:flex}.report li{background:#fff;border:2px solid #1f1d2b1f;border-radius:12px;align-items:flex-start;gap:8px;padding:7px 10px;font-size:.86rem;line-height:1.4;display:flex}.report li.report-good{background:#e7fbe9;border-color:#80ed99}.report li.report-warn{background:#fff4d6;border-color:#ffd166}.proj{border:2.5px solid var(--ink);border-left:10px solid var(--accent);background:#fff;border-radius:14px;margin-bottom:8px;padding:6px 10px 8px}.proj .row{margin:2px 0}.proj .floor-badge{width:30px;height:30px}.proj-name{text-overflow:ellipsis;white-space:nowrap;display:block;overflow:hidden}.proj-sum{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.proj-stats{flex-wrap:wrap;gap:10px;font-weight:600;display:flex}.proj-ready{color:#1b873a}@media (width<=520px){.phone-overlay{place-items:center;padding:8px}.phone-btn-label{display:none}}