@macroscope/cli 0.0.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,463 @@
1
+ // src/cloud/client.ts
2
+ import { readFile, stat } from "fs/promises";
3
+ import { homedir } from "os";
4
+ import path from "path";
5
+
6
+ // ../contracts/dist/index.js
7
+ import { z } from "zod";
8
+ import { z as z2 } from "zod";
9
+ import { z as z3 } from "zod";
10
+ import { z as z4 } from "zod";
11
+ import { z as z5 } from "zod";
12
+ import { z as z6 } from "zod";
13
+ var FILESYSTEM_LAYOUT = {
14
+ user: {
15
+ /** `~/.macroscope/` */
16
+ rootDir: ".macroscope",
17
+ /** `~/.macroscope/credentials` — OAuth token store, mode 0600. */
18
+ credentialsFile: ".macroscope/credentials",
19
+ /** `~/.macroscope/machine-id` — stable per-install identifier. */
20
+ machineIdFile: ".macroscope/machine-id"
21
+ },
22
+ project: {
23
+ /** `<project>/.macroscope/` */
24
+ rootDir: ".macroscope",
25
+ /** `<project>/.macroscope/blueprints/` — one folder per kind. */
26
+ blueprintsDir: ".macroscope/blueprints",
27
+ /** `<project>/.macroscope/cache/` */
28
+ cacheDir: ".macroscope/cache",
29
+ /** `<project>/.macroscope/cache/hashes.json` — content-hash cache used by catch-up scan. */
30
+ hashesFile: ".macroscope/cache/hashes.json",
31
+ /** `<project>/.macroscope/cache/queue.json` — watcher push queue, survives restart. */
32
+ queueFile: ".macroscope/cache/queue.json"
33
+ }
34
+ };
35
+ var BlockManifestSchema = z.object({
36
+ /** Must reference a registered blueprint's `kind`. */
37
+ kind: z.string().min(1),
38
+ /** Optional override for the auto-derived block id (POSIX relative path). */
39
+ id: z.string().optional(),
40
+ name: z.string().optional(),
41
+ description: z.string().optional(),
42
+ tags: z.array(z.string()).optional(),
43
+ source: z.string().optional(),
44
+ preview: z.string().optional(),
45
+ docs: z.string().optional(),
46
+ tests: z.union([z.string(), z.array(z.string())]).optional()
47
+ }).passthrough();
48
+ var SymbolSignatureSchema = z2.object({
49
+ name: z2.string().min(1),
50
+ kind: z2.string().min(1),
51
+ signature: z2.string()
52
+ });
53
+ var UploadPayloadSchema = z2.object({
54
+ /** Stable block id (POSIX relative path or manifest `id` override). */
55
+ blockId: z2.string().min(1),
56
+ kind: z2.string().min(1),
57
+ name: z2.string().optional(),
58
+ description: z2.string().optional(),
59
+ tags: z2.array(z2.string()).optional(),
60
+ /** Exported symbols extracted from the block's source files. */
61
+ symbols: z2.array(SymbolSignatureSchema),
62
+ /** First ~500 chars of the README, if any. */
63
+ readmeExcerpt: z2.string().optional()
64
+ });
65
+ var MeilisearchDocSchema = UploadPayloadSchema.extend({
66
+ /** SHA-256 over the canonical JSON of the UploadPayload (see T6). */
67
+ contentHash: z2.string().min(1),
68
+ /** Git remote URL (normalised) or local repo name when no remote exists. */
69
+ repo: z2.string().min(1),
70
+ /** hash(machineUuid + absolutePath) — see ARCHITECTURE.md. */
71
+ worktreeId: z2.string().min(1),
72
+ /** POSIX path from the worktree root to the block folder. */
73
+ path: z2.string().min(1),
74
+ /** Unix epoch milliseconds. Refreshed on every push and by `/scope/touch`. */
75
+ lastActiveAt: z2.number().int().nonnegative()
76
+ });
77
+ var BlockHitSchema = z3.object({
78
+ blockId: z3.string().min(1),
79
+ kind: z3.string().min(1),
80
+ name: z3.string().optional(),
81
+ description: z3.string().optional(),
82
+ repo: z3.string().min(1),
83
+ worktreeId: z3.string().min(1),
84
+ path: z3.string().min(1),
85
+ /** Relevance score from Meilisearch hybrid ranking. Larger = more relevant. */
86
+ score: z3.number()
87
+ });
88
+ var CodeMatchSchema = z3.object({
89
+ /** POSIX path from the worktree root. */
90
+ file: z3.string().min(1),
91
+ /** 1-based line number. */
92
+ line: z3.number().int().positive(),
93
+ /** 1-based column number, when available. */
94
+ column: z3.number().int().positive().optional(),
95
+ /** A single line of source text containing the match. */
96
+ preview: z3.string()
97
+ });
98
+ var IndexBatchRequestSchema = z4.object({
99
+ /** Per-block docs to upsert. The cloud routes these to the user's Meilisearch index. */
100
+ upserts: z4.array(MeilisearchDocSchema),
101
+ /** Block ids to delete. Empty array is valid (upsert-only batch). */
102
+ deletes: z4.array(z4.string().min(1))
103
+ });
104
+ var IndexBatchResponseSchema = z4.object({
105
+ /** Unix epoch ms of server-side acknowledgement. */
106
+ acceptedAt: z4.number().int().nonnegative(),
107
+ /** Number of upserts accepted (deletes excluded). */
108
+ accepted: z4.number().int().nonnegative()
109
+ });
110
+ var SearchRequestSchema = z4.object({
111
+ q: z4.string().min(1),
112
+ /** Restrict to one worktree. Omit to search across all of the user's worktrees. */
113
+ worktreeId: z4.string().optional(),
114
+ /** Restrict to one repo. */
115
+ repo: z4.string().optional(),
116
+ /** Restrict to one block kind. */
117
+ kind: z4.string().optional(),
118
+ /** Cap on returned hits. Server enforces an upper bound. */
119
+ limit: z4.number().int().positive().optional()
120
+ });
121
+ var SearchResponseSchema = z4.object({
122
+ hits: z4.array(BlockHitSchema),
123
+ /** Approximate total match count from Meilisearch (estimated, not exact). */
124
+ totalEstimated: z4.number().int().nonnegative()
125
+ });
126
+ var DeleteIndexResponseSchema = z4.object({
127
+ deletedAt: z4.number().int().nonnegative()
128
+ });
129
+ var ScopeTouchRequestSchema = z4.object({
130
+ worktreeId: z4.string().min(1),
131
+ repo: z4.string().min(1)
132
+ });
133
+ var ScopeTouchResponseSchema = z4.object({
134
+ touchedAt: z4.number().int().nonnegative()
135
+ });
136
+ var HealthResponseSchema = z4.object({
137
+ status: z4.literal("ok"),
138
+ schemaVersion: z4.number().int().positive()
139
+ });
140
+ var API_ENDPOINTS = {
141
+ indexBatch: {
142
+ method: "POST",
143
+ path: "/index/batch",
144
+ request: IndexBatchRequestSchema,
145
+ response: IndexBatchResponseSchema
146
+ },
147
+ search: {
148
+ method: "GET",
149
+ path: "/search",
150
+ request: SearchRequestSchema,
151
+ response: SearchResponseSchema
152
+ },
153
+ deleteIndex: {
154
+ method: "DELETE",
155
+ path: "/index",
156
+ request: null,
157
+ response: DeleteIndexResponseSchema
158
+ },
159
+ scopeTouch: {
160
+ method: "POST",
161
+ path: "/scope/touch",
162
+ request: ScopeTouchRequestSchema,
163
+ response: ScopeTouchResponseSchema
164
+ },
165
+ health: {
166
+ method: "GET",
167
+ path: "/health",
168
+ request: null,
169
+ response: HealthResponseSchema
170
+ }
171
+ };
172
+ var ErrorEnvelopeSchema = z5.object({
173
+ error: z5.object({
174
+ /** Stable machine-readable code (e.g. `unauthorized`, `validation_failed`). */
175
+ code: z5.string().min(1),
176
+ /** Human-readable message. */
177
+ message: z5.string().min(1),
178
+ /** Source file path when the error originates from parsing a manifest or other on-disk artifact. Set by the CLI side (see `ScanError`) and by the cloud when validating uploaded manifests. */
179
+ file: z5.string().optional(),
180
+ /** Path of the offending field when the error is validation-related. */
181
+ field: z5.string().optional(),
182
+ /** Server-assigned request id for log correlation. */
183
+ requestId: z5.string().optional()
184
+ })
185
+ });
186
+ var ProviderSchema = z6.enum(["github", "gitlab"]);
187
+ var OAuthCredentialsSchema = z6.object({
188
+ provider: ProviderSchema,
189
+ accessToken: z6.string().min(1),
190
+ refreshToken: z6.string().min(1).optional(),
191
+ /** Unix epoch milliseconds at which `accessToken` expires. */
192
+ expiresAt: z6.number().int().nonnegative().optional(),
193
+ /** Provider-side user id (e.g. GitHub `id`, GitLab `id`). Optional — useful
194
+ * for UI display ("logged in as alexspdlr on github") and for the CLI to
195
+ * short-circuit redundant `/user` lookups. */
196
+ providerUserId: z6.string().min(1).optional()
197
+ });
198
+ var UserContextSchema = z6.object({
199
+ userId: z6.string().min(1),
200
+ indexName: z6.string().min(1),
201
+ provider: ProviderSchema
202
+ });
203
+
204
+ // src/cloud/client.ts
205
+ var DEFAULT_BASE_URL = "http://localhost:3001";
206
+ var REQUEST_TIMEOUT_MS = 3e4;
207
+ var MAX_RETRIES = 3;
208
+ var BASE_BACKOFF_MS = 500;
209
+ var JITTER_FRACTION = 0.25;
210
+ var isRetryableStatus = (status) => status === 429 || status >= 500 && status <= 599;
211
+ var computeBackoffMs = (attempt) => {
212
+ const exp = BASE_BACKOFF_MS * 2 ** attempt;
213
+ const jitter = exp * JITTER_FRACTION * (Math.random() * 2 - 1);
214
+ return Math.max(0, Math.round(exp + jitter));
215
+ };
216
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
217
+ function parseRetryAfterMs(header) {
218
+ if (!header) return null;
219
+ const trimmed = header.trim();
220
+ if (/^\d+$/.test(trimmed)) {
221
+ return Number(trimmed) * 1e3;
222
+ }
223
+ const ts = Date.parse(trimmed);
224
+ if (Number.isNaN(ts)) return null;
225
+ return Math.max(0, ts - Date.now());
226
+ }
227
+ var notLoggedIn = (message) => ({
228
+ kind: "error",
229
+ status: 0,
230
+ envelope: { error: { code: "not_logged_in", message } }
231
+ });
232
+ var unexpectedResponse = (status, statusText) => ({
233
+ kind: "error",
234
+ status,
235
+ envelope: {
236
+ error: {
237
+ code: "unexpected_response",
238
+ message: statusText || `HTTP ${status}`
239
+ }
240
+ }
241
+ });
242
+ var invalidResponse = (status) => ({
243
+ kind: "error",
244
+ status,
245
+ envelope: {
246
+ error: {
247
+ code: "invalid_response",
248
+ message: "Server returned a body that did not match the expected schema"
249
+ }
250
+ }
251
+ });
252
+ var resolveCredentialsPath = (override) => override ?? path.join(homedir(), FILESYSTEM_LAYOUT.user.credentialsFile);
253
+ var resolveBaseUrl = (override) => override ?? process.env.MACROSCOPE_CLOUD_URL ?? DEFAULT_BASE_URL;
254
+ async function readAccessToken(credPath) {
255
+ let raw;
256
+ try {
257
+ raw = await readFile(credPath, "utf8");
258
+ } catch {
259
+ return null;
260
+ }
261
+ let parsed;
262
+ try {
263
+ parsed = JSON.parse(raw);
264
+ } catch {
265
+ return null;
266
+ }
267
+ const result = OAuthCredentialsSchema.safeParse(parsed);
268
+ if (!result.success) return null;
269
+ return result.data.accessToken;
270
+ }
271
+ async function parseErrorBody(res) {
272
+ let body;
273
+ try {
274
+ body = await res.json();
275
+ } catch {
276
+ return unexpectedResponse(res.status, res.statusText);
277
+ }
278
+ const envelope = ErrorEnvelopeSchema.safeParse(body);
279
+ if (!envelope.success) {
280
+ return unexpectedResponse(res.status, res.statusText);
281
+ }
282
+ return { kind: "error", status: res.status, envelope: envelope.data };
283
+ }
284
+ function clientValidationError(issue, fallbackMessage) {
285
+ return {
286
+ kind: "error",
287
+ status: 0,
288
+ envelope: {
289
+ error: {
290
+ code: "validation_failed",
291
+ message: issue?.message ?? fallbackMessage,
292
+ field: issue?.path.join(".") || void 0
293
+ }
294
+ }
295
+ };
296
+ }
297
+ function serializeRequest(method, data) {
298
+ if (data === null) return {};
299
+ if (method === "GET") {
300
+ const params = new URLSearchParams();
301
+ for (const [k, v] of Object.entries(data)) {
302
+ if (v === void 0) continue;
303
+ params.append(k, String(v));
304
+ }
305
+ const qs = params.toString();
306
+ return qs ? { query: `?${qs}` } : {};
307
+ }
308
+ return { body: JSON.stringify(data) };
309
+ }
310
+ async function parseOkBody(res, schema) {
311
+ let body;
312
+ try {
313
+ body = await res.json();
314
+ } catch {
315
+ return invalidResponse(res.status);
316
+ }
317
+ const parsed = schema.safeParse(body);
318
+ if (!parsed.success) {
319
+ return invalidResponse(res.status);
320
+ }
321
+ return { kind: "ok", data: parsed.data };
322
+ }
323
+ function createCloudClient(opts = {}) {
324
+ const credPath = resolveCredentialsPath(opts.credentialsPath);
325
+ const baseUrl = resolveBaseUrl(opts.baseUrl);
326
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
327
+ let cached = null;
328
+ async function getAccessToken() {
329
+ let mtimeMs;
330
+ try {
331
+ mtimeMs = (await stat(credPath)).mtimeMs;
332
+ } catch {
333
+ cached = null;
334
+ return null;
335
+ }
336
+ if (cached && cached.mtimeMs === mtimeMs) {
337
+ return cached.token;
338
+ }
339
+ const token = await readAccessToken(credPath);
340
+ cached = token ? { mtimeMs, token } : null;
341
+ return token;
342
+ }
343
+ async function executeRequest(endpoint, schema, init) {
344
+ const token = await getAccessToken();
345
+ if (!token) {
346
+ return notLoggedIn(`No valid credentials at ${credPath}. Run \`macroscope login\`.`);
347
+ }
348
+ const url = `${baseUrl}${endpoint.path}${init.query ?? ""}`;
349
+ const headers = {
350
+ Authorization: `Bearer ${token}`
351
+ };
352
+ if (init.body !== void 0) {
353
+ headers["Content-Type"] = "application/json";
354
+ }
355
+ let lastResponse = null;
356
+ let lastNetworkError = null;
357
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt += 1) {
358
+ let res;
359
+ try {
360
+ res = await fetchImpl(url, {
361
+ method: endpoint.method,
362
+ headers,
363
+ body: init.body,
364
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
365
+ });
366
+ } catch (err) {
367
+ lastNetworkError = err;
368
+ if (attempt === MAX_RETRIES) break;
369
+ await sleep(computeBackoffMs(attempt));
370
+ continue;
371
+ }
372
+ if (!isRetryableStatus(res.status)) {
373
+ if (res.status >= 200 && res.status < 300) {
374
+ return parseOkBody(res, schema);
375
+ }
376
+ return parseErrorBody(res);
377
+ }
378
+ lastResponse = res;
379
+ lastNetworkError = null;
380
+ if (attempt === MAX_RETRIES) break;
381
+ const retryAfterMs = res.status === 429 ? parseRetryAfterMs(res.headers.get("retry-after")) : null;
382
+ const waitMs = retryAfterMs ?? computeBackoffMs(attempt);
383
+ await sleep(waitMs);
384
+ }
385
+ if (lastResponse) {
386
+ return parseErrorBody(lastResponse);
387
+ }
388
+ return {
389
+ kind: "error",
390
+ status: 0,
391
+ envelope: {
392
+ error: {
393
+ code: "upstream_unreachable",
394
+ message: lastNetworkError instanceof Error ? lastNetworkError.message : "Network request failed"
395
+ }
396
+ }
397
+ };
398
+ }
399
+ return {
400
+ health: () => executeRequest(API_ENDPOINTS.health, HealthResponseSchema, serializeRequest("GET", null)),
401
+ search: (req) => {
402
+ const parsed = SearchRequestSchema.safeParse(req);
403
+ if (!parsed.success) {
404
+ return Promise.resolve(
405
+ clientValidationError(
406
+ parsed.error.issues[0],
407
+ "Invalid search request"
408
+ )
409
+ );
410
+ }
411
+ return executeRequest(
412
+ API_ENDPOINTS.search,
413
+ SearchResponseSchema,
414
+ serializeRequest("GET", parsed.data)
415
+ );
416
+ },
417
+ indexBatch: (req) => {
418
+ const parsed = IndexBatchRequestSchema.safeParse(req);
419
+ if (!parsed.success) {
420
+ return Promise.resolve(
421
+ clientValidationError(
422
+ parsed.error.issues[0],
423
+ "Invalid index batch request"
424
+ )
425
+ );
426
+ }
427
+ return executeRequest(
428
+ API_ENDPOINTS.indexBatch,
429
+ IndexBatchResponseSchema,
430
+ serializeRequest("POST", parsed.data)
431
+ );
432
+ },
433
+ scopeTouch: (req) => {
434
+ const parsed = ScopeTouchRequestSchema.safeParse(req);
435
+ if (!parsed.success) {
436
+ return Promise.resolve(
437
+ clientValidationError(
438
+ parsed.error.issues[0],
439
+ "Invalid scope touch request"
440
+ )
441
+ );
442
+ }
443
+ return executeRequest(
444
+ API_ENDPOINTS.scopeTouch,
445
+ ScopeTouchResponseSchema,
446
+ serializeRequest("POST", parsed.data)
447
+ );
448
+ },
449
+ deleteIndex: () => executeRequest(
450
+ API_ENDPOINTS.deleteIndex,
451
+ DeleteIndexResponseSchema,
452
+ serializeRequest("DELETE", null)
453
+ )
454
+ };
455
+ }
456
+
1
457
  // src/core/version.ts
