@testspectra/cli 1.1.11-rc.5 → 1.1.13

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 (92) hide show
  1. package/demo-app/assets/index-DDYS5fLp.css +1 -0
  2. package/demo-app/assets/index-euCENPMy.js +154 -0
  3. package/demo-app/index.html +2 -2
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/commands/__tests__/run-e2e.test.js +24 -6
  6. package/dist/commands/demo.d.ts +1 -0
  7. package/dist/commands/demo.js +26 -4
  8. package/dist/commands/doctor.js +23 -0
  9. package/dist/commands/run.d.ts +3 -0
  10. package/dist/commands/run.js +41 -4
  11. package/dist/commands/test.d.ts +9 -9
  12. package/dist/commands/test.js +40 -75
  13. package/dist/commands/update.d.ts +3 -0
  14. package/dist/commands/update.js +109 -0
  15. package/dist/config/loader.js +31 -4
  16. package/dist/config/schema.d.ts +58 -0
  17. package/dist/config/schema.js +4 -1
  18. package/dist/generator/__tests__/tsconfig-isolation.test.js +21 -0
  19. package/dist/generator/__tests__/type-generator.test.js +14 -0
  20. package/dist/generator/tsconfig-generator.js +1 -0
  21. package/dist/generator/type-generator.js +2 -0
  22. package/dist/index.js +8 -4
  23. package/dist/lifecycle/__tests__/lifecycle-engine.test.js +290 -0
  24. package/dist/lifecycle/hook-discovery.d.ts +24 -0
  25. package/dist/lifecycle/hook-discovery.js +60 -0
  26. package/dist/lifecycle/hook-dispatcher.d.ts +34 -0
  27. package/dist/lifecycle/hook-dispatcher.js +190 -0
  28. package/dist/lifecycle/index.d.ts +3 -0
  29. package/dist/lifecycle/index.js +3 -0
  30. package/dist/lifecycle/parallel-grouping.d.ts +27 -0
  31. package/dist/lifecycle/parallel-grouping.js +151 -0
  32. package/dist/reporter/semantic-formatter.js +2 -0
  33. package/dist/reporter/types.d.ts +1 -1
  34. package/dist/runner/bridge.d.ts +2 -0
  35. package/dist/runner/bridge.js +4 -1
  36. package/dist/runner/reporter.d.ts +5 -43
  37. package/dist/runner/reporter.js +46 -179
  38. package/dist/utils/__tests__/demo-state.test.d.ts +1 -0
  39. package/dist/utils/__tests__/demo-state.test.js +96 -0
  40. package/dist/utils/api-server.d.ts +1 -1
  41. package/dist/utils/api-server.js +7 -3
  42. package/dist/utils/demo-server.d.ts +2 -0
  43. package/dist/utils/demo-server.js +18 -5
  44. package/dist/utils/demo-state.d.ts +40 -0
  45. package/dist/utils/demo-state.js +157 -0
  46. package/package.json +8 -7
  47. package/templates/default/fixtures/sampleDocument.pdf +14 -0
  48. package/templates/default/fixtures/sampleImage.png +0 -0
  49. package/templates/default/package.json +2 -2
  50. package/templates/default/page-objects/MatchersPage/common.ts +41 -0
  51. package/templates/default/page-objects/MatchersPage/mobile.ts +8 -3
  52. package/templates/default/page-objects/PlaygroundPage/mobile.ts +6 -0
  53. package/templates/default/page-objects/PlaygroundPage/web.ts +2 -0
  54. package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/mobile.test.ts +3 -0
  55. package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/mobile.test.ts +3 -0
  56. package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +1 -1
  57. package/templates/default/specs/Playground/TC-0003-file-upload/web.test.ts +11 -0
  58. package/templates/default/spectra.config.ts +5 -1
  59. package/templates/nx/.nx/workspace-data/70094CFD-E89B-57A1-9619-2FC5F4963C54.db +0 -0
  60. package/templates/nx/.nx/workspace-data/70094CFD-E89B-57A1-9619-2FC5F4963C54.db-shm +0 -0
  61. package/templates/nx/.nx/workspace-data/70094CFD-E89B-57A1-9619-2FC5F4963C54.db-wal +0 -0
  62. package/templates/nx/.nx/workspace-data/d/daemon.log +7104 -1012
  63. package/templates/nx/.nx/workspace-data/d/server-process.json +3 -0
  64. package/templates/nx/.nx/workspace-data/file-map.json +116 -104
  65. package/templates/nx/.nx/workspace-data/lockfile.hash +1 -1
  66. package/templates/nx/.nx/workspace-data/nx_files.nxt +0 -0
  67. package/templates/nx/.nx/workspace-data/parsed-lock-file.json +81 -130
  68. package/templates/nx/.nx/workspace-data/project-graph.json +83 -138
  69. package/templates/nx/package.json +2 -2
  70. package/templates/nx/packages/matchers/e2e/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +1 -1
  71. package/templates/nx/packages/playground/e2e/specs/Playground/TC-0003-file-upload/web.test.ts +11 -0
  72. package/templates/nx/shared/testing/fixtures/sampleDocument.pdf +14 -0
  73. package/templates/nx/shared/testing/fixtures/sampleImage.png +0 -0
  74. package/templates/nx/shared/testing/page-objects/MatchersPage/mobile.ts +68 -26
  75. package/templates/nx/shared/testing/page-objects/PlaygroundPage/mobile.ts +39 -17
  76. package/templates/nx/shared/testing/page-objects/PlaygroundPage/web.ts +2 -0
  77. package/templates/nx/spectra.config.ts +3 -3
  78. package/templates/react-component/fixtures/sampleDocument.pdf +14 -0
  79. package/templates/react-component/fixtures/sampleImage.png +0 -0
  80. package/templates/react-component/package.json +3 -3
  81. package/templates/react-component/page-objects/FileUploadComponent/web.ts +15 -0
  82. package/templates/react-component/specs/FileUploadComponent/TC-0001-upload-fixtures/web.test.tsx +18 -0
  83. package/templates/react-component/specs/UserListComponent/TC-0001-intercepted-user-list/spec.md +20 -0
  84. package/templates/react-component/specs/UserListComponent/TC-0001-intercepted-user-list/web.test.tsx +15 -0
  85. package/templates/react-component/specs/UserListComponent/suite.md +12 -0
  86. package/templates/react-component/src/components/FileUpload/FileUpload.tsx +44 -0
  87. package/templates/react-component/src/components/UserList/UserList.tsx +48 -0
  88. package/bin/.testspectra-runner.hash +0 -1
  89. package/demo-app/assets/index-BhlW-eXG.css +0 -1
  90. package/demo-app/assets/index-DOtRypCa.js +0 -154
  91. package/dist/commands/__tests__/doctor-scope.test.js +0 -24
  92. /package/dist/{commands/__tests__/doctor-scope.test.d.ts → lifecycle/__tests__/lifecycle-engine.test.d.ts} +0 -0
