@askdb/studio 0.2.0-beta.4 → 0.2.0-beta.41
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/README.md +33 -29
- package/bin/askdb-studio.js +3 -1
- package/dist/bin.d.ts +1 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +24 -3
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +72 -15
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/index-Bl9jqOjj.css +2 -0
- package/dist/client/assets/index-CGC5sKu1.js +100 -0
- package/dist/client/index.html +2 -2
- package/dist/execute-registry.d.ts +89 -0
- package/dist/execute-registry.d.ts.map +1 -0
- package/dist/execute-registry.js +445 -0
- package/dist/execute-registry.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/introspection.d.ts +35 -0
- package/dist/introspection.d.ts.map +1 -0
- package/dist/introspection.js +106 -0
- package/dist/introspection.js.map +1 -0
- package/dist/package-manager.d.ts +44 -0
- package/dist/package-manager.d.ts.map +1 -0
- package/dist/package-manager.js +86 -0
- package/dist/package-manager.js.map +1 -0
- package/dist/prisma-install.d.ts +7 -0
- package/dist/prisma-install.d.ts.map +1 -0
- package/dist/prisma-install.js +7 -0
- package/dist/prisma-install.js.map +1 -0
- package/dist/request-guard.d.ts +44 -0
- package/dist/request-guard.d.ts.map +1 -0
- package/dist/request-guard.js +170 -0
- package/dist/request-guard.js.map +1 -0
- package/dist/server.d.ts +22 -4
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1123 -148
- package/dist/server.js.map +1 -1
- package/dist/setup.d.ts +77 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +511 -0
- package/dist/setup.js.map +1 -0
- package/dist/shared/api.d.ts +176 -3
- package/dist/shared/api.d.ts.map +1 -1
- package/package.json +81 -30
- package/dist/client/assets/index-Bsn2S5X2.css +0 -2
- package/dist/client/assets/index-C_RfRKkd.js +0 -8
package/README.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# @askdb/studio
|
|
2
2
|
|
|
3
|
-
Local React browser UI for editing AskDB Schema v2 enrichment, checking RAG
|
|
4
|
-
retrieval, and generating sample NL-to-SQL output.
|
|
3
|
+
Local React browser UI for editing AskDB Schema v2 enrichment, checking RAG retrieval, and generating sample NL-to-SQL output.
|
|
5
4
|
|
|
6
5
|
```sh
|
|
7
6
|
askdb-studio --schema ./my-app.schema
|
|
@@ -9,21 +8,32 @@ askdb-studio --schema ./my-app.schema
|
|
|
9
8
|
askdb studio --schema ./my-app.schema
|
|
10
9
|
```
|
|
11
10
|
|
|
12
|
-
Studio serves a local web app at `http://127.0.0.1:5556` by default. The
|
|
13
|
-
published package contains a Node local server plus a Vite-built React client.
|
|
14
|
-
It can:
|
|
11
|
+
Studio serves a local web app at `http://127.0.0.1:5556` by default. The published package contains a Node local server plus a Vite-built React client. It can:
|
|
15
12
|
|
|
16
13
|
- browse all physical tables and columns in `schema.json`
|
|
17
14
|
- edit table descriptions, aliases, primary entities, tags, common query language, example questions, and column metadata
|
|
18
15
|
- write the describable layer back to `tables/*.md`
|
|
19
|
-
- request AI enrichment suggestions when `
|
|
16
|
+
- request AI enrichment suggestions when the `ai` block in `askdb.config.*` has an API key
|
|
20
17
|
- build and query the configured RAG index (`memory`, file-backed, or `pgvector`)
|
|
21
18
|
- generate sample Postgres SQL for natural-language questions against the currently saved enrichment
|
|
19
|
+
- define and manage multi-tenancy policy (tenant roots, hierarchy, scoped/polymorphic/global tables) via the Tenancy view
|
|
20
|
+
- draft tenant policy with AI assistance
|
|
21
|
+
- test NL→SQL with tenant scope controls and SQL output modes (`sql-only` vs `sql-params`)
|
|
22
22
|
|
|
23
|
-
Studio
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
Schema browsing, enrichment, and SQL generation do not require a database driver. The optional Playground execute path runs generated SQL against a live database. Studio supports Postgres, MySQL, SQLite, and SQL Server. Each dialect requires its own optional peer driver package — install only the one you need:
|
|
24
|
+
|
|
25
|
+
| Dialect | Package |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Postgres | `pnpm add pg` |
|
|
28
|
+
| MySQL | `pnpm add mysql2` |
|
|
29
|
+
| SQLite | `pnpm add better-sqlite3` |
|
|
30
|
+
| SQL Server | `pnpm add mssql` |
|
|
31
|
+
|
|
32
|
+
Execute is off by default. Enable it with `studio.execute.enabled: true` plus an execute connection (`studio.execute.databaseUrl`, or `file` for SQLite), ideally a read-only database role. Studio only reuses the introspection connection when `studio.execute.useIntrospectionConnection` is `true`. Each query is validated as a single read-only SELECT and runs in a read-only (SQL Server: always-rolled-back) transaction with a timeout (`studio.execute.timeoutMs`, default 30 s) and a row cap (`studio.execute.maxRows`, default 500).
|
|
33
|
+
|
|
34
|
+
The execute provider is resolved from `studio.execute.provider` in `askdb.config.ts`, falling back to the active introspection provider, then defaulting to Postgres for backward compatibility. The Playground displays the configured provider, connection status, and driver readiness near the Execute button. When running locally, Studio can install the missing driver for you.
|
|
35
|
+
|
|
36
|
+
Studio uses `@askdb/enrich` for the shared non-UI Schema v2 authoring logic: workspace loading, editable drafts, markdown/frontmatter preservation, save helpers, and suggestion context.
|
|
27
37
|
|
|
28
38
|
## Development
|
|
29
39
|
|
|
@@ -33,30 +43,24 @@ pnpm --filter @askdb/studio test
|
|
|
33
43
|
pnpm --filter @askdb/studio start -- --schema ../../fixtures/schemas/orders-users.schema
|
|
34
44
|
```
|
|
35
45
|
|
|
36
|
-
The client source lives in `src/web/` and builds to `dist/client/`. The server
|
|
37
|
-
source lives in `src/` and serves the compiled client assets from that directory.
|
|
46
|
+
The client source lives in `src/web/` and builds to `dist/client/`. The server source lives in `src/` and serves the compiled client assets from that directory.
|
|
38
47
|
|
|
39
|
-
The React client is styled with Tailwind CSS and shadcn-style primitives. The
|
|
40
|
-
requested shadcn preset is recorded in `components.json`:
|
|
48
|
+
The React client is styled with Tailwind CSS and shadcn-style primitives. The requested shadcn preset is recorded in `components.json`:
|
|
41
49
|
|
|
42
50
|
```sh
|
|
43
51
|
pnpm dlx shadcn@latest init --preset b1D0eCA4
|
|
44
52
|
```
|
|
45
53
|
|
|
46
|
-
|
|
54
|
+
Configuration, in `askdb.config.*` (bind any value to an environment variable of your choosing with `env("NAME")`; Studio loads `.env` first):
|
|
47
55
|
|
|
48
|
-
|
|
|
56
|
+
| Config key | Purpose |
|
|
49
57
|
| --- | --- |
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
Studio uses the active `rag.store` branch from `askdb.config.*`. For `pgvector`,
|
|
61
|
-
make sure the configured table/extension already exist and `ASKDB_PGVECTOR_URL`
|
|
62
|
-
resolves correctly.
|
|
58
|
+
| `ai.provider`, `ai.providerConfig.<provider>.apiKey` | Enables AI suggestions and sample NL-to-SQL generation. |
|
|
59
|
+
| `ai.providerConfig.<provider>.baseUrl` | Optional base URL, e.g. an OpenAI-compatible endpoint. |
|
|
60
|
+
| `studio.listen.host` | Bind host. Defaults to `127.0.0.1`. `--host` overrides it. |
|
|
61
|
+
| `studio.listen.port` | Bind port. Defaults to `5556`. `--port` overrides it. |
|
|
62
|
+
| `dev.mockSql` | Deterministic generated SQL for tests or offline demos. |
|
|
63
|
+
|
|
64
|
+
Security: every `/api/*` request must carry the per-launch session token that Studio injects into the page it serves (`x-askdb-studio-token` header), come with an allowed `Host` (`localhost`, `127.0.0.1`, `[::1]`, or the bound host), and, for writes, be same-origin JSON. Programmatic callers of `createStudioServer()` can read the token from `server.sessionToken`. Binding to a non-loopback host exposes query execution and schema writes to anyone on that network who can load the page. Only do that on a trusted network. See [Studio → Security model](https://askdb.tools/studio/#security-model).
|
|
65
|
+
|
|
66
|
+
Studio uses the active `rag.store` branch from `askdb.config.*`, and embeds with `rag.embedder`: `mock`, a local lexical embedder that needs no key, or `ai`, the `ai.embedding` model, built from that section's connection only (see the [configuration reference](https://askdb.tools/reference/config/#aiembedding)). For `pgvector`, make sure `rag.storeConfig.pgvector.databaseUrl` resolves; there's no need to create the table. The first index build creates it, and the `vector` extension, at the width the embedding model returns (or `ai.embedding.dimensions`). A table that already exists at another width is refused, with a message saying how to resolve it. If Studio's database role can't create extensions, create `vector` first.
|
package/bin/askdb-studio.js
CHANGED
package/dist/bin.d.ts
CHANGED
package/dist/bin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAKA,wBAAsB,YAAY,CAAC,IAAI,GAAE,SAAS,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBnG"}
|
package/dist/bin.js
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { bootstrapAskDbEnv } from "@askdb/config";
|
|
2
|
+
import { bootstrapAskDbEnv, discoverAskDbConfigPath } from "@askdb/config";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
3
4
|
import { runStudioCli } from "./cli.js";
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
export async function runStudioBin(argv = process.argv.slice(2)) {
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
const configPath = discoverAskDbConfigPath(cwd);
|
|
8
|
+
// No config yet: Studio starts in setup mode and the browser wizard walks the user through
|
|
9
|
+
// creating one. runStudioCli re-probes.
|
|
10
|
+
if (configPath) {
|
|
11
|
+
try {
|
|
12
|
+
bootstrapAskDbEnv({ cwd });
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
// A config that exists but fails to load (a syntax error, or dependencies not installed
|
|
16
|
+
// yet) still lets Studio start so setup can continue, but the user must hear why their
|
|
17
|
+
// settings are ignored. Setup never overwrites an existing config file.
|
|
18
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
19
|
+
process.stderr.write(`askdb-studio: warning: ${configPath} could not be loaded, so Studio is ignoring it: ${message}\n`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return runStudioCli(argv);
|
|
23
|
+
}
|
|
24
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
25
|
+
process.exit(await runStudioBin());
|
|
26
|
+
}
|
|
6
27
|
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA0B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAChF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,UAAU,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAChD,2FAA2F;IAC3F,wCAAwC;IACxC,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,iBAAiB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,wFAAwF;YACxF,uFAAuF;YACvF,wEAAwE;YACxE,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0BAA0B,UAAU,mDAAmD,OAAO,IAAI,CACnG,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/E,OAAO,CAAC,IAAI,CAAC,MAAM,YAAY,EAAE,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAqBA,wBAAsB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkE3E"}
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { DEFAULT_INTROSPECT_OUTPUT_DIR, getAskDbRuntimeConfig } from "@askdb/config";
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
1
|
+
import { DEFAULT_INTROSPECT_OUTPUT_DIR, discoverAskDbConfigPath, getAskDbRuntimeConfig, } from "@askdb/config";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { networkInterfaces } from "node:os";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { isLoopbackHost } from "./request-guard.js";
|
|
4
6
|
import { createStudioServer } from "./server.js";
|
|
5
7
|
export async function runStudioCli(argv) {
|
|
6
8
|
let opts;
|
|
@@ -20,18 +22,25 @@ export async function runStudioCli(argv) {
|
|
|
20
22
|
printHelp(process.stdout);
|
|
21
23
|
return 0;
|
|
22
24
|
}
|
|
25
|
+
const setupReason = resolveSetupReason(opts);
|
|
23
26
|
let server;
|
|
24
27
|
try {
|
|
25
28
|
server = createStudioServer({
|
|
26
29
|
schema: opts.schema,
|
|
27
30
|
host: opts.host,
|
|
28
31
|
port: opts.port,
|
|
32
|
+
setupReason,
|
|
29
33
|
});
|
|
30
34
|
}
|
|
31
35
|
catch (error) {
|
|
32
36
|
process.stderr.write(`askdb-studio: ${formatError(error)}\n`);
|
|
33
37
|
return 1;
|
|
34
38
|
}
|
|
39
|
+
if (setupReason) {
|
|
40
|
+
process.stdout.write(setupReason === "no-config"
|
|
41
|
+
? "No askdb.config.* found — Studio will open with the guided setup wizard.\n"
|
|
42
|
+
: "No schema artifact found — Studio will open with the guided setup wizard.\n");
|
|
43
|
+
}
|
|
35
44
|
await new Promise((resolve, reject) => {
|
|
36
45
|
server.once("error", reject);
|
|
37
46
|
server.listen(opts.port, opts.host, resolve);
|
|
@@ -44,6 +53,9 @@ export async function runStudioCli(argv) {
|
|
|
44
53
|
return 1;
|
|
45
54
|
const shownHost = opts.host === "0.0.0.0" ? firstPrivateAddress() ?? "127.0.0.1" : opts.host;
|
|
46
55
|
process.stdout.write(`AskDB Studio is running at http://${shownHost}:${address.port}\n`);
|
|
56
|
+
if (!isLoopbackHost(opts.host)) {
|
|
57
|
+
process.stderr.write(formatNetworkExposureWarning(opts.host));
|
|
58
|
+
}
|
|
47
59
|
process.stdout.write("Press Ctrl+C to stop.\n");
|
|
48
60
|
return await new Promise((resolve) => {
|
|
49
61
|
const stop = () => {
|
|
@@ -54,23 +66,32 @@ export async function runStudioCli(argv) {
|
|
|
54
66
|
});
|
|
55
67
|
}
|
|
56
68
|
function parseOptions(argv) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
// Without a config the runtime snapshot is uninitialized — fall back to
|
|
70
|
+
// package defaults so Studio can still start (in setup mode).
|
|
71
|
+
const rt = (() => {
|
|
72
|
+
try {
|
|
73
|
+
return getAskDbRuntimeConfig();
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
})();
|
|
79
|
+
const listen = rt?.structured.studio?.listen;
|
|
80
|
+
const introspectOut = rt?.flat["ASKDB_INTROSPECT_OUT"] ?? DEFAULT_INTROSPECT_OUTPUT_DIR;
|
|
63
81
|
const opts = {
|
|
64
82
|
schema: introspectOut,
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
schemaFromFlag: false,
|
|
84
|
+
host: listen?.host ?? "127.0.0.1",
|
|
85
|
+
port: 5556,
|
|
67
86
|
};
|
|
87
|
+
let portFromFlag = false;
|
|
68
88
|
for (let i = 0; i < argv.length; i += 1) {
|
|
69
89
|
const arg = argv[i];
|
|
70
90
|
switch (arg) {
|
|
71
91
|
case "--schema":
|
|
72
92
|
case "-s":
|
|
73
93
|
opts.schema = readValue(argv, ++i, arg);
|
|
94
|
+
opts.schemaFromFlag = true;
|
|
74
95
|
break;
|
|
75
96
|
case "--host":
|
|
76
97
|
opts.host = readValue(argv, ++i, arg);
|
|
@@ -82,6 +103,7 @@ function parseOptions(argv) {
|
|
|
82
103
|
throw new Error(`Invalid --port: ${raw}`);
|
|
83
104
|
}
|
|
84
105
|
opts.port = port;
|
|
106
|
+
portFromFlag = true;
|
|
85
107
|
break;
|
|
86
108
|
}
|
|
87
109
|
case "--help":
|
|
@@ -96,8 +118,30 @@ function parseOptions(argv) {
|
|
|
96
118
|
throw new Error(`Unknown option: ${arg}`);
|
|
97
119
|
}
|
|
98
120
|
}
|
|
121
|
+
// A bad configured port must fail, not quietly bind 5556. `NaN` (`Number(env("X"))` with X
|
|
122
|
+
// unset) counts as unset, as it does in @askdb/config; a numeric string works like a number.
|
|
123
|
+
const configPort = listen?.port;
|
|
124
|
+
if (!portFromFlag && !opts.help && !opts.version && configPort !== undefined && !Number.isNaN(configPort)) {
|
|
125
|
+
const port = Number(configPort);
|
|
126
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
|
|
127
|
+
throw new Error(`Invalid studio.listen.port in askdb.config: ${String(configPort)} (expected an integer from 1 to 65535).`);
|
|
128
|
+
}
|
|
129
|
+
opts.port = port;
|
|
130
|
+
}
|
|
99
131
|
return opts;
|
|
100
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Decide whether to start in setup mode. An explicitly passed `--schema` that
|
|
135
|
+
* doesn't exist stays a hard error (the user pointed at a specific artifact);
|
|
136
|
+
* a missing config or a missing *default* artifact opens the wizard instead.
|
|
137
|
+
*/
|
|
138
|
+
function resolveSetupReason(opts) {
|
|
139
|
+
if (!discoverAskDbConfigPath(process.cwd()))
|
|
140
|
+
return "no-config";
|
|
141
|
+
if (!opts.schemaFromFlag && !existsSync(resolve(opts.schema)))
|
|
142
|
+
return "no-artifact";
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
101
145
|
function readValue(argv, index, flag) {
|
|
102
146
|
const value = argv[index];
|
|
103
147
|
if (!value || value.startsWith("--")) {
|
|
@@ -114,17 +158,30 @@ function printHelp(stream) {
|
|
|
114
158
|
"",
|
|
115
159
|
"Options:",
|
|
116
160
|
" -s, --schema <dir> Schema v2 directory (default: introspection.outputDir from",
|
|
117
|
-
" askdb.config, or
|
|
118
|
-
" --port <number> Port to listen on (default:
|
|
119
|
-
" --host <host> Host to bind (default: 127.0.0.1
|
|
161
|
+
" askdb.config, or ./askdb/)",
|
|
162
|
+
" --port <number> Port to listen on (default: studio.listen.port from askdb.config, or 5556)",
|
|
163
|
+
" --host <host> Host to bind (default: studio.listen.host from askdb.config, or 127.0.0.1)",
|
|
120
164
|
" -V, --version Print package version",
|
|
121
165
|
" -h, --help Print this help",
|
|
122
166
|
"",
|
|
123
|
-
"AI enrichment and sample NL-to-SQL use
|
|
124
|
-
"
|
|
167
|
+
"AI enrichment and sample NL-to-SQL use the ai block in askdb.config: ai.provider,",
|
|
168
|
+
"the key in ai.providerConfig.<provider>.apiKey, and the model in ai.language.model.",
|
|
169
|
+
"Bind any value to an environment variable with env(\"NAME\").",
|
|
125
170
|
"",
|
|
126
171
|
].join("\n"));
|
|
127
172
|
}
|
|
173
|
+
function formatNetworkExposureWarning(host) {
|
|
174
|
+
return [
|
|
175
|
+
"",
|
|
176
|
+
`WARNING: Studio is bound to ${host}, which other machines on your network can reach.`,
|
|
177
|
+
"Studio can execute SQL against your configured database and write schema files.",
|
|
178
|
+
"Anyone who can load the Studio page from this address gets its session token and",
|
|
179
|
+
"can use those features (setup, resync, and driver install stay loopback-only).",
|
|
180
|
+
"Only do this on a network you trust; the default 127.0.0.1 keeps Studio local.",
|
|
181
|
+
"",
|
|
182
|
+
"",
|
|
183
|
+
].join("\n");
|
|
184
|
+
}
|
|
128
185
|
function firstPrivateAddress() {
|
|
129
186
|
for (const entries of Object.values(networkInterfaces())) {
|
|
130
187
|
for (const entry of entries ?? []) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.4 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:block))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:""}}}@layer theme{:root,:host{--font-sans:var(--font-sans);--font-mono:var(--font-mono);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-green-500:oklch(72.3% .219 149.579);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--font-weight-medium:500;--font-weight-semibold:600;--radius-xs:.125rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.top-0{top:0}.top-1\.5{top:calc(var(--spacing) * 1.5)}.top-3\.5{top:calc(var(--spacing) * 3.5)}.top-4{top:calc(var(--spacing) * 4)}.right-0{right:0}.right-1{right:var(--spacing)}.right-3{right:calc(var(--spacing) * 3)}.right-4{right:calc(var(--spacing) * 4)}.bottom-0{bottom:0}.left-0{left:0}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mx-3\.5{margin-inline:calc(var(--spacing) * 3.5)}.mt-auto{margin-top:auto}.mr-2{margin-right:calc(var(--spacing) * 2)}.-ml-1{margin-left:calc(var(--spacing) * -1)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.\!h-4{height:calc(var(--spacing) * 4)!important}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-auto{height:auto}.h-full{height:100%}.h-svh{height:100svh}.\!min-h-0{min-height:0!important}.min-h-0{min-height:0}.min-h-6{min-height:calc(var(--spacing) * 6)}.min-h-24{min-height:calc(var(--spacing) * 24)}.min-h-32{min-height:calc(var(--spacing) * 32)}.min-h-36{min-height:calc(var(--spacing) * 36)}.min-h-48{min-height:calc(var(--spacing) * 48)}.min-h-svh{min-height:100svh}.w-\(--sidebar-width\){width:var(--sidebar-width)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-3\/4{width:75%}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.max-w-\(--skeleton-width\){max-width:var(--skeleton-width)}.max-w-full{max-width:100%}.min-w-0{min-width:0}.min-w-5{min-width:calc(var(--spacing) * 5)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.origin-\(--radix-tooltip-content-transform-origin\){transform-origin:var(--radix-tooltip-content-transform-origin)}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-x-px{--tw-translate-x:-1px;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-px{--tw-translate-x:1px;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-\[calc\(-50\%_-_2px\)\]{--tw-translate-y:calc(-50% - 2px);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-45{rotate:45deg}.transform{transform:var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, )}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-4{gap:calc(var(--spacing) * 4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.rounded-\[2px\]{border-radius:2px}.rounded-md{border-radius:var(--radius-md)}.rounded-xs{border-radius:var(--radius-xs)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-border,.border-input{border-color:var(--border)}.border-sidebar-border{border-color:var(--sidebar-border)}.bg-background{background-color:var(--bg)}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\/50{background-color:color-mix(in oklab, var(--color-black) 50%, transparent)}}.bg-border{background-color:var(--border)}.bg-destructive{background-color:var(--red-600)}.bg-foreground{background-color:var(--ink-900)}.bg-primary{background-color:var(--red-600)}.bg-secondary{background-color:var(--surface-2)}.bg-sidebar{background-color:var(--sidebar)}.bg-sidebar-border{background-color:var(--sidebar-border)}.bg-transparent{background-color:#0000}.bg-warning{background-color:#fef3cd}.fill-foreground{fill:var(--ink-900)}.p-0{padding:0}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-6{padding-block:calc(var(--spacing) * 6)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-balance{text-wrap:balance}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.text-background{color:var(--bg)}.text-destructive-foreground{color:#fff}.text-foreground{color:var(--ink-900)}.text-green-500{color:var(--color-green-500)}.text-muted-foreground{color:var(--ink-500)}.text-primary{color:var(--red-600)}.text-primary-foreground{color:#fff}.text-secondary-foreground{color:var(--ink-900)}.text-sidebar-foreground,.text-sidebar-foreground\/70{color:var(--sidebar-foreground)}@supports (color:color-mix(in lab, red, red)){.text-sidebar-foreground\/70{color:color-mix(in oklab, var(--sidebar-foreground) 70%, transparent)}}.text-warning-foreground{color:var(--amber-500)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, )}.no-underline{text-decoration-line:none}.underline-offset-4{text-underline-offset:4px}.opacity-70{opacity:.7}.shadow-\[0_0_0_1px_var\(--sidebar-border\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,var(--sidebar-border));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-sidebar-ring{--tw-ring-color:var(--sidebar-ring)}.ring-offset-background{--tw-ring-offset-color:var(--bg)}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, )}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[color\,box-shadow\]{transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[left\,right\,width\]{transition-property:left,right,width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[margin\,opacity\]{transition-property:margin,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\,height\,padding\]{transition-property:width,height,padding;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-linear{--tw-ease:linear;transition-timing-function:linear}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}:is(:where(.group\/menu-item):focus-within .group-focus-within\/menu-item\:opacity-100){opacity:1}@media (hover:hover){:is(:where(.group\/menu-item):hover .group-hover\/menu-item\:opacity-100){opacity:1}}:is(:where(.group\/menu-item):has([data-sidebar=menu-action]) .group-has-data-\[sidebar\=menu-action\]\/menu-item\:pr-8){padding-right:calc(var(--spacing) * 8)}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:-mt-8){margin-top:calc(var(--spacing) * -8)}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:hidden){display:none}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:size-8\!){width:calc(var(--spacing) * 8)!important;height:calc(var(--spacing) * 8)!important}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:w-\(--sidebar-width-icon\)){width:var(--sidebar-width-icon)}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:w-\[calc\(var\(--sidebar-width-icon\)\+\(--spacing\(4\)\)\)\]){width:calc(var(--sidebar-width-icon) + (calc(var(--spacing) * 4)))}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:w-\[calc\(var\(--sidebar-width-icon\)\+\(--spacing\(4\)\)\+2px\)\]){width:calc(var(--sidebar-width-icon) + (calc(var(--spacing) * 4)) + 2px)}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:justify-center){justify-content:center}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:overflow-hidden){overflow:hidden}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:p-0\!){padding:0!important}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:p-2\!){padding:calc(var(--spacing) * 2)!important}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:px-0){padding-inline:0}:is(:where(.group)[data-collapsible=icon] .group-data-\[collapsible\=icon\]\:opacity-0){opacity:0}:is(:where(.group)[data-collapsible=offcanvas] .group-data-\[collapsible\=offcanvas\]\:right-\[calc\(var\(--sidebar-width\)\*-1\)\]){right:calc(var(--sidebar-width) * -1)}:is(:where(.group)[data-collapsible=offcanvas] .group-data-\[collapsible\=offcanvas\]\:left-\[calc\(var\(--sidebar-width\)\*-1\)\]){left:calc(var(--sidebar-width) * -1)}:is(:where(.group)[data-collapsible=offcanvas] .group-data-\[collapsible\=offcanvas\]\:w-0){width:0}:is(:where(.group)[data-collapsible=offcanvas] .group-data-\[collapsible\=offcanvas\]\:translate-x-0){--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}:is(:where(.group)[data-side=left] .group-data-\[side\=left\]\:-right-4){right:calc(var(--spacing) * -4)}:is(:where(.group)[data-side=left] .group-data-\[side\=left\]\:border-r){border-right-style:var(--tw-border-style);border-right-width:1px}:is(:where(.group)[data-side=right] .group-data-\[side\=right\]\:left-0){left:0}:is(:where(.group)[data-side=right] .group-data-\[side\=right\]\:rotate-180){rotate:180deg}:is(:where(.group)[data-side=right] .group-data-\[side\=right\]\:border-l){border-left-style:var(--tw-border-style);border-left-width:1px}:is(:where(.group)[data-variant=floating] .group-data-\[variant\=floating\]\:rounded-lg){border-radius:var(--radius-lg)}:is(:where(.group)[data-variant=floating] .group-data-\[variant\=floating\]\:border){border-style:var(--tw-border-style);border-width:1px}:is(:where(.group)[data-variant=floating] .group-data-\[variant\=floating\]\:border-sidebar-border){border-color:var(--sidebar-border)}:is(:where(.group)[data-variant=floating] .group-data-\[variant\=floating\]\:shadow-sm){--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}@media (hover:hover){:is(:where(.peer\/menu-button):hover~.peer-hover\/menu-button\:text-sidebar-accent-foreground){color:var(--sidebar-accent-foreground)}}:is(:where(.peer\/menu-button)[data-active=true]~.peer-data-\[active\=true\]\/menu-button\:text-sidebar-accent-foreground){color:var(--sidebar-accent-foreground)}:is(:where(.peer\/menu-button)[data-size=default]~.peer-data-\[size\=default\]\/menu-button\:top-1\.5){top:calc(var(--spacing) * 1.5)}:is(:where(.peer\/menu-button)[data-size=lg]~.peer-data-\[size\=lg\]\/menu-button\:top-2\.5){top:calc(var(--spacing) * 2.5)}:is(:where(.peer\/menu-button)[data-size=sm]~.peer-data-\[size\=sm\]\/menu-button\:top-1){top:var(--spacing)}.selection\:bg-primary ::selection{background-color:var(--red-600)}.selection\:bg-primary::selection{background-color:var(--red-600)}.selection\:text-primary-foreground ::selection{color:#fff}.selection\:text-primary-foreground::selection{color:#fff}.file\:inline-flex::file-selector-button{display:inline-flex}.file\:h-7::file-selector-button{height:calc(var(--spacing) * 7)}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--ink-900)}.placeholder\:text-muted-foreground::placeholder{color:var(--ink-500)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:-inset-2:after{content:var(--tw-content);inset:calc(var(--spacing) * -2)}.after\:inset-y-0:after{content:var(--tw-content);inset-block:0}.after\:left-1\/2:after{content:var(--tw-content);left:50%}.after\:w-\[2px\]:after{content:var(--tw-content);width:2px}:is(:where(.group)[data-collapsible=offcanvas] .group-data-\[collapsible\=offcanvas\]\:after\:left-full):after{content:var(--tw-content);left:100%}@media (hover:hover){.hover\:bg-destructive\/90:hover{background-color:var(--red-600)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--red-600) 90%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--red-600)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--red-600) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--surface-2)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--surface-2) 80%, transparent)}}.hover\:bg-sidebar-accent:hover{background-color:var(--sidebar-accent)}.hover\:text-sidebar-accent-foreground:hover{color:var(--sidebar-accent-foreground)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-\[0_0_0_1px_var\(--sidebar-accent\)\]:hover{--tw-shadow:0 0 0 1px var(--tw-shadow-color,var(--sidebar-accent));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}:is(:where(.group)[data-collapsible=offcanvas] .hover\:group-data-\[collapsible\=offcanvas\]\:bg-sidebar:hover){background-color:var(--sidebar)}.hover\:after\:bg-sidebar-border:hover:after{content:var(--tw-content);background-color:var(--sidebar-border)}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--red-500)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.focus-visible\:border-ring:focus-visible{border-color:var(--red-500)}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-\[1\.5px\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset, ) 0 0 0 calc(1.5px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:var(--red-600)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--red-600) 20%, transparent)}}.focus-visible\:ring-ring:focus-visible,.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--red-500)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--red-500) 50%, transparent)}}.active\:bg-sidebar-accent:active{background-color:var(--sidebar-accent)}.active\:text-sidebar-accent-foreground:active{color:var(--sidebar-accent-foreground)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}:where([data-side=left]) .in-data-\[side\=left\]\:cursor-w-resize{cursor:w-resize}:where([data-side=right]) .in-data-\[side\=right\]\:cursor-e-resize{cursor:e-resize}.has-data-\[variant\=inset\]\:bg-sidebar:has([data-variant=inset]){background-color:var(--sidebar)}.has-\[\>svg\]\:px-1\.5:has(>svg){padding-inline:calc(var(--spacing) * 1.5)}.has-\[\>svg\]\:px-2\.5:has(>svg){padding-inline:calc(var(--spacing) * 2.5)}.has-\[\>svg\]\:px-3:has(>svg){padding-inline:calc(var(--spacing) * 3)}.has-\[\>svg\]\:px-4:has(>svg){padding-inline:calc(var(--spacing) * 4)}.aria-disabled\:pointer-events-none[aria-disabled=true]{pointer-events:none}.aria-disabled\:opacity-50[aria-disabled=true]{opacity:.5}.aria-invalid\:border-destructive[aria-invalid=true]{border-color:var(--red-600)}.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:var(--red-600)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--red-600) 20%, transparent)}}.data-\[active\=true\]\:bg-sidebar-accent[data-active=true]{background-color:var(--sidebar-accent)}.data-\[active\=true\]\:font-medium[data-active=true]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.data-\[active\=true\]\:text-sidebar-accent-foreground[data-active=true]{color:var(--sidebar-accent-foreground)}.data-\[orientation\=horizontal\]\:h-px[data-orientation=horizontal]{height:1px}.data-\[orientation\=horizontal\]\:w-full[data-orientation=horizontal]{width:100%}.data-\[orientation\=vertical\]\:h-full[data-orientation=vertical]{height:100%}.data-\[orientation\=vertical\]\:w-px[data-orientation=vertical]{width:1px}.data-\[state\=closed\]\:duration-300[data-state=closed]{--tw-duration:.3s;transition-duration:.3s}.data-\[state\=open\]\:bg-secondary[data-state=open]{background-color:var(--surface-2)}.data-\[state\=open\]\:opacity-100[data-state=open]{opacity:1}.data-\[state\=open\]\:duration-500[data-state=open]{--tw-duration:.5s;transition-duration:.5s}@media (hover:hover){.data-\[state\=open\]\:hover\:bg-sidebar-accent[data-state=open]:hover{background-color:var(--sidebar-accent)}.data-\[state\=open\]\:hover\:text-sidebar-accent-foreground[data-state=open]:hover{color:var(--sidebar-accent-foreground)}}@media (width>=40rem){.sm\:flex{display:flex}.sm\:max-w-sm{max-width:var(--container-sm)}}@media (width>=48rem){.md\:block{display:block}.md\:flex{display:flex}.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.md\:opacity-0{opacity:0}:is(:where(.peer)[data-variant=inset]~.md\:peer-data-\[variant\=inset\]\:m-2){margin:calc(var(--spacing) * 2)}:is(:where(.peer)[data-variant=inset]~.md\:peer-data-\[variant\=inset\]\:ml-0){margin-left:0}:is(:where(.peer)[data-variant=inset]~.md\:peer-data-\[variant\=inset\]\:rounded-xl){border-radius:var(--radius-xl)}:is(:where(.peer)[data-variant=inset]~.md\:peer-data-\[variant\=inset\]\:shadow-sm){--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}:is(:where(.peer)[data-state=collapsed]~:is(:where(.peer)[data-variant=inset]~.md\:peer-data-\[variant\=inset\]\:peer-data-\[state\=collapsed\]\:ml-2)){margin-left:calc(var(--spacing) * 2)}.md\:after\:hidden:after{content:var(--tw-content);display:none}}.dark\:border-input:is(.dark *){border-color:var(--border)}.dark\:bg-amber-500\/15:is(.dark *){background-color:#f99c0026}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-500\/15:is(.dark *){background-color:color-mix(in oklab, var(--color-amber-500) 15%, transparent)}}.dark\:bg-destructive\/60:is(.dark *){background-color:var(--red-600)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-destructive\/60:is(.dark *){background-color:color-mix(in oklab, var(--red-600) 60%, transparent)}}.dark\:bg-input\/30:is(.dark *){background-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-input\/30:is(.dark *){background-color:color-mix(in oklab, var(--border) 30%, transparent)}}.dark\:text-amber-400:is(.dark *){color:var(--color-amber-400)}@media (hover:hover){.dark\:hover\:bg-input\/50:is(.dark *):hover{background-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-input\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--border) 50%, transparent)}}}.dark\:focus-visible\:ring-destructive\/40:is(.dark *):focus-visible{--tw-ring-color:var(--red-600)}@supports (color:color-mix(in lab, red, red)){.dark\:focus-visible\:ring-destructive\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab, var(--red-600) 40%, transparent)}}.dark\:aria-invalid\:ring-destructive\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--red-600)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:ring-destructive\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--red-600) 40%, transparent)}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-3 svg:not([class*=size-]){width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\>button\]\:hidden>button{display:none}.\[\&\>span\:last-child\]\:truncate>span:last-child{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.\[\&\>svg\]\:size-4>svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\>svg\]\:shrink-0>svg{flex-shrink:0}.\[\&\>svg\]\:text-sidebar-accent-foreground>svg{color:var(--sidebar-accent-foreground)}[data-side=left][data-collapsible=offcanvas] .\[\[data-side\=left\]\[data-collapsible\=offcanvas\]_\&\]\:-right-2{right:calc(var(--spacing) * -2)}[data-side=left][data-state=collapsed] .\[\[data-side\=left\]\[data-state\=collapsed\]_\&\]\:cursor-e-resize{cursor:e-resize}[data-side=right][data-collapsible=offcanvas] .\[\[data-side\=right\]\[data-collapsible\=offcanvas\]_\&\]\:-left-2{left:calc(var(--spacing) * -2)}[data-side=right][data-state=collapsed] .\[\[data-side\=right\]\[data-state\=collapsed\]_\&\]\:cursor-w-resize{cursor:w-resize}}:root{--red-50:#fbf1f2;--red-100:#f7e2e4;--red-200:#efc5cb;--red-400:#cf5867;--red-500:#b8313f;--red-600:#9f1024;--red-700:#85101f;--red-800:#5f0a16;--bg:#fafaf9;--surface:#fff;--surface-2:#f5f4f1;--surface-3:#efeeea;--border:#e7e5e3;--border-strong:#d6d3cf;--ink-900:#1a1815;--ink-700:#3c3a36;--ink-500:#6b6862;--ink-400:#8a8680;--ink-300:#a8a39c;--green-500:#16a34a;--amber-500:#d97706;--blue-500:#2563eb;--font-sans:"Inter", -apple-system, BlinkMacSystemFont, sans-serif;--font-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--radius-sm:4px;--radius:6px;--radius-lg:10px;--shadow-1:0 1px 0 #14120f0a, 0 1px 2px #14120f0a;--shadow-2:0 4px 14px #14120f0f, 0 1px 2px #14120f0a;--nav-w:200px;--sub-w:400px;--pad-y:11px;--pad-x:14px;--sidebar:var(--surface);--sidebar-foreground:var(--ink-700);--sidebar-primary:var(--red-600);--sidebar-primary-foreground:#fff;--sidebar-accent:var(--surface-2);--sidebar-accent-foreground:var(--ink-900);--sidebar-border:var(--border);--sidebar-ring:var(--red-500)}[data-theme=dark]{--bg:#141210;--surface:#1c1a17;--surface-2:#252320;--surface-3:#2e2b28;--border:#332f2b;--border-strong:#403c37;--ink-900:#f5f3f0;--ink-700:#d4d0ca;--ink-500:#9a958d;--ink-400:#7a756d;--ink-300:#5c5852;--red-50:#2a1014;--red-100:#3a161c;--red-600:#c54353;--red-700:#a02a3a;--green-500:#4ade80;--amber-500:#fbbf24;--blue-500:#60a5fa;--shadow-1:0 1px 0 #0000004d, 0 1px 2px #0003;--shadow-2:0 4px 14px #00000059}*{box-sizing:border-box}html,body,#root{height:100%;overflow:hidden}body{background:var(--bg);color:var(--ink-900);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;margin:0;font-size:13px;line-height:1.45}button{font:inherit;color:inherit;cursor:default}input,textarea,select{font:inherit;color:inherit}code,pre,.mono{font-family:var(--font-mono)}.app-shell{background:var(--bg);justify-content:center;align-items:center;height:100vh;display:flex}.topbar{border-bottom:1px solid var(--border);background:var(--surface);color:var(--ink-700);align-items:center;gap:10px;height:38px;padding:0 14px;font-size:12px;display:flex}.app-content{grid-template-columns:var(--sub-w) 1fr;flex:1;min-height:0;display:grid;overflow:hidden}.app-content>.main-pane:only-child{grid-column:1/-1}.topbar .crumbs{flex:1;align-items:center;gap:8px;min-width:0;display:flex}.topbar .crumb{color:var(--ink-500)}.topbar .crumb.cur{color:var(--ink-900);font-weight:500}.topbar .sep{color:var(--ink-300)}.topbar .right{align-items:center;gap:8px;display:flex}.cmd-palette{border:1px solid var(--border);background:var(--surface-2);height:24px;color:var(--ink-400);cursor:default;border-radius:6px;align-items:center;gap:8px;width:240px;padding:0 8px 0 10px;font-size:11.5px;display:flex}.cmd-palette:hover{background:var(--surface);color:var(--ink-700)}.kbd{border:1px solid var(--border);background:var(--surface);height:18px;font:500 10px/1 var(--font-mono);color:var(--ink-500);border-bottom-width:2px;border-radius:4px;align-items:center;gap:3px;padding:0 5px;display:inline-flex}.btn.primary .kbd{color:#ffffffd9;background:#ffffff26;border-color:#ffffff4d}[data-sidebar=menu-button].active{background:var(--sidebar-accent);color:var(--sidebar-accent-foreground);font-weight:600}.sub-rail{border-right:1px solid var(--border);background:var(--surface);flex-direction:column;min-height:0;display:flex}.sub-rail-hd{border-bottom:1px solid var(--border);justify-content:space-between;align-items:center;gap:6px;padding:10px 14px 8px;display:flex}.sub-rail-hd h2{letter-spacing:-.01em;color:var(--ink-900);align-items:center;gap:8px;margin:0;font-size:13px;font-weight:600;display:flex}.sub-rail-search{border:1px solid var(--border);background:var(--surface-2);border-radius:6px;align-items:center;gap:8px;height:28px;padding:0 10px;display:flex}.sub-rail-search input{color:var(--ink-900);background:0 0;border:0;outline:0;flex:1;font-size:12.5px}.sub-rail-search input::placeholder{color:var(--ink-400)}.enrich-filter-bar{border-bottom:1px solid var(--border);flex-wrap:wrap;gap:4px;padding:6px 10px;display:flex}.enrich-filter-chip{border:1px solid var(--border);height:22px;color:var(--ink-400);cursor:pointer;white-space:nowrap;background:0 0;border-radius:11px;align-items:center;gap:4px;padding:0 7px;font-size:10.5px;transition:all .12s;display:flex}.enrich-filter-chip:hover{background:var(--surface-2);color:var(--ink-700)}.enrich-filter-chip.active{color:var(--ink-700);border-color:var(--border-strong);background:var(--surface-2)}.enrich-filter-chip.active.enriched{border-color:var(--green-500);background:var(--green-500)}@supports (color:color-mix(in lab, red, red)){.enrich-filter-chip.active.enriched{background:color-mix(in srgb, var(--green-500) 8%, transparent)}}.enrich-filter-chip.active.partial{border-color:var(--amber-500);background:var(--amber-500)}@supports (color:color-mix(in lab, red, red)){.enrich-filter-chip.active.partial{background:color-mix(in srgb, var(--amber-500) 8%, transparent)}}.enrich-filter-chip.active.none{border-color:var(--ink-300);background:var(--surface-2)}.enrich-filter-chip.active.untracked{color:var(--amber-700);border-color:var(--amber-500);background:var(--amber-500)}@supports (color:color-mix(in lab, red, red)){.enrich-filter-chip.active.untracked{background:color-mix(in srgb, var(--amber-500) 10%, transparent)}}.enrich-filter-chip:not(.active){opacity:.5}.enrich-filter-chip:not(.active):hover{opacity:.8}.enrich-filter-chip .enrich-dot{width:6px;height:6px}.enrich-filter-chip svg{flex:none}.enrich-filter-label{font-weight:500}.enrich-filter-count{font-variant-numeric:tabular-nums;font-weight:600}.sub-rail-list{flex:1;padding:4px 6px;overflow:auto}.sub-rail-list::-webkit-scrollbar{width:8px}.sub-rail-list::-webkit-scrollbar-thumb{background:var(--border-strong);background-clip:content-box;border:2px solid #0000;border-radius:4px}.sub-rail-row{cursor:default;width:100%;color:var(--ink-700);text-align:left;border-radius:6px;align-items:center;gap:8px;padding:5px 10px;text-decoration:none;transition:background .12s;display:flex}.sub-rail-row:hover{background:var(--surface-2);color:var(--ink-900)}.sub-rail-row.active{background:var(--red-50);color:var(--red-700)}.sub-rail-row .row-name{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12.5px;font-weight:500;overflow:hidden}.sub-rail-row .row-meta{color:var(--ink-400);text-overflow:ellipsis;white-space:nowrap;font-size:10.5px;overflow:hidden}.sub-rail-row.active .row-meta{color:var(--red-600)}.sub-rail-row.untracked{opacity:.55}.sub-rail-row.untracked:hover{opacity:.8}.sub-rail-row.untracked.active{opacity:1}.sub-section-hd{letter-spacing:.08em;text-transform:uppercase;color:var(--ink-400);align-items:center;gap:6px;padding:10px 12px 4px;font-size:9.5px;font-weight:600;display:flex}.sub-section-hd .count{color:var(--ink-300);letter-spacing:0;font-weight:500}.schema-group{margin-bottom:2px}.schema-group-hd{text-align:left;cursor:pointer;width:100%;color:var(--ink-600);text-transform:uppercase;letter-spacing:.04em;background:0 0;border:none;border-radius:6px;justify-content:flex-start;align-items:center;gap:6px;padding:6px 10px;font-size:11px;font-weight:600;transition:background .12s;display:flex}.schema-group-hd:hover{background:var(--surface-2);color:var(--ink-900)}.schema-chevron{color:var(--ink-400);flex-shrink:0;transition:transform .15s}.schema-icon{color:var(--ink-400);flex-shrink:0}.schema-name{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.schema-count{color:var(--ink-400);letter-spacing:0;text-transform:none;flex-shrink:0;font-size:10px;font-weight:500}.schema-group-bd{padding-left:8px}.table-leaf{padding-left:28px}.main-pane{background:var(--bg);flex-direction:column;min-width:0;min-height:0;display:flex}.main-hd{border-bottom:1px solid var(--border);background:var(--surface);align-items:center;gap:14px;padding:10px 18px;display:flex}.main-hd .main-title{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.main-hd h1{letter-spacing:-.02em;color:var(--ink-900);align-items:center;gap:10px;margin:0;font-size:16px;font-weight:600;display:flex}.main-hd .main-sub{color:var(--ink-500);font-size:11px;font-family:var(--font-mono)}.main-hd .main-actions{align-items:center;gap:8px;display:flex}.main-body{flex:1;padding:14px 18px 40px;overflow:auto}.sub-tabs{border-bottom:1px solid var(--border);background:var(--surface);gap:2px;padding:0 18px;display:flex}.sub-tab{height:30px;color:var(--ink-500);background:0 0;border:none;border-bottom:2px solid #0000;align-items:center;gap:6px;margin-bottom:-1px;padding:0 12px;font-size:12px;font-weight:500;text-decoration:none;transition:color .12s;display:flex}.sub-tab:hover{color:var(--ink-900)}.sub-tab.active{color:var(--red-600);border-bottom-color:var(--red-600)}.sub-tab .tab-badge{color:var(--ink-400);font-variant-numeric:tabular-nums;font-size:10.5px}.sub-tab.active .tab-badge{color:var(--red-600)}.btn{border:1px solid var(--border);background:var(--surface);height:28px;color:var(--ink-900);cursor:default;border-radius:6px;justify-content:center;align-items:center;gap:6px;padding:0 11px;font-size:12px;font-weight:500;text-decoration:none;transition:all .12s;display:inline-flex}.btn:hover{background:var(--surface-2);border-color:var(--border-strong)}.btn.primary{background:var(--red-600);color:#fff;border-color:var(--red-600);box-shadow:inset 0 -1.5px #0000002e,0 1px #14120f0a}.btn.primary:hover{background:var(--red-700);border-color:var(--red-700)}.btn.ghost{color:var(--ink-500);background:0 0;border-color:#0000}.btn.ghost:hover{background:var(--surface-2);color:var(--ink-900)}.btn.danger{color:var(--red-600);border-color:var(--red-600)}@supports (color:color-mix(in lab, red, red)){.btn.danger{border-color:color-mix(in oklab, var(--red-600), transparent 70%)}}.btn.danger:hover{background:var(--red-50)}.btn.sm{height:24px;padding:0 8px;font-size:11.5px}.btn.lg{height:32px;padding:0 13px;font-size:12.5px}.btn:disabled{opacity:.5;cursor:not-allowed}.card{background:var(--surface);border:1px solid var(--border);box-shadow:var(--shadow-1);border-radius:10px}.card-hd{border-bottom:1px solid var(--border);justify-content:space-between;align-items:center;padding:9px 14px;display:flex}.card-hd h3{color:var(--ink-900);letter-spacing:-.005em;align-items:center;gap:8px;margin:0;font-size:12.5px;font-weight:600;display:flex}.card-hd .card-meta{color:var(--ink-500);font-size:11px}.card-bd{padding:12px 14px}.card-bd.tight{padding:0}.field{flex-direction:column;gap:6px;display:flex}.field label{color:var(--ink-700);letter-spacing:.005em;justify-content:space-between;align-items:center;gap:8px;font-size:11px;font-weight:600;display:flex}.field .help{color:var(--ink-500);font-size:11px;font-weight:400}.env-var-field{border:1px solid var(--border);background:var(--surface-2);text-align:left;cursor:pointer;border-radius:6px;justify-content:space-between;align-items:center;gap:8px;width:100%;height:36px;padding:0 12px;display:flex}.env-var-field:disabled{cursor:default}.env-var-field .env-var-field-value{font-size:13px}.field input[type=text],.field input[type=number],.field input:not([type]),.field textarea,.field select{border:1px solid var(--border);background:var(--surface);color:var(--ink-900);border-radius:6px;outline:0;width:100%;padding:7px 9px;font-size:12px;transition:border-color .12s,box-shadow .12s}.field textarea{resize:vertical;min-height:64px;font-family:var(--font-sans);line-height:1.5}.field input:focus,.field textarea:focus,.field select:focus{border-color:var(--red-500);box-shadow:0 0 0 1.5px var(--red-100)}.pill{border:1px solid var(--border);background:var(--surface);height:20px;color:var(--ink-700);border-radius:10px;align-items:center;gap:6px;padding:0 8px;font-size:10.5px;display:inline-flex}.pill.ok{color:var(--green-500);border-color:var(--green-500)}@supports (color:color-mix(in lab, red, red)){.pill.ok{border-color:color-mix(in oklab, var(--green-500), transparent 70%)}}.pill.warn{color:var(--amber-500);border-color:var(--amber-500)}@supports (color:color-mix(in lab, red, red)){.pill.warn{border-color:color-mix(in oklab, var(--amber-500), transparent 70%)}}.chip{background:var(--surface-2);border:1px solid var(--border);height:20px;color:var(--ink-700);border-radius:10px;align-items:center;gap:5px;padding:0 8px;font-size:10.5px;font-weight:500;display:inline-flex}.chip.red{background:var(--red-50);border-color:var(--red-100);color:var(--red-700)}.chip.blue{background:var(--blue-500)}@supports (color:color-mix(in lab, red, red)){.chip.blue{background:color-mix(in oklab, var(--blue-500), transparent 92%)}}.chip.blue{border-color:var(--blue-500)}@supports (color:color-mix(in lab, red, red)){.chip.blue{border-color:color-mix(in oklab, var(--blue-500), transparent 80%)}}.chip.blue{color:var(--blue-500)}.chip.green{background:var(--green-500)}@supports (color:color-mix(in lab, red, red)){.chip.green{background:color-mix(in oklab, var(--green-500), transparent 92%)}}.chip.green{border-color:var(--green-500)}@supports (color:color-mix(in lab, red, red)){.chip.green{border-color:color-mix(in oklab, var(--green-500), transparent 80%)}}.chip.green{color:var(--green-500)}.chip.amber{background:var(--amber-500)}@supports (color:color-mix(in lab, red, red)){.chip.amber{background:color-mix(in oklab, var(--amber-500), transparent 92%)}}.chip.amber{border-color:var(--amber-500)}@supports (color:color-mix(in lab, red, red)){.chip.amber{border-color:color-mix(in oklab, var(--amber-500), transparent 80%)}}.chip.amber{color:var(--amber-500)}.stat-card{flex-direction:column;gap:6px;padding:10px 14px;display:flex}.stat-card .stat-label{color:var(--ink-500);text-transform:uppercase;letter-spacing:.06em;font-size:10px;font-weight:600}.stat-card .stat-num{letter-spacing:-.02em;color:var(--ink-900);font-variant-numeric:tabular-nums;font-size:22px;font-weight:600;line-height:1.1}.stat-card .stat-hint{color:var(--ink-500);font-size:11px}.stat-card .stat-delta{color:var(--ink-500);align-items:center;gap:5px;font-size:11px;display:flex}.stat-card .stat-delta.up{color:var(--green-500)}.stat-card .stat-delta.dn{color:var(--red-600)}.enrich-dot{background:var(--ink-300);border-radius:50%;flex:none;width:6px;height:6px;display:inline-block}.enrich-dot.full,.enrich-dot.enriched{background:var(--green-500)}.enrich-dot.partial{background:var(--amber-500)}.enrich-dot.none{background:var(--ink-300)}.toggle-seg{background:var(--surface-2);border:1px solid var(--border);border-radius:7px;gap:2px;margin:0;padding:2px;display:inline-flex}.toggle-seg button{height:24px;color:var(--ink-500);background:0 0;border:0;border-radius:5px;padding:0 12px;font-size:12px;font-weight:500}.toggle-seg button.on,.toggle-seg button.active{background:var(--surface);color:var(--ink-900);box-shadow:var(--shadow-1)}.tbl{border-collapse:separate;border-spacing:0;width:100%;font-size:12px}.tbl th{color:var(--ink-500);text-align:left;text-transform:uppercase;letter-spacing:.05em;background:var(--surface-2);border-bottom:1px solid var(--border);padding:6px 12px;font-size:10.5px;font-weight:600}.tbl td{border-bottom:1px solid var(--border);color:var(--ink-900);vertical-align:top;padding:7px 12px}.tbl tr:last-child td{border-bottom:0}.tbl tr:hover td{background:var(--surface-2)}.code-block{color:#f5f3f0;font:13px/1.6 var(--font-mono);white-space:pre-wrap;background:#15110f;border:1px solid #2a2421;border-radius:8px;margin:0;padding:14px 16px;overflow:auto}.code-block .k{color:#ff9ba6}.code-block .s{color:#a3e1b2}.code-block .n{color:#f4c879}.code-block .c{color:#7a756d;font-style:italic}.suggest-link{color:var(--red-600);cursor:default;background:0 0;border:none;align-items:center;gap:5px;padding:0;font-size:11.5px;font-weight:500;display:inline-flex}.suggest-link:hover{color:var(--red-700)}.bar{background:var(--surface-3);border-radius:3px;height:6px;overflow:hidden}.bar>i{background:var(--red-600);border-radius:3px;height:100%;display:block}.grid-2{grid-template-columns:1fr 1fr;gap:12px;display:grid}.grid-3{grid-template-columns:repeat(3,1fr);gap:10px;display:grid}.grid-4{grid-template-columns:repeat(4,1fr);gap:10px;display:grid}.stack{flex-direction:column;gap:12px;display:flex}.stack.tight{gap:8px}.row-h{align-items:center;gap:10px;display:flex}.spread{justify-content:space-between;align-items:center;gap:12px;display:flex}.muted{color:var(--ink-500)}.tiny{font-size:11px}.policy-edge-card{border:1px solid var(--border);border-radius:var(--radius);justify-content:space-between;align-items:start;gap:8px;padding:12px;font-size:13px;display:flex}.collapsible-btn{cursor:pointer;color:var(--ink-700);background:0 0;border:none;align-items:center;gap:6px;margin-bottom:8px;padding:0;font-size:13px;font-weight:600;display:flex}.check{color:var(--ink-700);align-items:center;gap:6px;font-size:12px;display:inline-flex}.check input{accent-color:var(--red-600);width:14px;height:14px}.status-banner{border-bottom:1px solid var(--border);align-items:center;gap:8px;min-height:32px;padding:6px 18px;font-size:12px;display:flex}.status-banner.neutral,.status-banner.loading{color:var(--ink-500)}.status-banner.success{color:var(--green-500)}.status-banner.error{color:var(--red-600)}.inline-status{overflow-wrap:anywhere;align-items:center;gap:6px;min-height:20px;font-size:12px;display:flex}.inline-status.neutral,.inline-status.loading{color:var(--ink-500)}.inline-status.success{color:var(--green-500)}.inline-status.error{color:var(--red-600)}.dialog-overlay{z-index:40;background:#14120f59;justify-content:center;align-items:center;padding:18px;display:flex;position:fixed;inset:0}.dialog{border:1px solid var(--border);background:var(--surface);width:min(720px,100%);max-height:min(760px,90vh);box-shadow:var(--shadow-2);border-radius:10px;flex-direction:column;display:flex;overflow:hidden}.dialog-hd{border-bottom:1px solid var(--border);justify-content:space-between;align-items:center;gap:10px;padding:14px 16px;display:flex}.dialog-hd h3{color:var(--ink-900);margin:0;font-size:14px;font-weight:600}.dialog-bd{flex-direction:column;flex:1;gap:10px;padding:16px;display:flex;overflow:auto}.candidate{white-space:pre-wrap;overflow-wrap:anywhere;border:1px solid var(--border);background:var(--bg);text-align:left;border-radius:6px;width:100%;padding:12px;font-size:12px}.candidate p{margin:0}.candidate:hover{border-color:var(--red-600)}@supports (color:color-mix(in lab, red, red)){.candidate:hover{border-color:color-mix(in oklab, var(--red-600), transparent 55%)}}.candidate:hover{background:var(--red-50)}.candidate-actions{justify-content:flex-end;margin-top:10px;display:flex}.sql-block{white-space:pre-wrap;overflow-wrap:anywhere;color:#f5f3f0;background:#15110f;border-radius:8px;min-height:120px;margin:0;padding:14px 16px;font-size:12px;line-height:1.5}.plain-block,.warning-block{white-space:pre-wrap;overflow-wrap:anywhere;border:1px solid var(--border);background:var(--surface);border-radius:6px;margin:0;padding:10px;font-size:12px;line-height:1.5}.warning-block{border-color:var(--amber-500)}@supports (color:color-mix(in lab, red, red)){.warning-block{border-color:color-mix(in oklab, var(--amber-500), transparent 75%)}}.warning-block{background:var(--amber-500)}@supports (color:color-mix(in lab, red, red)){.warning-block{background:color-mix(in oklab, var(--amber-500), transparent 92%)}}.warning-block{color:var(--amber-500)}.definition-list{grid-template-columns:110px minmax(0,1fr);gap:8px 12px;font-size:12px;display:grid}.definition-list dt{color:var(--ink-500);font-weight:600}.definition-list dd{overflow-wrap:anywhere;min-width:0}.chunk-card{border:1px solid var(--border);background:var(--surface);border-radius:8px;min-width:0;padding:12px}.chunk-text{border:1px solid var(--border);background:var(--bg);max-height:220px;color:var(--ink-900);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:6px;margin-top:10px;padding:10px;font-size:12px;line-height:1.5;overflow:auto}.chunk-toggle{border:1px solid var(--border);background:var(--bg);border-radius:999px;align-items:center;gap:5px;padding:4px 8px;font-size:12px;display:inline-flex}.chunk-toggle input{width:auto}.column-row{border:1px solid var(--border);background:var(--surface);border-radius:8px;min-width:0;padding:14px}.relationship-row{border:1px solid var(--border);background:var(--surface);border-radius:6px;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:8px;padding:10px;font-size:12px;display:grid}.usage-summary{gap:8px;display:grid}.usage-summary h3{color:var(--ink-500);margin:0;font-size:12px;font-weight:700}.usage-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;display:grid}.usage-grid div{border:1px solid var(--border);background:var(--bg);border-radius:6px;min-width:0;padding:8px}.usage-grid .usage-total{grid-column:1/-1}.usage-grid dt{color:var(--ink-500);font-size:11px;font-weight:600}.usage-grid dd{overflow-wrap:anywhere;margin-top:3px;font-size:15px;font-weight:700}.concept-id-input{border:1px solid var(--border);border-radius:var(--radius);background:var(--bg);align-items:center;height:36px;transition:border-color .12s,box-shadow .12s;display:flex;overflow:hidden}.concept-id-input:focus-within{border-color:var(--red-500);box-shadow:0 0 0 1.5px var(--red-100)}.concept-id-prefix{background:var(--surface-2);border-right:1px solid var(--border);height:100%;color:var(--ink-400);font-family:var(--font-mono);white-space:nowrap;-webkit-user-select:none;user-select:none;align-items:center;padding:0 8px;font-size:12px;font-weight:500;display:flex}.concept-id-slug{min-width:0;height:100%;font-family:var(--font-mono);color:var(--ink-900);background:0 0;border:none;outline:none;flex:1;padding:0 8px;font-size:12px}.concept-id-slug::placeholder{color:var(--ink-400)}.links-input{border:1px solid var(--border);border-radius:var(--radius);background:var(--bg);transition:border-color .12s,box-shadow .12s;position:relative}.links-input:focus-within{border-color:var(--red-500);box-shadow:0 0 0 1.5px var(--red-100)}.links-chips{flex-wrap:wrap;gap:4px;padding:6px 8px 2px;display:flex}.links-chip{height:22px;font-size:11px;font-family:var(--font-mono);white-space:nowrap;border-radius:4px;align-items:center;gap:3px;max-width:220px;padding:0 4px 0 6px;display:inline-flex;overflow:hidden}.links-chip.table{background:var(--blue-500)}@supports (color:color-mix(in lab, red, red)){.links-chip.table{background:color-mix(in srgb, var(--blue-500) 10%, transparent)}}.links-chip.table{color:var(--blue-500);border:1px solid var(--blue-500)}@supports (color:color-mix(in lab, red, red)){.links-chip.table{border:1px solid color-mix(in srgb, var(--blue-500) 25%, transparent)}}.links-chip.column{background:var(--green-500)}@supports (color:color-mix(in lab, red, red)){.links-chip.column{background:color-mix(in srgb, var(--green-500) 10%, transparent)}}.links-chip.column{color:var(--green-500);border:1px solid var(--green-500)}@supports (color:color-mix(in lab, red, red)){.links-chip.column{border:1px solid color-mix(in srgb, var(--green-500) 25%, transparent)}}.links-chip-label{text-overflow:ellipsis;overflow:hidden}.links-chip-remove{width:14px;height:14px;color:inherit;opacity:.6;cursor:pointer;background:0 0;border:none;border-radius:2px;flex-shrink:0;justify-content:center;align-items:center;display:flex}.links-chip-remove:hover{opacity:1;background:#00000014}.links-search{height:32px;color:var(--ink-400);align-items:center;gap:6px;padding:0 8px;display:flex}.links-search-input{min-width:0;color:var(--ink-900);background:0 0;border:none;outline:none;flex:1;font-size:12px}.links-search-input::placeholder{color:var(--ink-400)}.links-dropdown{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);max-height:240px;box-shadow:var(--shadow-2);z-index:50;margin:0;padding:0;list-style:none;position:absolute;top:100%;left:0;right:0;overflow:auto}.links-dropdown-item{text-align:left;width:100%;color:var(--ink-700);cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:6px 10px;font-size:12px;transition:background 80ms;display:flex}.links-dropdown-item:hover,.links-dropdown-item.highlighted{background:var(--surface-2);color:var(--ink-900)}.links-kind-badge{border-radius:3px;flex-shrink:0;justify-content:center;align-items:center;width:18px;height:18px;font-size:10px;font-weight:700;display:inline-flex}.links-kind-badge.table{background:var(--blue-500)}@supports (color:color-mix(in lab, red, red)){.links-kind-badge.table{background:color-mix(in srgb, var(--blue-500) 12%, transparent)}}.links-kind-badge.table{color:var(--blue-500)}.links-kind-badge.column{background:var(--green-500)}@supports (color:color-mix(in lab, red, red)){.links-kind-badge.column{background:color-mix(in srgb, var(--green-500) 12%, transparent)}}.links-kind-badge.column{color:var(--green-500)}.links-dropdown-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--font-mono);flex:1;overflow:hidden}.links-dropdown-more{color:var(--ink-400);text-align:center;border-top:1px solid var(--border);padding:6px 10px;font-size:11px}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:1s linear infinite spin}@keyframes fadeIn{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}.fade-in{animation:.18s ease-out fadeIn}.toggle-seg button{transition:background .12s,color .12s,box-shadow .12s}.sub-tab{transition:color .12s,border-color .12s}.card{transition:box-shadow .15s}.card:hover{box-shadow:var(--shadow-2)}.pill{transition:background .12s,border-color .12s}:focus-visible,button:focus-visible,a:focus-visible{outline:1.5px solid var(--red-500);outline-offset:1px}input:focus-visible,textarea:focus-visible,select:focus-visible{border-color:var(--red-500);box-shadow:0 0 0 1.5px var(--red-100);outline:none}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--border-strong);background-clip:content-box;border:2px solid #0000;border-radius:4px}::-webkit-scrollbar-thumb:hover{background-color:var(--ink-300)}@media (width<=1280px){:root{--sub-w:220px}.grid-4,.grid-3{grid-template-columns:repeat(2,1fr)}}@media (width<=960px){:root{--sub-w:0px}.sub-rail{display:none}.app-content,.grid-4,.grid-3,.grid-2{grid-template-columns:1fr}}[data-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--sidebar:var(--surface);--sidebar-foreground:var(--ink-700);--sidebar-primary:var(--red-600);--sidebar-primary-foreground:#fff;--sidebar-accent:var(--surface-2);--sidebar-accent-foreground:var(--ink-900);--sidebar-border:var(--border);--sidebar-ring:var(--red-500);--color-accent:var(--surface-2);--color-accent-foreground:var(--ink-900)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes pulse{50%{opacity:.5}}
|