@fengye404/termpilot 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/.env.example +2 -2
- package/README.md +7 -3
- package/app/dist/assets/index-atO44LHb.css +1 -0
- package/app/dist/assets/index-jGfu-e5z.js +21 -0
- package/app/dist/index.html +2 -2
- package/app/dist/sw.js +1 -1
- package/dist/cli.js +95 -15
- package/package.json +2 -1
- package/app/dist/assets/index-BaTd5hxV.css +0 -1
- package/app/dist/assets/index-IB7zdkzR.js +0 -20
package/app/dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
6
6
|
<meta name="theme-color" content="#0f172a" />
|
|
7
7
|
<title>TermPilot</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-jGfu-e5z.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-atO44LHb.css">
|
|
10
10
|
<link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
|
|
11
11
|
<body class="bg-slate-950">
|
|
12
12
|
<div id="root"></div>
|
package/app/dist/sw.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,
|
|
1
|
+
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,t)=>{const r=e||("document"in self?document.currentScript.src:"")||location.href;if(s[r])return;let o={};const c=e=>i(e,r),l={module:{uri:r},exports:o,require:c};s[r]=Promise.all(n.map(e=>l[e]||c(e))).then(e=>(t(...e),o))}}define(["./workbox-1d3d89e3"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"index.html",revision:"69ead67f3a4bb1589ee427bee6dccf60"},{url:"assets/index-jGfu-e5z.js",revision:null},{url:"assets/index-atO44LHb.css",revision:null},{url:"manifest.webmanifest",revision:"97cf47c913710ef5ce3dc79cf9c7c245"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
|
package/dist/cli.js
CHANGED
|
@@ -7,10 +7,6 @@ import { cwd as processCwd2 } from "process";
|
|
|
7
7
|
import { createInterface } from "readline/promises";
|
|
8
8
|
import { setTimeout as delay2 } from "timers/promises";
|
|
9
9
|
|
|
10
|
-
// agent/src/daemon.ts
|
|
11
|
-
import { setTimeout as delay } from "timers/promises";
|
|
12
|
-
import WebSocket from "ws";
|
|
13
|
-
|
|
14
10
|
// packages/protocol/src/index.ts
|
|
15
11
|
var DEFAULT_DEVICE_ID = "pc-main";
|
|
16
12
|
var DEFAULT_AGENT_TOKEN = "demo-agent-token";
|
|
@@ -23,10 +19,14 @@ function parseJsonMessage(raw) {
|
|
|
23
19
|
}
|
|
24
20
|
}
|
|
25
21
|
|
|
22
|
+
// agent/src/daemon.ts
|
|
23
|
+
import { setTimeout as delay } from "timers/promises";
|
|
24
|
+
import WebSocket from "ws";
|
|
25
|
+
|
|
26
26
|
// agent/src/state-store.ts
|
|
27
27
|
import { randomUUID } from "crypto";
|
|
28
28
|
import { closeSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
|
|
29
|
-
import { homedir } from "os";
|
|
29
|
+
import { homedir, hostname } from "os";
|
|
30
30
|
import path from "path";
|
|
31
31
|
var INITIAL_STATE = {
|
|
32
32
|
version: 1,
|
|
@@ -53,6 +53,9 @@ function getAgentLogFilePath() {
|
|
|
53
53
|
function getAgentConfigFilePath() {
|
|
54
54
|
return path.join(getAgentHome(), "config.json");
|
|
55
55
|
}
|
|
56
|
+
function getGeneratedDeviceIdFilePath() {
|
|
57
|
+
return path.join(getAgentHome(), "device-id");
|
|
58
|
+
}
|
|
56
59
|
function getStateLockPath() {
|
|
57
60
|
return `${getStateFilePath()}.lock`;
|
|
58
61
|
}
|
|
@@ -119,6 +122,42 @@ function withStateLock(action) {
|
|
|
119
122
|
rmSync(lockPath, { force: true });
|
|
120
123
|
}
|
|
121
124
|
}
|
|
125
|
+
function sanitizeDeviceLabel(value) {
|
|
126
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
127
|
+
}
|
|
128
|
+
function generateDeviceId() {
|
|
129
|
+
const base = sanitizeDeviceLabel(hostname().split(".")[0] ?? "") || "pc";
|
|
130
|
+
return `${base}-${randomUUID().slice(0, 8)}`;
|
|
131
|
+
}
|
|
132
|
+
function getOrCreateGeneratedDeviceId() {
|
|
133
|
+
ensureAgentHome();
|
|
134
|
+
const filePath = getGeneratedDeviceIdFilePath();
|
|
135
|
+
try {
|
|
136
|
+
const existing = readFileSync(filePath, "utf8").trim();
|
|
137
|
+
if (existing && existing !== DEFAULT_DEVICE_ID) {
|
|
138
|
+
return existing;
|
|
139
|
+
}
|
|
140
|
+
} catch {
|
|
141
|
+
}
|
|
142
|
+
const deviceId = generateDeviceId();
|
|
143
|
+
writeFileSync(filePath, `${deviceId}
|
|
144
|
+
`, "utf8");
|
|
145
|
+
return deviceId;
|
|
146
|
+
}
|
|
147
|
+
function rewriteSessionsDeviceId(previousDeviceId, nextDeviceId) {
|
|
148
|
+
return withStateLock((filePath) => {
|
|
149
|
+
const state = loadStateFromDisk(filePath);
|
|
150
|
+
const nextState = {
|
|
151
|
+
version: 1,
|
|
152
|
+
sessions: state.sessions.map((session) => session.deviceId === previousDeviceId ? {
|
|
153
|
+
...session,
|
|
154
|
+
deviceId: nextDeviceId
|
|
155
|
+
} : session)
|
|
156
|
+
};
|
|
157
|
+
saveStateToDisk(filePath, nextState);
|
|
158
|
+
return nextState;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
122
161
|
function upsertSession(session) {
|
|
123
162
|
return withStateLock((filePath) => {
|
|
124
163
|
const state = loadStateFromDisk(filePath);
|
|
@@ -244,7 +283,8 @@ async function createSession(input = {}) {
|
|
|
244
283
|
const name = input.name?.trim() || `session-${sid.slice(0, 6)}`;
|
|
245
284
|
const shell = input.shell?.trim() || process.env.SHELL || "/bin/zsh";
|
|
246
285
|
const workingDirectory = input.cwd?.trim() || processCwd();
|
|
247
|
-
const
|
|
286
|
+
const requestedDeviceId = input.deviceId?.trim() || process.env.TERMPILOT_DEVICE_ID?.trim();
|
|
287
|
+
const deviceId = requestedDeviceId && requestedDeviceId !== DEFAULT_DEVICE_ID ? requestedDeviceId : getOrCreateGeneratedDeviceId();
|
|
248
288
|
const startedAt = now();
|
|
249
289
|
const tmuxSessionName = buildTmuxSessionName(sid, name);
|
|
250
290
|
await runTmux(["new-session", "-d", "-s", tmuxSessionName, "-c", workingDirectory, shell]);
|
|
@@ -649,8 +689,8 @@ function createDaemonFromEnv() {
|
|
|
649
689
|
}
|
|
650
690
|
|
|
651
691
|
// agent/src/relay-admin.ts
|
|
652
|
-
function isLocalRelayHost(
|
|
653
|
-
return
|
|
692
|
+
function isLocalRelayHost(hostname2) {
|
|
693
|
+
return hostname2 === "localhost" || hostname2 === "127.0.0.1" || hostname2 === "::1" || /^10\./.test(hostname2) || /^192\.168\./.test(hostname2) || /^172\.(1[6-9]|2\d|3[0-1])\./.test(hostname2);
|
|
654
694
|
}
|
|
655
695
|
function getRelayBaseCandidates(relayUrl = process.env.TERMPILOT_RELAY_URL ?? "ws://127.0.0.1:8787/ws") {
|
|
656
696
|
let url;
|
|
@@ -715,7 +755,11 @@ function getAgentToken() {
|
|
|
715
755
|
return process.env.TERMPILOT_AGENT_TOKEN ?? DEFAULT_AGENT_TOKEN;
|
|
716
756
|
}
|
|
717
757
|
function resolveDeviceId(value) {
|
|
718
|
-
|
|
758
|
+
const normalized = value?.trim() || process.env.TERMPILOT_DEVICE_ID?.trim();
|
|
759
|
+
if (normalized && normalized !== DEFAULT_DEVICE_ID) {
|
|
760
|
+
return normalized;
|
|
761
|
+
}
|
|
762
|
+
return getOrCreateGeneratedDeviceId();
|
|
719
763
|
}
|
|
720
764
|
async function readJsonOrThrow(response, message) {
|
|
721
765
|
if (!response.ok) {
|
|
@@ -905,8 +949,28 @@ function getDeviceId(argv) {
|
|
|
905
949
|
const saved = loadAgentConfig();
|
|
906
950
|
return resolveDeviceId(saved?.deviceId);
|
|
907
951
|
}
|
|
908
|
-
function
|
|
909
|
-
|
|
952
|
+
function maybeMigrateLegacyDeviceId(config, source) {
|
|
953
|
+
if (source === "cli" || source === "env") {
|
|
954
|
+
return { config };
|
|
955
|
+
}
|
|
956
|
+
if (config.deviceId !== DEFAULT_DEVICE_ID) {
|
|
957
|
+
return { config };
|
|
958
|
+
}
|
|
959
|
+
const nextDeviceId = getOrCreateGeneratedDeviceId();
|
|
960
|
+
if (nextDeviceId === config.deviceId) {
|
|
961
|
+
return { config };
|
|
962
|
+
}
|
|
963
|
+
rewriteSessionsDeviceId(config.deviceId, nextDeviceId);
|
|
964
|
+
return {
|
|
965
|
+
config: {
|
|
966
|
+
...config,
|
|
967
|
+
deviceId: nextDeviceId
|
|
968
|
+
},
|
|
969
|
+
migratedFrom: config.deviceId
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
function isLocalRelayHost2(hostname2) {
|
|
973
|
+
return hostname2 === "localhost" || hostname2 === "127.0.0.1" || hostname2 === "::1" || /^10\./.test(hostname2) || /^192\.168\./.test(hostname2) || /^172\.(1[6-9]|2\d|3[0-1])\./.test(hostname2);
|
|
910
974
|
}
|
|
911
975
|
function normalizeRelayUrl(rawHost, rawPort) {
|
|
912
976
|
const hostInput = rawHost.trim();
|
|
@@ -1004,7 +1068,11 @@ function getResolvedConfig(argv) {
|
|
|
1004
1068
|
async function ensureConfigured(argv) {
|
|
1005
1069
|
const resolved = getResolvedConfig(argv);
|
|
1006
1070
|
if (resolved) {
|
|
1007
|
-
|
|
1071
|
+
const migrated = maybeMigrateLegacyDeviceId(resolved.config, resolved.source);
|
|
1072
|
+
if (migrated.migratedFrom) {
|
|
1073
|
+
saveAgentConfig(migrated.config);
|
|
1074
|
+
}
|
|
1075
|
+
return { config: migrated.config, source: resolved.source };
|
|
1008
1076
|
}
|
|
1009
1077
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1010
1078
|
throw new Error(`\u8FD8\u6CA1\u6709\u914D\u7F6E relay\uFF0C\u8BF7\u5148\u6267\u884C\uFF1Atermpilot agent --relay wss://\u4F60\u7684\u57DF\u540D/ws\uFF0C\u6216\u5728\u4EA4\u4E92\u7EC8\u7AEF\u91CC\u76F4\u63A5\u8FD0\u884C termpilot agent\u3002`);
|
|
@@ -1104,6 +1172,8 @@ async function runStart(argv) {
|
|
|
1104
1172
|
const resolved = await ensureConfigured(argv);
|
|
1105
1173
|
let { config } = resolved;
|
|
1106
1174
|
const { source } = resolved;
|
|
1175
|
+
const previousConfig = loadAgentConfig();
|
|
1176
|
+
const migratedDeviceId = previousConfig?.deviceId === DEFAULT_DEVICE_ID && config.deviceId !== previousConfig.deviceId ? previousConfig.deviceId : void 0;
|
|
1107
1177
|
const preferredRelayUrl = await resolvePreferredRelayUrl(config.relayUrl);
|
|
1108
1178
|
if (preferredRelayUrl !== config.relayUrl) {
|
|
1109
1179
|
config = {
|
|
@@ -1116,6 +1186,10 @@ async function runStart(argv) {
|
|
|
1116
1186
|
if (source === "cli" || source === "prompt" || source === "saved") {
|
|
1117
1187
|
saveAgentConfig(config);
|
|
1118
1188
|
}
|
|
1189
|
+
if (migratedDeviceId) {
|
|
1190
|
+
console.log(`\u68C0\u6D4B\u5230\u65E7\u7684\u5171\u4EAB\u8BBE\u5907\u540D ${migratedDeviceId}\uFF0C\u5DF2\u81EA\u52A8\u8FC1\u79FB\u4E3A\u552F\u4E00\u8BBE\u5907\u540D ${config.deviceId}\u3002`);
|
|
1191
|
+
console.log("\u8FD9\u662F\u4E00\u6B21\u5B89\u5168\u4FEE\u590D\uFF1A\u5171\u4EAB relay \u4E0A\u4E0D\u540C\u7535\u8111\u4E0D\u80FD\u7EE7\u7EED\u5171\u7528 pc-main\u3002\u8BF7\u91CD\u65B0\u7ED9\u624B\u673A\u914D\u5BF9\u3002");
|
|
1192
|
+
}
|
|
1119
1193
|
if (args.foreground) {
|
|
1120
1194
|
await runDaemon();
|
|
1121
1195
|
return;
|
|
@@ -1407,11 +1481,13 @@ import { setTimeout as delay3 } from "timers/promises";
|
|
|
1407
1481
|
|
|
1408
1482
|
// relay/src/config.ts
|
|
1409
1483
|
function loadConfig() {
|
|
1484
|
+
const rawClientToken = process.env.TERMPILOT_CLIENT_TOKEN?.trim();
|
|
1485
|
+
const clientToken = rawClientToken && rawClientToken !== DEFAULT_CLIENT_TOKEN ? rawClientToken : void 0;
|
|
1410
1486
|
return {
|
|
1411
1487
|
host: process.env.HOST ?? "0.0.0.0",
|
|
1412
1488
|
port: Number(process.env.PORT ?? 8787),
|
|
1413
1489
|
agentToken: process.env.TERMPILOT_AGENT_TOKEN ?? DEFAULT_AGENT_TOKEN,
|
|
1414
|
-
clientToken
|
|
1490
|
+
clientToken,
|
|
1415
1491
|
databaseUrl: process.env.DATABASE_URL?.trim() || void 0,
|
|
1416
1492
|
pairingTtlMinutes: Number(process.env.TERMPILOT_PAIRING_TTL_MINUTES ?? 10)
|
|
1417
1493
|
};
|
|
@@ -1990,6 +2066,9 @@ async function startRelayServer(options = {}) {
|
|
|
1990
2066
|
const sessionCache = /* @__PURE__ */ new Map();
|
|
1991
2067
|
const outputBuffers = /* @__PURE__ */ new Map();
|
|
1992
2068
|
const webDir = options.webDir ?? resolveDefaultWebDir(import.meta.url);
|
|
2069
|
+
if ((process.env.TERMPILOT_CLIENT_TOKEN ?? "").trim() === DEFAULT_CLIENT_TOKEN) {
|
|
2070
|
+
app.log.warn("\u68C0\u6D4B\u5230 TERMPILOT_CLIENT_TOKEN \u4ECD\u4E3A\u9ED8\u8BA4 demo-client-token\u3002\u51FA\u4E8E\u9694\u79BB\u5B89\u5168\u8003\u8651\uFF0Crelay \u5DF2\u81EA\u52A8\u7981\u7528\u5168\u5C40\u5BA2\u6237\u7AEF\u8BBF\u95EE\u4EE4\u724C\u3002");
|
|
2071
|
+
}
|
|
1993
2072
|
const storesPromise = (async () => {
|
|
1994
2073
|
if (!config.databaseUrl) {
|
|
1995
2074
|
app.log.warn("\u672A\u63D0\u4F9B DATABASE_URL\uFF0C\u5F53\u524D relay \u4F7F\u7528\u5185\u5B58\u5B58\u50A8\u4F1A\u8BDD\u5143\u6570\u636E\u3002");
|
|
@@ -2232,7 +2311,8 @@ async function startRelayServer(options = {}) {
|
|
|
2232
2311
|
storeMode: sessionStore.mode,
|
|
2233
2312
|
agentsOnline: agents.size,
|
|
2234
2313
|
clientsOnline: clients.size,
|
|
2235
|
-
webUiReady: existsSync(webDir)
|
|
2314
|
+
webUiReady: existsSync(webDir),
|
|
2315
|
+
adminClientTokenEnabled: Boolean(config.clientToken)
|
|
2236
2316
|
};
|
|
2237
2317
|
});
|
|
2238
2318
|
app.post("/api/pairing-codes", async (request, reply) => {
|
|
@@ -2380,7 +2460,7 @@ async function startRelayServer(options = {}) {
|
|
|
2380
2460
|
if (role === "client") {
|
|
2381
2461
|
void (async () => {
|
|
2382
2462
|
let client = null;
|
|
2383
|
-
if (token === config.clientToken) {
|
|
2463
|
+
if (config.clientToken && token === config.clientToken) {
|
|
2384
2464
|
client = {
|
|
2385
2465
|
socket,
|
|
2386
2466
|
deviceScope: "*"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fengye404/termpilot",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "pnpm@10.31.0",
|
|
6
6
|
"description": "一个基于 tmux 的终端会话跨端查看与控制原型。",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"agent:revoke": "pnpm --filter @termpilot/agent run revoke",
|
|
42
42
|
"agent:doctor": "pnpm --filter @termpilot/agent run doctor",
|
|
43
43
|
"check:stability": "pnpm build && node scripts/check-relay-agent-stability.mjs",
|
|
44
|
+
"test:isolation": "pnpm build && node scripts/check-device-isolation.mjs",
|
|
44
45
|
"test:ui-smoke": "pnpm build && TERMPILOT_APP_URL=http://127.0.0.1:18787 TERMPILOT_RELAY_URL=ws://127.0.0.1:18787/ws python3 /Users/fengye/.agents/skills/webapp-testing/scripts/with_server.py --server \"PORT=18787 node dist/cli.js relay\" --port 18787 -- python3 scripts/ui_smoke.py",
|
|
45
46
|
"prepack": "pnpm build"
|
|
46
47
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;inset:0}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm .xterm-accessibility,.xterm .xterm-message{position:absolute;inset:0;z-index:10;color:transparent;pointer-events:none}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}@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-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking: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-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-sky-100:oklch(95.1% .026 236.824);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-rose-100:oklch(94.1% .03 12.58);--color-rose-200:oklch(89.2% .058 10.001);--color-rose-400:oklch(71.2% .194 13.428);--color-rose-500:oklch(64.5% .246 16.439);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-2xl:42rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--radius-xl:.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--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)}}@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,ui-sans-serif, system-ui, 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{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}}@layer components;@layer utilities{.start{inset-inline-start:var(--spacing)}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-2{margin-left:calc(var(--spacing) * 2)}.block{display:block}.flex{display:flex}.grid{display:grid}.inline{display:inline}.inline-flex{display:inline-flex}.h-14{height:calc(var(--spacing) * 14)}.h-\[52svh\]{height:52svh}.h-\[56svh\]{height:56svh}.h-full{height:100%}.max-h-\[720px\]{max-height:720px}.min-h-10{min-height:calc(var(--spacing) * 10)}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-12{min-height:calc(var(--spacing) * 12)}.min-h-14{min-height:calc(var(--spacing) * 14)}.min-h-36{min-height:calc(var(--spacing) * 36)}.min-h-\[56vh\]{min-height:56vh}.min-h-\[68vh\]{min-height:68vh}.min-h-\[440px\]{min-height:440px}.min-h-\[460px\]{min-height:460px}.min-h-full{min-height:100%}.min-h-screen{min-height:100vh}.w-14{width:calc(var(--spacing) * 14)}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-md{max-width:var(--container-md)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-11{min-width:calc(var(--spacing) * 11)}.flex-1{flex:1}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.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-\[1fr_auto_1fr\]{grid-template-columns:1fr auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-\[22px\]{border-radius:22px}.rounded-\[28px\]{border-radius:28px}.rounded-full{border-radius:3.40282e38px}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-amber-400\/30{border-color:#fcbb004d}@supports (color:color-mix(in lab,red,red)){.border-amber-400\/30{border-color:color-mix(in oklab,var(--color-amber-400) 30%,transparent)}}.border-amber-400\/50{border-color:#fcbb0080}@supports (color:color-mix(in lab,red,red)){.border-amber-400\/50{border-color:color-mix(in oklab,var(--color-amber-400) 50%,transparent)}}.border-current\/30{border-color:currentColor}@supports (color:color-mix(in lab,red,red)){.border-current\/30{border-color:color-mix(in oklab,currentcolor 30%,transparent)}}.border-emerald-500\/30{border-color:#00bb7f4d}@supports (color:color-mix(in lab,red,red)){.border-emerald-500\/30{border-color:color-mix(in oklab,var(--color-emerald-500) 30%,transparent)}}.border-emerald-500\/40{border-color:#00bb7f66}@supports (color:color-mix(in lab,red,red)){.border-emerald-500\/40{border-color:color-mix(in oklab,var(--color-emerald-500) 40%,transparent)}}.border-emerald-500\/50{border-color:#00bb7f80}@supports (color:color-mix(in lab,red,red)){.border-emerald-500\/50{border-color:color-mix(in oklab,var(--color-emerald-500) 50%,transparent)}}.border-rose-400\/40{border-color:#ff667f66}@supports (color:color-mix(in lab,red,red)){.border-rose-400\/40{border-color:color-mix(in oklab,var(--color-rose-400) 40%,transparent)}}.border-rose-500\/40{border-color:#ff235766}@supports (color:color-mix(in lab,red,red)){.border-rose-500\/40{border-color:color-mix(in oklab,var(--color-rose-500) 40%,transparent)}}.border-sky-400\/40{border-color:#00bcfe66}@supports (color:color-mix(in lab,red,red)){.border-sky-400\/40{border-color:color-mix(in oklab,var(--color-sky-400) 40%,transparent)}}.border-sky-400\/70{border-color:#00bcfeb3}@supports (color:color-mix(in lab,red,red)){.border-sky-400\/70{border-color:color-mix(in oklab,var(--color-sky-400) 70%,transparent)}}.border-sky-500\/40{border-color:#00a5ef66}@supports (color:color-mix(in lab,red,red)){.border-sky-500\/40{border-color:color-mix(in oklab,var(--color-sky-500) 40%,transparent)}}.border-slate-700{border-color:var(--color-slate-700)}.border-slate-700\/80{border-color:#314158cc}@supports (color:color-mix(in lab,red,red)){.border-slate-700\/80{border-color:color-mix(in oklab,var(--color-slate-700) 80%,transparent)}}.border-slate-800{border-color:var(--color-slate-800)}.border-slate-800\/80{border-color:#1d293dcc}@supports (color:color-mix(in lab,red,red)){.border-slate-800\/80{border-color:color-mix(in oklab,var(--color-slate-800) 80%,transparent)}}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.border-white\/10{border-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.bg-\[\#020617\]{background-color:#020617}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/10{background-color:color-mix(in oklab,var(--color-amber-500) 10%,transparent)}}.bg-emerald-400{background-color:var(--color-emerald-400)}.bg-emerald-500\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/10{background-color:color-mix(in oklab,var(--color-emerald-500) 10%,transparent)}}.bg-emerald-500\/15{background-color:#00bb7f26}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/15{background-color:color-mix(in oklab,var(--color-emerald-500) 15%,transparent)}}.bg-rose-500\/10{background-color:#ff23571a}@supports (color:color-mix(in lab,red,red)){.bg-rose-500\/10{background-color:color-mix(in oklab,var(--color-rose-500) 10%,transparent)}}.bg-sky-500{background-color:var(--color-sky-500)}.bg-sky-500\/10{background-color:#00a5ef1a}@supports (color:color-mix(in lab,red,red)){.bg-sky-500\/10{background-color:color-mix(in oklab,var(--color-sky-500) 10%,transparent)}}.bg-slate-700{background-color:var(--color-slate-700)}.bg-slate-900\/70{background-color:#0f172bb3}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/70{background-color:color-mix(in oklab,var(--color-slate-900) 70%,transparent)}}.bg-slate-900\/72{background-color:#0f172bb8}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/72{background-color:color-mix(in oklab,var(--color-slate-900) 72%,transparent)}}.bg-slate-900\/80{background-color:#0f172bcc}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/80{background-color:color-mix(in oklab,var(--color-slate-900) 80%,transparent)}}.bg-slate-950{background-color:var(--color-slate-950)}.bg-slate-950\/35{background-color:#02061859}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/35{background-color:color-mix(in oklab,var(--color-slate-950) 35%,transparent)}}.bg-slate-950\/40{background-color:#02061866}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/40{background-color:color-mix(in oklab,var(--color-slate-950) 40%,transparent)}}.bg-slate-950\/60{background-color:#02061899}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/60{background-color:color-mix(in oklab,var(--color-slate-950) 60%,transparent)}}.bg-slate-950\/70{background-color:#020618b3}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/70{background-color:color-mix(in oklab,var(--color-slate-950) 70%,transparent)}}.bg-slate-950\/80{background-color:#020618cc}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/80{background-color:color-mix(in oklab,var(--color-slate-950) 80%,transparent)}}.bg-slate-950\/90{background-color:#020618e6}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/90{background-color:color-mix(in oklab,var(--color-slate-950) 90%,transparent)}}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.px-1{padding-inline:calc(var(--spacing) * 1)}.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-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-1{padding-block:calc(var(--spacing) * 1)}.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-5{padding-block:calc(var(--spacing) * 5)}.py-12{padding-block:calc(var(--spacing) * 12)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[16px\]{font-size:16px}.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)}.tracking-\[0\.25em\]{--tw-tracking:.25em;letter-spacing:.25em}.text-amber-100{color:var(--color-amber-100)}.text-amber-200{color:var(--color-amber-200)}.text-emerald-100{color:var(--color-emerald-100)}.text-emerald-200{color:var(--color-emerald-200)}.text-emerald-300{color:var(--color-emerald-300)}.text-rose-100{color:var(--color-rose-100)}.text-rose-200{color:var(--color-rose-200)}.text-sky-100{color:var(--color-sky-100)}.text-sky-300{color:var(--color-sky-300)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-950{color:var(--color-slate-950)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.opacity-80{opacity:.8}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_24px_80px_rgba\(2\,6\,23\,0\.45\)\]{--tw-shadow:0 24px 80px var(--tw-shadow-color,#02061773);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + 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)}.shadow-slate-950\/25{--tw-shadow-color:#02061840}@supports (color:color-mix(in lab,red,red)){.shadow-slate-950\/25{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-slate-950) 25%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-slate-950\/30{--tw-shadow-color:#0206184d}@supports (color:color-mix(in lab,red,red)){.shadow-slate-950\/30{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-slate-950) 30%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-slate-950\/40{--tw-shadow-color:#02061866}@supports (color:color-mix(in lab,red,red)){.shadow-slate-950\/40{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-slate-950) 40%, transparent) var(--tw-shadow-alpha), transparent)}}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,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))}.outline-none{--tw-outline-style:none;outline-style:none}.placeholder\:text-slate-500::placeholder{color:var(--color-slate-500)}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media(min-width:40rem){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-\[minmax\(0\,1fr\)_auto_auto\]{grid-template-columns:minmax(0,1fr) auto auto}.sm\:flex-row{flex-direction:row}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}}@media(min-width:48rem){.md\:flex-row{flex-direction:row}.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}@media(min-width:64rem){.lg\:grid-cols-\[360px_minmax\(0\,1fr\)\]{grid-template-columns:360px minmax(0,1fr)}.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}}@media(min-width:80rem){.xl\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xl\:grid-cols-\[minmax\(0\,1fr\)_312px\]{grid-template-columns:minmax(0,1fr) 312px}}}.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility,.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}:root{color-scheme:dark}body{color:#e2e8f0;background:radial-gradient(circle at 0 0,#38bdf824,#0000 32%),linear-gradient(#020617,#0f172a 48%,#020617);min-height:100vh;margin:0;font-family:SF Pro Display,PingFang SC,Helvetica Neue,sans-serif}#root{min-height:100vh}input,textarea,select{font:inherit;font-size:16px}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{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-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}
|