kiro-memory 1.9.0 → 2.1.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.
@@ -4,14 +4,15 @@ import { createRequire } from 'module';const require = createRequire(import.meta
4
4
  import BetterSqlite3 from "better-sqlite3";
5
5
  var Database = class {
6
6
  _db;
7
+ _stmtCache = /* @__PURE__ */ new Map();
7
8
  constructor(path, options) {
8
9
  this._db = new BetterSqlite3(path, {
9
- // better-sqlite3 crea il file di default (non serve 'create')
10
+ // better-sqlite3 creates the file by default ('create' not needed)
10
11
  readonly: options?.readwrite === false ? true : false
11
12
  });
12
13
  }
13
14
  /**
14
- * Esegui una query SQL senza risultati
15
+ * Execute a SQL query without results
15
16
  */
16
17
  run(sql, params) {
17
18
  const stmt = this._db.prepare(sql);
@@ -19,51 +20,53 @@ var Database = class {
19
20
  return result;
20
21
  }
21
22
  /**
22
- * Prepara una query con interfaccia compatibile bun:sqlite
23
+ * Prepare a query with bun:sqlite-compatible interface.
24
+ * Returns a cached prepared statement for repeated queries.
23
25
  */
24
26
  query(sql) {
25
- return new BunQueryCompat(this._db, sql);
27
+ let cached = this._stmtCache.get(sql);
28
+ if (!cached) {
29
+ cached = new BunQueryCompat(this._db, sql);
30
+ this._stmtCache.set(sql, cached);
31
+ }
32
+ return cached;
26
33
  }
27
34
  /**
28
- * Crea una transazione
35
+ * Create a transaction
29
36
  */
30
37
  transaction(fn) {
31
38
  return this._db.transaction(fn);
32
39
  }
33
40
  /**
34
- * Chiudi la connessione
41
+ * Close the connection
35
42
  */
36
43
  close() {
44
+ this._stmtCache.clear();
37
45
  this._db.close();
38
46
  }
39
47
  };
40
48
  var BunQueryCompat = class {
41
- _db;
42
- _sql;
49
+ _stmt;
43
50
  constructor(db, sql) {
44
- this._db = db;
45
- this._sql = sql;
51
+ this._stmt = db.prepare(sql);
46
52
  }
47
53
  /**
48
- * Restituisce tutte le righe
54
+ * Returns all rows
49
55
  */
50
56
  all(...params) {
51
- const stmt = this._db.prepare(this._sql);
52
- return params.length > 0 ? stmt.all(...params) : stmt.all();
57
+ return params.length > 0 ? this._stmt.all(...params) : this._stmt.all();
53
58
  }
54
59
  /**
55
- * Restituisce la prima riga o null
60
+ * Returns the first row or null
56
61
  */
57
62
  get(...params) {
58
- const stmt = this._db.prepare(this._sql);
59
- return params.length > 0 ? stmt.get(...params) : stmt.get();
63
+ return params.length > 0 ? this._stmt.get(...params) : this._stmt.get();
60
64
  }
61
65
  /**
62
- * Esegui senza risultati
66
+ * Execute without results
63
67
  */
64
68
  run(...params) {
65
- const stmt = this._db.prepare(this._sql);
66
- return params.length > 0 ? stmt.run(...params) : stmt.run();
69
+ return params.length > 0 ? this._stmt.run(...params) : this._stmt.run();
67
70
  }
68
71
  };
69
72
 
@@ -324,150 +327,63 @@ function ensureDir(dirPath) {
324
327
  // src/services/sqlite/Database.ts
325
328
  var SQLITE_MMAP_SIZE_BYTES = 256 * 1024 * 1024;
326
329
  var SQLITE_CACHE_SIZE_PAGES = 1e4;
327
- var dbInstance = null;
328
330
  var KiroMemoryDatabase = class {
329
- db;
331
+ _db;
330
332
  /**
331
- * @param dbPath - Percorso al file SQLite (default: DB_PATH)
332
- * @param skipMigrations - Se true, salta il migration runner (per hook ad alta frequenza)
333
+ * Readonly accessor for the underlying Database instance.
334
+ * Prefer using query() and run() proxy methods directly.
335
+ */
336
+ get db() {
337
+ return this._db;
338
+ }
339
+ /**
340
+ * @param dbPath - Path to the SQLite file (default: DB_PATH)
341
+ * @param skipMigrations - If true, skip the migration runner (for high-frequency hooks)
333
342
  */
334
343
  constructor(dbPath = DB_PATH, skipMigrations = false) {
335
344
  if (dbPath !== ":memory:") {
336
345
  ensureDir(DATA_DIR);
337
346
  }
338
- this.db = new Database(dbPath, { create: true, readwrite: true });
339
- this.db.run("PRAGMA journal_mode = WAL");
340
- this.db.run("PRAGMA synchronous = NORMAL");
341
- this.db.run("PRAGMA foreign_keys = ON");
342
- this.db.run("PRAGMA temp_store = memory");
343
- this.db.run(`PRAGMA mmap_size = ${SQLITE_MMAP_SIZE_BYTES}`);
344
- this.db.run(`PRAGMA cache_size = ${SQLITE_CACHE_SIZE_PAGES}`);
347
+ this._db = new Database(dbPath, { create: true, readwrite: true });
348
+ this._db.run("PRAGMA journal_mode = WAL");
349
+ this._db.run("PRAGMA busy_timeout = 5000");
350
+ this._db.run("PRAGMA synchronous = NORMAL");
351
+ this._db.run("PRAGMA foreign_keys = ON");
352
+ this._db.run("PRAGMA temp_store = memory");
353
+ this._db.run(`PRAGMA mmap_size = ${SQLITE_MMAP_SIZE_BYTES}`);
354
+ this._db.run(`PRAGMA cache_size = ${SQLITE_CACHE_SIZE_PAGES}`);
345
355
  if (!skipMigrations) {
346
- const migrationRunner = new MigrationRunner(this.db);
356
+ const migrationRunner = new MigrationRunner(this._db);
347
357
  migrationRunner.runAllMigrations();
348
358
  }
349
359
  }
350
360
  /**
351
- * Esegue una funzione all'interno di una transazione atomica.
352
- * Se fn() lancia un errore, la transazione viene annullata automaticamente.
353
- */
354
- withTransaction(fn) {
355
- const transaction = this.db.transaction(fn);
356
- return transaction(this.db);
357
- }
358
- /**
359
- * Close the database connection
360
- */
361
- close() {
362
- this.db.close();
363
- }
364
- };
365
- var DatabaseManager = class _DatabaseManager {
366
- static instance;
367
- db = null;
368
- migrations = [];
369
- static getInstance() {
370
- if (!_DatabaseManager.instance) {
371
- _DatabaseManager.instance = new _DatabaseManager();
372
- }
373
- return _DatabaseManager.instance;
374
- }
375
- /**
376
- * Register a migration to be run during initialization
377
- */
378
- registerMigration(migration) {
379
- this.migrations.push(migration);
380
- this.migrations.sort((a, b) => a.version - b.version);
381
- }
382
- /**
383
- * Initialize database connection with optimized settings
361
+ * Prepare a query (delegates to underlying Database).
362
+ * Proxy method to avoid ctx.db.db.query() double access.
384
363
  */
385
- async initialize() {
386
- if (this.db) {
387
- return this.db;
388
- }
389
- ensureDir(DATA_DIR);
390
- this.db = new Database(DB_PATH, { create: true, readwrite: true });
391
- this.db.run("PRAGMA journal_mode = WAL");
392
- this.db.run("PRAGMA synchronous = NORMAL");
393
- this.db.run("PRAGMA foreign_keys = ON");
394
- this.db.run("PRAGMA temp_store = memory");
395
- this.db.run(`PRAGMA mmap_size = ${SQLITE_MMAP_SIZE_BYTES}`);
396
- this.db.run(`PRAGMA cache_size = ${SQLITE_CACHE_SIZE_PAGES}`);
397
- this.initializeSchemaVersions();
398
- await this.runMigrations();
399
- dbInstance = this.db;
400
- return this.db;
364
+ query(sql) {
365
+ return this._db.query(sql);
401
366
  }
402
367
  /**
403
- * Get the current database connection
368
+ * Execute a SQL statement without results (delegates to underlying Database).
369
+ * Proxy method to avoid ctx.db.db.run() double access.
404
370
  */
405
- getConnection() {
406
- if (!this.db) {
407
- throw new Error("Database not initialized. Call initialize() first.");
408
- }
409
- return this.db;
371
+ run(sql, params) {
372
+ return this._db.run(sql, params);
410
373
  }
411
374
  /**
412
- * Execute a function within a transaction
375
+ * Executes a function within an atomic transaction.
376
+ * If fn() throws an error, the transaction is automatically rolled back.
413
377
  */
414
378
  withTransaction(fn) {
415
- const db = this.getConnection();
416
- const transaction = db.transaction(fn);
417
- return transaction(db);
379
+ const transaction = this._db.transaction(fn);
380
+ return transaction(this._db);
418
381
  }
419
382
  /**
420
383
  * Close the database connection
421
384
  */
422
385
  close() {
423
- if (this.db) {
424
- this.db.close();
425
- this.db = null;
426
- dbInstance = null;
427
- }
428
- }
429
- /**
430
- * Initialize the schema_versions table
431
- */
432
- initializeSchemaVersions() {
433
- if (!this.db) return;
434
- this.db.run(`
435
- CREATE TABLE IF NOT EXISTS schema_versions (
436
- id INTEGER PRIMARY KEY,
437
- version INTEGER UNIQUE NOT NULL,
438
- applied_at TEXT NOT NULL
439
- )
440
- `);
441
- }
442
- /**
443
- * Run all pending migrations
444
- */
445
- async runMigrations() {
446
- if (!this.db) return;
447
- const query = this.db.query("SELECT version FROM schema_versions ORDER BY version");
448
- const appliedVersions = query.all().map((row) => row.version);
449
- const maxApplied = appliedVersions.length > 0 ? Math.max(...appliedVersions) : 0;
450
- for (const migration of this.migrations) {
451
- if (migration.version > maxApplied) {
452
- logger.info("DB", `Applying migration ${migration.version}`);
453
- const transaction = this.db.transaction(() => {
454
- migration.up(this.db);
455
- const insertQuery = this.db.query("INSERT INTO schema_versions (version, applied_at) VALUES (?, ?)");
456
- insertQuery.run(migration.version, (/* @__PURE__ */ new Date()).toISOString());
457
- });
458
- transaction();
459
- logger.info("DB", `Migration ${migration.version} applied successfully`);
460
- }
461
- }
462
- }
463
- /**
464
- * Get current schema version
465
- */
466
- getCurrentVersion() {
467
- if (!this.db) return 0;
468
- const query = this.db.query("SELECT MAX(version) as version FROM schema_versions");
469
- const result = query.get();
470
- return result?.version || 0;
386
+ this._db.close();
471
387
  }
472
388
  };
473
389
  var MigrationRunner = class {
@@ -712,16 +628,6 @@ var MigrationRunner = class {
712
628
  ];
713
629
  }
714
630
  };
715
- function getDatabase() {
716
- if (!dbInstance) {
717
- throw new Error("Database not initialized. Call DatabaseManager.getInstance().initialize() first.");
718
- }
719
- return dbInstance;
720
- }
721
- async function initializeDatabase() {
722
- const manager = DatabaseManager.getInstance();
723
- return await manager.initialize();
724
- }
725
631
 
726
632
  // src/services/sqlite/Sessions.ts
727
633
  function createSession(db, contentSessionId, project, userPrompt) {
@@ -850,9 +756,25 @@ function consolidateObservations(db, project, options = {}) {
850
756
  ORDER BY cnt DESC
851
757
  `).all(project, minGroupSize);
852
758
  if (groups.length === 0) return { merged: 0, removed: 0 };
853
- let totalMerged = 0;
854
- let totalRemoved = 0;
759
+ if (options.dryRun) {
760
+ let totalMerged = 0;
761
+ let totalRemoved = 0;
762
+ for (const group of groups) {
763
+ const obsIds = group.ids.split(",").map(Number);
764
+ const placeholders = obsIds.map(() => "?").join(",");
765
+ const count = db.query(
766
+ `SELECT COUNT(*) as cnt FROM observations WHERE id IN (${placeholders})`
767
+ ).get(...obsIds)?.cnt || 0;
768
+ if (count >= minGroupSize) {
769
+ totalMerged += 1;
770
+ totalRemoved += count - 1;
771
+ }
772
+ }
773
+ return { merged: totalMerged, removed: totalRemoved };
774
+ }
855
775
  const runConsolidation = db.transaction(() => {
776
+ let merged = 0;
777
+ let removed = 0;
856
778
  for (const group of groups) {
857
779
  const obsIds = group.ids.split(",").map(Number);
858
780
  const placeholders = obsIds.map(() => "?").join(",");
@@ -860,11 +782,6 @@ function consolidateObservations(db, project, options = {}) {
860
782
  `SELECT * FROM observations WHERE id IN (${placeholders}) ORDER BY created_at_epoch DESC`
861
783
  ).all(...obsIds);
862
784
  if (observations.length < minGroupSize) continue;
863
- if (options.dryRun) {
864
- totalMerged += 1;
865
- totalRemoved += observations.length - 1;
866
- continue;
867
- }
868
785
  const keeper = observations[0];
869
786
  const others = observations.slice(1);
870
787
  const uniqueTexts = /* @__PURE__ */ new Set();
@@ -877,18 +794,18 @@ function consolidateObservations(db, project, options = {}) {
877
794
  const consolidatedText = Array.from(uniqueTexts).join("\n---\n").substring(0, 1e5);
878
795
  db.run(
879
796
  "UPDATE observations SET text = ?, title = ? WHERE id = ?",
880
- [consolidatedText, `[consolidato x${observations.length}] ${keeper.title}`, keeper.id]
797
+ [consolidatedText, `[consolidated x${observations.length}] ${keeper.title}`, keeper.id]
881
798
  );
882
799
  const removeIds = others.map((o) => o.id);
883
800
  const removePlaceholders = removeIds.map(() => "?").join(",");
884
801
  db.run(`DELETE FROM observations WHERE id IN (${removePlaceholders})`, removeIds);
885
802
  db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${removePlaceholders})`, removeIds);
886
- totalMerged += 1;
887
- totalRemoved += removeIds.length;
803
+ merged += 1;
804
+ removed += removeIds.length;
888
805
  }
806
+ return { merged, removed };
889
807
  });
890
- runConsolidation();
891
- return { merged: totalMerged, removed: totalRemoved };
808
+ return runConsolidation();
892
809
  }
893
810
 
894
811
  // src/services/sqlite/Summaries.ts
@@ -1134,7 +1051,7 @@ function escapeLikePattern3(input) {
1134
1051
  }
1135
1052
  function sanitizeFTS5Query(query) {
1136
1053
  const trimmed = query.length > 1e4 ? query.substring(0, 1e4) : query;
1137
- const terms = trimmed.replace(/[""]/g, "").split(/\s+/).filter((t) => t.length > 0).slice(0, 100).map((t) => `"${t}"`);
1054
+ const terms = trimmed.replace(/[""\u0022]/g, "").split(/\s+/).filter((t) => t.length > 0).slice(0, 100).map((t) => `"${t}"`);
1138
1055
  return terms.join(" ");
1139
1056
  }
1140
1057
  function searchObservationsFTS(db, query, filters = {}) {
@@ -1299,26 +1216,38 @@ function getTimeline(db, anchorId, depthBefore = 5, depthAfter = 5) {
1299
1216
  return [...before, ...self, ...after];
1300
1217
  }
1301
1218
  function getProjectStats(db, project) {
1302
- const obsStmt = db.query("SELECT COUNT(*) as count FROM observations WHERE project = ?");
1303
- const sumStmt = db.query("SELECT COUNT(*) as count FROM summaries WHERE project = ?");
1304
- const sesStmt = db.query("SELECT COUNT(*) as count FROM sessions WHERE project = ?");
1305
- const prmStmt = db.query("SELECT COUNT(*) as count FROM prompts WHERE project = ?");
1306
- const discoveryStmt = db.query(
1307
- "SELECT COALESCE(SUM(discovery_tokens), 0) as total FROM observations WHERE project = ?"
1308
- );
1309
- const discoveryTokens = discoveryStmt.get(project)?.total || 0;
1310
- const readStmt = db.query(
1311
- `SELECT COALESCE(SUM(
1312
- CAST((LENGTH(COALESCE(title, '')) + LENGTH(COALESCE(narrative, ''))) / 4 AS INTEGER)
1313
- ), 0) as total FROM observations WHERE project = ?`
1314
- );
1315
- const readTokens = readStmt.get(project)?.total || 0;
1219
+ const sql = `
1220
+ WITH
1221
+ obs_stats AS (
1222
+ SELECT
1223
+ COUNT(*) as count,
1224
+ COALESCE(SUM(discovery_tokens), 0) as discovery_tokens,
1225
+ COALESCE(SUM(
1226
+ CAST((LENGTH(COALESCE(title, '')) + LENGTH(COALESCE(narrative, ''))) / 4 AS INTEGER)
1227
+ ), 0) as read_tokens
1228
+ FROM observations WHERE project = ?
1229
+ ),
1230
+ sum_count AS (SELECT COUNT(*) as count FROM summaries WHERE project = ?),
1231
+ ses_count AS (SELECT COUNT(*) as count FROM sessions WHERE project = ?),
1232
+ prm_count AS (SELECT COUNT(*) as count FROM prompts WHERE project = ?)
1233
+ SELECT
1234
+ obs_stats.count as observations,
1235
+ obs_stats.discovery_tokens,
1236
+ obs_stats.read_tokens,
1237
+ sum_count.count as summaries,
1238
+ ses_count.count as sessions,
1239
+ prm_count.count as prompts
1240
+ FROM obs_stats, sum_count, ses_count, prm_count
1241
+ `;
1242
+ const row = db.query(sql).get(project, project, project, project);
1243
+ const discoveryTokens = row?.discovery_tokens || 0;
1244
+ const readTokens = row?.read_tokens || 0;
1316
1245
  const savings = Math.max(0, discoveryTokens - readTokens);
1317
1246
  return {
1318
- observations: obsStmt.get(project)?.count || 0,
1319
- summaries: sumStmt.get(project)?.count || 0,
1320
- sessions: sesStmt.get(project)?.count || 0,
1321
- prompts: prmStmt.get(project)?.count || 0,
1247
+ observations: row?.observations || 0,
1248
+ summaries: row?.summaries || 0,
1249
+ sessions: row?.sessions || 0,
1250
+ prompts: row?.prompts || 0,
1322
1251
  tokenEconomics: { discoveryTokens, readTokens, savings }
1323
1252
  };
1324
1253
  }
@@ -1362,8 +1291,6 @@ function markObservationsStale(db, ids, stale) {
1362
1291
  );
1363
1292
  }
1364
1293
  export {
1365
- KiroMemoryDatabase as ContextKitDatabase,
1366
- DatabaseManager,
1367
1294
  KiroMemoryDatabase,
1368
1295
  completeSession,
1369
1296
  consolidateObservations,
@@ -1379,7 +1306,6 @@ export {
1379
1306
  getActiveSessions,
1380
1307
  getAllSessions,
1381
1308
  getCheckpointsBySession,
1382
- getDatabase,
1383
1309
  getLatestCheckpoint,
1384
1310
  getLatestCheckpointByProject,
1385
1311
  getLatestPrompt,
@@ -1397,7 +1323,6 @@ export {
1397
1323
  getSummariesByProject,
1398
1324
  getSummaryBySession,
1399
1325
  getTimeline,
1400
- initializeDatabase,
1401
1326
  isDuplicateObservation,
1402
1327
  markObservationsStale,
1403
1328
  searchObservations,
@@ -0,0 +1 @@
1
+ *,:after,:before{--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:rgba(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:rgba(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: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif;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,pre,samp{font-family:JetBrains Mono,ui-monospace,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,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{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}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.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}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-2\.5{left:.625rem}.top-1\/2{top:50%}.z-40{z-index:40}.z-50{z-index:50}.z-\[999\]{z-index:999}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1\.5{margin-top:.375rem;margin-bottom:.375rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2\.5{margin-top:.625rem}.mt-\[12vh\]{margin-top:12vh}.mt-auto{margin-top:auto}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-1\.5{height:.375rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.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-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-\[360px\]{max-height:360px}.max-h-\[40vh\]{max-height:40vh}.w-1\.5{width:.375rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[260px\]{width:260px}.w-\[280px\]{width:280px}.w-full{width:100%}.min-w-0{min-width:0}.max-w-3xl{max-width:48rem}.max-w-md{max-width:28rem}.max-w-xl{max-width:36rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.rotate-180{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.scale-125{--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.animate-fade-in{animation:fade-in .3s ease-out forwards}@keyframes pulse-dot{0%,to{opacity:1}50%{opacity:.5}}.animate-pulse-dot{animation:pulse-dot 2s ease-in-out infinite}@keyframes scale-in{0%{opacity:0;transform:scale(.97)}to{opacity:1;transform:scale(1)}}.animate-scale-in{animation:scale-in .2s ease-out forwards}@keyframes slide-in-left{0%{opacity:0;transform:translateX(-100%)}to{opacity:1;transform:translateX(0)}}.animate-slide-in-left{animation:slide-in-left .25s ease-out forwards}@keyframes slide-up{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.animate-slide-up{animation:slide-up .35s ease-out forwards}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.animate-spin{animation:spin .8s linear infinite}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.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-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-\[2px\]{gap:2px}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(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*(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*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-l-full{border-top-left-radius:9999px;border-bottom-left-radius:9999px}.rounded-r-full{border-top-right-radius:9999px;border-bottom-right-radius:9999px}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l-\[3px\]{border-left-width:3px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-accent-violet{--tw-border-opacity:1;border-color:rgb(124 90 255/var(--tw-border-opacity,1))}.border-accent-violet\/30{border-color:rgba(124,90,255,.3)}.border-border{border-color:var(--border)}.border-transparent{border-color:transparent}.border-zinc-600{border-color:var(--zinc-600)}.border-l-amber-500{--tw-border-opacity:1;border-left-color:rgb(245 158 11/var(--tw-border-opacity,1))}.border-l-blue-500{--tw-border-opacity:1;border-left-color:rgb(59 130 246/var(--tw-border-opacity,1))}.border-l-cyan-500{--tw-border-opacity:1;border-left-color:rgb(6 182 212/var(--tw-border-opacity,1))}.border-l-emerald-500{--tw-border-opacity:1;border-left-color:rgb(16 185 129/var(--tw-border-opacity,1))}.border-l-rose-500{--tw-border-opacity:1;border-left-color:rgb(244 63 94/var(--tw-border-opacity,1))}.border-l-violet-500{--tw-border-opacity:1;border-left-color:rgb(139 92 246/var(--tw-border-opacity,1))}.border-l-zinc-500{border-left-color:var(--zinc-500)}.border-t-accent-violet{--tw-border-opacity:1;border-top-color:rgb(124 90 255/var(--tw-border-opacity,1))}.bg-accent-amber{--tw-bg-opacity:1;background-color:rgb(251 191 36/var(--tw-bg-opacity,1))}.bg-accent-amber\/15{background-color:rgba(251,191,36,.15)}.bg-accent-blue{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-accent-blue\/15{background-color:rgba(59,130,246,.15)}.bg-accent-cyan{--tw-bg-opacity:1;background-color:rgb(34 211 238/var(--tw-bg-opacity,1))}.bg-accent-cyan\/15{background-color:rgba(34,211,238,.15)}.bg-accent-green{--tw-bg-opacity:1;background-color:rgb(52 211 153/var(--tw-bg-opacity,1))}.bg-accent-green\/15{background-color:rgba(52,211,153,.15)}.bg-accent-orange\/15{background-color:rgba(251,146,60,.15)}.bg-accent-rose{--tw-bg-opacity:1;background-color:rgb(251 113 133/var(--tw-bg-opacity,1))}.bg-accent-rose\/15{background-color:rgba(251,113,133,.15)}.bg-accent-violet{--tw-bg-opacity:1;background-color:rgb(124 90 255/var(--tw-bg-opacity,1))}.bg-accent-violet\/10{background-color:rgba(124,90,255,.1)}.bg-accent-violet\/15{background-color:rgba(124,90,255,.15)}.bg-accent-violet\/50{background-color:rgba(124,90,255,.5)}.bg-amber-500{--tw-bg-opacity:1;background-color:rgb(245 158 11/var(--tw-bg-opacity,1))}.bg-amber-500\/10{background-color:rgba(245,158,11,.1)}.bg-amber-500\/15{background-color:rgba(245,158,11,.15)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/60{background-color:rgba(0,0,0,.6)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/15{background-color:rgba(59,130,246,.15)}.bg-border{background-color:var(--border)}.bg-cyan-500{--tw-bg-opacity:1;background-color:rgb(6 182 212/var(--tw-bg-opacity,1))}.bg-cyan-500\/10{background-color:rgba(6,182,212,.1)}.bg-cyan-500\/15{background-color:rgba(6,182,212,.15)}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-emerald-500\/10{background-color:rgba(16,185,129,.1)}.bg-emerald-500\/15{background-color:rgba(16,185,129,.15)}.bg-emerald-500\/40{background-color:rgba(16,185,129,.4)}.bg-indigo-500{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity,1))}.bg-indigo-500\/10{background-color:rgba(99,102,241,.1)}.bg-indigo-500\/15{background-color:rgba(99,102,241,.15)}.bg-lime-500\/15{background-color:rgba(132,204,22,.15)}.bg-orange-500{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity,1))}.bg-orange-500\/10{background-color:rgba(249,115,22,.1)}.bg-orange-500\/15{background-color:rgba(249,115,22,.15)}.bg-pink-500\/15{background-color:rgba(236,72,153,.15)}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/15{background-color:rgba(239,68,68,.15)}.bg-rose-500\/10{background-color:rgba(244,63,94,.1)}.bg-rose-500\/15{background-color:rgba(244,63,94,.15)}.bg-sky-500\/15{background-color:rgba(14,165,233,.15)}.bg-slate-500{--tw-bg-opacity:1;background-color:rgb(100 116 139/var(--tw-bg-opacity,1))}.bg-slate-500\/10{background-color:rgba(100,116,139,.1)}.bg-surface-0{background-color:var(--surface-0)}.bg-surface-1{background-color:var(--surface-1)}.bg-surface-2{background-color:var(--surface-2)}.bg-surface-3{background-color:var(--surface-3)}.bg-teal-500\/15{background-color:rgba(20,184,166,.15)}.bg-transparent{background-color:transparent}.bg-violet-500{--tw-bg-opacity:1;background-color:rgb(139 92 246/var(--tw-bg-opacity,1))}.bg-violet-500\/10{background-color:rgba(139,92,246,.1)}.bg-violet-500\/15{background-color:rgba(139,92,246,.15)}.bg-yellow-500\/15{background-color:rgba(234,179,8,.15)}.bg-zinc-400{background-color:var(--zinc-400)}.bg-zinc-500{background-color:var(--zinc-500)}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-cyan-500{--tw-gradient-from:#06b6d4 var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-500{--tw-gradient-from:#10b981 var(--tw-gradient-from-position);--tw-gradient-to:rgba(16,185,129,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-500\/40{--tw-gradient-from:rgba(16,185,129,.4) var(--tw-gradient-from-position);--tw-gradient-to:rgba(16,185,129,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-cyan-400{--tw-gradient-to:#22d3ee var(--tw-gradient-to-position)}.to-emerald-400{--tw-gradient-to:#34d399 var(--tw-gradient-to-position)}.to-emerald-400\/40{--tw-gradient-to:rgba(52,211,153,.4) var(--tw-gradient-to-position)}.p-0\.5{padding:.125rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.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}.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-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-20{padding-top:5rem;padding-bottom:5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-7{padding-left:1.75rem}.pr-2{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-right{text-align:right}.font-mono{font-family:JetBrains Mono,ui-monospace,monospace}.font-sans{font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif}.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-\[15px\]{font-size:15px}.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-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}.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-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-accent-amber{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-accent-blue{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-accent-cyan{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-accent-green{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-accent-orange{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-accent-rose{--tw-text-opacity:1;color:rgb(251 113 133/var(--tw-text-opacity,1))}.text-accent-violet{--tw-text-opacity:1;color:rgb(124 90 255/var(--tw-text-opacity,1))}.text-amber-400{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-amber-400\/80{color:rgba(251,191,36,.8)}.text-amber-600{--tw-text-opacity:1;color:rgb(217 119 6/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-cyan-600{--tw-text-opacity:1;color:rgb(8 145 178/var(--tw-text-opacity,1))}.text-emerald-400{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-emerald-600{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.text-indigo-400{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.text-indigo-600{--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity,1))}.text-lime-400{--tw-text-opacity:1;color:rgb(163 230 53/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-600{--tw-text-opacity:1;color:rgb(234 88 12/var(--tw-text-opacity,1))}.text-pink-400{--tw-text-opacity:1;color:rgb(244 114 182/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-600{--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity,1))}.text-rose-400{--tw-text-opacity:1;color:rgb(251 113 133/var(--tw-text-opacity,1))}.text-sky-400{--tw-text-opacity:1;color:rgb(56 189 248/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-teal-400{--tw-text-opacity:1;color:rgb(45 212 191/var(--tw-text-opacity,1))}.text-violet-400{--tw-text-opacity:1;color:rgb(167 139 250/var(--tw-text-opacity,1))}.text-violet-600{--tw-text-opacity:1;color:rgb(124 58 237/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-zinc-100{color:var(--zinc-100)}.text-zinc-200{color:var(--zinc-200)}.text-zinc-300{color:var(--zinc-300)}.text-zinc-400{color:var(--zinc-400)}.text-zinc-500{color:var(--zinc-500)}.text-zinc-600{color:var(--zinc-600)}.text-zinc-700{color:var(--zinc-700)}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.placeholder-zinc-600::-moz-placeholder{color:var(--zinc-600)}.placeholder-zinc-600::placeholder{color:var(--zinc-600)}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-30{opacity:.3}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-card{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-card{--tw-shadow:var(--shadow-card);--tw-shadow-colored:var(--shadow-card)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(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}.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)}.ring,.ring-1{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)}.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-accent-amber\/30{--tw-ring-color:rgba(251,191,36,.3)}.ring-accent-blue\/30{--tw-ring-color:rgba(59,130,246,.3)}.ring-accent-cyan\/30{--tw-ring-color:rgba(34,211,238,.3)}.ring-accent-green\/30{--tw-ring-color:rgba(52,211,153,.3)}.ring-accent-orange\/30{--tw-ring-color:rgba(251,146,60,.3)}.ring-accent-rose\/30{--tw-ring-color:rgba(251,113,133,.3)}.ring-accent-violet{--tw-ring-opacity:1;--tw-ring-color:rgb(124 90 255/var(--tw-ring-opacity,1))}.ring-accent-violet\/30{--tw-ring-color:rgba(124,90,255,.3)}.ring-amber-500\/25{--tw-ring-color:rgba(245,158,11,.25)}.ring-blue-500\/25{--tw-ring-color:rgba(59,130,246,.25)}.ring-cyan-500\/25{--tw-ring-color:rgba(6,182,212,.25)}.ring-emerald-500\/25{--tw-ring-color:rgba(16,185,129,.25)}.ring-indigo-500\/25{--tw-ring-color:rgba(99,102,241,.25)}.ring-lime-500\/25{--tw-ring-color:rgba(132,204,22,.25)}.ring-orange-500\/25{--tw-ring-color:rgba(249,115,22,.25)}.ring-pink-500\/25{--tw-ring-color:rgba(236,72,153,.25)}.ring-red-500\/25{--tw-ring-color:rgba(239,68,68,.25)}.ring-rose-500\/25{--tw-ring-color:rgba(244,63,94,.25)}.ring-sky-500\/25{--tw-ring-color:rgba(14,165,233,.25)}.ring-teal-500\/25{--tw-ring-color:rgba(20,184,166,.25)}.ring-violet-500\/25{--tw-ring-color:rgba(139,92,246,.25)}.ring-yellow-500\/25{--tw-ring-color:rgba(234,179,8,.25)}.ring-offset-2{--tw-ring-offset-width:2px}.ring-offset-surface-0{--tw-ring-offset-color:var(--surface-0)}.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-sm{--tw-backdrop-blur:blur(4px);-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-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-transform{transition-duration:.15s}.duration-500{transition-duration:.5s}:root{--surface-0:#f5f6fa;--surface-1:#fff;--surface-2:#ecedf3;--surface-3:#e0e2eb;--surface-4:#d3d6e0;--border:#d3d6e0;--border-subtle:#e6e8ef;--border-hover:#b5b9c8;--zinc-50:#f8f9fa;--zinc-100:#131520;--zinc-200:#1f2233;--zinc-300:#343750;--zinc-400:#4b5068;--zinc-500:#6b7085;--zinc-600:#9499aa;--zinc-700:#bfc3ce;--zinc-800:#e4e6ec;--zinc-900:#f3f4f6;--shadow-card:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04);--shadow-card-hover:0 4px 12px rgba(0,0,0,.08),0 2px 4px rgba(0,0,0,.04);--shadow-panel:0 0 0 1px rgba(0,0,0,.04),0 2px 8px rgba(0,0,0,.06);--scrollbar-thumb:#b5b9c8;--scrollbar-hover:#8b7fd4;--scrollbar-track:#ecedf3}.dark{--surface-0:#0e1015;--surface-1:#161820;--surface-2:#1e202a;--surface-3:#272935;--surface-4:#313342;--border:#313342;--border-subtle:#222430;--border-hover:#434558;--zinc-50:#18181b;--zinc-100:#f0f1f4;--zinc-200:#e0e2e8;--zinc-300:#c8ccd6;--zinc-400:#9ea3b2;--zinc-500:#757a8c;--zinc-600:#555968;--zinc-700:#3d4050;--zinc-800:#272935;--zinc-900:#1a1c24;--shadow-card:0 1px 3px rgba(0,0,0,.4),0 1px 2px rgba(0,0,0,.3);--shadow-card-hover:0 4px 12px rgba(0,0,0,.5),0 2px 4px rgba(0,0,0,.3);--shadow-panel:0 0 0 1px hsla(0,0%,100%,.03),0 2px 8px rgba(0,0,0,.4);--scrollbar-thumb:#434558;--scrollbar-hover:#7c5aff;--scrollbar-track:#1e202a}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--scrollbar-track);border-radius:4px;margin:2px}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:4px;border:2px solid var(--scrollbar-track);-webkit-transition:background .2s;transition:background .2s}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-hover)}::-webkit-scrollbar-corner{background:transparent}*{scrollbar-width:auto;scrollbar-color:var(--scrollbar-thumb) var(--scrollbar-track)}.stagger-1{animation-delay:30ms}.stagger-2{animation-delay:60ms}.stagger-3{animation-delay:90ms}.stagger-4{animation-delay:.12s}.stagger-5{animation-delay:.15s}.stagger-6{animation-delay:.18s}.stagger-7{animation-delay:.21s}.stagger-8{animation-delay:.24s}.cmd-input::-moz-placeholder{color:hsla(0,0%,100%,.3)}.cmd-input::placeholder{color:hsla(0,0%,100%,.3)}.hover\:border-border:hover{border-color:var(--border)}.hover\:border-border-hover:hover{border-color:var(--border-hover)}.hover\:bg-surface-2:hover{background-color:var(--surface-2)}.hover\:bg-surface-3:hover{background-color:var(--surface-3)}.hover\:text-accent-green\/80:hover{color:rgba(52,211,153,.8)}.hover\:text-zinc-100:hover{color:var(--zinc-100)}.hover\:text-zinc-200:hover{color:var(--zinc-200)}.hover\:text-zinc-300:hover{color:var(--zinc-300)}.hover\:text-zinc-400:hover{color:var(--zinc-400)}.hover\:shadow-card-hover:hover{--tw-shadow:var(--shadow-card-hover);--tw-shadow-colored:var(--shadow-card-hover);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.focus\:border-accent-violet\/50:focus{border-color:rgba(124,90,255,.5)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.group:hover .group-hover\:opacity-100{opacity:1}.dark\:bg-amber-500\/10:is(.dark *){background-color:rgba(245,158,11,.1)}.dark\:bg-blue-500\/10:is(.dark *){background-color:rgba(59,130,246,.1)}.dark\:bg-cyan-500\/10:is(.dark *){background-color:rgba(6,182,212,.1)}.dark\:bg-emerald-500\/10:is(.dark *){background-color:rgba(16,185,129,.1)}.dark\:bg-indigo-500\/10:is(.dark *){background-color:rgba(99,102,241,.1)}.dark\:bg-orange-500\/10:is(.dark *){background-color:rgba(249,115,22,.1)}.dark\:bg-red-500\/10:is(.dark *){background-color:rgba(239,68,68,.1)}.dark\:bg-slate-500\/10:is(.dark *){background-color:rgba(100,116,139,.1)}.dark\:bg-violet-500\/10:is(.dark *){background-color:rgba(139,92,246,.1)}.dark\:text-amber-400:is(.dark *){--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.dark\:text-blue-400:is(.dark *){--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.dark\:text-cyan-400:is(.dark *){--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.dark\:text-emerald-400:is(.dark *){--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.dark\:text-indigo-400:is(.dark *){--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.dark\:text-orange-400:is(.dark *){--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.dark\:text-slate-400:is(.dark *){--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.dark\:text-violet-400:is(.dark *){--tw-text-opacity:1;color:rgb(167 139 250/var(--tw-text-opacity,1))}.dark\:text-zinc-400:is(.dark *){color:var(--zinc-400)}@media (min-width:640px){.sm\:inline{display:inline}.sm\:flex{display:flex}}@media (min-width:768px){.md\:flex{display:flex}.md\:hidden{display:none}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}}@media (min-width:1024px){.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}