@gravito/zenith 1.0.1 โ†’ 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/ECOSYSTEM_EXPANSION_RFC.md +130 -0
  3. package/dist/bin.js +11945 -4241
  4. package/dist/client/assets/index-BSMp8oq_.js +436 -0
  5. package/dist/client/assets/index-BwxlHx-_.css +1 -0
  6. package/dist/client/index.html +2 -2
  7. package/dist/server/index.js +11945 -4241
  8. package/package.json +1 -1
  9. package/scripts/verify-throttle.ts +6 -2
  10. package/scripts/worker.ts +2 -1
  11. package/src/client/Layout.tsx +10 -0
  12. package/src/client/Sidebar.tsx +9 -0
  13. package/src/client/ThroughputChart.tsx +9 -0
  14. package/src/client/WorkerStatus.tsx +14 -3
  15. package/src/client/components/BrandIcons.tsx +30 -0
  16. package/src/client/components/ConfirmDialog.tsx +24 -0
  17. package/src/client/components/JobInspector.tsx +18 -0
  18. package/src/client/components/LogArchiveModal.tsx +51 -2
  19. package/src/client/components/NotificationBell.tsx +9 -0
  20. package/src/client/components/PageHeader.tsx +9 -0
  21. package/src/client/components/Toaster.tsx +10 -0
  22. package/src/client/components/UserProfileDropdown.tsx +9 -0
  23. package/src/client/contexts/AuthContext.tsx +12 -0
  24. package/src/client/contexts/NotificationContext.tsx +25 -0
  25. package/src/client/pages/LoginPage.tsx +9 -0
  26. package/src/client/pages/MetricsPage.tsx +9 -0
  27. package/src/client/pages/OverviewPage.tsx +9 -0
  28. package/src/client/pages/PulsePage.tsx +10 -0
  29. package/src/client/pages/QueuesPage.tsx +9 -0
  30. package/src/client/pages/SchedulesPage.tsx +9 -0
  31. package/src/client/pages/SettingsPage.tsx +9 -0
  32. package/src/client/pages/WorkersPage.tsx +10 -0
  33. package/src/client/utils.ts +9 -0
  34. package/src/server/config/ServerConfigManager.ts +87 -0
  35. package/src/server/index.ts +19 -18
  36. package/src/server/services/AlertService.ts +16 -3
  37. package/src/server/services/LogStreamProcessor.ts +93 -0
  38. package/src/server/services/MaintenanceScheduler.ts +78 -0
  39. package/src/server/services/PulseService.ts +12 -1
  40. package/src/server/services/QueueMetricsCollector.ts +138 -0
  41. package/src/server/services/QueueService.ts +29 -283
  42. package/src/shared/types.ts +126 -27
  43. package/vite.config.ts +1 -1
  44. package/DEMO.md +0 -156
  45. package/dist/client/assets/index-C332gZ-J.css +0 -1
  46. package/dist/client/assets/index-D4HibwTK.js +0 -436
@@ -1,76 +1,151 @@
1
+ /**
2
+ * Metrics representing CPU usage for a specific node/process.
3
+ *
4
+ * @public
5
+ * @since 3.0.0
6
+ */
1
7
  export interface PulseCpu {
2
- system: number // Percentage 0-100
3
- process: number // Percentage 0-100
8
+ /** System-wide CPU usage percentage (0-100). */
9
+ system: number
10
+ /** Process-specific CPU usage percentage (0-100). */
11
+ process: number
12
+ /** Number of CPU cores available. */
4
13
  cores: number
5
14
  }
6
15
 
16
+ /**
17
+ * Metrics representing memory usage for a specific node/process.
18
+ *
19
+ * @public
20
+ * @since 3.0.0
21
+ */
7
22
  export interface PulseMemory {
23
+ /** System-wide memory statistics. */
8
24
  system: {
9
- total: number // bytes
10
- free: number // bytes
11
- used: number // bytes
25
+ /** Total system memory in bytes. */
26
+ total: number
27
+ /** Free system memory in bytes. */
28
+ free: number
29
+ /** Used system memory in bytes. */
30
+ used: number
12
31
  }
32
+ /** Process-specific memory statistics. */
13
33
  process: {
14
- rss: number // bytes
15
- heapTotal: number // bytes
16
- heapUsed: number // bytes
34
+ /** Resident Set Size (RSS) in bytes. */
35
+ rss: number
36
+ /** Total allocated heap size in bytes. */
37
+ heapTotal: number
38
+ /** Used heap size in bytes. */
39
+ heapUsed: number
17
40
  }
18
41
  }
19
42
 
43
+ /**
44
+ * Runtime metadata for a monitored process.
45
+ *
46
+ * @public
47
+ * @since 3.0.0
48
+ */
20
49
  export interface PulseRuntime {
21
- uptime: number // seconds
22
- framework: string // e.g. "Node 20.1", "Laravel 10.0"
50
+ /** Uptime in seconds. */
51
+ uptime: number
52
+ /** Framework or runtime identification (e.g., "Node 21.4"). */
53
+ framework: string
54
+ /** Current process status (e.g., 'online', 'maintenance'). */
23
55
  status?: string
56
+ /** Last few error messages from the process. */
24
57
  errors?: string[]
25
58
  }
26
59
 
