vite-plugin-lingo 0.0.1

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.
Files changed (38) hide show
  1. package/README.md +266 -0
  2. package/dist/index.d.ts +8 -0
  3. package/dist/index.js +10 -0
  4. package/dist/plugin/gettext-parser.d.ts +44 -0
  5. package/dist/plugin/index.cjs +449 -0
  6. package/dist/plugin/index.cjs.map +1 -0
  7. package/dist/plugin/index.d.cts +84 -0
  8. package/dist/plugin/index.d.ts +84 -0
  9. package/dist/plugin/index.js +413 -0
  10. package/dist/plugin/index.js.map +1 -0
  11. package/dist/plugin/middleware.d.ts +10 -0
  12. package/dist/plugin/middleware.js +137 -0
  13. package/dist/plugin/po-parser.d.ts +25 -0
  14. package/dist/plugin/po-parser.js +147 -0
  15. package/dist/plugin/types.d.ts +67 -0
  16. package/dist/plugin/types.js +1 -0
  17. package/dist/ui/App.svelte +92 -0
  18. package/dist/ui/App.svelte.d.ts +3 -0
  19. package/dist/ui/app.css +64 -0
  20. package/dist/ui/components/LanguageList.svelte +166 -0
  21. package/dist/ui/components/LanguageList.svelte.d.ts +6 -0
  22. package/dist/ui/components/ProgressBar.svelte +47 -0
  23. package/dist/ui/components/ProgressBar.svelte.d.ts +9 -0
  24. package/dist/ui/components/SearchBar.svelte +54 -0
  25. package/dist/ui/components/SearchBar.svelte.d.ts +6 -0
  26. package/dist/ui/components/ThemeToggle.svelte +17 -0
  27. package/dist/ui/components/ThemeToggle.svelte.d.ts +18 -0
  28. package/dist/ui/components/TranslationEditor.svelte +418 -0
  29. package/dist/ui/components/TranslationEditor.svelte.d.ts +8 -0
  30. package/dist/ui/index.html +24 -0
  31. package/dist/ui/main.d.ts +3 -0
  32. package/dist/ui/main.js +7 -0
  33. package/dist/ui/stores/refresh-signal.svelte.d.ts +6 -0
  34. package/dist/ui/stores/refresh-signal.svelte.js +11 -0
  35. package/dist/ui-dist/assets/index-B5dZv0sy.css +1 -0
  36. package/dist/ui-dist/assets/index-DsX4xzGF.js +10 -0
  37. package/dist/ui-dist/index.html +25 -0
  38. package/package.json +118 -0
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const ThemeToggle: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type ThemeToggle = InstanceType<typeof ThemeToggle>;
18
+ export default ThemeToggle;
@@ -0,0 +1,418 @@
1
+ <script lang="ts">
2
+ import {
3
+ LoaderCircle,
4
+ TriangleAlert,
5
+ FileText,
6
+ Pencil,
7
+ Check,
8
+ X,
9
+ MapPin,
10
+ CircleCheck,
11
+ CircleAlert,
12
+ CircleDashed,
13
+ Flag,
14
+ FlagOff,
15
+ MessageSquareText,
16
+ Info
17
+ } from '@lucide/svelte';
18
+ import { triggerRefresh } from '../stores/refresh-signal.svelte';
19
+
20
+ interface Translation {
21
+ msgid: string;
22
+ msgstr: string;
23
+ context?: string;
24
+ fuzzy?: boolean;
25
+ comments?: {
26
+ reference?: string;
27
+ translator?: string;
28
+ extracted?: string;
29
+ flag?: string;
30
+ };
31
+ }
32
+
33
+ interface Props {
34
+ language: string;
35
+ searchQuery: string;
36
+ filter: 'all' | 'translated' | 'untranslated' | 'fuzzy';
37
+ }
38
+
39
+ let { language, searchQuery, filter }: Props = $props();
40
+
41
+ let translations = $state<Translation[]>([]);
42
+ let loading = $state(true);
43
+ let error = $state<string | null>(null);
44
+ let saving = $state<string | null>(null);
45
+ let editingId = $state<string | null>(null);
46
+ let editValue = $state('');
47
+ let togglingFuzzy = $state<string | null>(null);
48
+
49
+ // Derived filtered translations
50
+ let filteredTranslations = $derived.by(() => {
51
+ let result = translations;
52
+
53
+ // Apply filter
54
+ switch (filter) {
55
+ case 'translated':
56
+ result = result.filter((t) => t.msgstr && !t.fuzzy);
57
+ break;
58
+ case 'untranslated':
59
+ result = result.filter((t) => !t.msgstr);
60
+ break;
61
+ case 'fuzzy':
62
+ result = result.filter((t) => t.fuzzy);
63
+ break;
64
+ }
65
+
66
+ // Apply search
67
+ if (searchQuery) {
68
+ const query = searchQuery.toLowerCase();
69
+ result = result.filter(
70
+ (t) =>
71
+ t.msgid.toLowerCase().includes(query) || t.msgstr.toLowerCase().includes(query)
72
+ );
73
+ }
74
+
75
+ return result;
76
+ });
77
+
78
+ // Stats
79
+ let stats = $derived({
80
+ total: translations.length,
81
+ translated: translations.filter((t) => t.msgstr && !t.fuzzy).length,
82
+ untranslated: translations.filter((t) => !t.msgstr).length,
83
+ fuzzy: translations.filter((t) => t.fuzzy).length
84
+ });
85
+
86
+ // Load translations when language changes
87
+ $effect(() => {
88
+ if (language) {
89
+ loadTranslations();
90
+ }
91
+ });
92
+
93
+ async function loadTranslations() {
94
+ loading = true;
95
+ error = null;
96
+
97
+ try {
98
+ const res = await fetch(`./api/translations/${language}`);
99
+ const result = await res.json();
100
+
101
+ if (!result.success) {
102
+ throw new Error(result.error || 'Failed to load translations');
103
+ }
104
+
105
+ translations = result.data || [];
106
+ } catch (e) {
107
+ error = e instanceof Error ? e.message : 'Failed to load translations';
108
+ } finally {
109
+ loading = false;
110
+ }
111
+ }
112
+
113
+ function startEdit(t: Translation) {
114
+ editingId = t.msgid;
115
+ editValue = t.msgstr;
116
+ }
117
+
118
+ function cancelEdit() {
119
+ editingId = null;
120
+ editValue = '';
121
+ }
122
+
123
+ async function saveEdit(t: Translation) {
124
+ if (editValue === t.msgstr) {
125
+ cancelEdit();
126
+ return;
127
+ }
128
+
129
+ saving = t.msgid;
130
+
131
+ try {
132
+ const res = await fetch(`./api/translations/${language}`, {
133
+ method: 'PUT',
134
+ headers: { 'Content-Type': 'application/json' },
135
+ body: JSON.stringify({
136
+ msgid: t.msgid,
137
+ msgstr: editValue,
138
+ context: t.context
139
+ })
140
+ });
141
+
142
+ const result = await res.json();
143
+
144
+ if (!result.success) {
145
+ throw new Error(result.error || 'Failed to save');
146
+ }
147
+
148
+ // Update local state
149
+ const index = translations.findIndex((tr) => tr.msgid === t.msgid);
150
+ if (index !== -1) {
151
+ translations[index] = { ...translations[index], msgstr: editValue };
152
+ }
153
+
154
+ // Notify the language list to refresh stats
155
+ triggerRefresh();
156
+
157
+ cancelEdit();
158
+ } catch (e) {
159
+ alert(e instanceof Error ? e.message : 'Failed to save');
160
+ } finally {
161
+ saving = null;
162
+ }
163
+ }
164
+
165
+ function handleKeydown(e: KeyboardEvent, t: Translation) {
166
+ if (e.key === 'Enter' && !e.shiftKey) {
167
+ e.preventDefault();
168
+ saveEdit(t);
169
+ }
170
+ if (e.key === 'Escape') {
171
+ cancelEdit();
172
+ }
173
+ }
174
+
175
+ async function toggleFuzzy(t: Translation) {
176
+ togglingFuzzy = t.msgid;
177
+
178
+ try {
179
+ const res = await fetch(`./api/translations/${language}`, {
180
+ method: 'PUT',
181
+ headers: { 'Content-Type': 'application/json' },
182
+ body: JSON.stringify({
183
+ msgid: t.msgid,
184
+ msgstr: t.msgstr,
185
+ context: t.context,
186
+ fuzzy: !t.fuzzy
187
+ })
188
+ });
189
+
190
+ const result = await res.json();
191
+
192
+ if (!result.success) {
193
+ throw new Error(result.error || 'Failed to toggle fuzzy status');
194
+ }
195
+
196
+ // Update local state
197
+ const index = translations.findIndex((tr) => tr.msgid === t.msgid);
198
+ if (index !== -1) {
199
+ translations[index] = { ...translations[index], fuzzy: !t.fuzzy };
200
+ }
201
+
202
+ // Notify the language list to refresh stats
203
+ triggerRefresh();
204
+ } catch (e) {
205
+ alert(e instanceof Error ? e.message : 'Failed to toggle fuzzy status');
206
+ } finally {
207
+ togglingFuzzy = null;
208
+ }
209
+ }
210
+
211
+ function getStatusIcon(t: Translation) {
212
+ if (t.fuzzy) return { icon: CircleAlert, class: 'text-amber-500' };
213
+ if (t.msgstr) return { icon: CircleCheck, class: 'text-emerald-500' };
214
+ return { icon: CircleDashed, class: 'text-red-400' };
215
+ }
216
+ </script>
217
+
218
+ <div class="flex flex-1 flex-col overflow-hidden">
219
+ <!-- Stats bar -->
220
+ <div class="flex items-center gap-6 border-b border-slate-200 bg-white px-6 py-3 dark:border-slate-700 dark:bg-slate-800">
221
+ <div class="flex items-center gap-2">
222
+ <span class="text-2xl font-semibold text-slate-900 dark:text-white">{stats.total}</span>
223
+ <span class="text-sm text-slate-500 dark:text-slate-400">Total</span>
224
+ </div>
225
+ <div class="flex items-center gap-2">
226
+ <CircleCheck class="h-4 w-4 text-emerald-500" />
227
+ <span class="font-medium text-emerald-600 dark:text-emerald-400">{stats.translated}</span>
228
+ <span class="text-sm text-slate-500 dark:text-slate-400">Translated</span>
229
+ </div>
230
+ <div class="flex items-center gap-2">
231
+ <CircleDashed class="h-4 w-4 text-red-400" />
232
+ <span class="font-medium text-red-600 dark:text-red-400">{stats.untranslated}</span>
233
+ <span class="text-sm text-slate-500 dark:text-slate-400">Untranslated</span>
234
+ </div>
235
+ <div class="flex items-center gap-2">
236
+ <CircleAlert class="h-4 w-4 text-amber-500" />
237
+ <span class="font-medium text-amber-600 dark:text-amber-400">{stats.fuzzy}</span>
238
+ <span class="text-sm text-slate-500 dark:text-slate-400">Fuzzy</span>
239
+ </div>
240
+ <div class="ml-auto text-sm text-slate-500 dark:text-slate-400">
241
+ Showing {filteredTranslations.length} of {stats.total}
242
+ </div>
243
+ </div>
244
+
245
+ <!-- Content -->
246
+ {#if loading}
247
+ <div class="flex flex-1 flex-col items-center justify-center gap-3 text-slate-500 dark:text-slate-400">
248
+ <LoaderCircle class="h-8 w-8 animate-spin text-blue-500" />
249
+ <span>Loading translations...</span>
250
+ </div>
251
+ {:else if error}
252
+ <div class="flex flex-1 flex-col items-center justify-center gap-4">
253
+ <TriangleAlert class="h-10 w-10 text-red-400" />
254
+ <p class="text-red-600 dark:text-red-400">{error}</p>
255
+ <button type="button" class="btn btn-secondary" onclick={loadTranslations}>
256
+ Retry
257
+ </button>
258
+ </div>
259
+ {:else if filteredTranslations.length === 0}
260
+ <div class="flex flex-1 flex-col items-center justify-center gap-3 text-slate-500 dark:text-slate-400">
261
+ <FileText class="h-10 w-10 text-slate-300 dark:text-slate-600" />
262
+ <p class="font-medium">No translations found</p>
263
+ {#if searchQuery || filter !== 'all'}
264
+ <p class="text-sm text-slate-400 dark:text-slate-500">Try adjusting your search or filter</p>
265
+ {/if}
266
+ </div>
267
+ {:else}
268
+ <div class="flex-1 overflow-y-auto">
269
+ <div class="divide-y divide-slate-100 dark:divide-slate-700">
270
+ {#each filteredTranslations as t (t.msgid)}
271
+ {@const status = getStatusIcon(t)}
272
+ <div
273
+ class="group px-6 py-4 transition-colors hover:bg-slate-50 dark:hover:bg-slate-800/50 {t.fuzzy
274
+ ? 'bg-amber-50/50 dark:bg-amber-900/10'
275
+ : !t.msgstr
276
+ ? 'bg-red-50/30 dark:bg-red-900/10'
277
+ : ''}"
278
+ >
279
+ <div class="flex gap-4">
280
+ <!-- Status icon -->
281
+ <div class="shrink-0 pt-0.5">
282
+ <status.icon class="h-5 w-5 {status.class}" />
283
+ </div>
284
+
285
+ <!-- Content -->
286
+ <div class="min-w-0 flex-1 space-y-3">
287
+ <!-- Source -->
288
+ <div>
289
+ <div class="mb-1 flex items-center gap-2">
290
+ <span class="text-xs font-medium uppercase tracking-wide text-slate-400">Source</span>
291
+ {#if t.context}
292
+ <span class="badge badge-secondary text-xs">ctx: {t.context}</span>
293
+ {/if}
294
+ </div>
295
+ <code class="block rounded bg-slate-100 px-3 py-2 text-sm text-slate-800 dark:bg-slate-700 dark:text-slate-200">
296
+ {t.msgid}
297
+ </code>
298
+ {#if t.comments?.reference}
299
+ <div class="mt-1 flex items-center gap-1 text-xs text-slate-400 dark:text-slate-500">
300
+ <MapPin class="h-3 w-3" />
301
+ {t.comments.reference}
302
+ </div>
303
+ {/if}
304
+ </div>
305
+
306
+ <!-- Comments (translator notes, extracted comments) -->
307
+ {#if t.comments?.translator || t.comments?.extracted}
308
+ <div class="rounded-lg border border-slate-200 bg-slate-50 p-3 dark:border-slate-600 dark:bg-slate-800/50">
309
+ {#if t.comments.translator}
310
+ <div class="flex items-start gap-2 text-sm">
311
+ <MessageSquareText class="mt-0.5 h-4 w-4 shrink-0 text-blue-500" />
312
+ <div>
313
+ <span class="font-medium text-slate-600 dark:text-slate-300">Translator note:</span>
314
+ <span class="ml-1 text-slate-700 dark:text-slate-200">{t.comments.translator}</span>
315
+ </div>
316
+ </div>
317
+ {/if}
318
+ {#if t.comments.extracted}
319
+ <div class="flex items-start gap-2 text-sm {t.comments.translator ? 'mt-2' : ''}">
320
+ <Info class="mt-0.5 h-4 w-4 shrink-0 text-slate-400" />
321
+ <div>
322
+ <span class="font-medium text-slate-600 dark:text-slate-300">Context:</span>
323
+ <span class="ml-1 text-slate-700 dark:text-slate-200">{t.comments.extracted}</span>
324
+ </div>
325
+ </div>
326
+ {/if}
327
+ </div>
328
+ {/if}
329
+
330
+ <!-- Translation -->
331
+ <div>
332
+ <div class="mb-1 flex items-center gap-2">
333
+ <span class="text-xs font-medium uppercase tracking-wide text-slate-400">Translation</span>
334
+ {#if t.fuzzy}
335
+ <span class="badge badge-warning">Fuzzy</span>
336
+ {/if}
337
+ <!-- Fuzzy toggle button -->
338
+ {#if t.msgstr}
339
+ <button
340
+ type="button"
341
+ class="ml-auto flex items-center gap-1 rounded px-2 py-1 text-xs transition-colors {t.fuzzy
342
+ ? 'bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400 dark:hover:bg-amber-900/50'
343
+ : 'bg-slate-100 text-slate-600 hover:bg-slate-200 dark:bg-slate-700 dark:text-slate-400 dark:hover:bg-slate-600'}"
344
+ onclick={() => toggleFuzzy(t)}
345
+ disabled={togglingFuzzy === t.msgid}
346
+ title={t.fuzzy ? 'Mark as not fuzzy' : 'Mark as fuzzy (needs review)'}
347
+ >
348
+ {#if togglingFuzzy === t.msgid}
349
+ <LoaderCircle class="h-3 w-3 animate-spin" />
350
+ {:else if t.fuzzy}
351
+ <FlagOff class="h-3 w-3" />
352
+ <span>Unflag</span>
353
+ {:else}
354
+ <Flag class="h-3 w-3" />
355
+ <span>Mark fuzzy</span>
356
+ {/if}
357
+ </button>
358
+ {/if}
359
+ </div>
360
+
361
+ {#if editingId === t.msgid}
362
+ <!-- Edit mode -->
363
+ <div class="space-y-2">
364
+ <textarea
365
+ bind:value={editValue}
366
+ onkeydown={(e) => handleKeydown(e, t)}
367
+ rows="2"
368
+ class="input w-full resize-none font-mono text-sm"
369
+ placeholder="Enter translation..."
370
+ ></textarea>
371
+ <div class="flex items-center gap-2">
372
+ <button
373
+ type="button"
374
+ class="btn btn-primary"
375
+ onclick={() => saveEdit(t)}
376
+ disabled={saving === t.msgid}
377
+ >
378
+ {#if saving === t.msgid}
379
+ <LoaderCircle class="h-4 w-4 animate-spin" />
380
+ Saving...
381
+ {:else}
382
+ <Check class="h-4 w-4" />
383
+ Save
384
+ {/if}
385
+ </button>
386
+ <button type="button" class="btn btn-ghost" onclick={cancelEdit}>
387
+ <X class="h-4 w-4" />
388
+ Cancel
389
+ </button>
390
+ <span class="ml-2 text-xs text-slate-400 dark:text-slate-500">
391
+ Enter to save, Esc to cancel
392
+ </span>
393
+ </div>
394
+ </div>
395
+ {:else}
396
+ <!-- Display mode -->
397
+ <button
398
+ type="button"
399
+ class="group/edit flex w-full items-start gap-2 rounded-lg px-3 py-2 text-left transition-colors hover:bg-slate-100 dark:hover:bg-slate-700"
400
+ onclick={() => startEdit(t)}
401
+ >
402
+ {#if t.msgstr}
403
+ <span class="flex-1 text-sm text-slate-800 dark:text-slate-200">{t.msgstr}</span>
404
+ {:else}
405
+ <span class="flex-1 text-sm italic text-slate-400 dark:text-slate-500">Click to add translation</span>
406
+ {/if}
407
+ <Pencil class="h-4 w-4 shrink-0 text-slate-400 opacity-0 transition-opacity group-hover/edit:opacity-100" />
408
+ </button>
409
+ {/if}
410
+ </div>
411
+ </div>
412
+ </div>
413
+ </div>
414
+ {/each}
415
+ </div>
416
+ </div>
417
+ {/if}
418
+ </div>
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ language: string;
3
+ searchQuery: string;
4
+ filter: 'all' | 'translated' | 'untranslated' | 'fuzzy';
5
+ }
6
+ declare const TranslationEditor: import("svelte").Component<Props, {}, "">;
7
+ type TranslationEditor = ReturnType<typeof TranslationEditor>;
8
+ export default TranslationEditor;
@@ -0,0 +1,24 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Lingo Translation Editor</title>
7
+ <script>
8
+ // Prevent FOUC by setting theme before page renders
9
+ (function() {
10
+ const stored = localStorage.getItem('mode-watcher-mode');
11
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
12
+ const theme = stored ? JSON.parse(stored) : (prefersDark ? 'dark' : 'light');
13
+ if (theme === 'dark' || (theme === 'system' && prefersDark)) {
14
+ document.documentElement.classList.add('dark');
15
+ }
16
+ document.documentElement.style.colorScheme = theme === 'dark' || (theme === 'system' && prefersDark) ? 'dark' : 'light';
17
+ })();
18
+ </script>
19
+ </head>
20
+ <body>
21
+ <div id="app"></div>
22
+ <script type="module" src="./main.ts"></script>
23
+ </body>
24
+ </html>
@@ -0,0 +1,3 @@
1
+ import './app.css';
2
+ declare const app: {};
3
+ export default app;
@@ -0,0 +1,7 @@
1
+ import './app.css';
2
+ import { mount } from 'svelte';
3
+ import App from './App.svelte';
4
+ const app = mount(App, {
5
+ target: document.getElementById('app')
6
+ });
7
+ export default app;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Simple reactive signal to notify the LanguageList when translations are updated.
3
+ * Using Svelte 5 runes for fine-grained reactivity.
4
+ */
5
+ export declare function getRefreshCount(): number;
6
+ export declare function triggerRefresh(): void;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Simple reactive signal to notify the LanguageList when translations are updated.
3
+ * Using Svelte 5 runes for fine-grained reactivity.
4
+ */
5
+ let refreshCount = $state(0);
6
+ export function getRefreshCount() {
7
+ return refreshCount;
8
+ }
9
+ export function triggerRefresh() {
10
+ refreshCount++;
11
+ }
@@ -0,0 +1 @@
1
+ @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,::backdrop{--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-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-900:oklch(39.6% .141 25.723);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-900:oklch(41.4% .112 45.904);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-900:oklch(37.8% .077 168.94);--color-blue-50:oklch(97% .014 254.604);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-900:oklch(37.9% .146 265.522);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--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-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--animate-spin:spin 1s linear 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,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;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}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}body{background-color:var(--color-slate-50);color:var(--color-slate-900);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body:where(.dark,.dark *){background-color:var(--color-slate-900);color:var(--color-slate-100)}}@layer components{.btn{justify-content:center;align-items:center;gap:calc(var(--spacing)*2);border-radius:var(--radius-md);padding-inline:calc(var(--spacing)*3);padding-block:calc(var(--spacing)*1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);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));display:inline-flex}.btn: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);--tw-ring-color:var(--color-blue-500);--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);--tw-outline-style:none;outline-style:none}.btn:disabled{pointer-events:none;opacity:.5}.btn:where(.dark,.dark *):focus-visible{--tw-ring-offset-color:var(--color-slate-900)}.btn-primary{background-color:var(--color-blue-600);color:var(--color-white)}@media(hover:hover){.btn-primary:hover{background-color:var(--color-blue-700)}}.btn-primary:where(.dark,.dark *){background-color:var(--color-blue-500)}@media(hover:hover){.btn-primary:where(.dark,.dark *):hover{background-color:var(--color-blue-600)}}.btn-secondary{background-color:var(--color-slate-100);color:var(--color-slate-900)}@media(hover:hover){.btn-secondary:hover{background-color:var(--color-slate-200)}}.btn-secondary:where(.dark,.dark *){background-color:var(--color-slate-800);color:var(--color-slate-100)}@media(hover:hover){.btn-secondary:where(.dark,.dark *):hover{background-color:var(--color-slate-700)}.btn-ghost:hover{background-color:var(--color-slate-100)}.btn-ghost:where(.dark,.dark *):hover{background-color:var(--color-slate-800)}}.input{height:calc(var(--spacing)*9);border-radius:var(--radius-md);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-slate-300);background-color:var(--color-white);width:100%;padding-inline:calc(var(--spacing)*3);padding-block:calc(var(--spacing)*1);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--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);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));display:flex}.input::placeholder{color:var(--color-slate-400)}.input: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);--tw-ring-color:var(--color-blue-500);--tw-outline-style:none;border-color:#0000;outline-style:none}.input:disabled{cursor:not-allowed;opacity:.5}.input:where(.dark,.dark *){border-color:var(--color-slate-600);background-color:var(--color-slate-800);color:var(--color-slate-100)}.input:where(.dark,.dark *)::placeholder{color:var(--color-slate-500)}.badge{padding-inline:calc(var(--spacing)*2);padding-block:calc(var(--spacing)*.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);border-radius:3.40282e38px;align-items:center;display:inline-flex}.badge-success{background-color:var(--color-emerald-100);color:var(--color-emerald-700)}.badge-success:where(.dark,.dark *){background-color:#004e3b80}@supports (color:color-mix(in lab,red,red)){.badge-success:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-emerald-900)50%,transparent)}}.badge-success:where(.dark,.dark *){color:var(--color-emerald-400)}.badge-warning{background-color:var(--color-amber-100);color:var(--color-amber-700)}.badge-warning:where(.dark,.dark *){background-color:#7b330680}@supports (color:color-mix(in lab,red,red)){.badge-warning:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-amber-900)50%,transparent)}}.badge-warning:where(.dark,.dark *){color:var(--color-amber-400)}.badge-danger{background-color:var(--color-red-100);color:var(--color-red-700)}.badge-danger:where(.dark,.dark *){background-color:#82181a80}@supports (color:color-mix(in lab,red,red)){.badge-danger:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-red-900)50%,transparent)}}.badge-danger:where(.dark,.dark *){color:var(--color-red-400)}.card{border-radius:var(--radius-lg);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-slate-200);background-color:var(--color-white);--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)}.card:where(.dark,.dark *){border-color:var(--color-slate-700);background-color:var(--color-slate-800)}}@layer utilities{.absolute{position:absolute}.relative{position:relative}.right-3{right:calc(var(--spacing)*3)}.left-3{left:calc(var(--spacing)*3)}.mx-auto{margin-inline:auto}.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-1{margin-bottom:calc(var(--spacing)*1)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.h-1{height:calc(var(--spacing)*1)}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.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-full{height:100%}.h-screen{height:100vh}.w-1\.5{width:calc(var(--spacing)*1.5)}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-10{width:calc(var(--spacing)*10)}.w-12{width:calc(var(--spacing)*12)}.w-72{width:calc(var(--spacing)*72)}.w-full{width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.animate-spin{animation:var(--animate-spin)}.resize-none{resize:none}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}: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(.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-slate-100>:not(:last-child)){border-color:var(--color-slate-100)}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.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-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-slate-200{border-color:var(--color-slate-200)}.border-slate-300{border-color:var(--color-slate-300)}.bg-amber-50\/50{background-color:#fffbeb80}@supports (color:color-mix(in lab,red,red)){.bg-amber-50\/50{background-color:color-mix(in oklab,var(--color-amber-50)50%,transparent)}}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-red-50\/30{background-color:#fef2f24d}@supports (color:color-mix(in lab,red,red)){.bg-red-50\/30{background-color:color-mix(in oklab,var(--color-red-50)30%,transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-200{background-color:var(--color-slate-200)}.bg-white{background-color:var(--color-white)}.p-0\.5{padding:calc(var(--spacing)*.5)}.p-1\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.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)}.py-4{padding-block:calc(var(--spacing)*4)}.pt-0\.5{padding-top:calc(var(--spacing)*.5)}.pr-16{padding-right:calc(var(--spacing)*16)}.pl-9{padding-left:calc(var(--spacing)*9)}.text-center{text-align:center}.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))}.text-\[10px\]{font-size:10px}.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-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-amber-500{color:var(--color-amber-500)}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-blue-900{color:var(--color-blue-900)}.text-emerald-500{color:var(--color-emerald-500)}.text-emerald-600{color:var(--color-emerald-600)}.text-red-400{color:var(--color-red-400)}.text-red-600{color:var(--color-red-600)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-800{color:var(--color-slate-800)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.opacity-0{opacity:0}.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)}.ring-1{--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)}.ring-blue-200{--tw-ring-color:var(--color-blue-200)}.blur{--tw-blur:blur(8px);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,)}.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-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))}.duration-300{--tw-duration:.3s;transition-duration:.3s}@media(hover:hover){.group-hover\/edit\:opacity-100:is(:where(.group\/edit):hover *){opacity:1}}.placeholder\:text-slate-400::placeholder{color:var(--color-slate-400)}@media(hover:hover){.hover\:bg-amber-200:hover{background-color:var(--color-amber-200)}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-100:hover{background-color:var(--color-slate-100)}.hover\:bg-slate-200:hover{background-color:var(--color-slate-200)}.hover\:text-slate-600:hover{color:var(--color-slate-600)}.hover\:text-slate-700:hover{color:var(--color-slate-700)}}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.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-blue-500\/20:focus{--tw-ring-color:#3080ff33}@supports (color:color-mix(in lab,red,red)){.focus\:ring-blue-500\/20:focus{--tw-ring-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:opacity-50:disabled{opacity:.5}:where(.dark\:divide-slate-700:where(.dark,.dark *)>:not(:last-child)){border-color:var(--color-slate-700)}.dark\:border-slate-600:where(.dark,.dark *){border-color:var(--color-slate-600)}.dark\:border-slate-700:where(.dark,.dark *){border-color:var(--color-slate-700)}.dark\:bg-amber-900\/10:where(.dark,.dark *){background-color:#7b33061a}@supports (color:color-mix(in lab,red,red)){.dark\:bg-amber-900\/10:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-amber-900)10%,transparent)}}.dark\:bg-amber-900\/30:where(.dark,.dark *){background-color:#7b33064d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-amber-900\/30:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-amber-900)30%,transparent)}}.dark\:bg-blue-500:where(.dark,.dark *){background-color:var(--color-blue-500)}.dark\:bg-blue-900\/30:where(.dark,.dark *){background-color:#1c398e4d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-900\/30:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-blue-900)30%,transparent)}}.dark\:bg-red-900\/10:where(.dark,.dark *){background-color:#82181a1a}@supports (color:color-mix(in lab,red,red)){.dark\:bg-red-900\/10:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-red-900)10%,transparent)}}.dark\:bg-slate-700:where(.dark,.dark *){background-color:var(--color-slate-700)}.dark\:bg-slate-800:where(.dark,.dark *){background-color:var(--color-slate-800)}.dark\:bg-slate-800\/50:where(.dark,.dark *){background-color:#1d293d80}@supports (color:color-mix(in lab,red,red)){.dark\:bg-slate-800\/50:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-slate-800)50%,transparent)}}.dark\:bg-slate-900:where(.dark,.dark *){background-color:var(--color-slate-900)}.dark\:text-amber-400:where(.dark,.dark *){color:var(--color-amber-400)}.dark\:text-blue-300:where(.dark,.dark *){color:var(--color-blue-300)}.dark\:text-blue-400:where(.dark,.dark *){color:var(--color-blue-400)}.dark\:text-emerald-400:where(.dark,.dark *){color:var(--color-emerald-400)}.dark\:text-red-400:where(.dark,.dark *){color:var(--color-red-400)}.dark\:text-slate-100:where(.dark,.dark *){color:var(--color-slate-100)}.dark\:text-slate-200:where(.dark,.dark *){color:var(--color-slate-200)}.dark\:text-slate-300:where(.dark,.dark *){color:var(--color-slate-300)}.dark\:text-slate-400:where(.dark,.dark *){color:var(--color-slate-400)}.dark\:text-slate-500:where(.dark,.dark *){color:var(--color-slate-500)}.dark\:text-slate-600:where(.dark,.dark *){color:var(--color-slate-600)}.dark\:text-white:where(.dark,.dark *){color:var(--color-white)}.dark\:ring-blue-700:where(.dark,.dark *){--tw-ring-color:var(--color-blue-700)}.dark\:placeholder\:text-slate-500:where(.dark,.dark *)::placeholder{color:var(--color-slate-500)}@media(hover:hover){.dark\:hover\:bg-amber-900\/50:where(.dark,.dark *):hover{background-color:#7b330680}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-amber-900\/50:where(.dark,.dark *):hover{background-color:color-mix(in oklab,var(--color-amber-900)50%,transparent)}}.dark\:hover\:bg-slate-600:where(.dark,.dark *):hover{background-color:var(--color-slate-600)}.dark\:hover\:bg-slate-700:where(.dark,.dark *):hover{background-color:var(--color-slate-700)}.dark\:hover\:bg-slate-700\/50:where(.dark,.dark *):hover{background-color:#31415880}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-slate-700\/50:where(.dark,.dark *):hover{background-color:color-mix(in oklab,var(--color-slate-700)50%,transparent)}}.dark\:hover\:bg-slate-800:where(.dark,.dark *):hover{background-color:var(--color-slate-800)}.dark\:hover\:bg-slate-800\/50:where(.dark,.dark *):hover{background-color:#1d293d80}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-slate-800\/50:where(.dark,.dark *):hover{background-color:color-mix(in oklab,var(--color-slate-800)50%,transparent)}}.dark\:hover\:text-slate-200:where(.dark,.dark *):hover{color:var(--color-slate-200)}.dark\:hover\:text-slate-300:where(.dark,.dark *):hover{color:var(--color-slate-300)}}.dark\:focus\:border-blue-400:where(.dark,.dark *):focus{border-color:var(--color-blue-400)}}@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)}}