@adonis-agora/durable-dashboard 0.2.1 → 0.2.3

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.
@@ -10,8 +10,8 @@
10
10
  rel="stylesheet"
11
11
  />
12
12
  <title>durable · control plane</title>
13
- <script type="module" crossorigin src="/__DURABLE_DASHBOARD__/assets/index-CV232q_B.js"></script>
14
- <link rel="stylesheet" crossorigin href="/__DURABLE_DASHBOARD__/assets/index-CTsYsi6p.css">
13
+ <script type="module" crossorigin src="/__DURABLE_DASHBOARD__/assets/index-CS0tc60i.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/__DURABLE_DASHBOARD__/assets/index-97QpkU1f.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonis-agora/durable-dashboard",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Control-plane console (runs, step timeline, workflow graph, retry/cancel/fix-and-replay) for @adonis-agora/durable — a React SPA served by a thin AdonisJS provider. Part of the Agora ecosystem.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -13,6 +13,7 @@
13
13
  "sideEffects": false,
14
14
  "files": [
15
15
  "dist/",
16
+ "skills",
16
17
  "README.md",
17
18
  "CHANGELOG.md"
18
19
  ],
@@ -22,28 +23,28 @@
22
23
  },
23
24
  "devDependencies": {
24
25
  "@base-ui/react": "1.7.0",
25
- "@tanstack/react-query": "5.101.4",
26
- "@tanstack/react-virtual": "3.14.9",
26
+ "@tailwindcss/postcss": "4.3.3",
27
+ "@tanstack/intent": "^0.3.7",
28
+ "@tanstack/react-query": "5.102.8",
29
+ "@tanstack/react-virtual": "3.14.10",
27
30
  "@testing-library/dom": "10.4.1",
28
- "@testing-library/react": "16.3.2",
29
- "@types/node": "20.19.43",
30
- "@types/react": "18.3.31",
31
- "@types/react-dom": "18.3.7",
32
- "@vitejs/plugin-react": "4.7.0",
33
- "@xyflow/react": "12.11.3",
34
- "autoprefixer": "10.5.4",
31
+ "@testing-library/react": "16.3.3",
32
+ "@types/node": "26.4.0",
33
+ "@types/react": "19.2.18",
34
+ "@types/react-dom": "19.2.5",
35
+ "@vitejs/plugin-react": "6.1.1",
36
+ "@xyflow/react": "12.11.5",
35
37
  "class-variance-authority": "0.7.1",
36
38
  "clsx": "2.1.1",
37
- "happy-dom": "20.11.2",
38
- "jsdom": "25.0.1",
39
- "postcss": "8.5.26",
40
- "react": "18.3.1",
41
- "react-dom": "18.3.1",
39
+ "happy-dom": "20.12.0",
40
+ "jsdom": "30.0.1",
41
+ "react": "19.2.8",
42
+ "react-dom": "19.2.8",
42
43
  "tailwind-merge": "3.6.0",
43
- "tailwindcss": "3.4.19",
44
- "typescript": "5.9.3",
45
- "vite": "5.4.21",
46
- "vitest": "3.2.7"
44
+ "tailwindcss": "4.3.3",
45
+ "typescript": "7.0.2",
46
+ "vite": "8.2.2",
47
+ "vitest": "4.1.11"
47
48
  },
48
49
  "engines": {
49
50
  "node": ">=20.6.0"
@@ -56,6 +57,7 @@
56
57
  "dashboard",
57
58
  "admin",
58
59
  "console",
60
+ "tanstack-intent",
59
61
  "agora"
60
62
  ],