60
+ /**
61
+ * Statistics snapshot for a specific queue.
62
+ *
63
+ * @public
64
+ * @since 3.0.0
65
+ */
27
66
  export interface QueueSnapshot {
67
+ /** The name of the queue. */
28
68
  name: string
69
+ /** The driver used (redis, sqs, etc.). */
29
70
  driver: 'redis' | 'sqs' | 'rabbitmq'
71
+ /** Current counts of jobs in different states. */
30
72
  size: {
31
73
  waiting: number
32
74
  active: number
33
75
  failed: number
34
76
  delayed: number
35
77
  }
78
+ /** Historical throughput data. */
36
79
  throughput?: {
37
- in: number // jobs/min
38
- out: number // jobs/min
80
+ in: number
81
+ out: number
39
82
  }
40
83
  }
41
84
 
85
+ /**
86
+ * Represents a single application instance (node) monitored by Zenith.
87
+ *
88
+ * @public
89
+ * @since 3.0.0
90
+ */
42
91
  export interface PulseNode {
43
- id: string // Unique Instance ID
44
- service: string // Group name
92
+ /** Unique execution ID for the node. */
93
+ id: string
94
+ /** Service group name. */
95
+ service: string
96
+ /** Programming language or runtime type. */
45
97
  language: 'node' | 'bun' | 'deno' | 'php' | 'go' | 'python' | 'other'
46
- version: string // App Version
98
+ /** Application version. */
99
+ version: string
100
+ /** Process identifier. */
47
101
  pid: number
102
+ /** Hostname of the machine. */
48
103
  hostname: string
104
+ /** Operating system platform. */
49
105
  platform: string
106
+ /** CPU metrics. */
50
107
  cpu: PulseCpu
108
+ /** Memory metrics. */
51
109
  memory: PulseMemory
110
+ /** Optional list of queues managed by this node. */
52
111
  queues?: QueueSnapshot[]
112
+ /** Runtime details. */
53
113
  runtime: PulseRuntime
54
- meta?: any // Extra metadata like Laravel workers
55
- timestamp: number // Last heartbeat
114
+ /** Unstructured metadata (e.g., framework-specific details). */
115
+ meta?: any
116
+ /** Epoch timestamp of the last heartbeat. */
117
+ timestamp: number
56
118
  }
119
+
120
+ /**
121
+ * Definition of an alert rule for monitoring health.
122
+ *
123
+ * @public
124
+ * @since 3.0.0
125
+ */
57
126
  export interface AlertRule {
127
+ /** Unique rule ID. */
58
128
  id: string
129
+ /** Human-readable name. */
59
130
  name: string
131
+ /** The metric type to monitor. */
60
132
  type: 'backlog' | 'failure' | 'worker_lost' | 'node_cpu' | 'node_ram'
133
+ /** The value that triggers the alert. */
61
134
  threshold: number
62
- queue?: string // Optional: specific queue or all
135
+ /** Optional queue name (if applicable). */
136
+ queue?: string
137
+ /** Minutes to wait before re-triggering the alert. */
63
138
  cooldownMinutes: number
64
139
  }
65
140
 
