ralphx 0.2.2__py3-none-any.whl → 0.3.5__py3-none-any.whl
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.
- ralphx/__init__.py +1 -1
- ralphx/api/main.py +9 -1
- ralphx/api/routes/auth.py +730 -65
- ralphx/api/routes/config.py +3 -56
- ralphx/api/routes/export_import.py +795 -0
- ralphx/api/routes/loops.py +4 -4
- ralphx/api/routes/planning.py +19 -5
- ralphx/api/routes/projects.py +84 -2
- ralphx/api/routes/templates.py +115 -2
- ralphx/api/routes/workflows.py +22 -22
- ralphx/cli.py +21 -6
- ralphx/core/auth.py +346 -171
- ralphx/core/database.py +615 -167
- ralphx/core/executor.py +0 -3
- ralphx/core/loop.py +15 -2
- ralphx/core/loop_templates.py +69 -3
- ralphx/core/planning_service.py +109 -21
- ralphx/core/preview.py +9 -25
- ralphx/core/project_db.py +175 -75
- ralphx/core/project_export.py +469 -0
- ralphx/core/project_import.py +670 -0
- ralphx/core/sample_project.py +430 -0
- ralphx/core/templates.py +46 -9
- ralphx/core/workflow_executor.py +35 -5
- ralphx/core/workflow_export.py +606 -0
- ralphx/core/workflow_import.py +1149 -0
- ralphx/examples/sample_project/DESIGN.md +345 -0
- ralphx/examples/sample_project/README.md +37 -0
- ralphx/examples/sample_project/guardrails.md +57 -0
- ralphx/examples/sample_project/stories.jsonl +10 -0
- ralphx/mcp/__init__.py +6 -2
- ralphx/mcp/registry.py +3 -3
- ralphx/mcp/server.py +99 -29
- ralphx/mcp/tools/__init__.py +4 -0
- ralphx/mcp/tools/help.py +204 -0
- ralphx/mcp/tools/workflows.py +114 -32
- ralphx/mcp_server.py +6 -2
- ralphx/static/assets/index-0ovNnfOq.css +1 -0
- ralphx/static/assets/index-CY9s08ZB.js +251 -0
- ralphx/static/assets/index-CY9s08ZB.js.map +1 -0
- ralphx/static/index.html +14 -0
- {ralphx-0.2.2.dist-info → ralphx-0.3.5.dist-info}/METADATA +34 -12
- {ralphx-0.2.2.dist-info → ralphx-0.3.5.dist-info}/RECORD +45 -30
- {ralphx-0.2.2.dist-info → ralphx-0.3.5.dist-info}/WHEEL +0 -0
- {ralphx-0.2.2.dist-info → ralphx-0.3.5.dist-info}/entry_points.txt +0 -0
ralphx/mcp/tools/__init__.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""MCP tool implementations organized by category.
|
|
2
2
|
|
|
3
3
|
Tool modules:
|
|
4
|
+
- help: Product overview and guidance (call first!)
|
|
4
5
|
- projects: Project management (list, get, add, remove, update)
|
|
5
6
|
- loops: Loop/run management
|
|
6
7
|
- monitoring: Logs, sessions, diagnostics, stale runs
|
|
@@ -10,6 +11,7 @@ Tool modules:
|
|
|
10
11
|
- imports: Import operations
|
|
11
12
|
"""
|
|
12
13
|
|
|
14
|
+
from ralphx.mcp.tools.help import get_help_tools
|
|
13
15
|
from ralphx.mcp.tools.projects import get_project_tools
|
|
14
16
|
from ralphx.mcp.tools.loops import get_loop_tools
|
|
15
17
|
from ralphx.mcp.tools.items import get_item_tools
|
|
@@ -25,6 +27,8 @@ from ralphx.mcp.tools.resources import get_resource_tools
|
|
|
25
27
|
def get_all_tools():
|
|
26
28
|
"""Get all tool definitions."""
|
|
27
29
|
tools = []
|
|
30
|
+
# Help tool first - provides product context
|
|
31
|
+
tools.extend(get_help_tools())
|
|
28
32
|
tools.extend(get_project_tools())
|
|
29
33
|
tools.extend(get_loop_tools())
|
|
30
34
|
tools.extend(get_item_tools())
|
ralphx/mcp/tools/help.py
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""Help MCP tool.
|
|
2
|
+
|
|
3
|
+
Provides product context and guidance for using RalphX.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from ralphx.mcp.base import ToolDefinition, make_schema, prop_string
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
RALPHX_HELP = """
|
|
10
|
+
# RalphX - Autonomous AI Loop Orchestration
|
|
11
|
+
|
|
12
|
+
RalphX helps you run autonomous AI workflows. Instead of manually prompting Claude over and over, you define loops that execute automatically while you monitor progress.
|
|
13
|
+
|
|
14
|
+
## Core Concepts
|
|
15
|
+
|
|
16
|
+
**Project**: A directory registered with RalphX (e.g., your codebase)
|
|
17
|
+
**Loop**: An autonomous workflow defined in YAML (e.g., "planning loop" generates user stories)
|
|
18
|
+
**Work Item**: Data generated/consumed by loops (stories, tasks, research notes)
|
|
19
|
+
**Workflow**: A multi-step pipeline for complex tasks (research → implement → test)
|
|
20
|
+
**Run**: A single execution of a loop or workflow step
|
|
21
|
+
|
|
22
|
+
## Common Workflows
|
|
23
|
+
|
|
24
|
+
### 1. Getting Started
|
|
25
|
+
```
|
|
26
|
+
1. ralphx_add_project - Register a project directory
|
|
27
|
+
2. ralphx_check_system_health - Verify setup is correct
|
|
28
|
+
3. ralphx_list_loops - See available loops
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. Running a Loop
|
|
32
|
+
```
|
|
33
|
+
1. ralphx_list_loops - Find the loop you want
|
|
34
|
+
2. ralphx_start_loop - Start it running
|
|
35
|
+
3. ralphx_list_runs - Monitor progress
|
|
36
|
+
4. ralphx_get_logs - View detailed logs
|
|
37
|
+
5. ralphx_stop_loop - Stop when done (or it stops automatically)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 3. Creating a Workflow
|
|
41
|
+
```
|
|
42
|
+
1. ralphx_list_workflow_templates - See available templates
|
|
43
|
+
2. ralphx_create_workflow - Create from template or scratch
|
|
44
|
+
3. ralphx_create_workflow_step - Add steps (research, implement, test)
|
|
45
|
+
4. ralphx_start_workflow - Begin execution
|
|
46
|
+
5. ralphx_advance_workflow - Move to next step when ready
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 4. Managing Work Items
|
|
50
|
+
```
|
|
51
|
+
1. ralphx_list_items - View items (user stories, tasks, etc.)
|
|
52
|
+
2. ralphx_add_item - Add new items manually
|
|
53
|
+
3. ralphx_claim_item - Mark an item as being worked on
|
|
54
|
+
4. ralphx_complete_item - Mark as done
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 5. Troubleshooting
|
|
58
|
+
```
|
|
59
|
+
1. ralphx_check_system_health - System-wide health check
|
|
60
|
+
2. ralphx_diagnose_project - Project-specific diagnostics
|
|
61
|
+
3. ralphx_get_stop_reason - Why did a run fail?
|
|
62
|
+
4. ralphx_list_stale_runs - Find zombie runs
|
|
63
|
+
5. ralphx_cleanup_stale_runs - Clean them up
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 6. Permissions & Guardrails
|
|
67
|
+
```
|
|
68
|
+
1. ralphx_check_permissions - What tools are allowed?
|
|
69
|
+
2. ralphx_setup_permissions - Auto-configure based on loop needs
|
|
70
|
+
3. ralphx_apply_permission_preset - Quick setup (research/implementation/full)
|
|
71
|
+
4. ralphx_list_guardrails - See safety guardrails
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Tool Categories (67 tools total)
|
|
75
|
+
|
|
76
|
+
- **Projects (5)**: list, get, add, remove, update
|
|
77
|
+
- **Loops (7)**: list, status, start, stop, config, validate, sync
|
|
78
|
+
- **Items (6)**: list, get, add, update, claim, complete
|
|
79
|
+
- **Workflows (16)**: create, start, pause, advance, stop, steps, resources, archive
|
|
80
|
+
- **Monitoring (7)**: runs, logs, sessions, events
|
|
81
|
+
- **Diagnostics (5)**: health, diagnose, stop reason, stale runs
|
|
82
|
+
- **Guardrails (6)**: list, detect, validate, preview, templates
|
|
83
|
+
- **Permissions (3)**: check, setup, presets
|
|
84
|
+
- **Imports (5)**: paste, jsonl, inputs, templates
|
|
85
|
+
- **Resources (6)**: project resources, workflow resources
|
|
86
|
+
|
|
87
|
+
## Tips
|
|
88
|
+
|
|
89
|
+
- Always start with `ralphx_list_projects` to see what's registered
|
|
90
|
+
- Use `ralphx_check_system_health` if things aren't working
|
|
91
|
+
- Use `ralphx_get_stop_reason` to understand failures
|
|
92
|
+
- Workflows are for multi-step tasks; loops are for repetitive automation
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get_help(topic: str = None) -> dict:
|
|
97
|
+
"""Get help about RalphX.
|
|
98
|
+
|
|
99
|
+
Returns product overview and common workflows.
|
|
100
|
+
For specific topics, returns focused guidance.
|
|
101
|
+
"""
|
|
102
|
+
if topic:
|
|
103
|
+
topic_lower = topic.lower()
|
|
104
|
+
|
|
105
|
+
if "project" in topic_lower:
|
|
106
|
+
return {
|
|
107
|
+
"topic": "projects",
|
|
108
|
+
"help": (
|
|
109
|
+
"Projects are directories registered with RalphX.\n\n"
|
|
110
|
+
"Tools:\n"
|
|
111
|
+
"- ralphx_list_projects: See all registered projects\n"
|
|
112
|
+
"- ralphx_get_project: Get details about one project\n"
|
|
113
|
+
"- ralphx_add_project: Register a new project\n"
|
|
114
|
+
"- ralphx_remove_project: Unregister a project\n"
|
|
115
|
+
"- ralphx_update_project: Update project settings\n\n"
|
|
116
|
+
"Start with: ralphx_list_projects"
|
|
117
|
+
),
|
|
118
|
+
}
|
|
119
|
+
elif "loop" in topic_lower:
|
|
120
|
+
return {
|
|
121
|
+
"topic": "loops",
|
|
122
|
+
"help": (
|
|
123
|
+
"Loops are autonomous workflows defined in YAML.\n\n"
|
|
124
|
+
"Tools:\n"
|
|
125
|
+
"- ralphx_list_loops: See loops in a project\n"
|
|
126
|
+
"- ralphx_get_loop_status: Check if running\n"
|
|
127
|
+
"- ralphx_start_loop: Start execution\n"
|
|
128
|
+
"- ralphx_stop_loop: Stop execution\n"
|
|
129
|
+
"- ralphx_get_loop_config: View configuration\n"
|
|
130
|
+
"- ralphx_validate_loop: Check for config errors\n\n"
|
|
131
|
+
"Common flow: list_loops → start_loop → list_runs → stop_loop"
|
|
132
|
+
),
|
|
133
|
+
}
|
|
134
|
+
elif "workflow" in topic_lower:
|
|
135
|
+
return {
|
|
136
|
+
"topic": "workflows",
|
|
137
|
+
"help": (
|
|
138
|
+
"Workflows are multi-step pipelines for complex tasks.\n\n"
|
|
139
|
+
"Tools:\n"
|
|
140
|
+
"- ralphx_list_workflows: See workflows in a project\n"
|
|
141
|
+
"- ralphx_create_workflow: Create new workflow\n"
|
|
142
|
+
"- ralphx_start_workflow: Begin execution\n"
|
|
143
|
+
"- ralphx_advance_workflow: Move to next step\n"
|
|
144
|
+
"- ralphx_create_workflow_step: Add steps\n"
|
|
145
|
+
"- ralphx_list_workflow_templates: See templates\n\n"
|
|
146
|
+
"Common flow: create_workflow → create_workflow_step (x3) → start_workflow → advance_workflow"
|
|
147
|
+
),
|
|
148
|
+
}
|
|
149
|
+
elif "item" in topic_lower or "work" in topic_lower:
|
|
150
|
+
return {
|
|
151
|
+
"topic": "work_items",
|
|
152
|
+
"help": (
|
|
153
|
+
"Work items are data generated/consumed by loops (stories, tasks, etc.).\n\n"
|
|
154
|
+
"Tools:\n"
|
|
155
|
+
"- ralphx_list_items: View items with filters\n"
|
|
156
|
+
"- ralphx_add_item: Create new item\n"
|
|
157
|
+
"- ralphx_update_item: Modify item\n"
|
|
158
|
+
"- ralphx_claim_item: Mark as being worked on\n"
|
|
159
|
+
"- ralphx_complete_item: Mark as done\n\n"
|
|
160
|
+
"Filter by: status, category, phase, workflow_id"
|
|
161
|
+
),
|
|
162
|
+
}
|
|
163
|
+
elif "troubleshoot" in topic_lower or "debug" in topic_lower or "error" in topic_lower:
|
|
164
|
+
return {
|
|
165
|
+
"topic": "troubleshooting",
|
|
166
|
+
"help": (
|
|
167
|
+
"Tools for diagnosing issues:\n\n"
|
|
168
|
+
"- ralphx_check_system_health: Is Python/Node/Claude CLI working?\n"
|
|
169
|
+
"- ralphx_diagnose_project: Check database, loops, workflows\n"
|
|
170
|
+
"- ralphx_get_stop_reason: Why did a run fail?\n"
|
|
171
|
+
"- ralphx_list_stale_runs: Find zombie processes\n"
|
|
172
|
+
"- ralphx_cleanup_stale_runs: Clean them up\n"
|
|
173
|
+
"- ralphx_get_logs: View detailed logs\n\n"
|
|
174
|
+
"Start with: ralphx_check_system_health"
|
|
175
|
+
),
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
"topic": "overview",
|
|
180
|
+
"help": RALPHX_HELP,
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def get_help_tools() -> list[ToolDefinition]:
|
|
185
|
+
"""Get help tool definitions."""
|
|
186
|
+
return [
|
|
187
|
+
ToolDefinition(
|
|
188
|
+
name="ralphx_help",
|
|
189
|
+
description=(
|
|
190
|
+
"Get help about RalphX. Call this FIRST to understand how to use RalphX tools. "
|
|
191
|
+
"Returns product overview, common workflows, and tool categories. "
|
|
192
|
+
"Optionally pass a topic: 'projects', 'loops', 'workflows', 'items', 'troubleshooting'"
|
|
193
|
+
),
|
|
194
|
+
handler=get_help,
|
|
195
|
+
input_schema=make_schema(
|
|
196
|
+
properties={
|
|
197
|
+
"topic": prop_string(
|
|
198
|
+
"Optional topic: 'projects', 'loops', 'workflows', 'items', 'troubleshooting'"
|
|
199
|
+
),
|
|
200
|
+
},
|
|
201
|
+
required=[],
|
|
202
|
+
),
|
|
203
|
+
),
|
|
204
|
+
]
|
ralphx/mcp/tools/workflows.py
CHANGED
|
@@ -89,7 +89,6 @@ def list_workflows(
|
|
|
89
89
|
{
|
|
90
90
|
"id": w["id"],
|
|
91
91
|
"name": w["name"],
|
|
92
|
-
"namespace": w["namespace"],
|
|
93
92
|
"status": w["status"],
|
|
94
93
|
"current_step": w["current_step"],
|
|
95
94
|
"template_id": w.get("template_id"),
|
|
@@ -130,7 +129,6 @@ def get_workflow(slug: str, workflow_id: str) -> dict:
|
|
|
130
129
|
return {
|
|
131
130
|
"id": workflow["id"],
|
|
132
131
|
"name": workflow["name"],
|
|
133
|
-
"namespace": workflow["namespace"],
|
|
134
132
|
"status": workflow["status"],
|
|
135
133
|
"current_step": workflow["current_step"],
|
|
136
134
|
"template_id": workflow.get("template_id"),
|
|
@@ -157,7 +155,6 @@ def create_workflow(
|
|
|
157
155
|
slug: str,
|
|
158
156
|
name: str,
|
|
159
157
|
template_id: Optional[str] = None,
|
|
160
|
-
namespace: Optional[str] = None,
|
|
161
158
|
) -> dict:
|
|
162
159
|
"""Create a new workflow, optionally from a template."""
|
|
163
160
|
manager = get_manager()
|
|
@@ -168,11 +165,8 @@ def create_workflow(
|
|
|
168
165
|
|
|
169
166
|
project_db = manager.get_project_db(project.path)
|
|
170
167
|
|
|
171
|
-
# Generate unique ID
|
|
168
|
+
# Generate unique ID
|
|
172
169
|
workflow_id = f"wf-{uuid.uuid4().hex[:12]}"
|
|
173
|
-
if not namespace:
|
|
174
|
-
namespace = name.lower().replace(" ", "-")[:56]
|
|
175
|
-
namespace = f"{namespace}-{uuid.uuid4().hex[:7]}"
|
|
176
170
|
|
|
177
171
|
# Get template steps if specified
|
|
178
172
|
template_steps = []
|
|
@@ -194,23 +188,41 @@ def create_workflow(
|
|
|
194
188
|
project_db.create_workflow(
|
|
195
189
|
id=workflow_id,
|
|
196
190
|
name=name,
|
|
197
|
-
namespace=namespace,
|
|
198
191
|
template_id=template_id,
|
|
199
192
|
status="draft",
|
|
200
193
|
)
|
|
201
194
|
|
|
202
195
|
# Create steps from template
|
|
203
196
|
for step_def in template_steps:
|
|
197
|
+
# Look up processing_type config if specified
|
|
198
|
+
processing_type = step_def.get("processing_type")
|
|
199
|
+
if processing_type and processing_type in PROCESSING_TYPES:
|
|
200
|
+
type_config = PROCESSING_TYPES[processing_type]
|
|
201
|
+
step_type = type_config["step_type"]
|
|
202
|
+
config = {
|
|
203
|
+
**type_config["config"],
|
|
204
|
+
"description": step_def.get("description"),
|
|
205
|
+
"skippable": step_def.get("skippable", False),
|
|
206
|
+
"inputs": step_def.get("inputs", []),
|
|
207
|
+
"outputs": step_def.get("outputs", []),
|
|
208
|
+
}
|
|
209
|
+
if step_def.get("skipCondition"):
|
|
210
|
+
config["skipCondition"] = step_def["skipCondition"]
|
|
211
|
+
else:
|
|
212
|
+
# Fallback for legacy templates without processing_type
|
|
213
|
+
step_type = step_def.get("type", "autonomous")
|
|
214
|
+
config = {
|
|
215
|
+
"description": step_def.get("description"),
|
|
216
|
+
"loopType": step_def.get("loopType"),
|
|
217
|
+
"skippable": step_def.get("skippable", False),
|
|
218
|
+
}
|
|
219
|
+
|
|
204
220
|
project_db.create_workflow_step(
|
|
205
221
|
workflow_id=workflow_id,
|
|
206
222
|
step_number=step_def["number"],
|
|
207
223
|
name=step_def["name"],
|
|
208
|
-
step_type=
|
|
209
|
-
config=
|
|
210
|
-
"description": step_def.get("description"),
|
|
211
|
-
"loopType": step_def.get("loopType"),
|
|
212
|
-
"skippable": step_def.get("skippable", False),
|
|
213
|
-
},
|
|
224
|
+
step_type=step_type,
|
|
225
|
+
config=config,
|
|
214
226
|
status="pending",
|
|
215
227
|
)
|
|
216
228
|
except Exception as e:
|
|
@@ -223,7 +235,6 @@ def create_workflow(
|
|
|
223
235
|
return {
|
|
224
236
|
"id": workflow_id,
|
|
225
237
|
"name": name,
|
|
226
|
-
"namespace": namespace,
|
|
227
238
|
"template_id": template_id,
|
|
228
239
|
"step_count": len(template_steps),
|
|
229
240
|
"message": "Workflow created",
|
|
@@ -563,17 +574,82 @@ def list_workflow_templates(slug: str) -> dict:
|
|
|
563
574
|
|
|
564
575
|
# Workflow Step tools
|
|
565
576
|
|
|
577
|
+
# Processing type configurations - matches frontend StepSettings.tsx
|
|
578
|
+
PROCESSING_TYPES = {
|
|
579
|
+
"design_doc": {
|
|
580
|
+
"label": "Build Design Doc",
|
|
581
|
+
"description": "Interactive chat with web research to create a design document",
|
|
582
|
+
"step_type": "interactive",
|
|
583
|
+
"config": {
|
|
584
|
+
"loopType": "design_doc",
|
|
585
|
+
"allowedTools": ["WebSearch", "WebFetch", "Bash", "Read", "Glob", "Grep"],
|
|
586
|
+
"model": "opus",
|
|
587
|
+
"timeout": 300,
|
|
588
|
+
},
|
|
589
|
+
},
|
|
590
|
+
"extractgen_requirements": {
|
|
591
|
+
"label": "Generate Stories (Extract)",
|
|
592
|
+
"description": "Extract user stories from design documents",
|
|
593
|
+
"step_type": "autonomous",
|
|
594
|
+
"config": {
|
|
595
|
+
"loopType": "generator",
|
|
596
|
+
"template": "extractgen_requirements",
|
|
597
|
+
"allowedTools": ["WebSearch", "WebFetch"],
|
|
598
|
+
"model": "opus",
|
|
599
|
+
"timeout": 600,
|
|
600
|
+
"max_iterations": 100,
|
|
601
|
+
"cooldown_between_iterations": 5,
|
|
602
|
+
"max_consecutive_errors": 5,
|
|
603
|
+
},
|
|
604
|
+
},
|
|
605
|
+
"webgen_requirements": {
|
|
606
|
+
"label": "Generate Stories (WebSearch)",
|
|
607
|
+
"description": "Discover missing requirements via web research",
|
|
608
|
+
"step_type": "autonomous",
|
|
609
|
+
"config": {
|
|
610
|
+
"loopType": "generator",
|
|
611
|
+
"template": "webgen_requirements",
|
|
612
|
+
"allowedTools": ["WebSearch", "WebFetch"],
|
|
613
|
+
"model": "opus",
|
|
614
|
+
"timeout": 900,
|
|
615
|
+
"max_iterations": 15,
|
|
616
|
+
"cooldown_between_iterations": 15,
|
|
617
|
+
"max_consecutive_errors": 3,
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
"implementation": {
|
|
621
|
+
"label": "Implementation",
|
|
622
|
+
"description": "Consumes stories and commits code to git",
|
|
623
|
+
"step_type": "autonomous",
|
|
624
|
+
"config": {
|
|
625
|
+
"loopType": "consumer",
|
|
626
|
+
"template": "implementation",
|
|
627
|
+
"allowedTools": ["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
|
|
628
|
+
"model": "opus",
|
|
629
|
+
"timeout": 1800,
|
|
630
|
+
"max_iterations": 50,
|
|
631
|
+
"cooldown_between_iterations": 5,
|
|
632
|
+
"max_consecutive_errors": 3,
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
}
|
|
636
|
+
|
|
566
637
|
|
|
567
638
|
def create_workflow_step(
|
|
568
639
|
slug: str,
|
|
569
640
|
workflow_id: str,
|
|
570
|
-
|
|
571
|
-
|
|
641
|
+
step_name: str,
|
|
642
|
+
processing_type: str,
|
|
572
643
|
step_number: Optional[int] = None,
|
|
573
|
-
config: Optional[dict] = None,
|
|
574
644
|
loop_name: Optional[str] = None,
|
|
575
645
|
) -> dict:
|
|
576
|
-
"""Create a new step in a workflow.
|
|
646
|
+
"""Create a new step in a workflow from a processing type.
|
|
647
|
+
|
|
648
|
+
Processing types:
|
|
649
|
+
- design_doc: Interactive chat to build a design document (with web search)
|
|
650
|
+
- extractgen_requirements: Extract user stories from design documents
|
|
651
|
+
- webgen_requirements: Discover requirements via web research
|
|
652
|
+
- implementation: Implement stories and commit code
|
|
577
653
|
|
|
578
654
|
If step_number is not provided, appends to end.
|
|
579
655
|
"""
|
|
@@ -589,29 +665,34 @@ def create_workflow_step(
|
|
|
589
665
|
if not workflow:
|
|
590
666
|
raise ToolError.workflow_not_found(workflow_id)
|
|
591
667
|
|
|
592
|
-
|
|
593
|
-
if step_type not in valid_types:
|
|
668
|
+
if processing_type not in PROCESSING_TYPES:
|
|
594
669
|
raise ToolError.validation_error(
|
|
595
|
-
f"Invalid
|
|
670
|
+
f"Invalid processing_type: {processing_type}. "
|
|
671
|
+
f"Must be one of: {list(PROCESSING_TYPES.keys())}",
|
|
596
672
|
)
|
|
597
673
|
|
|
674
|
+
# Get the processing type configuration
|
|
675
|
+
type_config = PROCESSING_TYPES[processing_type]
|
|
676
|
+
step_type = type_config["step_type"]
|
|
677
|
+
config = {**type_config["config"]} # Copy to avoid mutation
|
|
678
|
+
|
|
598
679
|
try:
|
|
599
680
|
if step_number is None:
|
|
600
681
|
# Use atomic creation that auto-calculates step number
|
|
601
682
|
step = project_db.create_workflow_step_atomic(
|
|
602
683
|
workflow_id=workflow_id,
|
|
603
|
-
name=
|
|
684
|
+
name=step_name,
|
|
604
685
|
step_type=step_type,
|
|
605
|
-
config=config
|
|
686
|
+
config=config,
|
|
606
687
|
loop_name=loop_name,
|
|
607
688
|
)
|
|
608
689
|
else:
|
|
609
690
|
step = project_db.create_workflow_step(
|
|
610
691
|
workflow_id=workflow_id,
|
|
611
692
|
step_number=step_number,
|
|
612
|
-
name=
|
|
693
|
+
name=step_name,
|
|
613
694
|
step_type=step_type,
|
|
614
|
-
config=config
|
|
695
|
+
config=config,
|
|
615
696
|
loop_name=loop_name,
|
|
616
697
|
status="pending",
|
|
617
698
|
)
|
|
@@ -627,7 +708,9 @@ def create_workflow_step(
|
|
|
627
708
|
"step_number": step["step_number"],
|
|
628
709
|
"name": step["name"],
|
|
629
710
|
"step_type": step["step_type"],
|
|
630
|
-
"
|
|
711
|
+
"processing_type": processing_type,
|
|
712
|
+
"config": config,
|
|
713
|
+
"message": f"Step created with {type_config['label']} configuration",
|
|
631
714
|
}
|
|
632
715
|
|
|
633
716
|
|
|
@@ -877,7 +960,6 @@ def get_workflow_tools() -> list[ToolDefinition]:
|
|
|
877
960
|
"slug": prop_string("Project slug"),
|
|
878
961
|
"name": prop_string("Workflow name"),
|
|
879
962
|
"template_id": prop_string("Template ID (optional)"),
|
|
880
|
-
"namespace": prop_string("Custom namespace (optional)"),
|
|
881
963
|
},
|
|
882
964
|
required=["slug", "name"],
|
|
883
965
|
),
|
|
@@ -984,18 +1066,18 @@ def get_workflow_tools() -> list[ToolDefinition]:
|
|
|
984
1066
|
# Step management
|
|
985
1067
|
ToolDefinition(
|
|
986
1068
|
name="ralphx_create_workflow_step",
|
|
987
|
-
description="Create a new step in a workflow",
|
|
1069
|
+
description="Create a new step in a workflow. Processing types: design_doc (interactive chat with web research), extractgen_requirements (extract stories from docs), webgen_requirements (web research for requirements), implementation (implement stories)",
|
|
988
1070
|
handler=create_workflow_step,
|
|
989
1071
|
input_schema=make_schema(
|
|
990
1072
|
properties={
|
|
991
1073
|
"slug": prop_string("Project slug"),
|
|
992
1074
|
"workflow_id": prop_string("Workflow ID"),
|
|
993
|
-
"
|
|
994
|
-
"
|
|
1075
|
+
"step_name": prop_string("Step name (e.g., 'Design Document', 'Story Generation')"),
|
|
1076
|
+
"processing_type": prop_enum("Processing type", ["design_doc", "extractgen_requirements", "webgen_requirements", "implementation"]),
|
|
995
1077
|
"step_number": prop_int("Step number (optional, defaults to append)"),
|
|
996
1078
|
"loop_name": prop_string("Loop name for autonomous steps"),
|
|
997
1079
|
},
|
|
998
|
-
required=["slug", "workflow_id", "
|
|
1080
|
+
required=["slug", "workflow_id", "step_name", "processing_type"],
|
|
999
1081
|
),
|
|
1000
1082
|
),
|
|
1001
1083
|
ToolDefinition(
|
ralphx/mcp_server.py
CHANGED
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
This module provides backwards-compatible entry point for the MCP server.
|
|
4
4
|
The actual implementation is in the ralphx.mcp package.
|
|
5
5
|
|
|
6
|
-
Usage:
|
|
7
|
-
claude mcp add ralphx -- ralphx mcp
|
|
6
|
+
Usage (Linux/Mac):
|
|
7
|
+
claude mcp add ralphx -e PYTHONDONTWRITEBYTECODE=1 -- "$(which ralphx)" mcp
|
|
8
|
+
# Mac zsh: if "which" fails, run: conda init zsh && source ~/.zshrc
|
|
9
|
+
|
|
10
|
+
Usage (Windows - find path first with: where.exe ralphx):
|
|
11
|
+
claude mcp add ralphx -e PYTHONDONTWRITEBYTECODE=1 -- C:\\path\\to\\ralphx.exe mcp
|
|
8
12
|
"""
|
|
9
13
|
|
|
10
14
|
from ralphx.mcp import MCPServer
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=DM+Sans:wght@400;500;600;700&display=swap";*,: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:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";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:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,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}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.btn-primary{border-radius:.5rem;padding:.625rem 1.25rem;font-weight:600;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;background:linear-gradient(135deg,var(--color-cyan) 0%,#00b4d8 100%);color:var(--color-void);box-shadow:0 0 20px var(--color-cyan-dim),inset 0 1px #fff3}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 0 30px var(--color-cyan-dim),0 4px 12px #0006,inset 0 1px #fff3}.btn-secondary{border-radius:.5rem;padding:.625rem 1.25rem;font-weight:500;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;background:var(--color-elevated);color:var(--color-text-primary);border:1px solid var(--color-border)}.btn-secondary:hover{background:var(--color-border);border-color:var(--color-border-bright)}.btn-danger{border-radius:.5rem;padding:.625rem 1.25rem;font-weight:600;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;background:linear-gradient(135deg,var(--color-rose) 0%,#e91e63 100%);color:#fff;box-shadow:0 0 20px var(--color-rose-dim)}.btn-danger:hover{transform:translateY(-1px);box-shadow:0 0 30px var(--color-rose-dim),0 4px 12px #0006}.card{background:var(--color-surface);border:1px solid var(--color-border);border-radius:12px;padding:1.25rem;position:relative;overflow:hidden}.card:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,var(--color-border-bright),transparent)}.card-panel{background:var(--color-deep);border:1px solid var(--color-border);border-radius:16px;position:relative;overflow:hidden}.card-panel:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(180deg,rgba(255,255,255,.02) 0%,transparent 100%),repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(255,255,255,.01) 2px,rgba(255,255,255,.01) 4px);pointer-events:none}.status-dot{height:.625rem;width:.625rem;border-radius:9999px}.status-dot-running{background:var(--color-emerald);box-shadow:0 0 8px var(--color-emerald);animation:status-pulse 1.5s ease-in-out infinite}.status-dot-paused{background:var(--color-amber);box-shadow:0 0 8px var(--color-amber)}.status-dot-aborted{background:var(--color-rose);box-shadow:0 0 8px var(--color-rose)}.status-dot-completed{background:var(--color-emerald);box-shadow:0 0 6px var(--color-emerald-dim)}.badge{border-radius:.375rem;padding:.25rem .625rem;font-size:.75rem;line-height:1rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;font-family:JetBrains Mono,monospace}.badge-active{background:var(--color-cyan-dim);color:var(--color-cyan);border:1px solid var(--color-cyan)}.badge-running{background:var(--color-emerald-dim);color:var(--color-emerald);border:1px solid var(--color-emerald)}.badge-pending{background:var(--color-elevated);color:var(--color-text-muted);border:1px solid var(--color-border)}.badge-completed{background:#00ff881a;color:var(--color-emerald);border:1px solid rgba(0,255,136,.3)}.badge-aborted{background:var(--color-rose-dim);color:var(--color-rose);border:1px solid var(--color-rose)}.custom-scrollbar::-webkit-scrollbar{width:6px}.custom-scrollbar::-webkit-scrollbar-track{background:var(--color-deep);border-radius:3px}.custom-scrollbar::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:3px}.custom-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--color-border-bright)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.-left-2{left:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-6{bottom:1.5rem}.left-0{left:0}.right-0{right:0}.right-2{right:.5rem}.right-3{right:.75rem}.right-6{right:1.5rem}.top-0{top:0}.top-1\/2{top:50%}.top-2{top:.5rem}.top-3{top:.75rem}.top-full{top:100%}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.z-\[60\]{z-index:60}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-6{margin-left:1.5rem;margin-right:1.5rem}.mx-auto{margin-left:auto;margin-right:auto}.-mb-px{margin-bottom:-1px}.-mt-0\.5{margin-top:-.125rem}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-12{margin-left:3rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.ml-6{margin-left:1.5rem}.ml-7{margin-left:1.75rem}.ml-8{margin-left:2rem}.ml-auto{margin-left:auto}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.line-clamp-1{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline-block{display:inline-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-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-20{height:5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-60{height:15rem}.h-64{height:16rem}.h-8{height:2rem}.h-80{height:20rem}.h-\[300px\]{height:300px}.h-\[500px\]{height:500px}.h-\[600px\]{height:600px}.h-\[80vh\]{height:80vh}.h-\[calc\(100vh-220px\)\]{height:calc(100vh - 220px)}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0px}.max-h-48{max-height:12rem}.max-h-64{max-height:16rem}.max-h-96{max-height:24rem}.max-h-\[150px\]{max-height:150px}.max-h-\[2000px\]{max-height:2000px}.max-h-\[200px\]{max-height:200px}.max-h-\[3000px\]{max-height:3000px}.max-h-\[400px\]{max-height:400px}.max-h-\[500px\]{max-height:500px}.max-h-\[80vh\]{max-height:80vh}.max-h-\[90vh\]{max-height:90vh}.min-h-\[300px\]{min-height:300px}.min-h-\[400px\]{min-height:400px}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-1\/2{width:50%}.w-1\/3{width:33.333333%}.w-1\/4{width:25%}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-24{width:6rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-80{width:20rem}.w-96{width:24rem}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0px}.min-w-\[200px\]{min-width:200px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-\[80\%\]{max-width:80%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -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))}.rotate-180{--tw-rotate: 180deg;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))}.rotate-90{--tw-rotate: 90deg;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 bounce{0%,to{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}.animate-bounce{animation:bounce 1s infinite}@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-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.resize-y{resize:vertical}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.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))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.25rem * var(--tw-space-x-reverse));margin-left:calc(.25rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-1\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.375rem * var(--tw-space-x-reverse));margin-left:calc(.375rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.75rem * var(--tw-space-x-reverse));margin-left:calc(.75rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-6>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1.5rem * var(--tw-space-x-reverse));margin-left:calc(1.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(2rem * var(--tw-space-x-reverse));margin-left:calc(2rem * calc(1 - var(--tw-space-x-reverse)))}.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-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-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-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-700>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(55 65 81 / var(--tw-divide-opacity, 1))}.self-center{align-self:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-b-lg{border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.rounded-b-xl{border-bottom-right-radius:.75rem;border-bottom-left-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-4{border-width:4px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-\[var\(--color-border\)\]{border-color:var(--color-border)}.border-\[var\(--color-border-bright\)\]{border-color:var(--color-border-bright)}.border-\[var\(--color-cyan\)\]{border-color:var(--color-cyan)}.border-amber-500\/20{border-color:#f59e0b33}.border-amber-500\/30{border-color:#f59e0b4d}.border-amber-600{--tw-border-opacity: 1;border-color:rgb(217 119 6 / var(--tw-border-opacity, 1))}.border-amber-800\/50{border-color:#92400e80}.border-blue-500\/30{border-color:#3b82f64d}.border-blue-500\/50{border-color:#3b82f680}.border-blue-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.border-blue-800\/50{border-color:#1e40af80}.border-cyan-400{--tw-border-opacity: 1;border-color:rgb(34 211 238 / var(--tw-border-opacity, 1))}.border-cyan-500{--tw-border-opacity: 1;border-color:rgb(6 182 212 / var(--tw-border-opacity, 1))}.border-cyan-500\/20{border-color:#06b6d433}.border-cyan-500\/30{border-color:#06b6d44d}.border-cyan-500\/50{border-color:#06b6d480}.border-cyan-600{--tw-border-opacity: 1;border-color:rgb(8 145 178 / var(--tw-border-opacity, 1))}.border-emerald-500\/20{border-color:#10b98133}.border-emerald-500\/30{border-color:#10b9814d}.border-emerald-500\/50{border-color:#10b98180}.border-emerald-600{--tw-border-opacity: 1;border-color:rgb(5 150 105 / var(--tw-border-opacity, 1))}.border-emerald-700\/50{border-color:#04785780}.border-gray-500{--tw-border-opacity: 1;border-color:rgb(107 114 128 / var(--tw-border-opacity, 1))}.border-gray-500\/30{border-color:#6b72804d}.border-gray-600{--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.border-gray-600\/50{border-color:#4b556380}.border-gray-700{--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.border-gray-700\/30{border-color:#3741514d}.border-gray-700\/50{border-color:#37415180}.border-gray-800{--tw-border-opacity: 1;border-color:rgb(31 41 55 / var(--tw-border-opacity, 1))}.border-gray-800\/50{border-color:#1f293780}.border-gray-900{--tw-border-opacity: 1;border-color:rgb(17 24 39 / var(--tw-border-opacity, 1))}.border-green-500{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.border-green-700{--tw-border-opacity: 1;border-color:rgb(21 128 61 / var(--tw-border-opacity, 1))}.border-green-800{--tw-border-opacity: 1;border-color:rgb(22 101 52 / var(--tw-border-opacity, 1))}.border-green-800\/50{border-color:#16653480}.border-orange-800\/50{border-color:#9a341280}.border-primary-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-primary-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.border-primary-800\/50{border-color:#1e40af80}.border-purple-500\/30{border-color:#a855f74d}.border-red-500\/20{border-color:#ef444433}.border-red-600{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity, 1))}.border-red-700{--tw-border-opacity: 1;border-color:rgb(185 28 28 / var(--tw-border-opacity, 1))}.border-red-800{--tw-border-opacity: 1;border-color:rgb(153 27 27 / var(--tw-border-opacity, 1))}.border-red-800\/50{border-color:#991b1b80}.border-red-900\/30{border-color:#7f1d1d4d}.border-red-900\/50{border-color:#7f1d1d80}.border-rose-500\/30{border-color:#f43f5e4d}.border-transparent{border-color:transparent}.border-violet-500\/20{border-color:#8b5cf633}.border-violet-500\/30{border-color:#8b5cf64d}.border-violet-600{--tw-border-opacity: 1;border-color:rgb(124 58 237 / var(--tw-border-opacity, 1))}.border-violet-700\/50{border-color:#6d28d980}.border-yellow-500{--tw-border-opacity: 1;border-color:rgb(234 179 8 / var(--tw-border-opacity, 1))}.border-yellow-700{--tw-border-opacity: 1;border-color:rgb(161 98 7 / var(--tw-border-opacity, 1))}.border-yellow-700\/50{border-color:#a1620780}.border-yellow-800{--tw-border-opacity: 1;border-color:rgb(133 77 14 / var(--tw-border-opacity, 1))}.border-yellow-800\/50{border-color:#854d0e80}.border-t-transparent{border-top-color:transparent}.bg-\[\#1a1d23\]{--tw-bg-opacity: 1;background-color:rgb(26 29 35 / var(--tw-bg-opacity, 1))}.bg-\[var\(--color-amber\)\]{background-color:var(--color-amber)}.bg-\[var\(--color-base\)\]{background-color:var(--color-base)}.bg-\[var\(--color-border\)\]{background-color:var(--color-border)}.bg-\[var\(--color-cyan\)\]{background-color:var(--color-cyan)}.bg-\[var\(--color-deep\)\]{background-color:var(--color-deep)}.bg-\[var\(--color-elevated\)\]{background-color:var(--color-elevated)}.bg-\[var\(--color-emerald\)\]{background-color:var(--color-emerald)}.bg-\[var\(--color-rose\)\]{background-color:var(--color-rose)}.bg-\[var\(--color-slate\)\]{background-color:var(--color-slate)}.bg-\[var\(--color-surface\)\]{background-color:var(--color-surface)}.bg-\[var\(--color-void\)\]{background-color:var(--color-void)}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / 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\/10{background-color:#f59e0b1a}.bg-amber-500\/20{background-color:#f59e0b33}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-amber-900\/20{background-color:#78350f33}.bg-amber-900\/30{background-color:#78350f4d}.bg-amber-900\/50{background-color:#78350f80}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\/50{background-color:#00000080}.bg-black\/60{background-color:#0009}.bg-black\/70{background-color:#000000b3}.bg-blue-400{--tw-bg-opacity: 1;background-color:rgb(96 165 250 / var(--tw-bg-opacity, 1))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-500\/10{background-color:#3b82f61a}.bg-blue-500\/20{background-color:#3b82f633}.bg-blue-500\/50{background-color:#3b82f680}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-blue-600\/20{background-color:#2563eb33}.bg-blue-600\/30{background-color:#2563eb4d}.bg-blue-900{--tw-bg-opacity: 1;background-color:rgb(30 58 138 / var(--tw-bg-opacity, 1))}.bg-blue-900\/20{background-color:#1e3a8a33}.bg-blue-900\/30{background-color:#1e3a8a4d}.bg-blue-900\/50{background-color:#1e3a8a80}.bg-cyan-400{--tw-bg-opacity: 1;background-color:rgb(34 211 238 / 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\/20{background-color:#06b6d433}.bg-cyan-500\/5{background-color:#06b6d40d}.bg-cyan-600{--tw-bg-opacity: 1;background-color:rgb(8 145 178 / var(--tw-bg-opacity, 1))}.bg-cyan-600\/20{background-color:#0891b233}.bg-cyan-900\/30{background-color:#164e634d}.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\/10{background-color:#10b9811a}.bg-emerald-500\/20{background-color:#10b98133}.bg-emerald-500\/5{background-color:#10b9810d}.bg-emerald-900\/30{background-color:#064e3b4d}.bg-emerald-900\/50{background-color:#064e3b80}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.bg-gray-500{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.bg-gray-500\/10{background-color:#6b72801a}.bg-gray-500\/20{background-color:#6b728033}.bg-gray-600{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.bg-gray-600\/20{background-color:#4b556333}.bg-gray-600\/30{background-color:#4b55634d}.bg-gray-700{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.bg-gray-700\/30{background-color:#3741514d}.bg-gray-700\/50{background-color:#37415180}.bg-gray-800{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.bg-gray-800\/20{background-color:#1f293733}.bg-gray-800\/30{background-color:#1f29374d}.bg-gray-800\/50{background-color:#1f293780}.bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.bg-gray-900\/30{background-color:#1118274d}.bg-gray-900\/50{background-color:#11182780}.bg-gray-900\/70{background-color:#111827b3}.bg-gray-950{--tw-bg-opacity: 1;background-color:rgb(3 7 18 / var(--tw-bg-opacity, 1))}.bg-green-400{--tw-bg-opacity: 1;background-color:rgb(74 222 128 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-500\/20{background-color:#22c55e33}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.bg-green-600\/20{background-color:#16a34a33}.bg-green-700{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.bg-green-800{--tw-bg-opacity: 1;background-color:rgb(22 101 52 / var(--tw-bg-opacity, 1))}.bg-green-900{--tw-bg-opacity: 1;background-color:rgb(20 83 45 / var(--tw-bg-opacity, 1))}.bg-green-900\/20{background-color:#14532d33}.bg-green-900\/30{background-color:#14532d4d}.bg-green-900\/90{background-color:#14532de6}.bg-indigo-900{--tw-bg-opacity: 1;background-color:rgb(49 46 129 / var(--tw-bg-opacity, 1))}.bg-indigo-900\/50{background-color:#312e8180}.bg-orange-500\/20{background-color:#f9731633}.bg-orange-600{--tw-bg-opacity: 1;background-color:rgb(234 88 12 / var(--tw-bg-opacity, 1))}.bg-orange-600\/30{background-color:#ea580c4d}.bg-orange-900\/10{background-color:#7c2d121a}.bg-orange-900\/50{background-color:#7c2d1280}.bg-primary-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-primary-500\/20{background-color:#3b82f633}.bg-primary-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-primary-600\/20{background-color:#2563eb33}.bg-primary-600\/30{background-color:#2563eb4d}.bg-primary-900{--tw-bg-opacity: 1;background-color:rgb(30 58 138 / var(--tw-bg-opacity, 1))}.bg-primary-900\/20{background-color:#1e3a8a33}.bg-primary-900\/30{background-color:#1e3a8a4d}.bg-purple-500\/10{background-color:#a855f71a}.bg-purple-500\/20{background-color:#a855f733}.bg-purple-600{--tw-bg-opacity: 1;background-color:rgb(147 51 234 / var(--tw-bg-opacity, 1))}.bg-purple-600\/20{background-color:#9333ea33}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-red-500\/10{background-color:#ef44441a}.bg-red-500\/20{background-color:#ef444433}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-red-600\/20{background-color:#dc262633}.bg-red-600\/80{background-color:#dc2626cc}.bg-red-700{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.bg-red-800{--tw-bg-opacity: 1;background-color:rgb(153 27 27 / var(--tw-bg-opacity, 1))}.bg-red-900{--tw-bg-opacity: 1;background-color:rgb(127 29 29 / var(--tw-bg-opacity, 1))}.bg-red-900\/20{background-color:#7f1d1d33}.bg-red-900\/30{background-color:#7f1d1d4d}.bg-red-900\/50{background-color:#7f1d1d80}.bg-red-900\/90{background-color:#7f1d1de6}.bg-rose-500\/10{background-color:#f43f5e1a}.bg-transparent{background-color:transparent}.bg-violet-500\/10{background-color:#8b5cf61a}.bg-violet-500\/20{background-color:#8b5cf633}.bg-violet-900\/30{background-color:#4c1d954d}.bg-violet-900\/50{background-color:#4c1d9580}.bg-yellow-400{--tw-bg-opacity: 1;background-color:rgb(250 204 21 / 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\/10{background-color:#eab3081a}.bg-yellow-500\/20{background-color:#eab30833}.bg-yellow-600{--tw-bg-opacity: 1;background-color:rgb(202 138 4 / var(--tw-bg-opacity, 1))}.bg-yellow-600\/30{background-color:#ca8a044d}.bg-yellow-800{--tw-bg-opacity: 1;background-color:rgb(133 77 14 / var(--tw-bg-opacity, 1))}.bg-yellow-800\/50{background-color:#854d0e80}.bg-yellow-900{--tw-bg-opacity: 1;background-color:rgb(113 63 18 / var(--tw-bg-opacity, 1))}.bg-yellow-900\/10{background-color:#713f121a}.bg-yellow-900\/20{background-color:#713f1233}.bg-yellow-900\/30{background-color:#713f124d}.bg-yellow-900\/50{background-color:#713f1280}.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-\[var\(--color-cyan\)\]{--tw-gradient-from: var(--color-cyan) var(--tw-gradient-from-position);--tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-amber-500{--tw-gradient-from: #f59e0b var(--tw-gradient-from-position);--tw-gradient-to: rgb(245 158 11 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-cyan-500{--tw-gradient-from: #06b6d4 var(--tw-gradient-from-position);--tw-gradient-to: rgb(6 182 212 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-emerald-500{--tw-gradient-from: #10b981 var(--tw-gradient-from-position);--tw-gradient-to: rgb(16 185 129 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-gray-800{--tw-gradient-from: #1f2937 var(--tw-gradient-from-position);--tw-gradient-to: rgb(31 41 55 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-gray-900\/50{--tw-gradient-from: rgb(17 24 39 / .5) var(--tw-gradient-from-position);--tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-green-500{--tw-gradient-from: #22c55e var(--tw-gradient-from-position);--tw-gradient-to: rgb(34 197 94 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-primary-600{--tw-gradient-from: #2563eb var(--tw-gradient-from-position);--tw-gradient-to: rgb(37 99 235 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-primary-900\/30{--tw-gradient-from: rgb(30 58 138 / .3) var(--tw-gradient-from-position);--tw-gradient-to: rgb(30 58 138 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-rose-500{--tw-gradient-from: #f43f5e var(--tw-gradient-from-position);--tw-gradient-to: rgb(244 63 94 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-\[var\(--color-emerald\)\]{--tw-gradient-to: var(--color-emerald) var(--tw-gradient-to-position)}.to-amber-400{--tw-gradient-to: #fbbf24 var(--tw-gradient-to-position)}.to-emerald-400{--tw-gradient-to: #34d399 var(--tw-gradient-to-position)}.to-emerald-500{--tw-gradient-to: #10b981 var(--tw-gradient-to-position)}.to-gray-900{--tw-gradient-to: #111827 var(--tw-gradient-to-position)}.to-green-400{--tw-gradient-to: #4ade80 var(--tw-gradient-to-position)}.to-green-500{--tw-gradient-to: #22c55e var(--tw-gradient-to-position)}.to-primary-400{--tw-gradient-to: #60a5fa var(--tw-gradient-to-position)}.to-purple-900\/30{--tw-gradient-to: rgb(88 28 135 / .3) var(--tw-gradient-to-position)}.to-rose-400{--tw-gradient-to: #fb7185 var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to: transparent var(--tw-gradient-to-position)}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.\!py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.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-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-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pb-px{padding-bottom:1px}.pl-11{padding-left:2.75rem}.pl-4{padding-left:1rem}.pl-6{padding-left:1.5rem}.pl-8{padding-left:2rem}.pr-2{padding-right:.5rem}.pr-4{padding-right:1rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-base{font-size:1rem;line-height:1.5rem}.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-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-\[var\(--color-amber\)\]{color:var(--color-amber)}.text-\[var\(--color-border\)\]{color:var(--color-border)}.text-\[var\(--color-cyan\)\]{color:var(--color-cyan)}.text-\[var\(--color-emerald\)\]{color:var(--color-emerald)}.text-\[var\(--color-rose\)\]{color:var(--color-rose)}.text-\[var\(--color-text-muted\)\]{color:var(--color-text-muted)}.text-\[var\(--color-text-primary\)\]{color:var(--color-text-primary)}.text-\[var\(--color-text-secondary\)\]{color:var(--color-text-secondary)}.text-\[var\(--color-violet\)\]{color:var(--color-violet)}.text-amber-100{--tw-text-opacity: 1;color:rgb(254 243 199 / var(--tw-text-opacity, 1))}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-amber-400\/80{color:#fbbf24cc}.text-blue-100{--tw-text-opacity: 1;color:rgb(219 234 254 / var(--tw-text-opacity, 1))}.text-blue-300{--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-cyan-300{--tw-text-opacity: 1;color:rgb(103 232 249 / 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-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-green-100{--tw-text-opacity: 1;color:rgb(220 252 231 / var(--tw-text-opacity, 1))}.text-green-200{--tw-text-opacity: 1;color:rgb(187 247 208 / var(--tw-text-opacity, 1))}.text-green-300{--tw-text-opacity: 1;color:rgb(134 239 172 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-indigo-300{--tw-text-opacity: 1;color:rgb(165 180 252 / var(--tw-text-opacity, 1))}.text-orange-300{--tw-text-opacity: 1;color:rgb(253 186 116 / var(--tw-text-opacity, 1))}.text-orange-400{--tw-text-opacity: 1;color:rgb(251 146 60 / var(--tw-text-opacity, 1))}.text-primary-100{--tw-text-opacity: 1;color:rgb(219 234 254 / var(--tw-text-opacity, 1))}.text-primary-200{--tw-text-opacity: 1;color:rgb(191 219 254 / var(--tw-text-opacity, 1))}.text-primary-300{--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.text-primary-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-primary-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-primary-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-purple-400{--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-red-100{--tw-text-opacity: 1;color:rgb(254 226 226 / var(--tw-text-opacity, 1))}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-rose-300{--tw-text-opacity: 1;color:rgb(253 164 175 / var(--tw-text-opacity, 1))}.text-rose-400{--tw-text-opacity: 1;color:rgb(251 113 133 / var(--tw-text-opacity, 1))}.text-violet-400{--tw-text-opacity: 1;color:rgb(167 139 250 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-100{--tw-text-opacity: 1;color:rgb(254 249 195 / var(--tw-text-opacity, 1))}.text-yellow-200{--tw-text-opacity: 1;color:rgb(254 240 138 / var(--tw-text-opacity, 1))}.text-yellow-300{--tw-text-opacity: 1;color:rgb(253 224 71 / var(--tw-text-opacity, 1))}.text-yellow-300\/80{color:#fde047cc}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.placeholder-\[var\(--color-text-muted\)\]::-moz-placeholder{color:var(--color-text-muted)}.placeholder-\[var\(--color-text-muted\)\]::placeholder{color:var(--color-text-muted)}.placeholder-gray-400::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.placeholder-gray-400::placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(107 114 128 / var(--tw-placeholder-opacity, 1))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity: 1;color:rgb(107 114 128 / var(--tw-placeholder-opacity, 1))}.placeholder-gray-600::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(75 85 99 / var(--tw-placeholder-opacity, 1))}.placeholder-gray-600::placeholder{--tw-placeholder-opacity: 1;color:rgb(75 85 99 / var(--tw-placeholder-opacity, 1))}.accent-blue-500,.accent-primary-500{accent-color:#3b82f6}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-75{opacity:.75}.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_15px_var\(--color-cyan-dim\)\]{--tw-shadow: 0 0 15px var(--color-cyan-dim);--tw-shadow-colored: 0 0 15px 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_var\(--color-emerald\)\]{--tw-shadow: 0 0 8px var(--color-emerald);--tw-shadow-colored: 0 0 8px 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-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 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-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-blue-500\/10{--tw-shadow-color: rgb(59 130 246 / .1);--tw-shadow: var(--tw-shadow-colored)}.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-offset-1{--tw-ring-offset-width: 1px}.ring-offset-\[var\(--color-surface\)\]{--tw-ring-offset-color: var(--color-surface)}.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-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-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}:root{--color-void: #0a0c10;--color-deep: #0d1117;--color-surface: #161b22;--color-elevated: #21262d;--color-border: #30363d;--color-border-bright: #484f58;--color-cyan: #00d9ff;--color-cyan-dim: #00d9ff40;--color-cyan-glow: #00d9ff20;--color-emerald: #00ff88;--color-emerald-dim: #00ff8840;--color-amber: #ffb800;--color-amber-dim: #ffb80040;--color-rose: #ff3366;--color-rose-dim: #ff336640;--color-violet: #a855f7;--color-violet-dim: #a855f740;--color-text-primary: #e6edf3;--color-text-secondary: #8b949e;--color-text-muted: #6e7681;font-family:DM Sans,system-ui,sans-serif;line-height:1.5;font-weight:400;color-scheme:dark;color:var(--color-text-primary);background-color:var(--color-void);font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{margin:0;min-width:320px;min-height:100vh;background:radial-gradient(ellipse at 20% 0%,var(--color-cyan-glow) 0%,transparent 50%),radial-gradient(ellipse at 80% 100%,var(--color-violet-dim) 0%,transparent 50%),var(--color-void)}.font-mono{font-family:JetBrains Mono,monospace}.font-display{font-family:DM Sans,sans-serif;font-weight:700;letter-spacing:-.02em}@keyframes pulse-glow{0%,to{box-shadow:0 0 0 0 var(--glow-color, var(--color-cyan-dim));opacity:1}50%{box-shadow:0 0 20px 4px var(--glow-color, var(--color-cyan-dim));opacity:.8}}@keyframes scan-line{0%{transform:translateY(-100%)}to{transform:translateY(100vh)}}@keyframes terminal-blink{0%,to{opacity:1}50%{opacity:0}}@keyframes fade-in-up{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes status-pulse{0%,to{transform:scale(1)}50%{transform:scale(1.2)}}.animate-pulse-glow{animation:pulse-glow 2s ease-in-out infinite}.animate-terminal-blink{animation:terminal-blink 1s step-end infinite}.animate-fade-in-up{animation:fade-in-up .3s ease-out forwards}.animate-status-pulse{animation:status-pulse 1.5s ease-in-out infinite}.stagger-1{animation-delay:.05s}.stagger-2{animation-delay:.1s}.stagger-3{animation-delay:.15s}.stagger-4{animation-delay:.2s}.stagger-5{animation-delay:.25s}.last\:mb-0:last-child{margin-bottom:0}.last\:border-b-0:last-child{border-bottom-width:0px}.hover\:border-\[var\(--color-border-bright\)\]:hover{border-color:var(--color-border-bright)}.hover\:border-\[var\(--color-border-hover\)\]:hover{border-color:var(--color-border-hover)}.hover\:border-amber-500\/40:hover{border-color:#f59e0b66}.hover\:border-cyan-500:hover{--tw-border-opacity: 1;border-color:rgb(6 182 212 / var(--tw-border-opacity, 1))}.hover\:border-cyan-500\/40:hover{border-color:#06b6d466}.hover\:border-cyan-500\/50:hover{border-color:#06b6d480}.hover\:border-emerald-500\/40:hover{border-color:#10b98166}.hover\:border-gray-500:hover{--tw-border-opacity: 1;border-color:rgb(107 114 128 / var(--tw-border-opacity, 1))}.hover\:border-gray-600:hover{--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.hover\:border-primary-500:hover{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.hover\:border-primary-600:hover{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.hover\:border-violet-500\/40:hover{border-color:#8b5cf666}.hover\:border-violet-500\/50:hover{border-color:#8b5cf680}.hover\:bg-\[var\(--color-border\)\]:hover{background-color:var(--color-border)}.hover\:bg-\[var\(--color-border-hover\)\]:hover{background-color:var(--color-border-hover)}.hover\:bg-\[var\(--color-elevated\)\]:hover{background-color:var(--color-elevated)}.hover\:bg-\[var\(--color-surface\)\]:hover{background-color:var(--color-surface)}.hover\:bg-blue-500:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-600\/30:hover{background-color:#2563eb4d}.hover\:bg-cyan-500:hover{--tw-bg-opacity: 1;background-color:rgb(6 182 212 / var(--tw-bg-opacity, 1))}.hover\:bg-cyan-500\/10:hover{background-color:#06b6d41a}.hover\:bg-cyan-600:hover{--tw-bg-opacity: 1;background-color:rgb(8 145 178 / var(--tw-bg-opacity, 1))}.hover\:bg-cyan-600\/30:hover{background-color:#0891b24d}.hover\:bg-gray-500:hover{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-600:hover{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-600\/30:hover{background-color:#4b55634d}.hover\:bg-gray-600\/50:hover{background-color:#4b556380}.hover\:bg-gray-700:hover{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-700\/30:hover{background-color:#3741514d}.hover\:bg-gray-700\/50:hover{background-color:#37415180}.hover\:bg-gray-700\/70:hover{background-color:#374151b3}.hover\:bg-gray-800:hover{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-800\/30:hover{background-color:#1f29374d}.hover\:bg-gray-800\/50:hover{background-color:#1f293780}.hover\:bg-green-500:hover{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.hover\:bg-green-600\/30:hover{background-color:#16a34a4d}.hover\:bg-green-700:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.hover\:bg-orange-500:hover{--tw-bg-opacity: 1;background-color:rgb(249 115 22 / var(--tw-bg-opacity, 1))}.hover\:bg-primary-500:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.hover\:bg-primary-600\/30:hover{background-color:#2563eb4d}.hover\:bg-primary-900\/50:hover{background-color:#1e3a8a80}.hover\:bg-purple-600\/30:hover{background-color:#9333ea4d}.hover\:bg-red-500:hover{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.hover\:bg-red-600\/30:hover{background-color:#dc26264d}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:bg-red-800\/50:hover{background-color:#991b1b80}.hover\:bg-red-900\/30:hover{background-color:#7f1d1d4d}.hover\:bg-red-900\/50:hover{background-color:#7f1d1d80}.hover\:bg-yellow-500:hover{--tw-bg-opacity: 1;background-color:rgb(234 179 8 / var(--tw-bg-opacity, 1))}.hover\:bg-yellow-700:hover{--tw-bg-opacity: 1;background-color:rgb(161 98 7 / var(--tw-bg-opacity, 1))}.hover\:bg-yellow-800:hover{--tw-bg-opacity: 1;background-color:rgb(133 77 14 / var(--tw-bg-opacity, 1))}.hover\:text-\[var\(--color-text-primary\)\]:hover{color:var(--color-text-primary)}.hover\:text-\[var\(--color-text-secondary\)\]:hover{color:var(--color-text-secondary)}.hover\:text-blue-200:hover{--tw-text-opacity: 1;color:rgb(191 219 254 / var(--tw-text-opacity, 1))}.hover\:text-cyan-300:hover{--tw-text-opacity: 1;color:rgb(103 232 249 / var(--tw-text-opacity, 1))}.hover\:text-cyan-400:hover{--tw-text-opacity: 1;color:rgb(34 211 238 / var(--tw-text-opacity, 1))}.hover\:text-gray-200:hover{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.hover\:text-gray-300:hover{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.hover\:text-gray-400:hover{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.hover\:text-primary-300:hover{--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.hover\:text-primary-400:hover{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.hover\:text-red-200:hover{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.hover\:text-red-300:hover{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:text-yellow-200:hover{--tw-text-opacity: 1;color:rgb(254 240 138 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:no-underline:hover{text-decoration-line:none}.focus\:border-amber-500:focus{--tw-border-opacity: 1;border-color:rgb(245 158 11 / var(--tw-border-opacity, 1))}.focus\:border-blue-500\/50:focus{border-color:#3b82f680}.focus\:border-cyan-500:focus{--tw-border-opacity: 1;border-color:rgb(6 182 212 / var(--tw-border-opacity, 1))}.focus\:border-primary-500:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.focus\:border-red-500:focus{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--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)}.focus\:ring-2:focus{--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)}.focus\:ring-blue-500\/30:focus{--tw-ring-color: rgb(59 130 246 / .3)}.focus\:ring-cyan-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(6 182 212 / var(--tw-ring-opacity, 1))}.focus\:ring-cyan-500\/50:focus{--tw-ring-color: rgb(6 182 212 / .5)}.focus\:ring-primary-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.focus\:ring-opacity-50:focus{--tw-ring-opacity: .5}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.focus\:ring-offset-gray-800:focus{--tw-ring-offset-color: #1f2937}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-20:disabled{opacity:.2}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:hover\:bg-primary-600:hover:disabled{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.disabled\:hover\:bg-red-600:hover:disabled{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.group[open] .group-open\:rotate-180{--tw-rotate: 180deg;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))}.group:hover .group-hover\:bg-gray-600{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.group:hover .group-hover\:text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:text-primary-300{--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:text-primary-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:opacity-100{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))}.sm\:gap-4{gap:1rem}}@media(min-width:768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}}@media(min-width:1024px){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}
|