2
458
  var VERSION = "0.0.0";
3
459
  export {
4
- VERSION
460
+ VERSION,
461
+ createCloudClient
5
462
  };
6
463
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/version.ts"],"sourcesContent":["export const VERSION = '0.0.0';\n"],"mappings":";AAAO,IAAM,UAAU;","names":[]}
1
+ {"version":3,"sources":["../src/cloud/client.ts","../../contracts/src/version.ts","../../contracts/src/fs.ts","../../contracts/src/manifest.ts","../../contracts/src/payload.ts","../../contracts/src/search.ts","../../contracts/src/api.ts","../../contracts/src/error.ts","../../contracts/src/auth.ts","../src/core/version.ts"],"sourcesContent":["import { readFile, stat } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport path from 'node:path';\nimport {\n API_ENDPOINTS,\n type DeleteIndexResponse,\n DeleteIndexResponseSchema,\n type ErrorEnvelope,\n ErrorEnvelopeSchema,\n FILESYSTEM_LAYOUT,\n type HealthResponse,\n HealthResponseSchema,\n type IndexBatchRequest,\n IndexBatchRequestSchema,\n type IndexBatchResponse,\n IndexBatchResponseSchema,\n OAuthCredentialsSchema,\n type ScopeTouchRequest,\n ScopeTouchRequestSchema,\n type ScopeTouchResponse,\n ScopeTouchResponseSchema,\n type SearchRequest,\n SearchRequestSchema,\n type SearchResponse,\n SearchResponseSchema,\n} from '@macroscope/contracts';\nimport type { z } from 'zod';\n\nexport type Result<T> =\n | { kind: 'ok'; data: T }\n | { kind: 'error'; envelope: ErrorEnvelope; status: number };\n\nexport interface CloudClientOptions {\n /** Override the cloud base URL. Defaults to env MACROSCOPE_CLOUD_URL, then http://localhost:3001. */\n baseUrl?: string;\n /** Override the credentials path. Defaults to FILESYSTEM_LAYOUT.user.credentialsFile under os.homedir(). */\n credentialsPath?: string;\n /** Test seam — inject a fetch implementation. Defaults to globalThis.fetch. */\n fetchImpl?: typeof fetch;\n}\n\nexport interface CloudClient {\n health(): Promise<Result<HealthResponse>>;\n search(req: SearchRequest): Promise<Result<SearchResponse>>;\n indexBatch(req: IndexBatchRequest): Promise<Result<IndexBatchResponse>>;\n scopeTouch(req: ScopeTouchRequest): Promise<Result<ScopeTouchResponse>>;\n deleteIndex(): Promise<Result<DeleteIndexResponse>>;\n}\n\nconst DEFAULT_BASE_URL = 'http://localhost:3001';\nconst REQUEST_TIMEOUT_MS = 30_000;\nconst MAX_RETRIES = 3;\nconst BASE_BACKOFF_MS = 500;\nconst JITTER_FRACTION = 0.25;\n\nconst isRetryableStatus = (status: number): boolean =>\n status === 429 || (status >= 500 && status <= 599);\n\nconst computeBackoffMs = (attempt: number): number => {\n const exp = BASE_BACKOFF_MS * 2 ** attempt;\n const jitter = exp * JITTER_FRACTION * (Math.random() * 2 - 1);\n return Math.max(0, Math.round(exp + jitter));\n};\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nfunction parseRetryAfterMs(header: string | null): number | null {\n if (!header) return null;\n const trimmed = header.trim();\n // Seconds form: a non-negative integer.\n if (/^\\d+$/.test(trimmed)) {\n return Number(trimmed) * 1000;\n }\n // HTTP-date form.\n const ts = Date.parse(trimmed);\n if (Number.isNaN(ts)) return null;\n return Math.max(0, ts - Date.now());\n}\n\nconst notLoggedIn = (message: string): Result<never> => ({\n kind: 'error',\n status: 0,\n envelope: { error: { code: 'not_logged_in', message } },\n});\n\nconst unexpectedResponse = (status: number, statusText: string): Result<never> => ({\n kind: 'error',\n status,\n envelope: {\n error: {\n code: 'unexpected_response',\n message: statusText || `HTTP ${status}`,\n },\n },\n});\n\nconst invalidResponse = (status: number): Result<never> => ({\n kind: 'error',\n status,\n envelope: {\n error: {\n code: 'invalid_response',\n message: 'Server returned a body that did not match the expected schema',\n },\n },\n});\n\nconst resolveCredentialsPath = (override?: string): string =>\n override ?? path.join(homedir(), FILESYSTEM_LAYOUT.user.credentialsFile);\n\nconst resolveBaseUrl = (override?: string): string =>\n override ?? process.env.MACROSCOPE_CLOUD_URL ?? DEFAULT_BASE_URL;\n\nasync function readAccessToken(credPath: string): Promise<string | null> {\n let raw: string;\n try {\n raw = await readFile(credPath, 'utf8');\n } catch {\n return null;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n const result = OAuthCredentialsSchema.safeParse(parsed);\n if (!result.success) return null;\n return result.data.accessToken;\n}\n\nasync function parseErrorBody(res: Response): Promise<Result<never>> {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n return unexpectedResponse(res.status, res.statusText);\n }\n const envelope = ErrorEnvelopeSchema.safeParse(body);\n if (!envelope.success) {\n return unexpectedResponse(res.status, res.statusText);\n }\n return { kind: 'error', status: res.status, envelope: envelope.data };\n}\n\nfunction clientValidationError(\n issue: z.ZodIssue | undefined,\n fallbackMessage: string,\n): Result<never> {\n return {\n kind: 'error',\n status: 0,\n envelope: {\n error: {\n code: 'validation_failed',\n message: issue?.message ?? fallbackMessage,\n field: issue?.path.join('.') || undefined,\n },\n },\n };\n}\n\nfunction serializeRequest(\n method: 'GET' | 'POST' | 'DELETE',\n data: Record<string, unknown> | null,\n): { query?: string; body?: string } {\n if (data === null) return {};\n if (method === 'GET') {\n const params = new URLSearchParams();\n // ASSUMPTION: every GET request schema in @macroscope/contracts has only\n // primitive fields (string | number | optional thereof). If a future\n // endpoint adds an array or boolean, this `String(v)` will silently\n // misencode it — extend here when that happens. Verified against\n // SearchRequestSchema (currently the only GET with a request body) at\n // T7-time.\n for (const [k, v] of Object.entries(data)) {\n if (v === undefined) continue;\n params.append(k, String(v));\n }\n const qs = params.toString();\n return qs ? { query: `?${qs}` } : {};\n }\n return { body: JSON.stringify(data) };\n}\n\nasync function parseOkBody<T>(res: Response, schema: z.ZodType<T>): Promise<Result<T>> {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n return invalidResponse(res.status);\n }\n const parsed = schema.safeParse(body);\n if (!parsed.success) {\n return invalidResponse(res.status);\n }\n return { kind: 'ok', data: parsed.data };\n}\n\nexport function createCloudClient(opts: CloudClientOptions = {}): CloudClient {\n const credPath = resolveCredentialsPath(opts.credentialsPath);\n const baseUrl = resolveBaseUrl(opts.baseUrl);\n const fetchImpl = opts.fetchImpl ?? globalThis.fetch;\n\n let cached: { mtimeMs: number; token: string } | null = null;\n\n async function getAccessToken(): Promise<string | null> {\n let mtimeMs: number;\n try {\n mtimeMs = (await stat(credPath)).mtimeMs;\n } catch {\n cached = null;\n return null;\n }\n if (cached && cached.mtimeMs === mtimeMs) {\n return cached.token;\n }\n const token = await readAccessToken(credPath);\n cached = token ? { mtimeMs, token } : null;\n return token;\n }\n\n async function executeRequest<T>(\n endpoint: { method: string; path: string },\n schema: z.ZodType<T>,\n init: { body?: string; query?: string },\n ): Promise<Result<T>> {\n const token = await getAccessToken();\n if (!token) {\n return notLoggedIn(`No valid credentials at ${credPath}. Run \\`macroscope login\\`.`);\n }\n\n const url = `${baseUrl}${endpoint.path}${init.query ?? ''}`;\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n };\n if (init.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n let lastResponse: Response | null = null;\n let lastNetworkError: unknown = null;\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt += 1) {\n let res: Response;\n try {\n res = await fetchImpl(url, {\n method: endpoint.method,\n headers,\n body: init.body,\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n } catch (err) {\n // Network-level failure (ECONNREFUSED, DNS, TLS, abort, etc.). The\n // watcher's isRetryable() keys on `upstream_unreachable` to decide\n // whether to queue + emit \"Sync paused — retrying\"; if we let this\n // throw escape, the watcher's outer catch tags it as retryable:false\n // and the pill renders the wrong copy.\n lastNetworkError = err;\n if (attempt === MAX_RETRIES) break;\n await sleep(computeBackoffMs(attempt));\n continue;\n }\n\n if (!isRetryableStatus(res.status)) {\n if (res.status >= 200 && res.status < 300) {\n return parseOkBody(res, schema);\n }\n return parseErrorBody(res);\n }\n\n lastResponse = res;\n lastNetworkError = null;\n if (attempt === MAX_RETRIES) break;\n // Per the brief: Retry-After is honoured only on 429. 5xx uses the\n // standard exponential-backoff schedule even if the server echoes the\n // header.\n const retryAfterMs =\n res.status === 429 ? parseRetryAfterMs(res.headers.get('retry-after')) : null;\n const waitMs = retryAfterMs ?? computeBackoffMs(attempt);\n await sleep(waitMs);\n }\n\n if (lastResponse) {\n return parseErrorBody(lastResponse);\n }\n return {\n kind: 'error',\n status: 0,\n envelope: {\n error: {\n code: 'upstream_unreachable',\n message:\n lastNetworkError instanceof Error ? lastNetworkError.message : 'Network request failed',\n },\n },\n };\n }\n\n return {\n health: () =>\n executeRequest(API_ENDPOINTS.health, HealthResponseSchema, serializeRequest('GET', null)),\n\n search: (req) => {\n const parsed = SearchRequestSchema.safeParse(req);\n if (!parsed.success) {\n return Promise.resolve(\n clientValidationError(\n parsed.error.issues[0],\n 'Invalid search request',\n ) as Result<SearchResponse>,\n );\n }\n return executeRequest(\n API_ENDPOINTS.search,\n SearchResponseSchema,\n serializeRequest('GET', parsed.data),\n );\n },\n\n indexBatch: (req) => {\n const parsed = IndexBatchRequestSchema.safeParse(req);\n if (!parsed.success) {\n return Promise.resolve(\n clientValidationError(\n parsed.error.issues[0],\n 'Invalid index batch request',\n ) as Result<IndexBatchResponse>,\n );\n }\n return executeRequest(\n API_ENDPOINTS.indexBatch,\n IndexBatchResponseSchema,\n serializeRequest('POST', parsed.data),\n );\n },\n\n scopeTouch: (req) => {\n const parsed = ScopeTouchRequestSchema.safeParse(req);\n if (!parsed.success) {\n return Promise.resolve(\n clientValidationError(\n parsed.error.issues[0],\n 'Invalid scope touch request',\n ) as Result<ScopeTouchResponse>,\n );\n }\n return executeRequest(\n API_ENDPOINTS.scopeTouch,\n ScopeTouchResponseSchema,\n serializeRequest('POST', parsed.data),\n );\n },\n\n deleteIndex: () =>\n executeRequest(\n API_ENDPOINTS.deleteIndex,\n DeleteIndexResponseSchema,\n serializeRequest('DELETE', null),\n ),\n };\n}\n","/**\n * Wire-format version for cloud-side documents (MeilisearchDoc). Bumped when\n * the doc shape changes in a way that requires reindexing. The catch-up scan\n * watches for a mismatch with the server-reported version and triggers a full\n * re-push (see `catchup.ts`).\n */\nexport const SCHEMA_VERSION = 1 as const;\nexport type SchemaVersion = typeof SCHEMA_VERSION;\n","/**\n * Filesystem paths macroscope reads and writes. Two roots:\n *\n * user — under `~/.macroscope/`; survives across projects.\n * project — under `<project>/.macroscope/`; specific to a worktree.\n *\n * Paths are POSIX-style and relative to their root. Callers resolve them\n * against the relevant base directory (`os.homedir()` or the project root).\n */\nexport const FILESYSTEM_LAYOUT = {\n user: {\n /** `~/.macroscope/` */\n rootDir: '.macroscope',\n /** `~/.macroscope/credentials` — OAuth token store, mode 0600. */\n credentialsFile: '.macroscope/credentials',\n /** `~/.macroscope/machine-id` — stable per-install identifier. */\n machineIdFile: '.macroscope/machine-id',\n },\n project: {\n /** `<project>/.macroscope/` */\n rootDir: '.macroscope',\n /** `<project>/.macroscope/blueprints/` — one folder per kind. */\n blueprintsDir: '.macroscope/blueprints',\n /** `<project>/.macroscope/cache/` */\n cacheDir: '.macroscope/cache',\n /** `<project>/.macroscope/cache/hashes.json` — content-hash cache used by catch-up scan. */\n hashesFile: '.macroscope/cache/hashes.json',\n /** `<project>/.macroscope/cache/queue.json` — watcher push queue, survives restart. */\n queueFile: '.macroscope/cache/queue.json',\n },\n} as const;\n\nexport type FilesystemLayout = typeof FILESYSTEM_LAYOUT;\n","import { z } from 'zod';\n\n/**\n * The on-disk `macroscope.yaml` manifest. Substrate-level fields are listed\n * explicitly; blueprints may attach additional kind-specific fields, which\n * pass through unchanged (`.passthrough()`).\n */\nexport const BlockManifestSchema = z\n .object({\n /** Must reference a registered blueprint's `kind`. */\n kind: z.string().min(1),\n /** Optional override for the auto-derived block id (POSIX relative path). */\n id: z.string().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n source: z.string().optional(),\n preview: z.string().optional(),\n docs: z.string().optional(),\n tests: z.union([z.string(), z.array(z.string())]).optional(),\n })\n .passthrough();\n\nexport type BlockManifest = z.infer<typeof BlockManifestSchema>;\n","import { z } from 'zod';\n\n/**\n * One exported symbol from a block's source files. Extracted by the TS\n * compiler API. `signature` is the rendered TypeScript signature string\n * (e.g. `function foo(x: string): number`); the exact rendering is the\n * extractor's responsibility (see T5).\n */\nexport const SymbolSignatureSchema = z.object({\n name: z.string().min(1),\n kind: z.string().min(1),\n signature: z.string(),\n});\nexport type SymbolSignature = z.infer<typeof SymbolSignatureSchema>;\n\n/**\n * What the watcher pushes to the cloud per block. The cloud combines this\n * with cloud-side fields (repo, worktreeId, path, lastActiveAt, contentHash)\n * to form the `MeilisearchDoc` that lands in the user's index.\n */\nexport const UploadPayloadSchema = z.object({\n /** Stable block id (POSIX relative path or manifest `id` override). */\n blockId: z.string().min(1),\n kind: z.string().min(1),\n name: z.string().optional(),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n /** Exported symbols extracted from the block's source files. */\n symbols: z.array(SymbolSignatureSchema),\n /** First ~500 chars of the README, if any. */\n readmeExcerpt: z.string().optional(),\n});\nexport type UploadPayload = z.infer<typeof UploadPayloadSchema>;\n\n/**\n * The doc shape stored in Meilisearch. Identity is the tuple\n * (repo, worktreeId, blockId): two worktrees of the same repo produce\n * distinct docs and filter independently.\n */\nexport const MeilisearchDocSchema = UploadPayloadSchema.extend({\n /** SHA-256 over the canonical JSON of the UploadPayload (see T6). */\n contentHash: z.string().min(1),\n /** Git remote URL (normalised) or local repo name when no remote exists. */\n repo: z.string().min(1),\n /** hash(machineUuid + absolutePath) — see ARCHITECTURE.md. */\n worktreeId: z.string().min(1),\n /** POSIX path from the worktree root to the block folder. */\n path: z.string().min(1),\n /** Unix epoch milliseconds. Refreshed on every push and by `/scope/touch`. */\n lastActiveAt: z.number().int().nonnegative(),\n});\nexport type MeilisearchDoc = z.infer<typeof MeilisearchDocSchema>;\n","import { z } from 'zod';\n\n/**\n * One cloud-side search result. Returned by `GET /search`. Carries enough\n * to render a result row without a second fetch.\n */\nexport const BlockHitSchema = z.object({\n blockId: z.string().min(1),\n kind: z.string().min(1),\n name: z.string().optional(),\n description: z.string().optional(),\n repo: z.string().min(1),\n worktreeId: z.string().min(1),\n path: z.string().min(1),\n /** Relevance score from Meilisearch hybrid ranking. Larger = more relevant. */\n score: z.number(),\n});\nexport type BlockHit = z.infer<typeof BlockHitSchema>;\n\n/**\n * One local-side code search result. Produced by `git grep` (T10). Lives in\n * contracts so the UI's merged-results view can speak one type.\n */\nexport const CodeMatchSchema = z.object({\n /** POSIX path from the worktree root. */\n file: z.string().min(1),\n /** 1-based line number. */\n line: z.number().int().positive(),\n /** 1-based column number, when available. */\n column: z.number().int().positive().optional(),\n /** A single line of source text containing the match. */\n preview: z.string(),\n});\nexport type CodeMatch = z.infer<typeof CodeMatchSchema>;\n","import { z } from 'zod';\nimport { MeilisearchDocSchema } from './payload.js';\nimport { BlockHitSchema } from './search.js';\n\n/* ------------------------------ POST /index/batch ------------------------------ */\n\nexport const IndexBatchRequestSchema = z.object({\n /** Per-block docs to upsert. The cloud routes these to the user's Meilisearch index. */\n upserts: z.array(MeilisearchDocSchema),\n /** Block ids to delete. Empty array is valid (upsert-only batch). */\n deletes: z.array(z.string().min(1)),\n});\nexport type IndexBatchRequest = z.infer<typeof IndexBatchRequestSchema>;\n\nexport const IndexBatchResponseSchema = z.object({\n /** Unix epoch ms of server-side acknowledgement. */\n acceptedAt: z.number().int().nonnegative(),\n /** Number of upserts accepted (deletes excluded). */\n accepted: z.number().int().nonnegative(),\n});\nexport type IndexBatchResponse = z.infer<typeof IndexBatchResponseSchema>;\n\n/* --------------------------------- GET /search --------------------------------- */\n\nexport const SearchRequestSchema = z.object({\n q: z.string().min(1),\n /** Restrict to one worktree. Omit to search across all of the user's worktrees. */\n worktreeId: z.string().optional(),\n /** Restrict to one repo. */\n repo: z.string().optional(),\n /** Restrict to one block kind. */\n kind: z.string().optional(),\n /** Cap on returned hits. Server enforces an upper bound. */\n limit: z.number().int().positive().optional(),\n});\nexport type SearchRequest = z.infer<typeof SearchRequestSchema>;\n\nexport const SearchResponseSchema = z.object({\n hits: z.array(BlockHitSchema),\n /** Approximate total match count from Meilisearch (estimated, not exact). */\n totalEstimated: z.number().int().nonnegative(),\n});\nexport type SearchResponse = z.infer<typeof SearchResponseSchema>;\n\n/* --------------------------------- DELETE /index -------------------------------- */\n\nexport const DeleteIndexResponseSchema = z.object({\n deletedAt: z.number().int().nonnegative(),\n});\nexport type DeleteIndexResponse = z.infer<typeof DeleteIndexResponseSchema>;\n\n/* ------------------------------ POST /scope/touch ------------------------------ */\n\nexport const ScopeTouchRequestSchema = z.object({\n worktreeId: z.string().min(1),\n repo: z.string().min(1),\n});\nexport type ScopeTouchRequest = z.infer<typeof ScopeTouchRequestSchema>;\n\nexport const ScopeTouchResponseSchema = z.object({\n touchedAt: z.number().int().nonnegative(),\n});\nexport type ScopeTouchResponse = z.infer<typeof ScopeTouchResponseSchema>;\n\n/* --------------------------------- GET /health --------------------------------- */\n\nexport const HealthResponseSchema = z.object({\n status: z.literal('ok'),\n schemaVersion: z.number().int().positive(),\n});\nexport type HealthResponse = z.infer<typeof HealthResponseSchema>;\n\n/**\n * Endpoint manifest. One row per route, suitable for type-checking a server\n * router and a typed client against a single source of truth.\n *\n * Serialization convention: for `method: 'GET'` endpoints the request schema's\n * fields are sent as URL query parameters (never a body). For `POST`/`DELETE`\n * the request schema is the JSON body. `request: null` means the endpoint\n * takes no request payload at all.\n */\nexport const API_ENDPOINTS = {\n indexBatch: {\n method: 'POST',\n path: '/index/batch',\n request: IndexBatchRequestSchema,\n response: IndexBatchResponseSchema,\n },\n search: {\n method: 'GET',\n path: '/search',\n request: SearchRequestSchema,\n response: SearchResponseSchema,\n },\n deleteIndex: {\n method: 'DELETE',\n path: '/index',\n request: null,\n response: DeleteIndexResponseSchema,\n },\n scopeTouch: {\n method: 'POST',\n path: '/scope/touch',\n request: ScopeTouchRequestSchema,\n response: ScopeTouchResponseSchema,\n },\n health: {\n method: 'GET',\n path: '/health',\n request: null,\n response: HealthResponseSchema,\n },\n} as const;\n\nexport type ApiEndpoints = typeof API_ENDPOINTS;\n","import { z } from 'zod';\n\n/**\n * The uniform error shape returned by every API endpoint on failure. Per the\n * CLAUDE.md invariant: errors name the file path and the broken field where\n * applicable.\n */\nexport const ErrorEnvelopeSchema = z.object({\n error: z.object({\n /** Stable machine-readable code (e.g. `unauthorized`, `validation_failed`). */\n code: z.string().min(1),\n /** Human-readable message. */\n message: z.string().min(1),\n /** Source file path when the error originates from parsing a manifest or other on-disk artifact. Set by the CLI side (see `ScanError`) and by the cloud when validating uploaded manifests. */\n file: z.string().optional(),\n /** Path of the offending field when the error is validation-related. */\n field: z.string().optional(),\n /** Server-assigned request id for log correlation. */\n requestId: z.string().optional(),\n }),\n});\n\nexport type ErrorEnvelope = z.infer<typeof ErrorEnvelopeSchema>;\n","import { z } from 'zod';\n\n/**\n * Supported Git host identity providers. v1 ships GitHub and GitLab. Other\n * providers (Bitbucket, Gitea, self-hosted GitLab) are deferred to v1.1; see\n * TODOS.md.\n */\nexport const ProviderSchema = z.enum(['github', 'gitlab']);\nexport type Provider = z.infer<typeof ProviderSchema>;\n\n/**\n * On-disk shape of `~/.macroscope/credentials` (file mode 0600). Written by\n * `macroscope login` (T9) and read by the local proxy (T11) when forwarding\n * the bearer token to the cloud API. Refresh-token and expiry are optional —\n * not every provider issues a refresh token, and some access tokens have no\n * explicit expiry.\n */\nexport const OAuthCredentialsSchema = z.object({\n provider: ProviderSchema,\n accessToken: z.string().min(1),\n refreshToken: z.string().min(1).optional(),\n /** Unix epoch milliseconds at which `accessToken` expires. */\n expiresAt: z.number().int().nonnegative().optional(),\n /** Provider-side user id (e.g. GitHub `id`, GitLab `id`). Optional — useful\n * for UI display (\"logged in as alexspdlr on github\") and for the CLI to\n * short-circuit redundant `/user` lookups. */\n providerUserId: z.string().min(1).optional(),\n});\nexport type OAuthCredentials = z.infer<typeof OAuthCredentialsSchema>;\n\n/**\n * The authenticated-request context the OAuth validation middleware (T12)\n * attaches to every request after verifying the bearer token. Downstream\n * handlers read these fields to scope queries to the right user index.\n *\n * Identity derivation (per ARCHITECTURE.md):\n * userId = hash(provider + \":\" + providerUserId)\n * indexName = \"user_\" + userId\n *\n * Same human on different providers ⇒ different userId. Intentional — keeps\n * cross-provider identity confusion impossible at the storage layer.\n */\nexport const UserContextSchema = z.object({\n userId: z.string().min(1),\n indexName: z.string().min(1),\n provider: ProviderSchema,\n});\nexport type UserContext = z.infer<typeof UserContextSchema>;\n","export const VERSION = '0.0.0';\n"],"mappings":"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","names":["z","z"]}
@@ -0,0 +1 @@
1
+ .xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:-moz-fit-content;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking: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-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}::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking: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-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}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-amber-50:#fffbeb;--color-amber-200:#fee685;--color-amber-500:#f99c00;--color-amber-800:#953d00;--color-amber-900:#7b3306;--color-amber-950:#461901;--color-emerald-500:#00bb7f;--color-rose-50:#fff1f2;--color-rose-200:#ffccd3;--color-zinc-50:#fafafa;--color-zinc-100:#f4f4f5;--color-zinc-200:#e4e4e7;--color-zinc-300:#d4d4d8;--color-zinc-400:#9f9fa9;--color-zinc-500:#71717b;--color-zinc-600:#52525c;--color-zinc-700:#3f3f46;--color-zinc-800:#27272a;--color-zinc-900:#18181b;--color-zinc-950:#09090b;--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wider:.05em;--radius-md:.375rem;--radius-lg:.5rem;--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)}@supports (color:lab(0% 0 0)){:root,:host{--color-amber-50:lab(98.6252% -.635922 8.42309);--color-amber-200:lab(91.7203% -.505269 49.9084);--color-amber-500:lab(72.7183% 31.8672 97.9407);--color-amber-800:lab(37.8822% 37.1699 52.2718);--color-amber-900:lab(31.2288% 30.2627 40.0378);--color-amber-950:lab(15.8111% 20.9107 23.3752);--color-emerald-500:lab(66.9756% -58.27 19.5419);--color-rose-50:lab(96.2369% 4.94155 1.28011);--color-rose-200:lab(86.806% 19.1909 4.07754);--color-zinc-50:lab(98.26% 0 0);--color-zinc-100:lab(96.1634% .0993311 -.364041);--color-zinc-200:lab(90.6853% .399232 -1.45452);--color-zinc-300:lab(84.9837% .601262 -2.17986);--color-zinc-400:lab(65.6464% 1.53497 -5.42429);--color-zinc-500:lab(47.8878% 1.65477 -5.77283);--color-zinc-600:lab(35.1166% 1.78212 -6.1173);--color-zinc-700:lab(26.8019% 1.35387 -4.68303);--color-zinc-800:lab(15.7305% .613764 -2.16959);--color-zinc-900:lab(8.30603% .618205 -2.16572);--color-zinc-950:lab(2.51107% .242703 -.886115)}}}@layer base{*,:after,:before{box-sizing:border-box;border:0 solid;margin:0;padding:0}::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,ui-sans-serif, system-ui, 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{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}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.top-1\/2{top:50%}.top-3{top:calc(var(--spacing) * 3)}.right-2\.5{right:calc(var(--spacing) * 2.5)}.right-3{right:calc(var(--spacing) * 3)}.right-4{right:calc(var(--spacing) * 4)}.bottom-4{bottom:calc(var(--spacing) * 4)}.left-1\/2{left:50%}.left-2\.5{left:calc(var(--spacing) * 2.5)}.z-50{z-index:50}.my-2{margin-block:calc(var(--spacing) * 2)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-2{margin-left:calc(var(--spacing) * 2)}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-1{height:calc(var(--spacing) * 1)}.h-2{height:calc(var(--spacing) * 2)}.h-4{height:calc(var(--spacing) * 4)}.h-\[400px\]{height:400px}.h-\[600px\]{height:600px}.h-full{height:100%}.max-h-48{max-height:calc(var(--spacing) * 48)}.min-h-screen{min-height:100vh}.w-2{width:calc(var(--spacing) * 2)}.w-4{width:calc(var(--spacing) * 4)}.w-44{width:calc(var(--spacing) * 44)}.w-56{width:calc(var(--spacing) * 56)}.w-72{width:calc(var(--spacing) * 72)}.w-80{width:calc(var(--spacing) * 80)}.w-full{width:100%}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.list-disc{list-style-type:disc}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.justify-between{justify-content:space-between}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-zinc-100>:not(:last-child)){border-color:var(--color-zinc-100)}:where(.divide-zinc-200>:not(:last-child)){border-color:var(--color-zinc-200)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.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-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-amber-200{border-color:var(--color-amber-200)}.border-rose-200{border-color:var(--color-rose-200)}.border-zinc-200{border-color:var(--color-zinc-200)}.border-zinc-300{border-color:var(--color-zinc-300)}.border-zinc-800{border-color:var(--color-zinc-800)}.border-zinc-900{border-color:var(--color-zinc-900)}.bg-\[\#0b1020\]{background-color:#0b1020}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-rose-50{background-color:var(--color-rose-50)}.bg-white{background-color:var(--color-white)}.bg-zinc-50{background-color:var(--color-zinc-50)}.bg-zinc-100{background-color:var(--color-zinc-100)}.bg-zinc-200{background-color:var(--color-zinc-200)}.bg-zinc-700{background-color:var(--color-zinc-700)}.bg-zinc-900{background-color:var(--color-zinc-900)}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.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:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-5{padding-left:calc(var(--spacing) * 5)}.pl-9{padding-left:calc(var(--spacing) * 9)}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--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))}.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)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-800{color:var(--color-amber-800)}.text-white{color:var(--color-white)}.text-zinc-100{color:var(--color-zinc-100)}.text-zinc-400{color:var(--color-zinc-400)}.text-zinc-500{color:var(--color-zinc-500)}.text-zinc-600{color:var(--color-zinc-600)}.text-zinc-700{color:var(--color-zinc-700)}.text-zinc-900{color:var(--color-zinc-900)}.uppercase{text-transform:uppercase}.opacity-60{opacity:.6}.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-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px 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-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px 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)}.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-\[width\]{transition-property:width;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}.placeholder\:text-zinc-400::placeholder{color:var(--color-zinc-400)}@media (hover:hover){.hover\:bg-zinc-50:hover{background-color:var(--color-zinc-50)}.hover\:bg-zinc-100:hover{background-color:var(--color-zinc-100)}.hover\:bg-zinc-200:hover{background-color:var(--color-zinc-200)}.hover\:bg-zinc-700:hover{background-color:var(--color-zinc-700)}.hover\:text-zinc-700:hover{color:var(--color-zinc-700)}.hover\:text-zinc-900:hover{color:var(--color-zinc-900)}}.focus\:border-zinc-400:focus{border-color:var(--color-zinc-400)}.focus\:ring-zinc-400:focus{--tw-ring-color:var(--color-zinc-400)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:text-zinc-300:disabled{color:var(--color-zinc-300)}.disabled\:opacity-50:disabled{opacity:.5}@media (hover:hover){.disabled\:hover\:bg-transparent:disabled:hover{background-color:#0000}}:where(.dark\:divide-zinc-800:where(.dark,.dark *)>:not(:last-child)){border-color:var(--color-zinc-800)}.dark\:border-amber-900:where(.dark,.dark *){border-color:var(--color-amber-900)}.dark\:border-zinc-600:where(.dark,.dark *){border-color:var(--color-zinc-600)}.dark\:border-zinc-700:where(.dark,.dark *){border-color:var(--color-zinc-700)}.dark\:bg-amber-950:where(.dark,.dark *){background-color:var(--color-amber-950)}.dark\:bg-zinc-300:where(.dark,.dark *){background-color:var(--color-zinc-300)}.dark\:bg-zinc-800:where(.dark,.dark *){background-color:var(--color-zinc-800)}.dark\:bg-zinc-900:where(.dark,.dark *){background-color:var(--color-zinc-900)}.dark\:bg-zinc-950:where(.dark,.dark *){background-color:var(--color-zinc-950)}.dark\:text-amber-200:where(.dark,.dark *){color:var(--color-amber-200)}.dark\:text-zinc-100:where(.dark,.dark *){color:var(--color-zinc-100)}.dark\:text-zinc-200:where(.dark,.dark *){color:var(--color-zinc-200)}.dark\:text-zinc-300:where(.dark,.dark *){color:var(--color-zinc-300)}.dark\:text-zinc-400:where(.dark,.dark *){color:var(--color-zinc-400)}.dark\:text-zinc-500:where(.dark,.dark *),.dark\:placeholder\:text-zinc-500:where(.dark,.dark *)::placeholder{color:var(--color-zinc-500)}@media (hover:hover){.dark\:hover\:bg-zinc-800:where(.dark,.dark *):hover{background-color:var(--color-zinc-800)}.dark\:hover\:text-zinc-200:where(.dark,.dark *):hover{color:var(--color-zinc-200)}}}@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-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{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-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}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}