@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.
@@ -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-IB7zdkzR.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-BaTd5hxV.css">
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,r)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let o={};const c=e=>i(e,t),d={module:{uri:t},exports:o,require:c};s[t]=Promise.all(n.map(e=>d[e]||c(e))).then(e=>(r(...e),o))}}define(["./workbox-1d3d89e3"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"index.html",revision:"6c7eee85d0e5455e52f4e46570ce6356"},{url:"assets/index-IB7zdkzR.js",revision:null},{url:"assets/index-BaTd5hxV.css",revision:null},{url:"manifest.webmanifest",revision:"97cf47c913710ef5ce3dc79cf9c7c245"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
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 deviceId = input.deviceId?.trim() || process.env.TERMPILOT_DEVICE_ID || DEFAULT_DEVICE_ID;
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(hostname) {
653
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || /^10\./.test(hostname) || /^192\.168\./.test(hostname) || /^172\.(1[6-9]|2\d|3[0-1])\./.test(hostname);
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
- return value?.trim() || process.env.TERMPILOT_DEVICE_ID || DEFAULT_DEVICE_ID;
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 isLocalRelayHost2(hostname) {
909
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || /^10\./.test(hostname) || /^192\.168\./.test(hostname) || /^172\.(1[6-9]|2\d|3[0-1])\./.test(hostname);
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
- return resolved;
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: process.env.TERMPILOT_CLIENT_TOKEN ?? DEFAULT_CLIENT_TOKEN,
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",
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}