@@ -1,33 +1,75 @@
1
1
  class MatchersPage {
2
- get visibleElement() { return Spectra.get("~visible_element"); }
3
- get hiddenElement() { return Spectra.get("~hidden_element"); }
4
- get existingElement() { return Spectra.get("~existing_element"); }
5
- get submitButton() { return Spectra.get("~submit_button"); }
6
- get disabledButton() { return Spectra.get("~disabled_button"); }
7
- get checkbox() { return Spectra.get("~checkbox"); }
8
- get radio() { return Spectra.get("~radio"); }
9
- get emailInput() { return Spectra.get("~email_input"); }
10
- get tokenInput() { return Spectra.get("~token_input"); }
11
- get exactText() { return Spectra.get("~exact_text"); }
12
- get partialText() { return Spectra.get("~partial_text"); }
13
- get activeTab() { return Spectra.get("~active_tab"); }
14
- get navLink() { return Spectra.get("~nav_link"); }
15
- get productCards() { return Spectra.getAll("~product_card"); }
16
- get emptyList() { return Spectra.getAll("~empty_list"); }
2
+ get visibleElement() { return Spectra.get("~visible-element"); }
3
+ get hiddenElement() { return Spectra.get("~hidden-element"); }
4
+ get existingElement() { return Spectra.get("~existing-element"); }
5
+ get removableElement() { return Spectra.get("~removable-element"); }
6
+ get submitButton() { return Spectra.get("~submit-button"); }
7
+ get disabledButton() { return Spectra.get("~disabled-button"); }
8
+ get checkbox() { return Spectra.get("~terms-checkbox"); }
9
+ get radio() { return Spectra.get("~mode-radio"); }
10
+ get emailInput() { return Spectra.get("~email-input"); }
11
+ get tokenInput() { return Spectra.get("~token-input"); }
12
+ get exactText() { return Spectra.get("~exact-text"); }
13
+ get partialText() { return Spectra.get("~partial-text"); }
14
+ // `#` = native id (RN testID → resource-id). Its accessibility label deliberately reads
15
+ // "active-tab is-active" (RN exposes no CSS classes, so the class is carried in the a11y label
16
+ // for `shouldHaveClass`), so it isn't addressable by the a11y-id form `~active-tab`.
17
+ get activeTab() { return Spectra.get("#active-tab"); }
18
+ get navLink() { return Spectra.get("~nav-link"); }
19
+ get styledElement() { return Spectra.get("~styled-element"); }
20
+ get focusInput() { return Spectra.get("~focus-input"); }
21
+ get productCards() { return Spectra.getAll("~product-item-1, ~product-item-2, ~product-item-3, ~product-item-4"); }
22
+ get emptyList() { return Spectra.getAll("~empty-list-item"); }
23
+ get overviewSection() { return Spectra.get("#overview-section"); }
24
+ // Scoped lookups via element.get() — resolved within overview-section's own bounds (Android
25
+ // has no ancestor API, so this is a bounds-containment lookup), not screen-wide.
26
+ overviewSubtitle() { return this.overviewSection.get("#demo-page-subtitle"); }
27
+ overviewOutsideElement() { return this.overviewSection.get("~submit-button"); }
17
28
 
18
29
  // API Demo elements
19
- get fetchApiButton() { return Spectra.get("~fetch_api_btn"); }
20
- get fetchStatusBadge() { return Spectra.get("~fetch_status_badge"); }
21
- get fetchedItems() { return Spectra.getAll("~api_fetched_item"); }
22
- get fetchLoadingIndicator() { return Spectra.get("~fetch_loading_indicator"); }
23
- get postTitleInput() { return Spectra.get("~post_input_title"); }
24
- get postBodyInput() { return Spectra.get("~post_input_body"); }
25
- get submitPostButton() { return Spectra.get("~submit_post_btn"); }
26
- get postStatusBadge() { return Spectra.get("~post_status_badge"); }
27
- get postSuccessBanner() { return Spectra.get("~post_success_banner"); }
28
- get postResponseJson() { return Spectra.get("~post_response_json"); }
30
+ get fetchApiButton() { return Spectra.get("~fetch-api-btn"); }
31
+ get fetchStatusBadge() { return Spectra.get("~fetch-status-badge"); }
32
+ get fetchedItems() { return Spectra.getAll("~api-post-item"); }
33
+ get fetchLoadingIndicator() { return Spectra.get("~fetch-loading-indicator"); }
34
+ get fetchCustomUrlInput() { return Spectra.get("~fetch-custom-url"); }
35
+ get postTitleInput() { return Spectra.get("~post-title-input"); }
36
+ get postBodyInput() { return Spectra.get("~post-body-input"); }
37
+ get submitPostButton() { return Spectra.get("~submit-post-btn"); }
38
+ get postStatusBadge() { return Spectra.get("~post-status-badge"); }
39
+ get postSuccessBanner() { return Spectra.get("~post-success-banner"); }
40
+ get postResponseJson() { return Spectra.get("~post-response-json"); }
29
41
 
30
- async open(_section = "") {}
42
+ async open(section = "") {
43
+ try {
44
+ // If a previous test or deep link left the app on a sub-screen, return to home first
45
+ const hasBackBtn = await Spectra.get("~back-to-home-btn").isDisplayed().catch(() => false);
46
+ if (hasBackBtn) {
47
+ await Spectra.get("~back-to-home-btn").click();
48
+ }
49
+
50
+ // A fresh app process (relaunched by the orchestrator's bootstrap before every suite) has to
51
+ // fetch, parse, and execute the RN JS bundle from Metro before anything is on screen — on a
52
+ // cold start this can take well past a normal action's poll budget. Wait for the home screen
53
+ // itself first so that timing doesn't silently swallow the sidebar click below and leave the
54
+ // real failure to surface confusingly on whatever element the test touches next.
55
+ await Spectra.get("~toggle-sidebar-btn").waitForElement(30000);
56
+
57
+ const target = section || "overview";
58
+ const isDrawerOpen = await Spectra.get("~close-sidebar-btn").isDisplayed().catch(() => false);
59
+ if (!isDrawerOpen) {
60
+ await Spectra.get("~toggle-sidebar-btn").click();
61
+ // The mobile drawer is a React Native `<Modal>` — a separate OS-level window with its own
62
+ // slide-in animation, not a plain re-rendered View — so its content (including every
63
+ // nav-item below) isn't in the accessibility tree at all until Android actually finishes
64
+ // creating that window, which is async and occasionally slow under load. Without this
65
+ // wait, clicking a nav item right after the toggle relies entirely on click()'s own
66
+ // poll-retry to bridge that gap, which can eat most of the ~10s implicit-wait budget when
67
+ // the Modal is slow to materialize.
68
+ await Spectra.get("~close-sidebar-btn").waitForElement(10000);
69
+ }
70
+ await Spectra.get(`~nav-item-${target}`).click();
71
+ } catch {}
72
+ }
31
73
  }
