polymo 1.4.1__tar.gz → 1.4.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. {polymo-1.4.1 → polymo-1.4.3}/PKG-INFO +1 -1
  2. {polymo-1.4.1 → polymo-1.4.3}/pyproject.toml +1 -1
  3. {polymo-1.4.1 → polymo-1.4.3}/pyproject.toml.orig +1 -1
  4. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/app.py +61 -4
  5. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/preview.py +58 -0
  6. polymo-1.4.3/src/polymo/builder/static/main.css +1 -0
  7. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/main.js +13 -13
  8. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/codegen/bundle.py +37 -14
  9. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/codegen/templates/bundle/databricks.yml.jinja +3 -2
  10. polymo-1.4.3/src/polymo/codegen/templates/bundle/pipeline.py.jinja +41 -0
  11. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/codegen/templates/bundle/readme.md.jinja +2 -1
  12. polymo-1.4.3/src/polymo/codegen/templates/bundle/source.py.jinja +134 -0
  13. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/codegen/templates/dp.py.jinja +0 -7
  14. polymo-1.4.1/src/polymo/builder/static/main.css +0 -1
  15. polymo-1.4.1/src/polymo/codegen/templates/bundle/pipeline.py.jinja +0 -7
  16. {polymo-1.4.1 → polymo-1.4.3}/README.md +0 -0
  17. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/__init__.py +0 -0
  18. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/__init__.py +0 -0
  19. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/databricks.py +0 -0
  20. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/examples/countries.polymo.json +0 -0
  21. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/examples/githubrepos.polymo.json +0 -0
  22. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/examples/jsonplaceholder.polymo.json +0 -0
  23. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/examples/jsonplaceholder_endpoints.polymo.json +0 -0
  24. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/examples/weather.polymo.json +0 -0
  25. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/favicon.ico +0 -0
  26. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/favicon.png +0 -0
  27. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/index.html +0 -0
  28. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/logo.png +0 -0
  29. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/logo192.png +0 -0
  30. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/static/mockServiceWorker.js +0 -0
  31. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/builder/templates/index.html +0 -0
  32. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/cli.py +0 -0
  33. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/codegen/__init__.py +0 -0
  34. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/codegen/generator.py +0 -0
  35. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/codegen/templates/core.py.jinja +0 -0
  36. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/codegen/templating.py +0 -0
  37. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/config.py +0 -0
  38. {polymo-1.4.1 → polymo-1.4.3}/src/polymo/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: polymo
3
- Version: 1.4.1
3
+ Version: 1.4.3
4
4
  Summary: Generate standalone Lakeflow Declarative Pipelines scripts from a point-and-click REST connector builder
5
5
  Keywords: spark,pyspark,rest,api,ingestion,data-engineering,etl,http
6
6
  Author: Daniel Tom
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "polymo"
3
- version = "1.4.1"
3
+ version = "1.4.3"
4
4
  description = "Generate standalone Lakeflow Declarative Pipelines scripts from a point-and-click REST connector builder"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "polymo"
3
- version = "1.4.1"
3
+ version = "1.4.3"
4
4
  description = "Generate standalone Lakeflow Declarative Pipelines scripts from a point-and-click REST connector builder"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -20,7 +20,7 @@ from ..codegen import CodegenError, generate, generate_bundle
20
20
  from ..codegen.generator import _identifier
21
21
  from ..config import ConfigError, RestSourceConfig, config_to_dict, parse_config
22
22
  from . import databricks
23
- from .preview import run_preview
23
+ from .preview import _infer_field_types, infer_ddl_from_records, run_preview
24
24
 
25
25
  if TYPE_CHECKING: # pragma: no cover - typing only
26
26
  from pyspark.sql import SparkSession
@@ -215,11 +215,25 @@ def create_app() -> FastAPI:
215
215
  records, dtypes = await run_in_threadpool(
216
216
  partial(_collect_records, config, payload.token, payload.limit)
217
217
  )
218
- except Exception as exc: # pragma: no cover - surfaced to UI
218
+ except Exception as exc:
219
+ # The fetch itself already succeeded (raw_pages was collected
220
+ # above, before this records/dtypes step ever ran) — only the
221
+ # local dtypes-inference step failed. Surface that as a normal
222
+ # 200 with `rest_error` set rather than a 502, so the already
223
+ # -collected `raw_pages` aren't discarded: the UI's Raw API tab
224
+ # renders `raw_pages`/`rest_error` the same way it does for an
225
+ # actual fetch failure, and the prefix below makes clear to the
226
+ # user that the request itself worked.
219
227
  detail = str(exc)
220
228
  if needles:
221
229
  detail = _redact_secret(detail, needles)
222
- raise HTTPException(status_code=502, detail=detail) from exc
230
+ return SampleResponse(
231
+ stream=stream_config.name,
232
+ records=[],
233
+ dtypes=[],
234
+ raw_pages=raw_pages,
235
+ rest_error=f"records/schema step failed: {detail}",
236
+ )
223
237
 
