From 171848a0fc34c8bac7c01c8a29e5ddc77dd84f2a Mon Sep 17 00:00:00 2001 From: maziggy Date: Tue, 2 Jun 2026 12:42:16 +0200 Subject: [PATCH] fix(slicer-presets): #1581 SliceModal refresh + invalidate on local-profile delete/import Two-part fix for the reporter's "removed profiles still show on the slice menu" symptom. Local half (real bug). LocalProfilesView's import and delete mutations invalidated ['localPresets'] (the management view's own query) but not ['slicerPresets'] (the SliceModal's unified preset query, staleTime 60s). A freshly-deleted preset kept rendering in the slice dropdown until that staleTime elapsed plus a refocus/remount. Both mutations now also call queryClient.invalidateQueries({queryKey: ['slicerPresets']}). Cloud half (opt-in cache bypass). _fetch_cloud_presets keeps a 5-minute per-(user, token) in-process cache (slicer_presets.py:69, balances "users see freshly-saved presets quickly" against "busy install doesn't hit Bambu Cloud once per modal open"). Users delete cloud presets in Bambu Studio / Bambu Handy, not in Bambuddy, so there's no event hook to invalidate on. Rather than shorten the TTL globally, the listing endpoint gains an opt-in ?refresh=true query param that bypasses both the cloud cache AND the 1-hour bundled-preset cache for that one call; the fresh result is still written back so subsequent normal callers keep hitting the cache. New SliceModal "Refresh" button. Lives in the preset section header next to the cloud-status banner. Calls getSlicerPresets({refresh: true}) and writes the fresh slots into the ['slicerPresets'] cache via queryClient.setQueryData so the spinner stops immediately rather than triggering a second refetch. RefreshCw icon spins while in-flight; disabled during slice enqueue to prevent double-fire. --- CHANGELOG.md | 2 + backend/app/api/routes/slicer_presets.py | 42 ++- .../tests/unit/test_no_unsafe_path_joins.py | 105 +++++++- backend/tests/unit/test_slicer_presets.py | 89 +++++++ .../components/LocalProfilesView.test.tsx | 68 ++++- frontend/src/api/client.ts | 9 +- frontend/src/components/LocalProfilesView.tsx | 10 + frontend/src/components/SliceModal.tsx | 48 +++- frontend/src/i18n/locales/de.ts | 2 + frontend/src/i18n/locales/en.ts | 2 + frontend/src/i18n/locales/es.ts | 2 + frontend/src/i18n/locales/fr.ts | 2 + frontend/src/i18n/locales/it.ts | 2 + frontend/src/i18n/locales/ja.ts | 2 + frontend/src/i18n/locales/pt-BR.ts | 2 + frontend/src/i18n/locales/zh-CN.ts | 2 + frontend/src/i18n/locales/zh-TW.ts | 2 + .../{index-BeiuHSbR.js => index-DqHz1llA.js} | 244 +++++++++--------- static/index.html | 2 +- 19 files changed, 495 insertions(+), 142 deletions(-) rename static/assets/{index-BeiuHSbR.js => index-DqHz1llA.js} (83%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ebcf6224..4eb8c3fa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,8 @@ All notable changes to Bambuddy will be documented in this file. ### Security - **Path-traversal hardening across the upload / import / file-write surface (routes + services); fifth CI backstop ships alongside** — A private path-traversal report against `POST /api/v1/projects/import/file` traced two attacker-controlled strings being joined to `library_dir` with no resolve + containment check: (a) `linked_folders[*].name` from the request's `project.json` ("Vector A" — an absolute path in this field collapsed `library_dir / "/anywhere"` to `Path("/anywhere")` because pathlib discards the left side when the right is absolute, letting the next `write_bytes` land anywhere the backend could write), and (b) per-entry `zf.namelist()` paths from the ZIP itself ("Vector B" — ZIP filenames carry `..` segments by spec and the join `library_dir / folder_name / relative_path` had no per-component check). Concrete escalation: drop a `.pth` file into the venv's `site-packages` directory for code execution on next service restart; overwrite the JWT signing-secret file to forge an admin token; overwrite `~/.ssh/authorized_keys` or `~/.bashrc` on native installs. **Fix is structural, not just patch the diff** (per [[feedback_dont_dismiss_preexisting]]). New `backend/app/utils/safe_path.py::safe_join_under(parent, *parts)` helper joins under a trusted parent, resolves both sides, asserts `is_relative_to(parent.resolve())`, and rejects up-front empty / null-byte / absolute path components. Wired into `import_project_file` at both vectors. **Adjacent fix from the routes audit**: `GET /api/v1/archives/{id}/photos/{filename}` had NO validation on `filename` and FileResponse-served arbitrary paths — the existing DELETE endpoint at least had a membership check against `archive.photos` (which is UUID-generated on upload), but GET shared neither the check nor any traversal guard. Both GET and DELETE now route through `safe_join_under` for defence-in-depth on top of the membership check. **Second adjacent fix from the services audit**: `ArchiveService.attach_timelapse(archive_id, data, filename)` in `backend/app/services/archive.py:1456` wrote `archive_dir / filename` where `filename` ultimately comes from either a printer's FTP listing (compromised-printer threat model — the printer is part of the trust surface) or the `?filename=...` query param on `POST /api/v1/archives/{id}/timelapse/select`. A malicious printer that returns a directory listing entry with `..` segments could write the timelapse bytes outside the archive directory; the `f.get("name") == filename` gate in the route did not prevent it because the gate is satisfied by whatever the printer claims is on disk. `attach_timelapse` now routes through `safe_join_under(..., http=False)` and returns `False` (logging the rejection) when the join would escape — matching the existing not-found contract of the function rather than raising 400 from inside a background task. **Audit sweep methodology**: AST-walked every Python file under `backend/app/api/routes/` AND `backend/app/services/` for `Path / Name` shapes (the exact shape that produced the original report). 25 additional route-layer sites and 8 additional service-layer sites confirmed safe case-by-case (UUID-generated filenames written by Bambuddy itself, `_safe_filename(...)` / `Path(arg).name` basename-stripped inputs, `os.walk`-discovered names, denylist + format-validated backup names, hardcoded constants iterated through a tuple, DB-stored paths whose write origin already goes through a resolved-and-containment-checked helper). Each safe site got a `# SEC-PATH-OK: ` marker so future audits can trust the inline guard at a glance. Six pre-existing safe-with-marker sites (`library.py` external upload, `archives.py` timelapse output, `projects.py` attachment download/delete, `settings.py` backup extractall) carry the same marker shape. **Fifth CI backstop** `test_route_path_arithmetic_is_safe_joined_or_marked` (`backend/tests/unit/test_no_unsafe_path_joins.py`) AST-walks every Python file in `backend/app/api/routes/` AND `backend/app/services/` and fails the build on any ` / ` join that doesn't either route through `safe_join_under` or carry the marker on the join line. Joins matching the higher-structure shapes (Attribute access, Subscript, f-string, `str(...)` call) are categorically different and out of scope — those are caught by the broader audit sweep, not the regression backstop. The services layer is in scope because it receives values from the routes verbatim AND from external sources Bambuddy has no control over (the printer FTP-listing case above). **Tests**: 17 unit tests for `safe_join_under` covering every escape vector (absolute path, Windows abs path, `..` segments, embedded `..`, null byte, empty string, no parts, non-str, plus legitimate nested-path round-trip); 4 integration tests against `POST /api/v1/projects/import/file` exercising the full FastAPI stack with the verbatim shape from the report (absolute path in `folder_name` → 400 + filesystem assertion that the target file doesn't exist; `..` in `folder_name` → 400; `..` in `relative_path` → 400; legitimate nested ZIP still imports cleanly to guard against the fix being over-strict); 3 unit tests against `ArchiveService.attach_timelapse` exercising the compromised-printer threat model (filename with `..` segments → returns False + no file at the escape target; absolute filename → returns False + no file at `/tmp`; legitimate `timelapse_YYYY-MM-DD_HH-MM-SS.mp4` → returns True + file lands inside archive_dir, guarding against the fix being over-strict). **SECURITY.md** gains a fifth rule + a fifth row in the CI-test mapping table; the rule explicitly names the printer FTP-listing case as in-scope to set the expectation for future services-layer audits. Full 5500+ test backend suite green; ruff clean. ### Fixed +- **Path-traversal CI backstop now recognises markers on the closing-paren line (project-wide convention)** — `test_no_unsafe_path_joins.py::test_route_path_arithmetic_is_safe_joined_or_marked` AST-walks every Path-arithmetic site in `api/routes/` + `services/` and demands either `safe_join_under(...)` or a `# SEC-PATH-OK: ` marker. The marker-detection helper only scanned the BinOp's own line range (`lineno..end_lineno`), but the project's convention puts the marker on the line of the wrapping closing paren — one past `end_lineno`. The backstop flagged 30 already-marked, already-safe sites as findings, masking the fact that the post-GHSA marker work is complete. The helper now peeks one line past `end_lineno` IF that line begins with a continuation token (`)`, `]`, `}`, `,`), capturing exactly this convention without giving a free pass to a marker on a wholly unrelated next statement. 5 new tests in `TestMarkerDetection` pin the contract: marker on the BinOp line recognised; marker on the closing-paren line recognised; an unrelated marker on a later statement does NOT silence; a marker on a non-continuation line right after the BinOp does NOT silence; no marker anywhere is still flagged. Integration test now passes against the existing tree — 30 findings → 0 — with no changes to any guard / sanitisation in routes or services. +- **Deleted local profiles no longer linger in the SliceModal preset dropdown; new manual "Refresh" button surfaces cloud-side deletions without waiting for the 5-minute cache (#1581, reported by @lloydjohnson)** — Reporter saw deleted local AND cloud profiles still appearing in the slice menu after removing them. Two distinct causes wired together. **Local half (real bug)**: `LocalProfilesView`'s import and delete mutations invalidated `['localPresets']` (the Local Profiles management view's own query) but not `['slicerPresets']` — the SliceModal reads from the unified `/slicer/presets` endpoint via a separate React Query key (`SliceModal.tsx:425`, `staleTime: 60_000`), so a freshly-deleted preset kept rendering in the dropdown until the modal's 60 s staleTime elapsed plus a refocus / remount. The backend was correct end-to-end (`delete_local_preset` removes the DB row, `get_db()` auto-commits, `_fetch_local_presets` reads fresh from DB with no backend cache). Both mutations now also invalidate `['slicerPresets']` so the next modal open shows the current set. **Cloud half (by-design backend cache + new opt-in bypass)**: `_fetch_cloud_presets` keeps a 5-minute per-(user, token) in-process cache balancing "users see their freshly-saved presets quickly" against "a busy install doesn't hit Bambu Cloud once per modal open" (`slicer_presets.py:69`). The user deletes cloud presets in Bambu Studio / Bambu Handy, not in Bambuddy, so there's no event hook to invalidate on — the cache only refreshes when the TTL expires. Rather than shorten the TTL (which would effectively rate-limit the cloud for every user), the listing endpoint gains an opt-in `?refresh=true` query param that bypasses BOTH the cloud cache and the 1-hour bundled-preset cache for that one call; the fresh result is still written back so subsequent normal callers still hit cached responses. **New SliceModal "Refresh" button**: lives in the preset section header next to the cloud-status banner, calls `getSlicerPresets({refresh: true})` and writes the fresh slots into the `['slicerPresets']` cache via `queryClient.setQueryData` (so the spinner disappears immediately rather than triggering a second refetch). Spins the `RefreshCw` icon while in-flight; disabled during a slice enqueue so users can't fire it twice. **i18n**: real translations for `slice.refreshPresets` + `slice.refreshPresetsTitle` (action label + tooltip) across all 9 locales per the [[feedback_translate_dont_fallback]] HARD RULE; parity script green at 5007 leaves × 9 locales. **Tests**: 2 new backend in `test_slicer_presets.py` (`refresh=True` re-hits Bambu Cloud even with a warm cache + still writes the fresh result back for the next normal call; same shape for `_fetch_bundled_presets`); 1 new frontend in `LocalProfilesView.test.tsx` asserts the delete flow invalidates `['slicerPresets']` in addition to `['localPresets']` via a spied QueryClient. Full backend suite + frontend vitest + ruff + eslint + i18n parity green. - **STL thumbnail noise on first generation: matplotlib cache + font_manager scan (reported by @maziggy)** — On first STL upload, three matplotlib-internal log lines surfaced: `WARNING [matplotlib] /opt/claude/.config/matplotlib is not a writable directory` (Bambuddy's `$HOME` isn't writable for the default config path so matplotlib fell back to `/tmp/matplotlib-XXXXXX`), `INFO [matplotlib.font_manager] Failed to extract font properties from NotoColorEmoji.ttf` (matplotlib doesn't support the COLR/COLR1 emoji format; this is per-font), and `INFO [matplotlib.font_manager] generated new fontManager` (the cache was rebuilt). Because the fallback was `/tmp`, every host reboot lost the cache and the font scan ran again. **Fix is in `stl_thumbnail.py` before the matplotlib import**: (a) `_configure_matplotlib_cache()` sets `MPLCONFIGDIR` to `settings.base_dir / .cache / matplotlib` (mkdir'd if missing) so the cache persists across container restarts and the writable-dir warning never fires; respects an externally-set value so operators who chose their own path aren't overridden; best-effort with a debug fallback if settings can't be imported or the mkdir fails. (b) `logging.getLogger("matplotlib.font_manager").setLevel(WARNING)` at module import demotes the per-font INFO scan so the first cold start (before the cache is populated) doesn't surface a multi-line matplotlib preamble. **Tests**: 3 new in `test_stl_thumbnail.py` — the font_manager logger is at WARNING after module import; `_configure_matplotlib_cache` creates the directory under `base_dir` and sets `MPLCONFIGDIR` to point at it; an externally-set `MPLCONFIGDIR` is preserved verbatim. - **Bulk-upload ZIPs of stub / empty STL files no longer spam the log with thousands of warnings (reported by @maziggy)** — Uploading a ZIP containing many minimal STL stubs (e.g. the 24-byte `solid test\nendsolid test` shape) emitted one `WARNING [backend.app.services.stl_thumbnail] Failed to load STL or empty mesh: ` per file. The warnings were technically correct — `trimesh.load(...)` returned a valid Mesh with zero vertices, the safeguard at `stl_thumbnail.py:54` matched, and the function returned None so the library entry got created without a thumbnail — but the volume turned a successful ZIP upload into a journal full of WARNING lines. **Two-step fix**: (1) the per-file message at `stl_thumbnail.py:55` demoted from `logger.warning` to `logger.debug`; this is a per-file content observation, not an actionable error, and the caller already handles None correctly. The branch now catches only the rare "large enough but trimesh still can't parse it" case, still visible in debug logs without spamming production. (2) New module constant `MIN_USABLE_STL_BYTES = 200` (binary STL with one triangle = 80B header + 4B count + 50B triangle = 134B; ASCII STL with one triangle ≈ 150B; 200 is a safe floor below any real STL). Three thumbnail call sites in `library.py` (extract_zip_file ZIP entry path, single-file upload, `_backfill_external_stl_thumbnails`) pre-skip files below this size BEFORE calling `generate_stl_thumbnail`, so stubs / placeholders / corrupted files never enter the trimesh pipeline at all. **What this does NOT change**: behaviour is identical for any real STL — generation still runs, MAX_VERTICES still triggers simplification at 100k vertices for the 256×256 thumbnail render, large files still get thumbnails. **Tests**: 2 new in `test_stl_thumbnail.py` — one verifies `MIN_USABLE_STL_BYTES` sits above the smallest binary (134B), the smallest ASCII (150B), and the reporter's 24-byte stub case; the other writes the verbatim 24-byte stub from the bug report, calls `generate_stl_thumbnail`, and asserts no `WARNING`-level "empty mesh" record appears in `caplog`. Full backend suite green; ruff clean. - **Bambu Cloud sign-in failures caused by an upstream Cloudflare challenge now surface an actionable message instead of "Invalid response from Bambu Cloud" (#1575, reported by @cliveflint)** — Reporter hit "Invalid response from bambulabs when trying to sign in with authenticator pass code" on a Pi (UK network). Log showed three back-to-back `POST /api/sign-in/tfa` calls all returning Cloudflare's "Just a moment..." HTML interstitial instead of JSON; `backend/app/services/bambu_cloud.py::verify_totp` caught the `json.JSONDecodeError` and returned the opaque "Invalid response from Bambu Cloud" message. **Root cause is Cloudflare-side, not Bambuddy**: a curl from this machine with the same honest `Bambuddy/1.0 (+https://github.com/maziggy/bambuddy)` UA at 2026-06-02 returned a clean `HTTP/2 400 {"code":5,"error":"Login failed"}` JSON — same UA, same headers, different network. CF's bot management appears to flag conditions (per-IP / TLS-fingerprint / rate / transient mitigation window) that don't reproduce from us. No reliable way to *prevent* the challenge from our side without browser impersonation, which is explicitly off the table per the 2026-05-12 compliance audit. **Fix is diagnostic, not bypass**: new `_detect_cloudflare_challenge(response) -> str | None` helper inspects the failed-parse response for CF markers (`"Just a moment..."` in body, `"challenges.cloudflare.com"` in body, HTTP 403 with `cf-mitigated` header, HTTP 503 with `cf-ray` header) and returns a message that attributes the block to Bambu Lab's Cloudflare protection, suggests waiting a few minutes, and tells the user that signing in to bambulab.com from a browser on the same network usually clears the challenge. Wired into all three JSON-parse sites: `login_request`, `verify_code`, and `verify_totp` — previously only `verify_totp` had a defensive catch; `login_request` and `verify_code` let the parse error bubble to `BambuCloudAuthError` with `"Expecting value..."` as the detail, which surfaced as a generic 401 in the UI. **Tests**: 8 new in `TestCloudflareChallengeDetection` (`backend/tests/unit/services/test_bambu_cloud.py`) — direct helper tests for each of the four CF markers, a negative case (real JSON 400 with `cf-ray` header from the actual successful curl response above is NOT misclassified as a challenge so the application-level "Login failed" still surfaces), an attribution check (message must name "Cloudflare" and "bambulab.com" so users can act on it), and full-stack tests covering all three call sites with the verbatim interstitial fragment from the reporter's log. The existing `test_verify_totp_cloudflare_blocked` updated to assert the new actionable message. Full 5486-test backend suite green; backend ruff clean. diff --git a/backend/app/api/routes/slicer_presets.py b/backend/app/api/routes/slicer_presets.py index 01339f21b..1e34b5392 100644 --- a/backend/app/api/routes/slicer_presets.py +++ b/backend/app/api/routes/slicer_presets.py @@ -16,7 +16,7 @@ import json import logging import time -from fastapi import APIRouter, Depends, File, HTTPException, UploadFile +from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession @@ -88,7 +88,9 @@ def _empty_slots() -> dict[str, list[UnifiedPreset]]: return {"printer": [], "process": [], "filament": []} -async def _fetch_cloud_presets(db: AsyncSession, user: User | None) -> tuple[dict[str, list[UnifiedPreset]], str]: +async def _fetch_cloud_presets( + db: AsyncSession, user: User | None, *, refresh: bool = False +) -> tuple[dict[str, list[UnifiedPreset]], str]: """Return (slots, cloud_status). Slots are empty when cloud_status != 'ok'. Defence-in-depth: even if a stored cloud_token survived a permission @@ -96,6 +98,12 @@ async def _fetch_cloud_presets(db: AsyncSession, user: User | None) -> tuple[dic treated as not-authenticated for this endpoint — the cloud tier never surfaces for them. This keeps the per-tier visibility consistent with the /cloud/* endpoint suite that already gates on CLOUD_AUTH. + + ``refresh=True`` skips the in-process cache for this call (used by the + SliceModal's manual Refresh button so a user who just deleted a preset + in Bambu Studio / Handy can pick up the change without waiting for the + 5-minute TTL to expire). The fresh result is still written back to the + cache so subsequent non-refresh callers benefit. """ if user is not None and not user.has_permission(Permission.CLOUD_AUTH.value): return _empty_slots(), "not_authenticated" @@ -107,9 +115,10 @@ async def _fetch_cloud_presets(db: AsyncSession, user: User | None) -> tuple[dic user_key = user.id if user is not None else 0 cache_key = (user_key, _token_fingerprint(token)) now = time.monotonic() - cached = _cloud_cache.get(cache_key) - if cached and now - cached[0] < _CLOUD_TTL_S: - return cached[1], "ok" + if not refresh: + cached = _cloud_cache.get(cache_key) + if cached and now - cached[0] < _CLOUD_TTL_S: + return cached[1], "ok" cloud = BambuCloudService(region=region) cloud.set_token(token) @@ -227,11 +236,15 @@ def _first_scalar(value: object) -> str | None: return None -async def _fetch_bundled_presets(db: AsyncSession) -> dict[str, list[UnifiedPreset]]: - """Standard slicer-bundled profiles via the sidecar's /profiles/bundled.""" +async def _fetch_bundled_presets(db: AsyncSession, *, refresh: bool = False) -> dict[str, list[UnifiedPreset]]: + """Standard slicer-bundled profiles via the sidecar's /profiles/bundled. + + ``refresh=True`` skips the in-process cache; see _fetch_cloud_presets for + the same shape and rationale. + """ global _bundled_cache now = time.monotonic() - if _bundled_cache and now - _bundled_cache[0] < _BUNDLED_TTL_S: + if not refresh and _bundled_cache and now - _bundled_cache[0] < _BUNDLED_TTL_S: return _bundled_cache[1] api_url = await _resolve_slicer_api_url(db) @@ -383,6 +396,15 @@ async def list_unified_presets( db: AsyncSession = Depends(get_db), current_user: User | None = RequirePermissionIfAuthEnabled(Permission.LIBRARY_UPLOAD), api_key_cloud_owner: User | None = Depends(resolve_api_key_cloud_owner), + refresh: bool = Query( + False, + description=( + "Bypass the in-process cloud and bundled-preset caches for this " + "request. The SliceModal's Refresh button sets this so users who " + "deleted a preset in Bambu Studio or Bambu Handy don't have to " + "wait for the 5-minute cloud-cache TTL to expire." + ), + ), ) -> UnifiedPresetsResponse: """List slicer presets across cloud / local / standard tiers, deduped by name. @@ -399,9 +421,9 @@ async def list_unified_presets( too — matching the slice route (#1182 follow-up). """ cloud_token_user = current_user or api_key_cloud_owner - cloud, cloud_status = await _fetch_cloud_presets(db, cloud_token_user) + cloud, cloud_status = await _fetch_cloud_presets(db, cloud_token_user, refresh=refresh) local = await _fetch_local_presets(db) - standard = await _fetch_bundled_presets(db) + standard = await _fetch_bundled_presets(db, refresh=refresh) cloud, local, standard = _dedupe_by_name(cloud, local, standard) diff --git a/backend/tests/unit/test_no_unsafe_path_joins.py b/backend/tests/unit/test_no_unsafe_path_joins.py index dd3fb5cea..d98c61590 100644 --- a/backend/tests/unit/test_no_unsafe_path_joins.py +++ b/backend/tests/unit/test_no_unsafe_path_joins.py @@ -109,9 +109,26 @@ def _rhs_is_attacker_shape(node: ast.AST) -> bool: return isinstance(node, ast.Name) +_CONTINUATION_TOKENS = (")", "]", "}", ",") + + def _line_has_marker(source_lines: list[str], lineno: int, end_lineno: int | None) -> bool: - # Walk every line spanned by the BinOp — the marker can sit anywhere in the - # expression (start, end, or any continuation line of a multi-line join). + """Check whether a ``# SEC-PATH-OK:`` marker covers this join. + + Looks at every line spanned by the BinOp itself, plus one line past + ``end_lineno`` IF that line begins with a continuation token (``)``, + ``]``, ``}``, ``,``). The peek captures the project's convention of + wrapping a BinOp in parens and placing the marker on the closing line: + + file_path = ( + library_dir / filename + ) # SEC-PATH-OK: filename validated above + + The BinOp itself ends on the inner line, but the marker reads more + naturally on the closing line. Restricting the peek to continuation + lines prevents giving a free pass to a marker that happens to sit on + a wholly unrelated follow-on statement. + """ start = max(1, lineno) end = max(start, end_lineno or lineno) for i in range(start, end + 1): @@ -119,6 +136,13 @@ def _line_has_marker(source_lines: list[str], lineno: int, end_lineno: int | Non continue if _MARKER in source_lines[i - 1]: return True + # Project convention: marker often sits on the closing-paren line, one + # line past the BinOp's `end_lineno`. Only accept it when the line is a + # continuation of the wrapping expression. + if end < len(source_lines): + trailing = source_lines[end].lstrip() + if trailing.startswith(_CONTINUATION_TOKENS) and _MARKER in source_lines[end]: + return True return False @@ -174,6 +198,83 @@ def _scan_file(py_file: Path) -> list[str]: return findings +def _scan_source(source: str, tmp_path: Path) -> list[str]: + """Drop ``source`` into a temp .py file and run ``_scan_file`` against it. + Returns the findings list.""" + f = tmp_path / "candidate.py" + f.write_text(source) + return _scan_file(f) + + +class TestMarkerDetection: + """Pins the contract for where a ``# SEC-PATH-OK:`` marker is accepted. + + Markers must sit either (a) somewhere within the BinOp's own source + lines, or (b) on the immediately-following line when that line is a + continuation token (closing paren / bracket / brace / comma). The + second case is the project's convention of wrapping the BinOp in + parens and placing the marker on the closing-paren line. + """ + + def test_marker_on_binop_line_recognised(self, tmp_path): + source = ( + "from pathlib import Path\nbase_dir = Path('.')\ndef f(x): return base_dir / x # SEC-PATH-OK: trusted x\n" + ) + assert _scan_source(source, tmp_path) == [] + + def test_marker_on_closing_paren_line_recognised(self, tmp_path): + # The exact convention used across api/routes/ and services/: the + # BinOp lives inside a parenthesised expression and the marker sits + # on the closing-paren line, one past the BinOp's `end_lineno`. + source = ( + "from pathlib import Path\n" + "base_dir = Path('.')\n" + "def f(x):\n" + " return (\n" + " base_dir / x\n" + " ) # SEC-PATH-OK: trusted x\n" + ) + assert _scan_source(source, tmp_path) == [] + + def test_unrelated_marker_below_does_not_silence(self, tmp_path): + # A second join below carries a marker; the first does not. Only + # the first must be flagged — markers don't cross statement + # boundaries. + source = ( + "from pathlib import Path\n" + "base_dir = Path('.')\n" + "def f(x, y):\n" + " p = base_dir / x\n" + " q = base_dir / y # SEC-PATH-OK: trusted y\n" + ) + findings = _scan_source(source, tmp_path) + assert len(findings) == 1 + assert "base_dir / x" in findings[0] + + def test_marker_on_non_continuation_line_does_not_silence(self, tmp_path): + # A SEC-PATH-OK comment on the line right after the BinOp counts + # only when that line is a continuation of the wrapping expression. + # An unrelated next statement's marker must not free-pass the join. + source = ( + "from pathlib import Path\n" + "base_dir = Path('.')\n" + "def f(x):\n" + " a = base_dir / x\n" + " b = 1 # SEC-PATH-OK: unrelated, for a different statement\n" + ) + findings = _scan_source(source, tmp_path) + assert len(findings) == 1 + assert "base_dir / x" in findings[0] + + def test_no_marker_anywhere_is_flagged(self, tmp_path): + # Pin the negative path so a future refactor can't accidentally turn + # marker detection into "always returns True". + source = "from pathlib import Path\nbase_dir = Path('.')\ndef f(x): return base_dir / x\n" + findings = _scan_source(source, tmp_path) + assert len(findings) == 1 + assert "base_dir / x" in findings[0] + + def test_route_path_arithmetic_is_safe_joined_or_marked(): """Every `` / `` join in a route handler must either route through ``safe_join_under(...)`` or carry a diff --git a/backend/tests/unit/test_slicer_presets.py b/backend/tests/unit/test_slicer_presets.py index 71ac4bd3b..21d7aa15b 100644 --- a/backend/tests/unit/test_slicer_presets.py +++ b/backend/tests/unit/test_slicer_presets.py @@ -286,6 +286,60 @@ class TestFetchCloudPresets: assert first["printer"][0].name == "OldAccountX1C" assert second["printer"][0].name == "NewAccountX1C" + @pytest.mark.asyncio + async def test_refresh_bypasses_cloud_cache(self): + """``refresh=True`` must skip an otherwise-warm cache entry and hit + Bambu Cloud again — wiring for the SliceModal's Refresh button so a + user who deletes a cloud preset in Bambu Studio / Handy doesn't have + to wait for the 5-minute TTL to expire (#1581).""" + sp._cloud_cache.clear() + cloud_mock = MagicMock() + cloud_mock.set_token = MagicMock() + cloud_mock.get_slicer_settings = AsyncMock( + return_value={ + "printer": {"private": [{"setting_id": "id1", "name": "X1C"}], "public": []}, + "print": {"private": [], "public": []}, + "filament": {"private": [], "public": []}, + } + ) + cloud_mock.close = AsyncMock() + user = _user_with_cloud_auth(user_id=99) + with ( + patch.object(sp, "get_stored_token", AsyncMock(return_value=("tok", None, None))), + patch.object(sp, "BambuCloudService", return_value=cloud_mock), + ): + await sp._fetch_cloud_presets(MagicMock(), user) + # Without refresh, the second call hits cache (covered by + # test_cache_hit_skips_cloud_call). With refresh=True it MUST + # re-fetch. + await sp._fetch_cloud_presets(MagicMock(), user, refresh=True) + assert cloud_mock.get_slicer_settings.await_count == 2 + + @pytest.mark.asyncio + async def test_refresh_writes_back_to_cache(self): + """A refresh call must still update the cache so a subsequent normal + call doesn't re-hit the cloud immediately afterwards.""" + sp._cloud_cache.clear() + cloud_mock = MagicMock() + cloud_mock.set_token = MagicMock() + cloud_mock.get_slicer_settings = AsyncMock( + return_value={ + "printer": {"private": [{"setting_id": "id1", "name": "X1C"}], "public": []}, + "print": {"private": [], "public": []}, + "filament": {"private": [], "public": []}, + } + ) + cloud_mock.close = AsyncMock() + user = _user_with_cloud_auth(user_id=101) + with ( + patch.object(sp, "get_stored_token", AsyncMock(return_value=("tok", None, None))), + patch.object(sp, "BambuCloudService", return_value=cloud_mock), + ): + await sp._fetch_cloud_presets(MagicMock(), user, refresh=True) + await sp._fetch_cloud_presets(MagicMock(), user) + # Two calls — first refresh, second a normal cache hit. + assert cloud_mock.get_slicer_settings.await_count == 1 + class TestFetchBundledPresets: """Standard tier reaches out to the slicer-api sidecar; tolerate the @@ -356,6 +410,41 @@ class TestFetchBundledPresets: slots = await sp._fetch_bundled_presets(MagicMock()) assert slots["printer"][0].name == "Cached" + @pytest.mark.asyncio + async def test_refresh_bypasses_bundled_cache(self): + """``refresh=True`` must re-hit the sidecar even when the in-process + cache is warm — paired with the cloud-cache refresh, this is what + powers the SliceModal's Refresh button (#1581).""" + sp._bundled_cache = ( + time.monotonic(), + { + "printer": [UnifiedPreset(id="Stale", name="Stale", source="standard")], + "process": [], + "filament": [], + }, + ) + svc_mock = MagicMock() + svc_mock.list_bundled_profiles = AsyncMock( + return_value={ + "printer": [{"name": "Fresh", "base_id": None}], + "process": [], + "filament": [], + } + ) + svc_mock.__aenter__ = AsyncMock(return_value=svc_mock) + svc_mock.__aexit__ = AsyncMock(return_value=False) + with ( + patch.object(sp, "_resolve_slicer_api_url", AsyncMock(return_value="http://ok")), + patch.object(sp, "SlicerApiService", return_value=svc_mock), + ): + slots = await sp._fetch_bundled_presets(MagicMock(), refresh=True) + svc_mock.list_bundled_profiles.assert_awaited_once() + assert [p.name for p in slots["printer"]] == ["Fresh"] + # The fresh result must also be written back to the cache so a + # subsequent normal (non-refresh) call doesn't re-hit the sidecar. + assert sp._bundled_cache is not None + assert [p.name for p in sp._bundled_cache[1]["printer"]] == ["Fresh"] + class TestResolveSlicerApiUrl: """`_resolve_slicer_api_url` must respect the user's `preferred_slicer` diff --git a/frontend/src/__tests__/components/LocalProfilesView.test.tsx b/frontend/src/__tests__/components/LocalProfilesView.test.tsx index fc319e9da..ffb9e2aad 100644 --- a/frontend/src/__tests__/components/LocalProfilesView.test.tsx +++ b/frontend/src/__tests__/components/LocalProfilesView.test.tsx @@ -1,11 +1,17 @@ /** * Tests for LocalProfilesView component. */ -import { describe, it, expect, beforeEach } from 'vitest'; -import { screen, waitFor, fireEvent } from '@testing-library/react'; +import React from 'react'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; +import { screen, waitFor, fireEvent, render as rawRender } from '@testing-library/react'; import { http, HttpResponse } from 'msw'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { BrowserRouter } from 'react-router-dom'; import { server } from '../mocks/server'; import { render } from '../utils'; +import { ThemeProvider } from '../../contexts/ThemeContext'; +import { ToastProvider } from '../../contexts/ToastContext'; +import { AuthProvider } from '../../contexts/AuthContext'; import { LocalProfilesView } from '../../components/LocalProfilesView'; const mockLocalPresets = { @@ -209,4 +215,62 @@ describe('LocalProfilesView', () => { expect(screen.getByText(/\.bbscfg/i)).toBeInTheDocument(); }); + + it('invalidates the slicerPresets query after a delete (#1581)', async () => { + // Without this invalidation a preset deleted in Local Profiles still + // shows in the SliceModal until the modal's ['slicerPresets'] query + // staleTime (60s) expires + a refocus / remount. The bug report: + // "Removed local profiles still show on the slice menu even tho they + // have been deleted." We mirror the production provider tree but inject + // our own QueryClient so we can spy on invalidateQueries. + const queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false, gcTime: 0 }, + mutations: { retry: false }, + }, + }); + const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries'); + + rawRender( + + + + + + + + + + + , + ); + + await waitFor(() => { + expect(screen.getByText('Overture PLA Matte @BBL X1C')).toBeInTheDocument(); + }); + + // Open the delete confirmation, then confirm. The card-level delete + // icon buttons and the modal's Delete button both expose the accessible + // name "Delete"; the modal button is the last one to mount, so it's the + // tail of the findAllByRole result. + const deleteButtons = screen.getAllByTitle(/delete/i); + fireEvent.click(deleteButtons[0]); + await screen.findByText(/are you sure/i); + const confirmButtons = await screen.findAllByRole('button', { name: /^delete$/i }); + fireEvent.click(confirmButtons[confirmButtons.length - 1]); + + await waitFor(() => { + expect( + invalidateSpy.mock.calls.some( + ([arg]) => arg && (arg as { queryKey: unknown[] }).queryKey?.[0] === 'slicerPresets', + ), + ).toBe(true); + }); + // Sanity: the local-only invalidation is still there too. + expect( + invalidateSpy.mock.calls.some( + ([arg]) => arg && (arg as { queryKey: unknown[] }).queryKey?.[0] === 'localPresets', + ), + ).toBe(true); + }); }); diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index a968b62c0..7de0ca704 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -5796,8 +5796,13 @@ export const api = { // Unified slicer-preset listing — cloud + local + standard, deduped by name. // Used by the SliceModal; see UnifiedPresetsResponse for the shape and // backend/app/api/routes/slicer_presets.py for the priority rules. - getSlicerPresets: () => - request('/slicer/presets'), + // `refresh` bypasses the in-process cloud and bundled-preset caches on the + // backend; the SliceModal's Refresh button passes true so a preset deleted + // in Bambu Studio or Bambu Handy shows up without the 5-min TTL wait. + getSlicerPresets: (options?: { refresh?: boolean }) => + request( + options?.refresh ? '/slicer/presets?refresh=true' : '/slicer/presets', + ), // Canonical Bambu printer-model registry — "Bambu Lab " → short code. // Single source of truth shared with backend (PRINTER_MODEL_MAP); the diff --git a/frontend/src/components/LocalProfilesView.tsx b/frontend/src/components/LocalProfilesView.tsx index 0734ad4da..68f2d76de 100644 --- a/frontend/src/components/LocalProfilesView.tsx +++ b/frontend/src/components/LocalProfilesView.tsx @@ -245,6 +245,11 @@ export function LocalProfilesView() { }, onSuccess: (results) => { queryClient.invalidateQueries({ queryKey: ['localPresets'] }); + // The SliceModal reads from a separate `slicerPresets` query that lists + // cloud + local + standard in one shot. Without this second invalidation + // freshly-imported profiles wouldn't appear in the SliceModal dropdown + // until that query's staleTime elapsed plus a refocus / remount (#1581). + queryClient.invalidateQueries({ queryKey: ['slicerPresets'] }); let totalImported = 0; let totalSkipped = 0; let totalErrors = 0; @@ -273,6 +278,11 @@ export function LocalProfilesView() { mutationFn: (id: number) => api.deleteLocalPreset(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['localPresets'] }); + // Match the import path: the SliceModal's `slicerPresets` query needs + // to be invalidated too, otherwise the deleted preset keeps appearing + // in the slice dropdown until its 60s staleTime expires plus a + // refocus / remount (#1581). + queryClient.invalidateQueries({ queryKey: ['slicerPresets'] }); setDeleteConfirm(null); showToast(t('profiles.localProfiles.toast.deleted')); }, diff --git a/frontend/src/components/SliceModal.tsx b/frontend/src/components/SliceModal.tsx index 7a03ad96c..8c6d1542e 100644 --- a/frontend/src/components/SliceModal.tsx +++ b/frontend/src/components/SliceModal.tsx @@ -1,7 +1,7 @@ -import { Cloud, CloudOff, Cog, Loader2, Package, X } from 'lucide-react'; +import { Cloud, CloudOff, Cog, Loader2, Package, RefreshCw, X } from 'lucide-react'; import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useMutation, useQuery } from '@tanstack/react-query'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { api, type PresetRef, @@ -312,6 +312,7 @@ function formatElapsed(seconds: number): string { export function SliceModal({ source, onClose }: SliceModalProps) { const { t } = useTranslation(); const { trackJob } = useSliceJobTracker(); + const queryClient = useQueryClient(); const [printerPreset, setPrinterPreset] = useState(null); const [processPreset, setProcessPreset] = useState(null); @@ -431,6 +432,28 @@ export function SliceModal({ source, onClose }: SliceModalProps) { enabled: !platesQuery.isLoading && !needsPlatePicker, }); + // Manual refresh — bypasses the backend's 5-minute cloud cache and 1-hour + // bundled cache for one call so users who deleted a preset in Bambu + // Studio / Bambu Handy see the change immediately (#1581). The cache write + // inside _fetch_cloud_presets / _fetch_bundled_presets refills with the + // fresh result so subsequent normal callers still get cached responses. + const [isRefreshing, setIsRefreshing] = useState(false); + const handleRefreshPresets = async () => { + if (isRefreshing) return; + setIsRefreshing(true); + try { + const fresh = await api.getSlicerPresets({ refresh: true }); + queryClient.setQueryData(['slicerPresets'], fresh); + } catch { + // Fall through to invalidate so React Query retries via its normal + // path on the next render — surfacing the failure through the existing + // presetsQuery.isError banner instead of duplicating error UI here. + queryClient.invalidateQueries({ queryKey: ['slicerPresets'] }); + } finally { + setIsRefreshing(false); + } + }; + // Imported Printer Preset Bundles (.bbscfg). Empty list when no sidecar // configured / no bundles imported yet; the bundle picker hides itself // in that case so users without bundles see the original modal layout. @@ -723,7 +746,26 @@ export function SliceModal({ source, onClose }: SliceModalProps) { {presetsQuery.data && ( <> - +
+
+ +
+ +
+ {/* CloudStatusBanner above is hidden via flex-1 wrapper when + status === 'ok' (returns null in that case), but the Refresh + button stays visible regardless so users can pick up cloud / + bundled changes even when sign-in is healthy. */} {/* Bundle picker — only renders when at least one .bbscfg has been imported via Settings → Slicer Bundles. Lets the user trade the cloud/local/standard tier for a single curated diff --git a/frontend/src/i18n/locales/de.ts b/frontend/src/i18n/locales/de.ts index 4c1664a5e..d3a476ee6 100644 --- a/frontend/src/i18n/locales/de.ts +++ b/frontend/src/i18n/locales/de.ts @@ -3481,6 +3481,8 @@ export default { noPresetsForSlot: 'Keine Profile verfügbar', otherPrinters: 'Andere Drucker', presetsLoadFailed: 'Profile konnten nicht geladen werden. Importiere sie zuerst unter Einstellungen → Profile.', + refreshPresets: 'Aktualisieren', + refreshPresetsTitle: 'Profile neu laden — die aktuellen Cloud- und Bundle-Listen abrufen (nach dem Löschen eines Profils in Bambu Studio oder Bambu Handy verwenden)', allPresetsRequired: 'Alle Profile müssen ausgewählt sein', bundle: 'Slicer-Bundle', bundleNone: '— Keines (Profile einzeln auswählen) —', diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index cf7bf5f66..577794fdd 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -3484,6 +3484,8 @@ export default { noPresetsForSlot: 'No presets available', otherPrinters: 'Other printers', presetsLoadFailed: 'Failed to load presets. Open Settings → Profiles to import them first.', + refreshPresets: 'Refresh', + refreshPresetsTitle: 'Refresh presets — fetch the latest cloud and bundled listings (use after deleting a preset in Bambu Studio or Bambu Handy)', allPresetsRequired: 'All presets must be selected', bundle: 'Slicer bundle', bundleNone: '— None (pick presets individually) —', diff --git a/frontend/src/i18n/locales/es.ts b/frontend/src/i18n/locales/es.ts index f2448d028..b35c39f75 100644 --- a/frontend/src/i18n/locales/es.ts +++ b/frontend/src/i18n/locales/es.ts @@ -3484,6 +3484,8 @@ export default { noPresetsForSlot: 'No hay preajustes disponibles', otherPrinters: 'Otras impresoras', presetsLoadFailed: 'Error al cargar los preajustes. Abra Ajustes → Perfiles para importarlos primero.', + refreshPresets: 'Actualizar', + refreshPresetsTitle: 'Actualizar preajustes — recuperar los listados más recientes de la nube y los paquetes (úselo tras eliminar un preajuste en Bambu Studio o Bambu Handy)', allPresetsRequired: 'Deben seleccionarse todos los preajustes', bundle: 'Paquete del laminador', bundleNone: '— Ninguno (elegir preajustes individualmente) —', diff --git a/frontend/src/i18n/locales/fr.ts b/frontend/src/i18n/locales/fr.ts index 5d8d9e057..cf7400450 100644 --- a/frontend/src/i18n/locales/fr.ts +++ b/frontend/src/i18n/locales/fr.ts @@ -3470,6 +3470,8 @@ export default { noPresetsForSlot: 'Aucun préréglage disponible', otherPrinters: 'Autres imprimantes', presetsLoadFailed: 'Échec du chargement des préréglages. Ouvrez Paramètres → Profils pour les importer d\'abord.', + refreshPresets: 'Actualiser', + refreshPresetsTitle: 'Actualiser les préréglages — récupérer les dernières listes Cloud et bundle (à utiliser après avoir supprimé un préréglage dans Bambu Studio ou Bambu Handy)', allPresetsRequired: 'Tous les préréglages doivent être sélectionnés', bundle: 'Pack de découpage', bundleNone: '— Aucun (choisir les préréglages individuellement) —', diff --git a/frontend/src/i18n/locales/it.ts b/frontend/src/i18n/locales/it.ts index 6859dd233..b1e84d795 100644 --- a/frontend/src/i18n/locales/it.ts +++ b/frontend/src/i18n/locales/it.ts @@ -3469,6 +3469,8 @@ export default { noPresetsForSlot: 'Nessun preset disponibile', otherPrinters: 'Altre stampanti', presetsLoadFailed: 'Caricamento preset fallito. Apri Impostazioni → Profili per importarli prima.', + refreshPresets: 'Aggiorna', + refreshPresetsTitle: 'Aggiorna i preset — recupera gli elenchi più recenti dal cloud e dai bundle (da usare dopo aver eliminato un preset in Bambu Studio o Bambu Handy)', allPresetsRequired: 'Tutti i preset devono essere selezionati', bundle: 'Bundle slicer', bundleNone: '— Nessuno (scegli i preset singolarmente) —', diff --git a/frontend/src/i18n/locales/ja.ts b/frontend/src/i18n/locales/ja.ts index 1afa479db..1bba7813c 100644 --- a/frontend/src/i18n/locales/ja.ts +++ b/frontend/src/i18n/locales/ja.ts @@ -3481,6 +3481,8 @@ export default { noPresetsForSlot: 'プリセットなし', otherPrinters: '他のプリンター', presetsLoadFailed: 'プリセットの読み込みに失敗。先に設定 → プロファイルからインポートしてください。', + refreshPresets: '再読み込み', + refreshPresetsTitle: 'プリセットを再取得 — クラウドとバンドルの最新リストを取得します(Bambu Studio または Bambu Handy でプリセットを削除した後にお使いください)', allPresetsRequired: 'すべてのプリセットを選択する必要があります', bundle: 'スライサーバンドル', bundleNone: '— なし(プリセットを個別に選択)—', diff --git a/frontend/src/i18n/locales/pt-BR.ts b/frontend/src/i18n/locales/pt-BR.ts index dc343e026..53b6f7f06 100644 --- a/frontend/src/i18n/locales/pt-BR.ts +++ b/frontend/src/i18n/locales/pt-BR.ts @@ -3469,6 +3469,8 @@ export default { noPresetsForSlot: 'Nenhuma predefinição disponível', otherPrinters: 'Outras impressoras', presetsLoadFailed: 'Falha ao carregar predefinições. Abra Configurações → Perfis para importá-las primeiro.', + refreshPresets: 'Atualizar', + refreshPresetsTitle: 'Atualizar predefinições — buscar as listagens mais recentes da nuvem e dos pacotes (use após excluir uma predefinição no Bambu Studio ou Bambu Handy)', allPresetsRequired: 'Todas as predefinições devem ser selecionadas', bundle: 'Pacote do fatiador', bundleNone: '— Nenhum (escolher predefinições individualmente) —', diff --git a/frontend/src/i18n/locales/zh-CN.ts b/frontend/src/i18n/locales/zh-CN.ts index 16174b8ca..3a643782a 100644 --- a/frontend/src/i18n/locales/zh-CN.ts +++ b/frontend/src/i18n/locales/zh-CN.ts @@ -3469,6 +3469,8 @@ export default { noPresetsForSlot: '无可用预设', otherPrinters: '其他打印机', presetsLoadFailed: '加载预设失败。请先打开设置 → 配置文件以导入。', + refreshPresets: '刷新', + refreshPresetsTitle: '刷新预设 — 获取最新的云端和打包配置列表(在 Bambu Studio 或 Bambu Handy 中删除预设后使用)', allPresetsRequired: '必须选择所有预设', bundle: '切片器套装', bundleNone: '— 无(单独选择预设)—', diff --git a/frontend/src/i18n/locales/zh-TW.ts b/frontend/src/i18n/locales/zh-TW.ts index 04c4f75dd..48d5eacb8 100644 --- a/frontend/src/i18n/locales/zh-TW.ts +++ b/frontend/src/i18n/locales/zh-TW.ts @@ -3469,6 +3469,8 @@ export default { noPresetsForSlot: '無可用預設', otherPrinters: '其他印表機', presetsLoadFailed: '載入預設失敗。請先開啟設定 → 設定檔以匯入。', + refreshPresets: '重新整理', + refreshPresetsTitle: '重新整理預設 — 擷取最新的雲端與打包設定清單(在 Bambu Studio 或 Bambu Handy 中刪除預設後使用)', allPresetsRequired: '必須選擇所有預設', bundle: '切片器套裝', bundleNone: '— 無(單獨選擇預設)—', diff --git a/static/assets/index-BeiuHSbR.js b/static/assets/index-DqHz1llA.js similarity index 83% rename from static/assets/index-BeiuHSbR.js rename to static/assets/index-DqHz1llA.js index d874c5796..13b0d3fdc 100644 --- a/static/assets/index-BeiuHSbR.js +++ b/static/assets/index-DqHz1llA.js @@ -1,41 +1,41 @@ -function rme(t,e){for(var a=0;ar[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 a(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=a(i);fetch(i.href,s)}})();var T_=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Fc(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var rE={exports:{}},a0={};var TH;function ime(){if(TH)return a0;TH=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function a(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 a0.Fragment=e,a0.jsx=a,a0.jsxs=a,a0}var AH;function sme(){return AH||(AH=1,rE.exports=ime()),rE.exports}var n=sme(),iE={exports:{}},Ka={};var jH;function ome(){if(jH)return Ka;jH=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),a=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(Y){return Y===null||typeof Y!="object"?null:(Y=p&&Y[p]||Y["@@iterator"],typeof Y=="function"?Y:null)}var g={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},v=Object.assign,b={};function x(Y,se,pe){this.props=Y,this.context=se,this.refs=b,this.updater=pe||g}x.prototype.isReactComponent={},x.prototype.setState=function(Y,se){if(typeof Y!="object"&&typeof Y!="function"&&Y!=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,Y,se,"setState")},x.prototype.forceUpdate=function(Y){this.updater.enqueueForceUpdate(this,Y,"forceUpdate")};function S(){}S.prototype=x.prototype;function k(Y,se,pe){this.props=Y,this.context=se,this.refs=b,this.updater=pe||g}var C=k.prototype=new S;C.constructor=k,v(C,x.prototype),C.isPureReactComponent=!0;var P=Array.isArray;function T(){}var j={H:null,A:null,T:null,S:null},F=Object.prototype.hasOwnProperty;function N(Y,se,pe){var me=pe.ref;return{$$typeof:t,type:Y,key:se,ref:me!==void 0?me:null,props:pe}}function D(Y,se){return N(Y.type,se,Y.props)}function R(Y){return typeof Y=="object"&&Y!==null&&Y.$$typeof===t}function z(Y){var se={"=":"=0",":":"=2"};return"$"+Y.replace(/[=:]/g,function(pe){return se[pe]})}var O=/\/+/g;function L(Y,se){return typeof Y=="object"&&Y!==null&&Y.key!=null?z(""+Y.key):se.toString(36)}function Q(Y){switch(Y.status){case"fulfilled":return Y.value;case"rejected":throw Y.reason;default:switch(typeof Y.status=="string"?Y.then(T,T):(Y.status="pending",Y.then(function(se){Y.status==="pending"&&(Y.status="fulfilled",Y.value=se)},function(se){Y.status==="pending"&&(Y.status="rejected",Y.reason=se)})),Y.status){case"fulfilled":return Y.value;case"rejected":throw Y.reason}}throw Y}function ee(Y,se,pe,me,be){var H=typeof Y;(H==="undefined"||H==="boolean")&&(Y=null);var X=!1;if(Y===null)X=!0;else switch(H){case"bigint":case"string":case"number":X=!0;break;case"object":switch(Y.$$typeof){case t:case e:X=!0;break;case u:return X=Y._init,ee(X(Y._payload),se,pe,me,be)}}if(X)return be=be(Y),X=me===""?"."+L(Y,0):me,P(be)?(pe="",X!=null&&(pe=X.replace(O,"$&/")+"/"),ee(be,se,pe,"",function(B){return B})):be!=null&&(R(be)&&(be=D(be,pe+(be.key==null||Y&&Y.key===be.key?"":(""+be.key).replace(O,"$&/")+"/")+X)),se.push(be)),1;X=0;var A=me===""?".":me+":";if(P(Y))for(var M=0;M>>1,ue=ee[de];if(0>>1;dei(pe,le))mei(be,pe)?(ee[de]=be,ee[me]=le,de=me):(ee[de]=pe,ee[se]=le,de=se);else if(mei(be,le))ee[de]=be,ee[me]=le,de=me;else break e}}return J}function i(ee,J){var le=ee.sortIndex-J.sortIndex;return le!==0?le:ee.id-J.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,g=!1,v=!1,b=!1,x=typeof setTimeout=="function"?setTimeout:null,S=typeof clearTimeout=="function"?clearTimeout:null,k=typeof setImmediate<"u"?setImmediate:null;function C(ee){for(var J=a(d);J!==null;){if(J.callback===null)r(d);else if(J.startTime<=ee)r(d),J.sortIndex=J.expirationTime,e(c,J);else break;J=a(d)}}function P(ee){if(v=!1,C(ee),!g)if(a(c)!==null)g=!0,T||(T=!0,z());else{var J=a(d);J!==null&&Q(P,J.startTime-ee)}}var T=!1,j=-1,F=5,N=-1;function D(){return b?!0:!(t.unstable_now()-Nee&&D());){var de=m.callback;if(typeof de=="function"){m.callback=null,p=m.priorityLevel;var ue=de(m.expirationTime<=ee);if(ee=t.unstable_now(),typeof ue=="function"){m.callback=ue,C(ee),J=!0;break t}m===a(c)&&r(c),C(ee)}else r(c);m=a(c)}if(m!==null)J=!0;else{var Y=a(d);Y!==null&&Q(P,Y.startTime-ee),J=!1}}break e}finally{m=null,p=le,f=!1}J=void 0}}finally{J?z():T=!1}}}var z;if(typeof k=="function")z=function(){k(R)};else if(typeof MessageChannel<"u"){var O=new MessageChannel,L=O.port2;O.port1.onmessage=R,z=function(){L.postMessage(null)}}else z=function(){x(R,0)};function Q(ee,J){j=x(function(){ee(t.unstable_now())},J)}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(ee){ee.callback=null},t.unstable_forceFrameRate=function(ee){0>ee||125de?(ee.sortIndex=le,e(d,ee),a(c)===null&&ee===a(d)&&(v?(S(j),j=-1):v=!0,Q(P,le-de))):(ee.sortIndex=ue,e(c,ee),g||f||(g=!0,T||(T=!0,z()))),ee},t.unstable_shouldYield=D,t.unstable_wrapCallback=function(ee){var J=p;return function(){var le=p;p=J;try{return ee.apply(this,arguments)}finally{p=le}}}})(lE)),lE}var DH;function dme(){return DH||(DH=1,oE.exports=cme()),oE.exports}var cE={exports:{}},Hs={};var FH;function ume(){if(FH)return Hs;FH=1;var t=ob();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(),cE.exports=ume(),cE.exports}var RH;function mme(){if(RH)return n0;RH=1;var t=dme(),e=ob(),a=JX();function r(h){var w="https://react.dev/errors/"+h;if(1ue||(h.current=de[ue],de[ue]=null,ue--)}function pe(h,w){ue++,de[ue]=h.current,h.current=w}var me=Y(null),be=Y(null),H=Y(null),X=Y(null);function A(h,w){switch(pe(H,w),pe(be,h),pe(me,null),w.nodeType){case 9:case 11:h=(h=w.documentElement)&&(h=h.namespaceURI)?Xq(h):0;break;default:if(h=w.tagName,w=w.namespaceURI)w=Xq(w),h=Zq(w,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}se(me),pe(me,h)}function M(){se(me),se(be),se(H)}function B(h){h.memoizedState!==null&&pe(X,h);var w=me.current,_=Zq(w,h.type);w!==_&&(pe(be,h),pe(me,_))}function W(h){be.current===h&&(se(me),se(be)),X.current===h&&(se(X),Zv._currentValue=le)}var q,re;function U(h){if(q===void 0)try{throw Error()}catch(_){var w=_.stack.trim().match(/\n( *(at )?)/);q=w&&w[1]||"",re=-1<_.stack.indexOf(` +function rme(t,e){for(var a=0;ar[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 a(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=a(i);fetch(i.href,s)}})();var T_=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Fc(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var rE={exports:{}},a0={};var TH;function ime(){if(TH)return a0;TH=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function a(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 a0.Fragment=e,a0.jsx=a,a0.jsxs=a,a0}var AH;function sme(){return AH||(AH=1,rE.exports=ime()),rE.exports}var n=sme(),iE={exports:{}},Ka={};var jH;function ome(){if(jH)return Ka;jH=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),a=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(Y){return Y===null||typeof Y!="object"?null:(Y=p&&Y[p]||Y["@@iterator"],typeof Y=="function"?Y:null)}var g={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},v=Object.assign,b={};function x(Y,re,pe){this.props=Y,this.context=re,this.refs=b,this.updater=pe||g}x.prototype.isReactComponent={},x.prototype.setState=function(Y,re){if(typeof Y!="object"&&typeof Y!="function"&&Y!=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,Y,re,"setState")},x.prototype.forceUpdate=function(Y){this.updater.enqueueForceUpdate(this,Y,"forceUpdate")};function S(){}S.prototype=x.prototype;function k(Y,re,pe){this.props=Y,this.context=re,this.refs=b,this.updater=pe||g}var C=k.prototype=new S;C.constructor=k,v(C,x.prototype),C.isPureReactComponent=!0;var P=Array.isArray;function T(){}var j={H:null,A:null,T:null,S:null},F=Object.prototype.hasOwnProperty;function N(Y,re,pe){var me=pe.ref;return{$$typeof:t,type:Y,key:re,ref:me!==void 0?me:null,props:pe}}function D(Y,re){return N(Y.type,re,Y.props)}function R(Y){return typeof Y=="object"&&Y!==null&&Y.$$typeof===t}function B(Y){var re={"=":"=0",":":"=2"};return"$"+Y.replace(/[=:]/g,function(pe){return re[pe]})}var z=/\/+/g;function L(Y,re){return typeof Y=="object"&&Y!==null&&Y.key!=null?B(""+Y.key):re.toString(36)}function Q(Y){switch(Y.status){case"fulfilled":return Y.value;case"rejected":throw Y.reason;default:switch(typeof Y.status=="string"?Y.then(T,T):(Y.status="pending",Y.then(function(re){Y.status==="pending"&&(Y.status="fulfilled",Y.value=re)},function(re){Y.status==="pending"&&(Y.status="rejected",Y.reason=re)})),Y.status){case"fulfilled":return Y.value;case"rejected":throw Y.reason}}throw Y}function ee(Y,re,pe,me,be){var H=typeof Y;(H==="undefined"||H==="boolean")&&(Y=null);var J=!1;if(Y===null)J=!0;else switch(H){case"bigint":case"string":case"number":J=!0;break;case"object":switch(Y.$$typeof){case t:case e:J=!0;break;case u:return J=Y._init,ee(J(Y._payload),re,pe,me,be)}}if(J)return be=be(Y),J=me===""?"."+L(Y,0):me,P(be)?(pe="",J!=null&&(pe=J.replace(z,"$&/")+"/"),ee(be,re,pe,"",function(q){return q})):be!=null&&(R(be)&&(be=D(be,pe+(be.key==null||Y&&Y.key===be.key?"":(""+be.key).replace(z,"$&/")+"/")+J)),re.push(be)),1;J=0;var A=me===""?".":me+":";if(P(Y))for(var M=0;M>>1,ue=ee[de];if(0>>1;dei(pe,ce))mei(be,pe)?(ee[de]=be,ee[me]=ce,de=me):(ee[de]=pe,ee[re]=ce,de=re);else if(mei(be,ce))ee[de]=be,ee[me]=ce,de=me;else break e}}return Z}function i(ee,Z){var ce=ee.sortIndex-Z.sortIndex;return ce!==0?ce:ee.id-Z.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,g=!1,v=!1,b=!1,x=typeof setTimeout=="function"?setTimeout:null,S=typeof clearTimeout=="function"?clearTimeout:null,k=typeof setImmediate<"u"?setImmediate:null;function C(ee){for(var Z=a(d);Z!==null;){if(Z.callback===null)r(d);else if(Z.startTime<=ee)r(d),Z.sortIndex=Z.expirationTime,e(c,Z);else break;Z=a(d)}}function P(ee){if(v=!1,C(ee),!g)if(a(c)!==null)g=!0,T||(T=!0,B());else{var Z=a(d);Z!==null&&Q(P,Z.startTime-ee)}}var T=!1,j=-1,F=5,N=-1;function D(){return b?!0:!(t.unstable_now()-Nee&&D());){var de=m.callback;if(typeof de=="function"){m.callback=null,p=m.priorityLevel;var ue=de(m.expirationTime<=ee);if(ee=t.unstable_now(),typeof ue=="function"){m.callback=ue,C(ee),Z=!0;break t}m===a(c)&&r(c),C(ee)}else r(c);m=a(c)}if(m!==null)Z=!0;else{var Y=a(d);Y!==null&&Q(P,Y.startTime-ee),Z=!1}}break e}finally{m=null,p=ce,f=!1}Z=void 0}}finally{Z?B():T=!1}}}var B;if(typeof k=="function")B=function(){k(R)};else if(typeof MessageChannel<"u"){var z=new MessageChannel,L=z.port2;z.port1.onmessage=R,B=function(){L.postMessage(null)}}else B=function(){x(R,0)};function Q(ee,Z){j=x(function(){ee(t.unstable_now())},Z)}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(ee){ee.callback=null},t.unstable_forceFrameRate=function(ee){0>ee||125de?(ee.sortIndex=ce,e(d,ee),a(c)===null&&ee===a(d)&&(v?(S(j),j=-1):v=!0,Q(P,ce-de))):(ee.sortIndex=ue,e(c,ee),g||f||(g=!0,T||(T=!0,B()))),ee},t.unstable_shouldYield=D,t.unstable_wrapCallback=function(ee){var Z=p;return function(){var ce=p;p=Z;try{return ee.apply(this,arguments)}finally{p=ce}}}})(lE)),lE}var DH;function dme(){return DH||(DH=1,oE.exports=cme()),oE.exports}var cE={exports:{}},Hs={};var FH;function ume(){if(FH)return Hs;FH=1;var t=ob();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(),cE.exports=ume(),cE.exports}var RH;function mme(){if(RH)return n0;RH=1;var t=dme(),e=ob(),a=JX();function r(h){var w="https://react.dev/errors/"+h;if(1ue||(h.current=de[ue],de[ue]=null,ue--)}function pe(h,w){ue++,de[ue]=h.current,h.current=w}var me=Y(null),be=Y(null),H=Y(null),J=Y(null);function A(h,w){switch(pe(H,w),pe(be,h),pe(me,null),w.nodeType){case 9:case 11:h=(h=w.documentElement)&&(h=h.namespaceURI)?Xq(h):0;break;default:if(h=w.tagName,w=w.namespaceURI)w=Xq(w),h=Zq(w,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}re(me),pe(me,h)}function M(){re(me),re(be),re(H)}function q(h){h.memoizedState!==null&&pe(J,h);var w=me.current,_=Zq(w,h.type);w!==_&&(pe(be,h),pe(me,_))}function W(h){be.current===h&&(re(me),re(be)),J.current===h&&(re(J),Zv._currentValue=ce)}var U,se;function O(h){if(U===void 0)try{throw Error()}catch(_){var w=_.stack.trim().match(/\n( *(at )?)/);U=w&&w[1]||"",se=-1<_.stack.indexOf(` at`)?" ()":-1<_.stack.indexOf("@")?"@unknown:0:0":""}return` -`+q+h+re}var G=!1;function K(h,w){if(!h||G)return"";G=!0;var _=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var E={DetermineComponentFrameRoot:function(){try{if(w){var Gt=function(){throw Error()};if(Object.defineProperty(Gt.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(Gt,[])}catch(Ut){var Lt=Ut}Reflect.construct(h,[],Gt)}else{try{Gt.call()}catch(Ut){Lt=Ut}h.call(Gt.prototype)}}else{try{throw Error()}catch(Ut){Lt=Ut}(Gt=h())&&typeof Gt.catch=="function"&&Gt.catch(function(){})}}catch(Ut){if(Ut&&Lt&&typeof Ut.stack=="string")return[Ut.stack,Lt.stack]}return[null,null]}};E.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var V=Object.getOwnPropertyDescriptor(E.DetermineComponentFrameRoot,"name");V&&V.configurable&&Object.defineProperty(E.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var te=E.DetermineComponentFrameRoot(),we=te[0],qe=te[1];if(we&&qe){var mt=we.split(` +`+U+h+se}var $=!1;function K(h,w){if(!h||$)return"";$=!0;var _=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var E={DetermineComponentFrameRoot:function(){try{if(w){var Gt=function(){throw Error()};if(Object.defineProperty(Gt.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(Gt,[])}catch(Bt){var Lt=Bt}Reflect.construct(h,[],Gt)}else{try{Gt.call()}catch(Bt){Lt=Bt}h.call(Gt.prototype)}}else{try{throw Error()}catch(Bt){Lt=Bt}(Gt=h())&&typeof Gt.catch=="function"&&Gt.catch(function(){})}}catch(Bt){if(Bt&&Lt&&typeof Bt.stack=="string")return[Bt.stack,Lt.stack]}return[null,null]}};E.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var G=Object.getOwnPropertyDescriptor(E.DetermineComponentFrameRoot,"name");G&&G.configurable&&Object.defineProperty(E.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var te=E.DetermineComponentFrameRoot(),we=te[0],qe=te[1];if(we&&qe){var mt=we.split(` `),Et=qe.split(` -`);for(V=E=0;EV||mt[E]!==Et[V]){var Ht=` -`+mt[E].replace(" at new "," at ");return h.displayName&&Ht.includes("")&&(Ht=Ht.replace("",h.displayName)),Ht}while(1<=E&&0<=V);break}}}finally{G=!1,Error.prepareStackTrace=_}return(_=h?h.displayName||h.name:"")?U(_):""}function Z(h,w){switch(h.tag){case 26:case 27:case 5:return U(h.type);case 16:return U("Lazy");case 13:return h.child!==w&&w!==null?U("Suspense Fallback"):U("Suspense");case 19:return U("SuspenseList");case 0:case 15:return K(h.type,!1);case 11:return K(h.type.render,!1);case 1:return K(h.type,!0);case 31:return U("Activity");default:return""}}function ie(h){try{var w="",_=null;do w+=Z(h,_),_=h,h=h.return;while(h);return w}catch(E){return` +`);for(G=E=0;EG||mt[E]!==Et[G]){var Ht=` +`+mt[E].replace(" at new "," at ");return h.displayName&&Ht.includes("")&&(Ht=Ht.replace("",h.displayName)),Ht}while(1<=E&&0<=G);break}}}finally{$=!1,Error.prepareStackTrace=_}return(_=h?h.displayName||h.name:"")?O(_):""}function X(h,w){switch(h.tag){case 26:case 27:case 5:return O(h.type);case 16:return O("Lazy");case 13:return h.child!==w&&w!==null?O("Suspense Fallback"):O("Suspense");case 19:return O("SuspenseList");case 0:case 15:return K(h.type,!1);case 11:return K(h.type.render,!1);case 1:return K(h.type,!0);case 31:return O("Activity");default:return""}}function ie(h){try{var w="",_=null;do w+=X(h,_),_=h,h=h.return;while(h);return w}catch(E){return` Error generating stack: `+E.message+` -`+E.stack}}var oe=Object.prototype.hasOwnProperty,he=t.unstable_scheduleCallback,ce=t.unstable_cancelCallback,fe=t.unstable_shouldYield,$=t.unstable_requestPaint,I=t.unstable_now,ae=t.unstable_getCurrentPriorityLevel,ge=t.unstable_ImmediatePriority,xe=t.unstable_UserBlockingPriority,ve=t.unstable_NormalPriority,je=t.unstable_LowPriority,Me=t.unstable_IdlePriority,Se=t.log,Be=t.unstable_setDisableYieldValue,_e=null,Ie=null;function Fe(h){if(typeof Se=="function"&&Be(h),Ie&&typeof Ie.setStrictMode=="function")try{Ie.setStrictMode(_e,h)}catch{}}var He=Math.clz32?Math.clz32:Le,ze=Math.log,it=Math.LN2;function Le(h){return h>>>=0,h===0?32:31-(ze(h)/it|0)|0}var st=256,Te=262144,Xe=4194304;function Ve(h){var w=h&42;if(w!==0)return w;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 Ce(h,w,_){var E=h.pendingLanes;if(E===0)return 0;var V=0,te=h.suspendedLanes,we=h.pingedLanes;h=h.warmLanes;var qe=E&134217727;return qe!==0?(E=qe&~te,E!==0?V=Ve(E):(we&=qe,we!==0?V=Ve(we):_||(_=qe&~h,_!==0&&(V=Ve(_))))):(qe=E&~te,qe!==0?V=Ve(qe):we!==0?V=Ve(we):_||(_=E&~h,_!==0&&(V=Ve(_)))),V===0?0:w!==0&&w!==V&&(w&te)===0&&(te=V&-V,_=w&-w,te>=_||te===32&&(_&4194048)!==0)?w:V}function Oe(h,w){return(h.pendingLanes&~(h.suspendedLanes&~h.pingedLanes)&w)===0}function et(h,w){switch(h){case 1:case 2:case 4:case 8:case 64:return w+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 w+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 We(){var h=Xe;return Xe<<=1,(Xe&62914560)===0&&(Xe=4194304),h}function Ae(h){for(var w=[],_=0;31>_;_++)w.push(h);return w}function at(h,w){h.pendingLanes|=w,w!==268435456&&(h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0)}function nt(h,w,_,E,V,te){var we=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,mt=h.expirationTimes,Et=h.hiddenUpdates;for(_=we&~_;0<_;){var Ht=31-He(_),Gt=1<"u")return null;try{return h.activeElement||h.body}catch{return h.body}}var zn=/[\n"\\]/g;function Oa(h){return h.replace(zn,function(w){return"\\"+w.charCodeAt(0).toString(16)+" "})}function Br(h,w,_,E,V,te,we,qe){h.name="",we!=null&&typeof we!="function"&&typeof we!="symbol"&&typeof we!="boolean"?h.type=we:h.removeAttribute("type"),w!=null?we==="number"?(w===0&&h.value===""||h.value!=w)&&(h.value=""+da(w)):h.value!==""+da(w)&&(h.value=""+da(w)):we!=="submit"&&we!=="reset"||h.removeAttribute("value"),w!=null?ur(h,we,da(w)):_!=null?ur(h,we,da(_)):E!=null&&h.removeAttribute("value"),V==null&&te!=null&&(h.defaultChecked=!!te),V!=null&&(h.checked=V&&typeof V!="function"&&typeof V!="symbol"),qe!=null&&typeof qe!="function"&&typeof qe!="symbol"&&typeof qe!="boolean"?h.name=""+da(qe):h.removeAttribute("name")}function Ua(h,w,_,E,V,te,we,qe){if(te!=null&&typeof te!="function"&&typeof te!="symbol"&&typeof te!="boolean"&&(h.type=te),w!=null||_!=null){if(!(te!=="submit"&&te!=="reset"||w!=null)){ma(h);return}_=_!=null?""+da(_):"",w=w!=null?""+da(w):_,qe||w===h.value||(h.value=w),h.defaultValue=w}E=E??V,E=typeof E!="function"&&typeof E!="symbol"&&!!E,h.checked=qe?h.checked:!!E,h.defaultChecked=!!E,we!=null&&typeof we!="function"&&typeof we!="symbol"&&typeof we!="boolean"&&(h.name=we),ma(h)}function ur(h,w,_){w==="number"&&Ya(h.ownerDocument)===h||h.defaultValue===""+_||(h.defaultValue=""+_)}function Mn(h,w,_,E){if(h=h.options,w){w={};for(var V=0;V<_.length;V++)w["$"+_[V]]=!0;for(_=0;_"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),hp=!1;if(Xa)try{var _d={};Object.defineProperty(_d,"passive",{get:function(){hp=!0}}),window.addEventListener("test",_d,_d),window.removeEventListener("test",_d,_d)}catch{hp=!1}var li=null,Au=null,vi=null;function yf(){if(vi)return vi;var h,w=Au,_=w.length,E,V="value"in li?li.value:li.textContent,te=V.length;for(h=0;h<_&&w[h]===V[h];h++);var we=_-h;for(E=1;E<=we&&w[_-E]===V[te-E];E++);return vi=V.slice(h,1=di),yp=" ",_b=!1;function ye(h,w){switch(h){case"keyup":return kv.indexOf(w.keyCode)!==-1;case"keydown":return w.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function zt(h){return h=h.detail,typeof h=="object"&&"data"in h?h.data:null}var la=!1;function Ta(h,w){switch(h){case"compositionend":return zt(w);case"keypress":return w.which!==32?null:(_b=!0,yp);case"textInput":return h=w.data,h===yp&&_b?null:h;default:return null}}function Ba(h,w){if(la)return h==="compositionend"||!il&&ye(h,w)?(h=yf(),vi=Au=li=null,la=!1,h):null;switch(h){case"paste":return null;case"keypress":if(!(w.ctrlKey||w.altKey||w.metaKey)||w.ctrlKey&&w.altKey){if(w.char&&1=w)return{node:_,offset:w-h};h=E}e:{for(;_;){if(_.nextSibling){_=_.nextSibling;break e}_=_.parentNode}_=void 0}_=Eo(_)}}function Do(h,w){return h&&w?h===w?!0:h&&h.nodeType===3?!1:w&&w.nodeType===3?Do(h,w.parentNode):"contains"in h?h.contains(w):h.compareDocumentPosition?!!(h.compareDocumentPosition(w)&16):!1:!1}function uo(h){h=h!=null&&h.ownerDocument!=null&&h.ownerDocument.defaultView!=null?h.ownerDocument.defaultView:window;for(var w=Ya(h.document);w instanceof h.HTMLIFrameElement;){try{var _=typeof w.contentWindow.location.href=="string"}catch{_=!1}if(_)h=w.contentWindow;else break;w=Ya(h.document)}return w}function wi(h){var w=h&&h.nodeName&&h.nodeName.toLowerCase();return w&&(w==="input"&&(h.type==="text"||h.type==="search"||h.type==="tel"||h.type==="url"||h.type==="password")||w==="textarea"||h.contentEditable==="true")}var Ad=Xa&&"documentMode"in document&&11>=document.documentMode,mi=null,hn=null,En=null,Yr=!1;function vp(h,w,_){var E=_.window===_?_.document:_.nodeType===9?_:_.ownerDocument;Yr||mi==null||mi!==Ya(E)||(E=mi,"selectionStart"in E&&wi(E)?E={start:E.selectionStart,end:E.selectionEnd}:(E=(E.ownerDocument&&E.ownerDocument.defaultView||window).getSelection(),E={anchorNode:E.anchorNode,anchorOffset:E.anchorOffset,focusNode:E.focusNode,focusOffset:E.focusOffset}),En&&vs(En,E)||(En=E,E=p_(hn,"onSelect"),0>=we,V-=we,Md=1<<32-He(w)+V|_<tn?(_n=Ca,Ca=null):_n=Ca.sibling;var Rn=Lt(kt,Ca,jt[tn],Vt);if(Rn===null){Ca===null&&(Ca=_n);break}h&&Ca&&Rn.alternate===null&&w(kt,Ca),xt=te(Rn,xt,tn),Ln===null?Da=Rn:Ln.sibling=Rn,Ln=Rn,Ca=_n}if(tn===jt.length)return _(kt,Ca),Cn&&Iu(kt,tn),Da;if(Ca===null){for(;tntn?(_n=Ca,Ca=null):_n=Ca.sibling;var qp=Lt(kt,Ca,Rn.value,Vt);if(qp===null){Ca===null&&(Ca=_n);break}h&&Ca&&qp.alternate===null&&w(kt,Ca),xt=te(qp,xt,tn),Ln===null?Da=qp:Ln.sibling=qp,Ln=qp,Ca=_n}if(Rn.done)return _(kt,Ca),Cn&&Iu(kt,tn),Da;if(Ca===null){for(;!Rn.done;tn++,Rn=jt.next())Rn=Gt(kt,Rn.value,Vt),Rn!==null&&(xt=te(Rn,xt,tn),Ln===null?Da=Rn:Ln.sibling=Rn,Ln=Rn);return Cn&&Iu(kt,tn),Da}for(Ca=E(Ca);!Rn.done;tn++,Rn=jt.next())Rn=Ut(Ca,kt,tn,Rn.value,Vt),Rn!==null&&(h&&Rn.alternate!==null&&Ca.delete(Rn.key===null?tn:Rn.key),xt=te(Rn,xt,tn),Ln===null?Da=Rn:Ln.sibling=Rn,Ln=Rn);return h&&Ca.forEach(function(nme){return w(kt,nme)}),Cn&&Iu(kt,tn),Da}function ar(kt,xt,jt,Vt){if(typeof jt=="object"&&jt!==null&&jt.type===v&&jt.key===null&&(jt=jt.props.children),typeof jt=="object"&&jt!==null){switch(jt.$$typeof){case f:e:{for(var Da=jt.key;xt!==null;){if(xt.key===Da){if(Da=jt.type,Da===v){if(xt.tag===7){_(kt,xt.sibling),Vt=V(xt,jt.props.children),Vt.return=kt,kt=Vt;break e}}else if(xt.elementType===Da||typeof Da=="object"&&Da!==null&&Da.$$typeof===F&&Af(Da)===xt.type){_(kt,xt.sibling),Vt=V(xt,jt.props),Av(Vt,jt),Vt.return=kt,kt=Vt;break e}_(kt,xt);break}else w(kt,xt);xt=xt.sibling}jt.type===v?(Vt=_f(jt.props.children,kt.mode,Vt,jt.key),Vt.return=kt,kt=Vt):(Vt=jk(jt.type,jt.key,jt.props,null,kt.mode,Vt),Av(Vt,jt),Vt.return=kt,kt=Vt)}return we(kt);case g:e:{for(Da=jt.key;xt!==null;){if(xt.key===Da)if(xt.tag===4&&xt.stateNode.containerInfo===jt.containerInfo&&xt.stateNode.implementation===jt.implementation){_(kt,xt.sibling),Vt=V(xt,jt.children||[]),Vt.return=kt,kt=Vt;break e}else{_(kt,xt);break}else w(kt,xt);xt=xt.sibling}Vt=Sj(jt,kt.mode,Vt),Vt.return=kt,kt=Vt}return we(kt);case F:return jt=Af(jt),ar(kt,xt,jt,Vt)}if(Q(jt))return wa(kt,xt,jt,Vt);if(z(jt)){if(Da=z(jt),typeof Da!="function")throw Error(r(150));return jt=Da.call(jt),Ia(kt,xt,jt,Vt)}if(typeof jt.then=="function")return ar(kt,xt,Ik(jt),Vt);if(jt.$$typeof===k)return ar(kt,xt,Dk(kt,jt),Vt);Ok(kt,jt)}return typeof jt=="string"&&jt!==""||typeof jt=="number"||typeof jt=="bigint"?(jt=""+jt,xt!==null&&xt.tag===6?(_(kt,xt.sibling),Vt=V(xt,jt),Vt.return=kt,kt=Vt):(_(kt,xt),Vt=wj(jt,kt.mode,Vt),Vt.return=kt,kt=Vt),we(kt)):_(kt,xt)}return function(kt,xt,jt,Vt){try{Tv=0;var Da=ar(kt,xt,jt,Vt);return Fb=null,Da}catch(Ca){if(Ca===Db||Ca===Lk)throw Ca;var Ln=sl(29,Ca,null,kt.mode);return Ln.lanes=Vt,Ln.return=kt,Ln}}}var Mf=qU(!0),HU=qU(!1),Np=!1;function Fj(h){h.updateQueue={baseState:h.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Lj(h,w){h=h.updateQueue,w.updateQueue===h&&(w.updateQueue={baseState:h.baseState,firstBaseUpdate:h.firstBaseUpdate,lastBaseUpdate:h.lastBaseUpdate,shared:h.shared,callbacks:null})}function Cp(h){return{lane:h,tag:0,payload:null,callback:null,next:null}}function Pp(h,w,_){var E=h.updateQueue;if(E===null)return null;if(E=E.shared,(Bn&2)!==0){var V=E.pending;return V===null?w.next=w:(w.next=V.next,V.next=w),E.pending=w,w=Ak(h),CU(h,null,_),w}return Tk(h,E,w,_),Ak(h)}function jv(h,w,_){if(w=w.updateQueue,w!==null&&(w=w.shared,(_&4194048)!==0)){var E=w.lanes;E&=h.pendingLanes,_|=E,w.lanes=_,Bt(h,_)}}function Rj(h,w){var _=h.updateQueue,E=h.alternate;if(E!==null&&(E=E.updateQueue,_===E)){var V=null,te=null;if(_=_.firstBaseUpdate,_!==null){do{var we={lane:_.lane,tag:_.tag,payload:_.payload,callback:null,next:null};te===null?V=te=we:te=te.next=we,_=_.next}while(_!==null);te===null?V=te=w:te=te.next=w}else V=te=w;_={baseState:E.baseState,firstBaseUpdate:V,lastBaseUpdate:te,shared:E.shared,callbacks:E.callbacks},h.updateQueue=_;return}h=_.lastBaseUpdate,h===null?_.firstBaseUpdate=w:h.next=w,_.lastBaseUpdate=w}var Ij=!1;function Mv(){if(Ij){var h=Eb;if(h!==null)throw h}}function Ev(h,w,_,E){Ij=!1;var V=h.updateQueue;Np=!1;var te=V.firstBaseUpdate,we=V.lastBaseUpdate,qe=V.shared.pending;if(qe!==null){V.shared.pending=null;var mt=qe,Et=mt.next;mt.next=null,we===null?te=Et:we.next=Et,we=mt;var Ht=h.alternate;Ht!==null&&(Ht=Ht.updateQueue,qe=Ht.lastBaseUpdate,qe!==we&&(qe===null?Ht.firstBaseUpdate=Et:qe.next=Et,Ht.lastBaseUpdate=mt))}if(te!==null){var Gt=V.baseState;we=0,Ht=Et=mt=null,qe=te;do{var Lt=qe.lane&-536870913,Ut=Lt!==qe.lane;if(Ut?(kn&Lt)===Lt:(E&Lt)===Lt){Lt!==0&&Lt===Mb&&(Ij=!0),Ht!==null&&(Ht=Ht.next={lane:0,tag:qe.tag,payload:qe.payload,callback:null,next:null});e:{var wa=h,Ia=qe;Lt=w;var ar=_;switch(Ia.tag){case 1:if(wa=Ia.payload,typeof wa=="function"){Gt=wa.call(ar,Gt,Lt);break e}Gt=wa;break e;case 3:wa.flags=wa.flags&-65537|128;case 0:if(wa=Ia.payload,Lt=typeof wa=="function"?wa.call(ar,Gt,Lt):wa,Lt==null)break e;Gt=m({},Gt,Lt);break e;case 2:Np=!0}}Lt=qe.callback,Lt!==null&&(h.flags|=64,Ut&&(h.flags|=8192),Ut=V.callbacks,Ut===null?V.callbacks=[Lt]:Ut.push(Lt))}else Ut={lane:Lt,tag:qe.tag,payload:qe.payload,callback:qe.callback,next:null},Ht===null?(Et=Ht=Ut,mt=Gt):Ht=Ht.next=Ut,we|=Lt;if(qe=qe.next,qe===null){if(qe=V.shared.pending,qe===null)break;Ut=qe,qe=Ut.next,Ut.next=null,V.lastBaseUpdate=Ut,V.shared.pending=null}}while(!0);Ht===null&&(mt=Gt),V.baseState=mt,V.firstBaseUpdate=Et,V.lastBaseUpdate=Ht,te===null&&(V.shared.lanes=0),Ep|=we,h.lanes=we,h.memoizedState=Gt}}function $U(h,w){if(typeof h!="function")throw Error(r(191,h));h.call(w)}function VU(h,w){var _=h.callbacks;if(_!==null)for(h.callbacks=null,h=0;h<_.length;h++)$U(_[h],w)}var Lb=Y(null),zk=Y(0);function GU(h,w){h=Ku,pe(zk,h),pe(Lb,w),Ku=h|w.baseLanes}function Oj(){pe(zk,Ku),pe(Lb,Lb.current)}function zj(){Ku=zk.current,se(Lb),se(zk)}var ol=Y(null),Ql=null;function Tp(h){var w=h.alternate;pe(pi,pi.current&1),pe(ol,h),Ql===null&&(w===null||Lb.current!==null||w.memoizedState!==null)&&(Ql=h)}function Uj(h){pe(pi,pi.current),pe(ol,h),Ql===null&&(Ql=h)}function WU(h){h.tag===22?(pe(pi,pi.current),pe(ol,h),Ql===null&&(Ql=h)):Ap()}function Ap(){pe(pi,pi.current),pe(ol,ol.current)}function ll(h){se(ol),Ql===h&&(Ql=null),se(pi)}var pi=Y(0);function Uk(h){for(var w=h;w!==null;){if(w.tag===13){var _=w.memoizedState;if(_!==null&&(_=_.dehydrated,_===null||GM(_)||WM(_)))return w}else if(w.tag===19&&(w.memoizedProps.revealOrder==="forwards"||w.memoizedProps.revealOrder==="backwards"||w.memoizedProps.revealOrder==="unstable_legacy-backwards"||w.memoizedProps.revealOrder==="together")){if((w.flags&128)!==0)return w}else if(w.child!==null){w.child.return=w,w=w.child;continue}if(w===h)break;for(;w.sibling===null;){if(w.return===null||w.return===h)return null;w=w.return}w.sibling.return=w.return,w=w.sibling}return null}var Uu=0,Za=null,er=null,ki=null,Bk=!1,Rb=!1,Ef=!1,qk=0,Dv=0,Ib=null,Wde=0;function Xr(){throw Error(r(321))}function Bj(h,w){if(w===null)return!1;for(var _=0;_te?te:8;var we=ee.T,qe={};ee.T=qe,aM(h,!1,w,_);try{var mt=V(),Et=ee.S;if(Et!==null&&Et(qe,mt),mt!==null&&typeof mt=="object"&&typeof mt.then=="function"){var Ht=Gde(mt,E);Lv(h,w,Ht,ul(h))}else Lv(h,w,E,ul(h))}catch(Gt){Lv(h,w,{then:function(){},status:"rejected",reason:Gt},ul())}finally{J.p=te,we!==null&&qe.types!==null&&(we.types=qe.types),ee.T=we}}function Zde(){}function eM(h,w,_,E){if(h.tag!==5)throw Error(r(476));var V=kB(h).queue;SB(h,V,w,le,_===null?Zde:function(){return _B(h),_(E)})}function kB(h){var w=h.memoizedState;if(w!==null)return w;w={memoizedState:le,baseState:le,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bu,lastRenderedState:le},next:null};var _={};return w.next={memoizedState:_,baseState:_,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bu,lastRenderedState:_},next:null},h.memoizedState=w,h=h.alternate,h!==null&&(h.memoizedState=w),w}function _B(h){var w=kB(h);w.next===null&&(w=h.alternate.memoizedState),Lv(h,w.next.queue,{},ul())}function tM(){return Ss(Zv)}function NB(){return hi().memoizedState}function CB(){return hi().memoizedState}function Jde(h){for(var w=h.return;w!==null;){switch(w.tag){case 24:case 3:var _=ul();h=Cp(_);var E=Pp(w,h,_);E!==null&&(Oo(E,w,_),jv(E,w,_)),w={cache:jj()},h.payload=w;return}w=w.return}}function eue(h,w,_){var E=ul();_={lane:E,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null},Kk(h)?TB(w,_):(_=yj(h,w,_,E),_!==null&&(Oo(_,h,E),AB(_,w,E)))}function PB(h,w,_){var E=ul();Lv(h,w,_,E)}function Lv(h,w,_,E){var V={lane:E,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null};if(Kk(h))TB(w,V);else{var te=h.alternate;if(h.lanes===0&&(te===null||te.lanes===0)&&(te=w.lastRenderedReducer,te!==null))try{var we=w.lastRenderedState,qe=te(we,_);if(V.hasEagerState=!0,V.eagerState=qe,Mr(qe,we))return Tk(h,w,V,0),hr===null&&Pk(),!1}catch{}if(_=yj(h,w,V,E),_!==null)return Oo(_,h,E),AB(_,w,E),!0}return!1}function aM(h,w,_,E){if(E={lane:2,revertLane:FM(),gesture:null,action:E,hasEagerState:!1,eagerState:null,next:null},Kk(h)){if(w)throw Error(r(479))}else w=yj(h,_,E,2),w!==null&&Oo(w,h,2)}function Kk(h){var w=h.alternate;return h===Za||w!==null&&w===Za}function TB(h,w){Rb=Bk=!0;var _=h.pending;_===null?w.next=w:(w.next=_.next,_.next=w),h.pending=w}function AB(h,w,_){if((_&4194048)!==0){var E=w.lanes;E&=h.pendingLanes,_|=E,w.lanes=_,Bt(h,_)}}var Rv={readContext:Ss,use:$k,useCallback:Xr,useContext:Xr,useEffect:Xr,useImperativeHandle:Xr,useLayoutEffect:Xr,useInsertionEffect:Xr,useMemo:Xr,useReducer:Xr,useRef:Xr,useState:Xr,useDebugValue:Xr,useDeferredValue:Xr,useTransition:Xr,useSyncExternalStore:Xr,useId:Xr,useHostTransitionStatus:Xr,useFormState:Xr,useActionState:Xr,useOptimistic:Xr,useMemoCache:Xr,useCacheRefresh:Xr};Rv.useEffectEvent=Xr;var jB={readContext:Ss,use:$k,useCallback:function(h,w){return mo().memoizedState=[h,w===void 0?null:w],h},useContext:Ss,useEffect:pB,useImperativeHandle:function(h,w,_){_=_!=null?_.concat([h]):null,Gk(4194308,4,bB.bind(null,w,h),_)},useLayoutEffect:function(h,w){return Gk(4194308,4,h,w)},useInsertionEffect:function(h,w){Gk(4,2,h,w)},useMemo:function(h,w){var _=mo();w=w===void 0?null:w;var E=h();if(Ef){Fe(!0);try{h()}finally{Fe(!1)}}return _.memoizedState=[E,w],E},useReducer:function(h,w,_){var E=mo();if(_!==void 0){var V=_(w);if(Ef){Fe(!0);try{_(w)}finally{Fe(!1)}}}else V=w;return E.memoizedState=E.baseState=V,h={pending:null,lanes:0,dispatch:null,lastRenderedReducer:h,lastRenderedState:V},E.queue=h,h=h.dispatch=eue.bind(null,Za,h),[E.memoizedState,h]},useRef:function(h){var w=mo();return h={current:h},w.memoizedState=h},useState:function(h){h=Qj(h);var w=h.queue,_=PB.bind(null,Za,w);return w.dispatch=_,[h.memoizedState,_]},useDebugValue:Zj,useDeferredValue:function(h,w){var _=mo();return Jj(_,h,w)},useTransition:function(){var h=Qj(!1);return h=SB.bind(null,Za,h.queue,!0,!1),mo().memoizedState=h,[!1,h]},useSyncExternalStore:function(h,w,_){var E=Za,V=mo();if(Cn){if(_===void 0)throw Error(r(407));_=_()}else{if(_=w(),hr===null)throw Error(r(349));(kn&127)!==0||XU(E,w,_)}V.memoizedState=_;var te={value:_,getSnapshot:w};return V.queue=te,pB(JU.bind(null,E,te,h),[h]),E.flags|=2048,Ob(9,{destroy:void 0},ZU.bind(null,E,te,_,w),null),_},useId:function(){var h=mo(),w=hr.identifierPrefix;if(Cn){var _=Ed,E=Md;_=(E&~(1<<32-He(E)-1)).toString(32)+_,w="_"+w+"R_"+_,_=qk++,0<_&&(w+="H"+_.toString(32)),w+="_"}else _=Wde++,w="_"+w+"r_"+_.toString(32)+"_";return h.memoizedState=w},useHostTransitionStatus:tM,useFormState:lB,useActionState:lB,useOptimistic:function(h){var w=mo();w.memoizedState=w.baseState=h;var _={pending:null,lanes:0,dispatch:null,lastRenderedReducer:null,lastRenderedState:null};return w.queue=_,w=aM.bind(null,Za,!0,_),_.dispatch=w,[h,w]},useMemoCache:Gj,useCacheRefresh:function(){return mo().memoizedState=Jde.bind(null,Za)},useEffectEvent:function(h){var w=mo(),_={impl:h};return w.memoizedState=_,function(){if((Bn&2)!==0)throw Error(r(440));return _.impl.apply(void 0,arguments)}}},nM={readContext:Ss,use:$k,useCallback:yB,useContext:Ss,useEffect:Xj,useImperativeHandle:xB,useInsertionEffect:fB,useLayoutEffect:gB,useMemo:vB,useReducer:Vk,useRef:mB,useState:function(){return Vk(Bu)},useDebugValue:Zj,useDeferredValue:function(h,w){var _=hi();return wB(_,er.memoizedState,h,w)},useTransition:function(){var h=Vk(Bu)[0],w=hi().memoizedState;return[typeof h=="boolean"?h:Fv(h),w]},useSyncExternalStore:YU,useId:NB,useHostTransitionStatus:tM,useFormState:cB,useActionState:cB,useOptimistic:function(h,w){var _=hi();return aB(_,er,h,w)},useMemoCache:Gj,useCacheRefresh:CB};nM.useEffectEvent=hB;var MB={readContext:Ss,use:$k,useCallback:yB,useContext:Ss,useEffect:Xj,useImperativeHandle:xB,useInsertionEffect:fB,useLayoutEffect:gB,useMemo:vB,useReducer:Kj,useRef:mB,useState:function(){return Kj(Bu)},useDebugValue:Zj,useDeferredValue:function(h,w){var _=hi();return er===null?Jj(_,h,w):wB(_,er.memoizedState,h,w)},useTransition:function(){var h=Kj(Bu)[0],w=hi().memoizedState;return[typeof h=="boolean"?h:Fv(h),w]},useSyncExternalStore:YU,useId:NB,useHostTransitionStatus:tM,useFormState:uB,useActionState:uB,useOptimistic:function(h,w){var _=hi();return er!==null?aB(_,er,h,w):(_.baseState=h,[h,_.queue.dispatch])},useMemoCache:Gj,useCacheRefresh:CB};MB.useEffectEvent=hB;function rM(h,w,_,E){w=h.memoizedState,_=_(E,w),_=_==null?w:m({},w,_),h.memoizedState=_,h.lanes===0&&(h.updateQueue.baseState=_)}var iM={enqueueSetState:function(h,w,_){h=h._reactInternals;var E=ul(),V=Cp(E);V.payload=w,_!=null&&(V.callback=_),w=Pp(h,V,E),w!==null&&(Oo(w,h,E),jv(w,h,E))},enqueueReplaceState:function(h,w,_){h=h._reactInternals;var E=ul(),V=Cp(E);V.tag=1,V.payload=w,_!=null&&(V.callback=_),w=Pp(h,V,E),w!==null&&(Oo(w,h,E),jv(w,h,E))},enqueueForceUpdate:function(h,w){h=h._reactInternals;var _=ul(),E=Cp(_);E.tag=2,w!=null&&(E.callback=w),w=Pp(h,E,_),w!==null&&(Oo(w,h,_),jv(w,h,_))}};function EB(h,w,_,E,V,te,we){return h=h.stateNode,typeof h.shouldComponentUpdate=="function"?h.shouldComponentUpdate(E,te,we):w.prototype&&w.prototype.isPureReactComponent?!vs(_,E)||!vs(V,te):!0}function DB(h,w,_,E){h=w.state,typeof w.componentWillReceiveProps=="function"&&w.componentWillReceiveProps(_,E),typeof w.UNSAFE_componentWillReceiveProps=="function"&&w.UNSAFE_componentWillReceiveProps(_,E),w.state!==h&&iM.enqueueReplaceState(w,w.state,null)}function Df(h,w){var _=w;if("ref"in w){_={};for(var E in w)E!=="ref"&&(_[E]=w[E])}if(h=h.defaultProps){_===w&&(_=m({},_));for(var V in h)_[V]===void 0&&(_[V]=h[V])}return _}function FB(h){Ck(h)}function LB(h){console.error(h)}function RB(h){Ck(h)}function Qk(h,w){try{var _=h.onUncaughtError;_(w.value,{componentStack:w.stack})}catch(E){setTimeout(function(){throw E})}}function IB(h,w,_){try{var E=h.onCaughtError;E(_.value,{componentStack:_.stack,errorBoundary:w.tag===1?w.stateNode:null})}catch(V){setTimeout(function(){throw V})}}function sM(h,w,_){return _=Cp(_),_.tag=3,_.payload={element:null},_.callback=function(){Qk(h,w)},_}function OB(h){return h=Cp(h),h.tag=3,h}function zB(h,w,_,E){var V=_.type.getDerivedStateFromError;if(typeof V=="function"){var te=E.value;h.payload=function(){return V(te)},h.callback=function(){IB(w,_,E)}}var we=_.stateNode;we!==null&&typeof we.componentDidCatch=="function"&&(h.callback=function(){IB(w,_,E),typeof V!="function"&&(Dp===null?Dp=new Set([this]):Dp.add(this));var qe=E.stack;this.componentDidCatch(E.value,{componentStack:qe!==null?qe:""})})}function tue(h,w,_,E,V){if(_.flags|=32768,E!==null&&typeof E=="object"&&typeof E.then=="function"){if(w=_.alternate,w!==null&&jb(w,_,V,!0),_=ol.current,_!==null){switch(_.tag){case 31:case 13:return Ql===null?o_():_.alternate===null&&Zr===0&&(Zr=3),_.flags&=-257,_.flags|=65536,_.lanes=V,E===Rk?_.flags|=16384:(w=_.updateQueue,w===null?_.updateQueue=new Set([E]):w.add(E),MM(h,E,V)),!1;case 22:return _.flags|=65536,E===Rk?_.flags|=16384:(w=_.updateQueue,w===null?(w={transitions:null,markerInstances:null,retryQueue:new Set([E])},_.updateQueue=w):(_=w.retryQueue,_===null?w.retryQueue=new Set([E]):_.add(E)),MM(h,E,V)),!1}throw Error(r(435,_.tag))}return MM(h,E,V),o_(),!1}if(Cn)return w=ol.current,w!==null?((w.flags&65536)===0&&(w.flags|=256),w.flags|=65536,w.lanes=V,E!==Nj&&(h=Error(r(422),{cause:E}),Nv(Vl(h,_)))):(E!==Nj&&(w=Error(r(423),{cause:E}),Nv(Vl(w,_))),h=h.current.alternate,h.flags|=65536,V&=-V,h.lanes|=V,E=Vl(E,_),V=sM(h.stateNode,E,V),Rj(h,V),Zr!==4&&(Zr=2)),!1;var te=Error(r(520),{cause:E});if(te=Vl(te,_),$v===null?$v=[te]:$v.push(te),Zr!==4&&(Zr=2),w===null)return!0;E=Vl(E,_),_=w;do{switch(_.tag){case 3:return _.flags|=65536,h=V&-V,_.lanes|=h,h=sM(_.stateNode,E,h),Rj(_,h),!1;case 1:if(w=_.type,te=_.stateNode,(_.flags&128)===0&&(typeof w.getDerivedStateFromError=="function"||te!==null&&typeof te.componentDidCatch=="function"&&(Dp===null||!Dp.has(te))))return _.flags|=65536,V&=-V,_.lanes|=V,V=OB(V),zB(V,h,_,E),Rj(_,V),!1}_=_.return}while(_!==null);return!1}var oM=Error(r(461)),_i=!1;function ks(h,w,_,E){w.child=h===null?HU(w,null,_,E):Mf(w,h.child,_,E)}function UB(h,w,_,E,V){_=_.render;var te=w.ref;if("ref"in E){var we={};for(var qe in E)qe!=="ref"&&(we[qe]=E[qe])}else we=E;return Pf(w),E=qj(h,w,_,we,te,V),qe=Hj(),h!==null&&!_i?($j(h,w,V),qu(h,w,V)):(Cn&&qe&&kj(w),w.flags|=1,ks(h,w,E,V),w.child)}function BB(h,w,_,E,V){if(h===null){var te=_.type;return typeof te=="function"&&!vj(te)&&te.defaultProps===void 0&&_.compare===null?(w.tag=15,w.type=te,qB(h,w,te,E,V)):(h=jk(_.type,null,E,w,w.mode,V),h.ref=w.ref,h.return=w,w.child=h)}if(te=h.child,!fM(h,V)){var we=te.memoizedProps;if(_=_.compare,_=_!==null?_:vs,_(we,E)&&h.ref===w.ref)return qu(h,w,V)}return w.flags|=1,h=Ru(te,E),h.ref=w.ref,h.return=w,w.child=h}function qB(h,w,_,E,V){if(h!==null){var te=h.memoizedProps;if(vs(te,E)&&h.ref===w.ref)if(_i=!1,w.pendingProps=E=te,fM(h,V))(h.flags&131072)!==0&&(_i=!0);else return w.lanes=h.lanes,qu(h,w,V)}return lM(h,w,_,E,V)}function HB(h,w,_,E){var V=E.children,te=h!==null?h.memoizedState:null;if(h===null&&w.stateNode===null&&(w.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),E.mode==="hidden"){if((w.flags&128)!==0){if(te=te!==null?te.baseLanes|_:_,h!==null){for(E=w.child=h.child,V=0;E!==null;)V=V|E.lanes|E.childLanes,E=E.sibling;E=V&~te}else E=0,w.child=null;return $B(h,w,te,_,E)}if((_&536870912)!==0)w.memoizedState={baseLanes:0,cachePool:null},h!==null&&Fk(w,te!==null?te.cachePool:null),te!==null?GU(w,te):Oj(),WU(w);else return E=w.lanes=536870912,$B(h,w,te!==null?te.baseLanes|_:_,_,E)}else te!==null?(Fk(w,te.cachePool),GU(w,te),Ap(),w.memoizedState=null):(h!==null&&Fk(w,null),Oj(),Ap());return ks(h,w,V,_),w.child}function Iv(h,w){return h!==null&&h.tag===22||w.stateNode!==null||(w.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),w.sibling}function $B(h,w,_,E,V){var te=Ej();return te=te===null?null:{parent:Si._currentValue,pool:te},w.memoizedState={baseLanes:_,cachePool:te},h!==null&&Fk(w,null),Oj(),WU(w),h!==null&&jb(h,w,E,!0),w.childLanes=V,null}function Yk(h,w){return w=Zk({mode:w.mode,children:w.children},h.mode),w.ref=h.ref,h.child=w,w.return=h,w}function VB(h,w,_){return Mf(w,h.child,null,_),h=Yk(w,w.pendingProps),h.flags|=2,ll(w),w.memoizedState=null,h}function aue(h,w,_){var E=w.pendingProps,V=(w.flags&128)!==0;if(w.flags&=-129,h===null){if(Cn){if(E.mode==="hidden")return h=Yk(w,E),w.lanes=536870912,Iv(null,h);if(Uj(w),(h=_r)?(h=nH(h,Kl),h=h!==null&&h.data==="&"?h:null,h!==null&&(w.memoizedState={dehydrated:h,treeContext:wp!==null?{id:Md,overflow:Ed}:null,retryLane:536870912,hydrationErrors:null},_=TU(h),_.return=w,w.child=_,ws=w,_r=null)):h=null,h===null)throw kp(w);return w.lanes=536870912,null}return Yk(w,E)}var te=h.memoizedState;if(te!==null){var we=te.dehydrated;if(Uj(w),V)if(w.flags&256)w.flags&=-257,w=VB(h,w,_);else if(w.memoizedState!==null)w.child=h.child,w.flags|=128,w=null;else throw Error(r(558));else if(_i||jb(h,w,_,!1),V=(_&h.childLanes)!==0,_i||V){if(E=hr,E!==null&&(we=ft(E,_),we!==0&&we!==te.retryLane))throw te.retryLane=we,kf(h,we),Oo(E,h,we),oM;o_(),w=VB(h,w,_)}else h=te.treeContext,_r=Yl(we.nextSibling),ws=w,Cn=!0,Sp=null,Kl=!1,h!==null&&MU(w,h),w=Yk(w,E),w.flags|=4096;return w}return h=Ru(h.child,{mode:E.mode,children:E.children}),h.ref=w.ref,w.child=h,h.return=w,h}function Xk(h,w){var _=w.ref;if(_===null)h!==null&&h.ref!==null&&(w.flags|=4194816);else{if(typeof _!="function"&&typeof _!="object")throw Error(r(284));(h===null||h.ref!==_)&&(w.flags|=4194816)}}function lM(h,w,_,E,V){return Pf(w),_=qj(h,w,_,E,void 0,V),E=Hj(),h!==null&&!_i?($j(h,w,V),qu(h,w,V)):(Cn&&E&&kj(w),w.flags|=1,ks(h,w,_,V),w.child)}function GB(h,w,_,E,V,te){return Pf(w),w.updateQueue=null,_=QU(w,E,_,V),KU(h),E=Hj(),h!==null&&!_i?($j(h,w,te),qu(h,w,te)):(Cn&&E&&kj(w),w.flags|=1,ks(h,w,_,te),w.child)}function WB(h,w,_,E,V){if(Pf(w),w.stateNode===null){var te=Cb,we=_.contextType;typeof we=="object"&&we!==null&&(te=Ss(we)),te=new _(E,te),w.memoizedState=te.state!==null&&te.state!==void 0?te.state:null,te.updater=iM,w.stateNode=te,te._reactInternals=w,te=w.stateNode,te.props=E,te.state=w.memoizedState,te.refs={},Fj(w),we=_.contextType,te.context=typeof we=="object"&&we!==null?Ss(we):Cb,te.state=w.memoizedState,we=_.getDerivedStateFromProps,typeof we=="function"&&(rM(w,_,we,E),te.state=w.memoizedState),typeof _.getDerivedStateFromProps=="function"||typeof te.getSnapshotBeforeUpdate=="function"||typeof te.UNSAFE_componentWillMount!="function"&&typeof te.componentWillMount!="function"||(we=te.state,typeof te.componentWillMount=="function"&&te.componentWillMount(),typeof te.UNSAFE_componentWillMount=="function"&&te.UNSAFE_componentWillMount(),we!==te.state&&iM.enqueueReplaceState(te,te.state,null),Ev(w,E,te,V),Mv(),te.state=w.memoizedState),typeof te.componentDidMount=="function"&&(w.flags|=4194308),E=!0}else if(h===null){te=w.stateNode;var qe=w.memoizedProps,mt=Df(_,qe);te.props=mt;var Et=te.context,Ht=_.contextType;we=Cb,typeof Ht=="object"&&Ht!==null&&(we=Ss(Ht));var Gt=_.getDerivedStateFromProps;Ht=typeof Gt=="function"||typeof te.getSnapshotBeforeUpdate=="function",qe=w.pendingProps!==qe,Ht||typeof te.UNSAFE_componentWillReceiveProps!="function"&&typeof te.componentWillReceiveProps!="function"||(qe||Et!==we)&&DB(w,te,E,we),Np=!1;var Lt=w.memoizedState;te.state=Lt,Ev(w,E,te,V),Mv(),Et=w.memoizedState,qe||Lt!==Et||Np?(typeof Gt=="function"&&(rM(w,_,Gt,E),Et=w.memoizedState),(mt=Np||EB(w,_,mt,E,Lt,Et,we))?(Ht||typeof te.UNSAFE_componentWillMount!="function"&&typeof te.componentWillMount!="function"||(typeof te.componentWillMount=="function"&&te.componentWillMount(),typeof te.UNSAFE_componentWillMount=="function"&&te.UNSAFE_componentWillMount()),typeof te.componentDidMount=="function"&&(w.flags|=4194308)):(typeof te.componentDidMount=="function"&&(w.flags|=4194308),w.memoizedProps=E,w.memoizedState=Et),te.props=E,te.state=Et,te.context=we,E=mt):(typeof te.componentDidMount=="function"&&(w.flags|=4194308),E=!1)}else{te=w.stateNode,Lj(h,w),we=w.memoizedProps,Ht=Df(_,we),te.props=Ht,Gt=w.pendingProps,Lt=te.context,Et=_.contextType,mt=Cb,typeof Et=="object"&&Et!==null&&(mt=Ss(Et)),qe=_.getDerivedStateFromProps,(Et=typeof qe=="function"||typeof te.getSnapshotBeforeUpdate=="function")||typeof te.UNSAFE_componentWillReceiveProps!="function"&&typeof te.componentWillReceiveProps!="function"||(we!==Gt||Lt!==mt)&&DB(w,te,E,mt),Np=!1,Lt=w.memoizedState,te.state=Lt,Ev(w,E,te,V),Mv();var Ut=w.memoizedState;we!==Gt||Lt!==Ut||Np||h!==null&&h.dependencies!==null&&Ek(h.dependencies)?(typeof qe=="function"&&(rM(w,_,qe,E),Ut=w.memoizedState),(Ht=Np||EB(w,_,Ht,E,Lt,Ut,mt)||h!==null&&h.dependencies!==null&&Ek(h.dependencies))?(Et||typeof te.UNSAFE_componentWillUpdate!="function"&&typeof te.componentWillUpdate!="function"||(typeof te.componentWillUpdate=="function"&&te.componentWillUpdate(E,Ut,mt),typeof te.UNSAFE_componentWillUpdate=="function"&&te.UNSAFE_componentWillUpdate(E,Ut,mt)),typeof te.componentDidUpdate=="function"&&(w.flags|=4),typeof te.getSnapshotBeforeUpdate=="function"&&(w.flags|=1024)):(typeof te.componentDidUpdate!="function"||we===h.memoizedProps&&Lt===h.memoizedState||(w.flags|=4),typeof te.getSnapshotBeforeUpdate!="function"||we===h.memoizedProps&&Lt===h.memoizedState||(w.flags|=1024),w.memoizedProps=E,w.memoizedState=Ut),te.props=E,te.state=Ut,te.context=mt,E=Ht):(typeof te.componentDidUpdate!="function"||we===h.memoizedProps&&Lt===h.memoizedState||(w.flags|=4),typeof te.getSnapshotBeforeUpdate!="function"||we===h.memoizedProps&&Lt===h.memoizedState||(w.flags|=1024),E=!1)}return te=E,Xk(h,w),E=(w.flags&128)!==0,te||E?(te=w.stateNode,_=E&&typeof _.getDerivedStateFromError!="function"?null:te.render(),w.flags|=1,h!==null&&E?(w.child=Mf(w,h.child,null,V),w.child=Mf(w,null,_,V)):ks(h,w,_,V),w.memoizedState=te.state,h=w.child):h=qu(h,w,V),h}function KB(h,w,_,E){return Nf(),w.flags|=256,ks(h,w,_,E),w.child}var cM={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function dM(h){return{baseLanes:h,cachePool:IU()}}function uM(h,w,_){return h=h!==null?h.childLanes&~_:0,w&&(h|=dl),h}function QB(h,w,_){var E=w.pendingProps,V=!1,te=(w.flags&128)!==0,we;if((we=te)||(we=h!==null&&h.memoizedState===null?!1:(pi.current&2)!==0),we&&(V=!0,w.flags&=-129),we=(w.flags&32)!==0,w.flags&=-33,h===null){if(Cn){if(V?Tp(w):Ap(),(h=_r)?(h=nH(h,Kl),h=h!==null&&h.data!=="&"?h:null,h!==null&&(w.memoizedState={dehydrated:h,treeContext:wp!==null?{id:Md,overflow:Ed}:null,retryLane:536870912,hydrationErrors:null},_=TU(h),_.return=w,w.child=_,ws=w,_r=null)):h=null,h===null)throw kp(w);return WM(h)?w.lanes=32:w.lanes=536870912,null}var qe=E.children;return E=E.fallback,V?(Ap(),V=w.mode,qe=Zk({mode:"hidden",children:qe},V),E=_f(E,V,_,null),qe.return=w,E.return=w,qe.sibling=E,w.child=qe,E=w.child,E.memoizedState=dM(_),E.childLanes=uM(h,we,_),w.memoizedState=cM,Iv(null,E)):(Tp(w),mM(w,qe))}var mt=h.memoizedState;if(mt!==null&&(qe=mt.dehydrated,qe!==null)){if(te)w.flags&256?(Tp(w),w.flags&=-257,w=pM(h,w,_)):w.memoizedState!==null?(Ap(),w.child=h.child,w.flags|=128,w=null):(Ap(),qe=E.fallback,V=w.mode,E=Zk({mode:"visible",children:E.children},V),qe=_f(qe,V,_,null),qe.flags|=2,E.return=w,qe.return=w,E.sibling=qe,w.child=E,Mf(w,h.child,null,_),E=w.child,E.memoizedState=dM(_),E.childLanes=uM(h,we,_),w.memoizedState=cM,w=Iv(null,E));else if(Tp(w),WM(qe)){if(we=qe.nextSibling&&qe.nextSibling.dataset,we)var Et=we.dgst;we=Et,E=Error(r(419)),E.stack="",E.digest=we,Nv({value:E,source:null,stack:null}),w=pM(h,w,_)}else if(_i||jb(h,w,_,!1),we=(_&h.childLanes)!==0,_i||we){if(we=hr,we!==null&&(E=ft(we,_),E!==0&&E!==mt.retryLane))throw mt.retryLane=E,kf(h,E),Oo(we,h,E),oM;GM(qe)||o_(),w=pM(h,w,_)}else GM(qe)?(w.flags|=192,w.child=h.child,w=null):(h=mt.treeContext,_r=Yl(qe.nextSibling),ws=w,Cn=!0,Sp=null,Kl=!1,h!==null&&MU(w,h),w=mM(w,E.children),w.flags|=4096);return w}return V?(Ap(),qe=E.fallback,V=w.mode,mt=h.child,Et=mt.sibling,E=Ru(mt,{mode:"hidden",children:E.children}),E.subtreeFlags=mt.subtreeFlags&65011712,Et!==null?qe=Ru(Et,qe):(qe=_f(qe,V,_,null),qe.flags|=2),qe.return=w,E.return=w,E.sibling=qe,w.child=E,Iv(null,E),E=w.child,qe=h.child.memoizedState,qe===null?qe=dM(_):(V=qe.cachePool,V!==null?(mt=Si._currentValue,V=V.parent!==mt?{parent:mt,pool:mt}:V):V=IU(),qe={baseLanes:qe.baseLanes|_,cachePool:V}),E.memoizedState=qe,E.childLanes=uM(h,we,_),w.memoizedState=cM,Iv(h.child,E)):(Tp(w),_=h.child,h=_.sibling,_=Ru(_,{mode:"visible",children:E.children}),_.return=w,_.sibling=null,h!==null&&(we=w.deletions,we===null?(w.deletions=[h],w.flags|=16):we.push(h)),w.child=_,w.memoizedState=null,_)}function mM(h,w){return w=Zk({mode:"visible",children:w},h.mode),w.return=h,h.child=w}function Zk(h,w){return h=sl(22,h,null,w),h.lanes=0,h}function pM(h,w,_){return Mf(w,h.child,null,_),h=mM(w,w.pendingProps.children),h.flags|=2,w.memoizedState=null,h}function YB(h,w,_){h.lanes|=w;var E=h.alternate;E!==null&&(E.lanes|=w),Tj(h.return,w,_)}function hM(h,w,_,E,V,te){var we=h.memoizedState;we===null?h.memoizedState={isBackwards:w,rendering:null,renderingStartTime:0,last:E,tail:_,tailMode:V,treeForkCount:te}:(we.isBackwards=w,we.rendering=null,we.renderingStartTime=0,we.last=E,we.tail=_,we.tailMode=V,we.treeForkCount=te)}function XB(h,w,_){var E=w.pendingProps,V=E.revealOrder,te=E.tail;E=E.children;var we=pi.current,qe=(we&2)!==0;if(qe?(we=we&1|2,w.flags|=128):we&=1,pe(pi,we),ks(h,w,E,_),E=Cn?_v:0,!qe&&h!==null&&(h.flags&128)!==0)e:for(h=w.child;h!==null;){if(h.tag===13)h.memoizedState!==null&&YB(h,_,w);else if(h.tag===19)YB(h,_,w);else if(h.child!==null){h.child.return=h,h=h.child;continue}if(h===w)break e;for(;h.sibling===null;){if(h.return===null||h.return===w)break e;h=h.return}h.sibling.return=h.return,h=h.sibling}switch(V){case"forwards":for(_=w.child,V=null;_!==null;)h=_.alternate,h!==null&&Uk(h)===null&&(V=_),_=_.sibling;_=V,_===null?(V=w.child,w.child=null):(V=_.sibling,_.sibling=null),hM(w,!1,V,_,te,E);break;case"backwards":case"unstable_legacy-backwards":for(_=null,V=w.child,w.child=null;V!==null;){if(h=V.alternate,h!==null&&Uk(h)===null){w.child=V;break}h=V.sibling,V.sibling=_,_=V,V=h}hM(w,!0,_,null,te,E);break;case"together":hM(w,!1,null,null,void 0,E);break;default:w.memoizedState=null}return w.child}function qu(h,w,_){if(h!==null&&(w.dependencies=h.dependencies),Ep|=w.lanes,(_&w.childLanes)===0)if(h!==null){if(jb(h,w,_,!1),(_&w.childLanes)===0)return null}else return null;if(h!==null&&w.child!==h.child)throw Error(r(153));if(w.child!==null){for(h=w.child,_=Ru(h,h.pendingProps),w.child=_,_.return=w;h.sibling!==null;)h=h.sibling,_=_.sibling=Ru(h,h.pendingProps),_.return=w;_.sibling=null}return w.child}function fM(h,w){return(h.lanes&w)!==0?!0:(h=h.dependencies,!!(h!==null&&Ek(h)))}function nue(h,w,_){switch(w.tag){case 3:A(w,w.stateNode.containerInfo),_p(w,Si,h.memoizedState.cache),Nf();break;case 27:case 5:B(w);break;case 4:A(w,w.stateNode.containerInfo);break;case 10:_p(w,w.type,w.memoizedProps.value);break;case 31:if(w.memoizedState!==null)return w.flags|=128,Uj(w),null;break;case 13:var E=w.memoizedState;if(E!==null)return E.dehydrated!==null?(Tp(w),w.flags|=128,null):(_&w.child.childLanes)!==0?QB(h,w,_):(Tp(w),h=qu(h,w,_),h!==null?h.sibling:null);Tp(w);break;case 19:var V=(h.flags&128)!==0;if(E=(_&w.childLanes)!==0,E||(jb(h,w,_,!1),E=(_&w.childLanes)!==0),V){if(E)return XB(h,w,_);w.flags|=128}if(V=w.memoizedState,V!==null&&(V.rendering=null,V.tail=null,V.lastEffect=null),pe(pi,pi.current),E)break;return null;case 22:return w.lanes=0,HB(h,w,_,w.pendingProps);case 24:_p(w,Si,h.memoizedState.cache)}return qu(h,w,_)}function ZB(h,w,_){if(h!==null)if(h.memoizedProps!==w.pendingProps)_i=!0;else{if(!fM(h,_)&&(w.flags&128)===0)return _i=!1,nue(h,w,_);_i=(h.flags&131072)!==0}else _i=!1,Cn&&(w.flags&1048576)!==0&&jU(w,_v,w.index);switch(w.lanes=0,w.tag){case 16:e:{var E=w.pendingProps;if(h=Af(w.elementType),w.type=h,typeof h=="function")vj(h)?(E=Df(h,E),w.tag=1,w=WB(null,w,h,E,_)):(w.tag=0,w=lM(null,w,h,E,_));else{if(h!=null){var V=h.$$typeof;if(V===C){w.tag=11,w=UB(null,w,h,E,_);break e}else if(V===j){w.tag=14,w=BB(null,w,h,E,_);break e}}throw w=L(h)||h,Error(r(306,w,""))}}return w;case 0:return lM(h,w,w.type,w.pendingProps,_);case 1:return E=w.type,V=Df(E,w.pendingProps),WB(h,w,E,V,_);case 3:e:{if(A(w,w.stateNode.containerInfo),h===null)throw Error(r(387));E=w.pendingProps;var te=w.memoizedState;V=te.element,Lj(h,w),Ev(w,E,null,_);var we=w.memoizedState;if(E=we.cache,_p(w,Si,E),E!==te.cache&&Aj(w,[Si],_,!0),Mv(),E=we.element,te.isDehydrated)if(te={element:E,isDehydrated:!1,cache:we.cache},w.updateQueue.baseState=te,w.memoizedState=te,w.flags&256){w=KB(h,w,E,_);break e}else if(E!==V){V=Vl(Error(r(424)),w),Nv(V),w=KB(h,w,E,_);break e}else for(h=w.stateNode.containerInfo,h.nodeType===9?h=h.body:h=h.nodeName==="HTML"?h.ownerDocument.body:h,_r=Yl(h.firstChild),ws=w,Cn=!0,Sp=null,Kl=!0,_=HU(w,null,E,_),w.child=_;_;)_.flags=_.flags&-3|4096,_=_.sibling;else{if(Nf(),E===V){w=qu(h,w,_);break e}ks(h,w,E,_)}w=w.child}return w;case 26:return Xk(h,w),h===null?(_=cH(w.type,null,w.pendingProps,null))?w.memoizedState=_:Cn||(_=w.type,h=w.pendingProps,E=h_(H.current).createElement(_),E[vt]=w,E[Nt]=h,_s(E,_,h),ot(E),w.stateNode=E):w.memoizedState=cH(w.type,h.memoizedProps,w.pendingProps,h.memoizedState),null;case 27:return B(w),h===null&&Cn&&(E=w.stateNode=sH(w.type,w.pendingProps,H.current),ws=w,Kl=!0,V=_r,Ip(w.type)?(KM=V,_r=Yl(E.firstChild)):_r=V),ks(h,w,w.pendingProps.children,_),Xk(h,w),h===null&&(w.flags|=4194304),w.child;case 5:return h===null&&Cn&&((V=E=_r)&&(E=Due(E,w.type,w.pendingProps,Kl),E!==null?(w.stateNode=E,ws=w,_r=Yl(E.firstChild),Kl=!1,V=!0):V=!1),V||kp(w)),B(w),V=w.type,te=w.pendingProps,we=h!==null?h.memoizedProps:null,E=te.children,HM(V,te)?E=null:we!==null&&HM(V,we)&&(w.flags|=32),w.memoizedState!==null&&(V=qj(h,w,Kde,null,null,_),Zv._currentValue=V),Xk(h,w),ks(h,w,E,_),w.child;case 6:return h===null&&Cn&&((h=_=_r)&&(_=Fue(_,w.pendingProps,Kl),_!==null?(w.stateNode=_,ws=w,_r=null,h=!0):h=!1),h||kp(w)),null;case 13:return QB(h,w,_);case 4:return A(w,w.stateNode.containerInfo),E=w.pendingProps,h===null?w.child=Mf(w,null,E,_):ks(h,w,E,_),w.child;case 11:return UB(h,w,w.type,w.pendingProps,_);case 7:return ks(h,w,w.pendingProps,_),w.child;case 8:return ks(h,w,w.pendingProps.children,_),w.child;case 12:return ks(h,w,w.pendingProps.children,_),w.child;case 10:return E=w.pendingProps,_p(w,w.type,E.value),ks(h,w,E.children,_),w.child;case 9:return V=w.type._context,E=w.pendingProps.children,Pf(w),V=Ss(V),E=E(V),w.flags|=1,ks(h,w,E,_),w.child;case 14:return BB(h,w,w.type,w.pendingProps,_);case 15:return qB(h,w,w.type,w.pendingProps,_);case 19:return XB(h,w,_);case 31:return aue(h,w,_);case 22:return HB(h,w,_,w.pendingProps);case 24:return Pf(w),E=Ss(Si),h===null?(V=Ej(),V===null&&(V=hr,te=jj(),V.pooledCache=te,te.refCount++,te!==null&&(V.pooledCacheLanes|=_),V=te),w.memoizedState={parent:E,cache:V},Fj(w),_p(w,Si,V)):((h.lanes&_)!==0&&(Lj(h,w),Ev(w,null,null,_),Mv()),V=h.memoizedState,te=w.memoizedState,V.parent!==E?(V={parent:E,cache:E},w.memoizedState=V,w.lanes===0&&(w.memoizedState=w.updateQueue.baseState=V),_p(w,Si,E)):(E=te.cache,_p(w,Si,E),E!==V.cache&&Aj(w,[Si],_,!0))),ks(h,w,w.pendingProps.children,_),w.child;case 29:throw w.pendingProps}throw Error(r(156,w.tag))}function Hu(h){h.flags|=4}function gM(h,w,_,E,V){if((w=(h.mode&32)!==0)&&(w=!1),w){if(h.flags|=16777216,(V&335544128)===V)if(h.stateNode.complete)h.flags|=8192;else if(Nq())h.flags|=8192;else throw jf=Rk,Dj}else h.flags&=-16777217}function JB(h,w){if(w.type!=="stylesheet"||(w.state.loading&4)!==0)h.flags&=-16777217;else if(h.flags|=16777216,!hH(w))if(Nq())h.flags|=8192;else throw jf=Rk,Dj}function Jk(h,w){w!==null&&(h.flags|=4),h.flags&16384&&(w=h.tag!==22?We():536870912,h.lanes|=w,qb|=w)}function Ov(h,w){if(!Cn)switch(h.tailMode){case"hidden":w=h.tail;for(var _=null;w!==null;)w.alternate!==null&&(_=w),w=w.sibling;_===null?h.tail=null:_.sibling=null;break;case"collapsed":_=h.tail;for(var E=null;_!==null;)_.alternate!==null&&(E=_),_=_.sibling;E===null?w||h.tail===null?h.tail=null:h.tail.sibling=null:E.sibling=null}}function Nr(h){var w=h.alternate!==null&&h.alternate.child===h.child,_=0,E=0;if(w)for(var V=h.child;V!==null;)_|=V.lanes|V.childLanes,E|=V.subtreeFlags&65011712,E|=V.flags&65011712,V.return=h,V=V.sibling;else for(V=h.child;V!==null;)_|=V.lanes|V.childLanes,E|=V.subtreeFlags,E|=V.flags,V.return=h,V=V.sibling;return h.subtreeFlags|=E,h.childLanes=_,w}function rue(h,w,_){var E=w.pendingProps;switch(_j(w),w.tag){case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Nr(w),null;case 1:return Nr(w),null;case 3:return _=w.stateNode,E=null,h!==null&&(E=h.memoizedState.cache),w.memoizedState.cache!==E&&(w.flags|=2048),zu(Si),M(),_.pendingContext&&(_.context=_.pendingContext,_.pendingContext=null),(h===null||h.child===null)&&(Ab(w)?Hu(w):h===null||h.memoizedState.isDehydrated&&(w.flags&256)===0||(w.flags|=1024,Cj())),Nr(w),null;case 26:var V=w.type,te=w.memoizedState;return h===null?(Hu(w),te!==null?(Nr(w),JB(w,te)):(Nr(w),gM(w,V,null,E,_))):te?te!==h.memoizedState?(Hu(w),Nr(w),JB(w,te)):(Nr(w),w.flags&=-16777217):(h=h.memoizedProps,h!==E&&Hu(w),Nr(w),gM(w,V,h,E,_)),null;case 27:if(W(w),_=H.current,V=w.type,h!==null&&w.stateNode!=null)h.memoizedProps!==E&&Hu(w);else{if(!E){if(w.stateNode===null)throw Error(r(166));return Nr(w),null}h=me.current,Ab(w)?EU(w):(h=sH(V,E,_),w.stateNode=h,Hu(w))}return Nr(w),null;case 5:if(W(w),V=w.type,h!==null&&w.stateNode!=null)h.memoizedProps!==E&&Hu(w);else{if(!E){if(w.stateNode===null)throw Error(r(166));return Nr(w),null}if(te=me.current,Ab(w))EU(w);else{var we=h_(H.current);switch(te){case 1:te=we.createElementNS("http://www.w3.org/2000/svg",V);break;case 2:te=we.createElementNS("http://www.w3.org/1998/Math/MathML",V);break;default:switch(V){case"svg":te=we.createElementNS("http://www.w3.org/2000/svg",V);break;case"math":te=we.createElementNS("http://www.w3.org/1998/Math/MathML",V);break;case"script":te=we.createElement("div"),te.innerHTML=" +