maestro-automation 1.0.0__tar.gz

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 (110) hide show
  1. maestro_automation-1.0.0/LICENSE +21 -0
  2. maestro_automation-1.0.0/PKG-INFO +107 -0
  3. maestro_automation-1.0.0/README.md +72 -0
  4. maestro_automation-1.0.0/backend/__init__.py +3 -0
  5. maestro_automation-1.0.0/backend/_bundled/frontend/dist/assets/index-Bj_RDssb.css +1 -0
  6. maestro_automation-1.0.0/backend/_bundled/frontend/dist/assets/index-CRmxIGcZ.js +472 -0
  7. maestro_automation-1.0.0/backend/_bundled/frontend/dist/index.html +14 -0
  8. maestro_automation-1.0.0/backend/_bundled/frontend/dist/maestro-logo.svg +36 -0
  9. maestro_automation-1.0.0/backend/adapters/__init__.py +6 -0
  10. maestro_automation-1.0.0/backend/adapters/adapter_registry.py +128 -0
  11. maestro_automation-1.0.0/backend/adapters/adb_adapter/__init__.py +3 -0
  12. maestro_automation-1.0.0/backend/adapters/adb_adapter/adapter.py +188 -0
  13. maestro_automation-1.0.0/backend/adapters/adb_adapter/capabilities.py +34 -0
  14. maestro_automation-1.0.0/backend/adapters/adb_adapter/manifest.json +22 -0
  15. maestro_automation-1.0.0/backend/adapters/base_adapter.py +126 -0
  16. maestro_automation-1.0.0/backend/adapters/custom_script_loader.py +50 -0
  17. maestro_automation-1.0.0/backend/adapters/dlt_adapter/__init__.py +3 -0
  18. maestro_automation-1.0.0/backend/adapters/dlt_adapter/adapter.py +158 -0
  19. maestro_automation-1.0.0/backend/adapters/dlt_adapter/manifest.json +9 -0
  20. maestro_automation-1.0.0/backend/adapters/etfw_adapter/__init__.py +3 -0
  21. maestro_automation-1.0.0/backend/adapters/etfw_adapter/adapter.py +62 -0
  22. maestro_automation-1.0.0/backend/adapters/etfw_adapter/manifest.json +9 -0
  23. maestro_automation-1.0.0/backend/adapters/power_script_adapter/__init__.py +3 -0
  24. maestro_automation-1.0.0/backend/adapters/power_script_adapter/adapter.py +76 -0
  25. maestro_automation-1.0.0/backend/adapters/power_script_adapter/capabilities.py +14 -0
  26. maestro_automation-1.0.0/backend/adapters/power_script_adapter/manifest.json +9 -0
  27. maestro_automation-1.0.0/backend/adapters/serial_console_adapter/__init__.py +3 -0
  28. maestro_automation-1.0.0/backend/adapters/serial_console_adapter/adapter.py +145 -0
  29. maestro_automation-1.0.0/backend/adapters/serial_console_adapter/manifest.json +9 -0
  30. maestro_automation-1.0.0/backend/adapters/ssh_adapter/__init__.py +3 -0
  31. maestro_automation-1.0.0/backend/adapters/ssh_adapter/adapter.py +179 -0
  32. maestro_automation-1.0.0/backend/adapters/ssh_adapter/capabilities.py +18 -0
  33. maestro_automation-1.0.0/backend/adapters/ssh_adapter/manifest.json +16 -0
  34. maestro_automation-1.0.0/backend/adapters/system_adapter/__init__.py +3 -0
  35. maestro_automation-1.0.0/backend/adapters/system_adapter/adapter.py +257 -0
  36. maestro_automation-1.0.0/backend/adapters/system_adapter/manifest.json +9 -0
  37. maestro_automation-1.0.0/backend/adapters/windows_camera_adapter/__init__.py +3 -0
  38. maestro_automation-1.0.0/backend/adapters/windows_camera_adapter/adapter.py +168 -0
  39. maestro_automation-1.0.0/backend/adapters/windows_camera_adapter/manifest.json +9 -0
  40. maestro_automation-1.0.0/backend/api/__init__.py +1 -0
  41. maestro_automation-1.0.0/backend/api/admin.py +78 -0
  42. maestro_automation-1.0.0/backend/api/configuration.py +140 -0
  43. maestro_automation-1.0.0/backend/api/connections.py +97 -0
  44. maestro_automation-1.0.0/backend/api/datasets.py +98 -0
  45. maestro_automation-1.0.0/backend/api/execution.py +192 -0
  46. maestro_automation-1.0.0/backend/api/plugins.py +55 -0
  47. maestro_automation-1.0.0/backend/api/projects.py +153 -0
  48. maestro_automation-1.0.0/backend/api/reports.py +149 -0
  49. maestro_automation-1.0.0/backend/api/router.py +63 -0
  50. maestro_automation-1.0.0/backend/api/scheduling.py +179 -0
  51. maestro_automation-1.0.0/backend/api/test_cases.py +351 -0
  52. maestro_automation-1.0.0/backend/api/websocket.py +68 -0
  53. maestro_automation-1.0.0/backend/cli.py +71 -0
  54. maestro_automation-1.0.0/backend/config.py +112 -0
  55. maestro_automation-1.0.0/backend/database.py +104 -0
  56. maestro_automation-1.0.0/backend/db/__init__.py +5 -0
  57. maestro_automation-1.0.0/backend/main.py +107 -0
  58. maestro_automation-1.0.0/backend/models/__init__.py +25 -0
  59. maestro_automation-1.0.0/backend/models/artifact.py +64 -0
  60. maestro_automation-1.0.0/backend/models/device_config.py +64 -0
  61. maestro_automation-1.0.0/backend/models/execution.py +87 -0
  62. maestro_automation-1.0.0/backend/models/project.py +111 -0
  63. maestro_automation-1.0.0/backend/models/report.py +136 -0
  64. maestro_automation-1.0.0/backend/models/user.py +65 -0
  65. maestro_automation-1.0.0/backend/security/__init__.py +14 -0
  66. maestro_automation-1.0.0/backend/security/audit.py +40 -0
  67. maestro_automation-1.0.0/backend/security/auth.py +53 -0
  68. maestro_automation-1.0.0/backend/security/credential_manager.py +68 -0
  69. maestro_automation-1.0.0/backend/security/rbac.py +70 -0
  70. maestro_automation-1.0.0/backend/security/vault.py +107 -0
  71. maestro_automation-1.0.0/backend/security_middleware.py +35 -0
  72. maestro_automation-1.0.0/backend/services/__init__.py +1 -0
  73. maestro_automation-1.0.0/backend/services/cleanup.py +67 -0
  74. maestro_automation-1.0.0/backend/services/connection_tester.py +80 -0
  75. maestro_automation-1.0.0/backend/services/execution_sandbox.py +96 -0
  76. maestro_automation-1.0.0/backend/services/live_log.py +43 -0
  77. maestro_automation-1.0.0/backend/services/observability.py +116 -0
  78. maestro_automation-1.0.0/backend/services/plugin_manager.py +76 -0
  79. maestro_automation-1.0.0/backend/services/project_service.py +87 -0
  80. maestro_automation-1.0.0/backend/services/report_generator.py +556 -0
  81. maestro_automation-1.0.0/backend/services/resource_lock_mgr.py +50 -0
  82. maestro_automation-1.0.0/backend/services/scheduler_service.py +171 -0
  83. maestro_automation-1.0.0/backend/services/seed_data.py +178 -0
  84. maestro_automation-1.0.0/backend/services/test_data_manager.py +75 -0
  85. maestro_automation-1.0.0/backend/services/test_executor.py +706 -0
  86. maestro_automation-1.0.0/backend/services/versioning_service.py +122 -0
  87. maestro_automation-1.0.0/backend/services/ws_manager.py +59 -0
  88. maestro_automation-1.0.0/backend/templates/adb_templates.json +46 -0
  89. maestro_automation-1.0.0/backend/templates/camera_templates.json +7 -0
  90. maestro_automation-1.0.0/backend/templates/collectors_templates.json +9 -0
  91. maestro_automation-1.0.0/backend/templates/dlt_templates.json +5 -0
  92. maestro_automation-1.0.0/backend/templates/etfw_templates.json +6 -0
  93. maestro_automation-1.0.0/backend/templates/ignition_templates.json +7 -0
  94. maestro_automation-1.0.0/backend/templates/power_templates.json +7 -0
  95. maestro_automation-1.0.0/backend/templates/script_templates.json +13 -0
  96. maestro_automation-1.0.0/backend/templates/serial_templates.json +8 -0
  97. maestro_automation-1.0.0/backend/templates/ssh_templates.json +48 -0
  98. maestro_automation-1.0.0/backend/templates/system_templates.json +8 -0
  99. maestro_automation-1.0.0/backend/utils/__init__.py +1 -0
  100. maestro_automation-1.0.0/backend/utils/helpers.py +40 -0
  101. maestro_automation-1.0.0/backend/utils/logger.py +109 -0
  102. maestro_automation-1.0.0/backend/utils/validators.py +33 -0
  103. maestro_automation-1.0.0/maestro_automation.egg-info/PKG-INFO +107 -0
  104. maestro_automation-1.0.0/maestro_automation.egg-info/SOURCES.txt +108 -0
  105. maestro_automation-1.0.0/maestro_automation.egg-info/dependency_links.txt +1 -0
  106. maestro_automation-1.0.0/maestro_automation.egg-info/entry_points.txt +2 -0
  107. maestro_automation-1.0.0/maestro_automation.egg-info/requires.txt +18 -0
  108. maestro_automation-1.0.0/maestro_automation.egg-info/top_level.txt +1 -0
  109. maestro_automation-1.0.0/pyproject.toml +60 -0
  110. maestro_automation-1.0.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maestro Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,107 @@