61
63
  "scripts": {
@@ -0,0 +1,289 @@
1
+ ---
2
+ name: durable-observability
3
+ description: >-
4
+ Operate and observe @adonis-agora/durable runs: the embedded dashboard
5
+ (config/durable_dashboard.ts, enabled/path/authorize, dashboardAuth session
6
+ layer with session/login hooks, JSON API for listRuns/retry/retry-with-input/
7
+ cancel/redispatch/bulk, SSE live tail via EventSource), engine.subscribe
8
+ lifecycle events (run.started/completed/failed/suspended, step.*,
9
+ capability.unavailable), engine.use local-step interceptors, collectMetrics
10
+ Prometheus counters, OpenTelemetry tracing (attachDurableOtel,
11
+ otelTraceparent cross-process propagation), and the Telescope Workflows view
12
+ (durableTelescopeExtension). Use when mounting/securing the console,
13
+ scripting run actions, or wiring logs/metrics/traces.
14
+ license: MIT
15
+ metadata:
16
+ type: core
17
+ library: "@adonis-agora/durable-dashboard"
18
+ library_version: "0.2.1"
19
+ framework: adonisjs
20
+ sources:
21
+ - 'DavideCarvalho/adonis-durable:docs/observability/dashboard.mdx'
22
+ - 'DavideCarvalho/adonis-durable:docs/observability/dashboard-auth.mdx'
23
+ - 'DavideCarvalho/adonis-durable:docs/observability/events-and-interceptors.mdx'
24
+ - 'DavideCarvalho/adonis-durable:docs/observability/otel.mdx'
25
+ - 'DavideCarvalho/adonis-durable:docs/observability/telescope.mdx'
26
+ ---
27
+
28
+ # Observing & operating runs
29
+
30
+ The dashboard mounts an operations console into your AdonisJS app: a React SPA
31
+ plus the JSON API it runs on, reading straight from the state store. The SPA is
32
+ bundled from `@adonis-agora/durable-dashboard`; its provider and config ship in
33
+ the main package.
34
+
35
+ ## Setup
36
+
37
+ ```bash
38
+ node ace configure @adonis-agora/durable
39
+ # registers @adonis-agora/durable/dashboard_provider + publishes config/durable_dashboard.ts
40
+ ```
41
+
42
+ ```ts title="config/durable_dashboard.ts"
43
+ import { defineConfig } from '@adonis-agora/durable/dashboard'
44
+
45
+ export default defineConfig({
46
+ // enabled: true, // default true; false registers no routes at all
47
+ path: '/durable',
48
+ authorize: async (ctx) => {
49
+ await ctx.auth.check()
50
+ return ctx.auth.user?.isAdmin === true // denied requests get 403
51
+ },
52
+ })
53
+ ```
54
+
55
+ The default `authorize` is open outside production and requires a bearer token
56
+ equal to `DURABLE_DASHBOARD_TOKEN` in production (**fails closed if unset**).
57
+ The console mutates runs — always front it with a real guard in production.
58
+
59
+ ## Core patterns
60
+
61
+ ### Pattern 1 — operator sign-in with `dashboardAuth`
62
+
63
+ Opt-in session layer, additive to `authorize` (both must pass). `secret` plus at
64
+ least one of `session` / `login`; a mis-wired gate throws at boot:
65
+
66
+ ```ts title="config/durable_dashboard.ts"
67
+ import { defineConfig } from '@adonis-agora/durable/dashboard'
68
+ import env from '#start/env'
69
+ import User from '#models/user'
70
+
71
+ export default defineConfig({
72
+ path: '/durable',
73
+ dashboardAuth: {
74
+ secret: env.get('DURABLE_DASHBOARD_SECRET'), // HMAC-SHA256 key, 32+ bytes
75
+ ttl: '8h',
76
+ login: async (username, password) => {
77
+ const user = await User.verifyCredentials(username, password).catch(() => null)
78
+ if (!user || !user.isAdmin) return null // null denies
79
+ return { id: String(user.id), name: user.fullName, roles: ['admin'] }
80
+ },
81
+ // or Mode A — mint a session from your app's own cookie via
82
+ // POST <path>/session with credentials: 'include' and redirect: 'manual'.
83
+ },
84
+ })
85
+ ```
86
+
87
+ Adds `GET/POST <path>/login`, `POST <path>/session`, `GET <path>/logout`. Pages
88
+ redirect 302 to login without a valid cookie; API requests get
89
+ `401 { error, auth: { modes } }`. Source: `docs/observability/dashboard-auth.mdx`.
90
+
91
+ ### Pattern 2 — fix-and-replay and bulk actions
92
+
93
+ A run that failed on bad input cannot be retried into success — retry replays
94
+ the same input. Fix-and-replay starts a NEW run (`<originalRunId>~retry~<uuid>`,
95
+ clean history, original left intact as the record):
96
+
97
+ ```ts
98
+ const res = await fetch(`/durable/api/runs/${runId}/retry-with-input`, {
99
+ method: 'POST',
100
+ headers: { 'content-type': 'application/json', ...headers },
101
+ body: JSON.stringify({ input: { orderId: 'ord_42', amount: 1999 } }),
102
+ })
103
+ const { result } = await res.json()
104
+ result.runId // 'run-abc~retry~1f4c9e02'
105
+ ```
106
+
107
+ Apply an action to everything a filter matches — same filters as `GET /api/runs`
108
+ (`status`, `workflow`, `tag`, `namespace`, repeatable `attr=key:op:value`):
109
+
110
+ ```bash
111
+ curl -X POST '/durable/api/bulk/retry?status=failed&workflow=charge-order&namespace=eu-west'
112
+ curl -X POST '/durable/api/bulk/cancel?status=suspended&tag=stuck&compensate=true'
113
+ ```
114
+
115
+ Bulk acts on at most **500 runs per call**, no paging — compare `matched` to 500
116
+ and narrow + repeat. A compensating cancel answers with the PRE-cancel status;
117
+ watch the SSE stream until it reaches `cancelled`.
118
+ Source: `docs/observability/dashboard.mdx`.
119
+
120
+ ### Pattern 3 — lifecycle events → logs, metrics, traces
121
+
122
+ Everything observable is one event stream; subscribe directly or use the
123
+ shipped bridges:
124
+
125
+ ```ts title="start/durable.ts"
126
+ import router from '@adonisjs/core/services/router'
127
+ import engine from '@adonis-agora/durable/services/main'
128
+ import { attachDurableOtel } from '@adonis-agora/durable/otel'
129
+ import { collectMetrics } from '@adonis-agora/durable'
130
+
131
+ engine.subscribe((event) => {
132
+ if (event.type !== 'run.failed') return
133
+ logger.error({ runId: event.runId, workflow: event.workflow }, 'durable run failed')
134
+ })
135
+
136
+ const metrics = collectMetrics(engine)
137
+ router.get('/metrics/durable', ({ response }) => {
138
+ response.header('content-type', 'text/plain; version=0.0.4')
139
+ return metrics.prometheus()
140
+ })
141
+
142
+ const detach = attachDurableOtel(engine) // one root span per run, one per step
143
+ ```
144
+
145
+ Event types: `run.started|completed|failed|suspended`, `step.started|
146
+ completed|failed` (each retry emits its own `step.failed`), plus
147
+ `capability.unavailable` / `protocol.incompatible` carrying full diagnostics.
148
+ For distributed tracing across workers, stamp tasks with a provider:
149
+
150
+ ```ts title="config/durable.ts"
151
+ import { defineConfig } from '@adonis-agora/durable'
152
+ import { otelTraceparent } from '@adonis-agora/durable/otel'
153
+
154
+ export default defineConfig({
155
+ traceparent: () => otelTraceparent(), // W3C context continues on the worker
156
+ })
157
+ ```
158
+
159
+ Live-tail one run over SSE:
160
+ `new EventSource('/durable/api/runs/${runId}/stream')`.
161
+ Source: `docs/observability/events-and-interceptors.mdx`,
162
+ `docs/observability/otel.mdx`, `docs/observability/dashboard.mdx`.
163
+
164
+ ### Pattern 4 — golden signals in Telescope
165
+
166
+ Register the extension once and workflows appear next to requests/queries/jobs:
167
+
168
+ ```ts title="config/telescope.ts"
169
+ import { durableTelescopeExtension } from '@adonis-agora/durable/telescope'
170
+
171
+ export default defineConfig({
172
+ extensions: [durableTelescopeExtension({ runHref: '/durable/runs/{runId}' })],
173
+ })
174
+ ```
175
+
176
+ Rollups (success rate, throughput, duration percentiles, top failures) come from
177
+ captured entries bounded by Telescope's prune window; current-state gauges
178
+ (dead/suspended/running/pending NOW) read live from the store via `listRuns`.
179
+ Per-run actions stay in the durable dashboard. Source:
180
+ `docs/observability/telescope.mdx`.
181
+
182
+ ## Common mistakes
183
+
184
+ ### HIGH trusting an "empty" dashboard config in production
185
+
186
+ Wrong:
187
+
188
+ ```ts
189
+ export default defineConfig({}) // prod, DURABLE_DASHBOARD_TOKEN unset
190
+ ```
191
+
192
+ Correct:
193
+
194
+ ```ts
195
+ export default defineConfig({
196
+ authorize: async (ctx) => {
197
+ await ctx.auth.check()
198
+ return ctx.auth.user?.isAdmin === true
199
+ },
200
+ })
201
+ ```
202
+
203
+ Mechanism: the default authorize fails CLOSED in production when the token env
204
+ var is unset, so every console route 403s and the console looks broken rather
205
+ than leaking — either set the token deliberately or override authorize.
206
+ Source: `docs/observability/dashboard.mdx` ("Authorization").
207
+
208
+ ### HIGH making interceptor outputs depend on time, randomness or external state
209
+
210
+ Wrong:
211
+
212
+ ```ts
213
+ engine.use(async (invocation, next) => next().then((r) => ({ ...r, at: Date.now() })))
214
+ ```
215
+
216
+ Correct:
217
+
218
+ ```ts
219
+ engine.use(async (invocation, next) => {
220
+ const result = await next()
221
+ logger.info({ workflow: invocation.workflow, step: invocation.stepName })
222
+ return result
223
+ })
224
+ ```
225
+
226
+ Mechanism: interceptors wrap the REAL execution of local steps inside the
227
+ deterministic execution path — a returned value that differs between runs makes
228
+ replay disagree with the recorded checkpoint. Read, time, log, classify; don't
229
+ mutate results nondeterministically. Source:
230
+ `docs/observability/events-and-interceptors.mdx` (warning callout).
231
+
232
+ ### MEDIUM expecting interceptors to fire on replay or dispatched steps
233
+
234
+ Wrong:
235
+
236
+ ```ts
237
+ engine.use(enforceInvariant) // "runs on every turn" — it does not
238
+ ```
239
+
240
+ Correct: enforce invariants inside the workflow body or step handlers; register
241
+ interceptors on the worker's engine to observe dispatched steps there.
242
+
243
+ Mechanism: a replayed step returns its recorded output without executing (so
244
+ timings here are real-execution timings), and dispatched steps execute on
245
+ workers in another process — there is no local body to wrap. Source:
246
+ `docs/observability/events-and-interceptors.mdx`.
247
+
248
+ ### MEDIUM treating a compensating cancel's response as the final state
249
+
250
+ Wrong:
251
+
252
+ ```ts
253
+ const { run } = await cancelRun(runId, { compensate: true })
254
+ if (run.status !== 'cancelled') throw new Error('cancel failed') // premature
255
+ ```
256
+
257
+ Correct:
258
+
259
+ ```ts
260
+ await cancelRun(runId, { compensate: true })
261
+ // poll getRun / subscribe to the stream until status === 'cancelled'
262
+ ```
263
+
264
+ Mechanism: cancel-with-compensate answers immediately with the pre-cancel status
265
+ while the saga undo replays in the background; only a plain cancel is terminal in
266
+ the response itself. Source: `docs/observability/dashboard.mdx` (info callout).
267
+
268
+ ### MEDIUM scraping one pod's collectMetrics counters as fleet totals
269
+
270
+ Wrong:
271
+
272
+ ```yaml
273
+ # one Prometheus target pointed at a single web pod
274
+ ```
275
+
276
+ Correct:
277
+
278
+ ```yaml
279
+ # scrape /metrics/durable on EVERY engine-bearing pod; aggregate in PromQL
280
+ ```
281
+
282
+ Mechanism: counters are per process and reset on restart, so one target both
283
+ undercounts the fleet and zeroes on every deploy of that pod. Source:
284
+ `docs/observability/events-and-interceptors.mdx` ("Counters are per process").
285
+
286
+ See also: `durable-reliability` — what the events mean operationally; bulk
287
+ cancel + compensate semantics.
288
+ See also: `durable-cluster` — which verbs proxy over the wire on store-less pods
289
+ (`retry-with-input` / `continue` answer 404 there).
@@ -1 +0,0 @@
1
- .react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #555;--xy-background-pattern-lines-color-default: #333;--xy-background-pattern-cross-color-default: #333;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}*,: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:JetBrains Mono,ui-monospace,SFMono-Regular,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}}.visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.inset-x-0{left:0;right:0}.inset-x-6{left:1.5rem;right:1.5rem}.inset-y-0{top:0;bottom:0}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.top-full{top:100%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-\[10px\]{margin-left:10px}.ml-\[18px\]{margin-left:18px}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.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}.hidden{display:none}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-7{height:1.75rem}.h-full{height:100%}.h-px{height:1px}.max-h-48{max-height:12rem}.max-h-64{max-height:16rem}.max-h-80{max-height:20rem}.min-h-0{min-height:0px}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-16{width:4rem}.w-32{width:8rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-\[208px\]{width:208px}.w-\[300px\]{width:300px}.w-\[380px\]{width:380px}.w-\[3px\]{width:3px}.w-\[min\(560px\,92vw\)\]{width:min(560px,92vw)}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-3xl{max-width:48rem}.max-w-\[120px\]{max-width:120px}.max-w-\[180px\]{max-width:180px}.max-w-\[280px\]{max-width:280px}.max-w-\[90\%\]{max-width:90%}.max-w-full{max-width:100%}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-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\/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-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 pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.cursor-row-resize{cursor:row-resize}.resize-y{resize:vertical}.resize{resize:both}.grid-cols-\[130px_1fr\]{grid-template-columns:130px 1fr}.grid-cols-\[150px_1fr\]{grid-template-columns:150px 1fr}.grid-cols-\[minmax\(300px\,360px\)_1fr\]{grid-template-columns:minmax(300px,360px) 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.flex-nowrap{flex-wrap:nowrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-0\.5{row-gap:.125rem}.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))}.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-line-soft>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:color-mix(in srgb,var(--line-soft) calc(var(--tw-divide-opacity, 1) * 100%),transparent)}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-\[2px\]{border-radius:2px}.rounded-\[3px\]{border-radius:3px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.\!border-0{border-width:0px!important}.border{border-width:1px}.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-amber-500\/20{border-color:#f59e0b33}.border-amber-500\/25{border-color:#f59e0b40}.border-amber-500\/30{border-color:#f59e0b4d}.border-amber-500\/40{border-color:#f59e0b66}.border-amber-500\/50{border-color:#f59e0b80}.border-bad\/25{border-color:color-mix(in srgb,var(--bad) 25%,transparent)}.border-brand\/30{border-color:color-mix(in srgb,var(--accent) 30%,transparent)}.border-brand\/60{border-color:color-mix(in srgb,var(--accent) 60%,transparent)}.border-emerald-500\/25{border-color:#10b98140}.border-indigo-500\/30{border-color:#6366f14d}.border-indigo-500\/40{border-color:#6366f166}.border-line{--tw-border-opacity: 1;border-color:color-mix(in srgb,var(--line) calc(var(--tw-border-opacity, 1) * 100%),transparent)}.border-line-soft{--tw-border-opacity: 1;border-color:color-mix(in srgb,var(--line-soft) calc(var(--tw-border-opacity, 1) * 100%),transparent)}.border-line\/60{border-color:color-mix(in srgb,var(--line) 60%,transparent)}.border-red-500\/20{border-color:#ef444433}.border-red-500\/25{border-color:#ef444440}.border-red-500\/40{border-color:#ef444466}.border-rose-500\/30{border-color:#f43f5e4d}.border-rose-500\/40{border-color:#f43f5e66}.border-rose-500\/50{border-color:#f43f5e80}.border-sky-500\/30{border-color:#0ea5e94d}.border-sky-500\/40{border-color:#0ea5e966}.border-teal-500\/30{border-color:#14b8a64d}.border-transparent{border-color:transparent}.border-warn\/40{border-color:color-mix(in srgb,var(--warn) 40%,transparent)}.border-zinc-500{--tw-border-opacity: 1;border-color:rgb(113 113 122 / var(--tw-border-opacity, 1))}.border-zinc-600{--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1))}.border-zinc-600\/50{border-color:#52525b80}.border-zinc-700{--tw-border-opacity: 1;border-color:rgb(63 63 70 / var(--tw-border-opacity, 1))}.\!bg-zinc-600{--tw-bg-opacity: 1 !important;background-color:rgb(82 82 91 / var(--tw-bg-opacity, 1))!important}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.bg-amber-500\/10{background-color:#f59e0b1a}.bg-amber-500\/15{background-color:#f59e0b26}.bg-amber-500\/35{background-color:#f59e0b59}.bg-amber-500\/5{background-color:#f59e0b0d}.bg-bad\/10{background-color:color-mix(in srgb,var(--bad) 10%,transparent)}.bg-black\/15{background-color:#00000026}.bg-black\/20{background-color:#0003}.bg-black\/40{background-color:#0006}.bg-black\/60{background-color:#0009}.bg-brand\/10{background-color:color-mix(in srgb,var(--accent) 10%,transparent)}.bg-current{background-color:currentColor}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity, 1))}.bg-emerald-400\/45{background-color:#34d39973}.bg-emerald-500\/10{background-color:#10b9811a}.bg-emerald-500\/15{background-color:#10b98126}.bg-emerald-500\/20{background-color:#10b98133}.bg-emerald-500\/30{background-color:#10b9814d}.bg-emerald-500\/40{background-color:#10b98166}.bg-indigo-500\/10{background-color:#6366f11a}.bg-line-soft{--tw-bg-opacity: 1;background-color:color-mix(in srgb,var(--line-soft) calc(var(--tw-bg-opacity, 1) * 100%),transparent)}.bg-live{--tw-bg-opacity: 1;background-color:color-mix(in srgb,var(--live) calc(var(--tw-bg-opacity, 1) * 100%),transparent)}.bg-live\/15{background-color:color-mix(in srgb,var(--live) 15%,transparent)}.bg-live\/20{background-color:color-mix(in srgb,var(--live) 20%,transparent)}.bg-panel{--tw-bg-opacity: 1;background-color:color-mix(in srgb,var(--panel) calc(var(--tw-bg-opacity, 1) * 100%),transparent)}.bg-panel-2{--tw-bg-opacity: 1;background-color:color-mix(in srgb,var(--panel-2) calc(var(--tw-bg-opacity, 1) * 100%),transparent)}.bg-panel\/95{background-color:color-mix(in srgb,var(--panel) 95%,transparent)}.bg-popover\/95{background-color:color-mix(in srgb,var(--panel-2) 95%,transparent)}.bg-red-400{--tw-bg-opacity: 1;background-color:rgb(248 113 113 / var(--tw-bg-opacity, 1))}.bg-red-500\/10{background-color:#ef44441a}.bg-red-500\/15{background-color:#ef444426}.bg-red-500\/20{background-color:#ef444433}.bg-red-500\/35{background-color:#ef444459}.bg-red-500\/40{background-color:#ef444466}.bg-rose-500\/10{background-color:#f43f5e1a}.bg-rose-500\/15{background-color:#f43f5e26}.bg-rose-500\/80{background-color:#f43f5ecc}.bg-sky-500\/10{background-color:#0ea5e91a}.bg-teal-500\/10{background-color:#14b8a61a}.bg-transparent{background-color:transparent}.bg-warn\/10{background-color:color-mix(in srgb,var(--warn) 10%,transparent)}.bg-zinc-800{--tw-bg-opacity: 1;background-color:rgb(39 39 42 / var(--tw-bg-opacity, 1))}.bg-zinc-800\/40{background-color:#27272a66}.bg-zinc-800\/50{background-color:#27272a80}.bg-zinc-800\/60{background-color:#27272a99}.bg-zinc-800\/70{background-color:#27272ab3}.bg-zinc-900{--tw-bg-opacity: 1;background-color:rgb(24 24 27 / var(--tw-bg-opacity, 1))}.bg-zinc-900\/30{background-color:#18181b4d}.bg-zinc-900\/40{background-color:#18181b66}.bg-zinc-900\/60{background-color:#18181b99}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-7{padding-left:1.75rem;padding-right:1.75rem}.py-0{padding-top:0;padding-bottom:0}.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-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-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pl-3\.5{padding-left:.875rem}.pr-3{padding-right:.75rem}.pt-1\.5{padding-top:.375rem}.pt-3{padding-top:.75rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-\[10\.5px\]{font-size:10.5px}.text-\[10px\]{font-size:10px}.text-\[11\.5px\]{font-size:11.5px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.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-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.normal-case{text-transform:none}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-\[0\.15em\]{letter-spacing:.15em}.tracking-\[0\.16em\]{letter-spacing:.16em}.tracking-\[0\.18em\]{letter-spacing:.18em}.tracking-\[0\.2em\]{letter-spacing:.2em}.tracking-normal{letter-spacing:0em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-amber-100{--tw-text-opacity: 1;color:rgb(254 243 199 / var(--tw-text-opacity, 1))}.text-amber-200{--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity, 1))}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.text-amber-300\/70{color:#fcd34db3}.text-amber-400\/70{color:#fbbf24b3}.text-amber-400\/80{color:#fbbf24cc}.text-bad{--tw-text-opacity: 1;color:color-mix(in srgb,var(--bad) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.text-brand{--tw-text-opacity: 1;color:color-mix(in srgb,var(--accent) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.text-emerald-300{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity, 1))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-emerald-500\/80{color:#10b981cc}.text-foreground{--tw-text-opacity: 1;color:color-mix(in srgb,var(--text) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.text-good{--tw-text-opacity: 1;color:color-mix(in srgb,var(--good) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.text-indigo-300{--tw-text-opacity: 1;color:rgb(165 180 252 / var(--tw-text-opacity, 1))}.text-indigo-300\/80{color:#a5b4fccc}.text-indigo-400{--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.text-live{--tw-text-opacity: 1;color:color-mix(in srgb,var(--live) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.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-red-400\/80{color:#f87171cc}.text-rose-200{--tw-text-opacity: 1;color:rgb(254 205 211 / var(--tw-text-opacity, 1))}.text-rose-300{--tw-text-opacity: 1;color:rgb(253 164 175 / var(--tw-text-opacity, 1))}.text-rose-300\/70{color:#fda4afb3}.text-sky-300{--tw-text-opacity: 1;color:rgb(125 211 252 / var(--tw-text-opacity, 1))}.text-teal-300{--tw-text-opacity: 1;color:rgb(94 234 212 / var(--tw-text-opacity, 1))}.text-warn{--tw-text-opacity: 1;color:color-mix(in srgb,var(--warn) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-zinc-100{--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity, 1))}.text-zinc-200{--tw-text-opacity: 1;color:rgb(228 228 231 / var(--tw-text-opacity, 1))}.text-zinc-300{--tw-text-opacity: 1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.text-zinc-400{--tw-text-opacity: 1;color:rgb(161 161 170 / var(--tw-text-opacity, 1))}.text-zinc-50{--tw-text-opacity: 1;color:rgb(250 250 250 / var(--tw-text-opacity, 1))}.text-zinc-500{--tw-text-opacity: 1;color:rgb(113 113 122 / var(--tw-text-opacity, 1))}.text-zinc-600{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.text-zinc-800{--tw-text-opacity: 1;color:rgb(39 39 42 / var(--tw-text-opacity, 1))}.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-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-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)}.outline{outline-style:solid}.ring{--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(3px + 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-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-amber-500\/45{--tw-ring-color: rgb(245 158 11 / .45)}.ring-brand\/30{--tw-ring-color: color-mix(in srgb, var(--accent) 30% , transparent)}.ring-emerald-400\/60{--tw-ring-color: rgb(52 211 153 / .6)}.ring-emerald-500\/40{--tw-ring-color: rgb(16 185 129 / .4)}.ring-emerald-500\/50{--tw-ring-color: rgb(16 185 129 / .5)}.ring-line-soft{--tw-ring-opacity: 1;--tw-ring-color: color-mix(in srgb, var(--line-soft) calc(var(--tw-ring-opacity, 1) * 100%), transparent)}.ring-red-500\/50{--tw-ring-color: rgb(239 68 68 / .5)}.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{--tw-backdrop-blur: blur(8px);-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-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)}.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-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}.duration-500{transition-duration:.5s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}:root{--bg: #09090b;--panel: #0c0c0f;--panel-2: #101017;--line: #1c1c22;--line-soft: #16161a;--text: #e7e7ea;--muted: #76767f;--good: #34d399;--warn: #fbbf24;--bad: #f87171;--live: #60a5fa;--accent: #a3e635}*{box-sizing:border-box}html,body,#root{height:100%}body{margin:0;background:var(--bg);color:var(--text);font-family:Space Grotesk,ui-sans-serif,system-ui,sans-serif;-webkit-font-smoothing:antialiased}.app-bg{position:fixed;top:0;right:0;bottom:0;left:0;z-index:0;pointer-events:none;background-image:radial-gradient(900px 400px at 78% -8%,color-mix(in srgb,var(--accent) 8%,transparent),transparent 70%),linear-gradient(to right,var(--line-soft) 1px,transparent 1px),linear-gradient(to bottom,var(--line-soft) 1px,transparent 1px);background-size:100% 100%,44px 44px,44px 44px;-webkit-mask-image:linear-gradient(to bottom,black,black 60%,transparent);mask-image:linear-gradient(to bottom,black,black 60%,transparent);opacity:.5}.mono{font-family:JetBrains Mono,ui-monospace,monospace}.tnum{font-variant-numeric:tabular-nums}.s-running{color:var(--live)}.s-suspended{color:var(--warn)}.s-sleeping{color:#818cf8}.s-awaiting{color:var(--warn)}.s-completed{color:var(--good)}.s-failed{color:var(--bad)}.s-cancelling{color:#f59e0b}.s-cancelled{color:#71717a}.s-dead{color:#e11d48}.s-pending{color:#94a3b8}.s-no-worker{color:#fb923c}.s-queued{color:#a78bfa}.s-stale{color:#fb923c}.dot{width:7px;height:7px;border-radius:999px;background:currentColor;box-shadow:0 0 0 3px color-mix(in srgb,currentColor 18%,transparent)}.pulse{animation:pulse 1.6s ease-in-out infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.35}}@keyframes rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}.rise{animation:rise .32s cubic-bezier(.2,.7,.2,1) both}.react-flow{--xy-background-color: transparent;--xy-edge-stroke-default: var(--line);--xy-attribution-background-color: transparent}.react-flow__edge-path{stroke-width:1.5}.react-flow__controls{border:1px solid var(--line);border-radius:8px;overflow:hidden;box-shadow:none}.react-flow__controls-button{background:var(--panel);border-bottom:1px solid var(--line);color:var(--muted);fill:var(--muted)}.react-flow__controls-button:hover{background:#18181b}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:#26262c;border:3px solid var(--bg);border-radius:999px}.placeholder\:text-zinc-600::-moz-placeholder{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.placeholder\:text-zinc-600::placeholder{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.focus-within\:border-zinc-600:focus-within{--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1))}.hover\:-translate-y-0\.5:hover{--tw-translate-y: -.125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-amber-500\/40:hover{border-color:#f59e0b66}.hover\:border-indigo-400\/60:hover{border-color:#818cf899}.hover\:border-red-400\/60:hover{border-color:#f8717199}.hover\:border-sky-400\/60:hover{border-color:#38bdf899}.hover\:border-teal-400\/60:hover{border-color:#2dd4bf99}.hover\:border-zinc-500:hover{--tw-border-opacity: 1;border-color:rgb(113 113 122 / var(--tw-border-opacity, 1))}.hover\:border-zinc-600:hover{--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1))}.hover\:bg-brand\/20:hover{background-color:color-mix(in srgb,var(--accent) 20%,transparent)}.hover\:bg-brand\/40:hover{background-color:color-mix(in srgb,var(--accent) 40%,transparent)}.hover\:bg-indigo-500\/20:hover{background-color:#6366f133}.hover\:bg-rose-500\/20:hover{background-color:#f43f5e33}.hover\:bg-sky-500\/20:hover{background-color:#0ea5e933}.hover\:bg-warn\/20:hover{background-color:color-mix(in srgb,var(--warn) 20%,transparent)}.hover\:bg-zinc-800:hover{--tw-bg-opacity: 1;background-color:rgb(39 39 42 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-800\/50:hover{background-color:#27272a80}.hover\:bg-zinc-900\/50:hover{background-color:#18181b80}.hover\:bg-zinc-900\/60:hover{background-color:#18181b99}.hover\:text-indigo-100:hover{--tw-text-opacity: 1;color:rgb(224 231 255 / var(--tw-text-opacity, 1))}.hover\:text-indigo-200:hover{--tw-text-opacity: 1;color:rgb(199 210 254 / var(--tw-text-opacity, 1))}.hover\:text-sky-200:hover{--tw-text-opacity: 1;color:rgb(186 230 253 / var(--tw-text-opacity, 1))}.hover\:text-teal-200:hover{--tw-text-opacity: 1;color:rgb(153 246 228 / var(--tw-text-opacity, 1))}.hover\:text-zinc-100:hover{--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity, 1))}.hover\:text-zinc-200:hover{--tw-text-opacity: 1;color:rgb(228 228 231 / var(--tw-text-opacity, 1))}.hover\:text-zinc-300:hover{--tw-text-opacity: 1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.focus\:border-zinc-600:focus{--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-1:focus-visible{--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-visible\:ring-ring:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: color-mix(in srgb, var(--accent) calc(var(--tw-ring-opacity, 1) * 100%), transparent)}.enabled\:hover\:bg-rose-500\/25:hover:enabled{background-color:#f43f5e40}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-default:disabled{cursor:default}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-50:disabled{opacity:.5}.data-\[active\]\:bg-zinc-700[data-active]{--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity, 1))}.data-\[active\]\:text-zinc-100[data-active]{--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity, 1))}