ccpanel 0.1.4 → 0.1.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/{chunk-HRPQYUJV.js → chunk-LZFMCC5M.js} +4 -0
- package/dist/cli.js +37 -19
- package/dist/server/app.js +1 -1
- package/package.json +1 -1
- package/web/dist/assets/index-B5vT_l-U.css +1 -0
- package/web/dist/assets/{index-DtOjAT6i.js → index-XKaR9SwA.js} +27 -30
- package/web/dist/index.html +3 -3
- package/web/dist/assets/index-D8o1BXhX.css +0 -1
|
@@ -371,6 +371,10 @@ import { z as z4 } from "zod";
|
|
|
371
371
|
function projectRoutes(deps) {
|
|
372
372
|
const app = new Hono4();
|
|
373
373
|
app.get("/", async (c) => c.json({ projects: await deps.projects.list() }));
|
|
374
|
+
app.get(
|
|
375
|
+
"/known",
|
|
376
|
+
async (c) => c.json({ projects: await deps.projects.known() })
|
|
377
|
+
);
|
|
374
378
|
app.post("/", async (c) => {
|
|
375
379
|
const { path } = z4.object({ path: z4.string().min(1) }).parse(await c.req.json());
|
|
376
380
|
return c.json({ projects: await deps.projects.add(path) });
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
assertNoConflict,
|
|
9
9
|
createApp,
|
|
10
10
|
currentMtime
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LZFMCC5M.js";
|
|
12
12
|
|
|
13
13
|
// src/cli.ts
|
|
14
14
|
import { homedir, networkInterfaces } from "os";
|
|
@@ -447,19 +447,37 @@ var SkillService = class {
|
|
|
447
447
|
};
|
|
448
448
|
|
|
449
449
|
// src/core/project-service.ts
|
|
450
|
+
import { stat as stat2 } from "fs/promises";
|
|
450
451
|
var ProjectService = class {
|
|
451
|
-
constructor(store, registryFile) {
|
|
452
|
+
constructor(store, registryFile, userClaudeJson) {
|
|
452
453
|
this.store = store;
|
|
453
454
|
this.registryFile = registryFile;
|
|
455
|
+
this.userClaudeJson = userClaudeJson;
|
|
454
456
|
}
|
|
455
457
|
store;
|
|
456
458
|
registryFile;
|
|
459
|
+
userClaudeJson;
|
|
457
460
|
async list() {
|
|
458
461
|
const data = await this.store.readJson(
|
|
459
462
|
this.registryFile
|
|
460
463
|
);
|
|
461
464
|
return data?.projects ?? [];
|
|
462
465
|
}
|
|
466
|
+
// Claude Code 在 ~/.claude.json 的 projects 键下记录所有打开过的项目路径,
|
|
467
|
+
// 作为「添加项目」的候选来源;剔除已注册与已删除的目录。
|
|
468
|
+
async known() {
|
|
469
|
+
const data = await this.store.readJson(this.userClaudeJson);
|
|
470
|
+
const registered = new Set(await this.list());
|
|
471
|
+
const out = [];
|
|
472
|
+
for (const p of Object.keys(data?.projects ?? {})) {
|
|
473
|
+
if (registered.has(p)) continue;
|
|
474
|
+
try {
|
|
475
|
+
if ((await stat2(p)).isDirectory()) out.push(p);
|
|
476
|
+
} catch {
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return out.sort();
|
|
480
|
+
}
|
|
463
481
|
async add(path) {
|
|
464
482
|
const current = await this.list();
|
|
465
483
|
if (!current.includes(path)) current.push(path);
|
|
@@ -504,12 +522,12 @@ var MemoryService = class {
|
|
|
504
522
|
};
|
|
505
523
|
|
|
506
524
|
// src/core/memory-files-service.ts
|
|
507
|
-
import { readdir as readdir3, readFile as readFile5, stat as
|
|
525
|
+
import { readdir as readdir3, readFile as readFile5, stat as stat4 } from "fs/promises";
|
|
508
526
|
import { join as join5 } from "path";
|
|
509
527
|
import matter2 from "gray-matter";
|
|
510
528
|
|
|
511
529
|
// src/core/session-service.ts
|
|
512
|
-
import { readdir as readdir2, readFile as readFile4, stat as
|
|
530
|
+
import { readdir as readdir2, readFile as readFile4, stat as stat3 } from "fs/promises";
|
|
513
531
|
import { join as join4 } from "path";
|
|
514
532
|
var MAX_BLOCK = 1e4;
|
|
515
533
|
var NOISE_PREFIXES = ["<local-command", "<command-", "<system-reminder", "Caveat:"];
|
|
@@ -608,7 +626,7 @@ var SessionService = class {
|
|
|
608
626
|
const out = [];
|
|
609
627
|
for (const name of names) {
|
|
610
628
|
const full = join4(dir, name);
|
|
611
|
-
const st = await
|
|
629
|
+
const st = await stat3(full);
|
|
612
630
|
const { firstPrompt, messageCount } = await this.summarize(full);
|
|
613
631
|
out.push({
|
|
614
632
|
id: name.replace(/\.jsonl$/, ""),
|
|
@@ -720,7 +738,7 @@ var MemoryFilesService = class {
|
|
|
720
738
|
index = await readFile5(full, "utf8");
|
|
721
739
|
continue;
|
|
722
740
|
}
|
|
723
|
-
const st = await
|
|
741
|
+
const st = await stat4(full);
|
|
724
742
|
const fm = await this.parseFront(full, name);
|
|
725
743
|
files.push({ file: name, ...fm, size: st.size, mtime: st.mtimeMs });
|
|
726
744
|
}
|
|
@@ -750,7 +768,7 @@ var MemoryFilesService = class {
|
|
|
750
768
|
};
|
|
751
769
|
|
|
752
770
|
// src/core/plugin-service.ts
|
|
753
|
-
import { readFile as readFile6, readdir as readdir4, stat as
|
|
771
|
+
import { readFile as readFile6, readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
754
772
|
import { isAbsolute as isAbsolute2, join as join6, relative as relative2, resolve as resolve3 } from "path";
|
|
755
773
|
import matter3 from "gray-matter";
|
|
756
774
|
var PluginService = class {
|
|
@@ -759,7 +777,7 @@ var PluginService = class {
|
|
|
759
777
|
}
|
|
760
778
|
store;
|
|
761
779
|
async pathExists(p) {
|
|
762
|
-
return
|
|
780
|
+
return stat5(p).then(() => true).catch(() => false);
|
|
763
781
|
}
|
|
764
782
|
// 插件元数据要尽量容错:单个文件损坏不应让整页报错(启停写入除外)。
|
|
765
783
|
async safeReadJson(file) {
|
|
@@ -1013,7 +1031,7 @@ var PluginService = class {
|
|
|
1013
1031
|
};
|
|
1014
1032
|
|
|
1015
1033
|
// src/core/codex-plugin-service.ts
|
|
1016
|
-
import { readFile as readFile7, readdir as readdir5, stat as
|
|
1034
|
+
import { readFile as readFile7, readdir as readdir5, stat as stat6 } from "fs/promises";
|
|
1017
1035
|
import { isAbsolute as isAbsolute3, join as join7, relative as relative3, resolve as resolve4 } from "path";
|
|
1018
1036
|
import matter4 from "gray-matter";
|
|
1019
1037
|
import { parse as parse2, stringify as stringify2 } from "smol-toml";
|
|
@@ -1028,7 +1046,7 @@ var CodexPluginService = class {
|
|
|
1028
1046
|
}
|
|
1029
1047
|
store;
|
|
1030
1048
|
async pathExists(p) {
|
|
1031
|
-
return
|
|
1049
|
+
return stat6(p).then(() => true).catch(() => false);
|
|
1032
1050
|
}
|
|
1033
1051
|
async readConfig(paths) {
|
|
1034
1052
|
let raw;
|
|
@@ -1260,7 +1278,7 @@ var CodexPluginService = class {
|
|
|
1260
1278
|
}
|
|
1261
1279
|
async setEnabled(paths, id, enabled, baseMtime) {
|
|
1262
1280
|
if (baseMtime !== void 0) {
|
|
1263
|
-
const st = await
|
|
1281
|
+
const st = await stat6(paths.codexConfigToml);
|
|
1264
1282
|
if (Math.abs(st.mtimeMs - baseMtime) > 1) {
|
|
1265
1283
|
throw new Error("\u914D\u7F6E\u6587\u4EF6\u5DF2\u88AB\u5176\u4ED6\u8FDB\u7A0B\u4FEE\u6539\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5");
|
|
1266
1284
|
}
|
|
@@ -1274,7 +1292,7 @@ var CodexPluginService = class {
|
|
|
1274
1292
|
|
|
1275
1293
|
// src/core/codex-memory-service.ts
|
|
1276
1294
|
import Database from "better-sqlite3";
|
|
1277
|
-
import { readFile as readFile8, readdir as readdir6, stat as
|
|
1295
|
+
import { readFile as readFile8, readdir as readdir6, stat as stat7 } from "fs/promises";
|
|
1278
1296
|
import { basename, extname, isAbsolute as isAbsolute4, join as join8, relative as relative4, resolve as resolve5 } from "path";
|
|
1279
1297
|
var CodexDataCompatibilityError = class extends Error {
|
|
1280
1298
|
constructor(message = "Codex \u8BB0\u5FC6\u6570\u636E\u5E93\u683C\u5F0F\u6682\u4E0D\u652F\u6301") {
|
|
@@ -1409,7 +1427,7 @@ var CodexMemoryService = class {
|
|
|
1409
1427
|
for (const entry of entries) {
|
|
1410
1428
|
if (!entry.isFile() || !FILE_EXTENSIONS.has(extname(entry.name))) continue;
|
|
1411
1429
|
const file = join8(paths.codexMemoriesDir, entry.name);
|
|
1412
|
-
const st = await
|
|
1430
|
+
const st = await stat7(file);
|
|
1413
1431
|
out.push({
|
|
1414
1432
|
id: `file:${entry.name}`,
|
|
1415
1433
|
name: entry.name,
|
|
@@ -1435,7 +1453,7 @@ var CodexMemoryService = class {
|
|
|
1435
1453
|
return content.replace(/\s+/g, " ").trim().slice(0, 120);
|
|
1436
1454
|
}
|
|
1437
1455
|
async exists(file) {
|
|
1438
|
-
return
|
|
1456
|
+
return stat7(file).then(() => true).catch((err) => {
|
|
1439
1457
|
if (err.code === "ENOENT") return false;
|
|
1440
1458
|
throw err;
|
|
1441
1459
|
});
|
|
@@ -1443,7 +1461,7 @@ var CodexMemoryService = class {
|
|
|
1443
1461
|
};
|
|
1444
1462
|
|
|
1445
1463
|
// src/core/codex-session-service.ts
|
|
1446
|
-
import { readdir as readdir7, readFile as readFile9, stat as
|
|
1464
|
+
import { readdir as readdir7, readFile as readFile9, stat as stat8 } from "fs/promises";
|
|
1447
1465
|
import { join as join9, resolve as resolve6 } from "path";
|
|
1448
1466
|
var MAX_BLOCK2 = 1e4;
|
|
1449
1467
|
function truncate2(s) {
|
|
@@ -1556,7 +1574,7 @@ var CodexSessionService = class {
|
|
|
1556
1574
|
return out;
|
|
1557
1575
|
}
|
|
1558
1576
|
async summarizeRollout(file) {
|
|
1559
|
-
const st = await
|
|
1577
|
+
const st = await stat8(file);
|
|
1560
1578
|
const raw = await readFile9(file, "utf8");
|
|
1561
1579
|
let id = "";
|
|
1562
1580
|
let cwd = "";
|
|
@@ -1825,7 +1843,7 @@ var AgentCommandService = class {
|
|
|
1825
1843
|
};
|
|
1826
1844
|
|
|
1827
1845
|
// src/core/sync-service.ts
|
|
1828
|
-
import { cp as cp2, lstat, mkdir as mkdir5, readlink as readlink2, rm as rm3, rmdir, stat as
|
|
1846
|
+
import { cp as cp2, lstat, mkdir as mkdir5, readlink as readlink2, rm as rm3, rmdir, stat as stat9, symlink, unlink } from "fs/promises";
|
|
1829
1847
|
import { dirname as dirname5, join as join11, resolve as resolve7 } from "path";
|
|
1830
1848
|
var SyncService = class {
|
|
1831
1849
|
agentsSkillsDir;
|
|
@@ -1879,7 +1897,7 @@ var SyncService = class {
|
|
|
1879
1897
|
assertSafeName(name);
|
|
1880
1898
|
const src = join11(this.agentsSkillsDir, name);
|
|
1881
1899
|
try {
|
|
1882
|
-
if (!(await
|
|
1900
|
+
if (!(await stat9(src)).isDirectory()) throw new Error();
|
|
1883
1901
|
} catch {
|
|
1884
1902
|
throw new Error(`\u672A\u627E\u5230\u516C\u5171 skill\u300C${name}\u300D`);
|
|
1885
1903
|
}
|
|
@@ -1961,7 +1979,7 @@ async function main() {
|
|
|
1961
1979
|
store,
|
|
1962
1980
|
mcp: new McpService(store),
|
|
1963
1981
|
skills: new SkillService(),
|
|
1964
|
-
projects: new ProjectService(store, registryFile),
|
|
1982
|
+
projects: new ProjectService(store, registryFile, join12(home, ".claude.json")),
|
|
1965
1983
|
memory: new MemoryService(),
|
|
1966
1984
|
memoryFiles: new MemoryFilesService(),
|
|
1967
1985
|
sessions: new SessionService(),
|
package/dist/server/app.js
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,: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:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,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}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.inset-0{top:0;right:0;bottom:0;left:0}.right-0{right:0}.top-0{top:0}.z-40{z-index:40}.mx-1{margin-left:.25rem;margin-right:.25rem}.mb-1{margin-bottom:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.h-40{height:10rem}.h-5{height:1.25rem}.h-full{height:100%}.min-h-0{min-height:0px}.min-h-\[2\.5rem\]{min-height:2.5rem}.min-h-screen{min-height:100vh}.w-2\/5{width:40%}.w-56{width:14rem}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0px}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-\[10rem\]{max-width:10rem}.max-w-\[14rem\]{max-width:14rem}.max-w-lg{max-width:32rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-end{justify-content:flex-end}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.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))}.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))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-600{--tw-border-opacity: 1;border-color:rgb(217 119 6 / var(--tw-border-opacity, 1))}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-violet-200{--tw-border-opacity: 1;border-color:rgb(221 214 254 / var(--tw-border-opacity, 1))}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\/30{background-color:#0000004d}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-emerald-100{--tw-bg-opacity: 1;background-color:rgb(209 250 229 / var(--tw-bg-opacity, 1))}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-violet-100{--tw-bg-opacity: 1;background-color:rgb(237 233 254 / var(--tw-bg-opacity, 1))}.bg-violet-50{--tw-bg-opacity: 1;background-color:rgb(245 243 255 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.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-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}.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-2{padding-top:.5rem;padding-bottom:.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.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-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.normal-case{text-transform:none}.italic{font-style:italic}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-violet-400{--tw-text-opacity: 1;color:rgb(167 139 250 / var(--tw-text-opacity, 1))}.text-violet-500{--tw-text-opacity: 1;color:rgb(139 92 246 / var(--tw-text-opacity, 1))}.text-violet-700{--tw-text-opacity: 1;color:rgb(109 40 217 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.opacity-70{opacity:.7}.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)}.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}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:text-red-600:hover{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:shadow:hover{--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)}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width: 640px){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-\[18rem_minmax\(0\,1fr\)\]{grid-template-columns:18rem minmax(0,1fr)}}
|