224
238
  if needles:
225
239
  records = _redact_secret(records, needles)
@@ -634,7 +648,50 @@ def _get_preview_df(
634
648
  """
635
649
  if schema_ddl:
636
650
  return spark.createDataFrame(records, schema=schema_ddl)
637
- return spark.createDataFrame(records)
651
+
652
+ # No explicit schema: don't hand `records` to Spark's own type
653
+ # inference. It can't cope with a column that is `None` in every
654
+ # sampled record (`[CANNOT_DETERMINE_TYPE]`) — common for XML APIs,
655
+ # where an always-empty element decodes to `None`. Instead derive a DDL
656
+ # ourselves with the same voting rules the generated script's
657
+ # `_infer_schema` uses (see `infer_ddl_from_records`), which always
658
+ # produces a type for every column seen (defaulting to STRING).
659
+ #
660
+ # A DDL-typed `createDataFrame` also requires every value to match its
661
+ # declared column type, so a dict/list value under an inferred STRING
662
+ # column would crash Spark's row conversion. Mirror the generated batch
663
+ # reader's `_cell` helper (`codegen/templates/dp.py.jinja`) and
664
+ # JSON-encode nested values first — only in this inferred-schema path;
665
+ # `records` itself (returned to the API response) is left untouched.
666
+ field_types = _infer_field_types(records)
667
+ if not field_types:
668
+ # Records exist but carry no fields at all (e.g. all `{}`) — no
669
+ # columns to declare a DDL for; fall back to letting Spark infer.
670
+ return spark.createDataFrame(records)
671
+
672
+ # Unlike Spark's own type inference, `createDataFrame(data, schema=...)`
673
+ # verifies each value strictly against its declared column type instead
674
+ # of upcasting — a plain Python `int` under a merged DOUBLE column (int
675
+ # in one sampled record, float in another) raises
676
+ # `[FIELD_DATA_TYPE_UNACCEPTABLE_WITH_NAME]` unless it's coerced to
677
+ # `float` first.
678
+ double_columns = {name for name, type_ in field_types.items() if type_ == "DOUBLE"}
679
+ safe_records = [
680
+ {
681
+ key: (
682
+ json.dumps(value)
683
+ if isinstance(value, (dict, list))
684
+ else float(value)
685
+ if key in double_columns
686
+ and isinstance(value, int)
687
+ and not isinstance(value, bool)
688
+ else value
689
+ )
690
+ for key, value in record.items()
691
+ }
692
+ for record in records
693
+ ]
694
+ return spark.createDataFrame(safe_records, schema=infer_ddl_from_records(records))
638
695
 
639
696
 
640
697
  def _get_or_create_spark() -> Any:
@@ -116,3 +116,61 @@ def run_preview(
116
116
  error = str(exc)
117
117
 
118
118
  return records, raw_pages, error
119
+
120
+
121
+ def _infer_field_types(records: List[Dict[str, Any]]) -> Dict[str, str]:
122
+ """Vote a Spark type per column across `records`; the shared core of
123
+ `infer_ddl_from_records` (also used by `_get_preview_df` in `app.py` to
124
+ know which columns need numeric coercion before `createDataFrame`).
125
+
126
+ Mirrors `_infer_schema` in `codegen/templates/core.py.jinja` — keep the
127
+ two in sync. That template function is baked into every *generated*
128
+ script (so it can re-sample the live API at run time), while this one
129
+ runs against the preview records the builder UI already fetched.
130
+
131
+ One deliberate difference from the template: a column whose value is
132
+ `None` in every sampled record casts no type vote there, so the
133
+ template's `_infer_schema` just omits it from the DDL entirely (dropping
134
+ the column). That's fine for a generated script, which raises loudly if
135
+ sampling ever comes up completely empty. For the builder preview it
136
+ means the column silently vanishes from `dtypes` instead of showing up
137
+ as unknown/empty — worse, unqualified `spark.createDataFrame(records)`
138
+ (no schema at all) actually *crashes* with `[CANNOT_DETERMINE_TYPE]` in
139
+ this situation, which is the bug this function exists to fix (typical
140
+ for XML APIs, where an always-empty element decodes to `None` on every
141
+ record). So here, a no-vote column defaults to STRING instead of being
142
+ dropped.
143
+ """
144
+ columns: Dict[str, Optional[str]] = {}
145
+ for record in records:
146
+ for key, value in record.items():
147
+ columns.setdefault(key, None)
148
+ if value is None:
149
+ continue
150
+ if isinstance(value, bool):
151
+ candidate = "BOOLEAN"
152
+ elif isinstance(value, int):
153
+ candidate = "BIGINT"
154
+ elif isinstance(value, float):
155
+ candidate = "DOUBLE"
156
+ else:
157
+ candidate = "STRING"
158
+ current = columns[key]
159
+ if current is None:
160
+ columns[key] = candidate
161
+ elif current == candidate:
162
+ pass
163
+ elif {current, candidate} == {"BIGINT", "DOUBLE"}:
164
+ columns[key] = "DOUBLE"
165
+ else:
166
+ columns[key] = "STRING"
167
+ return {name: type_ or "STRING" for name, type_ in columns.items()}
168
+
169
+
170
+ def infer_ddl_from_records(records: List[Dict[str, Any]]) -> str:
171
+ """Infer a Spark DDL schema string from already-collected preview records.
172
+
173
+ See `_infer_field_types` for the voting rules this applies.
174
+ """
175
+ fields = _infer_field_types(records)
176
+ return ", ".join(f"`{name}` {type_}" for name, type_ in fields.items())
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap";*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family: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%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.right-3{right:.75rem}.top-0{top:0}.top-1\/2{top:50%}.top-full{top:100%}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-auto{margin-top:auto}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.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-8{height:2rem}.h-9{height:2.25rem}.h-\[520px\]{height:520px}.h-full{height:100%}.max-h-60{max-height:15rem}.min-h-\[260px\]{min-height:260px}.min-h-\[90px\]{min-height:90px}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-60{width:15rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.min-w-0{min-width:0px}.min-w-full{min-width:100%}.min-w-max{min-width:-moz-max-content;min-width:max-content}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-7xl{max-width:80rem}.max-w-\[140px\]{max-width:140px}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-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))}.translate-y-2{--tw-translate-y: .5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.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))}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.list-disc{list-style-type:disc}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.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-12{gap:3rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-blue-7\/40{border-color:#8ec8f666}.border-border{--tw-border-opacity: 1;border-color:rgb(219 216 224 / var(--tw-border-opacity, 1))}.border-border\/60{border-color:#dbd8e099}.border-border\/70{border-color:#dbd8e0b3}.border-error\/40{border-color:#e5484d66}.border-red-6{--tw-border-opacity: 1;border-color:rgb(253 189 190 / var(--tw-border-opacity, 1))}.bg-background{--tw-bg-opacity: 1;background-color:rgb(250 249 251 / var(--tw-bg-opacity, 1))}.bg-background\/60{background-color:#faf9fb99}.bg-background\/70{background-color:#faf9fbb3}.bg-background\/80{background-color:#faf9fbcc}.bg-black\/50{background-color:#00000080}.bg-blue-3\/40{background-color:#e6f4fe66}.bg-blue-4\/50{background-color:#d5efff80}.bg-blue-5{--tw-bg-opacity: 1;background-color:rgb(194 229 255 / var(--tw-bg-opacity, 1))}.bg-blue-9{--tw-bg-opacity: 1;background-color:rgb(0 144 255 / var(--tw-bg-opacity, 1))}.bg-current{background-color:currentColor}.bg-error{--tw-bg-opacity: 1;background-color:rgb(229 72 77 / var(--tw-bg-opacity, 1))}.bg-muted\/50{background-color:#bcbac780}.bg-red-3\/20{background-color:#feebec33}.bg-red-3\/60{background-color:#feebec99}.bg-slate-12{--tw-bg-opacity: 1;background-color:rgb(28 32 36 / var(--tw-bg-opacity, 1))}.bg-slate-2{--tw-bg-opacity: 1;background-color:rgb(249 249 251 / var(--tw-bg-opacity, 1))}.bg-surface{--tw-bg-opacity: 1;background-color:rgb(242 239 243 / var(--tw-bg-opacity, 1))}.bg-surface\/60{background-color:#f2eff399}.bg-surface\/70{background-color:#f2eff3b3}.bg-surface\/80{background-color:#f2eff3cc}.bg-surface\/90{background-color:#f2eff3e6}.bg-surface\/95{background-color:#f2eff3f2}.bg-transparent{background-color:transparent}.object-contain{-o-object-fit:contain;object-fit:contain}.p-1{padding:.25rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-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-8{padding-top:2rem;padding-bottom:2rem}.pl-4{padding-left:1rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.align-top{vertical-align:top}.align-bottom{vertical-align:bottom}.font-mono{font-family:JetBrains Mono,ui-monospace,SFMono-Regular,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.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-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}.leading-5{line-height:1.25rem}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.text-background-foreground{--tw-text-opacity: 1;color:rgb(33 31 38 / var(--tw-text-opacity, 1))}.text-blue-11{--tw-text-opacity: 1;color:rgb(13 116 206 / var(--tw-text-opacity, 1))}.text-blue-7{--tw-text-opacity: 1;color:rgb(142 200 246 / var(--tw-text-opacity, 1))}.text-blue-9{--tw-text-opacity: 1;color:rgb(0 144 255 / var(--tw-text-opacity, 1))}.text-error{--tw-text-opacity: 1;color:rgb(229 72 77 / var(--tw-text-opacity, 1))}.text-muted{--tw-text-opacity: 1;color:rgb(188 186 199 / var(--tw-text-opacity, 1))}.text-red-10{--tw-text-opacity: 1;color:rgb(220 62 66 / var(--tw-text-opacity, 1))}.text-red-11{--tw-text-opacity: 1;color:rgb(206 44 49 / var(--tw-text-opacity, 1))}.text-slate-10{--tw-text-opacity: 1;color:rgb(128 131 141 / var(--tw-text-opacity, 1))}.text-slate-11{--tw-text-opacity: 1;color:rgb(96 100 108 / var(--tw-text-opacity, 1))}.text-slate-12{--tw-text-opacity: 1;color:rgb(28 32 36 / var(--tw-text-opacity, 1))}.text-slate-9{--tw-text-opacity: 1;color:rgb(139 141 152 / var(--tw-text-opacity, 1))}.text-warning{--tw-text-opacity: 1;color:rgb(255 197 61 / 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}.accent-blue-9{accent-color:#0090ff}.opacity-0{opacity:0}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-soft{--tw-shadow: 0 10px 40px -15px rgba(15, 23, 42, .25);--tw-shadow-colored: 0 10px 40px -15px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-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-none{outline:2px solid transparent;outline-offset:2px}.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-border\/40{--tw-ring-color: rgb(219 216 224 / .4)}.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{--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-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-filter{-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-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}:root{color-scheme:light dark}body{--tw-bg-opacity: 1;background-color:rgb(250 249 251 / var(--tw-bg-opacity, 1));font-family:Inter,system-ui,sans-serif;--tw-text-opacity: 1;color:rgb(33 31 38 / var(--tw-text-opacity, 1));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.dark body{background-color:#282a36}.theme-fade{animation:theme-fade .24s ease-out}@keyframes theme-fade{0%{opacity:.4;filter:saturate(.6) brightness(.9)}to{opacity:1;filter:none}}.animate-param-enter{animation:param-enter .22s ease-out}@keyframes param-enter{0%{opacity:0;transform:scale(.97) translateY(4px)}to{opacity:1;transform:scale(1) translateY(0)}}.modern-select{width:100%;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(219 216 224 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(250 249 251 / var(--tw-bg-opacity, 1));padding:.5rem 2.25rem .5rem .75rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(28 32 36 / var(--tw-text-opacity, 1));--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property: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}.dark .modern-select{background-color:#282a36;border-color:#44475a;color:#f8f8f2}.modern-select:focus-visible{--tw-border-opacity: 1;border-color:rgb(142 200 246 / var(--tw-border-opacity, 1));outline:2px solid transparent;outline-offset:2px}.modern-select:is(.dark *){--tw-border-opacity: 1;border-color:rgb(68 71 90 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(48 50 65 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(248 248 242 / var(--tw-text-opacity, 1))}.modern-select:focus-visible:is(.dark *){--tw-border-opacity: 1;border-color:rgb(189 147 249 / var(--tw-border-opacity, 1))}.dark input:not([type=checkbox]),.dark textarea,.dark select{--tw-border-opacity: 1;border-color:rgb(68 71 90 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(48 50 65 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(248 248 242 / var(--tw-text-opacity, 1))}.dark input:not([type=checkbox])::-moz-placeholder,.dark textarea::-moz-placeholder,.dark select::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(98 114 164 / var(--tw-placeholder-opacity, 1))}.dark input:not([type=checkbox])::placeholder,.dark textarea::placeholder,.dark select::placeholder{--tw-placeholder-opacity: 1;color:rgb(98 114 164 / var(--tw-placeholder-opacity, 1))}.dark ::-moz-placeholder{--tw-text-opacity: 1;color:rgb(98 114 164 / var(--tw-text-opacity, 1))}.dark ::placeholder{--tw-text-opacity: 1;color:rgb(98 114 164 / var(--tw-text-opacity, 1))}.dark .bg-background{background-color:#282a36!important}.dark .bg-surface{background-color:#303241!important}.dark .border-border{border-color:#44475a!important}.dark .text-muted{color:#6272a4!important}.dark .shadow-soft{box-shadow:0 10px 40px -15px #000000a6}.dark .text-slate-12,.dark .text-slate-11,.dark .text-slate-10{color:#f8f8f2!important}.dark .text-slate-9,.dark .text-slate-8{color:#6272a4!important}.dark .group:hover.bg-background\/60{background-color:#484c5e8c!important}.radix-scroll-area-scrollbar{display:flex;touch-action:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;background-color:transparent;padding:.125rem;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-timing-function:cubic-bezier(0,0,.2,1)}.radix-scroll-area-thumb{flex:1 1 0%;border-radius:9999px;--tw-bg-opacity: 1;background-color:rgb(188 186 199 / var(--tw-bg-opacity, 1))}.radix-scroll-area-thumb:hover{--tw-bg-opacity: 1;background-color:rgb(142 140 153 / var(--tw-bg-opacity, 1))}.radix-scroll-area-thumb:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(68 71 90 / var(--tw-bg-opacity, 1))}.radix-scroll-area-thumb:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(98 114 164 / var(--tw-bg-opacity, 1))}button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(142 200 246 / var(--tw-ring-opacity, 1));--tw-ring-offset-width: 2px;--tw-ring-offset-color: #f2eff3}button:focus-visible:is(.dark *),input:focus-visible:is(.dark *),textarea:focus-visible:is(.dark *),select:focus-visible:is(.dark *){--tw-ring-opacity: 1;--tw-ring-color: rgb(189 147 249 / var(--tw-ring-opacity, 1));--tw-ring-offset-color: #303241}[data-status=success]{--tw-text-opacity: 1;color:rgb(48 164 108 / var(--tw-text-opacity, 1))}[data-status=warn],[data-status=warning]{--tw-text-opacity: 1;color:rgb(255 197 61 / var(--tw-text-opacity, 1))}[data-status=error]{--tw-text-opacity: 1;color:rgb(229 72 77 / var(--tw-text-opacity, 1))}[data-status=info]{--tw-text-opacity: 1;color:rgb(13 116 206 / var(--tw-text-opacity, 1))}[data-status=info]:is(.dark *){--tw-text-opacity: 1;color:rgb(189 147 249 / var(--tw-text-opacity, 1))}pre{overflow-x:auto;border-radius:.5rem;--tw-bg-opacity: 1;background-color:rgb(249 249 251 / var(--tw-bg-opacity, 1));padding:1rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(28 32 36 / var(--tw-text-opacity, 1))}.dark pre{color:#f8f8f2}pre:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(48 50 65 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(248 248 242 / var(--tw-text-opacity, 1))}.dark table thead tr{background-color:#ffffff0a!important}.dark table tbody tr.even\:bg-slate-2\/40{background-color:#ffffff05!important}.dark table tbody tr:hover{background-color:#bd93f91f!important}.prism-container{position:relative;height:100%;font-family:JetBrains Mono,ui-monospace,SFMono-Regular,monospace;font-size:.875rem;line-height:1.25rem}.prism-editor{position:absolute;inset:0;height:100%;width:100%;resize:none;background-color:transparent;line-height:1.25rem;color:transparent;caret-color:#fff;outline:2px solid transparent;outline-offset:2px}.prism-highlight{pointer-events:none;white-space:pre-wrap;overflow-wrap:break-word;text-align:left;font-family:JetBrains Mono,ui-monospace,SFMono-Regular,monospace;line-height:1.25rem}.dark .prism-highlight{color:#f8f8f2}.prism-highlight .token.comment{color:#6272a4}.prism-highlight .token.key{color:#ff79c6}.prism-highlight .token.punctuation{color:#f8f8f2}.prism-highlight .token.string{color:#f1fa8c}.prism-highlight .token.number{color:#bd93f9}.prism-highlight .token.boolean{color:#ffb86c}.prism-highlight .token.null{color:#f55}.prism-highlight .token.directive{color:#8be9fd}.prism-highlight{position:relative;--ch: .62ch}.prism-highlight .editor-line{position:relative;padding-left:0}.prism-highlight .editor-line:before{content:attr(data-line);position:absolute;left:-.75rem;transform:translate(-100%);width:3rem;text-align:right;padding-right:.75rem;color:#64748b;font-size:.75rem;line-height:1.25rem;font-variant-numeric:tabular-nums;opacity:.65}.dark .prism-highlight .editor-line:before{color:#6272a4;opacity:.55}.prism-highlight .editor-line.error{background:#ff55551a;box-shadow:inset 0 0 0 1px #ff555559}.dark .prism-highlight .editor-line.error{background:#ff55552b;box-shadow:inset 0 0 0 1px #ff555573}.prism-highlight .editor-line .col-marker{position:absolute;top:0;bottom:0;width:2px;background:#f55;left:calc(var(--col) * var(--ch));pointer-events:none;opacity:.4}.dark .prism-highlight .editor-line .col-marker{background:#f55;opacity:.55}.prism-highlight .editor-line .err-char{background:linear-gradient(transparent 70%,#ff55558c 70%);border-radius:2px}.dark .prism-highlight .editor-line .err-char{background:linear-gradient(transparent 65%,#ff5555bf 65%)}.prism-highlight::-webkit-scrollbar{width:10px;height:10px}.prism-highlight::-webkit-scrollbar-track{background:transparent}.prism-highlight::-webkit-scrollbar-thumb{background:#64748b59;border-radius:6px}.dark .prism-highlight::-webkit-scrollbar-thumb{background:#f8f8f233}.prism-highlight::-webkit-scrollbar-thumb:hover{background:#64748b8c}.dark .prism-highlight::-webkit-scrollbar-thumb:hover{background:#f8f8f259}.prism-highlight,.prism-highlight .editor-line,.prism-highlight .line-content{pointer-events:none}.prism-editor{color:transparent;text-shadow:none}.dark .prism-editor{color:transparent}.prism-editor{caret-color:#111}.dark .prism-editor{caret-color:#f8f8f2}[role=tooltip]{animation:fadeIn .12s ease-out}@keyframes fadeIn{0%{opacity:0;transform:translate(-50%,4px)}to{opacity:1;transform:translate(-50%)}}.dark .btn-accent{--tw-bg-opacity: 1;background-color:rgb(189 147 249 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(248 248 242 / var(--tw-text-opacity, 1))}.dark .btn-accent:hover{--tw-bg-opacity: 1;background-color:rgb(255 121 198 / var(--tw-bg-opacity, 1))}.dark .border-accent{--tw-border-opacity: 1;border-color:rgb(189 147 249 / var(--tw-border-opacity, 1))}.validate-flash-success{animation:validateFlashSuccess 4s ease-in-out forwards}.validate-flash-error{animation:validateFlashError 4s ease-in-out forwards}@keyframes validateFlashSuccess{0%,85%{background:#30a46c;color:#fff}to{background:transparent;color:inherit}}@keyframes validateFlashError{0%,85%{background:#e5484d;color:#fff}to{background:transparent;color:inherit}}.dark button.validate-flash-success,.dark .validate-flash-success{animation:darkValidateFlashSuccess 4s ease-in-out forwards;position:relative}.dark button.validate-flash-error,.dark .validate-flash-error{animation:darkValidateFlashError 4s ease-in-out forwards;position:relative}.dark button.validate-flash-success:after,.dark .validate-flash-success:after,.dark button.validate-flash-error:after,.dark .validate-flash-error:after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none}.dark button.validate-flash-success:after,.dark .validate-flash-success:after{background:radial-gradient(circle at 30% 30%,#50fa7b59,#50fa7b0d)}.dark button.validate-flash-error:after,.dark .validate-flash-error:after{background:radial-gradient(circle at 30% 30%,#f556,#ff55550f)}@keyframes darkValidateFlashSuccess{0%,85%{background-color:#50fa7b40!important;color:#fff!important;border-color:#50fa7b8c!important;box-shadow:0 0 #50fa7b99,0 0 16px 4px #50fa7b59}to{background-color:transparent!important;color:inherit!important;border-color:var(--border-color,rgba(100,100,120,.4))!important;box-shadow:none}}@keyframes darkValidateFlashError{0%,85%{background-color:#ff555547!important;color:#fff!important;border-color:#ff55558c!important;box-shadow:0 0 #f559,0 0 16px 4px #ff555561}to{background-color:transparent!important;color:inherit!important;border-color:var(--border-color,rgba(100,100,120,.4))!important;box-shadow:none}}.even\:bg-slate-2\/40:nth-child(2n){background-color:#f9f9fb66}.hover\:scale-105:hover{--tw-scale-x: 1.05;--tw-scale-y: 1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-blue-7:hover{--tw-border-opacity: 1;border-color:rgb(142 200 246 / var(--tw-border-opacity, 1))}.hover\:border-blue-7\/60:hover{border-color:#8ec8f699}.hover\:border-red-7:hover{--tw-border-opacity: 1;border-color:rgb(244 169 170 / var(--tw-border-opacity, 1))}.hover\:bg-blue-10:hover{--tw-bg-opacity: 1;background-color:rgb(5 136 240 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-3\/20:hover{background-color:#e6f4fe33}.hover\:bg-blue-3\/40:hover{background-color:#e6f4fe66}.hover\:bg-blue-3\/50:hover{background-color:#e6f4fe80}.hover\:bg-blue-5\/10:hover{background-color:#c2e5ff1a}.hover\:bg-red-3\/40:hover{background-color:#feebec66}.hover\:bg-red-3\/60:hover{background-color:#feebec99}.hover\:bg-slate-3:hover{--tw-bg-opacity: 1;background-color:rgb(240 240 243 / var(--tw-bg-opacity, 1))}.hover\:text-blue-11:hover{--tw-text-opacity: 1;color:rgb(13 116 206 / var(--tw-text-opacity, 1))}.hover\:text-red-10:hover{--tw-text-opacity: 1;color:rgb(220 62 66 / var(--tw-text-opacity, 1))}.hover\:text-red-9:hover{--tw-text-opacity: 1;color:rgb(229 72 77 / var(--tw-text-opacity, 1))}.hover\:text-slate-12:hover{--tw-text-opacity: 1;color:rgb(28 32 36 / 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-blue-7:focus{--tw-border-opacity: 1;border-color:rgb(142 200 246 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-blue-5:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(194 229 255 / var(--tw-ring-opacity, 1))}.focus\:ring-blue-7:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(142 200 246 / var(--tw-ring-opacity, 1))}.focus-visible\:border-blue-7:focus-visible{--tw-border-opacity: 1;border-color:rgb(142 200 246 / var(--tw-border-opacity, 1))}.focus-visible\:bg-blue-9:focus-visible{--tw-bg-opacity: 1;background-color:rgb(0 144 255 / var(--tw-bg-opacity, 1))}.focus-visible\:text-white:focus-visible{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.focus-visible\:opacity-100:focus-visible{opacity:1}.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-2: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(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-visible\:ring-blue-5:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(194 229 255 / var(--tw-ring-opacity, 1))}.focus-visible\:ring-blue-7:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(142 200 246 / var(--tw-ring-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.group:hover .group-hover\:border-blue-7\/50{border-color:#8ec8f680}.group:hover .group-hover\:bg-blue-5\/80{background-color:#c2e5ffcc}.group:hover .group-hover\:opacity-100{opacity:1}.data-\[state\=active\]\:border-b-2[data-state=active]{border-bottom-width:2px}.data-\[state\=active\]\:border-blue-9[data-state=active]{--tw-border-opacity: 1;border-color:rgb(0 144 255 / var(--tw-border-opacity, 1))}.data-\[state\=active\]\:bg-blue-9[data-state=active]{--tw-bg-opacity: 1;background-color:rgb(0 144 255 / var(--tw-bg-opacity, 1))}.data-\[state\=checked\]\:bg-blue-4[data-state=checked]{--tw-bg-opacity: 1;background-color:rgb(213 239 255 / var(--tw-bg-opacity, 1))}.data-\[state\=active\]\:text-blue-11[data-state=active]{--tw-text-opacity: 1;color:rgb(13 116 206 / var(--tw-text-opacity, 1))}.data-\[state\=active\]\:text-white[data-state=active]{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.data-\[state\=active\]\:shadow-sm[data-state=active]{--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)}@supports (backdrop-filter: var(--tw)){.supports-\[backdrop-filter\]\:bg-slate-2\/75{background-color:#f9f9fbbf}}.dark\:border-\[\#2c313a\]:is(.dark *){--tw-border-opacity: 1;border-color:rgb(44 49 58 / var(--tw-border-opacity, 1))}.dark\:border-drac-accent\/40:is(.dark *){border-color:#bd93f966}.dark\:border-drac-border:is(.dark *){--tw-border-opacity: 1;border-color:rgb(68 71 90 / var(--tw-border-opacity, 1))}.dark\:border-drac-border\/50:is(.dark *){border-color:#44475a80}.dark\:border-drac-border\/60:is(.dark *){border-color:#44475a99}.dark\:border-drac-border\/70:is(.dark *){border-color:#44475ab3}.dark\:border-drac-red\/40:is(.dark *){border-color:#f556}.dark\:border-slate-6:is(.dark *){--tw-border-opacity: 1;border-color:rgb(217 217 224 / var(--tw-border-opacity, 1))}.dark\:bg-\[\#1d2026\]:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(29 32 38 / var(--tw-bg-opacity, 1))}.dark\:bg-\[\#1f232b\]:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(31 35 43 / var(--tw-bg-opacity, 1))}.dark\:bg-\[\#1f232b\]\/60:is(.dark *){background-color:#1f232b99}.dark\:bg-\[\#1f232b\]\/80:is(.dark *){background-color:#1f232bcc}.dark\:bg-\[\#202530\]:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(32 37 48 / var(--tw-bg-opacity, 1))}.dark\:bg-\[\#242a33\]:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(36 42 51 / var(--tw-bg-opacity, 1))}.dark\:bg-\[\#262c35\]:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(38 44 53 / var(--tw-bg-opacity, 1))}.dark\:bg-\[\#272d38\]:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(39 45 56 / var(--tw-bg-opacity, 1))}.dark\:bg-\[\#282a36\]\/50:is(.dark *){background-color:#282a3680}.dark\:bg-\[\#282a36\]\/70:is(.dark *){background-color:#282a36b3}.dark\:bg-\[\#2d3541\]:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(45 53 65 / var(--tw-bg-opacity, 1))}.dark\:bg-\[\#303745\]:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(48 55 69 / var(--tw-bg-opacity, 1))}.dark\:bg-blue-7\/40:is(.dark *){background-color:#8ec8f666}.dark\:bg-blue-9\/20:is(.dark *){background-color:#0090ff33}.dark\:bg-drac-accent:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(189 147 249 / var(--tw-bg-opacity, 1))}.dark\:bg-drac-accent\/15:is(.dark *){background-color:#bd93f926}.dark\:bg-drac-base:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(40 42 54 / var(--tw-bg-opacity, 1))}.dark\:bg-drac-red\/25:is(.dark *){background-color:#ff555540}.dark\:bg-drac-surface:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(48 50 65 / var(--tw-bg-opacity, 1))}.dark\:bg-drac-surface\/60:is(.dark *){background-color:#30324199}.dark\:bg-drac-surface\/70:is(.dark *){background-color:#303241b3}.dark\:bg-drac-surface\/80:is(.dark *){background-color:#303241cc}.dark\:bg-slate-1:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(252 252 253 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-2:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(249 249 251 / var(--tw-bg-opacity, 1))}.dark\:text-blue-9:is(.dark *){--tw-text-opacity: 1;color:rgb(0 144 255 / var(--tw-text-opacity, 1))}.dark\:text-drac-accent:is(.dark *){--tw-text-opacity: 1;color:rgb(189 147 249 / var(--tw-text-opacity, 1))}.dark\:text-drac-foreground:is(.dark *){--tw-text-opacity: 1;color:rgb(248 248 242 / var(--tw-text-opacity, 1))}.dark\:text-drac-foreground\/80:is(.dark *){color:#f8f8f2cc}.dark\:text-drac-foreground\/90:is(.dark *){color:#f8f8f2e6}.dark\:text-drac-muted:is(.dark *){--tw-text-opacity: 1;color:rgb(98 114 164 / var(--tw-text-opacity, 1))}.dark\:text-slate-12:is(.dark *){--tw-text-opacity: 1;color:rgb(28 32 36 / var(--tw-text-opacity, 1))}.dark\:accent-drac-accent:is(.dark *){accent-color:#bd93f9}.dark\:shadow-\[0_8px_24px_-6px_rgba\(0\,0\,0\,0\.7\)\]:is(.dark *){--tw-shadow: 0 8px 24px -6px rgba(0,0,0,.7);--tw-shadow-colored: 0 8px 24px -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)}.dark\:ring-drac-border\/30:is(.dark *){--tw-ring-color: rgb(68 71 90 / .3)}.dark\:hover\:border-drac-accent:hover:is(.dark *){--tw-border-opacity: 1;border-color:rgb(189 147 249 / var(--tw-border-opacity, 1))}.dark\:hover\:border-drac-accent\/60:hover:is(.dark *){border-color:#bd93f999}.dark\:hover\:border-drac-red\/80:hover:is(.dark *){border-color:#f55c}.dark\:hover\:bg-\[\#273242\]:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(39 50 66 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-\[\#283546\]:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(40 53 70 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-\[\#383f4c\]:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(56 63 76 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-\[\#3a3f4b\]:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(58 63 75 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-blue-9\/10:hover:is(.dark *){background-color:#0090ff1a}.dark\:hover\:bg-blue-9\/20:hover:is(.dark *){background-color:#0090ff33}.dark\:hover\:bg-blue-9\/25:hover:is(.dark *){background-color:#0090ff40}.dark\:hover\:bg-drac-base\/60:hover:is(.dark *){background-color:#282a3699}.dark\:hover\:text-drac-accent:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(189 147 249 / var(--tw-text-opacity, 1))}.dark\:hover\:text-drac-foreground:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(248 248 242 / var(--tw-text-opacity, 1))}.dark\:hover\:text-drac-red:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(255 85 85 / var(--tw-text-opacity, 1))}.dark\:hover\:shadow-\[0_0_8px_rgba\(80\,250\,123\,0\.15\)\]:hover:is(.dark *){--tw-shadow: 0 0 8px rgba(80,250,123,.15);--tw-shadow-colored: 0 0 8px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.dark\:focus\:border-drac-accent:focus:is(.dark *){--tw-border-opacity: 1;border-color:rgb(189 147 249 / var(--tw-border-opacity, 1))}.dark\:focus\:ring-drac-accent:focus:is(.dark *){--tw-ring-opacity: 1;--tw-ring-color: rgb(189 147 249 / var(--tw-ring-opacity, 1))}.dark\:focus-visible\:border-drac-accent:focus-visible:is(.dark *){--tw-border-opacity: 1;border-color:rgb(189 147 249 / var(--tw-border-opacity, 1))}.dark\:focus-visible\:bg-drac-accent:focus-visible:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(189 147 249 / var(--tw-bg-opacity, 1))}.dark\:focus-visible\:ring-drac-accent:focus-visible:is(.dark *){--tw-ring-opacity: 1;--tw-ring-color: rgb(189 147 249 / var(--tw-ring-opacity, 1))}.dark\:focus-visible\:ring-drac-accent\/40:focus-visible:is(.dark *){--tw-ring-color: rgb(189 147 249 / .4)}.group:hover .dark\:group-hover\:bg-blue-9\/30:is(.dark *){background-color:#0090ff4d}.dark\:data-\[state\=active\]\:border-drac-accent[data-state=active]:is(.dark *){--tw-border-opacity: 1;border-color:rgb(189 147 249 / var(--tw-border-opacity, 1))}.dark\:data-\[state\=active\]\:text-drac-accent[data-state=active]:is(.dark *){--tw-text-opacity: 1;color:rgb(189 147 249 / var(--tw-text-opacity, 1))}@supports (backdrop-filter: var(--tw)){.dark\:supports-\[backdrop-filter\]\:bg-drac-surface\/70:is(.dark *){background-color:#303241b3}}@media(min-width:768px){.md\:col-span-1{grid-column:span 1 / span 1}.md\:col-span-2{grid-column:span 2 / span 2}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:1024px){.lg\:grid-cols-\[minmax\(0\,1fr\)_minmax\(200px\,auto\)\]{grid-template-columns:minmax(0,1fr) minmax(200px,auto)}.lg\:items-end{align-items:flex-end}.lg\:px-6{padding-left:1.5rem;padding-right:1.5rem}}.\[\&_td\]\:whitespace-nowrap td{white-space:nowrap}.\[\&_td\]\:whitespace-pre-wrap td{white-space:pre-wrap}