nextclaw 0.2.3 → 0.2.6
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/cli/index.js
CHANGED
|
@@ -36,6 +36,7 @@ import { join as join6, resolve } from "path";
|
|
|
36
36
|
import { spawn, spawnSync } from "child_process";
|
|
37
37
|
import { createInterface } from "readline";
|
|
38
38
|
import { fileURLToPath } from "url";
|
|
39
|
+
import { createServer } from "net";
|
|
39
40
|
|
|
40
41
|
// src/bus/queue.ts
|
|
41
42
|
var AsyncQueue = class {
|
|
@@ -2412,6 +2413,13 @@ var ChannelManager = class {
|
|
|
2412
2413
|
}
|
|
2413
2414
|
async stopAll() {
|
|
2414
2415
|
this.dispatching = false;
|
|
2416
|
+
await this.bus.publishOutbound({
|
|
2417
|
+
channel: "__control__",
|
|
2418
|
+
chatId: "",
|
|
2419
|
+
content: "",
|
|
2420
|
+
media: [],
|
|
2421
|
+
metadata: { reason: "shutdown" }
|
|
2422
|
+
});
|
|
2415
2423
|
if (this.dispatchTask) {
|
|
2416
2424
|
await this.dispatchTask;
|
|
2417
2425
|
}
|
|
@@ -2890,6 +2898,57 @@ function updateUi(configPath, patch) {
|
|
|
2890
2898
|
return next.ui;
|
|
2891
2899
|
}
|
|
2892
2900
|
|
|
2901
|
+
// src/channels/feishu-probe.ts
|
|
2902
|
+
import * as Lark2 from "@larksuiteoapi/node-sdk";
|
|
2903
|
+
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
2904
|
+
async function probeFeishu(appId, appSecret) {
|
|
2905
|
+
if (!appId || !appSecret) {
|
|
2906
|
+
return { ok: false, error: "missing credentials (appId, appSecret)" };
|
|
2907
|
+
}
|
|
2908
|
+
try {
|
|
2909
|
+
const client = new Lark2.Client({ appId, appSecret });
|
|
2910
|
+
const response = await client.request({
|
|
2911
|
+
method: "GET",
|
|
2912
|
+
url: "/open-apis/bot/v3/info",
|
|
2913
|
+
data: {}
|
|
2914
|
+
});
|
|
2915
|
+
if (!isRecord(response)) {
|
|
2916
|
+
return {
|
|
2917
|
+
ok: false,
|
|
2918
|
+
appId,
|
|
2919
|
+
error: "API error: invalid response"
|
|
2920
|
+
};
|
|
2921
|
+
}
|
|
2922
|
+
const code = typeof response.code === "number" ? response.code : null;
|
|
2923
|
+
if (code !== 0) {
|
|
2924
|
+
const msg = typeof response.msg === "string" ? response.msg : void 0;
|
|
2925
|
+
return {
|
|
2926
|
+
ok: false,
|
|
2927
|
+
appId,
|
|
2928
|
+
error: `API error: ${msg || `code ${code ?? "unknown"}`}`
|
|
2929
|
+
};
|
|
2930
|
+
}
|
|
2931
|
+
const botFromResponse = isRecord(response.bot) ? response.bot : void 0;
|
|
2932
|
+
const data = isRecord(response.data) ? response.data : void 0;
|
|
2933
|
+
const botFromData = data && isRecord(data.bot) ? data.bot : void 0;
|
|
2934
|
+
const bot = botFromResponse ?? botFromData;
|
|
2935
|
+
const botName = bot && typeof bot.bot_name === "string" ? bot.bot_name : void 0;
|
|
2936
|
+
const botOpenId = bot && typeof bot.open_id === "string" ? bot.open_id : void 0;
|
|
2937
|
+
return {
|
|
2938
|
+
ok: true,
|
|
2939
|
+
appId,
|
|
2940
|
+
botName,
|
|
2941
|
+
botOpenId
|
|
2942
|
+
};
|
|
2943
|
+
} catch (error) {
|
|
2944
|
+
return {
|
|
2945
|
+
ok: false,
|
|
2946
|
+
appId,
|
|
2947
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2948
|
+
};
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2893
2952
|
// src/ui/router.ts
|
|
2894
2953
|
function ok(data) {
|
|
2895
2954
|
return { ok: true, data };
|
|
@@ -2907,6 +2966,7 @@ async function readJson(req) {
|
|
|
2907
2966
|
}
|
|
2908
2967
|
function createUiRouter(options) {
|
|
2909
2968
|
const app = new Hono();
|
|
2969
|
+
app.notFound((c) => c.json(err("NOT_FOUND", "endpoint not found"), 404));
|
|
2910
2970
|
app.get("/api/health", (c) => c.json(ok({ status: "ok" })));
|
|
2911
2971
|
app.get("/api/config", (c) => {
|
|
2912
2972
|
const config = loadConfigOrDefault(options.configPath);
|
|
@@ -2951,6 +3011,24 @@ function createUiRouter(options) {
|
|
|
2951
3011
|
options.publish({ type: "config.updated", payload: { path: `channels.${channel}` } });
|
|
2952
3012
|
return c.json(ok(result));
|
|
2953
3013
|
});
|
|
3014
|
+
app.post("/api/channels/feishu/probe", async (c) => {
|
|
3015
|
+
const config = loadConfigOrDefault(options.configPath);
|
|
3016
|
+
const feishu = config.channels.feishu;
|
|
3017
|
+
if (!feishu?.appId || !feishu?.appSecret) {
|
|
3018
|
+
return c.json(err("MISSING_CREDENTIALS", "Feishu appId/appSecret not configured"), 400);
|
|
3019
|
+
}
|
|
3020
|
+
const result = await probeFeishu(String(feishu.appId), String(feishu.appSecret));
|
|
3021
|
+
if (!result.ok) {
|
|
3022
|
+
return c.json(err("PROBE_FAILED", result.error), 400);
|
|
3023
|
+
}
|
|
3024
|
+
return c.json(
|
|
3025
|
+
ok({
|
|
3026
|
+
appId: result.appId,
|
|
3027
|
+
botName: result.botName ?? null,
|
|
3028
|
+
botOpenId: result.botOpenId ?? null
|
|
3029
|
+
})
|
|
3030
|
+
);
|
|
3031
|
+
});
|
|
2954
3032
|
app.put("/api/config/ui", async (c) => {
|
|
2955
3033
|
const body = await readJson(c.req.raw);
|
|
2956
3034
|
if (!body.ok) {
|
|
@@ -2979,7 +3057,15 @@ function createUiRouter(options) {
|
|
|
2979
3057
|
|
|
2980
3058
|
// src/ui/server.ts
|
|
2981
3059
|
import { serveStatic } from "hono/serve-static";
|
|
2982
|
-
var DEFAULT_CORS_ORIGINS =
|
|
3060
|
+
var DEFAULT_CORS_ORIGINS = (origin) => {
|
|
3061
|
+
if (!origin) {
|
|
3062
|
+
return void 0;
|
|
3063
|
+
}
|
|
3064
|
+
if (origin.startsWith("http://localhost:") || origin.startsWith("http://127.0.0.1:")) {
|
|
3065
|
+
return origin;
|
|
3066
|
+
}
|
|
3067
|
+
return void 0;
|
|
3068
|
+
};
|
|
2983
3069
|
function startUiServer(options) {
|
|
2984
3070
|
const app = new Hono2();
|
|
2985
3071
|
const origin = options.corsOrigins ?? DEFAULT_CORS_ORIGINS;
|
|
@@ -3110,7 +3196,7 @@ program.command("ui").description(`Start the ${APP_NAME} UI with gateway`).optio
|
|
|
3110
3196
|
}
|
|
3111
3197
|
await startGateway({ uiOverrides, allowMissingProvider: true });
|
|
3112
3198
|
});
|
|
3113
|
-
program.command("start").description(`Start the ${APP_NAME} gateway + UI in the background`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server"
|
|
3199
|
+
program.command("start").description(`Start the ${APP_NAME} gateway + UI in the background`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server").option("--frontend-port <port>", "UI frontend dev server port").option("--open", "Open browser after start", false).action(async (opts) => {
|
|
3114
3200
|
const uiOverrides = {
|
|
3115
3201
|
enabled: true,
|
|
3116
3202
|
open: false
|
|
@@ -3121,6 +3207,31 @@ program.command("start").description(`Start the ${APP_NAME} gateway + UI in the
|
|
|
3121
3207
|
if (opts.uiPort) {
|
|
3122
3208
|
uiOverrides.port = Number(opts.uiPort);
|
|
3123
3209
|
}
|
|
3210
|
+
const devMode = isDevRuntime();
|
|
3211
|
+
if (devMode) {
|
|
3212
|
+
const requestedUiPort = Number.isFinite(Number(opts.uiPort)) ? Number(opts.uiPort) : 18792;
|
|
3213
|
+
const requestedFrontendPort = Number.isFinite(Number(opts.frontendPort)) ? Number(opts.frontendPort) : 5174;
|
|
3214
|
+
const uiHost = uiOverrides.host ?? "127.0.0.1";
|
|
3215
|
+
const devUiPort = await findAvailablePort(requestedUiPort, uiHost);
|
|
3216
|
+
const shouldStartFrontend = opts.frontend === void 0 ? true : Boolean(opts.frontend);
|
|
3217
|
+
const devFrontendPort = shouldStartFrontend ? await findAvailablePort(requestedFrontendPort, "127.0.0.1") : requestedFrontendPort;
|
|
3218
|
+
uiOverrides.port = devUiPort;
|
|
3219
|
+
if (requestedUiPort !== devUiPort) {
|
|
3220
|
+
console.log(`Dev mode: UI port ${requestedUiPort} is in use, switched to ${devUiPort}.`);
|
|
3221
|
+
}
|
|
3222
|
+
if (shouldStartFrontend && requestedFrontendPort !== devFrontendPort) {
|
|
3223
|
+
console.log(`Dev mode: Frontend port ${requestedFrontendPort} is in use, switched to ${devFrontendPort}.`);
|
|
3224
|
+
}
|
|
3225
|
+
console.log(`Dev mode: UI ${devUiPort}, Frontend ${devFrontendPort}`);
|
|
3226
|
+
console.log("Dev mode runs in the foreground (Ctrl+C to stop).");
|
|
3227
|
+
await runForeground({
|
|
3228
|
+
uiOverrides,
|
|
3229
|
+
frontend: shouldStartFrontend,
|
|
3230
|
+
frontendPort: devFrontendPort,
|
|
3231
|
+
open: Boolean(opts.open)
|
|
3232
|
+
});
|
|
3233
|
+
return;
|
|
3234
|
+
}
|
|
3124
3235
|
await startService({
|
|
3125
3236
|
uiOverrides,
|
|
3126
3237
|
frontend: Boolean(opts.frontend),
|
|
@@ -3128,7 +3239,7 @@ program.command("start").description(`Start the ${APP_NAME} gateway + UI in the
|
|
|
3128
3239
|
open: Boolean(opts.open)
|
|
3129
3240
|
});
|
|
3130
3241
|
});
|
|
3131
|
-
program.command("serve").description(`Run the ${APP_NAME} gateway + UI in the foreground`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server"
|
|
3242
|
+
program.command("serve").description(`Run the ${APP_NAME} gateway + UI in the foreground`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server").option("--frontend-port <port>", "UI frontend dev server port").option("--open", "Open browser after start", false).action(async (opts) => {
|
|
3132
3243
|
const uiOverrides = {
|
|
3133
3244
|
enabled: true,
|
|
3134
3245
|
open: false
|
|
@@ -3139,32 +3250,31 @@ program.command("serve").description(`Run the ${APP_NAME} gateway + UI in the fo
|
|
|
3139
3250
|
if (opts.uiPort) {
|
|
3140
3251
|
uiOverrides.port = Number(opts.uiPort);
|
|
3141
3252
|
}
|
|
3142
|
-
const
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
const shouldStartFrontend = Boolean(opts.frontend);
|
|
3146
|
-
const frontendPort = shouldStartFrontend && Number.isFinite(Number(opts.frontendPort)) ? Number(opts.frontendPort) : 5173;
|
|
3147
|
-
const frontendDir = shouldStartFrontend ? resolveUiFrontendDir() : null;
|
|
3148
|
-
let frontendUrl = null;
|
|
3149
|
-
if (shouldStartFrontend && frontendDir) {
|
|
3150
|
-
const frontend = startUiFrontend({
|
|
3151
|
-
apiBase: resolveUiApiBase(uiConfig.host, uiConfig.port),
|
|
3152
|
-
port: frontendPort,
|
|
3153
|
-
dir: frontendDir
|
|
3154
|
-
});
|
|
3155
|
-
frontendUrl = frontend?.url ?? null;
|
|
3156
|
-
} else if (shouldStartFrontend && !frontendDir) {
|
|
3157
|
-
console.log("Warning: UI frontend not found. Start it separately.");
|
|
3253
|
+
const devMode = isDevRuntime();
|
|
3254
|
+
if (devMode && uiOverrides.port === void 0) {
|
|
3255
|
+
uiOverrides.port = 18792;
|
|
3158
3256
|
}
|
|
3159
|
-
|
|
3160
|
-
|
|
3257
|
+
const shouldStartFrontend = Boolean(opts.frontend);
|
|
3258
|
+
const defaultFrontendPort = devMode ? 5174 : 5173;
|
|
3259
|
+
const requestedFrontendPort = Number.isFinite(Number(opts.frontendPort)) ? Number(opts.frontendPort) : defaultFrontendPort;
|
|
3260
|
+
if (devMode && uiOverrides.port !== void 0) {
|
|
3261
|
+
const uiHost = uiOverrides.host ?? "127.0.0.1";
|
|
3262
|
+
const uiPort = await findAvailablePort(uiOverrides.port, uiHost);
|
|
3263
|
+
if (uiPort !== uiOverrides.port) {
|
|
3264
|
+
console.log(`Dev mode: UI port ${uiOverrides.port} is in use, switched to ${uiPort}.`);
|
|
3265
|
+
uiOverrides.port = uiPort;
|
|
3266
|
+
}
|
|
3161
3267
|
}
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
console.log("Warning: UI frontend not started. Browser not opened.");
|
|
3268
|
+
const frontendPort = devMode && shouldStartFrontend ? await findAvailablePort(requestedFrontendPort, "127.0.0.1") : requestedFrontendPort;
|
|
3269
|
+
if (devMode && shouldStartFrontend && frontendPort !== requestedFrontendPort) {
|
|
3270
|
+
console.log(`Dev mode: Frontend port ${requestedFrontendPort} is in use, switched to ${frontendPort}.`);
|
|
3166
3271
|
}
|
|
3167
|
-
await
|
|
3272
|
+
await runForeground({
|
|
3273
|
+
uiOverrides,
|
|
3274
|
+
frontend: shouldStartFrontend,
|
|
3275
|
+
frontendPort,
|
|
3276
|
+
open: Boolean(opts.open)
|
|
3277
|
+
});
|
|
3168
3278
|
});
|
|
3169
3279
|
program.command("stop").description(`Stop the ${APP_NAME} background service`).action(async () => {
|
|
3170
3280
|
await stopService();
|
|
@@ -3341,7 +3451,7 @@ async function startGateway(options = {}) {
|
|
|
3341
3451
|
const cronStorePath = join6(getDataDir(), "cron", "jobs.json");
|
|
3342
3452
|
const cron2 = new CronService(cronStorePath);
|
|
3343
3453
|
const uiConfig = resolveUiConfig(config, options.uiOverrides);
|
|
3344
|
-
const uiStaticDir = options.uiStaticDir
|
|
3454
|
+
const uiStaticDir = options.uiStaticDir === void 0 ? resolveUiStaticDir() : options.uiStaticDir;
|
|
3345
3455
|
if (!provider) {
|
|
3346
3456
|
if (uiConfig.enabled) {
|
|
3347
3457
|
const uiServer = startUiServer({
|
|
@@ -3403,7 +3513,25 @@ async function startGateway(options = {}) {
|
|
|
3403
3513
|
30 * 60,
|
|
3404
3514
|
true
|
|
3405
3515
|
);
|
|
3406
|
-
|
|
3516
|
+
let channels2 = new ChannelManager(config, bus, sessionManager);
|
|
3517
|
+
let reloadTask = null;
|
|
3518
|
+
const reloadChannels = async () => {
|
|
3519
|
+
if (reloadTask) {
|
|
3520
|
+
await reloadTask;
|
|
3521
|
+
return;
|
|
3522
|
+
}
|
|
3523
|
+
reloadTask = (async () => {
|
|
3524
|
+
const nextConfig = loadConfig();
|
|
3525
|
+
await channels2.stopAll();
|
|
3526
|
+
channels2 = new ChannelManager(nextConfig, bus, sessionManager);
|
|
3527
|
+
await channels2.startAll();
|
|
3528
|
+
})();
|
|
3529
|
+
try {
|
|
3530
|
+
await reloadTask;
|
|
3531
|
+
} finally {
|
|
3532
|
+
reloadTask = null;
|
|
3533
|
+
}
|
|
3534
|
+
};
|
|
3407
3535
|
if (channels2.enabledChannels.length) {
|
|
3408
3536
|
console.log(`\u2713 Channels enabled: ${channels2.enabledChannels.join(", ")}`);
|
|
3409
3537
|
} else {
|
|
@@ -3416,7 +3544,7 @@ async function startGateway(options = {}) {
|
|
|
3416
3544
|
configPath: getConfigPath(),
|
|
3417
3545
|
staticDir: uiStaticDir ?? void 0,
|
|
3418
3546
|
onReload: async () => {
|
|
3419
|
-
|
|
3547
|
+
await reloadChannels();
|
|
3420
3548
|
}
|
|
3421
3549
|
});
|
|
3422
3550
|
const uiUrl = `http://${uiServer.host}:${uiServer.port}`;
|
|
@@ -3445,6 +3573,83 @@ function resolveUiApiBase(host, port) {
|
|
|
3445
3573
|
const normalizedHost = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
|
|
3446
3574
|
return `http://${normalizedHost}:${port}`;
|
|
3447
3575
|
}
|
|
3576
|
+
function isDevRuntime() {
|
|
3577
|
+
return import.meta.url.includes("/src/cli/") || process.env.NEXTCLAW_DEV === "1";
|
|
3578
|
+
}
|
|
3579
|
+
function normalizeHostForPortCheck(host) {
|
|
3580
|
+
return host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
|
|
3581
|
+
}
|
|
3582
|
+
async function findAvailablePort(port, host, attempts = 20) {
|
|
3583
|
+
const basePort = Number.isFinite(port) ? port : 0;
|
|
3584
|
+
let candidate = basePort;
|
|
3585
|
+
for (let i = 0; i < attempts; i += 1) {
|
|
3586
|
+
const ok2 = await isPortAvailable(candidate, host);
|
|
3587
|
+
if (ok2) {
|
|
3588
|
+
return candidate;
|
|
3589
|
+
}
|
|
3590
|
+
candidate += 1;
|
|
3591
|
+
}
|
|
3592
|
+
return basePort;
|
|
3593
|
+
}
|
|
3594
|
+
async function isPortAvailable(port, host) {
|
|
3595
|
+
const checkHost = normalizeHostForPortCheck(host);
|
|
3596
|
+
const hostsToCheck = [checkHost];
|
|
3597
|
+
if (checkHost === "127.0.0.1") {
|
|
3598
|
+
hostsToCheck.push("::1");
|
|
3599
|
+
} else if (checkHost === "::1") {
|
|
3600
|
+
hostsToCheck.push("127.0.0.1");
|
|
3601
|
+
}
|
|
3602
|
+
for (const hostToCheck of hostsToCheck) {
|
|
3603
|
+
const ok2 = await canBindPort(port, hostToCheck);
|
|
3604
|
+
if (!ok2) {
|
|
3605
|
+
return false;
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
return true;
|
|
3609
|
+
}
|
|
3610
|
+
async function canBindPort(port, host) {
|
|
3611
|
+
return await new Promise((resolve2) => {
|
|
3612
|
+
const server = createServer();
|
|
3613
|
+
server.unref();
|
|
3614
|
+
server.once("error", () => resolve2(false));
|
|
3615
|
+
server.listen({ port, host }, () => {
|
|
3616
|
+
server.close(() => resolve2(true));
|
|
3617
|
+
});
|
|
3618
|
+
});
|
|
3619
|
+
}
|
|
3620
|
+
async function runForeground(options) {
|
|
3621
|
+
const config = loadConfig();
|
|
3622
|
+
const uiConfig = resolveUiConfig(config, options.uiOverrides);
|
|
3623
|
+
const shouldStartFrontend = options.frontend;
|
|
3624
|
+
const frontendPort = Number.isFinite(options.frontendPort) ? options.frontendPort : 5173;
|
|
3625
|
+
const frontendDir = shouldStartFrontend ? resolveUiFrontendDir() : null;
|
|
3626
|
+
const staticDir = resolveUiStaticDir();
|
|
3627
|
+
let frontendUrl = null;
|
|
3628
|
+
if (shouldStartFrontend && frontendDir) {
|
|
3629
|
+
const frontend = startUiFrontend({
|
|
3630
|
+
apiBase: resolveUiApiBase(uiConfig.host, uiConfig.port),
|
|
3631
|
+
port: frontendPort,
|
|
3632
|
+
dir: frontendDir
|
|
3633
|
+
});
|
|
3634
|
+
frontendUrl = frontend?.url ?? null;
|
|
3635
|
+
} else if (shouldStartFrontend && !frontendDir) {
|
|
3636
|
+
console.log("Warning: UI frontend not found. Start it separately.");
|
|
3637
|
+
}
|
|
3638
|
+
if (!frontendUrl && staticDir) {
|
|
3639
|
+
frontendUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
|
|
3640
|
+
}
|
|
3641
|
+
if (options.open && frontendUrl) {
|
|
3642
|
+
openBrowser(frontendUrl);
|
|
3643
|
+
} else if (options.open && !frontendUrl) {
|
|
3644
|
+
console.log("Warning: UI frontend not started. Browser not opened.");
|
|
3645
|
+
}
|
|
3646
|
+
const uiStaticDir = shouldStartFrontend && frontendDir ? null : staticDir;
|
|
3647
|
+
await startGateway({
|
|
3648
|
+
uiOverrides: options.uiOverrides,
|
|
3649
|
+
allowMissingProvider: true,
|
|
3650
|
+
uiStaticDir
|
|
3651
|
+
});
|
|
3652
|
+
}
|
|
3448
3653
|
async function startService(options) {
|
|
3449
3654
|
const config = loadConfig();
|
|
3450
3655
|
const uiConfig = resolveUiConfig(config, options.uiOverrides);
|
|
@@ -3787,7 +3992,10 @@ function startUiFrontend(options) {
|
|
|
3787
3992
|
}
|
|
3788
3993
|
const args = [...runner.args];
|
|
3789
3994
|
if (options.port) {
|
|
3790
|
-
|
|
3995
|
+
if (runner.useArgSeparator) {
|
|
3996
|
+
args.push("--");
|
|
3997
|
+
}
|
|
3998
|
+
args.push("--port", String(options.port));
|
|
3791
3999
|
}
|
|
3792
4000
|
const env = { ...process.env, VITE_API_BASE: options.apiBase };
|
|
3793
4001
|
const child = spawn(runner.cmd, args, { cwd: uiDir, stdio: "inherit", env });
|
|
@@ -3802,10 +4010,10 @@ function startUiFrontend(options) {
|
|
|
3802
4010
|
}
|
|
3803
4011
|
function resolveUiFrontendRunner() {
|
|
3804
4012
|
if (which("pnpm")) {
|
|
3805
|
-
return { cmd: "pnpm", args: ["dev"] };
|
|
4013
|
+
return { cmd: "pnpm", args: ["dev"], useArgSeparator: false };
|
|
3806
4014
|
}
|
|
3807
4015
|
if (which("npm")) {
|
|
3808
|
-
return { cmd: "npm", args: ["run", "dev"] };
|
|
4016
|
+
return { cmd: "npm", args: ["run", "dev"], useArgSeparator: true };
|
|
3809
4017
|
}
|
|
3810
4018
|
return null;
|
|
3811
4019
|
}
|
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}:root{--background: 40 20% 98%;--foreground: 30 15% 10%;--card: 0 0% 100%;--card-foreground: 30 15% 10%;--popover: 0 0% 100%;--popover-foreground: 30 15% 10%;--primary: 30 15% 10%;--primary-foreground: 0 0% 100%;--secondary: 40 10% 94%;--secondary-foreground: 30 15% 10%;--muted: 40 10% 94%;--muted-foreground: 30 8% 45%;--accent: 40 10% 92%;--accent-foreground: 30 15% 10%;--destructive: 0 84% 60%;--destructive-foreground: 0 0% 98%;--border: 40 10% 92%;--input: 40 10% 92%;--ring: 30 15% 10%;--radius: 1.25rem;--milk-50: 40 20% 98%;--milk-100: 40 15% 96%;--milk-200: 40 12% 92%;--milk-300: 40 10% 88%;--milk-400: 40 8% 70%;--milk-500: 30 8% 45%;--milk-600: 30 10% 35%;--milk-700: 30 12% 25%;--milk-800: 30 15% 15%;--milk-900: 30 20% 8%}*{border-color:hsl(var(--border));outline:2px solid transparent;outline-offset:2px;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;animation-duration:.2s}html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{background-color:hsl(var(--background));color:hsl(var(--foreground));font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;overflow:hidden}*{scrollbar-width:thin;scrollbar-color:hsl(var(--warm-gray-300)) transparent}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.bottom-0{bottom:0}.left-0{left:0}.left-\[50\%\]{left:50%}.right-0{right:0}.right-1\.5{right:.375rem}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-1\.5{top:.375rem}.top-1\/2{top:50%}.top-4{top:1rem}.top-\[50\%\]{top:50%}.z-10{z-index:10}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-10{margin-bottom:2.5rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-auto{margin-top:auto}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[180px\]{height:180px}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[85vh\]{max-height:85vh}.min-h-\[42px\]{min-height:42px}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-20{width:5rem}.w-24{width:6rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-40{width:10rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[160px\]{width:160px}.w-\[240px\]{width:240px}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[100px\]{min-width:100px}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-\[200px\]{max-width:200px}.max-w-lg{max-width:32rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -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{--tw-translate-x: 0px;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-5{--tw-translate-x: 1.25rem;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-\[-50\%\]{--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-y-\[-50\%\]{--tw-translate-y: -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))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.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-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-12{gap:3rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-8{gap:2rem}.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-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * 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-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.625rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem * 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))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-\[1\.5rem\]{border-radius:1.5rem}.rounded-\[2\.5rem\]{border-radius:2.5rem}.rounded-\[2rem\]{border-radius:2rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-0{border-width:0px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-\[hsl\(40\,10\%\,92\%\)\]{--tw-border-opacity: 1;border-color:hsl(40 10% 92% / var(--tw-border-opacity, 1))}.border-\[hsl\(40\,10\%\,94\%\)\]{--tw-border-opacity: 1;border-color:hsl(40 10% 94% / var(--tw-border-opacity, 1))}.border-\[hsl\(40\,20\%\,90\%\)\]{--tw-border-opacity: 1;border-color:hsl(40 20% 90% / var(--tw-border-opacity, 1))}.border-input{border-color:hsl(var(--input))}.border-transparent{border-color:transparent}.bg-\[hsl\(30\,15\%\,10\%\)\]{--tw-bg-opacity: 1;background-color:hsl(30 15% 10% / var(--tw-bg-opacity, 1))}.bg-\[hsl\(30\,8\%\,55\%\)\]{--tw-bg-opacity: 1;background-color:hsl(30 8% 55% / var(--tw-bg-opacity, 1))}.bg-\[hsl\(40\,10\%\,92\%\)\]{--tw-bg-opacity: 1;background-color:hsl(40 10% 92% / var(--tw-bg-opacity, 1))}.bg-\[hsl\(40\,10\%\,98\%\)\]{--tw-bg-opacity: 1;background-color:hsl(40 10% 98% / var(--tw-bg-opacity, 1))}.bg-\[hsl\(40\,20\%\,94\%\)\]{--tw-bg-opacity: 1;background-color:hsl(40 20% 94% / var(--tw-bg-opacity, 1))}.bg-\[hsl\(40\,20\%\,96\%\)\]{--tw-bg-opacity: 1;background-color:hsl(40 20% 96% / var(--tw-bg-opacity, 1))}.bg-\[hsl\(40\,20\%\,98\%\)\]{--tw-bg-opacity: 1;background-color:hsl(40 20% 98% / var(--tw-bg-opacity, 1))}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-background{background-color:hsl(var(--background))}.bg-black\/50{background-color:#00000080}.bg-destructive{background-color:hsl(var(--destructive))}.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-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-input{background-color:hsl(var(--input))}.bg-muted{background-color:hsl(var(--muted))}.bg-orange-500{--tw-bg-opacity: 1;background-color:rgb(249 115 22 / var(--tw-bg-opacity, 1))}.bg-primary{background-color:hsl(var(--primary))}.bg-secondary{background-color:hsl(var(--secondary))}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/80{background-color:#fffc}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-l{background-image:linear-gradient(to left,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-emerald-400{--tw-gradient-from: #34d399 var(--tw-gradient-from-position);--tw-gradient-to: rgb(52 211 153 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-orange-400{--tw-gradient-from: #fb923c var(--tw-gradient-from-position);--tw-gradient-to: rgb(251 146 60 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-purple-400{--tw-gradient-from: #c084fc var(--tw-gradient-from-position);--tw-gradient-to: rgb(192 132 252 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-rose-400{--tw-gradient-from: #fb7185 var(--tw-gradient-from-position);--tw-gradient-to: rgb(251 113 133 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-sky-400{--tw-gradient-from: #38bdf8 var(--tw-gradient-from-position);--tw-gradient-to: rgb(56 189 248 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-slate-400{--tw-gradient-from: #94a3b8 var(--tw-gradient-from-position);--tw-gradient-to: rgb(148 163 184 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-transparent{--tw-gradient-from: transparent var(--tw-gradient-from-position);--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-amber-500{--tw-gradient-to: #f59e0b var(--tw-gradient-to-position)}.to-blue-500{--tw-gradient-to: #3b82f6 var(--tw-gradient-to-position)}.to-emerald-600{--tw-gradient-to: #059669 var(--tw-gradient-to-position)}.to-gray-500{--tw-gradient-to: #6b7280 var(--tw-gradient-to-position)}.to-indigo-500{--tw-gradient-to: #6366f1 var(--tw-gradient-to-position)}.to-pink-500{--tw-gradient-to: #ec4899 var(--tw-gradient-to-position)}.to-white\/10{--tw-gradient-to: rgb(255 255 255 / .1) var(--tw-gradient-to-position)}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.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}.px-8{padding-left:2rem;padding-right:2rem}.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}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-20{padding-bottom:5rem}.pb-4{padding-bottom:1rem}.pr-2{padding-right:.5rem}.pr-20{padding-right:5rem}.pt-0{padding-top:0}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.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-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-\[hsl\(30\,10\%\,35\%\)\]{--tw-text-opacity: 1;color:hsl(30 10% 35% / var(--tw-text-opacity, 1))}.text-\[hsl\(30\,15\%\,10\%\)\]{--tw-text-opacity: 1;color:hsl(30 15% 10% / var(--tw-text-opacity, 1))}.text-\[hsl\(30\,20\%\,12\%\)\]{--tw-text-opacity: 1;color:hsl(30 20% 12% / var(--tw-text-opacity, 1))}.text-\[hsl\(30\,8\%\,45\%\)\]{--tw-text-opacity: 1;color:hsl(30 8% 45% / var(--tw-text-opacity, 1))}.text-\[hsl\(30\,8\%\,55\%\)\]{--tw-text-opacity: 1;color:hsl(30 8% 55% / var(--tw-text-opacity, 1))}.text-\[hsl\(30\,8\%\,65\%\)\]{--tw-text-opacity: 1;color:hsl(30 8% 65% / var(--tw-text-opacity, 1))}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-destructive-foreground{color:hsl(var(--destructive-foreground))}.text-emerald-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-foreground{color:hsl(var(--foreground))}.text-muted-foreground{color:hsl(var(--muted-foreground))}.text-primary{color:hsl(var(--primary))}.text-primary-foreground{color:hsl(var(--primary-foreground))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-secondary-foreground{color:hsl(var(--secondary-foreground))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline-offset-4{text-underline-offset:4px}.accent-\[hsl\(30\,15\%\,10\%\)\]{accent-color:hsl(30,15%,10%)}.opacity-0{opacity:0}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.mix-blend-multiply{mix-blend-mode:multiply}.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-\[0_0_8px_rgba\(16\,185\,129\,0\.5\)\]{--tw-shadow: 0 0 8px rgba(16,185,129,.5);--tw-shadow-colored: 0 0 8px 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-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px 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-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 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}.outline{outline-style:solid}.ring-0{--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(0px + 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-offset-background{--tw-ring-offset-color: hsl(var(--background))}.ring-offset-white{--tw-ring-offset-color: #fff}.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-md{--tw-backdrop-blur: blur(12px);-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-all{transition-property:all;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-300{transition-duration:.3s}.duration-500{transition-duration:.5s}@keyframes enter{0%{opacity:var(--tw-enter-opacity, 1);transform:translate3d(var(--tw-enter-translate-x, 0),var(--tw-enter-translate-y, 0),0) scale3d(var(--tw-enter-scale, 1),var(--tw-enter-scale, 1),var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity, 1);transform:translate3d(var(--tw-exit-translate-x, 0),var(--tw-exit-translate-y, 0),0) scale3d(var(--tw-exit-scale, 1),var(--tw-exit-scale, 1),var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))}}.animate-in{animation-name:enter;animation-duration:.15s;--tw-enter-opacity: initial;--tw-enter-scale: initial;--tw-enter-rotate: initial;--tw-enter-translate-x: initial;--tw-enter-translate-y: initial}.fade-in{--tw-enter-opacity: 0}.slide-in-from-left-2{--tw-enter-translate-x: -.5rem}.duration-200{animation-duration:.2s}.duration-300{animation-duration:.3s}.duration-500{animation-duration:.5s}.custom-scrollbar::-webkit-scrollbar{width:6px;height:6px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background:hsl(var(--warm-gray-300));border-radius:6px}.custom-scrollbar::-webkit-scrollbar-thumb:hover{background:hsl(var(--warm-gray-400))}@keyframes fadeIn{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes slideIn{0%{opacity:0;transform:translate(-12px)}to{opacity:1;transform:translate(0)}}@keyframes scaleIn{0%{opacity:0;transform:scale(.97)}to{opacity:1;transform:scale(1)}}@keyframes pulse-soft{0%,to{opacity:1}50%{opacity:.8}}.animate-fade-in{animation:fadeIn .4s cubic-bezier(.16,1,.3,1) forwards}.animate-slide-in{animation:slideIn .35s cubic-bezier(.16,1,.3,1) forwards}.animate-scale-in{animation:scaleIn .35s cubic-bezier(.16,1,.3,1) forwards}.animate-pulse-soft{animation:pulse-soft 3s ease-in-out infinite}.file\:border-0::file-selector-button{border-width:0px}.file\:bg-transparent::file-selector-button{background-color:transparent}.file\:text-sm::file-selector-button{font-size:.875rem;line-height:1.25rem}.file\:font-medium::file-selector-button{font-weight:500}.placeholder\:text-muted-foreground::-moz-placeholder{color:hsl(var(--muted-foreground))}.placeholder\:text-muted-foreground::placeholder{color:hsl(var(--muted-foreground))}.hover\:border-\[hsl\(40\,10\%\,94\%\)\]:hover{--tw-border-opacity: 1;border-color:hsl(40 10% 94% / var(--tw-border-opacity, 1))}.hover\:bg-\[hsl\(30\,15\%\,20\%\)\]:hover{--tw-bg-opacity: 1;background-color:hsl(30 15% 20% / var(--tw-bg-opacity, 1))}.hover\:bg-\[hsl\(40\,10\%\,90\%\)\]:hover{--tw-bg-opacity: 1;background-color:hsl(40 10% 90% / var(--tw-bg-opacity, 1))}.hover\:bg-\[hsl\(40\,10\%\,94\%\)\]:hover{--tw-bg-opacity: 1;background-color:hsl(40 10% 94% / var(--tw-bg-opacity, 1))}.hover\:bg-\[hsl\(40\,10\%\,96\%\)\]:hover{--tw-bg-opacity: 1;background-color:hsl(40 10% 96% / var(--tw-bg-opacity, 1))}.hover\:bg-\[hsl\(40\,20\%\,94\%\)\]:hover{--tw-bg-opacity: 1;background-color:hsl(40 20% 94% / var(--tw-bg-opacity, 1))}.hover\:bg-\[hsl\(40\,20\%\,96\%\)\]:hover{--tw-bg-opacity: 1;background-color:hsl(40 20% 96% / var(--tw-bg-opacity, 1))}.hover\:bg-accent:hover{background-color:hsl(var(--accent))}.hover\:bg-background\/50:hover{background-color:hsl(var(--background) / .5)}.hover\:bg-destructive\/90:hover{background-color:hsl(var(--destructive) / .9)}.hover\:bg-primary\/90:hover{background-color:hsl(var(--primary) / .9)}.hover\:bg-secondary\/80:hover{background-color:hsl(var(--secondary) / .8)}.hover\:from-emerald-500:hover{--tw-gradient-from: #10b981 var(--tw-gradient-from-position);--tw-gradient-to: rgb(16 185 129 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:from-orange-500:hover{--tw-gradient-from: #f97316 var(--tw-gradient-from-position);--tw-gradient-to: rgb(249 115 22 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:to-amber-600:hover{--tw-gradient-to: #d97706 var(--tw-gradient-to-position)}.hover\:to-emerald-700:hover{--tw-gradient-to: #047857 var(--tw-gradient-to-position)}.hover\:text-\[hsl\(30\,15\%\,10\%\)\]:hover{--tw-text-opacity: 1;color:hsl(30 15% 10% / var(--tw-text-opacity, 1))}.hover\:text-\[hsl\(30\,20\%\,12\%\)\]:hover{--tw-text-opacity: 1;color:hsl(30 20% 12% / var(--tw-text-opacity, 1))}.hover\:text-accent-foreground:hover{color:hsl(var(--accent-foreground))}.hover\:text-red-300:hover{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-premium:hover{box-shadow:0 10px 30px -10px #00000014,0 4px 10px -4px #0000000a}.focus\:bg-white:focus{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--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)}.focus\:ring-2:focus{--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)}.focus\:ring-\[hsl\(25\,95\%\,53\%\)\]:focus{--tw-ring-opacity: 1;--tw-ring-color: hsl(25 95% 53% / var(--tw-ring-opacity, 1))}.focus\:ring-\[hsl\(30\,15\%\,10\%\)\]:focus{--tw-ring-opacity: 1;--tw-ring-color: hsl(30 15% 10% / var(--tw-ring-opacity, 1))}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--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)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color: hsl(var(--ring))}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width: 2px}.focus-visible\:ring-offset-background:focus-visible{--tw-ring-offset-color: hsl(var(--background))}.active\:scale-95:active{--tw-scale-x: .95;--tw-scale-y: .95;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))}.active\:scale-\[0\.98\]:active{--tw-scale-x: .98;--tw-scale-y: .98;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))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:scale-105{--tw-scale-x: 1.05;--tw-scale-y: 1.05;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))}.group:hover .group-hover\:scale-110{--tw-scale-x: 1.1;--tw-scale-y: 1.1;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))}.group:hover .group-hover\:text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:opacity-100{opacity:1}.peer:disabled~.peer-disabled\:cursor-not-allowed{cursor:not-allowed}.peer:disabled~.peer-disabled\:opacity-70{opacity:.7}.data-\[state\=checked\]\:bg-emerald-500[data-state=checked]{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.data-\[state\=open\]\:bg-\[hsl\(40\,20\%\,96\%\)\][data-state=open]{--tw-bg-opacity: 1;background-color:hsl(40 20% 96% / var(--tw-bg-opacity, 1))}.data-\[state\=open\]\:text-\[hsl\(30\,8\%\,45\%\)\][data-state=open]{--tw-text-opacity: 1;color:hsl(30 8% 45% / var(--tw-text-opacity, 1))}.data-\[state\=open\]\:animate-in[data-state=open]{animation-name:enter;animation-duration:.15s;--tw-enter-opacity: initial;--tw-enter-scale: initial;--tw-enter-rotate: initial;--tw-enter-translate-x: initial;--tw-enter-translate-y: initial}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation-name:exit;animation-duration:.15s;--tw-exit-opacity: initial;--tw-exit-scale: initial;--tw-exit-rotate: initial;--tw-exit-translate-x: initial;--tw-exit-translate-y: initial}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity: 0}.data-\[state\=open\]\:fade-in-0[data-state=open]{--tw-enter-opacity: 0}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale: .95}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale: .95}.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state=closed]{--tw-exit-translate-x: -50%}.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed]{--tw-exit-translate-y: -48%}.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state=open]{--tw-enter-translate-x: -50%}.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open]{--tw-enter-translate-y: -48%}@media(min-width:640px){.sm\:inline-flex{display:inline-flex}.sm\:max-w-\[500px\]{max-width:500px}.sm\:max-w-\[550px\]{max-width:550px}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}.sm\:gap-2{gap:.5rem}.sm\:text-left{text-align:left}}@media(min-width:768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}
|