From d5153f1de33ad983f2d56d02054b530ed7998c3d Mon Sep 17 00:00:00 2001 From: maziggy Date: Tue, 28 Apr 2026 16:36:49 +0200 Subject: [PATCH] feat(slicer): live progress + filament discovery polish + OrcaSlicer warning End-to-end live progress, two correctness fixes, and a UX warning around the upstream OrcaSlicer bugs we discovered while testing. LIVE PROGRESS ============= Wire OrcaSlicer / BambuStudio's --pipe progress channel through the sidecar -> Bambuddy -> persistent toast so a user-initiated slice shows "{name} -- Generating G-code (75%) -- 47s" instead of just elapsed time. The same wiring covers the SliceModal's filament-analysis preview slice (the real slice that fires before profile picking, used to discover which AMS slots an unsliced plate consumes) and the embedded-settings fallback path triggered by Orca's --load-settings segfault on complex H2D models. - Sidecar (orca-slicer-api/bambuddy/profile-resolver, separate commit): switch /slice from execFile to spawn, mkfifo per request, parse the CLI's structured JSON progress events into a per-process ProgressStore, expose GET /slice/progress/:requestId. - Bambuddy backend: slicer_api.slice_with_profiles + slice_without_profiles accept request_id + on_progress, spawn a 1Hz parallel poller that forwards each snapshot via SliceDispatchService.set_progress(job_id, ...) onto the matching SliceJob; GET /slice-jobs/:id includes the latest snapshot on every poll. The 404 from the early-race window (POST fired before sidecar's progressStore.start) is treated as a retry rather than terminal -- otherwise the poller bailed before any progress could ever arrive. - /api/v1/slicer/preview-progress/:requestId proxies the sidecar's progress endpoint for the modal's filament-discovery flow (the /filament-requirements call is server-originated; the browser can't reach the sidecar directly). - Frontend: SliceJobTrackerContext re-renders the persistent toast with the new format when a useful progress frame is present, falls back to elapsed-time-only when the sidecar hasn't emitted yet or doesn't support progress. SliceModal.FilamentAnalysisSpinner generates a per-(source, plate) UUID, polls the proxy at 1Hz, and mirrors the inline spinner contents into a separate persistent toast so the preview slice doesn't feel silent either. CORRECTNESS FIXES ================= - MakerWorld imports were persisting URL-encoded filenames verbatim ("stormtrooper-helmet%20h2d.3mf"). Backend now urllib.parse.unquote s the manifest-supplied name and the URL path-tail fallback before passing to save_3mf_bytes_to_library; frontend defensively decodeURIComponent s in the slice toast / analysis spinner so already-imported rows display cleanly without a backfill migration. - The fallback path's slice_without_profiles call now forwards the same request_id + on_progress as the primary slice_with_profiles call so the toast keeps updating across the segfault -> embedded- settings retry boundary instead of going blank. ORCASLICER WARNING ================== Verified two upstream OrcaSlicer CLI bugs reproduce on the latest nightly (2.4.0-dev, 2026-04-28) with the help of an isolated AppImage extract and a minimal sentinel-value-injected cube fixture: - OrcaSlicer/OrcaSlicer#12426 -- SIGSEGV in update_values_to_printer_extruders_for_multiple_filaments on painted multi-extruder 3MFs (commented on the existing thread, not a new issue) - OrcaSlicer/OrcaSlicer#13386 -- CLI strict-validates parameter values BambuStudio writes by default (solid_infill_filament: 0, tree_support_wall_count: -1, prime_tower_brim_width: -1) and rejects with exit 238, even though Orca's own GUI tolerates them (filed by us alongside this change) Settings -> Workflow -> Slicer card renders an amber inline warning under the preferred-slicer dropdown when orcaslicer is selected, linking both upstream issues and recommending BambuStudio until the fixes land. Option stays pickable -- users who only slice STLs aren't affected by either bug. --- CHANGELOG.md | 6 + backend/app/api/routes/archives.py | 10 +- backend/app/api/routes/library.py | 50 +- backend/app/api/routes/makerworld.py | 14 +- backend/app/api/routes/slice_jobs.py | 4 + backend/app/api/routes/slicer_presets.py | 44 + backend/app/services/slice_dispatch.py | 32 +- backend/app/services/slice_preview.py | 2 + backend/app/services/slicer_api.py | 102 ++ .../services/test_slice_dispatch_progress.py | 109 +++ .../tests/unit/services/test_slicer_api.py | 154 +++ .../contexts/SliceJobTrackerContext.test.tsx | 121 +++ frontend/src/api/client.ts | 51 +- frontend/src/components/SliceModal.tsx | 125 ++- .../src/contexts/SliceJobTrackerContext.tsx | 63 +- frontend/src/i18n/locales/de.ts | 4 + frontend/src/i18n/locales/en.ts | 4 + frontend/src/i18n/locales/fr.ts | 4 + frontend/src/i18n/locales/it.ts | 4 + frontend/src/i18n/locales/ja.ts | 4 + frontend/src/i18n/locales/pt-BR.ts | 4 + frontend/src/i18n/locales/zh-CN.ts | 4 + frontend/src/i18n/locales/zh-TW.ts | 4 + frontend/src/pages/SettingsPage.tsx | 19 + static/assets/index-Bbpbjxtl.css | 1 - .../{index-B6Qs-684.js => index-DRnoASko.js} | 876 +++++++++--------- static/assets/index-DrRF4CKf.css | 1 + static/index.html | 4 +- 28 files changed, 1347 insertions(+), 473 deletions(-) create mode 100644 backend/tests/unit/services/test_slice_dispatch_progress.py delete mode 100644 static/assets/index-Bbpbjxtl.css rename static/assets/{index-B6Qs-684.js => index-DRnoASko.js} (73%) create mode 100644 static/assets/index-DrRF4CKf.css diff --git a/CHANGELOG.md b/CHANGELOG.md index 8abae31b2..0ca2850b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,12 @@ All notable changes to Bambuddy will be documented in this file. - **"Analyzing plate filaments…" spinner gave no signal that anything was happening on the first Slice-modal open for an unsliced project file** — On a multi-color 3MF without slice_info data, the backend runs a preview slice via the sidecar to discover which AMS slots the picked plate actually consumes. That's the only source of truth: tried two heuristics — painted-face quadtree scan (silently missed extruders when `object_id` mapping between `model_settings.config` and `3D/3dmodel.model` diverged, surfaced as a single dropdown for a 4-color print) and project-wide AMS list (over-rendered every plate to the project's full slot count) — and both produced wrong counts on real-world multi-color projects. Reverted to preview-slice-as-source-of-truth. The result is cached per `(kind, source_id, plate_id, content_hash)` so re-opens of the same plate are instant, but the first open on a complex model is a real slice (multi-second to multi-minute). The inline spinner now shows elapsed seconds and, after 5s, a hint explaining that this is a one-time preview slice and re-opens will be instant — addresses the original "is anything happening?" complaint without sacrificing correctness. Project-wide `extract_project_filaments_from_3mf` remains as a final fallback when the sidecar isn't configured. New i18n key `slice.analyzingPlateFilamentsHint` localised across all 8 UI languages (English + German fully translated, the six others seeded with English copies pending native translation, matching the project's existing flow for newly-added user-facing features). +- **Settings warning when OrcaSlicer is selected as the preferred slicer** — OrcaSlicer 2.3.2 and 2.4.0-dev (latest nightly as of 2026-04-28) have two upstream CLI bugs that together block slicing on most Bambu-authored multi-color / H2D 3MFs: (1) a SIGSEGV in the multi-extruder filament-resolution path on painted 3MFs ([OrcaSlicer/OrcaSlicer#12426](https://github.com/OrcaSlicer/OrcaSlicer/issues/12426)), and (2) the CLI strict-validates parameter values that BambuStudio writes by default — `solid_infill_filament: 0`, `tree_support_wall_count: -1`, `prime_tower_brim_width: -1` — and exits 238 with `Param values in 3mf/config error: ... not in range`, even though OrcaSlicer's own GUI tolerates these ([OrcaSlicer/OrcaSlicer#13386](https://github.com/OrcaSlicer/OrcaSlicer/issues/13386), filed alongside this change with a minimal repro 3MF). Both bugs verified reproducible on the latest nightly build before filing. Settings → Workflow → Slicer card now renders an inline amber alert under the preferred-slicer dropdown when `orcaslicer` is the current selection, linking out to both upstream issues and recommending Bambu Studio until upstream fixes land. The OrcaSlicer option is intentionally left pickable rather than disabled — users who only slice STLs or single-color 3MFs aren't affected by either bug, and forcibly disabling would also affect them. Localised across all 8 UI languages (English + German fully translated). + +- **Live progress for the SliceModal's filament-analysis preview slice + URL-decoded filenames in the toast** — Two follow-ups to the live slicer-progress feature: (1) the modal's "Analyzing plate filaments…" preview slice (the real slice that fires before profile picking, to discover which AMS slots an unsliced plate consumes) now shows the same stage + percent live updates as the user-initiated slice. The frontend generates a per-(source, plate) request_id, forwards it via a new `request_id` query param on `/library/files/.../filament-requirements` and `/archives/.../filament-requirements`, the backend plumbs it through `slice_without_profiles` to the sidecar, and a new `GET /api/v1/slicer/preview-progress/{request_id}` proxy endpoint forwards browser polls to the sidecar's `/slice/progress/:requestId` (CORS-safe — the browser can't reach the sidecar directly). The inline spinner and a new persistent toast both render `Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}` while the preview runs; toast dismisses when filaments arrive. (2) MakerWorld imports were persisting URL-encoded filenames (`stormtrooper-helmet%20h2d.3mf`) verbatim because MakerWorld's API returns the same percent-encoding it uses on its CDN URLs. The import path now `urllib.parse.unquote`s both the manifest-supplied name and the URL path-tail fallback before passing to `save_3mf_bytes_to_library`, plus the frontend defensively `decodeURIComponent`s in the slice toast and analysis-spinner messages so already-imported rows display cleanly without a backfill migration. Falls back to the raw string on malformed encodings (`%XY` where `XY` isn't hex). New i18n keys `slice.previewToast` + `slice.previewWithProgress` localised across all 8 UI languages (English + German fully translated). + +- **Live slicer progress in the persistent slice toast** — The persistent slice toast already showed elapsed time + a spinner so the user could see the slice was still running, but for long slices on complex multi-color models that "is anything happening?" gap could last minutes. Bambuddy now wires up the slicer CLI's structured progress channel end-to-end, so the toast renders concrete stage labels + live percent — `Stormtrooper.3mf — Generating G-code (75%) — 47s` — through the entire slice. **Sidecar (`bambuddy/profile-resolver` branch of orca-slicer-api)**: switched the sync `/slice` route from `execFile` to `spawn` so the process can run alongside an FIFO reader; on each request the route generates (or accepts a caller-supplied) `requestId`, `mkfifo`s `${workdir}/progress.fifo`, passes `--pipe ${fifo}` to the OrcaSlicer / BambuStudio CLI, and reads the structured JSON-line progress events the slicer emits (`{"message":"Generating G-code","plate_count":1,"plate_index":1,"plate_percent":80,"total_percent":75}`) into a per-process `ProgressStore` keyed by `requestId`. New `GET /slice/progress/:requestId` returns the latest snapshot; entries linger 30s after slice completion so the caller's last poll still reads the terminal "All done, Success" frame instead of a 404. Both slicer forks share the same code lineage from PrusaSlicer's `BackgroundSlicingProcess`, so OrcaSlicer 2.3.2 and BambuStudio 02.06.00.51 emit identical JSON keys (verified by tracing the binary). **Bambuddy backend**: `slicer_api.slice_with_profiles` accepts `request_id` + `on_progress` callback and spawns a 1Hz parallel poller that hits the sidecar's progress endpoint while the blocking POST is in flight; `SliceDispatchService` gained a `set_progress(job_id, snapshot)` method and a `progress` field on `SliceJob`; the slice routes now generate a uuid `request_id` and wire a callback that forwards each snapshot onto the dispatcher. `GET /slice-jobs/:id` includes `progress` on every poll. **Frontend**: `SliceJobTrackerContext` reads the new `progress` field and re-renders the persistent toast with `{name} — {stage} ({percent}%) — {elapsed}` whenever a useful frame is present, falling back to the existing elapsed-time-only message when the sidecar hasn't emitted anything yet (early "Initializing" phase) or doesn't support progress (older sidecars without the FIFO wiring). 12 sidecar unit tests for the JSON-line parser + ProgressStore (cancellation/grace-window, malformed lines, missing fields), 3 dispatcher tests for `set_progress` (attach/replace/clear, unknown-job-id silent ignore), 3 slicer_api tests for the form-field forwarding + on_progress callback wire-up + 404 short-circuit, 2 frontend SliceJobTracker tests pinning the new toast format and the no-progress fallback. New i18n key `slice.runningWithProgress` localised across all 8 UI languages (English + German fully translated, the six others seeded with English copies pending native translation, matching the project's existing flow for newly-added user-facing features). Graceful when the sidecar lacks `--pipe` support (tested live: OrcaSlicer 2.3.2 + BambuStudio 02.06.00.51 both work; older sidecars without the new endpoint return 404 and the toast cleanly degrades to elapsed-time-only). + - **No visual indicator while a slice job was running — users couldn't tell if a long slice was still progressing or had hung** — Previously SliceJobTrackerProvider emitted one transient toast on enqueue ("Slicing X in the background…") and one on completion ("Sliced X"), with nothing in between. For large multi-color models that take 30s–several minutes to slice, the start toast auto-dismissed after 3s and left a UX dead zone where users would ask "is it still slicing?". The tracker now opens a persistent `slice-job-{id}` toast with a spinner that updates every second showing elapsed time + phase ("Queued: X — 4s" → "Slicing X — 47s"), then is replaced by the existing transient success/error toast on terminal state. Polling cadence (1.5s) is unchanged — a separate 1Hz tick re-renders just the elapsed-time counter so the toast stays smooth even if the backend is slow to respond. Time format compresses gracefully past 60s ("1m 5s") and 60m ("1h 12m"). 4 new unit tests in `SliceJobTrackerContext.test.tsx` covering: persistent toast renders at t=0 (no wait for first tick), elapsed time updates each second while running, success completion replaces persistent with transient "Sliced X", failure replaces with transient error toast carrying the sidecar's `error_detail`. New i18n keys `slice.queuedToast` / `slice.runningToast` localised across all 8 UI languages (English + German fully translated, the six others seeded with English copies pending native translation, matching the project's existing flow for newly-added user-facing features). - **MakerWorld URL-paste resolver listed plate instances without showing which printer each was sliced for** — MakerWorld's `/instances/hits` endpoint omits the per-instance compatibility info that lives on `design.instances[].extention.modelInfo` (`compatibility` = primary printer the instance was sliced for, `otherCompatibility` = additional printers the uploader marked it compatible with), so every instance row in the resolved-design preview looked identical and users blindly picked the first one regardless of whether it matched their printer — leading to "I downloaded the H2D version and got A1 g-code" complaints. The resolve route now joins both endpoint payloads by instance ID and forwards both fields onto each hit; the MakerWorld page renders "Sliced for {primaryPrinter}" + (when present) "Also marked compatible: ..." per instance row. Backend tests in `test_makerworld_routes.py::TestResolve` cover the merge happy path (compatibility lists land on the right hits) and the "missing modelInfo" fallback (older designs / hits without a matching design.instances entry don't crash the response, just lose the optional fields). New i18n keys `makerworld.slicedFor` / `makerworld.alsoCompatible` localised across all 8 UI languages. diff --git a/backend/app/api/routes/archives.py b/backend/app/api/routes/archives.py index d7e74b3e0..9e103a0ee 100644 --- a/backend/app/api/routes/archives.py +++ b/backend/app/api/routes/archives.py @@ -3128,11 +3128,13 @@ async def _try_preview_slice_filaments( source_id: int, plate_id: int, file_path: Path, + request_id: str | None = None, ) -> list[dict] | None: """Run a preview slice via the user's configured sidecar so the filament list endpoint can return real per-plate filaments for unsliced project files. Returns ``None`` on any failure — the caller falls back to the - painted-face heuristic.""" + painted-face heuristic. ``request_id`` flows through to the sidecar + for live progress on the SliceModal's inline spinner + toast.""" from backend.app.api.routes.settings import get_setting from backend.app.services.slice_preview import get_preview_filaments @@ -3159,6 +3161,7 @@ async def _try_preview_slice_filaments( file_bytes=file_bytes, file_name=file_path.name, api_url=api_url, + request_id=request_id, ) @@ -3166,6 +3169,7 @@ async def _try_preview_slice_filaments( async def get_filament_requirements( archive_id: int, plate_id: int | None = None, + request_id: str | None = None, db: AsyncSession = Depends(get_db), _: User | None = RequirePermissionIfAuthEnabled(Permission.ARCHIVES_READ), ): @@ -3286,6 +3290,7 @@ async def get_filament_requirements( source_id=archive_id, plate_id=plate_id, file_path=file_path, + request_id=request_id, ) if preview is not None: used_slot_ids = {f["slot_id"] for f in preview} @@ -3375,7 +3380,7 @@ async def slice_archive( archive_id_local = archive.id user_id = current_user.id if current_user else None - async def _run(): + async def _run(job_id: int): async with async_session() as task_db: # Re-fetch the source archive on the background-task session. src_archive = await task_db.get(PrintArchive, archive_id_local) @@ -3391,6 +3396,7 @@ async def slice_archive( request=request, source_archive=src_archive, current_user_id=user_id, + job_id=job_id, ) except HTTPException as exc: raise http_exception_to_job_error(exc) from exc diff --git a/backend/app/api/routes/library.py b/backend/app/api/routes/library.py index d34bcaeb3..3f5d7266a 100644 --- a/backend/app/api/routes/library.py +++ b/backend/app/api/routes/library.py @@ -2360,9 +2360,15 @@ async def _try_preview_slice_filaments( source_id: int, plate_id: int, file_path: Path, + request_id: str | None = None, ) -> list[dict] | None: """Run a preview slice via the user's configured sidecar. Same shape as - the matching helper in archives.py — see that module for rationale.""" + the matching helper in archives.py — see that module for rationale. + + ``request_id``: when supplied, forwarded to the sidecar so the + SliceModal's inline spinner + toast can poll the matching progress + endpoint and show "Generating G-code (45%)" for the preview as well. + """ from backend.app.api.routes.settings import get_setting from backend.app.services.slice_preview import get_preview_filaments @@ -2389,6 +2395,7 @@ async def _try_preview_slice_filaments( file_bytes=file_bytes, file_name=file_path.name, api_url=api_url, + request_id=request_id, ) @@ -2396,6 +2403,7 @@ async def _try_preview_slice_filaments( async def get_library_file_filament_requirements( file_id: int, plate_id: int | None = None, + request_id: str | None = None, db: AsyncSession = Depends(get_db), _: User | None = Depends(require_permission_if_auth_enabled(Permission.LIBRARY_READ)), ): @@ -2532,6 +2540,7 @@ async def get_library_file_filament_requirements( source_id=file_id, plate_id=plate_id, file_path=file_path, + request_id=request_id, ) if preview is not None: used_slot_ids = {f["slot_id"] for f in preview} @@ -2629,6 +2638,7 @@ async def _run_slicer_with_fallback( model_filename: str, request: SliceRequest, current_user_id: int | None = None, + job_id: int | None = None, ): """Validate presets, dispatch to the right sidecar, run the slicer with the auto-fallback for 3MF inputs whose `--load-settings` path crashes the @@ -2638,6 +2648,13 @@ async def _run_slicer_with_fallback( `current_user_id` is needed to resolve **cloud** presets — the cloud token is per-user when auth is enabled. For the legacy / local-only path it can be left ``None``. + + `job_id`: when set, a request_id is generated and a parallel poller + pushes the sidecar's --pipe-fed progress events onto + ``slice_dispatch.set_progress(job_id, ...)`` so the UI's persistent + toast can show "Generating G-code (75%)" instead of just elapsed + time. Pass None for synchronous routes that aren't tracked by the + dispatcher. """ from backend.app.api.routes.settings import get_setting from backend.app.services.preset_resolver import resolve_preset_ref @@ -2710,6 +2727,23 @@ async def _run_slicer_with_fallback( used_embedded_settings = False service = SlicerApiService(api_url) + # When this slice is dispatcher-tracked, generate a request_id so + # the sidecar publishes progress under it, and wire a callback that + # forwards each frame onto SliceDispatchService.set_progress for the + # status-poll endpoint to surface to the UI. + progress_request_id: str | None = None + progress_callback = None + if job_id is not None: + from uuid import uuid4 + + from backend.app.services.slice_dispatch import slice_dispatch as _dispatch + + progress_request_id = str(uuid4()) + + def _on_progress(snapshot: dict) -> None: + _dispatch.set_progress(job_id, snapshot) + + progress_callback = _on_progress try: try: result = await service.slice_with_profiles( @@ -2720,6 +2754,8 @@ async def _run_slicer_with_fallback( filament_profile_jsons=filament_jsons, plate=request.plate, export_3mf=request.export_3mf, + request_id=progress_request_id, + on_progress=progress_callback, ) except SlicerApiServerError as exc: if not is_3mf: @@ -2729,11 +2765,16 @@ async def _run_slicer_with_fallback( model_filename, exc, ) + # Forward the same request_id + callback so the toast's live + # progress keeps updating across the fallback retry instead + # of going blank for the rest of the slice. result = await service.slice_without_profiles( model_bytes=model_bytes, model_filename=model_filename, plate=request.plate, export_3mf=request.export_3mf, + request_id=progress_request_id, + on_progress=progress_callback, ) used_embedded_settings = True except SlicerInputError as exc: @@ -2757,6 +2798,7 @@ async def slice_and_persist( extra_metadata: dict | None, request: SliceRequest, current_user_id: int | None, + job_id: int | None = None, ) -> SliceResponse: """Slice a model and save the result as a new ``LibraryFile`` in ``folder_id`` (same folder as the source by convention). @@ -2775,6 +2817,7 @@ async def slice_and_persist( model_filename=model_filename, request=library_request, current_user_id=current_user_id, + job_id=job_id, ) base_name = model_filename.rsplit(".", 1)[0] @@ -2862,6 +2905,7 @@ async def slice_and_persist_as_archive( request: SliceRequest, source_archive, # PrintArchive — hint kept loose to avoid cyclic import current_user_id: int | None, + job_id: int | None = None, ): """Slice a model and save the result as a new ``PrintArchive`` row, inheriting printer / project / makerworld metadata from the source @@ -2882,6 +2926,7 @@ async def slice_and_persist_as_archive( model_bytes=model_bytes, model_filename=model_filename, request=archive_request, + job_id=job_id, current_user_id=current_user_id, ) @@ -3031,7 +3076,7 @@ async def slice_library_file( src_ext = Path(lib_file.filename).suffix.lower() or ".3mf" model_filename = f"{src_print_name}{src_ext}" if src_print_name else lib_file.filename - async def _run(): + async def _run(job_id: int): async with async_session() as task_db: try: response = await slice_and_persist( @@ -3042,6 +3087,7 @@ async def slice_library_file( extra_metadata={"sliced_from_library_file_id": source_lib_file_id}, request=request, current_user_id=user_id, + job_id=job_id, ) except HTTPException as exc: raise http_exception_to_job_error(exc) from exc diff --git a/backend/app/api/routes/makerworld.py b/backend/app/api/routes/makerworld.py index 42f990fe7..4afda6328 100644 --- a/backend/app/api/routes/makerworld.py +++ b/backend/app/api/routes/makerworld.py @@ -14,6 +14,7 @@ from __future__ import annotations import logging import os +from urllib.parse import unquote from fastapi import APIRouter, Depends, HTTPException, Query from fastapi.responses import Response @@ -339,7 +340,12 @@ async def import_instance( # filename regardless (see library.py), so this is defence-in-depth. raw_name = manifest.get("name") if isinstance(raw_name, str) and raw_name.strip(): - suggested_name = os.path.basename(raw_name.strip()) or f"makerworld-{body.model_id}.3mf" + # MakerWorld emits percent-encoded names (`%20` for spaces, etc.) + # because the same string round-trips through HTTP URLs in the + # CDN download path. Decode before persisting so the library + # row, the slice toast, and every later UI surface show the + # human-readable form. + suggested_name = os.path.basename(unquote(raw_name.strip())) or f"makerworld-{body.model_id}.3mf" else: suggested_name = f"makerworld-{body.model_id}.3mf" if not signed_url or not isinstance(signed_url, str): @@ -369,8 +375,10 @@ async def import_instance( await service.close() # Prefer the server-provided human-readable filename; the signed URL's - # path ends in a UUID that's not meaningful to users. - filename = suggested_name if suggested_name.endswith(".3mf") else download_filename + # path ends in a UUID that's not meaningful to users. Decode the + # fallback path-tail too — same percent-encoding round-trip applies + # there as on the manifest-supplied name. + filename = suggested_name if suggested_name.endswith(".3mf") else unquote(download_filename) library_file, was_existing = await save_3mf_bytes_to_library( db, diff --git a/backend/app/api/routes/slice_jobs.py b/backend/app/api/routes/slice_jobs.py index 934d56506..a4e83f29f 100644 --- a/backend/app/api/routes/slice_jobs.py +++ b/backend/app/api/routes/slice_jobs.py @@ -35,6 +35,10 @@ async def get_slice_job( "created_at": job.created_at.isoformat(), "started_at": job.started_at.isoformat() if job.started_at else None, "completed_at": job.completed_at.isoformat() if job.completed_at else None, + # Live progress fed by the sidecar's --pipe channel. Null when + # the slicer hasn't emitted yet (early "Initializing" phase) or + # the sidecar doesn't support progress (older versions). + "progress": job.progress, } if job.status == "completed": body["result"] = job.result diff --git a/backend/app/api/routes/slicer_presets.py b/backend/app/api/routes/slicer_presets.py index ba34437bc..ecfc4021a 100644 --- a/backend/app/api/routes/slicer_presets.py +++ b/backend/app/api/routes/slicer_presets.py @@ -359,3 +359,47 @@ async def list_unified_presets( standard=UnifiedPresetsBySlot(**standard), cloud_status=cloud_status, ) + + +@router.get("/preview-progress/{request_id}") +async def get_preview_slice_progress( + request_id: str, + db: AsyncSession = Depends(get_db), + _: User | None = RequirePermissionIfAuthEnabled(Permission.LIBRARY_READ), +): + """Proxy to the sidecar's ``GET /slice/progress/:requestId``. + + The SliceModal's filament-requirements call kicks off a real preview + slice on the sidecar to discover which AMS slots the picked plate + actually consumes. That HTTP call holds open for the full slice + duration (multi-second to multi-minute on complex models), and the + browser can't reach the sidecar directly thanks to the same-origin + policy + the sidecar's CORS allowlist. This endpoint forwards the + poll so the modal's inline spinner can show "Generating G-code (45%)" + instead of an opaque elapsed-time counter while the preview runs. + + Returns the sidecar's snapshot verbatim, or 404 when the request_id + is unknown / completed and grace-window-expired. + """ + import httpx + + api_url = await _resolve_slicer_api_url(db) + if not api_url: + from fastapi import HTTPException + + raise HTTPException(status_code=503, detail="No slicer sidecar configured") + url = f"{api_url}/slice/progress/{request_id}" + try: + async with httpx.AsyncClient(timeout=5.0) as client: + response = await client.get(url) + except httpx.RequestError: + # Sidecar unreachable: surface as 503 instead of 500 so the + # frontend's poller can keep trying without flagging a hard error. + from fastapi import HTTPException + + raise HTTPException(status_code=503, detail="Slicer sidecar unreachable") from None + if response.status_code == 404: + from fastapi import HTTPException + + raise HTTPException(status_code=404, detail="Progress unavailable") + return response.json() diff --git a/backend/app/services/slice_dispatch.py b/backend/app/services/slice_dispatch.py index 75d805507..938543b3c 100644 --- a/backend/app/services/slice_dispatch.py +++ b/backend/app/services/slice_dispatch.py @@ -41,6 +41,13 @@ class SliceJob: # On failure: HTTP status + error message. error_status: int | None = None error_detail: str | None = None + # Live progress fed by the sidecar's --pipe channel while the slicer + # is running. Populated by a polling task spawned alongside the + # blocking POST /slice request; None when the sidecar doesn't + # support progress (older sidecars, no request_id, etc.). Surfaced + # in the SliceJobState response so the persistent toast can render + # "Generating G-code (75%)" instead of just elapsed time. + progress: dict[str, Any] | None = None # Retention: keep finished jobs around for 30 minutes so the polling client @@ -62,13 +69,14 @@ class SliceDispatchService: kind: Literal["library_file", "archive"], source_id: int, source_name: str, - run: Callable[[], Awaitable[dict[str, Any]]], + run: Callable[[int], Awaitable[dict[str, Any]]], ) -> SliceJob: """Register a new slice job and start it on the event loop. - ``run`` is an async callable that performs the actual slice + save - and returns the response body the caller will receive once status - flips to ``completed``. + ``run`` is an async callable that takes the freshly-created + ``job_id`` (so it can wire up live-progress reporting via + :meth:`set_progress`) and returns the response body the caller + will receive once status flips to ``completed``. """ async with self._lock: job = SliceJob( @@ -88,12 +96,12 @@ class SliceDispatchService: async def _run_job( self, job: SliceJob, - run: Callable[[], Awaitable[dict[str, Any]]], + run: Callable[[int], Awaitable[dict[str, Any]]], ) -> None: job.started_at = datetime.now(timezone.utc) job.status = "running" try: - result = await run() + result = await run(job.id) job.result = result job.status = "completed" except _SliceJobError as exc: @@ -113,6 +121,18 @@ class SliceDispatchService: def get(self, job_id: int) -> SliceJob | None: return self._jobs.get(job_id) + def set_progress(self, job_id: int, progress: dict[str, Any] | None) -> None: + """Update the live-progress snapshot for a running job. + + Called by the slice route's progress poller every ~1s while the + sidecar slice request is in flight. Silently ignores unknown ids + (the job may have just finished and been retention-swept) so a + late poll doesn't crash the polling task. + """ + job = self._jobs.get(job_id) + if job is not None: + job.progress = progress + def _sweep_locked(self) -> None: """Drop finished jobs older than the retention window. Caller holds the lock.""" diff --git a/backend/app/services/slice_preview.py b/backend/app/services/slice_preview.py index 80ce67cc7..db46bbc2c 100644 --- a/backend/app/services/slice_preview.py +++ b/backend/app/services/slice_preview.py @@ -59,6 +59,7 @@ async def get_preview_filaments( file_bytes: bytes, file_name: str, api_url: str, + request_id: str | None = None, ) -> list[dict] | None: """Run a preview slice for ``plate_id`` using the file's embedded settings, parse the resulting slice_info, and return the per-plate filament list. @@ -90,6 +91,7 @@ async def get_preview_filaments( model_filename=file_name, plate=plate_id, export_3mf=True, + request_id=request_id, ) except SlicerApiError as e: logger.warning( diff --git a/backend/app/services/slicer_api.py b/backend/app/services/slicer_api.py index 080055c63..df6a482e5 100644 --- a/backend/app/services/slicer_api.py +++ b/backend/app/services/slicer_api.py @@ -8,7 +8,9 @@ under the hood, response body is raw G-code or 3MF with metadata in the `X-Print-Time-Seconds` / `X-Filament-Used-G` / `X-Filament-Used-Mm` headers). """ +import asyncio import logging +from collections.abc import Callable from typing import NamedTuple import httpx @@ -153,6 +155,46 @@ class SlicerApiService: raise SlicerApiUnavailableError(f"Slicer sidecar /profiles/bundled returned {response.status_code}") return response.json() + async def _poll_progress( + self, + request_id: str, + on_progress: Callable[[dict], None], + ) -> None: + """Poll the sidecar's progress endpoint at ~1Hz and forward each + snapshot to ``on_progress``. Runs until cancelled. + + 4xx is NOT treated as terminal: the FIRST poll fires the moment + the slice POST is sent, which can be milliseconds before the + request actually lands on the sidecar and `progressStore.start()` + runs — so a fresh request legitimately returns 404 for the first + tick or two. Bailing on the first 404 (the original implementation) + meant we'd quit before progress could ever arrive. The polling + task is cancelled by the outer slice request anyway, so a + sustained 404 (older sidecar without progress support, or post- + slice grace expiry) just costs a few wasted GETs that the cancel + will stop. Network errors and non-JSON 5xx are swallowed; the + next tick retries. + """ + url = f"{self.base_url}/slice/progress/{request_id}" + while True: + try: + response = await self._client.get(url, timeout=5.0) + if response.status_code == 200: + payload = response.json() + if isinstance(payload, dict): + on_progress(payload) + # 404 / other 4xx = no progress available (yet, or ever + # for older sidecars). Keep polling — the outer slice + # request will cancel this task on completion. + except (httpx.RequestError, ValueError): + # ValueError covers JSONDecodeError when the sidecar + # returns a non-JSON 5xx. Don't crash the poller. + pass + try: + await asyncio.sleep(1.0) + except asyncio.CancelledError: + return + async def slice_with_profiles( self, *, @@ -163,6 +205,8 @@ class SlicerApiService: filament_profile_jsons: list[str], plate: int | None = None, export_3mf: bool = False, + request_id: str | None = None, + on_progress: Callable[[dict], None] | None = None, ) -> SliceResult: """POST /slice with model + printer/process/filament profiles. @@ -173,6 +217,12 @@ class SlicerApiService: slicing service joins them as semicolon-separated ``--load-filaments`` for the OrcaSlicer / BambuStudio CLI. + ``request_id``: when supplied, the sidecar wires --pipe to a + per-request FIFO and publishes structured JSON progress events to + its in-memory ProgressStore under this id. Bambuddy's slice + dispatch polls ``GET /slice/progress/{request_id}`` in parallel + to drive the live-progress toast. + Raises: SlicerInputError: 4xx from sidecar (caller-supplied input is bad). SlicerApiUnavailableError: connection error or 5xx from sidecar. @@ -198,6 +248,20 @@ class SlicerApiService: data["plate"] = str(plate) if export_3mf: data["exportType"] = "3mf" + if request_id is not None: + data["requestId"] = request_id + + # When the caller supplied a request_id, kick off a parallel + # poller that reads the sidecar's --pipe-fed progress endpoint + # and surfaces structured updates via on_progress. Uses a + # short-tick poll (1s) since the slicer emits stage changes + # several times per minute on complex models. + progress_task: asyncio.Task | None = None + if request_id is not None and on_progress is not None: + progress_task = asyncio.create_task( + self._poll_progress(request_id, on_progress), + name=f"slicer-progress-{request_id}", + ) try: response = await self._client.post( @@ -208,6 +272,13 @@ class SlicerApiService: ) except httpx.RequestError as exc: raise SlicerApiUnavailableError(f"Slicer sidecar unreachable: {exc}") from exc + finally: + if progress_task is not None: + progress_task.cancel() + try: + await progress_task + except (asyncio.CancelledError, Exception): + pass # Polling errors must not fail the slice. if response.status_code >= 500: raise SlicerApiServerError(f"Slicer CLI failed ({response.status_code}): {_format_sidecar_error(response)}") @@ -228,6 +299,8 @@ class SlicerApiService: model_filename: str, plate: int | None = None, export_3mf: bool = False, + request_id: str | None = None, + on_progress: Callable[[dict], None] | None = None, ) -> SliceResult: """POST /slice with only the model file and no profile triplet. @@ -236,6 +309,14 @@ class SlicerApiService: `slice_with_profiles` triggers a CLI segfault or other 5xx — complex H2D / multi-extruder models hit upstream bugs in both the OrcaSlicer and BambuStudio CLIs when invoked via `--load-settings`. + + Also used by the SliceModal's per-plate filament discovery path: + for an unsliced project file we run a real preview slice via the + sidecar to find which AMS slots the picked plate consumes. The + ``request_id`` parameter routes the sidecar's --pipe progress + events to the ProgressStore so the modal's inline spinner + + toast can show "Generating G-code (75%)" for that preview as + well. """ files = { "file": (model_filename, model_bytes, _guess_model_content_type(model_filename)), @@ -245,6 +326,20 @@ class SlicerApiService: data["plate"] = str(plate) if export_3mf: data["exportType"] = "3mf" + if request_id is not None: + data["requestId"] = request_id + + # Same progress-poller wiring as slice_with_profiles. Used by the + # SliceModal's preview slice (for filament discovery) AND the + # embedded-settings fallback path triggered by an Orca/Bambu CLI + # segfault on complex H2D models — both want to keep updating + # the user's toast through the slow operation. + progress_task: asyncio.Task | None = None + if request_id is not None and on_progress is not None: + progress_task = asyncio.create_task( + self._poll_progress(request_id, on_progress), + name=f"slicer-progress-{request_id}", + ) try: response = await self._client.post( @@ -255,6 +350,13 @@ class SlicerApiService: ) except httpx.RequestError as exc: raise SlicerApiUnavailableError(f"Slicer sidecar unreachable: {exc}") from exc + finally: + if progress_task is not None: + progress_task.cancel() + try: + await progress_task + except (asyncio.CancelledError, Exception): + pass if response.status_code >= 500: raise SlicerApiServerError(f"Slicer CLI failed ({response.status_code}): {_format_sidecar_error(response)}") diff --git a/backend/tests/unit/services/test_slice_dispatch_progress.py b/backend/tests/unit/services/test_slice_dispatch_progress.py new file mode 100644 index 000000000..14a8ab832 --- /dev/null +++ b/backend/tests/unit/services/test_slice_dispatch_progress.py @@ -0,0 +1,109 @@ +"""Tests for SliceDispatchService.set_progress. + +The dispatcher exposes set_progress so the slice-route's parallel poller +(spawned alongside the blocking sidecar slice request) can publish +``{stage, total_percent, plate_index, plate_count}`` snapshots that the +status-poll endpoint surfaces to the UI's persistent progress toast. +""" + +from __future__ import annotations + +import asyncio + +import pytest + +from backend.app.services.slice_dispatch import SliceDispatchService + + +@pytest.mark.asyncio +async def test_set_progress_attaches_snapshot_to_running_job(): + dispatcher = SliceDispatchService() + + started = asyncio.Event() + release = asyncio.Event() + + async def runner(job_id: int) -> dict: + started.set() + # Hold the job in the running state until the test releases it. + await release.wait() + return {"library_file_id": 1} + + job = await dispatcher.enqueue( + kind="library_file", + source_id=1, + source_name="x.stl", + run=runner, + ) + await started.wait() + + # Without progress published yet, the job's progress is None. + assert dispatcher.get(job.id) is not None + assert dispatcher.get(job.id).progress is None + + # First snapshot lands on the job. + dispatcher.set_progress( + job.id, + {"stage": "Detecting perimeters", "total_percent": 12}, + ) + snap = dispatcher.get(job.id).progress + assert snap == {"stage": "Detecting perimeters", "total_percent": 12} + + # Second snapshot replaces, doesn't merge — the dispatcher just + # holds the latest frame; the sidecar's pipe protocol always emits + # the full set, so partial-frame merging would be wrong. + dispatcher.set_progress( + job.id, + {"stage": "Generating G-code", "total_percent": 75, "plate_index": 1}, + ) + snap = dispatcher.get(job.id).progress + assert snap == { + "stage": "Generating G-code", + "total_percent": 75, + "plate_index": 1, + } + + # Release the runner so the job completes and the test cleans up. + release.set() + # Yield to the event loop so the runner's completion settles. + await asyncio.sleep(0) + await asyncio.sleep(0) + + +@pytest.mark.asyncio +async def test_set_progress_silently_ignores_unknown_job_id(): + """A late poll after retention sweep mustn't crash the polling task.""" + dispatcher = SliceDispatchService() + # Should be a no-op, not an exception. + dispatcher.set_progress(99999, {"stage": "x", "total_percent": 50}) + + +@pytest.mark.asyncio +async def test_set_progress_can_clear_to_none(): + """Allow clearing — useful when the slice transitions to a final + state and we want the toast to revert to the elapsed-time fallback + on subsequent polls.""" + dispatcher = SliceDispatchService() + started = asyncio.Event() + release = asyncio.Event() + + async def runner(job_id: int) -> dict: + started.set() + await release.wait() + return {"library_file_id": 1} + + job = await dispatcher.enqueue( + kind="library_file", + source_id=1, + source_name="x.stl", + run=runner, + ) + await started.wait() + + dispatcher.set_progress(job.id, {"stage": "x", "total_percent": 50}) + assert dispatcher.get(job.id).progress is not None + dispatcher.set_progress(job.id, None) + assert dispatcher.get(job.id).progress is None + + release.set() + await asyncio.sleep(0) + await asyncio.sleep(0) diff --git a/backend/tests/unit/services/test_slicer_api.py b/backend/tests/unit/services/test_slicer_api.py index 0564253bf..8f4dc7517 100644 --- a/backend/tests/unit/services/test_slicer_api.py +++ b/backend/tests/unit/services/test_slicer_api.py @@ -2,6 +2,8 @@ from __future__ import annotations +import asyncio + import httpx import pytest @@ -325,3 +327,155 @@ class TestHealth: service = SlicerApiService("http://sidecar:3000", client=_mock_client(handler)) with pytest.raises(SlicerApiUnavailableError): await service.health() + + +class TestSliceWithProfilesProgress: + """Live-progress wiring for slice_with_profiles. + + When the caller supplies a ``request_id`` and an ``on_progress`` + callback, the service forwards the id as a ``requestId`` form field + (the sidecar uses it to wire up `--pipe` per request) and spawns a + background poller that calls back into ``on_progress`` for each + snapshot the sidecar publishes. The poller is cancelled the moment + the slice POST returns. + """ + + @pytest.mark.asyncio + async def test_request_id_forwarded_as_form_field(self): + captured: dict = {} + + def handler(request: httpx.Request) -> httpx.Response: + if request.url.path == "/slice": + captured["body"] = request.content + return httpx.Response( + status_code=200, + content=b"PK\x03\x04 fake", + headers={"x-print-time-seconds": "1", "x-filament-used-g": "0", "x-filament-used-mm": "0"}, + ) + # /slice/progress/ — return 404 so the poller exits cleanly. + return httpx.Response(status_code=404, json={"error": "not_found"}) + + service = SlicerApiService("http://sidecar:3000", client=_mock_client(handler)) + await service.slice_with_profiles( + model_bytes=b"x", + model_filename="Cube.stl", + printer_profile_json="{}", + process_profile_json="{}", + filament_profile_jsons=["{}"], + request_id="abc-123", + on_progress=lambda _snap: None, + ) + # The form field name on the wire is `requestId` (camelCase) to + # match the sidecar's SlicingSettings shape. + body = captured["body"].decode("utf-8", errors="ignore") + assert "requestId" in body + assert "abc-123" in body + + @pytest.mark.asyncio + async def test_on_progress_called_with_snapshots(self): + # Drive enough poller ticks for at least one progress 200 to land + # before the slice response unblocks the caller. + slice_release = asyncio.Event() + snapshots: list[dict] = [] + + async def slice_handler() -> httpx.Response: + # Hold the slice POST until the test signals release, mimicking + # a real long-running slice. + await slice_release.wait() + return httpx.Response( + status_code=200, + content=b"PK\x03\x04", + headers={"x-print-time-seconds": "1", "x-filament-used-g": "0", "x-filament-used-mm": "0"}, + ) + + def handler(request: httpx.Request) -> httpx.Response: + if request.url.path == "/slice": + # MockTransport supports async handlers if we return a + # coroutine — but the simpler path is to drive completion + # via the captured event below. + pass + if request.url.path == "/slice/progress/req-1": + return httpx.Response( + status_code=200, + json={ + "stage": "Generating G-code", + "total_percent": 75, + "plate_percent": 80, + "plate_index": 1, + "plate_count": 1, + "updated_at": 0, + }, + ) + return httpx.Response(404) + + # Use an async handler so the slice POST blocks until released. + async def async_handler(request: httpx.Request) -> httpx.Response: + if request.url.path == "/slice": + return await slice_handler() + return handler(request) + + client = httpx.AsyncClient(transport=httpx.MockTransport(async_handler)) + service = SlicerApiService("http://sidecar:3000", client=client) + + # Run the slice with progress callback, releasing it after a beat. + async def release_after_first_snapshot(): + # Wait until the poller has published at least one snapshot + # via the on_progress callback, then unblock the slice POST. + for _ in range(60): + if snapshots: + break + await asyncio.sleep(0.05) + slice_release.set() + + release_task = asyncio.create_task(release_after_first_snapshot()) + try: + await service.slice_with_profiles( + model_bytes=b"x", + model_filename="Cube.stl", + printer_profile_json="{}", + process_profile_json="{}", + filament_profile_jsons=["{}"], + request_id="req-1", + on_progress=lambda snap: snapshots.append(snap), + ) + finally: + release_task.cancel() + await asyncio.gather(release_task, return_exceptions=True) + await client.aclose() + + assert snapshots, "on_progress was never called" + first = snapshots[0] + assert first["stage"] == "Generating G-code" + assert first["total_percent"] == 75 + + @pytest.mark.asyncio + async def test_progress_404_does_not_crash_or_stop_polling(self): + """A 404 from /slice/progress/:id is expected during the early + race window (POST fired before sidecar's progressStore.start() + ran) and from older sidecars without progress support. Neither + should crash the slice or block the response — the poller just + keeps trying until the outer cancel fires.""" + + def handler(request: httpx.Request) -> httpx.Response: + if request.url.path == "/slice": + return httpx.Response( + status_code=200, + content=b"PK\x03\x04", + headers={"x-print-time-seconds": "1", "x-filament-used-g": "0", "x-filament-used-mm": "0"}, + ) + return httpx.Response(status_code=404, json={"error": "not_found"}) + + snapshots: list[dict] = [] + service = SlicerApiService("http://sidecar:3000", client=_mock_client(handler)) + result = await service.slice_with_profiles( + model_bytes=b"x", + model_filename="Cube.stl", + printer_profile_json="{}", + process_profile_json="{}", + filament_profile_jsons=["{}"], + request_id="legacy-sidecar", + on_progress=lambda snap: snapshots.append(snap), + ) + assert result is not None + # Sustained 404 → no snapshots ever forwarded. + assert snapshots == [] diff --git a/frontend/src/__tests__/contexts/SliceJobTrackerContext.test.tsx b/frontend/src/__tests__/contexts/SliceJobTrackerContext.test.tsx index 2a2016253..f7e6cb4ba 100644 --- a/frontend/src/__tests__/contexts/SliceJobTrackerContext.test.tsx +++ b/frontend/src/__tests__/contexts/SliceJobTrackerContext.test.tsx @@ -261,4 +261,125 @@ describe('SliceJobTrackerProvider — persistent progress toast', () => { // complaint that motivated `_format_sidecar_error` on the backend. expect(screen.getByText(/sidecar segfault/)).toBeDefined(); }); + + // The backend now exposes a `progress` field on each slice-job poll + // result, fed by the sidecar's --pipe channel. When a useful frame + // is present the toast must show "{name} — {stage} ({percent}%) — + // {elapsed}" so the user sees concrete progress instead of a wall of + // elapsed time. + it('weaves stage + percent into the toast when the sidecar reports progress', async () => { + let pollCount = 0; + mockApi.getSliceJob.mockImplementation(async () => { + pollCount += 1; + // First poll: running with a useful progress frame. + if (pollCount === 1) { + return { + job_id: 7, + status: 'running', + kind: 'library_file', + source_id: 200, + source_name: 'Helmet.3mf', + created_at: new Date().toISOString(), + started_at: new Date().toISOString(), + completed_at: null, + progress: { + stage: 'Generating G-code', + total_percent: 75, + plate_percent: 80, + plate_index: 1, + plate_count: 1, + updated_at: Date.now(), + }, + }; + } + // Subsequent polls keep the same frame so the test loop stays stable. + return { + job_id: 7, + status: 'running', + kind: 'library_file', + source_id: 200, + source_name: 'Helmet.3mf', + created_at: new Date().toISOString(), + started_at: new Date().toISOString(), + completed_at: null, + progress: { + stage: 'Generating G-code', + total_percent: 75, + plate_percent: 80, + plate_index: 1, + plate_count: 1, + updated_at: Date.now(), + }, + }; + }); + + render( + + + , + ); + + act(() => { + screen.getByText('track-7').click(); + }); + + // Drive the 1.5s poll so the progress frame lands in the ref, then + // tick the 1s renderer so the toast picks it up. + await act(async () => { + vi.advanceTimersByTime(1500); + }); + await act(async () => { + await Promise.resolve(); + }); + act(() => { + vi.advanceTimersByTime(1000); + }); + + // Toast contains the stage + percent + filename. + const text = screen.getByText(/Generating G-code/); + expect(text.textContent).toMatch(/Helmet\.3mf/); + expect(text.textContent).toMatch(/75%/); + }); + + it('falls back to elapsed-time message when progress is null', async () => { + // Sidecar without --pipe support / pre-progress feature: state.progress + // stays null and the toast shows the existing "Slicing X — 47s" text. + mockApi.getSliceJob.mockResolvedValue({ + job_id: 8, + status: 'running', + kind: 'library_file', + source_id: 201, + source_name: 'OldSidecar.3mf', + created_at: new Date().toISOString(), + started_at: new Date().toISOString(), + completed_at: null, + progress: null, + }); + + render( + + + , + ); + + act(() => { + screen.getByText('track-8').click(); + }); + + await act(async () => { + vi.advanceTimersByTime(1500); + }); + await act(async () => { + await Promise.resolve(); + }); + act(() => { + vi.advanceTimersByTime(1000); + }); + + // The "Slicing X — Ns" / "Queued: X — Ns" fallback must still render + // — the absence of progress mustn't blank the toast. + expect(screen.getByText(/OldSidecar\.3mf/)).toBeDefined(); + // No progress percent is shown when null. + expect(screen.queryByText(/%/)).toBeNull(); + }); }); diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index 8b22985fe..39152a12e 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -1192,6 +1192,17 @@ export interface SliceJobEnqueueResponse { status_url: string; } +export interface SliceJobProgress { + /** Stage label emitted by the slicer ("Generating G-code", "Slicing finished"). */ + stage: string; + total_percent: number; + plate_percent: number; + /** 1-indexed plate position; 0 means "all plates" / final completion. */ + plate_index: number; + plate_count: number; + updated_at: number; +} + export interface SliceJobState { job_id: number; status: SliceJobStatus; @@ -1201,6 +1212,10 @@ export interface SliceJobState { created_at: string; started_at: string | null; completed_at: string | null; + /** Live progress fed by the sidecar's --pipe channel; null until the + * slicer emits its first frame (early "Initializing" phase) or when + * the sidecar doesn't support progress. */ + progress: SliceJobProgress | null; result?: SliceResponse | SliceArchiveResponse; error_status?: number; error_detail?: string; @@ -3657,8 +3672,11 @@ export const api = { }, getArchivePlates: (archiveId: number) => request(`/archives/${archiveId}/plates`), - getArchiveFilamentRequirements: (archiveId: number, plateId?: number) => - request<{ + getArchiveFilamentRequirements: (archiveId: number, plateId?: number, requestId?: string) => { + const qs = new URLSearchParams(); + if (plateId !== undefined) qs.set('plate_id', String(plateId)); + if (requestId) qs.set('request_id', requestId); + return request<{ archive_id: number; filename: string; plate_id: number | null; @@ -3668,8 +3686,10 @@ export const api = { color: string; used_grams: number; used_meters: number; + used_in_plate?: boolean; }>; - }>(`/archives/${archiveId}/filament-requirements${plateId !== undefined ? `?plate_id=${plateId}` : ''}`), + }>(`/archives/${archiveId}/filament-requirements${qs.toString() ? `?${qs}` : ''}`); + }, reprintArchive: ( archiveId: number, printerId: number, @@ -4918,8 +4938,11 @@ export const api = { }), getLibraryFilePlates: (fileId: number) => request(`/library/files/${fileId}/plates`), - getLibraryFileFilamentRequirements: (fileId: number, plateId?: number) => - request<{ + getLibraryFileFilamentRequirements: (fileId: number, plateId?: number, requestId?: string) => { + const qs = new URLSearchParams(); + if (plateId !== undefined) qs.set('plate_id', String(plateId)); + if (requestId) qs.set('request_id', requestId); + return request<{ file_id: number; filename: string; filaments: Array<{ @@ -4928,8 +4951,24 @@ export const api = { color: string; used_grams: number; used_meters: number; + used_in_plate?: boolean; }>; - }>(`/library/files/${fileId}/filament-requirements${plateId !== undefined ? `?plate_id=${plateId}` : ''}`), + }>(`/library/files/${fileId}/filament-requirements${qs.toString() ? `?${qs}` : ''}`); + }, + + /** Poll the sidecar's per-request progress snapshot via the Bambuddy + * proxy. Used by the SliceModal's filament-discovery path so the inline + * spinner + persistent toast can show "Generating G-code (45%)" while + * the preview slice runs. Returns null on 404 (sidecar doesn't yet + * have an entry — early race window — or it expired) so the poller + * can keep trying. */ + getPreviewSliceProgress: async (requestId: string): Promise => { + try { + return await request(`/slicer/preview-progress/${encodeURIComponent(requestId)}`); + } catch { + return null; + } + }, // GitHub Backup getGitHubBackupConfig: () => diff --git a/frontend/src/components/SliceModal.tsx b/frontend/src/components/SliceModal.tsx index 767fd5601..8dc28644c 100644 --- a/frontend/src/components/SliceModal.tsx +++ b/frontend/src/components/SliceModal.tsx @@ -6,12 +6,14 @@ import { api, type PresetRef, type PresetSource, + type SliceJobProgress, type SlicerCloudStatus, type UnifiedPreset, type UnifiedPresetsBySlot, type UnifiedPresetsResponse, } from '../api/client'; import { useSliceJobTracker } from '../contexts/SliceJobTrackerContext'; +import { useToast } from '../contexts/ToastContext'; import { PlatePickerModal } from './PlatePickerModal'; import type { PlateFilament } from '../types/plates'; import { normalizeColorForCompare, colorsAreSimilar } from '../utils/amsHelpers'; @@ -108,22 +110,105 @@ function fromRefValue(raw: string): PresetRef | null { // on a complex multi-color model that's a real slice — multi-second to // multi-minute. The static "Analyzing plate filaments…" string left // users wondering whether anything was happening, so the spinner now -// shows elapsed seconds and a hint that explains the wait. After ~5s it -// also surfaces a "this is a one-time slice — repeat opens are instant" +// shows elapsed seconds, polls the sidecar's --pipe progress (via the +// /slicer/preview-progress proxy) for live stage + percent, and after ~5s +// surfaces a "this is a one-time slice — repeat opens are instant" // note so users don't worry it'll be slow forever. -function FilamentAnalysisSpinner() { +// +// requestId: a UUID generated by the modal when the filament-requirements +// fetch starts. Forwarded to the sidecar via the API call AND used here +// to poll the matching progress snapshot. Same id, two consumers. +function FilamentAnalysisSpinner({ + requestId, + sourceName, +}: { + requestId: string; + sourceName: string; +}) { const { t } = useTranslation(); + const { showPersistentToast, dismissToast } = useToast(); const [elapsed, setElapsed] = useState(0); + const [progress, setProgress] = useState(null); + // Defensive decode — see prettifyFilename comment in SliceJobTrackerContext. + let prettyName = sourceName; + try { + prettyName = decodeURIComponent(sourceName); + } catch { + /* keep raw on malformed encoding */ + } + + // Elapsed-time tick. useEffect(() => { const startedAt = Date.now(); const id = setInterval(() => setElapsed(Math.floor((Date.now() - startedAt) / 1000)), 1000); return () => clearInterval(id); }, []); + + // Progress polling — once per second while the spinner is mounted. + // Mirrors the slice-job tracker's cadence. Sidecar 404s during the + // race window between fetch start and progressStore.start() are + // swallowed by the API method (returns null) so we keep polling. + useEffect(() => { + let cancelled = false; + const id = setInterval(async () => { + if (cancelled) return; + const snap = await api.getPreviewSliceProgress(requestId); + if (!cancelled && snap) setProgress(snap); + }, 1000); + return () => { + cancelled = true; + clearInterval(id); + }; + }, [requestId]); + + // Mirror the spinner's contents into a persistent toast so the user + // sees activity even when their cursor is elsewhere on the page. + // Dismissed in the parent's effect when the requirements arrive. + const toastId = `slice-preview-${requestId}`; + useEffect(() => { + const hasUseful = progress && progress.stage && progress.total_percent > 0; + const elapsedStr = formatElapsed(elapsed); + if (hasUseful) { + showPersistentToast( + toastId, + t( + 'slice.previewWithProgress', + 'Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', + { + name: prettyName, + stage: progress!.stage, + percent: Math.min(100, Math.max(0, Math.round(progress!.total_percent))), + elapsed: elapsedStr, + }, + ), + 'loading', + ); + } else { + showPersistentToast( + toastId, + t('slice.previewToast', 'Analyzing {{name}} — {{elapsed}}', { + name: prettyName, + elapsed: elapsedStr, + }), + 'loading', + ); + } + return () => { + dismissToast(toastId); + }; + }, [elapsed, progress, sourceName, showPersistentToast, dismissToast, t, toastId]); + + const stage = progress?.stage; + const percent = progress?.total_percent; + const inlineLabel = + stage && typeof percent === 'number' && percent > 0 + ? `${stage} (${Math.min(100, Math.max(0, Math.round(percent)))}%)` + : t('slice.analyzingPlateFilaments', 'Analyzing plate filaments…'); return (
- {t('slice.analyzingPlateFilaments', 'Analyzing plate filaments…')} + {inlineLabel} {elapsed}s
{elapsed >= 5 && ( @@ -138,6 +223,17 @@ function FilamentAnalysisSpinner() { ); } +function formatElapsed(seconds: number): string { + const s = Math.max(0, Math.floor(seconds)); + if (s < 60) return `${s}s`; + const m = Math.floor(s / 60); + const remS = s % 60; + if (m < 60) return `${m}m ${remS}s`; + const h = Math.floor(m / 60); + const remM = m % 60; + return `${h}h ${remM}m`; +} + export function SliceModal({ source, onClose }: SliceModalProps) { const { t } = useTranslation(); const { trackJob } = useSliceJobTracker(); @@ -179,13 +275,25 @@ export function SliceModal({ source, onClose }: SliceModalProps) { // extraction. plate_id is always sent: single-plate falls through to plate // 1 server-side; multi-plate uses the user's pick. const effectivePlateId = selectedPlate ?? 1; + // Generate a request_id per (source, plate) pair so the backend's + // preview-slice and the FilamentAnalysisSpinner's progress poll share + // the same id. useMemo keeps it stable across renders within the same + // pair; switching plates regenerates so a stale poll doesn't bleed + // progress between plates. + const previewRequestId = useMemo(() => { + const id = + typeof crypto !== 'undefined' && 'randomUUID' in crypto + ? crypto.randomUUID() + : `${Date.now()}-${Math.random().toString(36).slice(2)}`; + return id; + }, [source.kind, source.id, effectivePlateId]); const filamentReqsQuery = useQuery({ queryKey: ['sliceFilamentReqs', source.kind, source.id, effectivePlateId], queryFn: async () => { if (source.kind === 'libraryFile') { - return api.getLibraryFileFilamentRequirements(source.id, effectivePlateId); + return api.getLibraryFileFilamentRequirements(source.id, effectivePlateId, previewRequestId); } - return api.getArchiveFilamentRequirements(source.id, effectivePlateId); + return api.getArchiveFilamentRequirements(source.id, effectivePlateId, previewRequestId); }, enabled: !needsPlatePicker, staleTime: 60_000, @@ -406,7 +514,10 @@ export function SliceModal({ source, onClose }: SliceModalProps) { scoped spinner so the user sees the printer/process dropdowns instead of an opaque "Loading presets…" wait. */} {filamentReqsQuery.isLoading ? ( - + ) : ( filamentSlots.map((slot, idx) => { // Slots flagged by the backend as not used by the diff --git a/frontend/src/contexts/SliceJobTrackerContext.tsx b/frontend/src/contexts/SliceJobTrackerContext.tsx index 1c3c1235a..f69c13f29 100644 --- a/frontend/src/contexts/SliceJobTrackerContext.tsx +++ b/frontend/src/contexts/SliceJobTrackerContext.tsx @@ -15,7 +15,7 @@ import { createContext, useCallback, useContext, useEffect, useRef, useState, type ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; import { useQueryClient } from '@tanstack/react-query'; -import { api, type SliceJobState, type SliceJobStatus } from '../api/client'; +import { api, type SliceJobProgress, type SliceJobState, type SliceJobStatus } from '../api/client'; import { useToast } from './ToastContext'; interface TrackedJob { @@ -36,6 +36,21 @@ const TICK_INTERVAL_MS = 1000; const toastIdFor = (jobId: number) => `slice-job-${jobId}`; +/** Decode percent-encoded characters in a filename so the toast doesn't + * show `stormtrooper-helmet%20h2d.3mf` for files that came from a source + * with URL-encoded names (MakerWorld API, S3 path tails, etc.). The + * MakerWorld import path now decodes at persist time, but already-imported + * rows still carry the encoded form — this is a belt-and-suspenders + * decode at display time so old rows look right too. Wrapped in try/catch + * because malformed encodings (`%XY` where XY isn't hex) throw URIError. */ +function prettifyFilename(name: string): string { + try { + return decodeURIComponent(name); + } catch { + return name; + } +} + function formatElapsed(seconds: number): string { const s = Math.max(0, Math.floor(seconds)); if (s < 60) return `${s}s`; @@ -58,10 +73,12 @@ export function SliceJobTrackerProvider({ children }: { children: ReactNode }) { const activeJobsRef = useRef([]); activeJobsRef.current = activeJobs; - // Per-job start time + latest phase, kept in refs so the 1s tick - // doesn't need to re-render on every update. Keyed by job id. + // Per-job start time, latest phase, and latest progress snapshot, + // kept in refs so the 1s tick doesn't need to re-render on every + // update. Keyed by job id. const startedAtRef = useRef>(new Map()); const phaseRef = useRef>(new Map()); + const progressRef = useRef>(new Map()); const renderProgressToast = useCallback( (job: TrackedJob) => { @@ -69,6 +86,33 @@ export function SliceJobTrackerProvider({ children }: { children: ReactNode }) { if (startedAt == null) return; const elapsedSecs = (Date.now() - startedAt) / 1000; const phase = phaseRef.current.get(job.id) ?? 'pending'; + const elapsedStr = formatElapsed(elapsedSecs); + const progress = progressRef.current.get(job.id) ?? null; + // When the sidecar has emitted at least one progress frame, weave + // the stage label + percent into the toast — that's what makes the + // wait feel professional ("Generating G-code 75%" beats "Slicing X + // — 47s"). Falls back to the elapsed-time-only message in three + // cases: queued/pending phase before the slicer has started, + // missing or zero progress (Initializing), or sidecar without + // --pipe support. + const hasUseful = progress && progress.stage && progress.total_percent > 0; + if (phase === 'running' && hasUseful) { + showPersistentToast( + toastIdFor(job.id), + t( + 'slice.runningWithProgress', + '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', + { + name: prettifyFilename(job.sourceName), + stage: progress.stage, + percent: Math.min(100, Math.max(0, Math.round(progress.total_percent))), + elapsed: elapsedStr, + }, + ), + 'loading', + ); + return; + } const messageKey = phase === 'pending' ? 'slice.queuedToast' : 'slice.runningToast'; const fallback = phase === 'pending' @@ -76,7 +120,7 @@ export function SliceJobTrackerProvider({ children }: { children: ReactNode }) { : 'Slicing {{name}} — {{elapsed}}'; showPersistentToast( toastIdFor(job.id), - t(messageKey, fallback, { name: job.sourceName, elapsed: formatElapsed(elapsedSecs) }), + t(messageKey, fallback, { name: prettifyFilename(job.sourceName), elapsed: elapsedStr }), 'loading', ); }, @@ -88,6 +132,7 @@ export function SliceJobTrackerProvider({ children }: { children: ReactNode }) { setActiveJobs((prev) => (prev.some((j) => j.id === id) ? prev : [...prev, { id, kind, sourceName }])); startedAtRef.current.set(id, Date.now()); phaseRef.current.set(id, 'pending'); + progressRef.current.set(id, null); // Render the initial frame immediately so the user sees the toast // before the first tick lands (~1s delay otherwise). renderProgressToast({ id, kind, sourceName }); @@ -100,6 +145,7 @@ export function SliceJobTrackerProvider({ children }: { children: ReactNode }) { setActiveJobs((prev) => prev.filter((j) => j.id !== job.id)); startedAtRef.current.delete(job.id); phaseRef.current.delete(job.id); + progressRef.current.delete(job.id); // Replace the persistent progress toast with a transient // success/error toast (auto-dismisses after 3s, same as showToast). @@ -112,12 +158,12 @@ export function SliceJobTrackerProvider({ children }: { children: ReactNode }) { // embedded-settings fallback as a normal path) and just added // noise — see the trailing yellow toast complaint, removed. showToast( - t('slice.completedToast', 'Sliced {{name}}', { name: job.sourceName }), + t('slice.completedToast', 'Sliced {{name}}', { name: prettifyFilename(job.sourceName) }), 'success', ); } else if (state.status === 'failed') { const detail = state.error_detail || t('slice.failed'); - showToast(t('slice.failedToast', 'Slicing {{name}} failed: {{detail}}', { name: job.sourceName, detail }), 'error'); + showToast(t('slice.failedToast', 'Slicing {{name}} failed: {{detail}}', { name: prettifyFilename(job.sourceName), detail }), 'error'); } // Refresh whichever list owns the result. Both are cheap to invalidate. @@ -139,6 +185,11 @@ export function SliceJobTrackerProvider({ children }: { children: ReactNode }) { try { const state = await api.getSliceJob(job.id); phaseRef.current.set(job.id, state.status); + // Capture the latest progress snapshot if the sidecar fed + // one through. The 1s tick re-renders the toast off this ref. + if (state.progress) { + progressRef.current.set(job.id, state.progress); + } if (state.status === 'completed' || state.status === 'failed') { completeJob(job, state); } diff --git a/frontend/src/i18n/locales/de.ts b/frontend/src/i18n/locales/de.ts index 373524d26..806950e19 100644 --- a/frontend/src/i18n/locales/de.ts +++ b/frontend/src/i18n/locales/de.ts @@ -1830,6 +1830,7 @@ export default { embeddedOverlay: 'Eingebettetes Overlay', preferredSlicer: 'Bevorzugter Slicer', preferredSlicerDescription: 'Wähle die Slicer-Anwendung zum Öffnen von Dateien', + orcaslicerKnownIssuesWarning: 'OrcaSlicer 2.3.2 / 2.4.0-dev haben bekannte CLI-Bugs, die das Slicen vieler von BambuStudio erstellter 3MF-Dateien blockieren — siehe Upstream-Issues #12426 (Segfault bei bemalten Multi-Extruder-Dateien) und #13386 (zu strikte Parameter-Range-Validierung). Bis die Upstream-Fixes verfügbar sind, wird Bambu Studio empfohlen.', useSlicerApi: 'Slicer-API verwenden', useSlicerApiDescription: 'Wenn aktiv, öffnen "Slice"-Aktionen das in-App Slicer-Modal und rufen den Slicer-API-Sidecar. Aus (Standard): Übergabe an den Desktop-Slicer per URI-Schema.', slicerCard: 'Slicer', @@ -3255,6 +3256,8 @@ export default { loadingPresets: 'Profile werden geladen…', analyzingPlateFilaments: 'Plattenfilamente werden analysiert…', analyzingPlateFilamentsHint: 'Es wird ein Probeschnitt ausgeführt, um die belegten AMS-Slots dieser Platte zu ermitteln. Wird zwischengespeichert — erneutes Öffnen ist sofort.', + previewToast: '{{name}} wird analysiert — {{elapsed}}', + previewWithProgress: '{{name}} wird analysiert — {{stage}} ({{percent}}%) — {{elapsed}}', notUsedByPlate: '— wird von dieser Platte nicht verwendet', printerMismatch: 'Dieses 3MF wurde für {{source}} gesliced, du hast aber {{target}} ausgewählt. Der Slicer-CLI kann ein 3MF nicht für einen anderen Drucker neu slicen — öffne die Quelle in Bambu Studio, ändere den Drucker und exportiere neu.', noPresetsForSlot: 'Keine Profile verfügbar', @@ -3266,6 +3269,7 @@ export default { startedToast: '{{name}} wird im Hintergrund gesliced…', queuedToast: 'Warteschlange: {{name}} — {{elapsed}}', runningToast: '{{name}} wird gesliced — {{elapsed}}', + runningWithProgress: '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', completedToast: '{{name}} wurde gesliced', failedToast: 'Slicen von {{name}} fehlgeschlagen: {{detail}}', tier: { diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index 092286075..fd4e45e02 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -1833,6 +1833,7 @@ export default { embeddedOverlay: 'Embedded Overlay', preferredSlicer: 'Preferred Slicer', preferredSlicerDescription: 'Choose which slicer application to open files with', + orcaslicerKnownIssuesWarning: 'OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.', useSlicerApi: 'Use Slicer API', useSlicerApiDescription: 'When on, "Slice" actions open the in-app slicer modal and call the slicer-API sidecar. When off (default), they hand off to the desktop slicer via URI scheme.', slicerCard: 'Slicer', @@ -3258,6 +3259,8 @@ export default { loadingPresets: 'Loading presets…', analyzingPlateFilaments: 'Analyzing plate filaments…', analyzingPlateFilamentsHint: 'Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.', + previewToast: 'Analyzing {{name}} — {{elapsed}}', + previewWithProgress: 'Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', notUsedByPlate: '— not used by this plate', printerMismatch: 'This 3MF was sliced for {{source}}, but you picked {{target}}. The slicer CLI cannot re-slice a 3MF for a different printer — open the source in Bambu Studio, change the printer, and re-export.', noPresetsForSlot: 'No presets available', @@ -3269,6 +3272,7 @@ export default { startedToast: 'Slicing {{name}} in the background…', queuedToast: 'Queued: {{name}} — {{elapsed}}', runningToast: 'Slicing {{name}} — {{elapsed}}', + runningWithProgress: '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', completedToast: 'Sliced {{name}}', failedToast: 'Slicing {{name}} failed: {{detail}}', tier: { diff --git a/frontend/src/i18n/locales/fr.ts b/frontend/src/i18n/locales/fr.ts index 9087db467..b8995323c 100644 --- a/frontend/src/i18n/locales/fr.ts +++ b/frontend/src/i18n/locales/fr.ts @@ -1779,6 +1779,7 @@ export default { embeddedOverlay: 'Superposition intégrée', preferredSlicer: 'Slicer préféré', preferredSlicerDescription: 'Application pour ouvrir les fichiers', + orcaslicerKnownIssuesWarning: 'OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.', useSlicerApi: 'Use Slicer API', useSlicerApiDescription: 'When on, "Slice" actions open the in-app slicer modal and call the slicer-API sidecar. When off (default), they hand off to the desktop slicer via URI scheme.', slicerCard: 'Slicer', @@ -3177,6 +3178,8 @@ export default { loadingPresets: 'Loading presets…', analyzingPlateFilaments: 'Analyzing plate filaments…', analyzingPlateFilamentsHint: 'Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.', + previewToast: 'Analyzing {{name}} — {{elapsed}}', + previewWithProgress: 'Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', notUsedByPlate: '— not used by this plate', printerMismatch: 'This 3MF was sliced for {{source}}, but you picked {{target}}. The slicer CLI cannot re-slice a 3MF for a different printer — open the source in Bambu Studio, change the printer, and re-export.', noPresetsForSlot: 'No presets available', @@ -3188,6 +3191,7 @@ export default { startedToast: 'Slicing {{name}} in the background…', queuedToast: 'Queued: {{name}} — {{elapsed}}', runningToast: 'Slicing {{name}} — {{elapsed}}', + runningWithProgress: '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', completedToast: 'Sliced {{name}}', failedToast: 'Slicing {{name}} failed: {{detail}}', tier: { diff --git a/frontend/src/i18n/locales/it.ts b/frontend/src/i18n/locales/it.ts index d79b0be20..9b4672d2f 100644 --- a/frontend/src/i18n/locales/it.ts +++ b/frontend/src/i18n/locales/it.ts @@ -1779,6 +1779,7 @@ export default { embeddedOverlay: 'Overlay incorporato', preferredSlicer: 'Slicer preferito', preferredSlicerDescription: 'Scegli quale applicazione slicer usare per aprire i file', + orcaslicerKnownIssuesWarning: 'OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.', useSlicerApi: 'Use Slicer API', useSlicerApiDescription: 'When on, "Slice" actions open the in-app slicer modal and call the slicer-API sidecar. When off (default), they hand off to the desktop slicer via URI scheme.', slicerCard: 'Slicer', @@ -3176,6 +3177,8 @@ export default { loadingPresets: 'Loading presets…', analyzingPlateFilaments: 'Analyzing plate filaments…', analyzingPlateFilamentsHint: 'Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.', + previewToast: 'Analyzing {{name}} — {{elapsed}}', + previewWithProgress: 'Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', notUsedByPlate: '— not used by this plate', printerMismatch: 'This 3MF was sliced for {{source}}, but you picked {{target}}. The slicer CLI cannot re-slice a 3MF for a different printer — open the source in Bambu Studio, change the printer, and re-export.', noPresetsForSlot: 'No presets available', @@ -3187,6 +3190,7 @@ export default { startedToast: 'Slicing {{name}} in the background…', queuedToast: 'Queued: {{name}} — {{elapsed}}', runningToast: 'Slicing {{name}} — {{elapsed}}', + runningWithProgress: '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', completedToast: 'Sliced {{name}}', failedToast: 'Slicing {{name}} failed: {{detail}}', tier: { diff --git a/frontend/src/i18n/locales/ja.ts b/frontend/src/i18n/locales/ja.ts index 9ed0e3d80..81c6355b9 100644 --- a/frontend/src/i18n/locales/ja.ts +++ b/frontend/src/i18n/locales/ja.ts @@ -1804,6 +1804,7 @@ export default { embeddedOverlay: '埋め込みオーバーレイ', preferredSlicer: '優先スライサー', preferredSlicerDescription: 'ファイルを開くスライサーアプリケーションを選択', + orcaslicerKnownIssuesWarning: 'OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.', useSlicerApi: 'Use Slicer API', useSlicerApiDescription: 'When on, "Slice" actions open the in-app slicer modal and call the slicer-API sidecar. When off (default), they hand off to the desktop slicer via URI scheme.', slicerCard: 'Slicer', @@ -3215,6 +3216,8 @@ export default { loadingPresets: 'Loading presets…', analyzingPlateFilaments: 'Analyzing plate filaments…', analyzingPlateFilamentsHint: 'Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.', + previewToast: 'Analyzing {{name}} — {{elapsed}}', + previewWithProgress: 'Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', notUsedByPlate: '— not used by this plate', printerMismatch: 'This 3MF was sliced for {{source}}, but you picked {{target}}. The slicer CLI cannot re-slice a 3MF for a different printer — open the source in Bambu Studio, change the printer, and re-export.', noPresetsForSlot: 'No presets available', @@ -3226,6 +3229,7 @@ export default { startedToast: 'Slicing {{name}} in the background…', queuedToast: 'Queued: {{name}} — {{elapsed}}', runningToast: 'Slicing {{name}} — {{elapsed}}', + runningWithProgress: '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', completedToast: 'Sliced {{name}}', failedToast: 'Slicing {{name}} failed: {{detail}}', tier: { diff --git a/frontend/src/i18n/locales/pt-BR.ts b/frontend/src/i18n/locales/pt-BR.ts index 69c2d3204..a5c3d6ffb 100644 --- a/frontend/src/i18n/locales/pt-BR.ts +++ b/frontend/src/i18n/locales/pt-BR.ts @@ -1779,6 +1779,7 @@ export default { embeddedOverlay: 'Sobreposição Incorporada', preferredSlicer: 'Fatiador Preferido', preferredSlicerDescription: 'Escolha qual aplicativo de fatiamento abrirá os arquivos', + orcaslicerKnownIssuesWarning: 'OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.', useSlicerApi: 'Use Slicer API', useSlicerApiDescription: 'When on, "Slice" actions open the in-app slicer modal and call the slicer-API sidecar. When off (default), they hand off to the desktop slicer via URI scheme.', slicerCard: 'Slicer', @@ -3190,6 +3191,8 @@ export default { loadingPresets: 'Loading presets…', analyzingPlateFilaments: 'Analyzing plate filaments…', analyzingPlateFilamentsHint: 'Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.', + previewToast: 'Analyzing {{name}} — {{elapsed}}', + previewWithProgress: 'Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', notUsedByPlate: '— not used by this plate', printerMismatch: 'This 3MF was sliced for {{source}}, but you picked {{target}}. The slicer CLI cannot re-slice a 3MF for a different printer — open the source in Bambu Studio, change the printer, and re-export.', noPresetsForSlot: 'No presets available', @@ -3201,6 +3204,7 @@ export default { startedToast: 'Slicing {{name}} in the background…', queuedToast: 'Queued: {{name}} — {{elapsed}}', runningToast: 'Slicing {{name}} — {{elapsed}}', + runningWithProgress: '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', completedToast: 'Sliced {{name}}', failedToast: 'Slicing {{name}} failed: {{detail}}', tier: { diff --git a/frontend/src/i18n/locales/zh-CN.ts b/frontend/src/i18n/locales/zh-CN.ts index f9b150a9b..f8d2d5c0d 100644 --- a/frontend/src/i18n/locales/zh-CN.ts +++ b/frontend/src/i18n/locales/zh-CN.ts @@ -1831,6 +1831,7 @@ export default { embeddedOverlay: '嵌入式叠加层', preferredSlicer: '首选切片软件', preferredSlicerDescription: '选择要用于打开文件的切片软件', + orcaslicerKnownIssuesWarning: 'OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.', useSlicerApi: 'Use Slicer API', useSlicerApiDescription: 'When on, "Slice" actions open the in-app slicer modal and call the slicer-API sidecar. When off (default), they hand off to the desktop slicer via URI scheme.', slicerCard: 'Slicer', @@ -3242,6 +3243,8 @@ export default { loadingPresets: 'Loading presets…', analyzingPlateFilaments: 'Analyzing plate filaments…', analyzingPlateFilamentsHint: 'Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.', + previewToast: 'Analyzing {{name}} — {{elapsed}}', + previewWithProgress: 'Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', notUsedByPlate: '— not used by this plate', printerMismatch: 'This 3MF was sliced for {{source}}, but you picked {{target}}. The slicer CLI cannot re-slice a 3MF for a different printer — open the source in Bambu Studio, change the printer, and re-export.', noPresetsForSlot: 'No presets available', @@ -3253,6 +3256,7 @@ export default { startedToast: 'Slicing {{name}} in the background…', queuedToast: 'Queued: {{name}} — {{elapsed}}', runningToast: 'Slicing {{name}} — {{elapsed}}', + runningWithProgress: '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', completedToast: 'Sliced {{name}}', failedToast: 'Slicing {{name}} failed: {{detail}}', tier: { diff --git a/frontend/src/i18n/locales/zh-TW.ts b/frontend/src/i18n/locales/zh-TW.ts index 977b7e1ed..3d8760bb9 100644 --- a/frontend/src/i18n/locales/zh-TW.ts +++ b/frontend/src/i18n/locales/zh-TW.ts @@ -1831,6 +1831,7 @@ export default { embeddedOverlay: '嵌入式疊加層', preferredSlicer: '首選切片軟體', preferredSlicerDescription: '選擇要用於開啟檔案的切片軟體', + orcaslicerKnownIssuesWarning: 'OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.', useSlicerApi: 'Use Slicer API', useSlicerApiDescription: 'When on, "Slice" actions open the in-app slicer modal and call the slicer-API sidecar. When off (default), they hand off to the desktop slicer via URI scheme.', slicerCard: 'Slicer', @@ -3242,6 +3243,8 @@ export default { loadingPresets: 'Loading presets…', analyzingPlateFilaments: 'Analyzing plate filaments…', analyzingPlateFilamentsHint: 'Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.', + previewToast: 'Analyzing {{name}} — {{elapsed}}', + previewWithProgress: 'Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', notUsedByPlate: '— not used by this plate', printerMismatch: 'This 3MF was sliced for {{source}}, but you picked {{target}}. The slicer CLI cannot re-slice a 3MF for a different printer — open the source in Bambu Studio, change the printer, and re-export.', noPresetsForSlot: 'No presets available', @@ -3253,6 +3256,7 @@ export default { startedToast: 'Slicing {{name}} in the background…', queuedToast: 'Queued: {{name}} — {{elapsed}}', runningToast: 'Slicing {{name}} — {{elapsed}}', + runningWithProgress: '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', completedToast: 'Sliced {{name}}', failedToast: 'Slicing {{name}} failed: {{detail}}', tier: { diff --git a/frontend/src/pages/SettingsPage.tsx b/frontend/src/pages/SettingsPage.tsx index afdeef4bf..18e21f02d 100644 --- a/frontend/src/pages/SettingsPage.tsx +++ b/frontend/src/pages/SettingsPage.tsx @@ -4100,6 +4100,25 @@ export function SettingsPage() {

{t('settings.preferredSlicerDescription')}

+ {/* Upstream OrcaSlicer 2.3.2 / 2.4.0-dev have two known + CLI bugs that block slicing many Bambu-authored 3MFs: + a SIGSEGV on painted multi-extruder 3MFs (#12426) and + a strict range-check on sentinel parameter values + BambuStudio writes by default. Until the upstream + fixes land, surface a clear warning when a user has + OrcaSlicer selected so they know what to expect; we + don't auto-switch them in case they're testing. */} + {(localSettings.preferred_slicer ?? 'bambu_studio') === 'orcaslicer' && ( +
+ {t( + 'settings.orcaslicerKnownIssuesWarning', + 'OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.', + )} +
+ )}
diff --git a/static/assets/index-Bbpbjxtl.css b/static/assets/index-Bbpbjxtl.css deleted file mode 100644 index c43a40e2a..000000000 --- a/static/assets/index-Bbpbjxtl.css +++ /dev/null @@ -1 +0,0 @@ -@import"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap";@layer properties,theme,base,components,utilities;@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-300:oklch(90.5% .182 98.111);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-yellow-600:oklch(68.1% .162 75.834);--color-yellow-700:oklch(55.4% .135 66.442);--color-lime-500:oklch(76.8% .233 130.85);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-green-900:oklch(39.3% .095 152.535);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-teal-400:oklch(77.7% .152 181.912);--color-teal-500:oklch(70.4% .14 182.503);--color-cyan-300:oklch(86.5% .127 207.078);--color-cyan-400:oklch(78.9% .154 211.53);--color-cyan-500:oklch(71.5% .143 215.221);--color-cyan-600:oklch(60.9% .126 221.723);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-500:oklch(58.5% .233 277.117);--color-violet-500:oklch(60.6% .25 292.717);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-700:oklch(49.6% .265 301.924);--color-fuchsia-500:oklch(66.7% .295 322.15);--color-rose-300:oklch(81% .117 11.638);--color-rose-400:oklch(71.2% .194 13.428);--color-rose-500:oklch(64.5% .246 16.439);--color-rose-600:oklch(58.6% .253 17.585);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-500:oklch(55.4% .046 257.417);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-black:#000;--color-white:#fff;--spacing:.25rem;--breakpoint-2xl:96rem;--container-xs:20rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--drop-shadow-md:0 3px 3px #0000001f;--drop-shadow-lg:0 4px 4px #00000026;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0,0,.2,1)infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-sm:8px;--blur-2xl:40px;--aspect-video:16/9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-bambu-green:var(--accent);--color-bambu-green-light:var(--accent-light);--color-bambu-green-dark:var(--accent-dark);--color-status-ok:var(--status-ok);--color-status-error:var(--status-error);--color-status-warning:var(--status-warning);--color-bambu-dark:var(--bg-primary);--color-bambu-dark-secondary:var(--bg-secondary);--color-bambu-dark-tertiary:var(--bg-tertiary);--color-bambu-gray:var(--text-muted);--color-bambu-gray-light:var(--text-secondary);--color-bambu-gray-dark:var(--text-tertiary)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}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;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.inset-2{inset:calc(var(--spacing)*2)}.inset-x-0{inset-inline:calc(var(--spacing)*0)}.inset-y-0{inset-block:calc(var(--spacing)*0)}.-top-0\.5{top:calc(var(--spacing)*-.5)}.-top-1{top:calc(var(--spacing)*-1)}.-top-1\.5{top:calc(var(--spacing)*-1.5)}.top-0{top:calc(var(--spacing)*0)}.top-0\.5{top:calc(var(--spacing)*.5)}.top-1{top:calc(var(--spacing)*1)}.top-1\.5{top:calc(var(--spacing)*1.5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing)*2)}.top-2\.5{top:calc(var(--spacing)*2.5)}.top-3{top:calc(var(--spacing)*3)}.top-4{top:calc(var(--spacing)*4)}.top-8{top:calc(var(--spacing)*8)}.top-\[2px\]{top:2px}.top-\[3px\]{top:3px}.top-\[52px\]{top:52px}.top-full{top:100%}.-right-0\.5{right:calc(var(--spacing)*-.5)}.-right-1{right:calc(var(--spacing)*-1)}.-right-1\.5{right:calc(var(--spacing)*-1.5)}.-right-2{right:calc(var(--spacing)*-2)}.right-0{right:calc(var(--spacing)*0)}.right-0\.5{right:calc(var(--spacing)*.5)}.right-1{right:calc(var(--spacing)*1)}.right-1\.5{right:calc(var(--spacing)*1.5)}.right-2{right:calc(var(--spacing)*2)}.right-3{right:calc(var(--spacing)*3)}.right-4{right:calc(var(--spacing)*4)}.right-6{right:calc(var(--spacing)*6)}.right-12{right:calc(var(--spacing)*12)}.right-20{right:calc(var(--spacing)*20)}.right-\[5\.5rem\]{right:5.5rem}.right-full{right:100%}.-bottom-0\.5{bottom:calc(var(--spacing)*-.5)}.-bottom-1{bottom:calc(var(--spacing)*-1)}.-bottom-2{bottom:calc(var(--spacing)*-2)}.-bottom-7{bottom:calc(var(--spacing)*-7)}.bottom-0{bottom:calc(var(--spacing)*0)}.bottom-0\.5{bottom:calc(var(--spacing)*.5)}.bottom-1{bottom:calc(var(--spacing)*1)}.bottom-2{bottom:calc(var(--spacing)*2)}.bottom-3{bottom:calc(var(--spacing)*3)}.bottom-4{bottom:calc(var(--spacing)*4)}.bottom-6{bottom:calc(var(--spacing)*6)}.bottom-8{bottom:calc(var(--spacing)*8)}.bottom-20{bottom:calc(var(--spacing)*20)}.bottom-full{bottom:100%}.-left-2{left:calc(var(--spacing)*-2)}.left-0{left:calc(var(--spacing)*0)}.left-0\.5{left:calc(var(--spacing)*.5)}.left-1{left:calc(var(--spacing)*1)}.left-1\/2{left:50%}.left-2{left:calc(var(--spacing)*2)}.left-2\.5{left:calc(var(--spacing)*2.5)}.left-3{left:calc(var(--spacing)*3)}.left-4{left:calc(var(--spacing)*4)}.left-10{left:calc(var(--spacing)*10)}.left-12{left:calc(var(--spacing)*12)}.left-\[2px\]{left:2px}.left-\[3px\]{left:3px}.left-full{left:100%}.z-0{z-index:0}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-60,.z-\[60\]{z-index:60}.z-\[100\]{z-index:100}.z-\[101\]{z-index:101}.z-\[9998\]{z-index:9998}.z-\[9999\]{z-index:9999}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-4{grid-column:span 4/span 4}.col-span-full{grid-column:1/-1}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.-m-4{margin:calc(var(--spacing)*-4)}.-mx-2{margin-inline:calc(var(--spacing)*-2)}.-mx-4{margin-inline:calc(var(--spacing)*-4)}.mx-1{margin-inline:calc(var(--spacing)*1)}.mx-1\.5{margin-inline:calc(var(--spacing)*1.5)}.mx-2{margin-inline:calc(var(--spacing)*2)}.mx-4{margin-inline:calc(var(--spacing)*4)}.mx-5{margin-inline:calc(var(--spacing)*5)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing)*1)}.my-2{margin-block:calc(var(--spacing)*2)}.my-8{margin-block:calc(var(--spacing)*8)}.my-auto{margin-block:auto}.-mt-0\.5{margin-top:calc(var(--spacing)*-.5)}.-mt-2{margin-top:calc(var(--spacing)*-2)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-6{margin-top:calc(var(--spacing)*6)}.mt-8{margin-top:calc(var(--spacing)*8)}.mt-14{margin-top:calc(var(--spacing)*14)}.mt-auto{margin-top:auto}.mr-1{margin-right:calc(var(--spacing)*1)}.mr-1\.5{margin-right:calc(var(--spacing)*1.5)}.mr-2{margin-right:calc(var(--spacing)*2)}.mr-3{margin-right:calc(var(--spacing)*3)}.mr-4{margin-right:calc(var(--spacing)*4)}.mr-auto{margin-right:auto}.-mb-px{margin-bottom:-1px}.mb-0{margin-bottom:calc(var(--spacing)*0)}.mb-0\.5{margin-bottom:calc(var(--spacing)*.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-2\.5{margin-bottom:calc(var(--spacing)*2.5)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.-ml-1{margin-left:calc(var(--spacing)*-1)}.-ml-2{margin-left:calc(var(--spacing)*-2)}.ml-0\.5{margin-left:calc(var(--spacing)*.5)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-1\.5{margin-left:calc(var(--spacing)*1.5)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-3{margin-left:calc(var(--spacing)*3)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-6{margin-left:calc(var(--spacing)*6)}.ml-7{margin-left:calc(var(--spacing)*7)}.ml-9{margin-left:calc(var(--spacing)*9)}.ml-14{margin-left:calc(var(--spacing)*14)}.ml-16{margin-left:calc(var(--spacing)*16)}.ml-64{margin-left:calc(var(--spacing)*64)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.aspect-video{aspect-ratio:var(--aspect-video)}.h-0{height:calc(var(--spacing)*0)}.h-0\.5{height:calc(var(--spacing)*.5)}.h-1{height:calc(var(--spacing)*1)}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-2{height:calc(var(--spacing)*2)}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-4\.5{height:calc(var(--spacing)*4.5)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-12{height:calc(var(--spacing)*12)}.h-14{height:calc(var(--spacing)*14)}.h-16{height:calc(var(--spacing)*16)}.h-20{height:calc(var(--spacing)*20)}.h-24{height:calc(var(--spacing)*24)}.h-32{height:calc(var(--spacing)*32)}.h-48{height:calc(var(--spacing)*48)}.h-64{height:calc(var(--spacing)*64)}.h-80{height:calc(var(--spacing)*80)}.h-\[18px\]{height:18px}.h-\[38px\]{height:38px}.h-\[40px\]{height:40px}.h-\[48px\]{height:48px}.h-\[80vh\]{height:80vh}.h-\[160px\]{height:160px}.h-\[300px\]{height:300px}.h-\[calc\(100\%-40px\)\]{height:calc(100% - 40px)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-40{max-height:calc(var(--spacing)*40)}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-56{max-height:calc(var(--spacing)*56)}.max-h-60{max-height:calc(var(--spacing)*60)}.max-h-64{max-height:calc(var(--spacing)*64)}.max-h-80{max-height:calc(var(--spacing)*80)}.max-h-96{max-height:calc(var(--spacing)*96)}.max-h-\[3\.75rem\]{max-height:3.75rem}.max-h-\[28rem\]{max-height:28rem}.max-h-\[50vh\]{max-height:50vh}.max-h-\[60vh\]{max-height:60vh}.max-h-\[80vh\]{max-height:80vh}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-\[300px\]{max-height:300px}.max-h-\[400px\]{max-height:400px}.max-h-\[500px\]{max-height:500px}.max-h-\[600px\]{max-height:600px}.max-h-\[calc\(90vh-80px\)\]{max-height:calc(90vh - 80px)}.max-h-\[calc\(100vh-2rem\)\]{max-height:calc(100vh - 2rem)}.max-h-\[calc\(100vh-320px\)\]{max-height:calc(100vh - 320px)}.max-h-full{max-height:100%}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-\[36px\]{min-height:36px}.min-h-\[40px\]{min-height:40px}.min-h-\[44px\]{min-height:44px}.min-h-\[48px\]{min-height:48px}.min-h-\[80px\]{min-height:80px}.min-h-\[120px\]{min-height:120px}.min-h-\[300px\]{min-height:300px}.min-h-\[400px\]{min-height:400px}.min-h-\[calc\(100vh-64px\)\]{min-height:calc(100vh - 64px)}.min-h-screen{min-height:100vh}.w-0{width:calc(var(--spacing)*0)}.w-0\.5{width:calc(var(--spacing)*.5)}.w-1{width:calc(var(--spacing)*1)}.w-1\.5{width:calc(var(--spacing)*1.5)}.w-1\/2{width:50%}.w-1\/3{width:33.3333%}.w-2{width:calc(var(--spacing)*2)}.w-2\.5{width:calc(var(--spacing)*2.5)}.w-3{width:calc(var(--spacing)*3)}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-4\.5{width:calc(var(--spacing)*4.5)}.w-5{width:calc(var(--spacing)*5)}.w-5\/12{width:41.6667%}.w-6{width:calc(var(--spacing)*6)}.w-7{width:calc(var(--spacing)*7)}.w-7\/12{width:58.3333%}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-10{width:calc(var(--spacing)*10)}.w-11{width:calc(var(--spacing)*11)}.w-12{width:calc(var(--spacing)*12)}.w-14{width:calc(var(--spacing)*14)}.w-16{width:calc(var(--spacing)*16)}.w-20{width:calc(var(--spacing)*20)}.w-24{width:calc(var(--spacing)*24)}.w-32{width:calc(var(--spacing)*32)}.w-36{width:calc(var(--spacing)*36)}.w-40{width:calc(var(--spacing)*40)}.w-44{width:calc(var(--spacing)*44)}.w-48{width:calc(var(--spacing)*48)}.w-52{width:calc(var(--spacing)*52)}.w-56{width:calc(var(--spacing)*56)}.w-64{width:calc(var(--spacing)*64)}.w-72{width:calc(var(--spacing)*72)}.w-96{width:calc(var(--spacing)*96)}.w-\[240px\]{width:240px}.w-\[340px\]{width:340px}.w-\[420px\]{width:420px}.w-\[560px\]{width:560px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.w-screen{width:100vw}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-32{max-width:calc(var(--spacing)*32)}.max-w-\[40\%\]{max-width:40%}.max-w-\[50\%\]{max-width:50%}.max-w-\[80px\]{max-width:80px}.max-w-\[90vw\]{max-width:90vw}.max-w-\[100px\]{max-width:100px}.max-w-\[120px\]{max-width:120px}.max-w-\[150px\]{max-width:150px}.max-w-\[160px\]{max-width:160px}.max-w-\[200px\]{max-width:200px}.max-w-\[220px\]{max-width:220px}.max-w-\[280px\]{max-width:280px}.max-w-\[600px\]{max-width:600px}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-screen-2xl{max-width:var(--breakpoint-2xl)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-48{min-width:calc(var(--spacing)*48)}.min-w-\[16px\]{min-width:16px}.min-w-\[18px\]{min-width:18px}.min-w-\[32px\]{min-width:32px}.min-w-\[40px\]{min-width:40px}.min-w-\[48px\]{min-width:48px}.min-w-\[50px\]{min-width:50px}.min-w-\[80px\]{min-width:80px}.min-w-\[100px\]{min-width:100px}.min-w-\[120px\]{min-width:120px}.min-w-\[130px\]{min-width:130px}.min-w-\[140px\]{min-width:140px}.min-w-\[150px\]{min-width:150px}.min-w-\[160px\]{min-width:160px}.min-w-\[180px\]{min-width:180px}.min-w-\[200px\]{min-width:200px}.min-w-full{min-width:100%}.flex-1{flex:1}.flex-\[2_1_190px\]{flex:2 190px}.flex-shrink{flex-shrink:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-x-full{--tw-translate-x:-100%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-0{--tw-translate-x:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-0\.5{--tw-translate-x:calc(var(--spacing)*.5);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-1{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-3\.5{--tw-translate-x:calc(var(--spacing)*3.5);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-4{--tw-translate-x:calc(var(--spacing)*4);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-5{--tw-translate-x:calc(var(--spacing)*5);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-6{--tw-translate-x:calc(var(--spacing)*6);translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-105{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.scale-110{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x)var(--tw-scale-y)}.scale-\[1\.02\]{scale:1.02}.-rotate-90{rotate:-90deg}.rotate-90{rotate:90deg}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-col-resize{cursor:col-resize}.cursor-default{cursor:default}.cursor-ew-resize{cursor:ew-resize}.cursor-grab{cursor:grab}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-row-resize{cursor:row-resize}.cursor-se-resize{cursor:se-resize}.touch-manipulation{touch-action:manipulation}.touch-none{touch-action:none}.resize{resize:both}.resize-none{resize:none}.resize-y{resize:vertical}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.\[appearance\:textfield\]{appearance:textfield}.appearance-none{appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-\[auto_1fr_100px_100px_100px_80px\]{grid-template-columns:auto 1fr 100px 100px 100px 80px}.grid-cols-\[auto_1fr_120px_100px_100px_100px_80px\]{grid-template-columns:auto 1fr 120px 100px 100px 100px 80px}.grid-cols-\[repeat\(auto-fill\,minmax\(130px\,1fr\)\)\]{grid-template-columns:repeat(auto-fill,minmax(130px,1fr))}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0{gap:calc(var(--spacing)*0)}.gap-0\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-5{gap:calc(var(--spacing)*5)}.gap-6{gap:calc(var(--spacing)*6)}.gap-8{gap:calc(var(--spacing)*8)}.gap-\[3px\]{gap:3px}:where(.space-y-0>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*0)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*0)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*8)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-y-reverse)))}.gap-x-2{column-gap:calc(var(--spacing)*2)}.gap-x-3{column-gap:calc(var(--spacing)*3)}.gap-x-4{column-gap:calc(var(--spacing)*4)}.gap-x-6{column-gap:calc(var(--spacing)*6)}.gap-y-1{row-gap:calc(var(--spacing)*1)}.gap-y-1\.5{row-gap:calc(var(--spacing)*1.5)}.gap-y-2{row-gap:calc(var(--spacing)*2)}.gap-y-3{row-gap:calc(var(--spacing)*3)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px*var(--tw-divide-y-reverse));border-bottom-width:calc(1px*calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-bambu-dark-tertiary>:not(:last-child)),:where(.divide-bambu-dark-tertiary\/30>:not(:last-child)){border-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){:where(.divide-bambu-dark-tertiary\/30>:not(:last-child)){border-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)30%,transparent)}}:where(.divide-bambu-gray\/20>:not(:last-child)){border-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){:where(.divide-bambu-gray\/20>:not(:last-child)){border-color:color-mix(in oklab,var(--color-bambu-gray)20%,transparent)}}:where(.divide-gray-100>:not(:last-child)){border-color:var(--color-gray-100)}.self-stretch{align-self:stretch}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-lg{border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg)}.rounded-t-xl{border-top-left-radius:var(--radius-xl);border-top-right-radius:var(--radius-xl)}.\!rounded-l-none{border-top-left-radius:0!important;border-bottom-left-radius:0!important}.rounded-l{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-l-lg{border-top-left-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg)}.rounded-tl{border-top-left-radius:.25rem}.\!rounded-r-none{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.rounded-r-lg{border-top-right-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.rounded-b-2xl{border-bottom-right-radius:var(--radius-2xl);border-bottom-left-radius:var(--radius-2xl)}.rounded-b-lg{border-bottom-right-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-t-2{border-top-style:var(--tw-border-style);border-top-width:2px}.border-t-\[5px\]{border-top-style:var(--tw-border-style);border-top-width:5px}.border-t-\[6px\]{border-top-style:var(--tw-border-style);border-top-width:6px}.\!border-r-0{border-right-style:var(--tw-border-style)!important;border-right-width:0!important}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-r-\[5px\]{border-right-style:var(--tw-border-style);border-right-width:5px}.border-r-\[6px\]{border-right-style:var(--tw-border-style);border-right-width:6px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-b-\[6px\]{border-bottom-style:var(--tw-border-style);border-bottom-width:6px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-l-\[3px\]{border-left-style:var(--tw-border-style);border-left-width:3px}.border-l-\[5px\]{border-left-style:var(--tw-border-style);border-left-width:5px}.border-l-\[6px\]{border-left-style:var(--tw-border-style);border-left-width:6px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.\!border-green-500{border-color:var(--color-green-500)!important}.\!border-yellow-500{border-color:var(--color-yellow-500)!important}.border-amber-200{border-color:var(--color-amber-200)}.border-amber-300{border-color:var(--color-amber-300)}.border-amber-500{border-color:var(--color-amber-500)}.border-amber-500\/20{border-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/20{border-color:color-mix(in oklab,var(--color-amber-500)20%,transparent)}}.border-amber-500\/30{border-color:#f99c004d}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/30{border-color:color-mix(in oklab,var(--color-amber-500)30%,transparent)}}.border-amber-700{border-color:var(--color-amber-700)}.border-amber-700\/40{border-color:#b7500066}@supports (color:color-mix(in lab,red,red)){.border-amber-700\/40{border-color:color-mix(in oklab,var(--color-amber-700)40%,transparent)}}.border-bambu-dark-secondary{border-color:var(--color-bambu-dark-secondary)}.border-bambu-dark-tertiary,.border-bambu-dark-tertiary\/20{border-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.border-bambu-dark-tertiary\/20{border-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)20%,transparent)}}.border-bambu-dark-tertiary\/30{border-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.border-bambu-dark-tertiary\/30{border-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)30%,transparent)}}.border-bambu-dark-tertiary\/40{border-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.border-bambu-dark-tertiary\/40{border-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)40%,transparent)}}.border-bambu-dark-tertiary\/50{border-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.border-bambu-dark-tertiary\/50{border-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)50%,transparent)}}.border-bambu-dark-tertiary\/60{border-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.border-bambu-dark-tertiary\/60{border-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)60%,transparent)}}.border-bambu-gray,.border-bambu-gray\/20{border-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.border-bambu-gray\/20{border-color:color-mix(in oklab,var(--color-bambu-gray)20%,transparent)}}.border-bambu-gray\/30{border-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.border-bambu-gray\/30{border-color:color-mix(in oklab,var(--color-bambu-gray)30%,transparent)}}.border-bambu-gray\/50{border-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.border-bambu-gray\/50{border-color:color-mix(in oklab,var(--color-bambu-gray)50%,transparent)}}.border-bambu-green,.border-bambu-green\/20{border-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.border-bambu-green\/20{border-color:color-mix(in oklab,var(--color-bambu-green)20%,transparent)}}.border-bambu-green\/30{border-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.border-bambu-green\/30{border-color:color-mix(in oklab,var(--color-bambu-green)30%,transparent)}}.border-bambu-green\/40{border-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.border-bambu-green\/40{border-color:color-mix(in oklab,var(--color-bambu-green)40%,transparent)}}.border-bambu-green\/50{border-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.border-bambu-green\/50{border-color:color-mix(in oklab,var(--color-bambu-green)50%,transparent)}}.border-black\/20{border-color:#0003}@supports (color:color-mix(in lab,red,red)){.border-black\/20{border-color:color-mix(in oklab,var(--color-black)20%,transparent)}}.border-blue-400\/20{border-color:#54a2ff33}@supports (color:color-mix(in lab,red,red)){.border-blue-400\/20{border-color:color-mix(in oklab,var(--color-blue-400)20%,transparent)}}.border-blue-400\/50{border-color:#54a2ff80}@supports (color:color-mix(in lab,red,red)){.border-blue-400\/50{border-color:color-mix(in oklab,var(--color-blue-400)50%,transparent)}}.border-blue-500{border-color:var(--color-blue-500)}.border-blue-500\/20{border-color:#3080ff33}@supports (color:color-mix(in lab,red,red)){.border-blue-500\/20{border-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.border-blue-500\/30{border-color:#3080ff4d}@supports (color:color-mix(in lab,red,red)){.border-blue-500\/30{border-color:color-mix(in oklab,var(--color-blue-500)30%,transparent)}}.border-blue-500\/40{border-color:#3080ff66}@supports (color:color-mix(in lab,red,red)){.border-blue-500\/40{border-color:color-mix(in oklab,var(--color-blue-500)40%,transparent)}}.border-blue-500\/50{border-color:#3080ff80}@supports (color:color-mix(in lab,red,red)){.border-blue-500\/50{border-color:color-mix(in oklab,var(--color-blue-500)50%,transparent)}}.border-emerald-500\/20{border-color:#00bb7f33}@supports (color:color-mix(in lab,red,red)){.border-emerald-500\/20{border-color:color-mix(in oklab,var(--color-emerald-500)20%,transparent)}}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-400\/20{border-color:#99a1af33}@supports (color:color-mix(in lab,red,red)){.border-gray-400\/20{border-color:color-mix(in oklab,var(--color-gray-400)20%,transparent)}}.border-gray-500{border-color:var(--color-gray-500)}.border-gray-500\/40{border-color:#6a728266}@supports (color:color-mix(in lab,red,red)){.border-gray-500\/40{border-color:color-mix(in oklab,var(--color-gray-500)40%,transparent)}}.border-gray-700{border-color:var(--color-gray-700)}.border-gray-800{border-color:var(--color-gray-800)}.border-green-300{border-color:var(--color-green-300)}.border-green-400{border-color:var(--color-green-400)}.border-green-500{border-color:var(--color-green-500)}.border-green-500\/30{border-color:#00c7584d}@supports (color:color-mix(in lab,red,red)){.border-green-500\/30{border-color:color-mix(in oklab,var(--color-green-500)30%,transparent)}}.border-green-500\/40{border-color:#00c75866}@supports (color:color-mix(in lab,red,red)){.border-green-500\/40{border-color:color-mix(in oklab,var(--color-green-500)40%,transparent)}}.border-green-500\/50{border-color:#00c75880}@supports (color:color-mix(in lab,red,red)){.border-green-500\/50{border-color:color-mix(in oklab,var(--color-green-500)50%,transparent)}}.border-green-800{border-color:var(--color-green-800)}.border-orange-400\/20{border-color:#ff8b1a33}@supports (color:color-mix(in lab,red,red)){.border-orange-400\/20{border-color:color-mix(in oklab,var(--color-orange-400)20%,transparent)}}.border-orange-400\/50{border-color:#ff8b1a80}@supports (color:color-mix(in lab,red,red)){.border-orange-400\/50{border-color:color-mix(in oklab,var(--color-orange-400)50%,transparent)}}.border-orange-500\/20{border-color:#fe6e0033}@supports (color:color-mix(in lab,red,red)){.border-orange-500\/20{border-color:color-mix(in oklab,var(--color-orange-500)20%,transparent)}}.border-orange-500\/30{border-color:#fe6e004d}@supports (color:color-mix(in lab,red,red)){.border-orange-500\/30{border-color:color-mix(in oklab,var(--color-orange-500)30%,transparent)}}.border-purple-400\/20{border-color:#c07eff33}@supports (color:color-mix(in lab,red,red)){.border-purple-400\/20{border-color:color-mix(in oklab,var(--color-purple-400)20%,transparent)}}.border-purple-500{border-color:var(--color-purple-500)}.border-purple-500\/20{border-color:#ac4bff33}@supports (color:color-mix(in lab,red,red)){.border-purple-500\/20{border-color:color-mix(in oklab,var(--color-purple-500)20%,transparent)}}.border-purple-500\/30{border-color:#ac4bff4d}@supports (color:color-mix(in lab,red,red)){.border-purple-500\/30{border-color:color-mix(in oklab,var(--color-purple-500)30%,transparent)}}.border-red-300{border-color:var(--color-red-300)}.border-red-500{border-color:var(--color-red-500)}.border-red-500\/20{border-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.border-red-500\/20{border-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.border-red-500\/30{border-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.border-red-500\/30{border-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.border-red-500\/40{border-color:#fb2c3666}@supports (color:color-mix(in lab,red,red)){.border-red-500\/40{border-color:color-mix(in oklab,var(--color-red-500)40%,transparent)}}.border-red-500\/50{border-color:#fb2c3680}@supports (color:color-mix(in lab,red,red)){.border-red-500\/50{border-color:color-mix(in oklab,var(--color-red-500)50%,transparent)}}.border-red-800{border-color:var(--color-red-800)}.border-red-800\/70{border-color:#9f0712b3}@supports (color:color-mix(in lab,red,red)){.border-red-800\/70{border-color:color-mix(in oklab,var(--color-red-800)70%,transparent)}}.border-red-900\/40{border-color:#82181a66}@supports (color:color-mix(in lab,red,red)){.border-red-900\/40{border-color:color-mix(in oklab,var(--color-red-900)40%,transparent)}}.border-slate-500{border-color:var(--color-slate-500)}.border-status-error\/20{border-color:var(--color-status-error)}@supports (color:color-mix(in lab,red,red)){.border-status-error\/20{border-color:color-mix(in oklab,var(--color-status-error)20%,transparent)}}.border-status-ok,.border-status-ok\/20{border-color:var(--color-status-ok)}@supports (color:color-mix(in lab,red,red)){.border-status-ok\/20{border-color:color-mix(in oklab,var(--color-status-ok)20%,transparent)}}.border-status-warning\/20{border-color:var(--color-status-warning)}@supports (color:color-mix(in lab,red,red)){.border-status-warning\/20{border-color:color-mix(in oklab,var(--color-status-warning)20%,transparent)}}.border-transparent{border-color:#0000}.border-white{border-color:var(--color-white)}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.border-white\/10{border-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.border-white\/20{border-color:#fff3}@supports (color:color-mix(in lab,red,red)){.border-white\/20{border-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.border-white\/30{border-color:#ffffff4d}@supports (color:color-mix(in lab,red,red)){.border-white\/30{border-color:color-mix(in oklab,var(--color-white)30%,transparent)}}.border-yellow-400\/20{border-color:#fac80033}@supports (color:color-mix(in lab,red,red)){.border-yellow-400\/20{border-color:color-mix(in oklab,var(--color-yellow-400)20%,transparent)}}.border-yellow-400\/40{border-color:#fac80066}@supports (color:color-mix(in lab,red,red)){.border-yellow-400\/40{border-color:color-mix(in oklab,var(--color-yellow-400)40%,transparent)}}.border-yellow-400\/50{border-color:#fac80080}@supports (color:color-mix(in lab,red,red)){.border-yellow-400\/50{border-color:color-mix(in oklab,var(--color-yellow-400)50%,transparent)}}.border-yellow-500{border-color:var(--color-yellow-500)}.border-yellow-500\/20{border-color:#edb20033}@supports (color:color-mix(in lab,red,red)){.border-yellow-500\/20{border-color:color-mix(in oklab,var(--color-yellow-500)20%,transparent)}}.border-yellow-500\/30{border-color:#edb2004d}@supports (color:color-mix(in lab,red,red)){.border-yellow-500\/30{border-color:color-mix(in oklab,var(--color-yellow-500)30%,transparent)}}.border-yellow-500\/50{border-color:#edb20080}@supports (color:color-mix(in lab,red,red)){.border-yellow-500\/50{border-color:color-mix(in oklab,var(--color-yellow-500)50%,transparent)}}.border-zinc-500{border-color:var(--color-zinc-500)}.border-zinc-600{border-color:var(--color-zinc-600)}.border-zinc-700{border-color:var(--color-zinc-700)}.border-zinc-700\/50{border-color:#3f3f4680}@supports (color:color-mix(in lab,red,red)){.border-zinc-700\/50{border-color:color-mix(in oklab,var(--color-zinc-700)50%,transparent)}}.border-zinc-800{border-color:var(--color-zinc-800)}.border-t-bambu-dark-tertiary{border-top-color:var(--color-bambu-dark-tertiary)}.border-t-transparent{border-top-color:#0000}.border-r-transparent{border-right-color:#0000}.border-b-bambu-dark-tertiary{border-bottom-color:var(--color-bambu-dark-tertiary)}.border-l-blue-500{border-left-color:var(--color-blue-500)}.border-l-emerald-500{border-left-color:var(--color-emerald-500)}.border-l-gray-500{border-left-color:var(--color-gray-500)}.border-l-red-500{border-left-color:var(--color-red-500)}.border-l-transparent{border-left-color:#0000}.border-l-yellow-500{border-left-color:var(--color-yellow-500)}.\!bg-bambu-green{background-color:var(--color-bambu-green)!important}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\/5{background-color:#f99c000d}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/5{background-color:color-mix(in oklab,var(--color-amber-500)5%,transparent)}}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/10{background-color:color-mix(in oklab,var(--color-amber-500)10%,transparent)}}.bg-amber-500\/20{background-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/20{background-color:color-mix(in oklab,var(--color-amber-500)20%,transparent)}}.bg-amber-600{background-color:var(--color-amber-600)}.bg-amber-600\/20{background-color:#dd740033}@supports (color:color-mix(in lab,red,red)){.bg-amber-600\/20{background-color:color-mix(in oklab,var(--color-amber-600)20%,transparent)}}.bg-amber-900\/20{background-color:#7b330633}@supports (color:color-mix(in lab,red,red)){.bg-amber-900\/20{background-color:color-mix(in oklab,var(--color-amber-900)20%,transparent)}}.bg-amber-900\/30{background-color:#7b33064d}@supports (color:color-mix(in lab,red,red)){.bg-amber-900\/30{background-color:color-mix(in oklab,var(--color-amber-900)30%,transparent)}}.bg-bambu-dark{background-color:var(--color-bambu-dark)}.bg-bambu-dark-secondary,.bg-bambu-dark-secondary\/30{background-color:var(--color-bambu-dark-secondary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-secondary\/30{background-color:color-mix(in oklab,var(--color-bambu-dark-secondary)30%,transparent)}}.bg-bambu-dark-secondary\/50{background-color:var(--color-bambu-dark-secondary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-secondary\/50{background-color:color-mix(in oklab,var(--color-bambu-dark-secondary)50%,transparent)}}.bg-bambu-dark-secondary\/60{background-color:var(--color-bambu-dark-secondary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-secondary\/60{background-color:color-mix(in oklab,var(--color-bambu-dark-secondary)60%,transparent)}}.bg-bambu-dark-secondary\/90{background-color:var(--color-bambu-dark-secondary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-secondary\/90{background-color:color-mix(in oklab,var(--color-bambu-dark-secondary)90%,transparent)}}.bg-bambu-dark-secondary\/95{background-color:var(--color-bambu-dark-secondary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-secondary\/95{background-color:color-mix(in oklab,var(--color-bambu-dark-secondary)95%,transparent)}}.bg-bambu-dark-tertiary,.bg-bambu-dark-tertiary\/20{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-tertiary\/20{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)20%,transparent)}}.bg-bambu-dark-tertiary\/30{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-tertiary\/30{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)30%,transparent)}}.bg-bambu-dark-tertiary\/40{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-tertiary\/40{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)40%,transparent)}}.bg-bambu-dark-tertiary\/50{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-tertiary\/50{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)50%,transparent)}}.bg-bambu-dark-tertiary\/70{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-tertiary\/70{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)70%,transparent)}}.bg-bambu-dark-tertiary\/80{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark-tertiary\/80{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)80%,transparent)}}.bg-bambu-dark\/20{background-color:var(--color-bambu-dark)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark\/20{background-color:color-mix(in oklab,var(--color-bambu-dark)20%,transparent)}}.bg-bambu-dark\/30{background-color:var(--color-bambu-dark)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark\/30{background-color:color-mix(in oklab,var(--color-bambu-dark)30%,transparent)}}.bg-bambu-dark\/50{background-color:var(--color-bambu-dark)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark\/50{background-color:color-mix(in oklab,var(--color-bambu-dark)50%,transparent)}}.bg-bambu-dark\/80{background-color:var(--color-bambu-dark)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark\/80{background-color:color-mix(in oklab,var(--color-bambu-dark)80%,transparent)}}.bg-bambu-dark\/90{background-color:var(--color-bambu-dark)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-dark\/90{background-color:color-mix(in oklab,var(--color-bambu-dark)90%,transparent)}}.bg-bambu-gray,.bg-bambu-gray\/10{background-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-gray\/10{background-color:color-mix(in oklab,var(--color-bambu-gray)10%,transparent)}}.bg-bambu-gray\/20{background-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-gray\/20{background-color:color-mix(in oklab,var(--color-bambu-gray)20%,transparent)}}.bg-bambu-gray\/30{background-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-gray\/30{background-color:color-mix(in oklab,var(--color-bambu-gray)30%,transparent)}}.bg-bambu-gray\/40{background-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-gray\/40{background-color:color-mix(in oklab,var(--color-bambu-gray)40%,transparent)}}.bg-bambu-gray\/50{background-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-gray\/50{background-color:color-mix(in oklab,var(--color-bambu-gray)50%,transparent)}}.bg-bambu-gray\/60{background-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-gray\/60{background-color:color-mix(in oklab,var(--color-bambu-gray)60%,transparent)}}.bg-bambu-gray\/90{background-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-gray\/90{background-color:color-mix(in oklab,var(--color-bambu-gray)90%,transparent)}}.bg-bambu-green,.bg-bambu-green\/5{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-green\/5{background-color:color-mix(in oklab,var(--color-bambu-green)5%,transparent)}}.bg-bambu-green\/10{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-green\/10{background-color:color-mix(in oklab,var(--color-bambu-green)10%,transparent)}}.bg-bambu-green\/15{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-green\/15{background-color:color-mix(in oklab,var(--color-bambu-green)15%,transparent)}}.bg-bambu-green\/20{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-green\/20{background-color:color-mix(in oklab,var(--color-bambu-green)20%,transparent)}}.bg-bambu-green\/30{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-green\/30{background-color:color-mix(in oklab,var(--color-bambu-green)30%,transparent)}}.bg-bambu-green\/40{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-green\/40{background-color:color-mix(in oklab,var(--color-bambu-green)40%,transparent)}}.bg-bambu-green\/50{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-green\/50{background-color:color-mix(in oklab,var(--color-bambu-green)50%,transparent)}}.bg-bambu-green\/75{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-green\/75{background-color:color-mix(in oklab,var(--color-bambu-green)75%,transparent)}}.bg-bambu-green\/90{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.bg-bambu-green\/90{background-color:color-mix(in oklab,var(--color-bambu-green)90%,transparent)}}.bg-black{background-color:var(--color-black)}.bg-black\/15{background-color:#00000026}@supports (color:color-mix(in lab,red,red)){.bg-black\/15{background-color:color-mix(in oklab,var(--color-black)15%,transparent)}}.bg-black\/30{background-color:#0000004d}@supports (color:color-mix(in lab,red,red)){.bg-black\/30{background-color:color-mix(in oklab,var(--color-black)30%,transparent)}}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab,red,red)){.bg-black\/40{background-color:color-mix(in oklab,var(--color-black)40%,transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab,red,red)){.bg-black\/60{background-color:color-mix(in oklab,var(--color-black)60%,transparent)}}.bg-black\/70{background-color:#000000b3}@supports (color:color-mix(in lab,red,red)){.bg-black\/70{background-color:color-mix(in oklab,var(--color-black)70%,transparent)}}.bg-black\/80{background-color:#000c}@supports (color:color-mix(in lab,red,red)){.bg-black\/80{background-color:color-mix(in oklab,var(--color-black)80%,transparent)}}.bg-black\/90{background-color:#000000e6}@supports (color:color-mix(in lab,red,red)){.bg-black\/90{background-color:color-mix(in oklab,var(--color-black)90%,transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-400{background-color:var(--color-blue-400)}.bg-blue-400\/10{background-color:#54a2ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-400\/10{background-color:color-mix(in oklab,var(--color-blue-400)10%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-500\/5{background-color:#3080ff0d}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/5{background-color:color-mix(in oklab,var(--color-blue-500)5%,transparent)}}.bg-blue-500\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/10{background-color:color-mix(in oklab,var(--color-blue-500)10%,transparent)}}.bg-blue-500\/15{background-color:#3080ff26}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/15{background-color:color-mix(in oklab,var(--color-blue-500)15%,transparent)}}.bg-blue-500\/20{background-color:#3080ff33}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/20{background-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.bg-blue-500\/30{background-color:#3080ff4d}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/30{background-color:color-mix(in oklab,var(--color-blue-500)30%,transparent)}}.bg-blue-500\/90{background-color:#3080ffe6}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/90{background-color:color-mix(in oklab,var(--color-blue-500)90%,transparent)}}.bg-blue-600{background-color:var(--color-blue-600)}.bg-blue-600\/20{background-color:#155dfc33}@supports (color:color-mix(in lab,red,red)){.bg-blue-600\/20{background-color:color-mix(in oklab,var(--color-blue-600)20%,transparent)}}.bg-blue-700{background-color:var(--color-blue-700)}.bg-cyan-500{background-color:var(--color-cyan-500)}.bg-cyan-500\/10{background-color:#00b7d71a}@supports (color:color-mix(in lab,red,red)){.bg-cyan-500\/10{background-color:color-mix(in oklab,var(--color-cyan-500)10%,transparent)}}.bg-cyan-500\/20{background-color:#00b7d733}@supports (color:color-mix(in lab,red,red)){.bg-cyan-500\/20{background-color:color-mix(in oklab,var(--color-cyan-500)20%,transparent)}}.bg-cyan-600\/20{background-color:#0092b533}@supports (color:color-mix(in lab,red,red)){.bg-cyan-600\/20{background-color:color-mix(in oklab,var(--color-cyan-600)20%,transparent)}}.bg-emerald-500\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/10{background-color:color-mix(in oklab,var(--color-emerald-500)10%,transparent)}}.bg-emerald-500\/20{background-color:#00bb7f33}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/20{background-color:color-mix(in oklab,var(--color-emerald-500)20%,transparent)}}.bg-emerald-600\/20{background-color:#00976733}@supports (color:color-mix(in lab,red,red)){.bg-emerald-600\/20{background-color:color-mix(in oklab,var(--color-emerald-600)20%,transparent)}}.bg-emerald-700{background-color:var(--color-emerald-700)}.bg-fuchsia-500{background-color:var(--color-fuchsia-500)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-400{background-color:var(--color-gray-400)}.bg-gray-400\/10{background-color:#99a1af1a}@supports (color:color-mix(in lab,red,red)){.bg-gray-400\/10{background-color:color-mix(in oklab,var(--color-gray-400)10%,transparent)}}.bg-gray-500{background-color:var(--color-gray-500)}.bg-gray-500\/15{background-color:#6a728226}@supports (color:color-mix(in lab,red,red)){.bg-gray-500\/15{background-color:color-mix(in oklab,var(--color-gray-500)15%,transparent)}}.bg-gray-500\/20{background-color:#6a728233}@supports (color:color-mix(in lab,red,red)){.bg-gray-500\/20{background-color:color-mix(in oklab,var(--color-gray-500)20%,transparent)}}.bg-gray-600{background-color:var(--color-gray-600)}.bg-gray-800{background-color:var(--color-gray-800)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-400{background-color:var(--color-green-400)}.bg-green-400\/10{background-color:#05df721a}@supports (color:color-mix(in lab,red,red)){.bg-green-400\/10{background-color:color-mix(in oklab,var(--color-green-400)10%,transparent)}}.bg-green-500{background-color:var(--color-green-500)}.bg-green-500\/10{background-color:#00c7581a}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/10{background-color:color-mix(in oklab,var(--color-green-500)10%,transparent)}}.bg-green-500\/15{background-color:#00c75826}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/15{background-color:color-mix(in oklab,var(--color-green-500)15%,transparent)}}.bg-green-500\/20{background-color:#00c75833}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/20{background-color:color-mix(in oklab,var(--color-green-500)20%,transparent)}}.bg-green-600{background-color:var(--color-green-600)}.bg-green-600\/20{background-color:#00a54433}@supports (color:color-mix(in lab,red,red)){.bg-green-600\/20{background-color:color-mix(in oklab,var(--color-green-600)20%,transparent)}}.bg-green-600\/40{background-color:#00a54466}@supports (color:color-mix(in lab,red,red)){.bg-green-600\/40{background-color:color-mix(in oklab,var(--color-green-600)40%,transparent)}}.bg-green-700{background-color:var(--color-green-700)}.bg-green-900\/30{background-color:#0d542b4d}@supports (color:color-mix(in lab,red,red)){.bg-green-900\/30{background-color:color-mix(in oklab,var(--color-green-900)30%,transparent)}}.bg-green-900\/50{background-color:#0d542b80}@supports (color:color-mix(in lab,red,red)){.bg-green-900\/50{background-color:color-mix(in oklab,var(--color-green-900)50%,transparent)}}.bg-indigo-500\/10{background-color:#625fff1a}@supports (color:color-mix(in lab,red,red)){.bg-indigo-500\/10{background-color:color-mix(in oklab,var(--color-indigo-500)10%,transparent)}}.bg-indigo-500\/15{background-color:#625fff26}@supports (color:color-mix(in lab,red,red)){.bg-indigo-500\/15{background-color:color-mix(in oklab,var(--color-indigo-500)15%,transparent)}}.bg-indigo-500\/20{background-color:#625fff33}@supports (color:color-mix(in lab,red,red)){.bg-indigo-500\/20{background-color:color-mix(in oklab,var(--color-indigo-500)20%,transparent)}}.bg-lime-500{background-color:var(--color-lime-500)}.bg-orange-400\/10{background-color:#ff8b1a1a}@supports (color:color-mix(in lab,red,red)){.bg-orange-400\/10{background-color:color-mix(in oklab,var(--color-orange-400)10%,transparent)}}.bg-orange-500{background-color:var(--color-orange-500)}.bg-orange-500\/10{background-color:#fe6e001a}@supports (color:color-mix(in lab,red,red)){.bg-orange-500\/10{background-color:color-mix(in oklab,var(--color-orange-500)10%,transparent)}}.bg-orange-500\/20{background-color:#fe6e0033}@supports (color:color-mix(in lab,red,red)){.bg-orange-500\/20{background-color:color-mix(in oklab,var(--color-orange-500)20%,transparent)}}.bg-orange-600{background-color:var(--color-orange-600)}.bg-orange-600\/20{background-color:#f0510033}@supports (color:color-mix(in lab,red,red)){.bg-orange-600\/20{background-color:color-mix(in oklab,var(--color-orange-600)20%,transparent)}}.bg-purple-400\/10{background-color:#c07eff1a}@supports (color:color-mix(in lab,red,red)){.bg-purple-400\/10{background-color:color-mix(in oklab,var(--color-purple-400)10%,transparent)}}.bg-purple-500{background-color:var(--color-purple-500)}.bg-purple-500\/10{background-color:#ac4bff1a}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/10{background-color:color-mix(in oklab,var(--color-purple-500)10%,transparent)}}.bg-purple-500\/20{background-color:#ac4bff33}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/20{background-color:color-mix(in oklab,var(--color-purple-500)20%,transparent)}}.bg-purple-500\/80{background-color:#ac4bffcc}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/80{background-color:color-mix(in oklab,var(--color-purple-500)80%,transparent)}}.bg-purple-500\/90{background-color:#ac4bffe6}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/90{background-color:color-mix(in oklab,var(--color-purple-500)90%,transparent)}}.bg-purple-700{background-color:var(--color-purple-700)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-400{background-color:var(--color-red-400)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\/5{background-color:#fb2c360d}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/5{background-color:color-mix(in oklab,var(--color-red-500)5%,transparent)}}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/10{background-color:color-mix(in oklab,var(--color-red-500)10%,transparent)}}.bg-red-500\/15{background-color:#fb2c3626}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/15{background-color:color-mix(in oklab,var(--color-red-500)15%,transparent)}}.bg-red-500\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/20{background-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.bg-red-500\/30{background-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/30{background-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.bg-red-500\/40{background-color:#fb2c3666}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/40{background-color:color-mix(in oklab,var(--color-red-500)40%,transparent)}}.bg-red-500\/80{background-color:#fb2c36cc}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/80{background-color:color-mix(in oklab,var(--color-red-500)80%,transparent)}}.bg-red-600{background-color:var(--color-red-600)}.bg-red-900\/20{background-color:#82181a33}@supports (color:color-mix(in lab,red,red)){.bg-red-900\/20{background-color:color-mix(in oklab,var(--color-red-900)20%,transparent)}}.bg-red-900\/30{background-color:#82181a4d}@supports (color:color-mix(in lab,red,red)){.bg-red-900\/30{background-color:color-mix(in oklab,var(--color-red-900)30%,transparent)}}.bg-red-950\/70{background-color:#460809b3}@supports (color:color-mix(in lab,red,red)){.bg-red-950\/70{background-color:color-mix(in oklab,var(--color-red-950)70%,transparent)}}.bg-rose-500\/20{background-color:#ff235733}@supports (color:color-mix(in lab,red,red)){.bg-rose-500\/20{background-color:color-mix(in oklab,var(--color-rose-500)20%,transparent)}}.bg-rose-600\/20{background-color:#e7004433}@supports (color:color-mix(in lab,red,red)){.bg-rose-600\/20{background-color:color-mix(in oklab,var(--color-rose-600)20%,transparent)}}.bg-sky-500{background-color:var(--color-sky-500)}.bg-sky-500\/10{background-color:#00a5ef1a}@supports (color:color-mix(in lab,red,red)){.bg-sky-500\/10{background-color:color-mix(in oklab,var(--color-sky-500)10%,transparent)}}.bg-sky-500\/20{background-color:#00a5ef33}@supports (color:color-mix(in lab,red,red)){.bg-sky-500\/20{background-color:color-mix(in oklab,var(--color-sky-500)20%,transparent)}}.bg-status-error,.bg-status-error\/10{background-color:var(--color-status-error)}@supports (color:color-mix(in lab,red,red)){.bg-status-error\/10{background-color:color-mix(in oklab,var(--color-status-error)10%,transparent)}}.bg-status-error\/20{background-color:var(--color-status-error)}@supports (color:color-mix(in lab,red,red)){.bg-status-error\/20{background-color:color-mix(in oklab,var(--color-status-error)20%,transparent)}}.bg-status-error\/80{background-color:var(--color-status-error)}@supports (color:color-mix(in lab,red,red)){.bg-status-error\/80{background-color:color-mix(in oklab,var(--color-status-error)80%,transparent)}}.bg-status-ok,.bg-status-ok\/10{background-color:var(--color-status-ok)}@supports (color:color-mix(in lab,red,red)){.bg-status-ok\/10{background-color:color-mix(in oklab,var(--color-status-ok)10%,transparent)}}.bg-status-ok\/20{background-color:var(--color-status-ok)}@supports (color:color-mix(in lab,red,red)){.bg-status-ok\/20{background-color:color-mix(in oklab,var(--color-status-ok)20%,transparent)}}.bg-status-warning,.bg-status-warning\/10{background-color:var(--color-status-warning)}@supports (color:color-mix(in lab,red,red)){.bg-status-warning\/10{background-color:color-mix(in oklab,var(--color-status-warning)10%,transparent)}}.bg-status-warning\/20{background-color:var(--color-status-warning)}@supports (color:color-mix(in lab,red,red)){.bg-status-warning\/20{background-color:color-mix(in oklab,var(--color-status-warning)20%,transparent)}}.bg-teal-500{background-color:var(--color-teal-500)}.bg-teal-500\/20{background-color:#00baa733}@supports (color:color-mix(in lab,red,red)){.bg-teal-500\/20{background-color:color-mix(in oklab,var(--color-teal-500)20%,transparent)}}.bg-transparent{background-color:#0000}.bg-violet-500{background-color:var(--color-violet-500)}.bg-white{background-color:var(--color-white)}.bg-white\/10{background-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.bg-white\/10{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.bg-white\/20{background-color:#fff3}@supports (color:color-mix(in lab,red,red)){.bg-white\/20{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.bg-white\/50{background-color:#ffffff80}@supports (color:color-mix(in lab,red,red)){.bg-white\/50{background-color:color-mix(in oklab,var(--color-white)50%,transparent)}}.bg-white\/70{background-color:#ffffffb3}@supports (color:color-mix(in lab,red,red)){.bg-white\/70{background-color:color-mix(in oklab,var(--color-white)70%,transparent)}}.bg-white\/90{background-color:#ffffffe6}@supports (color:color-mix(in lab,red,red)){.bg-white\/90{background-color:color-mix(in oklab,var(--color-white)90%,transparent)}}.bg-yellow-400{background-color:var(--color-yellow-400)}.bg-yellow-400\/10{background-color:#fac8001a}@supports (color:color-mix(in lab,red,red)){.bg-yellow-400\/10{background-color:color-mix(in oklab,var(--color-yellow-400)10%,transparent)}}.bg-yellow-400\/20{background-color:#fac80033}@supports (color:color-mix(in lab,red,red)){.bg-yellow-400\/20{background-color:color-mix(in oklab,var(--color-yellow-400)20%,transparent)}}.bg-yellow-500{background-color:var(--color-yellow-500)}.bg-yellow-500\/5{background-color:#edb2000d}@supports (color:color-mix(in lab,red,red)){.bg-yellow-500\/5{background-color:color-mix(in oklab,var(--color-yellow-500)5%,transparent)}}.bg-yellow-500\/10{background-color:#edb2001a}@supports (color:color-mix(in lab,red,red)){.bg-yellow-500\/10{background-color:color-mix(in oklab,var(--color-yellow-500)10%,transparent)}}.bg-yellow-500\/20{background-color:#edb20033}@supports (color:color-mix(in lab,red,red)){.bg-yellow-500\/20{background-color:color-mix(in oklab,var(--color-yellow-500)20%,transparent)}}.bg-yellow-700{background-color:var(--color-yellow-700)}.bg-zinc-600{background-color:var(--color-zinc-600)}.bg-zinc-700{background-color:var(--color-zinc-700)}.bg-zinc-800{background-color:var(--color-zinc-800)}.bg-zinc-800\/50{background-color:#27272a80}@supports (color:color-mix(in lab,red,red)){.bg-zinc-800\/50{background-color:color-mix(in oklab,var(--color-zinc-800)50%,transparent)}}.bg-zinc-800\/60{background-color:#27272a99}@supports (color:color-mix(in lab,red,red)){.bg-zinc-800\/60{background-color:color-mix(in oklab,var(--color-zinc-800)60%,transparent)}}.bg-zinc-900{background-color:var(--color-zinc-900)}.bg-zinc-900\/50{background-color:#18181b80}@supports (color:color-mix(in lab,red,red)){.bg-zinc-900\/50{background-color:color-mix(in oklab,var(--color-zinc-900)50%,transparent)}}.bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-t{--tw-gradient-position:to top in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-bambu-dark-secondary{--tw-gradient-from:var(--color-bambu-dark-secondary);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-black\/80{--tw-gradient-from:#000c}@supports (color:color-mix(in lab,red,red)){.from-black\/80{--tw-gradient-from:color-mix(in oklab,var(--color-black)80%,transparent)}}.from-black\/80{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-blue-500\/5{--tw-gradient-from:#3080ff0d}@supports (color:color-mix(in lab,red,red)){.from-blue-500\/5{--tw-gradient-from:color-mix(in oklab,var(--color-blue-500)5%,transparent)}}.from-blue-500\/5{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-white\/10{--tw-gradient-from:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.from-white\/10{--tw-gradient-from:color-mix(in oklab,var(--color-white)10%,transparent)}}.from-white\/10{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.via-black\/60{--tw-gradient-via:#0009}@supports (color:color-mix(in lab,red,red)){.via-black\/60{--tw-gradient-via:color-mix(in oklab,var(--color-black)60%,transparent)}}.via-black\/60{--tw-gradient-via-stops:var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-via)var(--tw-gradient-via-position),var(--tw-gradient-to)var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-bambu-dark-secondary{--tw-gradient-to:var(--color-bambu-dark-secondary);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-bambu-dark-tertiary{--tw-gradient-to:var(--color-bambu-dark-tertiary);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.bg-cover{background-size:cover}.bg-center{background-position:50%}.fill-yellow-400{fill:var(--color-yellow-400)}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.object-left{object-position:left}.p-0{padding:calc(var(--spacing)*0)}.p-0\.5{padding:calc(var(--spacing)*.5)}.p-1{padding:calc(var(--spacing)*1)}.p-1\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-2\.5{padding:calc(var(--spacing)*2.5)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.p-12{padding:calc(var(--spacing)*12)}.\!px-1\.5{padding-inline:calc(var(--spacing)*1.5)!important}.\!px-3{padding-inline:calc(var(--spacing)*3)!important}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.py-6{padding-block:calc(var(--spacing)*6)}.py-8{padding-block:calc(var(--spacing)*8)}.py-12{padding-block:calc(var(--spacing)*12)}.py-16{padding-block:calc(var(--spacing)*16)}.py-20{padding-block:calc(var(--spacing)*20)}.py-24{padding-block:calc(var(--spacing)*24)}.pt-0{padding-top:calc(var(--spacing)*0)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-2{padding-top:calc(var(--spacing)*2)}.pt-3{padding-top:calc(var(--spacing)*3)}.pt-4{padding-top:calc(var(--spacing)*4)}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-3{padding-right:calc(var(--spacing)*3)}.pr-4{padding-right:calc(var(--spacing)*4)}.pr-6{padding-right:calc(var(--spacing)*6)}.pr-7{padding-right:calc(var(--spacing)*7)}.pr-8{padding-right:calc(var(--spacing)*8)}.pr-10{padding-right:calc(var(--spacing)*10)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-2{padding-bottom:calc(var(--spacing)*2)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pb-4{padding-bottom:calc(var(--spacing)*4)}.pl-2{padding-left:calc(var(--spacing)*2)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-4{padding-left:calc(var(--spacing)*4)}.pl-5{padding-left:calc(var(--spacing)*5)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-7{padding-left:calc(var(--spacing)*7)}.pl-8{padding-left:calc(var(--spacing)*8)}.pl-9{padding-left:calc(var(--spacing)*9)}.pl-10{padding-left:calc(var(--spacing)*10)}.pl-20{padding-left:calc(var(--spacing)*20)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[6px\]{font-size:6px}.text-\[7px\]{font-size:7px}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-5{--tw-leading:calc(var(--spacing)*5);line-height:calc(var(--spacing)*5)}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-light{--tw-font-weight:var(--font-weight-light);font-weight:var(--font-weight-light)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.\!text-green-400{color:var(--color-green-400)!important}.\!text-white{color:var(--color-white)!important}.\!text-yellow-400{color:var(--color-yellow-400)!important}.text-amber-200{color:var(--color-amber-200)}.text-amber-200\/80{color:#fee685cc}@supports (color:color-mix(in lab,red,red)){.text-amber-200\/80{color:color-mix(in oklab,var(--color-amber-200)80%,transparent)}}.text-amber-300{color:var(--color-amber-300)}.text-amber-300\/60{color:#ffd23699}@supports (color:color-mix(in lab,red,red)){.text-amber-300\/60{color:color-mix(in oklab,var(--color-amber-300)60%,transparent)}}.text-amber-300\/70{color:#ffd236b3}@supports (color:color-mix(in lab,red,red)){.text-amber-300\/70{color:color-mix(in oklab,var(--color-amber-300)70%,transparent)}}.text-amber-300\/80{color:#ffd236cc}@supports (color:color-mix(in lab,red,red)){.text-amber-300\/80{color:color-mix(in oklab,var(--color-amber-300)80%,transparent)}}.text-amber-400{color:var(--color-amber-400)}.text-amber-400\/70{color:#fcbb00b3}@supports (color:color-mix(in lab,red,red)){.text-amber-400\/70{color:color-mix(in oklab,var(--color-amber-400)70%,transparent)}}.text-amber-500{color:var(--color-amber-500)}.text-amber-500\/80{color:#f99c00cc}@supports (color:color-mix(in lab,red,red)){.text-amber-500\/80{color:color-mix(in oklab,var(--color-amber-500)80%,transparent)}}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-amber-800{color:var(--color-amber-800)}.text-amber-900{color:var(--color-amber-900)}.text-bambu-dark{color:var(--color-bambu-dark)}.text-bambu-dark-tertiary{color:var(--color-bambu-dark-tertiary)}.text-bambu-gray{color:var(--color-bambu-gray)}.text-bambu-gray-dark{color:var(--color-bambu-gray-dark)}.text-bambu-gray-light{color:var(--color-bambu-gray-light)}.text-bambu-gray\/30{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.text-bambu-gray\/30{color:color-mix(in oklab,var(--color-bambu-gray)30%,transparent)}}.text-bambu-gray\/40{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.text-bambu-gray\/40{color:color-mix(in oklab,var(--color-bambu-gray)40%,transparent)}}.text-bambu-gray\/50{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.text-bambu-gray\/50{color:color-mix(in oklab,var(--color-bambu-gray)50%,transparent)}}.text-bambu-gray\/60{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.text-bambu-gray\/60{color:color-mix(in oklab,var(--color-bambu-gray)60%,transparent)}}.text-bambu-gray\/70{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.text-bambu-gray\/70{color:color-mix(in oklab,var(--color-bambu-gray)70%,transparent)}}.text-bambu-gray\/80{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.text-bambu-gray\/80{color:color-mix(in oklab,var(--color-bambu-gray)80%,transparent)}}.text-bambu-green,.text-bambu-green\/70{color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.text-bambu-green\/70{color:color-mix(in oklab,var(--color-bambu-green)70%,transparent)}}.text-black{color:var(--color-black)}.text-black\/80{color:#000c}@supports (color:color-mix(in lab,red,red)){.text-black\/80{color:color-mix(in oklab,var(--color-black)80%,transparent)}}.text-blue-100{color:var(--color-blue-100)}.text-blue-300{color:var(--color-blue-300)}.text-blue-300\/70{color:#90c5ffb3}@supports (color:color-mix(in lab,red,red)){.text-blue-300\/70{color:color-mix(in oklab,var(--color-blue-300)70%,transparent)}}.text-blue-300\/80{color:#90c5ffcc}@supports (color:color-mix(in lab,red,red)){.text-blue-300\/80{color:color-mix(in oklab,var(--color-blue-300)80%,transparent)}}.text-blue-400{color:var(--color-blue-400)}.text-blue-500{color:var(--color-blue-500)}.text-blue-500\/70{color:#3080ffb3}@supports (color:color-mix(in lab,red,red)){.text-blue-500\/70{color:color-mix(in oklab,var(--color-blue-500)70%,transparent)}}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-cyan-300{color:var(--color-cyan-300)}.text-cyan-400{color:var(--color-cyan-400)}.text-emerald-100{color:var(--color-emerald-100)}.text-emerald-300{color:var(--color-emerald-300)}.text-emerald-400{color:var(--color-emerald-400)}.text-emerald-600{color:var(--color-emerald-600)}.text-emerald-700{color:var(--color-emerald-700)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-200{color:var(--color-green-200)}.text-green-300{color:var(--color-green-300)}.text-green-400{color:var(--color-green-400)}.text-green-400\/60{color:#05df7299}@supports (color:color-mix(in lab,red,red)){.text-green-400\/60{color:color-mix(in oklab,var(--color-green-400)60%,transparent)}}.text-green-400\/70{color:#05df72b3}@supports (color:color-mix(in lab,red,red)){.text-green-400\/70{color:color-mix(in oklab,var(--color-green-400)70%,transparent)}}.text-green-500{color:var(--color-green-500)}.text-green-500\/60{color:#00c75899}@supports (color:color-mix(in lab,red,red)){.text-green-500\/60{color:color-mix(in oklab,var(--color-green-500)60%,transparent)}}.text-green-600{color:var(--color-green-600)}.text-green-700{color:var(--color-green-700)}.text-indigo-300{color:var(--color-indigo-300)}.text-indigo-400{color:var(--color-indigo-400)}.text-orange-200{color:var(--color-orange-200)}.text-orange-300{color:var(--color-orange-300)}.text-orange-400{color:var(--color-orange-400)}.text-orange-500{color:var(--color-orange-500)}.text-orange-600{color:var(--color-orange-600)}.text-orange-700{color:var(--color-orange-700)}.text-purple-300{color:var(--color-purple-300)}.text-purple-300\/70{color:#d9b3ffb3}@supports (color:color-mix(in lab,red,red)){.text-purple-300\/70{color:color-mix(in oklab,var(--color-purple-300)70%,transparent)}}.text-purple-400{color:var(--color-purple-400)}.text-purple-400\/80{color:#c07effcc}@supports (color:color-mix(in lab,red,red)){.text-purple-400\/80{color:color-mix(in oklab,var(--color-purple-400)80%,transparent)}}.text-red-200{color:var(--color-red-200)}.text-red-300{color:var(--color-red-300)}.text-red-300\/80{color:#ffa3a3cc}@supports (color:color-mix(in lab,red,red)){.text-red-300\/80{color:color-mix(in oklab,var(--color-red-300)80%,transparent)}}.text-red-400{color:var(--color-red-400)}.text-red-400\/50{color:#ff656880}@supports (color:color-mix(in lab,red,red)){.text-red-400\/50{color:color-mix(in oklab,var(--color-red-400)50%,transparent)}}.text-red-400\/60{color:#ff656899}@supports (color:color-mix(in lab,red,red)){.text-red-400\/60{color:color-mix(in oklab,var(--color-red-400)60%,transparent)}}.text-red-400\/70{color:#ff6568b3}@supports (color:color-mix(in lab,red,red)){.text-red-400\/70{color:color-mix(in oklab,var(--color-red-400)70%,transparent)}}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-rose-300{color:var(--color-rose-300)}.text-rose-400{color:var(--color-rose-400)}.text-sky-400{color:var(--color-sky-400)}.text-slate-300{color:var(--color-slate-300)}.text-status-error{color:var(--color-status-error)}.text-status-ok{color:var(--color-status-ok)}.text-status-warning{color:var(--color-status-warning)}.text-teal-400{color:var(--color-teal-400)}.text-white{color:var(--color-white)}.text-white\/30{color:#ffffff4d}@supports (color:color-mix(in lab,red,red)){.text-white\/30{color:color-mix(in oklab,var(--color-white)30%,transparent)}}.text-white\/40{color:#fff6}@supports (color:color-mix(in lab,red,red)){.text-white\/40{color:color-mix(in oklab,var(--color-white)40%,transparent)}}.text-white\/50{color:#ffffff80}@supports (color:color-mix(in lab,red,red)){.text-white\/50{color:color-mix(in oklab,var(--color-white)50%,transparent)}}.text-white\/60{color:#fff9}@supports (color:color-mix(in lab,red,red)){.text-white\/60{color:color-mix(in oklab,var(--color-white)60%,transparent)}}.text-white\/70{color:#ffffffb3}@supports (color:color-mix(in lab,red,red)){.text-white\/70{color:color-mix(in oklab,var(--color-white)70%,transparent)}}.text-white\/80{color:#fffc}@supports (color:color-mix(in lab,red,red)){.text-white\/80{color:color-mix(in oklab,var(--color-white)80%,transparent)}}.text-white\/90{color:#ffffffe6}@supports (color:color-mix(in lab,red,red)){.text-white\/90{color:color-mix(in oklab,var(--color-white)90%,transparent)}}.text-yellow-100{color:var(--color-yellow-100)}.text-yellow-200{color:var(--color-yellow-200)}.text-yellow-200\/70{color:#fff085b3}@supports (color:color-mix(in lab,red,red)){.text-yellow-200\/70{color:color-mix(in oklab,var(--color-yellow-200)70%,transparent)}}.text-yellow-300{color:var(--color-yellow-300)}.text-yellow-400{color:var(--color-yellow-400)}.text-yellow-500{color:var(--color-yellow-500)}.text-yellow-500\/70{color:#edb200b3}@supports (color:color-mix(in lab,red,red)){.text-yellow-500\/70{color:color-mix(in oklab,var(--color-yellow-500)70%,transparent)}}.text-yellow-500\/80{color:#edb200cc}@supports (color:color-mix(in lab,red,red)){.text-yellow-500\/80{color:color-mix(in oklab,var(--color-yellow-500)80%,transparent)}}.text-yellow-600{color:var(--color-yellow-600)}.text-yellow-700{color:var(--color-yellow-700)}.text-zinc-100{color:var(--color-zinc-100)}.text-zinc-200{color:var(--color-zinc-200)}.text-zinc-300{color:var(--color-zinc-300)}.text-zinc-400{color:var(--color-zinc-400)}.text-zinc-500{color:var(--color-zinc-500)}.text-zinc-600{color:var(--color-zinc-600)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.placeholder-bambu-gray::placeholder{color:var(--color-bambu-gray)}.placeholder-bambu-gray-dark::placeholder{color:var(--color-bambu-gray-dark)}.placeholder-bambu-gray\/40::placeholder{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.placeholder-bambu-gray\/40::placeholder{color:color-mix(in oklab,var(--color-bambu-gray)40%,transparent)}}.placeholder-bambu-gray\/50::placeholder{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.placeholder-bambu-gray\/50::placeholder{color:color-mix(in oklab,var(--color-bambu-gray)50%,transparent)}}.placeholder-bambu-gray\/60::placeholder{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.placeholder-bambu-gray\/60::placeholder{color:color-mix(in oklab,var(--color-bambu-gray)60%,transparent)}}.placeholder-gray-400::placeholder{color:var(--color-gray-400)}.placeholder-white\/30::placeholder{color:#ffffff4d}@supports (color:color-mix(in lab,red,red)){.placeholder-white\/30::placeholder{color:color-mix(in oklab,var(--color-white)30%,transparent)}}.placeholder-zinc-500::placeholder{color:var(--color-zinc-500)}.accent-amber-500{accent-color:var(--color-amber-500)}.accent-bambu-green{accent-color:var(--color-bambu-green)}.accent-green-500{accent-color:var(--color-green-500)}.\[color-scheme\:dark\]{color-scheme:dark}.opacity-0{opacity:0}.opacity-20{opacity:.2}.opacity-25{opacity:.25}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_6px_rgba\(34\,197\,94\,0\.5\)\]{--tw-shadow:0 0 6px var(--tw-shadow-color,#22c55e80);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow\/depth{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-bambu-green\/20{--tw-shadow-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.shadow-bambu-green\/20{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-bambu-green)20%,transparent)var(--tw-shadow-alpha),transparent)}}.shadow-bambu-green\/25{--tw-shadow-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.shadow-bambu-green\/25{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-bambu-green)25%,transparent)var(--tw-shadow-alpha),transparent)}}.ring-bambu-green,.ring-bambu-green\/30{--tw-ring-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.ring-bambu-green\/30{--tw-ring-color:color-mix(in oklab,var(--color-bambu-green)30%,transparent)}}.ring-blue-400\/50{--tw-ring-color:#54a2ff80}@supports (color:color-mix(in lab,red,red)){.ring-blue-400\/50{--tw-ring-color:color-mix(in oklab,var(--color-blue-400)50%,transparent)}}.ring-green-500{--tw-ring-color:var(--color-green-500)}.ring-white{--tw-ring-color:var(--color-white)}.ring-offset-1{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.ring-offset-2{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.ring-offset-bambu-dark{--tw-ring-offset-color:var(--color-bambu-dark)}.ring-offset-bambu-dark-secondary{--tw-ring-offset-color:var(--color-bambu-dark-secondary)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.blur-2xl{--tw-blur:blur(var(--blur-2xl));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,)}.drop-shadow-lg{--tw-drop-shadow-size:drop-shadow(0 4px 4px var(--tw-drop-shadow-color,#00000026));--tw-drop-shadow:drop-shadow(var(--drop-shadow-lg));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,)}.drop-shadow-md{--tw-drop-shadow-size:drop-shadow(0 3px 3px var(--tw-drop-shadow-color,#0000001f));--tw-drop-shadow:drop-shadow(var(--drop-shadow-md));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,)!important}.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(var(--blur-sm));-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,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-all{-webkit-user-select:all;user-select:all}.select-none{-webkit-user-select:none;user-select:none}@media(hover:hover){.group-hover\:bg-bambu-green\/20:is(:where(.group):hover *){background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.group-hover\:bg-bambu-green\/20:is(:where(.group):hover *){background-color:color-mix(in oklab,var(--color-bambu-green)20%,transparent)}}.group-hover\:text-bambu-gray:is(:where(.group):hover *){color:var(--color-bambu-gray)}.group-hover\:text-bambu-green:is(:where(.group):hover *){color:var(--color-bambu-green)}.group-hover\:opacity-50:is(:where(.group):hover *){opacity:.5}.group-hover\:opacity-100:is(:where(.group):hover *),.group-hover\/resize\:opacity-100:is(:where(.group\/resize):hover *){opacity:1}.group-hover\/thumb\:block:is(:where(.group\/thumb):hover *){display:block}}.peer-checked\:bg-amber-500:is(:where(.peer):checked~*){background-color:var(--color-amber-500)}.peer-checked\:bg-bambu-green:is(:where(.peer):checked~*){background-color:var(--color-bambu-green)}.peer-focus\:ring-2:is(:where(.peer):focus~*){--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.peer-focus\:ring-bambu-green\/50:is(:where(.peer):focus~*){--tw-ring-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.peer-focus\:ring-bambu-green\/50:is(:where(.peer):focus~*){--tw-ring-color:color-mix(in oklab,var(--color-bambu-green)50%,transparent)}}.peer-focus\:outline-none:is(:where(.peer):focus~*){--tw-outline-style:none;outline-style:none}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.placeholder\:text-bambu-gray::placeholder,.placeholder\:text-bambu-gray\/40::placeholder{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.placeholder\:text-bambu-gray\/40::placeholder{color:color-mix(in oklab,var(--color-bambu-gray)40%,transparent)}}.placeholder\:text-bambu-gray\/50::placeholder{color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.placeholder\:text-bambu-gray\/50::placeholder{color:color-mix(in oklab,var(--color-bambu-gray)50%,transparent)}}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:top-0:before{content:var(--tw-content);top:calc(var(--spacing)*0)}.before\:right-0:before{content:var(--tw-content);right:calc(var(--spacing)*0)}.before\:left-0:before{content:var(--tw-content);left:calc(var(--spacing)*0)}.before\:h-0\.5:before{content:var(--tw-content);height:calc(var(--spacing)*.5)}.before\:bg-bambu-green:before{content:var(--tw-content);background-color:var(--color-bambu-green)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:top-0\.5:after{content:var(--tw-content);top:calc(var(--spacing)*.5)}.after\:top-\[2px\]:after{content:var(--tw-content);top:2px}.after\:left-0\.5:after{content:var(--tw-content);left:calc(var(--spacing)*.5)}.after\:left-\[2px\]:after{content:var(--tw-content);left:2px}.after\:h-4:after{content:var(--tw-content);height:calc(var(--spacing)*4)}.after\:h-5:after{content:var(--tw-content);height:calc(var(--spacing)*5)}.after\:w-4:after{content:var(--tw-content);width:calc(var(--spacing)*4)}.after\:w-5:after{content:var(--tw-content);width:calc(var(--spacing)*5)}.after\:rounded-full:after{content:var(--tw-content);border-radius:3.40282e38px}.after\:border:after{content:var(--tw-content);border-style:var(--tw-border-style);border-width:1px}.after\:border-gray-300:after{content:var(--tw-content);border-color:var(--color-gray-300)}.after\:bg-white:after{content:var(--tw-content);background-color:var(--color-white)}.after\:transition-all:after{content:var(--tw-content);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.after\:transition-transform:after{content:var(--tw-content);transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.after\:content-\[\'\'\]:after{--tw-content:"";content:var(--tw-content)}.peer-checked\:after\:translate-x-5:is(:where(.peer):checked~*):after{content:var(--tw-content);--tw-translate-x:calc(var(--spacing)*5);translate:var(--tw-translate-x)var(--tw-translate-y)}.peer-checked\:after\:translate-x-full:is(:where(.peer):checked~*):after{content:var(--tw-content);--tw-translate-x:100%;translate:var(--tw-translate-x)var(--tw-translate-y)}.peer-checked\:after\:border-white:is(:where(.peer):checked~*):after{content:var(--tw-content);border-color:var(--color-white)}.last\:border-0:last-child{border-style:var(--tw-border-style);border-width:0}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.focus-within\:border-bambu-green:focus-within{border-color:var(--color-bambu-green)}@media(hover:hover){.hover\:z-20:hover{z-index:20}.hover\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.hover\:scale-110:hover{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x)var(--tw-scale-y)}.hover\:border-amber-500:hover{border-color:var(--color-amber-500)}.hover\:border-bambu-dark-tertiary\/80:hover{border-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.hover\:border-bambu-dark-tertiary\/80:hover{border-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)80%,transparent)}}.hover\:border-bambu-gray:hover{border-color:var(--color-bambu-gray)}.hover\:border-bambu-gray-dark:hover{border-color:var(--color-bambu-gray-dark)}.hover\:border-bambu-gray\/50:hover{border-color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.hover\:border-bambu-gray\/50:hover{border-color:color-mix(in oklab,var(--color-bambu-gray)50%,transparent)}}.hover\:border-bambu-green:hover,.hover\:border-bambu-green\/40:hover{border-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:border-bambu-green\/40:hover{border-color:color-mix(in oklab,var(--color-bambu-green)40%,transparent)}}.hover\:border-bambu-green\/50:hover{border-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:border-bambu-green\/50:hover{border-color:color-mix(in oklab,var(--color-bambu-green)50%,transparent)}}.hover\:border-gray-400:hover{border-color:var(--color-gray-400)}.hover\:border-green-500\/50:hover{border-color:#00c75880}@supports (color:color-mix(in lab,red,red)){.hover\:border-green-500\/50:hover{border-color:color-mix(in oklab,var(--color-green-500)50%,transparent)}}.hover\:border-white:hover{border-color:var(--color-white)}.hover\:border-white\/40:hover{border-color:#fff6}@supports (color:color-mix(in lab,red,red)){.hover\:border-white\/40:hover{border-color:color-mix(in oklab,var(--color-white)40%,transparent)}}.hover\:\!bg-bambu-green\/80:hover{background-color:var(--color-bambu-green)!important}@supports (color:color-mix(in lab,red,red)){.hover\:\!bg-bambu-green\/80:hover{background-color:color-mix(in oklab,var(--color-bambu-green)80%,transparent)!important}}.hover\:\!bg-green-500\/20:hover{background-color:#00c75833!important}@supports (color:color-mix(in lab,red,red)){.hover\:\!bg-green-500\/20:hover{background-color:color-mix(in oklab,var(--color-green-500)20%,transparent)!important}}.hover\:\!bg-yellow-500\/20:hover{background-color:#edb20033!important}@supports (color:color-mix(in lab,red,red)){.hover\:\!bg-yellow-500\/20:hover{background-color:color-mix(in oklab,var(--color-yellow-500)20%,transparent)!important}}.hover\:bg-amber-400:hover{background-color:var(--color-amber-400)}.hover\:bg-amber-500\/20:hover{background-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.hover\:bg-amber-500\/20:hover{background-color:color-mix(in oklab,var(--color-amber-500)20%,transparent)}}.hover\:bg-amber-500\/30:hover{background-color:#f99c004d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-amber-500\/30:hover{background-color:color-mix(in oklab,var(--color-amber-500)30%,transparent)}}.hover\:bg-amber-700:hover{background-color:var(--color-amber-700)}.hover\:bg-amber-900\/50:hover{background-color:#7b330680}@supports (color:color-mix(in lab,red,red)){.hover\:bg-amber-900\/50:hover{background-color:color-mix(in oklab,var(--color-amber-900)50%,transparent)}}.hover\:bg-bambu-dark:hover{background-color:var(--color-bambu-dark)}.hover\:bg-bambu-dark-secondary:hover,.hover\:bg-bambu-dark-secondary\/50:hover{background-color:var(--color-bambu-dark-secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-dark-secondary\/50:hover{background-color:color-mix(in oklab,var(--color-bambu-dark-secondary)50%,transparent)}}.hover\:bg-bambu-dark-secondary\/80:hover{background-color:var(--color-bambu-dark-secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-dark-secondary\/80:hover{background-color:color-mix(in oklab,var(--color-bambu-dark-secondary)80%,transparent)}}.hover\:bg-bambu-dark-tertiary:hover,.hover\:bg-bambu-dark-tertiary\/30:hover{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-dark-tertiary\/30:hover{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)30%,transparent)}}.hover\:bg-bambu-dark-tertiary\/50:hover{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-dark-tertiary\/50:hover{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)50%,transparent)}}.hover\:bg-bambu-dark-tertiary\/70:hover{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-dark-tertiary\/70:hover{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)70%,transparent)}}.hover\:bg-bambu-dark-tertiary\/80:hover{background-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-dark-tertiary\/80:hover{background-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)80%,transparent)}}.hover\:bg-bambu-dark\/50:hover{background-color:var(--color-bambu-dark)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-dark\/50:hover{background-color:color-mix(in oklab,var(--color-bambu-dark)50%,transparent)}}.hover\:bg-bambu-dark\/80:hover{background-color:var(--color-bambu-dark)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-dark\/80:hover{background-color:color-mix(in oklab,var(--color-bambu-dark)80%,transparent)}}.hover\:bg-bambu-gray-dark:hover{background-color:var(--color-bambu-gray-dark)}.hover\:bg-bambu-green:hover{background-color:var(--color-bambu-green)}.hover\:bg-bambu-green-dark:hover{background-color:var(--color-bambu-green-dark)}.hover\:bg-bambu-green-light:hover{background-color:var(--color-bambu-green-light)}.hover\:bg-bambu-green\/10:hover{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-green\/10:hover{background-color:color-mix(in oklab,var(--color-bambu-green)10%,transparent)}}.hover\:bg-bambu-green\/20:hover{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-green\/20:hover{background-color:color-mix(in oklab,var(--color-bambu-green)20%,transparent)}}.hover\:bg-bambu-green\/30:hover{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-green\/30:hover{background-color:color-mix(in oklab,var(--color-bambu-green)30%,transparent)}}.hover\:bg-bambu-green\/50:hover{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-green\/50:hover{background-color:color-mix(in oklab,var(--color-bambu-green)50%,transparent)}}.hover\:bg-bambu-green\/80:hover{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-green\/80:hover{background-color:color-mix(in oklab,var(--color-bambu-green)80%,transparent)}}.hover\:bg-bambu-green\/90:hover{background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bambu-green\/90:hover{background-color:color-mix(in oklab,var(--color-bambu-green)90%,transparent)}}.hover\:bg-black\/40:hover{background-color:#0006}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/40:hover{background-color:color-mix(in oklab,var(--color-black)40%,transparent)}}.hover\:bg-black\/70:hover{background-color:#000000b3}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/70:hover{background-color:color-mix(in oklab,var(--color-black)70%,transparent)}}.hover\:bg-black\/80:hover{background-color:#000c}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/80:hover{background-color:color-mix(in oklab,var(--color-black)80%,transparent)}}.hover\:bg-blue-500\/20:hover{background-color:#3080ff33}@supports (color:color-mix(in lab,red,red)){.hover\:bg-blue-500\/20:hover{background-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.hover\:bg-blue-500\/30:hover{background-color:#3080ff4d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-blue-500\/30:hover{background-color:color-mix(in oklab,var(--color-blue-500)30%,transparent)}}.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-emerald-600:hover{background-color:var(--color-emerald-600)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-gray-700:hover{background-color:var(--color-gray-700)}.hover\:bg-green-500\/20:hover{background-color:#00c75833}@supports (color:color-mix(in lab,red,red)){.hover\:bg-green-500\/20:hover{background-color:color-mix(in oklab,var(--color-green-500)20%,transparent)}}.hover\:bg-green-600:hover{background-color:var(--color-green-600)}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-indigo-500\/20:hover{background-color:#625fff33}@supports (color:color-mix(in lab,red,red)){.hover\:bg-indigo-500\/20:hover{background-color:color-mix(in oklab,var(--color-indigo-500)20%,transparent)}}.hover\:bg-indigo-500\/30:hover{background-color:#625fff4d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-indigo-500\/30:hover{background-color:color-mix(in oklab,var(--color-indigo-500)30%,transparent)}}.hover\:bg-orange-400\/20:hover{background-color:#ff8b1a33}@supports (color:color-mix(in lab,red,red)){.hover\:bg-orange-400\/20:hover{background-color:color-mix(in oklab,var(--color-orange-400)20%,transparent)}}.hover\:bg-orange-500\/20:hover{background-color:#fe6e0033}@supports (color:color-mix(in lab,red,red)){.hover\:bg-orange-500\/20:hover{background-color:color-mix(in oklab,var(--color-orange-500)20%,transparent)}}.hover\:bg-purple-600\/90:hover{background-color:#9810fae6}@supports (color:color-mix(in lab,red,red)){.hover\:bg-purple-600\/90:hover{background-color:color-mix(in oklab,var(--color-purple-600)90%,transparent)}}.hover\:bg-red-200:hover{background-color:var(--color-red-200)}.hover\:bg-red-400\/10:hover{background-color:#ff65681a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-400\/10:hover{background-color:color-mix(in oklab,var(--color-red-400)10%,transparent)}}.hover\:bg-red-500\/10:hover{background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/10:hover{background-color:color-mix(in oklab,var(--color-red-500)10%,transparent)}}.hover\:bg-red-500\/20:hover{background-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/20:hover{background-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.hover\:bg-red-500\/30:hover{background-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/30:hover{background-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:bg-red-900\/50:hover{background-color:#82181a80}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-900\/50:hover{background-color:color-mix(in oklab,var(--color-red-900)50%,transparent)}}.hover\:bg-sky-500\/20:hover{background-color:#00a5ef33}@supports (color:color-mix(in lab,red,red)){.hover\:bg-sky-500\/20:hover{background-color:color-mix(in oklab,var(--color-sky-500)20%,transparent)}}.hover\:bg-white\/5:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/5:hover{background-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.hover\:bg-white\/10:hover{background-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/10:hover{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.hover\:bg-white\/20:hover{background-color:#fff3}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/20:hover{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.hover\:bg-white\/80:hover{background-color:#fffc}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/80:hover{background-color:color-mix(in oklab,var(--color-white)80%,transparent)}}.hover\:bg-yellow-500\/30:hover{background-color:#edb2004d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-yellow-500\/30:hover{background-color:color-mix(in oklab,var(--color-yellow-500)30%,transparent)}}.hover\:bg-yellow-600:hover{background-color:var(--color-yellow-600)}.hover\:bg-zinc-600:hover{background-color:var(--color-zinc-600)}.hover\:bg-zinc-700:hover{background-color:var(--color-zinc-700)}.hover\:bg-zinc-700\/50:hover{background-color:#3f3f4680}@supports (color:color-mix(in lab,red,red)){.hover\:bg-zinc-700\/50:hover{background-color:color-mix(in oklab,var(--color-zinc-700)50%,transparent)}}.hover\:bg-zinc-700\/60:hover{background-color:#3f3f4699}@supports (color:color-mix(in lab,red,red)){.hover\:bg-zinc-700\/60:hover{background-color:color-mix(in oklab,var(--color-zinc-700)60%,transparent)}}.hover\:bg-zinc-800:hover{background-color:var(--color-zinc-800)}.hover\:text-amber-300:hover{color:var(--color-amber-300)}.hover\:text-amber-800:hover{color:var(--color-amber-800)}.hover\:text-bambu-gray:hover{color:var(--color-bambu-gray)}.hover\:text-bambu-green:hover{color:var(--color-bambu-green)}.hover\:text-bambu-green-light:hover{color:var(--color-bambu-green-light)}.hover\:text-bambu-green\/70:hover{color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:text-bambu-green\/70:hover{color:color-mix(in oklab,var(--color-bambu-green)70%,transparent)}}.hover\:text-bambu-green\/80:hover{color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:text-bambu-green\/80:hover{color:color-mix(in oklab,var(--color-bambu-green)80%,transparent)}}.hover\:text-blue-300:hover{color:var(--color-blue-300)}.hover\:text-blue-600:hover{color:var(--color-blue-600)}.hover\:text-blue-800:hover{color:var(--color-blue-800)}.hover\:text-gray-600:hover{color:var(--color-gray-600)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-gray-900:hover{color:var(--color-gray-900)}.hover\:text-orange-300:hover{color:var(--color-orange-300)}.hover\:text-red-200:hover{color:var(--color-red-200)}.hover\:text-red-300:hover{color:var(--color-red-300)}.hover\:text-red-400:hover{color:var(--color-red-400)}.hover\:text-red-800:hover{color:var(--color-red-800)}.hover\:text-white:hover{color:var(--color-white)}.hover\:text-white\/60:hover{color:#fff9}@supports (color:color-mix(in lab,red,red)){.hover\:text-white\/60:hover{color:color-mix(in oklab,var(--color-white)60%,transparent)}}.hover\:text-white\/70:hover{color:#ffffffb3}@supports (color:color-mix(in lab,red,red)){.hover\:text-white\/70:hover{color:color-mix(in oklab,var(--color-white)70%,transparent)}}.hover\:text-white\/80:hover{color:#fffc}@supports (color:color-mix(in lab,red,red)){.hover\:text-white\/80:hover{color:color-mix(in oklab,var(--color-white)80%,transparent)}}.hover\:text-yellow-400:hover{color:var(--color-yellow-400)}.hover\:text-zinc-200:hover{color:var(--color-zinc-200)}.hover\:text-zinc-300:hover{color:var(--color-zinc-300)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-70:hover{opacity:.7}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\:shadow-xl:hover{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\:shadow-bambu-green\/5:hover{--tw-shadow-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:shadow-bambu-green\/5:hover{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-bambu-green)5%,transparent)var(--tw-shadow-alpha),transparent)}}.hover\:shadow-bambu-green\/30:hover{--tw-shadow-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.hover\:shadow-bambu-green\/30:hover{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-bambu-green)30%,transparent)var(--tw-shadow-alpha),transparent)}}}.focus\:border-amber-500\/50:focus{border-color:#f99c0080}@supports (color:color-mix(in lab,red,red)){.focus\:border-amber-500\/50:focus{border-color:color-mix(in oklab,var(--color-amber-500)50%,transparent)}}.focus\:border-bambu-gray:focus{border-color:var(--color-bambu-gray)}.focus\:border-bambu-green:focus{border-color:var(--color-bambu-green)}.focus\:border-red-500:focus{border-color:var(--color-red-500)}.focus\:border-transparent:focus{border-color:#0000}.focus\:ring-0:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-bambu-gray:focus{--tw-ring-color:var(--color-bambu-gray)}.focus\:ring-bambu-green:focus,.focus\:ring-bambu-green\/50:focus{--tw-ring-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.focus\:ring-bambu-green\/50:focus{--tw-ring-color:color-mix(in oklab,var(--color-bambu-green)50%,transparent)}}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:ring-red-500:focus{--tw-ring-color:var(--color-red-500)}.focus\:ring-offset-0:focus{--tw-ring-offset-width:0px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\:ring-offset-bambu-dark:focus{--tw-ring-offset-color:var(--color-bambu-dark)}.focus\:ring-offset-bambu-dark-secondary:focus{--tw-ring-offset-color:var(--color-bambu-dark-secondary)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.active\:scale-95:active{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x)var(--tw-scale-y)}.active\:cursor-grabbing:active{cursor:grabbing}.active\:bg-amber-500\/30:active{background-color:#f99c004d}@supports (color:color-mix(in lab,red,red)){.active\:bg-amber-500\/30:active{background-color:color-mix(in oklab,var(--color-amber-500)30%,transparent)}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:cursor-wait:disabled{cursor:wait}.disabled\:bg-gray-600:disabled{background-color:var(--color-gray-600)}.disabled\:bg-zinc-700:disabled{background-color:var(--color-zinc-700)}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media(hover:hover){.disabled\:hover\:bg-bambu-green:disabled:hover{background-color:var(--color-bambu-green)}}@media not all and (min-width:640px){.max-\[640px\]\:hidden{display:none}.max-\[640px\]\:w-full{width:100%}.max-\[640px\]\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.max-\[640px\]\:flex-col{flex-direction:column}.max-\[640px\]\:flex-wrap{flex-wrap:wrap}.max-\[640px\]\:items-center{align-items:center}.max-\[640px\]\:items-start{align-items:flex-start}}@media not all and (min-width:550px){.max-\[550px\]\:order-1{order:1}.max-\[550px\]\:order-2{order:2}.max-\[550px\]\:order-3{order:3}.max-\[550px\]\:order-4{order:4}.max-\[550px\]\:mt-1{margin-top:calc(var(--spacing)*1)}.max-\[550px\]\:w-full{width:100%}.max-\[550px\]\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.max-\[550px\]\:flex-col{flex-direction:column}.max-\[550px\]\:flex-wrap{flex-wrap:wrap}.max-\[550px\]\:items-center{align-items:center}.max-\[550px\]\:items-start{align-items:flex-start}.max-\[550px\]\:justify-end{justify-content:flex-end}.max-\[550px\]\:gap-3{gap:calc(var(--spacing)*3)}.max-\[550px\]\:self-start{align-self:flex-start}}@media(min-width:40rem){.sm\:mt-0{margin-top:calc(var(--spacing)*0)}.sm\:mt-2{margin-top:calc(var(--spacing)*2)}.sm\:mt-3{margin-top:calc(var(--spacing)*3)}.sm\:mr-1{margin-right:calc(var(--spacing)*1)}.sm\:mb-4{margin-bottom:calc(var(--spacing)*4)}.sm\:ml-\[68px\]{margin-left:68px}.sm\:ml-auto{margin-left:auto}.sm\:block{display:block}.sm\:flex{display:flex}.sm\:grid{display:grid}.sm\:hidden{display:none}.sm\:inline{display:inline}.sm\:h-2{height:calc(var(--spacing)*2)}.sm\:h-3{height:calc(var(--spacing)*3)}.sm\:h-3\.5{height:calc(var(--spacing)*3.5)}.sm\:h-4{height:calc(var(--spacing)*4)}.sm\:h-5{height:calc(var(--spacing)*5)}.sm\:h-6{height:calc(var(--spacing)*6)}.sm\:h-14{height:calc(var(--spacing)*14)}.sm\:w-3{width:calc(var(--spacing)*3)}.sm\:w-3\.5{width:calc(var(--spacing)*3.5)}.sm\:w-4{width:calc(var(--spacing)*4)}.sm\:w-5{width:calc(var(--spacing)*5)}.sm\:w-6{width:calc(var(--spacing)*6)}.sm\:w-14{width:calc(var(--spacing)*14)}.sm\:w-16{width:calc(var(--spacing)*16)}.sm\:w-40{width:calc(var(--spacing)*40)}.sm\:w-72{width:calc(var(--spacing)*72)}.sm\:w-auto{width:auto}.sm\:max-w-none{max-width:none}.sm\:max-w-sm{max-width:var(--container-sm)}.sm\:max-w-xs{max-width:var(--container-xs)}.sm\:flex-1{flex:1}.sm\:flex-none{flex:none}.sm\:cursor-default{cursor:default}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-1{gap:calc(var(--spacing)*1)}.sm\:gap-1\.5{gap:calc(var(--spacing)*1.5)}.sm\:gap-2{gap:calc(var(--spacing)*2)}.sm\:gap-3{gap:calc(var(--spacing)*3)}.sm\:gap-4{gap:calc(var(--spacing)*4)}.sm\:gap-5{gap:calc(var(--spacing)*5)}.sm\:gap-6{gap:calc(var(--spacing)*6)}:where(.sm\:space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.sm\:space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.sm\:space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*8)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-y-reverse)))}.sm\:border-bambu-dark-tertiary{border-color:var(--color-bambu-dark-tertiary)}.sm\:p-1\.5{padding:calc(var(--spacing)*1.5)}.sm\:p-2{padding:calc(var(--spacing)*2)}.sm\:p-3{padding:calc(var(--spacing)*3)}.sm\:p-4{padding:calc(var(--spacing)*4)}.sm\:px-2{padding-inline:calc(var(--spacing)*2)}.sm\:px-3{padding-inline:calc(var(--spacing)*3)}.sm\:px-4{padding-inline:calc(var(--spacing)*4)}.sm\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.sm\:text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.sm\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.sm\:text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}}@media(min-width:48rem){.md\:top-\[2px\]{top:2px}.md\:left-\[2px\]{left:2px}.md\:col-span-2{grid-column:span 2/span 2}.md\:mx-0{margin-inline:calc(var(--spacing)*0)}.md\:block{display:block}.md\:inline{display:inline}.md\:h-4{height:calc(var(--spacing)*4)}.md\:h-5{height:calc(var(--spacing)*5)}.md\:min-h-0{min-height:calc(var(--spacing)*0)}.md\:w-4{width:calc(var(--spacing)*4)}.md\:w-9{width:calc(var(--spacing)*9)}.md\:min-w-\[200px\]{min-width:200px}.md\:flex-1{flex:1}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:grid-cols-\[1fr_140px_auto\]{grid-template-columns:1fr 140px auto}.md\:flex-row{flex-direction:row}.md\:flex-wrap{flex-wrap:wrap}.md\:items-center{align-items:center}.md\:gap-4{gap:calc(var(--spacing)*4)}.md\:p-6{padding:calc(var(--spacing)*6)}.md\:p-8{padding:calc(var(--spacing)*8)}.md\:px-0{padding-inline:calc(var(--spacing)*0)}.md\:py-2{padding-block:calc(var(--spacing)*2)}.md\:pb-0{padding-bottom:calc(var(--spacing)*0)}}@media(min-width:64rem){.lg\:static{position:static}.lg\:sticky{position:sticky}.lg\:top-4{top:calc(var(--spacing)*4)}.lg\:top-6{top:calc(var(--spacing)*6)}.lg\:col-span-2{grid-column:span 2/span 2}.lg\:mb-0{margin-bottom:calc(var(--spacing)*0)}.lg\:-ml-px{margin-left:-1px}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:h-\[calc\(100vh-64px\)\]{height:calc(100vh - 64px)}.lg\:w-1\/2{width:50%}.lg\:w-1\/3{width:33.3333%}.lg\:w-2\/3{width:66.6667%}.lg\:w-48{width:calc(var(--spacing)*48)}.lg\:w-80{width:calc(var(--spacing)*80)}.lg\:w-\[480px\]{width:480px}.lg\:max-w-md{max-width:var(--container-md)}.lg\:max-w-sm{max-width:var(--container-sm)}.lg\:max-w-xl{max-width:var(--container-xl)}.lg\:flex-shrink-0{flex-shrink:0}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:grid-cols-\[1fr_20rem\]{grid-template-columns:1fr 20rem}.lg\:flex-col{flex-direction:column}.lg\:flex-row{flex-direction:row}.lg\:flex-nowrap{flex-wrap:nowrap}.lg\:justify-start{justify-content:flex-start}.lg\:gap-0{gap:calc(var(--spacing)*0)}.lg\:gap-6{gap:calc(var(--spacing)*6)}.lg\:gap-8{gap:calc(var(--spacing)*8)}.lg\:self-start{align-self:flex-start}.lg\:overflow-y-auto{overflow-y:auto}.lg\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.lg\:border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.lg\:border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.lg\:p-8{padding:calc(var(--spacing)*8)}}@media(min-width:80rem){.xl\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}}@media(min-width:96rem){.\32xl\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}}:where(.dark\:divide-gray-800:where(.dark,.dark *)>:not(:last-child)){border-color:var(--color-gray-800)}.dark\:border-amber-700:where(.dark,.dark *){border-color:var(--color-amber-700)}.dark\:border-amber-800:where(.dark,.dark *){border-color:var(--color-amber-800)}.dark\:border-bambu-dark-tertiary:where(.dark,.dark *),.dark\:border-bambu-dark-tertiary\/50:where(.dark,.dark *){border-color:var(--color-bambu-dark-tertiary)}@supports (color:color-mix(in lab,red,red)){.dark\:border-bambu-dark-tertiary\/50:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-bambu-dark-tertiary)50%,transparent)}}.dark\:border-bambu-green\/40:where(.dark,.dark *){border-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.dark\:border-bambu-green\/40:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-bambu-green)40%,transparent)}}.dark\:border-gray-600:where(.dark,.dark *){border-color:var(--color-gray-600)}.dark\:border-gray-700:where(.dark,.dark *){border-color:var(--color-gray-700)}.dark\:border-red-500\/30:where(.dark,.dark *){border-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.dark\:border-red-500\/30:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.dark\:border-red-500\/40:where(.dark,.dark *){border-color:#fb2c3666}@supports (color:color-mix(in lab,red,red)){.dark\:border-red-500\/40:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-red-500)40%,transparent)}}.dark\:bg-amber-500\/10:where(.dark,.dark *){background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.dark\:bg-amber-500\/10:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-amber-500)10%,transparent)}}.dark\:bg-amber-900\/20:where(.dark,.dark *){background-color:#7b330633}@supports (color:color-mix(in lab,red,red)){.dark\:bg-amber-900\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-amber-900)20%,transparent)}}.dark\:bg-bambu-dark:where(.dark,.dark *){background-color:var(--color-bambu-dark)}.dark\:bg-bambu-dark-secondary:where(.dark,.dark *){background-color:var(--color-bambu-dark-secondary)}.dark\:bg-bambu-green\/20:where(.dark,.dark *){background-color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.dark\:bg-bambu-green\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-bambu-green)20%,transparent)}}.dark\:bg-black\/80:where(.dark,.dark *){background-color:#000c}@supports (color:color-mix(in lab,red,red)){.dark\:bg-black\/80:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-black)80%,transparent)}}.dark\:bg-blue-500\/10:where(.dark,.dark *){background-color:#3080ff1a}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-500\/10:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-blue-500)10%,transparent)}}.dark\:bg-blue-500\/20:where(.dark,.dark *){background-color:#3080ff33}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-500\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.dark\:bg-blue-900\/20:where(.dark,.dark *){background-color:#1c398e33}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-900\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-blue-900)20%,transparent)}}.dark\:bg-gray-700:where(.dark,.dark *){background-color:var(--color-gray-700)}.dark\:bg-gray-800:where(.dark,.dark *){background-color:var(--color-gray-800)}.dark\:bg-gray-800\/30:where(.dark,.dark *){background-color:#1e29394d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-gray-800\/30:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-gray-800)30%,transparent)}}.dark\:bg-gray-800\/40:where(.dark,.dark *){background-color:#1e293966}@supports (color:color-mix(in lab,red,red)){.dark\:bg-gray-800\/40:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-gray-800)40%,transparent)}}.dark\:bg-gray-800\/50:where(.dark,.dark *){background-color:#1e293980}@supports (color:color-mix(in lab,red,red)){.dark\:bg-gray-800\/50:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-gray-800)50%,transparent)}}.dark\:bg-gray-900:where(.dark,.dark *){background-color:var(--color-gray-900)}.dark\:bg-red-500\/10:where(.dark,.dark *){background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.dark\:bg-red-500\/10:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-red-500)10%,transparent)}}.dark\:bg-red-500\/20:where(.dark,.dark *){background-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.dark\:bg-red-500\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.dark\:text-amber-100:where(.dark,.dark *){color:var(--color-amber-100)}.dark\:text-amber-200:where(.dark,.dark *){color:var(--color-amber-200)}.dark\:text-amber-300:where(.dark,.dark *){color:var(--color-amber-300)}.dark\:text-amber-400:where(.dark,.dark *){color:var(--color-amber-400)}.dark\:text-bambu-gray:where(.dark,.dark *),.dark\:text-bambu-gray\/30:where(.dark,.dark *){color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.dark\:text-bambu-gray\/30:where(.dark,.dark *){color:color-mix(in oklab,var(--color-bambu-gray)30%,transparent)}}.dark\:text-bambu-gray\/50:where(.dark,.dark *){color:var(--color-bambu-gray)}@supports (color:color-mix(in lab,red,red)){.dark\:text-bambu-gray\/50:where(.dark,.dark *){color:color-mix(in oklab,var(--color-bambu-gray)50%,transparent)}}.dark\:text-bambu-green:where(.dark,.dark *),.dark\:text-bambu-green\/60:where(.dark,.dark *){color:var(--color-bambu-green)}@supports (color:color-mix(in lab,red,red)){.dark\:text-bambu-green\/60:where(.dark,.dark *){color:color-mix(in oklab,var(--color-bambu-green)60%,transparent)}}.dark\:text-blue-200:where(.dark,.dark *){color:var(--color-blue-200)}.dark\:text-blue-200\/80:where(.dark,.dark *){color:#bedbffcc}@supports (color:color-mix(in lab,red,red)){.dark\:text-blue-200\/80:where(.dark,.dark *){color:color-mix(in oklab,var(--color-blue-200)80%,transparent)}}.dark\:text-blue-300:where(.dark,.dark *){color:var(--color-blue-300)}.dark\:text-blue-300\/60:where(.dark,.dark *){color:#90c5ff99}@supports (color:color-mix(in lab,red,red)){.dark\:text-blue-300\/60:where(.dark,.dark *){color:color-mix(in oklab,var(--color-blue-300)60%,transparent)}}.dark\:text-blue-400:where(.dark,.dark *){color:var(--color-blue-400)}.dark\:text-emerald-300:where(.dark,.dark *){color:var(--color-emerald-300)}.dark\:text-emerald-400:where(.dark,.dark *){color:var(--color-emerald-400)}.dark\:text-gray-100:where(.dark,.dark *){color:var(--color-gray-100)}.dark\:text-gray-300:where(.dark,.dark *){color:var(--color-gray-300)}.dark\:text-gray-400:where(.dark,.dark *){color:var(--color-gray-400)}.dark\:text-gray-500:where(.dark,.dark *){color:var(--color-gray-500)}.dark\:text-gray-600:where(.dark,.dark *){color:var(--color-gray-600)}.dark\:text-green-400:where(.dark,.dark *){color:var(--color-green-400)}.dark\:text-orange-200:where(.dark,.dark *){color:var(--color-orange-200)}.dark\:text-orange-400:where(.dark,.dark *){color:var(--color-orange-400)}.dark\:text-red-400:where(.dark,.dark *){color:var(--color-red-400)}.dark\:text-red-400\/70:where(.dark,.dark *){color:#ff6568b3}@supports (color:color-mix(in lab,red,red)){.dark\:text-red-400\/70:where(.dark,.dark *){color:color-mix(in oklab,var(--color-red-400)70%,transparent)}}.dark\:text-white:where(.dark,.dark *){color:var(--color-white)}.dark\:text-yellow-200:where(.dark,.dark *){color:var(--color-yellow-200)}.dark\:text-yellow-200\/70:where(.dark,.dark *){color:#fff085b3}@supports (color:color-mix(in lab,red,red)){.dark\:text-yellow-200\/70:where(.dark,.dark *){color:color-mix(in oklab,var(--color-yellow-200)70%,transparent)}}@media(hover:hover){.dark\:hover\:border-gray-500:where(.dark,.dark *):hover{border-color:var(--color-gray-500)}.dark\:hover\:bg-bambu-dark-tertiary:where(.dark,.dark *):hover{background-color:var(--color-bambu-dark-tertiary)}.dark\:hover\:bg-bambu-dark\/50:where(.dark,.dark *):hover{background-color:var(--color-bambu-dark)}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-bambu-dark\/50:where(.dark,.dark *):hover{background-color:color-mix(in oklab,var(--color-bambu-dark)50%,transparent)}}.dark\:hover\:bg-gray-600:where(.dark,.dark *):hover{background-color:var(--color-gray-600)}.dark\:hover\:bg-gray-800\/50:where(.dark,.dark *):hover{background-color:#1e293980}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-gray-800\/50:where(.dark,.dark *):hover{background-color:color-mix(in oklab,var(--color-gray-800)50%,transparent)}}.dark\:hover\:bg-red-500\/30:where(.dark,.dark *):hover{background-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-red-500\/30:where(.dark,.dark *):hover{background-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.dark\:hover\:text-amber-200:where(.dark,.dark *):hover{color:var(--color-amber-200)}.dark\:hover\:text-blue-300:where(.dark,.dark *):hover{color:var(--color-blue-300)}.dark\:hover\:text-gray-200:where(.dark,.dark *):hover{color:var(--color-gray-200)}.dark\:hover\:text-gray-300:where(.dark,.dark *):hover{color:var(--color-gray-300)}.dark\:hover\:text-red-300:where(.dark,.dark *):hover{color:var(--color-red-300)}.dark\:hover\:text-white:where(.dark,.dark *):hover{color:var(--color-white)}}.\[\&\:\:-webkit-inner-spin-button\]\:appearance-none::-webkit-inner-spin-button{appearance:none}.\[\&\:\:-webkit-outer-spin-button\]\:appearance-none::-webkit-outer-spin-button{appearance:none}.\[\&\:\:-webkit-slider-thumb\]\:h-3::-webkit-slider-thumb{height:calc(var(--spacing)*3)}.\[\&\:\:-webkit-slider-thumb\]\:w-3::-webkit-slider-thumb{width:calc(var(--spacing)*3)}.\[\&\:\:-webkit-slider-thumb\]\:cursor-pointer::-webkit-slider-thumb{cursor:pointer}.\[\&\:\:-webkit-slider-thumb\]\:appearance-none::-webkit-slider-thumb{appearance:none}.\[\&\:\:-webkit-slider-thumb\]\:rounded-full::-webkit-slider-thumb{border-radius:3.40282e38px}.\[\&\:\:-webkit-slider-thumb\]\:bg-bambu-green::-webkit-slider-thumb{background-color:var(--color-bambu-green)}}:root{--accent:#00ae42;--accent-light:#00c64d;--accent-dark:#009438;--status-ok:#22c55e;--status-error:#ef4444;--status-warning:#f59e0b;--bg-primary:#f5f5f5;--bg-secondary:#fff;--bg-tertiary:#e5e5e5;--text-primary:#1a1a1a;--text-secondary:#4a4a4a;--text-muted:#6b6b6b;--text-tertiary:gray;--border-color:#d4d4d4;--card-shadow:0 2px 8px #00000014;--glow-color:transparent;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter,system-ui,sans-serif;font-weight:400;line-height:1.5}.dark{--bg-primary:#1a1a1a;--bg-secondary:#2d2d2d;--bg-tertiary:#3d3d3d;--text-primary:#fff;--text-secondary:#a0a0a0;--text-muted:gray;--text-tertiary:#4a4a4a;--border-color:#3d3d3d;--card-shadow:0 4px 16px #0006}.bg-warm{--bg-primary:#faf8f5;--bg-secondary:#fffefa;--bg-tertiary:#e8e4dd;--text-primary:#2d2a26;--text-secondary:#5c5750;--text-muted:#7a756c;--text-tertiary:#9a9590;--border-color:#d8d4cc}.bg-cool{--bg-primary:#f0f4f8;--bg-secondary:#fff;--bg-tertiary:#dce4ec;--text-primary:#1a2530;--text-secondary:#4a5568;--text-muted:#6b7a8a;--text-tertiary:#8a9aaa;--border-color:#c8d4e0}.dark.bg-neutral{--bg-primary:#1a1a1a;--bg-secondary:#2d2d2d;--bg-tertiary:#3d3d3d;--text-primary:#fff;--text-secondary:#a0a0a0;--text-muted:gray;--text-tertiary:#4a4a4a;--border-color:#3d3d3d}.dark.bg-warm{--bg-primary:#1c1a18;--bg-secondary:#2e2a26;--bg-tertiary:#3e3a36;--text-primary:#f5f0ea;--text-secondary:#b0a898;--text-muted:#8a8278;--text-tertiary:#5a5248;--border-color:#3e3a36}.dark.bg-cool{--bg-primary:#181c20;--bg-secondary:#262c32;--bg-tertiary:#363e46;--text-primary:#f0f4f8;--text-secondary:#98a8b8;--text-muted:#788898;--text-tertiary:#4a5a6a;--border-color:#363e46}.dark.bg-oled{--bg-primary:#000;--bg-secondary:#141414;--bg-tertiary:#1f1f1f;--text-primary:#fff;--text-secondary:#a0a0a0;--text-muted:#707070;--text-tertiary:#404040;--border-color:#2a2a2a}.dark.bg-slate{--bg-primary:#0f172a;--bg-secondary:#1e293b;--bg-tertiary:#334155;--text-primary:#f1f5f9;--text-secondary:#94a3b8;--text-muted:#64748b;--text-tertiary:#475569;--border-color:#334155}.dark.bg-forest{--bg-primary:#121a16;--bg-secondary:#1c2a22;--bg-tertiary:#2a3d30;--text-primary:#e8f5ec;--text-secondary:#8aa894;--text-muted:#6a8874;--text-tertiary:#4a6854;--border-color:#2a3d30}.printer-control-buttons-container{container-type:inline-size}@container (max-width:220px){.printer-control-buttons{flex-direction:column;align-items:stretch}.printer-control-buttons>button{width:100%}}.style-glow{--card-shadow:0 2px 8px #00000014,0 0 25px var(--accent)}@supports (color:color-mix(in lab,red,red)){.style-glow{--card-shadow:0 2px 8px #00000014,0 0 25px color-mix(in srgb,var(--accent)12%,transparent)}}.dark.style-glow{--card-shadow:0 4px 20px #00000080,0 0 40px var(--accent)}@supports (color:color-mix(in lab,red,red)){.dark.style-glow{--card-shadow:0 4px 20px #00000080,0 0 40px color-mix(in srgb,var(--accent)15%,transparent)}}.style-vibrant{--card-shadow:0 8px 30px #00000026,0 2px 8px #0000001a}.dark.style-vibrant{--card-shadow:0 10px 40px #0009,0 4px 12px #0006}.accent-green{--accent:#00ae42;--accent-light:#00c64d;--accent-dark:#009438}.accent-teal{--accent:#14b8a6;--accent-light:#2dd4bf;--accent-dark:#0d9488}.accent-blue{--accent:#3b82f6;--accent-light:#60a5fa;--accent-dark:#2563eb}.accent-orange{--accent:#f97316;--accent-light:#fb923c;--accent-dark:#ea580c}.accent-purple{--accent:#8b5cf6;--accent-light:#a78bfa;--accent-dark:#7c3aed}.accent-red{--accent:#ef4444;--accent-light:#f87171;--accent-dark:#dc2626}body{background-color:var(--bg-primary);color:var(--text-primary);min-height:100vh;margin:0;transition:background-color .2s,color .2s}#root{min-height:100vh}.text-white{color:var(--text-primary)}.bg-bambu-dark,.bg-bambu-dark-secondary,.bg-bambu-dark-tertiary,.border-bambu-dark-tertiary{transition:background-color .2s,border-color .2s}@keyframes slide-in{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}.animate-slide-in{animation:.2s ease-out slide-in}.icon-theme{opacity:.5}.dark .icon-theme{filter:invert();opacity:.4}.icon-green{filter:invert(48%)sepia(89%)saturate(459%)hue-rotate(93deg)brightness(95%)contrast(92%);opacity:1}.icon-heating{filter:invert(50%)sepia()saturate(1000%)hue-rotate(360deg)brightness()contrast();opacity:1}.dark .jogpad-theme{filter:brightness(.35)contrast(1.2)}.ams-empty-slot{background:repeating-linear-gradient(45deg,#444,#444 2px,#222 2px 4px)}.dark .ams-empty-slot{background:repeating-linear-gradient(45deg,#555,#555 2px,#333 2px 4px)}.touch-manipulation{touch-action:manipulation}.safe-area-bottom{padding-bottom:env(safe-area-inset-bottom,0)}.safe-area-top{padding-top:env(safe-area-inset-top,0)}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}@keyframes slide-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}.animate-slide-in-left{animation:.3s ease-out slide-in-left}@keyframes spoolbuddy-optimized-ping{0%{opacity:.8;transform:scale(.8)}80%,to{opacity:0;transform:scale(2.2)}}.spoolbuddy-optimized-ping{will-change:auto;contain:layout;animation:3.5s cubic-bezier(0,0,.2,1) infinite spoolbuddy-optimized-ping}.spoolbuddy-spool-glow{will-change:auto;transform:scale(2)}@media(prefers-reduced-motion:reduce){.spoolbuddy-optimized-ping{opacity:.25;animation:none;transform:scale(1.2)}.spoolbuddy-spool-glow{transition:none}}@keyframes slide-down{0%{transform:translateY(-100%)}to{transform:translateY(0)}}.animate-slide-down{animation:.25s ease-out slide-down}.card-shadow{box-shadow:var(--card-shadow)}[data-spoolbuddy-kiosk] .fixed .relative.max-w-2xl{flex-direction:column;height:90vh;max-height:90vh;display:flex}[data-spoolbuddy-kiosk] .fixed .relative.max-w-2xl>div:first-child,[data-spoolbuddy-kiosk] .fixed .relative.max-w-2xl>div:last-child{flex-shrink:0}[data-spoolbuddy-kiosk] .fixed .relative.max-w-2xl>div:nth-child(2){flex:auto;min-height:0;overflow-y:auto}[data-spoolbuddy-kiosk] .fixed .relative.max-w-2xl .max-h-96{max-height:none}.calendar-scroll{scrollbar-width:thin;scrollbar-color:var(--text-muted)transparent}@supports (color:color-mix(in lab,red,red)){.calendar-scroll{scrollbar-color:color-mix(in srgb,var(--text-muted)60%,transparent)transparent}}.calendar-scroll::-webkit-scrollbar{width:8px}.calendar-scroll::-webkit-scrollbar-track{background:0 0}.calendar-scroll::-webkit-scrollbar-thumb{background-color:var(--text-muted)}@supports (color:color-mix(in lab,red,red)){.calendar-scroll::-webkit-scrollbar-thumb{background-color:color-mix(in srgb,var(--text-muted)60%,transparent)}}.calendar-scroll::-webkit-scrollbar-thumb{border:2px solid var(--bg-secondary);border-radius:999px}@supports (color:color-mix(in lab,red,red)){.calendar-scroll::-webkit-scrollbar-thumb{border:2px solid color-mix(in srgb,var(--bg-secondary)70%,transparent)}}.calendar-scroll::-webkit-scrollbar-thumb:hover{background-color:var(--text-muted)}@supports (color:color-mix(in lab,red,red)){.calendar-scroll::-webkit-scrollbar-thumb:hover{background-color:color-mix(in srgb,var(--text-muted)80%,transparent)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:""}}}.hg-theme-default{background-color:#ececec;border-radius:5px;box-sizing:border-box;font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;overflow:hidden;padding:5px;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.hg-theme-default .hg-button span,.hg-theme-default .hg-button span svg{pointer-events:none}.hg-theme-default button.hg-button{border-width:0;font-size:inherit}.hg-theme-default .hg-button{display:inline-block;flex-grow:1}.hg-theme-default .hg-row{display:flex}.hg-theme-default .hg-row:not(:last-child){margin-bottom:5px}.hg-theme-default .hg-row .hg-button-container,.hg-theme-default .hg-row .hg-button:not(:last-child){margin-right:5px}.hg-theme-default .hg-row>div:last-child{margin-right:0}.hg-theme-default .hg-row .hg-button-container{display:flex}.hg-theme-default .hg-button{align-items:center;background:#fff;border-bottom:1px solid #b5b5b5;border-radius:5px;box-shadow:0 0 3px -1px #0000004d;box-sizing:border-box;cursor:pointer;display:flex;height:40px;justify-content:center;padding:5px;-webkit-tap-highlight-color:rgba(0,0,0,0)}.hg-theme-default .hg-button.hg-standardBtn{width:20px}.hg-theme-default .hg-button.hg-activeButton{background:#efefef}.hg-theme-default.hg-layout-numeric .hg-button{align-items:center;display:flex;height:60px;justify-content:center;width:33.3%}.hg-theme-default .hg-button.hg-button-numpadadd,.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.hg-theme-default .hg-button.hg-button-com{max-width:85px}.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.hg-theme-default .hg-button.hg-selectedButton{background:#05194687;color:#fff}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}.hg-candidate-box{background:#ececec;border-bottom:2px solid #b5b5b5;border-radius:5px;display:inline-flex;margin-top:-10px;position:absolute;transform:translateY(-100%);-webkit-user-select:none;-moz-user-select:none;user-select:none}ul.hg-candidate-box-list{display:flex;flex:1;list-style:none;margin:0;padding:0}li.hg-candidate-box-list-item{align-items:center;display:flex;height:40px;justify-content:center;width:40px}li.hg-candidate-box-list-item:hover{background:#00000008;cursor:pointer}li.hg-candidate-box-list-item:active{background:#0000001a}.hg-candidate-box-prev:before{content:"◄"}.hg-candidate-box-next:before{content:"►"}.hg-candidate-box-next,.hg-candidate-box-prev{align-items:center;color:#969696;cursor:pointer;display:flex;padding:0 10px}.hg-candidate-box-next{border-bottom-right-radius:5px;border-top-right-radius:5px}.hg-candidate-box-prev{border-bottom-left-radius:5px;border-top-left-radius:5px}.hg-candidate-box-btn-active{color:#444}.simple-keyboard.vkb-theme{background:#1a1a1a;border-top:1px solid #333;padding:8px 4px;font-family:inherit}.simple-keyboard.vkb-theme .hg-row{display:flex!important;flex-direction:row!important;flex-wrap:nowrap!important;gap:4px;margin-bottom:4px}.simple-keyboard.vkb-theme .hg-row:last-child{margin-bottom:0}.simple-keyboard.vkb-theme .hg-button{display:inline-flex!important;align-items:center;justify-content:center;flex-grow:1;flex-shrink:1;flex-basis:auto;background:#2d2d2d;color:#e0e0e0;border:none;border-radius:6px;height:44px;font-size:16px;font-weight:500;box-shadow:0 1px 2px #0000004d;transition:background .1s;cursor:pointer;padding:0 2px;min-width:0}.simple-keyboard.vkb-theme .hg-button:active{background:#00ae42;color:#fff}.simple-keyboard.vkb-theme .hg-button-bksp,.simple-keyboard.vkb-theme .hg-button-shift,.simple-keyboard.vkb-theme .hg-button-lock{background:#3a3a3a;color:#aaa;flex-grow:1.5}.simple-keyboard.vkb-theme .hg-button-close{background:#3a3a3a;color:#aaa;flex-grow:2;font-weight:600}.simple-keyboard.vkb-theme .hg-button-close:active{background:#555}.simple-keyboard.vkb-theme .hg-button-space{flex-grow:7}.simple-keyboard.vkb-theme .hg-activeButton{background:#00ae42;color:#fff} diff --git a/static/assets/index-B6Qs-684.js b/static/assets/index-DRnoASko.js similarity index 73% rename from static/assets/index-B6Qs-684.js rename to static/assets/index-DRnoASko.js index 1f017c7c6..49a8b96de 100644 --- a/static/assets/index-B6Qs-684.js +++ b/static/assets/index-DRnoASko.js @@ -1,42 +1,42 @@ -function Zde(t,e){for(var n=0;nr[i]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();var Z_=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function gc(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var SM={exports:{}},Ev={};var H8;function eue(){if(H8)return Ev;H8=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(r,i,s){var o=null;if(s!==void 0&&(o=""+s),i.key!==void 0&&(o=""+i.key),"key"in i){s={};for(var l in i)l!=="key"&&(s[l]=i[l])}else s=i;return i=s.ref,{$$typeof:t,type:r,key:o,ref:i!==void 0?i:null,props:s}}return Ev.Fragment=e,Ev.jsx=n,Ev.jsxs=n,Ev}var q8;function tue(){return q8||(q8=1,SM.exports=eue()),SM.exports}var a=tue(),_M={exports:{}},Wn={};var $8;function nue(){if($8)return Wn;$8=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.consumer"),o=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),c=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),u=Symbol.for("react.lazy"),m=Symbol.for("react.activity"),p=Symbol.iterator;function f(K){return K===null||typeof K!="object"?null:(K=p&&K[p]||K["@@iterator"],typeof K=="function"?K:null)}var x={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},v=Object.assign,b={};function g(K,ae,me){this.props=K,this.context=ae,this.refs=b,this.updater=me||x}g.prototype.isReactComponent={},g.prototype.setState=function(K,ae){if(typeof K!="object"&&typeof K!="function"&&K!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,K,ae,"setState")},g.prototype.forceUpdate=function(K){this.updater.enqueueForceUpdate(this,K,"forceUpdate")};function S(){}S.prototype=g.prototype;function N(K,ae,me){this.props=K,this.context=ae,this.refs=b,this.updater=me||x}var P=N.prototype=new S;P.constructor=N,v(P,g.prototype),P.isPureReactComponent=!0;var C=Array.isArray;function A(){}var T={H:null,A:null,T:null,S:null},F=Object.prototype.hasOwnProperty;function k(K,ae,me){var xe=me.ref;return{$$typeof:t,type:K,key:ae,ref:xe!==void 0?xe:null,props:me}}function M(K,ae){return k(K.type,ae,K.props)}function U(K){return typeof K=="object"&&K!==null&&K.$$typeof===t}function z(K){var ae={"=":"=0",":":"=2"};return"$"+K.replace(/[=:]/g,function(me){return ae[me]})}var X=/\/+/g;function L(K,ae){return typeof K=="object"&&K!==null&&K.key!=null?z(""+K.key):ae.toString(36)}function ne(K){switch(K.status){case"fulfilled":return K.value;case"rejected":throw K.reason;default:switch(typeof K.status=="string"?K.then(A,A):(K.status="pending",K.then(function(ae){K.status==="pending"&&(K.status="fulfilled",K.value=ae)},function(ae){K.status==="pending"&&(K.status="rejected",K.reason=ae)})),K.status){case"fulfilled":return K.value;case"rejected":throw K.reason}}throw K}function re(K,ae,me,xe,be){var H=typeof K;(H==="undefined"||H==="boolean")&&(K=null);var Q=!1;if(K===null)Q=!0;else switch(H){case"bigint":case"string":case"number":Q=!0;break;case"object":switch(K.$$typeof){case t:case e:Q=!0;break;case u:return Q=K._init,re(Q(K._payload),ae,me,xe,be)}}if(Q)return be=be(K),Q=xe===""?"."+L(K,0):xe,C(be)?(me="",Q!=null&&(me=Q.replace(X,"$&/")+"/"),re(be,ae,me,"",function(B){return B})):be!=null&&(U(be)&&(be=M(be,me+(be.key==null||K&&K.key===be.key?"":(""+be.key).replace(X,"$&/")+"/")+Q)),ae.push(be)),1;Q=0;var D=xe===""?".":xe+":";if(C(K))for(var E=0;E>>1,oe=re[se];if(0>>1;sei(me,ue))xei(be,me)?(re[se]=be,re[xe]=ue,se=xe):(re[se]=me,re[ae]=ue,se=ae);else if(xei(be,ue))re[se]=be,re[xe]=ue,se=xe;else break e}}return ee}function i(re,ee){var ue=re.sortIndex-ee.sortIndex;return ue!==0?ue:re.id-ee.id}if(t.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var s=performance;t.unstable_now=function(){return s.now()}}else{var o=Date,l=o.now();t.unstable_now=function(){return o.now()-l}}var c=[],d=[],u=1,m=null,p=3,f=!1,x=!1,v=!1,b=!1,g=typeof setTimeout=="function"?setTimeout:null,S=typeof clearTimeout=="function"?clearTimeout:null,N=typeof setImmediate<"u"?setImmediate:null;function P(re){for(var ee=n(d);ee!==null;){if(ee.callback===null)r(d);else if(ee.startTime<=re)r(d),ee.sortIndex=ee.expirationTime,e(c,ee);else break;ee=n(d)}}function C(re){if(v=!1,P(re),!x)if(n(c)!==null)x=!0,A||(A=!0,z());else{var ee=n(d);ee!==null&&ne(C,ee.startTime-re)}}var A=!1,T=-1,F=5,k=-1;function M(){return b?!0:!(t.unstable_now()-kre&&M());){var se=m.callback;if(typeof se=="function"){m.callback=null,p=m.priorityLevel;var oe=se(m.expirationTime<=re);if(re=t.unstable_now(),typeof oe=="function"){m.callback=oe,P(re),ee=!0;break t}m===n(c)&&r(c),P(re)}else r(c);m=n(c)}if(m!==null)ee=!0;else{var K=n(d);K!==null&&ne(C,K.startTime-re),ee=!1}}break e}finally{m=null,p=ue,f=!1}ee=void 0}}finally{ee?z():A=!1}}}var z;if(typeof N=="function")z=function(){N(U)};else if(typeof MessageChannel<"u"){var X=new MessageChannel,L=X.port2;X.port1.onmessage=U,z=function(){L.postMessage(null)}}else z=function(){g(U,0)};function ne(re,ee){T=g(function(){re(t.unstable_now())},ee)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(re){re.callback=null},t.unstable_forceFrameRate=function(re){0>re||125se?(re.sortIndex=ue,e(d,re),n(c)===null&&re===n(d)&&(v?(S(T),T=-1):v=!0,ne(C,ue-se))):(re.sortIndex=oe,e(c,re),x||f||(x=!0,A||(A=!0,z()))),re},t.unstable_shouldYield=M,t.unstable_wrapCallback=function(re){var ee=p;return function(){var ue=p;p=ee;try{return re.apply(this,arguments)}finally{p=ue}}}})(CM)),CM}var W8;function iue(){return W8||(W8=1,NM.exports=aue()),NM.exports}var PM={exports:{}},Es={};var K8;function sue(){if(K8)return Es;K8=1;var t=Ug();function e(c){var d="https://react.dev/errors/"+c;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(e){console.error(e)}}return t(),PM.exports=sue(),PM.exports}var Y8;function oue(){if(Y8)return Dv;Y8=1;var t=iue(),e=Ug(),n=aQ();function r(h){var y="https://react.dev/errors/"+h;if(1oe||(h.current=se[oe],se[oe]=null,oe--)}function me(h,y){oe++,se[oe]=h.current,h.current=y}var xe=K(null),be=K(null),H=K(null),Q=K(null);function D(h,y){switch(me(H,y),me(be,h),me(xe,null),y.nodeType){case 9:case 11:h=(h=y.documentElement)&&(h=h.namespaceURI)?u8(h):0;break;default:if(h=y.tagName,y=y.namespaceURI)y=u8(y),h=m8(y,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}ae(xe),me(xe,h)}function E(){ae(xe),ae(be),ae(H)}function B(h){h.memoizedState!==null&&me(Q,h);var y=xe.current,_=m8(y,h.type);y!==_&&(me(be,h),me(xe,_))}function Y(h){be.current===h&&(ae(xe),ae(be)),Q.current===h&&(ae(Q),Tv._currentValue=ue)}var I,ce;function O(h){if(I===void 0)try{throw Error()}catch(_){var y=_.stack.trim().match(/\n( *(at )?)/);I=y&&y[1]||"",ce=-1<_.stack.indexOf(` +function eue(t,e){for(var n=0;nr[i]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();var Z_=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function gc(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var _M={exports:{}},Ev={};var $8;function tue(){if($8)return Ev;$8=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(r,i,s){var o=null;if(s!==void 0&&(o=""+s),i.key!==void 0&&(o=""+i.key),"key"in i){s={};for(var l in i)l!=="key"&&(s[l]=i[l])}else s=i;return i=s.ref,{$$typeof:t,type:r,key:o,ref:i!==void 0?i:null,props:s}}return Ev.Fragment=e,Ev.jsx=n,Ev.jsxs=n,Ev}var V8;function nue(){return V8||(V8=1,_M.exports=tue()),_M.exports}var a=nue(),kM={exports:{}},Wn={};var G8;function rue(){if(G8)return Wn;G8=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.consumer"),o=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),c=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),u=Symbol.for("react.lazy"),m=Symbol.for("react.activity"),p=Symbol.iterator;function f(K){return K===null||typeof K!="object"?null:(K=p&&K[p]||K["@@iterator"],typeof K=="function"?K:null)}var x={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},v=Object.assign,b={};function g(K,ae,me){this.props=K,this.context=ae,this.refs=b,this.updater=me||x}g.prototype.isReactComponent={},g.prototype.setState=function(K,ae){if(typeof K!="object"&&typeof K!="function"&&K!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,K,ae,"setState")},g.prototype.forceUpdate=function(K){this.updater.enqueueForceUpdate(this,K,"forceUpdate")};function S(){}S.prototype=g.prototype;function N(K,ae,me){this.props=K,this.context=ae,this.refs=b,this.updater=me||x}var P=N.prototype=new S;P.constructor=N,v(P,g.prototype),P.isPureReactComponent=!0;var C=Array.isArray;function A(){}var T={H:null,A:null,T:null,S:null},F=Object.prototype.hasOwnProperty;function k(K,ae,me){var xe=me.ref;return{$$typeof:t,type:K,key:ae,ref:xe!==void 0?xe:null,props:me}}function E(K,ae){return k(K.type,ae,K.props)}function $(K){return typeof K=="object"&&K!==null&&K.$$typeof===t}function z(K){var ae={"=":"=0",":":"=2"};return"$"+K.replace(/[=:]/g,function(me){return ae[me]})}var X=/\/+/g;function L(K,ae){return typeof K=="object"&&K!==null&&K.key!=null?z(""+K.key):ae.toString(36)}function ne(K){switch(K.status){case"fulfilled":return K.value;case"rejected":throw K.reason;default:switch(typeof K.status=="string"?K.then(A,A):(K.status="pending",K.then(function(ae){K.status==="pending"&&(K.status="fulfilled",K.value=ae)},function(ae){K.status==="pending"&&(K.status="rejected",K.reason=ae)})),K.status){case"fulfilled":return K.value;case"rejected":throw K.reason}}throw K}function re(K,ae,me,xe,be){var B=typeof K;(B==="undefined"||B==="boolean")&&(K=null);var Q=!1;if(K===null)Q=!0;else switch(B){case"bigint":case"string":case"number":Q=!0;break;case"object":switch(K.$$typeof){case t:case e:Q=!0;break;case u:return Q=K._init,re(Q(K._payload),ae,me,xe,be)}}if(Q)return be=be(K),Q=xe===""?"."+L(K,0):xe,C(be)?(me="",Q!=null&&(me=Q.replace(X,"$&/")+"/"),re(be,ae,me,"",function(U){return U})):be!=null&&($(be)&&(be=E(be,me+(be.key==null||K&&K.key===be.key?"":(""+be.key).replace(X,"$&/")+"/")+Q)),ae.push(be)),1;Q=0;var D=xe===""?".":xe+":";if(C(K))for(var M=0;M>>1,oe=re[se];if(0>>1;sei(me,ue))xei(be,me)?(re[se]=be,re[xe]=ue,se=xe):(re[se]=me,re[ae]=ue,se=ae);else if(xei(be,ue))re[se]=be,re[xe]=ue,se=xe;else break e}}return ee}function i(re,ee){var ue=re.sortIndex-ee.sortIndex;return ue!==0?ue:re.id-ee.id}if(t.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var s=performance;t.unstable_now=function(){return s.now()}}else{var o=Date,l=o.now();t.unstable_now=function(){return o.now()-l}}var c=[],d=[],u=1,m=null,p=3,f=!1,x=!1,v=!1,b=!1,g=typeof setTimeout=="function"?setTimeout:null,S=typeof clearTimeout=="function"?clearTimeout:null,N=typeof setImmediate<"u"?setImmediate:null;function P(re){for(var ee=n(d);ee!==null;){if(ee.callback===null)r(d);else if(ee.startTime<=re)r(d),ee.sortIndex=ee.expirationTime,e(c,ee);else break;ee=n(d)}}function C(re){if(v=!1,P(re),!x)if(n(c)!==null)x=!0,A||(A=!0,z());else{var ee=n(d);ee!==null&&ne(C,ee.startTime-re)}}var A=!1,T=-1,F=5,k=-1;function E(){return b?!0:!(t.unstable_now()-kre&&E());){var se=m.callback;if(typeof se=="function"){m.callback=null,p=m.priorityLevel;var oe=se(m.expirationTime<=re);if(re=t.unstable_now(),typeof oe=="function"){m.callback=oe,P(re),ee=!0;break t}m===n(c)&&r(c),P(re)}else r(c);m=n(c)}if(m!==null)ee=!0;else{var K=n(d);K!==null&&ne(C,K.startTime-re),ee=!1}}break e}finally{m=null,p=ue,f=!1}ee=void 0}}finally{ee?z():A=!1}}}var z;if(typeof N=="function")z=function(){N($)};else if(typeof MessageChannel<"u"){var X=new MessageChannel,L=X.port2;X.port1.onmessage=$,z=function(){L.postMessage(null)}}else z=function(){g($,0)};function ne(re,ee){T=g(function(){re(t.unstable_now())},ee)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(re){re.callback=null},t.unstable_forceFrameRate=function(re){0>re||125se?(re.sortIndex=ue,e(d,re),n(c)===null&&re===n(d)&&(v?(S(T),T=-1):v=!0,ne(C,ue-se))):(re.sortIndex=oe,e(c,re),x||f||(x=!0,A||(A=!0,z()))),re},t.unstable_shouldYield=E,t.unstable_wrapCallback=function(re){var ee=p;return function(){var ue=p;p=ee;try{return re.apply(this,arguments)}finally{p=ue}}}})(PM)),PM}var X8;function sue(){return X8||(X8=1,CM.exports=iue()),CM.exports}var TM={exports:{}},Es={};var Y8;function oue(){if(Y8)return Es;Y8=1;var t=Ug();function e(c){var d="https://react.dev/errors/"+c;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(e){console.error(e)}}return t(),TM.exports=oue(),TM.exports}var J8;function lue(){if(J8)return Dv;J8=1;var t=sue(),e=Ug(),n=iQ();function r(h){var y="https://react.dev/errors/"+h;if(1oe||(h.current=se[oe],se[oe]=null,oe--)}function me(h,y){oe++,se[oe]=h.current,h.current=y}var xe=K(null),be=K(null),B=K(null),Q=K(null);function D(h,y){switch(me(B,y),me(be,h),me(xe,null),y.nodeType){case 9:case 11:h=(h=y.documentElement)&&(h=h.namespaceURI)?h8(h):0;break;default:if(h=y.tagName,y=y.namespaceURI)y=h8(y),h=p8(y,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}ae(xe),me(xe,h)}function M(){ae(xe),ae(be),ae(B)}function U(h){h.memoizedState!==null&&me(Q,h);var y=xe.current,_=p8(y,h.type);y!==_&&(me(be,h),me(xe,_))}function Y(h){be.current===h&&(ae(xe),ae(be)),Q.current===h&&(ae(Q),Tv._currentValue=ue)}var I,ce;function O(h){if(I===void 0)try{throw Error()}catch(_){var y=_.stack.trim().match(/\n( *(at )?)/);I=y&&y[1]||"",ce=-1<_.stack.indexOf(` at`)?" ()":-1<_.stack.indexOf("@")?"@unknown:0:0":""}return` `+I+h+ce}var W=!1;function V(h,y){if(!h||W)return"";W=!0;var _=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var j={DetermineComponentFrameRoot:function(){try{if(y){var Ut=function(){throw Error()};if(Object.defineProperty(Ut.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(Ut,[])}catch(At){var St=At}Reflect.construct(h,[],Ut)}else{try{Ut.call()}catch(At){St=At}h.call(Ut.prototype)}}else{try{throw Error()}catch(At){St=At}(Ut=h())&&typeof Ut.catch=="function"&&Ut.catch(function(){})}}catch(At){if(At&&St&&typeof At.stack=="string")return[At.stack,St.stack]}return[null,null]}};j.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var G=Object.getOwnPropertyDescriptor(j.DetermineComponentFrameRoot,"name");G&&G.configurable&&Object.defineProperty(j.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var Z=j.DetermineComponentFrameRoot(),Ne=Z[0],qe=Z[1];if(Ne&&qe){var lt=Ne.split(` `),vt=qe.split(` `);for(G=j=0;jG||lt[j]!==vt[G]){var Rt=` -`+lt[j].replace(" at new "," at ");return h.displayName&&Rt.includes("")&&(Rt=Rt.replace("",h.displayName)),Rt}while(1<=j&&0<=G);break}}}finally{W=!1,Error.prepareStackTrace=_}return(_=h?h.displayName||h.name:"")?O(_):""}function q(h,y){switch(h.tag){case 26:case 27:case 5:return O(h.type);case 16:return O("Lazy");case 13:return h.child!==y&&y!==null?O("Suspense Fallback"):O("Suspense");case 19:return O("SuspenseList");case 0:case 15:return V(h.type,!1);case 11:return V(h.type.render,!1);case 1:return V(h.type,!0);case 31:return O("Activity");default:return""}}function J(h){try{var y="",_=null;do y+=q(h,_),_=h,h=h.return;while(h);return y}catch(j){return` +`+lt[j].replace(" at new "," at ");return h.displayName&&Rt.includes("")&&(Rt=Rt.replace("",h.displayName)),Rt}while(1<=j&&0<=G);break}}}finally{W=!1,Error.prepareStackTrace=_}return(_=h?h.displayName||h.name:"")?O(_):""}function H(h,y){switch(h.tag){case 26:case 27:case 5:return O(h.type);case 16:return O("Lazy");case 13:return h.child!==y&&y!==null?O("Suspense Fallback"):O("Suspense");case 19:return O("SuspenseList");case 0:case 15:return V(h.type,!1);case 11:return V(h.type.render,!1);case 1:return V(h.type,!0);case 31:return O("Activity");default:return""}}function J(h){try{var y="",_=null;do y+=H(h,_),_=h,h=h.return;while(h);return y}catch(j){return` Error generating stack: `+j.message+` -`+j.stack}}var ie=Object.prototype.hasOwnProperty,ge=t.unstable_scheduleCallback,pe=t.unstable_cancelCallback,he=t.unstable_shouldYield,$=t.unstable_requestPaint,R=t.unstable_now,te=t.unstable_getCurrentPriorityLevel,fe=t.unstable_ImmediatePriority,ke=t.unstable_UserBlockingPriority,je=t.unstable_NormalPriority,Ae=t.unstable_LowPriority,ye=t.unstable_IdlePriority,Re=t.log,Be=t.unstable_setDisableYieldValue,Ce=null,ze=null;function Me(h){if(typeof Re=="function"&&Be(h),ze&&typeof ze.setStrictMode=="function")try{ze.setStrictMode(Ce,h)}catch{}}var Ie=Math.clz32?Math.clz32:ve,Ge=Math.log,et=Math.LN2;function ve(h){return h>>>=0,h===0?32:31-(Ge(h)/et|0)|0}var Xe=256,Pe=262144,Ve=4194304;function we(h){var y=h&42;if(y!==0)return y;switch(h&-h){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return h&261888;case 262144:case 524288:case 1048576:case 2097152:return h&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return h&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return h}}function de(h,y,_){var j=h.pendingLanes;if(j===0)return 0;var G=0,Z=h.suspendedLanes,Ne=h.pingedLanes;h=h.warmLanes;var qe=j&134217727;return qe!==0?(j=qe&~Z,j!==0?G=we(j):(Ne&=qe,Ne!==0?G=we(Ne):_||(_=qe&~h,_!==0&&(G=we(_))))):(qe=j&~Z,qe!==0?G=we(qe):Ne!==0?G=we(Ne):_||(_=j&~h,_!==0&&(G=we(_)))),G===0?0:y!==0&&y!==G&&(y&Z)===0&&(Z=G&-G,_=y&-y,Z>=_||Z===32&&(_&4194048)!==0)?y:G}function Se(h,y){return(h.pendingLanes&~(h.suspendedLanes&~h.pingedLanes)&y)===0}function $e(h,y){switch(h){case 1:case 2:case 4:case 8:case 64:return y+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return y+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function st(){var h=Ve;return Ve<<=1,(Ve&62914560)===0&&(Ve=4194304),h}function He(h){for(var y=[],_=0;31>_;_++)y.push(h);return y}function rt(h,y){h.pendingLanes|=y,y!==268435456&&(h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0)}function ht(h,y,_,j,G,Z){var Ne=h.pendingLanes;h.pendingLanes=_,h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0,h.expiredLanes&=_,h.entangledLanes&=_,h.errorRecoveryDisabledLanes&=_,h.shellSuspendCounter=0;var qe=h.entanglements,lt=h.expirationTimes,vt=h.hiddenUpdates;for(_=Ne&~_;0<_;){var Rt=31-Ie(_),Ut=1<"u")return null;try{return h.activeElement||h.body}catch{return h.body}}var Pr=/[\n"\\]/g;function In(h){return h.replace(Pr,function(y){return"\\"+y.charCodeAt(0).toString(16)+" "})}function Da(h,y,_,j,G,Z,Ne,qe){h.name="",Ne!=null&&typeof Ne!="function"&&typeof Ne!="symbol"&&typeof Ne!="boolean"?h.type=Ne:h.removeAttribute("type"),y!=null?Ne==="number"?(y===0&&h.value===""||h.value!=y)&&(h.value=""+cn(y)):h.value!==""+cn(y)&&(h.value=""+cn(y)):Ne!=="submit"&&Ne!=="reset"||h.removeAttribute("value"),y!=null?Br(h,Ne,cn(y)):_!=null?Br(h,Ne,cn(_)):j!=null&&h.removeAttribute("value"),G==null&&Z!=null&&(h.defaultChecked=!!Z),G!=null&&(h.checked=G&&typeof G!="function"&&typeof G!="symbol"),qe!=null&&typeof qe!="function"&&typeof qe!="symbol"&&typeof qe!="boolean"?h.name=""+cn(qe):h.removeAttribute("name")}function $n(h,y,_,j,G,Z,Ne,qe){if(Z!=null&&typeof Z!="function"&&typeof Z!="symbol"&&typeof Z!="boolean"&&(h.type=Z),y!=null||_!=null){if(!(Z!=="submit"&&Z!=="reset"||y!=null)){Sn(h);return}_=_!=null?""+cn(_):"",y=y!=null?""+cn(y):_,qe||y===h.value||(h.value=y),h.defaultValue=y}j=j??G,j=typeof j!="function"&&typeof j!="symbol"&&!!j,h.checked=qe?h.checked:!!j,h.defaultChecked=!!j,Ne!=null&&typeof Ne!="function"&&typeof Ne!="symbol"&&typeof Ne!="boolean"&&(h.name=Ne),Sn(h)}function Br(h,y,_){y==="number"&&br(h.ownerDocument)===h||h.defaultValue===""+_||(h.defaultValue=""+_)}function Kr(h,y,_,j){if(h=h.options,y){y={};for(var G=0;G<_.length;G++)y["$"+_[G]]=!0;for(_=0;_"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),zi=!1;if($o)try{var wl={};Object.defineProperty(wl,"passive",{get:function(){zi=!0}}),window.addEventListener("test",wl,wl),window.removeEventListener("test",wl,wl)}catch{zi=!1}var wo=null,ha=null,vc=null;function Om(){if(vc)return vc;var h,y=ha,_=y.length,j,G="value"in wo?wo.value:wo.textContent,Z=G.length;for(h=0;h<_&&y[h]===G[h];h++);var Ne=_-h;for(j=1;j<=Ne&&y[_-j]===G[Z-j];j++);return vc=G.slice(h,1=it),ct=" ",Mn=!1;function xr(h,y){switch(h){case"keyup":return Fn.indexOf(y.keyCode)!==-1;case"keydown":return y.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function lr(h){return h=h.detail,typeof h=="object"&&"data"in h?h.data:null}var Ir=!1;function Fa(h,y){switch(h){case"compositionend":return lr(y);case"keypress":return y.which!==32?null:(Mn=!0,ct);case"textInput":return h=y.data,h===ct&&Mn?null:h;default:return null}}function un(h,y){if(Ir)return h==="compositionend"||!_n&&xr(h,y)?(h=Om(),vc=ha=wo=null,Ir=!1,h):null;switch(h){case"paste":return null;case"keypress":if(!(y.ctrlKey||y.altKey||y.metaKey)||y.ctrlKey&&y.altKey){if(y.char&&1=y)return{node:_,offset:y-h};h=j}e:{for(;_;){if(_.nextSibling){_=_.nextSibling;break e}_=_.parentNode}_=void 0}_=Yp(_)}}function Jy(h,y){return h&&y?h===y?!0:h&&h.nodeType===3?!1:y&&y.nodeType===3?Jy(h,y.parentNode):"contains"in h?h.contains(y):h.compareDocumentPosition?!!(h.compareDocumentPosition(y)&16):!1:!1}function YS(h){h=h!=null&&h.ownerDocument!=null&&h.ownerDocument.defaultView!=null?h.ownerDocument.defaultView:window;for(var y=br(h.document);y instanceof h.HTMLIFrameElement;){try{var _=typeof y.contentWindow.location.href=="string"}catch{_=!1}if(_)h=y.contentWindow;else break;y=br(h.document)}return y}function MA(h){var y=h&&h.nodeName&&h.nodeName.toLowerCase();return y&&(y==="input"&&(h.type==="text"||h.type==="search"||h.type==="tel"||h.type==="url"||h.type==="password")||y==="textarea"||h.contentEditable==="true")}var Ece=$o&&"documentMode"in document&&11>=document.documentMode,eb=null,EA=null,Zy=null,DA=!1;function D5(h,y,_){var j=_.window===_?_.document:_.nodeType===9?_:_.ownerDocument;DA||eb==null||eb!==br(j)||(j=eb,"selectionStart"in j&&MA(j)?j={start:j.selectionStart,end:j.selectionEnd}:(j=(j.ownerDocument&&j.ownerDocument.defaultView||window).getSelection(),j={anchorNode:j.anchorNode,anchorOffset:j.anchorOffset,focusNode:j.focusNode,focusOffset:j.focusOffset}),Zy&&Vm(Zy,j)||(Zy=j,j=I_(EA,"onSelect"),0>=Ne,G-=Ne,ld=1<<32-Ie(y)+G|_<Qn?(vr=vn,vn=null):vr=vn.sibling;var Mr=St(gt,vn,yt[Qn],It);if(Mr===null){vn===null&&(vn=vr);break}h&&vn&&Mr.alternate===null&&y(gt,vn),pt=Z(Mr,pt,Qn),jr===null?An=Mr:jr.sibling=Mr,jr=Mr,vn=vr}if(Qn===yt.length)return _(gt,vn),Sr&&cu(gt,Qn),An;if(vn===null){for(;QnQn?(vr=vn,vn=null):vr=vn.sibling;var hh=St(gt,vn,Mr.value,It);if(hh===null){vn===null&&(vn=vr);break}h&&vn&&hh.alternate===null&&y(gt,vn),pt=Z(hh,pt,Qn),jr===null?An=hh:jr.sibling=hh,jr=hh,vn=vr}if(Mr.done)return _(gt,vn),Sr&&cu(gt,Qn),An;if(vn===null){for(;!Mr.done;Qn++,Mr=yt.next())Mr=Ut(gt,Mr.value,It),Mr!==null&&(pt=Z(Mr,pt,Qn),jr===null?An=Mr:jr.sibling=Mr,jr=Mr);return Sr&&cu(gt,Qn),An}for(vn=j(vn);!Mr.done;Qn++,Mr=yt.next())Mr=At(vn,gt,Qn,Mr.value,It),Mr!==null&&(h&&Mr.alternate!==null&&vn.delete(Mr.key===null?Qn:Mr.key),pt=Z(Mr,pt,Qn),jr===null?An=Mr:jr.sibling=Mr,jr=Mr);return h&&vn.forEach(function(Jde){return y(gt,Jde)}),Sr&&cu(gt,Qn),An}function Qr(gt,pt,yt,It){if(typeof yt=="object"&&yt!==null&&yt.type===v&&yt.key===null&&(yt=yt.props.children),typeof yt=="object"&&yt!==null){switch(yt.$$typeof){case f:e:{for(var An=yt.key;pt!==null;){if(pt.key===An){if(An=yt.type,An===v){if(pt.tag===7){_(gt,pt.sibling),It=G(pt,yt.props.children),It.return=gt,gt=It;break e}}else if(pt.elementType===An||typeof An=="object"&&An!==null&&An.$$typeof===F&&sf(An)===pt.type){_(gt,pt.sibling),It=G(pt,yt.props),iv(It,yt),It.return=gt,gt=It;break e}_(gt,pt);break}else y(gt,pt);pt=pt.sibling}yt.type===v?(It=ef(yt.props.children,gt.mode,It,yt.key),It.return=gt,gt=It):(It=t_(yt.type,yt.key,yt.props,null,gt.mode,It),iv(It,yt),It.return=gt,gt=It)}return Ne(gt);case x:e:{for(An=yt.key;pt!==null;){if(pt.key===An)if(pt.tag===4&&pt.stateNode.containerInfo===yt.containerInfo&&pt.stateNode.implementation===yt.implementation){_(gt,pt.sibling),It=G(pt,yt.children||[]),It.return=gt,gt=It;break e}else{_(gt,pt);break}else y(gt,pt);pt=pt.sibling}It=UA(yt,gt.mode,It),It.return=gt,gt=It}return Ne(gt);case F:return yt=sf(yt),Qr(gt,pt,yt,It)}if(ne(yt))return gn(gt,pt,yt,It);if(z(yt)){if(An=z(yt),typeof An!="function")throw Error(r(150));return yt=An.call(yt),Ln(gt,pt,yt,It)}if(typeof yt.then=="function")return Qr(gt,pt,l_(yt),It);if(yt.$$typeof===N)return Qr(gt,pt,a_(gt,yt),It);c_(gt,yt)}return typeof yt=="string"&&yt!==""||typeof yt=="number"||typeof yt=="bigint"?(yt=""+yt,pt!==null&&pt.tag===6?(_(gt,pt.sibling),It=G(pt,yt),It.return=gt,gt=It):(_(gt,pt),It=zA(yt,gt.mode,It),It.return=gt,gt=It),Ne(gt)):_(gt,pt)}return function(gt,pt,yt,It){try{av=0;var An=Qr(gt,pt,yt,It);return ub=null,An}catch(vn){if(vn===db||vn===s_)throw vn;var jr=Ko(29,vn,null,gt.mode);return jr.lanes=It,jr.return=gt,jr}}}var lf=nU(!0),rU=nU(!1),Ym=!1;function JA(h){h.updateQueue={baseState:h.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function ZA(h,y){h=h.updateQueue,y.updateQueue===h&&(y.updateQueue={baseState:h.baseState,firstBaseUpdate:h.firstBaseUpdate,lastBaseUpdate:h.lastBaseUpdate,shared:h.shared,callbacks:null})}function Qm(h){return{lane:h,tag:0,payload:null,callback:null,next:null}}function Jm(h,y,_){var j=h.updateQueue;if(j===null)return null;if(j=j.shared,(Lr&2)!==0){var G=j.pending;return G===null?y.next=y:(y.next=G.next,G.next=y),j.pending=y,y=e_(h),U5(h,null,_),y}return ZS(h,j,y,_),e_(h)}function sv(h,y,_){if(y=y.updateQueue,y!==null&&(y=y.shared,(_&4194048)!==0)){var j=y.lanes;j&=h.pendingLanes,_|=j,y.lanes=_,qt(h,_)}}function ej(h,y){var _=h.updateQueue,j=h.alternate;if(j!==null&&(j=j.updateQueue,_===j)){var G=null,Z=null;if(_=_.firstBaseUpdate,_!==null){do{var Ne={lane:_.lane,tag:_.tag,payload:_.payload,callback:null,next:null};Z===null?G=Z=Ne:Z=Z.next=Ne,_=_.next}while(_!==null);Z===null?G=Z=y:Z=Z.next=y}else G=Z=y;_={baseState:j.baseState,firstBaseUpdate:G,lastBaseUpdate:Z,shared:j.shared,callbacks:j.callbacks},h.updateQueue=_;return}h=_.lastBaseUpdate,h===null?_.firstBaseUpdate=y:h.next=y,_.lastBaseUpdate=y}var tj=!1;function ov(){if(tj){var h=cb;if(h!==null)throw h}}function lv(h,y,_,j){tj=!1;var G=h.updateQueue;Ym=!1;var Z=G.firstBaseUpdate,Ne=G.lastBaseUpdate,qe=G.shared.pending;if(qe!==null){G.shared.pending=null;var lt=qe,vt=lt.next;lt.next=null,Ne===null?Z=vt:Ne.next=vt,Ne=lt;var Rt=h.alternate;Rt!==null&&(Rt=Rt.updateQueue,qe=Rt.lastBaseUpdate,qe!==Ne&&(qe===null?Rt.firstBaseUpdate=vt:qe.next=vt,Rt.lastBaseUpdate=lt))}if(Z!==null){var Ut=G.baseState;Ne=0,Rt=vt=lt=null,qe=Z;do{var St=qe.lane&-536870913,At=St!==qe.lane;if(At?(yr&St)===St:(j&St)===St){St!==0&&St===lb&&(tj=!0),Rt!==null&&(Rt=Rt.next={lane:0,tag:qe.tag,payload:qe.payload,callback:null,next:null});e:{var gn=h,Ln=qe;St=y;var Qr=_;switch(Ln.tag){case 1:if(gn=Ln.payload,typeof gn=="function"){Ut=gn.call(Qr,Ut,St);break e}Ut=gn;break e;case 3:gn.flags=gn.flags&-65537|128;case 0:if(gn=Ln.payload,St=typeof gn=="function"?gn.call(Qr,Ut,St):gn,St==null)break e;Ut=m({},Ut,St);break e;case 2:Ym=!0}}St=qe.callback,St!==null&&(h.flags|=64,At&&(h.flags|=8192),At=G.callbacks,At===null?G.callbacks=[St]:At.push(St))}else At={lane:St,tag:qe.tag,payload:qe.payload,callback:qe.callback,next:null},Rt===null?(vt=Rt=At,lt=Ut):Rt=Rt.next=At,Ne|=St;if(qe=qe.next,qe===null){if(qe=G.shared.pending,qe===null)break;At=qe,qe=At.next,At.next=null,G.lastBaseUpdate=At,G.shared.pending=null}}while(!0);Rt===null&&(lt=Ut),G.baseState=lt,G.firstBaseUpdate=vt,G.lastBaseUpdate=Rt,Z===null&&(G.shared.lanes=0),rh|=Ne,h.lanes=Ne,h.memoizedState=Ut}}function aU(h,y){if(typeof h!="function")throw Error(r(191,h));h.call(y)}function iU(h,y){var _=h.callbacks;if(_!==null)for(h.callbacks=null,h=0;h<_.length;h++)aU(_[h],y)}var mb=K(null),d_=K(0);function sU(h,y){h=vu,me(d_,h),me(mb,y),vu=h|y.baseLanes}function nj(){me(d_,vu),me(mb,mb.current)}function rj(){vu=d_.current,ae(mb),ae(d_)}var Xo=K(null),Dl=null;function Zm(h){var y=h.alternate;me(ai,ai.current&1),me(Xo,h),Dl===null&&(y===null||mb.current!==null||y.memoizedState!==null)&&(Dl=h)}function aj(h){me(ai,ai.current),me(Xo,h),Dl===null&&(Dl=h)}function oU(h){h.tag===22?(me(ai,ai.current),me(Xo,h),Dl===null&&(Dl=h)):eh()}function eh(){me(ai,ai.current),me(Xo,Xo.current)}function Yo(h){ae(Xo),Dl===h&&(Dl=null),ae(ai)}var ai=K(0);function u_(h){for(var y=h;y!==null;){if(y.tag===13){var _=y.memoizedState;if(_!==null&&(_=_.dehydrated,_===null||dM(_)||uM(_)))return y}else if(y.tag===19&&(y.memoizedProps.revealOrder==="forwards"||y.memoizedProps.revealOrder==="backwards"||y.memoizedProps.revealOrder==="unstable_legacy-backwards"||y.memoizedProps.revealOrder==="together")){if((y.flags&128)!==0)return y}else if(y.child!==null){y.child.return=y,y=y.child;continue}if(y===h)break;for(;y.sibling===null;){if(y.return===null||y.return===h)return null;y=y.return}y.sibling.return=y.return,y=y.sibling}return null}var mu=0,Xn=null,Xr=null,mi=null,m_=!1,hb=!1,cf=!1,h_=0,cv=0,pb=null,Hce=0;function $a(){throw Error(r(321))}function ij(h,y){if(y===null)return!1;for(var _=0;_Z?Z:8;var Ne=re.T,qe={};re.T=qe,vj(h,!1,y,_);try{var lt=G(),vt=re.S;if(vt!==null&&vt(qe,lt),lt!==null&&typeof lt=="object"&&typeof lt.then=="function"){var Rt=Bce(lt,j);uv(h,y,Rt,Zo(h))}else uv(h,y,j,Zo(h))}catch(Ut){uv(h,y,{then:function(){},status:"rejected",reason:Ut},Zo())}finally{ee.p=Z,Ne!==null&&qe.types!==null&&(Ne.types=qe.types),re.T=Ne}}function Wce(){}function xj(h,y,_,j){if(h.tag!==5)throw Error(r(476));var G=OU(h).queue;LU(h,G,y,ue,_===null?Wce:function(){return IU(h),_(j)})}function OU(h){var y=h.memoizedState;if(y!==null)return y;y={memoizedState:ue,baseState:ue,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:hu,lastRenderedState:ue},next:null};var _={};return y.next={memoizedState:_,baseState:_,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:hu,lastRenderedState:_},next:null},h.memoizedState=y,h=h.alternate,h!==null&&(h.memoizedState=y),y}function IU(h){var y=OU(h);y.next===null&&(y=h.alternate.memoizedState),uv(h,y.next.queue,{},Zo())}function yj(){return ds(Tv)}function zU(){return ii().memoizedState}function UU(){return ii().memoizedState}function Kce(h){for(var y=h.return;y!==null;){switch(y.tag){case 24:case 3:var _=Zo();h=Qm(_);var j=Jm(y,h,_);j!==null&&(To(j,y,_),sv(j,y,_)),y={cache:KA()},h.payload=y;return}y=y.return}}function Xce(h,y,_){var j=Zo();_={lane:j,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null},y_(h)?HU(y,_):(_=OA(h,y,_,j),_!==null&&(To(_,h,j),qU(_,y,j)))}function BU(h,y,_){var j=Zo();uv(h,y,_,j)}function uv(h,y,_,j){var G={lane:j,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null};if(y_(h))HU(y,G);else{var Z=h.alternate;if(h.lanes===0&&(Z===null||Z.lanes===0)&&(Z=y.lastRenderedReducer,Z!==null))try{var Ne=y.lastRenderedState,qe=Z(Ne,_);if(G.hasEagerState=!0,G.eagerState=qe,_o(qe,Ne))return ZS(h,y,G,0),oa===null&&JS(),!1}catch{}if(_=OA(h,y,G,j),_!==null)return To(_,h,j),qU(_,y,j),!0}return!1}function vj(h,y,_,j){if(j={lane:2,revertLane:Jj(),gesture:null,action:j,hasEagerState:!1,eagerState:null,next:null},y_(h)){if(y)throw Error(r(479))}else y=OA(h,_,j,2),y!==null&&To(y,h,2)}function y_(h){var y=h.alternate;return h===Xn||y!==null&&y===Xn}function HU(h,y){hb=m_=!0;var _=h.pending;_===null?y.next=y:(y.next=_.next,_.next=y),h.pending=y}function qU(h,y,_){if((_&4194048)!==0){var j=y.lanes;j&=h.pendingLanes,_|=j,y.lanes=_,qt(h,_)}}var mv={readContext:ds,use:f_,useCallback:$a,useContext:$a,useEffect:$a,useImperativeHandle:$a,useLayoutEffect:$a,useInsertionEffect:$a,useMemo:$a,useReducer:$a,useRef:$a,useState:$a,useDebugValue:$a,useDeferredValue:$a,useTransition:$a,useSyncExternalStore:$a,useId:$a,useHostTransitionStatus:$a,useFormState:$a,useActionState:$a,useOptimistic:$a,useMemoCache:$a,useCacheRefresh:$a};mv.useEffectEvent=$a;var $U={readContext:ds,use:f_,useCallback:function(h,y){return Zs().memoizedState=[h,y===void 0?null:y],h},useContext:ds,useEffect:PU,useImperativeHandle:function(h,y,_){_=_!=null?_.concat([h]):null,b_(4194308,4,MU.bind(null,y,h),_)},useLayoutEffect:function(h,y){return b_(4194308,4,h,y)},useInsertionEffect:function(h,y){b_(4,2,h,y)},useMemo:function(h,y){var _=Zs();y=y===void 0?null:y;var j=h();if(cf){Me(!0);try{h()}finally{Me(!1)}}return _.memoizedState=[j,y],j},useReducer:function(h,y,_){var j=Zs();if(_!==void 0){var G=_(y);if(cf){Me(!0);try{_(y)}finally{Me(!1)}}}else G=y;return j.memoizedState=j.baseState=G,h={pending:null,lanes:0,dispatch:null,lastRenderedReducer:h,lastRenderedState:G},j.queue=h,h=h.dispatch=Xce.bind(null,Xn,h),[j.memoizedState,h]},useRef:function(h){var y=Zs();return h={current:h},y.memoizedState=h},useState:function(h){h=hj(h);var y=h.queue,_=BU.bind(null,Xn,y);return y.dispatch=_,[h.memoizedState,_]},useDebugValue:gj,useDeferredValue:function(h,y){var _=Zs();return bj(_,h,y)},useTransition:function(){var h=hj(!1);return h=LU.bind(null,Xn,h.queue,!0,!1),Zs().memoizedState=h,[!1,h]},useSyncExternalStore:function(h,y,_){var j=Xn,G=Zs();if(Sr){if(_===void 0)throw Error(r(407));_=_()}else{if(_=y(),oa===null)throw Error(r(349));(yr&127)!==0||uU(j,y,_)}G.memoizedState=_;var Z={value:_,getSnapshot:y};return G.queue=Z,PU(hU.bind(null,j,Z,h),[h]),j.flags|=2048,fb(9,{destroy:void 0},mU.bind(null,j,Z,_,y),null),_},useId:function(){var h=Zs(),y=oa.identifierPrefix;if(Sr){var _=cd,j=ld;_=(j&~(1<<32-Ie(j)-1)).toString(32)+_,y="_"+y+"R_"+_,_=h_++,0<_&&(y+="H"+_.toString(32)),y+="_"}else _=Hce++,y="_"+y+"r_"+_.toString(32)+"_";return h.memoizedState=y},useHostTransitionStatus:yj,useFormState:SU,useActionState:SU,useOptimistic:function(h){var y=Zs();y.memoizedState=y.baseState=h;var _={pending:null,lanes:0,dispatch:null,lastRenderedReducer:null,lastRenderedState:null};return y.queue=_,y=vj.bind(null,Xn,!0,_),_.dispatch=y,[h,y]},useMemoCache:dj,useCacheRefresh:function(){return Zs().memoizedState=Kce.bind(null,Xn)},useEffectEvent:function(h){var y=Zs(),_={impl:h};return y.memoizedState=_,function(){if((Lr&2)!==0)throw Error(r(440));return _.impl.apply(void 0,arguments)}}},wj={readContext:ds,use:f_,useCallback:DU,useContext:ds,useEffect:fj,useImperativeHandle:EU,useInsertionEffect:AU,useLayoutEffect:jU,useMemo:FU,useReducer:g_,useRef:CU,useState:function(){return g_(hu)},useDebugValue:gj,useDeferredValue:function(h,y){var _=ii();return RU(_,Xr.memoizedState,h,y)},useTransition:function(){var h=g_(hu)[0],y=ii().memoizedState;return[typeof h=="boolean"?h:dv(h),y]},useSyncExternalStore:dU,useId:zU,useHostTransitionStatus:yj,useFormState:_U,useActionState:_U,useOptimistic:function(h,y){var _=ii();return gU(_,Xr,h,y)},useMemoCache:dj,useCacheRefresh:UU};wj.useEffectEvent=TU;var VU={readContext:ds,use:f_,useCallback:DU,useContext:ds,useEffect:fj,useImperativeHandle:EU,useInsertionEffect:AU,useLayoutEffect:jU,useMemo:FU,useReducer:mj,useRef:CU,useState:function(){return mj(hu)},useDebugValue:gj,useDeferredValue:function(h,y){var _=ii();return Xr===null?bj(_,h,y):RU(_,Xr.memoizedState,h,y)},useTransition:function(){var h=mj(hu)[0],y=ii().memoizedState;return[typeof h=="boolean"?h:dv(h),y]},useSyncExternalStore:dU,useId:zU,useHostTransitionStatus:yj,useFormState:NU,useActionState:NU,useOptimistic:function(h,y){var _=ii();return Xr!==null?gU(_,Xr,h,y):(_.baseState=h,[h,_.queue.dispatch])},useMemoCache:dj,useCacheRefresh:UU};VU.useEffectEvent=TU;function Sj(h,y,_,j){y=h.memoizedState,_=_(j,y),_=_==null?y:m({},y,_),h.memoizedState=_,h.lanes===0&&(h.updateQueue.baseState=_)}var _j={enqueueSetState:function(h,y,_){h=h._reactInternals;var j=Zo(),G=Qm(j);G.payload=y,_!=null&&(G.callback=_),y=Jm(h,G,j),y!==null&&(To(y,h,j),sv(y,h,j))},enqueueReplaceState:function(h,y,_){h=h._reactInternals;var j=Zo(),G=Qm(j);G.tag=1,G.payload=y,_!=null&&(G.callback=_),y=Jm(h,G,j),y!==null&&(To(y,h,j),sv(y,h,j))},enqueueForceUpdate:function(h,y){h=h._reactInternals;var _=Zo(),j=Qm(_);j.tag=2,y!=null&&(j.callback=y),y=Jm(h,j,_),y!==null&&(To(y,h,_),sv(y,h,_))}};function GU(h,y,_,j,G,Z,Ne){return h=h.stateNode,typeof h.shouldComponentUpdate=="function"?h.shouldComponentUpdate(j,Z,Ne):y.prototype&&y.prototype.isPureReactComponent?!Vm(_,j)||!Vm(G,Z):!0}function WU(h,y,_,j){h=y.state,typeof y.componentWillReceiveProps=="function"&&y.componentWillReceiveProps(_,j),typeof y.UNSAFE_componentWillReceiveProps=="function"&&y.UNSAFE_componentWillReceiveProps(_,j),y.state!==h&&_j.enqueueReplaceState(y,y.state,null)}function df(h,y){var _=y;if("ref"in y){_={};for(var j in y)j!=="ref"&&(_[j]=y[j])}if(h=h.defaultProps){_===y&&(_=m({},_));for(var G in h)_[G]===void 0&&(_[G]=h[G])}return _}function KU(h){QS(h)}function XU(h){console.error(h)}function YU(h){QS(h)}function v_(h,y){try{var _=h.onUncaughtError;_(y.value,{componentStack:y.stack})}catch(j){setTimeout(function(){throw j})}}function QU(h,y,_){try{var j=h.onCaughtError;j(_.value,{componentStack:_.stack,errorBoundary:y.tag===1?y.stateNode:null})}catch(G){setTimeout(function(){throw G})}}function kj(h,y,_){return _=Qm(_),_.tag=3,_.payload={element:null},_.callback=function(){v_(h,y)},_}function JU(h){return h=Qm(h),h.tag=3,h}function ZU(h,y,_,j){var G=_.type.getDerivedStateFromError;if(typeof G=="function"){var Z=j.value;h.payload=function(){return G(Z)},h.callback=function(){QU(y,_,j)}}var Ne=_.stateNode;Ne!==null&&typeof Ne.componentDidCatch=="function"&&(h.callback=function(){QU(y,_,j),typeof G!="function"&&(ah===null?ah=new Set([this]):ah.add(this));var qe=j.stack;this.componentDidCatch(j.value,{componentStack:qe!==null?qe:""})})}function Yce(h,y,_,j,G){if(_.flags|=32768,j!==null&&typeof j=="object"&&typeof j.then=="function"){if(y=_.alternate,y!==null&&ob(y,_,G,!0),_=Xo.current,_!==null){switch(_.tag){case 31:case 13:return Dl===null?E_():_.alternate===null&&Va===0&&(Va=3),_.flags&=-257,_.flags|=65536,_.lanes=G,j===o_?_.flags|=16384:(y=_.updateQueue,y===null?_.updateQueue=new Set([j]):y.add(j),Xj(h,j,G)),!1;case 22:return _.flags|=65536,j===o_?_.flags|=16384:(y=_.updateQueue,y===null?(y={transitions:null,markerInstances:null,retryQueue:new Set([j])},_.updateQueue=y):(_=y.retryQueue,_===null?y.retryQueue=new Set([j]):_.add(j)),Xj(h,j,G)),!1}throw Error(r(435,_.tag))}return Xj(h,j,G),E_(),!1}if(Sr)return y=Xo.current,y!==null?((y.flags&65536)===0&&(y.flags|=256),y.flags|=65536,y.lanes=G,j!==qA&&(h=Error(r(422),{cause:j}),tv(Al(h,_)))):(j!==qA&&(y=Error(r(423),{cause:j}),tv(Al(y,_))),h=h.current.alternate,h.flags|=65536,G&=-G,h.lanes|=G,j=Al(j,_),G=kj(h.stateNode,j,G),ej(h,G),Va!==4&&(Va=2)),!1;var Z=Error(r(520),{cause:j});if(Z=Al(Z,_),vv===null?vv=[Z]:vv.push(Z),Va!==4&&(Va=2),y===null)return!0;j=Al(j,_),_=y;do{switch(_.tag){case 3:return _.flags|=65536,h=G&-G,_.lanes|=h,h=kj(_.stateNode,j,h),ej(_,h),!1;case 1:if(y=_.type,Z=_.stateNode,(_.flags&128)===0&&(typeof y.getDerivedStateFromError=="function"||Z!==null&&typeof Z.componentDidCatch=="function"&&(ah===null||!ah.has(Z))))return _.flags|=65536,G&=-G,_.lanes|=G,G=JU(G),ZU(G,h,_,j),ej(_,G),!1}_=_.return}while(_!==null);return!1}var Nj=Error(r(461)),hi=!1;function us(h,y,_,j){y.child=h===null?rU(y,null,_,j):lf(y,h.child,_,j)}function eB(h,y,_,j,G){_=_.render;var Z=y.ref;if("ref"in j){var Ne={};for(var qe in j)qe!=="ref"&&(Ne[qe]=j[qe])}else Ne=j;return rf(y),j=sj(h,y,_,Ne,Z,G),qe=oj(),h!==null&&!hi?(lj(h,y,G),pu(h,y,G)):(Sr&&qe&&BA(y),y.flags|=1,us(h,y,j,G),y.child)}function tB(h,y,_,j,G){if(h===null){var Z=_.type;return typeof Z=="function"&&!IA(Z)&&Z.defaultProps===void 0&&_.compare===null?(y.tag=15,y.type=Z,nB(h,y,Z,j,G)):(h=t_(_.type,null,j,y,y.mode,G),h.ref=y.ref,h.return=y,y.child=h)}if(Z=h.child,!Dj(h,G)){var Ne=Z.memoizedProps;if(_=_.compare,_=_!==null?_:Vm,_(Ne,j)&&h.ref===y.ref)return pu(h,y,G)}return y.flags|=1,h=lu(Z,j),h.ref=y.ref,h.return=y,y.child=h}function nB(h,y,_,j,G){if(h!==null){var Z=h.memoizedProps;if(Vm(Z,j)&&h.ref===y.ref)if(hi=!1,y.pendingProps=j=Z,Dj(h,G))(h.flags&131072)!==0&&(hi=!0);else return y.lanes=h.lanes,pu(h,y,G)}return Cj(h,y,_,j,G)}function rB(h,y,_,j){var G=j.children,Z=h!==null?h.memoizedState:null;if(h===null&&y.stateNode===null&&(y.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),j.mode==="hidden"){if((y.flags&128)!==0){if(Z=Z!==null?Z.baseLanes|_:_,h!==null){for(j=y.child=h.child,G=0;j!==null;)G=G|j.lanes|j.childLanes,j=j.sibling;j=G&~Z}else j=0,y.child=null;return aB(h,y,Z,_,j)}if((_&536870912)!==0)y.memoizedState={baseLanes:0,cachePool:null},h!==null&&i_(y,Z!==null?Z.cachePool:null),Z!==null?sU(y,Z):nj(),oU(y);else return j=y.lanes=536870912,aB(h,y,Z!==null?Z.baseLanes|_:_,_,j)}else Z!==null?(i_(y,Z.cachePool),sU(y,Z),eh(),y.memoizedState=null):(h!==null&&i_(y,null),nj(),eh());return us(h,y,G,_),y.child}function hv(h,y){return h!==null&&h.tag===22||y.stateNode!==null||(y.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),y.sibling}function aB(h,y,_,j,G){var Z=YA();return Z=Z===null?null:{parent:ui._currentValue,pool:Z},y.memoizedState={baseLanes:_,cachePool:Z},h!==null&&i_(y,null),nj(),oU(y),h!==null&&ob(h,y,j,!0),y.childLanes=G,null}function w_(h,y){return y=__({mode:y.mode,children:y.children},h.mode),y.ref=h.ref,h.child=y,y.return=h,y}function iB(h,y,_){return lf(y,h.child,null,_),h=w_(y,y.pendingProps),h.flags|=2,Yo(y),y.memoizedState=null,h}function Qce(h,y,_){var j=y.pendingProps,G=(y.flags&128)!==0;if(y.flags&=-129,h===null){if(Sr){if(j.mode==="hidden")return h=w_(y,j),y.lanes=536870912,hv(null,h);if(aj(y),(h=xa)?(h=b8(h,El),h=h!==null&&h.data==="&"?h:null,h!==null&&(y.memoizedState={dehydrated:h,treeContext:Gm!==null?{id:ld,overflow:cd}:null,retryLane:536870912,hydrationErrors:null},_=H5(h),_.return=y,y.child=_,cs=y,xa=null)):h=null,h===null)throw Km(y);return y.lanes=536870912,null}return w_(y,j)}var Z=h.memoizedState;if(Z!==null){var Ne=Z.dehydrated;if(aj(y),G)if(y.flags&256)y.flags&=-257,y=iB(h,y,_);else if(y.memoizedState!==null)y.child=h.child,y.flags|=128,y=null;else throw Error(r(558));else if(hi||ob(h,y,_,!1),G=(_&h.childLanes)!==0,hi||G){if(j=oa,j!==null&&(Ne=Vt(j,_),Ne!==0&&Ne!==Z.retryLane))throw Z.retryLane=Ne,Zp(h,Ne),To(j,h,Ne),Nj;E_(),y=iB(h,y,_)}else h=Z.treeContext,xa=Fl(Ne.nextSibling),cs=y,Sr=!0,Wm=null,El=!1,h!==null&&V5(y,h),y=w_(y,j),y.flags|=4096;return y}return h=lu(h.child,{mode:j.mode,children:j.children}),h.ref=y.ref,y.child=h,h.return=y,h}function S_(h,y){var _=y.ref;if(_===null)h!==null&&h.ref!==null&&(y.flags|=4194816);else{if(typeof _!="function"&&typeof _!="object")throw Error(r(284));(h===null||h.ref!==_)&&(y.flags|=4194816)}}function Cj(h,y,_,j,G){return rf(y),_=sj(h,y,_,j,void 0,G),j=oj(),h!==null&&!hi?(lj(h,y,G),pu(h,y,G)):(Sr&&j&&BA(y),y.flags|=1,us(h,y,_,G),y.child)}function sB(h,y,_,j,G,Z){return rf(y),y.updateQueue=null,_=cU(y,j,_,G),lU(h),j=oj(),h!==null&&!hi?(lj(h,y,Z),pu(h,y,Z)):(Sr&&j&&BA(y),y.flags|=1,us(h,y,_,Z),y.child)}function oB(h,y,_,j,G){if(rf(y),y.stateNode===null){var Z=rb,Ne=_.contextType;typeof Ne=="object"&&Ne!==null&&(Z=ds(Ne)),Z=new _(j,Z),y.memoizedState=Z.state!==null&&Z.state!==void 0?Z.state:null,Z.updater=_j,y.stateNode=Z,Z._reactInternals=y,Z=y.stateNode,Z.props=j,Z.state=y.memoizedState,Z.refs={},JA(y),Ne=_.contextType,Z.context=typeof Ne=="object"&&Ne!==null?ds(Ne):rb,Z.state=y.memoizedState,Ne=_.getDerivedStateFromProps,typeof Ne=="function"&&(Sj(y,_,Ne,j),Z.state=y.memoizedState),typeof _.getDerivedStateFromProps=="function"||typeof Z.getSnapshotBeforeUpdate=="function"||typeof Z.UNSAFE_componentWillMount!="function"&&typeof Z.componentWillMount!="function"||(Ne=Z.state,typeof Z.componentWillMount=="function"&&Z.componentWillMount(),typeof Z.UNSAFE_componentWillMount=="function"&&Z.UNSAFE_componentWillMount(),Ne!==Z.state&&_j.enqueueReplaceState(Z,Z.state,null),lv(y,j,Z,G),ov(),Z.state=y.memoizedState),typeof Z.componentDidMount=="function"&&(y.flags|=4194308),j=!0}else if(h===null){Z=y.stateNode;var qe=y.memoizedProps,lt=df(_,qe);Z.props=lt;var vt=Z.context,Rt=_.contextType;Ne=rb,typeof Rt=="object"&&Rt!==null&&(Ne=ds(Rt));var Ut=_.getDerivedStateFromProps;Rt=typeof Ut=="function"||typeof Z.getSnapshotBeforeUpdate=="function",qe=y.pendingProps!==qe,Rt||typeof Z.UNSAFE_componentWillReceiveProps!="function"&&typeof Z.componentWillReceiveProps!="function"||(qe||vt!==Ne)&&WU(y,Z,j,Ne),Ym=!1;var St=y.memoizedState;Z.state=St,lv(y,j,Z,G),ov(),vt=y.memoizedState,qe||St!==vt||Ym?(typeof Ut=="function"&&(Sj(y,_,Ut,j),vt=y.memoizedState),(lt=Ym||GU(y,_,lt,j,St,vt,Ne))?(Rt||typeof Z.UNSAFE_componentWillMount!="function"&&typeof Z.componentWillMount!="function"||(typeof Z.componentWillMount=="function"&&Z.componentWillMount(),typeof Z.UNSAFE_componentWillMount=="function"&&Z.UNSAFE_componentWillMount()),typeof Z.componentDidMount=="function"&&(y.flags|=4194308)):(typeof Z.componentDidMount=="function"&&(y.flags|=4194308),y.memoizedProps=j,y.memoizedState=vt),Z.props=j,Z.state=vt,Z.context=Ne,j=lt):(typeof Z.componentDidMount=="function"&&(y.flags|=4194308),j=!1)}else{Z=y.stateNode,ZA(h,y),Ne=y.memoizedProps,Rt=df(_,Ne),Z.props=Rt,Ut=y.pendingProps,St=Z.context,vt=_.contextType,lt=rb,typeof vt=="object"&&vt!==null&&(lt=ds(vt)),qe=_.getDerivedStateFromProps,(vt=typeof qe=="function"||typeof Z.getSnapshotBeforeUpdate=="function")||typeof Z.UNSAFE_componentWillReceiveProps!="function"&&typeof Z.componentWillReceiveProps!="function"||(Ne!==Ut||St!==lt)&&WU(y,Z,j,lt),Ym=!1,St=y.memoizedState,Z.state=St,lv(y,j,Z,G),ov();var At=y.memoizedState;Ne!==Ut||St!==At||Ym||h!==null&&h.dependencies!==null&&r_(h.dependencies)?(typeof qe=="function"&&(Sj(y,_,qe,j),At=y.memoizedState),(Rt=Ym||GU(y,_,Rt,j,St,At,lt)||h!==null&&h.dependencies!==null&&r_(h.dependencies))?(vt||typeof Z.UNSAFE_componentWillUpdate!="function"&&typeof Z.componentWillUpdate!="function"||(typeof Z.componentWillUpdate=="function"&&Z.componentWillUpdate(j,At,lt),typeof Z.UNSAFE_componentWillUpdate=="function"&&Z.UNSAFE_componentWillUpdate(j,At,lt)),typeof Z.componentDidUpdate=="function"&&(y.flags|=4),typeof Z.getSnapshotBeforeUpdate=="function"&&(y.flags|=1024)):(typeof Z.componentDidUpdate!="function"||Ne===h.memoizedProps&&St===h.memoizedState||(y.flags|=4),typeof Z.getSnapshotBeforeUpdate!="function"||Ne===h.memoizedProps&&St===h.memoizedState||(y.flags|=1024),y.memoizedProps=j,y.memoizedState=At),Z.props=j,Z.state=At,Z.context=lt,j=Rt):(typeof Z.componentDidUpdate!="function"||Ne===h.memoizedProps&&St===h.memoizedState||(y.flags|=4),typeof Z.getSnapshotBeforeUpdate!="function"||Ne===h.memoizedProps&&St===h.memoizedState||(y.flags|=1024),j=!1)}return Z=j,S_(h,y),j=(y.flags&128)!==0,Z||j?(Z=y.stateNode,_=j&&typeof _.getDerivedStateFromError!="function"?null:Z.render(),y.flags|=1,h!==null&&j?(y.child=lf(y,h.child,null,G),y.child=lf(y,null,_,G)):us(h,y,_,G),y.memoizedState=Z.state,h=y.child):h=pu(h,y,G),h}function lB(h,y,_,j){return tf(),y.flags|=256,us(h,y,_,j),y.child}var Pj={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function Tj(h){return{baseLanes:h,cachePool:Q5()}}function Aj(h,y,_){return h=h!==null?h.childLanes&~_:0,y&&(h|=Jo),h}function cB(h,y,_){var j=y.pendingProps,G=!1,Z=(y.flags&128)!==0,Ne;if((Ne=Z)||(Ne=h!==null&&h.memoizedState===null?!1:(ai.current&2)!==0),Ne&&(G=!0,y.flags&=-129),Ne=(y.flags&32)!==0,y.flags&=-33,h===null){if(Sr){if(G?Zm(y):eh(),(h=xa)?(h=b8(h,El),h=h!==null&&h.data!=="&"?h:null,h!==null&&(y.memoizedState={dehydrated:h,treeContext:Gm!==null?{id:ld,overflow:cd}:null,retryLane:536870912,hydrationErrors:null},_=H5(h),_.return=y,y.child=_,cs=y,xa=null)):h=null,h===null)throw Km(y);return uM(h)?y.lanes=32:y.lanes=536870912,null}var qe=j.children;return j=j.fallback,G?(eh(),G=y.mode,qe=__({mode:"hidden",children:qe},G),j=ef(j,G,_,null),qe.return=y,j.return=y,qe.sibling=j,y.child=qe,j=y.child,j.memoizedState=Tj(_),j.childLanes=Aj(h,Ne,_),y.memoizedState=Pj,hv(null,j)):(Zm(y),jj(y,qe))}var lt=h.memoizedState;if(lt!==null&&(qe=lt.dehydrated,qe!==null)){if(Z)y.flags&256?(Zm(y),y.flags&=-257,y=Mj(h,y,_)):y.memoizedState!==null?(eh(),y.child=h.child,y.flags|=128,y=null):(eh(),qe=j.fallback,G=y.mode,j=__({mode:"visible",children:j.children},G),qe=ef(qe,G,_,null),qe.flags|=2,j.return=y,qe.return=y,j.sibling=qe,y.child=j,lf(y,h.child,null,_),j=y.child,j.memoizedState=Tj(_),j.childLanes=Aj(h,Ne,_),y.memoizedState=Pj,y=hv(null,j));else if(Zm(y),uM(qe)){if(Ne=qe.nextSibling&&qe.nextSibling.dataset,Ne)var vt=Ne.dgst;Ne=vt,j=Error(r(419)),j.stack="",j.digest=Ne,tv({value:j,source:null,stack:null}),y=Mj(h,y,_)}else if(hi||ob(h,y,_,!1),Ne=(_&h.childLanes)!==0,hi||Ne){if(Ne=oa,Ne!==null&&(j=Vt(Ne,_),j!==0&&j!==lt.retryLane))throw lt.retryLane=j,Zp(h,j),To(Ne,h,j),Nj;dM(qe)||E_(),y=Mj(h,y,_)}else dM(qe)?(y.flags|=192,y.child=h.child,y=null):(h=lt.treeContext,xa=Fl(qe.nextSibling),cs=y,Sr=!0,Wm=null,El=!1,h!==null&&V5(y,h),y=jj(y,j.children),y.flags|=4096);return y}return G?(eh(),qe=j.fallback,G=y.mode,lt=h.child,vt=lt.sibling,j=lu(lt,{mode:"hidden",children:j.children}),j.subtreeFlags=lt.subtreeFlags&65011712,vt!==null?qe=lu(vt,qe):(qe=ef(qe,G,_,null),qe.flags|=2),qe.return=y,j.return=y,j.sibling=qe,y.child=j,hv(null,j),j=y.child,qe=h.child.memoizedState,qe===null?qe=Tj(_):(G=qe.cachePool,G!==null?(lt=ui._currentValue,G=G.parent!==lt?{parent:lt,pool:lt}:G):G=Q5(),qe={baseLanes:qe.baseLanes|_,cachePool:G}),j.memoizedState=qe,j.childLanes=Aj(h,Ne,_),y.memoizedState=Pj,hv(h.child,j)):(Zm(y),_=h.child,h=_.sibling,_=lu(_,{mode:"visible",children:j.children}),_.return=y,_.sibling=null,h!==null&&(Ne=y.deletions,Ne===null?(y.deletions=[h],y.flags|=16):Ne.push(h)),y.child=_,y.memoizedState=null,_)}function jj(h,y){return y=__({mode:"visible",children:y},h.mode),y.return=h,h.child=y}function __(h,y){return h=Ko(22,h,null,y),h.lanes=0,h}function Mj(h,y,_){return lf(y,h.child,null,_),h=jj(y,y.pendingProps.children),h.flags|=2,y.memoizedState=null,h}function dB(h,y,_){h.lanes|=y;var j=h.alternate;j!==null&&(j.lanes|=y),GA(h.return,y,_)}function Ej(h,y,_,j,G,Z){var Ne=h.memoizedState;Ne===null?h.memoizedState={isBackwards:y,rendering:null,renderingStartTime:0,last:j,tail:_,tailMode:G,treeForkCount:Z}:(Ne.isBackwards=y,Ne.rendering=null,Ne.renderingStartTime=0,Ne.last=j,Ne.tail=_,Ne.tailMode=G,Ne.treeForkCount=Z)}function uB(h,y,_){var j=y.pendingProps,G=j.revealOrder,Z=j.tail;j=j.children;var Ne=ai.current,qe=(Ne&2)!==0;if(qe?(Ne=Ne&1|2,y.flags|=128):Ne&=1,me(ai,Ne),us(h,y,j,_),j=Sr?ev:0,!qe&&h!==null&&(h.flags&128)!==0)e:for(h=y.child;h!==null;){if(h.tag===13)h.memoizedState!==null&&dB(h,_,y);else if(h.tag===19)dB(h,_,y);else if(h.child!==null){h.child.return=h,h=h.child;continue}if(h===y)break e;for(;h.sibling===null;){if(h.return===null||h.return===y)break e;h=h.return}h.sibling.return=h.return,h=h.sibling}switch(G){case"forwards":for(_=y.child,G=null;_!==null;)h=_.alternate,h!==null&&u_(h)===null&&(G=_),_=_.sibling;_=G,_===null?(G=y.child,y.child=null):(G=_.sibling,_.sibling=null),Ej(y,!1,G,_,Z,j);break;case"backwards":case"unstable_legacy-backwards":for(_=null,G=y.child,y.child=null;G!==null;){if(h=G.alternate,h!==null&&u_(h)===null){y.child=G;break}h=G.sibling,G.sibling=_,_=G,G=h}Ej(y,!0,_,null,Z,j);break;case"together":Ej(y,!1,null,null,void 0,j);break;default:y.memoizedState=null}return y.child}function pu(h,y,_){if(h!==null&&(y.dependencies=h.dependencies),rh|=y.lanes,(_&y.childLanes)===0)if(h!==null){if(ob(h,y,_,!1),(_&y.childLanes)===0)return null}else return null;if(h!==null&&y.child!==h.child)throw Error(r(153));if(y.child!==null){for(h=y.child,_=lu(h,h.pendingProps),y.child=_,_.return=y;h.sibling!==null;)h=h.sibling,_=_.sibling=lu(h,h.pendingProps),_.return=y;_.sibling=null}return y.child}function Dj(h,y){return(h.lanes&y)!==0?!0:(h=h.dependencies,!!(h!==null&&r_(h)))}function Jce(h,y,_){switch(y.tag){case 3:D(y,y.stateNode.containerInfo),Xm(y,ui,h.memoizedState.cache),tf();break;case 27:case 5:B(y);break;case 4:D(y,y.stateNode.containerInfo);break;case 10:Xm(y,y.type,y.memoizedProps.value);break;case 31:if(y.memoizedState!==null)return y.flags|=128,aj(y),null;break;case 13:var j=y.memoizedState;if(j!==null)return j.dehydrated!==null?(Zm(y),y.flags|=128,null):(_&y.child.childLanes)!==0?cB(h,y,_):(Zm(y),h=pu(h,y,_),h!==null?h.sibling:null);Zm(y);break;case 19:var G=(h.flags&128)!==0;if(j=(_&y.childLanes)!==0,j||(ob(h,y,_,!1),j=(_&y.childLanes)!==0),G){if(j)return uB(h,y,_);y.flags|=128}if(G=y.memoizedState,G!==null&&(G.rendering=null,G.tail=null,G.lastEffect=null),me(ai,ai.current),j)break;return null;case 22:return y.lanes=0,rB(h,y,_,y.pendingProps);case 24:Xm(y,ui,h.memoizedState.cache)}return pu(h,y,_)}function mB(h,y,_){if(h!==null)if(h.memoizedProps!==y.pendingProps)hi=!0;else{if(!Dj(h,_)&&(y.flags&128)===0)return hi=!1,Jce(h,y,_);hi=(h.flags&131072)!==0}else hi=!1,Sr&&(y.flags&1048576)!==0&&$5(y,ev,y.index);switch(y.lanes=0,y.tag){case 16:e:{var j=y.pendingProps;if(h=sf(y.elementType),y.type=h,typeof h=="function")IA(h)?(j=df(h,j),y.tag=1,y=oB(null,y,h,j,_)):(y.tag=0,y=Cj(null,y,h,j,_));else{if(h!=null){var G=h.$$typeof;if(G===P){y.tag=11,y=eB(null,y,h,j,_);break e}else if(G===T){y.tag=14,y=tB(null,y,h,j,_);break e}}throw y=L(h)||h,Error(r(306,y,""))}}return y;case 0:return Cj(h,y,y.type,y.pendingProps,_);case 1:return j=y.type,G=df(j,y.pendingProps),oB(h,y,j,G,_);case 3:e:{if(D(y,y.stateNode.containerInfo),h===null)throw Error(r(387));j=y.pendingProps;var Z=y.memoizedState;G=Z.element,ZA(h,y),lv(y,j,null,_);var Ne=y.memoizedState;if(j=Ne.cache,Xm(y,ui,j),j!==Z.cache&&WA(y,[ui],_,!0),ov(),j=Ne.element,Z.isDehydrated)if(Z={element:j,isDehydrated:!1,cache:Ne.cache},y.updateQueue.baseState=Z,y.memoizedState=Z,y.flags&256){y=lB(h,y,j,_);break e}else if(j!==G){G=Al(Error(r(424)),y),tv(G),y=lB(h,y,j,_);break e}else for(h=y.stateNode.containerInfo,h.nodeType===9?h=h.body:h=h.nodeName==="HTML"?h.ownerDocument.body:h,xa=Fl(h.firstChild),cs=y,Sr=!0,Wm=null,El=!0,_=rU(y,null,j,_),y.child=_;_;)_.flags=_.flags&-3|4096,_=_.sibling;else{if(tf(),j===G){y=pu(h,y,_);break e}us(h,y,j,_)}y=y.child}return y;case 26:return S_(h,y),h===null?(_=_8(y.type,null,y.pendingProps,null))?y.memoizedState=_:Sr||(_=y.type,h=y.pendingProps,j=z_(H.current).createElement(_),j[jt]=y,j[Jt]=h,ms(j,_,h),nt(j),y.stateNode=j):y.memoizedState=_8(y.type,h.memoizedProps,y.pendingProps,h.memoizedState),null;case 27:return B(y),h===null&&Sr&&(j=y.stateNode=v8(y.type,y.pendingProps,H.current),cs=y,El=!0,G=xa,lh(y.type)?(mM=G,xa=Fl(j.firstChild)):xa=G),us(h,y,y.pendingProps.children,_),S_(h,y),h===null&&(y.flags|=4194304),y.child;case 5:return h===null&&Sr&&((G=j=xa)&&(j=Tde(j,y.type,y.pendingProps,El),j!==null?(y.stateNode=j,cs=y,xa=Fl(j.firstChild),El=!1,G=!0):G=!1),G||Km(y)),B(y),G=y.type,Z=y.pendingProps,Ne=h!==null?h.memoizedProps:null,j=Z.children,oM(G,Z)?j=null:Ne!==null&&oM(G,Ne)&&(y.flags|=32),y.memoizedState!==null&&(G=sj(h,y,qce,null,null,_),Tv._currentValue=G),S_(h,y),us(h,y,j,_),y.child;case 6:return h===null&&Sr&&((h=_=xa)&&(_=Ade(_,y.pendingProps,El),_!==null?(y.stateNode=_,cs=y,xa=null,h=!0):h=!1),h||Km(y)),null;case 13:return cB(h,y,_);case 4:return D(y,y.stateNode.containerInfo),j=y.pendingProps,h===null?y.child=lf(y,null,j,_):us(h,y,j,_),y.child;case 11:return eB(h,y,y.type,y.pendingProps,_);case 7:return us(h,y,y.pendingProps,_),y.child;case 8:return us(h,y,y.pendingProps.children,_),y.child;case 12:return us(h,y,y.pendingProps.children,_),y.child;case 10:return j=y.pendingProps,Xm(y,y.type,j.value),us(h,y,j.children,_),y.child;case 9:return G=y.type._context,j=y.pendingProps.children,rf(y),G=ds(G),j=j(G),y.flags|=1,us(h,y,j,_),y.child;case 14:return tB(h,y,y.type,y.pendingProps,_);case 15:return nB(h,y,y.type,y.pendingProps,_);case 19:return uB(h,y,_);case 31:return Qce(h,y,_);case 22:return rB(h,y,_,y.pendingProps);case 24:return rf(y),j=ds(ui),h===null?(G=YA(),G===null&&(G=oa,Z=KA(),G.pooledCache=Z,Z.refCount++,Z!==null&&(G.pooledCacheLanes|=_),G=Z),y.memoizedState={parent:j,cache:G},JA(y),Xm(y,ui,G)):((h.lanes&_)!==0&&(ZA(h,y),lv(y,null,null,_),ov()),G=h.memoizedState,Z=y.memoizedState,G.parent!==j?(G={parent:j,cache:j},y.memoizedState=G,y.lanes===0&&(y.memoizedState=y.updateQueue.baseState=G),Xm(y,ui,j)):(j=Z.cache,Xm(y,ui,j),j!==G.cache&&WA(y,[ui],_,!0))),us(h,y,y.pendingProps.children,_),y.child;case 29:throw y.pendingProps}throw Error(r(156,y.tag))}function fu(h){h.flags|=4}function Fj(h,y,_,j,G){if((y=(h.mode&32)!==0)&&(y=!1),y){if(h.flags|=16777216,(G&335544128)===G)if(h.stateNode.complete)h.flags|=8192;else if(zB())h.flags|=8192;else throw of=o_,QA}else h.flags&=-16777217}function hB(h,y){if(y.type!=="stylesheet"||(y.state.loading&4)!==0)h.flags&=-16777217;else if(h.flags|=16777216,!T8(y))if(zB())h.flags|=8192;else throw of=o_,QA}function k_(h,y){y!==null&&(h.flags|=4),h.flags&16384&&(y=h.tag!==22?st():536870912,h.lanes|=y,yb|=y)}function pv(h,y){if(!Sr)switch(h.tailMode){case"hidden":y=h.tail;for(var _=null;y!==null;)y.alternate!==null&&(_=y),y=y.sibling;_===null?h.tail=null:_.sibling=null;break;case"collapsed":_=h.tail;for(var j=null;_!==null;)_.alternate!==null&&(j=_),_=_.sibling;j===null?y||h.tail===null?h.tail=null:h.tail.sibling=null:j.sibling=null}}function ya(h){var y=h.alternate!==null&&h.alternate.child===h.child,_=0,j=0;if(y)for(var G=h.child;G!==null;)_|=G.lanes|G.childLanes,j|=G.subtreeFlags&65011712,j|=G.flags&65011712,G.return=h,G=G.sibling;else for(G=h.child;G!==null;)_|=G.lanes|G.childLanes,j|=G.subtreeFlags,j|=G.flags,G.return=h,G=G.sibling;return h.subtreeFlags|=j,h.childLanes=_,y}function Zce(h,y,_){var j=y.pendingProps;switch(HA(y),y.tag){case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return ya(y),null;case 1:return ya(y),null;case 3:return _=y.stateNode,j=null,h!==null&&(j=h.memoizedState.cache),y.memoizedState.cache!==j&&(y.flags|=2048),uu(ui),E(),_.pendingContext&&(_.context=_.pendingContext,_.pendingContext=null),(h===null||h.child===null)&&(sb(y)?fu(y):h===null||h.memoizedState.isDehydrated&&(y.flags&256)===0||(y.flags|=1024,$A())),ya(y),null;case 26:var G=y.type,Z=y.memoizedState;return h===null?(fu(y),Z!==null?(ya(y),hB(y,Z)):(ya(y),Fj(y,G,null,j,_))):Z?Z!==h.memoizedState?(fu(y),ya(y),hB(y,Z)):(ya(y),y.flags&=-16777217):(h=h.memoizedProps,h!==j&&fu(y),ya(y),Fj(y,G,h,j,_)),null;case 27:if(Y(y),_=H.current,G=y.type,h!==null&&y.stateNode!=null)h.memoizedProps!==j&&fu(y);else{if(!j){if(y.stateNode===null)throw Error(r(166));return ya(y),null}h=xe.current,sb(y)?G5(y):(h=v8(G,j,_),y.stateNode=h,fu(y))}return ya(y),null;case 5:if(Y(y),G=y.type,h!==null&&y.stateNode!=null)h.memoizedProps!==j&&fu(y);else{if(!j){if(y.stateNode===null)throw Error(r(166));return ya(y),null}if(Z=xe.current,sb(y))G5(y);else{var Ne=z_(H.current);switch(Z){case 1:Z=Ne.createElementNS("http://www.w3.org/2000/svg",G);break;case 2:Z=Ne.createElementNS("http://www.w3.org/1998/Math/MathML",G);break;default:switch(G){case"svg":Z=Ne.createElementNS("http://www.w3.org/2000/svg",G);break;case"math":Z=Ne.createElementNS("http://www.w3.org/1998/Math/MathML",G);break;case"script":Z=Ne.createElement("div"),Z.innerHTML=" - + +