trellis-datamodel 0.3.3__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. trellis_datamodel/adapters/base.py +5 -1
  2. trellis_datamodel/adapters/dbt_core.py +79 -8
  3. trellis_datamodel/config.py +43 -1
  4. trellis_datamodel/routes/__init__.py +2 -0
  5. trellis_datamodel/routes/lineage.py +60 -0
  6. trellis_datamodel/routes/manifest.py +6 -0
  7. trellis_datamodel/server.py +2 -1
  8. trellis_datamodel/services/__init__.py +2 -0
  9. trellis_datamodel/services/lineage.py +427 -0
  10. trellis_datamodel/static/_app/immutable/assets/0.DRr1NRor.css +1 -0
  11. trellis_datamodel/static/_app/immutable/chunks/{CXDUumOQ.js → COKQndWa.js} +1 -1
  12. trellis_datamodel/static/_app/immutable/entry/{app.abCkWeAJ.js → app.BA1wC-Z2.js} +2 -2
  13. trellis_datamodel/static/_app/immutable/entry/start.Cq8bDFFs.js +1 -0
  14. trellis_datamodel/static/_app/immutable/nodes/{1.J_r941Qf.js → 1.CITYWtIe.js} +1 -1
  15. trellis_datamodel/static/_app/immutable/nodes/2.DBgiABuH.js +27 -0
  16. trellis_datamodel/static/_app/version.json +1 -1
  17. trellis_datamodel/static/index.html +6 -6
  18. trellis_datamodel/tests/test_dbt_schema.py +260 -4
  19. trellis_datamodel/tests/test_yaml_handler.py +228 -0
  20. trellis_datamodel/utils/yaml_handler.py +131 -20
  21. {trellis_datamodel-0.3.3.dist-info → trellis_datamodel-0.4.0.dist-info}/METADATA +8 -4
  22. {trellis_datamodel-0.3.3.dist-info → trellis_datamodel-0.4.0.dist-info}/RECORD +28 -25
  23. trellis_datamodel/static/_app/immutable/assets/0.ByDwyx3a.css +0 -1
  24. trellis_datamodel/static/_app/immutable/entry/start.B7CjH6Z7.js +0 -1
  25. trellis_datamodel/static/_app/immutable/nodes/2.WqbMkq6o.js +0 -27
  26. /trellis_datamodel/static/_app/immutable/nodes/{0.bFI_DI3G.js → 0.CXLfbIn-.js} +0 -0
  27. {trellis_datamodel-0.3.3.dist-info → trellis_datamodel-0.4.0.dist-info}/WHEEL +0 -0
  28. {trellis_datamodel-0.3.3.dist-info → trellis_datamodel-0.4.0.dist-info}/entry_points.txt +0 -0
  29. {trellis_datamodel-0.3.3.dist-info → trellis_datamodel-0.4.0.dist-info}/licenses/LICENSE +0 -0
  30. {trellis_datamodel-0.3.3.dist-info → trellis_datamodel-0.4.0.dist-info}/licenses/NOTICE +0 -0
  31. {trellis_datamodel-0.3.3.dist-info → trellis_datamodel-0.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,427 @@
1
+ """
2
+ Lineage extraction service.
3
+
4
+ Extracts table-level upstream lineage from dbt manifest.json and catalog.json files.
5
+ Uses native manifest parsing (primary) with optional dbt-colibri support.
6
+ """
7
+
8
+ import json
9
+ import os
10
+ from typing import Any, Optional
11
+ from collections import deque
12
+ from trellis_datamodel import config as cfg
13
+
14
+ try:
15
+ from dbt_colibri import extract_lineage as colibri_extract_lineage
16
+
17
+ COLIBRI_AVAILABLE = True
18
+ except ImportError:
19
+ COLIBRI_AVAILABLE = False
20
+
21
+
22
+ class LineageError(Exception):
23
+ """Error during lineage extraction."""
24
+
25
+ pass
26
+
27
+
28
+ def extract_upstream_lineage(
29
+ manifest_path: str,
30
+ catalog_path: Optional[str],
31
+ model_unique_id: str,
32
+ ) -> dict[str, Any]:
33
+ """
34
+ Extract upstream table-level lineage for a given model using dbt-colibri.
35
+
36
+ Args:
37
+ manifest_path: Path to dbt manifest.json file
38
+ catalog_path: Path to dbt catalog.json file (optional but recommended)
39
+ model_unique_id: Unique ID of the model (e.g., "model.project.model_name")
40
+
41
+ Returns:
42
+ Dictionary with:
43
+ - nodes: List of lineage nodes with id, label, level, isSource
44
+ - edges: List of edges with source, target, level
45
+ - metadata: Additional metadata including model counts per level
46
+
47
+ Raises:
48
+ LineageError: If lineage extraction fails
49
+ FileNotFoundError: If manifest.json is missing
50
+ """
51
+ # Validate manifest exists
52
+ if not os.path.exists(manifest_path):
53
+ raise FileNotFoundError(f"Manifest not found at {manifest_path}")
54
+
55
+ try:
56
+ # Load manifest
57
+ with open(manifest_path, "r") as f:
58
+ manifest = json.load(f)
59
+
60
+ # Load catalog if available (optional)
61
+ catalog = None
62
+ if catalog_path and os.path.exists(catalog_path):
63
+ with open(catalog_path, "r") as f:
64
+ catalog = json.load(f)
65
+
66
+ # Verify model exists in manifest
67
+ nodes = manifest.get("nodes", {})
68
+ if model_unique_id not in nodes:
69
+ # Check if it's a versioned model issue
70
+ model_name = (
71
+ model_unique_id.split(".")[-1]
72
+ if "." in model_unique_id
73
+ else model_unique_id
74
+ )
75
+ matching_models = [
76
+ uid
77
+ for uid in nodes.keys()
78
+ if uid.endswith(f".{model_name}") or uid.endswith(f".{model_name}.v")
79
+ ]
80
+ if matching_models:
81
+ raise LineageError(
82
+ f"Model '{model_unique_id}' not found in manifest. "
83
+ f"Found similar models: {', '.join(matching_models[:3])}"
84
+ )
85
+ raise LineageError(
86
+ f"Model '{model_unique_id}' not found in manifest. "
87
+ f"Available models: {len([n for n in nodes.values() if n.get('resource_type') == 'model'])} model(s)"
88
+ )
89
+
90
+ # Extract lineage using native manifest parsing
91
+ # This works without dbt-colibri by traversing depends_on relationships
92
+ lineage_data = _extract_lineage_from_manifest(manifest, model_unique_id)
93
+
94
+ # Transform to our format
95
+ return _transform_lineage_data(lineage_data, model_unique_id, manifest)
96
+
97
+ except FileNotFoundError:
98
+ raise
99
+ except Exception as e:
100
+ raise LineageError(f"Failed to extract lineage: {str(e)}") from e
101
+
102
+
103
+ def _extract_lineage_from_manifest(
104
+ manifest: dict[str, Any],
105
+ root_model_id: str,
106
+ ) -> dict[str, Any]:
107
+ """
108
+ Extract upstream lineage directly from manifest.json.
109
+
110
+ Traverses depends_on relationships to build upstream lineage graph.
111
+ Includes all models (no filtering) - frontend handles progressive display
112
+ based on model count per level threshold.
113
+
114
+ Args:
115
+ manifest: Parsed manifest.json dictionary
116
+ root_model_id: Starting model unique_id
117
+
118
+ Returns:
119
+ Dictionary with nodes (list of unique_ids) and edges (list of {source, target})
120
+ """
121
+ nodes = manifest.get("nodes", {})
122
+ sources = manifest.get("sources", {})
123
+
124
+ # Track all nodes in lineage
125
+ lineage_node_ids: set[str] = {root_model_id}
126
+ lineage_edges: list[dict[str, str]] = []
127
+
128
+ # BFS to find all upstream dependencies
129
+ queue = deque([root_model_id])
130
+ visited = {root_model_id}
131
+
132
+ while queue:
133
+ current_id = queue.popleft()
134
+ current_node = nodes.get(current_id)
135
+
136
+ if not current_node:
137
+ continue
138
+
139
+ # Get upstream dependencies
140
+ depends_on = current_node.get("depends_on")
141
+ if not depends_on:
142
+ continue
143
+
144
+ # Handle both dict and list formats
145
+ if isinstance(depends_on, dict):
146
+ upstream_nodes = depends_on.get("nodes", [])
147
+ elif isinstance(depends_on, list):
148
+ upstream_nodes = depends_on
149
+ else:
150
+ upstream_nodes = []
151
+
152
+ for upstream_id in upstream_nodes:
153
+ # Add edge for all dependencies (models and sources)
154
+ lineage_edges.append(
155
+ {
156
+ "source": upstream_id,
157
+ "target": current_id,
158
+ }
159
+ )
160
+
161
+ # Add upstream node to lineage
162
+ lineage_node_ids.add(upstream_id)
163
+
164
+ # Continue BFS if not visited
165
+ if upstream_id not in visited:
166
+ visited.add(upstream_id)
167
+ # Only continue BFS for models (not sources)
168
+ if upstream_id.startswith("model."):
169
+ queue.append(upstream_id)
170
+
171
+ # Identify source tables
172
+ source_ids = set()
173
+ for node_id in lineage_node_ids:
174
+ if node_id.startswith("source."):
175
+ source_ids.add(node_id)
176
+ elif node_id in sources:
177
+ source_ids.add(node_id)
178
+
179
+ return {
180
+ "nodes": list(lineage_node_ids),
181
+ "edges": lineage_edges,
182
+ "sources": list(source_ids),
183
+ }
184
+
185
+
186
+ def _extract_folder_from_path(original_file_path: str) -> Optional[str]:
187
+ """
188
+ Extract the first folder after models/ from original_file_path.
189
+
190
+ Examples:
191
+ models/1_clean/employee.sql -> 1_clean
192
+ models/stg/staging_users.sql -> stg
193
+ models/3_core/all/employee_history.sql -> 3_core
194
+ models/employee.sql -> None (no folder)
195
+
196
+ Args:
197
+ original_file_path: Path from manifest node's original_file_path field
198
+
199
+ Returns:
200
+ Folder name or None if no folder exists after models/
201
+ """
202
+ if not original_file_path:
203
+ return None
204
+
205
+ # Normalize path separators (handle Windows backslashes)
206
+ normalized_path = original_file_path.replace("\\", "/")
207
+
208
+ # Check if path starts with models/
209
+ if not normalized_path.startswith("models/"):
210
+ return None
211
+
212
+ # Remove models/ prefix
213
+ path_after_models = normalized_path[7:] # len("models/") = 7
214
+
215
+ # Split by / and get first part
216
+ parts = path_after_models.split("/")
217
+ if len(parts) > 0 and parts[0]:
218
+ return parts[0]
219
+
220
+ return None
221
+
222
+
223
+ def _transform_lineage_data(
224
+ lineage_data: dict[str, Any],
225
+ root_model_id: str,
226
+ manifest: dict[str, Any],
227
+ ) -> dict[str, Any]:
228
+ """
229
+ Transform dbt-colibri lineage output to frontend-friendly format.
230
+
231
+ Args:
232
+ lineage_data: Raw lineage data from dbt-colibri
233
+ root_model_id: The root model unique_id
234
+
235
+ Returns:
236
+ Transformed lineage data with nodes, edges, and metadata
237
+ """
238
+ # This is a placeholder - actual transformation depends on dbt-colibri output format
239
+ # We'll need to adjust based on actual API
240
+
241
+ nodes: list[dict[str, Any]] = []
242
+ edges: list[dict[str, Any]] = []
243
+ node_map: dict[str, dict[str, Any]] = {}
244
+
245
+ # Extract nodes and edges from lineage_data
246
+ # Structure:
247
+ # {
248
+ # "nodes": [list of unique_ids],
249
+ # "edges": [list of {source, target}],
250
+ # "sources": [list of source unique_ids]
251
+ # }
252
+
253
+ lineage_nodes = lineage_data.get("nodes", [])
254
+ lineage_edges = lineage_data.get("edges", [])
255
+ sources = lineage_data.get("sources", [])
256
+
257
+ # Build source set for quick lookup
258
+ source_set = set(sources) if sources else set()
259
+
260
+ # Calculate depth/level for each node using BFS from root
261
+ levels = _calculate_node_levels(lineage_edges, root_model_id)
262
+
263
+ # Create nodes
264
+ for node_id in lineage_nodes:
265
+ node_info = _get_node_info(node_id, source_set, levels, root_model_id, manifest)
266
+ nodes.append(node_info)
267
+ node_map[node_id] = node_info
268
+
269
+ # Create edges
270
+ for edge in lineage_edges:
271
+ source_id = edge.get("source")
272
+ target_id = edge.get("target")
273
+ if source_id in node_map and target_id in node_map:
274
+ source_level = node_map[source_id]["level"]
275
+ edges.append(
276
+ {
277
+ "source": source_id,
278
+ "target": target_id,
279
+ "level": source_level, # Use source level
280
+ }
281
+ )
282
+
283
+ # Calculate model counts per level
284
+ level_counts = {}
285
+ for node in nodes:
286
+ level = node["level"]
287
+ level_counts[level] = level_counts.get(level, 0) + 1
288
+
289
+ # Include configured layers in metadata if layers are configured
290
+ metadata = {
291
+ "root_model_id": root_model_id,
292
+ "level_counts": level_counts,
293
+ "total_nodes": len(nodes),
294
+ "total_edges": len(edges),
295
+ }
296
+
297
+ if cfg.LINEAGE_LAYERS:
298
+ metadata["lineage_layers"] = cfg.LINEAGE_LAYERS
299
+
300
+ return {
301
+ "nodes": nodes,
302
+ "edges": edges,
303
+ "metadata": metadata,
304
+ }
305
+
306
+
307
+ def _calculate_node_levels(
308
+ edges: list[dict[str, Any]],
309
+ root_id: str,
310
+ ) -> dict[str, int]:
311
+ """
312
+ Calculate depth/level for each node using BFS from root.
313
+
314
+ Level 0 = root model
315
+ Level 1 = direct dependencies
316
+ Level 2 = dependencies of level 1, etc.
317
+ """
318
+ levels: dict[str, int] = {root_id: 0}
319
+
320
+ # Build adjacency list (reverse: target -> sources)
321
+ # For upstream lineage, we want to traverse from root to sources
322
+ adjacency: dict[str, list[str]] = {}
323
+ for edge in edges:
324
+ source = edge.get("source")
325
+ target = edge.get("target")
326
+ if source and target:
327
+ if target not in adjacency:
328
+ adjacency[target] = []
329
+ adjacency[target].append(source)
330
+
331
+ # BFS from root
332
+ queue = deque([root_id])
333
+ visited = {root_id}
334
+
335
+ while queue:
336
+ current = queue.popleft()
337
+ current_level = levels[current]
338
+
339
+ # Process upstream nodes (sources of current)
340
+ for upstream in adjacency.get(current, []):
341
+ if upstream not in visited:
342
+ visited.add(upstream)
343
+ levels[upstream] = current_level + 1
344
+ queue.append(upstream)
345
+
346
+ return levels
347
+
348
+
349
+ def _get_node_info(
350
+ node_id: str,
351
+ source_set: set[str],
352
+ levels: dict[str, int],
353
+ root_model_id: str,
354
+ manifest: dict[str, Any],
355
+ ) -> dict[str, Any]:
356
+ """
357
+ Get node information for lineage visualization.
358
+
359
+ Args:
360
+ node_id: Unique ID of the node
361
+ source_set: Set of source node IDs
362
+ levels: Dictionary mapping node_id to level
363
+ root_model_id: Root model unique_id
364
+ manifest: Parsed manifest.json dictionary
365
+
366
+ Returns:
367
+ Node info dictionary
368
+ """
369
+ # Extract model name from unique_id (e.g., "model.project.name" -> "name")
370
+ parts = node_id.split(".")
371
+ label = parts[-1] if parts else node_id
372
+
373
+ # Determine if this is a source table
374
+ is_source = node_id in source_set or node_id.startswith("source.")
375
+
376
+ # Extract source-name for source nodes
377
+ # Source IDs follow format: source.project.source_name.table_name
378
+ source_name = None
379
+ if is_source and len(parts) >= 3:
380
+ source_name = parts[2] # Third part is the source-name
381
+
382
+ # Get level (distance from root)
383
+ level = levels.get(node_id, 0)
384
+
385
+ result = {
386
+ "id": node_id,
387
+ "label": label,
388
+ "level": level,
389
+ "isSource": is_source,
390
+ }
391
+
392
+ # Add source-name if this is a source node
393
+ if source_name is not None:
394
+ result["sourceName"] = source_name
395
+
396
+ # Assign layer based on folder structure
397
+ layer = None
398
+ lineage_layers = cfg.LINEAGE_LAYERS
399
+
400
+ if is_source:
401
+ # Sources always get "sources" layer
402
+ layer = "sources"
403
+ elif lineage_layers:
404
+ # Only assign layers if configuration exists
405
+ # Get node from manifest to extract original_file_path
406
+ nodes = manifest.get("nodes", {})
407
+ node = nodes.get(node_id)
408
+
409
+ if node:
410
+ original_file_path = node.get("original_file_path", "")
411
+ folder = _extract_folder_from_path(original_file_path)
412
+
413
+ if folder and folder in lineage_layers:
414
+ # Match found in configured layers
415
+ layer = folder
416
+ else:
417
+ # No match - assign to unassigned
418
+ layer = "unassigned"
419
+ else:
420
+ # Node not found in manifest (shouldn't happen, but handle gracefully)
421
+ layer = "unassigned"
422
+
423
+ # Only add layer field if layers are configured (backward compatibility)
424
+ if lineage_layers and layer:
425
+ result["layer"] = layer
426
+
427
+ return result
@@ -0,0 +1 @@
1
+ .svelte-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}.svelte-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: #777;--xy-background-pattern-lines-color-default: #777;--xy-background-pattern-cross-color-default: #777;--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}.svelte-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.svelte-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.svelte-flow__pane{z-index:1}.svelte-flow__pane.draggable{cursor:grab}.svelte-flow__pane.dragging{cursor:grabbing}.svelte-flow__pane.selection{cursor:pointer}.svelte-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.svelte-flow__renderer{z-index:4}.svelte-flow__selection{z-index:6}.svelte-flow__nodesselection-rect:focus,.svelte-flow__nodesselection-rect:focus-visible{outline:none}.svelte-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}.svelte-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}.svelte-flow .svelte-flow__edges{position:absolute}.svelte-flow .svelte-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.svelte-flow__edge{pointer-events:visibleStroke}.svelte-flow__edge.selectable{cursor:pointer}.svelte-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.svelte-flow__edge.animated path.svelte-flow__edge-interaction{stroke-dasharray:none;animation:none}.svelte-flow__edge.inactive{pointer-events:none}.svelte-flow__edge.selected,.svelte-flow__edge:focus,.svelte-flow__edge:focus-visible{outline:none}.svelte-flow__edge.selected .svelte-flow__edge-path,.svelte-flow__edge.selectable:focus .svelte-flow__edge-path,.svelte-flow__edge.selectable:focus-visible .svelte-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.svelte-flow__edge-textwrapper{pointer-events:all}.svelte-flow__edge .svelte-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.svelte-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.svelte-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.svelte-flow__connection{pointer-events:none}.svelte-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.svelte-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.svelte-flow__nodes{pointer-events:none;transform-origin:0 0}.svelte-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}.svelte-flow__node.selectable{cursor:pointer}.svelte-flow__node.draggable{cursor:grab;pointer-events:all}.svelte-flow__node.draggable.dragging{cursor:grabbing}.svelte-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.svelte-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.svelte-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%}.svelte-flow__handle.connectingfrom{pointer-events:all}.svelte-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.svelte-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.svelte-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.svelte-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.svelte-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.svelte-flow__edgeupdater{cursor:move;pointer-events:all}.svelte-flow__pane.selection .svelte-flow__panel{pointer-events:none}.svelte-flow__panel{position:absolute;z-index:5;margin:15px}.svelte-flow__panel.top{top:0}.svelte-flow__panel.bottom{bottom:0}.svelte-flow__panel.top.center,.svelte-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.svelte-flow__panel.left{left:0}.svelte-flow__panel.right{right:0}.svelte-flow__panel.left.center,.svelte-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.svelte-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.svelte-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.svelte-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}.svelte-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.svelte-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.svelte-flow__minimap-svg{display:block}.svelte-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)) )}.svelte-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)) )}.svelte-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.svelte-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.svelte-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.svelte-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.svelte-flow__controls.horizontal{flex-direction:row}.svelte-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}.svelte-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.svelte-flow__edge.updating .svelte-flow__edge-path{stroke:#777}.svelte-flow__edge-text{font-size:10px}.svelte-flow__node.selectable:focus,.svelte-flow__node.selectable:focus-visible{outline:none}.svelte-flow__node-input,.svelte-flow__node-default,.svelte-flow__node-output,.svelte-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))}.svelte-flow__node-input.selectable:hover,.svelte-flow__node-default.selectable:hover,.svelte-flow__node-output.selectable:hover,.svelte-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.svelte-flow__node-input.selectable.selected,.svelte-flow__node-input.selectable:focus,.svelte-flow__node-input.selectable:focus-visible,.svelte-flow__node-default.selectable.selected,.svelte-flow__node-default.selectable:focus,.svelte-flow__node-default.selectable:focus-visible,.svelte-flow__node-output.selectable.selected,.svelte-flow__node-output.selectable:focus,.svelte-flow__node-output.selectable:focus-visible,.svelte-flow__node-group.selectable.selected,.svelte-flow__node-group.selectable:focus,.svelte-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.svelte-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.svelte-flow__nodesselection-rect,.svelte-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.svelte-flow__nodesselection-rect:focus,.svelte-flow__nodesselection-rect:focus-visible,.svelte-flow__selection:focus,.svelte-flow__selection:focus-visible{outline:none}.svelte-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)) )}.svelte-flow__controls-button:disabled{pointer-events:none}.svelte-flow__controls-button:disabled svg{fill-opacity:.4}.svelte-flow__controls-button:last-child{border-bottom:none}.svelte-flow__controls.horizontal .svelte-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)) )}.svelte-flow__controls.horizontal .svelte-flow__controls-button:last-child{border-right:none}.svelte-flow__resize-control{position:absolute}.svelte-flow__resize-control.left,.svelte-flow__resize-control.right{cursor:ew-resize}.svelte-flow__resize-control.top,.svelte-flow__resize-control.bottom{cursor:ns-resize}.svelte-flow__resize-control.top.left,.svelte-flow__resize-control.bottom.right{cursor:nwse-resize}.svelte-flow__resize-control.bottom.left,.svelte-flow__resize-control.top.right{cursor:nesw-resize}.svelte-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%}.svelte-flow__resize-control.handle.left{left:0;top:50%}.svelte-flow__resize-control.handle.right{left:100%;top:50%}.svelte-flow__resize-control.handle.top{left:50%;top:0}.svelte-flow__resize-control.handle.bottom{left:50%;top:100%}.svelte-flow__resize-control.handle.top.left,.svelte-flow__resize-control.handle.bottom.left{left:0}.svelte-flow__resize-control.handle.top.right,.svelte-flow__resize-control.handle.bottom.right{left:100%}.svelte-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.svelte-flow__resize-control.line.left,.svelte-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.svelte-flow__resize-control.line.left{left:0;border-left-width:1px}.svelte-flow__resize-control.line.right{left:100%;border-right-width:1px}.svelte-flow__resize-control.line.top,.svelte-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.svelte-flow__resize-control.line.top{top:0;border-top-width:1px}.svelte-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.svelte-flow__edge-label{text-align:center;position:absolute;padding:2px;font-size:10px;color:var(--xy-edge-label-color, var(--xy-edge-label-color-default));background:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.svelte-flow__container{-webkit-user-select:none;-moz-user-select:none;user-select:none}*,: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:#e2e8f0}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:IBM Plex Mono,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:#94a3b8}input::placeholder,textarea::placeholder{opacity:1;color:#94a3b8}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}body{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.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}}.\!pointer-events-none{pointer-events:none!important}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.collapse{visibility:collapse}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-right-1{right:-.25rem}.-top-1{top:-.25rem}.left-0{left:0}.left-2\.5{left:.625rem}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-1\/2{top:50%}.top-2{top:.5rem}.top-4{top:1rem}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-2\.5{margin-bottom:.625rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-5{margin-left:1.25rem}.ml-\[11px\]{margin-left:11px}.ml-auto{margin-left:auto}.mr-1\.5{margin-right:.375rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-2\.5{margin-top:.625rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.contents{display:contents}.hidden{display:none}.\!h-0{height:0px!important}.\!h-2{height:.5rem!important}.h-10{height:2.5rem}.h-16{height:4rem}.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-8{height:2rem}.h-\[92vh\]{height:92vh}.h-full{height:100%}.h-screen{height:100vh}.max-h-48{max-height:12rem}.max-h-64{max-height:16rem}.max-h-\[70vh\]{max-height:70vh}.max-h-\[90vh\]{max-height:90vh}.max-h-\[920px\]{max-height:920px}.max-h-\[calc\(100vh-18rem\)\]{max-height:calc(100vh - 18rem)}.min-h-\[60px\]{min-height:60px}.\!w-0{width:0px!important}.\!w-2{width:.5rem!important}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-\[94vw\]{width:94vw}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0px}.min-w-\[100px\]{min-width:100px}.min-w-\[120px\]{min-width:120px}.min-w-\[150px\]{min-width:150px}.min-w-full{min-width:100%}.max-w-3xl{max-width:48rem}.max-w-\[100px\]{max-width:100px}.max-w-\[150px\]{max-width:150px}.max-w-\[1600px\]{max-width:1600px}.max-w-\[200px\]{max-width:200px}.max-w-full{max-width:100%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-rotate-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))}.rotate-0{--tw-rotate: 0deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.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-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-move{cursor:move}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-y{resize:vertical}.resize{resize:both}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.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}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-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))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(241 245 249 / var(--tw-divide-opacity, 1))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(226 232 240 / var(--tw-divide-opacity, 1))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.rounded-t-xl{border-top-left-radius:.75rem;border-top-right-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-y{border-top-width:1px;border-bottom-width:1px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-\[\#26A69A\]{--tw-border-opacity: 1;border-color:rgb(38 166 154 / var(--tw-border-opacity, 1))}.border-amber-100{--tw-border-opacity: 1;border-color:rgb(254 243 199 / var(--tw-border-opacity, 1))}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity, 1))}.border-blue-100{--tw-border-opacity: 1;border-color:rgb(219 234 254 / var(--tw-border-opacity, 1))}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-blue-400{--tw-border-opacity: 1;border-color:rgb(96 165 250 / var(--tw-border-opacity, 1))}.border-danger-100{--tw-border-opacity: 1;border-color:rgb(255 228 230 / var(--tw-border-opacity, 1))}.border-danger-200{--tw-border-opacity: 1;border-color:rgb(254 205 211 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-gray-200\/60{border-color:#e2e8f099}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.border-gray-900{--tw-border-opacity: 1;border-color:rgb(15 23 42 / var(--tw-border-opacity, 1))}.border-green-500{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.border-primary-100{--tw-border-opacity: 1;border-color:rgb(204 251 241 / var(--tw-border-opacity, 1))}.border-primary-500{--tw-border-opacity: 1;border-color:rgb(20 184 166 / var(--tw-border-opacity, 1))}.border-primary-600{--tw-border-opacity: 1;border-color:rgb(13 148 136 / var(--tw-border-opacity, 1))}.border-primary-600\/10{border-color:#0d94881a}.border-purple-200{--tw-border-opacity: 1;border-color:rgb(233 213 255 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-red-500{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-slate-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.border-success-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.\!bg-gray-400{--tw-bg-opacity: 1 !important;background-color:rgb(148 163 184 / var(--tw-bg-opacity, 1))!important}.bg-\[\#0f172a\]{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\/40{background-color:#0006}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-danger-50{--tw-bg-opacity: 1;background-color:rgb(255 241 242 / var(--tw-bg-opacity, 1))}.bg-danger-500{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity, 1))}.bg-danger-600{--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-gray-200\/50{background-color:#e2e8f080}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(203 213 225 / var(--tw-bg-opacity, 1))}.bg-gray-300\/80{background-color:#cbd5e1cc}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-gray-50\/50{background-color:#f8fafc80}.bg-primary-100{--tw-bg-opacity: 1;background-color:rgb(204 251 241 / var(--tw-bg-opacity, 1))}.bg-primary-50{--tw-bg-opacity: 1;background-color:rgb(240 253 250 / var(--tw-bg-opacity, 1))}.bg-primary-500{--tw-bg-opacity: 1;background-color:rgb(20 184 166 / var(--tw-bg-opacity, 1))}.bg-primary-500\/\[0\.03\]{background-color:#14b8a608}.bg-primary-600{--tw-bg-opacity: 1;background-color:rgb(13 148 136 / var(--tw-bg-opacity, 1))}.bg-purple-50{--tw-bg-opacity: 1;background-color:rgb(250 245 255 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-slate-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-success-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-success-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/80{background-color:#fffc}.bg-white\/90{background-color:#ffffffe6}.bg-opacity-50{--tw-bg-opacity: .5}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.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-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-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-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pl-0{padding-left:0}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pl-6{padding-left:1.5rem}.pl-8{padding-left:2rem}.pr-1{padding-right:.25rem}.pr-2{padding-right:.5rem}.pr-8{padding-right:2rem}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:IBM Plex Mono,monospace}.font-sans{font-family:Inter,sans-serif}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-tight{line-height:1.25}.tracking-\[0\.3em\]{letter-spacing:.3em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-blue-900{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity, 1))}.text-danger-500{--tw-text-opacity: 1;color:rgb(244 63 94 / var(--tw-text-opacity, 1))}.text-danger-700{--tw-text-opacity: 1;color:rgb(190 18 60 / var(--tw-text-opacity, 1))}.text-danger-800{--tw-text-opacity: 1;color:rgb(159 18 57 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-primary-500{--tw-text-opacity: 1;color:rgb(20 184 166 / var(--tw-text-opacity, 1))}.text-primary-600{--tw-text-opacity: 1;color:rgb(13 148 136 / var(--tw-text-opacity, 1))}.text-primary-700{--tw-text-opacity: 1;color:rgb(15 118 110 / var(--tw-text-opacity, 1))}.text-primary-700\/50{color:#0f766e80}.text-purple-700{--tw-text-opacity: 1;color:rgb(126 34 206 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-800{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.text-success-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-success-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.\!opacity-0{opacity:0!important}.opacity-0{opacity:0}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[inset_0_1px_0_0_rgba\(255\,255\,255\,0\.4\)\]{--tw-shadow: inset 0 1px 0 0 rgba(255,255,255,.4);--tw-shadow-colored: inset 0 1px 0 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-md{--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)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.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-blue-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(147 197 253 / var(--tw-ring-opacity, 1))}.ring-blue-500{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.ring-primary-500{--tw-ring-opacity: 1;--tw-ring-color: rgb(20 184 166 / var(--tw-ring-opacity, 1))}.ring-opacity-50{--tw-ring-opacity: .5}.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)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.svelte-flow__selection,.react-flow__selection,.xy-flow__selection{display:none!important;pointer-events:none!important}.svelte-flow__pane,.svelte-flow__node,.cursor-grab{cursor:default!important}.svelte-flow__pane{color:transparent;background-image:linear-gradient(90deg,#0f172a00 85%,#fff);background-clip:text;-webkit-background-clip:text}.svelte-flow__pane.dragging,.svelte-flow__node.dragging,.cursor-grabbing,.svelte-flow__pane:active,.svelte-flow__node:active{cursor:move!important}.svelte-flow__node,.svelte-flow__node.svelte-flow__node-default,.svelte-flow__node.svelte-flow__node-entity,.svelte-flow__node.svelte-flow__node-source,.svelte-flow__node.svelte-flow__node-group{border:none!important;outline:none!important;box-shadow:none!important;color:#0f172a00}.svelte-flow__node:focus,.svelte-flow__node:focus-visible,.svelte-flow__node.svelte-flow__node-default:focus,.svelte-flow__node.svelte-flow__node-default:focus-visible{outline:none!important;box-shadow:none!important;border:none!important}.svelte-flow__node-default{border:none!important;padding:0!important;background:transparent!important;box-shadow:none!important;outline:none!important}.svelte-flow__node-default:focus,.svelte-flow__node-default:focus-visible{outline:none!important;box-shadow:none!important}input,textarea,[contenteditable]{cursor:default!important}input[type=text].font-mono,select.font-mono,select.font-mono option{background-color:#fff!important;color:#4b5563!important}input[type=text].font-medium:not(.font-mono),input[type=text][placeholder*=field_name],input[type=text][placeholder*=column_name]{background-color:#fff!important;color:#111827!important}.scrollbar-thin::-webkit-scrollbar{width:6px!important;height:6px!important}.scrollbar-thin::-webkit-scrollbar-track{background:transparent!important}.scrollbar-thin::-webkit-scrollbar-thumb{background-color:#e5e7eb!important;border-radius:3px!important}.scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:#d1d5db!important}.scrollbar-thin{scrollbar-width:thin!important;scrollbar-color:rgb(229 231 235) transparent!important}.placeholder\:text-gray-300::-moz-placeholder{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.placeholder\:text-gray-300::placeholder{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.last\:border-0:last-child{border-width:0px}.last\:border-b-0:last-child{border-bottom-width:0px}.hover\:border-primary-500:hover{--tw-border-opacity: 1;border-color:rgb(20 184 166 / var(--tw-border-opacity, 1))}.hover\:border-primary-600:hover{--tw-border-opacity: 1;border-color:rgb(13 148 136 / var(--tw-border-opacity, 1))}.hover\:bg-amber-700:hover{--tw-bg-opacity: 1;background-color:rgb(180 83 9 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-50:hover{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.hover\:bg-danger-50:hover{--tw-bg-opacity: 1;background-color:rgb(255 241 242 / var(--tw-bg-opacity, 1))}.hover\:bg-danger-700:hover{--tw-bg-opacity: 1;background-color:rgb(190 18 60 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200\/50:hover{background-color:#e2e8f080}.hover\:bg-gray-200\/70:hover{background-color:#e2e8f0b3}.hover\:bg-gray-300:hover{--tw-bg-opacity: 1;background-color:rgb(203 213 225 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.hover\:bg-primary-50:hover{--tw-bg-opacity: 1;background-color:rgb(240 253 250 / var(--tw-bg-opacity, 1))}.hover\:bg-primary-700:hover{--tw-bg-opacity: 1;background-color:rgb(15 118 110 / var(--tw-bg-opacity, 1))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-800:hover{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.hover\:bg-white:hover{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.hover\:text-\[\#26A69A\]:hover{--tw-text-opacity: 1;color:rgb(38 166 154 / var(--tw-text-opacity, 1))}.hover\:text-blue-700:hover{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.hover\:text-danger-500:hover{--tw-text-opacity: 1;color:rgb(244 63 94 / var(--tw-text-opacity, 1))}.hover\:text-danger-600:hover{--tw-text-opacity: 1;color:rgb(225 29 72 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.hover\:text-gray-800:hover{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.hover\:text-gray-900:hover{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.hover\:text-primary-500:hover{--tw-text-opacity: 1;color:rgb(20 184 166 / var(--tw-text-opacity, 1))}.hover\:text-primary-600:hover{--tw-text-opacity: 1;color:rgb(13 148 136 / var(--tw-text-opacity, 1))}.hover\:text-primary-700:hover{--tw-text-opacity: 1;color:rgb(15 118 110 / var(--tw-text-opacity, 1))}.hover\:shadow-md:hover{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-sm:hover{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:border-\[\#26A69A\]:focus{--tw-border-opacity: 1;border-color:rgb(38 166 154 / var(--tw-border-opacity, 1))}.focus\:border-transparent:focus{border-color:transparent}.focus\:bg-white:focus{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-amber-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(245 158 11 / var(--tw-ring-opacity, 1))}.focus\:ring-blue-400:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(96 165 250 / var(--tw-ring-opacity, 1))}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.focus\:ring-danger-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(244 63 94 / var(--tw-ring-opacity, 1))}.focus\:ring-gray-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(100 116 139 / var(--tw-ring-opacity, 1))}.focus\:ring-primary-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(20 184 166 / var(--tw-ring-opacity, 1))}.focus\:ring-primary-600:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(13 148 136 / var(--tw-ring-opacity, 1))}.focus\:ring-red-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1))}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-gray-50:disabled{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.disabled\:text-gray-400:disabled{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:text-primary-600{--tw-text-opacity: 1;color:rgb(13 148 136 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:opacity-100{opacity:1}