1
+ Metadata-Version: 2.4
2
+ Name: maestro-automation
3
+ Version: 1.0.0
4
+ Summary: Maestro โ€” Automotive Test Automation Framework (web dashboard + adapters)
5
+ Author: Maestro Team
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/your-org/maestro
8
+ Keywords: test-automation,automotive,ssh,adb,dlt,ecu
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: Microsoft :: Windows
12
+ Classifier: Framework :: FastAPI
13
+ Classifier: Topic :: Software Development :: Testing
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: fastapi>=0.110
18
+ Requires-Dist: uvicorn[standard]>=0.29
19
+ Requires-Dist: sqlalchemy>=2.0
20
+ Requires-Dist: pydantic>=2.5
21
+ Requires-Dist: apscheduler<4,>=3.10
22
+ Requires-Dist: paramiko>=2.11
23
+ Requires-Dist: cryptography>=42.0
24
+ Requires-Dist: websockets>=11.0
25
+ Requires-Dist: pyserial>=3.5
26
+ Requires-Dist: structlog>=24.1
27
+ Requires-Dist: prometheus-client>=0.20
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8.0; extra == "dev"
30
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
31
+ Requires-Dist: httpx>=0.27; extra == "dev"
32
+ Requires-Dist: build; extra == "dev"
33
+ Requires-Dist: twine; extra == "dev"
34
+ Dynamic: license-file
35
+
36
+ # ๐Ÿ Maestro โ€” Automotive Test Automation Framework
37
+
38
+ Maestro consolidates SSH, ADB, bench power control, ETFW, DLT logging, serial
39
+ consoles and Windows camera capture into a single browser-based dashboard.
40
+ Non-technical users design test cases with drag-and-drop; engineers extend it
41
+ through a hot-reloadable plugin system.
42
+
43
+ ## ๐Ÿš€ Quick start
44
+
45
+ ```bash
46
+ # Requirements: Python 3.10+ (3.11.9 recommended), Node.js 18+
47
+
48
+ cd maestro
49
+ pip install -r requirements.txt # or: pip install poetry && poetry install
50
+ python app.py
51
+ ```
52
+
53
+ `app.py` installs anything missing, builds the React frontend on first run,
54
+ starts the FastAPI backend on **http://localhost:8000** and opens your
55
+ browser. That's it.
56
+
57
+ | URL | What |
58
+ |---|---|
59
+ | `http://localhost:8000` | Maestro dashboard |
60
+ | `http://localhost:8000/api/docs` | Interactive API documentation (Swagger) |
61
+ | `http://localhost:8000/metrics` | Prometheus metrics |
62
+
63
+ ## โœจ Highlights
64
+
65
+ - **4-column drag-and-drop test designer** with pre-built step templates for
66
+ SSH, ADB, power, ignition, ETFW, DLT, camera and serial console
67
+ - **Execution engine**: serial / parallel / step-by-step modes, retry with
68
+ exponential backoff, IF/THEN conditional jumps, loops, parallel groups,
69
+ per-device resource locking, sandboxed user scripts
70
+ - **Live monitoring** over WebSocket: step status, logs, pause/resume/stop
71
+ - **Allure-style HTML reports** with timelines, artifacts and report diffing
72
+ - **Scheduling** via cron expressions (APScheduler)
73
+ - **Enterprise security**: AES-256-GCM credential vault, 5-role RBAC,
74
+ full audit logging
75
+ - **Observability**: structured JSON logs, Prometheus metrics, adapter health
76
+ - **Plugin system**: manifest-based adapters, enable/disable, hot reload,
77
+ custom plugins in `data/plugins/`
78
+
79
+ ## ๐Ÿงช Development
80
+
81
+ ```bash
82
+ # Backend tests
83
+ python -m pytest tests/
84
+
85
+ # Frontend dev server (proxies API to :8000)
86
+ cd frontend && npm install && npm run dev
87
+
88
+ # Frontend tests & build
89
+ npm run test && npm run build
90
+ ```
91
+
92
+ ## ๐Ÿณ Docker
93
+
94
+ ```bash
95
+ docker compose -f docker/docker-compose.yml up --build
96
+ ```
97
+
98
+ ## ๐Ÿ“š Documentation
99
+
100
+ - [USER_GUIDE.md](docs/USER_GUIDE.md) โ€” using the dashboard
101
+ - [DEVELOPER_GUIDE.md](docs/DEVELOPER_GUIDE.md) โ€” extending Maestro
102
+ - [API_REFERENCE.md](docs/API_REFERENCE.md) โ€” REST/WebSocket API
103
+ - [MAESTRO_COMPLETE_ARCHITECTURE.md](MAESTRO_COMPLETE_ARCHITECTURE.md) โ€” full architecture spec
104
+
105
+ ## ๐Ÿ“„ License
106
+
107
+ MIT โ€” see [LICENSE](LICENSE).
@@ -0,0 +1,72 @@
1
+ # ๐Ÿ Maestro โ€” Automotive Test Automation Framework
2
+
3
+ Maestro consolidates SSH, ADB, bench power control, ETFW, DLT logging, serial
4
+ consoles and Windows camera capture into a single browser-based dashboard.
5
+ Non-technical users design test cases with drag-and-drop; engineers extend it
6
+ through a hot-reloadable plugin system.
7
+
8
+ ## ๐Ÿš€ Quick start
9
+
10
+ ```bash
11
+ # Requirements: Python 3.10+ (3.11.9 recommended), Node.js 18+
12
+
13
+ cd maestro
14
+ pip install -r requirements.txt # or: pip install poetry && poetry install
15
+ python app.py
16
+ ```
17
+
18
+ `app.py` installs anything missing, builds the React frontend on first run,
19
+ starts the FastAPI backend on **http://localhost:8000** and opens your
20
+ browser. That's it.
21
+
22
+ | URL | What |
23
+ |---|---|
24
+ | `http://localhost:8000` | Maestro dashboard |
25
+ | `http://localhost:8000/api/docs` | Interactive API documentation (Swagger) |
26
+ | `http://localhost:8000/metrics` | Prometheus metrics |
27
+
28
+ ## โœจ Highlights
29
+
30
+ - **4-column drag-and-drop test designer** with pre-built step templates for
31
+ SSH, ADB, power, ignition, ETFW, DLT, camera and serial console
32
+ - **Execution engine**: serial / parallel / step-by-step modes, retry with
33
+ exponential backoff, IF/THEN conditional jumps, loops, parallel groups,
34
+ per-device resource locking, sandboxed user scripts
35
+ - **Live monitoring** over WebSocket: step status, logs, pause/resume/stop
36
+ - **Allure-style HTML reports** with timelines, artifacts and report diffing
37
+ - **Scheduling** via cron expressions (APScheduler)
38
+ - **Enterprise security**: AES-256-GCM credential vault, 5-role RBAC,
39
+ full audit logging
40
+ - **Observability**: structured JSON logs, Prometheus metrics, adapter health
41
+ - **Plugin system**: manifest-based adapters, enable/disable, hot reload,
42
+ custom plugins in `data/plugins/`
43
+
44
+ ## ๐Ÿงช Development
45
+
46
+ ```bash
47
+ # Backend tests
48
+ python -m pytest tests/
49
+
50
+ # Frontend dev server (proxies API to :8000)
51
+ cd frontend && npm install && npm run dev
52
+
53
+ # Frontend tests & build
54
+ npm run test && npm run build
55
+ ```
56
+
57
+ ## ๐Ÿณ Docker
58
+
59
+ ```bash
60
+ docker compose -f docker/docker-compose.yml up --build
61
+ ```
62
+
63
+ ## ๐Ÿ“š Documentation
64
+
65
+ - [USER_GUIDE.md](docs/USER_GUIDE.md) โ€” using the dashboard
66
+ - [DEVELOPER_GUIDE.md](docs/DEVELOPER_GUIDE.md) โ€” extending Maestro
67
+ - [API_REFERENCE.md](docs/API_REFERENCE.md) โ€” REST/WebSocket API
68
+ - [MAESTRO_COMPLETE_ARCHITECTURE.md](MAESTRO_COMPLETE_ARCHITECTURE.md) โ€” full architecture spec
69
+
70
+ ## ๐Ÿ“„ License
71
+
72
+ MIT โ€” see [LICENSE](LICENSE).
@@ -0,0 +1,3 @@
1
+ """Maestro - Automotive Test Automation Framework backend package."""
2
+
3
+ __version__ = "1.0.0"
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,Segoe UI,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:Fira Code,Consolas,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.card{border-radius:1rem;border-width:1px;border-color:rgb(var(--color-border) / .5);background-color:rgb(var(--color-surface) / .7);--tw-shadow: 0 1px 3px rgba(0,0,0,.12);--tw-shadow-colored: 0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.section-title{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity: 1;color:rgb(var(--color-text-muted) / var(--tw-text-opacity, 1))}.btn{display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;padding:.5rem .875rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(var(--color-primary) / .5)}.btn:disabled{pointer-events:none;opacity:.5}.btn-primary{display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;padding:.5rem .875rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn-primary:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(var(--color-primary) / .5)}.btn-primary:disabled{pointer-events:none;opacity:.5}.btn-primary{--tw-bg-opacity: 1;background-color:rgb(var(--color-primary) / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-primary:hover{opacity:.9}.btn-primary:active{--tw-scale-x: .98;--tw-scale-y: .98;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.btn-outline{display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;padding:.5rem .875rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn-outline:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(var(--color-primary) / .5)}.btn-outline:disabled{pointer-events:none;opacity:.5}.btn-outline{border-width:1px;--tw-border-opacity: 1;border-color:rgb(var(--color-border) / var(--tw-border-opacity, 1));background-color:transparent}.btn-outline:hover{--tw-bg-opacity: 1;background-color:rgb(var(--color-surface-2) / var(--tw-bg-opacity, 1))}.btn-ghost{display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;padding:.5rem .875rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn-ghost:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(var(--color-primary) / .5)}.btn-ghost:disabled{pointer-events:none;opacity:.5}.btn-ghost{background-color:transparent}.btn-ghost:hover{--tw-bg-opacity: 1;background-color:rgb(var(--color-surface-2) / var(--tw-bg-opacity, 1))}.btn-danger{display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;padding:.5rem .875rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn-danger:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(var(--color-primary) / .5)}.btn-danger:disabled{pointer-events:none;opacity:.5}.btn-danger{--tw-bg-opacity: 1;background-color:rgb(var(--color-error) / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-danger:hover{opacity:.9}.input{width:100%;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(var(--color-border) / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(var(--color-background) / var(--tw-bg-opacity, 1));padding:.5rem .75rem;font-size:.875rem;line-height:1.25rem}.input::-moz-placeholder{--tw-text-opacity: 1;color:rgb(var(--color-text-muted) / var(--tw-text-opacity, 1))}.input::placeholder{--tw-text-opacity: 1;color:rgb(var(--color-text-muted) / var(--tw-text-opacity, 1))}.input:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(var(--color-primary) / .5)}.\!label,.label{margin-bottom:.375rem;display:block;font-size:.75rem;line-height:1rem;font-weight:600;text-transform:uppercase;letter-spacing:.025em;--tw-text-opacity: 1;color:rgb(var(--color-text-muted) / var(--tw-text-opacity, 1))}.badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .625rem;font-size:.75rem;line-height:1rem;font-weight:600}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.-right-1{right:-.25rem}.-top-2{top:-.5rem}.bottom-4{bottom:1rem}.left-0\.5{left:.125rem}.left-2{left:.5rem}.left-2\.5{left:.625rem}.left-3{left:.75rem}.left-\[18px\]{left:18px}.right-0{right:0}.right-4{right:1rem}.top-0{top:0}.top-0\.5{top:.125rem}.top-2\.5{top:.625rem}.top-full{top:100%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-\[100\]{z-index:100}.z-\[60\]{z-index:60}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.-ml-0\.5{margin-left:-.125rem}.-ml-1{margin-left:-.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-2\.5{margin-bottom:.625rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-6{margin-left:1.5rem}.ml-7{margin-left:1.75rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-6{margin-top:1.5rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-1{height:.25rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-7{height:1.75rem}.h-9{height:2.25rem}.h-fit{height:-moz-fit-content;height:fit-content}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-\[48vh\]{max-height:48vh}.max-h-\[85vh\]{max-height:85vh}.min-h-0{min-height:0px}.min-h-\[100px\]{min-height:100px}.min-h-\[150px\]{min-height:150px}.min-h-\[170px\]{min-height:170px}.min-h-\[260px\]{min-height:260px}.min-h-\[460px\]{min-height:460px}.min-h-\[70px\]{min-height:70px}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-24{width:6rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-40{width:10rem}.w-44{width:11rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-52{width:13rem}.w-56{width:14rem}.w-60{width:15rem}.w-64{width:16rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-9{width:2.25rem}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[220px\]{min-width:220px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-\[120px\]{max-width:120px}.max-w-\[180px\]{max-width:180px}.max-w-\[260px\]{max-width:260px}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.scroll-mt-4{scroll-margin-top:1rem}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-10{-moz-column-gap:2.5rem;column-gap:2.5rem}.gap-y-3{row-gap:.75rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.625rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-dashed{border-style:dashed}.border-amber-500\/40{border-color:#f59e0b66}.border-amber-500\/50{border-color:#f59e0b80}.border-border{--tw-border-opacity: 1;border-color:rgb(var(--color-border) / var(--tw-border-opacity, 1))}.border-border\/40{border-color:rgb(var(--color-border) / .4)}.border-border\/60{border-color:rgb(var(--color-border) / .6)}.border-cyan-500\/30{border-color:#06b6d44d}.border-cyan-500\/40{border-color:#06b6d466}.border-emerald-500\/30{border-color:#10b9814d}.border-emerald-500\/50{border-color:#10b98180}.border-error\/40{border-color:rgb(var(--color-error) / .4)}.border-indigo-500\/30{border-color:#6366f14d}.border-info{--tw-border-opacity: 1;border-color:rgb(var(--color-info) / var(--tw-border-opacity, 1))}.border-info\/40{border-color:rgb(var(--color-info) / .4)}.border-info\/50{border-color:rgb(var(--color-info) / .5)}.border-orange-500\/30{border-color:#f973164d}.border-pink-500\/30{border-color:#ec48994d}.border-primary{--tw-border-opacity: 1;border-color:rgb(var(--color-primary) / var(--tw-border-opacity, 1))}.border-primary\/40{border-color:rgb(var(--color-primary) / .4)}.border-primary\/60{border-color:rgb(var(--color-primary) / .6)}.border-purple-500\/30{border-color:#a855f74d}.border-red-500\/30{border-color:#ef44444d}.border-sky-500\/30{border-color:#0ea5e94d}.border-success\/30{border-color:rgb(var(--color-success) / .3)}.border-success\/40{border-color:rgb(var(--color-success) / .4)}.border-violet-500\/40{border-color:#8b5cf666}.border-warning\/40{border-color:rgb(var(--color-warning) / .4)}.border-yellow-500\/30{border-color:#eab3084d}.border-t-primary{--tw-border-opacity: 1;border-top-color:rgb(var(--color-primary) / var(--tw-border-opacity, 1))}.bg-\[\#0b1220\]{--tw-bg-opacity: 1;background-color:rgb(11 18 32 / var(--tw-bg-opacity, 1))}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.bg-amber-500\/15{background-color:#f59e0b26}.bg-background{--tw-bg-opacity: 1;background-color:rgb(var(--color-background) / var(--tw-bg-opacity, 1))}.bg-black\/60{background-color:#0009}.bg-border{--tw-bg-opacity: 1;background-color:rgb(var(--color-border) / var(--tw-bg-opacity, 1))}.bg-cyan-500{--tw-bg-opacity: 1;background-color:rgb(6 182 212 / var(--tw-bg-opacity, 1))}.bg-cyan-500\/10{background-color:#06b6d41a}.bg-cyan-500\/15{background-color:#06b6d426}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity, 1))}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-emerald-500\/15{background-color:#10b98126}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity, 1))}.bg-error\/10{background-color:rgb(var(--color-error) / .1)}.bg-error\/15{background-color:rgb(var(--color-error) / .15)}.bg-error\/5{background-color:rgb(var(--color-error) / .05)}.bg-indigo-500{--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity, 1))}.bg-indigo-500\/15{background-color:#6366f126}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.bg-info\/10{background-color:rgb(var(--color-info) / .1)}.bg-info\/15{background-color:rgb(var(--color-info) / .15)}.bg-orange-500{--tw-bg-opacity: 1;background-color:rgb(249 115 22 / var(--tw-bg-opacity, 1))}.bg-orange-500\/15{background-color:#f9731626}.bg-pink-500{--tw-bg-opacity: 1;background-color:rgb(236 72 153 / var(--tw-bg-opacity, 1))}.bg-pink-500\/15{background-color:#ec489926}.bg-primary{--tw-bg-opacity: 1;background-color:rgb(var(--color-primary) / var(--tw-bg-opacity, 1))}.bg-primary\/10{background-color:rgb(var(--color-primary) / .1)}.bg-primary\/15{background-color:rgb(var(--color-primary) / .15)}.bg-primary\/5{background-color:rgb(var(--color-primary) / .05)}.bg-purple-500{--tw-bg-opacity: 1;background-color:rgb(168 85 247 / var(--tw-bg-opacity, 1))}.bg-purple-500\/15{background-color:#a855f726}.bg-red-400{--tw-bg-opacity: 1;background-color:rgb(248 113 113 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-red-500\/15{background-color:#ef444426}.bg-rose-500\/15{background-color:#f43f5e26}.bg-secondary\/15{background-color:rgb(var(--color-secondary) / .15)}.bg-sky-500{--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity, 1))}.bg-sky-500\/15{background-color:#0ea5e926}.bg-sky-600{--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity, 1))}.bg-slate-400{--tw-bg-opacity: 1;background-color:rgb(148 163 184 / var(--tw-bg-opacity, 1))}.bg-success{--tw-bg-opacity: 1;background-color:rgb(var(--color-success) / var(--tw-bg-opacity, 1))}.bg-success\/10{background-color:rgb(var(--color-success) / .1)}.bg-success\/15{background-color:rgb(var(--color-success) / .15)}.bg-success\/5{background-color:rgb(var(--color-success) / .05)}.bg-surface{--tw-bg-opacity: 1;background-color:rgb(var(--color-surface) / var(--tw-bg-opacity, 1))}.bg-surface-2{--tw-bg-opacity: 1;background-color:rgb(var(--color-surface-2) / var(--tw-bg-opacity, 1))}.bg-surface-2\/50{background-color:rgb(var(--color-surface-2) / .5)}.bg-transparent{background-color:transparent}.bg-violet-500\/10{background-color:#8b5cf61a}.bg-violet-500\/15{background-color:#8b5cf626}.bg-violet-500\/40{background-color:#8b5cf666}.bg-violet-500\/5{background-color:#8b5cf60d}.bg-warning\/10{background-color:rgb(var(--color-warning) / .1)}.bg-warning\/15{background-color:rgb(var(--color-warning) / .15)}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-yellow-500{--tw-bg-opacity: 1;background-color:rgb(234 179 8 / var(--tw-bg-opacity, 1))}.bg-yellow-500\/15{background-color:#eab30826}.bg-\[radial-gradient\(circle\,_rgba\(148\,163\,184\,0\.18\)_1px\,_transparent_1px\)\]{background-image:radial-gradient(circle,rgba(148,163,184,.18) 1px,transparent 1px)}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-blue-500{--tw-gradient-from: #3b82f6 var(--tw-gradient-from-position);--tw-gradient-to: rgb(59 130 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-indigo-500{--tw-gradient-from: #6366f1 var(--tw-gradient-from-position);--tw-gradient-to: rgb(99 102 241 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-violet-500{--tw-gradient-from: #8b5cf6 var(--tw-gradient-from-position);--tw-gradient-to: rgb(139 92 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-fuchsia-500{--tw-gradient-to: #d946ef var(--tw-gradient-to-position)}.to-purple-500{--tw-gradient-to: #a855f7 var(--tw-gradient-to-position)}.to-sky-400{--tw-gradient-to: #38bdf8 var(--tw-gradient-to-position)}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-3\.5{padding:.875rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-24{padding-top:6rem;padding-bottom:6rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-px{padding-top:1px;padding-bottom:1px}.pl-2{padding-left:.5rem}.pl-5{padding-left:1.25rem}.pl-8{padding-left:2rem}.pl-9{padding-left:2.25rem}.pr-1{padding-right:.25rem}.pt-1{padding-top:.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:Fira Code,Consolas,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-6xl{font-size:3.75rem;line-height:1}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[9px\]{font-size:9px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-black{font-weight:900}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-cyan-400{--tw-text-opacity: 1;color:rgb(34 211 238 / var(--tw-text-opacity, 1))}.text-cyan-500{--tw-text-opacity: 1;color:rgb(6 182 212 / var(--tw-text-opacity, 1))}.text-cyan-600{--tw-text-opacity: 1;color:rgb(8 145 178 / var(--tw-text-opacity, 1))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-emerald-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-error{--tw-text-opacity: 1;color:rgb(var(--color-error) / var(--tw-text-opacity, 1))}.text-indigo-400{--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.text-indigo-500{--tw-text-opacity: 1;color:rgb(99 102 241 / var(--tw-text-opacity, 1))}.text-info{--tw-text-opacity: 1;color:rgb(var(--color-info) / var(--tw-text-opacity, 1))}.text-orange-400{--tw-text-opacity: 1;color:rgb(251 146 60 / var(--tw-text-opacity, 1))}.text-orange-500{--tw-text-opacity: 1;color:rgb(249 115 22 / var(--tw-text-opacity, 1))}.text-pink-500{--tw-text-opacity: 1;color:rgb(236 72 153 / var(--tw-text-opacity, 1))}.text-primary{--tw-text-opacity: 1;color:rgb(var(--color-primary) / var(--tw-text-opacity, 1))}.text-purple-400{--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-purple-500{--tw-text-opacity: 1;color:rgb(168 85 247 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-rose-400{--tw-text-opacity: 1;color:rgb(251 113 133 / var(--tw-text-opacity, 1))}.text-secondary{--tw-text-opacity: 1;color:rgb(var(--color-secondary) / var(--tw-text-opacity, 1))}.text-sky-400{--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.text-sky-600{--tw-text-opacity: 1;color:rgb(2 132 199 / var(--tw-text-opacity, 1))}.text-slate-200{--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.text-slate-300{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-success{--tw-text-opacity: 1;color:rgb(var(--color-success) / var(--tw-text-opacity, 1))}.text-teal-400{--tw-text-opacity: 1;color:rgb(45 212 191 / var(--tw-text-opacity, 1))}.text-text-muted{--tw-text-opacity: 1;color:rgb(var(--color-text-muted) / var(--tw-text-opacity, 1))}.text-text-primary{--tw-text-opacity: 1;color:rgb(var(--color-text-primary) / var(--tw-text-opacity, 1))}.text-text-secondary{--tw-text-opacity: 1;color:rgb(var(--color-text-secondary) / var(--tw-text-opacity, 1))}.text-transparent{color:transparent}.text-violet-300{--tw-text-opacity: 1;color:rgb(196 181 253 / var(--tw-text-opacity, 1))}.text-violet-400{--tw-text-opacity: 1;color:rgb(167 139 250 / var(--tw-text-opacity, 1))}.text-violet-400\/80{color:#a78bfacc}.text-warning{--tw-text-opacity: 1;color:rgb(var(--color-warning) / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.underline-offset-2{text-underline-offset:2px}.accent-primary{accent-color:rgb(var(--color-primary) / 1)}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-50{opacity:.5}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_8px_1px\]{--tw-shadow: 0 0 8px 1px;--tw-shadow-colored: 0 0 8px 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-primary\/50{--tw-shadow-color: rgb(var(--color-primary) / .5);--tw-shadow: var(--tw-shadow-colored)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-inset{--tw-ring-inset: inset}.ring-info\/40{--tw-ring-color: rgb(var(--color-info) / .4)}.ring-primary\/20{--tw-ring-color: rgb(var(--color-primary) / .2)}.ring-primary\/30{--tw-ring-color: rgb(var(--color-primary) / .3)}.ring-primary\/40{--tw-ring-color: rgb(var(--color-primary) / .4)}.ring-primary\/50{--tw-ring-color: rgb(var(--color-primary) / .5)}.drop-shadow{--tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / .1)) drop-shadow(0 1px 1px rgb(0 0 0 / .06));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)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-500{transition-duration:.5s}.\[background-size\:22px_22px\]{background-size:22px 22px}:root{--color-primary: 37 99 235;--color-secondary: 14 165 233;--color-success: 22 163 74;--color-warning: 217 119 6;--color-error: 220 38 38;--color-info: 2 132 199;--color-background: 246 249 252;--color-surface: 255 255 255;--color-surface-2: 240 244 249;--color-border: 224 231 240;--color-text-primary: 17 24 39;--color-text-secondary: 71 85 105;--color-text-muted: 130 142 161;--color-on-primary: 255 255 255}.dark{--color-primary: 59 130 246;--color-secondary: 56 189 248;--color-success: 34 197 94;--color-warning: 245 158 11;--color-error: 248 113 113;--color-info: 56 189 248;--color-background: 15 23 42;--color-surface: 22 32 53;--color-surface-2: 33 46 73;--color-border: 45 60 90;--color-text-primary: 237 242 249;--color-text-secondary: 203 213 225;--color-text-muted: 148 163 184;--color-on-primary: 255 255 255}body{--tw-bg-opacity: 1;background-color:rgb(var(--color-background) / var(--tw-bg-opacity, 1));font-family:Inter,Segoe UI,system-ui,sans-serif;--tw-text-opacity: 1;color:rgb(var(--color-text-primary) / var(--tw-text-opacity, 1));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*{border-color:rgb(var(--color-border))}select{color:rgb(var(--color-text-primary))}option{background-color:rgb(var(--color-surface));color:rgb(var(--color-text-primary))}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:rgb(var(--color-border));border-radius:4px}::-webkit-scrollbar-track{background:transparent}.hover\:-translate-y-px:hover{--tw-translate-y: -1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-\[1\.02\]:hover{--tw-scale-x: 1.02;--tw-scale-y: 1.02;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-amber-500\/50:hover{border-color:#f59e0b80}.hover\:border-amber-500\/70:hover{border-color:#f59e0bb3}.hover\:border-primary\/30:hover{border-color:rgb(var(--color-primary) / .3)}.hover\:border-primary\/50:hover{border-color:rgb(var(--color-primary) / .5)}.hover\:bg-indigo-500\/30:hover{background-color:#6366f14d}.hover\:bg-surface-2:hover{--tw-bg-opacity: 1;background-color:rgb(var(--color-surface-2) / var(--tw-bg-opacity, 1))}.hover\:bg-violet-500\/10:hover{background-color:#8b5cf61a}.hover\:text-primary:hover{--tw-text-opacity: 1;color:rgb(var(--color-primary) / var(--tw-text-opacity, 1))}.hover\:text-text-primary:hover{--tw-text-opacity: 1;color:rgb(var(--color-text-primary) / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.hover\:shadow-md:hover{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-sm:hover{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:opacity-40:disabled{opacity:.4}.group\/p:hover .group-hover\/p\:opacity-100,.group:hover .group-hover\:opacity-100{opacity:1}.dark\:text-cyan-400:is(.dark *){--tw-text-opacity: 1;color:rgb(34 211 238 / var(--tw-text-opacity, 1))}.dark\:text-emerald-400:is(.dark *){--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.dark\:text-indigo-400:is(.dark *){--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.dark\:text-orange-400:is(.dark *){--tw-text-opacity: 1;color:rgb(251 146 60 / var(--tw-text-opacity, 1))}.dark\:text-pink-400:is(.dark *){--tw-text-opacity: 1;color:rgb(244 114 182 / var(--tw-text-opacity, 1))}.dark\:text-purple-400:is(.dark *){--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.dark\:text-sky-400:is(.dark *){--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.dark\:text-yellow-400:is(.dark *){--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}@media (min-width: 640px){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width: 768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-\[230px_1fr\]{grid-template-columns:230px 1fr}.lg\:grid-cols-\[280px_1fr\]{grid-template-columns:280px 1fr}.lg\:grid-rows-\[minmax\(0\,1fr\)\]{grid-template-rows:minmax(0,1fr)}}@media (min-width: 1280px){.xl\:col-span-2{grid-column:span 2 / span 2}.xl\:col-span-3{grid-column:span 3 / span 3}.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}}