32
74
 
33
75
  export default new MatchersPage();
@@ -1,22 +1,44 @@
1
1
  class PlaygroundPage {
2
- get visibleElement() { return Spectra.get("~visible_element"); }
3
- get hiddenElement() { return Spectra.get("~hidden_element"); }
4
- get existingElement() { return Spectra.get("~existing_element"); }
5
- get removedElement() { return Spectra.get("~removed_element"); }
6
- get enabledButton() { return Spectra.get("~enabled_button"); }
7
- get disabledButton() { return Spectra.get("~disabled_button"); }
8
- get termsCheckbox() { return Spectra.get("~terms_checkbox"); }
9
- get modeRadio() { return Spectra.get("~mode_radio"); }
10
- get emailInput() { return Spectra.get("~email_input"); }
11
- get tokenInput() { return Spectra.get("~token_input"); }
12
- get exactText() { return Spectra.get("~exact_text"); }
13
- get partialText() { return Spectra.get("~partial_text"); }
14
- get activeTab() { return Spectra.get("~active_tab"); }
15
- get navLink() { return Spectra.get("~nav_link"); }
16
- get productItems() { return Spectra.getAll("~product_item"); }
17
- get emptyList() { return Spectra.getAll("~empty_list"); }
2
+ get visibleElement() { return Spectra.get("~playground-visible"); }
3
+ get hiddenElement() { return Spectra.get("~playground-hidden"); }
4
+ get existingElement() { return Spectra.get("~playground-existing"); }
5
+ get removedElement() { return Spectra.get("~playground-removable"); }
6
+ get enabledButton() { return Spectra.get("~enabled-button"); }
7
+ get disabledButton() { return Spectra.get("~pg-disabled-button"); }
8
+ get termsCheckbox() { return Spectra.get("~pg-terms-checkbox"); }
9
+ get modeRadio() { return Spectra.get("~pg-mode-radio"); }
10
+ get emailInput() { return Spectra.get("~pg-email-input"); }
11
+ get tokenInput() { return Spectra.get("~pg-token-input"); }
12
+ get exactText() { return Spectra.get("~exact-text-el"); }
13
+ get partialText() { return Spectra.get("~partial-text-el"); }
14
+ get activeTab() { return Spectra.get("~active-tab-el"); }
15
+ get navLink() { return Spectra.get("~nav-link-el"); }
16
+ get styledElement() { return Spectra.get("~playground-styled-element"); }
17
+ get focusInput() { return Spectra.get("~playground-focus-input"); }
18
+ get productItems() { return Spectra.getAll("~product-item-1, ~product-item-2, ~product-item-3, ~product-item-4"); }
19
+ get emptyList() { return Spectra.getAll("~empty-list-el-item"); }
18
20
 
19
- async open() {}
21
+ async open() {
22
+ try {
23
+ // If a previous test or deep link left the app on a sub-screen, return to home first
24
+ const hasBackBtn = await Spectra.get("~back-to-home-btn").isDisplayed().catch(() => false);
25
+ if (hasBackBtn) {
26
+ await Spectra.get("~back-to-home-btn").click();
27
+ }
28
+
29
+ // See MatchersPage.open()'s equivalent comment: waits for the cold-start home screen, then
30
+ // for the drawer Modal to actually finish materializing before clicking a nav item inside
31
+ // it — both races that otherwise surface as an occasional ~10s stall on the next click.
32
+ await Spectra.get("~toggle-sidebar-btn").waitForElement(30000);
33
+
34
+ const isDrawerOpen = await Spectra.get("~close-sidebar-btn").isDisplayed().catch(() => false);
35
+ if (!isDrawerOpen) {
36
+ await Spectra.get("~toggle-sidebar-btn").click();
37
+ await Spectra.get("~close-sidebar-btn").waitForElement(10000);
38
+ }
39
+ await Spectra.get("~nav-item-playground").click();
40
+ } catch {}
41
+ }
20
42
  async fillCredentials(email = Fixture.playgroundData.defaultEmail, token = Fixture.playgroundData.defaultToken) {
21
43
  await this.emailInput.type(email);
22
44
  await this.tokenInput.type(token);
@@ -17,6 +17,8 @@ class PlaygroundPage {
17
17
  get focusInput() { return Spectra.get("#demo-focus-input-pg"); }
18
18
  get productItems() { return Spectra.getAll(".demo-product-item"); }
19
19
  get emptyList() { return Spectra.getAll("#demo-empty-list-pg > *"); }
20
+ get fileInput() { return Spectra.get("#demo-file-input-pg"); }
21
+ get uploadedFilename() { return Spectra.get("#demo-uploaded-filename"); }
20
22
 
21
23
  async open() {
22
24
  await Spectra.navigate("/#playground");
@@ -2,7 +2,7 @@ import { defineConfig } from "@testspectra/cli";
2
2
 
3
3
  export default defineConfig({
4
4
  webConfig: {
5
- baseUrl: "http://localhost:5173",
5
+ baseUrl: "http://localhost:5180",
6
6
  hosts: {
7
7
  // Named host aliases for microfrontends and multi-entrypoint apps
8
8
  // e.g. sso: "https://sso.local:5174", admin: "https://admin.local:5176"
@@ -23,8 +23,8 @@ export default defineConfig({
23
23
  },
24
24
  androidConfig: {
25
25
  driverServer: "tcp://127.0.0.1:8200",
26
- appPackage: "",
27
- appActivity: "",
26
+ appPackage: "dev.testspectra.demoapp",
27
+ appActivity: "dev.testspectra.demoapp.MainActivity",
28
28
  noReset: false,
29
29
  implicitWait: "10000",
30
30
  parallelizationMode: "suite",
@@ -0,0 +1,14 @@
1
+ %PDF-1.4
2
+ 1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
3
+ 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj
4
+ 3 0 obj<</Type/Page/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<<>>>>endobj
5
+ xref
6
+ 0 4
7
+ 0000000000 65535 f
8
+ 0000000009 00000 n
9
+ 0000000058 00000 n
10
+ 0000000115 00000 n
11
+ trailer<</Size 4/Root 1 0 R>>
12
+ startxref
13
+ 206
14
+ %%EOF
@@ -14,9 +14,9 @@
14
14
  "postinstall": "spectra sync-types"
15
15
  },
16
16
  "devDependencies": {
17
- "@testspectra/cli": "^1.1.11-rc.5",
18
- "@testspectra/matchers": "^1.1.11-rc.5",
19
- "@testspectra/react": "^1.1.11-rc.5",
17
+ "@testspectra/cli": "^1.1.13",
18
+ "@testspectra/matchers": "^1.1.13",
19
+ "@testspectra/react": "^1.1.13",
20
20
  "@types/node": "^20.14.0",
21
21
  "@types/react": "^18.3.3",
22
22
  "@types/react-dom": "^18.3.0",
@@ -0,0 +1,15 @@
1
+ class FileUploadComponent {
2
+ get root() {
3
+ return Spectra.get('~file-upload');
4
+ }
5
+
6
+ get input() {
7
+ return Spectra.get('input[type="file"]');
8
+ }
9
+
10
+ get filename() {
11
+ return Spectra.get('~uploaded-filename');
12
+ }
13
+ }
14
+
15
+ export default new FileUploadComponent();
@@ -0,0 +1,18 @@
1
+ import { FileUpload } from '../../../src/components/FileUpload/FileUpload.js';
2
+ import { withProviders } from '../../../src/test-utils.js';
3
+
4
+ it('Verify uploading image and document fixtures to FileUpload component', async () => {
5
+ await Spectra.mount(withProviders(<FileUpload />));
6
+
7
+ // 1. Initial state
8
+ await FileUploadComponent.root.shouldBeVisible();
9
+ await FileUploadComponent.filename.shouldHaveText('No file selected');
10
+
11
+ // 2. Upload image fixture
12
+ await FileUploadComponent.root.upload(Fixture.sampleImage);
13
+ await FileUploadComponent.filename.shouldContainText('sampleImage');
14
+
15
+ // 3. Upload PDF document fixture
16
+ await FileUploadComponent.root.upload(Fixture.sampleDocument);
17
+ await FileUploadComponent.filename.shouldContainText('sampleDocument');
18
+ });
@@ -0,0 +1,20 @@
1
+ ---
2
+ id: TC-0001
3
+ title: Verify intercepted user list renders mocked users
4
+ priority: Critical
5
+ caseType: Positive
6
+ status: automated
7
+ coverage:
8
+ web: automated
9
+ ---
10
+
11
+ # TC-0001: Intercepted User List
12
+
13
+ Verify that `Spectra.intercept()` mocks `fetch('/api/users')` in component tests, so the mounted
14
+ `<UserList />` renders the mocked users without any real network request.
15
+
16
+ ## Test Steps
17
+
18
+ 1. Register `Spectra.intercept('/api/users', 'GET', [...mocked users...])`.
19
+ 2. Mount `<UserList />`.
20
+ 3. Verify the user list is visible with the mocked user names.
@@ -0,0 +1,15 @@
1
+ import { UserList } from '../../../src/components/UserList/UserList.js';
2
+ import { withProviders } from '../../../src/test-utils.js';
3
+
4
+ it('Verify intercepted user list renders mocked users', async () => {
5
+ await Spectra.intercept('/api/users', 'GET', [
6
+ { id: 1, name: 'Alice' },
7
+ { id: 2, name: 'Bob' },
8
+ ]);
9
+
10
+ await Spectra.mount(withProviders(<UserList />));
11
+
12
+ await Spectra.get('~user-list').shouldBeVisible();
13
+ await Spectra.get('~user-1').shouldHaveText('Alice');
14
+ await Spectra.get('~user-2').shouldHaveText('Bob');
15
+ });
@@ -0,0 +1,12 @@
1
+ ---
2
+ id: userlist-component-suite
3
+ name: UserList Component Suite
4
+ executionOrder: 5
5
+ tags:
6
+ - component
7
+ - userlist
8
+ - intercept
9
+ ---
10
+
11
+ # UserList Component Testing Suite
12
+ Verification of async data loading with `Spectra.intercept()` network mocking in component tests.
@@ -0,0 +1,44 @@
1
+ import React, { useState } from 'react';
2
+
3
+ export interface FileUploadProps {
4
+ accept?: string;
5
+ disabled?: boolean;
6
+ onFileSelect?: (file: File) => void;
7
+ ariaLabel?: string;
8
+ }
9
+
10
+ export const FileUpload: React.FC<FileUploadProps> = ({
11
+ accept,
12
+ disabled = false,
13
+ onFileSelect,
14
+ ariaLabel = 'file-upload',
15
+ }) => {
16
+ const [selectedFileName, setSelectedFileName] = useState<string>('');
17
+
18
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
19
+ const file = e.target.files?.[0];
20
+ if (file) {
21
+ setSelectedFileName(file.name);
22
+ onFileSelect?.(file);
23
+ }
24
+ };
25
+
26
+ return (
27
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
28
+ <input
29
+ type="file"
30
+ aria-label={ariaLabel}
31
+ accept={accept}
32
+ disabled={disabled}
33
+ onChange={handleChange}
34
+ style={{
35
+ fontSize: '14px',
36
+ cursor: disabled ? 'not-allowed' : 'pointer',
37
+ }}
38
+ />
39
+ <span aria-label="uploaded-filename" style={{ fontSize: '13px', color: '#374151' }}>
40
+ {selectedFileName || 'No file selected'}
41
+ </span>
42
+ </div>
43
+ );
44
+ };
@@ -0,0 +1,48 @@
1
+ import React, { useEffect, useState } from 'react';
2
+
3
+ export interface UserListUser {
4
+ id: number;
5
+ name: string;
6
+ }
7
+
8
+ /**
9
+ * Demo component for `Spectra.intercept()` in component testing: loads its data via
10
+ * `fetch('/api/users')` on mount. In tests the request never leaves the page — the in-page
11
+ * intercept patch fulfills it from the registered mock rule.
12
+ */
13
+ export const UserList: React.FC = () => {
14
+ const [users, setUsers] = useState<UserListUser[]>([]);
15
+ const [loading, setLoading] = useState(true);
16
+
17
+ useEffect(() => {
18
+ let cancelled = false;
19
+ fetch('/api/users')
20
+ .then((res) => res.json())
21
+ .then((data: UserListUser[]) => {
22
+ if (!cancelled) {
23
+ setUsers(data);
24
+ setLoading(false);
25
+ }
26
+ })
27
+ .catch(() => {
28
+ if (!cancelled) setLoading(false);
29
+ });
30
+ return () => {
31
+ cancelled = true;
32
+ };
33
+ }, []);
34
+
35
+ if (loading) {
36
+ return <p aria-label="user-list-loading">Loading users…</p>;
37
+ }
38
+
39
+ return (
40
+ <ul aria-label="user-list">
41
+ {users.map((user) => (
42
+ <li key={user.id} aria-label={`user-${user.id}`}>
43
+ {user.name}
44
+ </li>
45
+ ))}
46
+ </ul>
47
+ );
48
+ };
@@ -1 +0,0 @@
1
- 2db95c618fc201b3c5e4b2f56e93c5e5fca36ba0d31250c65c98aabed5385361
@@ -1 +0,0 @@
1
- /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */@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-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--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-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-300:oklch(80.8% .114 19.571);--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-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-orange-800:oklch(47% .157 37.304);--color-orange-950:oklch(26.6% .079 36.259);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-950:oklch(27.9% .077 45.635);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-lime-400:oklch(84.1% .238 128.85);--color-lime-500:oklch(76.8% .233 130.85);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-green-900:oklch(39.3% .095 152.535);--color-green-950:oklch(26.6% .065 152.934);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-800:oklch(43.2% .095 166.913);--color-emerald-900:oklch(37.8% .077 168.94);--color-emerald-950:oklch(26.2% .051 172.552);--color-teal-200:oklch(91% .096 180.426);--color-teal-300:oklch(85.5% .138 181.071);--color-teal-400:oklch(77.7% .152 181.912);--color-teal-500:oklch(70.4% .14 182.503);--color-teal-600:oklch(60% .118 184.704);--color-teal-700:oklch(51.1% .096 186.391);--color-teal-800:oklch(43.7% .078 188.216);--color-teal-900:oklch(38.6% .063 188.416);--color-teal-950:oklch(27.7% .046 192.524);--color-cyan-400:oklch(78.9% .154 211.53);--color-cyan-500:oklch(71.5% .143 215.221);--color-cyan-600:oklch(60.9% .126 221.723);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--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-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-blue-950:oklch(28.2% .091 267.935);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-500:oklch(58.5% .233 277.117);--color-violet-300:oklch(81.1% .111 293.571);--color-violet-400:oklch(70.2% .183 293.541);--color-violet-500:oklch(60.6% .25 292.717);--color-violet-700:oklch(49.1% .27 292.581);--color-violet-800:oklch(43.2% .232 292.759);--color-violet-950:oklch(28.3% .141 291.089);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-950:oklch(29.1% .149 302.717);--color-fuchsia-400:oklch(74% .238 322.16);--color-fuchsia-500:oklch(66.7% .295 322.15);--color-pink-400:oklch(71.8% .202 349.761);--color-pink-500:oklch(65.6% .241 354.308);--color-rose-400:oklch(71.2% .194 13.428);--color-rose-500:oklch(64.5% .246 16.439);--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-slate-950:oklch(12.9% .042 264.695);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-black:#000;--color-white:#fff;--spacing:.25rem;--breakpoint-sm:40rem;--breakpoint-md:48rem;--breakpoint-lg:64rem;--breakpoint-xl:80rem;--breakpoint-2xl:96rem;--container-md:28rem;--container-2xl:42rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-sm:8px;--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%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance: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{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.top-1{top:var(--spacing)}.right-1{right:var(--spacing)}.right-3{right:calc(var(--spacing) * 3)}.left-1{left:var(--spacing)}.left-3{left:calc(var(--spacing) * 3)}.z-40{z-index:40}.z-50{z-index:50}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.mx-auto{margin-inline:auto}.my-2{margin-block:calc(var(--spacing) * 2)}.mt-0{margin-top:0}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-7{margin-top:calc(var(--spacing) * 7)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mr-1{margin-right:var(--spacing)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-0{margin-bottom:0}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-7{margin-bottom:calc(var(--spacing) * 7)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.mb-20{margin-bottom:calc(var(--spacing) * 20)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.h-2{height:calc(var(--spacing) * 2)}.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-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-24{height:calc(var(--spacing) * 24)}.h-64{height:calc(var(--spacing) * 64)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-32{max-height:calc(var(--spacing) * 32)}.max-h-36{max-height:calc(var(--spacing) * 36)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-56{max-height:calc(var(--spacing) * 56)}.max-h-96{max-height:calc(var(--spacing) * 96)}.min-h-8{min-height:calc(var(--spacing) * 8)}.min-h-screen{min-height:100vh}.w-2{width:calc(var(--spacing) * 2)}.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-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-56{width:calc(var(--spacing) * 56)}.w-64{width:calc(var(--spacing) * 64)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-md{max-width:var(--container-md)}.min-w-0{min-width:0}.flex-1{flex:1}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-translate-y-1{--tw-translate-y:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-none{resize:none}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}: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-2\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2.5) * 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-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * 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-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(var(--spacing) * var(--tw-space-x-reverse));margin-inline-end:calc(var(--spacing) * calc(1 - var(--tw-space-x-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-800>:not(:last-child)){border-color:var(--color-slate-800)}:where(.divide-slate-800\/40>:not(:last-child)){border-color:#1d293d66}@supports (color:color-mix(in lab,red,red)){:where(.divide-slate-800\/40>:not(:last-child)){border-color:color-mix(in oklab,var(--color-slate-800) 40%,transparent)}}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.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-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-amber-500{border-color:var(--color-amber-500)}.border-amber-500\/20{border-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/20{border-color:color-mix(in oklab,var(--color-amber-500) 20%,transparent)}}.border-amber-800\/60{border-color:#953d0099}@supports (color:color-mix(in lab,red,red)){.border-amber-800\/60{border-color:color-mix(in oklab,var(--color-amber-800) 60%,transparent)}}.border-blue-500{border-color:var(--color-blue-500)}.border-blue-600{border-color:var(--color-blue-600)}.border-blue-800\/60{border-color:#193cb899}@supports (color:color-mix(in lab,red,red)){.border-blue-800\/60{border-color:color-mix(in oklab,var(--color-blue-800) 60%,transparent)}}.border-cyan-500{border-color:var(--color-cyan-500)}.border-emerald-500{border-color:var(--color-emerald-500)}.border-emerald-800\/50{border-color:#005f4680}@supports (color:color-mix(in lab,red,red)){.border-emerald-800\/50{border-color:color-mix(in oklab,var(--color-emerald-800) 50%,transparent)}}.border-emerald-800\/60{border-color:#005f4699}@supports (color:color-mix(in lab,red,red)){.border-emerald-800\/60{border-color:color-mix(in oklab,var(--color-emerald-800) 60%,transparent)}}.border-fuchsia-500{border-color:var(--color-fuchsia-500)}.border-gray-500{border-color:var(--color-gray-500)}.border-green-500{border-color:var(--color-green-500)}.border-green-800{border-color:var(--color-green-800)}.border-indigo-500{border-color:var(--color-indigo-500)}.border-lime-500{border-color:var(--color-lime-500)}.border-orange-500{border-color:var(--color-orange-500)}.border-orange-800\/50{border-color:#9f2d0080}@supports (color:color-mix(in lab,red,red)){.border-orange-800\/50{border-color:color-mix(in oklab,var(--color-orange-800) 50%,transparent)}}.border-pink-500{border-color:var(--color-pink-500)}.border-purple-500{border-color:var(--color-purple-500)}.border-red-500{border-color:var(--color-red-500)}.border-red-600{border-color:var(--color-red-600)}.border-red-700{border-color:var(--color-red-700)}.border-red-800{border-color:var(--color-red-800)}.border-red-800\/50{border-color:#9f071280}@supports (color:color-mix(in lab,red,red)){.border-red-800\/50{border-color:color-mix(in oklab,var(--color-red-800) 50%,transparent)}}.border-rose-500{border-color:var(--color-rose-500)}.border-sky-500{border-color:var(--color-sky-500)}.border-slate-500{border-color:var(--color-slate-500)}.border-slate-600{border-color:var(--color-slate-600)}.border-slate-700{border-color:var(--color-slate-700)}.border-slate-700\/40{border-color:#31415866}@supports (color:color-mix(in lab,red,red)){.border-slate-700\/40{border-color:color-mix(in oklab,var(--color-slate-700) 40%,transparent)}}.border-slate-700\/50{border-color:#31415880}@supports (color:color-mix(in lab,red,red)){.border-slate-700\/50{border-color:color-mix(in oklab,var(--color-slate-700) 50%,transparent)}}.border-slate-700\/60{border-color:#31415899}@supports (color:color-mix(in lab,red,red)){.border-slate-700\/60{border-color:color-mix(in oklab,var(--color-slate-700) 60%,transparent)}}.border-slate-700\/70{border-color:#314158b3}@supports (color:color-mix(in lab,red,red)){.border-slate-700\/70{border-color:color-mix(in oklab,var(--color-slate-700) 70%,transparent)}}.border-slate-800{border-color:var(--color-slate-800)}.border-slate-800\/50{border-color:#1d293d80}@supports (color:color-mix(in lab,red,red)){.border-slate-800\/50{border-color:color-mix(in oklab,var(--color-slate-800) 50%,transparent)}}.border-slate-800\/60{border-color:#1d293d99}@supports (color:color-mix(in lab,red,red)){.border-slate-800\/60{border-color:color-mix(in oklab,var(--color-slate-800) 60%,transparent)}}.border-teal-500{border-color:var(--color-teal-500)}.border-teal-800\/40{border-color:#005f5a66}@supports (color:color-mix(in lab,red,red)){.border-teal-800\/40{border-color:color-mix(in oklab,var(--color-teal-800) 40%,transparent)}}.border-teal-800\/50{border-color:#005f5a80}@supports (color:color-mix(in lab,red,red)){.border-teal-800\/50{border-color:color-mix(in oklab,var(--color-teal-800) 50%,transparent)}}.border-teal-800\/60{border-color:#005f5a99}@supports (color:color-mix(in lab,red,red)){.border-teal-800\/60{border-color:color-mix(in oklab,var(--color-teal-800) 60%,transparent)}}.border-teal-900\/40{border-color:#0b4f4a66}@supports (color:color-mix(in lab,red,red)){.border-teal-900\/40{border-color:color-mix(in oklab,var(--color-teal-900) 40%,transparent)}}.border-transparent{border-color:#0000}.border-violet-500{border-color:var(--color-violet-500)}.border-violet-700\/50{border-color:#7008e780}@supports (color:color-mix(in lab,red,red)){.border-violet-700\/50{border-color:color-mix(in oklab,var(--color-violet-700) 50%,transparent)}}.border-violet-700\/60{border-color:#7008e799}@supports (color:color-mix(in lab,red,red)){.border-violet-700\/60{border-color:color-mix(in oklab,var(--color-violet-700) 60%,transparent)}}.border-violet-800\/60{border-color:#5d0ec099}@supports (color:color-mix(in lab,red,red)){.border-violet-800\/60{border-color:color-mix(in oklab,var(--color-violet-800) 60%,transparent)}}.border-yellow-500{border-color:var(--color-yellow-500)}.border-t-amber-400{border-top-color:var(--color-amber-400)}.bg-\[\#030a14\]{background-color:#030a14}.bg-\[\#020817\]{background-color:#020817}.bg-\[\#020817\]\/95{background-color:#020817f2}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/10{background-color:color-mix(in oklab,var(--color-amber-500) 10%,transparent)}}.bg-amber-950\/40{background-color:#46190166}@supports (color:color-mix(in lab,red,red)){.bg-amber-950\/40{background-color:color-mix(in oklab,var(--color-amber-950) 40%,transparent)}}.bg-amber-950\/60{background-color:#46190199}@supports (color:color-mix(in lab,red,red)){.bg-amber-950\/60{background-color:color-mix(in oklab,var(--color-amber-950) 60%,transparent)}}.bg-black{background-color:var(--color-black)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-500\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/10{background-color:color-mix(in oklab,var(--color-blue-500) 10%,transparent)}}.bg-blue-600{background-color:var(--color-blue-600)}.bg-blue-950{background-color:var(--color-blue-950)}.bg-blue-950\/40{background-color:#16245666}@supports (color:color-mix(in lab,red,red)){.bg-blue-950\/40{background-color:color-mix(in oklab,var(--color-blue-950) 40%,transparent)}}.bg-cyan-500{background-color:var(--color-cyan-500)}.bg-cyan-600{background-color:var(--color-cyan-600)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-emerald-900\/80{background-color:#004e3bcc}@supports (color:color-mix(in lab,red,red)){.bg-emerald-900\/80{background-color:color-mix(in oklab,var(--color-emerald-900) 80%,transparent)}}.bg-emerald-950{background-color:var(--color-emerald-950)}.bg-emerald-950\/40{background-color:#002c2266}@supports (color:color-mix(in lab,red,red)){.bg-emerald-950\/40{background-color:color-mix(in oklab,var(--color-emerald-950) 40%,transparent)}}.bg-emerald-950\/60{background-color:#002c2299}@supports (color:color-mix(in lab,red,red)){.bg-emerald-950\/60{background-color:color-mix(in oklab,var(--color-emerald-950) 60%,transparent)}}.bg-fuchsia-500{background-color:var(--color-fuchsia-500)}.bg-gray-500{background-color:var(--color-gray-500)}.bg-green-500{background-color:var(--color-green-500)}.bg-green-600{background-color:var(--color-green-600)}.bg-green-950{background-color:var(--color-green-950)}.bg-indigo-500{background-color:var(--color-indigo-500)}.bg-lime-500{background-color:var(--color-lime-500)}.bg-orange-500{background-color:var(--color-orange-500)}.bg-orange-600{background-color:var(--color-orange-600)}.bg-orange-950{background-color:var(--color-orange-950)}.bg-orange-950\/40{background-color:#44130666}@supports (color:color-mix(in lab,red,red)){.bg-orange-950\/40{background-color:color-mix(in oklab,var(--color-orange-950) 40%,transparent)}}.bg-pink-500{background-color:var(--color-pink-500)}.bg-purple-500{background-color:var(--color-purple-500)}.bg-purple-600{background-color:var(--color-purple-600)}.bg-purple-950{background-color:var(--color-purple-950)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-red-950{background-color:var(--color-red-950)}.bg-red-950\/40{background-color:#46080966}@supports (color:color-mix(in lab,red,red)){.bg-red-950\/40{background-color:color-mix(in oklab,var(--color-red-950) 40%,transparent)}}.bg-rose-500{background-color:var(--color-rose-500)}.bg-sky-500{background-color:var(--color-sky-500)}.bg-slate-500{background-color:var(--color-slate-500)}.bg-slate-600{background-color:var(--color-slate-600)}.bg-slate-700{background-color:var(--color-slate-700)}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-800\/40{background-color:#1d293d66}@supports (color:color-mix(in lab,red,red)){.bg-slate-800\/40{background-color:color-mix(in oklab,var(--color-slate-800) 40%,transparent)}}.bg-slate-800\/50{background-color:#1d293d80}@supports (color:color-mix(in lab,red,red)){.bg-slate-800\/50{background-color:color-mix(in oklab,var(--color-slate-800) 50%,transparent)}}.bg-slate-800\/60{background-color:#1d293d99}@supports (color:color-mix(in lab,red,red)){.bg-slate-800\/60{background-color:color-mix(in oklab,var(--color-slate-800) 60%,transparent)}}.bg-slate-800\/80{background-color:#1d293dcc}@supports (color:color-mix(in lab,red,red)){.bg-slate-800\/80{background-color:color-mix(in oklab,var(--color-slate-800) 80%,transparent)}}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/20{background-color:#0f172b33}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/20{background-color:color-mix(in oklab,var(--color-slate-900) 20%,transparent)}}.bg-slate-900\/50{background-color:#0f172b80}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/50{background-color:color-mix(in oklab,var(--color-slate-900) 50%,transparent)}}.bg-slate-900\/60{background-color:#0f172b99}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/60{background-color:color-mix(in oklab,var(--color-slate-900) 60%,transparent)}}.bg-slate-900\/80{background-color:#0f172bcc}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/80{background-color:color-mix(in oklab,var(--color-slate-900) 80%,transparent)}}.bg-slate-950{background-color:var(--color-slate-950)}.bg-slate-950\/20{background-color:#02061833}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/20{background-color:color-mix(in oklab,var(--color-slate-950) 20%,transparent)}}.bg-slate-950\/60{background-color:#02061899}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/60{background-color:color-mix(in oklab,var(--color-slate-950) 60%,transparent)}}.bg-teal-500{background-color:var(--color-teal-500)}.bg-teal-500\/10{background-color:#00baa71a}@supports (color:color-mix(in lab,red,red)){.bg-teal-500\/10{background-color:color-mix(in oklab,var(--color-teal-500) 10%,transparent)}}.bg-teal-600{background-color:var(--color-teal-600)}.bg-teal-950{background-color:var(--color-teal-950)}.bg-teal-950\/30{background-color:#022f2e4d}@supports (color:color-mix(in lab,red,red)){.bg-teal-950\/30{background-color:color-mix(in oklab,var(--color-teal-950) 30%,transparent)}}.bg-teal-950\/40{background-color:#022f2e66}@supports (color:color-mix(in lab,red,red)){.bg-teal-950\/40{background-color:color-mix(in oklab,var(--color-teal-950) 40%,transparent)}}.bg-teal-950\/50{background-color:#022f2e80}@supports (color:color-mix(in lab,red,red)){.bg-teal-950\/50{background-color:color-mix(in oklab,var(--color-teal-950) 50%,transparent)}}.bg-teal-950\/60{background-color:#022f2e99}@supports (color:color-mix(in lab,red,red)){.bg-teal-950\/60{background-color:color-mix(in oklab,var(--color-teal-950) 60%,transparent)}}.bg-transparent{background-color:#0000}.bg-violet-400{background-color:var(--color-violet-400)}.bg-violet-500{background-color:var(--color-violet-500)}.bg-violet-500\/10{background-color:#8d54ff1a}@supports (color:color-mix(in lab,red,red)){.bg-violet-500\/10{background-color:color-mix(in oklab,var(--color-violet-500) 10%,transparent)}}.bg-violet-950\/40{background-color:#2f0d6866}@supports (color:color-mix(in lab,red,red)){.bg-violet-950\/40{background-color:color-mix(in oklab,var(--color-violet-950) 40%,transparent)}}.bg-violet-950\/50{background-color:#2f0d6880}@supports (color:color-mix(in lab,red,red)){.bg-violet-950\/50{background-color:color-mix(in oklab,var(--color-violet-950) 50%,transparent)}}.bg-yellow-500{background-color:var(--color-yellow-500)}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-blue-500{--tw-gradient-from:var(--color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-orange-600{--tw-gradient-from:var(--color-orange-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-500{--tw-gradient-from:var(--color-purple-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-teal-500{--tw-gradient-from:var(--color-teal-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-blue-600{--tw-gradient-to:var(--color-blue-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-orange-500{--tw-gradient-to:var(--color-orange-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-pink-500{--tw-gradient-to:var(--color-pink-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-teal-600{--tw-gradient-to:var(--color-teal-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.p-0{padding:0}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0{padding-block:0}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-12{padding-block:calc(var(--spacing) * 12)}.pt-1{padding-top:var(--spacing)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pr-1{padding-right:var(--spacing)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pr-12{padding-right:calc(var(--spacing) * 12)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-12{padding-bottom:calc(var(--spacing) * 12)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-7{padding-left:calc(var(--spacing) * 7)}.pl-10{padding-left:calc(var(--spacing) * 10)}.pl-11{padding-left:calc(var(--spacing) * 11)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.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-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--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-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.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-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.text-amber-300{color:var(--color-amber-300)}.text-amber-300\/90{color:#ffd236e6}@supports (color:color-mix(in lab,red,red)){.text-amber-300\/90{color:color-mix(in oklab,var(--color-amber-300) 90%,transparent)}}.text-amber-400{color:var(--color-amber-400)}.text-blue-300{color:var(--color-blue-300)}.text-blue-400{color:var(--color-blue-400)}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-cyan-400{color:var(--color-cyan-400)}.text-emerald-200{color:var(--color-emerald-200)}.text-emerald-300{color:var(--color-emerald-300)}.text-emerald-400{color:var(--color-emerald-400)}.text-fuchsia-400{color:var(--color-fuchsia-400)}.text-gray-400{color:var(--color-gray-400)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-indigo-400{color:var(--color-indigo-400)}.text-lime-400{color:var(--color-lime-400)}.text-orange-300{color:var(--color-orange-300)}.text-orange-400{color:var(--color-orange-400)}.text-orange-500{color:var(--color-orange-500)}.text-pink-400{color:var(--color-pink-400)}.text-purple-300{color:var(--color-purple-300)}.text-purple-400{color:var(--color-purple-400)}.text-purple-500{color:var(--color-purple-500)}.text-red-300{color:var(--color-red-300)}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-rose-400{color:var(--color-rose-400)}.text-sky-400{color:var(--color-sky-400)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.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-950{color:var(--color-slate-950)}.text-teal-300{color:var(--color-teal-300)}.text-teal-400{color:var(--color-teal-400)}.text-teal-500{color:var(--color-teal-500)}.text-violet-300{color:var(--color-violet-300)}.text-violet-400{color:var(--color-violet-400)}.text-white{color:var(--color-white)}.text-yellow-400{color:var(--color-yellow-400)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.italic{font-style:italic}.no-underline{text-decoration-line:none}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.accent-teal-400{accent-color:var(--color-teal-400)}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-75{opacity:.75}.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)}.ring-2{--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)}.ring-blue-500{--tw-ring-color:var(--color-blue-500)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-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-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.outline-none{--tw-outline-style:none;outline-style:none}.placeholder\:text-slate-600::placeholder{color:var(--color-slate-600)}.first\:mt-0:first-child{margin-top:0}@media (hover:hover){.hover\:border-slate-600:hover{border-color:var(--color-slate-600)}.hover\:border-slate-600\/60:hover{border-color:#45556c99}@supports (color:color-mix(in lab,red,red)){.hover\:border-slate-600\/60:hover{border-color:color-mix(in oklab,var(--color-slate-600) 60%,transparent)}}.hover\:border-teal-800\/50:hover{border-color:#005f5a80}@supports (color:color-mix(in lab,red,red)){.hover\:border-teal-800\/50:hover{border-color:color-mix(in oklab,var(--color-teal-800) 50%,transparent)}}.hover\:border-teal-800\/60:hover{border-color:#005f5a99}@supports (color:color-mix(in lab,red,red)){.hover\:border-teal-800\/60:hover{border-color:color-mix(in oklab,var(--color-teal-800) 60%,transparent)}}.hover\:bg-amber-400:hover{background-color:var(--color-amber-400)}.hover\:bg-slate-800\/20:hover{background-color:#1d293d33}@supports (color:color-mix(in lab,red,red)){.hover\:bg-slate-800\/20:hover{background-color:color-mix(in oklab,var(--color-slate-800) 20%,transparent)}}.hover\:bg-slate-800\/30:hover{background-color:#1d293d4d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-slate-800\/30:hover{background-color:color-mix(in oklab,var(--color-slate-800) 30%,transparent)}}.hover\:bg-slate-800\/40:hover{background-color:#1d293d66}@supports (color:color-mix(in lab,red,red)){.hover\:bg-slate-800\/40:hover{background-color:color-mix(in oklab,var(--color-slate-800) 40%,transparent)}}.hover\:bg-teal-500:hover{background-color:var(--color-teal-500)}.hover\:bg-teal-950\/40:hover{background-color:#022f2e66}@supports (color:color-mix(in lab,red,red)){.hover\:bg-teal-950\/40:hover{background-color:color-mix(in oklab,var(--color-teal-950) 40%,transparent)}}.hover\:text-slate-100:hover{color:var(--color-slate-100)}.hover\:text-slate-200:hover{color:var(--color-slate-200)}.hover\:text-slate-300:hover{color:var(--color-slate-300)}.hover\:text-teal-300:hover{color:var(--color-teal-300)}.hover\:text-teal-400:hover{color:var(--color-teal-400)}}.focus\:border-amber-500:focus{border-color:var(--color-amber-500)}.focus\:border-teal-500:focus{border-color:var(--color-teal-500)}.focus\:border-teal-700:focus{border-color:var(--color-teal-700)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-teal-500:focus{--tw-ring-color:var(--color-teal-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-slate-700:disabled{background-color:var(--color-slate-700)}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:40rem){.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:80rem){.xl\:col-span-2{grid-column:span 2/span 2}.xl\:col-span-3{grid-column:span 3/span 3}.xl\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.xl\:border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}}html,body,#app{height:100%}body{background-color:#020817;font-family:Inter,ui-sans-serif,system-ui,sans-serif}code,pre,.font-mono{font-family:JetBrains Mono,ui-monospace,SFMono-Regular,monospace}::-webkit-scrollbar{width:4px;height:4px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:#1e293b;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#334155}html{scroll-behavior:smooth}section[id]{scroll-margin-top:56px}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-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-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@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-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}