diff --git a/CHANGELOG.md b/CHANGELOG.md
index 56dcdcc4c..7e4feffed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,15 @@ All notable changes to Bambuddy will be documented in this file.
## [0.1.6] - 2026-01-24
### New Features
+- **Project Import/Export** - Export and import projects with full file support (Issue #152):
+ - Export single project as ZIP (includes project settings, BOM, and all files from linked library folders)
+ - Export all projects as JSON for metadata-only backup
+ - Import from ZIP (with files) or JSON (metadata only)
+ - Linked folders and files are automatically created on import
+ - Useful for sharing complete project bundles or migrating between instances
+- **BOM Item Editing** - Bill of Materials items are now fully editable:
+ - Edit name, quantity, price, URL, and remarks after creation
+ - Pencil icon on each BOM item to enter edit mode
- **External Link for Archives** - Add custom external links to archives for non-MakerWorld sources (Issue #151):
- Link archives to Printables, Thingiverse, or any other URL
- Globe button opens external link when set, falls back to auto-detected MakerWorld URL
diff --git a/README.md b/README.md
index 642c1c79a..605dbe7a4 100644
--- a/README.md
+++ b/README.md
@@ -100,6 +100,7 @@
- Auto-detect parts count from 3MF files
- Color-coded project badges
- Bulk assign archives via multi-select toolbar
+- Import/Export projects as ZIP (includes files) or JSON
diff --git a/backend/app/api/routes/projects.py b/backend/app/api/routes/projects.py
index edab46e3b..b69d7d452 100644
--- a/backend/app/api/routes/projects.py
+++ b/backend/app/api/routes/projects.py
@@ -1,18 +1,23 @@
+import io
+import json
import logging
import os
import uuid
+import zipfile
from datetime import datetime
from pathlib import Path
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
-from fastapi.responses import FileResponse
+from fastapi.responses import FileResponse, StreamingResponse
from sqlalchemy import case, func, select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
+from backend.app.api.routes.library import get_library_dir
from backend.app.core.config import settings
from backend.app.core.database import get_db
from backend.app.models.archive import PrintArchive
+from backend.app.models.library import LibraryFile, LibraryFolder
from backend.app.models.print_queue import PrintQueueItem
from backend.app.models.project import Project
from backend.app.models.project_bom import ProjectBOMItem
@@ -25,6 +30,7 @@ from backend.app.schemas.project import (
BOMItemUpdate,
ProjectChildPreview,
ProjectCreate,
+ ProjectImport,
ProjectListResponse,
ProjectResponse,
ProjectStats,
@@ -1322,3 +1328,392 @@ async def get_project_timeline(
events.sort(key=lambda e: e.timestamp, reverse=True)
return events[:limit]
+
+
+# ============ Phase 10: Import/Export Endpoints ============
+
+
+@router.get("/{project_id}/export")
+async def export_project(
+ project_id: int,
+ format: str = "zip", # "zip" (with files) or "json" (metadata only)
+ db: AsyncSession = Depends(get_db),
+):
+ """Export a project. Use format=zip (default) for full export with files, or format=json for metadata only."""
+ result = await db.execute(select(Project).where(Project.id == project_id))
+ project = result.scalar_one_or_none()
+
+ if not project:
+ raise HTTPException(status_code=404, detail="Project not found")
+
+ # Get BOM items
+ bom_result = await db.execute(
+ select(ProjectBOMItem).where(ProjectBOMItem.project_id == project_id).order_by(ProjectBOMItem.sort_order)
+ )
+ bom_items = bom_result.scalars().all()
+
+ bom_export = [
+ {
+ "name": item.name,
+ "quantity_needed": item.quantity_needed,
+ "quantity_acquired": item.quantity_acquired,
+ "unit_price": item.unit_price,
+ "sourcing_url": item.sourcing_url,
+ "stl_filename": item.stl_filename,
+ "remarks": item.remarks,
+ }
+ for item in bom_items
+ ]
+
+ # Get linked folders and their files
+ folders_result = await db.execute(
+ select(LibraryFolder).where(LibraryFolder.project_id == project_id).order_by(LibraryFolder.name)
+ )
+ linked_folders = folders_result.scalars().all()
+
+ folders_export = []
+ files_to_include = [] # (archive_path, zip_path)
+
+ for folder in linked_folders:
+ # Get files in this folder
+ files_result = await db.execute(
+ select(LibraryFile).where(LibraryFile.folder_id == folder.id).order_by(LibraryFile.filename)
+ )
+ files = files_result.scalars().all()
+
+ folder_files = []
+ for f in files:
+ folder_files.append(
+ {
+ "filename": f.filename,
+ "file_type": f.file_type,
+ "notes": f.notes,
+ }
+ )
+ # Add file to include in ZIP
+ library_dir = get_library_dir()
+ file_path = library_dir / f.file_path
+ if file_path.exists():
+ zip_path = f"files/{folder.name}/{f.filename}"
+ files_to_include.append((file_path, zip_path))
+ # Also include thumbnail if exists
+ if f.thumbnail_path:
+ thumb_path = library_dir / f.thumbnail_path
+ if thumb_path.exists():
+ thumb_zip_path = f"files/{folder.name}/.thumbnails/{f.filename}.png"
+ files_to_include.append((thumb_path, thumb_zip_path))
+
+ folders_export.append(
+ {
+ "name": folder.name,
+ "files": folder_files,
+ }
+ )
+
+ # Build project JSON
+ project_data = {
+ "name": project.name,
+ "description": project.description,
+ "color": project.color,
+ "status": project.status,
+ "target_count": project.target_count,
+ "target_parts_count": project.target_parts_count,
+ "notes": project.notes,
+ "tags": project.tags,
+ "due_date": project.due_date.isoformat() if project.due_date else None,
+ "priority": project.priority,
+ "budget": project.budget,
+ "bom_items": bom_export,
+ "linked_folders": folders_export,
+ }
+
+ # Return JSON if requested (for bulk export)
+ if format == "json":
+ return project_data
+
+ # Create ZIP in memory
+ zip_buffer = io.BytesIO()
+ with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zf:
+ # Add project.json
+ zf.writestr("project.json", json.dumps(project_data, indent=2))
+
+ # Add files
+ for file_path, zip_path in files_to_include:
+ zf.write(file_path, zip_path)
+
+ zip_buffer.seek(0)
+
+ # Generate filename
+ safe_name = "".join(c if c.isalnum() or c in "-_ " else "_" for c in project.name)
+ filename = f"{safe_name}_{datetime.now().strftime('%Y-%m-%d')}.zip"
+
+ return StreamingResponse(
+ zip_buffer,
+ media_type="application/zip",
+ headers={"Content-Disposition": f'attachment; filename="{filename}"'},
+ )
+
+
+@router.post("/import", response_model=ProjectResponse)
+async def import_project(
+ data: ProjectImport,
+ db: AsyncSession = Depends(get_db),
+):
+ """Import a project with optional BOM items and linked folders."""
+ # Create the project
+ project = Project(
+ name=data.name,
+ description=data.description,
+ color=data.color,
+ status=data.status,
+ target_count=data.target_count,
+ target_parts_count=data.target_parts_count,
+ notes=data.notes,
+ tags=data.tags,
+ due_date=data.due_date,
+ priority=data.priority,
+ budget=data.budget,
+ )
+ db.add(project)
+ await db.flush()
+
+ # Create BOM items
+ for idx, bom_data in enumerate(data.bom_items):
+ bom_item = ProjectBOMItem(
+ project_id=project.id,
+ name=bom_data.name,
+ quantity_needed=bom_data.quantity_needed,
+ quantity_acquired=bom_data.quantity_acquired,
+ unit_price=bom_data.unit_price,
+ sourcing_url=bom_data.sourcing_url,
+ stl_filename=bom_data.stl_filename,
+ remarks=bom_data.remarks,
+ sort_order=idx,
+ )
+ db.add(bom_item)
+
+ # Create linked folders in library
+ for folder_data in data.linked_folders:
+ # Check if folder with this name already exists at root level
+ existing_result = await db.execute(
+ select(LibraryFolder).where(
+ LibraryFolder.name == folder_data.name,
+ LibraryFolder.parent_id.is_(None),
+ )
+ )
+ existing_folder = existing_result.scalar_one_or_none()
+
+ if existing_folder:
+ # Link existing folder to project
+ existing_folder.project_id = project.id
+ else:
+ # Create new folder linked to project
+ new_folder = LibraryFolder(
+ name=folder_data.name,
+ project_id=project.id,
+ is_external=False,
+ external_readonly=False,
+ external_show_hidden=False,
+ )
+ db.add(new_folder)
+
+ await db.flush()
+ await db.refresh(project)
+
+ stats = await compute_project_stats(db, project.id, project.target_count, project.target_parts_count)
+
+ return ProjectResponse(
+ id=project.id,
+ name=project.name,
+ description=project.description,
+ color=project.color,
+ status=project.status,
+ target_count=project.target_count,
+ target_parts_count=project.target_parts_count,
+ notes=project.notes,
+ attachments=project.attachments,
+ tags=project.tags,
+ due_date=project.due_date,
+ priority=project.priority,
+ budget=project.budget,
+ is_template=project.is_template,
+ template_source_id=project.template_source_id,
+ parent_id=project.parent_id,
+ parent_name=None,
+ children=[],
+ created_at=project.created_at,
+ updated_at=project.updated_at,
+ stats=stats,
+ )
+
+
+@router.post("/import/file", response_model=ProjectResponse)
+async def import_project_file(
+ file: UploadFile = File(...),
+ db: AsyncSession = Depends(get_db),
+):
+ """Import a project from a ZIP or JSON file."""
+ if not file.filename:
+ raise HTTPException(status_code=400, detail="No filename provided")
+
+ # Determine file type
+ filename_lower = file.filename.lower()
+ content = await file.read()
+
+ if filename_lower.endswith(".zip"):
+ # Extract project.json from ZIP
+ try:
+ with zipfile.ZipFile(io.BytesIO(content)) as zf:
+ if "project.json" not in zf.namelist():
+ raise HTTPException(status_code=400, detail="ZIP must contain project.json")
+ project_json = zf.read("project.json")
+ data = json.loads(project_json)
+
+ # Get list of files in the ZIP
+ zip_files = {name: zf.read(name) for name in zf.namelist() if name.startswith("files/")}
+ except zipfile.BadZipFile:
+ raise HTTPException(status_code=400, detail="Invalid ZIP file")
+ elif filename_lower.endswith(".json"):
+ try:
+ data = json.loads(content)
+ zip_files = {}
+ except json.JSONDecodeError:
+ raise HTTPException(status_code=400, detail="Invalid JSON file")
+ else:
+ raise HTTPException(status_code=400, detail="File must be .zip or .json")
+
+ # Create the project
+ project = Project(
+ name=data.get("name", "Imported Project"),
+ description=data.get("description"),
+ color=data.get("color"),
+ status=data.get("status", "active"),
+ target_count=data.get("target_count"),
+ target_parts_count=data.get("target_parts_count"),
+ notes=data.get("notes"),
+ tags=data.get("tags"),
+ due_date=datetime.fromisoformat(data["due_date"]) if data.get("due_date") else None,
+ priority=data.get("priority", 0),
+ budget=data.get("budget"),
+ )
+ db.add(project)
+ await db.flush()
+
+ # Create BOM items
+ for idx, bom_data in enumerate(data.get("bom_items", [])):
+ bom_item = ProjectBOMItem(
+ project_id=project.id,
+ name=bom_data.get("name", "Unnamed"),
+ quantity_needed=bom_data.get("quantity_needed", 1),
+ quantity_acquired=bom_data.get("quantity_acquired", 0),
+ unit_price=bom_data.get("unit_price"),
+ sourcing_url=bom_data.get("sourcing_url"),
+ stl_filename=bom_data.get("stl_filename"),
+ remarks=bom_data.get("remarks"),
+ sort_order=idx,
+ )
+ db.add(bom_item)
+
+ # Create linked folders and files
+ library_dir = get_library_dir()
+ for folder_data in data.get("linked_folders", []):
+ folder_name = folder_data.get("name")
+ if not folder_name:
+ continue
+
+ # Check if folder exists
+ existing_result = await db.execute(
+ select(LibraryFolder).where(
+ LibraryFolder.name == folder_name,
+ LibraryFolder.parent_id.is_(None),
+ )
+ )
+ existing_folder = existing_result.scalar_one_or_none()
+
+ if existing_folder:
+ # Link existing folder to project
+ existing_folder.project_id = project.id
+ folder = existing_folder
+ else:
+ # Create new folder
+ folder = LibraryFolder(
+ name=folder_name,
+ project_id=project.id,
+ is_external=False,
+ external_readonly=False,
+ external_show_hidden=False,
+ )
+ db.add(folder)
+ await db.flush()
+
+ # Create folder on disk
+ folder_path = library_dir / folder_name
+ folder_path.mkdir(parents=True, exist_ok=True)
+
+ # Import files for this folder from ZIP
+ folder_prefix = f"files/{folder_name}/"
+ for zip_path, file_content in zip_files.items():
+ if not zip_path.startswith(folder_prefix):
+ continue
+ if "/.thumbnails/" in zip_path:
+ continue # Skip thumbnails, we'll regenerate them
+
+ relative_path = zip_path[len(folder_prefix) :]
+ if not relative_path:
+ continue
+
+ # Write file to disk
+ file_disk_path = library_dir / folder_name / relative_path
+ file_disk_path.parent.mkdir(parents=True, exist_ok=True)
+ file_disk_path.write_bytes(file_content)
+
+ # Determine file type
+ ext = Path(relative_path).suffix.lower()
+ if ext in [".stl", ".3mf", ".obj"]:
+ file_type = "model"
+ elif ext in [".gcode"]:
+ file_type = "gcode"
+ elif ext in [".jpg", ".jpeg", ".png", ".gif", ".webp"]:
+ file_type = "image"
+ else:
+ file_type = "other"
+
+ # Create library file record
+ lib_file = LibraryFile(
+ folder_id=folder.id,
+ filename=relative_path,
+ file_path=f"{folder_name}/{relative_path}",
+ file_type=file_type,
+ file_size=len(file_content),
+ is_external=False,
+ )
+ db.add(lib_file)
+
+ await db.flush()
+ await db.refresh(project)
+
+ stats = await compute_project_stats(db, project.id, project.target_count, project.target_parts_count)
+
+ return ProjectResponse(
+ id=project.id,
+ name=project.name,
+ description=project.description,
+ color=project.color,
+ status=project.status,
+ target_count=project.target_count,
+ target_parts_count=project.target_parts_count,
+ notes=project.notes,
+ attachments=project.attachments,
+ tags=project.tags,
+ due_date=project.due_date,
+ priority=project.priority,
+ budget=project.budget,
+ is_template=project.is_template,
+ template_source_id=project.template_source_id,
+ parent_id=project.parent_id,
+ parent_name=None,
+ children=[],
+ created_at=project.created_at,
+ updated_at=project.updated_at,
+ stats=stats,
+ )
diff --git a/backend/app/models/library.py b/backend/app/models/library.py
index f138c827c..4e0023638 100644
--- a/backend/app/models/library.py
+++ b/backend/app/models/library.py
@@ -2,7 +2,7 @@
from datetime import datetime
-from sqlalchemy import JSON, DateTime, ForeignKey, Integer, String, Text, func
+from sqlalchemy import JSON, Boolean, DateTime, ForeignKey, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column, relationship
from backend.app.core.database import Base
@@ -17,6 +17,12 @@ class LibraryFolder(Base):
name: Mapped[str] = mapped_column(String(255))
parent_id: Mapped[int | None] = mapped_column(ForeignKey("library_folders.id", ondelete="CASCADE"), nullable=True)
+ # External folder flags (for folders that point to external paths)
+ is_external: Mapped[bool] = mapped_column(Boolean, default=False)
+ external_readonly: Mapped[bool] = mapped_column(Boolean, default=False)
+ external_show_hidden: Mapped[bool] = mapped_column(Boolean, default=False)
+ external_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
+
# Link to project or archive
project_id: Mapped[int | None] = mapped_column(ForeignKey("projects.id", ondelete="SET NULL"), nullable=True)
archive_id: Mapped[int | None] = mapped_column(ForeignKey("print_archives.id", ondelete="SET NULL"), nullable=True)
@@ -55,6 +61,9 @@ class LibraryFile(Base):
folder_id: Mapped[int | None] = mapped_column(ForeignKey("library_folders.id", ondelete="CASCADE"), nullable=True)
project_id: Mapped[int | None] = mapped_column(ForeignKey("projects.id", ondelete="SET NULL"), nullable=True)
+ # External file flag
+ is_external: Mapped[bool] = mapped_column(Boolean, default=False)
+
# File info
filename: Mapped[str] = mapped_column(String(255)) # Original filename
file_path: Mapped[str] = mapped_column(String(500)) # Storage path
diff --git a/backend/app/schemas/project.py b/backend/app/schemas/project.py
index 1d3a54d49..74732b6cb 100644
--- a/backend/app/schemas/project.py
+++ b/backend/app/schemas/project.py
@@ -205,3 +205,58 @@ class TimelineEvent(BaseModel):
title: str
description: str | None = None
metadata: dict | None = None # Additional event-specific data
+
+
+# Phase 10: Import/Export Schemas
+class BOMItemExport(BaseModel):
+ """Schema for exporting a BOM item."""
+
+ name: str
+ quantity_needed: int
+ quantity_acquired: int
+ unit_price: float | None
+ sourcing_url: str | None
+ stl_filename: str | None
+ remarks: str | None
+
+
+class LinkedFolderExport(BaseModel):
+ """Schema for exporting a linked library folder."""
+
+ name: str
+
+
+class ProjectExport(BaseModel):
+ """Schema for exporting a project."""
+
+ name: str
+ description: str | None
+ color: str | None
+ status: str
+ target_count: int | None
+ target_parts_count: int | None
+ notes: str | None
+ tags: str | None
+ due_date: datetime | None
+ priority: str
+ budget: float | None
+ bom_items: list[BOMItemExport] = []
+ linked_folders: list[LinkedFolderExport] = []
+
+
+class ProjectImport(BaseModel):
+ """Schema for importing a project."""
+
+ name: str
+ description: str | None = None
+ color: str | None = None
+ status: str = "active"
+ target_count: int | None = None
+ target_parts_count: int | None = None
+ notes: str | None = None
+ tags: str | None = None
+ due_date: datetime | None = None
+ priority: str = "normal"
+ budget: float | None = None
+ bom_items: list[BOMItemExport] = []
+ linked_folders: list[LinkedFolderExport] = []
diff --git a/backend/tests/integration/test_projects_api.py b/backend/tests/integration/test_projects_api.py
index 1be7178ba..7ff1bc518 100644
--- a/backend/tests/integration/test_projects_api.py
+++ b/backend/tests/integration/test_projects_api.py
@@ -297,3 +297,330 @@ class TestProjectArchivesAPI:
# Project should have an archive count (may be 0)
data = response.json()
assert "name" in data
+
+
+class TestProjectExportImport:
+ """Tests for project export/import functionality."""
+
+ @pytest.fixture
+ async def project_factory(self, db_session):
+ """Factory to create test projects."""
+ _counter = [0]
+
+ async def _create_project(**kwargs):
+ from backend.app.models.project import Project
+
+ _counter[0] += 1
+ counter = _counter[0]
+
+ defaults = {
+ "name": f"Export Test Project {counter}",
+ "description": "Test project for export",
+ "color": "#00FF00",
+ }
+ defaults.update(kwargs)
+
+ project = Project(**defaults)
+ db_session.add(project)
+ await db_session.commit()
+ await db_session.refresh(project)
+ return project
+
+ return _create_project
+
+ @pytest.fixture
+ async def bom_item_factory(self, db_session):
+ """Factory to create test BOM items."""
+
+ async def _create_bom_item(project_id: int, **kwargs):
+ from backend.app.models.project_bom import ProjectBOMItem
+
+ defaults = {
+ "project_id": project_id,
+ "name": "Test Part",
+ "quantity_needed": 1,
+ "quantity_acquired": 0,
+ "sort_order": 0,
+ }
+ defaults.update(kwargs)
+
+ item = ProjectBOMItem(**defaults)
+ db_session.add(item)
+ await db_session.commit()
+ await db_session.refresh(item)
+ return item
+
+ return _create_bom_item
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_export_project(self, async_client: AsyncClient, project_factory, bom_item_factory, db_session):
+ """Verify project export includes BOM items."""
+ project = await project_factory(
+ name="Export Me",
+ description="A test project",
+ target_count=10,
+ target_parts_count=50,
+ budget=100.0,
+ )
+
+ # Add BOM items
+ await bom_item_factory(project.id, name="M3x8 Screws", quantity_needed=20, unit_price=0.10)
+ await bom_item_factory(project.id, name="Heat Inserts", quantity_needed=10, unit_price=0.25)
+
+ # Test JSON format export
+ response = await async_client.get(f"/api/v1/projects/{project.id}/export?format=json")
+ assert response.status_code == 200
+
+ data = response.json()
+ assert data["name"] == "Export Me"
+ assert data["description"] == "A test project"
+ assert data["target_count"] == 10
+ assert data["target_parts_count"] == 50
+ assert data["budget"] == 100.0
+ assert len(data["bom_items"]) == 2
+
+ # Check BOM items
+ bom_names = [item["name"] for item in data["bom_items"]]
+ assert "M3x8 Screws" in bom_names
+ assert "Heat Inserts" in bom_names
+
+ # Test ZIP format export (default)
+ zip_response = await async_client.get(f"/api/v1/projects/{project.id}/export")
+ assert zip_response.status_code == 200
+ assert zip_response.headers["content-type"] == "application/zip"
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_import_project(self, async_client: AsyncClient):
+ """Verify project can be imported with BOM items."""
+ import_data = {
+ "name": "Imported Project",
+ "description": "Imported from JSON",
+ "color": "#FF00FF",
+ "target_count": 5,
+ "target_parts_count": 25,
+ "budget": 50.0,
+ "bom_items": [
+ {
+ "name": "PTFE Tubes",
+ "quantity_needed": 4,
+ "quantity_acquired": 0,
+ "unit_price": 2.50,
+ "sourcing_url": "https://example.com",
+ "stl_filename": None,
+ "remarks": "Need 4mm ID",
+ },
+ ],
+ }
+
+ response = await async_client.post("/api/v1/projects/import", json=import_data)
+ assert response.status_code == 200
+
+ data = response.json()
+ assert data["name"] == "Imported Project"
+ assert data["description"] == "Imported from JSON"
+ assert data["target_count"] == 5
+ assert data["target_parts_count"] == 25
+ assert data["budget"] == 50.0
+ assert data["id"] > 0 # Has a valid ID
+ # BOM stats should show 1 item imported
+ assert data["stats"]["bom_total_items"] == 1
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_export_project_with_linked_folder(self, async_client: AsyncClient, project_factory, db_session):
+ """Verify project export includes linked folders."""
+ from backend.app.models.library import LibraryFolder
+
+ project = await project_factory(name="Project With Folder")
+
+ # Create a linked folder
+ folder = LibraryFolder(name="Project Files", project_id=project.id)
+ db_session.add(folder)
+ await db_session.commit()
+
+ response = await async_client.get(f"/api/v1/projects/{project.id}/export?format=json")
+ assert response.status_code == 200
+
+ data = response.json()
+ assert data["name"] == "Project With Folder"
+ assert len(data["linked_folders"]) == 1
+ assert data["linked_folders"][0]["name"] == "Project Files"
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_import_project_with_linked_folder(self, async_client: AsyncClient):
+ """Verify project import accepts linked folders data."""
+ import_data = {
+ "name": "Imported With Folders",
+ "linked_folders": [
+ {"name": "STL Files"},
+ {"name": "Documentation"},
+ ],
+ }
+
+ # Import should succeed with linked_folders
+ response = await async_client.post("/api/v1/projects/import", json=import_data)
+ assert response.status_code == 200
+ data = response.json()
+ assert data["name"] == "Imported With Folders"
+ assert data["id"] > 0
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_import_project_from_json_file(self, async_client: AsyncClient):
+ """Verify project can be imported from JSON file upload."""
+ import io
+ import json
+
+ project_data = {
+ "name": "File Uploaded Project",
+ "description": "Imported from JSON file",
+ "color": "#123456",
+ }
+
+ # Create a file-like object
+ file_content = json.dumps(project_data).encode()
+ files = {"file": ("project.json", io.BytesIO(file_content), "application/json")}
+
+ response = await async_client.post("/api/v1/projects/import/file", files=files)
+ assert response.status_code == 200
+ data = response.json()
+ assert data["name"] == "File Uploaded Project"
+ assert data["description"] == "Imported from JSON file"
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_import_project_from_zip_file(self, async_client: AsyncClient):
+ """Verify project can be imported from ZIP file with files."""
+ import io
+ import json
+ import zipfile
+
+ project_data = {
+ "name": "ZIP Imported Project",
+ "description": "Imported from ZIP",
+ "linked_folders": [{"name": "TestFolder", "files": [{"filename": "test.txt"}]}],
+ }
+
+ # Create a ZIP file in memory
+ zip_buffer = io.BytesIO()
+ with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zf:
+ zf.writestr("project.json", json.dumps(project_data))
+ zf.writestr("files/TestFolder/test.txt", "Hello World")
+
+ zip_buffer.seek(0)
+ files = {"file": ("project.zip", zip_buffer, "application/zip")}
+
+ response = await async_client.post("/api/v1/projects/import/file", files=files)
+ assert response.status_code == 200
+ data = response.json()
+ assert data["name"] == "ZIP Imported Project"
+ assert data["description"] == "Imported from ZIP"
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_export_zip_contains_files(self, async_client: AsyncClient, project_factory, db_session):
+ """Verify ZIP export contains actual files from linked folders."""
+ import io
+ import json
+ import zipfile
+ from pathlib import Path
+
+ from backend.app.api.routes.library import get_library_dir
+ from backend.app.models.library import LibraryFile, LibraryFolder
+
+ project = await project_factory(name="Project With Files")
+
+ # Create a linked folder with is_external fields
+ folder = LibraryFolder(
+ name="TestExportFolder",
+ project_id=project.id,
+ is_external=False,
+ external_readonly=False,
+ external_show_hidden=False,
+ )
+ db_session.add(folder)
+ await db_session.flush()
+
+ # Create a test file on disk
+ library_dir = get_library_dir()
+ folder_path = library_dir / "TestExportFolder"
+ folder_path.mkdir(parents=True, exist_ok=True)
+ test_file_path = folder_path / "test_export.txt"
+ test_file_path.write_text("Export test content")
+
+ # Create library file record
+ lib_file = LibraryFile(
+ folder_id=folder.id,
+ filename="test_export.txt",
+ file_path="TestExportFolder/test_export.txt",
+ file_type="other",
+ file_size=19,
+ is_external=False,
+ )
+ db_session.add(lib_file)
+ await db_session.commit()
+
+ # Export as ZIP
+ response = await async_client.get(f"/api/v1/projects/{project.id}/export")
+ assert response.status_code == 200
+ assert response.headers["content-type"] == "application/zip"
+
+ # Verify ZIP contents
+ zip_buffer = io.BytesIO(response.content)
+ with zipfile.ZipFile(zip_buffer, "r") as zf:
+ assert "project.json" in zf.namelist()
+ assert "files/TestExportFolder/test_export.txt" in zf.namelist()
+
+ # Verify file content
+ file_content = zf.read("files/TestExportFolder/test_export.txt").decode()
+ assert file_content == "Export test content"
+
+ # Verify project.json
+ project_data = json.loads(zf.read("project.json"))
+ assert project_data["name"] == "Project With Files"
+
+ # Cleanup
+ test_file_path.unlink(missing_ok=True)
+ folder_path.rmdir()
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_import_invalid_file_type(self, async_client: AsyncClient):
+ """Verify import rejects invalid file types."""
+ import io
+
+ files = {"file": ("project.txt", io.BytesIO(b"invalid"), "text/plain")}
+ response = await async_client.post("/api/v1/projects/import/file", files=files)
+ assert response.status_code == 400
+ assert "must be .zip or .json" in response.json()["detail"]
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_import_zip_missing_project_json(self, async_client: AsyncClient):
+ """Verify import rejects ZIP without project.json."""
+ import io
+ import zipfile
+
+ zip_buffer = io.BytesIO()
+ with zipfile.ZipFile(zip_buffer, "w") as zf:
+ zf.writestr("other.txt", "no project.json here")
+
+ zip_buffer.seek(0)
+ files = {"file": ("project.zip", zip_buffer, "application/zip")}
+ response = await async_client.post("/api/v1/projects/import/file", files=files)
+ assert response.status_code == 400
+ assert "project.json" in response.json()["detail"]
+
+ @pytest.mark.asyncio
+ @pytest.mark.integration
+ async def test_import_invalid_json(self, async_client: AsyncClient):
+ """Verify import rejects invalid JSON content."""
+ import io
+
+ files = {"file": ("project.json", io.BytesIO(b"not valid json"), "application/json")}
+ response = await async_client.post("/api/v1/projects/import/file", files=files)
+ assert response.status_code == 400
+ assert "Invalid JSON" in response.json()["detail"]
diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts
index 0c7f2a63e..99a788887 100644
--- a/frontend/src/api/client.ts
+++ b/frontend/src/api/client.ts
@@ -530,6 +530,53 @@ export interface BOMItemUpdate {
remarks?: string;
}
+// Project Export/Import Types
+export interface BOMItemExport {
+ name: string;
+ quantity_needed: number;
+ quantity_acquired: number;
+ unit_price: number | null;
+ sourcing_url: string | null;
+ stl_filename: string | null;
+ remarks: string | null;
+}
+
+export interface LinkedFolderExport {
+ name: string;
+}
+
+export interface ProjectExport {
+ name: string;
+ description: string | null;
+ color: string | null;
+ status: string;
+ target_count: number | null;
+ target_parts_count: number | null;
+ notes: string | null;
+ tags: string | null;
+ due_date: string | null;
+ priority: string;
+ budget: number | null;
+ bom_items: BOMItemExport[];
+ linked_folders: LinkedFolderExport[];
+}
+
+export interface ProjectImport {
+ name: string;
+ description?: string;
+ color?: string;
+ status?: string;
+ target_count?: number;
+ target_parts_count?: number;
+ notes?: string;
+ tags?: string;
+ due_date?: string;
+ priority?: string;
+ budget?: number;
+ bom_items?: BOMItemExport[];
+ linked_folders?: LinkedFolderExport[];
+}
+
// Timeline Types
export interface TimelineEvent {
event_type: string;
@@ -2683,6 +2730,15 @@ export const api = {
getProjectTimeline: (projectId: number, limit = 50) =>
request(`/projects/${projectId}/timeline?limit=${limit}`),
+ // Project Export/Import
+ exportProjectJson: (projectId: number) =>
+ request(`/projects/${projectId}/export?format=json`),
+ importProject: (data: ProjectImport) =>
+ request('/projects/import', {
+ method: 'POST',
+ body: JSON.stringify(data),
+ }),
+
// API Keys
getAPIKeys: () => request('/api-keys/'),
createAPIKey: (data: APIKeyCreate) =>
diff --git a/frontend/src/pages/ProjectDetailPage.tsx b/frontend/src/pages/ProjectDetailPage.tsx
index 7bec16493..e9f8cc072 100644
--- a/frontend/src/pages/ProjectDetailPage.tsx
+++ b/frontend/src/pages/ProjectDetailPage.tsx
@@ -27,10 +27,12 @@ import {
ExternalLink,
ShoppingCart,
FolderOpen,
+ Download,
+ Pencil,
} from 'lucide-react';
import { api } from '../api/client';
import { parseUTCDate, formatDateOnly, formatDateTime, type TimeFormat } from '../utils/date';
-import type { Archive, ProjectUpdate, BOMItem, BOMItemCreate } from '../api/client';
+import type { Archive, ProjectUpdate, BOMItem, BOMItemCreate, BOMItemUpdate } from '../api/client';
import { Card, CardContent } from '../components/Card';
import { Button } from '../components/Button';
import { useToast } from '../contexts/ToastContext';
@@ -276,6 +278,12 @@ export function ProjectDetailPage() {
const [newBomRemarks, setNewBomRemarks] = useState('');
const [showBomForm, setShowBomForm] = useState(false);
const [hideBomCompleted, setHideBomCompleted] = useState(false);
+ const [editingBomItem, setEditingBomItem] = useState(null);
+ const [editBomName, setEditBomName] = useState('');
+ const [editBomQty, setEditBomQty] = useState(1);
+ const [editBomPrice, setEditBomPrice] = useState('');
+ const [editBomUrl, setEditBomUrl] = useState('');
+ const [editBomRemarks, setEditBomRemarks] = useState('');
// Confirm modal state
const [confirmModal, setConfirmModal] = useState<{
@@ -302,11 +310,12 @@ export function ProjectDetailPage() {
});
const updateBomMutation = useMutation({
- mutationFn: ({ itemId, data }: { itemId: number; data: { quantity_acquired?: number } }) =>
+ mutationFn: ({ itemId, data }: { itemId: number; data: BOMItemUpdate }) =>
api.updateBOMItem(projectId, itemId, data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['project-bom', projectId] });
queryClient.invalidateQueries({ queryKey: ['project', projectId] });
+ setEditingBomItem(null);
},
onError: (error: Error) => showToast(error.message, 'error'),
});
@@ -353,6 +362,57 @@ export function ProjectDetailPage() {
});
};
+ const handleEditBomItem = (item: BOMItem) => {
+ setEditingBomItem(item);
+ setEditBomName(item.name);
+ setEditBomQty(item.quantity_needed);
+ setEditBomPrice(item.unit_price?.toString() || '');
+ setEditBomUrl(item.sourcing_url || '');
+ setEditBomRemarks(item.remarks || '');
+ };
+
+ const handleSaveBomEdit = (e: React.FormEvent) => {
+ e.preventDefault();
+ if (!editingBomItem || !editBomName.trim()) return;
+ updateBomMutation.mutate({
+ itemId: editingBomItem.id,
+ data: {
+ name: editBomName.trim(),
+ quantity_needed: editBomQty,
+ unit_price: editBomPrice ? parseFloat(editBomPrice) : undefined,
+ sourcing_url: editBomUrl.trim() || undefined,
+ remarks: editBomRemarks.trim() || undefined,
+ },
+ });
+ };
+
+ const handleCancelBomEdit = () => {
+ setEditingBomItem(null);
+ };
+
+ const handleExportProject = async () => {
+ try {
+ // Fetch ZIP file directly
+ const response = await fetch(`/api/v1/projects/${projectId}/export`);
+ if (!response.ok) {
+ throw new Error('Export failed');
+ }
+ const blob = await response.blob();
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ // Get filename from Content-Disposition header or use default
+ const contentDisposition = response.headers.get('Content-Disposition');
+ const filenameMatch = contentDisposition?.match(/filename="(.+)"/);
+ a.download = filenameMatch?.[1] || `${project?.name || 'project'}_${new Date().toISOString().split('T')[0]}.zip`;
+ a.click();
+ URL.revokeObjectURL(url);
+ showToast('Project exported', 'success');
+ } catch (error) {
+ showToast((error as Error).message, 'error');
+ }
+ };
+
// Template handlers
const createTemplateMutation = useMutation({
mutationFn: () => api.createTemplateFromProject(projectId),
@@ -433,10 +493,16 @@ export function ProjectDetailPage() {
- setShowEditModal(true)}>
-
- Edit
-
+
+
+
+ Export
+
+ setShowEditModal(true)}>
+
+ Edit
+
+
{/* Progress bars (if targets set) */}
@@ -903,70 +969,140 @@ export function ProjectDetailPage() {
item.is_complete ? 'bg-status-ok/10' : 'bg-bambu-dark'
}`}
>
-
-
handleToggleAcquired(item)}
- disabled={updateBomMutation.isPending}
- className={`w-5 h-5 mt-0.5 rounded border-2 flex items-center justify-center transition-colors flex-shrink-0 ${
- item.is_complete
- ? 'bg-status-ok border-status-ok text-white'
- : 'border-bambu-gray hover:border-bambu-green'
- }`}
- >
- {item.is_complete && }
-
-
-
-
-
- {item.name}
-
- x{item.quantity_needed}
-
-
- {item.unit_price !== null && (
-
- {currency}{(item.unit_price * item.quantity_needed).toFixed(2)}
-
- )}
+ {editingBomItem?.id === item.id ? (
+ // Edit form for this BOM item
+
+ ) : (
+ // Display mode
+
+
handleToggleAcquired(item)}
+ disabled={updateBomMutation.isPending}
+ className={`w-5 h-5 mt-0.5 rounded border-2 flex items-center justify-center transition-colors flex-shrink-0 ${
+ item.is_complete
+ ? 'bg-status-ok border-status-ok text-white'
+ : 'border-bambu-gray hover:border-bambu-green'
+ }`}
+ >
+ {item.is_complete && }
+
+
-
+ )}
))}
{/* BOM Total */}
diff --git a/frontend/src/pages/ProjectsPage.tsx b/frontend/src/pages/ProjectsPage.tsx
index c8b1c937b..f3c810100 100644
--- a/frontend/src/pages/ProjectsPage.tsx
+++ b/frontend/src/pages/ProjectsPage.tsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useState, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {
@@ -16,9 +16,11 @@ import {
AlertTriangle,
ChevronRight,
MoreVertical,
+ Download,
+ Upload,
} from 'lucide-react';
import { api } from '../api/client';
-import type { ProjectListItem, ProjectCreate, ProjectUpdate } from '../api/client';
+import type { ProjectListItem, ProjectCreate, ProjectUpdate, ProjectImport } from '../api/client';
import { Button } from '../components/Button';
import { ConfirmModal } from '../components/ConfirmModal';
import { useToast } from '../contexts/ToastContext';
@@ -613,6 +615,94 @@ export function ProjectsPage() {
},
});
+ const importMutation = useMutation({
+ mutationFn: (data: ProjectImport) => api.importProject(data),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['projects'] });
+ showToast('Project imported', 'success');
+ },
+ onError: (error: Error) => {
+ showToast(error.message, 'error');
+ },
+ });
+
+ const fileInputRef = useRef
(null);
+
+ const handleExportAll = async () => {
+ try {
+ // Export all projects as JSON (metadata only, no files)
+ const allProjects = await api.getProjects();
+ const exports = await Promise.all(
+ allProjects.map(async (p) => {
+ const exported = await api.exportProjectJson(p.id);
+ return exported;
+ })
+ );
+ const blob = new Blob([JSON.stringify(exports, null, 2)], { type: 'application/json' });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `bambuddy_projects_${new Date().toISOString().split('T')[0]}.json`;
+ a.click();
+ URL.revokeObjectURL(url);
+ showToast('Projects exported (metadata only)', 'success');
+ } catch (error) {
+ showToast((error as Error).message, 'error');
+ }
+ };
+
+ const handleImportClick = () => {
+ fileInputRef.current?.click();
+ };
+
+ const handleFileChange = async (e: React.ChangeEvent) => {
+ const file = e.target.files?.[0];
+ if (!file) return;
+
+ try {
+ const filename = file.name.toLowerCase();
+
+ if (filename.endsWith('.zip')) {
+ // ZIP file: upload via file endpoint
+ const formData = new FormData();
+ formData.append('file', file);
+
+ const response = await fetch('/api/v1/projects/import/file', {
+ method: 'POST',
+ body: formData,
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json();
+ throw new Error(errorData.detail || 'Import failed');
+ }
+
+ queryClient.invalidateQueries({ queryKey: ['projects'] });
+ showToast('Project imported', 'success');
+ } else {
+ // JSON file: parse and handle bulk or single import
+ const text = await file.text();
+ const data = JSON.parse(text);
+
+ // Handle both single project and array of projects
+ const projectsToImport = Array.isArray(data) ? data : [data];
+
+ for (const project of projectsToImport) {
+ await importMutation.mutateAsync(project);
+ }
+
+ if (projectsToImport.length > 1) {
+ showToast(`${projectsToImport.length} projects imported`, 'success');
+ }
+ }
+ } catch (error) {
+ showToast(`Import failed: ${(error as Error).message}`, 'error');
+ }
+
+ // Reset file input
+ e.target.value = '';
+ };
+
const handleSave = (data: ProjectCreate | ProjectUpdate) => {
if (editingProject) {
updateMutation.mutate({ id: editingProject.id, data });
@@ -650,6 +740,15 @@ export function ProjectsPage() {
return (
+ {/* Hidden file input for import */}
+
+
{/* Header */}
@@ -663,10 +762,20 @@ export function ProjectsPage() {
Organize and track your 3D printing projects
-
setShowModal(true)} className="sm:w-auto w-full">
-
- New Project
-
+
+
+
+ Import
+
+
+
+ Export
+
+
setShowModal(true)} className="sm:w-auto w-full">
+
+ New Project
+
+
{/* Filter tabs */}
diff --git a/static/assets/index-BQzscOA-.js b/static/assets/index-CTmc90ua.js
similarity index 56%
rename from static/assets/index-BQzscOA-.js
rename to static/assets/index-CTmc90ua.js
index ac3169ec1..671e50d68 100644
--- a/static/assets/index-BQzscOA-.js
+++ b/static/assets/index-CTmc90ua.js
@@ -1,20 +1,20 @@
-function wae(t,e){for(var n=0;n
r[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 a of i)if(a.type==="childList")for(const o of a.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const a={};return i.integrity&&(a.integrity=i.integrity),i.referrerPolicy&&(a.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?a.credentials="include":i.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function r(i){if(i.ep)return;i.ep=!0;const a=n(i);fetch(i.href,a)}})();var Gv=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function ko(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var gT={exports:{}},Bx={};var mU;function Sae(){if(mU)return Bx;mU=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(r,i,a){var o=null;if(a!==void 0&&(o=""+a),i.key!==void 0&&(o=""+i.key),"key"in i){a={};for(var l in i)l!=="key"&&(a[l]=i[l])}else a=i;return i=a.ref,{$$typeof:t,type:r,key:o,ref:i!==void 0?i:null,props:a}}return Bx.Fragment=e,Bx.jsx=n,Bx.jsxs=n,Bx}var pU;function Mae(){return pU||(pU=1,gT.exports=Sae()),gT.exports}var s=Mae(),xT={exports:{}},hn={};var gU;function Nae(){if(gU)return hn;gU=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),a=Symbol.for("react.consumer"),o=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),c=Symbol.for("react.suspense"),u=Symbol.for("react.memo"),d=Symbol.for("react.lazy"),f=Symbol.for("react.activity"),m=Symbol.iterator;function g(z){return z===null||typeof z!="object"?null:(z=m&&z[m]||z["@@iterator"],typeof z=="function"?z:null)}var x={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},y=Object.assign,b={};function v(z,G,ee){this.props=z,this.context=G,this.refs=b,this.updater=ee||x}v.prototype.isReactComponent={},v.prototype.setState=function(z,G){if(typeof z!="object"&&typeof z!="function"&&z!=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,z,G,"setState")},v.prototype.forceUpdate=function(z){this.updater.enqueueForceUpdate(this,z,"forceUpdate")};function M(){}M.prototype=v.prototype;function S(z,G,ee){this.props=z,this.context=G,this.refs=b,this.updater=ee||x}var T=S.prototype=new M;T.constructor=S,y(T,v.prototype),T.isPureReactComponent=!0;var E=Array.isArray;function k(){}var A={H:null,A:null,T:null,S:null},D=Object.prototype.hasOwnProperty;function C(z,G,ee){var ie=ee.ref;return{$$typeof:t,type:z,key:G,ref:ie!==void 0?ie:null,props:ee}}function P(z,G){return C(z.type,G,z.props)}function F(z){return typeof z=="object"&&z!==null&&z.$$typeof===t}function L(z){var G={"=":"=0",":":"=2"};return"$"+z.replace(/[=:]/g,function(ee){return G[ee]})}var X=/\/+/g;function R(z,G){return typeof z=="object"&&z!==null&&z.key!=null?L(""+z.key):G.toString(36)}function W(z){switch(z.status){case"fulfilled":return z.value;case"rejected":throw z.reason;default:switch(typeof z.status=="string"?z.then(k,k):(z.status="pending",z.then(function(G){z.status==="pending"&&(z.status="fulfilled",z.value=G)},function(G){z.status==="pending"&&(z.status="rejected",z.reason=G)})),z.status){case"fulfilled":return z.value;case"rejected":throw z.reason}}throw z}function Y(z,G,ee,ie,he){var fe=typeof z;(fe==="undefined"||fe==="boolean")&&(z=null);var ue=!1;if(z===null)ue=!0;else switch(fe){case"bigint":case"string":case"number":ue=!0;break;case"object":switch(z.$$typeof){case t:case e:ue=!0;break;case d:return ue=z._init,Y(ue(z._payload),G,ee,ie,he)}}if(ue)return he=he(z),ue=ie===""?"."+R(z,0):ie,E(he)?(ee="",ue!=null&&(ee=ue.replace(X,"$&/")+"/"),Y(he,G,ee,"",function(_e){return _e})):he!=null&&(F(he)&&(he=P(he,ee+(he.key==null||z&&z.key===he.key?"":(""+he.key).replace(X,"$&/")+"/")+ue)),G.push(he)),1;ue=0;var Se=ie===""?".":ie+":";if(E(z))for(var me=0;me>>1,ae=Y[ne];if(0>>1;nei(ee,J))iei(he,ee)?(Y[ne]=he,Y[ie]=J,ne=ie):(Y[ne]=ee,Y[G]=J,ne=G);else if(iei(he,J))Y[ne]=he,Y[ie]=J,ne=ie;else break e}}return q}function i(Y,q){var J=Y.sortIndex-q.sortIndex;return J!==0?J:Y.id-q.id}if(t.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var a=performance;t.unstable_now=function(){return a.now()}}else{var o=Date,l=o.now();t.unstable_now=function(){return o.now()-l}}var c=[],u=[],d=1,f=null,m=3,g=!1,x=!1,y=!1,b=!1,v=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,S=typeof setImmediate<"u"?setImmediate:null;function T(Y){for(var q=n(u);q!==null;){if(q.callback===null)r(u);else if(q.startTime<=Y)r(u),q.sortIndex=q.expirationTime,e(c,q);else break;q=n(u)}}function E(Y){if(y=!1,T(Y),!x)if(n(c)!==null)x=!0,k||(k=!0,L());else{var q=n(u);q!==null&&W(E,q.startTime-Y)}}var k=!1,A=-1,D=5,C=-1;function P(){return b?!0:!(t.unstable_now()-CY&&P());){var ne=f.callback;if(typeof ne=="function"){f.callback=null,m=f.priorityLevel;var ae=ne(f.expirationTime<=Y);if(Y=t.unstable_now(),typeof ae=="function"){f.callback=ae,T(Y),q=!0;break t}f===n(c)&&r(c),T(Y)}else r(c);f=n(c)}if(f!==null)q=!0;else{var z=n(u);z!==null&&W(E,z.startTime-Y),q=!1}}break e}finally{f=null,m=J,g=!1}q=void 0}}finally{q?L():k=!1}}}var L;if(typeof S=="function")L=function(){S(F)};else if(typeof MessageChannel<"u"){var X=new MessageChannel,R=X.port2;X.port1.onmessage=F,L=function(){R.postMessage(null)}}else L=function(){v(F,0)};function W(Y,q){A=v(function(){Y(t.unstable_now())},q)}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(Y){Y.callback=null},t.unstable_forceFrameRate=function(Y){0>Y||125ne?(Y.sortIndex=J,e(u,Y),n(c)===null&&Y===n(u)&&(y?(M(A),A=-1):y=!0,W(E,J-ne))):(Y.sortIndex=ae,e(c,Y),x||g||(x=!0,k||(k=!0,L()))),Y},t.unstable_shouldYield=P,t.unstable_wrapCallback=function(Y){var q=m;return function(){var J=m;m=q;try{return Y.apply(this,arguments)}finally{m=J}}}})(vT)),vT}var yU;function Aae(){return yU||(yU=1,yT.exports=Tae()),yT.exports}var _T={exports:{}},_a={};var vU;function Cae(){if(vU)return _a;vU=1;var t=Tg();function e(c){var u="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(),_T.exports=Cae(),_T.exports}var wU;function kae(){if(wU)return $x;wU=1;var t=Aae(),e=Tg(),n=QG();function r(h){var p="https://react.dev/errors/"+h;if(1ae||(h.current=ne[ae],ne[ae]=null,ae--)}function ee(h,p){ae++,ne[ae]=h.current,h.current=p}var ie=z(null),he=z(null),fe=z(null),ue=z(null);function Se(h,p){switch(ee(fe,p),ee(he,h),ee(ie,null),p.nodeType){case 9:case 11:h=(h=p.documentElement)&&(h=h.namespaceURI)?IF(h):0;break;default:if(h=p.tagName,p=p.namespaceURI)p=IF(p),h=FF(p,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}G(ie),ee(ie,h)}function me(){G(ie),G(he),G(fe)}function _e(h){h.memoizedState!==null&&ee(ue,h);var p=ie.current,_=FF(p,h.type);p!==_&&(ee(he,h),ee(ie,_))}function je(h){he.current===h&&(G(ie),G(he)),ue.current===h&&(G(ue),Ix._currentValue=J)}var re,Qe;function B(h){if(re===void 0)try{throw Error()}catch(_){var p=_.stack.trim().match(/\n( *(at )?)/);re=p&&p[1]||"",Qe=-1<_.stack.indexOf(`
+function wae(t,e){for(var n=0;nr[i]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const a of i)if(a.type==="childList")for(const o of a.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const a={};return i.integrity&&(a.integrity=i.integrity),i.referrerPolicy&&(a.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?a.credentials="include":i.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function r(i){if(i.ep)return;i.ep=!0;const a=n(i);fetch(i.href,a)}})();var Gv=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function ko(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var gT={exports:{}},Bx={};var mU;function Sae(){if(mU)return Bx;mU=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(r,i,a){var o=null;if(a!==void 0&&(o=""+a),i.key!==void 0&&(o=""+i.key),"key"in i){a={};for(var l in i)l!=="key"&&(a[l]=i[l])}else a=i;return i=a.ref,{$$typeof:t,type:r,key:o,ref:i!==void 0?i:null,props:a}}return Bx.Fragment=e,Bx.jsx=n,Bx.jsxs=n,Bx}var pU;function Mae(){return pU||(pU=1,gT.exports=Sae()),gT.exports}var s=Mae(),xT={exports:{}},hn={};var gU;function Nae(){if(gU)return hn;gU=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),a=Symbol.for("react.consumer"),o=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),c=Symbol.for("react.suspense"),u=Symbol.for("react.memo"),d=Symbol.for("react.lazy"),f=Symbol.for("react.activity"),m=Symbol.iterator;function g(z){return z===null||typeof z!="object"?null:(z=m&&z[m]||z["@@iterator"],typeof z=="function"?z:null)}var x={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},y=Object.assign,b={};function v(z,G,J){this.props=z,this.context=G,this.refs=b,this.updater=J||x}v.prototype.isReactComponent={},v.prototype.setState=function(z,G){if(typeof z!="object"&&typeof z!="function"&&z!=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,z,G,"setState")},v.prototype.forceUpdate=function(z){this.updater.enqueueForceUpdate(this,z,"forceUpdate")};function M(){}M.prototype=v.prototype;function S(z,G,J){this.props=z,this.context=G,this.refs=b,this.updater=J||x}var T=S.prototype=new M;T.constructor=S,y(T,v.prototype),T.isPureReactComponent=!0;var E=Array.isArray;function k(){}var A={H:null,A:null,T:null,S:null},D=Object.prototype.hasOwnProperty;function C(z,G,J){var re=J.ref;return{$$typeof:t,type:z,key:G,ref:re!==void 0?re:null,props:J}}function R(z,G){return C(z.type,G,z.props)}function F(z){return typeof z=="object"&&z!==null&&z.$$typeof===t}function O(z){var G={"=":"=0",":":"=2"};return"$"+z.replace(/[=:]/g,function(J){return G[J]})}var K=/\/+/g;function P(z,G){return typeof z=="object"&&z!==null&&z.key!=null?O(""+z.key):G.toString(36)}function W(z){switch(z.status){case"fulfilled":return z.value;case"rejected":throw z.reason;default:switch(typeof z.status=="string"?z.then(k,k):(z.status="pending",z.then(function(G){z.status==="pending"&&(z.status="fulfilled",z.value=G)},function(G){z.status==="pending"&&(z.status="rejected",z.reason=G)})),z.status){case"fulfilled":return z.value;case"rejected":throw z.reason}}throw z}function X(z,G,J,re,he){var fe=typeof z;(fe==="undefined"||fe==="boolean")&&(z=null);var ue=!1;if(z===null)ue=!0;else switch(fe){case"bigint":case"string":case"number":ue=!0;break;case"object":switch(z.$$typeof){case t:case e:ue=!0;break;case d:return ue=z._init,X(ue(z._payload),G,J,re,he)}}if(ue)return he=he(z),ue=re===""?"."+P(z,0):re,E(he)?(J="",ue!=null&&(J=ue.replace(K,"$&/")+"/"),X(he,G,J,"",function(we){return we})):he!=null&&(F(he)&&(he=R(he,J+(he.key==null||z&&z.key===he.key?"":(""+he.key).replace(K,"$&/")+"/")+ue)),G.push(he)),1;ue=0;var Ne=re===""?".":re+":";if(E(z))for(var me=0;me>>1,ie=X[ne];if(0>>1;nei(J,Z))rei(he,J)?(X[ne]=he,X[re]=Z,ne=re):(X[ne]=J,X[G]=Z,ne=G);else if(rei(he,Z))X[ne]=he,X[re]=Z,ne=re;else break e}}return q}function i(X,q){var Z=X.sortIndex-q.sortIndex;return Z!==0?Z:X.id-q.id}if(t.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var a=performance;t.unstable_now=function(){return a.now()}}else{var o=Date,l=o.now();t.unstable_now=function(){return o.now()-l}}var c=[],u=[],d=1,f=null,m=3,g=!1,x=!1,y=!1,b=!1,v=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,S=typeof setImmediate<"u"?setImmediate:null;function T(X){for(var q=n(u);q!==null;){if(q.callback===null)r(u);else if(q.startTime<=X)r(u),q.sortIndex=q.expirationTime,e(c,q);else break;q=n(u)}}function E(X){if(y=!1,T(X),!x)if(n(c)!==null)x=!0,k||(k=!0,O());else{var q=n(u);q!==null&&W(E,q.startTime-X)}}var k=!1,A=-1,D=5,C=-1;function R(){return b?!0:!(t.unstable_now()-CX&&R());){var ne=f.callback;if(typeof ne=="function"){f.callback=null,m=f.priorityLevel;var ie=ne(f.expirationTime<=X);if(X=t.unstable_now(),typeof ie=="function"){f.callback=ie,T(X),q=!0;break t}f===n(c)&&r(c),T(X)}else r(c);f=n(c)}if(f!==null)q=!0;else{var z=n(u);z!==null&&W(E,z.startTime-X),q=!1}}break e}finally{f=null,m=Z,g=!1}q=void 0}}finally{q?O():k=!1}}}var O;if(typeof S=="function")O=function(){S(F)};else if(typeof MessageChannel<"u"){var K=new MessageChannel,P=K.port2;K.port1.onmessage=F,O=function(){P.postMessage(null)}}else O=function(){v(F,0)};function W(X,q){A=v(function(){X(t.unstable_now())},q)}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(X){X.callback=null},t.unstable_forceFrameRate=function(X){0>X||125ne?(X.sortIndex=Z,e(u,X),n(c)===null&&X===n(u)&&(y?(M(A),A=-1):y=!0,W(E,Z-ne))):(X.sortIndex=ie,e(c,X),x||g||(x=!0,k||(k=!0,O()))),X},t.unstable_shouldYield=R,t.unstable_wrapCallback=function(X){var q=m;return function(){var Z=m;m=q;try{return X.apply(this,arguments)}finally{m=Z}}}})(vT)),vT}var yU;function Aae(){return yU||(yU=1,yT.exports=Tae()),yT.exports}var _T={exports:{}},_a={};var vU;function Cae(){if(vU)return _a;vU=1;var t=Tg();function e(c){var u="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(),_T.exports=Cae(),_T.exports}var wU;function kae(){if(wU)return $x;wU=1;var t=Aae(),e=Tg(),n=QG();function r(h){var p="https://react.dev/errors/"+h;if(1ie||(h.current=ne[ie],ne[ie]=null,ie--)}function J(h,p){ie++,ne[ie]=h.current,h.current=p}var re=z(null),he=z(null),fe=z(null),ue=z(null);function Ne(h,p){switch(J(fe,p),J(he,h),J(re,null),p.nodeType){case 9:case 11:h=(h=p.documentElement)&&(h=h.namespaceURI)?IF(h):0;break;default:if(h=p.tagName,p=p.namespaceURI)p=IF(p),h=FF(p,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}G(re),J(re,h)}function me(){G(re),G(he),G(fe)}function we(h){h.memoizedState!==null&&J(ue,h);var p=re.current,_=FF(p,h.type);p!==_&&(J(he,h),J(re,_))}function Pe(h){he.current===h&&(G(re),G(he)),ue.current===h&&(G(ue),Ix._currentValue=Z)}var te,Ze;function B(h){if(te===void 0)try{throw Error()}catch(_){var p=_.stack.trim().match(/\n( *(at )?)/);te=p&&p[1]||"",Ze=-1<_.stack.indexOf(`
at`)?" ()":-1<_.stack.indexOf("@")?"@unknown:0:0":""}return`
-`+re+h+Qe}var H=!1;function K(h,p){if(!h||H)return"";H=!0;var _=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var N={DetermineComponentFrameRoot:function(){try{if(p){var yt=function(){throw Error()};if(Object.defineProperty(yt.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(yt,[])}catch(ot){var at=ot}Reflect.construct(h,[],yt)}else{try{yt.call()}catch(ot){at=ot}h.call(yt.prototype)}}else{try{throw Error()}catch(ot){at=ot}(yt=h())&&typeof yt.catch=="function"&&yt.catch(function(){})}}catch(ot){if(ot&&at&&typeof ot.stack=="string")return[ot.stack,at.stack]}return[null,null]}};N.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var j=Object.getOwnPropertyDescriptor(N.DetermineComponentFrameRoot,"name");j&&j.configurable&&Object.defineProperty(N.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var O=N.DetermineComponentFrameRoot(),te=O[0],pe=O[1];if(te&&pe){var Pe=te.split(`
-`),rt=pe.split(`
-`);for(j=N=0;Nj||Pe[N]!==rt[j]){var mt=`
-`+Pe[N].replace(" at new "," at ");return h.displayName&&mt.includes("")&&(mt=mt.replace("",h.displayName)),mt}while(1<=N&&0<=j);break}}}finally{H=!1,Error.prepareStackTrace=_}return(_=h?h.displayName||h.name:"")?B(_):""}function U(h,p){switch(h.tag){case 26:case 27:case 5:return B(h.type);case 16:return B("Lazy");case 13:return h.child!==p&&p!==null?B("Suspense Fallback"):B("Suspense");case 19:return B("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 B("Activity");default:return""}}function V(h){try{var p="",_=null;do p+=U(h,_),_=h,h=h.return;while(h);return p}catch(N){return`
+`+te+h+Ze}var H=!1;function Y(h,p){if(!h||H)return"";H=!0;var _=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var N={DetermineComponentFrameRoot:function(){try{if(p){var yt=function(){throw Error()};if(Object.defineProperty(yt.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(yt,[])}catch(lt){var st=lt}Reflect.construct(h,[],yt)}else{try{yt.call()}catch(lt){st=lt}h.call(yt.prototype)}}else{try{throw Error()}catch(lt){st=lt}(yt=h())&&typeof yt.catch=="function"&&yt.catch(function(){})}}catch(lt){if(lt&&st&&typeof lt.stack=="string")return[lt.stack,st.stack]}return[null,null]}};N.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var j=Object.getOwnPropertyDescriptor(N.DetermineComponentFrameRoot,"name");j&&j.configurable&&Object.defineProperty(N.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var L=N.DetermineComponentFrameRoot(),ee=L[0],ge=L[1];if(ee&&ge){var De=ee.split(`
+`),it=ge.split(`
+`);for(j=N=0;Nj||De[N]!==it[j]){var mt=`
+`+De[N].replace(" at new "," at ");return h.displayName&&mt.includes("")&&(mt=mt.replace("",h.displayName)),mt}while(1<=N&&0<=j);break}}}finally{H=!1,Error.prepareStackTrace=_}return(_=h?h.displayName||h.name:"")?B(_):""}function U(h,p){switch(h.tag){case 26:case 27:case 5:return B(h.type);case 16:return B("Lazy");case 13:return h.child!==p&&p!==null?B("Suspense Fallback"):B("Suspense");case 19:return B("SuspenseList");case 0:case 15:return Y(h.type,!1);case 11:return Y(h.type.render,!1);case 1:return Y(h.type,!0);case 31:return B("Activity");default:return""}}function V(h){try{var p="",_=null;do p+=U(h,_),_=h,h=h.return;while(h);return p}catch(N){return`
Error generating stack: `+N.message+`
-`+N.stack}}var Q=Object.prototype.hasOwnProperty,Ee=t.unstable_scheduleCallback,ke=t.unstable_cancelCallback,Ne=t.unstable_shouldYield,$=t.unstable_requestPaint,I=t.unstable_now,Z=t.unstable_getCurrentPriorityLevel,xe=t.unstable_ImmediatePriority,ve=t.unstable_UserBlockingPriority,oe=t.unstable_NormalPriority,Ae=t.unstable_LowPriority,De=t.unstable_IdlePriority,Ze=t.log,ut=t.unstable_setDisableYieldValue,Ye=null,le=null;function Ve(h){if(typeof Ze=="function"&&ut(h),le&&typeof le.setStrictMode=="function")try{le.setStrictMode(Ye,h)}catch{}}var $e=Math.clz32?Math.clz32:se,qe=Math.log,it=Math.LN2;function se(h){return h>>>=0,h===0?32:31-(qe(h)/it|0)|0}var He=256,ye=262144,Ie=4194304;function Oe(h){var p=h&42;if(p!==0)return p;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 Te(h,p,_){var N=h.pendingLanes;if(N===0)return 0;var j=0,O=h.suspendedLanes,te=h.pingedLanes;h=h.warmLanes;var pe=N&134217727;return pe!==0?(N=pe&~O,N!==0?j=Oe(N):(te&=pe,te!==0?j=Oe(te):_||(_=pe&~h,_!==0&&(j=Oe(_))))):(pe=N&~O,pe!==0?j=Oe(pe):te!==0?j=Oe(te):_||(_=N&~h,_!==0&&(j=Oe(_)))),j===0?0:p!==0&&p!==j&&(p&O)===0&&(O=j&-j,_=p&-p,O>=_||O===32&&(_&4194048)!==0)?p:j}function Ke(h,p){return(h.pendingLanes&~(h.suspendedLanes&~h.pingedLanes)&p)===0}function xt(h,p){switch(h){case 1:case 2:case 4:case 8:case 64:return p+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 p+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 jt(){var h=Ie;return Ie<<=1,(Ie&62914560)===0&&(Ie=4194304),h}function gt(h){for(var p=[],_=0;31>_;_++)p.push(h);return p}function Jt(h,p){h.pendingLanes|=p,p!==268435456&&(h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0)}function kt(h,p,_,N,j,O){var te=h.pendingLanes;h.pendingLanes=_,h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0,h.expiredLanes&=_,h.entangledLanes&=_,h.errorRecoveryDisabledLanes&=_,h.shellSuspendCounter=0;var pe=h.entanglements,Pe=h.expirationTimes,rt=h.hiddenUpdates;for(_=te&~_;0<_;){var mt=31-$e(_),yt=1<"u")return null;try{return h.activeElement||h.body}catch{return h.body}}var Wn=/[\n"\\]/g;function Nn(h){return h.replace(Wn,function(p){return"\\"+p.charCodeAt(0).toString(16)+" "})}function Fn(h,p,_,N,j,O,te,pe){h.name="",te!=null&&typeof te!="function"&&typeof te!="symbol"&&typeof te!="boolean"?h.type=te:h.removeAttribute("type"),p!=null?te==="number"?(p===0&&h.value===""||h.value!=p)&&(h.value=""+gn(p)):h.value!==""+gn(p)&&(h.value=""+gn(p)):te!=="submit"&&te!=="reset"||h.removeAttribute("value"),p!=null?Ui(h,te,gn(p)):_!=null?Ui(h,te,gn(_)):N!=null&&h.removeAttribute("value"),j==null&&O!=null&&(h.defaultChecked=!!O),j!=null&&(h.checked=j&&typeof j!="function"&&typeof j!="symbol"),pe!=null&&typeof pe!="function"&&typeof pe!="symbol"&&typeof pe!="boolean"?h.name=""+gn(pe):h.removeAttribute("name")}function qn(h,p,_,N,j,O,te,pe){if(O!=null&&typeof O!="function"&&typeof O!="symbol"&&typeof O!="boolean"&&(h.type=O),p!=null||_!=null){if(!(O!=="submit"&&O!=="reset"||p!=null)){Nt(h);return}_=_!=null?""+gn(_):"",p=p!=null?""+gn(p):_,pe||p===h.value||(h.value=p),h.defaultValue=p}N=N??j,N=typeof N!="function"&&typeof N!="symbol"&&!!N,h.checked=pe?h.checked:!!N,h.defaultChecked=!!N,te!=null&&typeof te!="function"&&typeof te!="symbol"&&typeof te!="boolean"&&(h.name=te),Nt(h)}function Ui(h,p,_){p==="number"&&nn(h.ownerDocument)===h||h.defaultValue===""+_||(h.defaultValue=""+_)}function Si(h,p,_,N){if(h=h.options,p){p={};for(var j=0;j<_.length;j++)p["$"+_[j]]=!0;for(_=0;_"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),gN=!1;if(Jl)try{var tx={};Object.defineProperty(tx,"passive",{get:function(){gN=!0}}),window.addEventListener("test",tx,tx),window.removeEventListener("test",tx,tx)}catch{gN=!1}var gu=null,xN=null,Iy=null;function FL(){if(Iy)return Iy;var h,p=xN,_=p.length,N,j="value"in gu?gu.value:gu.textContent,O=j.length;for(h=0;h<_&&p[h]===j[h];h++);var te=_-h;for(N=1;N<=te&&p[_-N]===j[O-N];N++);return Iy=j.slice(h,1=ix),VL=" ",GL=!1;function WL(h,p){switch(h){case"keyup":return Vre.indexOf(p.keyCode)!==-1;case"keydown":return p.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function qL(h){return h=h.detail,typeof h=="object"&&"data"in h?h.data:null}var Jf=!1;function Wre(h,p){switch(h){case"compositionend":return qL(p);case"keypress":return p.which!==32?null:(GL=!0,VL);case"textInput":return h=p.data,h===VL&&GL?null:h;default:return null}}function qre(h,p){if(Jf)return h==="compositionend"||!wN&&WL(h,p)?(h=FL(),Iy=xN=gu=null,Jf=!1,h):null;switch(h){case"paste":return null;case"keypress":if(!(p.ctrlKey||p.altKey||p.metaKey)||p.ctrlKey&&p.altKey){if(p.char&&1=p)return{node:_,offset:p-h};h=N}e:{for(;_;){if(_.nextSibling){_=_.nextSibling;break e}_=_.parentNode}_=void 0}_=tI(_)}}function rI(h,p){return h&&p?h===p?!0:h&&h.nodeType===3?!1:p&&p.nodeType===3?rI(h,p.parentNode):"contains"in h?h.contains(p):h.compareDocumentPosition?!!(h.compareDocumentPosition(p)&16):!1:!1}function iI(h){h=h!=null&&h.ownerDocument!=null&&h.ownerDocument.defaultView!=null?h.ownerDocument.defaultView:window;for(var p=nn(h.document);p instanceof h.HTMLIFrameElement;){try{var _=typeof p.contentWindow.location.href=="string"}catch{_=!1}if(_)h=p.contentWindow;else break;p=nn(h.document)}return p}function NN(h){var p=h&&h.nodeName&&h.nodeName.toLowerCase();return p&&(p==="input"&&(h.type==="text"||h.type==="search"||h.type==="tel"||h.type==="url"||h.type==="password")||p==="textarea"||h.contentEditable==="true")}var tie=Jl&&"documentMode"in document&&11>=document.documentMode,em=null,EN=null,lx=null,TN=!1;function aI(h,p,_){var N=_.window===_?_.document:_.nodeType===9?_:_.ownerDocument;TN||em==null||em!==nn(N)||(N=em,"selectionStart"in N&&NN(N)?N={start:N.selectionStart,end:N.selectionEnd}:(N=(N.ownerDocument&&N.ownerDocument.defaultView||window).getSelection(),N={anchorNode:N.anchorNode,anchorOffset:N.anchorOffset,focusNode:N.focusNode,focusOffset:N.focusOffset}),lx&&ox(lx,N)||(lx=N,N=kv(EN,"onSelect"),0>=te,j-=te,fl=1<<32-$e(p)+j|_<pn?(Dn=Wt,Wt=null):Dn=Wt.sibling;var $n=at(Xe,Wt,nt[pn],pt);if($n===null){Wt===null&&(Wt=Dn);break}h&&Wt&&$n.alternate===null&&p(Xe,Wt),Ue=O($n,Ue,pn),Bn===null?Xt=$n:Bn.sibling=$n,Bn=$n,Wt=Dn}if(pn===nt.length)return _(Xe,Wt),Ln&&tc(Xe,pn),Xt;if(Wt===null){for(;pnpn?(Dn=Wt,Wt=null):Dn=Wt.sibling;var Fu=at(Xe,Wt,$n.value,pt);if(Fu===null){Wt===null&&(Wt=Dn);break}h&&Wt&&Fu.alternate===null&&p(Xe,Wt),Ue=O(Fu,Ue,pn),Bn===null?Xt=Fu:Bn.sibling=Fu,Bn=Fu,Wt=Dn}if($n.done)return _(Xe,Wt),Ln&&tc(Xe,pn),Xt;if(Wt===null){for(;!$n.done;pn++,$n=nt.next())$n=yt(Xe,$n.value,pt),$n!==null&&(Ue=O($n,Ue,pn),Bn===null?Xt=$n:Bn.sibling=$n,Bn=$n);return Ln&&tc(Xe,pn),Xt}for(Wt=N(Wt);!$n.done;pn++,$n=nt.next())$n=ot(Wt,Xe,pn,$n.value,pt),$n!==null&&(h&&$n.alternate!==null&&Wt.delete($n.key===null?pn:$n.key),Ue=O($n,Ue,pn),Bn===null?Xt=$n:Bn.sibling=$n,Bn=$n);return h&&Wt.forEach(function(_ae){return p(Xe,_ae)}),Ln&&tc(Xe,pn),Xt}function lr(Xe,Ue,nt,pt){if(typeof nt=="object"&&nt!==null&&nt.type===y&&nt.key===null&&(nt=nt.props.children),typeof nt=="object"&&nt!==null){switch(nt.$$typeof){case g:e:{for(var Xt=nt.key;Ue!==null;){if(Ue.key===Xt){if(Xt=nt.type,Xt===y){if(Ue.tag===7){_(Xe,Ue.sibling),pt=j(Ue,nt.props.children),pt.return=Xe,Xe=pt;break e}}else if(Ue.elementType===Xt||typeof Xt=="object"&&Xt!==null&&Xt.$$typeof===D&&fh(Xt)===Ue.type){_(Xe,Ue.sibling),pt=j(Ue,nt.props),mx(pt,nt),pt.return=Xe,Xe=pt;break e}_(Xe,Ue);break}else p(Xe,Ue);Ue=Ue.sibling}nt.type===y?(pt=lh(nt.props.children,Xe.mode,pt,nt.key),pt.return=Xe,Xe=pt):(pt=qy(nt.type,nt.key,nt.props,null,Xe.mode,pt),mx(pt,nt),pt.return=Xe,Xe=pt)}return te(Xe);case x:e:{for(Xt=nt.key;Ue!==null;){if(Ue.key===Xt)if(Ue.tag===4&&Ue.stateNode.containerInfo===nt.containerInfo&&Ue.stateNode.implementation===nt.implementation){_(Xe,Ue.sibling),pt=j(Ue,nt.children||[]),pt.return=Xe,Xe=pt;break e}else{_(Xe,Ue);break}else p(Xe,Ue);Ue=Ue.sibling}pt=DN(nt,Xe.mode,pt),pt.return=Xe,Xe=pt}return te(Xe);case D:return nt=fh(nt),lr(Xe,Ue,nt,pt)}if(W(nt))return Vt(Xe,Ue,nt,pt);if(L(nt)){if(Xt=L(nt),typeof Xt!="function")throw Error(r(150));return nt=Xt.call(nt),en(Xe,Ue,nt,pt)}if(typeof nt.then=="function")return lr(Xe,Ue,ev(nt),pt);if(nt.$$typeof===S)return lr(Xe,Ue,Yy(Xe,nt),pt);tv(Xe,nt)}return typeof nt=="string"&&nt!==""||typeof nt=="number"||typeof nt=="bigint"?(nt=""+nt,Ue!==null&&Ue.tag===6?(_(Xe,Ue.sibling),pt=j(Ue,nt),pt.return=Xe,Xe=pt):(_(Xe,Ue),pt=RN(nt,Xe.mode,pt),pt.return=Xe,Xe=pt),te(Xe)):_(Xe,Ue)}return function(Xe,Ue,nt,pt){try{fx=0;var Xt=lr(Xe,Ue,nt,pt);return dm=null,Xt}catch(Wt){if(Wt===um||Wt===Zy)throw Wt;var Bn=Ms(29,Wt,null,Xe.mode);return Bn.lanes=pt,Bn.return=Xe,Bn}finally{}}}var ph=AI(!0),CI=AI(!1),_u=!1;function WN(h){h.updateQueue={baseState:h.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function qN(h,p){h=h.updateQueue,p.updateQueue===h&&(p.updateQueue={baseState:h.baseState,firstBaseUpdate:h.firstBaseUpdate,lastBaseUpdate:h.lastBaseUpdate,shared:h.shared,callbacks:null})}function wu(h){return{lane:h,tag:0,payload:null,callback:null,next:null}}function Su(h,p,_){var N=h.updateQueue;if(N===null)return null;if(N=N.shared,(Kn&2)!==0){var j=N.pending;return j===null?p.next=p:(p.next=j.next,j.next=p),N.pending=p,p=Wy(h),hI(h,null,_),p}return Gy(h,N,p,_),Wy(h)}function px(h,p,_){if(p=p.updateQueue,p!==null&&(p=p.shared,(_&4194048)!==0)){var N=p.lanes;N&=h.pendingLanes,_|=N,p.lanes=_,dt(h,_)}}function KN(h,p){var _=h.updateQueue,N=h.alternate;if(N!==null&&(N=N.updateQueue,_===N)){var j=null,O=null;if(_=_.firstBaseUpdate,_!==null){do{var te={lane:_.lane,tag:_.tag,payload:_.payload,callback:null,next:null};O===null?j=O=te:O=O.next=te,_=_.next}while(_!==null);O===null?j=O=p:O=O.next=p}else j=O=p;_={baseState:N.baseState,firstBaseUpdate:j,lastBaseUpdate:O,shared:N.shared,callbacks:N.callbacks},h.updateQueue=_;return}h=_.lastBaseUpdate,h===null?_.firstBaseUpdate=p:h.next=p,_.lastBaseUpdate=p}var XN=!1;function gx(){if(XN){var h=cm;if(h!==null)throw h}}function xx(h,p,_,N){XN=!1;var j=h.updateQueue;_u=!1;var O=j.firstBaseUpdate,te=j.lastBaseUpdate,pe=j.shared.pending;if(pe!==null){j.shared.pending=null;var Pe=pe,rt=Pe.next;Pe.next=null,te===null?O=rt:te.next=rt,te=Pe;var mt=h.alternate;mt!==null&&(mt=mt.updateQueue,pe=mt.lastBaseUpdate,pe!==te&&(pe===null?mt.firstBaseUpdate=rt:pe.next=rt,mt.lastBaseUpdate=Pe))}if(O!==null){var yt=j.baseState;te=0,mt=rt=Pe=null,pe=O;do{var at=pe.lane&-536870913,ot=at!==pe.lane;if(ot?(Rn&at)===at:(N&at)===at){at!==0&&at===lm&&(XN=!0),mt!==null&&(mt=mt.next={lane:0,tag:pe.tag,payload:pe.payload,callback:null,next:null});e:{var Vt=h,en=pe;at=p;var lr=_;switch(en.tag){case 1:if(Vt=en.payload,typeof Vt=="function"){yt=Vt.call(lr,yt,at);break e}yt=Vt;break e;case 3:Vt.flags=Vt.flags&-65537|128;case 0:if(Vt=en.payload,at=typeof Vt=="function"?Vt.call(lr,yt,at):Vt,at==null)break e;yt=f({},yt,at);break e;case 2:_u=!0}}at=pe.callback,at!==null&&(h.flags|=64,ot&&(h.flags|=8192),ot=j.callbacks,ot===null?j.callbacks=[at]:ot.push(at))}else ot={lane:at,tag:pe.tag,payload:pe.payload,callback:pe.callback,next:null},mt===null?(rt=mt=ot,Pe=yt):mt=mt.next=ot,te|=at;if(pe=pe.next,pe===null){if(pe=j.shared.pending,pe===null)break;ot=pe,pe=ot.next,ot.next=null,j.lastBaseUpdate=ot,j.shared.pending=null}}while(!0);mt===null&&(Pe=yt),j.baseState=Pe,j.firstBaseUpdate=rt,j.lastBaseUpdate=mt,O===null&&(j.shared.lanes=0),Au|=te,h.lanes=te,h.memoizedState=yt}}function kI(h,p){if(typeof h!="function")throw Error(r(191,h));h.call(p)}function jI(h,p){var _=h.callbacks;if(_!==null)for(h.callbacks=null,h=0;h<_.length;h++)kI(_[h],p)}var hm=z(null),nv=z(0);function PI(h,p){h=hc,ee(nv,h),ee(hm,p),hc=h|p.baseLanes}function YN(){ee(nv,hc),ee(hm,hm.current)}function QN(){hc=nv.current,G(hm),G(nv)}var Ns=z(null),eo=null;function Mu(h){var p=h.alternate;ee(ni,ni.current&1),ee(Ns,h),eo===null&&(p===null||hm.current!==null||p.memoizedState!==null)&&(eo=h)}function ZN(h){ee(ni,ni.current),ee(Ns,h),eo===null&&(eo=h)}function RI(h){h.tag===22?(ee(ni,ni.current),ee(Ns,h),eo===null&&(eo=h)):Nu()}function Nu(){ee(ni,ni.current),ee(Ns,Ns.current)}function Es(h){G(Ns),eo===h&&(eo=null),G(ni)}var ni=z(0);function rv(h){for(var p=h;p!==null;){if(p.tag===13){var _=p.memoizedState;if(_!==null&&(_=_.dehydrated,_===null||iT(_)||aT(_)))return p}else if(p.tag===19&&(p.memoizedProps.revealOrder==="forwards"||p.memoizedProps.revealOrder==="backwards"||p.memoizedProps.revealOrder==="unstable_legacy-backwards"||p.memoizedProps.revealOrder==="together")){if((p.flags&128)!==0)return p}else if(p.child!==null){p.child.return=p,p=p.child;continue}if(p===h)break;for(;p.sibling===null;){if(p.return===null||p.return===h)return null;p=p.return}p.sibling.return=p.return,p=p.sibling}return null}var ic=0,fn=null,sr=null,ci=null,iv=!1,fm=!1,gh=!1,av=0,bx=0,mm=null,die=0;function Gr(){throw Error(r(321))}function JN(h,p){if(p===null)return!1;for(var _=0;_O?O:8;var te=Y.T,pe={};Y.T=pe,mE(h,!1,p,_);try{var Pe=j(),rt=Y.S;if(rt!==null&&rt(pe,Pe),Pe!==null&&typeof Pe=="object"&&typeof Pe.then=="function"){var mt=uie(Pe,N);vx(h,p,mt,Cs(h))}else vx(h,p,N,Cs(h))}catch(yt){vx(h,p,{then:function(){},status:"rejected",reason:yt},Cs())}finally{q.p=O,te!==null&&pe.types!==null&&(te.types=pe.types),Y.T=te}}function gie(){}function hE(h,p,_,N){if(h.tag!==5)throw Error(r(476));var j=c5(h).queue;l5(h,j,p,J,_===null?gie:function(){return u5(h),_(N)})}function c5(h){var p=h.memoizedState;if(p!==null)return p;p={memoizedState:J,baseState:J,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ac,lastRenderedState:J},next:null};var _={};return p.next={memoizedState:_,baseState:_,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ac,lastRenderedState:_},next:null},h.memoizedState=p,h=h.alternate,h!==null&&(h.memoizedState=p),p}function u5(h){var p=c5(h);p.next===null&&(p=h.alternate.memoizedState),vx(h,p.next.queue,{},Cs())}function fE(){return aa(Ix)}function d5(){return ri().memoizedState}function h5(){return ri().memoizedState}function xie(h){for(var p=h.return;p!==null;){switch(p.tag){case 24:case 3:var _=Cs();h=wu(_);var N=Su(p,h,_);N!==null&&(is(N,p,_),px(N,p,_)),p={cache:$N()},h.payload=p;return}p=p.return}}function bie(h,p,_){var N=Cs();_={lane:N,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null},dv(h)?m5(p,_):(_=jN(h,p,_,N),_!==null&&(is(_,h,N),p5(_,p,N)))}function f5(h,p,_){var N=Cs();vx(h,p,_,N)}function vx(h,p,_,N){var j={lane:N,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null};if(dv(h))m5(p,j);else{var O=h.alternate;if(h.lanes===0&&(O===null||O.lanes===0)&&(O=p.lastRenderedReducer,O!==null))try{var te=p.lastRenderedState,pe=O(te,_);if(j.hasEagerState=!0,j.eagerState=pe,Ss(pe,te))return Gy(h,p,j,0),xr===null&&Vy(),!1}catch{}finally{}if(_=jN(h,p,j,N),_!==null)return is(_,h,N),p5(_,p,N),!0}return!1}function mE(h,p,_,N){if(N={lane:2,revertLane:WE(),gesture:null,action:N,hasEagerState:!1,eagerState:null,next:null},dv(h)){if(p)throw Error(r(479))}else p=jN(h,_,N,2),p!==null&&is(p,h,2)}function dv(h){var p=h.alternate;return h===fn||p!==null&&p===fn}function m5(h,p){fm=iv=!0;var _=h.pending;_===null?p.next=p:(p.next=_.next,_.next=p),h.pending=p}function p5(h,p,_){if((_&4194048)!==0){var N=p.lanes;N&=h.pendingLanes,_|=N,p.lanes=_,dt(h,_)}}var _x={readContext:aa,use:ov,useCallback:Gr,useContext:Gr,useEffect:Gr,useImperativeHandle:Gr,useLayoutEffect:Gr,useInsertionEffect:Gr,useMemo:Gr,useReducer:Gr,useRef:Gr,useState:Gr,useDebugValue:Gr,useDeferredValue:Gr,useTransition:Gr,useSyncExternalStore:Gr,useId:Gr,useHostTransitionStatus:Gr,useFormState:Gr,useActionState:Gr,useOptimistic:Gr,useMemoCache:Gr,useCacheRefresh:Gr};_x.useEffectEvent=Gr;var g5={readContext:aa,use:ov,useCallback:function(h,p){return La().memoizedState=[h,p===void 0?null:p],h},useContext:aa,useEffect:JI,useImperativeHandle:function(h,p,_){_=_!=null?_.concat([h]):null,cv(4194308,4,r5.bind(null,p,h),_)},useLayoutEffect:function(h,p){return cv(4194308,4,h,p)},useInsertionEffect:function(h,p){cv(4,2,h,p)},useMemo:function(h,p){var _=La();p=p===void 0?null:p;var N=h();if(gh){Ve(!0);try{h()}finally{Ve(!1)}}return _.memoizedState=[N,p],N},useReducer:function(h,p,_){var N=La();if(_!==void 0){var j=_(p);if(gh){Ve(!0);try{_(p)}finally{Ve(!1)}}}else j=p;return N.memoizedState=N.baseState=j,h={pending:null,lanes:0,dispatch:null,lastRenderedReducer:h,lastRenderedState:j},N.queue=h,h=h.dispatch=bie.bind(null,fn,h),[N.memoizedState,h]},useRef:function(h){var p=La();return h={current:h},p.memoizedState=h},useState:function(h){h=oE(h);var p=h.queue,_=f5.bind(null,fn,p);return p.dispatch=_,[h.memoizedState,_]},useDebugValue:uE,useDeferredValue:function(h,p){var _=La();return dE(_,h,p)},useTransition:function(){var h=oE(!1);return h=l5.bind(null,fn,h.queue,!0,!1),La().memoizedState=h,[!1,h]},useSyncExternalStore:function(h,p,_){var N=fn,j=La();if(Ln){if(_===void 0)throw Error(r(407));_=_()}else{if(_=p(),xr===null)throw Error(r(349));(Rn&127)!==0||II(N,p,_)}j.memoizedState=_;var O={value:_,getSnapshot:p};return j.queue=O,JI(UI.bind(null,N,O,h),[h]),N.flags|=2048,pm(9,{destroy:void 0},FI.bind(null,N,O,_,p),null),_},useId:function(){var h=La(),p=xr.identifierPrefix;if(Ln){var _=ml,N=fl;_=(N&~(1<<32-$e(N)-1)).toString(32)+_,p="_"+p+"R_"+_,_=av++,0<_&&(p+="H"+_.toString(32)),p+="_"}else _=die++,p="_"+p+"r_"+_.toString(32)+"_";return h.memoizedState=p},useHostTransitionStatus:fE,useFormState:KI,useActionState:KI,useOptimistic:function(h){var p=La();p.memoizedState=p.baseState=h;var _={pending:null,lanes:0,dispatch:null,lastRenderedReducer:null,lastRenderedState:null};return p.queue=_,p=mE.bind(null,fn,!0,_),_.dispatch=p,[h,p]},useMemoCache:iE,useCacheRefresh:function(){return La().memoizedState=xie.bind(null,fn)},useEffectEvent:function(h){var p=La(),_={impl:h};return p.memoizedState=_,function(){if((Kn&2)!==0)throw Error(r(440));return _.impl.apply(void 0,arguments)}}},pE={readContext:aa,use:ov,useCallback:a5,useContext:aa,useEffect:cE,useImperativeHandle:i5,useInsertionEffect:t5,useLayoutEffect:n5,useMemo:s5,useReducer:lv,useRef:ZI,useState:function(){return lv(ac)},useDebugValue:uE,useDeferredValue:function(h,p){var _=ri();return o5(_,sr.memoizedState,h,p)},useTransition:function(){var h=lv(ac)[0],p=ri().memoizedState;return[typeof h=="boolean"?h:yx(h),p]},useSyncExternalStore:LI,useId:d5,useHostTransitionStatus:fE,useFormState:XI,useActionState:XI,useOptimistic:function(h,p){var _=ri();return $I(_,sr,h,p)},useMemoCache:iE,useCacheRefresh:h5};pE.useEffectEvent=e5;var x5={readContext:aa,use:ov,useCallback:a5,useContext:aa,useEffect:cE,useImperativeHandle:i5,useInsertionEffect:t5,useLayoutEffect:n5,useMemo:s5,useReducer:sE,useRef:ZI,useState:function(){return sE(ac)},useDebugValue:uE,useDeferredValue:function(h,p){var _=ri();return sr===null?dE(_,h,p):o5(_,sr.memoizedState,h,p)},useTransition:function(){var h=sE(ac)[0],p=ri().memoizedState;return[typeof h=="boolean"?h:yx(h),p]},useSyncExternalStore:LI,useId:d5,useHostTransitionStatus:fE,useFormState:QI,useActionState:QI,useOptimistic:function(h,p){var _=ri();return sr!==null?$I(_,sr,h,p):(_.baseState=h,[h,_.queue.dispatch])},useMemoCache:iE,useCacheRefresh:h5};x5.useEffectEvent=e5;function gE(h,p,_,N){p=h.memoizedState,_=_(N,p),_=_==null?p:f({},p,_),h.memoizedState=_,h.lanes===0&&(h.updateQueue.baseState=_)}var xE={enqueueSetState:function(h,p,_){h=h._reactInternals;var N=Cs(),j=wu(N);j.payload=p,_!=null&&(j.callback=_),p=Su(h,j,N),p!==null&&(is(p,h,N),px(p,h,N))},enqueueReplaceState:function(h,p,_){h=h._reactInternals;var N=Cs(),j=wu(N);j.tag=1,j.payload=p,_!=null&&(j.callback=_),p=Su(h,j,N),p!==null&&(is(p,h,N),px(p,h,N))},enqueueForceUpdate:function(h,p){h=h._reactInternals;var _=Cs(),N=wu(_);N.tag=2,p!=null&&(N.callback=p),p=Su(h,N,_),p!==null&&(is(p,h,_),px(p,h,_))}};function b5(h,p,_,N,j,O,te){return h=h.stateNode,typeof h.shouldComponentUpdate=="function"?h.shouldComponentUpdate(N,O,te):p.prototype&&p.prototype.isPureReactComponent?!ox(_,N)||!ox(j,O):!0}function y5(h,p,_,N){h=p.state,typeof p.componentWillReceiveProps=="function"&&p.componentWillReceiveProps(_,N),typeof p.UNSAFE_componentWillReceiveProps=="function"&&p.UNSAFE_componentWillReceiveProps(_,N),p.state!==h&&xE.enqueueReplaceState(p,p.state,null)}function xh(h,p){var _=p;if("ref"in p){_={};for(var N in p)N!=="ref"&&(_[N]=p[N])}if(h=h.defaultProps){_===p&&(_=f({},_));for(var j in h)_[j]===void 0&&(_[j]=h[j])}return _}function v5(h){Hy(h)}function _5(h){console.error(h)}function w5(h){Hy(h)}function hv(h,p){try{var _=h.onUncaughtError;_(p.value,{componentStack:p.stack})}catch(N){setTimeout(function(){throw N})}}function S5(h,p,_){try{var N=h.onCaughtError;N(_.value,{componentStack:_.stack,errorBoundary:p.tag===1?p.stateNode:null})}catch(j){setTimeout(function(){throw j})}}function bE(h,p,_){return _=wu(_),_.tag=3,_.payload={element:null},_.callback=function(){hv(h,p)},_}function M5(h){return h=wu(h),h.tag=3,h}function N5(h,p,_,N){var j=_.type.getDerivedStateFromError;if(typeof j=="function"){var O=N.value;h.payload=function(){return j(O)},h.callback=function(){S5(p,_,N)}}var te=_.stateNode;te!==null&&typeof te.componentDidCatch=="function"&&(h.callback=function(){S5(p,_,N),typeof j!="function"&&(Cu===null?Cu=new Set([this]):Cu.add(this));var pe=N.stack;this.componentDidCatch(N.value,{componentStack:pe!==null?pe:""})})}function yie(h,p,_,N,j){if(_.flags|=32768,N!==null&&typeof N=="object"&&typeof N.then=="function"){if(p=_.alternate,p!==null&&om(p,_,j,!0),_=Ns.current,_!==null){switch(_.tag){case 31:case 13:return eo===null?Mv():_.alternate===null&&Wr===0&&(Wr=3),_.flags&=-257,_.flags|=65536,_.lanes=j,N===Jy?_.flags|=16384:(p=_.updateQueue,p===null?_.updateQueue=new Set([N]):p.add(N),HE(h,N,j)),!1;case 22:return _.flags|=65536,N===Jy?_.flags|=16384:(p=_.updateQueue,p===null?(p={transitions:null,markerInstances:null,retryQueue:new Set([N])},_.updateQueue=p):(_=p.retryQueue,_===null?p.retryQueue=new Set([N]):_.add(N)),HE(h,N,j)),!1}throw Error(r(435,_.tag))}return HE(h,N,j),Mv(),!1}if(Ln)return p=Ns.current,p!==null?((p.flags&65536)===0&&(p.flags|=256),p.flags|=65536,p.lanes=j,N!==IN&&(h=Error(r(422),{cause:N}),ux(Ys(h,_)))):(N!==IN&&(p=Error(r(423),{cause:N}),ux(Ys(p,_))),h=h.current.alternate,h.flags|=65536,j&=-j,h.lanes|=j,N=Ys(N,_),j=bE(h.stateNode,N,j),KN(h,j),Wr!==4&&(Wr=2)),!1;var O=Error(r(520),{cause:N});if(O=Ys(O,_),Cx===null?Cx=[O]:Cx.push(O),Wr!==4&&(Wr=2),p===null)return!0;N=Ys(N,_),_=p;do{switch(_.tag){case 3:return _.flags|=65536,h=j&-j,_.lanes|=h,h=bE(_.stateNode,N,h),KN(_,h),!1;case 1:if(p=_.type,O=_.stateNode,(_.flags&128)===0&&(typeof p.getDerivedStateFromError=="function"||O!==null&&typeof O.componentDidCatch=="function"&&(Cu===null||!Cu.has(O))))return _.flags|=65536,j&=-j,_.lanes|=j,j=M5(j),N5(j,h,_,N),KN(_,j),!1}_=_.return}while(_!==null);return!1}var yE=Error(r(461)),ui=!1;function sa(h,p,_,N){p.child=h===null?CI(p,null,_,N):ph(p,h.child,_,N)}function E5(h,p,_,N,j){_=_.render;var O=p.ref;if("ref"in N){var te={};for(var pe in N)pe!=="ref"&&(te[pe]=N[pe])}else te=N;return dh(p),N=eE(h,p,_,te,O,j),pe=tE(),h!==null&&!ui?(nE(h,p,j),sc(h,p,j)):(Ln&&pe&&ON(p),p.flags|=1,sa(h,p,N,j),p.child)}function T5(h,p,_,N,j){if(h===null){var O=_.type;return typeof O=="function"&&!PN(O)&&O.defaultProps===void 0&&_.compare===null?(p.tag=15,p.type=O,A5(h,p,O,N,j)):(h=qy(_.type,null,N,p,p.mode,j),h.ref=p.ref,h.return=p,p.child=h)}if(O=h.child,!TE(h,j)){var te=O.memoizedProps;if(_=_.compare,_=_!==null?_:ox,_(te,N)&&h.ref===p.ref)return sc(h,p,j)}return p.flags|=1,h=ec(O,N),h.ref=p.ref,h.return=p,p.child=h}function A5(h,p,_,N,j){if(h!==null){var O=h.memoizedProps;if(ox(O,N)&&h.ref===p.ref)if(ui=!1,p.pendingProps=N=O,TE(h,j))(h.flags&131072)!==0&&(ui=!0);else return p.lanes=h.lanes,sc(h,p,j)}return vE(h,p,_,N,j)}function C5(h,p,_,N){var j=N.children,O=h!==null?h.memoizedState:null;if(h===null&&p.stateNode===null&&(p.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),N.mode==="hidden"){if((p.flags&128)!==0){if(O=O!==null?O.baseLanes|_:_,h!==null){for(N=p.child=h.child,j=0;N!==null;)j=j|N.lanes|N.childLanes,N=N.sibling;N=j&~O}else N=0,p.child=null;return k5(h,p,O,_,N)}if((_&536870912)!==0)p.memoizedState={baseLanes:0,cachePool:null},h!==null&&Qy(p,O!==null?O.cachePool:null),O!==null?PI(p,O):YN(),RI(p);else return N=p.lanes=536870912,k5(h,p,O!==null?O.baseLanes|_:_,_,N)}else O!==null?(Qy(p,O.cachePool),PI(p,O),Nu(),p.memoizedState=null):(h!==null&&Qy(p,null),YN(),Nu());return sa(h,p,j,_),p.child}function wx(h,p){return h!==null&&h.tag===22||p.stateNode!==null||(p.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),p.sibling}function k5(h,p,_,N,j){var O=VN();return O=O===null?null:{parent:li._currentValue,pool:O},p.memoizedState={baseLanes:_,cachePool:O},h!==null&&Qy(p,null),YN(),RI(p),h!==null&&om(h,p,N,!0),p.childLanes=j,null}function fv(h,p){return p=pv({mode:p.mode,children:p.children},h.mode),p.ref=h.ref,h.child=p,p.return=h,p}function j5(h,p,_){return ph(p,h.child,null,_),h=fv(p,p.pendingProps),h.flags|=2,Es(p),p.memoizedState=null,h}function vie(h,p,_){var N=p.pendingProps,j=(p.flags&128)!==0;if(p.flags&=-129,h===null){if(Ln){if(N.mode==="hidden")return h=fv(p,N),p.lanes=536870912,wx(null,h);if(ZN(p),(h=Er)?(h=HF(h,Js),h=h!==null&&h.data==="&"?h:null,h!==null&&(p.memoizedState={dehydrated:h,treeContext:xu!==null?{id:fl,overflow:ml}:null,retryLane:536870912,hydrationErrors:null},_=mI(h),_.return=p,p.child=_,ia=p,Er=null)):h=null,h===null)throw yu(p);return p.lanes=536870912,null}return fv(p,N)}var O=h.memoizedState;if(O!==null){var te=O.dehydrated;if(ZN(p),j)if(p.flags&256)p.flags&=-257,p=j5(h,p,_);else if(p.memoizedState!==null)p.child=h.child,p.flags|=128,p=null;else throw Error(r(558));else if(ui||om(h,p,_,!1),j=(_&h.childLanes)!==0,ui||j){if(N=xr,N!==null&&(te=Gt(N,_),te!==0&&te!==O.retryLane))throw O.retryLane=te,oh(h,te),is(N,h,te),yE;Mv(),p=j5(h,p,_)}else h=O.treeContext,Er=to(te.nextSibling),ia=p,Ln=!0,bu=null,Js=!1,h!==null&&xI(p,h),p=fv(p,N),p.flags|=4096;return p}return h=ec(h.child,{mode:N.mode,children:N.children}),h.ref=p.ref,p.child=h,h.return=p,h}function mv(h,p){var _=p.ref;if(_===null)h!==null&&h.ref!==null&&(p.flags|=4194816);else{if(typeof _!="function"&&typeof _!="object")throw Error(r(284));(h===null||h.ref!==_)&&(p.flags|=4194816)}}function vE(h,p,_,N,j){return dh(p),_=eE(h,p,_,N,void 0,j),N=tE(),h!==null&&!ui?(nE(h,p,j),sc(h,p,j)):(Ln&&N&&ON(p),p.flags|=1,sa(h,p,_,j),p.child)}function P5(h,p,_,N,j,O){return dh(p),p.updateQueue=null,_=OI(p,N,_,j),DI(h),N=tE(),h!==null&&!ui?(nE(h,p,O),sc(h,p,O)):(Ln&&N&&ON(p),p.flags|=1,sa(h,p,_,O),p.child)}function R5(h,p,_,N,j){if(dh(p),p.stateNode===null){var O=rm,te=_.contextType;typeof te=="object"&&te!==null&&(O=aa(te)),O=new _(N,O),p.memoizedState=O.state!==null&&O.state!==void 0?O.state:null,O.updater=xE,p.stateNode=O,O._reactInternals=p,O=p.stateNode,O.props=N,O.state=p.memoizedState,O.refs={},WN(p),te=_.contextType,O.context=typeof te=="object"&&te!==null?aa(te):rm,O.state=p.memoizedState,te=_.getDerivedStateFromProps,typeof te=="function"&&(gE(p,_,te,N),O.state=p.memoizedState),typeof _.getDerivedStateFromProps=="function"||typeof O.getSnapshotBeforeUpdate=="function"||typeof O.UNSAFE_componentWillMount!="function"&&typeof O.componentWillMount!="function"||(te=O.state,typeof O.componentWillMount=="function"&&O.componentWillMount(),typeof O.UNSAFE_componentWillMount=="function"&&O.UNSAFE_componentWillMount(),te!==O.state&&xE.enqueueReplaceState(O,O.state,null),xx(p,N,O,j),gx(),O.state=p.memoizedState),typeof O.componentDidMount=="function"&&(p.flags|=4194308),N=!0}else if(h===null){O=p.stateNode;var pe=p.memoizedProps,Pe=xh(_,pe);O.props=Pe;var rt=O.context,mt=_.contextType;te=rm,typeof mt=="object"&&mt!==null&&(te=aa(mt));var yt=_.getDerivedStateFromProps;mt=typeof yt=="function"||typeof O.getSnapshotBeforeUpdate=="function",pe=p.pendingProps!==pe,mt||typeof O.UNSAFE_componentWillReceiveProps!="function"&&typeof O.componentWillReceiveProps!="function"||(pe||rt!==te)&&y5(p,O,N,te),_u=!1;var at=p.memoizedState;O.state=at,xx(p,N,O,j),gx(),rt=p.memoizedState,pe||at!==rt||_u?(typeof yt=="function"&&(gE(p,_,yt,N),rt=p.memoizedState),(Pe=_u||b5(p,_,Pe,N,at,rt,te))?(mt||typeof O.UNSAFE_componentWillMount!="function"&&typeof O.componentWillMount!="function"||(typeof O.componentWillMount=="function"&&O.componentWillMount(),typeof O.UNSAFE_componentWillMount=="function"&&O.UNSAFE_componentWillMount()),typeof O.componentDidMount=="function"&&(p.flags|=4194308)):(typeof O.componentDidMount=="function"&&(p.flags|=4194308),p.memoizedProps=N,p.memoizedState=rt),O.props=N,O.state=rt,O.context=te,N=Pe):(typeof O.componentDidMount=="function"&&(p.flags|=4194308),N=!1)}else{O=p.stateNode,qN(h,p),te=p.memoizedProps,mt=xh(_,te),O.props=mt,yt=p.pendingProps,at=O.context,rt=_.contextType,Pe=rm,typeof rt=="object"&&rt!==null&&(Pe=aa(rt)),pe=_.getDerivedStateFromProps,(rt=typeof pe=="function"||typeof O.getSnapshotBeforeUpdate=="function")||typeof O.UNSAFE_componentWillReceiveProps!="function"&&typeof O.componentWillReceiveProps!="function"||(te!==yt||at!==Pe)&&y5(p,O,N,Pe),_u=!1,at=p.memoizedState,O.state=at,xx(p,N,O,j),gx();var ot=p.memoizedState;te!==yt||at!==ot||_u||h!==null&&h.dependencies!==null&&Xy(h.dependencies)?(typeof pe=="function"&&(gE(p,_,pe,N),ot=p.memoizedState),(mt=_u||b5(p,_,mt,N,at,ot,Pe)||h!==null&&h.dependencies!==null&&Xy(h.dependencies))?(rt||typeof O.UNSAFE_componentWillUpdate!="function"&&typeof O.componentWillUpdate!="function"||(typeof O.componentWillUpdate=="function"&&O.componentWillUpdate(N,ot,Pe),typeof O.UNSAFE_componentWillUpdate=="function"&&O.UNSAFE_componentWillUpdate(N,ot,Pe)),typeof O.componentDidUpdate=="function"&&(p.flags|=4),typeof O.getSnapshotBeforeUpdate=="function"&&(p.flags|=1024)):(typeof O.componentDidUpdate!="function"||te===h.memoizedProps&&at===h.memoizedState||(p.flags|=4),typeof O.getSnapshotBeforeUpdate!="function"||te===h.memoizedProps&&at===h.memoizedState||(p.flags|=1024),p.memoizedProps=N,p.memoizedState=ot),O.props=N,O.state=ot,O.context=Pe,N=mt):(typeof O.componentDidUpdate!="function"||te===h.memoizedProps&&at===h.memoizedState||(p.flags|=4),typeof O.getSnapshotBeforeUpdate!="function"||te===h.memoizedProps&&at===h.memoizedState||(p.flags|=1024),N=!1)}return O=N,mv(h,p),N=(p.flags&128)!==0,O||N?(O=p.stateNode,_=N&&typeof _.getDerivedStateFromError!="function"?null:O.render(),p.flags|=1,h!==null&&N?(p.child=ph(p,h.child,null,j),p.child=ph(p,null,_,j)):sa(h,p,_,j),p.memoizedState=O.state,h=p.child):h=sc(h,p,j),h}function D5(h,p,_,N){return ch(),p.flags|=256,sa(h,p,_,N),p.child}var _E={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function wE(h){return{baseLanes:h,cachePool:SI()}}function SE(h,p,_){return h=h!==null?h.childLanes&~_:0,p&&(h|=As),h}function O5(h,p,_){var N=p.pendingProps,j=!1,O=(p.flags&128)!==0,te;if((te=O)||(te=h!==null&&h.memoizedState===null?!1:(ni.current&2)!==0),te&&(j=!0,p.flags&=-129),te=(p.flags&32)!==0,p.flags&=-33,h===null){if(Ln){if(j?Mu(p):Nu(),(h=Er)?(h=HF(h,Js),h=h!==null&&h.data!=="&"?h:null,h!==null&&(p.memoizedState={dehydrated:h,treeContext:xu!==null?{id:fl,overflow:ml}:null,retryLane:536870912,hydrationErrors:null},_=mI(h),_.return=p,p.child=_,ia=p,Er=null)):h=null,h===null)throw yu(p);return aT(h)?p.lanes=32:p.lanes=536870912,null}var pe=N.children;return N=N.fallback,j?(Nu(),j=p.mode,pe=pv({mode:"hidden",children:pe},j),N=lh(N,j,_,null),pe.return=p,N.return=p,pe.sibling=N,p.child=pe,N=p.child,N.memoizedState=wE(_),N.childLanes=SE(h,te,_),p.memoizedState=_E,wx(null,N)):(Mu(p),ME(p,pe))}var Pe=h.memoizedState;if(Pe!==null&&(pe=Pe.dehydrated,pe!==null)){if(O)p.flags&256?(Mu(p),p.flags&=-257,p=NE(h,p,_)):p.memoizedState!==null?(Nu(),p.child=h.child,p.flags|=128,p=null):(Nu(),pe=N.fallback,j=p.mode,N=pv({mode:"visible",children:N.children},j),pe=lh(pe,j,_,null),pe.flags|=2,N.return=p,pe.return=p,N.sibling=pe,p.child=N,ph(p,h.child,null,_),N=p.child,N.memoizedState=wE(_),N.childLanes=SE(h,te,_),p.memoizedState=_E,p=wx(null,N));else if(Mu(p),aT(pe)){if(te=pe.nextSibling&&pe.nextSibling.dataset,te)var rt=te.dgst;te=rt,N=Error(r(419)),N.stack="",N.digest=te,ux({value:N,source:null,stack:null}),p=NE(h,p,_)}else if(ui||om(h,p,_,!1),te=(_&h.childLanes)!==0,ui||te){if(te=xr,te!==null&&(N=Gt(te,_),N!==0&&N!==Pe.retryLane))throw Pe.retryLane=N,oh(h,N),is(te,h,N),yE;iT(pe)||Mv(),p=NE(h,p,_)}else iT(pe)?(p.flags|=192,p.child=h.child,p=null):(h=Pe.treeContext,Er=to(pe.nextSibling),ia=p,Ln=!0,bu=null,Js=!1,h!==null&&xI(p,h),p=ME(p,N.children),p.flags|=4096);return p}return j?(Nu(),pe=N.fallback,j=p.mode,Pe=h.child,rt=Pe.sibling,N=ec(Pe,{mode:"hidden",children:N.children}),N.subtreeFlags=Pe.subtreeFlags&65011712,rt!==null?pe=ec(rt,pe):(pe=lh(pe,j,_,null),pe.flags|=2),pe.return=p,N.return=p,N.sibling=pe,p.child=N,wx(null,N),N=p.child,pe=h.child.memoizedState,pe===null?pe=wE(_):(j=pe.cachePool,j!==null?(Pe=li._currentValue,j=j.parent!==Pe?{parent:Pe,pool:Pe}:j):j=SI(),pe={baseLanes:pe.baseLanes|_,cachePool:j}),N.memoizedState=pe,N.childLanes=SE(h,te,_),p.memoizedState=_E,wx(h.child,N)):(Mu(p),_=h.child,h=_.sibling,_=ec(_,{mode:"visible",children:N.children}),_.return=p,_.sibling=null,h!==null&&(te=p.deletions,te===null?(p.deletions=[h],p.flags|=16):te.push(h)),p.child=_,p.memoizedState=null,_)}function ME(h,p){return p=pv({mode:"visible",children:p},h.mode),p.return=h,h.child=p}function pv(h,p){return h=Ms(22,h,null,p),h.lanes=0,h}function NE(h,p,_){return ph(p,h.child,null,_),h=ME(p,p.pendingProps.children),h.flags|=2,p.memoizedState=null,h}function L5(h,p,_){h.lanes|=p;var N=h.alternate;N!==null&&(N.lanes|=p),zN(h.return,p,_)}function EE(h,p,_,N,j,O){var te=h.memoizedState;te===null?h.memoizedState={isBackwards:p,rendering:null,renderingStartTime:0,last:N,tail:_,tailMode:j,treeForkCount:O}:(te.isBackwards=p,te.rendering=null,te.renderingStartTime=0,te.last=N,te.tail=_,te.tailMode=j,te.treeForkCount=O)}function I5(h,p,_){var N=p.pendingProps,j=N.revealOrder,O=N.tail;N=N.children;var te=ni.current,pe=(te&2)!==0;if(pe?(te=te&1|2,p.flags|=128):te&=1,ee(ni,te),sa(h,p,N,_),N=Ln?cx:0,!pe&&h!==null&&(h.flags&128)!==0)e:for(h=p.child;h!==null;){if(h.tag===13)h.memoizedState!==null&&L5(h,_,p);else if(h.tag===19)L5(h,_,p);else if(h.child!==null){h.child.return=h,h=h.child;continue}if(h===p)break e;for(;h.sibling===null;){if(h.return===null||h.return===p)break e;h=h.return}h.sibling.return=h.return,h=h.sibling}switch(j){case"forwards":for(_=p.child,j=null;_!==null;)h=_.alternate,h!==null&&rv(h)===null&&(j=_),_=_.sibling;_=j,_===null?(j=p.child,p.child=null):(j=_.sibling,_.sibling=null),EE(p,!1,j,_,O,N);break;case"backwards":case"unstable_legacy-backwards":for(_=null,j=p.child,p.child=null;j!==null;){if(h=j.alternate,h!==null&&rv(h)===null){p.child=j;break}h=j.sibling,j.sibling=_,_=j,j=h}EE(p,!0,_,null,O,N);break;case"together":EE(p,!1,null,null,void 0,N);break;default:p.memoizedState=null}return p.child}function sc(h,p,_){if(h!==null&&(p.dependencies=h.dependencies),Au|=p.lanes,(_&p.childLanes)===0)if(h!==null){if(om(h,p,_,!1),(_&p.childLanes)===0)return null}else return null;if(h!==null&&p.child!==h.child)throw Error(r(153));if(p.child!==null){for(h=p.child,_=ec(h,h.pendingProps),p.child=_,_.return=p;h.sibling!==null;)h=h.sibling,_=_.sibling=ec(h,h.pendingProps),_.return=p;_.sibling=null}return p.child}function TE(h,p){return(h.lanes&p)!==0?!0:(h=h.dependencies,!!(h!==null&&Xy(h)))}function _ie(h,p,_){switch(p.tag){case 3:Se(p,p.stateNode.containerInfo),vu(p,li,h.memoizedState.cache),ch();break;case 27:case 5:_e(p);break;case 4:Se(p,p.stateNode.containerInfo);break;case 10:vu(p,p.type,p.memoizedProps.value);break;case 31:if(p.memoizedState!==null)return p.flags|=128,ZN(p),null;break;case 13:var N=p.memoizedState;if(N!==null)return N.dehydrated!==null?(Mu(p),p.flags|=128,null):(_&p.child.childLanes)!==0?O5(h,p,_):(Mu(p),h=sc(h,p,_),h!==null?h.sibling:null);Mu(p);break;case 19:var j=(h.flags&128)!==0;if(N=(_&p.childLanes)!==0,N||(om(h,p,_,!1),N=(_&p.childLanes)!==0),j){if(N)return I5(h,p,_);p.flags|=128}if(j=p.memoizedState,j!==null&&(j.rendering=null,j.tail=null,j.lastEffect=null),ee(ni,ni.current),N)break;return null;case 22:return p.lanes=0,C5(h,p,_,p.pendingProps);case 24:vu(p,li,h.memoizedState.cache)}return sc(h,p,_)}function F5(h,p,_){if(h!==null)if(h.memoizedProps!==p.pendingProps)ui=!0;else{if(!TE(h,_)&&(p.flags&128)===0)return ui=!1,_ie(h,p,_);ui=(h.flags&131072)!==0}else ui=!1,Ln&&(p.flags&1048576)!==0&&gI(p,cx,p.index);switch(p.lanes=0,p.tag){case 16:e:{var N=p.pendingProps;if(h=fh(p.elementType),p.type=h,typeof h=="function")PN(h)?(N=xh(h,N),p.tag=1,p=R5(null,p,h,N,_)):(p.tag=0,p=vE(null,p,h,N,_));else{if(h!=null){var j=h.$$typeof;if(j===T){p.tag=11,p=E5(null,p,h,N,_);break e}else if(j===A){p.tag=14,p=T5(null,p,h,N,_);break e}}throw p=R(h)||h,Error(r(306,p,""))}}return p;case 0:return vE(h,p,p.type,p.pendingProps,_);case 1:return N=p.type,j=xh(N,p.pendingProps),R5(h,p,N,j,_);case 3:e:{if(Se(p,p.stateNode.containerInfo),h===null)throw Error(r(387));N=p.pendingProps;var O=p.memoizedState;j=O.element,qN(h,p),xx(p,N,null,_);var te=p.memoizedState;if(N=te.cache,vu(p,li,N),N!==O.cache&&BN(p,[li],_,!0),gx(),N=te.element,O.isDehydrated)if(O={element:N,isDehydrated:!1,cache:te.cache},p.updateQueue.baseState=O,p.memoizedState=O,p.flags&256){p=D5(h,p,N,_);break e}else if(N!==j){j=Ys(Error(r(424)),p),ux(j),p=D5(h,p,N,_);break e}else{switch(h=p.stateNode.containerInfo,h.nodeType){case 9:h=h.body;break;default:h=h.nodeName==="HTML"?h.ownerDocument.body:h}for(Er=to(h.firstChild),ia=p,Ln=!0,bu=null,Js=!0,_=CI(p,null,N,_),p.child=_;_;)_.flags=_.flags&-3|4096,_=_.sibling}else{if(ch(),N===j){p=sc(h,p,_);break e}sa(h,p,N,_)}p=p.child}return p;case 26:return mv(h,p),h===null?(_=XF(p.type,null,p.pendingProps,null))?p.memoizedState=_:Ln||(_=p.type,h=p.pendingProps,N=jv(fe.current).createElement(_),N[gr]=p,N[bt]=h,oa(N,_,h),Le(N),p.stateNode=N):p.memoizedState=XF(p.type,h.memoizedProps,p.pendingProps,h.memoizedState),null;case 27:return _e(p),h===null&&Ln&&(N=p.stateNode=WF(p.type,p.pendingProps,fe.current),ia=p,Js=!0,j=Er,Ru(p.type)?(sT=j,Er=to(N.firstChild)):Er=j),sa(h,p,p.pendingProps.children,_),mv(h,p),h===null&&(p.flags|=4194304),p.child;case 5:return h===null&&Ln&&((j=N=Er)&&(N=Qie(N,p.type,p.pendingProps,Js),N!==null?(p.stateNode=N,ia=p,Er=to(N.firstChild),Js=!1,j=!0):j=!1),j||yu(p)),_e(p),j=p.type,O=p.pendingProps,te=h!==null?h.memoizedProps:null,N=O.children,tT(j,O)?N=null:te!==null&&tT(j,te)&&(p.flags|=32),p.memoizedState!==null&&(j=eE(h,p,hie,null,null,_),Ix._currentValue=j),mv(h,p),sa(h,p,N,_),p.child;case 6:return h===null&&Ln&&((h=_=Er)&&(_=Zie(_,p.pendingProps,Js),_!==null?(p.stateNode=_,ia=p,Er=null,h=!0):h=!1),h||yu(p)),null;case 13:return O5(h,p,_);case 4:return Se(p,p.stateNode.containerInfo),N=p.pendingProps,h===null?p.child=ph(p,null,N,_):sa(h,p,N,_),p.child;case 11:return E5(h,p,p.type,p.pendingProps,_);case 7:return sa(h,p,p.pendingProps,_),p.child;case 8:return sa(h,p,p.pendingProps.children,_),p.child;case 12:return sa(h,p,p.pendingProps.children,_),p.child;case 10:return N=p.pendingProps,vu(p,p.type,N.value),sa(h,p,N.children,_),p.child;case 9:return j=p.type._context,N=p.pendingProps.children,dh(p),j=aa(j),N=N(j),p.flags|=1,sa(h,p,N,_),p.child;case 14:return T5(h,p,p.type,p.pendingProps,_);case 15:return A5(h,p,p.type,p.pendingProps,_);case 19:return I5(h,p,_);case 31:return vie(h,p,_);case 22:return C5(h,p,_,p.pendingProps);case 24:return dh(p),N=aa(li),h===null?(j=VN(),j===null&&(j=xr,O=$N(),j.pooledCache=O,O.refCount++,O!==null&&(j.pooledCacheLanes|=_),j=O),p.memoizedState={parent:N,cache:j},WN(p),vu(p,li,j)):((h.lanes&_)!==0&&(qN(h,p),xx(p,null,null,_),gx()),j=h.memoizedState,O=p.memoizedState,j.parent!==N?(j={parent:N,cache:N},p.memoizedState=j,p.lanes===0&&(p.memoizedState=p.updateQueue.baseState=j),vu(p,li,N)):(N=O.cache,vu(p,li,N),N!==j.cache&&BN(p,[li],_,!0))),sa(h,p,p.pendingProps.children,_),p.child;case 29:throw p.pendingProps}throw Error(r(156,p.tag))}function oc(h){h.flags|=4}function AE(h,p,_,N,j){if((p=(h.mode&32)!==0)&&(p=!1),p){if(h.flags|=16777216,(j&335544128)===j)if(h.stateNode.complete)h.flags|=8192;else if(dF())h.flags|=8192;else throw mh=Jy,GN}else h.flags&=-16777217}function U5(h,p){if(p.type!=="stylesheet"||(p.state.loading&4)!==0)h.flags&=-16777217;else if(h.flags|=16777216,!eU(p))if(dF())h.flags|=8192;else throw mh=Jy,GN}function gv(h,p){p!==null&&(h.flags|=4),h.flags&16384&&(p=h.tag!==22?jt():536870912,h.lanes|=p,ym|=p)}function Sx(h,p){if(!Ln)switch(h.tailMode){case"hidden":p=h.tail;for(var _=null;p!==null;)p.alternate!==null&&(_=p),p=p.sibling;_===null?h.tail=null:_.sibling=null;break;case"collapsed":_=h.tail;for(var N=null;_!==null;)_.alternate!==null&&(N=_),_=_.sibling;N===null?p||h.tail===null?h.tail=null:h.tail.sibling=null:N.sibling=null}}function Tr(h){var p=h.alternate!==null&&h.alternate.child===h.child,_=0,N=0;if(p)for(var j=h.child;j!==null;)_|=j.lanes|j.childLanes,N|=j.subtreeFlags&65011712,N|=j.flags&65011712,j.return=h,j=j.sibling;else for(j=h.child;j!==null;)_|=j.lanes|j.childLanes,N|=j.subtreeFlags,N|=j.flags,j.return=h,j=j.sibling;return h.subtreeFlags|=N,h.childLanes=_,p}function wie(h,p,_){var N=p.pendingProps;switch(LN(p),p.tag){case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Tr(p),null;case 1:return Tr(p),null;case 3:return _=p.stateNode,N=null,h!==null&&(N=h.memoizedState.cache),p.memoizedState.cache!==N&&(p.flags|=2048),rc(li),me(),_.pendingContext&&(_.context=_.pendingContext,_.pendingContext=null),(h===null||h.child===null)&&(sm(p)?oc(p):h===null||h.memoizedState.isDehydrated&&(p.flags&256)===0||(p.flags|=1024,FN())),Tr(p),null;case 26:var j=p.type,O=p.memoizedState;return h===null?(oc(p),O!==null?(Tr(p),U5(p,O)):(Tr(p),AE(p,j,null,N,_))):O?O!==h.memoizedState?(oc(p),Tr(p),U5(p,O)):(Tr(p),p.flags&=-16777217):(h=h.memoizedProps,h!==N&&oc(p),Tr(p),AE(p,j,h,N,_)),null;case 27:if(je(p),_=fe.current,j=p.type,h!==null&&p.stateNode!=null)h.memoizedProps!==N&&oc(p);else{if(!N){if(p.stateNode===null)throw Error(r(166));return Tr(p),null}h=ie.current,sm(p)?bI(p):(h=WF(j,N,_),p.stateNode=h,oc(p))}return Tr(p),null;case 5:if(je(p),j=p.type,h!==null&&p.stateNode!=null)h.memoizedProps!==N&&oc(p);else{if(!N){if(p.stateNode===null)throw Error(r(166));return Tr(p),null}if(O=ie.current,sm(p))bI(p);else{var te=jv(fe.current);switch(O){case 1:O=te.createElementNS("http://www.w3.org/2000/svg",j);break;case 2:O=te.createElementNS("http://www.w3.org/1998/Math/MathML",j);break;default:switch(j){case"svg":O=te.createElementNS("http://www.w3.org/2000/svg",j);break;case"math":O=te.createElementNS("http://www.w3.org/1998/Math/MathML",j);break;case"script":O=te.createElement("div"),O.innerHTML="
+