pi-straw-boss 0.50.0 → 0.51.1

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.
Files changed (68) hide show
  1. package/README.md +19 -9
  2. package/README.zh-TW.md +19 -9
  3. package/dist/gui/assets/ask-FRar8gzy.js +1 -0
  4. package/dist/gui/assets/chat-Cnwa5u2G.js +2 -0
  5. package/dist/gui/assets/drawer-C9utOrrY.js +1 -0
  6. package/dist/gui/assets/index-FO2Ty88u.css +1 -0
  7. package/dist/gui/assets/index-ssJXzFr1.js +1 -0
  8. package/dist/gui/assets/{lanwait-1tqNsDfl.js → lanwait-CtR4DV4f.js} +1 -1
  9. package/dist/gui/assets/layer-EgjFvD5x.js +3 -0
  10. package/dist/gui/assets/{lightbox-MfTy-vN-.js → lightbox-DuZhRtbe.js} +1 -1
  11. package/dist/gui/assets/link-B6aJ5Y09.js +1 -0
  12. package/dist/gui/assets/pair-BNS75VyE.js +3 -0
  13. package/dist/gui/assets/{picker-CdZJwZaP.js → picker-DZ5Z-CMj.js} +1 -1
  14. package/dist/gui/assets/{server-CcYiCOxA.js → server-nVRtjUSJ.js} +2 -2
  15. package/dist/gui/assets/settings-Dsyd3opg.js +2 -0
  16. package/dist/gui/assets/{spawn-CCzQczfO.js → spawn-BQKu3cNX.js} +1 -1
  17. package/dist/gui/assets/{trust-Bf_itCgj.js → trust-BQmCgkTM.js} +1 -1
  18. package/dist/gui/assets/{unit_count-zv9hdHDK.js → unit_count-DgKn8slE.js} +1 -1
  19. package/dist/gui/assets/views-CDGlbQpm.js +13 -0
  20. package/dist/gui/index.html +32 -21
  21. package/dist/server/{chunk-QVHQNAUG.mjs → chunk-BYPS7OLU.mjs} +179 -52
  22. package/dist/server/cli.mjs +7 -2
  23. package/dist/server/main.mjs +189 -95
  24. package/package.json +1 -1
  25. package/prompts/tower-run.md +1 -1
  26. package/src/agent/cli.ts +13 -4
  27. package/src/agent/legacy.ts +33 -0
  28. package/src/agent/paths.ts +31 -20
  29. package/src/agent/sidecar.ts +8 -24
  30. package/src/boss.ts +17 -4
  31. package/src/bossopen.ts +246 -0
  32. package/src/bosspaths.ts +237 -0
  33. package/src/bridge.ts +3 -2
  34. package/src/control.ts +14 -0
  35. package/src/dialogs.ts +8 -4
  36. package/src/gui.ts +18 -8
  37. package/src/handover.ts +1 -1
  38. package/src/host.ts +11 -2
  39. package/src/index.ts +2 -1
  40. package/src/intercept.ts +16 -9
  41. package/src/link/allow.ts +22 -7
  42. package/src/link/approval.ts +8 -3
  43. package/src/link/gate.ts +8 -3
  44. package/src/link/service.ts +3 -1
  45. package/src/netdata.ts +13 -12
  46. package/src/owners.ts +14 -12
  47. package/src/runallow.ts +75 -0
  48. package/src/runmode.ts +15 -3
  49. package/src/server/cli.ts +7 -2
  50. package/src/server/client.ts +158 -28
  51. package/src/server/guihost.ts +33 -4
  52. package/src/server/guiprefs.ts +25 -0
  53. package/src/server/main.ts +6 -4
  54. package/src/server/record.ts +2 -0
  55. package/src/server/runs.ts +3 -1
  56. package/src/server/socket.ts +97 -42
  57. package/src/server/towerclient.ts +2 -0
  58. package/src/server-look.ts +11 -3
  59. package/src/startof.ts +3 -1
  60. package/dist/gui/assets/ask-DyF8bCRN.js +0 -1
  61. package/dist/gui/assets/chat-BgcA-aNY.js +0 -2
  62. package/dist/gui/assets/drawer-CT88mAQS.js +0 -1
  63. package/dist/gui/assets/index-B8Ea0mR1.js +0 -1
  64. package/dist/gui/assets/index-Bj0Wj2Bi.css +0 -1
  65. package/dist/gui/assets/layer-BBxY5qmM.js +0 -3
  66. package/dist/gui/assets/link-DPtk3xuD.js +0 -1
  67. package/dist/gui/assets/pair-CHVRgr0q.js +0 -3
  68. package/dist/gui/assets/views-DZXa6Ete.js +0 -13
