From d459b6eabbb34cc36029c0759eb2a3efae0bc691 Mon Sep 17 00:00:00 2001 From: maziggy Date: Thu, 11 Jun 2026 12:17:45 +0200 Subject: [PATCH] fix(slicer): preset visibility + lookup precedence + signed-out banner + AMS slot badges (#1712) Four #1712 issues from the 2026-06-04 Orca Cloud integration: (1) Tier order put Orca Cloud above everything across SliceModal, auto-pick scoring, dropdown groups, the AMS slot picker, and the backend precedence. Bambu-Cloud-only users saw their profiles deprioritised behind an empty Orca tier. (2) Cross-tier dedup hid a same-named preset in all but the highest- priority tier. A user with both a local-imported and an Orca-synced "Bambu PLA Basic" couldn't see the Orca copy as a picker option. (3) CloudStatusBanner nagged signed-out users with a permanent "Sign in to Orca Cloud" line at the top of every slice -- even after explicit logout. Bambu Cloud had the symmetric problem. (4) ConfigureAmsSlotModal source badges were inconsistent: Orca rows showed only "Custom" (no source identity), Bambu Cloud built-in rows had no badge at all, and the orthogonal isUser-driven "Custom" badge collided with the source badge for cloud user presets. Order is local > orca_cloud > cloud > standard everywhere it lives (SliceModal SLICE_MODAL_TIER_ORDER + TIER_BONUS + dropdown tier list, ConfigureAmsSlotModal sourceOrder, and backend precedence). The order drives auto-pick + visual group rendering; it does NOT hide profiles. _dedupe_by_name replaced with _enrich_cloud_metadata: every tier returns its full list across all three slots (printer / process / filament). The function still backfills Bambu Cloud filament metadata from same-named local / orca_cloud / standard entries so cloud filaments score in pickFilamentForSlot. CloudStatusBanner silently no-ops on not_authenticated for both clouds; expired / unreachable still surface. The not_authenticated i18n keys stay in the locale files dormant. ConfigureAmsSlotModal: one source badge per row, one colour per source (green Local / purple Orca Cloud / bambu-blue Bambu Cloud / amber Built-in). The legacy isUser-driven "Custom" badge is gone; every row identifies its tier consistently. --- CHANGELOG.md | 2 + backend/app/api/routes/slicer_presets.py | 68 +++----- backend/app/schemas/slicer_presets.py | 13 +- backend/tests/unit/test_slicer_presets.py | 155 ++++++++++++------ .../__tests__/components/SliceModal.test.tsx | 12 +- frontend/src/api/client.ts | 5 +- .../src/components/ConfigureAmsSlotModal.tsx | 37 +++-- frontend/src/components/SliceModal.tsx | 44 ++--- 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/ko.ts | 2 + frontend/src/i18n/locales/pt-BR.ts | 2 + frontend/src/i18n/locales/tr.ts | 2 + frontend/src/i18n/locales/zh-CN.ts | 2 + frontend/src/i18n/locales/zh-TW.ts | 2 + .../{index-OCdsEuOz.js => index-B3h_dfeT.js} | 114 ++++++------- static/index.html | 2 +- 21 files changed, 272 insertions(+), 202 deletions(-) rename static/assets/{index-OCdsEuOz.js => index-B3h_dfeT.js} (75%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 935994dc5..b3af75ded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,8 @@ All notable changes to Bambuddy will be documented in this file. - **Print Log page: per-row delete (#1687 part 1, reported by @IndividualGhost1905)** — Reporter noted that the existing "Also remove this print from Quick Stats" toggle on archive delete is one-shot: if you tick "keep stats" at delete time, there was no later way to drop the row from /stats; and rows that aren't tied to an archive (errors, aborts, manual entries) had no delete affordance at all. **Fix:** every row in the Archives → Print Log table now has a trash icon next to the filament cell, gated on `archives:delete_own` (own rows) or `archives:delete_all` (any row), matching the archive-delete permission shape. Click → confirm modal → row is gone, and because /archives/stats aggregates over `PrintLogEntry` the filament / time / cost contribution drops out of Quick Stats in the same response cycle. The matching archive (if any) is untouched — the log row is a sibling, not a child. **Backend:** new `DELETE /print-log/{entry_id}` mirrors `delete_archive`'s ownership flow via `require_ownership_permission(ARCHIVES_DELETE_ALL, ARCHIVES_DELETE_OWN)`; owners can drop their own rows, admins can drop any row, missing IDs return 404 rather than 200-silently. **Frontend:** new `deletePrintLogEntry` API helper, per-row mutation that invalidates both `print-log` and `archives-stats` query keys so the totals re-render without a manual refresh. **i18n:** 4 new keys (`deleteEntryTitle`, `deleteEntryConfirm`, `entryDeleted`, `entryDeleteFailed`) translated across all 11 locales (de / en / es / fr / it / ja / ko / pt-BR / tr / zh-CN / zh-TW). **Tests:** 3 backend integration cases — delete drops the row from /stats while keeping the linked archive listed, missing ID returns 404, delete-one does not touch siblings (regression guard against an accidental `delete(PrintLogEntry)` without a `where`). Frontend ArchivesPage / PrintLogModal vitests stay green (31 / 31). i18n parity green (5099 leaves × 11 locales). Issue #1687 also asks for per-row tagging (already covered by `EditArchiveModal`'s tags field) and per-row filament-usage-history edits (deferred — see the issue thread for the reasoning). ### Fixed +- **SliceModal preset-lookup precedence + cross-tier dedup + signed-out banner (#1712, reported by @IndividualGhost1905)** — After the Orca Cloud integration shipped (2026-06-04), every user — including Bambu-Cloud-only / Bambu-Studio-preferred users — got Orca Cloud as the top tier across the SliceModal preset picker, the per-preset auto-pick scoring, the dropdown's optgroup rendering, the AMS slot picker's filament sort, and the backend dedup precedence. A Bambu-Cloud / X1C user reported seeing his Bambu Cloud profiles disappear from auto-pick because Orca Cloud's empty tier shadowed them. The cross-tier dedup (introduced with #1150 and inherited as-is by the Orca change) compounded the problem: a name that existed in multiple tiers showed in only ONE group, so a user with a local-imported and Orca-synced "Bambu PLA Basic" never saw the Orca copy as a picker option — even though they curate both sources. And the cloud-status banner (`CloudStatusBanner`) nagged signed-out users with a permanent *"Sign in to Orca Cloud (Profiles → Orca Cloud) to see your Orca presets"* at the top of every SliceModal open — even after a user had explicitly logged out of Orca Cloud. The Bambu Cloud banner had the symmetric problem. **Fix — order:** precedence is `local > orca_cloud > cloud > standard` across `SliceModal.tsx` (`SLICE_MODAL_TIER_ORDER` + `TIER_BONUS` + dropdown tier list), `ConfigureAmsSlotModal.tsx` (`sourceOrder`), and docstrings in `slicer_presets.py` / `schemas/slicer_presets.py` / `client.ts`. Local imports win (the user did them on purpose), Orca Cloud comes next, Bambu Cloud, bundled fallback last. The order drives auto-pick + visual group order; it does NOT hide profiles. **Fix — no dedup, full lists:** `_dedupe_by_name` is replaced by `_enrich_cloud_metadata`, which returns every tier's full preset list across all three slots (printer / process / filament) — a name in local AND orca_cloud AND cloud renders in EACH of their groups so the user can pick any source. The only work the function still does is filament-metadata backfill: a Bambu Cloud filament without its own `filament_type` / `filament_colour` inherits values from a same-named local / orca_cloud / standard entry so it can still score in `pickFilamentForSlot`. Printer + process presets carry their metadata inline and need no enrich. Frontend code already iterates tiers in priority order and surfaces every entry — no change needed there once the backend stops filtering. **Fix — banner:** `CloudStatusBanner` now silently returns null on `not_authenticated` in addition to `ok` — applies symmetrically to both Bambu and Orca cloud banners. `expired` (token broke) and `unreachable` (network / service down) still surface — those are real breakage states a previously-signed-in user needs to see. Sign-in lives on the Profiles page; the modal doesn't need to advertise it. The `slice.cloud.notAuthenticated` / `slice.orcaCloud.notAuthenticated` i18n keys stay in the locale files (dormant) so re-enabling later doesn't need a re-translation pass. **Fix — ConfigureAmsSlotModal source badges:** before this change, the per-row source badge fired three branches independently — `local` got a green "Local" badge, `builtin` got an amber "Built-in" badge, and a blue "Custom" badge appeared on top of those when `isUser` was true. Since ALL Orca Cloud entries are marked `isUser: true` and Bambu Cloud user presets also get the same flag, the result was visually inconsistent: Orca Cloud rows showed *only* "Custom" (no source identification, no way to tell them from Bambu Cloud user presets), Bambu Cloud built-in rows had NO badge at all, and the "Custom" badge collided with the actual source. Replaced with a single source badge per row: green "Local", purple "Orca Cloud" (new), bambu-blue "Bambu Cloud" (new), amber "Built-in". One badge per row; one colour per source; the `isUser` distinction within the Bambu Cloud tier is dropped (the preset name itself carries the "is this user-authored" signal). Same change in both render blocks (the filament-list code is duplicated in the modal — kept the duplication local rather than refactoring out a helper component in this PR to keep the diff tight). i18n: 2 new keys (`configureAmsSlot.orcaCloud`, `configureAmsSlot.bambuCloud`) translated to all 11 locales — both are brand names, already on the per-locale `IDENTICAL_TO_EN_ALLOWED` lists so the parity check is satisfied without per-locale variants. The dormant `configureAmsSlot.custom` key stays in the locale files. **Tests:** `TestEnrichCloudMetadata` replaces `TestDedupeByName` (5 cases): regression guard pinning that a name in all four tiers appears in EACH (not just local), tier order preserved within a tier, Bambu Cloud filament metadata backfilled from local, backfill falls through to orca / standard when local doesn't carry the name, backfill does NOT overwrite Bambu Cloud's own metadata when present. The "renders a sign-in banner when cloud_status is not_authenticated" case flipped to assert no banner appears, with the test name updated to call out the #1712 reason. Backend `test_slicer_presets.py` 47/47 green; `SliceModal.test.tsx` 34/34 green; `ConfigureAmsSlotModal.test.tsx` 24/24 green; ruff clean; frontend build clean; i18n parity 5120 leaves × 11 locales green. + - **Telegram (and other image-bearing) finish notification on a reprint-from-archive showed the original print's finish photo instead of the new run's (#1707, reported by @kycrna)** — P2S user reprinted an archived job and observed the Telegram notification arriving with the photo of the *original* print (white box) attached to the completion message for the *new* run (black box). **Root cause:** reprints reuse the source archive row — `register_expected_print` stores the source `archive_id` in `_expected_prints`, and the on-print-start expected-archive promotion branch at `main.py:2207-2245` updates the row's status / started_at / printer_id / subtask_id but never reset `archive.timelapse_path`. Two failure modes cascaded from the stale path: (a) `_scan_for_timelapse_with_retries` early-returns at `main.py:3062` with `if archive.timelapse_path: return` — the reprint's new timelapse MP4 sitting on the printer's SD card was never downloaded, the archive's `timelapse_path` kept pointing at the original run's local file; (b) `_capture_finish_photo_from_timelapse` polls `archive.timelapse_path` and immediately found the *original* video, extracted ITS last frame as `finish__.jpg`, and handed those bytes to `_background_notifications` as `image_data` — which then went out to Telegram via the `sendPhoto` path. The filename was new (so log lines and the archive's `photos` list looked correct), but the pixels were the original run's finish frame. Surface was specific to the timelapse-prefer path: with `data.timelapse_was_active` true and no external camera, `prefer_timelapse_source` was True, which is the exact configuration on P2S with timelapse-on for both runs. External-camera, buffered-frame, and fresh-RTSP fallback paths grab the *current* camera frame, so users on those paths saw correct photos and the bug stayed hidden. **Fix:** at expected-archive promotion, capture and clear `archive.timelapse_path` to None before the commit, and `os.unlink` the stale on-disk video so reprints don't accumulate orphaned MP4s in the archive directory. Photos list is left alone — accumulating one finish photo per run across the archive's lifetime is the right behaviour. The unlink is wrapped in `OSError`-catching best-effort logging so a missing file (manual delete, archive purge, container rebuild with bind-mount drift) doesn't break promotion. The clear-and-unlink runs unconditionally when `timelapse_path` is set, so even if a user has been reprinting under the buggy build for months, the next reprint self-heals. **Tests:** 3 new cases in `test_reprint_clears_stale_timelapse.py` exercise the full `on_print_start` callback through the expected-archive branch — happy path (path cleared + file unlinked), no-prior-timelapse (no-op, promotion still succeeds), missing-stale-file (best-effort unlink doesn't raise). Full `test_print_start_expected_promotion.py` + `test_print_start_assigns_printer_id_to_vp_archive.py` suite (28/28) stays green; ruff clean. - **Connection diagnostic no longer flags `external_storage: fail` on A1 / A1 Mini, which physically have no MicroSD slot (#1703, reported by @MartinNYHC)** — Bug report from an A1 user complained that BambuStudio and OrcaSlicer don't have an "external storage" tick box (correct — there's nothing to toggle, the A1 series ships without a SD card slot at all) while the Bambuddy support bundle simultaneously reported `external_storage: fail` in the printer's connection diagnostic. The two together left the user thinking Bambuddy was wrong about a setting their hardware doesn't have. **Root cause:** the `external_storage` check at `services/printer_diagnostic.py:179-189` reads `state.store_to_sdcard`, which is parsed from MQTT `home_flag` bit 11. On A1 and A1 Mini that bit is never set (no hardware slot, no firmware-side toggle, no slicer-side equivalent), so the value pushes as `False` and the check fell through to `fail` instead of `skip`. **Fix:** new `NO_EXTERNAL_STORAGE_MODELS` frozenset in `utils/printer_models.py` enumerating A1, A1 Mini, and their internal codes (N1, N2S, A04, A11, A12), plus a `has_external_storage(model)` helper that returns False for those and True for everything else (unknown models default to True so the check stays active for any future Bambu model that ships *with* a slot — new no-slot models must be added to the set explicitly). The diagnostic now short-circuits to `skip` before reading `store_to_sdcard` when `printer.model` is in the set. **What this does NOT change:** X1 / X1E / P1S / P1P / P2S / H2D / H2D Pro / H2C / H2S / X2D continue to evaluate `store_to_sdcard` exactly as before — the home-flag-bit-off → `fail` path is still the right signal for them. **The companion FTP-upload-timeout symptom in the same bug report (ftp code 28 from BambuStudio when sending to the proxy VP) is a separate Docker-bridge-mode networking constraint, not addressed by this change.** **Tests:** 8 new cases — `TestHasExternalStorage` (5 cases) pins the model list, internal-code aliasing, case/whitespace normalisation, unknown-defaults-true, and null/empty-defaults-true; `TestExternalStorageCheck` gains `test_skips_on_a1_no_external_storage_slot`, `test_skips_on_a1_mini_no_external_storage_slot`, and `test_still_fails_on_x1c_when_toggle_off` (regression guard that the model-aware skip doesn't accidentally silence the genuine signal on slotted models). Full `test_printer_models.py` + `test_printer_diagnostic.py` + archives integration suite green (172/172); ruff clean. diff --git a/backend/app/api/routes/slicer_presets.py b/backend/app/api/routes/slicer_presets.py index 29138c043..458441673 100644 --- a/backend/app/api/routes/slicer_presets.py +++ b/backend/app/api/routes/slicer_presets.py @@ -173,11 +173,10 @@ async def _fetch_cloud_presets( # one-by-one trips Bambu's limiter and returns 429 on every request # for users with large preset libraries (#1150 follow-up). # - # The dedup pass (see _dedupe_by_name) compensates: when a cloud entry - # wins over a same-named local entry, the cloud entry inherits the - # local entry's filament_type / filament_colour. So cloud presets that - # also exist locally still get metadata-aware pre-pick in the - # SliceModal; cloud-only presets fall back to plain priority order. + # The metadata-enrich pass (see _enrich_cloud_metadata) compensates: + # a Bambu Cloud entry without its own filament_type/colour inherits + # those values from a same-named local / orca_cloud / standard entry + # so it can still score for type/colour matches in pickFilamentForSlot. _cloud_cache[cache_key] = (now, slots) return slots, "ok" finally: @@ -420,7 +419,7 @@ async def _resolve_slicer_api_url(db: AsyncSession) -> str | None: return url or None -def _dedupe_by_name( +def _enrich_cloud_metadata( orca_cloud: dict[str, list[UnifiedPreset]], cloud: dict[str, list[UnifiedPreset]], local: dict[str, list[UnifiedPreset]], @@ -431,26 +430,29 @@ def _dedupe_by_name( dict[str, list[UnifiedPreset]], dict[str, list[UnifiedPreset]], ]: - """Filter so each preset name appears in exactly one tier. + """Backfill Bambu Cloud filament metadata; do NOT dedup tiers. - Precedence: ``orca_cloud > cloud > local > standard``. Orca Cloud is - highest because a user who set up Orca sync is explicitly curating - those profiles for use here; Bambu Cloud follows for the same reason - one tier down. Order within each tier is preserved. + Every tier surfaces its full list — a name that exists in both ``local`` + and ``orca_cloud`` shows up in BOTH dropdown groups so the user can pick + either source. Tier ORDER (``local > orca_cloud > cloud > standard``) + is communicated by the SliceModal's group rendering and by the + name-collision fallback in ``findPresetByName``; this function does not + enforce it. - Filament metadata merges across tiers: a Bambu Cloud entry without its - own ``filament_type`` / ``filament_colour`` (Bambu Cloud doesn't surface + Filament metadata merge: a Bambu Cloud entry without its own + ``filament_type`` / ``filament_colour`` (Bambu Cloud doesn't surface these in the list response for rate-limiting reasons — see - :func:`_fetch_cloud_presets`) inherits values from the same-named local - or standard entry. Orca Cloud already carries metadata inline, so no - backfill is needed for it. + :func:`_fetch_cloud_presets`) inherits values from a same-named entry + in ``local`` / ``orca_cloud`` / ``standard``. This is the only reason + this function exists post-#1712 — without the enrich the Bambu Cloud + tier can't score in ``pickFilamentForSlot``. """ - # Build a name → metadata lookup from the tiers that carry it (orca_cloud, - # local, standard). Bambu cloud is intentionally skipped — it doesn't - # populate filament_type/colour in the list response. Take whichever - # non-empty entry shows up first. + # Build a name → metadata lookup from the tiers that carry it (local, + # orca_cloud, standard). Bambu cloud is intentionally skipped — it + # doesn't populate filament_type/colour in the list response. Take + # whichever non-empty entry shows up first. metadata_by_name: dict[str, tuple[str | None, str | None]] = {} - for tier in (orca_cloud, local, standard): + for tier in (local, orca_cloud, standard): for p in tier["filament"]: if p.name in metadata_by_name: continue @@ -466,27 +468,7 @@ def _dedupe_by_name( if p.filament_colour is None and c is not None: p.filament_colour = c - deduped_cloud = _empty_slots() - deduped_local = _empty_slots() - deduped_standard = _empty_slots() - for slot in ("printer", "process", "filament"): - seen = {p.name for p in orca_cloud[slot]} - for p in cloud[slot]: - if p.name in seen: - continue - deduped_cloud[slot].append(p) - seen.add(p.name) - for p in local[slot]: - if p.name in seen: - continue - deduped_local[slot].append(p) - seen.add(p.name) - for p in standard[slot]: - if p.name in seen: - continue - deduped_standard[slot].append(p) - seen.add(p.name) - return orca_cloud, deduped_cloud, deduped_local, deduped_standard + return orca_cloud, cloud, local, standard @router.get("/printer-models") @@ -541,7 +523,7 @@ async def list_unified_presets( local = await _fetch_local_presets(db) standard = await _fetch_bundled_presets(db, refresh=refresh) - orca_cloud, cloud, local, standard = _dedupe_by_name(orca_cloud, cloud, local, standard) + orca_cloud, cloud, local, standard = _enrich_cloud_metadata(orca_cloud, cloud, local, standard) return UnifiedPresetsResponse( orca_cloud=UnifiedPresetsBySlot(**orca_cloud), diff --git a/backend/app/schemas/slicer_presets.py b/backend/app/schemas/slicer_presets.py index d110ef205..7b5b6b148 100644 --- a/backend/app/schemas/slicer_presets.py +++ b/backend/app/schemas/slicer_presets.py @@ -59,13 +59,14 @@ class UnifiedPresetsBySlot(BaseModel): class UnifiedPresetsResponse(BaseModel): - """Each tier carries only the names that didn't appear in a higher tier. + """Every tier carries its full preset list — no cross-tier dedup. - Priority order: ``orca_cloud > cloud > local > standard``. Orca Cloud is - highest because it's the most-recently-explicitly-curated source for - users who set up Orca sync (they did it on purpose; their Orca picks - should outrank everything else). Bambu Cloud follows as the next-most- - curated tier. Local imports beat the slicer's stock fallback. + Priority order: ``local > orca_cloud > cloud > standard``. The order + drives auto-pick (first non-empty tier wins, name-lookup walks tiers + in this order, filament scoring tiebreaks by per-tier bonus) and + determines the visual rendering order of the SliceModal's optgroups, + but a name that exists in multiple tiers appears in EACH of their + groups so the user can pick any source. ``cloud_status`` / ``orca_cloud_status`` let the frontend show a banner explaining why a cloud tier is empty when the user expected to see it diff --git a/backend/tests/unit/test_slicer_presets.py b/backend/tests/unit/test_slicer_presets.py index 49ab5c0c7..5eb0ad667 100644 --- a/backend/tests/unit/test_slicer_presets.py +++ b/backend/tests/unit/test_slicer_presets.py @@ -1,9 +1,13 @@ """Tests for the unified slicer-presets endpoint helpers. -The endpoint stitches together three preset sources (cloud / local / -standard) with name-based dedup. These tests pin the dedup logic, the -cloud-status mapping, and the per-user / sidecar caches at the -helper level — full HTTP integration is covered by the routes test. +The endpoint stitches together four preset sources (local / orca_cloud / +cloud / standard). It does NOT dedup across tiers — every tier surfaces +its full list so the user can pick any source. Bambu Cloud filament +metadata is enriched from same-named entries in the other tiers so it +can still score in the SliceModal's auto-pick. These tests pin the +enrich behaviour, the cloud-status mapping, and the per-user / sidecar +caches at the helper level — full HTTP integration is covered by the +routes test. """ from __future__ import annotations @@ -28,50 +32,31 @@ def _slot(items: list[tuple[str, str, str]]) -> dict[str, list[UnifiedPreset]]: } -class TestDedupeByName: - """Cloud > local > standard, by ``name``, order preserved within tier.""" +class TestEnrichCloudMetadata: + """No cross-tier dedup — every tier's full list comes back; Bambu Cloud + filament metadata is enriched from same-named entries in other tiers.""" - def test_cloud_wins_over_local_and_standard(self): + def test_same_name_in_all_tiers_appears_in_every_tier(self): + """Critical regression guard for #1712: a user who has imported a + local profile AND signed in to Orca AND has Bambu Cloud with the + same name should see it under EACH source, not just the highest- + priority tier. The order is used for auto-pick + group rendering; + it is NOT used to hide profiles.""" + orca = _slot([("oid1", "Bambu PLA Basic", "orca_cloud")]) cloud = _slot([("cid1", "Bambu PLA Basic", "cloud")]) local = _slot([("lid1", "Bambu PLA Basic", "local")]) standard = _slot([("Bambu PLA Basic", "Bambu PLA Basic", "standard")]) - _oc, c, l_, s = sp._dedupe_by_name(_slot([]), cloud, local, standard) + oc, c, l_, s = sp._enrich_cloud_metadata(orca, cloud, local, standard) + assert [p.source for p in l_["printer"]] == ["local"] + assert [p.source for p in oc["printer"]] == ["orca_cloud"] assert [p.source for p in c["printer"]] == ["cloud"] - assert l_["printer"] == [] - assert s["printer"] == [] - - def test_local_filtered_only_when_present_in_cloud(self): - cloud = _slot([("cid1", "Custom PLA", "cloud")]) - local = _slot( - [ - ("lid1", "Custom PLA", "local"), # filtered (in cloud) - ("lid2", "My Workhorse PLA", "local"), # kept - ] - ) - standard = _slot([]) - - _oc, _c, l_, _s = sp._dedupe_by_name(_slot([]), cloud, local, standard) - assert [p.name for p in l_["printer"]] == ["My Workhorse PLA"] - - def test_standard_filtered_against_both_higher_tiers(self): - cloud = _slot([("c1", "A", "cloud")]) - local = _slot([("l1", "B", "local")]) - standard = _slot( - [ - ("A", "A", "standard"), # filtered (in cloud) - ("B", "B", "standard"), # filtered (in local) - ("C", "C", "standard"), # kept - ] - ) - - _oc, _c, _l, s = sp._dedupe_by_name(_slot([]), cloud, local, standard) - assert [p.name for p in s["printer"]] == ["C"] + assert [p.source for p in s["printer"]] == ["standard"] def test_preserves_order_within_tier(self): - """A tier's input order must be preserved in its output — nothing in - the dedupe pass should sort, reverse, or otherwise reorder entries.""" + """A tier's input order must be preserved — nothing in the enrich + pass should sort, reverse, or otherwise reorder entries.""" cloud = _slot( [ ("c1", "Z-First", "cloud"), @@ -79,25 +64,95 @@ class TestDedupeByName: ("c3", "M-Third", "cloud"), ] ) - _oc, c, _l, _s = sp._dedupe_by_name(_slot([]), cloud, _slot([]), _slot([])) + _oc, c, _l, _s = sp._enrich_cloud_metadata(_slot([]), cloud, _slot([]), _slot([])) assert [p.name for p in c["printer"]] == ["Z-First", "A-Second", "M-Third"] - def test_dedupe_is_per_slot(self): - """A name colliding across DIFFERENT slots must NOT cross-filter — - a "Custom" filament shouldn't hide a "Custom" printer.""" + def test_bambu_cloud_filament_metadata_backfilled_from_local(self): + """Bambu Cloud's list response omits filament_type/colour for + rate-limit reasons. A same-named local entry's metadata fills in + so the cloud entry can still score in pickFilamentForSlot.""" + local = { + "printer": [], + "process": [], + "filament": [ + UnifiedPreset( + id="lp1", + name="Bambu PLA Basic", + source="local", + filament_type="PLA", + filament_colour="#FF0000", + ) + ], + } cloud = { "printer": [], "process": [], - "filament": [UnifiedPreset(id="cf1", name="Custom", source="cloud")], + "filament": [UnifiedPreset(id="cp1", name="Bambu PLA Basic", source="cloud")], } - local = { - "printer": [UnifiedPreset(id="lp1", name="Custom", source="local")], + _oc, c, _l, _s = sp._enrich_cloud_metadata(_slot([]), cloud, local, _slot([])) + # Cloud entry now carries the local entry's metadata. + assert c["filament"][0].filament_type == "PLA" + assert c["filament"][0].filament_colour == "#FF0000" + # Local entry is untouched. + assert local["filament"][0].filament_type == "PLA" + + def test_bambu_cloud_metadata_falls_back_through_orca_and_standard(self): + """When local doesn't carry the name, orca_cloud / standard fill in.""" + orca = { + "printer": [], "process": [], - "filament": [], + "filament": [ + UnifiedPreset( + id="o1", + name="Bambu PLA Basic", + source="orca_cloud", + filament_type="PLA", + filament_colour="#00FF00", + ) + ], } - _oc, _c, l_, _s = sp._dedupe_by_name(_slot([]), cloud, local, _slot([])) - # The filament-tier collision must NOT remove the printer-tier "Custom". - assert [p.name for p in l_["printer"]] == ["Custom"] + cloud = { + "printer": [], + "process": [], + "filament": [UnifiedPreset(id="cp1", name="Bambu PLA Basic", source="cloud")], + } + _oc, c, _l, _s = sp._enrich_cloud_metadata(orca, cloud, _slot([]), _slot([])) + assert c["filament"][0].filament_type == "PLA" + assert c["filament"][0].filament_colour == "#00FF00" + + def test_bambu_cloud_keeps_its_own_metadata_when_present(self): + """If Bambu Cloud already has filament_type / filament_colour the + enrich pass must not overwrite them with a different same-named + entry's values.""" + local = { + "printer": [], + "process": [], + "filament": [ + UnifiedPreset( + id="lp1", + name="Bambu PLA Basic", + source="local", + filament_type="PETG", + filament_colour="#000000", + ) + ], + } + cloud = { + "printer": [], + "process": [], + "filament": [ + UnifiedPreset( + id="cp1", + name="Bambu PLA Basic", + source="cloud", + filament_type="PLA", + filament_colour="#FFFFFF", + ) + ], + } + _oc, c, _l, _s = sp._enrich_cloud_metadata(_slot([]), cloud, local, _slot([])) + assert c["filament"][0].filament_type == "PLA" + assert c["filament"][0].filament_colour == "#FFFFFF" def _user_with_cloud_auth(user_id: int = 1) -> MagicMock: diff --git a/frontend/src/__tests__/components/SliceModal.test.tsx b/frontend/src/__tests__/components/SliceModal.test.tsx index fdb9afc81..8000fedda 100644 --- a/frontend/src/__tests__/components/SliceModal.test.tsx +++ b/frontend/src/__tests__/components/SliceModal.test.tsx @@ -392,10 +392,15 @@ describe('SliceModal', () => { }); }); - it('renders a "sign in" banner when cloud_status is not_authenticated', async () => { + it('omits the cloud banner when status is not_authenticated (#1712)', async () => { + // A signed-out user (Bambu or Orca) shouldn't get a permanent "sign in" + // nag at the top of every slice. Sign-in lives on the Profiles page; the + // modal stays silent unless a previously-signed-in session actually broke + // (expired / unreachable). mockApi.getSlicerPresets.mockResolvedValue( makeUnified({ cloud_status: 'not_authenticated', + orca_cloud_status: 'not_authenticated', local: fullThreeTier.local, standard: fullThreeTier.standard, }), @@ -405,9 +410,8 @@ describe('SliceModal', () => { onClose: vi.fn(), }); - await waitFor(() => { - expect(screen.getByRole('status')).toHaveTextContent(/Sign in to Bambu Cloud/i); - }); + await waitFor(() => expect(screen.getByText('Imported X1C 0.4')).toBeDefined()); + expect(screen.queryByRole('status')).toBeNull(); }); it('renders an "expired" banner when cloud_status is expired', async () => { diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index 85baca5df..1d7dd4f53 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -1464,8 +1464,9 @@ export interface UnifiedPresetsBySlot { filament: UnifiedPreset[]; } export interface UnifiedPresetsResponse { - // Priority order: orca_cloud > cloud > local > standard. Dedup is applied - // backend-side so each name appears in only one tier. + // Priority order: local > orca_cloud > cloud > standard. No cross-tier + // dedup — every tier surfaces its full list so the user can pick from + // any source. The order drives auto-pick + visual group rendering only. orca_cloud: UnifiedPresetsBySlot; cloud: UnifiedPresetsBySlot; local: UnifiedPresetsBySlot; diff --git a/frontend/src/components/ConfigureAmsSlotModal.tsx b/frontend/src/components/ConfigureAmsSlotModal.tsx index 60b942d9b..7510967a9 100644 --- a/frontend/src/components/ConfigureAmsSlotModal.tsx +++ b/frontend/src/components/ConfigureAmsSlotModal.tsx @@ -639,10 +639,11 @@ export function ConfigureAmsSlotModal({ } } - // Sort: orca_cloud first (user-curated), then cloud user presets, then - // cloud built-in, then local, then builtin fallback + // Sort: local first (user explicitly imported them), then orca_cloud, + // then bambu cloud, then builtin fallback. Matches the SliceModal + // tier priority. return items.sort((a, b) => { - const sourceOrder = { orca_cloud: 0, cloud: 1, local: 2, builtin: 3 }; + const sourceOrder = { local: 0, orca_cloud: 1, cloud: 2, builtin: 3 }; if (a.source !== b.source) return sourceOrder[a.source] - sourceOrder[b.source]; if (a.isUser && !b.isUser) return -1; if (!a.isUser && b.isUser) return 1; @@ -1099,16 +1100,21 @@ export function ConfigureAmsSlotModal({ {t('profiles.localProfiles.badge')} )} + {preset.source === 'orca_cloud' && ( + + {t('configureAmsSlot.orcaCloud')} + + )} + {preset.source === 'cloud' && ( + + {t('configureAmsSlot.bambuCloud')} + + )} {preset.source === 'builtin' && ( {t('configureAmsSlot.builtin')} )} - {preset.isUser && ( - - {t('configureAmsSlot.custom')} - - )} @@ -1334,16 +1340,21 @@ export function ConfigureAmsSlotModal({ {t('profiles.localProfiles.badge')} )} + {preset.source === 'orca_cloud' && ( + + {t('configureAmsSlot.orcaCloud')} + + )} + {preset.source === 'cloud' && ( + + {t('configureAmsSlot.bambuCloud')} + + )} {preset.source === 'builtin' && ( {t('configureAmsSlot.builtin')} )} - {preset.isUser && ( - - {t('configureAmsSlot.custom')} - - )} diff --git a/frontend/src/components/SliceModal.tsx b/frontend/src/components/SliceModal.tsx index bde7237f7..aa741fdcd 100644 --- a/frontend/src/components/SliceModal.tsx +++ b/frontend/src/components/SliceModal.tsx @@ -38,15 +38,14 @@ interface SliceModalProps { type Slot = 'printer' | 'process' | 'filament'; -// SliceModal-specific tier priority: orca_cloud → local → cloud → standard. -// Imported (local) profiles are surfaced before Bambu Cloud because they're -// metadata-tagged (Bambu Cloud isn't, by design — see -// `_fetch_cloud_presets`'s rate-limit note). Orca Cloud comes first because -// its sync_pull response inlines metadata too AND represents the user's -// most-recently-curated source. Standard is the bundled fallback. This is -// distinct from the listing endpoint's dedup order and only affects what -// the SliceModal renders / pre-picks. -const SLICE_MODAL_TIER_ORDER = ['orca_cloud', 'local', 'cloud', 'standard'] as const; +// Lookup priority: local → orca_cloud → cloud → standard. Local imports +// outrank everything else because the user explicitly imported them for +// this install; Orca Cloud comes next; Bambu Cloud after that; standard +// (bundled) is the final fallback. The backend does NOT dedup tiers — +// every group renders its full set so the user can pick a same-named +// preset from a lower-priority source if they want to override the +// auto-pick. +const SLICE_MODAL_TIER_ORDER = ['local', 'orca_cloud', 'cloud', 'standard'] as const; function pickDefault(by: UnifiedPresetsResponse, slot: Slot): PresetRef | null { for (const tier of SLICE_MODAL_TIER_ORDER) { @@ -117,8 +116,8 @@ function pickProcessDefault( } const TIER_BONUS: Record = { - orca_cloud: 1.75, - local: 1.5, + local: 1.75, + orca_cloud: 1.5, cloud: 1.0, standard: 0.5, }; @@ -999,7 +998,12 @@ function CloudStatusBanner({ cloudName?: 'bambu' | 'orca'; }) { const { t } = useTranslation(); - if (status === 'ok') return null; + // `ok` is the happy path. `not_authenticated` is silenced too: a user who + // hasn't signed in (or has explicitly logged out — #1712) doesn't need a + // permanent nag at the top of the modal; sign-in lives on the Profiles + // page if they want it. Only `expired` and `unreachable` surface — those + // are real breakage states a previously-signed-in user needs to see. + if (status === 'ok' || status === 'not_authenticated') return null; // Same status vocabulary for both Bambu and Orca Cloud — only the // user-facing text varies. The fallbacks below name each cloud explicitly @@ -1008,10 +1012,6 @@ function CloudStatusBanner({ const messages = cloudName === 'orca' ? { - not_authenticated: { - key: 'slice.orcaCloud.notAuthenticated', - fallback: 'Sign in to Orca Cloud (Profiles → Orca Cloud) to see your Orca presets.', - }, expired: { key: 'slice.orcaCloud.expired', fallback: 'Orca Cloud session expired — sign in again to refresh your Orca presets.', @@ -1022,10 +1022,6 @@ function CloudStatusBanner({ }, } : { - not_authenticated: { - key: 'slice.cloud.notAuthenticated', - fallback: 'Sign in to Bambu Cloud (Settings → Profiles → Cloud) to see your cloud presets.', - }, expired: { key: 'slice.cloud.expired', fallback: 'Bambu Cloud session expired — sign in again to refresh your cloud presets.', @@ -1036,11 +1032,7 @@ function CloudStatusBanner({ }, }; - const tones: Record, { tone: string; icon: typeof Cloud }> = { - not_authenticated: { - tone: 'border-bambu-dark-tertiary/40 bg-bambu-dark text-bambu-gray', - icon: Cloud, - }, + const tones: Record<'expired' | 'unreachable', { tone: string; icon: typeof Cloud }> = { expired: { tone: 'border-amber-700/40 bg-amber-900/20 text-amber-200', icon: CloudOff, @@ -1149,8 +1141,8 @@ function PresetDropdown({ // empty sections collapse out. const { sections, otherEntries } = useMemo(() => { const tiers: { key: keyof UnifiedPresetsResponse; label: string; fallback: string }[] = [ - { key: 'orca_cloud', label: 'slice.tier.orcaCloud', fallback: 'Orca Cloud' }, { key: 'local', label: 'slice.tier.local', fallback: 'Imported' }, + { key: 'orca_cloud', label: 'slice.tier.orcaCloud', fallback: 'Orca Cloud' }, { key: 'cloud', label: 'slice.tier.cloud', fallback: 'Bambu Cloud' }, { key: 'standard', label: 'slice.tier.standard', fallback: 'Standard' }, ]; diff --git a/frontend/src/i18n/locales/de.ts b/frontend/src/i18n/locales/de.ts index e59ff179b..3bbe23c06 100644 --- a/frontend/src/i18n/locales/de.ts +++ b/frontend/src/i18n/locales/de.ts @@ -5246,6 +5246,8 @@ export default { noMatchingPresets: 'Keine passenden Voreinstellungen gefunden.', custom: 'Benutzerdefiniert', builtin: 'Integriert', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: 'Einstellungen an Drucker gesendet', filamentProfile: 'Filamentprofil', kProfileLabel: 'K-Profil (Pressure Advance)', diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index 3c49eeb59..3bfb1f657 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -5259,6 +5259,8 @@ export default { noMatchingPresets: 'No matching presets found.', custom: 'Custom', builtin: 'Built-in', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: 'Settings sent to printer', filamentProfile: 'Filament Profile', kProfileLabel: 'K Profile (Pressure Advance)', diff --git a/frontend/src/i18n/locales/es.ts b/frontend/src/i18n/locales/es.ts index 39dc28089..7448ac428 100644 --- a/frontend/src/i18n/locales/es.ts +++ b/frontend/src/i18n/locales/es.ts @@ -5255,6 +5255,8 @@ export default { noMatchingPresets: 'No se encontraron preajustes coincidentes.', custom: 'Personalizado', builtin: 'Integrado', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: 'Ajustes enviados a la impresora', filamentProfile: 'Perfil de filamento', kProfileLabel: 'Perfil K (avance de presión)', diff --git a/frontend/src/i18n/locales/fr.ts b/frontend/src/i18n/locales/fr.ts index ec0b7a31c..bf3bd80fb 100644 --- a/frontend/src/i18n/locales/fr.ts +++ b/frontend/src/i18n/locales/fr.ts @@ -5236,6 +5236,8 @@ export default { noMatchingPresets: 'Aucun profil trouvé.', custom: 'Perso', builtin: 'Inclus', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: 'Réglages envoyés', filamentProfile: 'Profil Filament', kProfileLabel: 'Profil K (Pressure Advance)', diff --git a/frontend/src/i18n/locales/it.ts b/frontend/src/i18n/locales/it.ts index ca61ca735..e54667be9 100644 --- a/frontend/src/i18n/locales/it.ts +++ b/frontend/src/i18n/locales/it.ts @@ -5235,6 +5235,8 @@ export default { noMatchingPresets: 'Nessun preset corrispondente trovato.', custom: 'Personalizzato', builtin: 'Integrato', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: 'Impostazioni inviate alla stampante', filamentProfile: 'Profilo filamento', kProfileLabel: 'Profilo K (Pressure Advance)', diff --git a/frontend/src/i18n/locales/ja.ts b/frontend/src/i18n/locales/ja.ts index 732ae7cfd..f688a6068 100644 --- a/frontend/src/i18n/locales/ja.ts +++ b/frontend/src/i18n/locales/ja.ts @@ -5247,6 +5247,8 @@ export default { noMatchingPresets: '一致するプリセットが見つかりません。', custom: 'カスタム', builtin: '内蔵', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: '設定をプリンターに送信しました', filamentProfile: 'フィラメントプロファイル', kProfileLabel: 'Kプロファイル(Pressure Advance)', diff --git a/frontend/src/i18n/locales/ko.ts b/frontend/src/i18n/locales/ko.ts index b98e1bd01..a00e6d1af 100644 --- a/frontend/src/i18n/locales/ko.ts +++ b/frontend/src/i18n/locales/ko.ts @@ -4939,6 +4939,8 @@ export default { noMatchingPresets: '일치하는 프리셋을 찾을 수 없습니다.', custom: '사용자 지정', builtin: '기본 제공', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: '설정이 프린터로 전송됨', filamentProfile: '필라멘트 프로필', kProfileLabel: 'K 프로필 (압력 전진)', diff --git a/frontend/src/i18n/locales/pt-BR.ts b/frontend/src/i18n/locales/pt-BR.ts index ee1801568..348ad8fba 100644 --- a/frontend/src/i18n/locales/pt-BR.ts +++ b/frontend/src/i18n/locales/pt-BR.ts @@ -5235,6 +5235,8 @@ export default { noMatchingPresets: 'Nenhuma predefinição correspondente encontrada.', custom: 'Personalizado', builtin: 'Integrado', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: 'Configurações enviadas para a impressora', filamentProfile: 'Perfil de Filamento', kProfileLabel: 'Perfil K (Avanço de Pressão)', diff --git a/frontend/src/i18n/locales/tr.ts b/frontend/src/i18n/locales/tr.ts index 580d6c7c3..53a3ab2ef 100644 --- a/frontend/src/i18n/locales/tr.ts +++ b/frontend/src/i18n/locales/tr.ts @@ -5190,6 +5190,8 @@ export default { noMatchingPresets: 'Eşleşen ön ayar bulunamadı.', custom: 'Özel', builtin: 'Yerleşik', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: 'Ayarlar yazıcıya gönderildi', filamentProfile: 'Filament Profili', kProfileLabel: 'K Profili (Basınç İlerlemesi)', diff --git a/frontend/src/i18n/locales/zh-CN.ts b/frontend/src/i18n/locales/zh-CN.ts index 14117d56d..323e10ccb 100644 --- a/frontend/src/i18n/locales/zh-CN.ts +++ b/frontend/src/i18n/locales/zh-CN.ts @@ -5234,6 +5234,8 @@ export default { noMatchingPresets: '未找到匹配的预设。', custom: '自定义', builtin: '内置', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: '设置已发送到打印机', filamentProfile: '耗材配置', kProfileLabel: 'K 值配置(压力推进)', diff --git a/frontend/src/i18n/locales/zh-TW.ts b/frontend/src/i18n/locales/zh-TW.ts index c2db9d8b5..b6fa1222a 100644 --- a/frontend/src/i18n/locales/zh-TW.ts +++ b/frontend/src/i18n/locales/zh-TW.ts @@ -5234,6 +5234,8 @@ export default { noMatchingPresets: '未找到匹配的預設。', custom: '自訂', builtin: '內建', + orcaCloud: 'Orca Cloud', + bambuCloud: 'Bambu Cloud', settingsSentToPrinter: '設定已傳送到印表機', filamentProfile: '耗材設定', kProfileLabel: 'K 值設定(壓力推進)', diff --git a/static/assets/index-OCdsEuOz.js b/static/assets/index-B3h_dfeT.js similarity index 75% rename from static/assets/index-OCdsEuOz.js rename to static/assets/index-B3h_dfeT.js index b23deb929..82a0fd8cf 100644 --- a/static/assets/index-OCdsEuOz.js +++ b/static/assets/index-B3h_dfeT.js @@ -5,43 +5,43 @@ function hme(t,e){for(var a=0;aW||mt[M]!==Et[W]){var Ut=` `+mt[M].replace(" at new "," at ");return h.displayName&&Ut.includes("")&&(Ut=Ut.replace("",h.displayName)),Ut}while(1<=M&&0<=W);break}}}finally{q=!1,Error.prepareStackTrace=_}return(_=h?h.displayName||h.name:"")?O(_):""}function ee(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 Z(h.type,!1);case 11:return Z(h.type.render,!1);case 1:return Z(h.type,!0);case 31:return O("Activity");default:return""}}function re(h){try{var w="",_=null;do w+=ee(h,_),_=h,h=h.return;while(h);return w}catch(M){return` Error generating stack: `+M.message+` -`+M.stack}}var se=Object.prototype.hasOwnProperty,fe=t.unstable_scheduleCallback,ue=t.unstable_cancelCallback,pe=t.unstable_shouldYield,G=t.unstable_requestPaint,L=t.unstable_now,ae=t.unstable_getCurrentPriorityLevel,ge=t.unstable_ImmediatePriority,be=t.unstable_UserBlockingPriority,ve=t.unstable_NormalPriority,De=t.unstable_LowPriority,je=t.unstable_IdlePriority,Te=t.log,qe=t.unstable_setDisableYieldValue,Ce=null,Ie=null;function Re(h){if(typeof Te=="function"&&qe(h),Ie&&typeof Ie.setStrictMode=="function")try{Ie.setStrictMode(Ce,h)}catch{}}var Ue=Math.clz32?Math.clz32:Oe,ze=Math.log,nt=Math.LN2;function Oe(h){return h>>>=0,h===0?32:31-(ze(h)/nt|0)|0}var tt=256,Fe=262144,Ke=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 Me(h,w,_){var M=h.pendingLanes;if(M===0)return 0;var W=0,te=h.suspendedLanes,_e=h.pingedLanes;h=h.warmLanes;var He=M&134217727;return He!==0?(M=He&~te,M!==0?W=Ve(M):(_e&=He,_e!==0?W=Ve(_e):_||(_=He&~h,_!==0&&(W=Ve(_))))):(He=M&~te,He!==0?W=Ve(He):_e!==0?W=Ve(_e):_||(_=M&~h,_!==0&&(W=Ve(_)))),W===0?0:w!==0&&w!==W&&(w&te)===0&&(te=W&-W,_=w&-w,te>=_||te===32&&(_&4194048)!==0)?w:W}function Be(h,w){return(h.pendingLanes&~(h.suspendedLanes&~h.pingedLanes)&w)===0}function Qe(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 Ge(){var h=Ke;return Ke<<=1,(Ke&62914560)===0&&(Ke=4194304),h}function Ee(h){for(var w=[],_=0;31>_;_++)w.push(h);return w}function rt(h,w){h.pendingLanes|=w,w!==268435456&&(h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0)}function Xe(h,w,_,M,W,te){var _e=h.pendingLanes;h.pendingLanes=_,h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0,h.expiredLanes&=_,h.entangledLanes&=_,h.errorRecoveryDisabledLanes&=_,h.shellSuspendCounter=0;var He=h.entanglements,mt=h.expirationTimes,Et=h.hiddenUpdates;for(_=_e&~_;0<_;){var Ut=31-Ue(_),Wt=1<"u")return null;try{return h.activeElement||h.body}catch{return h.body}}var yr=/[\n"\\]/g;function ja(h){return h.replace(yr,function(w){return"\\"+w.charCodeAt(0).toString(16)+" "})}function $a(h,w,_,M,W,te,_e,He){h.name="",_e!=null&&typeof _e!="function"&&typeof _e!="symbol"&&typeof _e!="boolean"?h.type=_e:h.removeAttribute("type"),w!=null?_e==="number"?(w===0&&h.value===""||h.value!=w)&&(h.value=""+ia(w)):h.value!==""+ia(w)&&(h.value=""+ia(w)):_e!=="submit"&&_e!=="reset"||h.removeAttribute("value"),w!=null?Gr(h,_e,ia(w)):_!=null?Gr(h,_e,ia(_)):M!=null&&h.removeAttribute("value"),W==null&&te!=null&&(h.defaultChecked=!!te),W!=null&&(h.checked=W&&typeof W!="function"&&typeof W!="symbol"),He!=null&&typeof He!="function"&&typeof He!="symbol"&&typeof He!="boolean"?h.name=""+ia(He):h.removeAttribute("name")}function Oa(h,w,_,M,W,te,_e,He){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)){Jt(h);return}_=_!=null?""+ia(_):"",w=w!=null?""+ia(w):_,He||w===h.value||(h.value=w),h.defaultValue=w}M=M??W,M=typeof M!="function"&&typeof M!="symbol"&&!!M,h.checked=He?h.checked:!!M,h.defaultChecked=!!M,_e!=null&&typeof _e!="function"&&typeof _e!="symbol"&&typeof _e!="boolean"&&(h.name=_e),Jt(h)}function Gr(h,w,_){w==="number"&&Ua(h.ownerDocument)===h||h.defaultValue===""+_||(h.defaultValue=""+_)}function et(h,w,_,M){if(h=h.options,w){w={};for(var W=0;W<_.length;W++)w["$"+_[W]]=!0;for(_=0;_"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),bp=!1;if(rr)try{var Cd={};Object.defineProperty(Cd,"passive",{get:function(){bp=!0}}),window.addEventListener("test",Cd,Cd),window.removeEventListener("test",Cd,Cd)}catch{bp=!1}var mi=null,Du=null,Si=null;function Sf(){if(Si)return Si;var h,w=Du,_=w.length,M,W="value"in mi?mi.value:mi.textContent,te=W.length;for(h=0;h<_&&w[h]===W[h];h++);var _e=_-h;for(M=1;M<=_e&&w[_-M]===W[te-M];M++);return Si=W.slice(h,1=hi),Sp=" ",Nb=!1;function ye(h,w){switch(h){case"keyup":return Cv.indexOf(w.keyCode)!==-1;case"keydown":return w.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Rt(h){return h=h.detail,typeof h=="object"&&"data"in h?h.data:null}var pa=!1;function Ma(h,w){switch(h){case"compositionend":return Rt(w);case"keypress":return w.which!==32?null:(Nb=!0,Sp);case"textInput":return h=w.data,h===Sp&&Nb?null:h;default:return null}}function Wa(h,w){if(pa)return h==="compositionend"||!ul&&ye(h,w)?(h=Sf(),Si=Du=mi=null,pa=!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=M}e:{for(;_;){if(_.nextSibling){_=_.nextSibling;break e}_=_.parentNode}_=void 0}_=Fo(_)}}function Lo(h,w){return h&&w?h===w?!0:h&&h.nodeType===3?!1:w&&w.nodeType===3?Lo(h,w.parentNode):"contains"in h?h.contains(w):h.compareDocumentPosition?!!(h.compareDocumentPosition(w)&16):!1:!1}function mo(h){h=h!=null&&h.ownerDocument!=null&&h.ownerDocument.defaultView!=null?h.ownerDocument.defaultView:window;for(var w=Ua(h.document);w instanceof h.HTMLIFrameElement;){try{var _=typeof w.contentWindow.location.href=="string"}catch{_=!1}if(_)h=w.contentWindow;else break;w=Ua(h.document)}return w}function _i(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 Md=rr&&"documentMode"in document&&11>=document.documentMode,fi=null,wr=null,zr=null,Zn=!1;function kp(h,w,_){var M=_.window===_?_.document:_.nodeType===9?_:_.ownerDocument;Zn||fi==null||fi!==Ua(M)||(M=fi,"selectionStart"in M&&_i(M)?M={start:M.selectionStart,end:M.selectionEnd}:(M=(M.ownerDocument&&M.ownerDocument.defaultView||window).getSelection(),M={anchorNode:M.anchorNode,anchorOffset:M.anchorOffset,focusNode:M.focusNode,focusOffset:M.focusOffset}),zr&&Ss(zr,M)||(zr=M,M=x_(wr,"onSelect"),0>=_e,W-=_e,Dd=1<<32-Ue(w)+W|_<sr?(jr=Aa,Aa=null):jr=Aa.sibling;var Or=Dt(Pt,Aa,Mt[sr],Gt);if(Or===null){Aa===null&&(Aa=jr);break}h&&Aa&&Or.alternate===null&&w(Pt,Aa),gt=te(Or,gt,sr),Ir===null?Ra=Or:Ir.sibling=Or,Ir=Or,Aa=jr}if(sr===Mt.length)return _(Pt,Aa),Mr&&Uu(Pt,sr),Ra;if(Aa===null){for(;srsr?(jr=Aa,Aa=null):jr=Aa.sibling;var Gp=Dt(Pt,Aa,Or.value,Gt);if(Gp===null){Aa===null&&(Aa=jr);break}h&&Aa&&Gp.alternate===null&&w(Pt,Aa),gt=te(Gp,gt,sr),Ir===null?Ra=Gp:Ir.sibling=Gp,Ir=Gp,Aa=jr}if(Or.done)return _(Pt,Aa),Mr&&Uu(Pt,sr),Ra;if(Aa===null){for(;!Or.done;sr++,Or=Mt.next())Or=Wt(Pt,Or.value,Gt),Or!==null&&(gt=te(Or,gt,sr),Ir===null?Ra=Or:Ir.sibling=Or,Ir=Or);return Mr&&Uu(Pt,sr),Ra}for(Aa=M(Aa);!Or.done;sr++,Or=Mt.next())Or=zt(Aa,Pt,sr,Or.value,Gt),Or!==null&&(h&&Or.alternate!==null&&Aa.delete(Or.key===null?sr:Or.key),gt=te(Or,gt,sr),Ir===null?Ra=Or:Ir.sibling=Or,Ir=Or);return h&&Aa.forEach(function(pme){return w(Pt,pme)}),Mr&&Uu(Pt,sr),Ra}function ln(Pt,gt,Mt,Gt){if(typeof Mt=="object"&&Mt!==null&&Mt.type===v&&Mt.key===null&&(Mt=Mt.props.children),typeof Mt=="object"&&Mt!==null){switch(Mt.$$typeof){case f:e:{for(var Ra=Mt.key;gt!==null;){if(gt.key===Ra){if(Ra=Mt.type,Ra===v){if(gt.tag===7){_(Pt,gt.sibling),Gt=W(gt,Mt.props.children),Gt.return=Pt,Pt=Gt;break e}}else if(gt.elementType===Ra||typeof Ra=="object"&&Ra!==null&&Ra.$$typeof===D&&Ef(Ra)===gt.type){_(Pt,gt.sibling),Gt=W(gt,Mt.props),Ev(Gt,Mt),Gt.return=Pt,Pt=Gt;break e}_(Pt,gt);break}else w(Pt,gt);gt=gt.sibling}Mt.type===v?(Gt=Nf(Mt.props.children,Pt.mode,Gt,Mt.key),Gt.return=Pt,Pt=Gt):(Gt=Lk(Mt.type,Mt.key,Mt.props,null,Pt.mode,Gt),Ev(Gt,Mt),Gt.return=Pt,Pt=Gt)}return _e(Pt);case g:e:{for(Ra=Mt.key;gt!==null;){if(gt.key===Ra)if(gt.tag===4&>.stateNode.containerInfo===Mt.containerInfo&>.stateNode.implementation===Mt.implementation){_(Pt,gt.sibling),Gt=W(gt,Mt.children||[]),Gt.return=Pt,Pt=Gt;break e}else{_(Pt,gt);break}else w(Pt,gt);gt=gt.sibling}Gt=Cj(Mt,Pt.mode,Gt),Gt.return=Pt,Pt=Gt}return _e(Pt);case D:return Mt=Ef(Mt),ln(Pt,gt,Mt,Gt)}if(K(Mt))return Pa(Pt,gt,Mt,Gt);if(I(Mt)){if(Ra=I(Mt),typeof Ra!="function")throw Error(n(150));return Mt=Ra.call(Mt),qa(Pt,gt,Mt,Gt)}if(typeof Mt.then=="function")return ln(Pt,gt,Hk(Mt),Gt);if(Mt.$$typeof===k)return ln(Pt,gt,Ik(Pt,Mt),Gt);qk(Pt,Mt)}return typeof Mt=="string"&&Mt!==""||typeof Mt=="number"||typeof Mt=="bigint"?(Mt=""+Mt,gt!==null&>.tag===6?(_(Pt,gt.sibling),Gt=W(gt,Mt),Gt.return=Pt,Pt=Gt):(_(Pt,gt),Gt=Pj(Mt,Pt.mode,Gt),Gt.return=Pt,Pt=Gt),_e(Pt)):_(Pt,gt)}return function(Pt,gt,Mt,Gt){try{Mv=0;var Ra=ln(Pt,gt,Mt,Gt);return zb=null,Ra}catch(Aa){if(Aa===Rb||Aa===Bk)throw Aa;var Ir=ml(29,Aa,null,Pt.mode);return Ir.lanes=Gt,Ir.return=Pt,Ir}}}var Ff=Y5(!0),Q5=Y5(!1),Tp=!1;function Ij(h){h.updateQueue={baseState:h.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Oj(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 Ap(h){return{lane:h,tag:0,payload:null,callback:null,next:null}}function jp(h,w,_){var M=h.updateQueue;if(M===null)return null;if(M=M.shared,(Vr&2)!==0){var W=M.pending;return W===null?w.next=w:(w.next=W.next,W.next=w),M.pending=w,w=Fk(h),D5(h,null,_),w}return Dk(h,M,w,_),Fk(h)}function Dv(h,w,_){if(w=w.updateQueue,w!==null&&(w=w.shared,(_&4194048)!==0)){var M=w.lanes;M&=h.pendingLanes,_|=M,w.lanes=_,Vt(h,_)}}function Bj(h,w){var _=h.updateQueue,M=h.alternate;if(M!==null&&(M=M.updateQueue,_===M)){var W=null,te=null;if(_=_.firstBaseUpdate,_!==null){do{var _e={lane:_.lane,tag:_.tag,payload:_.payload,callback:null,next:null};te===null?W=te=_e:te=te.next=_e,_=_.next}while(_!==null);te===null?W=te=w:te=te.next=w}else W=te=w;_={baseState:M.baseState,firstBaseUpdate:W,lastBaseUpdate:te,shared:M.shared,callbacks:M.callbacks},h.updateQueue=_;return}h=_.lastBaseUpdate,h===null?_.firstBaseUpdate=w:h.next=w,_.lastBaseUpdate=w}var Uj=!1;function Fv(){if(Uj){var h=Lb;if(h!==null)throw h}}function Lv(h,w,_,M){Uj=!1;var W=h.updateQueue;Tp=!1;var te=W.firstBaseUpdate,_e=W.lastBaseUpdate,He=W.shared.pending;if(He!==null){W.shared.pending=null;var mt=He,Et=mt.next;mt.next=null,_e===null?te=Et:_e.next=Et,_e=mt;var Ut=h.alternate;Ut!==null&&(Ut=Ut.updateQueue,He=Ut.lastBaseUpdate,He!==_e&&(He===null?Ut.firstBaseUpdate=Et:He.next=Et,Ut.lastBaseUpdate=mt))}if(te!==null){var Wt=W.baseState;_e=0,Ut=Et=mt=null,He=te;do{var Dt=He.lane&-536870913,zt=Dt!==He.lane;if(zt?(Ar&Dt)===Dt:(M&Dt)===Dt){Dt!==0&&Dt===Fb&&(Uj=!0),Ut!==null&&(Ut=Ut.next={lane:0,tag:He.tag,payload:He.payload,callback:null,next:null});e:{var Pa=h,qa=He;Dt=w;var ln=_;switch(qa.tag){case 1:if(Pa=qa.payload,typeof Pa=="function"){Wt=Pa.call(ln,Wt,Dt);break e}Wt=Pa;break e;case 3:Pa.flags=Pa.flags&-65537|128;case 0:if(Pa=qa.payload,Dt=typeof Pa=="function"?Pa.call(ln,Wt,Dt):Pa,Dt==null)break e;Wt=m({},Wt,Dt);break e;case 2:Tp=!0}}Dt=He.callback,Dt!==null&&(h.flags|=64,zt&&(h.flags|=8192),zt=W.callbacks,zt===null?W.callbacks=[Dt]:zt.push(Dt))}else zt={lane:Dt,tag:He.tag,payload:He.payload,callback:He.callback,next:null},Ut===null?(Et=Ut=zt,mt=Wt):Ut=Ut.next=zt,_e|=Dt;if(He=He.next,He===null){if(He=W.shared.pending,He===null)break;zt=He,He=zt.next,zt.next=null,W.lastBaseUpdate=zt,W.shared.pending=null}}while(!0);Ut===null&&(mt=Wt),W.baseState=mt,W.firstBaseUpdate=Et,W.lastBaseUpdate=Ut,te===null&&(W.shared.lanes=0),Lp|=_e,h.lanes=_e,h.memoizedState=Wt}}function X5(h,w){if(typeof h!="function")throw Error(n(191,h));h.call(w)}function Z5(h,w){var _=h.callbacks;if(_!==null)for(h.callbacks=null,h=0;h<_.length;h++)X5(_[h],w)}var Ib=Y(null),Vk=Y(0);function J5(h,w){h=Zu,me(Vk,h),me(Ib,w),Zu=h|w.baseLanes}function Hj(){me(Vk,Zu),me(Ib,Ib.current)}function qj(){Zu=Vk.current,ie(Ib),ie(Vk)}var pl=Y(null),Zl=null;function Mp(h){var w=h.alternate;me(gi,gi.current&1),me(pl,h),Zl===null&&(w===null||Ib.current!==null||w.memoizedState!==null)&&(Zl=h)}function Vj(h){me(gi,gi.current),me(pl,h),Zl===null&&(Zl=h)}function eU(h){h.tag===22?(me(gi,gi.current),me(pl,h),Zl===null&&(Zl=h)):Ep()}function Ep(){me(gi,gi.current),me(pl,pl.current)}function hl(h){ie(pl),Zl===h&&(Zl=null),ie(gi)}var gi=Y(0);function Gk(h){for(var w=h;w!==null;){if(w.tag===13){var _=w.memoizedState;if(_!==null&&(_=_.dehydrated,_===null||QM(_)||XM(_)))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 Vu=0,nr=null,sn=null,Ci=null,$k=!1,Ob=!1,Lf=!1,Wk=0,Rv=0,Bb=null,rue=0;function Jn(){throw Error(n(321))}function Gj(h,w){if(w===null)return!1;for(var _=0;_te?te:8;var _e=J.T,He={};J.T=He,sM(h,!1,w,_);try{var mt=W(),Et=J.S;if(Et!==null&&Et(He,mt),mt!==null&&typeof mt=="object"&&typeof mt.then=="function"){var Ut=aue(mt,M);Iv(h,w,Ut,bl(h))}else Iv(h,w,M,bl(h))}catch(Wt){Iv(h,w,{then:function(){},status:"rejected",reason:Wt},bl())}finally{X.p=te,_e!==null&&He.types!==null&&(_e.types=He.types),J.T=_e}}function lue(){}function nM(h,w,_,M){if(h.tag!==5)throw Error(n(476));var W=jU(h).queue;AU(h,W,w,ce,_===null?lue:function(){return MU(h),_(M)})}function jU(h){var w=h.memoizedState;if(w!==null)return w;w={memoizedState:ce,baseState:ce,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Gu,lastRenderedState:ce},next:null};var _={};return w.next={memoizedState:_,baseState:_,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Gu,lastRenderedState:_},next:null},h.memoizedState=w,h=h.alternate,h!==null&&(h.memoizedState=w),w}function MU(h){var w=jU(h);w.next===null&&(w=h.alternate.memoizedState),Iv(h,w.next.queue,{},bl())}function iM(){return _s(t0)}function EU(){return bi().memoizedState}function DU(){return bi().memoizedState}function cue(h){for(var w=h.return;w!==null;){switch(w.tag){case 24:case 3:var _=bl();h=Ap(_);var M=jp(w,h,_);M!==null&&(Bo(M,w,_),Dv(M,w,_)),w={cache:Fj()},h.payload=w;return}w=w.return}}function due(h,w,_){var M=bl();_={lane:M,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null},Jk(h)?LU(w,_):(_=kj(h,w,_,M),_!==null&&(Bo(_,h,M),RU(_,w,M)))}function FU(h,w,_){var M=bl();Iv(h,w,_,M)}function Iv(h,w,_,M){var W={lane:M,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null};if(Jk(h))LU(w,W);else{var te=h.alternate;if(h.lanes===0&&(te===null||te.lanes===0)&&(te=w.lastRenderedReducer,te!==null))try{var _e=w.lastRenderedState,He=te(_e,_);if(W.hasEagerState=!0,W.eagerState=He,Fn(He,_e))return Dk(h,w,W,0),xn===null&&Ek(),!1}catch{}if(_=kj(h,w,W,M),_!==null)return Bo(_,h,M),RU(_,w,M),!0}return!1}function sM(h,w,_,M){if(M={lane:2,revertLane:IM(),gesture:null,action:M,hasEagerState:!1,eagerState:null,next:null},Jk(h)){if(w)throw Error(n(479))}else w=kj(h,_,M,2),w!==null&&Bo(w,h,2)}function Jk(h){var w=h.alternate;return h===nr||w!==null&&w===nr}function LU(h,w){Ob=$k=!0;var _=h.pending;_===null?w.next=w:(w.next=_.next,_.next=w),h.pending=w}function RU(h,w,_){if((_&4194048)!==0){var M=w.lanes;M&=h.pendingLanes,_|=M,w.lanes=_,Vt(h,_)}}var Ov={readContext:_s,use:Yk,useCallback:Jn,useContext:Jn,useEffect:Jn,useImperativeHandle:Jn,useLayoutEffect:Jn,useInsertionEffect:Jn,useMemo:Jn,useReducer:Jn,useRef:Jn,useState:Jn,useDebugValue:Jn,useDeferredValue:Jn,useTransition:Jn,useSyncExternalStore:Jn,useId:Jn,useHostTransitionStatus:Jn,useFormState:Jn,useActionState:Jn,useOptimistic:Jn,useMemoCache:Jn,useCacheRefresh:Jn};Ov.useEffectEvent=Jn;var zU={readContext:_s,use:Yk,useCallback:function(h,w){return po().memoizedState=[h,w===void 0?null:w],h},useContext:_s,useEffect:vU,useImperativeHandle:function(h,w,_){_=_!=null?_.concat([h]):null,Xk(4194308,4,_U.bind(null,w,h),_)},useLayoutEffect:function(h,w){return Xk(4194308,4,h,w)},useInsertionEffect:function(h,w){Xk(4,2,h,w)},useMemo:function(h,w){var _=po();w=w===void 0?null:w;var M=h();if(Lf){Re(!0);try{h()}finally{Re(!1)}}return _.memoizedState=[M,w],M},useReducer:function(h,w,_){var M=po();if(_!==void 0){var W=_(w);if(Lf){Re(!0);try{_(w)}finally{Re(!1)}}}else W=w;return M.memoizedState=M.baseState=W,h={pending:null,lanes:0,dispatch:null,lastRenderedReducer:h,lastRenderedState:W},M.queue=h,h=h.dispatch=due.bind(null,nr,h),[M.memoizedState,h]},useRef:function(h){var w=po();return h={current:h},w.memoizedState=h},useState:function(h){h=Jj(h);var w=h.queue,_=FU.bind(null,nr,w);return w.dispatch=_,[h.memoizedState,_]},useDebugValue:aM,useDeferredValue:function(h,w){var _=po();return rM(_,h,w)},useTransition:function(){var h=Jj(!1);return h=AU.bind(null,nr,h.queue,!0,!1),po().memoizedState=h,[!1,h]},useSyncExternalStore:function(h,w,_){var M=nr,W=po();if(Mr){if(_===void 0)throw Error(n(407));_=_()}else{if(_=w(),xn===null)throw Error(n(349));(Ar&127)!==0||nU(M,w,_)}W.memoizedState=_;var te={value:_,getSnapshot:w};return W.queue=te,vU(sU.bind(null,M,te,h),[h]),M.flags|=2048,Ub(9,{destroy:void 0},iU.bind(null,M,te,_,w),null),_},useId:function(){var h=po(),w=xn.identifierPrefix;if(Mr){var _=Fd,M=Dd;_=(M&~(1<<32-Ue(M)-1)).toString(32)+_,w="_"+w+"R_"+_,_=Wk++,0<_&&(w+="H"+_.toString(32)),w+="_"}else _=rue++,w="_"+w+"r_"+_.toString(32)+"_";return h.memoizedState=w},useHostTransitionStatus:iM,useFormState:fU,useActionState:fU,useOptimistic:function(h){var w=po();w.memoizedState=w.baseState=h;var _={pending:null,lanes:0,dispatch:null,lastRenderedReducer:null,lastRenderedState:null};return w.queue=_,w=sM.bind(null,nr,!0,_),_.dispatch=w,[h,w]},useMemoCache:Qj,useCacheRefresh:function(){return po().memoizedState=cue.bind(null,nr)},useEffectEvent:function(h){var w=po(),_={impl:h};return w.memoizedState=_,function(){if((Vr&2)!==0)throw Error(n(440));return _.impl.apply(void 0,arguments)}}},oM={readContext:_s,use:Yk,useCallback:CU,useContext:_s,useEffect:tM,useImperativeHandle:PU,useInsertionEffect:SU,useLayoutEffect:kU,useMemo:NU,useReducer:Qk,useRef:yU,useState:function(){return Qk(Gu)},useDebugValue:aM,useDeferredValue:function(h,w){var _=bi();return TU(_,sn.memoizedState,h,w)},useTransition:function(){var h=Qk(Gu)[0],w=bi().memoizedState;return[typeof h=="boolean"?h:zv(h),w]},useSyncExternalStore:rU,useId:EU,useHostTransitionStatus:iM,useFormState:gU,useActionState:gU,useOptimistic:function(h,w){var _=bi();return cU(_,sn,h,w)},useMemoCache:Qj,useCacheRefresh:DU};oM.useEffectEvent=wU;var IU={readContext:_s,use:Yk,useCallback:CU,useContext:_s,useEffect:tM,useImperativeHandle:PU,useInsertionEffect:SU,useLayoutEffect:kU,useMemo:NU,useReducer:Zj,useRef:yU,useState:function(){return Zj(Gu)},useDebugValue:aM,useDeferredValue:function(h,w){var _=bi();return sn===null?rM(_,h,w):TU(_,sn.memoizedState,h,w)},useTransition:function(){var h=Zj(Gu)[0],w=bi().memoizedState;return[typeof h=="boolean"?h:zv(h),w]},useSyncExternalStore:rU,useId:EU,useHostTransitionStatus:iM,useFormState:xU,useActionState:xU,useOptimistic:function(h,w){var _=bi();return sn!==null?cU(_,sn,h,w):(_.baseState=h,[h,_.queue.dispatch])},useMemoCache:Qj,useCacheRefresh:DU};IU.useEffectEvent=wU;function lM(h,w,_,M){w=h.memoizedState,_=_(M,w),_=_==null?w:m({},w,_),h.memoizedState=_,h.lanes===0&&(h.updateQueue.baseState=_)}var cM={enqueueSetState:function(h,w,_){h=h._reactInternals;var M=bl(),W=Ap(M);W.payload=w,_!=null&&(W.callback=_),w=jp(h,W,M),w!==null&&(Bo(w,h,M),Dv(w,h,M))},enqueueReplaceState:function(h,w,_){h=h._reactInternals;var M=bl(),W=Ap(M);W.tag=1,W.payload=w,_!=null&&(W.callback=_),w=jp(h,W,M),w!==null&&(Bo(w,h,M),Dv(w,h,M))},enqueueForceUpdate:function(h,w){h=h._reactInternals;var _=bl(),M=Ap(_);M.tag=2,w!=null&&(M.callback=w),w=jp(h,M,_),w!==null&&(Bo(w,h,_),Dv(w,h,_))}};function OU(h,w,_,M,W,te,_e){return h=h.stateNode,typeof h.shouldComponentUpdate=="function"?h.shouldComponentUpdate(M,te,_e):w.prototype&&w.prototype.isPureReactComponent?!Ss(_,M)||!Ss(W,te):!0}function BU(h,w,_,M){h=w.state,typeof w.componentWillReceiveProps=="function"&&w.componentWillReceiveProps(_,M),typeof w.UNSAFE_componentWillReceiveProps=="function"&&w.UNSAFE_componentWillReceiveProps(_,M),w.state!==h&&cM.enqueueReplaceState(w,w.state,null)}function Rf(h,w){var _=w;if("ref"in w){_={};for(var M in w)M!=="ref"&&(_[M]=w[M])}if(h=h.defaultProps){_===w&&(_=m({},_));for(var W in h)_[W]===void 0&&(_[W]=h[W])}return _}function UU(h){Mk(h)}function HU(h){console.error(h)}function qU(h){Mk(h)}function e_(h,w){try{var _=h.onUncaughtError;_(w.value,{componentStack:w.stack})}catch(M){setTimeout(function(){throw M})}}function VU(h,w,_){try{var M=h.onCaughtError;M(_.value,{componentStack:_.stack,errorBoundary:w.tag===1?w.stateNode:null})}catch(W){setTimeout(function(){throw W})}}function dM(h,w,_){return _=Ap(_),_.tag=3,_.payload={element:null},_.callback=function(){e_(h,w)},_}function GU(h){return h=Ap(h),h.tag=3,h}function $U(h,w,_,M){var W=_.type.getDerivedStateFromError;if(typeof W=="function"){var te=M.value;h.payload=function(){return W(te)},h.callback=function(){VU(w,_,M)}}var _e=_.stateNode;_e!==null&&typeof _e.componentDidCatch=="function"&&(h.callback=function(){VU(w,_,M),typeof W!="function"&&(Rp===null?Rp=new Set([this]):Rp.add(this));var He=M.stack;this.componentDidCatch(M.value,{componentStack:He!==null?He:""})})}function uue(h,w,_,M,W){if(_.flags|=32768,M!==null&&typeof M=="object"&&typeof M.then=="function"){if(w=_.alternate,w!==null&&Db(w,_,W,!0),_=pl.current,_!==null){switch(_.tag){case 31:case 13:return Zl===null?m_():_.alternate===null&&ei===0&&(ei=3),_.flags&=-257,_.flags|=65536,_.lanes=W,M===Uk?_.flags|=16384:(w=_.updateQueue,w===null?_.updateQueue=new Set([M]):w.add(M),LM(h,M,W)),!1;case 22:return _.flags|=65536,M===Uk?_.flags|=16384:(w=_.updateQueue,w===null?(w={transitions:null,markerInstances:null,retryQueue:new Set([M])},_.updateQueue=w):(_=w.retryQueue,_===null?w.retryQueue=new Set([M]):_.add(M)),LM(h,M,W)),!1}throw Error(n(435,_.tag))}return LM(h,M,W),m_(),!1}if(Mr)return w=pl.current,w!==null?((w.flags&65536)===0&&(w.flags|=256),w.flags|=65536,w.lanes=W,M!==Aj&&(h=Error(n(422),{cause:M}),Tv(Kl(h,_)))):(M!==Aj&&(w=Error(n(423),{cause:M}),Tv(Kl(w,_))),h=h.current.alternate,h.flags|=65536,W&=-W,h.lanes|=W,M=Kl(M,_),W=dM(h.stateNode,M,W),Bj(h,W),ei!==4&&(ei=2)),!1;var te=Error(n(520),{cause:M});if(te=Kl(te,_),Wv===null?Wv=[te]:Wv.push(te),ei!==4&&(ei=2),w===null)return!0;M=Kl(M,_),_=w;do{switch(_.tag){case 3:return _.flags|=65536,h=W&-W,_.lanes|=h,h=dM(_.stateNode,M,h),Bj(_,h),!1;case 1:if(w=_.type,te=_.stateNode,(_.flags&128)===0&&(typeof w.getDerivedStateFromError=="function"||te!==null&&typeof te.componentDidCatch=="function"&&(Rp===null||!Rp.has(te))))return _.flags|=65536,W&=-W,_.lanes|=W,W=GU(W),$U(W,h,_,M),Bj(_,W),!1}_=_.return}while(_!==null);return!1}var uM=Error(n(461)),Ni=!1;function Ps(h,w,_,M){w.child=h===null?Q5(w,null,_,M):Ff(w,h.child,_,M)}function WU(h,w,_,M,W){_=_.render;var te=w.ref;if("ref"in M){var _e={};for(var He in M)He!=="ref"&&(_e[He]=M[He])}else _e=M;return jf(w),M=$j(h,w,_,_e,te,W),He=Wj(),h!==null&&!Ni?(Kj(h,w,W),$u(h,w,W)):(Mr&&He&&Nj(w),w.flags|=1,Ps(h,w,M,W),w.child)}function KU(h,w,_,M,W){if(h===null){var te=_.type;return typeof te=="function"&&!_j(te)&&te.defaultProps===void 0&&_.compare===null?(w.tag=15,w.type=te,YU(h,w,te,M,W)):(h=Lk(_.type,null,M,w,w.mode,W),h.ref=w.ref,h.return=w,w.child=h)}if(te=h.child,!yM(h,W)){var _e=te.memoizedProps;if(_=_.compare,_=_!==null?_:Ss,_(_e,M)&&h.ref===w.ref)return $u(h,w,W)}return w.flags|=1,h=Bu(te,M),h.ref=w.ref,h.return=w,w.child=h}function YU(h,w,_,M,W){if(h!==null){var te=h.memoizedProps;if(Ss(te,M)&&h.ref===w.ref)if(Ni=!1,w.pendingProps=M=te,yM(h,W))(h.flags&131072)!==0&&(Ni=!0);else return w.lanes=h.lanes,$u(h,w,W)}return mM(h,w,_,M,W)}function QU(h,w,_,M){var W=M.children,te=h!==null?h.memoizedState:null;if(h===null&&w.stateNode===null&&(w.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),M.mode==="hidden"){if((w.flags&128)!==0){if(te=te!==null?te.baseLanes|_:_,h!==null){for(M=w.child=h.child,W=0;M!==null;)W=W|M.lanes|M.childLanes,M=M.sibling;M=W&~te}else M=0,w.child=null;return XU(h,w,te,_,M)}if((_&536870912)!==0)w.memoizedState={baseLanes:0,cachePool:null},h!==null&&Ok(w,te!==null?te.cachePool:null),te!==null?J5(w,te):Hj(),eU(w);else return M=w.lanes=536870912,XU(h,w,te!==null?te.baseLanes|_:_,_,M)}else te!==null?(Ok(w,te.cachePool),J5(w,te),Ep(),w.memoizedState=null):(h!==null&&Ok(w,null),Hj(),Ep());return Ps(h,w,W,_),w.child}function Bv(h,w){return h!==null&&h.tag===22||w.stateNode!==null||(w.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),w.sibling}function XU(h,w,_,M,W){var te=Rj();return te=te===null?null:{parent:Pi._currentValue,pool:te},w.memoizedState={baseLanes:_,cachePool:te},h!==null&&Ok(w,null),Hj(),eU(w),h!==null&&Db(h,w,M,!0),w.childLanes=W,null}function t_(h,w){return w=r_({mode:w.mode,children:w.children},h.mode),w.ref=h.ref,h.child=w,w.return=h,w}function ZU(h,w,_){return Ff(w,h.child,null,_),h=t_(w,w.pendingProps),h.flags|=2,hl(w),w.memoizedState=null,h}function mue(h,w,_){var M=w.pendingProps,W=(w.flags&128)!==0;if(w.flags&=-129,h===null){if(Mr){if(M.mode==="hidden")return h=t_(w,M),w.lanes=536870912,Bv(null,h);if(Vj(w),(h=Nn)?(h=dq(h,Xl),h=h!==null&&h.data==="&"?h:null,h!==null&&(w.memoizedState={dehydrated:h,treeContext:_p!==null?{id:Dd,overflow:Fd}:null,retryLane:536870912,hydrationErrors:null},_=L5(h),_.return=w,w.child=_,ks=w,Nn=null)):h=null,h===null)throw Cp(w);return w.lanes=536870912,null}return t_(w,M)}var te=h.memoizedState;if(te!==null){var _e=te.dehydrated;if(Vj(w),W)if(w.flags&256)w.flags&=-257,w=ZU(h,w,_);else if(w.memoizedState!==null)w.child=h.child,w.flags|=128,w=null;else throw Error(n(558));else if(Ni||Db(h,w,_,!1),W=(_&h.childLanes)!==0,Ni||W){if(M=xn,M!==null&&(_e=ht(M,_),_e!==0&&_e!==te.retryLane))throw te.retryLane=_e,Cf(h,_e),Bo(M,h,_e),uM;m_(),w=ZU(h,w,_)}else h=te.treeContext,Nn=Jl(_e.nextSibling),ks=w,Mr=!0,Pp=null,Xl=!1,h!==null&&I5(w,h),w=t_(w,M),w.flags|=4096;return w}return h=Bu(h.child,{mode:M.mode,children:M.children}),h.ref=w.ref,w.child=h,h.return=w,h}function a_(h,w){var _=w.ref;if(_===null)h!==null&&h.ref!==null&&(w.flags|=4194816);else{if(typeof _!="function"&&typeof _!="object")throw Error(n(284));(h===null||h.ref!==_)&&(w.flags|=4194816)}}function mM(h,w,_,M,W){return jf(w),_=$j(h,w,_,M,void 0,W),M=Wj(),h!==null&&!Ni?(Kj(h,w,W),$u(h,w,W)):(Mr&&M&&Nj(w),w.flags|=1,Ps(h,w,_,W),w.child)}function JU(h,w,_,M,W,te){return jf(w),w.updateQueue=null,_=aU(w,M,_,W),tU(h),M=Wj(),h!==null&&!Ni?(Kj(h,w,te),$u(h,w,te)):(Mr&&M&&Nj(w),w.flags|=1,Ps(h,w,_,te),w.child)}function eH(h,w,_,M,W){if(jf(w),w.stateNode===null){var te=Ab,_e=_.contextType;typeof _e=="object"&&_e!==null&&(te=_s(_e)),te=new _(M,te),w.memoizedState=te.state!==null&&te.state!==void 0?te.state:null,te.updater=cM,w.stateNode=te,te._reactInternals=w,te=w.stateNode,te.props=M,te.state=w.memoizedState,te.refs={},Ij(w),_e=_.contextType,te.context=typeof _e=="object"&&_e!==null?_s(_e):Ab,te.state=w.memoizedState,_e=_.getDerivedStateFromProps,typeof _e=="function"&&(lM(w,_,_e,M),te.state=w.memoizedState),typeof _.getDerivedStateFromProps=="function"||typeof te.getSnapshotBeforeUpdate=="function"||typeof te.UNSAFE_componentWillMount!="function"&&typeof te.componentWillMount!="function"||(_e=te.state,typeof te.componentWillMount=="function"&&te.componentWillMount(),typeof te.UNSAFE_componentWillMount=="function"&&te.UNSAFE_componentWillMount(),_e!==te.state&&cM.enqueueReplaceState(te,te.state,null),Lv(w,M,te,W),Fv(),te.state=w.memoizedState),typeof te.componentDidMount=="function"&&(w.flags|=4194308),M=!0}else if(h===null){te=w.stateNode;var He=w.memoizedProps,mt=Rf(_,He);te.props=mt;var Et=te.context,Ut=_.contextType;_e=Ab,typeof Ut=="object"&&Ut!==null&&(_e=_s(Ut));var Wt=_.getDerivedStateFromProps;Ut=typeof Wt=="function"||typeof te.getSnapshotBeforeUpdate=="function",He=w.pendingProps!==He,Ut||typeof te.UNSAFE_componentWillReceiveProps!="function"&&typeof te.componentWillReceiveProps!="function"||(He||Et!==_e)&&BU(w,te,M,_e),Tp=!1;var Dt=w.memoizedState;te.state=Dt,Lv(w,M,te,W),Fv(),Et=w.memoizedState,He||Dt!==Et||Tp?(typeof Wt=="function"&&(lM(w,_,Wt,M),Et=w.memoizedState),(mt=Tp||OU(w,_,mt,M,Dt,Et,_e))?(Ut||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=M,w.memoizedState=Et),te.props=M,te.state=Et,te.context=_e,M=mt):(typeof te.componentDidMount=="function"&&(w.flags|=4194308),M=!1)}else{te=w.stateNode,Oj(h,w),_e=w.memoizedProps,Ut=Rf(_,_e),te.props=Ut,Wt=w.pendingProps,Dt=te.context,Et=_.contextType,mt=Ab,typeof Et=="object"&&Et!==null&&(mt=_s(Et)),He=_.getDerivedStateFromProps,(Et=typeof He=="function"||typeof te.getSnapshotBeforeUpdate=="function")||typeof te.UNSAFE_componentWillReceiveProps!="function"&&typeof te.componentWillReceiveProps!="function"||(_e!==Wt||Dt!==mt)&&BU(w,te,M,mt),Tp=!1,Dt=w.memoizedState,te.state=Dt,Lv(w,M,te,W),Fv();var zt=w.memoizedState;_e!==Wt||Dt!==zt||Tp||h!==null&&h.dependencies!==null&&zk(h.dependencies)?(typeof He=="function"&&(lM(w,_,He,M),zt=w.memoizedState),(Ut=Tp||OU(w,_,Ut,M,Dt,zt,mt)||h!==null&&h.dependencies!==null&&zk(h.dependencies))?(Et||typeof te.UNSAFE_componentWillUpdate!="function"&&typeof te.componentWillUpdate!="function"||(typeof te.componentWillUpdate=="function"&&te.componentWillUpdate(M,zt,mt),typeof te.UNSAFE_componentWillUpdate=="function"&&te.UNSAFE_componentWillUpdate(M,zt,mt)),typeof te.componentDidUpdate=="function"&&(w.flags|=4),typeof te.getSnapshotBeforeUpdate=="function"&&(w.flags|=1024)):(typeof te.componentDidUpdate!="function"||_e===h.memoizedProps&&Dt===h.memoizedState||(w.flags|=4),typeof te.getSnapshotBeforeUpdate!="function"||_e===h.memoizedProps&&Dt===h.memoizedState||(w.flags|=1024),w.memoizedProps=M,w.memoizedState=zt),te.props=M,te.state=zt,te.context=mt,M=Ut):(typeof te.componentDidUpdate!="function"||_e===h.memoizedProps&&Dt===h.memoizedState||(w.flags|=4),typeof te.getSnapshotBeforeUpdate!="function"||_e===h.memoizedProps&&Dt===h.memoizedState||(w.flags|=1024),M=!1)}return te=M,a_(h,w),M=(w.flags&128)!==0,te||M?(te=w.stateNode,_=M&&typeof _.getDerivedStateFromError!="function"?null:te.render(),w.flags|=1,h!==null&&M?(w.child=Ff(w,h.child,null,W),w.child=Ff(w,null,_,W)):Ps(h,w,_,W),w.memoizedState=te.state,h=w.child):h=$u(h,w,W),h}function tH(h,w,_,M){return Tf(),w.flags|=256,Ps(h,w,_,M),w.child}var pM={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function hM(h){return{baseLanes:h,cachePool:V5()}}function fM(h,w,_){return h=h!==null?h.childLanes&~_:0,w&&(h|=gl),h}function aH(h,w,_){var M=w.pendingProps,W=!1,te=(w.flags&128)!==0,_e;if((_e=te)||(_e=h!==null&&h.memoizedState===null?!1:(gi.current&2)!==0),_e&&(W=!0,w.flags&=-129),_e=(w.flags&32)!==0,w.flags&=-33,h===null){if(Mr){if(W?Mp(w):Ep(),(h=Nn)?(h=dq(h,Xl),h=h!==null&&h.data!=="&"?h:null,h!==null&&(w.memoizedState={dehydrated:h,treeContext:_p!==null?{id:Dd,overflow:Fd}:null,retryLane:536870912,hydrationErrors:null},_=L5(h),_.return=w,w.child=_,ks=w,Nn=null)):h=null,h===null)throw Cp(w);return XM(h)?w.lanes=32:w.lanes=536870912,null}var He=M.children;return M=M.fallback,W?(Ep(),W=w.mode,He=r_({mode:"hidden",children:He},W),M=Nf(M,W,_,null),He.return=w,M.return=w,He.sibling=M,w.child=He,M=w.child,M.memoizedState=hM(_),M.childLanes=fM(h,_e,_),w.memoizedState=pM,Bv(null,M)):(Mp(w),gM(w,He))}var mt=h.memoizedState;if(mt!==null&&(He=mt.dehydrated,He!==null)){if(te)w.flags&256?(Mp(w),w.flags&=-257,w=bM(h,w,_)):w.memoizedState!==null?(Ep(),w.child=h.child,w.flags|=128,w=null):(Ep(),He=M.fallback,W=w.mode,M=r_({mode:"visible",children:M.children},W),He=Nf(He,W,_,null),He.flags|=2,M.return=w,He.return=w,M.sibling=He,w.child=M,Ff(w,h.child,null,_),M=w.child,M.memoizedState=hM(_),M.childLanes=fM(h,_e,_),w.memoizedState=pM,w=Bv(null,M));else if(Mp(w),XM(He)){if(_e=He.nextSibling&&He.nextSibling.dataset,_e)var Et=_e.dgst;_e=Et,M=Error(n(419)),M.stack="",M.digest=_e,Tv({value:M,source:null,stack:null}),w=bM(h,w,_)}else if(Ni||Db(h,w,_,!1),_e=(_&h.childLanes)!==0,Ni||_e){if(_e=xn,_e!==null&&(M=ht(_e,_),M!==0&&M!==mt.retryLane))throw mt.retryLane=M,Cf(h,M),Bo(_e,h,M),uM;QM(He)||m_(),w=bM(h,w,_)}else QM(He)?(w.flags|=192,w.child=h.child,w=null):(h=mt.treeContext,Nn=Jl(He.nextSibling),ks=w,Mr=!0,Pp=null,Xl=!1,h!==null&&I5(w,h),w=gM(w,M.children),w.flags|=4096);return w}return W?(Ep(),He=M.fallback,W=w.mode,mt=h.child,Et=mt.sibling,M=Bu(mt,{mode:"hidden",children:M.children}),M.subtreeFlags=mt.subtreeFlags&65011712,Et!==null?He=Bu(Et,He):(He=Nf(He,W,_,null),He.flags|=2),He.return=w,M.return=w,M.sibling=He,w.child=M,Bv(null,M),M=w.child,He=h.child.memoizedState,He===null?He=hM(_):(W=He.cachePool,W!==null?(mt=Pi._currentValue,W=W.parent!==mt?{parent:mt,pool:mt}:W):W=V5(),He={baseLanes:He.baseLanes|_,cachePool:W}),M.memoizedState=He,M.childLanes=fM(h,_e,_),w.memoizedState=pM,Bv(h.child,M)):(Mp(w),_=h.child,h=_.sibling,_=Bu(_,{mode:"visible",children:M.children}),_.return=w,_.sibling=null,h!==null&&(_e=w.deletions,_e===null?(w.deletions=[h],w.flags|=16):_e.push(h)),w.child=_,w.memoizedState=null,_)}function gM(h,w){return w=r_({mode:"visible",children:w},h.mode),w.return=h,h.child=w}function r_(h,w){return h=ml(22,h,null,w),h.lanes=0,h}function bM(h,w,_){return Ff(w,h.child,null,_),h=gM(w,w.pendingProps.children),h.flags|=2,w.memoizedState=null,h}function rH(h,w,_){h.lanes|=w;var M=h.alternate;M!==null&&(M.lanes|=w),Ej(h.return,w,_)}function xM(h,w,_,M,W,te){var _e=h.memoizedState;_e===null?h.memoizedState={isBackwards:w,rendering:null,renderingStartTime:0,last:M,tail:_,tailMode:W,treeForkCount:te}:(_e.isBackwards=w,_e.rendering=null,_e.renderingStartTime=0,_e.last=M,_e.tail=_,_e.tailMode=W,_e.treeForkCount=te)}function nH(h,w,_){var M=w.pendingProps,W=M.revealOrder,te=M.tail;M=M.children;var _e=gi.current,He=(_e&2)!==0;if(He?(_e=_e&1|2,w.flags|=128):_e&=1,me(gi,_e),Ps(h,w,M,_),M=Mr?Nv:0,!He&&h!==null&&(h.flags&128)!==0)e:for(h=w.child;h!==null;){if(h.tag===13)h.memoizedState!==null&&rH(h,_,w);else if(h.tag===19)rH(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(W){case"forwards":for(_=w.child,W=null;_!==null;)h=_.alternate,h!==null&&Gk(h)===null&&(W=_),_=_.sibling;_=W,_===null?(W=w.child,w.child=null):(W=_.sibling,_.sibling=null),xM(w,!1,W,_,te,M);break;case"backwards":case"unstable_legacy-backwards":for(_=null,W=w.child,w.child=null;W!==null;){if(h=W.alternate,h!==null&&Gk(h)===null){w.child=W;break}h=W.sibling,W.sibling=_,_=W,W=h}xM(w,!0,_,null,te,M);break;case"together":xM(w,!1,null,null,void 0,M);break;default:w.memoizedState=null}return w.child}function $u(h,w,_){if(h!==null&&(w.dependencies=h.dependencies),Lp|=w.lanes,(_&w.childLanes)===0)if(h!==null){if(Db(h,w,_,!1),(_&w.childLanes)===0)return null}else return null;if(h!==null&&w.child!==h.child)throw Error(n(153));if(w.child!==null){for(h=w.child,_=Bu(h,h.pendingProps),w.child=_,_.return=w;h.sibling!==null;)h=h.sibling,_=_.sibling=Bu(h,h.pendingProps),_.return=w;_.sibling=null}return w.child}function yM(h,w){return(h.lanes&w)!==0?!0:(h=h.dependencies,!!(h!==null&&zk(h)))}function pue(h,w,_){switch(w.tag){case 3:A(w,w.stateNode.containerInfo),Np(w,Pi,h.memoizedState.cache),Tf();break;case 27:case 5:U(w);break;case 4:A(w,w.stateNode.containerInfo);break;case 10:Np(w,w.type,w.memoizedProps.value);break;case 31:if(w.memoizedState!==null)return w.flags|=128,Vj(w),null;break;case 13:var M=w.memoizedState;if(M!==null)return M.dehydrated!==null?(Mp(w),w.flags|=128,null):(_&w.child.childLanes)!==0?aH(h,w,_):(Mp(w),h=$u(h,w,_),h!==null?h.sibling:null);Mp(w);break;case 19:var W=(h.flags&128)!==0;if(M=(_&w.childLanes)!==0,M||(Db(h,w,_,!1),M=(_&w.childLanes)!==0),W){if(M)return nH(h,w,_);w.flags|=128}if(W=w.memoizedState,W!==null&&(W.rendering=null,W.tail=null,W.lastEffect=null),me(gi,gi.current),M)break;return null;case 22:return w.lanes=0,QU(h,w,_,w.pendingProps);case 24:Np(w,Pi,h.memoizedState.cache)}return $u(h,w,_)}function iH(h,w,_){if(h!==null)if(h.memoizedProps!==w.pendingProps)Ni=!0;else{if(!yM(h,_)&&(w.flags&128)===0)return Ni=!1,pue(h,w,_);Ni=(h.flags&131072)!==0}else Ni=!1,Mr&&(w.flags&1048576)!==0&&z5(w,Nv,w.index);switch(w.lanes=0,w.tag){case 16:e:{var M=w.pendingProps;if(h=Ef(w.elementType),w.type=h,typeof h=="function")_j(h)?(M=Rf(h,M),w.tag=1,w=eH(null,w,h,M,_)):(w.tag=0,w=mM(null,w,h,M,_));else{if(h!=null){var W=h.$$typeof;if(W===C){w.tag=11,w=WU(null,w,h,M,_);break e}else if(W===j){w.tag=14,w=KU(null,w,h,M,_);break e}}throw w=R(h)||h,Error(n(306,w,""))}}return w;case 0:return mM(h,w,w.type,w.pendingProps,_);case 1:return M=w.type,W=Rf(M,w.pendingProps),eH(h,w,M,W,_);case 3:e:{if(A(w,w.stateNode.containerInfo),h===null)throw Error(n(387));M=w.pendingProps;var te=w.memoizedState;W=te.element,Oj(h,w),Lv(w,M,null,_);var _e=w.memoizedState;if(M=_e.cache,Np(w,Pi,M),M!==te.cache&&Dj(w,[Pi],_,!0),Fv(),M=_e.element,te.isDehydrated)if(te={element:M,isDehydrated:!1,cache:_e.cache},w.updateQueue.baseState=te,w.memoizedState=te,w.flags&256){w=tH(h,w,M,_);break e}else if(M!==W){W=Kl(Error(n(424)),w),Tv(W),w=tH(h,w,M,_);break e}else for(h=w.stateNode.containerInfo,h.nodeType===9?h=h.body:h=h.nodeName==="HTML"?h.ownerDocument.body:h,Nn=Jl(h.firstChild),ks=w,Mr=!0,Pp=null,Xl=!0,_=Q5(w,null,M,_),w.child=_;_;)_.flags=_.flags&-3|4096,_=_.sibling;else{if(Tf(),M===W){w=$u(h,w,_);break e}Ps(h,w,M,_)}w=w.child}return w;case 26:return a_(h,w),h===null?(_=gq(w.type,null,w.pendingProps,null))?w.memoizedState=_:Mr||(_=w.type,h=w.pendingProps,M=y_(V.current).createElement(_),M[vt]=w,M[Ct]=h,Cs(M,_,h),Je(M),w.stateNode=M):w.memoizedState=gq(w.type,h.memoizedProps,w.pendingProps,h.memoizedState),null;case 27:return U(w),h===null&&Mr&&(M=w.stateNode=pq(w.type,w.pendingProps,V.current),ks=w,Xl=!0,W=Nn,Bp(w.type)?(ZM=W,Nn=Jl(M.firstChild)):Nn=W),Ps(h,w,w.pendingProps.children,_),a_(h,w),h===null&&(w.flags|=4194304),w.child;case 5:return h===null&&Mr&&((W=M=Nn)&&(M=que(M,w.type,w.pendingProps,Xl),M!==null?(w.stateNode=M,ks=w,Nn=Jl(M.firstChild),Xl=!1,W=!0):W=!1),W||Cp(w)),U(w),W=w.type,te=w.pendingProps,_e=h!==null?h.memoizedProps:null,M=te.children,WM(W,te)?M=null:_e!==null&&WM(W,_e)&&(w.flags|=32),w.memoizedState!==null&&(W=$j(h,w,nue,null,null,_),t0._currentValue=W),a_(h,w),Ps(h,w,M,_),w.child;case 6:return h===null&&Mr&&((h=_=Nn)&&(_=Vue(_,w.pendingProps,Xl),_!==null?(w.stateNode=_,ks=w,Nn=null,h=!0):h=!1),h||Cp(w)),null;case 13:return aH(h,w,_);case 4:return A(w,w.stateNode.containerInfo),M=w.pendingProps,h===null?w.child=Ff(w,null,M,_):Ps(h,w,M,_),w.child;case 11:return WU(h,w,w.type,w.pendingProps,_);case 7:return Ps(h,w,w.pendingProps,_),w.child;case 8:return Ps(h,w,w.pendingProps.children,_),w.child;case 12:return Ps(h,w,w.pendingProps.children,_),w.child;case 10:return M=w.pendingProps,Np(w,w.type,M.value),Ps(h,w,M.children,_),w.child;case 9:return W=w.type._context,M=w.pendingProps.children,jf(w),W=_s(W),M=M(W),w.flags|=1,Ps(h,w,M,_),w.child;case 14:return KU(h,w,w.type,w.pendingProps,_);case 15:return YU(h,w,w.type,w.pendingProps,_);case 19:return nH(h,w,_);case 31:return mue(h,w,_);case 22:return QU(h,w,_,w.pendingProps);case 24:return jf(w),M=_s(Pi),h===null?(W=Rj(),W===null&&(W=xn,te=Fj(),W.pooledCache=te,te.refCount++,te!==null&&(W.pooledCacheLanes|=_),W=te),w.memoizedState={parent:M,cache:W},Ij(w),Np(w,Pi,W)):((h.lanes&_)!==0&&(Oj(h,w),Lv(w,null,null,_),Fv()),W=h.memoizedState,te=w.memoizedState,W.parent!==M?(W={parent:M,cache:M},w.memoizedState=W,w.lanes===0&&(w.memoizedState=w.updateQueue.baseState=W),Np(w,Pi,M)):(M=te.cache,Np(w,Pi,M),M!==W.cache&&Dj(w,[Pi],_,!0))),Ps(h,w,w.pendingProps.children,_),w.child;case 29:throw w.pendingProps}throw Error(n(156,w.tag))}function Wu(h){h.flags|=4}function vM(h,w,_,M,W){if((w=(h.mode&32)!==0)&&(w=!1),w){if(h.flags|=16777216,(W&335544128)===W)if(h.stateNode.complete)h.flags|=8192;else if(EH())h.flags|=8192;else throw Df=Uk,zj}else h.flags&=-16777217}function sH(h,w){if(w.type!=="stylesheet"||(w.state.loading&4)!==0)h.flags&=-16777217;else if(h.flags|=16777216,!wq(w))if(EH())h.flags|=8192;else throw Df=Uk,zj}function n_(h,w){w!==null&&(h.flags|=4),h.flags&16384&&(w=h.tag!==22?Ge():536870912,h.lanes|=w,Gb|=w)}function Uv(h,w){if(!Mr)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 M=null;_!==null;)_.alternate!==null&&(M=_),_=_.sibling;M===null?w||h.tail===null?h.tail=null:h.tail.sibling=null:M.sibling=null}}function Tn(h){var w=h.alternate!==null&&h.alternate.child===h.child,_=0,M=0;if(w)for(var W=h.child;W!==null;)_|=W.lanes|W.childLanes,M|=W.subtreeFlags&65011712,M|=W.flags&65011712,W.return=h,W=W.sibling;else for(W=h.child;W!==null;)_|=W.lanes|W.childLanes,M|=W.subtreeFlags,M|=W.flags,W.return=h,W=W.sibling;return h.subtreeFlags|=M,h.childLanes=_,w}function hue(h,w,_){var M=w.pendingProps;switch(Tj(w),w.tag){case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Tn(w),null;case 1:return Tn(w),null;case 3:return _=w.stateNode,M=null,h!==null&&(M=h.memoizedState.cache),w.memoizedState.cache!==M&&(w.flags|=2048),qu(Pi),F(),_.pendingContext&&(_.context=_.pendingContext,_.pendingContext=null),(h===null||h.child===null)&&(Eb(w)?Wu(w):h===null||h.memoizedState.isDehydrated&&(w.flags&256)===0||(w.flags|=1024,jj())),Tn(w),null;case 26:var W=w.type,te=w.memoizedState;return h===null?(Wu(w),te!==null?(Tn(w),sH(w,te)):(Tn(w),vM(w,W,null,M,_))):te?te!==h.memoizedState?(Wu(w),Tn(w),sH(w,te)):(Tn(w),w.flags&=-16777217):(h=h.memoizedProps,h!==M&&Wu(w),Tn(w),vM(w,W,h,M,_)),null;case 27:if($(w),_=V.current,W=w.type,h!==null&&w.stateNode!=null)h.memoizedProps!==M&&Wu(w);else{if(!M){if(w.stateNode===null)throw Error(n(166));return Tn(w),null}h=he.current,Eb(w)?O5(w):(h=pq(W,M,_),w.stateNode=h,Wu(w))}return Tn(w),null;case 5:if($(w),W=w.type,h!==null&&w.stateNode!=null)h.memoizedProps!==M&&Wu(w);else{if(!M){if(w.stateNode===null)throw Error(n(166));return Tn(w),null}if(te=he.current,Eb(w))O5(w);else{var _e=y_(V.current);switch(te){case 1:te=_e.createElementNS("http://www.w3.org/2000/svg",W);break;case 2:te=_e.createElementNS("http://www.w3.org/1998/Math/MathML",W);break;default:switch(W){case"svg":te=_e.createElementNS("http://www.w3.org/2000/svg",W);break;case"math":te=_e.createElementNS("http://www.w3.org/1998/Math/MathML",W);break;case"script":te=_e.createElement("div"),te.innerHTML=" +