66
- export interface AlertEvent {
67
- ruleId: string
68
- timestamp: number
69
- message: string
70
- severity: 'warning' | 'critical'
71
- }
72
-
141
+ /**
142
+ * Configuration for alert notification channels.
143
+ *
144
+ * @public
145
+ * @since 3.0.0
146
+ */
73
147
  export interface AlertConfig {
148
+ /** Map of enabled notification channels. */
74
149
  channels: {
75
150
  slack?: {
76
151
  enabled: boolean
@@ -87,13 +162,37 @@ export interface AlertConfig {
87
162
  smtpUser: string
88
163
  smtpPass: string
89
164
  from: string
90
- to: string // Comma separated list
165
+ to: string
91
166
  }
92
167
  }
93
168
  }
94
169
 
170
+ /**
171
+ * Configuration for automated system maintenance.
172
+ *
173
+ * @public
174
+ * @since 3.0.0
175
+ */
95
176
  export interface MaintenanceConfig {
177
+ /** Whether to automatically delete old data. */
96
178
  autoCleanup: boolean
179
+ /** Number of days to retain records. */
97
180
  retentionDays: number
98
- lastRun?: number // Timestamp
181
+ /** Timestamp of the last maintenance run. */
182
+ lastRun?: number
183
+ }
184
+
185
+ /**
186
+ * Represents a historical alert event.
187
+ */
188
+ export interface AlertEvent {
189
+ id?: string
190
+ ruleId: string
191
+ ruleName?: string
192
+ type?: string
193
+ severity: 'critical' | 'warning' | 'info'
194
+ message: string
195
+ timestamp: number
196
+ resolved?: boolean
197
+ resolvedAt?: number
99
198
  }
package/vite.config.ts CHANGED
@@ -1,5 +1,5 @@
1
+ import { resolve } from 'node:path'
1
2
  import react from '@vitejs/plugin-react'
2
- import { resolve } from 'path'
3
3
  import { defineConfig } from 'vite'
4
4
 
5
5
  // https://vitejs.dev/config/
package/DEMO.md DELETED
@@ -1,156 +0,0 @@
1
- # ๐ŸŽฎ Flux Console - Live Demo Walkthrough
2
-
3
- This guide provides a step-by-step script for demonstrating the capabilities of **Flux Console**. It simulates a real-world production environment with traffic spikes, worker processing, and real-time monitoring.
4
-
5
- ## ๐Ÿ—๏ธ Architecture Setup
6
-
7
- In this demo, we will run three components locally:
8
- 1. **Redis**: The message broker (must be running on `localhost:6379`).
9
- 2. **Flux Console**: The monitoring dashboard.
10
- 3. **Demo Worker**: A simulated worker that processes jobs from queues (`orders`, `reports`, etc.).
11
- 4. **Traffic Generator**: A script to flood the queues with jobs.
12
-
13
- ---
14
-
15
- ## ๐Ÿ›๏ธ Persistence & History (Optional)
16
-
17
- To test the **Job Archive**, **Operational Logs**, and **Search** features, you need a database. Flux Console supports two modes:
18
-
19
- ### A. Zero-Config (SQLite) - **Recommended for Quick Tests**
20
- Simply set the `DB_DRIVER` and `DB_NAME` environment variables. It will create a local `.sqlite` file.
21
- ```bash
22
- export DB_DRIVER=sqlite
23
- export DB_NAME=flux.sqlite
24
- export PERSIST_ARCHIVE_COMPLETED=true # Archive successful jobs too
25
- ```
26
-
27
- ### B. Full Stack (MySQL + Redis) - **Using Docker**
28
- If you have Docker installed, you can spin up a production-ready environment:
29
- ```bash
30
- cd packages/flux-console
31
- docker-compose up -d
32
- ```
33
- Then set your env variables to match:
34
- ```bash
35
- export DB_HOST=localhost
36
- export DB_USER=root
37
- export DB_PASSWORD=root
38
- export DB_NAME=flux
39
- ```
40
-
41
- ---
42
-
43
- ## ๐ŸŽฌ Step-by-Step Demo Script
44
-
45
- ### Step 1: Start the Flux Console ๐Ÿ–ฅ๏ธ
46
-
47
- Open your first terminal window and launch the console. This starts both the web server and the SSE (Server-Sent Events) stream.
48
-
49
- ```bash
50
- cd packages/flux-console
51
- bun run start
52
- ```
53
-
54
- > **Verify**: Open [http://localhost:3000](http://localhost:3000) in your browser. You should see the dashboard. It might be empty or show "No Data" initially.
55
-
56
- ### Step 2: Start the Worker ๐Ÿ‘ท
57
-
58
- We need a worker to "eat" the jobs. Without this, jobs will just pile up in the queue.
59
- Open a **second terminal window**:
60
-
61
- ```bash
62
- cd packages/flux-console
63
- bun run scripts/demo-worker.ts
64
- ```
65
-
66
- > **Observe**:
67
- > - You should see `[Consumer] Started`.
68
- > - The console output will show it's watching queues: `orders`, `notifications`, `billing`, etc.
69
- > - **In the Browser**: Go to the **Workers** page. You should see `worker-xxxxx` appear as "Online". Note the **Cluster RAM** and **Load** metrics which reflect your actual machine's status.
70
-
71
- ### Step 3: Unleash the Traffic! ๐Ÿš€
72
-
73
- Now, let's simulate a traffic spike (e.g., Black Friday sale).
74
- Open a **third terminal window**:
75
-
76
- ```bash
77
- cd packages/flux-console
78
- bun run scripts/generate-random-traffic.ts
79
- ```
80
-
81
- This script will:
82
- - Push **50 jobs** randomly distributed to different queues.
83
- - Some jobs are designed to **fail** (to test error handling).
84
- - Some jobs are **delayed**.
85
-
86
- > **Pro Tip**: Run this command multiple times rapidly to simulate a higher load spike!
87
-
88
- ---
89
-
90
- ## ๐Ÿงช Understanding Test Job Behavior
91
-
92
- The demo worker uses a special `TestJob` class that simulates different real-world scenarios:
93
-
94
- ### Intentional Failures (DLQ Testing)
95
- Jobs with IDs containing `"fail"` (e.g., `job-fail-1767244949663-25`) are **designed to always throw an error**. This is intentional and serves to demonstrate:
96
-
97
- 1. **Retry Mechanism**: You'll see these jobs attempt multiple times (`Attempt: 1, 2, 3...`).
98
- 2. **Exponential Backoff**: Each retry waits longer than the previous one (2s, 6s, 18s...).
99
- 3. **Dead Letter Queue (DLQ)**: After max attempts (default: 3), the job moves to the **Failed** queue.
100
- 4. **Error Handling UI**: You can see these in the Console's "Failed" tab with full error stack traces.
101
-
102
- **This is expected behavior!** These jobs represent scenarios like:
103
- - Invalid order IDs
104
- - Malformed email addresses
105
- - External API permanently rejecting a request
106
-
107
- ### Normal Jobs
108
- Jobs without `"fail"` in their ID will:
109
- - Process successfully after a simulated 50ms delay
110
- - Update the throughput metrics
111
- - Disappear from the queue
112
-
113
- ### The `default` Queue
114
- When you click **"Retry All Failed"** in the Console, failed jobs are moved back to the queue. Due to how the retry mechanism works, they may be placed in the `default` queue instead of their original queue. This is why the worker monitors both specific queues (`orders`, `email`, etc.) **and** the `default` queue.
115
-
116
- ---
117
-
118
- ## ๐ŸŽฌ Step 4: The Showcase (What to show in the UI) โœจ
119
-
120
- Now, switch to the browser window and walk through these views:
121
-
122
- #### 1. ๐Ÿ“Š Dashboard (Overview)
123
- - **Throughput Chart**: You will see a sudden spike in the green line (Processed/min).
124
- - **Active Queues**: You'll see numbers jumping in `Waiting` and `Active` columns.
125
- - **Top Right Live Logs**: Watch the logs stream in real-time as the worker processes jobs.
126
- - **Log Search**: Click on **"Search Archive"** in the logs panel to open the historical log browser. This allows querying through millions of past events stored in SQL.
127
-
128
- #### 2. ๐Ÿงฑ Queues Page
129
- - Navigate to the **Queues** tab.
130
- - Click on `queue:orders` or `queue:email`.
131
- - **Action**: You can see jobs moving from **Waiting** to **Active**.
132
- - **Inspection**: Click the "Eye" icon (Inspector) on a queue to see the JSON payload of waiting jobs.
133
-
134
- #### 3. ๐Ÿšจ Retry Handling (The "Oh No!" Moment)
135
- - Go to the **Queues** page and look for the **Failed** tab (Red badge).
136
- - You should see jobs with an error like `Simulated permanent failure`.
137
- - **Action**: Click the "Retry All" button specifically for the failed jobs.
138
- - **Result**: Watch the "Failed" count drop to 0 and the "Waiting" count go up. The worker will pick them up again.
139
-
140
- #### 4. โš™๏ธ Workers Page
141
- - Refresh or stay on the **Workers** page.
142
- - Observe the **Avg Load** bar changing colors (Green -> Amber) depending on your CPU usage.
143
- - Explain that this demonstrates the **Real-time Health Monitoring** of the infrastructure.
144
-
145
- ---
146
-
147
- ## ๐Ÿงน Cleanup
148
-
149
- To reset the demo environment (purge all queues):
150
-
151
- ```bash
152
- # In the third terminal
153
- bun run scripts/debug-redis.ts
154
- # OR manually flush redis if you have redis-cli installed
155
- # redis-cli flushall
156
- ```
@@ -1 +0,0 @@
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: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}:root{--background: 0 0% 100%;--foreground: 224 71.4% 4.1%;--card: 0 0% 100%;--card-foreground: 224 71.4% 4.1%;--popover: 0 0% 100%;--popover-foreground: 224 71.4% 4.1%;--primary: 238.7 83.5% 66.7%;--primary-foreground: 210 20% 98%;--secondary: 220 14.3% 95.9%;--secondary-foreground: 238.7 83.5% 66.7%;--muted: 220 14.3% 95.9%;--muted-foreground: 220 8.9% 46.1%;--accent: 220 14.3% 95.9%;--accent-foreground: 238.7 83.5% 66.7%;--destructive: 0 84.2% 60.2%;--destructive-foreground: 210 20% 98%;--border: 220 13% 91%;--input: 220 13% 91%;--ring: 238.7 83.5% 66.7%;--radius: 1rem}.dark{--background: 222 47% 2%;--foreground: 213 31% 91%;--card: 222 47% 6%;--card-foreground: 213 31% 91%;--popover: 222 47% 4%;--popover-foreground: 213 31% 91%;--primary: 238.7 83.5% 66.7%;--primary-foreground: 222 47% 4%;--secondary: 222 47% 10%;--secondary-foreground: 213 31% 91%;--muted: 222 47% 8%;--muted-foreground: 215.4 16.3% 56.9%;--accent: 222 47% 12%;--accent-foreground: 213 31% 91%;--destructive: 0 62.8% 30.6%;--destructive-foreground: 210 20% 98%;--border: 222 47% 14%;--input: 222 47% 12%;--ring: 238.7 83.5% 66.7%}*{border-color:hsl(var(--border))}body{background-color:hsl(var(--background));color:hsl(var(--foreground));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-feature-settings:"ss01","ss02","cv01","cv02","cv03"}.dark body{background-image:radial-gradient(at 50% 0%,hsla(238,83%,66%,.05) 0%,transparent 50%),radial-gradient(at 100% 100%,hsla(238,83%,66%,.02) 0%,transparent 50%);background-attachment:fixed}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.-bottom-1{bottom:-.25rem}.-left-1\/4{left:-25%}.-right-1{right:-.25rem}.-right-1\/4{right:-25%}.bottom-0{bottom:0}.bottom-1\/4{bottom:25%}.bottom-8{bottom:2rem}.bottom-full{bottom:100%}.left-0{left:0}.left-1{left:.25rem}.left-1\/2{left:50%}.left-3{left:.75rem}.left-4{left:1rem}.right-0{right:0}.right-1\.5{right:.375rem}.right-2{right:.5rem}.right-4{right:1rem}.right-8{right:2rem}.top-0{top:0}.top-1\.5{top:.375rem}.top-1\/2{top:50%}.top-1\/4{top:25%}.top-4{top:1rem}.top-full{top:100%}.z-0{z-index:0}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.z-\[1001\]{z-index:1001}.z-\[1002\]{z-index:1002}.z-\[100\]{z-index:100}.z-\[2000\]{z-index:2000}.z-\[4000\]{z-index:4000}.z-\[5000\]{z-index:5000}.col-span-2{grid-column:span 2 / span 2}.col-span-full{grid-column:1 / -1}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mr-2{margin-right:.5rem}.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-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.aspect-square{aspect-ratio:1 / 1}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-20{height:5rem}.h-24{height:6rem}.h-3{height:.75rem}.h-32{height:8rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-96{height:24rem}.h-\[300px\]{height:300px}.h-\[350px\]{height:350px}.h-\[400px\]{height:400px}.h-\[85vh\]{height:85vh}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[400px\]{max-height:400px}.max-h-\[850px\]{max-height:850px}.min-h-0{min-height:0px}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-32{width:8rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-72{width:18rem}.w-8{width:2rem}.w-96{width:24rem}.w-\[1px\]{width:1px}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0px}.min-w-\[140px\]{min-width:140px}.min-w-\[16px\]{min-width:16px}.min-w-\[200px\]{min-width:200px}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-none{flex:none}.flex-shrink-0,.shrink-0{flex-shrink:0}.origin-left{transform-origin:left}.-translate-x-1{--tw-translate-x: -.25rem;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))}.-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))}.-translate-y-1{--tw-translate-y: -.25rem;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))}.-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))}.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))}.scale-110{--tw-scale-x: 1.1;--tw-scale-y: 1.1;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))}.scale-\[1\.02\]{--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))}.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 ping{75%,to{transform:scale(2);opacity:0}}.animate-ping{animation:ping 1s cubic-bezier(0,0,.2,1) 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-help{cursor:help}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-10{grid-template-columns:repeat(10,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}.items-baseline{align-items:baseline}.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-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.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-12>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(3rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(3rem * 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))}.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-border\/10>:not([hidden])~:not([hidden]){border-color:hsl(var(--border) / .1)}.divide-border\/30>:not([hidden])~:not([hidden]){border-color:hsl(var(--border) / .3)}.divide-border\/50>:not([hidden])~:not([hidden]){border-color:hsl(var(--border) / .5)}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-3xl{border-radius:1.5rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:.75rem}.rounded-r-full{border-top-right-radius:9999px;border-bottom-right-radius:9999px}.rounded-t-lg{border-top-left-radius:var(--radius);border-top-right-radius:var(--radius)}.rounded-bl-full{border-bottom-left-radius:9999px}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-amber-500{--tw-border-opacity: 1;border-color:rgb(245 158 11 / var(--tw-border-opacity, 1))}.border-amber-500\/10{border-color:#f59e0b1a}.border-amber-500\/20{border-color:#f59e0b33}.border-amber-500\/30{border-color:#f59e0b4d}.border-background{border-color:hsl(var(--background))}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-border{border-color:hsl(var(--border))}.border-border\/10{border-color:hsl(var(--border) / .1)}.border-border\/20{border-color:hsl(var(--border) / .2)}.border-border\/30{border-color:hsl(var(--border) / .3)}.border-border\/40{border-color:hsl(var(--border) / .4)}.border-border\/5{border-color:hsl(var(--border) / .05)}.border-border\/50{border-color:hsl(var(--border) / .5)}.border-card{border-color:hsl(var(--card))}.border-green-500{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.border-green-500\/20{border-color:#22c55e33}.border-indigo-500{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.border-primary{border-color:hsl(var(--primary))}.border-primary-foreground\/30{border-color:hsl(var(--primary-foreground) / .3)}.border-primary\/10{border-color:hsl(var(--primary) / .1)}.border-primary\/20{border-color:hsl(var(--primary) / .2)}.border-primary\/50{border-color:hsl(var(--primary) / .5)}.border-red-500{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.border-red-500\/10{border-color:#ef44441a}.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-transparent{border-color:transparent}.border-yellow-500\/20{border-color:#eab30833}.border-t-primary-foreground{border-top-color:hsl(var(--primary-foreground))}.bg-\[\#4A154B\]\/10{background-color:#4a154b1a}.bg-\[\#5865F2\]\/10{background-color:#5865f21a}.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-500\/5{background-color:#f59e0b0d}.bg-background{background-color:hsl(var(--background))}.bg-background\/50{background-color:hsl(var(--background) / .5)}.bg-background\/80{background-color:hsl(var(--background) / .8)}.bg-black\/20{background-color:#0003}.bg-black\/60{background-color:#0009}.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-border\/30{background-color:hsl(var(--border) / .3)}.bg-border\/50{background-color:hsl(var(--border) / .5)}.bg-card{background-color:hsl(var(--card))}.bg-card\/50{background-color:hsl(var(--card) / .5)}.bg-card\/80{background-color:hsl(var(--card) / .8)}.bg-current{background-color:currentColor}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-foreground{background-color:hsl(var(--foreground))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-500\/10{background-color:#22c55e1a}.bg-green-500\/20{background-color:#22c55e33}.bg-green-500\/40{background-color:#22c55e66}.bg-indigo-500{--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity, 1))}.bg-indigo-500\/10{background-color:#6366f11a}.bg-muted{background-color:hsl(var(--muted))}.bg-muted-foreground{background-color:hsl(var(--muted-foreground))}.bg-muted-foreground\/20{background-color:hsl(var(--muted-foreground) / .2)}.bg-muted-foreground\/30{background-color:hsl(var(--muted-foreground) / .3)}.bg-muted-foreground\/40{background-color:hsl(var(--muted-foreground) / .4)}.bg-muted\/10{background-color:hsl(var(--muted) / .1)}.bg-muted\/20{background-color:hsl(var(--muted) / .2)}.bg-muted\/30{background-color:hsl(var(--muted) / .3)}.bg-muted\/40{background-color:hsl(var(--muted) / .4)}.bg-muted\/5{background-color:hsl(var(--muted) / .05)}.bg-muted\/50{background-color:hsl(var(--muted) / .5)}.bg-orange-500{--tw-bg-opacity: 1;background-color:rgb(249 115 22 / var(--tw-bg-opacity, 1))}.bg-orange-500\/10{background-color:#f973161a}.bg-popover{background-color:hsl(var(--popover))}.bg-primary{background-color:hsl(var(--primary))}.bg-primary-foreground{background-color:hsl(var(--primary-foreground))}.bg-primary\/10{background-color:hsl(var(--primary) / .1)}.bg-primary\/40{background-color:hsl(var(--primary) / .4)}.bg-primary\/5{background-color:hsl(var(--primary) / .05)}.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-500\/5{background-color:#ef44440d}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/10{background-color:#ffffff1a}.bg-white\/20{background-color:#fff3}.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-\[linear-gradient\(rgba\(var\(--primary-rgb\)\,0\.03\)_1px\,transparent_1px\)\,linear-gradient\(90deg\,rgba\(var\(--primary-rgb\)\,0\.03\)_1px\,transparent_1px\)\]{background-image:linear-gradient(rgba(var(--primary-rgb),.03) 1px,transparent 1px),linear-gradient(90deg,rgba(var(--primary-rgb),.03) 1px,transparent 1px)}.bg-gradient-to-bl{background-image:linear-gradient(to bottom left,var(--tw-gradient-stops))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-l{background-image:linear-gradient(to left,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-card{--tw-gradient-from: hsl(var(--card)) var(--tw-gradient-from-position);--tw-gradient-to: hsl(var(--card) / 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-primary{--tw-gradient-from: hsl(var(--primary)) var(--tw-gradient-from-position);--tw-gradient-to: hsl(var(--primary) / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-primary\/10{--tw-gradient-from: hsl(var(--primary) / .1) var(--tw-gradient-from-position);--tw-gradient-to: hsl(var(--primary) / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-primary\/5{--tw-gradient-from: hsl(var(--primary) / .05) var(--tw-gradient-from-position);--tw-gradient-to: hsl(var(--primary) / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-red-500{--tw-gradient-from: #ef4444 var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 68 68 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-yellow-500{--tw-gradient-from: #eab308 var(--tw-gradient-from-position);--tw-gradient-to: rgb(234 179 8 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.via-card{--tw-gradient-to: hsl(var(--card) / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), hsl(var(--card)) var(--tw-gradient-via-position), var(--tw-gradient-to)}.via-transparent{--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), transparent var(--tw-gradient-via-position), var(--tw-gradient-to)}.to-indigo-500\/10{--tw-gradient-to: rgb(99 102 241 / .1) var(--tw-gradient-to-position)}.to-indigo-500\/5{--tw-gradient-to: rgb(99 102 241 / .05) var(--tw-gradient-to-position)}.to-indigo-600{--tw-gradient-to: #4f46e5 var(--tw-gradient-to-position)}.to-primary\/60{--tw-gradient-to: hsl(var(--primary) / .6) var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to: transparent var(--tw-gradient-to-position)}.bg-\[size\:64px_64px\]{background-size:64px 64px}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.fill-current{fill:currentColor}.p-0{padding:0}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-10{padding:2.5rem}.p-12{padding:3rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-20{padding:5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.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-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.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-20{padding-top:5rem;padding-bottom:5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-0{padding-bottom:0}.pb-20{padding-bottom:5rem}.pb-3{padding-bottom:.75rem}.pb-6{padding-bottom:1.5rem}.pl-10{padding-left:2.5rem}.pl-12{padding-left:3rem}.pl-4{padding-left:1rem}.pl-9{padding-left:2.25rem}.pl-\[3\.75rem\]{padding-left:3.75rem}.pr-12{padding-right:3rem}.pr-4{padding-right:1rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-1\.5{padding-top:.375rem}.pt-2{padding-top:.5rem}.pt-24{padding-top:6rem}.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-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[8px\]{font-size:8px}.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-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-\[0\.1em\]{letter-spacing:.1em}.tracking-\[0\.2em\]{letter-spacing:.2em}.tracking-\[0\.3em\]{letter-spacing:.3em}.tracking-\[0\.4em\]{letter-spacing:.4em}.tracking-tight{letter-spacing:-.025em}.tracking-tighter{letter-spacing:-.05em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-\[\#4A154B\]{--tw-text-opacity: 1;color:rgb(74 21 75 / var(--tw-text-opacity, 1))}.text-\[\#5865F2\]{--tw-text-opacity: 1;color:rgb(88 101 242 / var(--tw-text-opacity, 1))}.text-amber-500{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-emerald-500{--tw-text-opacity: 1;color:rgb(16 185 129 / var(--tw-text-opacity, 1))}.text-foreground{color:hsl(var(--foreground))}.text-foreground\/80{color:hsl(var(--foreground) / .8)}.text-foreground\/90{color:hsl(var(--foreground) / .9)}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-indigo-400{--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.text-indigo-400\/80{color:#818cf8cc}.text-indigo-500{--tw-text-opacity: 1;color:rgb(99 102 241 / var(--tw-text-opacity, 1))}.text-muted-foreground{color:hsl(var(--muted-foreground))}.text-muted-foreground\/20{color:hsl(var(--muted-foreground) / .2)}.text-muted-foreground\/30{color:hsl(var(--muted-foreground) / .3)}.text-muted-foreground\/40{color:hsl(var(--muted-foreground) / .4)}.text-muted-foreground\/50{color:hsl(var(--muted-foreground) / .5)}.text-muted-foreground\/60{color:hsl(var(--muted-foreground) / .6)}.text-orange-500{--tw-text-opacity: 1;color:rgb(249 115 22 / var(--tw-text-opacity, 1))}.text-popover-foreground{color:hsl(var(--popover-foreground))}.text-primary{color:hsl(var(--primary))}.text-primary-foreground{color:hsl(var(--primary-foreground))}.text-primary\/40{color:hsl(var(--primary) / .4)}.text-primary\/60{color:hsl(var(--primary) / .6)}.text-primary\/80{color:hsl(var(--primary) / .8)}.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-red-500\/60{color:#ef444499}.text-red-500\/80{color:#ef4444cc}.text-red-900\/60{color:#7f1d1d99}.text-transparent{color:transparent}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-white\/80{color:#fffc}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.opacity-0{opacity:0}.opacity-10{opacity:.1}.opacity-20{opacity:.2}.opacity-25{opacity:.25}.opacity-30{opacity:.3}.opacity-5{opacity:.05}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.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_10px_currentColor\]{--tw-shadow: 0 0 10px currentColor;--tw-shadow-colored: 0 0 10px 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_12px_rgba\(34\,197\,94\,0\.6\)\]{--tw-shadow: 0 0 12px rgba(34,197,94,.6);--tw-shadow-colored: 0 0 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_20px_rgba\(var\(--primary-rgb\)\,0\.1\)\]{--tw-shadow: 0 0 20px rgba(var(--primary-rgb),.1);--tw-shadow-colored: 0 0 20px 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_rgba\(34\,197\,94\,0\.4\)\]{--tw-shadow: 0 0 8px rgba(34,197,94,.4);--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-\[0_0_8px_rgba\(34\,197\,94\,0\.6\)\]{--tw-shadow: 0 0 8px rgba(34,197,94,.6);--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-amber-500\/20{--tw-shadow-color: rgb(245 158 11 / .2);--tw-shadow: var(--tw-shadow-colored)}.shadow-green-500\/20{--tw-shadow-color: rgb(34 197 94 / .2);--tw-shadow: var(--tw-shadow-colored)}.shadow-indigo-500\/20{--tw-shadow-color: rgb(99 102 241 / .2);--tw-shadow: var(--tw-shadow-colored)}.shadow-primary\/10{--tw-shadow-color: hsl(var(--primary) / .1);--tw-shadow: var(--tw-shadow-colored)}.shadow-primary\/20{--tw-shadow-color: hsl(var(--primary) / .2);--tw-shadow: var(--tw-shadow-colored)}.shadow-primary\/30{--tw-shadow-color: hsl(var(--primary) / .3);--tw-shadow: var(--tw-shadow-colored)}.shadow-red-500\/20{--tw-shadow-color: rgb(239 68 68 / .2);--tw-shadow: var(--tw-shadow-colored)}.shadow-transparent{--tw-shadow-color: transparent;--tw-shadow: var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.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-primary{--tw-ring-color: hsl(var(--primary))}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-3xl{--tw-blur: blur(64px);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-md{--tw-backdrop-blur: blur(12px);-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)}.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)}.backdrop-blur-xl{--tw-backdrop-blur: blur(24px);-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-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-1000{transition-duration:1s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-700{transition-duration:.7s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.scrollbar-thin::-webkit-scrollbar{width:6px;height:6px}.scrollbar-thin::-webkit-scrollbar-track{background:transparent}.scrollbar-thin::-webkit-scrollbar-thumb{border-radius:9999px;background-color:hsl(var(--muted-foreground) / .2);-webkit-transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:hsl(var(--muted-foreground) / .4)}.scanline{position:relative;overflow:hidden}.scanline:after{content:" ";display:block;position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(to bottom,transparent 50%,rgba(var(--primary),.02) 50%);background-size:100% 4px;z-index:2;pointer-events:none;animation:scanline-move 10s linear infinite}@keyframes scanline-move{0%{background-position:0 0}to{background-position:0 100%}}.glow-pulse{animation:glow-pulse 2.5s ease-in-out infinite}@keyframes glow-pulse{0%,to{opacity:.3;transform:scale(1);filter:blur(2px)}50%{opacity:.7;transform:scale(1.5);filter:blur(4px)}}.card-premium{border-width:1px;border-color:hsl(var(--border) / .5);background-color:hsl(var(--card));--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);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}.dark .card-premium{background-color:#080c1699;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-color:#ffffff0d;box-shadow:0 4px 20px #00000080}.dark .card-premium:hover{border-color:#6065f033;box-shadow:0 8px 30px #6366f10d}.animate-in{animation-duration:.4s;animation-timing-function:cubic-bezier(.16,1,.3,1);fill-mode:forwards}@keyframes toast-progress{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.animate-toast-progress{animation:toast-progress 5s linear forwards}.placeholder\:text-muted-foreground\/30::-moz-placeholder{color:hsl(var(--muted-foreground) / .3)}.placeholder\:text-muted-foreground\/30::placeholder{color:hsl(var(--muted-foreground) / .3)}.placeholder\:text-muted-foreground\/40::-moz-placeholder{color:hsl(var(--muted-foreground) / .4)}.placeholder\:text-muted-foreground\/40::placeholder{color:hsl(var(--muted-foreground) / .4)}.last\:hidden:last-child{display:none}.hover\:-translate-y-2:hover{--tw-translate-y: -.5rem;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-125:hover{--tw-scale-x: 1.25;--tw-scale-y: 1.25;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-primary\/20:hover{border-color:hsl(var(--primary) / .2)}.hover\:border-primary\/30:hover{border-color:hsl(var(--primary) / .3)}.hover\:border-primary\/50:hover{border-color:hsl(var(--primary) / .5)}.hover\:bg-amber-500:hover{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.hover\:bg-amber-500\/10:hover{background-color:#f59e0b1a}.hover\:bg-amber-500\/20:hover{background-color:#f59e0b33}.hover\:bg-amber-600:hover{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.hover\:bg-background:hover{background-color:hsl(var(--background))}.hover\:bg-blue-500\/10:hover{background-color:#3b82f61a}.hover\:bg-blue-600:hover{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.hover\:bg-emerald-500\/20:hover{background-color:#10b98133}.hover\:bg-green-500\/10:hover{background-color:#22c55e1a}.hover\:bg-muted:hover{background-color:hsl(var(--muted))}.hover\:bg-muted\/10:hover{background-color:hsl(var(--muted) / .1)}.hover\:bg-muted\/30:hover{background-color:hsl(var(--muted) / .3)}.hover\:bg-muted\/5:hover{background-color:hsl(var(--muted) / .05)}.hover\:bg-muted\/50:hover{background-color:hsl(var(--muted) / .5)}.hover\:bg-muted\/60:hover{background-color:hsl(var(--muted) / .6)}.hover\:bg-muted\/80:hover{background-color:hsl(var(--muted) / .8)}.hover\:bg-primary:hover{background-color:hsl(var(--primary))}.hover\:bg-primary\/10:hover{background-color:hsl(var(--primary) / .1)}.hover\:bg-primary\/20:hover{background-color:hsl(var(--primary) / .2)}.hover\:bg-primary\/5:hover{background-color:hsl(var(--primary) / .05)}.hover\:bg-primary\/\[0\.02\]:hover{background-color:hsl(var(--primary) / .02)}.hover\:bg-red-500:hover{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.hover\:bg-red-500\/10:hover{background-color:#ef44441a}.hover\:bg-red-500\/20:hover{background-color:#ef444433}.hover\:bg-red-600:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.hover\:bg-white\/10:hover{background-color:#ffffff1a}.hover\:bg-white\/\[0\.02\]:hover{background-color:#ffffff05}.hover\:text-amber-500:hover{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.hover\:text-foreground:hover{color:hsl(var(--foreground))}.hover\:text-primary:hover{color:hsl(var(--primary))}.hover\:text-primary-foreground:hover{color:hsl(var(--primary-foreground))}.hover\:text-red-500:hover{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-2xl:hover{--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)}.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-xl:hover{--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)}.hover\:shadow-primary\/20:hover{--tw-shadow-color: hsl(var(--primary) / .2);--tw-shadow: var(--tw-shadow-colored)}.hover\:shadow-primary\/40:hover{--tw-shadow-color: hsl(var(--primary) / .4);--tw-shadow: var(--tw-shadow-colored)}.focus\:border-primary\/50:focus{border-color:hsl(var(--primary) / .5)}.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-inset:focus{--tw-ring-inset: inset}.focus\:ring-primary:focus{--tw-ring-color: hsl(var(--primary))}.focus\:ring-primary\/20:focus{--tw-ring-color: hsl(var(--primary) / .2)}.focus\:ring-primary\/30:focus{--tw-ring-color: hsl(var(--primary) / .3)}.active\:scale-90:active{--tw-scale-x: .9;--tw-scale-y: .9;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))}.active\:scale-95:active{--tw-scale-x: .95;--tw-scale-y: .95;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))}.active\:scale-\[0\.98\]: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))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:hover\:scale-100:hover:disabled{--tw-scale-x: 1;--tw-scale-y: 1;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\:rotate-12{--tw-rotate: 12deg;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\: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))}.group:hover .group-hover\:rotate-\[15deg\]{--tw-rotate: 15deg;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\/item:hover .group-hover\/item\:scale-110{--tw-scale-x: 1.1;--tw-scale-y: 1.1;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\:scale-105{--tw-scale-x: 1.05;--tw-scale-y: 1.05;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\:scale-110{--tw-scale-x: 1.1;--tw-scale-y: 1.1;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\:scale-150{--tw-scale-x: 1.5;--tw-scale-y: 1.5;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\:border-border\/10{border-color:hsl(var(--border) / .1)}.group:hover .group-hover\:border-primary\/20{border-color:hsl(var(--primary) / .2)}.group:hover .group-hover\:bg-primary\/10{background-color:hsl(var(--primary) / .1)}.group:hover .group-hover\:bg-primary\/20{background-color:hsl(var(--primary) / .2)}.group:hover .group-hover\:text-foreground{color:hsl(var(--foreground))}.group:hover .group-hover\:text-primary{color:hsl(var(--primary))}.group\/tile:hover .group-hover\/tile\:opacity-100,.group:hover .group-hover\:opacity-100{opacity:1}.group:hover .group-hover\:opacity-20{opacity:.2}@media(min-width:640px){.sm\:block{display:block}.sm\:inline{display:inline}.sm\:w-auto{width:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:p-6{padding:1.5rem}.sm\:p-8{padding:2rem}}@media(min-width:768px){.md\:col-span-2{grid-column:span 2 / span 2}.md\:inline{display:inline}.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\:p-10{padding:2.5rem}}@media(min-width:1024px){.lg\:col-span-1{grid-column:span 1 / span 1}.lg\:col-span-2{grid-column:span 2 / span 2}.lg\:inline{display:inline}.lg\:flex{display:flex}.lg\:grid{display:grid}.lg\:h-\[600px\]{height:600px}.lg\:h-full{height:100%}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}}@media(min-width:1280px){.xl\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(prefers-color-scheme:dark){.dark\:bg-card{background-color:hsl(var(--card))}.dark\:text-\[\#E01E5A\]{--tw-text-opacity: 1;color:rgb(224 30 90 / var(--tw-text-opacity, 1))}.dark\:text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.dark\:text-red-400\/60{color:#f8717199}}