package/README.md CHANGED
@@ -6,15 +6,17 @@ English | [繁體中文](https://github.com/wayne930242/pi-straw-boss/blob/main/
6
6
 
7
7
  **[Try the browser view live](https://wayne930242.github.io/pi-straw-boss/)**: a demo with made-up agents that runs in your browser, nothing to install.
8
8
 
9
- ![The straw net in the browser: its bases with their towers, agents, subagents, and an outpost, in live states, with the alerts and the notices in the header](docs/straw-net-gui.png)
9
+ ![The straw net in the browser in the Standard view: its bases with their towers, agents, and subagents in live states, with the counts and the waiting units in the header](docs/straw-net-gui.png)
10
10
 
11
11
  <p align="center"><sub><code>/boss gui</code>: every workspace of the net, live, in your browser. <a href="docs/straw-net-gui.gif">Watch it move</a>.</sub></p>
12
12
 
13
- <p align="center"><img src="docs/gui-comms.png" width="49%" alt="A unit's comms: its chat as a live log, the messages queued for its next turn, its todo list, its background monitors, and its dossier with documents and dispatched subagents"> <img src="docs/gui-alert.png" width="49%" alt="An alert dialog with the question a unit waits on, answerable from the browser, beside the list of finished units under the header's Done button"></p>
13
+ <p align="center"><img src="docs/gui-comms.png" width="49%" alt="A unit's comms: its chat as a live log, the messages queued for its next turn, its todo list, its background monitors, and its dossier with documents and dispatched subagents"> <img src="docs/gui-alert.png" width="49%" alt="An alert dialog with the question a unit waits on, answerable from the browser, with its options to pick and a note to add"></p>
14
14
 
15
- <p align="center"><img src="docs/gui-phone-map.png" width="220" alt="The map on a phone"> <img src="docs/gui-phone-comms.png" width="220" alt="A unit's comms on a phone"></p>
15
+ <p align="center"><img src="docs/gui-geek.png" width="49%" alt="The Geek view of the map: black, monospace, high contrast, with each unit's state as a tag such as [WORK], [WAIT?], or [ERR!]"> <img src="docs/gui-settings.png" width="49%" alt="The settings page: this device's view (Auto, Standard, or Geek), reminders, sound and volume, and language, with the sections for phones and devices, teams, and the server below"></p>
16
16
 
17
- <p align="center"><sub>A unit's comms, a question you can answer from the browser, and the same page on a phone.</sub></p>
17
+ <p align="center"><img src="docs/gui-phone-map.png" width="220" alt="The map on a phone: the header's and each base's and tab's ⋯ menus, and a finished subagent with its Dismiss button"> <img src="docs/gui-phone-comms.png" width="220" alt="A unit's comms on a phone: the log takes the screen, with the queued messages, todos, and monitors folded above the composer, and the dossier behind Info"></p>
18
+
19
+ <p align="center"><sub>A unit's comms, a question you can answer from the browser, the Geek view, the settings page where each device picks its view, and the same page on a phone.</sub></p>
18
20
 
19
21
  ![Herdr with pi-straw-boss: the sidebar's net view of every workspace, tower, main agent, and subagent, beside a main agent at work](docs/herdr-window.png)
20
22
 
@@ -53,7 +55,7 @@ pi install npm:pi-straw-boss
53
55
  - pi running inside [Herdr](https://herdr.dev) 0.9.4 or newer.
54
56
  - Herdr's pi integration (`herdr integration install pi`): without it Herdr does not name a pane's pi session, and the session cannot join the net; each session warns once, 20 s after its start, when it is missing.
55
57
  - [pi-intercom](https://www.npmjs.com/package/pi-intercom) 0.18.1 or newer: the net's channels, messages, and the GUI's dialog relay run over it, and so does the sb server's connection (it checks the version at start and says so in `start-error.json` and `boss_server status` when pi-intercom is older or missing).
56
- - Windows support is experimental: the extension reaches Herdr over its named pipe there, the sidebar plugin runs with the `node` on `PATH`, and the worktree reaper is macOS and Linux only ([what differs](docs/how-it-works.md#windows)).
58
+ - Windows support is experimental: the extension reaches Herdr over its named pipe there, the sidebar plugin runs with the `node` on `PATH`, the worktree reaper is macOS and Linux only, and the project-trust relay works only while pi's agent folder lies inside your user profile (elsewhere pi asks in its terminal as before) ([what differs](docs/how-it-works.md#windows)).
57
59
 
58
60
  ### Works with
59
61
 
@@ -62,14 +64,14 @@ Each of these is optional. When it is installed, Straw Boss picks it up; without
62
64
  | Package | What Straw Boss does with it |
63
65
  | --- | --- |
64
66
  | [pi-herdr-agents](https://github.com/giuseppecrj/pi-herdr-agents) | Subagents show under the session that launched them, in the tower dashboard, the sidebar, and the GUI; a member that dispatches one is promoted to main and its tower opens. |
65
- | [@juicesharp/rpiv-ask-user-question](https://www.npmjs.com/package/@juicesharp/rpiv-ask-user-question) 2.13 or newer | `ask_user_question` questionnaires can be answered from the GUI, and a waiting one marks its unit as waiting. |
67
+ | [@juicesharp/rpiv-ask-user-question](https://www.npmjs.com/package/@juicesharp/rpiv-ask-user-question) 2.13 or newer | `ask_user_question` questionnaires can be answered or cancelled (the Cancel button, as Escape does in the terminal) from the GUI, and a waiting one marks its unit as waiting. |
66
68
  | [pi-robot-hand](https://www.npmjs.com/package/pi-robot-hand) 0.3.0 or newer | `robot_hand` selectors can be answered from the GUI. |
67
69
  | pi-code (hooks extension, with its dialog events) | Its hook confirmation ("Allow bash?": Allow or Deny, before any gated tool call) can be answered from the GUI. |
68
70
  | [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 or newer | Documents a session shows open beside its comms: HTML in a sandboxed frame whose form answers the agent, text read-only. |
69
71
  | [@juicesharp/rpiv-todo](https://www.npmjs.com/package/@juicesharp/rpiv-todo) 2.13 or newer | A session's todo list shows above its composer in the GUI, read from the session file. |
70
72
  | [straw-boss](https://github.com/wayne930242/straw-boss) (Claude Code and Codex) | A Claude Code or Codex main-agent session joins the tab's net through a small sidecar process that straw-boss starts with the session: a member, or a main when it registers as an orchestrator. It shows in the tower dashboard, the sidebar, and the GUI with an agent badge (the GUI cannot type into it), calls the tower and broadcasts with `straw-net.py`, and hears net messages as `[straw net …]` lines typed into its pane ([how](docs/how-it-works.md#from-claude-code-or-codex)). |
71
73
 
72
- Any extension's `select` and `confirm` (an `mp-infra` command review, say) can be answered from the GUI too, with no change to that extension: Straw Boss wraps them on pi's shared `ctx.ui`, opens pi's own dialog as always, and relays the same dialog; the first answer wins. Both can be answered from a paired device. `input`, `editor`, and `custom` are never touched, and they, with `ask_user` from pi-ask-user, show read-only in the GUI, with the terminal one tap away.
74
+ Any extension's `select` and `confirm` (an `mp-infra` command review, say) can be answered from the GUI too, with no change to that extension: Straw Boss wraps them on pi's shared `ctx.ui`, opens pi's own dialog as always, and relays the same dialog; the first answer wins. Both can be answered from a paired device, and cancelled with the question card's Cancel button (what Escape gives in the terminal: nothing for a select, No for a confirm), except where every choice is for this computer's own page only (such as the `/boss` link approval, or `gui rotate`). `input`, `editor`, and `custom` are never touched, and they, with `ask_user` from pi-ask-user, show read-only in the GUI, with the terminal one tap away.
73
75
 
74
76
  ## Quick start
75
77
 
@@ -100,13 +102,21 @@ The tower only routes and coordinates, so it can run a lighter model: set `tower
100
102
  | `/boss status`, `/boss tower` | Show the status; open and focus the tower. |
101
103
  | `/boss memory [-w workspace]`, `/boss memory confirm P1`, `reject P1`, `add standing\|decision <text>`, `edit S1 <text>`, `delete D1`, `resolve W1` | Read and change the tower's memory from pi: its standing instructions, decisions, and waits, and the proposals the tower made that wait for you. The GUI's Memory panel is the same operation. See [Tower memory](docs/how-it-works.md#tower-memory). |
102
104
  | `/boss server`, `/boss server stop`, `/boss server restart [reason]` | Show the sb server and start it when it is down; stop it on purpose (after a confirm; nothing but a boss command starts it again); restart it (after a confirm) on the same port; the GUI keeps its address, so open pages reconnect by themselves. See [The sb server](docs/how-it-works.md#the-sb-server). |
105
+ | `/boss server logs [n]` | Show the last `n` lines of the sb server's log (default and most 200), as the `boss_server` tool's `logs` does. |
103
106
  | `/boss close` | Quit this session and close its pane. |
104
107
  | `/boss close all` | Quit this base's tower, mains, and members and close it with its shells, without stashing. It is checked first as a stash checks it; anything running that would be lost (a turn, a queued message, a dialog, a monitor, a subagent, a busy shell) closes nothing, and every reason is listed. Other bases are never touched. |
105
108
  | Stash, Stashed, Pop on the page | A base's Stash puts it away under its label; the HUD's Stashed list opens each one again with Pop. A base's Quit is checked first, as `/boss close all` is. |
106
109
  | `/boss stash [name]`, `/boss pop [name]` | Put this whole base away (its tower, mains, members, and idle shells) and close it; open it again later, every pi resumed from its own session file in its old role. A stash refuses, naming why, while anything a resume would lose is there: a running turn, a queued message, an open dialog, a running monitor, a subagent, or a busy shell. |
107
- | `/boss gui`, `/boss gui stop`, `/boss gui rotate` | Open the net in the browser (any session, joins nothing); stop its GUI, from any session. The GUI is served by the sb server, one per machine, so it does not depend on which pi session runs: `/boss gui` starts the server when none runs and prints the URL, and a server that went down comes back when any pi session starts or looks (or from `cli.mjs up`). The URL carries a random token that is kept across a restart, an upgrade, a crash, a reboot, and a `/boss gui stop` followed by `/boss gui` (on the same port, in `gui-secrets.json`), so a page left open reconnects by itself and a phone stays paired. A new token comes only from `/boss gui rotate` (after a confirm; it unpairs every phone and opens the new address), a missing or corrupt `gui-secrets.json`, or a port that was taken at the next start: the old address then answers 403 and a phone scans the QR code again. Keeping the token has a cost you chose: another account on this machine that binds the port during a crash or restart gap sees what an open page sends; rotate after a gap you do not trust. With `STRAW_BOSS_DESK=1` (a desk shell shows the page itself) it opens no browser and the page leaves out Phone and Stash. Only `/boss gui stop` keeps the GUI stopped, until the next `/boss gui` or `cli.mjs up`; `/boss stash` and `/boss close all` do not start a stopped GUI. The header's Server button (this computer's page only) shows the server's state, restarts it, and shows its log. Type into a session from its comms view, or work its terminal with the key pad under the terminal tile, or on a desktop by clicking into it and typing; answer a waiting `robot_hand` selector, `ask_user_question` questionnaire, or pi-code hook confirmation there or in its alert (so can any extension's `select` and `confirm`, also from a paired device; other dialogs show read-only, to answer in the terminal; `secret_drop` always takes its secret in the terminal, never on a page, local or over the tailnet, because pi-intercom identities are self-reported). Documents a session shows with [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 or newer open beside its comms: HTML in a sandboxed frame whose form answers the agent, text read-only. |
110
+ | `/boss close <name\|key>`, `/boss close all <workspace>` | Quit another unit, a squad (tab), or a whole base, after you confirm in pi (the confirm names what quits). A name that fits more than one thing lists the candidates and does nothing; `unit:`, `squad:`, or `base:` before the name narrows it. It posts to the route the page's Quit posts to, so the server's checks stay the same. Bare `/boss close` still quits this session; typed by the boss only, never in a tower run or an ally run. |
111
+ | `/boss stash [name] --workspace <label\|id>` | Put another base away (after a confirm), under `name` or its label. |
112
+ | `/boss dismiss [all\|<name>]` | Hide finished subagents from the net, all of them or one by name, as the page's Dismiss does. |
113
+ | `/boss open base <dir> [label]`, `/boss open member [dir]`, `/boss open main <dir> [prompt]` | The page's + Base, + Member, and + Main, typed. `<dir>` is relative to this session's folder (`~` is home; quote a path with spaces); the server still only takes folders under home. A base opens with one member; a member opens beside this session (or in a tab of its own in `<dir>`); a main opens in a new tab of this base and takes the prompt. A project trust question the new pi waits on is asked in pi. |
114
+ | `/boss link [status]`, `/boss link decide <id> approve\|refuse` | This device's teams and members and the join requests waiting (with a short id), and the page's Approve / Refuse. Approving an attended device shows the team, the device, and the sets of words in pi: pick the set the new computer's screen shows (none of them refuses); approving an unattended device asks first. An unknown or ambiguous id does nothing. A paired phone can read and open but not decide. |
115
+ | `/boss gui`, `/boss gui stop`, `/boss gui rotate` | Open the net in the browser (any session, joins nothing); stop its GUI, from any session. The GUI is served by the sb server, one per machine, so it does not depend on which pi session runs: `/boss gui` starts the server when none runs and prints the URL, and a server that went down comes back when any pi session starts or looks (or from `cli.mjs up`). The URL carries a random token that is kept across a restart, an upgrade, a crash, a reboot, and a `/boss gui stop` followed by `/boss gui` (on the same port, in `gui-secrets.json`), so a page left open reconnects by itself and a phone stays paired. A new token comes only from `/boss gui rotate` (after a confirm; it unpairs every phone and opens the new address), a missing or corrupt `gui-secrets.json`, or a port that was taken at the next start: the old address then answers 403 and a phone scans the QR code again. Keeping the token has a cost you chose: another account on this machine that binds the port during a crash or restart gap sees what an open page sends; rotate after a gap you do not trust. With `STRAW_BOSS_DESK=1` (a desk shell shows the page itself) it opens no browser and the page leaves out Phone & devices and Stash. Only `/boss gui stop` keeps the GUI stopped, until the next `/boss gui` or `cli.mjs up`; `/boss stash` and `/boss close all` do not start a stopped GUI. The settings page's Server section (this computer's page only) shows the server's state, restarts it, and shows its log. Type into a session from its comms view, or work its terminal with the key pad under the terminal tile, or on a desktop by clicking into it and typing; answer a waiting `robot_hand` selector, `ask_user_question` questionnaire, or pi-code hook confirmation there or in its alert (so can any extension's `select` and `confirm`, also from a paired device; other dialogs show read-only, to answer in the terminal; `secret_drop` always takes its secret in the terminal, never on a page, local or over the tailnet, because pi-intercom identities are self-reported). Documents a session shows with [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 or newer open beside its comms: HTML in a sandboxed frame whose form answers the agent, text read-only. |
116
+ | `/boss gui devices`, `/boss gui unpair <id\|all>` | List the paired phones (id, label, Tailscale or Wi-Fi, when paired and last seen) and unpair one (an id or the start of one) or all of them (after a confirm). The address does not change; `/boss gui rotate` is the one that gives a new address. |
108
117
  | `/boss gui lan`, `/boss gui lan off`, `/boss gui lan reset` | Reach the GUI from a phone on the same Wi-Fi, without Tailscale. It is off until you turn it on. This computer makes its own certificate, after showing you the risk: anyone who copies its key from this computer could pose to your phones as private-network sites (your router's page, a NAS) until you remove it from each phone. So use it on your phone's hotspot, or on a Wi-Fi that connects the phone directly to this computer. Each phone installs the certificate once (AirDrop or Quick Share it from the computer, and check it as the screen says), then pairs by QR code or typed code, and you allow each new phone on the computer by typing the number it shows. [How it works](docs/how-it-works.md#browser-view). |
109
- | `/boss gui remote`, `/boss gui remote off` | Reach the GUI from your phone over your tailnet (`tailscale serve`, never Funnel): pair by QR code (or, in an installed app, by the short code shown beside it), and a phone stays paired (90 days from its last use, `remote off` included) until you unpair it in the Phone tile or the GUI gets a new token (a pairing belongs to the token, which a restart keeps; `/boss gui rotate`, a lost `gui-secrets.json`, or a taken port makes a new one and the old pairings are cleared); remote access stays on across a restart or a new server until `remote off`, and a paired phone keeps working after a restart; after a new token a phone pairs again: in the browser by scanning the QR code, in an installed app by typing the pairing code (see below); off removes only its own serve entry. The serve entry points at a second loopback listener of the sb server's GUI, so a request is remote because of the listener it arrived on, whatever headers it carries. The page installs as an app (Add to Home Screen, or Chrome's Install) with a fixed entry, `https://<this machine>.<tailnet>.ts.net:8443/sb-app/`, as its start URL (a token-free address on the tailnet listener only): open with a pairing, it leads to the current page; open without one (after a new token, or on iOS, where the app keeps cookies of its own and scanning the QR in Safari never reaches it), it shows eight boxes for the **pairing code** that `/boss gui remote` prints under the QR (and the Phone tile shows beside it), one character per box (a paste fills them all). The code is 8 characters, shown as two groups of four (`ABCD EFGH`; no hyphen to type), works once within ten minutes, and is void after five wrong tries until you ask this computer for a new one. An app installed before this entry existed opens its old address, which now leads to the entry as well. |
118
+ | `/boss gui view`, `/boss gui view auto\|standard\|geek` | Show or set the GUI's default view. A device on Auto (the page's default) shows it; a device that chose Standard or Geek in its settings keeps its choice, and with the default on `auto` a device follows its screen's contrast setting. Open pages switch at once, and a new page paints it on its first frame (the Geek view and the settings page are pictured at the top). Only this command sets it: no page, paired phone included, can. Showing it (no value) only reads: it starts no server, so one stopped on purpose stays down. |
119
+ | `/boss gui remote`, `/boss gui remote off` | Reach the GUI from your phone over your tailnet (`tailscale serve`, never Funnel): pair by QR code (or, in an installed app, by the short code shown beside it), and a phone stays paired (90 days from its last use, `remote off` included) until you unpair it in the settings page's Phone & devices section or the GUI gets a new token (a pairing belongs to the token, which a restart keeps; `/boss gui rotate`, a lost `gui-secrets.json`, or a taken port makes a new one and the old pairings are cleared); remote access stays on across a restart or a new server until `remote off`, and a paired phone keeps working after a restart; after a new token a phone pairs again: in the browser by scanning the QR code, in an installed app by typing the pairing code (see below); off removes only its own serve entry. The serve entry points at a second loopback listener of the sb server's GUI, so a request is remote because of the listener it arrived on, whatever headers it carries. The page installs as an app (Add to Home Screen, or Chrome's Install) with a fixed entry, `https://<this machine>.<tailnet>.ts.net:8443/sb-app/`, as its start URL (a token-free address on the tailnet listener only): open with a pairing, it leads to the current page; open without one (after a new token, or on iOS, where the app keeps cookies of its own and scanning the QR in Safari never reaches it), it shows eight boxes for the **pairing code** that `/boss gui remote` prints under the QR (and the Phone & devices section shows beside it), one character per box (a paste fills them all). The code is 8 characters, shown as two groups of four (`ABCD EFGH`; no hyphen to type), works once within ten minutes, and is void after five wrong tries until you ask this computer for a new one. An app installed before this entry existed opens its old address, which now leads to the entry as well. |
110
120
  | `node dist/server/cli.mjs up --dir <folder> --label <name>` (a shell, not a pi command) | The desk steps of `up`, for a shell that shows the page itself (straw-boss-desk): with `STRAW_BOSS_DESK=1` set in the environment of `herdr server` and of this command, it installs Herdr's pi integration when it is not current, makes the shell's home base (a workspace in the folder, recorded in `desk.json` and found again by its workspace id), has the sb server stand in for its tower, waits for the GUI, and prints one JSON line with `url`, `workspace`, `pane`, `tower`, `created`, and `integration`. Idempotent: a second run opens nothing. Without the switch it exits 2. See [Desk mode](docs/how-it-works.md#desk-mode-up---dir). |
111
121
 
112
122
  Subagents and sessions in Herdr worktree workspaces never join: the session that launched them speaks for them. Outside Herdr the extension does nothing.
package/README.zh-TW.md CHANGED
@@ -6,15 +6,17 @@
6
6
 
7
7
  **[直接在瀏覽器試用](https://wayne930242.github.io/pi-straw-boss/)**:這是用假資料跑的展示頁,不用安裝任何東西。
8
8
 
9
- ![瀏覽器裡的稻草網:各座基地的塔台、智慧體、子智慧體和前哨,狀態即時更新,頂端有警示和通知](docs/straw-net-gui.png)
9
+ ![標準檢視下瀏覽器裡的稻草網:各座基地的塔台、智慧體和子智慧體,狀態即時更新,頂端有各項計數和等待中的單位](docs/straw-net-gui.png)
10
10
 
11
11
  <p align="center"><sub><code>/boss gui</code>:在瀏覽器即時看整張網的每個工作區。<a href="docs/straw-net-gui.gif">看它動起來</a>。</sub></p>
12
12
 
13
- <p align="center"><img src="docs/gui-comms.png" width="49%" alt="單位的通訊畫面:即時的對話紀錄、排隊等下一輪的訊息、待辦清單、背景 Monitor,以及附有文件和已派出子智慧體的單位檔案"> <img src="docs/gui-alert.png" width="49%" alt="警示對話框裡是單位正在等的問題,可以直接在瀏覽器回答;旁邊是頂端「完成」按鈕打開的已完成清單"></p>
13
+ <p align="center"><img src="docs/gui-comms.png" width="49%" alt="單位的通訊畫面:即時的對話紀錄、排隊等下一輪的訊息、待辦清單、背景 Monitor,以及附有文件和已派出子智慧體的單位檔案"> <img src="docs/gui-alert.png" width="49%" alt="警示對話框裡是單位正在等的問題,可以直接在瀏覽器回答,有選項可選、可以加註"></p>
14
14
 
15
- <p align="center"><img src="docs/gui-phone-map.png" width="220" alt="手機上的地圖"> <img src="docs/gui-phone-comms.png" width="220" alt="手機上的單位通訊畫面"></p>
15
+ <p align="center"><img src="docs/gui-geek.png" width="49%" alt="極客檢視的地圖:黑底、等寬字、高對比,每個單位的狀態以 [WORK]、[WAIT?]、[ERR!] 這類標籤標示"> <img src="docs/gui-settings.png" width="49%" alt="設定頁:這個裝置的檢視(自動、標準或極客)、提醒、音效與音量、語言,下方是手機與裝置、團隊、伺服器各區"></p>
16
16
 
17
- <p align="center"><sub>單位的通訊畫面、可以直接在瀏覽器回答的問題,以及同一個頁面在手機上的樣子。</sub></p>
17
+ <p align="center"><img src="docs/gui-phone-map.png" width="220" alt="手機上的地圖:頂端、每座基地和每個分頁各有一個 ⋯ 選單,已完成的子智慧體有「Dismiss」按鈕"> <img src="docs/gui-phone-comms.png" width="220" alt="手機上的單位通訊畫面:對話紀錄佔滿畫面,排隊訊息、待辦和 Monitor 收合在輸入框上方,單位檔案在「Info」後面"></p>
18
+
19
+ <p align="center"><sub>單位的通訊畫面、可以直接在瀏覽器回答的問題、極客檢視、每個裝置自選檢視的設定頁,以及同一個頁面在手機上的樣子。</sub></p>
18
20
 
19
21
  ![裝了 pi-straw-boss 的 Herdr:側邊欄的網路檢視列出每個工作區、塔台、主智慧體和子智慧體,旁邊是一個正在工作的主智慧體](docs/herdr-window.png)
20
22
 
@@ -53,7 +55,7 @@ pi install npm:pi-straw-boss
53
55
  - pi 要跑在 [Herdr](https://herdr.dev) 0.9.4 以上。
54
56
  - Herdr 的 pi 整合(`herdr integration install pi`):沒有它,Herdr 不會替窗格標出 pi session,該 session 就無法加入網;每個 session 啟動 20 秒後若發現缺少,會警告一次。
55
57
  - [pi-intercom](https://www.npmjs.com/package/pi-intercom) 0.18.1 以上:網的頻道、訊息,以及 GUI 轉送對話框,都是透過它,sb server 的連線也是;版本較舊或沒裝時,sb server 起不來(`start-error.json` 與 `boss_server status` 會說明)。
56
- - Windows 支援是實驗性的:擴充套件在 Windows 上透過 Herdr 的 named pipe 連線,側邊欄 plugin 用 `PATH` 上的 `node` 執行,worktree reaper 則只支援 macOS 和 Linux([差異在哪](docs/how-it-works.md#windows),英文)。
58
+ - Windows 支援是實驗性的:擴充套件在 Windows 上透過 Herdr 的 named pipe 連線,側邊欄 plugin 用 `PATH` 上的 `node` 執行,worktree reaper 只支援 macOS 和 Linux,專案信任(project trust)的轉送則要求 pi 的 agent 資料夾位在你的使用者設定檔(user profile)之內,否則 pi 照舊在終端機裡詢問([差異在哪](docs/how-it-works.md#windows),英文)。
57
59
 
58
60
  ### 支援的套件
59
61
 
@@ -62,14 +64,14 @@ pi install npm:pi-straw-boss
62
64
  | 套件 | Straw Boss 怎麼用它 |
63
65
  | --- | --- |
64
66
  | [pi-herdr-agents](https://github.com/giuseppecrj/pi-herdr-agents) | 子智慧體會顯示在開出它的 session 底下,塔台面板、側邊欄和 GUI 都看得到;成員派出子智慧體時,會升格成主智慧體,塔台也會跟著開。 |
65
- | [@juicesharp/rpiv-ask-user-question](https://www.npmjs.com/package/@juicesharp/rpiv-ask-user-question) 2.13 以上 | `ask_user_question` 問卷可以在 GUI 作答,等待作答的問卷也會讓該單位顯示為等待中。 |
67
+ | [@juicesharp/rpiv-ask-user-question](https://www.npmjs.com/package/@juicesharp/rpiv-ask-user-question) 2.13 以上 | `ask_user_question` 問卷可以在 GUI 作答或取消(「取消」按鈕,等同終端機裡按 Escape),等待作答的問卷也會讓該單位顯示為等待中。 |
66
68
  | [pi-robot-hand](https://www.npmjs.com/package/pi-robot-hand) 0.3.0 以上 | `robot_hand` 選單可以在 GUI 作答。 |
67
69
  | pi-code(hooks 擴充,需含它的對話框事件) | 它的 hook 確認(「Allow bash?」:允許或拒絕,在任何被攔下的工具呼叫之前)可以在 GUI 作答。 |
68
70
  | [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 以上 | session 展示的文件會開在它的通訊畫面旁邊:HTML 放在沙箱框架裡,表單送出的內容會回給 agent;文字檔只能讀。 |
69
71
  | [@juicesharp/rpiv-todo](https://www.npmjs.com/package/@juicesharp/rpiv-todo) 2.13 以上 | session 的待辦清單會顯示在 GUI 的輸入框上方,內容從 session 檔讀取。 |
70
72
  | [straw-boss](https://github.com/wayne930242/straw-boss)(Claude Code 和 Codex) | Claude Code 或 Codex 的主智慧體 session 會透過 straw-boss 隨 session 啟動的小型 sidecar 行程加入分頁的網:預設是成員,登記成 orchestrator 後升成主智慧體。它會出現在塔台儀表板、側邊欄和 GUI(帶智慧體徽章,GUI 無法對它輸入),可以用 `straw-net.py` 呼叫塔台、廣播,網上的訊息會以 `[straw net …]` 開頭的一行打進它的 pane([說明](docs/how-it-works.md#from-claude-code-or-codex),英文)。 |
71
73
 
72
- 任何 extension 的 `select` 和 `confirm`(例如 `mp-infra` 的指令審查)也可以在 GUI 作答,不必改動那個 extension:Straw Boss 把它們包在 pi 共用的 `ctx.ui` 上,照常打開 pi 自己的對話框,同時轉送同一個對話框,先答的算數。`select` 和 `confirm` 都可以從配對的裝置作答。`input`、`editor`、`custom` 完全不碰,它們和 pi-ask-user 的 `ask_user` 在 GUI 裡只能看,可以一鍵切到終端機回答。
74
+ 任何 extension 的 `select` 和 `confirm`(例如 `mp-infra` 的指令審查)也可以在 GUI 作答,不必改動那個 extension:Straw Boss 把它們包在 pi 共用的 `ctx.ui` 上,照常打開 pi 自己的對話框,同時轉送同一個對話框,先答的算數。`select` 和 `confirm` 都可以從配對的裝置作答,也都可以用問題卡片上的「取消」按鈕取消(效果等同終端機裡按 Escape:select 沒有選擇,confirm 回答「否」);但每個選項都只限這台電腦頁面使用的對話框(例如 `/boss` link 核准、`gui rotate`),配對的裝置不能取消。`input`、`editor`、`custom` 完全不碰,它們和 pi-ask-user 的 `ask_user` 在 GUI 裡只能看,可以一鍵切到終端機回答。
73
75
 
74
76
  ## 快速開始
75
77
 
@@ -101,8 +103,16 @@ pi install npm:pi-straw-boss
101
103
  | `/boss close all` | 讓這個基地的塔台、主智慧體和成員結束,連同 shell 一起關掉,不存 stash。會先用 stash 的同一套檢查;有會遺失的東西(正在跑的回合、排隊中的訊息、對話框、Monitor、子智慧體、前景有程式的 shell)就什麼都不關,並列出所有原因。其他基地完全不碰。 |
102
104
  | 網頁上的「收起」「已收起」「接回」 | 基地的「收起」以基地名稱收起它;上方的「已收起」列出收起的基地,按「接回」打開。基地的「關掉」會先檢查,和 `/boss close all` 一樣。 |
103
105
  | `/boss stash [名稱]`、`/boss pop [名稱]` | 把整個基地(塔台、主智慧體、成員和閒置的 shell)收起來並關掉;之後再打開,每個 pi 都從自己的 session 檔接回原本的角色。只要有接回後會遺失的東西就拒絕並說明原因:正在跑的回合、排隊中的訊息、開著的對話框、執行中的 Monitor、子智慧體,或前景有程式在跑的 shell。 |
104
- | `/boss gui`、`/boss gui stop`、`/boss gui rotate` | 在瀏覽器開啟網(任何 session 都能開,不會加入任何東西);停止它的伺服器,在哪個 session 都可以。整台機器只跑一個伺服器,網址會保留(見下):開它的 session `/reload` 之後會重開(網址不變);跑它的 session 結束時(關掉 pane、離開 pi、當機),另一個還開著的 session 會在幾秒內重開它(網址不變)(塔台優先;pi-straw-boss 版本比伺服器舊的 session 要等約六秒才接手,直到下一個較新的 session 再接回去);之後才啟動的 session 也會把停著的伺服器重開,即使所有 session 都離開過或機器重開機;版本較新的 session 會接手,但開著的頁面不會自動換成新版:它會顯示「這個網址已失效」,要用 `/boss gui` 重開。網址裡的 token 會跨過重啟保留:伺服器重啟、升級、當機、重開機,或 `/boss gui stop` 之後再 `/boss gui`,都沿用同一個 token(存在 `gui-secrets.json`,連同埠號),開著的分頁會自行重新連線,手機仍維持配對。只有 `/boss gui rotate`(會先確認;換新 token 與 CSRF 密鑰、解除所有手機的配對並開啟新網址)、`gui-secrets.json` 遺失或損毀,或下次啟動時埠號被占用,才會換新 token:舊網址回 403,手機要重新掃 QR code。保留 token 的代價是你選擇接受的:當機或重啟的空檔裡,這台機器上其他帳號若搶先佔用該埠,會看到開著的頁面送出的內容;對空檔不放心時請 rotate。設了 `STRAW_BOSS_DESK=1`(桌面殼自己顯示頁面)時,它不會開瀏覽器,頁面也不顯示 Phone 與 Stash。只有 `/boss gui stop` 會讓它維持停止,直到下一次 `/boss gui`;`/boss stash` 和 `/boss close all` 不會把停著的伺服器重開。可以在通訊畫面直接打字給某個 session,或用終端機畫面下方的按鍵面板操作它的終端機,在桌面上也可以點進終端機直接打字;在等回覆的 `robot_hand` 選單、`ask_user_question` 問卷或 pi-code 的 hook 確認,可以在那裡或它的警示裡作答(任何 extension 的 `select` 和 `confirm` 也可以,`confirm` 也可以從配對的裝置作答;其他對話框只能看,要回到終端機回答;`secret_drop` 的機密一律在終端機輸入,任何頁面(本機或 tailnet)都不接受,因為 pi-intercom 的身分是自己申報的,無法驗證)。session 用 [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 以上顯示的文件,會開在它的通訊畫面旁邊:HTML 放在沙箱框架裡,表單送出的答案會傳給智慧體;純文字只能讀。 |
105
- | `/boss gui remote`、`/boss gui remote off` | 透過你的 tailnet 用手機連 GUI(`tailscale serve`,絕不用 Funnel):掃 QR code 配對(已安裝的 app 則輸入 QR 旁邊顯示的短配對碼),手機配對後的紀錄會保留(從最後一次使用起算 90 天,重啟與 `remote off` 都不影響),直到你在「手機」視窗解除配對;遠端存取在 stop、`/reload`、換新伺服器之後仍會保持開啟,直到 `remote off`;伺服器重啟後 token 不變,已配對的手機照常使用;GUI 換新 token(`/boss gui rotate`、`gui-secrets.json` 遺失,或埠號被占用)時,舊的配對全部清除(cookie 綁在舊 token 的路徑上),手機要重新配對:瀏覽器掃 QR code,已安裝的 app 輸入配對碼(見下);關閉時只移除它自己的 serve 設定。serve 指向 GUI 伺服器的第二個 loopback 監聽埠,請求算不算遠端取決於它進來的監聽埠,不看它帶什麼標頭。頁面可以安裝成 app(加入主畫面,或 Chrome 的「安裝」):app 的起始網址是固定入口 `https://<這台機器>.<tailnet>.ts.net:8443/sb-app/`(沒有 token,只在 tailnet 監聽埠上):已配對時它會帶你到目前的頁面;沒有配對時(換新 token 後,或 iOS 上 app 有自己的 cookie、在 Safari 掃 QR code 永遠到不了 app),它會顯示 8 個輸入格,輸入 `/boss gui remote` 在 QR code 下方印出的**配對碼**(「手機」視窗也顯示在 QR code 旁),每格一個字元(貼上整組會自動填滿)。配對碼 8 個字元,顯示成兩組各四個(`ABCD EFGH`,不需要輸入連字號),十分鐘內只能用一次,輸錯五次後作廢,要在這台電腦上重新取得新的才能再試。在這個入口出現之前安裝的 app,舊網址現在也會導向入口。 |
106
+ | `/boss close <名稱\|key>`、`/boss close all <工作區>` | 結束另一個單位、小隊(分頁)或整個基地,結束前在 pi 裡確認(確認畫面會列出誰要結束)。名稱對到不只一個時會列出候選並什麼都不做,名稱前加 `unit:`、`squad:` 或 `base:` 可指定種類。它送到網頁「關掉」用的同一個伺服器路由,所以檢查規則不變。單獨的 `/boss close` 仍是結束這個 session;只有老闆打的指令才有效,塔台執行與盟友執行都碰不到。 |
107
+ | `/boss stash [名稱] --workspace <標籤\|id>` | 把另一個基地收起來(先確認),名稱預設為它的標籤。 |
108
+ | `/boss dismiss [all\|<名稱>]` | 把已結束的子智慧體從網路上隱藏,全部或依名稱一個,和網頁的「移除」相同。 |
109
+ | `/boss open base <資料夾> [名稱]`、`/boss open member [資料夾]`、`/boss open main <資料夾> [提示]` | 網頁的「+基地」「+成員」「+主智慧體」,用打字完成。`<資料夾>` 相對於本工作階段的資料夾(`~` 是家目錄;路徑有空格要加引號);伺服器仍只接受家目錄底下的資料夾。基地會附一位成員;成員開在本工作階段旁邊(給資料夾則開在它的新分頁);主智慧體開在本基地的新分頁,可帶提示。新的 pi 若在等專案信任問題,會在 pi 裡問你。 |
110
+ | `/boss link [status]`、`/boss link decide <id> approve\|refuse` | 列出本裝置的團隊與成員,以及等待中的加入要求(附短 id),並做網頁的「核准/拒絕」。核准有人值守的裝置時,pi 會顯示團隊、裝置與各組單字:選新電腦螢幕上顯示的那一組(都不是就是拒絕);核准無人值守的裝置會先確認。id 不存在或不唯一就什麼都不做。已配對的手機能讀、能開單位,但不能決定。 |
111
+ | `/boss gui`、`/boss gui stop`、`/boss gui rotate` | 在瀏覽器開啟網(任何 session 都能開,不會加入任何東西);停止它的伺服器,在哪個 session 都可以。整台機器只跑一個伺服器,網址會保留(見下):開它的 session `/reload` 之後會重開(網址不變);跑它的 session 結束時(關掉 pane、離開 pi、當機),另一個還開著的 session 會在幾秒內重開它(網址不變)(塔台優先;pi-straw-boss 版本比伺服器舊的 session 要等約六秒才接手,直到下一個較新的 session 再接回去);之後才啟動的 session 也會把停著的伺服器重開,即使所有 session 都離開過或機器重開機;版本較新的 session 會接手,但開著的頁面不會自動換成新版:它會顯示「這個網址已失效」,要用 `/boss gui` 重開。網址裡的 token 會跨過重啟保留:伺服器重啟、升級、當機、重開機,或 `/boss gui stop` 之後再 `/boss gui`,都沿用同一個 token(存在 `gui-secrets.json`,連同埠號),開著的分頁會自行重新連線,手機仍維持配對。只有 `/boss gui rotate`(會先確認;換新 token 與 CSRF 密鑰、解除所有手機的配對並開啟新網址)、`gui-secrets.json` 遺失或損毀,或下次啟動時埠號被占用,才會換新 token:舊網址回 403,手機要重新掃 QR code。保留 token 的代價是你選擇接受的:當機或重啟的空檔裡,這台機器上其他帳號若搶先佔用該埠,會看到開著的頁面送出的內容;對空檔不放心時請 rotate。設了 `STRAW_BOSS_DESK=1`(桌面殼自己顯示頁面)時,它不會開瀏覽器,頁面也不顯示設定頁的「手機與裝置」與 Stash。只有 `/boss gui stop` 會讓它維持停止,直到下一次 `/boss gui`;`/boss stash` 和 `/boss close all` 不會把停著的伺服器重開。可以在通訊畫面直接打字給某個 session,或用終端機畫面下方的按鍵面板操作它的終端機,在桌面上也可以點進終端機直接打字;在等回覆的 `robot_hand` 選單、`ask_user_question` 問卷或 pi-code 的 hook 確認,可以在那裡或它的警示裡作答(任何 extension 的 `select` 和 `confirm` 也可以,`confirm` 也可以從配對的裝置作答;其他對話框只能看,要回到終端機回答;`secret_drop` 的機密一律在終端機輸入,任何頁面(本機或 tailnet)都不接受,因為 pi-intercom 的身分是自己申報的,無法驗證)。session 用 [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 以上顯示的文件,會開在它的通訊畫面旁邊:HTML 放在沙箱框架裡,表單送出的答案會傳給智慧體;純文字只能讀。 |
112
+ | `/boss gui devices`、`/boss gui unpair <id\|all>` | 列出已配對的手機(id、標籤、Tailscale 或 Wi-Fi、配對與最後使用時間),並解除配對一支(給 id 或 id 的開頭)或全部(先確認)。網址不會變;要換網址是 `/boss gui rotate`。 |
113
+ | `/boss server logs [n]` | 顯示 sb 伺服器記錄的最後 `n` 行(預設與上限都是 200),和 `boss_server` 工具的 `logs` 相同。 |
114
+ | `/boss gui view`、`/boss gui view auto\|standard\|geek` | 顯示或設定 GUI 的預設檢視。設定頁維持「自動」的裝置會顯示這個預設;自己選了標準或極客的裝置保留自己的選擇;預設為 `auto` 時,裝置依自己螢幕的對比設定。已開啟的頁面立即切換,新開的頁面第一個畫面就是預設檢視(頂端有極客檢視和設定頁的截圖)。只有這個指令能設定:任何頁面(包括已配對的手機)都不行。 |
115
+ | `/boss gui remote`、`/boss gui remote off` | 透過你的 tailnet 用手機連 GUI(`tailscale serve`,絕不用 Funnel):掃 QR code 配對(已安裝的 app 則輸入 QR 旁邊顯示的短配對碼),手機配對後的紀錄會保留(從最後一次使用起算 90 天,重啟與 `remote off` 都不影響),直到你在設定頁的「手機與裝置」區解除配對;遠端存取在 stop、`/reload`、換新伺服器之後仍會保持開啟,直到 `remote off`;伺服器重啟後 token 不變,已配對的手機照常使用;GUI 換新 token(`/boss gui rotate`、`gui-secrets.json` 遺失,或埠號被占用)時,舊的配對全部清除(cookie 綁在舊 token 的路徑上),手機要重新配對:瀏覽器掃 QR code,已安裝的 app 輸入配對碼(見下);關閉時只移除它自己的 serve 設定。serve 指向 GUI 伺服器的第二個 loopback 監聽埠,請求算不算遠端取決於它進來的監聽埠,不看它帶什麼標頭。頁面可以安裝成 app(加入主畫面,或 Chrome 的「安裝」):app 的起始網址是固定入口 `https://<這台機器>.<tailnet>.ts.net:8443/sb-app/`(沒有 token,只在 tailnet 監聽埠上):已配對時它會帶你到目前的頁面;沒有配對時(換新 token 後,或 iOS 上 app 有自己的 cookie、在 Safari 掃 QR code 永遠到不了 app),它會顯示 8 個輸入格,輸入 `/boss gui remote` 在 QR code 下方印出的**配對碼**(設定頁的「手機與裝置」區也顯示在 QR code 旁),每格一個字元(貼上整組會自動填滿)。配對碼 8 個字元,顯示成兩組各四個(`ABCD EFGH`,不需要輸入連字號),十分鐘內只能用一次,輸錯五次後作廢,要在這台電腦上重新取得新的才能再試。在這個入口出現之前安裝的 app,舊網址現在也會導向入口。 |
106
116
  | `node dist/server/cli.mjs up --dir <資料夾> --label <名稱>`(給外殼程式用,不是 pi 指令) | `up` 的桌面步驟,給自己顯示頁面的外殼程式(straw-boss-desk)使用:在啟動 `herdr server` 與執行這個指令的環境都設了 `STRAW_BOSS_DESK=1` 時,它會在 Herdr 的 pi 整合不是最新時安裝,建立外殼的家基地(在該資料夾開一個工作區,記在 `desk.json`,之後以工作區 id 找回),讓 sb server 代替這個工作區的塔台,等 GUI 起來,最後印出一行 JSON,內有 `url`、`workspace`、`pane`、`tower`、`created`、`integration`。重複執行不會多開東西;沒設這個開關時以代碼 2 結束。詳見[桌面模式](docs/how-it-works.md#desk-mode-up---dir)。 |
107
117
 
108
118
  子智慧體,以及在 Herdr worktree 工作區裡的 session,都不會加入網,由開出它們的 session 代表它們。不在 Herdr 裡時,這個擴充套件什麼都不做。
@@ -0,0 +1 @@
1
+ import{t as e}from"./runtime-ZX6HkxDa.js";import{a as t,i as n,n as r,r as i,t as a}from"./sending-aEpvzoz2.js";import{Q as o,jt as s,pt as c}from"./index-ssJXzFr1.js";var l=((t={},n={})=>(n.locale??e())===`zh-TW`?`請在終端機中回答。`:`Answer it in the terminal.`),u=((t={},n={})=>(n.locale??e())===`zh-TW`?`請在終端機中回答。`:`Answer them in the terminal.`),d=((t={},n={})=>(n.locale??e())===`zh-TW`?`下方還有 ▾`:`More below ▾`),f=((t={},n={})=>(n.locale??e())===`zh-TW`?`也可以自己輸入答案。`:`It also takes your own words.`),p=((t={},n={})=>(n.locale??e())===`zh-TW`?`可以複選。`:`It takes several choices.`),m=((t={},n={})=>(n.locale??e())===`zh-TW`?`已取消。`:`Cancelled.`),h=((t={},n={})=>(n.locale??e())===`zh-TW`?`選擇`:`Choices`),g=((t={},n={})=>(n.locale??e())===`zh-TW`?`瀏覽器拒絕存取剪貼簿。`:`The browser refused the clipboard.`),_=((t={},n={})=>(n.locale??e())===`zh-TW`?`已複製到這台裝置的剪貼簿。`:`Copied to this device's clipboard.`),v=((t={},n={})=>(n.locale??e())===`zh-TW`?`複製指令`:`Copy command`),y=((t={},n={})=>(n.locale??e())===`zh-TW`?`這個選項有預覽;請在終端機中查看。`:`It has a preview; see it in the terminal.`),b=((t={},n={})=>(n.locale??e())===`zh-TW`?`備註`:`Note`),x=((t={},n={})=>(n.locale??e())===`zh-TW`?`備註(選填)`:`Note (optional)`),S=e=>`Opened while ${e?.tool} was running; it may not be about that call.`,C=e=>`在 ${e?.tool} 執行時開啟,不一定與該呼叫有關。`,w=((t,n={})=>(n.locale??e())===`zh-TW`?C(t):S(t)),T=((t={},n={})=>(n.locale??e())===`zh-TW`?`選項`:`Options`),E=((t={},n={})=>(n.locale??e())===`zh-TW`?`另一個答案沒有被採用;這個可以送出。`:`The other answer was not taken; this one can go.`),D=((t={},n={})=>(n.locale??e())===`zh-TW`?`你的答案`:`Your own answer`),O=((t={},n={})=>(n.locale??e())===`zh-TW`?`或自己輸入答案`:`Or type your own answer`),k=((t={},n={})=>(n.locale??e())===`zh-TW`?`問題已變更,請重新閱讀。`:`The question changed; read it again.`),A=((t={},n={})=>(n.locale??e())===`zh-TW`?`session 讀不懂這個答案。`:`The session could not read that answer.`),j=((t={},n={})=>(n.locale??e())===`zh-TW`?`這個答案不符合問題。`:`That answer does not fit the question.`),M=((t={},n={})=>(n.locale??e())===`zh-TW`?`session 拒絕了這個答案。`:`The session refused that answer.`),ee=((t={},n={})=>(n.locale??e())===`zh-TW`?`安全考量,遠端不支援輸入機密。請到執行 GUI 的那台電腦的終端機中回答。`:`For security, entering a secret is not supported remotely. Answer it in the terminal on the computer the GUI runs on.`),N=((t={},n={})=>(n.locale??e())===`zh-TW`?`機密內容只能在終端機輸入,這裡不接受。請到執行 GUI 的那台電腦的終端機中回答。`:`A secret is entered in the terminal only, not here. Answer it in the terminal on the computer the GUI runs on.`),P=((t={},n={})=>(n.locale??e())===`zh-TW`?`送出答案`:`Send answer`),F=((t={},n={})=>(n.locale??e())===`zh-TW`?`顯示終端機`:`Show terminal`),I=((t={},n={})=>(n.locale??e())===`zh-TW`?`已在終端機中關閉。`:`It was dismissed in the terminal.`),L=((t={},n={})=>(n.locale??e())===`zh-TW`?`它已不再開啟。`:`It is no longer open.`),R=((t={},n={})=>(n.locale??e())===`zh-TW`?`已在終端機中回答。`:`It was already answered in the terminal.`),z=((t={},n={})=>(n.locale??e())===`zh-TW`?`它在等待對話框。`:`It waits on a dialog.`),B={ArrowDown:1,ArrowRight:1,ArrowUp:-1,ArrowLeft:-1};function V(e,t,n,r,i){let{q:a}=n,o=r[a],s=B[e]??0,c=e===`ArrowUp`,l=c||e===`ArrowDown`,u=()=>({to:r.map((e,t)=>({q:(a+1+t)%r.length,part:`opt`})).find(e=>e.q!==a&&!i[e.q])??`send`});if(e===`Tab`)return t?n.part===`opt`&&a>0?{to:{q:a-1,part:`opt`}}:void 0:a<r.length-1?{to:{q:a+1,part:`opt`}}:void 0;if(!t){if(n.part===`opt`){let t=n.o+s;if(s)return t>=0&&t<o.options?{to:{q:a,part:`opt`,o:t},...o.multiple?{}:{pick:t}}:{to:s>0&&o.own?{q:a,part:`own`}:n};if(e===`Enter`||e===` `&&!o.multiple)return{...u(),...o.multiple?{}:{pick:n.o}}}else if(n.part===`own`){if(e===`Enter`)return u();if(l)return{to:c?{q:a,part:`opt`,o:o.options-1}:{q:a,part:`note`}}}else if(c)return{to:{q:a,part:`own`}}}}function H(e,t,n){let r=e=>Math.max(0,e.opts.findIndex(e=>e.getAttribute(`aria-checked`)===`true`)),i=(e,t)=>e.opts.forEach((e,n)=>e.setAttribute(`tabindex`,n===t?`0`:`-1`)),a=e=>{for(let[n,r]of t.entries()){let t=r.opts.indexOf(e);if(t>=0)return{q:n,part:`opt`,o:t};if(e===r.own||e===r.note)return{q:n,part:e===r.own?`own`:`note`}}};t.forEach(e=>i(e,r(e)));let o=e=>{let n=a(e.target);n?.part===`opt`&&i(t[n.q],n.o)};e.addEventListener(`focusin`,o),e.addEventListener(`click`,o);let s=!1;return e.addEventListener(`keydown`,e=>{let i=a(e.target);if(!i||e.ctrlKey||e.altKey||e.metaKey||e.isComposing)return;let o=e.target;if(i.part!==`opt`&&(e.key===`ArrowUp`?o.selectionStart!==0:e.key===`ArrowDown`&&o.selectionEnd!==o.value.length))return;let c=V(e.key,e.shiftKey,i,t.map(e=>({options:e.opts.length,multiple:e.multiple,own:!!e.own})),t.map(e=>e.answered()));if(!c||(e.preventDefault(),e.repeat&&[`Enter`,` `].includes(e.key)))return;if(s=e.key===` `,c.pick!==void 0){let e=t[i.q].opts[c.pick];e.getAttribute(`aria-checked`)!==`true`&&e.click()}let l=c.to===`send`?void 0:t[c.to.q],u=c.to===`send`?n():c.to.part===`opt`?l.opts[c.to.o??r(l)]:c.to.part===`own`?l.own:l.note;u&&!u.disabled&&u.focus()}),e.addEventListener(`keyup`,e=>s&&e.key===` `&&(s=!1,e.preventDefault())),()=>t[0]?.opts[r(t[0])]}var U=e=>e.multiple?p():e.freeform&&e.options.length?f():``,W=(e,t)=>o(`div`,{class:`ask-one`},e.header&&o(`b`,{class:`ask-head`},e.header),o(`p`,{class:`ask-q`},e.question),e.context&&o(`div`,{class:`ask-ctx`},e.context),e.options.length>0&&o(`ol`,{class:`ask-opts`,"aria-label":T()},...e.options.map(e=>o(`li`,{class:`ask-opt`},o(`b`,null,e.title),e.description&&o(`small`,null,e.description)))),t&&U(e)&&o(`small`,{class:`ask-how`},U(e))),G=e=>e.replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f\p{Cf}]/gu,`�`),K=e=>(e.select?.choices??[]).map((e,t)=>({...e,i:t})),q=(e,t,n)=>({...e.size?{choices:[...e].sort((e,t)=>e-t)}:{},...t.trim()?{text:t}:{},...n.trim()?{note:n}:{}}),J=(e,t,n)=>({dialog:e.dialog,digest:e.digest,answerId:n,...t}),Y=(e,t)=>({dialog:e.dialog,digest:e.digest,answerId:t,cancel:!0}),X=(e,t)=>e.cancel===!0&&!(t&&e.select?.choices.every(e=>e.hereOnly)),Z={digest:k,"not-allowed":j,malformed:A};function Q(e,i=!1){let{outcome:a,reason:o,by:s}=e.body;return a===`accepted`?[`ok`,i?m():n()]:a===`stale`?[`error`,s===`local`?R():s===`cancel`?I():L()]:a===`rejected`?[`error`,(Object.hasOwn(Z,String(o))?Z[String(o)]:M)()]:a===`busy`?[`error`,t()]:a===`unknown`||e.status===504?[`error`,r(),!0]:[`error`,o??c({status:e.status})]}var te=e=>[`accepted`,`stale`,`busy`,`unknown`].includes(String(e.body.outcome))||e.status===504,$=e=>e.answer?`d\n${e.answer.dialog}\n${e.answer.digest}`:`c\n${e.callId}\n${e.why??``}`;function ne(e){if(e.dataset.cued)return;e.dataset.cued=`1`;let t=()=>{e.toggleAttribute(`data-more`,e.scrollHeight-e.scrollTop-e.clientHeight>4);for(let t of e.querySelectorAll(`.ask-acts`))t.dataset.cue=d()};for(let n of[`scroll`,`input`])e.addEventListener(n,t,{passive:!0});typeof ResizeObserver<`u`&&new ResizeObserver(t).observe(e),typeof MutationObserver<`u`&&new MutationObserver(t).observe(e,{childList:!0,subtree:!0,characterData:!0}),typeof requestAnimationFrame<`u`&&requestAnimationFrame(t)}function re(e,t,n=location.hostname!==`127.0.0.1`,c,d){let f,p,m,S=!1,C=!1,k;for(let e of[`focusin`,`pointerdown`])document.addEventListener(e,e=>p&&!p.el.contains(e.target)&&(p.lost=void 0));let A=(e,t,n,...r)=>(e.dataset.tone=t,e.replaceChildren(n,...r)),j=()=>{if(!p)return;let e=document.activeElement;e&&e!==document.body&&e!==p.lost&&(p.lost=void 0),p.controls.forEach(e=>e.disabled=!S||C||p.done),p.send&&(p.send.disabled=!S||C||p.done||!p.pick()),e&&p.el.contains(e)&&e.disabled&&(p.lost=e);let t=p.lost;t&&!t.disabled&&p.el.contains(t)&&(!document.activeElement||document.activeElement===document.body)&&(t.focus(),p.lost=void 0)};async function M(e,n){[e.sending,C,e.spell]=[!0,!0,!1],j(),A(e.note,``,a());let s=await t(`answer`,n).catch(()=>void 0),c=o(`button`,{type:`button`,class:`cmp-link`},i());c.onclick=()=>void M(e,n);let[l,u,f]=s?Q(s,n.cancel===!0):[`error`,r(),!0];[e.done,e.sending,C,e.busy]=[!s||te(s),!1,!1,s?.body.outcome===`busy`],A(e.note,l,u,...f?[c]:[]),j(),e.note.scrollIntoView?.({block:`nearest`}),d&&s?.body.outcome===`accepted`&&setTimeout(d,1200)}let I=(e,t,n,r,i)=>{let a=o(`button`,{type:`button`,class:`ask-opt`,role:e,"aria-checked":`false`},o(`b`,i?{"data-n":String(i)}:null,t),...n.filter(Boolean).map(e=>o(`small`,null,e)));return a.onclick=r,a};function L(e,t){let r,i=K(t).map(e=>I(`radio`,G(e.label),[e.note&&G(e.note)],()=>(r=e.i,i.forEach((n,r)=>n.setAttribute(`aria-checked`,String(K(t)[r].i===e.i))),j()),e.i+1)),a=t.select?.copy!==void 0&&o(`button`,{type:`button`,class:`cmp-link`},v());a&&(a.disabled=!navigator.clipboard,a.onclick=()=>void navigator.clipboard.writeText(t.select.copy).then(()=>A(e.note,`ok`,_()),()=>A(e.note,`error`,g())));let s=i.filter((e,r)=>!(n&&K(t)[r].hereOnly));return i.forEach(e=>!s.includes(e)&&(e.disabled=!0)),e.pick=()=>r===void 0?void 0:{choice:r},e.first=H(e.el,[{opts:i,multiple:!1,answered:()=>r!==void 0}],()=>e.send),e.controls=s,[o(`pre`,{class:`ask-title`},G(t.select.title)),o(`div`,{class:`ask-opts`,role:`radiogroup`,"aria-label":h()},...i),o(`div`,{class:`ask-acts`},e.send,e.cancel,a)]}function R(e,t){let n=t.questions.map(()=>({picks:new Set,text:o(`textarea`,{rows:`1`,maxlength:`8192`,class:`ask-own`,placeholder:O(),"aria-label":D()}),note:o(`input`,{type:`text`,maxlength:`2048`,class:`ask-own ask-memo`,placeholder:x(),"aria-label":b()})})),r=[],i=t.questions.map((t,i)=>{let a=n[i],s=t.multiple?`checkbox`:`radio`,c=t.options.map((e,n)=>I(s,e.title,[e.description,e.preview&&y()],()=>{t.multiple||(a.picks.clear(),a.text.value=``),a.picks.has(n)?a.picks.delete(n):a.picks.add(n),c.forEach((e,t)=>e.setAttribute(`aria-checked`,String(a.picks.has(t)))),j()}));return a.text.oninput=()=>(t.multiple||(a.picks.clear(),c.forEach(e=>e.setAttribute(`aria-checked`,`false`))),j()),e.controls.push(...c,a.text,a.note),r.push({opts:c,multiple:!!t.multiple,own:a.text,note:a.note,answered:()=>a.picks.size>0||a.text.value.trim()!==``}),o(`div`,{class:`ask-one`},t.header&&o(`b`,{class:`ask-head`},t.header),o(`p`,{class:`ask-q`},t.question),o(`div`,{class:`ask-opts`,role:t.multiple?`group`:`radiogroup`,"aria-label":T()},...c),a.text,a.note)});return e.pick=()=>n.every(e=>e.picks.size||e.text.value.trim())?{answers:n.map(e=>q(e.picks,e.text.value,e.note.value))}:void 0,e.first=H(e.el,r,()=>e.send),[...i,o(`div`,{class:`ask-acts`},e.send,e.cancel)]}function B(e){let t=e.asks??(e.ask?[e.ask]:[]),r=t.length>1,i=e.answer,a={key:$(e),el:o(`section`,{class:`ask`}),note:o(`p`,{class:`ask-note`,role:`status`,"aria-live":`polite`}),controls:[],pick:()=>void 0,done:!1,sending:!1};i&&((a.send=o(`button`,{type:`button`,class:`ask-send`},P())).onclick=()=>void(a.pick()&&M(a,J(i,a.pick(),crypto.randomUUID())))),i&&X(i,n)&&((a.cancel=o(`button`,{type:`button`,class:`ask-cancel`},s())).onclick=()=>void M(a,Y(i,crypto.randomUUID())));let d=e.tool===`secret_drop`,f=o(`p`,{class:`ask-term`},e.why&&t.length?e.why:`${r?u():l()} ${r||!t[0]?``:U(t[0])}`.trim()),p=c&&e.tool!==`secret_drop`&&o(`button`,{type:`button`,class:`cmp-link`},F());p&&(p.onclick=c);let m=e.answer?.twin&&e.tool&&e.tool!==`dialog`?[o(`p`,{class:`ask-why`},w({tool:e.tool}))]:[];return a.el.append(...m,...i&&!d?i.select?L(a,i):R(a,i):[...t.length?t.map(e=>W(e,r)):[o(`p`,{class:`ask-why`},d?n?ee():N():e.why??z())],o(`div`,{class:`ask-acts`},d?o(`p`,{class:`ask-term`},l()):f,p)],a.note),a.cancel&&a.controls.push(a.cancel),a}let V=(t,n)=>{let r=document.activeElement;p&&p!==n&&(p.focus=p.el.contains(r)?r:void 0),[f,p,m]=[t,n,n?.send?n:m],e.replaceChildren(...n?[n.el]:[]),n&&ne(n.el),j(),n?.focus&&(!document.activeElement||document.activeElement===document.body)&&n.focus.focus()};return{enter(){let e=p&&!p.done?p.first?.():void 0;return!!(e&&!e.disabled&&(e.focus(),1))},update(e,t){S=t,e&&(k=void clearTimeout(k)),!e&&(p?.done||p?.sending)?k??=setTimeout(()=>(k=void 0,V()),6e3):e?p&&($(e)===p.key||!e.answer&&(p.done||p.sending)&&e.callId===f?.callId)?((p.busy||p.sending)&&!e.answer?p.spell=!0:p.busy&&p.spell&&e.answer&&([p.done,p.busy]=[!1,!1],A(p.note,``,E())),f=e):V(e,m?.key===$(e)&&!m.done?m:B(e)):V(),j()}}}export{re as t};
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-FO2Ty88u.css"])))=>i.map(i=>d[i]);
2
+ import{t as e}from"./runtime-ZX6HkxDa.js";import{O as t,Q as n,d as r,et as i,h as a,n as o,w as s}from"./index-ssJXzFr1.js";import{a as c,i as l,n as u,o as d,r as ee,t as te}from"./views-CDGlbQpm.js";var ne=((t={},n={})=>(n.locale??e())===`zh-TW`?`可能已被當機的 run 處理過:動手前先確認。`:`A run that crashed may already have handled this: check before acting.`),re=((t={},n={})=>(n.locale??e())===`zh-TW`?`分支摘要`:`branch summary`),ie=((t={},n={})=>(n.locale??e())===`zh-TW`?`通訊紀錄`:`Comms log`),f=e=>`context compacted · ${e?.tokens} tokens summarized`,p=e=>`上下文已壓縮 · 摘要了 ${e?.tokens} tokens`,ae=((t,n={})=>(n.locale??e())===`zh-TW`?p(t):f(t)),oe=((t={},n={})=>(n.locale??e())===`zh-TW`?`…(於 1 MB 截斷)`:`… (cut at 1 MB)`),m=e=>`exit ${e?.code}`,h=e=>`結束碼 ${e?.code}`,se=((t,n={})=>(n.locale??e())===`zh-TW`?h(t):m(t)),g=e=>`Image ${e?.n}`,_=e=>`圖片 ${e?.n}`,ce=((t,n={})=>(n.locale??e())===`zh-TW`?_(t):g(t)),le=((t={},n={})=>(n.locale??e())===`zh-TW`?`圖片無法讀取`:`Image unavailable`),v=e=>`${e?.count} image(s)`,y=e=>`${e?.count} 張圖片`,ue=((t,n={})=>(n.locale??e())===`zh-TW`?y(t):v(t)),de=((t={},n={})=>(n.locale??e())===`zh-TW`?`收到`:`incoming`),b=((t={},n={})=>(n.locale??e())===`zh-TW`?`跳到最新`:`jump to latest`),x=e=>`${e?.count} new`,S=e=>`${e?.count} 則新訊息`,C=((t,n={})=>(n.locale??e())===`zh-TW`?S(t):x(t)),fe=((t={},n={})=>(n.locale??e())===`zh-TW`?`還沒有通訊。`:`No transmissions yet.`),pe=((t={},n={})=>(n.locale??e())===`zh-TW`?`通知`:`notice`),me=((t={},n={})=>(n.locale??e())===`zh-TW`?`細節`:`details`),w=((t={},n={})=>(n.locale??e())===`zh-TW`?`表單回覆`:`form answers`),he=((t={},n={})=>(n.locale??e())===`zh-TW`?`訊息,來自`:`message from`),T=e=>`answer from ${e?.from}`,E=e=>`${e?.from} 的回答`,ge=((t,n={})=>(n.locale??e())===`zh-TW`?E(t):T(t)),D=e=>`request from ${e?.from}`,O=e=>`${e?.from} 的請求`,_e=((t,n={})=>(n.locale??e())===`zh-TW`?O(t):D(t)),k=e=>`message from ${e?.from}`,A=e=>`${e?.from} 的訊息`,ve=((t,n={})=>(n.locale??e())===`zh-TW`?A(t):k(t)),j=e=>`reply to your ask from ${e?.from}`,M=e=>`${e?.from} 回覆了你的詢問`,ye=((t,n={})=>(n.locale??e())===`zh-TW`?M(t):j(t)),N=((t={},n={})=>(n.locale??e())===`zh-TW`?`記憶`:`memory`),P=((t={},n={})=>(n.locale??e())===`zh-TW`?`監看`:`monitor`),be=((t={},n={})=>(n.locale??e())===`zh-TW`?`本機`:`this computer`),xe=((t={},n={})=>(n.locale??e())===`zh-TW`?`隊友`:`teammate`),F=((t={},n={})=>(n.locale??e())===`zh-TW`?`提問,來自`:`question from`),I=((t={},n={})=>(n.locale??e())===`zh-TW`?`回報,來自`:`report from`),Se=((t={},n={})=>(n.locale??e())===`zh-TW`?`sb server 的通知`:`notice from the sb server`),L=((t={},n={})=>(n.locale??e())===`zh-TW`?`狀態:`:`status of`),R=((t={},n={})=>(n.locale??e())===`zh-TW`?`Straw Link 訊息`:`Straw Link message`),Ce=((t={},n={})=>(n.locale??e())===`zh-TW`?`喚醒鬧鐘`:`wake-up call`),z=((t={},n={})=>(n.locale??e())===`zh-TW`?`塔台事件`:`tower event`),we=((t={},n={})=>(n.locale??e())===`zh-TW`?`在旁開啟`:`open beside`),B=e=>`Open image ${e?.n}`,V=e=>`打開圖片 ${e?.n}`,Te=((t,n={})=>(n.locale??e())===`zh-TW`?V(t):B(t)),H=e=>`show all (${e?.size})`,U=e=>`顯示全部(${e?.size})`,Ee=((t,n={})=>(n.locale??e())===`zh-TW`?U(t):H(t)),De=((t={},n={})=>(n.locale??e())===`zh-TW`?`顯示全部參數`:`show all arguments`),W=e=>`◇ thought · ${e?.count} chars`,Oe=e=>`◇ 思考 · ${e?.count} 字元`,ke=((t,n={})=>(n.locale??e())===`zh-TW`?Oe(t):W(t)),Ae=((t={},n={})=>(n.locale??e())===`zh-TW`?`◇ 思考 · 已遮蔽`:`◇ thought · redacted`),je=((t={},n={})=>(n.locale??e())===`zh-TW`?`這座塔台正在待命。有訊息進來時,sb server 會喚醒它跑一個 run;你在這裡送出的第一則訊息就會啟動它。`:`This tower stands by. The sb server wakes it for a run when a message arrives; your first message here starts that run.`),Me=((t={},n={})=>(n.locale??e())===`zh-TW`?`無法取得`:`unavailable`),Ne=((t={},n={})=>(n.locale??e())===`zh-TW`?`你`:`you`);function Pe(){let e=!0,t=0;return{get pinned(){return e},scrolled(n){e=n,n&&(t=0)},hold:()=>void(e=!1),arrived(n){return e||(t+=n),e},jump:()=>void(e=!0,t=0),button:n=>e&&!n?void 0:t&&!n?C({count:t}):b()}}async function Fe(e,t,n,r){let i=()=>e.items.some(e=>e.id===n);for(;!i()&&e.before;)r(e.prepend(await t.older(e.before)));return i()?!0:(r(e.reset(await t.latest())),!1)}function Ie(e=600){let t=[],n,r=!1,i=new Set,a=new Map,o=new Map,s=e=>e.forEach(e=>(i.delete(e.id),e.tools?.forEach(e=>(o.delete(e.id),a.delete(e.id)))));function c(e,t){let n=[];for(let r of e)i.has(r.id)||(i.add(r.id),r.kind===`result`&&r.callId?(a.set(r.callId,r),o.has(r.callId)&&t.add(o.get(r.callId))):(r.tools?.forEach(e=>o.set(e.id,r.id)),n.push(r)));return n}let l=e=>({rebuild:!1,added:[],touched:[],dropped:[],front:!1,...e});return{get items(){return t},get before(){return n},get detached(){return r},result:e=>a.get(e),reset(e){return[t,n,r]=[[],e.before,!1],i.clear(),a.clear(),o.clear(),t=c(e.items,new Set),l({rebuild:!0,added:t})},append(i){if(r)return l({});let a=new Set,o=c(i,a);t.push(...o);let u=t.length>e?t.splice(0,t.length-e):[];return s(u),u.length&&(n=t[0].id),l({added:o,touched:[...a],dropped:u.map(e=>e.id)})},prepend(i){let a=new Set,o=c(i.items,a);t.unshift(...o),n=i.before;let u=t.length>e?t.splice(e):[];return s(u),u.length&&(r=!0),l({added:o,touched:[...a],dropped:u.map(e=>e.id),front:!0})}}}var Le=e=>a(e.role),Re=e=>e?new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,hour12:!1}):``,ze=e=>e>=1024?`${(e/1024).toFixed(e>=10240?0:1)} KB`:`${e} B`,Be={intercom_message:he,subagent_result:I,subagent_ping:F,subagent_status:L,"pi-loop-monitor":P,"memory-context":N,"doc-review":w,"straw-tower":z,"straw-link":R},G=e=>{let t=r(`<span class="ava"><svg><use/></svg></span>`);return t.querySelector(`use`).setAttribute(`href`,`#i-${o[e]??e}`),t};function Ve(e){let t=[],r=0;for(let i of e.matchAll(/https?:\/\/[^\s<>)\]]+/g))t.push(e.slice(r,i.index),n(`a`,{href:i[0],rel:`noopener noreferrer`,target:`_blank`},i[0])),r=i.index+i[0].length;return[...t,e.slice(r)]}function K(e,r,{who:a,link:o,docFor:f}){let p=Ie(),m=new Map,h=new Set,g=()=>h.forEach(e=>e.button.isConnected?(e.shown=!0,e.button.hidden=!e.paths.some(e=>f?.(e))):e.shown&&h.delete(e)),_=n(`div`,{class:`chat-list`}),v=n(`div`,{class:`chat-top`}),y=n(`div`,{class:`chat-live`}),b=n(`div`,{class:`chat-end`}),x=n(`button`,{class:`chat-pill`,type:`button`,hidden:``}),S=n(`p`,{class:`chat-empty`},fe()),C=n(`div`,{class:`chat-scroll`,tabindex:`-1`,"aria-label":ie()},v,_,y,b);e.replaceChildren(C,x);let w=Pe(),T=!1,E=!1,D,O,k=0,A=!1,j,M=()=>A||j!==void 0,N=()=>(clearTimeout(j),j=setTimeout(()=>(j=void 0,w.pinned&&!p.detached&&F()),250)),P=(e=w.button(p.detached))=>(x.hidden=!e,x.textContent=e??``),F=()=>(w.jump(),O=void 0,C.scrollTop=C.scrollHeight,P());async function I(e){T=!0;let t=await Fe(p,r,e,e=>(q(e),X(e))).finally(()=>T=!1),n=m.get(e);if(D===e){if(!t||!n)return F();w.hold(),O=n,n.scrollIntoView({block:`center`}),i(n,`lit`),clearTimeout(k),k=window.setTimeout(()=>(O=void 0,n.classList.remove(`lit`)),2e3),P()}}let L=()=>D?void I(D):F(),R=(e,t,n,i)=>{e.disabled=!0,r.entry(n).then(n=>{let r=n&&i(n);if(r===void 0)return void(e.textContent=Me());t.textContent=r,e.remove()},()=>e.textContent=Me())};function z(e,t=0){if(!t||!r.pic)return null;let i=Array.from({length:t},(t,n)=>r.pic(e,n));return n(`div`,{class:`pics`},...i.map((e,t)=>{let r=n(`img`,{src:e,alt:ce({n:t+1}),loading:`lazy`,decoding:`async`}),a=n(`button`,{type:`button`,class:`pic`,"aria-label":Te({n:t+1})},r);return r.addEventListener(`error`,()=>a.replaceWith(n(`em`,{class:`pic-gone`},le()))),a.addEventListener(`click`,()=>void s(async()=>{let{lightbox:e}=await import(`./lightbox-DuZhRtbe.js`);return{lightbox:e}},__vite__mapDeps([0]),import.meta.url).then(({lightbox:e})=>e(i,t))),a}))}function B(e,t){let r=p.result(e.id),i=n(`pre`,{class:`out`},r?.text??``),a=n(`pre`,{class:`args`},e.args??``),o=e.cut?n(`button`,{class:`more`,type:`button`},De()):null;o?.addEventListener(`click`,()=>R(o,a,t,t=>(e=>e&&`${e.args??``}${e.cut?`\n${oe()}`:``}`)(t.tools?.find(t=>t.id===e.id))));let s=r?.more?n(`button`,{class:`more`,type:`button`},Ee({size:ze(r.bytes??0)})):null;s?.addEventListener(`click`,()=>R(s,i,r.id,e=>e.text));let c=e.name===`show_doc`&&f?n(`button`,{class:`more open`,type:`button`,hidden:``},we()):null;c?.addEventListener(`click`,t=>(t.preventDefault(),e.summary.split(`, `).forEach(e=>f?.(e)?.()))),c&&h.add({paths:e.summary.split(`, `),button:c}),c&&queueMicrotask(g);let l=n(`details`,{class:`act`},n(`summary`,{"data-mark":r?r.isError?`error`:`done`:`working`},n(`b`,{class:`badge`}),n(`code`,null,e.name),n(`span`,{class:`sum`},e.summary),c),a,o,r&&n(`div`,{class:`result`},r.images?n(`em`,null,ue({count:r.images})):null,i,s)),u=r&&z(r.id,r.images);return u?[l,u]:[l]}let V=e=>n(`time`,null,Re(e.at)),H=(e,t,r,i)=>n(`article`,{class:`tx you`},n(`header`,null,V(e),n(`b`,null,Ne()),G(`user`)),n(`div`,{class:`bubble`,title:i},r?n(`small`,{class:`boss-flag`},ne()):null,...Ve(t),z(e.id,e.images))),U=(e,t,r,i={})=>n(`article`,{class:`tx sys`},n(`details`,{class:`notice`},n(`summary`,null,G(`comms`),n(`em`,null,de()),...t,V(e)),i.crashed?n(`small`,{class:`boss-flag`},ne()):null,n(`pre`,null,r),i.raw?n(`details`,{class:`notice-raw`},n(`summary`,null,me()),n(`pre`,{class:`raw`},i.raw)):null)),W=e=>{let t=l(e);return[he(),` `,t.name&&o(t.name)||t.name,t.id?` (${t.id})`:``,` · `,be()]},Oe=e=>e.kind===`link`?[{ask:_e,reply:ye,answer:ge,message:ve}[e.what]({from:e.from}),` · `,xe()]:e.kind===`intercom`?W(e.from):[e.kind===`server`?Se():Ce()];function K(e){switch(e.kind){case`user`:{let t=a().service?ee(e.text):void 0;if(t)return U(e,t.kind===`intercom`?W(t.from):[t.kind===`server`?Se():Ce()],e.text??``);let n=a().service?te(e.text):void 0;return H(e,n?n.body:e.text??``,n?.crashed,n?e.text??``:``)}case`assistant`:{let t=a(),r=n(`pre`,{class:`thought-text`}),i=e.thought?n(`button`,{class:`thought`,type:`button`},e.thought<0?Ae():ke({count:e.thought.toLocaleString()})):null;return e.thought&&e.thought>0&&i?.addEventListener(`click`,()=>R(i,r,e.id,e=>e.thoughtText)),n(`article`,{class:`tx in`},G(t.role),n(`div`,{class:`tx-body`},n(`header`,null,n(`b`,null,Le(t)),e.model?n(`span`,null,e.model):null,V(e),e.stop?n(`span`,{class:`stop`,"data-mark":`error`},e.stop):null),i,r,e.text?n(`div`,{class:`md`},c(d(e.text))):null,e.error?n(`p`,{class:`fault`},e.error):null,...(e.tools??[]).flatMap(t=>B(t,e.id))))}case`bash`:return n(`article`,{class:`tx sys`},n(`details`,{class:`act`},n(`summary`,{"data-mark":e.exit?`error`:`done`},n(`b`,{class:`badge`}),n(`code`,null,`shell`),n(`span`,{class:`sum`},`! ${e.command}`),e.exit?n(`span`,{class:`stop`,"data-mark":`error`},se({code:e.exit})):null),e.text?n(`pre`,{class:`out`},e.text):null));case`notice`:{let t=u(e);return t?.kind===`boss`&&a().service?H(e,t.body,t.crashed,e.text??``):t&&t.kind!==`boss`?U(e,Oe(t),t.body,t.kind===`link`?{raw:t.raw}:{crashed:t.crashed}):U(e,[Be[e.type??``]?.()??e.type??pe(),` `,e.from&&o(e.from)||(e.from??``)],e.text??``)}case`divider`:return n(`article`,{class:`tx rule`},n(`details`,null,n(`summary`,null,e.type===`compaction`?ae({tokens:(e.tokens??0).toLocaleString()}):re()),n(`pre`,null,e.text??``)));default:return n(`article`,{class:`tx note`},e.text??``,` `,V(e))}}function q(e){e.rebuild&&(m.clear(),_.replaceChildren());for(let t of e.dropped)m.get(t)?.remove(),m.delete(t);let t=e.added.map(e=>(m.set(e.id,K(e)),m.get(e.id)));e.front?_.prepend(...t):_.append(...t),E&&!e.front&&!e.rebuild&&t.forEach(e=>(e.classList.add(`fresh`),e.dataset.born=String(Date.now()))),S.remove();let n=a().service;S.textContent=n?.state===`standing`&&!n.run?je():fe(),p.items.length||_.append(S),v.hidden=!p.before,He()}let J=[],Y=new Map;function He(){let e=new Set;for(let r of J){let i=Date.parse(r.startedAt),a=p.items.findIndex(e=>e.at!==void 0&&Date.parse(e.at)>=i);if(a===0&&p.before)continue;let o=a<0?``:p.items[a].id,s=JSON.stringify([o,t(r)]),c=Y.get(r.id);if(e.add(r.id),c&&c.sig===s&&c.el.isConnected)continue;c?.el.remove();let l=t(r),u=n(`article`,{class:`tx rule conv-rule`},n(`div`,null,n(`b`,null,l.title),l.ended?n(`small`,null,l.ended):null));Y.set(r.id,{el:u,sig:s});let d=o?m.get(o):void 0;d?d.before(u):_.append(u)}for(let[t,n]of Y)e.has(t)||(n.el.remove(),Y.delete(t))}let X=e=>e.touched.forEach(e=>{let t=m.get(e),n=p.items.find(t=>t.id===e);if(t&&n){let r=K(n);t.classList.contains(`fresh`)&&Date.now()-Number(t.dataset.born??0)<400&&r.classList.add(`fresh`),t.replaceWith(r),m.set(e,r)}}),Ue=async()=>{if(!T&&p.before&&E){T=!0;try{let e=C.scrollHeight,t=p.prepend(await r.older(p.before));q(t),X(t),C.scrollTop+=C.scrollHeight-e}finally{T=!1}p.before&&C.clientHeight&&v.getBoundingClientRect().bottom>=C.getBoundingClientRect().top&&Ue()}};x.addEventListener(`click`,()=>{D=void 0,p.detached?r.latest().then(e=>(q(p.reset(e)),F())):F()});let Z=[new IntersectionObserver(e=>e.some(e=>e.isIntersecting)&&void Ue(),{root:C}),new IntersectionObserver(e=>C.clientHeight&&(w.scrolled(e.at(-1).isIntersecting),P()),{root:C,rootMargin:`0px 0px 67px`})],Q,We=()=>(Q??(Z[0].observe(v),Z[1].observe(b)),clearTimeout(Q),Q=setTimeout(()=>(Q=void 0,Z.forEach(e=>e.disconnect())),600));C.addEventListener(`scroll`,()=>(We(),!A&&j!==void 0&&N()),{passive:!0}),C.addEventListener(`touchstart`,()=>(A=!0,clearTimeout(j),j=void 0),{passive:!0});for(let e of[`touchend`,`touchcancel`])C.addEventListener(e,()=>(A=!1,N()),{passive:!0});for(let e of[`wheel`,`touchstart`,`pointerdown`,`keydown`])C.addEventListener(e,()=>O=D=void 0,{passive:!0});let $=new ResizeObserver(()=>M()?void 0:w.pinned&&!p.detached?C.scrollTop=C.scrollHeight:O?.scrollIntoView({block:`center`}));return $.observe(_),$.observe(C),{log:C,docs:g,runs(e){JSON.stringify(e)!==JSON.stringify(J)&&(J=e,He())},apply(e){if(e.reset)q(p.reset({items:e.items??[],before:e.before})),E=!0,L();else if(e.items?.length){let t=p.append(e.items);q(t),X(t),w.arrived(t.added.length)&&!p.detached&&!M()?F():P()}},reveal(e){D=e,E&&L()},setLive(e,t){y.dataset.mark=t,y.lastChild?.textContent!==e&&y.replaceChildren(...e?[n(`b`,{class:`badge`}),n(`span`,null,e)]:[])}}}export{K as mountChat,ce as t};
@@ -0,0 +1 @@
1
+ import{t as e}from"./runtime-ZX6HkxDa.js";import{t}from"./open_main_title-Ccbha5pD.js";import{n,t as r}from"./unit_count-DgKn8slE.js";import{C as i,Q as a,S as o,_ as s,a as c,d as l,g as u,h as d,i as f,l as p,m,o as h,ot as g,v as _,x as v}from"./index-ssJXzFr1.js";var y=((t={},n={})=>(n.locale??e())===`zh-TW`?`關閉清單`:`Close the list`),b=((t={},n={})=>(n.locale??e())===`zh-TW`?`切換到其他單位`:`Switch to a unit`),x=((t={},n={})=>(n.locale??e())===`zh-TW`?`回到主地圖`:`Back to the map`),S=((t={},n={})=>(n.locale??e())===`zh-TW`?`所有單位`:`All units`),C=((t={},n={})=>(n.locale??e())===`zh-TW`?`指揮中`:`commanding`),w=((t={},n={})=>(n.locale??e())===`zh-TW`?`已結束`:`ended`),T=((t={},n={})=>(n.locale??e())===`zh-TW`?`錯誤`:`error`),E=((t={},n={})=>(n.locale??e())===`zh-TW`?`閒置`:`idle`),D=((t={},n={})=>(n.locale??e())===`zh-TW`?`無狀態`:`unknown`),O=((t={},n={})=>(n.locale??e())===`zh-TW`?`等待`:`waiting`),k=((t={},n={})=>(n.locale??e())===`zh-TW`?`工作中`:`working`),A=.4;function j(e,t,n){let[r,i]=[Math.abs(e),Math.abs(t)];return Math.max(r,i)<10?`wait`:r>=1.7*i&&(n?e<0:e>0)?`drag`:`pass`}var M=(e,t,n)=>Math.abs(n)>=.45?n>0:e>=t*A,N=(e,t)=>t||e.some(e=>e.editable||e.sink||e.scrollsX||[`input`,`textarea`,`select`].includes(e.tag));function P(e){let t=e,n=getComputedStyle(e).overflowX;return{tag:e.tagName.toLowerCase(),editable:t.isContentEditable,sink:e.matches(`.composer, .term-sink`),scrollsX:(n===`auto`||n===`scroll`)&&e.scrollWidth>e.clientWidth+1}}var F=e=>{let t=[];for(let n=e;n;n=n.parentElement)t.push(P(n));return t},I={working:k,waiting:O,idle:E,done:w,error:T,unknown:D,commanding:C},L=(e,t,n)=>(t?w:I[e])({},n&&{locale:n}),R=(e,t)=>t.flatMap(t=>[t,...t.subs.map(e=>({...e,sub:!0}))].map(t=>({id:t.key,key:t.key,ws:e,name:t.name,role:t.role,mark:t.mark,note:t.note,ended:!!t.ended,sub:`sub`in t,control:!!t.control})));function z(e){return e.bases.flatMap(e=>{let t=[{id:`tower`,rows:e.tower?R(e.id,[{...e.tower,role:`tower`}]):[]},...e.tabs.map(t=>({id:t.id,label:g({label:t.label}),rows:R(e.id,t.units)})),{id:`outside`,label:n(),rows:R(e.id,e.outside)}].filter(e=>e.rows.length);return t.length?[{id:e.id,label:e.label,mark:e.mark,groups:t}]:[]})}var B=e=>e.role===`main`&&e.mark===`idle`,V=e=>e.reduce((e,t)=>(t.sub?e.at(-1)?.subs.push(t):e.push({...t,subs:[]}),e),[]),H=()=>l(`<div class="unit"><div class="card"><a class="hit"></a>${f}<div class="meta"><span class="name"></span><span class="line"><em class="role"></em><b class="dstate"></b><span class="note"></span></span></div><button type="button" class="quit-btn" data-close="unit" hidden></button></div><div class="subs"></div></div>`),U=()=>l(`<div class="unit tower-row"><div class="trow"><a class="tower-go">${f}<span class="meta"><span class="name"></span><span class="line"><em class="role"></em><b class="dstate"></b></span></span></a><button type="button" class="pair-btn tower-add"></button></div><div class="subs"></div></div>`),W=()=>l(`<section class="dbase"><h3><a></a><small></small></h3><div class="dgroups"></div></section>`),G=()=>l(`<div class="dgroup"><h4></h4><div class="drows"></div></div>`),K=()=>matchMedia(`(max-width: 640px)`).matches;function q(){let e=a(`div`,{class:`drawer-body`}),n=a(`button`,{type:`button`,class:`x`,"aria-label":y()},`×`),l=a(`a`,{class:`drawer-map`},x()),f=a(`button`,{type:`button`,class:`pair-btn`,"data-close":`dismiss-all`,hidden:``}),g=a(`div`,{class:`drawer-sweep`,hidden:``},f);c(l,{view:`map`});let C=a(`aside`,{class:`drawer`,"aria-label":b()},a(`header`,null,a(`b`,null,S()),n),e,a(`footer`,{class:`drawer-foot`},g,l)),w=a(`div`,{class:`drawer-veil`});document.body.append(w,C);let T,E,D=!1,O=0,k=0,A,P=()=>{i(f,T??{bases:[]}),g.hidden=f.hidden;let n=(e,t)=>{c(e.querySelector(`.hit`),{view:`session`,ws:t.ws,key:t.key}),e.querySelector(`.hit`).setAttribute(`aria-label`,`${t.name}: ${L(t.mark,t.ended)}`),e.classList.toggle(`current`,t.key===E),e.toggleAttribute(`data-dismiss`,t.role===`subagent`&&t.ended),e.dataset.key=t.key,m(e,t.mark),p(e.querySelector(`.plate`),t.role,t.mark),_(e,`.name`,t.name),_(e,`.role`,d(t.role)),_(e,`.dstate`,L(t.mark,t.ended)),u(e,`.note`,t.note,t.mark,t.note?void 0:``);let r=e.querySelector(`:scope > .card > .quit-btn`);B(t)?v(r,t):r.hidden=!0,s(e.querySelector(`.subs`),t.subs??[],H,n)},a=(e,r)=>{let i=e.querySelector(`.tower-go`),a=e.querySelector(`.tower-add`),o=T?.bases.find(e=>e.id===r.ws);c(i,{view:`session`,ws:r.ws,key:r.key}),i.setAttribute(`aria-label`,`${r.name}: ${L(r.mark,r.ended)}`),e.classList.toggle(`current`,r.key===E),e.dataset.key=r.key,m(e,r.mark),p(i.querySelector(`.plate`),`tower`,r.mark),_(i,`.name`,r.name),_(i,`.role`,d(`tower`)),_(i,`.dstate`,L(r.mark,r.ended)),a.hidden=!o,o&&(h(a,o),a.setAttribute(`aria-label`,t({base:o.label}))),s(e.querySelector(`.subs`),r.subs,H,n)};s(e,z(T??{bases:[]}),W,(e,t)=>{m(e,t.mark),_(e,`h3 a`,t.label),c(e.querySelector(`h3 a`),{view:`workspace`,ws:t.id}),_(e,`small`,r({count:t.groups.reduce((e,t)=>e+t.rows.length,0)})),s(e.querySelector(`.dgroups`),t.groups,G,(e,t)=>{_(e,`h4`,t.label??``),e.querySelector(`h4`).toggleAttribute(`hidden`,!t.label),t.id===`tower`?s(e.querySelector(`.drows`),V(t.rows),U,a):s(e.querySelector(`.drows`),V(t.rows),H,n)})})},I=e=>{O=Math.max(0,Math.min(k,e)),C.style.setProperty(`--dx`,`${O}px`),w.style.opacity=String(k?O/k:0),w.style.pointerEvents=O>0?`auto`:`none`},R=e=>{D=e,C.classList.toggle(`on`,e),C.inert=!e,document.documentElement.classList.remove(`drawer-drag`),I(e?k:0)},q=()=>{k=C.offsetWidth,P(),C.classList.add(`on`),document.documentElement.classList.add(`drawer-drag`)};C.inert=!0,document.addEventListener(`touchstart`,e=>{let t=e.target,n=C.contains(t)||t===w;if(A=void 0,!K()||e.touches.length!==1||document.querySelector(`dialog.sheet[open], dialog.lightbox[open], [popover]:popover-open`)||(D?!n:N(F(t),!!getSelection()?.toString())))return;let r=e.touches[0],i=D?t.closest(`.unit[data-dismiss] > .card`)??void 0:void 0;A={x0:r.clientX,y0:r.clientY,mode:`wait`,was:D,base:O,last:r.clientX,at:performance.now(),v:0,card:i}},{passive:!0}),document.addEventListener(`touchmove`,e=>{if(!A||A.mode===`pass`)return;let t=e.touches[0],n=t.clientX-A.x0,r=t.clientY-A.y0;if(A.mode===`wait`){let e=j(n,r,A.was);if(e===`wait`)return;if(e===`pass`&&A.card&&j(n,r,!1)===`drag`)A.mode=`card`,A.card.classList.add(`swiping`);else if(e===`pass`)return void(A.mode=`pass`);else A.mode=`drag`,q()}e.preventDefault();let i=performance.now();if(A.v=(t.clientX-A.last)/Math.max(1,i-A.at),[A.last,A.at]=[t.clientX,i],A.mode!==`card`)return I(A.base+n);let a=Math.max(0,n);A.card.style.setProperty(`--sx`,`${a}px`),A.card.style.setProperty(`--so`,String(1-a/A.card.offsetWidth))},{passive:!1});let J=(e,t)=>{e.classList.remove(`swiping`),e.style.removeProperty(`--sx`),e.style.removeProperty(`--so`),t&&(e.classList.add(`gone`),o({key:e.parentElement.dataset.key}).then(t=>t||e.classList.remove(`gone`)))},Y=e=>{let t=A;A=void 0,t?.mode===`drag`&&R(M(O,k,t.v)),t?.mode===`card`&&J(t.card,e.type===`touchend`&&M(Math.max(0,t.last-t.x0),t.card.offsetWidth,t.v))};return document.addEventListener(`touchend`,Y),document.addEventListener(`touchcancel`,Y),w.addEventListener(`click`,()=>R(!1)),C.addEventListener(`click`,e=>e.target.closest(`a[data-route], button[data-open], .x`)&&R(!1)),document.addEventListener(`keydown`,e=>D&&e.key===`Escape`&&(e.preventDefault(),R(!1)),!0),document.addEventListener(`sb-drawer`,()=>(D||q(),R(!D))),{net(e){T=e,D&&P()},route(e){E=e.view===`session`?e.key:void 0,l.toggleAttribute(`aria-current`,e.view===`map`),D&&P()}}}export{q as mountDrawer};
@@ -0,0 +1 @@
1
+ :root{--bg:#16161e;--bg-2:#1a1b26;--surface-0:#1f2335;--surface-1:#24283b;--raised:#1f2335;--sunken:#16161e;--well:#16161e8c;--panel:#1f2335eb;--plate:#1a1b26;--plate-hi:#292e42;--term-bg:#16161e;--term-fg:#c0caf5;--line-c:#737aa2;--line:#737aa242;--hi:#fff;--shadow:#08080d;--text:#c0caf5;--dim:#868dba;--ink:#16161e;--accent:#7dcfff;--accent-hi:#b4e4ff;--working:#7dcfff;--gold:#e0af68;--amber:#ff9e64;--ok:#9ece6a;--err:#f7768e;--err-soft:#ff9fb0;--violet:#bb9af7;--idle:#737aa2;--unknown:#545c7e;--paper-hi:#f6e6b8;--paper:#d8bd78;--paper-ink:#3b2a06;--paper-edge:#8a6f33;--aura-1:color-mix(in srgb, var(--accent) 7%, transparent);--aura-2:color-mix(in srgb, var(--violet) 8%, transparent);--grid:linear-gradient(color-mix(in srgb, var(--line-c) 5%, transparent) 1px, transparent 1px) 0 0 / 44px 44px, linear-gradient(90deg, color-mix(in srgb, var(--line-c) 5%, transparent) 1px, transparent 1px) 0 0 / 44px 44px;--mono:ui-monospace, "SF Mono", Menlo, Consolas, monospace;--sans:ui-rounded, "Avenir Next", "Trebuchet MS", system-ui, -apple-system, "Segoe UI", sans-serif}*{box-sizing:border-box;margin:0}html{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;-webkit-font-smoothing:antialiased;scrollbar-color:color-mix(in srgb, var(--line-c) 45%, transparent) transparent}::selection{background:color-mix(in srgb, var(--accent) 28%, transparent)}body{min-height:100vh;color:var(--text);font:14px/1.4 var(--sans);background:radial-gradient(1100px 640px at 12% -10%, var(--aura-1), transparent 62%), radial-gradient(900px 600px at 98% 8%, var(--aura-2), transparent 60%), linear-gradient(var(--bg), var(--bg-2));background-attachment:fixed}svg{display:block}[data-mark=working]{--c:var(--working)}[data-mark=waiting]{--c:var(--amber)}[data-mark=idle]{--c:var(--idle)}[data-mark=done]{--c:var(--ok)}[data-mark=error]{--c:var(--err)}[data-mark=unknown]{--c:var(--unknown)}[data-mark=commanding]{--c:var(--violet)}[data-mark]{--c1:color-mix(in srgb, var(--c) 13%, transparent);--c4:color-mix(in srgb, var(--c) 45%, transparent)}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.shell{max-width:2200px;margin:0 auto;padding:14px 20px 32px}.hud{border:1px solid var(--line);background:var(--panel);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);z-index:5;border-radius:16px;flex-wrap:wrap;align-items:center;gap:8px 12px;padding:8px 12px;display:flex;position:sticky;top:8px}.brand{align-items:center;gap:12px;margin-right:8px;display:flex}.logo{width:36px;height:36px;color:var(--accent);background:radial-gradient(circle at 30% 25%, color-mix(in srgb, var(--accent) 30%, transparent), color-mix(in srgb, var(--bg-2) 90%, transparent));border:1px solid var(--line);border-radius:11px;place-items:center;display:grid}.logo svg{width:24px;height:24px;filter:drop-shadow(0 0 5px color-mix(in srgb, var(--accent) 70%, transparent))}.brand h1{letter-spacing:.14em;text-transform:uppercase;white-space:nowrap;font-size:17px}.brand p{color:var(--dim);font-size:12px}.stats{background:color-mix(in srgb, var(--hi) 4%, transparent);border:1px solid color-mix(in srgb, var(--hi) 6%, transparent);border-radius:13px;gap:2px;padding:2px;display:flex}.stats div,.tally div,.alerts{background:color-mix(in srgb, var(--hi) 4%, transparent);border:1px solid color-mix(in srgb, var(--hi) 6%, transparent);border-radius:12px;min-width:0;padding:4px 10px}.stats dt,.tally dt{color:var(--dim);letter-spacing:.08em;text-transform:uppercase;font-size:10px}.stats dd,.tally dd{font:600 17px/1.15 var(--mono);font-variant-numeric:tabular-nums}.stats div{background:0 0;border-color:#0000;border-radius:10px;min-width:4.5em;padding:3px 10px}.tally dd{font-size:20px}.stats [data-mark] dd,.tally [data-mark] dd,.count b{color:var(--c)}.pair-btn{white-space:nowrap;border:1px solid var(--line);color:var(--dim);font:600 12px var(--sans);letter-spacing:.08em;text-transform:uppercase;cursor:pointer;background:0 0;border-radius:12px;padding:6px 10px}.tog{align-items:center;gap:6px;display:inline-flex}.tog:before{content:"";background:var(--line);border-radius:50%;flex:none;width:7px;height:7px}.tog[data-state=on]{color:var(--text);border-color:color-mix(in srgb, var(--accent) 35%, var(--bg))}.tog[data-state=on]:before{background:var(--accent);box-shadow:0 0 6px var(--accent)}.tog[data-state=ask]:before{background:var(--gold)}.tog[data-state=blocked]:before{background:var(--err)}.tog[data-state=done]{color:var(--text)}.tog[data-state=done]:before{background:var(--ok);box-shadow:0 0 6px var(--ok)}.tog[data-state=error]{color:color-mix(in srgb, var(--err-soft) 45%, var(--hi))}.tog[data-state=error]:before{background:var(--err);box-shadow:0 0 6px var(--err)}.alert-row{align-items:center;gap:10px;min-width:0;display:flex}.done-btn{white-space:nowrap;flex:none}.prefs-btn{place-items:center;width:34px;height:34px;margin-left:auto;padding:0;text-decoration:none;display:grid}.prefs-btn svg{fill:currentColor;width:18px;height:18px}.prefs-btn:hover,.prefs-btn[aria-current]{color:var(--text)}body:has(#remind[data-state=blocked]) .prefs-btn{color:var(--err-soft)}.menu,.menu-pop{display:contents}.menu-btn{display:none}.hud-pop{border:1px solid var(--line);background:var(--raised);color:var(--text);font:13px/1.4 var(--sans);box-shadow:0 12px 32px color-mix(in srgb, var(--shadow) 60%, transparent);border-radius:14px;margin:0;padding:12px;position:fixed;inset:auto}.done-pop{width:min(340px,100vw - 16px)}.done-pop ul{gap:2px;max-height:50vh;margin:0 0 10px;padding:0;list-style:none;display:grid;overflow:auto}.done-go{color:inherit;border-radius:10px;align-items:center;gap:10px;padding:6px 8px;text-decoration:none;display:flex}.done-go:hover,.done-go:focus-visible{background:color-mix(in srgb, var(--hi) 6%, transparent)}.done-go .plate{--s:30px;flex:none}.done-go .badge{display:none}.done-go span{min-width:0;display:grid}.done-go .name{font-weight:600}.done-go .name,.done-go small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.done-go small{color:var(--dim)}#done-clear{width:100%}.view-pick{gap:6px;display:grid}.view-pick>span{color:var(--text);font-size:14px}.view-pick>div{gap:4px;display:flex}.view-pick button{text-align:center;text-transform:none;letter-spacing:0;flex:1 1 0;justify-content:center;padding-inline:4px}.view-pick>div{flex-wrap:wrap}.view-pick[data-following] button[data-choice=auto]{flex-basis:100%}.view-pick button[aria-pressed=true]{color:var(--text);border-color:var(--accent);background:color-mix(in srgb, var(--accent) 22%, transparent);font-weight:700}.lang{text-transform:none}.lang option{background:var(--bg);color:var(--text)}.pair{text-align:center;color:var(--dim);justify-items:center;gap:12px;font-size:13px;display:grid}.pair-code{color:var(--text);font:600 22px var(--mono);letter-spacing:.12em;-webkit-user-select:all;user-select:all}.qr{shape-rendering:crispedges;border-radius:12px;width:min(100%,300px)}.devices{text-align:left;border-top:1px solid var(--line);gap:8px;width:100%;padding-top:12px;display:grid}.devices h4{font:600 12px var(--sans);letter-spacing:.08em;text-transform:uppercase;margin:0}.devices ul{gap:6px;margin:0;padding:0;list-style:none;display:grid}.devices li{grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:2px 10px;display:grid}.devices li small{overflow-wrap:anywhere;grid-column:1/-1}.devices li b{color:var(--text);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.devices-head{justify-content:space-between;align-items:center;gap:10px;display:flex}.server-facts{grid-template-columns:max-content minmax(0,1fr);gap:6px 16px;margin:0 0 12px;display:grid}.server-facts dt{color:var(--dim);letter-spacing:.08em;text-transform:uppercase;font-size:11px}.server-facts dd{overflow-wrap:anywhere;min-width:0;margin:0}:where(input:not([type=checkbox],[type=radio],[type=range],[type=file],[type=hidden],[type=color]),select){box-sizing:border-box;border:1px solid var(--line);background:var(--surface-0);color:var(--text);font:14px var(--sans);border-radius:8px;padding:6px 10px}:where(input,select):focus-visible{outline:2px solid var(--accent);outline-offset:1px}:where(input,select):disabled{opacity:.5}.devices-acts{flex-wrap:wrap;gap:8px;display:flex}.devices small,.devices .chat-empty{color:var(--dim)}.pair-tabs{flex-wrap:wrap;justify-content:center;gap:6px;display:flex}.pair-tabs .later.on,.pair-tabs .later[aria-selected=true]{color:var(--text);border-color:var(--accent);background:color-mix(in srgb, var(--accent) 22%, transparent);font-weight:700}.pair .lan{text-align:left;justify-items:start;gap:10px;width:100%;display:grid}.lan p,.lan h4,.lan ul{margin:0}.lan h4{color:var(--text);font:600 13px var(--sans)}.lan>*,.lan-main,.lan-board,.lan-pair{min-width:0;max-width:100%}.lan-main,.lan-board,.lan-pair{justify-items:start;gap:10px;width:100%;display:grid}.lan button,.lan a.go{text-transform:none}#lan-wait{text-transform:none;letter-spacing:normal;white-space:normal;text-align:left;flex:100%}.alert-row:has(#lan-wait:not([hidden])){flex-wrap:wrap}.lan .go{--c:var(--accent);text-align:left;white-space:normal;border:0}.lan .pair-btn{white-space:normal;text-align:left;max-width:100%}.lan .qr{justify-self:center}.lan-pair{text-align:center;justify-items:center}.lan-pair .devices-acts{justify-content:center}.lan code{overflow-wrap:anywhere}.lan-risk{color:var(--gold)}.lan details{max-width:100%}.lan summary{cursor:pointer;color:var(--text)}.lan details p{margin-top:6px}.lan-board{border:1px solid var(--gold);background:color-mix(in srgb, var(--gold) 6%, transparent);border-radius:12px;padding:10px}.lan-board:not([hidden]){display:grid}.lan-rows{gap:8px;width:100%;padding:0;list-style:none;display:grid}.lan-rows li{color:var(--text);justify-content:space-between;align-items:center;gap:10px;display:flex}.lan-rows li>button{white-space:nowrap;flex:none}.lan-rows li span{overflow-wrap:anywhere;min-width:0}.lan-ask{gap:6px;width:100%;display:grid}.lan-ask label{color:var(--text)}.lan-ask-row{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.lan-number{border:1px solid var(--line);background:var(--sunken);width:7ch;color:var(--text);font:600 20px var(--mono);letter-spacing:.2em;text-align:center;border-radius:10px;padding:7px 10px}.lan-no{color:var(--err-soft)}.lan-no:empty{display:none}.lan-note{gap:4px;display:grid}.lan-note:empty{display:none}.lan-info{color:var(--gold)}.lan-news li{color:var(--dim)}.lan-news{gap:4px;padding:0;list-style:none;display:grid}.lan-news:empty{display:none}.lan-fp{letter-spacing:.04em;-webkit-user-select:all;user-select:all;font-size:15px}.lan-fps{gap:6px;padding-left:18px;display:grid}.lan-hint{color:var(--dim);font-size:12px}.lan hr{border:0;border-top:1px solid var(--line);width:100%;margin:2px 0}.lan{overflow-wrap:anywhere}.lan-fps,.lan,.lan-main,.lan-board,.lan-pair,.pair,.devices{grid-template-columns:minmax(0,1fr)}.spawn-btns{flex-wrap:wrap;gap:8px;margin:12px 0 4px;display:flex}.base>.spawn-btns{margin:-4px 0 12px}.tab h3>span:not(.menu),.squad h3>b{white-space:nowrap;text-overflow:ellipsis;flex:0 auto;min-width:0;overflow:hidden}.tab h3>button{flex:none}.tab h3>span:not(.menu){flex-grow:1}.tab-add{white-space:nowrap;border:1px solid var(--line);color:var(--dim);font:600 11px var(--sans);letter-spacing:.08em;cursor:pointer;background:0 0;border-radius:10px;flex:none;margin-left:auto;padding:2px 8px}.squad .tab-add{margin-left:0}.tab-add:hover,.new-base:hover{color:var(--accent);border-color:var(--accent)}.quit-btn{border:1px solid var(--line);color:var(--dim);font:600 12px var(--sans);cursor:pointer;background:0 0;border-radius:8px;flex:none;margin-left:6px;padding:2px 9px}.quit-btn:hover{color:var(--err-soft);border-color:color-mix(in srgb, var(--err-soft) 40%, transparent)}.base>header .menu-pop>.quit-btn{align-self:flex-start;margin-left:auto}@media (hover:hover) and (pointer:fine){:is(.card>.quit-btn,.tab h3 .menu-pop>.quit-btn,.base>header .menu-pop>.quit-btn,.tower-quit){opacity:0;transition:opacity .15s}:is(.card:hover,.card:focus-within)>.quit-btn,:is(.tab h3:hover,.tab h3:focus-within) .menu-pop>.quit-btn,:is(.base>header:hover,.base>header:focus-within) :is(.quit-btn,.tower-quit){opacity:1}}#stashed-list li{align-items:center;gap:8px;display:flex}#stashed-list span{overflow-wrap:anywhere;flex:1}.card>.quit-btn{margin-left:auto}.card>.quit-btn,.base>header .menu-pop>.quit-btn,.base>header .menu-btn,.tower-quit{z-index:2;position:relative}.tower-quit{margin:6px 0 0}.sheet{border:1px solid var(--line);background:var(--raised);max-width:min(420px,100vw - 32px);color:var(--text);font:14px/1.5 var(--sans);border-radius:16px;margin:auto;padding:18px 20px}.sheet::backdrop{background:color-mix(in srgb, var(--shadow) 60%, transparent)}.sheet p{margin:0 0 14px}.sheet-row{justify-content:flex-end;gap:10px;display:flex}.sheet .later{cursor:pointer;border-radius:10px;padding:6px 14px}.sheet-yes{background:var(--err-soft);color:var(--ink);font:600 13px var(--sans);cursor:pointer;border:0;border-radius:10px;padding:6px 14px}.modes{flex:none;gap:4px;display:flex}.modes button{white-space:nowrap;border:1px solid var(--line);color:var(--dim);font:600 12px var(--sans);cursor:pointer;background:0 0;border-radius:999px;padding:4px 14px}.modes button[aria-pressed=true]{border-color:var(--accent);color:var(--accent);background:color-mix(in srgb, var(--accent) 8%, transparent)}.term-root{min-height:0;padding:10px 16px 14px}.term-root .term-tile{height:100%}.pics{flex-wrap:wrap;align-items:flex-start;gap:6px;margin-top:8px;display:flex}.pic{border:1px solid var(--line);background:var(--plate);cursor:zoom-in;border-radius:8px;max-width:100%;padding:0;line-height:0;overflow:hidden}.pic img{max-width:240px;max-height:180px;display:block}.pic-gone{color:var(--dim);font-size:12px}.lightbox{background:color-mix(in srgb, var(--bg) 94%, transparent);border:0;width:100vw;max-width:none;height:100dvh;max-height:none;margin:0;padding:0;overflow:auto}.lightbox[open]{place-items:center;display:grid}.lightbox::backdrop{background:0 0}.lightbox img{object-fit:contain;cursor:zoom-in;max-width:94vw;max-height:88dvh}.lightbox.zoom[open]{place-items:start}.lightbox.zoom img{cursor:zoom-out;max-width:none;max-height:none}.lightbox button{border:1px solid var(--line);background:var(--panel);width:44px;height:44px;color:var(--text);border-radius:50%;place-items:center;font-size:26px;line-height:1;display:grid;position:fixed}.lb-close{top:14px;right:14px}.lb-prev,.lb-next{top:calc(50% - 22px)}.lb-prev{left:14px}.lb-next{right:14px}.lb-count{color:var(--dim);font:13px var(--mono);position:fixed;bottom:14px;left:50%;transform:translate(-50%)}.queue-list{justify-items:end;gap:4px;margin:0 16px 6px;display:grid}.queue-list p{border:1px dashed color-mix(in srgb, var(--accent) 45%, transparent);max-width:min(80%,640px);color:var(--dim);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:12px;margin:0;padding:6px 12px;font-size:14px;line-height:1.45}.queue-list p>span{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.queue-list p[role=button]{cursor:pointer}.queue-list p[role=button]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.queue-list p[data-open]>span{display:block;overflow:visible}.queue-list b{color:var(--accent);letter-spacing:.06em;margin-right:8px;font-size:11px;font-weight:600}.queue-act{color:var(--dim);flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:4px 10px;margin:0 16px 6px;font-size:12px;line-height:1.4;display:flex}.queue-act[hidden],.queue-bar,.in-term .queue-list,.in-term .queue-act,.in-term .queue-bar{display:none}.todos{border:1px solid var(--line);background:var(--panel);border-radius:12px;margin:0 16px;padding:6px 12px;font-size:13px}.todos summary{cursor:pointer;align-items:baseline;gap:10px;min-width:0;list-style:none;display:flex}.todos summary::-webkit-details-marker{display:none}.todos summary b{color:var(--violet);flex:none;font-weight:600}.todos summary span{min-width:0;color:var(--dim);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.todos summary:after{content:"▸";color:var(--dim);margin-left:auto}.todos[open] summary:after{content:"▾"}.todos ol{gap:3px;max-height:30vh;margin:6px 0 2px;padding:0;list-style:none;display:grid;overflow-y:auto}.todos li{font:13px/1.5 var(--sans);margin:0}.todos li:before{content:"○";width:1.4em;color:var(--dim);display:inline-block}.todos li.in_progress{color:var(--accent)}.todos li.in_progress:before{content:"◐"}.todos li.completed{color:var(--dim);text-decoration:line-through}.todos li.completed:before{content:"✓";color:var(--ok)}.in-term .todos,.in-term .monitors{display:none}.monitors{border:1px solid var(--line);background:var(--panel);border-radius:12px;margin:6px 16px 0;padding:6px 12px;font-size:13px}.monitors summary{cursor:pointer;align-items:baseline;gap:10px;min-width:0;list-style:none;display:flex}.monitors summary::-webkit-details-marker{display:none}.monitors summary b{color:var(--accent);flex:none;font-weight:600}.monitors[data-failed=true] summary b{color:var(--err)}.monitors summary span{min-width:0;color:var(--dim);font:12px var(--mono);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.monitors summary:after{content:"▸";color:var(--dim);margin-left:auto}.monitors[open] summary:after{content:"▾"}.monitors ul{gap:6px;max-height:30vh;margin:6px 0 2px;padding:0;list-style:none;display:grid;overflow-y:auto}.monitors li{text-indent:-1.4em;gap:1px;padding-left:1.4em;display:grid}.monitors li b{overflow-wrap:anywhere;font-weight:500}.monitors li b:before{content:"◐";text-indent:0;width:1.4em;color:var(--accent);display:inline-block}.monitors li.done b:before{content:"✓";color:var(--ok)}.monitors li.stopped b:before{content:"■";color:var(--dim)}.monitors li.error b:before,.monitors li.stale b:before{content:"!";color:var(--err)}.monitors li.error small,.monitors li.stale small{color:var(--err)}.monitors li small{color:var(--dim);text-indent:0}.monitors li code{color:var(--dim);font:12px var(--mono);text-indent:0;overflow-wrap:anywhere}.new-base{border:1px dashed var(--line);min-height:96px;color:var(--dim);font:600 14px var(--sans);letter-spacing:.08em;cursor:pointer;background:0 0;border-radius:18px}.spawn .go{--c:var(--accent);border:0}.spawn{color:var(--dim);gap:10px;font-size:13px;display:grid}.spawn-at{flex-wrap:wrap;align-items:center;gap:8px;margin:0;display:flex}.spawn-path{color:var(--text);overflow-wrap:anywhere}.spawn textarea,.spawn input{box-sizing:border-box;border:1px solid var(--line);width:100%;color:var(--text);font:14px var(--sans);background:0 0;border-radius:8px;padding:8px 10px}.picker{gap:8px;min-width:0;display:grid}.picker-bar{align-items:center;gap:6px;min-width:0;display:flex}.picker-bar .later{font:13px var(--sans);cursor:pointer;border-radius:8px;flex:none;padding:4px 10px}.picker-bar .later:disabled{opacity:.4;cursor:default}.picker-crumbs{scrollbar-width:none;white-space:nowrap;flex:1;align-items:center;min-width:0;display:flex;overflow-x:auto}.picker-crumbs::-webkit-scrollbar{display:none}.picker-crumbs button{text-overflow:ellipsis;max-width:14em;color:var(--dim);font:13px var(--sans);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;padding:3px 6px;overflow:hidden}.picker-crumbs button:hover{color:var(--text);background:color-mix(in srgb, var(--accent) 8%, transparent)}.picker-crumbs button+button:before{content:"›";color:var(--dim);margin-right:6px}.picker-crumbs button[aria-current=true]{color:var(--text);font-weight:600}.picker input{box-sizing:border-box}.picker-body{border:1px solid var(--line);border-radius:10px;grid-template-columns:minmax(90px,130px) minmax(0,1fr);min-width:0;height:min(40vh,280px);min-height:170px;display:grid;overflow:hidden}.picker-places{background:color-mix(in srgb, var(--bg) 40%, transparent);border-right:1px solid var(--line);flex-direction:column;gap:2px;padding:6px;display:flex;overflow-y:auto}.picker-places button{color:var(--text);font:13px var(--sans);text-align:left;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;background:0 0;border:0;border-radius:6px;padding:5px 8px;overflow:hidden}.picker-places button:hover{background:color-mix(in srgb, var(--accent) 10%, transparent)}.picker-places b{color:var(--dim);font:600 11px var(--sans);letter-spacing:.08em;text-transform:uppercase;margin:8px 8px 2px}.picker-cols{outline-offset:-2px;min-width:0;display:flex;overflow:auto hidden}@media (prefers-reduced-motion:no-preference){.picker-cols,.pcol{scroll-behavior:smooth}}.pcol{width:var(--pw,176px);border-right:1px solid var(--line);flex-direction:column;flex:none;gap:1px;padding:4px;display:flex;overflow-y:auto}.pcol:last-child{border-right:0}.pitem{width:100%;color:var(--text);font:13px var(--sans);text-align:left;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;padding:5px 8px;display:block;overflow:hidden}.pitem:hover{background:color-mix(in srgb, var(--accent) 8%, transparent)}.pitem[aria-selected=true]{background:color-mix(in srgb, var(--accent) 14%, transparent);color:var(--accent-hi)}.pcol[data-focus=true] .pitem[aria-selected=true]{background:color-mix(in srgb, var(--accent) 32%, transparent)}.pitem[aria-selected=true]:after{content:"›";float:right;opacity:.7}.pempty{color:var(--dim);margin:6px 8px;font-size:12px}.spawn-name{color:var(--dim);gap:4px;font-size:12px;display:grid}@media (width<=640px){.picker-body{grid-template-rows:auto minmax(0,1fr);grid-template-columns:minmax(0,1fr);height:min(52vh,360px)}.picker-places{border-right:0;border-bottom:1px solid var(--line);flex-direction:row;align-items:center;overflow:auto hidden}.picker-places b{display:none}.picker-places button{flex:none;max-width:10em}.pcol:not(:last-child){display:none}.pcol{border-right:0;flex:1;width:auto}.pitem{padding:10px 12px}}.deploy{border:1px solid var(--line);background:color-mix(in srgb, var(--accent) 5%, transparent);color:var(--text);border-radius:14px;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px 12px;padding:14px 16px;display:grid}.deploy>*{grid-column:1/-1;margin:0}.deploy>.deploy-bar{grid-column:1}.deploy>.deploy-count{grid-column:2}.deploy-title{font:600 15px var(--sans);letter-spacing:.04em;overflow-wrap:anywhere;align-items:center;gap:8px;display:flex}.deploy-title svg{width:24px;height:24px;color:var(--gold);filter:drop-shadow(0 0 5px color-mix(in srgb, var(--gold) 60%, transparent));flex:none}.deploy-bar{border:1px solid var(--line);background:color-mix(in srgb, var(--bg) 70%, transparent);border-radius:4px;height:14px;position:relative;overflow:hidden}.deploy-bar:after{content:"";background:repeating-linear-gradient(90deg, transparent 0 calc(5% - 2px), var(--bg-2,var(--bg)) calc(5% - 2px) 5%);position:absolute;inset:0}.deploy-fill{height:100%;width:calc(var(--done,0) / var(--of,1) * 100%);background:linear-gradient(90deg, var(--accent), var(--accent-hi), var(--accent)) 0 0 / 200% 100%;transition:width .7s cubic-bezier(.2,.8,.2,1),background-color .4s;display:block}.deploy[data-state=running] .deploy-fill{animation:1.8s linear infinite deploy-sheen}.deploy-count{font:600 13px var(--mono);color:var(--accent)}.deploy-steps{gap:6px;padding:0;list-style:none;display:grid}.deploy-steps li{color:var(--dim);grid-template-columns:1.6em minmax(0,1fr) auto;align-items:baseline;display:grid}.deploy-steps .deploy-mark:before{content:"·"}.deploy-steps [data-state=done]{color:var(--text)}.deploy-steps [data-state=done] .deploy-mark{color:var(--ok)}.deploy-steps [data-state=done] .deploy-mark:before{content:"✔"}.deploy-steps [data-state=active]{color:var(--text);font-weight:600}.deploy-steps [data-state=active] .deploy-mark{color:var(--accent);animation:1s ease-in-out infinite deploy-pulse}.deploy-steps [data-state=active] .deploy-mark:before{content:"▶"}.deploy-steps [data-state=failed]{color:var(--err-soft);font-weight:600}.deploy-steps [data-state=failed] .deploy-mark{color:var(--err)}.deploy-steps [data-state=failed] .deploy-mark:before{content:"✖"}.deploy-time{font:12px var(--mono);color:var(--dim)}.deploy-steps [data-state=active] .deploy-time{color:var(--accent)}.deploy-note{overflow-wrap:anywhere;font-size:13px;line-height:1.5}.deploy-note:empty{display:none}.deploy[data-state=failed]{border-color:color-mix(in srgb, var(--err) 55%, var(--line));background:color-mix(in srgb, var(--err) 8%, transparent)}.deploy[data-state=failed] .deploy-note{color:var(--err-soft)}.deploy[data-state=failed] .deploy-fill{background:var(--err)}.deploy[data-state=ready]{border-color:color-mix(in srgb, var(--ok) 60%, var(--line));animation:1.1s ease-out deploy-ready}.deploy[data-state=ready] .deploy-fill{background:var(--ok)}.deploy[data-state=ready] .deploy-note{color:var(--ok);letter-spacing:.08em;font-weight:600;animation:.6s ease-out deploy-rise}.deploy[data-state=ready] .deploy-title svg{animation:.7s ease-out deploy-hop}.deploy .later{justify-self:start;display:none}.deploy[data-state=failed] .later{display:inline-block}@keyframes deploy-sheen{to{background-position:-200% 0}}@keyframes deploy-pulse{50%{opacity:.3;transform:translate(2px)}}@keyframes deploy-ready{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--ok) 55%, transparent)}to{box-shadow:0 0 0 18px #0000}}@keyframes deploy-rise{0%{opacity:0;transform:translateY(6px)}}@keyframes deploy-hop{40%{transform:translateY(-5px)scale(1.2)}}.link{color:var(--dim);text-transform:uppercase;letter-spacing:.08em;align-items:center;gap:8px;padding:0 4px;font-size:12px;display:flex}.link span{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.link i{background:var(--unknown);border-radius:50%;width:9px;height:9px}.link[data-state=live] i{background:var(--ok);animation:2.4s ease-in-out infinite blink}.link[data-state=live]{color:var(--ok)}.link[data-state=reconnecting] i,.link[data-state=connecting] i{background:var(--amber);animation:1s ease-in-out infinite blink}.link[data-state=offline] i,.link[data-state=replaced] i{background:var(--err)}.banner{background:color-mix(in srgb, var(--idle) 16%, transparent);color:var(--text);border-radius:14px;margin:14px 0 0;padding:10px 16px;font-size:13px}.banner b{font-family:var(--mono);font-weight:600}.stage{grid-template-columns:minmax(0,1fr);align-items:start;gap:20px;margin-top:12px;transition:opacity .4s;display:grid}.stage[data-view=session]{grid-template-columns:minmax(0,1fr) 300px}.stage:not([data-view=session])>.side{display:none}.stage[data-stale=true] .map,body[data-stale=true] .stats{opacity:.4}.stage[data-stale=true] *{animation-play-state:paused!important}.map{border:1px solid var(--line);background:var(--grid), var(--well);border-radius:18px;min-height:420px;padding:20px;transition:opacity .4s;position:relative}.links{pointer-events:none;width:100%;height:100%;position:absolute;inset:0}.wire{fill:none;stroke:color-mix(in srgb, var(--accent) 30%, transparent);stroke-width:1.5px;stroke-dasharray:3 7;stroke-linecap:round}.packets{pointer-events:none;position:absolute;inset:0;overflow:hidden}.packet{background:var(--accent);opacity:0;will-change:transform;border-radius:50%;width:6px;height:6px;transition:opacity .4s;animation:none;position:absolute;top:-3px;left:-3px}.packet[data-live]{opacity:.9;animation-play-state:running}.bases{grid-template-columns:repeat(auto-fill,minmax(min(100%,330px),1fr));grid-auto-rows:2px;align-items:start;gap:0 20px;display:grid;position:relative}.base{border:1px solid var(--line);background:linear-gradient(180deg, var(--surface-1), var(--surface-0));box-shadow:0 18px 40px color-mix(in srgb, var(--shadow) 35%, transparent);border-radius:16px;padding:14px;position:relative}.base.head{background:linear-gradient(180deg, color-mix(in srgb, var(--gold) 10%, transparent), transparent 38%), linear-gradient(180deg, var(--surface-1), var(--surface-0))}.base[data-mark=waiting]{box-shadow:0 18px 40px color-mix(in srgb, var(--shadow) 35%, transparent), inset 0 0 0 999px color-mix(in srgb, var(--amber) 4%, transparent)}.base>header{align-items:center;gap:12px;margin-bottom:10px;display:flex;position:relative}.title{justify-items:start;min-width:0;margin-right:auto;display:grid}.title h2{white-space:nowrap;text-overflow:ellipsis;max-width:100%;font-size:17px;overflow:hidden}.title p{max-width:100%;color:var(--dim);white-space:nowrap;text-overflow:ellipsis;font-size:12px;overflow:hidden}.crown{letter-spacing:.12em;text-transform:uppercase;color:var(--gold);background:color-mix(in srgb, var(--gold) 12%, transparent);border-radius:999px;align-items:center;gap:5px;margin-bottom:3px;padding:2px 9px 2px 6px;font-size:10px;display:inline-flex}.crown svg{width:14px;height:14px}.base:not(.head) .crown{display:none}.tower{width:64px;height:64px;color:var(--c);flex:none;place-items:center;display:grid;position:relative}.tower:before{content:"";background:radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--c) 24%, var(--plate-hi)), var(--plate) 70%);border:1px solid color-mix(in srgb, var(--c) 45%, transparent);border-radius:50%;position:absolute;inset:0}.tower svg{width:38px;height:38px;filter:drop-shadow(0 0 5px color-mix(in srgb, var(--c) 55%, transparent));position:relative}.tower.ghost{opacity:.45}.tower.ghost:before{border-style:dashed}.sweep,.pulse{opacity:0;pointer-events:none;border-radius:50%;position:absolute;inset:0}.sweep{background:conic-gradient(from 0deg, transparent 0 70%, color-mix(in srgb, var(--c) 55%, transparent) 100%)}.pulse{border:2px solid var(--c)}.tower[data-mark=working] .sweep{opacity:1;animation:3.2s linear infinite spin}.tower[data-mark=waiting] .pulse{animation:1.5s ease-out infinite ping}.tower>.badge{--s:36px;position:absolute;bottom:-3px;right:-3px}.tabs{gap:10px;display:grid}.tab{background:color-mix(in srgb, var(--hi) 2%, transparent);border:1px solid color-mix(in srgb, var(--hi) 5%, transparent);border-radius:14px;padding:8px}.tab h3{color:var(--dim);letter-spacing:.12em;text-transform:uppercase;align-items:center;gap:8px;margin-bottom:8px;font-size:11px;font-weight:600;display:flex}.units,.subs{gap:8px;display:grid}.outposts{gap:8px;margin-top:12px;display:grid}.outposts:empty{display:none}.outposts:before{content:attr(data-label);color:var(--dim);letter-spacing:.12em;text-transform:uppercase;font-size:11px}.card{background:color-mix(in srgb, var(--hi) 4%, transparent);border:1px solid color-mix(in srgb, var(--hi) 6%, transparent);border-radius:12px;align-items:center;gap:10px;padding:8px 10px;transition:background-color .4s;display:flex;position:relative}@media (hover:hover) and (pointer:fine){.card{transition:background-color .4s,border-color .2s,transform .18s cubic-bezier(.2,.8,.2,1),box-shadow .18s}.card:hover{border-color:color-mix(in srgb, var(--c,var(--line-c)) 40%, transparent);box-shadow:0 6px 18px color-mix(in srgb, var(--shadow) 55%, transparent);transform:translateY(-1px)}.base{transition:border-color .25s}.base:hover{border-color:color-mix(in srgb, var(--line-c) 36%, transparent)}.pair-btn,.tab-add,.quit-btn,.modes button,.later,.cmp-alt{transition:color .15s,border-color .15s,background-color .15s,transform .12s}.pair-btn:hover:not(:disabled){color:var(--text);border-color:color-mix(in srgb, var(--line-c) 50%, transparent);background:color-mix(in srgb, var(--hi) 4%, transparent)}}:is(.pair-btn,.tab-add,.quit-btn,.go,.later,.cmp-send,.cmp-alt,.ask-send,.ask-cancel,.sheet-yes,.new-base,.modes button,.pitem,.d-doc,.thought,.more,.tab-btn):active:not(:disabled){transform:scale(.97)}.unit[data-mark=waiting]>.card{background:color-mix(in srgb, var(--amber) 11%, transparent)}.unit[data-mark=error]>.card{background:color-mix(in srgb, var(--err) 11%, transparent)}.unit[data-mark=working]>.card{background:color-mix(in srgb, var(--c) 7%, transparent)}.unit[data-mark=commanding]>.card,.token[data-mark=commanding]{background:color-mix(in srgb, var(--violet) 9%, transparent)}.plate{width:var(--s,40px);height:var(--s,40px);color:var(--c);background:radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--c) 26%, var(--plate-hi)), var(--plate) 72%);border-radius:50%;flex:none;place-items:center;transition:color .4s;display:grid;position:relative}.plate svg{width:calc(var(--s,40px) * .55);height:calc(var(--s,40px) * .55)}.ring,.plate:after{pointer-events:none;border-radius:50%;position:absolute;inset:-3px}.ring{opacity:0;background:conic-gradient(from 0deg, transparent 0 55%, var(--c));-webkit-mask:radial-gradient(farthest-side, transparent calc(100% - 3px), var(--shadow) calc(100% - 2px));mask:radial-gradient(farthest-side, transparent calc(100% - 3px), var(--shadow) calc(100% - 2px))}.plate[data-mark=working]>.ring{opacity:1;animation:1.1s linear infinite spin}.plate:after{content:"";border:2px solid var(--c);opacity:0}.plate[data-mark=waiting]:after{animation:1.5s ease-out infinite ping}.badge{width:clamp(16px, calc(var(--s,40px) * .3), 24px);height:clamp(16px, calc(var(--s,40px) * .3), 24px);font:700 10px/1 var(--mono);color:var(--ink);background:var(--c);border-radius:50%;flex:none;place-items:center;transition:background-color .4s;display:grid}.plate>.badge{position:absolute;bottom:-4px;right:-4px}[data-mark=waiting]>.badge:after{content:"?"}[data-mark=idle]>.badge:after{content:"z"}[data-mark=done]>.badge:after{content:"✓"}[data-mark=error]>.badge:after{content:"!"}[data-mark=unknown]>.badge:after{content:"·"}[data-mark=commanding]>.badge:after{content:"◈"}[data-mark=working]>.badge:after{content:"";border:2px solid var(--ink);border-right-color:#0000;border-radius:50%;width:8px;height:8px;animation:.8s linear infinite spin}[data-mark=waiting]>.badge{animation:1.2s ease-in-out infinite hop}.meta{min-width:0;display:grid}.name{white-space:nowrap;text-overflow:ellipsis;font-weight:600;overflow:hidden}.line{color:var(--dim);align-items:baseline;gap:8px;min-width:0;font-size:12px;display:flex}.role{white-space:nowrap;letter-spacing:.1em;text-transform:uppercase;color:color-mix(in srgb, var(--c) 70%, var(--dim));flex:none;font-size:10px;font-style:normal}.note{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}[data-monitoring]{color:var(--err);font-weight:600}.unit[data-mark=idle]>.card{opacity:.85}.subs{margin:6px 0 0 22px;padding-left:18px;position:relative}.subs:empty{display:none}.base>.tower-subs{margin:-8px 0 12px 22px}.base>.tower-notices:empty{display:none}.base>.tower-notices{gap:6px;min-width:0;margin:0 0 12px 22px;display:grid}.tower-notices .tnote{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;margin:0;font-size:.85em;display:flex}.tower-notices .tnote span{overflow-wrap:anywhere;flex:14em;min-width:0}.tower-notices .tnote.error span{color:var(--err-soft)}.tower-notices .tnote.warning span{color:var(--gold)}.tower-notices .tnote .tnote-fail{color:var(--err-soft);flex:100%;font-size:.95em}.tower-notices .tnote .tnote-fail:empty{display:none}.tower-notices .tnote button:disabled{opacity:.6;cursor:progress}.tower-notes{margin:0 16px 8px}.tower-notes:has(>.tower-notices:empty):not(:has(>.tower-memory:not([hidden]))):not(:has(>.tower-conv:not([hidden]))){display:none}.tower-notes .tower-notices{gap:6px;min-width:0;display:grid}.base:not(.ally)>header .title p{white-space:normal;flex-wrap:wrap;align-items:center;gap:2px 0;display:flex;overflow:visible}.title .tqueue{border:1px solid color-mix(in srgb, var(--accent) 45%, transparent);color:var(--accent);white-space:nowrap;border-radius:999px;margin-left:8px;padding:0 7px;font-size:11px}.title .tqueue:empty{display:none}.allies{flex-wrap:wrap;align-items:center;gap:4px 8px;margin-top:6px;font-size:.85em;display:flex}.allies[hidden]{display:none}.allies b{color:var(--dim);font-weight:600}.ally-chip{border:1px solid color-mix(in srgb, var(--accent) 45%, transparent);color:var(--accent);white-space:nowrap;border-radius:999px;padding:0 8px;font-size:11px;text-decoration:none}a.ally-chip:hover{background:color-mix(in srgb, var(--accent) 14%, transparent)}.zoom-in>.tower-notices:empty{display:none}.zoom-in>.tower-notices{gap:6px;min-width:0;margin:12px 0;display:grid}.term-hold{border:1px dashed var(--line);color:var(--dim);border-radius:12px;margin:16px;padding:14px 16px;line-height:1.5}.subs:before{content:"";background:repeating-linear-gradient(color-mix(in srgb, var(--line-c) 50%, transparent) 0 4px, transparent 4px 8px);width:1px;position:absolute;top:-4px;bottom:22px;left:3px}.subs>.unit>.card:before{content:"";background:repeating-linear-gradient(90deg, color-mix(in srgb, var(--line-c) 50%, transparent) 0 4px, transparent 4px 8px);width:15px;height:1px;position:absolute;top:50%;left:-15px}.subs>.unit{position:relative}.subs>.unit>.card:after{content:"";border:3px solid #0000;border-left:4px solid color-mix(in srgb, var(--line-c) 60%, transparent);pointer-events:none;position:absolute;top:calc(50% - 3px);left:-5px}.subs>.unit:is([data-mark=working],[data-mark=commanding])>.card:before{animation:.8s linear infinite flow-x}.subs:has(>.unit:is([data-mark=working],[data-mark=commanding])):before{animation:.8s linear infinite flow-y}@keyframes flow-x{to{background-position:8px 0}}@keyframes flow-y{to{background-position:0 8px}}.subs .plate{--s:30px}.subs .name{font-size:13px}.side{top:calc(var(--hud,64px) + 20px);gap:16px;display:grid;position:sticky}.panel{border:1px solid var(--line);background:var(--panel);border-radius:18px;padding:14px 16px}.panel h2{color:var(--dim);letter-spacing:.14em;text-transform:uppercase;margin-bottom:10px;font-size:11px}.timeline summary{cursor:pointer;align-items:baseline;gap:10px;min-width:0;list-style:none;display:flex}.timeline summary::-webkit-details-marker{display:none}.timeline summary:after{content:"▾";color:var(--dim);margin-left:8px;transition:transform .2s}.timeline:not([open]) summary:after{transform:rotate(-90deg)}.timeline h2{flex:none;margin:0}.tl-at{color:var(--dim);font:11px var(--mono);flex:none}.tl-last{white-space:nowrap;text-overflow:ellipsis;min-width:0;font-size:12.5px;overflow:hidden}.tl-span{color:var(--dim);flex:none;margin-left:auto;font-size:11px}.tl-lanes{border-top:1px dashed var(--line);height:46px;margin-top:8px;position:relative}.tl-lanes:after{content:"";background:var(--accent);width:2px;box-shadow:0 0 8px color-mix(in srgb, var(--accent) 60%, transparent);border-radius:1px;position:absolute;top:0;bottom:0;right:0}.tl-mark{width:10px;height:10px;margin-left:-5px;position:absolute}.tl-mark:before{content:"";background:var(--c);border-radius:2px;position:absolute;inset:1px}.tl-mark:is([data-mark=waiting],[data-mark=error],[data-mark=commanding]):before{transform:rotate(45deg)}.tl-mark:is([data-mark=done],.joined,.left):before{border-radius:50%}.tl-mark.left:before{box-shadow:inset 0 0 0 1.5px var(--c);background:0 0}.tl-mark:hover:before,.tl-mark:focus-visible:before{box-shadow:0 0 0 3px color-mix(in srgb, var(--c) 35%, transparent)}.tl-mark:focus-visible{outline:none}.tl-mark:hover:after,.tl-mark:focus-visible:after{content:attr(aria-label);z-index:1;border:1px solid var(--line);background:var(--raised);color:var(--text);font:12px var(--sans);white-space:nowrap;box-shadow:0 6px 16px color-mix(in srgb, var(--shadow) 60%, transparent);border-radius:8px;padding:4px 8px;position:absolute;bottom:calc(100% + 8px);left:-6px}.tl-mark.end:hover:after,.tl-mark.end:focus-visible:after{left:auto;right:-6px}.tl-axis{color:var(--dim);font:10px var(--mono);justify-content:space-between;margin-top:4px;display:flex}.line .age{color:var(--dim);font:10.5px var(--mono);opacity:.85;flex:none}.line .age:empty{display:none}.line .age:before{content:"· "}.unit[data-mark=waiting]>.card .age,.title .age{color:var(--amber);opacity:1}.title .age{color:var(--dim)}.title .age:not(:empty):before{content:" · "}.todo{align-items:baseline;gap:6px;min-width:0;font-size:11.5px;display:flex}.todo b{color:var(--violet);font:600 10.5px var(--mono);flex:none}.todo span{white-space:nowrap;text-overflow:ellipsis;opacity:.85;min-width:0;overflow:hidden}.todo span:empty{display:none}.ticks{pointer-events:none;gap:3px;height:3px;display:flex;position:absolute;bottom:3px;left:52px;right:12px}.ticks:empty{display:none}.ticks i{background:var(--c);opacity:calc(.25 + .65 * var(--o,1));border-radius:1px;flex:0 0 6px}.card.ticked{padding-bottom:11px}.subs .ticks{left:44px}.minimap{z-index:4;box-sizing:content-box;border:1px solid var(--line);background:var(--panel);opacity:.65;cursor:pointer;border-radius:10px;padding:6px;transition:opacity .2s;position:fixed;bottom:20px;right:20px}.minimap:hover{opacity:1}body:has(.tile) .minimap{opacity:0;pointer-events:none}body:has(.tile-layer:not([hidden])) .minimap{opacity:0;pointer-events:none}.minimap.away{opacity:0;pointer-events:none}.mm-in{position:absolute;inset:6px}.mm-in i{background:color-mix(in srgb, var(--c) 35%, var(--surface-1));border-radius:2px;position:absolute}.mm-view{border:1px solid var(--accent);background:color-mix(in srgb, var(--accent) 8%, transparent);pointer-events:none;border-radius:3px;position:absolute;top:6px;left:4px;right:4px}.credit{color:var(--dim);padding:0 6px;font-size:11px}.bar{flex-wrap:wrap;align-items:center;gap:6px 16px;margin:12px 6px 0;display:flex}.bar-acts{align-items:center;gap:8px;display:flex}.bar-acts .pair-btn{border-radius:10px;padding:3px 9px;font-size:11px}.legend{color:var(--dim);flex-wrap:wrap;gap:4px 14px;margin:0 0 0 auto;padding:0;font-size:11px;list-style:none;display:flex}.legend li{align-items:center;gap:6px;display:flex}.legend .badge{width:13px;height:13px;font-size:8px}.foot{grid-template-columns:minmax(0,1fr);gap:10px;margin-top:14px;display:grid}.foot .credit{opacity:.75}.enter{animation:.5s cubic-bezier(.2,.9,.3,1.15) both pop}.leaving{pointer-events:none;animation:.35s ease-in both out}.flash>.card>.plate,.flash.tower{animation:.6s ease-out flash}.flash>.card{animation:.9s ease-out card-glow}.flash.flip>.card{animation-name:card-glow-b}.flash.flip>.card>.plate,.flash.flip.tower,.flash.flip.token>.plate{animation-name:flash-b}@keyframes spin{to{transform:rotate(360deg)}}@keyframes glow{0%,to{box-shadow:0 0 5px 0 var(--c4)}50%{box-shadow:0 0 16px 4px var(--c)}}.plate[data-mark=commanding]:before,.tower[data-mark=commanding]:after{content:"";pointer-events:none;border-radius:50%;animation:2.4s ease-in-out infinite glow;position:absolute;inset:-2px}.stats [data-mark=commanding][data-on],.comms-head[data-mark=commanding] .logo{border-color:var(--c4);animation:2.4s ease-in-out infinite glow}.comms-head[data-mark=commanding] .logo{color:var(--c)}.comms-head[data-mark=commanding] h2 span{color:var(--c);text-shadow:0 0 10px var(--c4)}@keyframes ping{0%{opacity:.6;transform:scale(1)}to{opacity:0;transform:scale(1.7)}}@keyframes hop{50%{transform:translateY(-3px)}}@keyframes blink{50%{opacity:.35}}@keyframes pop{0%{opacity:0;transform:scale(.92)translateY(8px)}}@keyframes pop-b{0%{opacity:0;transform:scale(.92)translateY(8px)}}@keyframes out{to{opacity:0;transform:scale(.94)}}@keyframes out-b{to{opacity:0;transform:scale(.94)}}@keyframes flash{40%{transform:scale(1.12)}}@keyframes card-glow{30%{box-shadow:0 0 0 1px var(--c4), 0 0 18px 1px var(--c4)}}@keyframes card-glow-b{30%{box-shadow:0 0 0 1px var(--c4), 0 0 18px 1px var(--c4)}}@keyframes flash-b{40%{transform:scale(1.12)}}@keyframes slide{0%{opacity:0;transform:translate(10px)}}@keyframes slide-b{0%{opacity:0;transform:translate(10px)}}@keyframes zoom{0%{opacity:0;transform:scale(.45)}}@keyframes zoom-b{0%{opacity:0;transform:scale(.45)}}@keyframes come-in{0%{opacity:0;transform:translate(-14px)scale(.98)}}@keyframes go-out{0%{opacity:0;transform:translate(14px)scale(.98)}}.tx.fresh{animation:.32s cubic-bezier(.2,.8,.2,1) both come-in}.tx.you.fresh{animation-name:go-out}:is([data-calm],[data-view=geek]) :is(.link i,.sweep,.pulse,.ring,.badge,.term-typing),:is([data-calm],[data-view=geek]) :is(.plate,.badge):after{animation:none!important}:is([data-calm],[data-view=geek]) .tower[data-mark=waiting] .pulse{opacity:.55}:is([data-calm],[data-view=geek]) .plate[data-mark=waiting]:after{opacity:.55;transform:scale(1.25)}:is([data-calm],[data-view=geek]) .packet{opacity:0;animation-play-state:paused!important}:is([data-calm],[data-view=geek]) .subs:before,:is([data-calm],[data-view=geek]) .subs>.unit>.card:before{animation:none!important}@media (prefers-reduced-motion:reduce),(hover:none) and (prefers-reduced-motion:reduce){.plate[data-mark=commanding]:before,.tower[data-mark=commanding]:after{box-shadow:0 0 12px 3px var(--c4)}.stats [data-mark=commanding][data-on],.comms-head[data-mark=commanding] .logo{box-shadow:0 0 12px 2px var(--c4)}}:is([data-calm],[data-view=geek]) :is(.plate,.tower)[data-mark=commanding]:before,:is([data-calm],[data-view=geek]) .tower[data-mark=commanding]:after{box-shadow:0 0 12px 3px var(--c4);animation:none!important}[hidden]{display:none!important}a{color:inherit}.crumbs,.tally dt,.comms-head small,.tx.you>header,.notice em,.rule summary,.dossier-in>.tag,.d-drones h4,.d-docs h4,.specs dt,.stop,.dialog .tag,.intel h4,.pending b{color:var(--dim);letter-spacing:.14em;text-transform:uppercase;font-size:11px;font-style:normal}.token .name,.drone .note,.count small,.sum,.where,.tile b{white-space:nowrap;text-overflow:ellipsis;max-width:100%;overflow:hidden}.md a,.bubble a,.notice a,.d-note a,.specs a,.crumbs a{color:var(--accent)}.crumbs{gap:10px;min-width:0;display:flex}.crumbs>*+:before{content:"›";opacity:.5;margin-right:10px}.crumbs>*{white-space:nowrap;text-overflow:ellipsis;letter-spacing:.06em;flex:0 auto;min-width:0;max-width:28ch;overflow:hidden}.crumbs>:last-child{flex:auto;max-width:none}.crumb-more{cursor:pointer;color:var(--accent);display:none}.crumbs a,.brand{text-decoration:none}.work{align-items:flex-start;gap:20px;min-width:0;display:flex;position:relative}.gauge{visibility:hidden;height:0;position:absolute;left:0;right:0}.view{flex:1 1 0;min-width:0}body[data-stale=true] .work{opacity:.45}.enter-zoom{transform-origin:var(--ox,50%) var(--oy,0);animation:.5s ease-out both zoom}.enter-slide,.dossier{animation:.4s ease-out both slide}.enter-back{animation:.4s ease-out both pop}.enter-zoom.flip{animation-name:zoom-b}.enter-slide.flip{animation-name:slide-b}.enter-back.flip{animation-name:pop-b}.hit,.enter-base:after{z-index:1;border-radius:inherit;position:absolute;inset:0}.enter-base:after{content:"";z-index:0}.hit:hover{box-shadow:inset 0 0 0 1px var(--c)}.enter-base{text-decoration:none}.base>header:hover h2{color:var(--accent)}.alerts{width:210px;color:inherit;font:inherit;text-align:left;cursor:pointer;align-items:center;gap:10px;display:flex;position:relative}.alerts:disabled{cursor:default;opacity:.6}.alerts:not(:disabled){border-color:var(--c4);background:var(--c1)}.faces{flex:none;padding-left:10px;display:flex}.faces .plate{--s:28px;box-shadow:0 0 0 2px var(--raised);margin-left:-10px}.faces .badge{display:none}.count{min-width:0;display:grid}.count b{font:600 18px/1.1 var(--mono)}.count small,.comms-head p,.cmp-note,.where,.queued,.d-line,.who p{color:var(--dim);font-size:12px}.token{border:1px solid #0000;border-radius:16px;justify-items:center;gap:3px;width:100%;padding:10px 8px 9px;text-decoration:none;display:grid;position:relative}a.token:hover{border-color:var(--c4)}.token[data-mark=waiting]{background:color-mix(in srgb, var(--amber) 11%, transparent)}.token[data-mark=error]{background:color-mix(in srgb, var(--err) 11%, transparent)}.token .plate{--s:64px;margin-bottom:4px}.token .name{font-weight:600}.token .line{justify-items:center;max-width:100%;display:grid}.drone{width:94px;padding:6px;font-size:12px}.drone .plate{--s:44px}.drone .role{display:none}.agent{letter-spacing:.08em;text-transform:uppercase;border:1px solid var(--c4);color:var(--dim);border-radius:8px;margin-left:4px;padding:0 5px;font-size:9px;font-style:normal}.agent:empty,.drone .agent{display:none}.flash.token>.plate{animation:.6s ease-out flash}.zoom-in,.comms-in{border:1px solid var(--line);background:var(--grid), var(--well);border-radius:22px;position:relative}.zoom-in{min-height:420px;padding:24px}.zoom-in.void>:not(.lost){display:none}.lost,.chat-empty{color:var(--dim);text-align:center;padding:60px 0}.keep{align-items:center;gap:20px;padding:18px 22px;display:flex}.keep h2{font-size:24px}.tower.big{width:120px;height:120px}.tower.big svg{width:72px;height:72px}.tower.big>.badge{--s:96px;bottom:4px;right:4px}a.tower:hover:before{border-color:var(--c)}.tally{gap:10px;display:flex}.squads,.camps{grid-template-columns:repeat(auto-fit,minmax(min(100%,430px),1fr));align-items:start;gap:18px;margin-top:20px;display:grid}.squad{background:color-mix(in srgb, var(--surface-0) 78%, transparent);padding:14px 16px 18px}.squad[data-mark=waiting]{background:color-mix(in srgb, var(--amber) 7%, var(--surface-0))}.squad h3{align-items:center;gap:10px;margin-bottom:14px;display:flex}.squad h3 b,.crumbs b{color:var(--text)}.squad h3 small{margin-left:auto}.squad h3 svg{width:18px;height:18px}.flag{background:var(--c);width:10px;height:10px;box-shadow:0 0 8px var(--c);border-radius:2px;transform:rotate(45deg)}.formation{flex-wrap:wrap;align-items:flex-start;gap:16px 20px;display:flex}.col{justify-items:center;gap:8px;width:196px;display:grid}.say{background:var(--raised);width:100%;color:var(--dim);border-radius:12px;margin-top:4px;padding:7px 10px;font-size:12px;line-height:1.35}.say p{overflow-wrap:anywhere;max-height:4.05em;overflow:hidden}.drones{flex-wrap:wrap;justify-content:center;gap:8px;width:100%;padding-top:16px;display:flex;position:relative}.drones:empty{display:none}.tower-drones{justify-content:flex-start;margin-top:-8px;padding-left:35px}.drones.tower-drones:before{left:82px}.drones:before{content:"";background:repeating-linear-gradient(color-mix(in srgb, var(--line-c) 60%, transparent) 0 4px, transparent 4px 8px);width:1px;height:14px;position:absolute;top:0;left:50%}.camp .token{width:156px}[data-group=outside] .plate{filter:saturate(.3);outline:1px dashed color-mix(in srgb, var(--dim) 55%, transparent);outline-offset:4px}.comms-in{grid-template-columns:minmax(0,1fr)}.comms-in,.tile{height:calc(var(--vvh,100vh) - var(--hud,64px) - 64px);grid-template-rows:auto minmax(0,1fr) auto;min-height:380px;display:grid;overflow:hidden}.comms-head,.tile>header{background:var(--panel);align-items:center;gap:12px;padding:12px 18px;display:flex}.ava{width:30px;height:30px;color:var(--accent);background:radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--accent) 28%, transparent), var(--plate) 72%);border-radius:50%;flex:none;place-items:center;display:grid}.ava svg{width:58%;height:58%}.comms-head h2{font-size:16px}.chan{white-space:nowrap;flex:none;margin-left:auto}.head-id{flex:auto;min-width:0}.head-id h2,.head-id p{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.head-back{display:none}.modes+.chan{margin-left:12px}.head-main,.head-quit{margin-left:4px}.head-quit{letter-spacing:.08em;text-transform:uppercase;border-radius:12px;padding:6px 10px}.chat-root{min-height:0;display:grid;position:relative}.comms-in .ask{max-height:calc((var(--vvh,100vh) - var(--hud,64px) - 64px) * .55);overscroll-behavior:contain;overflow-y:auto}.chat-scroll{overflow-anchor:none;padding:12px 16px;font-size:15px;overflow-y:auto}.chat-list{gap:8px;max-width:1040px;margin-inline:auto;display:grid}.tx.in+.tx.in,.tx.you+.tx.you{margin-top:-4px}.tx.in+.tx.in>.ava,.tx.you+.tx.you .ava{visibility:hidden}.tx.in+.tx.in .tx-body>header b,.tx.you+.tx.you>header b{display:none}.chat-top{height:1px}.chat-end{height:1px;margin-top:-1px}.chat-live{max-width:1040px;color:var(--c);align-items:center;gap:10px;margin:14px auto 0;padding-left:44px;font-size:12px;display:flex}.chat-pill{--c:var(--accent);border:0;position:absolute;bottom:14px;left:50%;transform:translate(-50%)}.lit:after{content:"";background:color-mix(in srgb, var(--accent) 18%, transparent);border-radius:14px;animation:1s 1s forwards out;position:absolute;inset:0}.lit.flip:after{animation-name:out-b}.composer{border-top:1px solid var(--line);background:var(--panel);gap:8px;padding:12px 18px 14px;display:grid;position:relative}.cmp-row,.cmp-acts,.cmp-foot,.cmp-note{align-items:center;gap:8px;display:flex}.cmp-row{align-items:flex-end;gap:10px}.composer textarea{resize:none;border:1px solid var(--line);background:var(--sunken);min-width:0;color:var(--text);font:14px/1.4 var(--sans);border-radius:12px;flex:1;padding:9px 12px}@supports (field-sizing:content){.composer textarea{field-sizing:content;max-height:220px}.composer{grid-template-columns:minmax(0,1fr)}}.composer textarea:focus{border-color:color-mix(in srgb, var(--accent) 50%, transparent);box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent);outline:none}.composer.ended{padding:12px 18px calc(12px + env(safe-area-inset-bottom))}.cmp-bar{text-align:center;color:var(--dim);margin:0;font-size:13px}.composer button:disabled{opacity:.45;cursor:default}.cmp-note{flex-wrap:wrap;flex:1;min-height:18px}.cmp-note[data-tone=error],.cmp-alt.cmp-stop{color:var(--err-soft)}.cmp-note[data-tone=ok]{color:var(--ok)}.cmp-note[data-tone=ask]{color:var(--gold)}.cmp-link{color:var(--accent);font:12px var(--sans);cursor:pointer;background:0 0;border:0;padding:0}.slash{z-index:5;border:1px solid var(--line);background:var(--surface-0);max-height:260px;box-shadow:0 8px 24px color-mix(in srgb, var(--shadow) 53%, transparent);border-radius:12px;margin:0;padding:4px;list-style:none;position:absolute;bottom:calc(100% - 6px);left:18px;right:18px;overflow-y:auto}.slash[hidden]{display:none}.slash li{cursor:pointer;border-radius:8px;align-items:baseline;gap:10px;padding:6px 10px;display:flex}.slash li[aria-selected=true]{background:color-mix(in srgb, var(--accent) 12%, transparent)}.slash b{color:var(--accent);font:600 13px var(--mono);white-space:nowrap}.slash span{min-width:0;color:var(--dim);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.cmp-yes{background:var(--gold);color:var(--ink);font:600 12px var(--sans);cursor:pointer;border:0;border-radius:8px;padding:3px 10px}.tx{content-visibility:auto;contain-intrinsic-size:auto 220px;min-width:0}.tx.you{contain-intrinsic-size:auto 76px}.tx.sys,.tx.rule{contain-intrinsic-size:auto 40px}.tx.note{contain-intrinsic-size:auto 24px}.tx time,.tx.note{color:var(--dim);font:11px var(--mono)}.tx.you{justify-items:end;gap:5px;display:grid}.tx.you>header{color:var(--gold);align-items:center;gap:8px;display:flex}.tx.you .ava{color:var(--gold)}.bubble{border:1px solid color-mix(in srgb, var(--gold) 22%, transparent);background:color-mix(in srgb, var(--gold) 8%, transparent);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:14px;max-width:80%;padding:7px 12px;line-height:1.5}.bubble .boss-flag{opacity:.7;display:block}.tx.in{grid-template-columns:30px minmax(0,1fr);align-items:start;gap:8px;display:grid}.tx-body{border:1px solid var(--line);background:var(--panel);border-radius:14px;gap:6px;padding:8px 12px;display:grid}.tx-body,.tx-body>*{min-width:0}.tx-body>header{color:var(--dim);font:11px var(--mono);align-items:baseline;gap:10px;display:flex}.tx-body>header b{color:var(--accent);font:600 13px var(--sans)}.stop,.dialog .tag{background:var(--c1);color:var(--c);border-radius:999px;padding:1px 8px;font-size:10px}.fault{color:var(--err-soft);font-size:13px}.thought,.more,.tab-btn{border:1px solid var(--line);color:var(--dim);font:11px var(--sans);cursor:pointer;background:0 0;border-radius:999px;justify-self:start;padding:2px 10px}.thought-text:empty{display:none}.thought-text,.out,.args,.notice pre,.rule pre{white-space:pre-wrap;overflow-wrap:anywhere;color:var(--dim);font:13px/1.45 var(--mono)}.act,.notice{border:1px solid color-mix(in srgb, var(--hi) 7%, transparent);background:color-mix(in srgb, var(--hi) 3%, transparent);border-radius:10px}.act>summary,.notice>summary,.rule summary{cursor:pointer;align-items:center;gap:8px;min-width:0;padding:5px 10px;font-size:13.5px;list-style:none;display:flex}summary::-webkit-details-marker{display:none}.act code{color:var(--c);font:600 11px var(--mono);letter-spacing:.06em;text-transform:uppercase}.sum{min-width:0;color:var(--dim)}.act[open] .sum{white-space:normal}.open{flex:none;margin-left:auto}.act>pre,.result{margin:0 10px 8px}.result{gap:6px;display:grid}.tx.sys{padding-left:38px}.notice{border-color:color-mix(in srgb, var(--violet) 20%, transparent);background:color-mix(in srgb, var(--violet) 7%, transparent)}.notice .ava{width:22px;height:22px}.notice pre,.rule pre{padding:0 10px 8px}.notice>.boss-flag{opacity:.7;padding:0 10px 4px;display:block}.notice-raw{margin:0 10px 8px}.notice-raw>summary{color:var(--dim);cursor:pointer;font-size:12px}.notice-raw pre{padding:4px 0 0}.rule summary{justify-content:center}.rule summary:before,.rule summary:after{content:"";background:var(--line);flex:1;height:1px}.tx.note{text-align:center}.dossier-in{text-align:center;justify-items:center;gap:6px;display:grid;position:relative}.dossier-in>.tag{text-align:left;justify-self:stretch}.portrait{background:radial-gradient(var(--c1), transparent 70%);border-radius:50%;padding:8px}.portrait .plate{--s:96px}.dossier-in h3{overflow-wrap:anywhere;margin-top:4px;font-size:18px}.d-line,.who p{align-items:baseline;gap:8px;display:flex}.d-note{background:color-mix(in srgb, var(--amber) 12%, transparent);border-radius:10px;padding:8px 10px;font-size:12px}.specs{text-align:left;justify-self:stretch;gap:2px;margin-top:10px;display:grid}.specs div{background:color-mix(in srgb, var(--hi) 4%, transparent);grid-template-columns:76px minmax(0,1fr);gap:8px;padding:7px 10px;display:grid}.specs dt{font-size:10px}.specs dd{overflow-wrap:anywhere;font-size:12.5px}.d-drones,.d-squads{margin-top:8px}.d-squads{justify-self:stretch;gap:10px;display:grid}.d-squad{gap:6px;display:grid}.d-squad small{color:var(--dim)}.d-squad .formation{gap:6px}.d-x,.head-info{display:none}.d-drones .formation{justify-content:center;gap:6px}.md{overflow-wrap:anywhere;line-height:1.55}.md p,.md ul,.md ol,.md pre,.md table,.md blockquote{margin:0 0 8px}.md>:last-child{margin-bottom:0}.md :is(h1,h2,h3,h4,h5,h6){margin:12px 0 6px;font-size:16px}.md>:first-child{margin-top:0}.md h1{font-size:19px}.md ul,.md ol{padding-left:22px}.md li>p{margin:0}.md li.task{margin-left:-18px;list-style:none}.check{vertical-align:-2px;text-align:center;width:14px;height:14px;font:700 10px/12px var(--mono);border:1px solid;border-radius:4px;margin-right:7px;display:inline-block}.check[data-done=true]{background:var(--ok);color:var(--ink)}.md code{background:color-mix(in srgb, var(--hi) 8%, transparent);font:13.5px var(--mono);border-radius:5px;padding:1px 5px}.md pre{border:1px solid var(--line);background:var(--sunken);border-radius:10px;padding:10px 12px;overflow-x:auto}.md pre code{background:0 0;padding:0}.md blockquote{background:color-mix(in srgb, var(--hi) 4%, transparent);color:var(--dim);padding:6px 12px}.md table{border-collapse:collapse;display:block;overflow-x:auto}.md th,.md td{border:1px solid var(--line);padding:4px 10px}.tiles{flex:1 1 0;gap:20px;min-width:0;display:flex}.tile-tabs{display:none}.tile{min-width:0;top:calc(var(--hud,64px) + 20px);border:1px solid var(--line);background:var(--panel);border-radius:22px;flex:1 1 0;position:sticky}.tile>header svg{width:22px;height:22px;color:var(--gold)}.tile{grid-template-columns:minmax(0,1fr)}.tile>header b{flex:1;min-width:0}.tile-body{padding:16px 20px;overflow:auto}.tiles.tabbed{flex-direction:column;gap:8px}.tile:has(.spawn,.pair){height:auto;min-height:0;max-height:calc(var(--vvh,100vh) - var(--hud,64px) - 64px);align-self:flex-start}.spawn .chat-empty{text-align:left;padding:0}.spawn .chat-empty:empty{display:none}.tiles.tabbed .tile-tabs{gap:6px;display:flex}.tiles.tabbed .tile:not(.active){display:none}.tiles.tabbed .tile{flex:none}.tab-btn.active,.open{border-color:color-mix(in srgb, var(--gold) 40%, transparent);color:var(--gold)}.dock{z-index:20;top:calc(var(--hud,64px) + 24px);pointer-events:none;width:min(300px,100vw - 44px);display:grid;position:fixed;right:max(20px,50vw - 1080px)}.dialog{pointer-events:auto;border:1px solid var(--c4);background:linear-gradient(var(--c1), var(--surface-0) 70%), var(--raised);box-shadow:0 24px 60px color-mix(in srgb, var(--shadow) 80%, transparent);transform-origin:top;border-radius:18px;grid-area:1/1;padding:14px 16px 16px;transition:transform .3s,opacity .3s;position:relative}.dialog:focus{outline:none}.dialog{max-height:calc(100dvh - var(--hud,64px) - 44px);overscroll-behavior:contain;overflow-y:auto}.dialog>header{align-items:center;gap:8px;min-width:0;margin-bottom:12px;display:flex}.where{min-width:0}.x{color:var(--dim);cursor:pointer;background:0 0;border:0;margin-left:auto;font-size:20px}.zoom{color:var(--dim);cursor:pointer;background:0 0;border:0;margin-left:auto;padding:0 6px;font-size:17px}.zoom+.x{margin-left:0}.zoom:hover,.x:hover{color:var(--text)}.dock.wide{width:min(880px,100vw - 44px);top:72px;right:50%;transform:translate(50%)}.dock.wide .dialog{max-height:calc(100dvh - 96px)}.who{align-items:center;gap:14px;display:flex}.who .plate{--s:56px}.who h3{font-size:17px}.intel{background:color-mix(in srgb, var(--bg) 55%, transparent);border-radius:12px;margin-top:12px;padding:10px 12px}.intel h4{margin-bottom:4px}.said{overflow-wrap:anywhere;font-size:13px;line-height:1.45}.pending{color:var(--c);font:12px var(--mono);overflow-wrap:anywhere;margin-top:8px}.dialog footer{flex-wrap:wrap;align-items:center;gap:10px;margin-top:14px;display:flex}.ask{border:1px solid color-mix(in srgb, var(--amber) 35%, transparent);background:color-mix(in srgb, var(--amber) 6%, transparent);border-radius:14px;gap:8px;margin:10px 18px 0;padding:12px 14px;display:grid}.dialog .ask{margin:10px 0 0}.ask-one{gap:8px;display:grid}.ask-one+.ask-one{margin-top:8px}.ask-head{background:color-mix(in srgb, var(--amber) 14%, transparent);color:var(--gold);letter-spacing:.06em;text-transform:uppercase;border-radius:999px;justify-self:start;padding:1px 9px;font-size:11px}.ask-how{color:var(--dim);font-size:12px}.ask-q{white-space:pre-wrap;overflow-wrap:anywhere;font-weight:600}.ask-ctx,.ask-why{color:var(--dim);white-space:pre-wrap;overflow-wrap:anywhere;max-height:9em;font-size:13px;overflow:auto}.ask-opts{counter-reset:opt;gap:6px;max-height:16em;margin:0;padding:0;list-style:none;display:grid;overflow:auto}.ask-opt{border:1px solid var(--line);background:var(--sunken);overflow-wrap:anywhere;counter-increment:opt;border-radius:10px;gap:2px;padding:7px 12px;font-size:13px;display:grid}.ask-opt b:before{content:counter(opt) ". ";color:var(--dim)}.ask-opt b[data-n]:before{content:attr(data-n) ". "}.ask-opt small{color:var(--dim);font-size:12px}.ask-acts{flex-wrap:wrap;align-items:center;gap:6px 14px;display:flex}.ask-acts>:last-child{margin-left:auto}.ask-term{color:var(--gold);font-size:12px}.ask button:disabled{opacity:.45;cursor:default}.ask-note:empty{display:none}.ask-note{color:var(--dim);flex-wrap:wrap;align-items:center;gap:4px 10px;font-size:12px;display:flex}.ask-note[data-tone=error]{color:var(--err-soft)}.ask-note[data-tone=ok]{color:var(--ok)}.ask-title{font:12.5px/1.45 var(--mono);white-space:pre-wrap;overflow-wrap:anywhere;max-height:12em;margin:0;overflow:auto}div.ask-opts{max-height:none;overflow:visible}button.ask-opt{text-align:left;color:var(--text);font:13px var(--sans);cursor:pointer}.ask-opt[aria-checked=true]{border-color:var(--amber);background:color-mix(in srgb, var(--amber) 12%, transparent)}.ask-own{resize:vertical;field-sizing:content;border:1px solid var(--line);background:var(--sunken);min-width:0;max-height:10em;color:var(--text);font:13px var(--sans);border-radius:10px;padding:7px 12px}.ask-memo{font-size:12px}.ask input:disabled,.ask textarea:disabled{opacity:.45}.ask-send{background:var(--amber);color:var(--ink);font:600 13px var(--sans);cursor:pointer;border:0;border-radius:10px;padding:7px 13px}.ask-cancel{border:1px solid var(--line);color:var(--text);font:600 13px var(--sans);cursor:pointer;background:0 0;border-radius:10px;padding:7px 13px}.trust h4{color:var(--dim);letter-spacing:.14em;text-transform:uppercase;margin:4px 0 0;font-size:11px;font-weight:400}.trust-found{gap:8px;max-height:14em;display:grid;overflow:auto}.trust-group b{font:12.5px var(--mono);overflow-wrap:anywhere}.trust-group small{color:var(--err-soft);display:block}.trust-group ul{font:12px/1.5 var(--mono);color:var(--dim);overflow-wrap:anywhere;margin:2px 0 0;padding:0 0 0 1.2em}.trust-more{font-family:var(--sans);margin-left:-1.2em;font-style:italic;list-style:none}.trust-folder{font:600 13px/1.4 var(--mono);overflow-wrap:anywhere;margin:0}.trust .ask-why{max-height:none;overflow:visible}.trust .ask-acts>:last-child{margin-left:0}@media (width<=600px){.deploy-trust .trust-found{max-height:7em}.deploy-trust .ask-why{font-size:12px}}.deploy-trust:empty{display:none}.deploy-trust .ask{margin:0}.go,.later,.chat-pill,.cmp-send,.cmp-alt{font:600 13px var(--sans);cursor:pointer;border-radius:10px;padding:7px 13px;text-decoration:none}.go,.chat-pill{background:var(--c);color:var(--ink)}a.go{justify-content:center;align-items:center;display:inline-flex}.cmp-send{background:var(--accent);color:var(--ink);border:0}.later,.cmp-alt{border:1px solid var(--line);color:var(--text);background:0 0}.queued{color:var(--dim);flex:1 0 100%;font-size:12px}.queued:empty{display:none}html.paused *,html.paused :before,html.paused :after{animation-play-state:paused!important}@media (width<=1100px){.stage[data-view]{grid-template-columns:1fr}.side{position:static}}@media (width<=1040px){.stats{display:none}}.term-tile{grid-template-rows:auto minmax(0,1fr) auto;gap:10px;height:100%;display:grid}.tile-body:has(.term-tile){padding:12px 14px;overflow:hidden}.term-bar{justify-content:space-between;align-items:center;gap:12px;font-size:12px;display:flex}.term-scroll{transition:border-color .2s,box-shadow .2s}.term-scroll.typing{border-color:var(--accent);box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent), 0 0 22px color-mix(in srgb, var(--accent) 18%, transparent)}.term-scroll.engage{animation:.6s ease-out term-engage}.term-scroll.blip{animation:.22s ease-out term-blip}.term-scroll.blip.flip{animation-name:term-blip-b}@keyframes term-engage{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--accent) 80%, transparent), 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent)}60%{box-shadow:0 0 0 7px color-mix(in srgb, var(--accent) 0%, transparent), 0 0 34px color-mix(in srgb, var(--accent) 40%, transparent)}to{box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent), 0 0 22px color-mix(in srgb, var(--accent) 18%, transparent)}}@keyframes term-blip{0%{box-shadow:0 0 0 2px color-mix(in srgb, var(--accent-hi) 80%, transparent), 0 0 32px color-mix(in srgb, var(--accent) 53%, transparent)}to{box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent), 0 0 22px color-mix(in srgb, var(--accent) 18%, transparent)}}@keyframes term-blip-b{0%{box-shadow:0 0 0 2px color-mix(in srgb, var(--accent-hi) 80%, transparent), 0 0 32px color-mix(in srgb, var(--accent) 53%, transparent)}to{box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent), 0 0 22px color-mix(in srgb, var(--accent) 18%, transparent)}}.term-sink{opacity:0;resize:none;pointer-events:none;border:0;width:1px;height:18px;padding:0;font-size:16px;position:fixed;overflow:hidden}.term-typing{color:var(--accent);margin-left:auto;font-weight:600;animation:1.6s ease-in-out infinite term-note}@keyframes term-note{50%{opacity:.55;text-shadow:0 0 10px color-mix(in srgb, var(--accent) 60%, transparent)}}.term-state{color:var(--dim)}.term-state[data-tone=ok]{color:var(--ok)}.term-state[data-tone=error]{color:var(--err-soft)}.term-scroll{overscroll-behavior:contain;border:1px solid var(--line);background:var(--term-bg);border-radius:14px;padding:8px 10px;overflow:auto}@font-face{font-family:SB Nerd Symbols;src:local(SymbolsNFM),local(Symbols Nerd Font Mono),local(HackNFM-Regular),url(./SymbolsNerdFontMono-DkrHkSnn.woff2)format("woff2");unicode-range:U+E000-F8FF,U+F0000-FFFFD;font-display:swap}.term{width:max-content;min-width:100%;color:var(--term-fg);font:12px/1.3 var(--mono);white-space:pre;font-family:ui-monospace,SF Mono,Menlo,Consolas,SB Nerd Symbols,monospace;transition:opacity .2s}.term .tr{min-height:1.3em}.term.stale{opacity:.5}.term.hidden{display:none}.plate[data-docs]:before{content:attr(data-docs);z-index:1;background:linear-gradient(var(--paper-hi), var(--paper));min-width:10px;height:16px;color:var(--paper-ink);font:700 9px/16px var(--mono);text-align:center;box-shadow:0 0 0 2px var(--plate), 2px 2px 0 1px var(--paper-edge);border-radius:3px 6px;padding:0 3px;position:absolute;top:-5px;left:-5px}.d-docs{text-align:left;margin-top:12px}.d-docs h4{text-align:center;margin:0 0 6px}.d-doc-list{gap:6px;display:grid}.d-doc{border:1px solid color-mix(in srgb, var(--paper) 25%, transparent);background:color-mix(in srgb, var(--paper) 7%, transparent) no-repeat 9px 50% / 13px 16px linear-gradient(var(--paper-hi), var(--paper));width:100%;color:var(--text);font:13px var(--sans);text-align:left;cursor:pointer;border-radius:10px;gap:1px;padding:7px 10px 7px 30px;display:grid}.d-doc:hover{border-color:color-mix(in srgb, var(--paper) 67%, transparent)}.d-doc b{overflow-wrap:anywhere;font-weight:600}.d-doc small{color:var(--dim);font-size:11px}.d-docs-cut{color:var(--dim);margin:6px 0 0;font-size:12px}.doc-tile{grid-template-rows:auto minmax(0,1fr);gap:10px;height:100%;display:grid}.tile-body:has(.doc-tile){padding:12px 14px;overflow:hidden}.doc-bar{flex-wrap:wrap;justify-content:flex-start}.doc-why{min-width:0;color:var(--text);flex:160px}.doc-off{color:var(--gold);font-style:normal}.doc-acts{align-items:center;gap:14px;display:flex}.doc-acts>.cmp-link{align-items:center;display:inline-flex}.doc-frame{border:1px solid color-mix(in srgb, var(--paper) 33%, transparent);background:#fff;border-radius:12px;width:100%;height:100%;min-height:240px}.doc-text{border:1px solid color-mix(in srgb, var(--paper) 25%, transparent);background:var(--plate);border-radius:12px;padding:14px 18px;overflow:auto}.doc-pre{white-space:pre-wrap;font:12.5px/1.45 var(--mono);margin:0}.pad{gap:6px;display:grid}.pad-row{grid-template-columns:repeat(auto-fit,minmax(48px,1fr));gap:6px;display:grid}.pad-key{border:1px solid var(--line);background:var(--surface-0);min-height:34px;color:var(--text);font:600 12px var(--mono);cursor:pointer;border-bottom-width:3px;border-radius:9px;padding:4px 6px}.pad-key:active:not(:disabled){background:var(--raised);border-bottom-width:1px;transform:translateY(2px)}.pad-key:disabled{opacity:.35;cursor:default}.pad-key[data-key=enter]{color:var(--accent)}.pad-key[data-key=esc]{color:var(--gold)}.pad-key:is([data-key=up],[data-key=down],[data-key=left],[data-key=right],[data-key=backspace]){font-size:16px}.pad-digits summary{color:var(--dim);cursor:pointer;padding:2px 0;font-size:12px}.pad-note:empty{display:none}.pad-note{color:var(--dim);flex-wrap:wrap;align-items:center;gap:6px 12px;margin:0;font-size:12px;display:flex}.pad-note[data-tone=error]{color:var(--err-soft)}.pad-note[data-tone=ask]{border:1px solid color-mix(in srgb, var(--amber) 40%, transparent);background:color-mix(in srgb, var(--amber) 8%, transparent);color:var(--text);border-radius:10px;padding:8px 10px}.pad-yes{background:var(--amber);color:var(--ink);font:600 12px var(--sans);cursor:pointer;border:0;border-radius:9px;padding:5px 11px}.c0{color:#414868}.cz{color:var(--term-bg)}.c1{color:#f7768e}.c2{color:#9ece6a}.c3{color:#e0af68}.c4{color:#7aa2f7}.c5{color:#bb9af7}.c6{color:#7dcfff}.c7{color:#a9b1d6}.c8{color:#545c7e}.c9{color:#ff899d}.c10{color:#9fe044}.c11{color:#faba4a}.c12{color:#8db0ff}.c13{color:#c7a9ff}.c14{color:#a4daff}.c15{color:#c0caf5}.k0{background:var(--term-bg)}.k1{background:#f7768e}.k2{background:#9ece6a}.k3{background:#e0af68}.k4{background:#7aa2f7}.k5{background:#bb9af7}.k6{background:#7dcfff}.k7,.kz{background:#a9b1d6}.k8{background:#545c7e}.k9{background:#ff899d}.k10{background:#9fe044}.k11{background:#faba4a}.k12{background:#8db0ff}.k13{background:#c7a9ff}.k14{background:#a4daff}.k15{background:#c0caf5}.tb{font-weight:700}.td{opacity:.6}.ti{font-style:italic}.tu{text-decoration:underline}.ts{text-decoration:line-through}.tu.ts{text-decoration:underline line-through}.drawer,.drawer-veil{display:none}.drawer{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;z-index:30;background:var(--surface-0);border-right:1px solid var(--line);width:min(86vw,360px);box-shadow:8px 0 30px color-mix(in srgb, var(--shadow) 50%, transparent);transform:translateX(calc(var(--dx,0px) - 100%));visibility:hidden;flex-direction:column;transition:transform .22s ease-out,visibility 0s .22s;display:flex;position:fixed;inset:0 auto 0 0}.drawer.on{visibility:visible;transition:transform .22s ease-out}.drawer-veil{z-index:29;background:color-mix(in srgb, var(--shadow) 60%, transparent);opacity:0;pointer-events:none;transition:opacity .22s;position:fixed;inset:0}.drawer-drag .drawer,.drawer-drag .drawer-veil{transition:none}.drawer>header{padding:max(12px, env(safe-area-inset-top)) 12px 8px max(14px, env(safe-area-inset-left));color:var(--dim);letter-spacing:.1em;text-transform:uppercase;justify-content:space-between;align-items:center;font-size:12px;display:flex}.drawer-body{overscroll-behavior:contain;min-height:0;padding:4px 10px 16px max(10px, env(safe-area-inset-left));flex:1;align-content:start;gap:12px;display:grid;overflow-y:auto}.drawer-foot{padding:8px 10px max(10px, env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left));border-top:1px solid var(--line);background:var(--surface-0);flex:none}.drawer-sweep{justify-content:flex-end;margin-bottom:8px;display:flex}.drawer-sweep[hidden]{display:none}.drawer-sweep .pair-btn{flex:1;min-height:36px}.drawer-sweep .pair-btn[hidden]{display:none}.drawer-map{border:1px solid var(--line);background:color-mix(in srgb, var(--hi) 4%, transparent);min-height:48px;color:var(--text);border-radius:12px;justify-content:center;align-items:center;padding:0 12px;font-size:14px;font-weight:600;text-decoration:none;display:flex}.drawer-map[aria-current]{color:var(--dim)}.dbase h3{justify-content:space-between;align-items:baseline;gap:8px;margin:0 0 6px;font-size:14px;display:flex}.dbase h3 a{color:var(--text);text-overflow:ellipsis;white-space:nowrap;text-decoration:none;overflow:hidden}.dbase h3 small,.dgroup h4{color:var(--dim);letter-spacing:.1em;text-transform:uppercase;font-size:11px}.dbase[data-mark=waiting] h3 a{color:var(--c)}.dgroups,.drows{gap:6px;display:grid}.dgroup h4{margin:4px 0 0;font-weight:600}.drawer .card{gap:8px;min-height:44px;padding:6px 8px}.drawer .plate{--s:28px}.drawer .subs{margin-left:16px;padding-left:12px}.drawer .trow{justify-content:space-between;align-items:center;gap:8px;display:flex}.drawer .tower-go{border:1px solid var(--line);min-width:0;min-height:44px;color:var(--c);border-radius:12px;flex:1;align-items:center;gap:8px;padding:0 8px;text-decoration:none;display:flex}.drawer .tower-go .meta{min-width:0;color:var(--text);display:grid}.drawer .tower-go .line{gap:6px;min-width:0;display:flex}.drawer .tower-row.current>.trow>.tower-go{border-color:var(--c4);background:var(--c1)}.drawer .tower-go .plate{--s:28px;flex:none}.drawer .tower-add{white-space:nowrap;flex:none;place-items:center;min-width:56px;min-height:44px;padding:0 12px;display:grid}.drawer .tower-add[hidden]{display:none}.drawer .quit-btn{min-height:44px}.drawer .quit-btn[hidden]{display:none}.drawer .line{gap:6px}.drawer .dstate{color:var(--c);flex:none;font-size:11px;font-weight:600}.drawer .unit.current>.card{background:var(--c1);border-color:var(--c4)}.drawer .unit.current>.card>.hit:after{content:"›";color:var(--c);font:700 20px/1 var(--sans);position:absolute;top:50%;right:12px;transform:translateY(-50%)}.drawer .unit[data-dismiss]>.card{transform:translateX(var(--sx,0px));opacity:var(--so,1);transition:transform .2s ease-out,opacity .2s}.drawer .unit>.card.swiping{transition:none}.drawer .unit>.card.gone{--sx:110%;--so:0}@media (width<=640px){.drawer{display:flex}.drawer-veil{display:block}}@media (width<=900px){.work{flex-direction:column;align-items:stretch}.view,.tiles{flex:none}.tile{position:static}.keep{flex-wrap:wrap}}@media (width<=640px){.shell{padding:max(8px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right)) calc(24px + env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-left))}.hud{flex-wrap:wrap;gap:10px;padding:10px 12px;position:static}.brand p,.link span{display:none}.alert-row{flex:100%;order:3;min-width:0}.alert-row .alerts{flex:auto;width:auto;min-width:0}.done-btn{min-height:40px}.brand{flex:auto;min-width:0}.prefs-btn{width:40px;height:40px}.tl-span{display:none}.crumbs{gap:6px}.crumbs>*+:before{margin-right:6px}.crumbs>*{max-width:16ch}.crumbs:not(.open)>.mid{display:none}.crumbs:not(.open)>.crumb-more{flex:none;display:block}.crumbs.open{flex-wrap:wrap;row-gap:4px}.map,.zoom-in{padding:14px}.bases{column-gap:18px}.legend{display:none}.keep{gap:12px;padding:6px}.tower.big{width:84px;height:84px}.tower-drones{padding-left:1px}.drones.tower-drones:before{left:48px}.tally{flex-wrap:wrap}.col{width:100%}.dossier:not(.full){content-visibility:hidden}.comms-in,.dossier.full{left:0;right:0;top:var(--vvt,0px);height:var(--vvh,100dvh);background:var(--bg);position:fixed}.tiles:has(.tile){left:0;right:0;top:var(--vvt,0px);height:var(--vvh,100dvh);background:var(--bg);position:fixed}.comms-in{z-index:15;border:0;border-radius:0;grid-template-columns:minmax(0,1fr);min-height:0}#session-view.enter-slide,#session-view.enter-back{animation:none}#session-view.enter-slide>.comms-in{animation:.4s ease-out both slide}#session-view>.lost{inset:var(--vvt,0px) 0 auto;height:var(--vvh,100dvh);z-index:15;background:var(--bg);margin:0;position:fixed}.tiles:has(.tile){z-index:16;padding:8px;overflow-y:auto}.tile{height:calc(var(--vvh,100dvh) - 16px);border-radius:16px;min-height:300px}.dossier.full{z-index:17;overscroll-behavior:contain;padding:max(16px, env(safe-area-inset-top)) 16px calc(16px + env(safe-area-inset-bottom));border:0;border-radius:0;overflow-y:auto}.dossier.full .d-x{place-items:center;display:grid;position:absolute;top:0;right:0}.comms-head{padding:max(10px, env(safe-area-inset-top)) 12px 10px;grid-template-columns:auto minmax(0,1fr) auto auto auto;gap:8px 10px;display:grid}.comms-head .logo{display:none}.head-back{border:1px solid var(--line);width:40px;height:40px;color:var(--text);border-radius:12px;place-items:center;font-size:24px;text-decoration:none;display:grid}.head-info,.head-main:not([hidden]),.head-quit:not([hidden]){margin:0;padding:0 12px;display:block}.comms-head h2 small,.chan b{display:none}.modes+.chan{margin-left:0}.modes{border:1px solid var(--line);border-radius:12px;grid-area:2/1/auto/-1;padding:3px}.modes button{border:0;border-radius:9px;flex:1;min-height:40px;padding:0;font-size:14px}.modes button[aria-pressed=true]{background:color-mix(in srgb, var(--accent) 12%, transparent)}.chat-scroll{overscroll-behavior:contain;padding:12px}.chat-scroll:focus-visible{outline:none}.bubble{max-width:92%}.composer{padding:10px 12px calc(10px + env(safe-area-inset-bottom))}.cmp-foot:has(>.cmp-note:empty){display:none}.cmp-row{flex-wrap:wrap}.composer textarea{flex:100%;order:-1;min-height:64px}.cmp-acts{margin-left:auto}.dock,.dock.wide{width:calc(100vw - 20px);top:auto;right:10px}.dock{bottom:calc(10px + env(safe-area-inset-bottom))}.dock.wide{transform:none}.dialog .zoom{display:none}}@media (pointer:coarse){.composer textarea,.ask input,.ask textarea{font-size:16px}.composer button,.go,.later,.x,.chat-pill,.pair-btn,.alerts,.ask button,.term-bar button,.doc-acts>.cmp-link,.quit-btn,.d-doc{min-height:40px}}@media (width<=640px),(pointer:coarse){.pad-key,.pad-yes{min-height:44px}.pad-digits summary{padding:14px 0}}@media (width<=640px){.brand{min-height:44px}.prefs-btn{width:44px;height:44px}.crumbs{align-items:center}.crumbs>*{padding-block:14px;line-height:16px}:is(.pair-btn,.alerts,.done-btn,.quit-btn,.later,.go,.x,.d-doc,.ask-send,.ask-cancel,.ask-opt,.sheet-yes,.cmp-yes,.chat-pill){min-height:44px}:is(.pair-btn,.quit-btn,.later,.go,.x,.tab-add,.ask-send,.ask-cancel,.sheet-yes,.cmp-yes){min-width:44px}.set-head .head-back{width:44px;min-height:44px}.lan summary{min-width:44px;padding-block:13px}.set-ctl input[type=range]{min-height:44px}.set-group{padding:12px}.set-row .lang{max-width:55%}.set-ctl{flex-wrap:wrap}.tab h3{min-height:44px}:is(.tab-add,.thought,.more,.tab-btn){isolation:isolate;background:0 0;border:0;min-height:44px;position:relative}:is(.tab-add,.thought,.more,.tab-btn):before{content:"";z-index:-1;border:1px solid var(--line);pointer-events:none;border-radius:999px;position:absolute;inset:11px 0}.tab-add:before{border-radius:10px}.tab-btn.active:before,.more.open:before{border-color:color-mix(in srgb, var(--gold) 40%, transparent)}:is(.act>summary,.notice>summary,.rule summary,.todos summary,.monitors summary,.timeline summary){box-sizing:border-box;align-items:center;min-height:44px;padding-block:0}.todos,.monitors{padding-block:0}:is(.todos ol,.monitors ul){margin:0 0 10px}.link-form summary{padding-block:13px}.queue-act{flex-wrap:nowrap;justify-content:flex-end;gap:10px}.queue-act button{flex:none;min-width:56px;min-height:44px}.trust .ask-acts{grid-template-columns:1fr 1fr;gap:8px;display:grid}.trust .ask-send{grid-column:1/-1}.tl-mark{pointer-events:none}.picker-body{height:clamp(180px,100dvh - 412px,360px)}.tile:has(.spawn,.pair){max-height:calc(var(--vvh,100dvh) - 16px)}.teams-tile{grid-template-columns:minmax(0,1fr)}.teams-tile b{white-space:normal;overflow-wrap:anywhere}.specs a,.d-squad a{padding-block:12px;line-height:20px;display:inline-block}.specs a{margin-block:-7px}.dbase h3{align-items:center}.dbase h3 a{padding-block:12px;line-height:20px}.cmp-link{align-items:center;padding-inline:8px;display:inline-flex}:is(.ask,.term-bar,.doc-acts,.composer) :is(button,.cmp-link){min-height:44px}.slash li{align-items:center;min-height:44px}:where(input:not([type=checkbox],[type=radio],[type=file],[type=hidden]),select,textarea){box-sizing:border-box;min-height:44px}.picker-crumbs button,.picker-places button,.pitem,.drawer-sweep .pair-btn{min-height:44px}.head-back{width:44px;min-width:44px;height:44px}.modes button{min-height:44px}:is(.head-info,.head-main:not([hidden]),.head-quit:not([hidden])){min-width:44px;min-height:44px}.composer textarea{min-height:56px}.cmp-row{gap:8px 10px}.comms-in .ask-acts{background:color-mix(in srgb, var(--amber) 6%, var(--bg));margin:0 -14px -12px;padding:8px 14px 12px;position:sticky;bottom:-12px}.composer :is(.cmp-alt,.cmp-send){min-height:48px}.composer .cmp-alt{min-width:48px}.composer .cmp-send{min-width:64px}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none!important;animation:none!important}}.base.ally{background:linear-gradient(180deg, color-mix(in srgb, var(--accent) 7%, transparent), transparent 42%), linear-gradient(180deg, var(--surface-1), var(--surface-0))}.base.ally .crown{color:var(--accent);background:color-mix(in srgb, var(--accent) 12%, transparent);text-transform:none;letter-spacing:.04em;display:inline-flex}.base.ally.offline{opacity:.55}.ally-tabs{gap:4px;margin:0;padding:0;list-style:none;display:grid}.ally-tab{border:1px solid var(--line);border-radius:10px;justify-content:space-between;gap:10px;padding:6px 10px;font-size:12px;display:flex}.ally-tab b{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.ally-tab span{color:var(--dim);flex:none}.ally-tab[data-state=working] span{color:var(--accent)}.ally-tab[data-state=blocked] span{color:var(--amber)}.link-pop{width:min(460px,100vw - 16px)}.link-pop ul{gap:8px;max-height:60vh;margin:0;padding:0;list-style:none;display:grid;overflow:auto}.link-alert{border:1px solid var(--line);border-radius:10px;gap:6px;padding:8px 10px;font-size:13px;display:grid}.link-alert[data-level=error]{background:#f7768e1a}.link-alert[data-level=warning]{background:color-mix(in srgb, var(--amber) 9%, transparent)}.link-args{border:1px solid var(--line);white-space:pre-wrap;word-break:break-word;border-radius:8px;max-height:180px;margin:0;padding:8px;font-size:11px;overflow:auto}.link-note{color:var(--dim)}.teams-tile{gap:14px;padding:4px 2px 12px;font-size:13px;display:grid}.teams-tile .go{--c:var(--accent)}.teams-tile h3{font-size:15px}.teams-tile h4{margin:0 0 4px;font-size:13px}.link-status{min-height:1.2em;color:var(--amber);margin:0}.link-short{color:var(--dim);font-family:ui-monospace,monospace}.link-meta{color:var(--dim);overflow-wrap:anywhere;margin:2px 0 8px;font-size:12px}.link-team,.link-request,.link-invite,.link-form{border:1px solid var(--line);background:color-mix(in srgb, var(--surface-1) 70%, transparent);border-radius:12px;padding:10px 12px}.link-request{background:color-mix(in srgb, var(--amber) 9%, transparent)}.link-team[data-status=stopped]{background:#f7768e1a}.link-warn{border:1px solid var(--line);background:color-mix(in srgb, var(--amber) 10%, transparent);border-radius:8px;margin:6px 0;padding:6px 10px}.link-roster{border-collapse:collapse;width:100%;margin:6px 0 10px}.link-roster th{text-align:left;color:var(--dim);padding:2px 6px;font-size:11px;font-weight:500}.link-roster .nw{white-space:nowrap}.link-roster select{max-width:100%}.link-roster td{vertical-align:middle;overflow-wrap:anywhere;padding:5px 6px}.link-roster tr[data-online=false] td{color:var(--dim)}.link-roster em{color:var(--dim);margin-left:6px;font-size:11px;font-style:normal}.link-roster .link-dup{color:var(--amber)}.link-acts{flex-wrap:wrap;gap:6px;display:flex}.link-acts button{white-space:nowrap}.link-inline{gap:8px;margin-top:8px;display:flex}.link-inline input{flex:1;min-width:0}.link-words{gap:8px;margin:8px 0;display:grid}.link-set{letter-spacing:.02em;text-align:left;padding:10px 12px;font-size:15px}.link-bigwords{letter-spacing:.04em;overflow-wrap:anywhere;margin:8px 0;font-size:20px;font-weight:700}.link-invite{justify-items:start;gap:8px;display:grid}.link-invite .qr{border-radius:8px;width:min(240px,100%);height:auto}.link-invite textarea,.link-form textarea{width:100%;font-family:ui-monospace,monospace;font-size:11px}.link-invite[data-lapsed=true] .qr{opacity:.25}.link-count{font-variant-numeric:tabular-nums}.link-form{gap:8px;display:grid}.link-form summary{cursor:pointer;font-weight:600}.link-form label{color:var(--dim);gap:3px;display:grid}.link-scan video{border-radius:10px;width:min(320px,100%)}.link-open-invite{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.teams-tile [data-armed=true]{color:var(--amber)}@media (width<=640px){.link-roster thead{display:none}.link-roster tr{border-bottom:1px solid var(--line);grid-template-columns:1fr 1fr;gap:2px 8px;padding:6px 0;display:grid}}.tower-memory .tmem>summary{cursor:pointer;align-items:baseline;gap:8px;font-size:.85em;display:flex}.tower-memory .tmem-counts{opacity:.7}.tmem-body{gap:10px;min-width:0;margin-top:6px;font-size:.85em;display:grid}.tmem-body h4{margin:0 0 4px;font-size:1em}.tmem-body h4 small{opacity:.6;margin-left:6px}.tmem-body ul{gap:4px;margin:0;padding:0;list-style:none;display:grid}.tmem-body li{flex-wrap:wrap;align-items:center;gap:6px;min-width:0;display:flex}.tmem-body .tmem-text{overflow-wrap:anywhere;flex:14em;min-width:0}.tmem-body li small{opacity:.65}.tmem-ended .tmem-text{opacity:.6;text-decoration:line-through}.tmem-body input{flex:12em;min-width:0}.tmem-add{gap:6px;margin-top:4px;display:flex}.tmem-empty,.tmem-note{opacity:.7;margin:0}.tmem-body .tnote-fail{color:var(--err-soft)}.tmem-body .tnote-fail:empty{display:none}.tower-conv{border:1px solid var(--line);border-radius:10px;gap:4px;min-width:0;margin-bottom:6px;padding:8px 10px;font-size:.85em;display:grid}.tower-conv[hidden]{display:none}.tower-conv p{overflow-wrap:anywhere;min-width:0;margin:0}.tower-conv .conv-line>span{max-width:100%;display:inline-block}.tower-conv .conv-line b{color:var(--accent)}.tower-conv .conv-now,.tower-conv .conv-cap{opacity:.85}.tower-conv .conv-acts{flex-wrap:wrap;align-items:center;gap:6px 8px;display:flex}.tower-conv .conv-acts button:disabled{opacity:.6;cursor:progress}.tower-conv .conv-done{color:var(--dim)}.tower-conv .conv-done:empty,.tower-conv .tnote-fail:empty{display:none}.tower-conv .tnote-fail{color:var(--err-soft)}.tower-conv .conv-runs{flex-wrap:wrap;gap:4px 6px;display:flex}.tower-conv :is(.conv-facts,.conv-runs-bar){display:none}.tx.conv-rule{justify-content:center;padding:6px 0;display:flex}.tx.conv-rule>div{border-top:1px solid color-mix(in srgb, var(--accent) 40%, transparent);color:var(--accent);text-align:center;flex-wrap:wrap;justify-content:center;gap:2px 10px;padding:2px 12px;font-size:.8em;display:flex}.tx.conv-rule small{color:var(--dim)}.term-bar .term-kb{border:1px solid var(--line);background:var(--surface-0);border-radius:9px;padding:4px 12px;font-weight:600}.term-bar .term-kb[aria-pressed=true]{border-color:var(--accent);background:color-mix(in srgb, var(--accent) 14%, var(--surface-0))}@media (width<=640px){.term-typing{display:none}.menu-btn{letter-spacing:0;place-items:center;width:44px;min-width:44px;height:44px;padding:0;font-size:22px;line-height:1;display:grid}.menu-pop:not(:popover-open){display:none}.menu-pop:popover-open{gap:6px;min-width:200px;max-width:calc(100vw - 16px);display:grid}.menu-pop :is(.pair-btn,.quit-btn){text-align:left;justify-content:flex-start;width:100%;margin:0;padding-inline:14px}.menu-pop .quit-btn{opacity:1;font-size:14px}.menu-pop:popover-open .quit-btn{color:var(--err-soft)}.hud{gap:6px 8px;padding:6px 8px 6px 10px}.bar-acts{gap:6px;display:grid}.bar-acts .pair-btn{justify-content:flex-start;width:100%}body[data-route=map] .crumbs{display:none}body[data-route=map] .bar{margin:0}.map{min-height:0;padding:8px}.base :is(.card>.quit-btn[data-close=unit],.tower-quit){display:none}.comms-head{padding-block:max(6px, env(safe-area-inset-top)) 6px;gap:6px 8px}.comms-head:not([data-tower]) .menu-btn{display:none}.comms-head:not([data-tower]) .menu-pop{display:contents}.modes{padding:1px}.tx.in{grid-template-columns:minmax(0,1fr)}.tx.in>.ava{display:none}.tx.sys,.chat-live{padding-left:0}.tower-notes,.queue-bar,.queue-list,.queue-act,.todos,.monitors{margin-inline:10px}.todos,.monitors{margin-top:2px}.composer{padding:6px 10px calc(6px + env(safe-area-inset-bottom))}.composer textarea{min-height:44px}.cmp-row{gap:6px 10px}.queue-bar:not([hidden]){margin-bottom:0;display:block}.queue-fold{border:1px dashed color-mix(in srgb, var(--accent) 45%, transparent);width:100%;min-height:44px;color:var(--accent);font:600 13px var(--sans);text-align:left;cursor:pointer;background:0 0;border-radius:12px;justify-content:space-between;align-items:center;padding:0 14px;display:flex}.queue-fold:after{content:"▸";color:var(--dim)}.queue-bar[data-open] .queue-fold:after{content:"▾"}.queue-bar:not([hidden]):not([data-open])~:is(.queue-list,.queue-act){display:none}.tower-conv{grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:0 4px;margin-bottom:0;padding:0 0 0 12px}.tower-conv .conv-line{white-space:nowrap;text-overflow:ellipsis;grid-column:1;overflow:hidden}.tower-conv .conv-line>span{max-width:none;display:inline}.tower-conv .conv-line>:is(.conv-began,.conv-cap,.conv-sep){display:none}.tower-conv .conv-line:has(.conv-now) b:after{content:" ·";color:var(--dim)}.tower-conv .conv-runs-bar{display:block}.tower-conv .conv-facts{color:var(--dim);font-size:12px;display:block}.menu-pop .conv-acts{gap:6px;display:grid}.menu-pop .conv-runs{gap:6px;padding-top:2px}.menu-pop .ally-chip{box-sizing:border-box;align-items:center;min-height:44px;padding-inline:12px;display:inline-flex}.tower-conv .menu-btn{background:0 0;border:0;grid-area:1/2}.zoom-in{min-height:0;padding:8px}.tally{grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;width:100%;display:grid}.tally div{padding:4px 6px}.squads,.camps{gap:10px;margin-top:10px}.squad{padding:10px}.squad h3{margin-bottom:8px}.formation{gap:8px;display:grid}.col{justify-items:stretch;gap:4px;width:100%}.col>.token{text-align:left;grid-template-columns:auto minmax(0,1fr);place-items:center start;column-gap:12px;padding:6px 10px}.col>.token .plate{--s:44px;grid-row:span 2;margin:0}.col>.token :is(.name,.line){grid-column:2}.col>.token .line{flex-wrap:wrap;align-items:baseline;gap:0 8px;display:flex}.col .say{margin-top:0}.col .drones{justify-content:flex-start;padding-top:8px}.base .card:has(>.quit-btn:not([hidden])){flex-wrap:wrap;row-gap:2px}.base .card>.meta{flex:1 1 0;min-width:0}.base .card>.quit-btn:not([hidden]){flex:100%;margin:0}.base .card>.quit-btn:not([hidden])~.ticks{bottom:3px}.comms-in .ask-opts{max-height:none;overflow:visible}.comms-in .ask-ctx,.comms-in .ask-why{max-height:5em}.comms-in .ask-acts{z-index:1}.comms-in .ask[data-more] .ask-acts:before{content:attr(data-cue);text-align:center;color:var(--gold);white-space:nowrap;pointer-events:none;flex:100%;order:-1;padding:0;font-size:12px;line-height:18px}.comms-in .ask[data-more] .ask-acts:after{content:"";background:linear-gradient(transparent, color-mix(in srgb, var(--amber) 6%, var(--bg)));pointer-events:none;z-index:-1;height:24px;position:absolute;bottom:100%;left:0;right:0}.composer textarea::placeholder{font-size:13px}}@media (width<=380px){.composer textarea::placeholder{font-size:12px}.tower-conv .conv-line{-webkit-line-clamp:2;white-space:normal;-webkit-box-orient:vertical;padding-block:6px;display:-webkit-box}.composer:has(textarea:placeholder-shown:not(:focus)) .cmp-row{flex-wrap:nowrap;align-items:center}.composer:has(textarea:placeholder-shown:not(:focus)) textarea{flex:1 1 0;order:0;min-width:0}.composer:has(textarea:placeholder-shown:not(:focus)) .cmp-row>.cmp-alt{order:-1}.composer:has(textarea:placeholder-shown:not(:focus)) .cmp-acts{order:1;margin-left:0}.brand{flex:1 1 0}[data-view=geek] .brand h1{letter-spacing:.06em;font-size:15px}[data-view=geek] .brand{gap:8px}}.settings.view{grid-template-columns:minmax(0,1fr);align-content:start;gap:14px;max-width:760px;margin-inline:auto;display:grid}.set-head{align-items:center;gap:12px;display:flex}.set-head h2{font:600 20px var(--sans);margin:0}.set-head .head-back{border:1px solid var(--line);width:40px;height:40px;color:var(--text);border-radius:12px;place-items:center;font-size:24px;text-decoration:none;display:grid}.set-group{border:1px solid var(--line);background:var(--panel);border-radius:18px;grid-template-columns:minmax(0,1fr);gap:4px;padding:14px 18px;font-size:13px;display:grid}.set-group h3{font:600 15px var(--sans);margin:0}details.set-group>summary{cursor:pointer;align-items:center;gap:10px;min-height:44px;list-style:none;display:flex}details.set-group>summary::-webkit-details-marker{display:none}details.set-group>summary:after{content:"▸";color:var(--dim);margin-left:auto}details.set-group[open]>summary:after{content:"▾"}details.set-group:not([open]){padding-block:6px}details.set-group[open]>summary{margin-bottom:8px}details.set-group[hidden]{display:none}.set-note{color:var(--dim);margin:0;font-size:12px}.set-note:empty{display:none}.set-row{justify-content:space-between;align-items:center;gap:12px;min-height:44px;display:flex}.set-row>:first-child{color:var(--text);font-size:14px}.set-row .tog{text-transform:none;letter-spacing:0;justify-content:flex-start;min-width:7em;font-size:13px}.set-sub{padding-left:14px}.set-sub>:first-child{color:var(--dim);font-size:13px}.set-ctl{flex:auto;justify-content:flex-end;align-items:center;gap:10px;min-width:0;display:flex}.set-ctl input[type=range]{min-width:0;max-width:220px;accent-color:var(--accent);flex:1}.set-ctl output{text-align:right;width:3ch;font:12px var(--mono);color:var(--dim)}.set-ctl .pair-btn{text-transform:none;letter-spacing:0}.set-row .lang{max-width:60%}.set-body .pair-btn{text-transform:none;letter-spacing:0}.set-body{min-width:0}.set-body .pair,.set-body .teams-tile{padding:0}.set-body .chat-empty{padding:6px 0}.set-body .chat-empty:empty{display:none}.set-row+.set-note{margin-top:-2px}body[data-route=settings] :is(.bar-acts,.crumbs){display:none}[data-view=geek]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--bg:#000;--bg-2:#000;--surface-0:#0d0d0d;--surface-1:#161616;--raised:#0d0d0d;--sunken:#000;--well:#000;--panel:#0d0d0d;--plate:#000;--plate-hi:#1f1f1f;--term-bg:#000;--term-fg:#f2f2f2;--line-c:#8a8a8a;--line:#8a8a8a;--hi:#fff;--shadow:#000;--text:#f2f2f2;--dim:#bdbdbd;--ink:#000;--accent:#5fd7ff;--accent-hi:#a8e8ff;--working:#5fd7ff;--gold:#ffd75f;--amber:#ffd75f;--ok:#87e087;--err:#ffa0a0;--err-soft:#ffb4b4;--violet:#d7afff;--idle:silver;--unknown:#bababa;--paper-hi:#f6e6b8;--paper:#d8bd78;--paper-ink:#3b2a06;--paper-edge:#8a6f33;--aura-1:transparent;--aura-2:transparent;--grid:none;--sans:var(--mono)}[data-view=geek] body{font-size:13px}[data-view=geek] [data-mark]{--c1:color-mix(in srgb, var(--c) 12%, transparent);--c4:var(--line)}[data-view=geek] *,[data-view=geek] :before,[data-view=geek] :after{scroll-behavior:auto!important;box-shadow:none!important;text-shadow:none!important;transition:none!important;animation:none!important}[data-view=geek] :is(.logo svg,.deploy-title svg,.tower svg){filter:none}[data-view=geek] .hud{-webkit-backdrop-filter:none;backdrop-filter:none}[data-view=geek] .card:hover,[data-view=geek] :is(.pair-btn,.tab-add,.quit-btn,.go,.later,.cmp-send,.cmp-alt,.ask-send,.ask-cancel,.sheet-yes,.new-base,.modes button,.pitem,.d-doc,.thought,.more,.tab-btn,.pad-key):active:not(:disabled){transform:none!important}[data-view=geek] .pad-key{border-bottom-width:1px}[data-view=geek] :where(:not(.token,.stats>div,.pulse)),[data-view=geek] :not(.plate,.tower):before,[data-view=geek] :not(.plate,.tower):after{border-color:var(--line)!important}[data-view=geek] .drawer .unit.current>.card{border-color:var(--text)!important}[data-view=geek] :is(.base,.base.head,.base.ally,.dialog,.squad,.squad[data-mark=waiting]){background:var(--surface-0)}[data-view=geek] :is(.plate,.logo,.ava){background:var(--plate)}[data-view=geek] :is(.plate,.ava){border:1px solid var(--line)}[data-view=geek] .portrait{background:0 0}[data-view=geek] .deploy-fill{background:var(--accent)}[data-view=geek] .tower:before{border-color:var(--line)}[data-view=geek] :is(.unit[data-mark=idle]>.card,.tower.ghost,.base.ally.offline,.stage[data-stale=true] .map,body[data-stale=true] .stats,body[data-stale=true] .work),[data-view=geek] :is(.line .age,.todo span,.tower-conv .conv-now,.tower-conv .conv-cap,.bubble .boss-flag,.notice>.boss-flag,.tmem-empty,.tmem-note,.tmem-counts,.tmem-body li small,.tmem-body h4 small,.foot .credit,.tmem-ended .tmem-text){opacity:1}[data-view=geek] .link span{clip-path:none;width:auto;height:auto;display:inline;position:static;overflow:visible}[data-view=geek] [data-mark=working]{--tag:"[WORK]"}[data-view=geek] [data-mark=waiting]{--tag:"[WAIT?]"}[data-view=geek] [data-mark=commanding]{--tag:"[CMD◈]"}[data-view=geek] [data-mark=idle]{--tag:"[IDLE]"}[data-view=geek] [data-mark=done]{--tag:"[DONE✓]"}[data-view=geek] [data-mark=error]{--tag:"[ERR!]"}[data-view=geek] [data-mark=unknown]{--tag:"[UNKN]"}[data-view=geek] :is(.card,.token) .name:before{content:var(--tag);color:var(--c);margin-right:1ch;font-weight:400}[data-view=geek] .token .name:before{margin-right:0;display:block}[data-view=geek] .tog:before{display:none}[data-view=geek] .set-row .tog:before{content:"[";width:auto;height:auto;color:inherit;font:inherit;background:0 0;border-radius:0;display:inline}[data-view=geek] .set-row .tog:after{content:"]"}[data-view=geek] :is(.modes button[aria-pressed=true],.term-bar .term-kb[aria-pressed=true],.pair-tabs .later.on,.pair-tabs .later[aria-selected=true],.tab-btn.active,.view-pick button[aria-pressed=true],.pcol[data-focus=true] .pitem[aria-selected=true]){background:var(--text);color:var(--ink);font-weight:700}[data-view=geek] .pitem[aria-selected=true]{background:var(--surface-1);color:var(--text);font-weight:700}[data-view=geek] .ask-opt[aria-checked=true]{background:var(--text);color:var(--ink);font-weight:700}[data-view=geek] :is(.ask-opt[aria-checked=true] small){color:var(--ink)}[data-view=geek] .ask-head{background:0 0}[data-view=geek] ::selection{background:var(--text);color:var(--ink)}[data-view=geek] a.ally-chip:hover,[data-view=geek] .banner{background:var(--surface-1)}[data-view=geek] :is(.composer,.ask) button:disabled{opacity:1;color:var(--dim);border:1px dashed var(--line);cursor:not-allowed;background:0 0}[data-view=geek] .tl-mark:focus-visible{outline:2px solid var(--text);outline-offset:3px}@media (forced-colors:active){.badge,.link i,.tog:before,.flag,.tl-mark:before{border:1px solid canvastext}.qr,.term-scroll{forced-color-adjust:none}:is(.composer,.ask) button:disabled{opacity:1;color:graytext;border-color:graytext}:is(textarea,input)::placeholder{color:graytext;opacity:1}.subs:before,.subs>.unit>.card:before,.subs>.unit>.card:after,.drones:before,.links,.packets{display:none}}