claude-code-session-manager 0.5.0 → 0.7.0
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/{cssMode-DuceD2Ek.js → cssMode-DKDWYdvl.js} +1 -1
- package/dist/assets/{editor.main-W7kZjY3Y.js → editor.main-5I0NYqsz.js} +3 -3
- package/dist/assets/{freemarker2-BrfVQxqM.js → freemarker2-rgV6AhZc.js} +1 -1
- package/dist/assets/{handlebars-CEk4GZAW.js → handlebars-C9k_1YsY.js} +1 -1
- package/dist/assets/{html-Dsr1hOJo.js → html-C4yLjsNO.js} +1 -1
- package/dist/assets/{htmlMode-DTyxWkAs.js → htmlMode-0zBN-DQG.js} +1 -1
- package/dist/assets/{index-DUYNLg5N.js → index-CdR1wDrv.js} +271 -272
- package/dist/assets/index-DsC4vT8M.css +32 -0
- package/dist/assets/{javascript-DDnXRxuX.js → javascript-BvI2NTgX.js} +1 -1
- package/dist/assets/{jsonMode-BFDUayfd.js → jsonMode-DT9apm2G.js} +1 -1
- package/dist/assets/{liquid-BcvXX-ei.js → liquid-DH47ZRer.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-D6rzws04.js → lspLanguageFeatures-D-jU4xBn.js} +1 -1
- package/dist/assets/{mdx-DnY5OLKT.js → mdx-D_9bvVKA.js} +1 -1
- package/dist/assets/{python-BA4bdGM0.js → python-hRhgz_Ws.js} +1 -1
- package/dist/assets/{razor-VjEf8dER.js → razor-ceB22WsC.js} +1 -1
- package/dist/assets/{tsMode-BzXie6uX.js → tsMode-DCqcH3IQ.js} +1 -1
- package/dist/assets/{typescript-BEjKh90W.js → typescript-rK_WNycK.js} +1 -1
- package/dist/assets/{xml-C64Hq61M.js → xml-Bd6rwwQn.js} +1 -1
- package/dist/assets/{yaml-BvsE9PT3.js → yaml-ChfRx-G9.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/main/index.cjs +33 -4
- package/src/main/scheduler.cjs +35 -34
- package/dist/assets/index-QriiiRo1.css +0 -32
package/dist/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Claude Session Manager</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-CdR1wDrv.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="./assets/index-DsC4vT8M.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body class="bg-bg text-fg font-mono antialiased">
|
|
11
11
|
<div id="root"></div>
|
package/package.json
CHANGED
package/src/main/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { app, BrowserWindow, ipcMain, dialog, Menu, session, systemPreferences, globalShortcut } = require('electron');
|
|
1
|
+
const { app, BrowserWindow, ipcMain, dialog, Menu, session, systemPreferences, globalShortcut, shell } = require('electron');
|
|
2
2
|
const { spawn, execFile, execFileSync } = require('node:child_process');
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
const fs = require('node:fs');
|
|
@@ -24,7 +24,9 @@ const REBOOT_LOG = path.join(os.homedir(), '.claude', 'session-manager-reboot.lo
|
|
|
24
24
|
function logReboot(line) {
|
|
25
25
|
try {
|
|
26
26
|
fs.mkdirSync(path.dirname(REBOOT_LOG), { recursive: true });
|
|
27
|
-
|
|
27
|
+
// 0o600 — reboot log can include npx paths and pid traces. Match the
|
|
28
|
+
// mode used by logs.cjs / otelSettings.cjs for consistency.
|
|
29
|
+
fs.appendFileSync(REBOOT_LOG, `[${new Date().toISOString()}] ${line}\n`, { mode: 0o600 });
|
|
28
30
|
} catch { /* best-effort */ }
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -60,7 +62,7 @@ function relaunchViaNpx() {
|
|
|
60
62
|
if (!npxPath) throw new Error('npx not found on PATH');
|
|
61
63
|
|
|
62
64
|
fs.mkdirSync(path.dirname(REBOOT_LOG), { recursive: true });
|
|
63
|
-
const logFd = fs.openSync(REBOOT_LOG, 'a');
|
|
65
|
+
const logFd = fs.openSync(REBOOT_LOG, 'a', 0o600);
|
|
64
66
|
// `--yes` auto-accepts install prompt; `@latest` forces registry resolution
|
|
65
67
|
// of the dist-tag so a freshly published version is picked up.
|
|
66
68
|
const child = spawn(npxPath, ['--yes', 'claude-code-session-manager@latest'], {
|
|
@@ -160,9 +162,36 @@ function createWindow() {
|
|
|
160
162
|
} else if (fs.existsSync(distIndex)) {
|
|
161
163
|
mainWindow.loadFile(distIndex);
|
|
162
164
|
} else {
|
|
163
|
-
|
|
165
|
+
// Hard-fail in production rather than silently load a remote URL. If
|
|
166
|
+
// dist/index.html is missing the install is broken — surface clearly
|
|
167
|
+
// instead of blindly trying http://localhost:5173, which would (a) load
|
|
168
|
+
// remote content and (b) almost always fail in a packaged install.
|
|
169
|
+
console.error('[main] dist/index.html missing and SM_DEV is not set — refusing to load remote content. Reinstall or set SM_DEV=1 for dev.');
|
|
170
|
+
app.exit(1);
|
|
171
|
+
return;
|
|
164
172
|
}
|
|
165
173
|
|
|
174
|
+
// Lock down navigation: deny window.open + reject any navigation away from
|
|
175
|
+
// the loaded UI. External links are routed to the OS browser via shell
|
|
176
|
+
// instead of opening inside the Electron window. Defense against XSS or
|
|
177
|
+
// a compromised dependency that tries to navigate to a phishing page.
|
|
178
|
+
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
|
179
|
+
if (url.startsWith('http://') || url.startsWith('https://')) {
|
|
180
|
+
shell.openExternal(url).catch(() => {});
|
|
181
|
+
}
|
|
182
|
+
return { action: 'deny' };
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
mainWindow.webContents.on('will-navigate', (event, url) => {
|
|
186
|
+
const allowed = useDevServer
|
|
187
|
+
? ['http://localhost:5173', 'http://127.0.0.1:5173']
|
|
188
|
+
: []; // file:// loads happen via loadFile, not navigation
|
|
189
|
+
if (!allowed.some((a) => url.startsWith(a))) {
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
console.warn('[main] blocked will-navigate to', url);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
166
195
|
mainWindow.on('closed', () => {
|
|
167
196
|
mainWindow = null;
|
|
168
197
|
});
|
package/src/main/scheduler.cjs
CHANGED
|
@@ -220,23 +220,22 @@ function reconcile(state) {
|
|
|
220
220
|
|
|
221
221
|
// ---------- next-reset detection ----------
|
|
222
222
|
|
|
223
|
-
let cachedNextReset =
|
|
223
|
+
let cachedNextReset = null;
|
|
224
224
|
let cachedUtilization = null; // five_hour utilization %, 0–100, or null if unknown
|
|
225
225
|
|
|
226
226
|
async function refreshNextReset() {
|
|
227
227
|
try {
|
|
228
228
|
const r = await billing.fetchUsage();
|
|
229
|
-
|
|
230
|
-
cachedNextReset = { at, fetchedAt: Date.now() };
|
|
229
|
+
cachedNextReset = r?.usage?.five_hour?.resets_at ?? null;
|
|
231
230
|
cachedUtilization = r?.usage?.five_hour?.utilization ?? cachedUtilization;
|
|
232
|
-
return
|
|
231
|
+
return cachedNextReset;
|
|
233
232
|
} catch {
|
|
234
|
-
return cachedNextReset
|
|
233
|
+
return cachedNextReset;
|
|
235
234
|
}
|
|
236
235
|
}
|
|
237
236
|
|
|
238
237
|
function getNextResetCached() {
|
|
239
|
-
return cachedNextReset
|
|
238
|
+
return cachedNextReset;
|
|
240
239
|
}
|
|
241
240
|
|
|
242
241
|
// ---------- timer ----------
|
|
@@ -245,6 +244,8 @@ let mainWindow = null;
|
|
|
245
244
|
let fireTimer = null;
|
|
246
245
|
let resumeTimer = null;
|
|
247
246
|
let pollTimer = null;
|
|
247
|
+
let rescheduleInterval = null;
|
|
248
|
+
let initialPollTimeout = null;
|
|
248
249
|
let isExecuting = false;
|
|
249
250
|
let cancelToken = { cancelled: false };
|
|
250
251
|
let claudeBinPathCached = null;
|
|
@@ -315,7 +316,6 @@ async function rescheduleTimer() {
|
|
|
315
316
|
function setPaused(reason, resumeAtIso) {
|
|
316
317
|
const s = readQueue();
|
|
317
318
|
if (s.paused && s.paused.reason === reason) {
|
|
318
|
-
// already paused for this reason; just refresh resumeAt if newer
|
|
319
319
|
if (resumeAtIso) s.paused.resumeAt = resumeAtIso;
|
|
320
320
|
} else {
|
|
321
321
|
s.paused = { reason, since: new Date().toISOString(), resumeAt: resumeAtIso || null };
|
|
@@ -324,19 +324,18 @@ function setPaused(reason, resumeAtIso) {
|
|
|
324
324
|
broadcast();
|
|
325
325
|
cancelToken.cancelled = true;
|
|
326
326
|
if (resumeTimer) { clearTimeout(resumeTimer); resumeTimer = null; }
|
|
327
|
-
if (resumeAtIso)
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
runDueJobs().catch(() => {});
|
|
334
|
-
}, delay);
|
|
335
|
-
console.log(`[scheduler] paused (${reason}); auto-resume in ${Math.round(delay/1000)}s`);
|
|
336
|
-
} else {
|
|
337
|
-
console.warn(`[scheduler] paused (${reason}); resumeAt too far in future for setTimeout (${delay}ms)`);
|
|
338
|
-
}
|
|
327
|
+
if (!resumeAtIso) return;
|
|
328
|
+
// Resume 30s after the reset to give the auth/billing endpoint time to flip.
|
|
329
|
+
const delay = Math.max(30_000, new Date(resumeAtIso).getTime() - Date.now() + 30_000);
|
|
330
|
+
if (delay > 0x7fffffff) {
|
|
331
|
+
console.warn(`[scheduler] paused (${reason}); resumeAt too far for setTimeout (${delay}ms)`);
|
|
332
|
+
return;
|
|
339
333
|
}
|
|
334
|
+
resumeTimer = setTimeout(() => {
|
|
335
|
+
clearPause('resume-timer');
|
|
336
|
+
runDueJobs().catch(() => {});
|
|
337
|
+
}, delay);
|
|
338
|
+
console.log(`[scheduler] paused (${reason}); auto-resume in ${Math.round(delay/1000)}s`);
|
|
340
339
|
}
|
|
341
340
|
|
|
342
341
|
function clearPause(source) {
|
|
@@ -350,6 +349,16 @@ function clearPause(source) {
|
|
|
350
349
|
}
|
|
351
350
|
}
|
|
352
351
|
|
|
352
|
+
/** Mutate a job in place to "pending" with cleared run metadata. */
|
|
353
|
+
function resetJobFields(job, errorMsg) {
|
|
354
|
+
job.status = 'pending';
|
|
355
|
+
job.runId = null;
|
|
356
|
+
job.startedAt = null;
|
|
357
|
+
job.finishedAt = null;
|
|
358
|
+
job.exitCode = null;
|
|
359
|
+
job.error = errorMsg ?? null;
|
|
360
|
+
}
|
|
361
|
+
|
|
353
362
|
/** Scan the tail of a job's log for the canonical rate-limit signal. We look
|
|
354
363
|
* at the last 16 KB — final result event always lands at the end. */
|
|
355
364
|
function detectRateLimitInLog(logPath) {
|
|
@@ -514,12 +523,7 @@ async function runDueJobs() {
|
|
|
514
523
|
if (i2 >= 0) {
|
|
515
524
|
const treatAsPending = res.rateLimited || (sn.paused && sn.paused.reason === 'rate_limit');
|
|
516
525
|
if (treatAsPending) {
|
|
517
|
-
sn.jobs[i2].
|
|
518
|
-
sn.jobs[i2].runId = null;
|
|
519
|
-
sn.jobs[i2].startedAt = null;
|
|
520
|
-
sn.jobs[i2].finishedAt = null;
|
|
521
|
-
sn.jobs[i2].exitCode = null;
|
|
522
|
-
sn.jobs[i2].error = res.rateLimited ? 'paused: rate limit' : 'paused: queue halted';
|
|
526
|
+
resetJobFields(sn.jobs[i2], res.rateLimited ? 'paused: rate limit' : 'paused: queue halted');
|
|
523
527
|
} else {
|
|
524
528
|
sn.jobs[i2].status = res.exitCode === 0 ? 'completed' : 'failed';
|
|
525
529
|
sn.jobs[i2].finishedAt = new Date().toISOString();
|
|
@@ -632,12 +636,7 @@ function registerScheduleHandlers() {
|
|
|
632
636
|
const state = readQueue();
|
|
633
637
|
const idx = state.jobs.findIndex((j) => j.slug === slug);
|
|
634
638
|
if (idx < 0) return { ok: false, error: 'not found' };
|
|
635
|
-
state.jobs[idx]
|
|
636
|
-
state.jobs[idx].runId = null;
|
|
637
|
-
state.jobs[idx].startedAt = null;
|
|
638
|
-
state.jobs[idx].finishedAt = null;
|
|
639
|
-
state.jobs[idx].exitCode = null;
|
|
640
|
-
state.jobs[idx].error = null;
|
|
639
|
+
resetJobFields(state.jobs[idx]);
|
|
641
640
|
writeQueue(state);
|
|
642
641
|
broadcast();
|
|
643
642
|
return { ok: true };
|
|
@@ -704,14 +703,16 @@ async function init() {
|
|
|
704
703
|
|
|
705
704
|
await rescheduleTimer();
|
|
706
705
|
// Refresh next-reset every 10 minutes — billing window can shift if usage
|
|
707
|
-
// resets early or the auth token rotates.
|
|
708
|
-
|
|
706
|
+
// resets early or the auth token rotates. Tracked so re-init doesn't leak.
|
|
707
|
+
if (rescheduleInterval) clearInterval(rescheduleInterval);
|
|
708
|
+
rescheduleInterval = setInterval(() => { rescheduleTimer().catch(() => {}); }, 10 * 60_000);
|
|
709
709
|
// when-available poll loop. Tick every 2 minutes; the function itself is
|
|
710
710
|
// a no-op when policy != 'when-available' or queue is empty/paused.
|
|
711
711
|
if (pollTimer) clearInterval(pollTimer);
|
|
712
712
|
pollTimer = setInterval(() => { pollWhenAvailable().catch(() => {}); }, 2 * 60_000);
|
|
713
713
|
// First tick fires after a short delay so billing is warmed up.
|
|
714
|
-
|
|
714
|
+
if (initialPollTimeout) clearTimeout(initialPollTimeout);
|
|
715
|
+
initialPollTimeout = setTimeout(() => { pollWhenAvailable().catch(() => {}); }, 15_000);
|
|
715
716
|
}
|
|
716
717
|
|
|
717
718
|
module.exports = { registerScheduleHandlers, attachWindow, init, ROOT, PRDS_DIR };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
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;-moz-user-select:none;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 .xterm-scroll-area{visibility:hidden}.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) *::-moz-selection{color:transparent}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;-moz-user-select:text;user-select:text;white-space:pre}.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{-webkit-text-decoration:double underline;text-decoration:double underline}.xterm-underline-3{-webkit-text-decoration:wavy underline;text-decoration:wavy underline}.xterm-underline-4{-webkit-text-decoration:dotted underline;text-decoration:dotted underline}.xterm-underline-5{-webkit-text-decoration:dashed underline;text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:JetBrains Mono,ui-monospace,SFMono-Regular,Menlo,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.-bottom-\[5px\]{bottom:-5px}.-bottom-\[7px\]{bottom:-7px}.-top-20{top:-5rem}.-top-28{top:-7rem}.-top-48{top:-12rem}.bottom-0{bottom:0}.bottom-24{bottom:6rem}.bottom-3{bottom:.75rem}.bottom-4{bottom:1rem}.bottom-\[88px\]{bottom:88px}.left-0{left:0}.left-1\/2{left:50%}.left-4{left:1rem}.left-\[72\%\]{left:72%}.right-0{right:0}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-0\.5{top:.125rem}.top-10{top:2.5rem}.top-4{top:1rem}.top-full{top:100%}.z-10{z-index:10}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-3{margin-left:.75rem;margin-right:.75rem}.mx-4{margin-left:1rem;margin-right:1rem}.-mb-px{margin-bottom:-1px}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-2{height:.5rem}.h-24{height:6rem}.h-3{height:.75rem}.h-4{height:1rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-9{height:2.25rem}.h-full{height:100%}.h-px{height:1px}.max-h-24{max-height:6rem}.max-h-40{max-height:10rem}.max-h-64{max-height:16rem}.max-h-72{max-height:18rem}.max-h-\[60vh\]{max-height:60vh}.min-h-0{min-height:0px}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-20{width:5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-32{width:8rem}.w-4{width:1rem}.w-48{width:12rem}.w-56{width:14rem}.w-64{width:16rem}.w-7{width:1.75rem}.w-\[420px\]{width:420px}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-\[12rem\]{max-width:12rem}.max-w-\[8rem\]{max-width:8rem}.max-w-md{max-width:28rem}.max-w-xl{max-width:36rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0\.5{--tw-translate-x: .125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-3\.5{--tw-translate-x: .875rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-45{--tw-rotate: 45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-col-resize{cursor:col-resize}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-wait{cursor:wait}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-y{resize:vertical}.resize{resize:both}.list-inside{list-style-position:inside}.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))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-1{row-gap:.25rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-line>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(36 42 51 / var(--tw-divide-opacity, 1))}.divide-line\/60>:not([hidden])~:not([hidden]){border-color:#242a3399}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-b-0{border-bottom-width:0px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-t-2{border-top-width:2px}.border-accent{--tw-border-opacity: 1;border-color:rgb(217 119 87 / var(--tw-border-opacity, 1))}.border-accent-muted{--tw-border-opacity: 1;border-color:rgb(138 74 51 / var(--tw-border-opacity, 1))}.border-accent\/30{border-color:#d977574d}.border-accent\/40{border-color:#d9775766}.border-accent\/50{border-color:#d9775780}.border-blue-900\/40{border-color:#1e3a8a66}.border-emerald-900\/40{border-color:#064e3b66}.border-line{--tw-border-opacity: 1;border-color:rgb(36 42 51 / var(--tw-border-opacity, 1))}.border-line\/50{border-color:#242a3380}.border-line\/60{border-color:#242a3399}.border-purple-900\/40{border-color:#581c8766}.border-red-500\/70{border-color:#ef4444b3}.border-red-800{--tw-border-opacity: 1;border-color:rgb(153 27 27 / var(--tw-border-opacity, 1))}.border-red-900\/40{border-color:#7f1d1d66}.border-transparent{border-color:transparent}.border-yellow-600\/50{border-color:#ca8a0480}.border-yellow-600\/60{border-color:#ca8a0499}.border-yellow-900\/40{border-color:#713f1266}.bg-accent{--tw-bg-opacity: 1;background-color:rgb(217 119 87 / var(--tw-bg-opacity, 1))}.bg-accent\/15{background-color:#d9775726}.bg-accent\/5{background-color:#d977570d}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.bg-amber-500\/10{background-color:#f59e0b1a}.bg-amber-500\/5{background-color:#f59e0b0d}.bg-bg{--tw-bg-opacity: 1;background-color:rgb(11 13 16 / var(--tw-bg-opacity, 1))}.bg-bg-elev{--tw-bg-opacity: 1;background-color:rgb(18 21 26 / var(--tw-bg-opacity, 1))}.bg-bg-elev\/40{background-color:#12151a66}.bg-bg-elev\/60{background-color:#12151a99}.bg-bg-elev\/80{background-color:#12151acc}.bg-bg-hi{--tw-bg-opacity: 1;background-color:rgb(26 31 39 / var(--tw-bg-opacity, 1))}.bg-bg-hi\/30{background-color:#1a1f274d}.bg-bg\/50{background-color:#0b0d1080}.bg-black\/60{background-color:#0009}.bg-blue-950\/30{background-color:#1725544d}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity, 1))}.bg-emerald-950\/30{background-color:#022c224d}.bg-fg{--tw-bg-opacity: 1;background-color:rgb(230 232 236 / var(--tw-bg-opacity, 1))}.bg-fg-dim{--tw-bg-opacity: 1;background-color:rgb(138 147 160 / var(--tw-bg-opacity, 1))}.bg-fg-faint{--tw-bg-opacity: 1;background-color:rgb(84 92 104 / var(--tw-bg-opacity, 1))}.bg-fg-faint\/40{background-color:#545c6866}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-900\/30{background-color:#14532d4d}.bg-line\/60{background-color:#242a3399}.bg-purple-950\/30{background-color:#3b07644d}.bg-red-400{--tw-bg-opacity: 1;background-color:rgb(248 113 113 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-red-900\/30{background-color:#7f1d1d4d}.bg-red-950\/20{background-color:#450a0a33}.bg-red-950\/30{background-color:#450a0a4d}.bg-red-950\/60{background-color:#450a0a99}.bg-yellow-400{--tw-bg-opacity: 1;background-color:rgb(250 204 21 / var(--tw-bg-opacity, 1))}.bg-yellow-500{--tw-bg-opacity: 1;background-color:rgb(234 179 8 / var(--tw-bg-opacity, 1))}.bg-yellow-950\/20{background-color:#42200633}.bg-yellow-950\/30{background-color:#4220064d}.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.from-bg{--tw-gradient-from: #0b0d10 var(--tw-gradient-from-position);--tw-gradient-to: rgb(11 13 16 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.via-bg{--tw-gradient-to: rgb(11 13 16 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), #0b0d10 var(--tw-gradient-via-position), var(--tw-gradient-to)}.to-bg-elev{--tw-gradient-to: #12151a var(--tw-gradient-to-position)}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-4{padding-left:1rem}.pr-2{padding-right:.5rem}.pt-1{padding-top:.25rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:JetBrains Mono,ui-monospace,SFMono-Regular,Menlo,monospace}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.normal-case{text-transform:none}.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)}.leading-5{line-height:1.25rem}.leading-relaxed{line-height:1.625}.tracking-normal{letter-spacing:0em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-accent{--tw-text-opacity: 1;color:rgb(217 119 87 / var(--tw-text-opacity, 1))}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-bg{--tw-text-opacity: 1;color:rgb(11 13 16 / var(--tw-text-opacity, 1))}.text-blue-400\/80{color:#60a5facc}.text-emerald-200{--tw-text-opacity: 1;color:rgb(167 243 208 / var(--tw-text-opacity, 1))}.text-fg{--tw-text-opacity: 1;color:rgb(230 232 236 / var(--tw-text-opacity, 1))}.text-fg-dim{--tw-text-opacity: 1;color:rgb(138 147 160 / var(--tw-text-opacity, 1))}.text-fg-faint{--tw-text-opacity: 1;color:rgb(84 92 104 / var(--tw-text-opacity, 1))}.text-green-300{--tw-text-opacity: 1;color:rgb(134 239 172 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-purple-400\/80{color:#c084fccc}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-400\/80{color:#f87171cc}.text-yellow-200{--tw-text-opacity: 1;color:rgb(254 240 138 / var(--tw-text-opacity, 1))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.text-yellow-500\/70{color:#eab308b3}.text-yellow-500\/80{color:#eab308cc}.text-yellow-500\/90{color:#eab308e6}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.underline-offset-2{text-underline-offset:2px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.placeholder-fg-faint::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(84 92 104 / var(--tw-placeholder-opacity, 1))}.placeholder-fg-faint::placeholder{--tw-placeholder-opacity: 1;color:rgb(84 92 104 / var(--tw-placeholder-opacity, 1))}.accent-accent{accent-color:#d97757}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-75{opacity:.75}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-red-400{--tw-ring-opacity: 1;--tw-ring-color: rgb(248 113 113 / var(--tw-ring-opacity, 1))}.ring-red-500{--tw-ring-opacity: 1;--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1))}.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)}.drop-shadow-2xl{--tw-drop-shadow: drop-shadow(0 25px 25px rgb(0 0 0 / .15));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)}.invert{--tw-invert: invert(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.\!filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[width\]{transition-property:width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-75{transition-duration:75ms}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}html,body,#root{height:100%;margin:0;overflow:hidden}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:#0b0d10}::-webkit-scrollbar-thumb{background:#242a33;border-radius:5px}::-webkit-scrollbar-thumb:hover{background:#2f3742}.placeholder\:text-fg-faint::-moz-placeholder{--tw-text-opacity: 1;color:rgb(84 92 104 / var(--tw-text-opacity, 1))}.placeholder\:text-fg-faint::placeholder{--tw-text-opacity: 1;color:rgb(84 92 104 / var(--tw-text-opacity, 1))}.hover\:border-accent:hover{--tw-border-opacity: 1;border-color:rgb(217 119 87 / var(--tw-border-opacity, 1))}.hover\:border-fg-faint:hover{--tw-border-opacity: 1;border-color:rgb(84 92 104 / var(--tw-border-opacity, 1))}.hover\:bg-accent:hover{--tw-bg-opacity: 1;background-color:rgb(217 119 87 / var(--tw-bg-opacity, 1))}.hover\:bg-accent\/25:hover{background-color:#d9775740}.hover\:bg-accent\/40:hover{background-color:#d9775766}.hover\:bg-bg:hover{--tw-bg-opacity: 1;background-color:rgb(11 13 16 / var(--tw-bg-opacity, 1))}.hover\:bg-bg-elev:hover{--tw-bg-opacity: 1;background-color:rgb(18 21 26 / var(--tw-bg-opacity, 1))}.hover\:bg-bg-elev\/20:hover{background-color:#12151a33}.hover\:bg-bg-elev\/50:hover{background-color:#12151a80}.hover\:bg-bg-hi:hover{--tw-bg-opacity: 1;background-color:rgb(26 31 39 / var(--tw-bg-opacity, 1))}.hover\:bg-bg-hi\/50:hover{background-color:#1a1f2780}.hover\:bg-transparent:hover{background-color:transparent}.hover\:bg-yellow-600:hover{--tw-bg-opacity: 1;background-color:rgb(202 138 4 / var(--tw-bg-opacity, 1))}.hover\:text-bg:hover{--tw-text-opacity: 1;color:rgb(11 13 16 / var(--tw-text-opacity, 1))}.hover\:text-fg:hover{--tw-text-opacity: 1;color:rgb(230 232 236 / var(--tw-text-opacity, 1))}.hover\:text-fg-dim:hover{--tw-text-opacity: 1;color:rgb(138 147 160 / var(--tw-text-opacity, 1))}.hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.focus\:border-fg-faint:focus{--tw-border-opacity: 1;border-color:rgb(84 92 104 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.active\:bg-accent\/60:active{background-color:#d9775799}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:opacity-100{opacity:1}
|