nebula-notebook 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/dist/assets/{errorwidget-Wy5ajPiM.js → errorwidget-DQl0VDhF.js} +1 -1
- package/dist/assets/{index-DeQN03nW.js → index-2nV_DRXf.js} +1 -1
- package/dist/assets/{index-B_Bs5koo.js → index-BElcu9UX.js} +1 -1
- package/dist/assets/{index-DK4nS74r.js → index-BRnOuVqD.js} +203 -200
- package/dist/assets/index-Czch8hB-.css +32 -0
- package/dist/assets/{index-g6MjT-VG.js → index-FGb2qbG1.js} +1 -1
- package/dist/assets/{services-shim-BirHVsih.js → services-shim-BksFNANN.js} +1 -1
- package/dist/index.html +2 -2
- package/node-server/dist/terminal/agent-registry.d.ts +14 -12
- package/node-server/dist/terminal/agent-registry.js +19 -17
- package/node-server/dist/terminal/pty-manager.d.ts +17 -7
- package/node-server/dist/terminal/pty-manager.js +23 -25
- package/node-server/dist/terminal/remote-agent-config.d.ts +58 -0
- package/node-server/dist/terminal/remote-agent-config.js +168 -0
- package/node-server/dist/terminal/remote-agent-identity.d.ts +20 -0
- package/node-server/dist/terminal/remote-agent-identity.js +98 -0
- package/node-server/dist/terminal/server.js +55 -7
- package/package.json +1 -1
- package/dist/assets/index-DzjpmUak.css +0 -32
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote-agent config — ONE per Nebula installation.
|
|
3
|
+
*
|
|
4
|
+
* How to reach the user's machine describes the INSTALLATION, not a browser:
|
|
5
|
+
* which loopback port here their sshd is reverse-forwarded to, their username
|
|
6
|
+
* on that machine, its sshd port, an optional jump host. It used to live only
|
|
7
|
+
* in browser localStorage, where two failures followed:
|
|
8
|
+
* - a fresh browser minted a NEW random port and silently orphaned the
|
|
9
|
+
* tunnel the user had already built (lab report: "tunnel not detected");
|
|
10
|
+
* - a fresh browser re-prompted the whole setup dialog for a tunnel that
|
|
11
|
+
* was up and working — and "fresh" includes merely a second ORIGIN, since
|
|
12
|
+
* localhost:3000 and localhost:8867 have separate localStorage.
|
|
13
|
+
* The server owns it now; browsers mirror it (same pattern as bindings).
|
|
14
|
+
*/
|
|
15
|
+
export interface RemoteAgentConfig {
|
|
16
|
+
/** Reverse-channel port on THIS host (the -R target). */
|
|
17
|
+
port?: number;
|
|
18
|
+
/** Username on the user's machine, for the ssh hop back. */
|
|
19
|
+
user?: string;
|
|
20
|
+
/** sshd port on the user's machine (macOS policy often forces 2222). */
|
|
21
|
+
localSshPort?: number;
|
|
22
|
+
/** Optional ProxyJump host shown in the tunnel command. */
|
|
23
|
+
jumpHost?: string;
|
|
24
|
+
/** Nebula URL as seen FROM the user's machine (their -L forward). */
|
|
25
|
+
localUrl?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Field-level patch; null means "erase this field". */
|
|
28
|
+
export type RemoteAgentConfigPatch = {
|
|
29
|
+
[K in keyof RemoteAgentConfig]?: RemoteAgentConfig[K] | null;
|
|
30
|
+
};
|
|
31
|
+
export declare class RemoteAgentConfigStore {
|
|
32
|
+
private file;
|
|
33
|
+
private config;
|
|
34
|
+
private loaded;
|
|
35
|
+
constructor(file?: string);
|
|
36
|
+
private ensureLoaded;
|
|
37
|
+
private persist;
|
|
38
|
+
get(): RemoteAgentConfig;
|
|
39
|
+
/**
|
|
40
|
+
* The installation port, generating one on first use. A valid `claim` is
|
|
41
|
+
* adopted ONLY when none is stored — the first browser to sync keeps the
|
|
42
|
+
* port its user already built a tunnel for; later browsers converge.
|
|
43
|
+
*/
|
|
44
|
+
ensurePort(claim?: number): number;
|
|
45
|
+
/**
|
|
46
|
+
* Adopt a browser's local values for whatever this installation does NOT
|
|
47
|
+
* know yet, and return the effective config. Stored truth always wins, so
|
|
48
|
+
* one browser's stale copy can never overwrite a working setup.
|
|
49
|
+
*/
|
|
50
|
+
claim(claimed: RemoteAgentConfig): RemoteAgentConfig;
|
|
51
|
+
/**
|
|
52
|
+
* Explicit override (setup dialog). Merges: omitted fields keep their
|
|
53
|
+
* stored value, `null` erases, invalid values are ignored rather than
|
|
54
|
+
* stored — a typo must not break a working installation.
|
|
55
|
+
*/
|
|
56
|
+
patch(fields: RemoteAgentConfigPatch): RemoteAgentConfig;
|
|
57
|
+
}
|
|
58
|
+
export declare const remoteAgentConfig: RemoteAgentConfigStore;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Remote-agent config — ONE per Nebula installation.
|
|
4
|
+
*
|
|
5
|
+
* How to reach the user's machine describes the INSTALLATION, not a browser:
|
|
6
|
+
* which loopback port here their sshd is reverse-forwarded to, their username
|
|
7
|
+
* on that machine, its sshd port, an optional jump host. It used to live only
|
|
8
|
+
* in browser localStorage, where two failures followed:
|
|
9
|
+
* - a fresh browser minted a NEW random port and silently orphaned the
|
|
10
|
+
* tunnel the user had already built (lab report: "tunnel not detected");
|
|
11
|
+
* - a fresh browser re-prompted the whole setup dialog for a tunnel that
|
|
12
|
+
* was up and working — and "fresh" includes merely a second ORIGIN, since
|
|
13
|
+
* localhost:3000 and localhost:8867 have separate localStorage.
|
|
14
|
+
* The server owns it now; browsers mirror it (same pattern as bindings).
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.remoteAgentConfig = exports.RemoteAgentConfigStore = void 0;
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const os = __importStar(require("os"));
|
|
54
|
+
/** Loopback-only, user-space, random to avoid collisions on shared login nodes. */
|
|
55
|
+
const PORT_MIN = 20000;
|
|
56
|
+
const PORT_RANGE = 40000;
|
|
57
|
+
function validPort(p) {
|
|
58
|
+
return Number.isInteger(p) && p >= 1024 && p <= 65535;
|
|
59
|
+
}
|
|
60
|
+
function cleanString(v) {
|
|
61
|
+
return typeof v === 'string' && v.trim() ? v.trim() : undefined;
|
|
62
|
+
}
|
|
63
|
+
class RemoteAgentConfigStore {
|
|
64
|
+
file;
|
|
65
|
+
config = {};
|
|
66
|
+
loaded = false;
|
|
67
|
+
constructor(file) {
|
|
68
|
+
this.file =
|
|
69
|
+
file ||
|
|
70
|
+
process.env.NEBULA_REMOTE_AGENT_FILE ||
|
|
71
|
+
path.join(os.homedir(), '.nebula', 'remote-agent.json');
|
|
72
|
+
}
|
|
73
|
+
ensureLoaded() {
|
|
74
|
+
if (this.loaded)
|
|
75
|
+
return;
|
|
76
|
+
this.loaded = true;
|
|
77
|
+
try {
|
|
78
|
+
const raw = JSON.parse(fs.readFileSync(this.file, 'utf-8'));
|
|
79
|
+
// Field-by-field so a legacy {port}-only file (and any junk) reads clean.
|
|
80
|
+
if (validPort(raw.port))
|
|
81
|
+
this.config.port = raw.port;
|
|
82
|
+
if (validPort(raw.localSshPort))
|
|
83
|
+
this.config.localSshPort = raw.localSshPort;
|
|
84
|
+
this.config.user = cleanString(raw.user);
|
|
85
|
+
this.config.jumpHost = cleanString(raw.jumpHost);
|
|
86
|
+
this.config.localUrl = cleanString(raw.localUrl);
|
|
87
|
+
}
|
|
88
|
+
catch { /* missing/corrupt file — nothing configured yet */ }
|
|
89
|
+
}
|
|
90
|
+
persist() {
|
|
91
|
+
try {
|
|
92
|
+
fs.mkdirSync(path.dirname(this.file), { recursive: true });
|
|
93
|
+
const tmp = `${this.file}.tmp`;
|
|
94
|
+
fs.writeFileSync(tmp, JSON.stringify(this.config, null, 2));
|
|
95
|
+
fs.renameSync(tmp, this.file);
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
console.warn('Failed to persist remote-agent config:', e);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
get() {
|
|
102
|
+
this.ensureLoaded();
|
|
103
|
+
return { ...this.config };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The installation port, generating one on first use. A valid `claim` is
|
|
107
|
+
* adopted ONLY when none is stored — the first browser to sync keeps the
|
|
108
|
+
* port its user already built a tunnel for; later browsers converge.
|
|
109
|
+
*/
|
|
110
|
+
ensurePort(claim) {
|
|
111
|
+
this.ensureLoaded();
|
|
112
|
+
if (this.config.port !== undefined)
|
|
113
|
+
return this.config.port;
|
|
114
|
+
this.config.port = validPort(claim) ? claim : PORT_MIN + Math.floor(Math.random() * PORT_RANGE);
|
|
115
|
+
this.persist();
|
|
116
|
+
return this.config.port;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Adopt a browser's local values for whatever this installation does NOT
|
|
120
|
+
* know yet, and return the effective config. Stored truth always wins, so
|
|
121
|
+
* one browser's stale copy can never overwrite a working setup.
|
|
122
|
+
*/
|
|
123
|
+
claim(claimed) {
|
|
124
|
+
this.ensureLoaded();
|
|
125
|
+
const missing = {};
|
|
126
|
+
if (this.config.user === undefined && cleanString(claimed.user))
|
|
127
|
+
missing.user = claimed.user;
|
|
128
|
+
if (this.config.localSshPort === undefined && validPort(claimed.localSshPort))
|
|
129
|
+
missing.localSshPort = claimed.localSshPort;
|
|
130
|
+
if (this.config.jumpHost === undefined && cleanString(claimed.jumpHost))
|
|
131
|
+
missing.jumpHost = claimed.jumpHost;
|
|
132
|
+
if (this.config.localUrl === undefined && cleanString(claimed.localUrl))
|
|
133
|
+
missing.localUrl = claimed.localUrl;
|
|
134
|
+
if (Object.keys(missing).length)
|
|
135
|
+
this.patch(missing);
|
|
136
|
+
this.ensurePort(claimed.port); // adopt-if-missing, and always end up with one
|
|
137
|
+
return this.get();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Explicit override (setup dialog). Merges: omitted fields keep their
|
|
141
|
+
* stored value, `null` erases, invalid values are ignored rather than
|
|
142
|
+
* stored — a typo must not break a working installation.
|
|
143
|
+
*/
|
|
144
|
+
patch(fields) {
|
|
145
|
+
this.ensureLoaded();
|
|
146
|
+
const setOrClear = (key, value, clean) => {
|
|
147
|
+
if (value === undefined)
|
|
148
|
+
return; // not mentioned — keep
|
|
149
|
+
if (value === null) {
|
|
150
|
+
delete this.config[key];
|
|
151
|
+
return;
|
|
152
|
+
} // explicit erase
|
|
153
|
+
const ok = clean(value);
|
|
154
|
+
if (ok !== undefined)
|
|
155
|
+
this.config[key] = ok; // invalid — keep stored
|
|
156
|
+
};
|
|
157
|
+
const asPort = (v) => (validPort(v) ? v : undefined);
|
|
158
|
+
setOrClear('port', fields.port, asPort);
|
|
159
|
+
setOrClear('localSshPort', fields.localSshPort, asPort);
|
|
160
|
+
setOrClear('user', fields.user, cleanString);
|
|
161
|
+
setOrClear('jumpHost', fields.jumpHost, cleanString);
|
|
162
|
+
setOrClear('localUrl', fields.localUrl, cleanString);
|
|
163
|
+
this.persist();
|
|
164
|
+
return this.get();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.RemoteAgentConfigStore = RemoteAgentConfigStore;
|
|
168
|
+
exports.remoteAgentConfig = new RemoteAgentConfigStore();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding out who the user is on their OWN machine, so remote-agent mode
|
|
3
|
+
* doesn't have to ask.
|
|
4
|
+
*
|
|
5
|
+
* The reverse tunnel already reaches the user's sshd; once their key is
|
|
6
|
+
* authorized, `whoami` over it answers the question exactly. The only guess is
|
|
7
|
+
* which login to attempt, and the server's own username is both the common
|
|
8
|
+
* answer and precisely what a bare `ssh localhost` would try.
|
|
9
|
+
*/
|
|
10
|
+
/** Logins worth trying, best first: an explicit hint, then the server's own. */
|
|
11
|
+
export declare function candidateUsernames(serverUser: string, hint?: string): string[];
|
|
12
|
+
/** The login reported by the remote `whoami`, or null if nothing usable came back. */
|
|
13
|
+
export declare function parseWhoami(stdout: string): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* Try each candidate login over the reverse channel and return the first that
|
|
16
|
+
* authenticates, as the remote host itself reports it. null = nobody answered
|
|
17
|
+
* (tunnel down, key not authorized yet, or a different login) — the caller
|
|
18
|
+
* must then ask, and say plainly that this is what it needs.
|
|
19
|
+
*/
|
|
20
|
+
export declare function discoverRemoteUser(port: number, hint?: string): Promise<string | null>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Finding out who the user is on their OWN machine, so remote-agent mode
|
|
4
|
+
* doesn't have to ask.
|
|
5
|
+
*
|
|
6
|
+
* The reverse tunnel already reaches the user's sshd; once their key is
|
|
7
|
+
* authorized, `whoami` over it answers the question exactly. The only guess is
|
|
8
|
+
* which login to attempt, and the server's own username is both the common
|
|
9
|
+
* answer and precisely what a bare `ssh localhost` would try.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.candidateUsernames = candidateUsernames;
|
|
46
|
+
exports.parseWhoami = parseWhoami;
|
|
47
|
+
exports.discoverRemoteUser = discoverRemoteUser;
|
|
48
|
+
const child_process_1 = require("child_process");
|
|
49
|
+
const os = __importStar(require("os"));
|
|
50
|
+
/** POSIX-portable login names — anything else never reaches an ssh argument. */
|
|
51
|
+
const LOGIN_RE = /^[A-Za-z0-9._-]+$/;
|
|
52
|
+
/** Logins worth trying, best first: an explicit hint, then the server's own. */
|
|
53
|
+
function candidateUsernames(serverUser, hint) {
|
|
54
|
+
const out = [];
|
|
55
|
+
for (const candidate of [hint, serverUser]) {
|
|
56
|
+
const value = (candidate ?? '').trim();
|
|
57
|
+
if (!value || !LOGIN_RE.test(value) || out.includes(value))
|
|
58
|
+
continue;
|
|
59
|
+
out.push(value);
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
/** The login reported by the remote `whoami`, or null if nothing usable came back. */
|
|
64
|
+
function parseWhoami(stdout) {
|
|
65
|
+
const line = stdout.split('\n').find((l) => l.startsWith('NB_USER='));
|
|
66
|
+
const value = line ? line.slice('NB_USER='.length).trim() : '';
|
|
67
|
+
return value && LOGIN_RE.test(value) ? value : null;
|
|
68
|
+
}
|
|
69
|
+
function sshWhoami(port, user, timeoutMs) {
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
const child = (0, child_process_1.execFile)('ssh', ['-p', String(port), '-o', 'ProxyCommand=none', '-o', 'StrictHostKeyChecking=accept-new',
|
|
72
|
+
// BatchMode: never hang on a password prompt — key auth or nothing.
|
|
73
|
+
'-o', 'BatchMode=yes', '-o', 'ConnectTimeout=8', `${user}@localhost`,
|
|
74
|
+
'printf "NB_USER=%s\\n" "$(whoami)"'], { timeout: timeoutMs }, (err, stdout) => resolve(err ? null : parseWhoami(String(stdout))));
|
|
75
|
+
child.on('error', () => resolve(null));
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Try each candidate login over the reverse channel and return the first that
|
|
80
|
+
* authenticates, as the remote host itself reports it. null = nobody answered
|
|
81
|
+
* (tunnel down, key not authorized yet, or a different login) — the caller
|
|
82
|
+
* must then ask, and say plainly that this is what it needs.
|
|
83
|
+
*/
|
|
84
|
+
async function discoverRemoteUser(port, hint) {
|
|
85
|
+
if (!Number.isInteger(port) || port < 1024 || port > 65535)
|
|
86
|
+
return null;
|
|
87
|
+
let serverUser = '';
|
|
88
|
+
try {
|
|
89
|
+
serverUser = os.userInfo().username;
|
|
90
|
+
}
|
|
91
|
+
catch { /* no passwd entry — hint only */ }
|
|
92
|
+
for (const candidate of candidateUsernames(serverUser, hint)) {
|
|
93
|
+
const found = await sshWhoami(port, candidate, 12000);
|
|
94
|
+
if (found)
|
|
95
|
+
return found;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
@@ -46,6 +46,8 @@ const path = __importStar(require("path"));
|
|
|
46
46
|
const pty_manager_1 = require("./pty-manager");
|
|
47
47
|
const agent_registry_1 = require("./agent-registry");
|
|
48
48
|
const binding_store_1 = require("./binding-store");
|
|
49
|
+
const remote_agent_config_1 = require("./remote-agent-config");
|
|
50
|
+
const remote_agent_identity_1 = require("./remote-agent-identity");
|
|
49
51
|
const fs_service_1 = require("../fs/fs-service");
|
|
50
52
|
// Get configured root directory for terminals
|
|
51
53
|
function getDefaultCwd() {
|
|
@@ -74,6 +76,50 @@ async function setupTerminalRoutes(fastify) {
|
|
|
74
76
|
port: Number(process.env.PORT) || 3000,
|
|
75
77
|
});
|
|
76
78
|
});
|
|
79
|
+
// Remote-agent config: ONE per installation, owned by the server, so every
|
|
80
|
+
// browser converges on the same reverse port (per-browser random ports
|
|
81
|
+
// orphaned the user's standing tunnel) and inherits a completed setup
|
|
82
|
+
// instead of re-prompting for it (both lab reports). The claim* params let
|
|
83
|
+
// the FIRST browser to sync donate what it already had working; stored
|
|
84
|
+
// truth always wins afterwards.
|
|
85
|
+
fastify.get('/api/terminals/agent-config', async (request, reply) => {
|
|
86
|
+
const q = request.query;
|
|
87
|
+
const num = (v) => (v === undefined ? undefined : Number(v));
|
|
88
|
+
return reply.send(remote_agent_config_1.remoteAgentConfig.claim({
|
|
89
|
+
port: num(q.claimPort),
|
|
90
|
+
user: q.claimUser,
|
|
91
|
+
localSshPort: num(q.claimSshPort),
|
|
92
|
+
jumpHost: q.claimJump,
|
|
93
|
+
localUrl: q.claimUrl,
|
|
94
|
+
}));
|
|
95
|
+
});
|
|
96
|
+
// Find the user's login on their OWN machine over the reverse channel, so
|
|
97
|
+
// remote-agent mode stops demanding something it can look up (lab report:
|
|
98
|
+
// "I cannot use it until I put in my username — I thought it should already
|
|
99
|
+
// know"). Stores what it finds, so every browser inherits it.
|
|
100
|
+
fastify.post('/api/terminals/agent-config/discover-user', async (request, reply) => {
|
|
101
|
+
const body = request.body || {};
|
|
102
|
+
const port = remote_agent_config_1.remoteAgentConfig.get().port;
|
|
103
|
+
if (port === undefined)
|
|
104
|
+
return reply.send({ user: null, reason: 'no reverse port configured yet' });
|
|
105
|
+
const user = await (0, remote_agent_identity_1.discoverRemoteUser)(port, body.hint);
|
|
106
|
+
if (!user) {
|
|
107
|
+
return reply.send({
|
|
108
|
+
user: null,
|
|
109
|
+
reason: 'your machine did not answer on the reverse tunnel — connect the tunnel and authorize this server\'s key, then try again',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return reply.send({ user: remote_agent_config_1.remoteAgentConfig.patch({ user }).user });
|
|
113
|
+
});
|
|
114
|
+
fastify.put('/api/terminals/agent-config', async (request, reply) => {
|
|
115
|
+
const body = request.body || {};
|
|
116
|
+
// Only fields actually present are touched (undefined keeps, null erases).
|
|
117
|
+
const pick = (k) => (k in body ? body[k] : undefined);
|
|
118
|
+
return reply.send(remote_agent_config_1.remoteAgentConfig.patch({
|
|
119
|
+
port: pick('port'), user: pick('user'), localSshPort: pick('localSshPort'),
|
|
120
|
+
jumpHost: pick('jumpHost'), localUrl: pick('localUrl'),
|
|
121
|
+
}));
|
|
122
|
+
});
|
|
77
123
|
// Probe a loopback port on THIS host — used by remote-agent mode to detect
|
|
78
124
|
// whether the user's reverse SSH channel (ssh -R <port>:localhost:22) is up.
|
|
79
125
|
// Loopback-only by construction; the port is user-chosen and random.
|
|
@@ -109,7 +155,7 @@ async function setupTerminalRoutes(fastify) {
|
|
|
109
155
|
// List all terminals
|
|
110
156
|
// ---- Agent registry: project-scoped agent sessions (see agent-registry.ts) ----
|
|
111
157
|
fastify.get('/api/agents', async (_request, reply) => {
|
|
112
|
-
return reply.send({ agents:
|
|
158
|
+
return reply.send({ agents: agent_registry_1.agentRegistry.listEnriched() });
|
|
113
159
|
});
|
|
114
160
|
fastify.post('/api/agents/register', async (request, reply) => {
|
|
115
161
|
const b = (request.body ?? {});
|
|
@@ -227,13 +273,15 @@ async function setupTerminalRoutes(fastify) {
|
|
|
227
273
|
binding_store_1.terminalBindings.delete(file_path, plane);
|
|
228
274
|
return reply.send({ ok: true });
|
|
229
275
|
});
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
//
|
|
276
|
+
// Tty-foreground probe: is something running in this pty's foreground (a
|
|
277
|
+
// TUI, an ssh hop, a command)? Clients MUST check this before typing a
|
|
278
|
+
// launch command into an existing pty — records can mis-score liveness (a
|
|
279
|
+
// hand-resumed agent never re-registers), and a launch line typed into a
|
|
280
|
+
// live TUI becomes a chat prompt (lab report). A fresh login shell sourcing
|
|
281
|
+
// rc files reads false — its init children never own the tty.
|
|
282
|
+
// busy:null = unknown (pty gone / foreground unreadable) — claim nothing.
|
|
235
283
|
fastify.get('/api/terminals/:id/busy', async (request, reply) => {
|
|
236
|
-
const busy =
|
|
284
|
+
const busy = pty_manager_1.ptyManager.isBusy(request.params.id);
|
|
237
285
|
return reply.send({ busy });
|
|
238
286
|
});
|
|
239
287
|
// Get terminal info
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nebula-notebook",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "AI-native notebook computing environment — real Jupyter kernels, real filesystem, built to be driven by agents (Claude Code / Codex) via MCP",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */@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-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-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking: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-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;--tw-duration:initial;--tw-ease: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-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-orange-50:oklch(98% .016 73.684);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-yellow-500:oklch(79.5% .184 86.047);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-cyan-500:oklch(71.5% .143 215.221);--color-sky-600:oklch(58.8% .158 241.966);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-800:oklch(39.8% .195 277.366);--color-violet-50:oklch(96.9% .016 293.756);--color-violet-100:oklch(94.3% .029 294.588);--color-violet-200:oklch(89.4% .057 293.283);--color-violet-500:oklch(60.6% .25 292.717);--color-violet-700:oklch(49.1% .27 292.581);--color-violet-800:oklch(43.2% .232 292.759);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-200:oklch(90.2% .063 306.703);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-700:oklch(49.6% .265 301.924);--color-purple-800:oklch(43.8% .218 303.724);--color-slate-50:oklch(98.4% .003 247.858);--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-600:oklch(44.6% .043 257.281);--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-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-5xl:64rem;--container-6xl:72rem;--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-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-normal:1.5;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-sm:8px;--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%;-moz-tab-size:4;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]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance: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{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.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:calc(var(--spacing) * 0)}.inset-x-0{inset-inline:calc(var(--spacing) * 0)}.inset-y-0{inset-block:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-1{top:calc(var(--spacing) * 1)}.top-1\.5{top:calc(var(--spacing) * 1.5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-2\.5{top:calc(var(--spacing) * 2.5)}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.top-16{top:calc(var(--spacing) * 16)}.top-full{top:100%}.right-0{right:calc(var(--spacing) * 0)}.right-2{right:calc(var(--spacing) * 2)}.right-4{right:calc(var(--spacing) * 4)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-24{bottom:calc(var(--spacing) * 24)}.left-0{left:calc(var(--spacing) * 0)}.left-1{left:calc(var(--spacing) * 1)}.left-1\/2{left:50%}.left-2\.5{left:calc(var(--spacing) * 2.5)}.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}.z-\[70\]{z-index:70}.z-\[80\]{z-index:80}.z-\[100\]{z-index:100}.z-\[101\]{z-index:101}.z-\[102\]{z-index:102}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.m-auto{margin:auto}.mx-1{margin-inline:calc(var(--spacing) * 1)}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing) * 1)}.my-2{margin-block:calc(var(--spacing) * 2)}.my-3{margin-block:calc(var(--spacing) * 3)}.my-4{margin-block:calc(var(--spacing) * 4)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-auto{margin-top:auto}.mt-px{margin-top:1px}.mr-1{margin-right:calc(var(--spacing) * 1)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.-ml-1{margin-left:calc(var(--spacing) * -1)}.-ml-1\.5{margin-left:calc(var(--spacing) * -1.5)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-3{margin-left:calc(var(--spacing) * 3)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-6{margin-left:calc(var(--spacing) * 6)}.ml-auto{margin-left:auto}.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}.table{display:table}.h-0\.5{height:calc(var(--spacing) * .5)}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-32{height:calc(var(--spacing) * 32)}.h-904{height:calc(var(--spacing) * 904)}.h-\[24rem\]{height:24rem}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-20{max-height:calc(var(--spacing) * 20)}.max-h-24{max-height:calc(var(--spacing) * 24)}.max-h-32{max-height:calc(var(--spacing) * 32)}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-56{max-height:calc(var(--spacing) * 56)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-80{max-height:calc(var(--spacing) * 80)}.max-h-\[9\.375rem\]{max-height:9.375rem}.max-h-\[12\.5rem\]{max-height:12.5rem}.max-h-\[18\.75rem\]{max-height:18.75rem}.max-h-\[32rem\]{max-height:32rem}.max-h-\[60vh\]{max-height:60vh}.max-h-\[70vh\]{max-height:70vh}.max-h-\[75vh\]{max-height:75vh}.max-h-\[80vh\]{max-height:80vh}.max-h-\[85vh\]{max-height:85vh}.max-h-full{max-height:100%}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-\[1\.5rem\]{min-height:1.5rem}.min-h-\[2\.5rem\]{min-height:2.5rem}.min-h-\[18rem\]{min-height:18rem}.min-h-\[20rem\]{min-height:20rem}.min-h-full{min-height:100%}.min-h-screen{min-height:100vh}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-1\/3{width:33.3333%}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-2\/3{width:66.6667%}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-11{width:calc(var(--spacing) * 11)}.w-12{width:calc(var(--spacing) * 12)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-28{width:calc(var(--spacing) * 28)}.w-32{width:calc(var(--spacing) * 32)}.w-40{width:calc(var(--spacing) * 40)}.w-48{width:calc(var(--spacing) * 48)}.w-52{width:calc(var(--spacing) * 52)}.w-72{width:calc(var(--spacing) * 72)}.w-80{width:calc(var(--spacing) * 80)}.w-\[1px\]{width:1px}.w-full{width:100%}.w-max{width:max-content}.w-screen{width:100vw}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-72{max-width:calc(var(--spacing) * 72)}.max-w-\[6\.5rem\]{max-width:6.5rem}.max-w-\[6\.25rem\]{max-width:6.25rem}.max-w-\[9rem\]{max-width:9rem}.max-w-\[11\.25rem\]{max-width:11.25rem}.max-w-\[12\.5rem\]{max-width:12.5rem}.max-w-\[15rem\]{max-width:15rem}.max-w-\[20rem\]{max-width:20rem}.max-w-\[22rem\]{max-width:22rem}.max-w-\[24rem\]{max-width:24rem}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-48{min-width:calc(var(--spacing) * 48)}.min-w-\[1\.5rem\]{min-width:1.5rem}.min-w-\[3\.75rem\]{min-width:3.75rem}.min-w-\[6\.25rem\]{min-width:6.25rem}.min-w-\[10rem\]{min-width:10rem}.min-w-\[12\.5rem\]{min-width:12.5rem}.min-w-\[14rem\]{min-width:14rem}.min-w-\[15rem\]{min-width:15rem}.min-w-\[17\.5rem\]{min-width:17.5rem}.flex-1{flex:1}.flex-none{flex:none}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-x-full{--tw-translate-x:-100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-0{--tw-translate-x:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-5{--tw-translate-x:calc(var(--spacing) * 5);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)}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-col-resize{cursor:col-resize}.cursor-default{cursor:default}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-not-allowed{cursor:not-allowed}.cursor-ns-resize{cursor:ns-resize}.cursor-pointer{cursor:pointer}.cursor-zoom-in{cursor:zoom-in}.resize{resize:both}.scroll-mt-20{scroll-margin-top:calc(var(--spacing) * 20)}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-nowrap{flex-wrap:nowrap}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.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-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-0\.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)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}: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)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-slate-100>:not(:last-child)){border-color:var(--color-slate-100)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-lg{border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg)}.rounded-t-xl{border-top-left-radius:var(--radius-xl);border-top-right-radius:var(--radius-xl)}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.rounded-b-lg{border-bottom-right-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg)}.rounded-b-xl{border-bottom-right-radius:var(--radius-xl);border-bottom-left-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-none{--tw-border-style:none;border-style:none}.border-amber-100{border-color:var(--color-amber-100)}.border-amber-200{border-color:var(--color-amber-200)}.border-amber-300{border-color:var(--color-amber-300)}.border-amber-400{border-color:var(--color-amber-400)}.border-blue-100{border-color:var(--color-blue-100)}.border-blue-200{border-color:var(--color-blue-200)}.border-blue-300{border-color:var(--color-blue-300)}.border-blue-400{border-color:var(--color-blue-400)}.border-blue-500{border-color:var(--color-blue-500)}.border-blue-600{border-color:var(--color-blue-600)}.border-current,.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-gray-100{border-color:var(--color-gray-100)}.border-gray-200{border-color:var(--color-gray-200)}.border-green-100{border-color:var(--color-green-100)}.border-green-200{border-color:var(--color-green-200)}.border-green-500{border-color:var(--color-green-500)}.border-indigo-100{border-color:var(--color-indigo-100)}.border-indigo-200{border-color:var(--color-indigo-200)}.border-indigo-300{border-color:var(--color-indigo-300)}.border-orange-400{border-color:var(--color-orange-400)}.border-purple-100{border-color:var(--color-purple-100)}.border-purple-200{border-color:var(--color-purple-200)}.border-purple-300{border-color:var(--color-purple-300)}.border-red-100{border-color:var(--color-red-100)}.border-red-200{border-color:var(--color-red-200)}.border-red-300{border-color:var(--color-red-300)}.border-red-400{border-color:var(--color-red-400)}.border-red-500{border-color:var(--color-red-500)}.border-slate-100{border-color:var(--color-slate-100)}.border-slate-200{border-color:var(--color-slate-200)}.border-slate-300{border-color:var(--color-slate-300)}.border-slate-400{border-color:var(--color-slate-400)}.border-transparent{border-color:#0000}.border-violet-100{border-color:var(--color-violet-100)}.border-violet-200{border-color:var(--color-violet-200)}.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)}}.border-white\/30{border-color:#ffffff4d}@supports (color:color-mix(in lab,red,red)){.border-white\/30{border-color:color-mix(in oklab,var(--color-white) 30%,transparent)}}.border-t-transparent{border-top-color:#0000}.border-t-white{border-top-color:var(--color-white)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-600{background-color:var(--color-amber-600)}.bg-black\/20{background-color:#0003}@supports (color:color-mix(in lab,red,red)){.bg-black\/20{background-color:color-mix(in oklab,var(--color-black) 20%,transparent)}}.bg-black\/30{background-color:#0000004d}@supports (color:color-mix(in lab,red,red)){.bg-black\/30{background-color:color-mix(in oklab,var(--color-black) 30%,transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black) 50%,transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab,red,red)){.bg-black\/60{background-color:color-mix(in oklab,var(--color-black) 60%,transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-50\/30{background-color:#eff6ff4d}@supports (color:color-mix(in lab,red,red)){.bg-blue-50\/30{background-color:color-mix(in oklab,var(--color-blue-50) 30%,transparent)}}.bg-blue-50\/40{background-color:#eff6ff66}@supports (color:color-mix(in lab,red,red)){.bg-blue-50\/40{background-color:color-mix(in oklab,var(--color-blue-50) 40%,transparent)}}.bg-blue-50\/50{background-color:#eff6ff80}@supports (color:color-mix(in lab,red,red)){.bg-blue-50\/50{background-color:color-mix(in oklab,var(--color-blue-50) 50%,transparent)}}.bg-blue-50\/80{background-color:#eff6ffcc}@supports (color:color-mix(in lab,red,red)){.bg-blue-50\/80{background-color:color-mix(in oklab,var(--color-blue-50) 80%,transparent)}}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-100\/50{background-color:#dbeafe80}@supports (color:color-mix(in lab,red,red)){.bg-blue-100\/50{background-color:color-mix(in oklab,var(--color-blue-100) 50%,transparent)}}.bg-blue-100\/70{background-color:#dbeafeb3}@supports (color:color-mix(in lab,red,red)){.bg-blue-100\/70{background-color:color-mix(in oklab,var(--color-blue-100) 70%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-400{background-color:var(--color-green-400)}.bg-green-500{background-color:var(--color-green-500)}.bg-indigo-50{background-color:var(--color-indigo-50)}.bg-indigo-50\/50{background-color:#eef2ff80}@supports (color:color-mix(in lab,red,red)){.bg-indigo-50\/50{background-color:color-mix(in oklab,var(--color-indigo-50) 50%,transparent)}}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-orange-50{background-color:var(--color-orange-50)}.bg-orange-50\/30{background-color:#fff7ed4d}@supports (color:color-mix(in lab,red,red)){.bg-orange-50\/30{background-color:color-mix(in oklab,var(--color-orange-50) 30%,transparent)}}.bg-purple-50{background-color:var(--color-purple-50)}.bg-purple-100{background-color:var(--color-purple-100)}.bg-purple-200{background-color:var(--color-purple-200)}.bg-purple-600{background-color:var(--color-purple-600)}.bg-purple-700{background-color:var(--color-purple-700)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-50\/30{background-color:#fef2f24d}@supports (color:color-mix(in lab,red,red)){.bg-red-50\/30{background-color:color-mix(in oklab,var(--color-red-50) 30%,transparent)}}.bg-red-100{background-color:var(--color-red-100)}.bg-red-400{background-color:var(--color-red-400)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-50\/50{background-color:#f8fafc80}@supports (color:color-mix(in lab,red,red)){.bg-slate-50\/50{background-color:color-mix(in oklab,var(--color-slate-50) 50%,transparent)}}.bg-slate-50\/70{background-color:#f8fafcb3}@supports (color:color-mix(in lab,red,red)){.bg-slate-50\/70{background-color:color-mix(in oklab,var(--color-slate-50) 70%,transparent)}}.bg-slate-50\/80{background-color:#f8fafccc}@supports (color:color-mix(in lab,red,red)){.bg-slate-50\/80{background-color:color-mix(in oklab,var(--color-slate-50) 80%,transparent)}}.bg-slate-50\/90{background-color:#f8fafce6}@supports (color:color-mix(in lab,red,red)){.bg-slate-50\/90{background-color:color-mix(in oklab,var(--color-slate-50) 90%,transparent)}}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-200{background-color:var(--color-slate-200)}.bg-slate-200\/30{background-color:#e2e8f04d}@supports (color:color-mix(in lab,red,red)){.bg-slate-200\/30{background-color:color-mix(in oklab,var(--color-slate-200) 30%,transparent)}}.bg-slate-300{background-color:var(--color-slate-300)}.bg-slate-500\/10{background-color:#62748e1a}@supports (color:color-mix(in lab,red,red)){.bg-slate-500\/10{background-color:color-mix(in oklab,var(--color-slate-500) 10%,transparent)}}.bg-slate-700{background-color:var(--color-slate-700)}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-800\/70{background-color:#1d293db3}@supports (color:color-mix(in lab,red,red)){.bg-slate-800\/70{background-color:color-mix(in oklab,var(--color-slate-800) 70%,transparent)}}.bg-slate-800\/90{background-color:#1d293de6}@supports (color:color-mix(in lab,red,red)){.bg-slate-800\/90{background-color:color-mix(in oklab,var(--color-slate-800) 90%,transparent)}}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/30{background-color:#0f172b4d}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/30{background-color:color-mix(in oklab,var(--color-slate-900) 30%,transparent)}}.bg-slate-900\/40{background-color:#0f172b66}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/40{background-color:color-mix(in oklab,var(--color-slate-900) 40%,transparent)}}.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-950{background-color:var(--color-slate-950)}.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-transparent{background-color:#0000}.bg-violet-50{background-color:var(--color-violet-50)}.bg-violet-100{background-color:var(--color-violet-100)}.bg-white{background-color:var(--color-white)}.bg-white\/70{background-color:#ffffffb3}@supports (color:color-mix(in lab,red,red)){.bg-white\/70{background-color:color-mix(in oklab,var(--color-white) 70%,transparent)}}.bg-white\/80{background-color:#fffc}@supports (color:color-mix(in lab,red,red)){.bg-white\/80{background-color:color-mix(in oklab,var(--color-white) 80%,transparent)}}.bg-white\/95{background-color:#fffffff2}@supports (color:color-mix(in lab,red,red)){.bg-white\/95{background-color:color-mix(in oklab,var(--color-white) 95%,transparent)}}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-indigo-500{--tw-gradient-from:var(--color-indigo-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-violet-500{--tw-gradient-from:var(--color-violet-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.via-indigo-500{--tw-gradient-via:var(--color-indigo-500);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-blue-500{--tw-gradient-to:var(--color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.object-contain{object-fit:contain}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:calc(var(--spacing) * 1)}.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-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:calc(var(--spacing) * 0)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.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-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-px{padding-block:1px}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-24{padding-top:calc(var(--spacing) * 24)}.pr-1{padding-right:calc(var(--spacing) * 1)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pl-1{padding-left:calc(var(--spacing) * 1)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-6{padding-left:calc(var(--spacing) * 6)}.pl-8{padding-left:calc(var(--spacing) * 8)}.text-center{text-align:center}.text-left{text-align:left}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--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-\[0\.7rem\]{font-size:.7rem}.text-\[0\.65rem\]{font-size:.65rem}.text-\[0\.625rem\]{font-size:.625rem}.text-\[0\.5625rem\]{font-size:.5625rem}.text-\[0\.6875rem\]{font-size:.6875rem}.text-\[0\.8125rem\]{font-size:.8125rem}.text-\[11px\]{font-size:11px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-none{--tw-leading:1;line-height:1}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.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-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.\[overflow-wrap\:anywhere\]{overflow-wrap:anywhere}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-300{color:var(--color-amber-300)}.text-amber-500{color:var(--color-amber-500)}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-amber-800{color:var(--color-amber-800)}.text-amber-900{color:var(--color-amber-900)}.text-blue-200{color:var(--color-blue-200)}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-blue-800{color:var(--color-blue-800)}.text-blue-900{color:var(--color-blue-900)}.text-cyan-500{color:var(--color-cyan-500)}.text-emerald-600{color:var(--color-emerald-600)}.text-emerald-700{color:var(--color-emerald-700)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-green-500{color:var(--color-green-500)}.text-green-600{color:var(--color-green-600)}.text-green-700{color:var(--color-green-700)}.text-green-800{color:var(--color-green-800)}.text-indigo-500{color:var(--color-indigo-500)}.text-indigo-600{color:var(--color-indigo-600)}.text-indigo-700{color:var(--color-indigo-700)}.text-indigo-800{color:var(--color-indigo-800)}.text-orange-500{color:var(--color-orange-500)}.text-orange-600{color:var(--color-orange-600)}.text-purple-200{color:var(--color-purple-200)}.text-purple-300{color:var(--color-purple-300)}.text-purple-500{color:var(--color-purple-500)}.text-purple-600{color:var(--color-purple-600)}.text-purple-700{color:var(--color-purple-700)}.text-purple-800{color:var(--color-purple-800)}.text-red-300{color:var(--color-red-300)}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-sky-600{color:var(--color-sky-600)}.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-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-800{color:var(--color-slate-800)}.text-slate-900{color:var(--color-slate-900)}.text-transparent{color:#0000}.text-violet-500{color:var(--color-violet-500)}.text-violet-700{color:var(--color-violet-700)}.text-violet-800{color:var(--color-violet-800)}.text-white{color:var(--color-white)}.text-white\/85{color:#ffffffd9}@supports (color:color-mix(in lab,red,red)){.text-white\/85{color:color-mix(in oklab,var(--color-white) 85%,transparent)}}.text-yellow-500{color:var(--color-yellow-500)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.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,)}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.decoration-blue-200{-webkit-text-decoration-color:var(--color-blue-200);text-decoration-color:var(--color-blue-200)}.decoration-dotted{text-decoration-style:dotted}.underline-offset-2{text-underline-offset:2px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px 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)}.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-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px 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)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px 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)}.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,.ring-1{--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)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + 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)}.ring-blue-100{--tw-ring-color:var(--color-blue-100)}.ring-blue-300{--tw-ring-color:var(--color-blue-300)}.ring-blue-400{--tw-ring-color:var(--color-blue-400)}.ring-green-100{--tw-ring-color:var(--color-green-100)}.ring-orange-100{--tw-ring-color:var(--color-orange-100)}.ring-purple-200{--tw-ring-color:var(--color-purple-200)}.ring-purple-300{--tw-ring-color:var(--color-purple-300)}.ring-red-100{--tw-ring-color:var(--color-red-100)}.ring-offset-1{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);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,)}.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,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-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))}.transition-all{transition-property:all;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-opacity{transition-property:opacity;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-150{--tw-duration:.15s;transition-duration:.15s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.will-change-transform{will-change:transform}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.select-none{-webkit-user-select:none;user-select:none}.select-text{-webkit-user-select:text;user-select:text}@media(hover:hover){.group-hover\:pointer-events-auto:is(:where(.group):hover *){pointer-events:auto}.group-hover\:bg-blue-200:is(:where(.group):hover *){background-color:var(--color-blue-200)}.group-hover\:bg-green-200:is(:where(.group):hover *){background-color:var(--color-green-200)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.selection\:bg-blue-100 ::selection{background-color:var(--color-blue-100)}.selection\:bg-blue-100::selection{background-color:var(--color-blue-100)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.odd\:bg-white:nth-child(odd){background-color:var(--color-white)}.even\:bg-slate-50\/50:nth-child(2n){background-color:#f8fafc80}@supports (color:color-mix(in lab,red,red)){.even\:bg-slate-50\/50:nth-child(2n){background-color:color-mix(in oklab,var(--color-slate-50) 50%,transparent)}}@media(hover:hover){.hover\:border-blue-300:hover{border-color:var(--color-blue-300)}.hover\:border-blue-400:hover{border-color:var(--color-blue-400)}.hover\:border-green-400:hover{border-color:var(--color-green-400)}.hover\:border-indigo-300:hover{border-color:var(--color-indigo-300)}.hover\:border-indigo-400:hover{border-color:var(--color-indigo-400)}.hover\:border-purple-300:hover{border-color:var(--color-purple-300)}.hover\:border-red-300:hover{border-color:var(--color-red-300)}.hover\:border-slate-300:hover{border-color:var(--color-slate-300)}.hover\:bg-amber-50:hover{background-color:var(--color-amber-50)}.hover\:bg-amber-100:hover{background-color:var(--color-amber-100)}.hover\:bg-amber-700:hover{background-color:var(--color-amber-700)}.hover\:bg-black\/5:hover{background-color:#0000000d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/5:hover{background-color:color-mix(in oklab,var(--color-black) 5%,transparent)}}.hover\:bg-blue-50:hover{background-color:var(--color-blue-50)}.hover\:bg-blue-50\/60:hover{background-color:#eff6ff99}@supports (color:color-mix(in lab,red,red)){.hover\:bg-blue-50\/60:hover{background-color:color-mix(in oklab,var(--color-blue-50) 60%,transparent)}}.hover\:bg-blue-100:hover{background-color:var(--color-blue-100)}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-green-50:hover{background-color:var(--color-green-50)}.hover\:bg-green-100:hover{background-color:var(--color-green-100)}.hover\:bg-indigo-50:hover{background-color:var(--color-indigo-50)}.hover\:bg-indigo-50\/60:hover{background-color:#eef2ff99}@supports (color:color-mix(in lab,red,red)){.hover\:bg-indigo-50\/60:hover{background-color:color-mix(in oklab,var(--color-indigo-50) 60%,transparent)}}.hover\:bg-indigo-100:hover{background-color:var(--color-indigo-100)}.hover\:bg-indigo-700:hover{background-color:var(--color-indigo-700)}.hover\:bg-purple-50:hover{background-color:var(--color-purple-50)}.hover\:bg-purple-50\/60:hover{background-color:#faf5ff99}@supports (color:color-mix(in lab,red,red)){.hover\:bg-purple-50\/60:hover{background-color:color-mix(in oklab,var(--color-purple-50) 60%,transparent)}}.hover\:bg-purple-100:hover{background-color:var(--color-purple-100)}.hover\:bg-purple-700:hover{background-color:var(--color-purple-700)}.hover\:bg-purple-800:hover{background-color:var(--color-purple-800)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-100:hover{background-color:var(--color-red-100)}.hover\:bg-red-200:hover{background-color:var(--color-red-200)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-100:hover{background-color:var(--color-slate-100)}.hover\:bg-slate-200:hover{background-color:var(--color-slate-200)}.hover\:bg-slate-200\/50:hover{background-color:#e2e8f080}@supports (color:color-mix(in lab,red,red)){.hover\:bg-slate-200\/50:hover{background-color:color-mix(in oklab,var(--color-slate-200) 50%,transparent)}}.hover\:bg-slate-300:hover{background-color:var(--color-slate-300)}.hover\:bg-slate-300\/50:hover{background-color:#cad5e280}@supports (color:color-mix(in lab,red,red)){.hover\:bg-slate-300\/50:hover{background-color:color-mix(in oklab,var(--color-slate-300) 50%,transparent)}}.hover\:bg-slate-700:hover{background-color:var(--color-slate-700)}.hover\:bg-slate-800:hover{background-color:var(--color-slate-800)}.hover\:bg-slate-900:hover{background-color:var(--color-slate-900)}.hover\:bg-violet-100:hover{background-color:var(--color-violet-100)}.hover\:bg-white:hover{background-color:var(--color-white)}.hover\:text-amber-600:hover{color:var(--color-amber-600)}.hover\:text-amber-700:hover{color:var(--color-amber-700)}.hover\:text-amber-800:hover{color:var(--color-amber-800)}.hover\:text-amber-900:hover{color:var(--color-amber-900)}.hover\:text-blue-600:hover{color:var(--color-blue-600)}.hover\:text-blue-800:hover{color:var(--color-blue-800)}.hover\:text-gray-600:hover{color:var(--color-gray-600)}.hover\:text-gray-900:hover{color:var(--color-gray-900)}.hover\:text-green-600:hover{color:var(--color-green-600)}.hover\:text-green-700:hover{color:var(--color-green-700)}.hover\:text-green-800:hover{color:var(--color-green-800)}.hover\:text-orange-500:hover{color:var(--color-orange-500)}.hover\:text-purple-600:hover{color:var(--color-purple-600)}.hover\:text-purple-800:hover{color:var(--color-purple-800)}.hover\:text-red-500:hover{color:var(--color-red-500)}.hover\:text-red-600:hover{color:var(--color-red-600)}.hover\:text-red-700:hover{color:var(--color-red-700)}.hover\:text-red-800:hover{color:var(--color-red-800)}.hover\:text-slate-500:hover{color:var(--color-slate-500)}.hover\:text-slate-600:hover{color:var(--color-slate-600)}.hover\:text-slate-700:hover{color:var(--color-slate-700)}.hover\:text-slate-800:hover{color:var(--color-slate-800)}.hover\:text-white:hover{color:var(--color-white)}.hover\:underline:hover{text-decoration-line:underline}.hover\:decoration-blue-400:hover{-webkit-text-decoration-color:var(--color-blue-400);text-decoration-color:var(--color-blue-400)}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px 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)}.hover\:shadow-sm:hover{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px 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)}}.focus\:border-blue-400:focus{border-color:var(--color-blue-400)}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:border-transparent:focus{border-color:#0000}.focus\:bg-blue-50:focus{background-color:var(--color-blue-50)}.focus\:opacity-100:focus{opacity:1}.focus\:ring-1:focus{--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)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + 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)}.focus\:ring-amber-500:focus{--tw-ring-color:var(--color-amber-500)}.focus\:ring-blue-400:focus{--tw-ring-color:var(--color-blue-400)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:ring-blue-500\/30:focus{--tw-ring-color:#3080ff4d}@supports (color:color-mix(in lab,red,red)){.focus\:ring-blue-500\/30:focus{--tw-ring-color:color-mix(in oklab, var(--color-blue-500) 30%, transparent)}}.focus\:ring-purple-400:focus{--tw-ring-color:var(--color-purple-400)}.focus\:ring-purple-500:focus{--tw-ring-color:var(--color-purple-500)}.focus\:ring-red-500:focus{--tw-ring-color:var(--color-red-500)}.focus\:ring-slate-500:focus{--tw-ring-color:var(--color-slate-500)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:cursor-wait:disabled{cursor:wait}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media(hover:hover){.disabled\:hover\:bg-transparent:disabled:hover{background-color:#0000}}@media(min-width:40rem){.sm\:inline{display:inline}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:p-6{padding:calc(var(--spacing) * 6)}.sm\:p-8{padding:calc(var(--spacing) * 8)}.sm\:px-3{padding-inline:calc(var(--spacing) * 3)}}@media(min-width:48rem){.md\:inline{display:inline}.md\:max-w-\[10rem\]{max-width:10rem}.md\:max-w-\[14rem\]{max-width:14rem}}@media(min-width:64rem){.lg\:col-span-3{grid-column:span 3/span 3}.lg\:hidden{display:none}.lg\:inline{display:inline}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:items-stretch{align-items:stretch}}@media(prefers-color-scheme:dark){.dark\:border-slate-700{border-color:var(--color-slate-700)}.dark\:bg-slate-700{background-color:var(--color-slate-700)}.dark\:bg-slate-800{background-color:var(--color-slate-800)}.dark\:text-slate-300{color:var(--color-slate-300)}.dark\:text-slate-400{color:var(--color-slate-400)}@media(hover:hover){.dark\:hover\:bg-slate-700:hover{background-color:var(--color-slate-700)}}}}:root{--ui-scale:.9}html{font-size:calc(16px * var(--ui-scale));scroll-behavior:smooth}.cm-editor,.cm-editor:focus,.cm-editor:focus-within,.cm-editor.cm-focused{outline:none}@media(min-width:1024px){.nebula-filebrowser-offset{padding-left:var(--nebula-filebrowser-width,18rem)}.nebula-chat-offset{padding-right:20rem}}@keyframes slideInFromTop{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.animate-in.slide-in-from-top-2{animation:.2s ease-out slideInFromTop}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.animate-in.fade-in{animation:.2s ease-out fadeIn}@keyframes loadingBar{0%{width:0%;margin-left:0%}50%{width:60%;margin-left:20%}to{width:0%;margin-left:100%}}.animate-loading-bar{animation:1.2s ease-in-out infinite loadingBar}@keyframes cellHighlight{0%{background-color:#3b82f61a;box-shadow:0 0 #3b82f680}25%{background-color:#3b82f626;box-shadow:0 0 0 4px #3b82f666}50%{background-color:#3b82f61a;box-shadow:0 0 0 4px #3b82f64d}to{background-color:#0000;box-shadow:0 0 #3b82f600}}.cell-highlight-animation{animation:1.5s ease-out forwards cellHighlight}@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-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{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-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}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}/**
|
|
2
|
-
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
-
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
-
* https://github.com/chjj/term.js
|
|
5
|
-
* @license MIT
|
|
6
|
-
*
|
|
7
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
-
* in the Software without restriction, including without limitation the rights
|
|
10
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
-
* furnished to do so, subject to the following conditions:
|
|
13
|
-
*
|
|
14
|
-
* The above copyright notice and this permission notice shall be included in
|
|
15
|
-
* all copies or substantial portions of the Software.
|
|
16
|
-
*
|
|
17
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
-
* THE SOFTWARE.
|
|
24
|
-
*
|
|
25
|
-
* Originally forked from (with the author's permission):
|
|
26
|
-
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
-
* http://bellard.org/jslinux/
|
|
28
|
-
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
-
* The original design remains. The terminal itself
|
|
30
|
-
* has been extended to include xterm CSI codes, among
|
|
31
|
-
* other features.
|
|
32
|
-
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline: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 .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.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.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.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{text-decoration:overline}.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-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;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}
|