From 4c2cef64b3376fc12d8b66a2dbee764ebfa92763 Mon Sep 17 00:00:00 2001 From: maziggy Date: Fri, 30 Jan 2026 09:46:03 +0100 Subject: [PATCH] Add script automation and visibility options (#176) Enhance Home Assistant script support with automation triggers and printer card visibility control. - Script automation: Run scripts automatically when main plug turns on/off - Show/hide scripts on printer cards (configurable per script) - Scripts appear in dedicated row on printer cards with quick-run buttons - Toast notification when triggering scripts from settings/sidebar Closes #176 --- CHANGELOG.md | 7 + backend/app/api/routes/settings.py | 3 + backend/app/api/routes/smart_plugs.py | 129 +++++++- backend/app/core/database.py | 73 +++++ backend/app/models/smart_plug.py | 9 +- backend/app/schemas/smart_plug.py | 10 +- backend/app/services/homeassistant.py | 2 +- backend/app/services/smart_plug_manager.py | 5 + .../tests/integration/test_smart_plugs_api.py | 197 ++++++++++++ frontend/src/api/client.ts | 14 +- frontend/src/components/AddSmartPlugModal.tsx | 300 ++++++++++++------ frontend/src/components/SmartPlugCard.tsx | 169 +++++++--- frontend/src/components/SwitchbarPopover.tsx | 101 ++++-- frontend/src/pages/PrintersPage.tsx | 37 +++ frontend/src/pages/SettingsPage.tsx | 2 +- .../{index-CKmo1TxA.js => index-Di2BGmGD.js} | 260 +++++++-------- static/index.html | 2 +- 17 files changed, 982 insertions(+), 338 deletions(-) rename static/assets/{index-CKmo1TxA.js => index-Di2BGmGD.js} (66%) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6cb5e142..def11d183 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to Bambuddy will be documented in this file. ## [0.1.6-final] - Not released ### New Features +- **Home Assistant Script Support** - Control multiple devices together using HA scripts (Issue #176): + - Add HA script entities (e.g., `script.turn_on_printer_setup`) as smart plugs + - Trigger scripts to control printer + enclosure fan + other devices simultaneously + - Scripts show "Run" button instead of On/Off (scripts execute once when triggered) + - Script automation: Run scripts automatically when main printer plug turns on/off + - Show/hide scripts on printer cards (configurable per script) + - Scripts appear in dedicated row on printer cards with quick-run buttons - **Disable Printer Firmware Checks** - New toggle in Settings → General → Updates to disable printer firmware update checks: - Prevents Bambuddy from checking Bambu Lab servers for firmware updates - Useful for users who prefer to manage firmware manually or have network restrictions diff --git a/backend/app/api/routes/settings.py b/backend/app/api/routes/settings.py index de1e235e6..d71249194 100644 --- a/backend/app/api/routes/settings.py +++ b/backend/app/api/routes/settings.py @@ -376,6 +376,7 @@ async def export_backup( "schedule_on_time": plug.schedule_on_time, "schedule_off_time": plug.schedule_off_time, "show_in_switchbar": plug.show_in_switchbar, + "show_on_printer_card": plug.show_on_printer_card, } ) backup["included"].append("smart_plugs") @@ -1295,6 +1296,7 @@ async def import_backup( existing.schedule_on_time = plug_data.get("schedule_on_time") existing.schedule_off_time = plug_data.get("schedule_off_time") existing.show_in_switchbar = plug_data.get("show_in_switchbar", False) + existing.show_on_printer_card = plug_data.get("show_on_printer_card", True) restored["smart_plugs"] += 1 else: skipped["smart_plugs"] += 1 @@ -1324,6 +1326,7 @@ async def import_backup( schedule_on_time=plug_data.get("schedule_on_time"), schedule_off_time=plug_data.get("schedule_off_time"), show_in_switchbar=plug_data.get("show_in_switchbar", False), + show_on_printer_card=plug_data.get("show_on_printer_card", True), ) db.add(plug) restored["smart_plugs"] += 1 diff --git a/backend/app/api/routes/smart_plugs.py b/backend/app/api/routes/smart_plugs.py index 1a73338cf..29aec241f 100644 --- a/backend/app/api/routes/smart_plugs.py +++ b/backend/app/api/routes/smart_plugs.py @@ -56,9 +56,21 @@ async def create_smart_plug( raise HTTPException(400, "Printer not found") # Check if printer already has a plug assigned - result = await db.execute(select(SmartPlug).where(SmartPlug.printer_id == data.printer_id)) - if result.scalar_one_or_none(): - raise HTTPException(400, "This printer already has a smart plug assigned") + # Scripts can coexist with other plugs (they're for multi-device control, not power on/off) + is_script = data.plug_type == "homeassistant" and data.ha_entity_id and data.ha_entity_id.startswith("script.") + if not is_script: + # For non-script plugs, check there's no other non-script plug assigned + result = await db.execute(select(SmartPlug).where(SmartPlug.printer_id == data.printer_id)) + existing = result.scalar_one_or_none() + if existing: + # Allow if existing plug is a script + existing_is_script = ( + existing.plug_type == "homeassistant" + and existing.ha_entity_id + and existing.ha_entity_id.startswith("script.") + ) + if not existing_is_script: + raise HTTPException(400, "This printer already has a smart plug assigned") plug = SmartPlug(**data.model_dump()) db.add(plug) @@ -74,12 +86,48 @@ async def create_smart_plug( @router.get("/by-printer/{printer_id}", response_model=SmartPlugResponse | None) async def get_smart_plug_by_printer(printer_id: int, db: AsyncSession = Depends(get_db)): - """Get the smart plug assigned to a printer.""" + """Get the main smart plug assigned to a printer. + + When multiple plugs are assigned (e.g., a regular plug + script), + returns the main (non-script) plug for power control. + """ result = await db.execute(select(SmartPlug).where(SmartPlug.printer_id == printer_id)) - plug = result.scalar_one_or_none() - if not plug: + plugs = result.scalars().all() + + if not plugs: return None - return plug + + # If multiple plugs, prefer the non-script one (main power plug) + for plug in plugs: + is_script = plug.plug_type == "homeassistant" and plug.ha_entity_id and plug.ha_entity_id.startswith("script.") + if not is_script: + return plug + + # All are scripts, return the first one + return plugs[0] + + +@router.get("/by-printer/{printer_id}/scripts", response_model=list[SmartPlugResponse]) +async def get_script_plugs_by_printer(printer_id: int, db: AsyncSession = Depends(get_db)): + """Get all HA script plugs assigned to a printer. + + Returns only script entities (script.*) for the printer that have + show_on_printer_card enabled. + Used to display "Run Script" buttons alongside the main power plug. + """ + result = await db.execute(select(SmartPlug).where(SmartPlug.printer_id == printer_id)) + plugs = result.scalars().all() + + # Filter to only scripts with show_on_printer_card enabled + scripts = [ + plug + for plug in plugs + if plug.plug_type == "homeassistant" + and plug.ha_entity_id + and plug.ha_entity_id.startswith("script.") + and plug.show_on_printer_card + ] + return scripts # Tasmota Discovery Endpoints @@ -287,14 +335,29 @@ async def update_smart_plug( raise HTTPException(400, "Printer not found") # Check if that printer already has a different plug assigned - result = await db.execute( - select(SmartPlug).where( - SmartPlug.printer_id == new_printer_id, - SmartPlug.id != plug_id, + # Scripts can coexist with other plugs + # Determine if the plug being updated is/will be a script + new_entity_id = update_data.get("ha_entity_id", plug.ha_entity_id) + new_plug_type = update_data.get("plug_type", plug.plug_type) + is_script = new_plug_type == "homeassistant" and new_entity_id and new_entity_id.startswith("script.") + + if not is_script: + result = await db.execute( + select(SmartPlug).where( + SmartPlug.printer_id == new_printer_id, + SmartPlug.id != plug_id, + ) ) - ) - if result.scalar_one_or_none(): - raise HTTPException(400, "This printer already has a smart plug assigned") + existing = result.scalar_one_or_none() + if existing: + # Allow if existing plug is a script + existing_is_script = ( + existing.plug_type == "homeassistant" + and existing.ha_entity_id + and existing.ha_entity_id.startswith("script.") + ) + if not existing_is_script: + raise HTTPException(400, "This printer already has a smart plug assigned") for field, value in update_data.items(): setattr(plug, field, value) @@ -376,6 +439,13 @@ async def control_smart_plug( plug.last_checked = datetime.utcnow() await db.commit() + # Trigger associated scripts if this is a main (non-script) plug + is_main_plug = not ( + plug.plug_type == "homeassistant" and plug.ha_entity_id and plug.ha_entity_id.startswith("script.") + ) + if is_main_plug and plug.printer_id and expected_state: + await trigger_associated_scripts(plug.printer_id, expected_state, db) + # MQTT relay - publish smart plug state change if expected_state: try: @@ -401,6 +471,37 @@ async def control_smart_plug( return {"success": True, "action": control.action} +async def trigger_associated_scripts(printer_id: int, plug_state: str, db: AsyncSession): + """Trigger scripts linked to a printer based on main plug state change. + + When the main plug turns ON, triggers scripts with auto_on=True. + When the main plug turns OFF, triggers scripts with auto_off=True. + """ + result = await db.execute(select(SmartPlug).where(SmartPlug.printer_id == printer_id)) + plugs = result.scalars().all() + + # Find scripts that should be triggered + for plug in plugs: + is_script = plug.plug_type == "homeassistant" and plug.ha_entity_id and plug.ha_entity_id.startswith("script.") + if not is_script: + continue + + should_trigger = False + if plug_state == "ON" and plug.auto_on: + should_trigger = True + logger.info(f"Auto-triggering script '{plug.name}' on printer power-on") + elif plug_state == "OFF" and plug.auto_off: + should_trigger = True + logger.info(f"Auto-triggering script '{plug.name}' on printer power-off") + + if should_trigger: + try: + service = await _get_service_for_plug(plug, db) + await service.turn_on(plug) # Scripts are triggered by calling turn_on + except Exception as e: + logger.error(f"Failed to trigger script '{plug.name}': {e}") + + @router.get("/{plug_id}/status", response_model=SmartPlugStatus) async def get_plug_status(plug_id: int, db: AsyncSession = Depends(get_db)): """Get current plug status from device including energy data.""" diff --git a/backend/app/core/database.py b/backend/app/core/database.py index 4b2506d76..d8d4701e8 100644 --- a/backend/app/core/database.py +++ b/backend/app/core/database.py @@ -760,6 +760,79 @@ async def run_migrations(conn): except Exception: pass + # Migration: Remove UNIQUE constraint from smart_plugs.printer_id + # This allows HA scripts to coexist with regular plugs (scripts are for multi-device control) + # SQLite requires table recreation to drop constraints + try: + # Check if we need to migrate (if UNIQUE constraint exists) + result = await conn.execute(text("SELECT sql FROM sqlite_master WHERE type='table' AND name='smart_plugs'")) + row = result.fetchone() + if row and "printer_id INTEGER UNIQUE" in (row[0] or ""): + # Create new table without UNIQUE constraint on printer_id + await conn.execute( + text(""" + CREATE TABLE smart_plugs_temp ( + id INTEGER PRIMARY KEY, + name VARCHAR(100) NOT NULL, + ip_address VARCHAR(45), + plug_type VARCHAR(20) DEFAULT 'tasmota', + ha_entity_id VARCHAR(100), + ha_power_entity VARCHAR(100), + ha_energy_today_entity VARCHAR(100), + ha_energy_total_entity VARCHAR(100), + printer_id INTEGER REFERENCES printers(id) ON DELETE SET NULL, + enabled BOOLEAN NOT NULL DEFAULT 1, + auto_on BOOLEAN NOT NULL DEFAULT 1, + auto_off BOOLEAN NOT NULL DEFAULT 1, + off_delay_mode VARCHAR(20) NOT NULL DEFAULT 'time', + off_delay_minutes INTEGER NOT NULL DEFAULT 5, + off_temp_threshold INTEGER NOT NULL DEFAULT 70, + username VARCHAR(50), + password VARCHAR(100), + power_alert_enabled BOOLEAN NOT NULL DEFAULT 0, + power_alert_high FLOAT, + power_alert_low FLOAT, + power_alert_last_triggered DATETIME, + schedule_enabled BOOLEAN NOT NULL DEFAULT 0, + schedule_on_time VARCHAR(5), + schedule_off_time VARCHAR(5), + show_in_switchbar BOOLEAN DEFAULT 0, + last_state VARCHAR(10), + last_checked DATETIME, + auto_off_executed BOOLEAN NOT NULL DEFAULT 0, + auto_off_pending BOOLEAN DEFAULT 0, + auto_off_pending_since DATETIME, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL + ) + """) + ) + # Copy data + await conn.execute( + text(""" + INSERT INTO smart_plugs_temp + SELECT id, name, ip_address, plug_type, ha_entity_id, ha_power_entity, + ha_energy_today_entity, ha_energy_total_entity, printer_id, enabled, + auto_on, auto_off, off_delay_mode, off_delay_minutes, off_temp_threshold, + username, password, power_alert_enabled, power_alert_high, power_alert_low, + power_alert_last_triggered, schedule_enabled, schedule_on_time, schedule_off_time, + show_in_switchbar, last_state, last_checked, auto_off_executed, + auto_off_pending, auto_off_pending_since, created_at, updated_at + FROM smart_plugs + """) + ) + # Drop old table and rename new one + await conn.execute(text("DROP TABLE smart_plugs")) + await conn.execute(text("ALTER TABLE smart_plugs_temp RENAME TO smart_plugs")) + except Exception: + pass + + # Migration: Add show_on_printer_card column to smart_plugs + try: + await conn.execute(text("ALTER TABLE smart_plugs ADD COLUMN show_on_printer_card BOOLEAN DEFAULT 1")) + except Exception: + pass + async def seed_notification_templates(): """Seed default notification templates if they don't exist.""" diff --git a/backend/app/models/smart_plug.py b/backend/app/models/smart_plug.py index 2f13ebc38..8f0ff1650 100644 --- a/backend/app/models/smart_plug.py +++ b/backend/app/models/smart_plug.py @@ -24,10 +24,8 @@ class SmartPlug(Base): ha_energy_today_entity: Mapped[str | None] = mapped_column(String(100), nullable=True) # sensor.xxx_today ha_energy_total_entity: Mapped[str | None] = mapped_column(String(100), nullable=True) # sensor.xxx_total - # Link to printer (1:1) - printer_id: Mapped[int | None] = mapped_column( - ForeignKey("printers.id", ondelete="SET NULL"), unique=True, nullable=True - ) + # Link to printer (scripts can coexist with regular plugs for multi-device control) + printer_id: Mapped[int | None] = mapped_column(ForeignKey("printers.id", ondelete="SET NULL"), nullable=True) # Automation settings enabled: Mapped[bool] = mapped_column(Boolean, default=True) @@ -54,8 +52,9 @@ class SmartPlug(Base): schedule_on_time: Mapped[str | None] = mapped_column(String(5), nullable=True) # "HH:MM" format schedule_off_time: Mapped[str | None] = mapped_column(String(5), nullable=True) # "HH:MM" format - # Switchbar visibility + # Visibility options show_in_switchbar: Mapped[bool] = mapped_column(Boolean, default=False) + show_on_printer_card: Mapped[bool] = mapped_column(Boolean, default=True) # For scripts: show on printer card # Status tracking last_state: Mapped[str | None] = mapped_column(String(10), nullable=True) # "ON"/"OFF" diff --git a/backend/app/schemas/smart_plug.py b/backend/app/schemas/smart_plug.py index d60fac854..ca9816228 100644 --- a/backend/app/schemas/smart_plug.py +++ b/backend/app/schemas/smart_plug.py @@ -14,7 +14,7 @@ class SmartPlugBase(BaseModel): password: str | None = None # Home Assistant fields (required when plug_type="homeassistant") - ha_entity_id: str | None = Field(default=None, pattern=r"^(switch|light|input_boolean)\.[a-z0-9_]+$") + ha_entity_id: str | None = Field(default=None, pattern=r"^(switch|light|input_boolean|script)\.[a-z0-9_]+$") # Home Assistant energy sensor entities (optional, for separate energy sensors) ha_power_entity: str | None = Field(default=None, pattern=r"^sensor\.[a-z0-9_]+$") ha_energy_today_entity: str | None = Field(default=None, pattern=r"^sensor\.[a-z0-9_]+$") @@ -35,8 +35,9 @@ class SmartPlugBase(BaseModel): schedule_enabled: bool = False schedule_on_time: str | None = Field(default=None, pattern=r"^([01]\d|2[0-3]):[0-5]\d$") # HH:MM format schedule_off_time: str | None = Field(default=None, pattern=r"^([01]\d|2[0-3]):[0-5]\d$") # HH:MM format - # Switchbar visibility + # Visibility options show_in_switchbar: bool = False + show_on_printer_card: bool = True # For scripts: show on printer card @model_validator(mode="after") def validate_plug_type_fields(self) -> "SmartPlugBase": @@ -77,8 +78,9 @@ class SmartPlugUpdate(BaseModel): schedule_enabled: bool | None = None schedule_on_time: str | None = Field(default=None, pattern=r"^([01]\d|2[0-3]):[0-5]\d$") schedule_off_time: str | None = Field(default=None, pattern=r"^([01]\d|2[0-3]):[0-5]\d$") - # Switchbar visibility + # Visibility options show_in_switchbar: bool | None = None + show_on_printer_card: bool | None = None class SmartPlugResponse(SmartPlugBase): @@ -147,7 +149,7 @@ class HAEntity(BaseModel): entity_id: str friendly_name: str state: str | None = None - domain: str # "switch", "light", "input_boolean" + domain: str # "switch", "light", "input_boolean", "script" class HASensorEntity(BaseModel): diff --git a/backend/app/services/homeassistant.py b/backend/app/services/homeassistant.py index 38fca794b..45ba70920 100644 --- a/backend/app/services/homeassistant.py +++ b/backend/app/services/homeassistant.py @@ -228,7 +228,7 @@ class HomeAssistantService: - domain: str """ # Default domains for smart plug control - default_domains = {"switch", "light", "input_boolean"} + default_domains = {"switch", "light", "input_boolean", "script"} try: async with httpx.AsyncClient(timeout=self.timeout) as client: diff --git a/backend/app/services/smart_plug_manager.py b/backend/app/services/smart_plug_manager.py index 39366d7da..6d9a3bf57 100644 --- a/backend/app/services/smart_plug_manager.py +++ b/backend/app/services/smart_plug_manager.py @@ -195,6 +195,11 @@ class SmartPlugManager: logger.debug(f"Smart plug '{plug.name}' auto_off is disabled") return + # Skip auto-off for HA script entities (scripts can only be triggered, not turned off) + if plug.plug_type == "homeassistant" and plug.ha_entity_id and plug.ha_entity_id.startswith("script."): + logger.debug(f"Smart plug '{plug.name}' is a HA script entity, skipping auto-off") + return + # Only auto-off on successful completion, not on failures # This allows the user to investigate errors before power-off if status != "completed": diff --git a/backend/tests/integration/test_smart_plugs_api.py b/backend/tests/integration/test_smart_plugs_api.py index e6ad7b573..8c47c2b5f 100644 --- a/backend/tests/integration/test_smart_plugs_api.py +++ b/backend/tests/integration/test_smart_plugs_api.py @@ -573,3 +573,200 @@ class TestSmartPlugsAPI: assert response.status_code == 400 assert "not configured" in response.json()["detail"].lower() + + @pytest.mark.asyncio + @pytest.mark.integration + async def test_create_homeassistant_script_plug(self, async_client: AsyncClient): + """Verify Home Assistant script entity can be created as a plug. + + Scripts allow users to trigger HA automations that control multiple devices + (e.g., turn on printer + fan together). Scripts can only be triggered (turn_on), + not turned off. + """ + data = { + "name": "Turn On Printer Setup", + "plug_type": "homeassistant", + "ha_entity_id": "script.turn_on_printer_and_fan", + "enabled": True, + "auto_on": True, + "auto_off": False, # Scripts don't support auto_off + } + + response = await async_client.post("/api/v1/smart-plugs/", json=data) + + assert response.status_code == 200 + result = response.json() + assert result["name"] == "Turn On Printer Setup" + assert result["plug_type"] == "homeassistant" + assert result["ha_entity_id"] == "script.turn_on_printer_and_fan" + + @pytest.mark.asyncio + @pytest.mark.integration + async def test_control_homeassistant_script( + self, async_client: AsyncClient, smart_plug_factory, mock_homeassistant_service, db_session + ): + """Verify HA script entity can be triggered via control endpoint.""" + plug = await smart_plug_factory(plug_type="homeassistant", ha_entity_id="script.turn_on_printer") + + # Scripts use "on" action to trigger + response = await async_client.post(f"/api/v1/smart-plugs/{plug.id}/control", json={"action": "on"}) + + assert response.status_code == 200 + result = response.json() + assert result["success"] is True + assert result["action"] == "on" + + @pytest.mark.asyncio + @pytest.mark.integration + async def test_invalid_ha_entity_domain(self, async_client: AsyncClient): + """Verify invalid HA entity domains are rejected.""" + data = { + "name": "Invalid Entity", + "plug_type": "homeassistant", + "ha_entity_id": "sensor.some_sensor", # sensor domain not allowed + "enabled": True, + } + + response = await async_client.post("/api/v1/smart-plugs/", json=data) + + assert response.status_code == 422 # Validation error + + @pytest.mark.asyncio + @pytest.mark.integration + async def test_script_can_coexist_with_regular_plug( + self, async_client: AsyncClient, smart_plug_factory, printer_factory, db_session + ): + """Verify HA scripts can be assigned to printers that already have a regular plug. + + Scripts are for multi-device control (e.g., turn on printer + fan together), + so they should coexist with the main power plug. + """ + # Create a printer + printer = await printer_factory(name="Test Printer") + + # Create a regular Tasmota plug assigned to the printer + main_plug = await smart_plug_factory( + name="Main Power Plug", + plug_type="tasmota", + ip_address="192.168.1.100", + printer_id=printer.id, + ) + assert main_plug.printer_id == printer.id + + # Now try to create a script also assigned to the same printer + script_data = { + "name": "Turn On Everything", + "plug_type": "homeassistant", + "ha_entity_id": "script.turn_on_printer_setup", + "printer_id": printer.id, + "enabled": True, + } + + response = await async_client.post("/api/v1/smart-plugs/", json=script_data) + + # Should succeed - scripts can coexist with regular plugs + assert response.status_code == 200 + result = response.json() + assert result["printer_id"] == printer.id + assert result["ha_entity_id"] == "script.turn_on_printer_setup" + + @pytest.mark.asyncio + @pytest.mark.integration + async def test_regular_plug_blocked_when_another_exists( + self, async_client: AsyncClient, smart_plug_factory, printer_factory, db_session + ): + """Verify regular plugs cannot be assigned if printer already has one.""" + # Create a printer + printer = await printer_factory(name="Test Printer") + + # Create a regular plug assigned to the printer + await smart_plug_factory( + name="Main Power Plug", + plug_type="tasmota", + ip_address="192.168.1.100", + printer_id=printer.id, + ) + + # Try to create another regular plug for the same printer + another_plug = { + "name": "Second Plug", + "plug_type": "homeassistant", + "ha_entity_id": "switch.another_plug", + "printer_id": printer.id, + "enabled": True, + } + + response = await async_client.post("/api/v1/smart-plugs/", json=another_plug) + + # Should fail - only one regular plug per printer + assert response.status_code == 400 + assert "already has a smart plug" in response.json()["detail"] + + @pytest.mark.asyncio + @pytest.mark.integration + async def test_get_scripts_by_printer_filters_by_show_on_printer_card( + self, async_client: AsyncClient, smart_plug_factory, printer_factory, db_session + ): + """Verify scripts endpoint only returns scripts with show_on_printer_card=True.""" + printer = await printer_factory(name="Test Printer") + + # Create a script with show_on_printer_card=True (default) + visible_script = await smart_plug_factory( + name="Visible Script", + plug_type="homeassistant", + ha_entity_id="script.visible_script", + printer_id=printer.id, + show_on_printer_card=True, + ) + + # Create a script with show_on_printer_card=False + await smart_plug_factory( + name="Hidden Script", + plug_type="homeassistant", + ha_entity_id="script.hidden_script", + printer_id=printer.id, + show_on_printer_card=False, + ) + + response = await async_client.get(f"/api/v1/smart-plugs/by-printer/{printer.id}/scripts") + + assert response.status_code == 200 + scripts = response.json() + # Should only return the visible script + assert len(scripts) == 1 + assert scripts[0]["id"] == visible_script.id + assert scripts[0]["name"] == "Visible Script" + + @pytest.mark.asyncio + @pytest.mark.integration + async def test_script_auto_on_auto_off_fields( + self, async_client: AsyncClient, smart_plug_factory, printer_factory, db_session + ): + """Verify scripts can have auto_on and auto_off set for automation triggers.""" + printer = await printer_factory(name="Test Printer") + + # Create a script with custom auto_on/auto_off settings + script_data = { + "name": "Fan Control Script", + "plug_type": "homeassistant", + "ha_entity_id": "script.fan_control", + "printer_id": printer.id, + "auto_on": True, + "auto_off": False, + "show_on_printer_card": True, + } + + response = await async_client.post("/api/v1/smart-plugs/", json=script_data) + + assert response.status_code == 200 + result = response.json() + assert result["auto_on"] is True + assert result["auto_off"] is False + assert result["show_on_printer_card"] is True + + # Update the script's auto_off setting + update_response = await async_client.patch(f"/api/v1/smart-plugs/{result['id']}", json={"auto_off": True}) + + assert update_response.status_code == 200 + updated = update_response.json() + assert updated["auto_off"] is True diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index 75eea481c..399beda70 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -842,7 +842,7 @@ export interface SmartPlug { name: string; plug_type: 'tasmota' | 'homeassistant'; ip_address: string | null; // Required for Tasmota - ha_entity_id: string | null; // Required for Home Assistant (e.g., "switch.printer_plug") + ha_entity_id: string | null; // Required for Home Assistant (e.g., "switch.printer_plug", "script.turn_on_printer") // Home Assistant energy sensor entities (optional) ha_power_entity: string | null; ha_energy_today_entity: string | null; @@ -865,8 +865,9 @@ export interface SmartPlug { schedule_enabled: boolean; schedule_on_time: string | null; schedule_off_time: string | null; - // Switchbar visibility + // Visibility options show_in_switchbar: boolean; + show_on_printer_card: boolean; // For scripts: show on printer card // Status last_state: string | null; last_checked: string | null; @@ -901,8 +902,9 @@ export interface SmartPlugCreate { schedule_enabled?: boolean; schedule_on_time?: string | null; schedule_off_time?: string | null; - // Switchbar visibility + // Visibility options show_in_switchbar?: boolean; + show_on_printer_card?: boolean; } export interface SmartPlugUpdate { @@ -931,8 +933,9 @@ export interface SmartPlugUpdate { schedule_enabled?: boolean; schedule_on_time?: string | null; schedule_off_time?: string | null; - // Switchbar visibility + // Visibility options show_in_switchbar?: boolean; + show_on_printer_card?: boolean; } // Home Assistant entity for smart plug selection @@ -940,7 +943,7 @@ export interface HAEntity { entity_id: string; friendly_name: string; state: string | null; - domain: string; // "switch", "light", "input_boolean" + domain: string; // "switch", "light", "input_boolean", "script" } // Home Assistant sensor entity for energy monitoring @@ -2394,6 +2397,7 @@ export const api = { getSmartPlugs: () => request('/smart-plugs/'), getSmartPlug: (id: number) => request(`/smart-plugs/${id}`), getSmartPlugByPrinter: (printerId: number) => request(`/smart-plugs/by-printer/${printerId}`), + getScriptPlugsByPrinter: (printerId: number) => request(`/smart-plugs/by-printer/${printerId}/scripts`), createSmartPlug: (data: SmartPlugCreate) => request('/smart-plugs/', { method: 'POST', diff --git a/frontend/src/components/AddSmartPlugModal.tsx b/frontend/src/components/AddSmartPlugModal.tsx index bba6c11d0..df4c760b6 100644 --- a/frontend/src/components/AddSmartPlugModal.tsx +++ b/frontend/src/components/AddSmartPlugModal.tsx @@ -1,6 +1,6 @@ import { useState, useEffect, useRef } from 'react'; import { useMutation, useQueryClient, useQuery } from '@tanstack/react-query'; -import { X, Save, Loader2, Wifi, WifiOff, CheckCircle, Bell, Clock, LayoutGrid, Search, Plug, Power, Home } from 'lucide-react'; +import { X, Save, Loader2, Wifi, WifiOff, CheckCircle, Bell, Clock, LayoutGrid, Search, Plug, Power, Home, Play, Eye } from 'lucide-react'; import { api } from '../api/client'; import type { SmartPlug, SmartPlugCreate, SmartPlugUpdate, DiscoveredTasmotaDevice } from '../api/client'; import { Button } from './Button'; @@ -51,6 +51,10 @@ export function AddSmartPlugModal({ plug, onClose }: AddSmartPlugModalProps) { const [testResult, setTestResult] = useState<{ success: boolean; state?: string | null; device_name?: string | null } | null>(null); const [error, setError] = useState(null); + // Automation settings + const [autoOn, setAutoOn] = useState(plug?.auto_on ?? true); + const [autoOff, setAutoOff] = useState(plug?.auto_off ?? true); + // Power alert settings const [powerAlertEnabled, setPowerAlertEnabled] = useState(plug?.power_alert_enabled || false); const [powerAlertHigh, setPowerAlertHigh] = useState(plug?.power_alert_high?.toString() || ''); @@ -61,8 +65,9 @@ export function AddSmartPlugModal({ plug, onClose }: AddSmartPlugModalProps) { const [scheduleOnTime, setScheduleOnTime] = useState(plug?.schedule_on_time || ''); const [scheduleOffTime, setScheduleOffTime] = useState(plug?.schedule_off_time || ''); - // Switchbar visibility + // Visibility options const [showInSwitchbar, setShowInSwitchbar] = useState(plug?.show_in_switchbar || false); + const [showOnPrinterCard, setShowOnPrinterCard] = useState(plug?.show_on_printer_card ?? true); // Discovery state const [isScanning, setIsScanning] = useState(false); @@ -235,6 +240,10 @@ export function AddSmartPlugModal({ plug, onClose }: AddSmartPlugModalProps) { mutationFn: (data: SmartPlugCreate) => api.createSmartPlug(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['smart-plugs'] }); + // Also invalidate script plugs queries for printer cards + queryClient.invalidateQueries({ predicate: (query) => + Array.isArray(query.queryKey) && query.queryKey[0] === 'scriptPlugsByPrinter' + }); onClose(); }, onError: (err: Error) => { @@ -247,6 +256,10 @@ export function AddSmartPlugModal({ plug, onClose }: AddSmartPlugModalProps) { mutationFn: (data: SmartPlugUpdate) => api.updateSmartPlug(plug!.id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['smart-plugs'] }); + // Also invalidate script plugs queries for printer cards + queryClient.invalidateQueries({ predicate: (query) => + Array.isArray(query.queryKey) && query.queryKey[0] === 'scriptPlugsByPrinter' + }); onClose(); }, onError: (err: Error) => { @@ -254,11 +267,17 @@ export function AddSmartPlugModal({ plug, onClose }: AddSmartPlugModalProps) { }, }); + // Check if selected entity is a script (scripts allow multiple plugs per printer) + const isScript = plugType === 'homeassistant' && haEntityId?.startsWith('script.'); + // Filter out printers that already have a plug assigned (except current plug's printer) - const availablePrinters = printers?.filter(p => { - const hasPlug = existingPlugs?.some(ep => ep.printer_id === p.id && ep.id !== plug?.id); - return !hasPlug; - }); + // Scripts can link to any printer (they're for multi-device control) + const availablePrinters = isScript + ? printers + : printers?.filter(p => { + const hasPlug = existingPlugs?.some(ep => ep.printer_id === p.id && ep.id !== plug?.id); + return !hasPlug; + }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); @@ -291,6 +310,9 @@ export function AddSmartPlugModal({ plug, onClose }: AddSmartPlugModalProps) { username: plugType === 'tasmota' ? (username.trim() || null) : null, password: plugType === 'tasmota' ? (password.trim() || null) : null, printer_id: printerId, + // Automation + auto_on: autoOn, + auto_off: autoOff, // Power alerts power_alert_enabled: powerAlertEnabled, power_alert_high: powerAlertHigh ? parseFloat(powerAlertHigh) : null, @@ -299,8 +321,9 @@ export function AddSmartPlugModal({ plug, onClose }: AddSmartPlugModalProps) { schedule_enabled: scheduleEnabled, schedule_on_time: scheduleOnTime || null, schedule_off_time: scheduleOffTime || null, - // Switchbar + // Visibility options show_in_switchbar: showInSwitchbar, + show_on_printer_card: showOnPrinterCard, }; if (isEditing) { @@ -582,15 +605,15 @@ export function AddSmartPlugModal({ plug, onClose }: AddSmartPlugModalProps) {

{debouncedSearch ? `Searching all entities (${availableEntities.length} found)` - : `Showing switch, light, input_boolean (${availableEntities.length} available)`} + : `Showing switch, light, input_boolean, script (${availableEntities.length} available)`}

); })()} - {/* Energy Monitoring Section (Optional) */} - {haEntityId && haSensorEntities && haSensorEntities.length > 0 && ( + {/* Energy Monitoring Section (Optional) - hidden for scripts */} + {haEntityId && !isScript && haSensorEntities && haSensorEntities.length > 0 && (

Energy Monitoring (Optional)

@@ -975,110 +998,183 @@ export function AddSmartPlugModal({ plug, onClose }: AddSmartPlugModalProps) { ))}

- Linking enables automatic on/off when prints start/complete + {isScript + ? 'Link to a printer to enable auto-run triggers' + : 'Linking enables automatic on/off when prints start/complete'}

- {/* Power Alerts */} -
-
-
- - Power Alerts + {/* Script Options - only show for HA scripts */} + {isScript && ( +
+
+ + Script Automation +
+ + {/* Auto-run when printer turns on */} +
+
+ Run when printer turns on +

Execute script when main plug is switched on

+
+ +
+ + {/* Auto-run when printer turns off */} +
+
+ Run when printer turns off +

Execute script when main plug is switched off

+
+
-
- {powerAlertEnabled && ( -
-
-
- - setPowerAlertHigh(e.target.value)} - placeholder="e.g. 200" - min="0" - max="5000" - className="w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none" - /> + )} + + {/* Power Alerts - hidden for scripts (no power monitoring) */} + {!isScript && ( +
+
+
+ + Power Alerts +
+ +
+ {powerAlertEnabled && ( +
+
+
+ + setPowerAlertHigh(e.target.value)} + placeholder="e.g. 200" + min="0" + max="5000" + className="w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none" + /> +
+
+ + setPowerAlertLow(e.target.value)} + placeholder="e.g. 10" + min="0" + max="5000" + className="w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none" + /> +
+

+ Get notified when power consumption crosses these thresholds. Leave empty to disable that direction. +

+
+ )} +
+ )} + + {/* Schedule - hidden for scripts */} + {!isScript && ( +
+
+
+ + Daily Schedule +
+ +
+ {scheduleEnabled && ( +
+
+
+ + setScheduleOnTime(e.target.value)} + className="w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none" + /> +
+
+ + setScheduleOffTime(e.target.value)} + className="w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none" + /> +
+
+

+ Automatically turn the plug on/off at these times daily. Leave empty to skip that action. +

+
+ )} +
+ )} + + {/* Visibility Options */} +
+ {/* Show on printer card - only for scripts */} + {isScript && ( +
+
+
- - setPowerAlertLow(e.target.value)} - placeholder="e.g. 10" - min="0" - max="5000" - className="w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none" - /> + Show on Printer Card +

Display script button on printer card

-

- Get notified when power consumption crosses these thresholds. Leave empty to disable that direction. -

+
)} -
- {/* Schedule */} -
-
-
- - Daily Schedule -
- -
- {scheduleEnabled && ( -
-
-
- - setScheduleOnTime(e.target.value)} - className="w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none" - /> -
-
- - setScheduleOffTime(e.target.value)} - className="w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none" - /> -
-
-

- Automatically turn the plug on/off at these times daily. Leave empty to skip that action. -

-
- )} -
- - {/* Switchbar Visibility */} -
+ {/* Show in Switchbar */}
diff --git a/frontend/src/components/SmartPlugCard.tsx b/frontend/src/components/SmartPlugCard.tsx index 4ec49c610..739c65410 100644 --- a/frontend/src/components/SmartPlugCard.tsx +++ b/frontend/src/components/SmartPlugCard.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; import { useMutation, useQueryClient, useQuery } from '@tanstack/react-query'; -import { Plug, Power, PowerOff, Loader2, Trash2, Settings2, Thermometer, Clock, Wifi, WifiOff, Edit2, Bell, Calendar, LayoutGrid, ExternalLink, Home } from 'lucide-react'; +import { Plug, Power, PowerOff, Loader2, Trash2, Settings2, Thermometer, Clock, Wifi, WifiOff, Edit2, Bell, Calendar, LayoutGrid, ExternalLink, Home, Play, Eye } from 'lucide-react'; import { api } from '../api/client'; import type { SmartPlug, SmartPlugUpdate } from '../api/client'; import { Card, CardContent } from './Card'; @@ -55,12 +55,24 @@ export function SmartPlugCard({ plug, onEdit }: SmartPlugCardProps) { return { previousStatus }; }, + onSuccess: (_data, action) => { + // Show toast for script triggers + const isScriptPlug = plug.plug_type === 'homeassistant' && plug.ha_entity_id?.startsWith('script.'); + if (isScriptPlug && action === 'on') { + showToast(`Script "${plug.name}" triggered`, 'success'); + } + }, onError: (_err, action, context) => { // Rollback on error if (context?.previousStatus) { queryClient.setQueryData(['smart-plug-status', plug.id], context.previousStatus); } - showToast(`Failed to turn ${action} "${plug.name}"`, 'error'); + const isScriptPlug = plug.plug_type === 'homeassistant' && plug.ha_entity_id?.startsWith('script.'); + if (isScriptPlug) { + showToast(`Failed to trigger script "${plug.name}"`, 'error'); + } else { + showToast(`Failed to turn ${action} "${plug.name}"`, 'error'); + } }, onSettled: () => { // Refetch after a short delay to get actual state @@ -80,6 +92,10 @@ export function SmartPlugCard({ plug, onEdit }: SmartPlugCardProps) { if (plug.printer_id) { queryClient.invalidateQueries({ queryKey: ['smartPlugByPrinter', plug.printer_id] }); } + // Invalidate script plugs queries for printer cards + queryClient.invalidateQueries({ predicate: (query) => + Array.isArray(query.queryKey) && query.queryKey[0] === 'scriptPlugsByPrinter' + }); }, }); @@ -88,6 +104,10 @@ export function SmartPlugCard({ plug, onEdit }: SmartPlugCardProps) { mutationFn: () => api.deleteSmartPlug(plug.id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['smart-plugs'] }); + // Also invalidate script plugs queries for printer cards + queryClient.invalidateQueries({ predicate: (query) => + Array.isArray(query.queryKey) && query.queryKey[0] === 'scriptPlugsByPrinter' + }); }, }); @@ -95,6 +115,9 @@ export function SmartPlugCard({ plug, onEdit }: SmartPlugCardProps) { const isReachable = status?.reachable ?? false; const isPending = controlMutation.isPending; + // Check if this is a HA script entity (scripts can only be triggered, not toggled) + const isScript = plug.plug_type === 'homeassistant' && plug.ha_entity_id?.startsWith('script.'); + // Generate admin URL with auto-login credentials (Tasmota only) const getAdminUrl = () => { if (plug.plug_type !== 'tasmota' || !plug.ip_address) return null; @@ -113,31 +136,46 @@ export function SmartPlugCard({ plug, onEdit }: SmartPlugCardProps) { {/* Header Row */} -
-
-
- {plug.plug_type === 'homeassistant' ? ( +
+
+
+ {isScript ? ( + + ) : plug.plug_type === 'homeassistant' ? ( ) : ( )}
-
-

{plug.name}

-

+

+

{plug.name}

+

{plug.plug_type === 'homeassistant' ? plug.ha_entity_id : plug.ip_address}

{/* Status indicator */} -
+
{statusLoading ? ( + ) : isScript ? ( + /* Script entities: show badge and Ready status stacked */ +
+ + + Script + + + {isReachable ? 'Ready' : 'Offline'} + +
) : isReachable ? (
- {status?.state || 'Unknown'} + + {status?.state || 'Unknown'} +
) : (
@@ -193,26 +231,43 @@ export function SmartPlugCard({ plug, onEdit }: SmartPlugCardProps) { {/* Quick Controls */}
- - + {isScript ? ( + /* Script entities: single "Run" button */ + + ) : ( + /* Regular entities: On/Off buttons */ + <> + + + + )}
{/* Toggle Settings Panel */} @@ -230,6 +285,28 @@ export function SmartPlugCard({ plug, onEdit }: SmartPlugCardProps) { {/* Expanded Settings */} {isExpanded && (
+ {/* Show on Printer Card Toggle - only for scripts */} + {isScript && ( +
+
+ +
+

Show on Printer Card

+

Display script button on printer card

+
+
+ +
+ )} + {/* Show in Switchbar Toggle */}
@@ -267,11 +344,13 @@ export function SmartPlugCard({ plug, onEdit }: SmartPlugCardProps) {
- {/* Auto On */} + {/* Auto On / Run when printer turns on */}
-

Auto On

-

Turn on when print starts

+

{isScript ? 'Run when printer turns on' : 'Auto On'}

+

+ {isScript ? 'Execute script when main plug is switched on' : 'Turn on when print starts'} +

- {/* Auto Off */} + {/* Auto Off / Run when printer turns off */}
-

Auto Off

-

Turn off when print completes (one-shot)

+

{isScript ? 'Run when printer turns off' : 'Auto Off'}

+

+ {isScript ? 'Execute script when main plug is switched off' : 'Turn off when print completes (one-shot)'} +

- {/* Delay Mode */} - {plug.auto_off && ( + {/* Delay Mode - hidden for script entities */} + {plug.auto_off && !isScript && (

Turn Off Delay Mode

@@ -401,12 +482,14 @@ export function SmartPlugCard({ plug, onEdit }: SmartPlugCardProps) { /> )} - {/* Power On Confirmation */} + {/* Power On / Run Script Confirmation */} {showPowerOnConfirm && ( { controlMutation.mutate('on'); diff --git a/frontend/src/components/SwitchbarPopover.tsx b/frontend/src/components/SwitchbarPopover.tsx index 081387cbe..2a7f6d606 100644 --- a/frontend/src/components/SwitchbarPopover.tsx +++ b/frontend/src/components/SwitchbarPopover.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; -import { Plug, Power, PowerOff, Loader2, Wifi, WifiOff, Zap } from 'lucide-react'; +import { Plug, Power, PowerOff, Loader2, Wifi, WifiOff, Zap, Play } from 'lucide-react'; import { api } from '../api/client'; import type { SmartPlug } from '../api/client'; import { ConfirmModal } from './ConfirmModal'; @@ -32,6 +32,9 @@ function SwitchItem({ plug }: { plug: SmartPlug }) { const isReachable = status?.reachable ?? false; const isPending = controlMutation.isPending; + // Check if this is a HA script entity + const isScript = plug.plug_type === 'homeassistant' && plug.ha_entity_id?.startsWith('script.'); + const handleConfirm = () => { if (confirmAction) { controlMutation.mutate(confirmAction); @@ -43,18 +46,33 @@ function SwitchItem({ plug }: { plug: SmartPlug }) { <>
-
- +
+ {isScript ? ( + + ) : ( + + )}
-

{plug.name}

+
+

{plug.name}

+ {isScript && ( + Script + )} +
{statusLoading ? ( + ) : isScript ? ( + + {isReachable ? 'Ready' : 'Offline'} + ) : isReachable ? ( <> - {status?.state || 'Unknown'} + + {status?.state || 'Unknown'} + {status?.energy?.power !== null && status?.energy?.power !== undefined && ( <> | @@ -74,38 +92,57 @@ function SwitchItem({ plug }: { plug: SmartPlug }) {
- - + {isScript ? ( + /* Script: single Run button */ + + ) : ( + /* Regular: On/Off buttons */ + <> + + + + )}
{confirmAction && ( setConfirmAction(null)} diff --git a/frontend/src/pages/PrintersPage.tsx b/frontend/src/pages/PrintersPage.tsx index be7e92ca7..6e8930382 100644 --- a/frontend/src/pages/PrintersPage.tsx +++ b/frontend/src/pages/PrintersPage.tsx @@ -1093,6 +1093,12 @@ function PrinterCard({ queryFn: () => api.getSmartPlugByPrinter(printer.id), }); + // Fetch script plugs for this printer (for multi-device control) + const { data: scriptPlugs } = useQuery({ + queryKey: ['scriptPlugsByPrinter', printer.id], + queryFn: () => api.getScriptPlugsByPrinter(printer.id), + }); + // Fetch smart plug status if plug exists (faster refresh for energy monitoring) const { data: plugStatus } = useQuery({ queryKey: ['smartPlugStatus', smartPlug?.id], @@ -1155,6 +1161,15 @@ function PrinterCard({ }, }); + // Run script mutation + const runScriptMutation = useMutation({ + mutationFn: (scriptId: number) => api.controlSmartPlug(scriptId, 'on'), + onSuccess: () => { + showToast('Script triggered'); + }, + onError: (error: Error) => showToast(error.message || 'Failed to run script', 'error'), + }); + // Print control mutations const stopPrintMutation = useMutation({ mutationFn: () => api.stopPrint(printer.id), @@ -2683,6 +2698,28 @@ function PrinterCard({
+ + {/* Script buttons row */} + {scriptPlugs && scriptPlugs.length > 0 && ( +
+ + Scripts: +
+ {scriptPlugs.map(script => ( + + ))} +
+
+ )}
)} diff --git a/frontend/src/pages/SettingsPage.tsx b/frontend/src/pages/SettingsPage.tsx index 7d1af648b..eadb19e73 100644 --- a/frontend/src/pages/SettingsPage.tsx +++ b/frontend/src/pages/SettingsPage.tsx @@ -1643,7 +1643,7 @@ export function SettingsPage() {

- Connect to Home Assistant to control smart plugs via HA's REST API. Supports switch, light, and input_boolean entities. + Connect to Home Assistant to control smart plugs via HA's REST API. Supports switch, light, input_boolean, and script entities.

diff --git a/static/assets/index-CKmo1TxA.js b/static/assets/index-Di2BGmGD.js similarity index 66% rename from static/assets/index-CKmo1TxA.js rename to static/assets/index-Di2BGmGD.js index 730ca0279..33e8b5df1 100644 --- a/static/assets/index-CKmo1TxA.js +++ b/static/assets/index-Di2BGmGD.js @@ -1,20 +1,20 @@ -function jae(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 Jv=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Fo(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var _T={exports:{}},Kx={};var _U;function Pae(){if(_U)return Kx;_U=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 Kx.Fragment=e,Kx.jsx=n,Kx.jsxs=n,Kx}var wU;function Rae(){return wU||(wU=1,_T.exports=Pae()),_T.exports}var s=Rae(),wT={exports:{}},bn={};var SU;function Dae(){if(SU)return bn;SU=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,ae){this.props=z,this.context=G,this.refs=b,this.updater=ae||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,ae){this.props=z,this.context=G,this.refs=b,this.updater=ae||x}var A=S.prototype=new M;A.constructor=S,y(A,v.prototype),A.isPureReactComponent=!0;var T=Array.isArray;function C(){}var E={H:null,A:null,T:null,S:null},D=Object.prototype.hasOwnProperty;function k(z,G,ae){var se=ae.ref;return{$$typeof:t,type:z,key:G,ref:se!==void 0?se:null,props:ae}}function R(z,G){return k(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(ae){return G[ae]})}var X=/\/+/g;function j(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(C,C):(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,ae,se,de){var me=typeof z;(me==="undefined"||me==="boolean")&&(z=null);var ue=!1;if(z===null)ue=!0;else switch(me){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,ae,se,de)}}if(ue)return de=de(z),ue=se===""?"."+j(z,0):se,T(de)?(ae="",ue!=null&&(ae=ue.replace(X,"$&/")+"/"),Y(de,G,ae,"",function(Me){return Me})):de!=null&&(F(de)&&(de=R(de,ae+(de.key==null||z&&z.key===de.key?"":(""+de.key).replace(X,"$&/")+"/")+ue)),G.push(de)),1;ue=0;var Ee=se===""?".":se+":";if(T(z))for(var pe=0;pe>>1,ne=Y[ee];if(0>>1;eei(ae,Z))sei(de,ae)?(Y[ee]=de,Y[se]=Z,ee=se):(Y[ee]=ae,Y[G]=Z,ee=G);else if(sei(de,Z))Y[ee]=de,Y[se]=Z,ee=se;else break e}}return q}function i(Y,q){var Z=Y.sortIndex-q.sortIndex;return Z!==0?Z: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 A(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 T(Y){if(y=!1,A(Y),!x)if(n(c)!==null)x=!0,C||(C=!0,O());else{var q=n(u);q!==null&&W(T,q.startTime-Y)}}var C=!1,E=-1,D=5,k=-1;function R(){return b?!0:!(t.unstable_now()-kY&&R());){var ee=f.callback;if(typeof ee=="function"){f.callback=null,m=f.priorityLevel;var ne=ee(f.expirationTime<=Y);if(Y=t.unstable_now(),typeof ne=="function"){f.callback=ne,A(Y),q=!0;break t}f===n(c)&&r(c),A(Y)}else r(c);f=n(c)}if(f!==null)q=!0;else{var z=n(u);z!==null&&W(T,z.startTime-Y),q=!1}}break e}finally{f=null,m=Z,g=!1}q=void 0}}finally{q?O():C=!1}}}var O;if(typeof S=="function")O=function(){S(F)};else if(typeof MessageChannel<"u"){var X=new MessageChannel,j=X.port2;X.port1.onmessage=F,O=function(){j.postMessage(null)}}else O=function(){v(F,0)};function W(Y,q){E=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||125ee?(Y.sortIndex=Z,e(u,Y),n(c)===null&&Y===n(u)&&(y?(M(E),E=-1):y=!0,W(T,Z-ee))):(Y.sortIndex=ne,e(c,Y),x||g||(x=!0,C||(C=!0,O()))),Y},t.unstable_shouldYield=R,t.unstable_wrapCallback=function(Y){var q=m;return function(){var Z=m;m=q;try{return Y.apply(this,arguments)}finally{m=Z}}}})(NT)),NT}var EU;function Iae(){return EU||(EU=1,MT.exports=Lae()),MT.exports}var ET={exports:{}},Ma={};var TU;function Fae(){if(TU)return Ma;TU=1;var t=Dg();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(),ET.exports=Fae(),ET.exports}var CU;function Uae(){if(CU)return Xx;CU=1;var t=Iae(),e=Dg(),n=aW();function r(h){var p="https://react.dev/errors/"+h;if(1ne||(h.current=ee[ne],ee[ne]=null,ne--)}function ae(h,p){ne++,ee[ne]=h.current,h.current=p}var se=z(null),de=z(null),me=z(null),ue=z(null);function Ee(h,p){switch(ae(me,p),ae(de,h),ae(se,null),p.nodeType){case 9:case 11:h=(h=p.documentElement)&&(h=h.namespaceURI)?VF(h):0;break;default:if(h=p.tagName,p=p.namespaceURI)p=VF(p),h=GF(p,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}G(se),ae(se,h)}function pe(){G(se),G(de),G(me)}function Me(h){h.memoizedState!==null&&ae(ue,h);var p=se.current,_=GF(p,h.type);p!==_&&(ae(de,h),ae(se,_))}function ve(h){de.current===h&&(G(se),G(de)),ue.current===h&&(G(ue),Vx._currentValue=Z)}var oe,Oe;function V(h){if(oe===void 0)try{throw Error()}catch(_){var p=_.stack.trim().match(/\n( *(at )?)/);oe=p&&p[1]||"",Oe=-1<_.stack.indexOf(` +function jae(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 t_=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Uo(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var _T={exports:{}},Yx={};var _U;function Pae(){if(_U)return Yx;_U=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 Yx.Fragment=e,Yx.jsx=n,Yx.jsxs=n,Yx}var wU;function Rae(){return wU||(wU=1,_T.exports=Pae()),_T.exports}var s=Rae(),wT={exports:{}},bn={};var SU;function Dae(){if(SU)return bn;SU=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,ae){this.props=z,this.context=G,this.refs=b,this.updater=ae||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 N(){}N.prototype=v.prototype;function S(z,G,ae){this.props=z,this.context=G,this.refs=b,this.updater=ae||x}var A=S.prototype=new N;A.constructor=S,y(A,v.prototype),A.isPureReactComponent=!0;var T=Array.isArray;function C(){}var E={H:null,A:null,T:null,S:null},D=Object.prototype.hasOwnProperty;function k(z,G,ae){var se=ae.ref;return{$$typeof:t,type:z,key:G,ref:se!==void 0?se:null,props:ae}}function P(z,G){return k(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(ae){return G[ae]})}var K=/\/+/g;function j(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(C,C):(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,ae,se,de){var me=typeof z;(me==="undefined"||me==="boolean")&&(z=null);var ue=!1;if(z===null)ue=!0;else switch(me){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,ae,se,de)}}if(ue)return de=de(z),ue=se===""?"."+j(z,0):se,T(de)?(ae="",ue!=null&&(ae=ue.replace(K,"$&/")+"/"),Y(de,G,ae,"",function(Ne){return Ne})):de!=null&&(F(de)&&(de=P(de,ae+(de.key==null||z&&z.key===de.key?"":(""+de.key).replace(K,"$&/")+"/")+ue)),G.push(de)),1;ue=0;var Te=se===""?".":se+":";if(T(z))for(var pe=0;pe>>1,ne=Y[ee];if(0>>1;eei(ae,Z))sei(de,ae)?(Y[ee]=de,Y[se]=Z,ee=se):(Y[ee]=ae,Y[G]=Z,ee=G);else if(sei(de,Z))Y[ee]=de,Y[se]=Z,ee=se;else break e}}return q}function i(Y,q){var Z=Y.sortIndex-q.sortIndex;return Z!==0?Z: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,N=typeof clearTimeout=="function"?clearTimeout:null,S=typeof setImmediate<"u"?setImmediate:null;function A(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 T(Y){if(y=!1,A(Y),!x)if(n(c)!==null)x=!0,C||(C=!0,O());else{var q=n(u);q!==null&&W(T,q.startTime-Y)}}var C=!1,E=-1,D=5,k=-1;function P(){return b?!0:!(t.unstable_now()-kY&&P());){var ee=f.callback;if(typeof ee=="function"){f.callback=null,m=f.priorityLevel;var ne=ee(f.expirationTime<=Y);if(Y=t.unstable_now(),typeof ne=="function"){f.callback=ne,A(Y),q=!0;break t}f===n(c)&&r(c),A(Y)}else r(c);f=n(c)}if(f!==null)q=!0;else{var z=n(u);z!==null&&W(T,z.startTime-Y),q=!1}}break e}finally{f=null,m=Z,g=!1}q=void 0}}finally{q?O():C=!1}}}var O;if(typeof S=="function")O=function(){S(F)};else if(typeof MessageChannel<"u"){var K=new MessageChannel,j=K.port2;K.port1.onmessage=F,O=function(){j.postMessage(null)}}else O=function(){v(F,0)};function W(Y,q){E=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||125ee?(Y.sortIndex=Z,e(u,Y),n(c)===null&&Y===n(u)&&(y?(N(E),E=-1):y=!0,W(T,Z-ee))):(Y.sortIndex=ne,e(c,Y),x||g||(x=!0,C||(C=!0,O()))),Y},t.unstable_shouldYield=P,t.unstable_wrapCallback=function(Y){var q=m;return function(){var Z=m;m=q;try{return Y.apply(this,arguments)}finally{m=Z}}}})(MT)),MT}var EU;function Iae(){return EU||(EU=1,NT.exports=Lae()),NT.exports}var ET={exports:{}},Aa={};var TU;function Fae(){if(TU)return Aa;TU=1;var t=Og();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(),ET.exports=Fae(),ET.exports}var CU;function Uae(){if(CU)return Qx;CU=1;var t=Iae(),e=Og(),n=aW();function r(h){var p="https://react.dev/errors/"+h;if(1ne||(h.current=ee[ne],ee[ne]=null,ne--)}function ae(h,p){ne++,ee[ne]=h.current,h.current=p}var se=z(null),de=z(null),me=z(null),ue=z(null);function Te(h,p){switch(ae(me,p),ae(de,h),ae(se,null),p.nodeType){case 9:case 11:h=(h=p.documentElement)&&(h=h.namespaceURI)?VF(h):0;break;default:if(h=p.tagName,p=p.namespaceURI)p=VF(p),h=GF(p,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}G(se),ae(se,h)}function pe(){G(se),G(de),G(me)}function Ne(h){h.memoizedState!==null&&ae(ue,h);var p=se.current,_=GF(p,h.type);p!==_&&(ae(de,h),ae(se,_))}function ve(h){de.current===h&&(G(se),G(de)),ue.current===h&&(G(ue),Wx._currentValue=Z)}var oe,Oe;function V(h){if(oe===void 0)try{throw Error()}catch(_){var p=_.stack.trim().match(/\n( *(at )?)/);oe=p&&p[1]||"",Oe=-1<_.stack.indexOf(` at`)?" ()":-1<_.stack.indexOf("@")?"@unknown:0:0":""}return` -`+oe+h+Oe}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 _t=function(){throw Error()};if(Object.defineProperty(_t.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(_t,[])}catch(dt){var st=dt}Reflect.construct(h,[],_t)}else{try{_t.call()}catch(dt){st=dt}h.call(_t.prototype)}}else{try{throw Error()}catch(dt){st=dt}(_t=h())&&typeof _t.catch=="function"&&_t.catch(function(){})}}catch(dt){if(dt&&st&&typeof dt.stack=="string")return[dt.stack,st.stack]}return[null,null]}};N.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var P=Object.getOwnPropertyDescriptor(N.DetermineComponentFrameRoot,"name");P&&P.configurable&&Object.defineProperty(N.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var L=N.DetermineComponentFrameRoot(),J=L[0],ge=L[1];if(J&&ge){var Le=J.split(` -`),rt=ge.split(` -`);for(P=N=0;NP||Le[N]!==rt[P]){var bt=` -`+Le[N].replace(" at new "," at ");return h.displayName&&bt.includes("")&&(bt=bt.replace("",h.displayName)),bt}while(1<=N&&0<=P);break}}}finally{H=!1,Error.prepareStackTrace=_}return(_=h?h.displayName||h.name:"")?V(_):""}function U(h,p){switch(h.tag){case 26:case 27:case 5:return V(h.type);case 16:return V("Lazy");case 13:return h.child!==p&&p!==null?V("Suspense Fallback"):V("Suspense");case 19:return V("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 V("Activity");default:return""}}function Q(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 ce=Object.prototype.hasOwnProperty,Ae=t.unstable_scheduleCallback,je=t.unstable_cancelCallback,Te=t.unstable_shouldYield,B=t.unstable_requestPaint,I=t.unstable_now,$=t.unstable_getCurrentPriorityLevel,te=t.unstable_ImmediatePriority,be=t.unstable_UserBlockingPriority,xe=t.unstable_NormalPriority,Qe=t.unstable_LowPriority,ze=t.unstable_IdlePriority,Je=t.log,We=t.unstable_setDisableYieldValue,qe=null,le=null;function ie(h){if(typeof Je=="function"&&We(h),le&&typeof le.setStrictMode=="function")try{le.setStrictMode(qe,h)}catch{}}var Ne=Math.clz32?Math.clz32:re,He=Math.log,nt=Math.LN2;function re(h){return h>>>=0,h===0?32:31-(He(h)/nt|0)|0}var Pe=256,_e=262144,Re=4194304;function Ie(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 Ce(h,p,_){var N=h.pendingLanes;if(N===0)return 0;var P=0,L=h.suspendedLanes,J=h.pingedLanes;h=h.warmLanes;var ge=N&134217727;return ge!==0?(N=ge&~L,N!==0?P=Ie(N):(J&=ge,J!==0?P=Ie(J):_||(_=ge&~h,_!==0&&(P=Ie(_))))):(ge=N&~L,ge!==0?P=Ie(ge):J!==0?P=Ie(J):_||(_=N&~h,_!==0&&(P=Ie(_)))),P===0?0:p!==0&&p!==P&&(p&L)===0&&(L=P&-P,_=p&-p,L>=_||L===32&&(_&4194048)!==0)?p:P}function Ze(h,p){return(h.pendingLanes&~(h.suspendedLanes&~h.pingedLanes)&p)===0}function yt(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 kt(){var h=Re;return Re<<=1,(Re&62914560)===0&&(Re=4194304),h}function Lt(h){for(var p=[],_=0;31>_;_++)p.push(h);return p}function cn(h,p){h.pendingLanes|=p,p!==268435456&&(h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0)}function Ht(h,p,_,N,P,L){var J=h.pendingLanes;h.pendingLanes=_,h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0,h.expiredLanes&=_,h.entangledLanes&=_,h.errorRecoveryDisabledLanes&=_,h.shellSuspendCounter=0;var ge=h.entanglements,Le=h.expirationTimes,rt=h.hiddenUpdates;for(_=J&~_;0<_;){var bt=31-Ne(_),_t=1<"u")return null;try{return h.activeElement||h.body}catch{return h.body}}var Ft=/[\n"\\]/g;function sn(h){return h.replace(Ft,function(p){return"\\"+p.charCodeAt(0).toString(16)+" "})}function Xn(h,p,_,N,P,L,J,ge){h.name="",J!=null&&typeof J!="function"&&typeof J!="symbol"&&typeof J!="boolean"?h.type=J:h.removeAttribute("type"),p!=null?J==="number"?(p===0&&h.value===""||h.value!=p)&&(h.value=""+ye(p)):h.value!==""+ye(p)&&(h.value=""+ye(p)):J!=="submit"&&J!=="reset"||h.removeAttribute("value"),p!=null?wr(h,J,ye(p)):_!=null?wr(h,J,ye(_)):N!=null&&h.removeAttribute("value"),P==null&&L!=null&&(h.defaultChecked=!!L),P!=null&&(h.checked=P&&typeof P!="function"&&typeof P!="symbol"),ge!=null&&typeof ge!="function"&&typeof ge!="symbol"&&typeof ge!="boolean"?h.name=""+ye(ge):h.removeAttribute("name")}function dn(h,p,_,N,P,L,J,ge){if(L!=null&&typeof L!="function"&&typeof L!="symbol"&&typeof L!="boolean"&&(h.type=L),p!=null||_!=null){if(!(L!=="submit"&&L!=="reset"||p!=null)){mt(h);return}_=_!=null?""+ye(_):"",p=p!=null?""+ye(p):_,ge||p===h.value||(h.value=p),h.defaultValue=p}N=N??P,N=typeof N!="function"&&typeof N!="symbol"&&!!N,h.checked=ge?h.checked:!!N,h.defaultChecked=!!N,J!=null&&typeof J!="function"&&typeof J!="symbol"&&typeof J!="boolean"&&(h.name=J),mt(h)}function wr(h,p,_){p==="number"&>(h.ownerDocument)===h||h.defaultValue===""+_||(h.defaultValue=""+_)}function Wt(h,p,_,N){if(h=h.options,p){p={};for(var P=0;P<_.length;P++)p["$"+_[P]]=!0;for(_=0;_"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),_N=!1;if(rc)try{var lx={};Object.defineProperty(lx,"passive",{get:function(){_N=!0}}),window.addEventListener("test",lx,lx),window.removeEventListener("test",lx,lx)}catch{_N=!1}var wu=null,wN=null,Gy=null;function GL(){if(Gy)return Gy;var h,p=wN,_=p.length,N,P="value"in wu?wu.value:wu.textContent,L=P.length;for(h=0;h<_&&p[h]===P[h];h++);var J=_-h;for(N=1;N<=J&&p[_-N]===P[L-N];N++);return Gy=P.slice(h,1=dx),QL=" ",ZL=!1;function JL(h,p){switch(h){case"keyup":return Jre.indexOf(p.keyCode)!==-1;case"keydown":return p.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function eI(h){return h=h.detail,typeof h=="object"&&"data"in h?h.data:null}var lm=!1;function tie(h,p){switch(h){case"compositionend":return eI(p);case"keypress":return p.which!==32?null:(ZL=!0,QL);case"textInput":return h=p.data,h===QL&&ZL?null:h;default:return null}}function nie(h,p){if(lm)return h==="compositionend"||!TN&&JL(h,p)?(h=GL(),Gy=wN=wu=null,lm=!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}_=lI(_)}}function uI(h,p){return h&&p?h===p?!0:h&&h.nodeType===3?!1:p&&p.nodeType===3?uI(h,p.parentNode):"contains"in h?h.contains(p):h.compareDocumentPosition?!!(h.compareDocumentPosition(p)&16):!1:!1}function dI(h){h=h!=null&&h.ownerDocument!=null&&h.ownerDocument.defaultView!=null?h.ownerDocument.defaultView:window;for(var p=gt(h.document);p instanceof h.HTMLIFrameElement;){try{var _=typeof p.contentWindow.location.href=="string"}catch{_=!1}if(_)h=p.contentWindow;else break;p=gt(h.document)}return p}function kN(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 uie=rc&&"documentMode"in document&&11>=document.documentMode,cm=null,jN=null,px=null,PN=!1;function hI(h,p,_){var N=_.window===_?_.document:_.nodeType===9?_:_.ownerDocument;PN||cm==null||cm!==gt(N)||(N=cm,"selectionStart"in N&&kN(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}),px&&mx(px,N)||(px=N,N=Fv(jN,"onSelect"),0>=J,P-=J,xl=1<<32-Ne(p)+P|_<_n?(Ln=Qt,Qt=null):Ln=Qt.sibling;var Gn=st(Ye,Qt,tt[_n],vt);if(Gn===null){Qt===null&&(Qt=Ln);break}h&&Qt&&Gn.alternate===null&&p(Ye,Qt),Ve=L(Gn,Ve,_n),Vn===null?Jt=Gn:Vn.sibling=Gn,Vn=Gn,Qt=Ln}if(_n===tt.length)return _(Ye,Qt),Fn&&ac(Ye,_n),Jt;if(Qt===null){for(;_n_n?(Ln=Qt,Qt=null):Ln=Qt.sibling;var Vu=st(Ye,Qt,Gn.value,vt);if(Vu===null){Qt===null&&(Qt=Ln);break}h&&Qt&&Vu.alternate===null&&p(Ye,Qt),Ve=L(Vu,Ve,_n),Vn===null?Jt=Vu:Vn.sibling=Vu,Vn=Vu,Qt=Ln}if(Gn.done)return _(Ye,Qt),Fn&&ac(Ye,_n),Jt;if(Qt===null){for(;!Gn.done;_n++,Gn=tt.next())Gn=_t(Ye,Gn.value,vt),Gn!==null&&(Ve=L(Gn,Ve,_n),Vn===null?Jt=Gn:Vn.sibling=Gn,Vn=Gn);return Fn&&ac(Ye,_n),Jt}for(Qt=N(Qt);!Gn.done;_n++,Gn=tt.next())Gn=dt(Qt,Ye,_n,Gn.value,vt),Gn!==null&&(h&&Gn.alternate!==null&&Qt.delete(Gn.key===null?_n:Gn.key),Ve=L(Gn,Ve,_n),Vn===null?Jt=Gn:Vn.sibling=Gn,Vn=Gn);return h&&Qt.forEach(function(kae){return p(Ye,kae)}),Fn&&ac(Ye,_n),Jt}function lr(Ye,Ve,tt,vt){if(typeof tt=="object"&&tt!==null&&tt.type===y&&tt.key===null&&(tt=tt.props.children),typeof tt=="object"&&tt!==null){switch(tt.$$typeof){case g:e:{for(var Jt=tt.key;Ve!==null;){if(Ve.key===Jt){if(Jt=tt.type,Jt===y){if(Ve.tag===7){_(Ye,Ve.sibling),vt=P(Ve,tt.props.children),vt.return=Ye,Ye=vt;break e}}else if(Ve.elementType===Jt||typeof Jt=="object"&&Jt!==null&&Jt.$$typeof===D&&vh(Jt)===Ve.type){_(Ye,Ve.sibling),vt=P(Ve,tt.props),_x(vt,tt),vt.return=Ye,Ye=vt;break e}_(Ye,Ve);break}else p(Ye,Ve);Ve=Ve.sibling}tt.type===y?(vt=ph(tt.props.children,Ye.mode,vt,tt.key),vt.return=Ye,Ye=vt):(vt=tv(tt.type,tt.key,tt.props,null,Ye.mode,vt),_x(vt,tt),vt.return=Ye,Ye=vt)}return J(Ye);case x:e:{for(Jt=tt.key;Ve!==null;){if(Ve.key===Jt)if(Ve.tag===4&&Ve.stateNode.containerInfo===tt.containerInfo&&Ve.stateNode.implementation===tt.implementation){_(Ye,Ve.sibling),vt=P(Ve,tt.children||[]),vt.return=Ye,Ye=vt;break e}else{_(Ye,Ve);break}else p(Ye,Ve);Ve=Ve.sibling}vt=UN(tt,Ye.mode,vt),vt.return=Ye,Ye=vt}return J(Ye);case D:return tt=vh(tt),lr(Ye,Ve,tt,vt)}if(W(tt))return qt(Ye,Ve,tt,vt);if(O(tt)){if(Jt=O(tt),typeof Jt!="function")throw Error(r(150));return tt=Jt.call(tt),an(Ye,Ve,tt,vt)}if(typeof tt.then=="function")return lr(Ye,Ve,lv(tt),vt);if(tt.$$typeof===S)return lr(Ye,Ve,iv(Ye,tt),vt);cv(Ye,tt)}return typeof tt=="string"&&tt!==""||typeof tt=="number"||typeof tt=="bigint"?(tt=""+tt,Ve!==null&&Ve.tag===6?(_(Ye,Ve.sibling),vt=P(Ve,tt),vt.return=Ye,Ye=vt):(_(Ye,Ve),vt=FN(tt,Ye.mode,vt),vt.return=Ye,Ye=vt),J(Ye)):_(Ye,Ve)}return function(Ye,Ve,tt,vt){try{vx=0;var Jt=lr(Ye,Ve,tt,vt);return vm=null,Jt}catch(Qt){if(Qt===ym||Qt===sv)throw Qt;var Vn=Cs(29,Qt,null,Ye.mode);return Vn.lanes=vt,Vn.return=Ye,Vn}finally{}}}var wh=OI(!0),LI=OI(!1),Tu=!1;function QN(h){h.updateQueue={baseState:h.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function ZN(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 Au(h){return{lane:h,tag:0,payload:null,callback:null,next:null}}function Cu(h,p,_){var N=h.updateQueue;if(N===null)return null;if(N=N.shared,(Yn&2)!==0){var P=N.pending;return P===null?p.next=p:(p.next=P.next,P.next=p),N.pending=p,p=ev(h),yI(h,null,_),p}return Jy(h,N,p,_),ev(h)}function wx(h,p,_){if(p=p.updateQueue,p!==null&&(p=p.shared,(_&4194048)!==0)){var N=p.lanes;N&=h.pendingLanes,_|=N,p.lanes=_,xt(h,_)}}function JN(h,p){var _=h.updateQueue,N=h.alternate;if(N!==null&&(N=N.updateQueue,_===N)){var P=null,L=null;if(_=_.firstBaseUpdate,_!==null){do{var J={lane:_.lane,tag:_.tag,payload:_.payload,callback:null,next:null};L===null?P=L=J:L=L.next=J,_=_.next}while(_!==null);L===null?P=L=p:L=L.next=p}else P=L=p;_={baseState:N.baseState,firstBaseUpdate:P,lastBaseUpdate:L,shared:N.shared,callbacks:N.callbacks},h.updateQueue=_;return}h=_.lastBaseUpdate,h===null?_.firstBaseUpdate=p:h.next=p,_.lastBaseUpdate=p}var eE=!1;function Sx(){if(eE){var h=bm;if(h!==null)throw h}}function Mx(h,p,_,N){eE=!1;var P=h.updateQueue;Tu=!1;var L=P.firstBaseUpdate,J=P.lastBaseUpdate,ge=P.shared.pending;if(ge!==null){P.shared.pending=null;var Le=ge,rt=Le.next;Le.next=null,J===null?L=rt:J.next=rt,J=Le;var bt=h.alternate;bt!==null&&(bt=bt.updateQueue,ge=bt.lastBaseUpdate,ge!==J&&(ge===null?bt.firstBaseUpdate=rt:ge.next=rt,bt.lastBaseUpdate=Le))}if(L!==null){var _t=P.baseState;J=0,bt=rt=Le=null,ge=L;do{var st=ge.lane&-536870913,dt=st!==ge.lane;if(dt?(On&st)===st:(N&st)===st){st!==0&&st===xm&&(eE=!0),bt!==null&&(bt=bt.next={lane:0,tag:ge.tag,payload:ge.payload,callback:null,next:null});e:{var qt=h,an=ge;st=p;var lr=_;switch(an.tag){case 1:if(qt=an.payload,typeof qt=="function"){_t=qt.call(lr,_t,st);break e}_t=qt;break e;case 3:qt.flags=qt.flags&-65537|128;case 0:if(qt=an.payload,st=typeof qt=="function"?qt.call(lr,_t,st):qt,st==null)break e;_t=f({},_t,st);break e;case 2:Tu=!0}}st=ge.callback,st!==null&&(h.flags|=64,dt&&(h.flags|=8192),dt=P.callbacks,dt===null?P.callbacks=[st]:dt.push(st))}else dt={lane:st,tag:ge.tag,payload:ge.payload,callback:ge.callback,next:null},bt===null?(rt=bt=dt,Le=_t):bt=bt.next=dt,J|=st;if(ge=ge.next,ge===null){if(ge=P.shared.pending,ge===null)break;dt=ge,ge=dt.next,dt.next=null,P.lastBaseUpdate=dt,P.shared.pending=null}}while(!0);bt===null&&(Le=_t),P.baseState=Le,P.firstBaseUpdate=rt,P.lastBaseUpdate=bt,L===null&&(P.shared.lanes=0),Du|=J,h.lanes=J,h.memoizedState=_t}}function II(h,p){if(typeof h!="function")throw Error(r(191,h));h.call(p)}function FI(h,p){var _=h.callbacks;if(_!==null)for(h.callbacks=null,h=0;h<_.length;h++)II(_[h],p)}var _m=z(null),uv=z(0);function UI(h,p){h=gc,ae(uv,h),ae(_m,p),gc=h|p.baseLanes}function tE(){ae(uv,gc),ae(_m,_m.current)}function nE(){gc=uv.current,G(_m),G(uv)}var ks=z(null),ao=null;function ku(h){var p=h.alternate;ae(oi,oi.current&1),ae(ks,h),ao===null&&(p===null||_m.current!==null||p.memoizedState!==null)&&(ao=h)}function rE(h){ae(oi,oi.current),ae(ks,h),ao===null&&(ao=h)}function zI(h){h.tag===22?(ae(oi,oi.current),ae(ks,h),ao===null&&(ao=h)):ju()}function ju(){ae(oi,oi.current),ae(ks,ks.current)}function js(h){G(ks),ao===h&&(ao=null),G(oi)}var oi=z(0);function dv(h){for(var p=h;p!==null;){if(p.tag===13){var _=p.memoizedState;if(_!==null&&(_=_.dehydrated,_===null||cT(_)||uT(_)))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 lc=0,vn=null,sr=null,mi=null,hv=!1,wm=!1,Sh=!1,fv=0,Nx=0,Sm=null,vie=0;function Qr(){throw Error(r(321))}function iE(h,p){if(p===null)return!1;for(var _=0;_L?L:8;var J=Y.T,ge={};Y.T=ge,yE(h,!1,p,_);try{var Le=P(),rt=Y.S;if(rt!==null&&rt(ge,Le),Le!==null&&typeof Le=="object"&&typeof Le.then=="function"){var bt=yie(Le,N);Tx(h,p,bt,Ds(h))}else Tx(h,p,N,Ds(h))}catch(_t){Tx(h,p,{then:function(){},status:"rejected",reason:_t},Ds())}finally{q.p=L,J!==null&&ge.types!==null&&(J.types=ge.types),Y.T=J}}function Nie(){}function xE(h,p,_,N){if(h.tag!==5)throw Error(r(476));var P=g5(h).queue;p5(h,P,p,Z,_===null?Nie:function(){return x5(h),_(N)})}function g5(h){var p=h.memoizedState;if(p!==null)return p;p={memoizedState:Z,baseState:Z,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cc,lastRenderedState:Z},next:null};var _={};return p.next={memoizedState:_,baseState:_,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cc,lastRenderedState:_},next:null},h.memoizedState=p,h=h.alternate,h!==null&&(h.memoizedState=p),p}function x5(h){var p=g5(h);p.next===null&&(p=h.alternate.memoizedState),Tx(h,p.next.queue,{},Ds())}function bE(){return la(Vx)}function b5(){return li().memoizedState}function y5(){return li().memoizedState}function Eie(h){for(var p=h.return;p!==null;){switch(p.tag){case 24:case 3:var _=Ds();h=Au(_);var N=Cu(p,h,_);N!==null&&(us(N,p,_),wx(N,p,_)),p={cache:qN()},h.payload=p;return}p=p.return}}function Tie(h,p,_){var N=Ds();_={lane:N,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null},yv(h)?_5(p,_):(_=LN(h,p,_,N),_!==null&&(us(_,h,N),w5(_,p,N)))}function v5(h,p,_){var N=Ds();Tx(h,p,_,N)}function Tx(h,p,_,N){var P={lane:N,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null};if(yv(h))_5(p,P);else{var L=h.alternate;if(h.lanes===0&&(L===null||L.lanes===0)&&(L=p.lastRenderedReducer,L!==null))try{var J=p.lastRenderedState,ge=L(J,_);if(P.hasEagerState=!0,P.eagerState=ge,As(ge,J))return Jy(h,p,P,0),br===null&&Zy(),!1}catch{}finally{}if(_=LN(h,p,P,N),_!==null)return us(_,h,N),w5(_,p,N),!0}return!1}function yE(h,p,_,N){if(N={lane:2,revertLane:QE(),gesture:null,action:N,hasEagerState:!1,eagerState:null,next:null},yv(h)){if(p)throw Error(r(479))}else p=LN(h,_,N,2),p!==null&&us(p,h,2)}function yv(h){var p=h.alternate;return h===vn||p!==null&&p===vn}function _5(h,p){wm=hv=!0;var _=h.pending;_===null?p.next=p:(p.next=_.next,_.next=p),h.pending=p}function w5(h,p,_){if((_&4194048)!==0){var N=p.lanes;N&=h.pendingLanes,_|=N,p.lanes=_,xt(h,_)}}var Ax={readContext:la,use:pv,useCallback:Qr,useContext:Qr,useEffect:Qr,useImperativeHandle:Qr,useLayoutEffect:Qr,useInsertionEffect:Qr,useMemo:Qr,useReducer:Qr,useRef:Qr,useState:Qr,useDebugValue:Qr,useDeferredValue:Qr,useTransition:Qr,useSyncExternalStore:Qr,useId:Qr,useHostTransitionStatus:Qr,useFormState:Qr,useActionState:Qr,useOptimistic:Qr,useMemoCache:Qr,useCacheRefresh:Qr};Ax.useEffectEvent=Qr;var S5={readContext:la,use:pv,useCallback:function(h,p){return za().memoizedState=[h,p===void 0?null:p],h},useContext:la,useEffect:s5,useImperativeHandle:function(h,p,_){_=_!=null?_.concat([h]):null,xv(4194308,4,u5.bind(null,p,h),_)},useLayoutEffect:function(h,p){return xv(4194308,4,h,p)},useInsertionEffect:function(h,p){xv(4,2,h,p)},useMemo:function(h,p){var _=za();p=p===void 0?null:p;var N=h();if(Sh){ie(!0);try{h()}finally{ie(!1)}}return _.memoizedState=[N,p],N},useReducer:function(h,p,_){var N=za();if(_!==void 0){var P=_(p);if(Sh){ie(!0);try{_(p)}finally{ie(!1)}}}else P=p;return N.memoizedState=N.baseState=P,h={pending:null,lanes:0,dispatch:null,lastRenderedReducer:h,lastRenderedState:P},N.queue=h,h=h.dispatch=Tie.bind(null,vn,h),[N.memoizedState,h]},useRef:function(h){var p=za();return h={current:h},p.memoizedState=h},useState:function(h){h=hE(h);var p=h.queue,_=v5.bind(null,vn,p);return p.dispatch=_,[h.memoizedState,_]},useDebugValue:pE,useDeferredValue:function(h,p){var _=za();return gE(_,h,p)},useTransition:function(){var h=hE(!1);return h=p5.bind(null,vn,h.queue,!0,!1),za().memoizedState=h,[!1,h]},useSyncExternalStore:function(h,p,_){var N=vn,P=za();if(Fn){if(_===void 0)throw Error(r(407));_=_()}else{if(_=p(),br===null)throw Error(r(349));(On&127)!==0||VI(N,p,_)}P.memoizedState=_;var L={value:_,getSnapshot:p};return P.queue=L,s5(WI.bind(null,N,L,h),[h]),N.flags|=2048,Mm(9,{destroy:void 0},GI.bind(null,N,L,_,p),null),_},useId:function(){var h=za(),p=br.identifierPrefix;if(Fn){var _=bl,N=xl;_=(N&~(1<<32-Ne(N)-1)).toString(32)+_,p="_"+p+"R_"+_,_=fv++,0<_&&(p+="H"+_.toString(32)),p+="_"}else _=vie++,p="_"+p+"r_"+_.toString(32)+"_";return h.memoizedState=p},useHostTransitionStatus:bE,useFormState:t5,useActionState:t5,useOptimistic:function(h){var p=za();p.memoizedState=p.baseState=h;var _={pending:null,lanes:0,dispatch:null,lastRenderedReducer:null,lastRenderedState:null};return p.queue=_,p=yE.bind(null,vn,!0,_),_.dispatch=p,[h,p]},useMemoCache:cE,useCacheRefresh:function(){return za().memoizedState=Eie.bind(null,vn)},useEffectEvent:function(h){var p=za(),_={impl:h};return p.memoizedState=_,function(){if((Yn&2)!==0)throw Error(r(440));return _.impl.apply(void 0,arguments)}}},vE={readContext:la,use:pv,useCallback:h5,useContext:la,useEffect:mE,useImperativeHandle:d5,useInsertionEffect:l5,useLayoutEffect:c5,useMemo:f5,useReducer:gv,useRef:a5,useState:function(){return gv(cc)},useDebugValue:pE,useDeferredValue:function(h,p){var _=li();return m5(_,sr.memoizedState,h,p)},useTransition:function(){var h=gv(cc)[0],p=li().memoizedState;return[typeof h=="boolean"?h:Ex(h),p]},useSyncExternalStore:HI,useId:b5,useHostTransitionStatus:bE,useFormState:n5,useActionState:n5,useOptimistic:function(h,p){var _=li();return XI(_,sr,h,p)},useMemoCache:cE,useCacheRefresh:y5};vE.useEffectEvent=o5;var M5={readContext:la,use:pv,useCallback:h5,useContext:la,useEffect:mE,useImperativeHandle:d5,useInsertionEffect:l5,useLayoutEffect:c5,useMemo:f5,useReducer:dE,useRef:a5,useState:function(){return dE(cc)},useDebugValue:pE,useDeferredValue:function(h,p){var _=li();return sr===null?gE(_,h,p):m5(_,sr.memoizedState,h,p)},useTransition:function(){var h=dE(cc)[0],p=li().memoizedState;return[typeof h=="boolean"?h:Ex(h),p]},useSyncExternalStore:HI,useId:b5,useHostTransitionStatus:bE,useFormState:i5,useActionState:i5,useOptimistic:function(h,p){var _=li();return sr!==null?XI(_,sr,h,p):(_.baseState=h,[h,_.queue.dispatch])},useMemoCache:cE,useCacheRefresh:y5};M5.useEffectEvent=o5;function _E(h,p,_,N){p=h.memoizedState,_=_(N,p),_=_==null?p:f({},p,_),h.memoizedState=_,h.lanes===0&&(h.updateQueue.baseState=_)}var wE={enqueueSetState:function(h,p,_){h=h._reactInternals;var N=Ds(),P=Au(N);P.payload=p,_!=null&&(P.callback=_),p=Cu(h,P,N),p!==null&&(us(p,h,N),wx(p,h,N))},enqueueReplaceState:function(h,p,_){h=h._reactInternals;var N=Ds(),P=Au(N);P.tag=1,P.payload=p,_!=null&&(P.callback=_),p=Cu(h,P,N),p!==null&&(us(p,h,N),wx(p,h,N))},enqueueForceUpdate:function(h,p){h=h._reactInternals;var _=Ds(),N=Au(_);N.tag=2,p!=null&&(N.callback=p),p=Cu(h,N,_),p!==null&&(us(p,h,_),wx(p,h,_))}};function N5(h,p,_,N,P,L,J){return h=h.stateNode,typeof h.shouldComponentUpdate=="function"?h.shouldComponentUpdate(N,L,J):p.prototype&&p.prototype.isPureReactComponent?!mx(_,N)||!mx(P,L):!0}function E5(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&&wE.enqueueReplaceState(p,p.state,null)}function Mh(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 P in h)_[P]===void 0&&(_[P]=h[P])}return _}function T5(h){Qy(h)}function A5(h){console.error(h)}function C5(h){Qy(h)}function vv(h,p){try{var _=h.onUncaughtError;_(p.value,{componentStack:p.stack})}catch(N){setTimeout(function(){throw N})}}function k5(h,p,_){try{var N=h.onCaughtError;N(_.value,{componentStack:_.stack,errorBoundary:p.tag===1?p.stateNode:null})}catch(P){setTimeout(function(){throw P})}}function SE(h,p,_){return _=Au(_),_.tag=3,_.payload={element:null},_.callback=function(){vv(h,p)},_}function j5(h){return h=Au(h),h.tag=3,h}function P5(h,p,_,N){var P=_.type.getDerivedStateFromError;if(typeof P=="function"){var L=N.value;h.payload=function(){return P(L)},h.callback=function(){k5(p,_,N)}}var J=_.stateNode;J!==null&&typeof J.componentDidCatch=="function"&&(h.callback=function(){k5(p,_,N),typeof P!="function"&&(Ou===null?Ou=new Set([this]):Ou.add(this));var ge=N.stack;this.componentDidCatch(N.value,{componentStack:ge!==null?ge:""})})}function Aie(h,p,_,N,P){if(_.flags|=32768,N!==null&&typeof N=="object"&&typeof N.then=="function"){if(p=_.alternate,p!==null&&gm(p,_,P,!0),_=ks.current,_!==null){switch(_.tag){case 31:case 13:return ao===null?Pv():_.alternate===null&&Zr===0&&(Zr=3),_.flags&=-257,_.flags|=65536,_.lanes=P,N===ov?_.flags|=16384:(p=_.updateQueue,p===null?_.updateQueue=new Set([N]):p.add(N),KE(h,N,P)),!1;case 22:return _.flags|=65536,N===ov?_.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)),KE(h,N,P)),!1}throw Error(r(435,_.tag))}return KE(h,N,P),Pv(),!1}if(Fn)return p=ks.current,p!==null?((p.flags&65536)===0&&(p.flags|=256),p.flags|=65536,p.lanes=P,N!==$N&&(h=Error(r(422),{cause:N}),xx(to(h,_)))):(N!==$N&&(p=Error(r(423),{cause:N}),xx(to(p,_))),h=h.current.alternate,h.flags|=65536,P&=-P,h.lanes|=P,N=to(N,_),P=SE(h.stateNode,N,P),JN(h,P),Zr!==4&&(Zr=2)),!1;var L=Error(r(520),{cause:N});if(L=to(L,_),Lx===null?Lx=[L]:Lx.push(L),Zr!==4&&(Zr=2),p===null)return!0;N=to(N,_),_=p;do{switch(_.tag){case 3:return _.flags|=65536,h=P&-P,_.lanes|=h,h=SE(_.stateNode,N,h),JN(_,h),!1;case 1:if(p=_.type,L=_.stateNode,(_.flags&128)===0&&(typeof p.getDerivedStateFromError=="function"||L!==null&&typeof L.componentDidCatch=="function"&&(Ou===null||!Ou.has(L))))return _.flags|=65536,P&=-P,_.lanes|=P,P=j5(P),P5(P,h,_,N),JN(_,P),!1}_=_.return}while(_!==null);return!1}var ME=Error(r(461)),pi=!1;function ca(h,p,_,N){p.child=h===null?LI(p,null,_,N):wh(p,h.child,_,N)}function R5(h,p,_,N,P){_=_.render;var L=p.ref;if("ref"in N){var J={};for(var ge in N)ge!=="ref"&&(J[ge]=N[ge])}else J=N;return bh(p),N=aE(h,p,_,J,L,P),ge=sE(),h!==null&&!pi?(oE(h,p,P),uc(h,p,P)):(Fn&&ge&&zN(p),p.flags|=1,ca(h,p,N,P),p.child)}function D5(h,p,_,N,P){if(h===null){var L=_.type;return typeof L=="function"&&!IN(L)&&L.defaultProps===void 0&&_.compare===null?(p.tag=15,p.type=L,O5(h,p,L,N,P)):(h=tv(_.type,null,N,p,p.mode,P),h.ref=p.ref,h.return=p,p.child=h)}if(L=h.child,!PE(h,P)){var J=L.memoizedProps;if(_=_.compare,_=_!==null?_:mx,_(J,N)&&h.ref===p.ref)return uc(h,p,P)}return p.flags|=1,h=ic(L,N),h.ref=p.ref,h.return=p,p.child=h}function O5(h,p,_,N,P){if(h!==null){var L=h.memoizedProps;if(mx(L,N)&&h.ref===p.ref)if(pi=!1,p.pendingProps=N=L,PE(h,P))(h.flags&131072)!==0&&(pi=!0);else return p.lanes=h.lanes,uc(h,p,P)}return NE(h,p,_,N,P)}function L5(h,p,_,N){var P=N.children,L=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(L=L!==null?L.baseLanes|_:_,h!==null){for(N=p.child=h.child,P=0;N!==null;)P=P|N.lanes|N.childLanes,N=N.sibling;N=P&~L}else N=0,p.child=null;return I5(h,p,L,_,N)}if((_&536870912)!==0)p.memoizedState={baseLanes:0,cachePool:null},h!==null&&av(p,L!==null?L.cachePool:null),L!==null?UI(p,L):tE(),zI(p);else return N=p.lanes=536870912,I5(h,p,L!==null?L.baseLanes|_:_,_,N)}else L!==null?(av(p,L.cachePool),UI(p,L),ju(),p.memoizedState=null):(h!==null&&av(p,null),tE(),ju());return ca(h,p,P,_),p.child}function Cx(h,p){return h!==null&&h.tag===22||p.stateNode!==null||(p.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),p.sibling}function I5(h,p,_,N,P){var L=XN();return L=L===null?null:{parent:fi._currentValue,pool:L},p.memoizedState={baseLanes:_,cachePool:L},h!==null&&av(p,null),tE(),zI(p),h!==null&&gm(h,p,N,!0),p.childLanes=P,null}function _v(h,p){return p=Sv({mode:p.mode,children:p.children},h.mode),p.ref=h.ref,h.child=p,p.return=h,p}function F5(h,p,_){return wh(p,h.child,null,_),h=_v(p,p.pendingProps),h.flags|=2,js(p),p.memoizedState=null,h}function Cie(h,p,_){var N=p.pendingProps,P=(p.flags&128)!==0;if(p.flags&=-129,h===null){if(Fn){if(N.mode==="hidden")return h=_v(p,N),p.lanes=536870912,Cx(null,h);if(rE(p),(h=Ar)?(h=YF(h,io),h=h!==null&&h.data==="&"?h:null,h!==null&&(p.memoizedState={dehydrated:h,treeContext:Su!==null?{id:xl,overflow:bl}:null,retryLane:536870912,hydrationErrors:null},_=_I(h),_.return=p,p.child=_,oa=p,Ar=null)):h=null,h===null)throw Nu(p);return p.lanes=536870912,null}return _v(p,N)}var L=h.memoizedState;if(L!==null){var J=L.dehydrated;if(rE(p),P)if(p.flags&256)p.flags&=-257,p=F5(h,p,_);else if(p.memoizedState!==null)p.child=h.child,p.flags|=128,p=null;else throw Error(r(558));else if(pi||gm(h,p,_,!1),P=(_&h.childLanes)!==0,pi||P){if(N=br,N!==null&&(J=Kt(N,_),J!==0&&J!==L.retryLane))throw L.retryLane=J,mh(h,J),us(N,h,J),ME;Pv(),p=F5(h,p,_)}else h=L.treeContext,Ar=so(J.nextSibling),oa=p,Fn=!0,Mu=null,io=!1,h!==null&&MI(p,h),p=_v(p,N),p.flags|=4096;return p}return h=ic(h.child,{mode:N.mode,children:N.children}),h.ref=p.ref,p.child=h,h.return=p,h}function wv(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 NE(h,p,_,N,P){return bh(p),_=aE(h,p,_,N,void 0,P),N=sE(),h!==null&&!pi?(oE(h,p,P),uc(h,p,P)):(Fn&&N&&zN(p),p.flags|=1,ca(h,p,_,P),p.child)}function U5(h,p,_,N,P,L){return bh(p),p.updateQueue=null,_=$I(p,N,_,P),BI(h),N=sE(),h!==null&&!pi?(oE(h,p,L),uc(h,p,L)):(Fn&&N&&zN(p),p.flags|=1,ca(h,p,_,L),p.child)}function z5(h,p,_,N,P){if(bh(p),p.stateNode===null){var L=hm,J=_.contextType;typeof J=="object"&&J!==null&&(L=la(J)),L=new _(N,L),p.memoizedState=L.state!==null&&L.state!==void 0?L.state:null,L.updater=wE,p.stateNode=L,L._reactInternals=p,L=p.stateNode,L.props=N,L.state=p.memoizedState,L.refs={},QN(p),J=_.contextType,L.context=typeof J=="object"&&J!==null?la(J):hm,L.state=p.memoizedState,J=_.getDerivedStateFromProps,typeof J=="function"&&(_E(p,_,J,N),L.state=p.memoizedState),typeof _.getDerivedStateFromProps=="function"||typeof L.getSnapshotBeforeUpdate=="function"||typeof L.UNSAFE_componentWillMount!="function"&&typeof L.componentWillMount!="function"||(J=L.state,typeof L.componentWillMount=="function"&&L.componentWillMount(),typeof L.UNSAFE_componentWillMount=="function"&&L.UNSAFE_componentWillMount(),J!==L.state&&wE.enqueueReplaceState(L,L.state,null),Mx(p,N,L,P),Sx(),L.state=p.memoizedState),typeof L.componentDidMount=="function"&&(p.flags|=4194308),N=!0}else if(h===null){L=p.stateNode;var ge=p.memoizedProps,Le=Mh(_,ge);L.props=Le;var rt=L.context,bt=_.contextType;J=hm,typeof bt=="object"&&bt!==null&&(J=la(bt));var _t=_.getDerivedStateFromProps;bt=typeof _t=="function"||typeof L.getSnapshotBeforeUpdate=="function",ge=p.pendingProps!==ge,bt||typeof L.UNSAFE_componentWillReceiveProps!="function"&&typeof L.componentWillReceiveProps!="function"||(ge||rt!==J)&&E5(p,L,N,J),Tu=!1;var st=p.memoizedState;L.state=st,Mx(p,N,L,P),Sx(),rt=p.memoizedState,ge||st!==rt||Tu?(typeof _t=="function"&&(_E(p,_,_t,N),rt=p.memoizedState),(Le=Tu||N5(p,_,Le,N,st,rt,J))?(bt||typeof L.UNSAFE_componentWillMount!="function"&&typeof L.componentWillMount!="function"||(typeof L.componentWillMount=="function"&&L.componentWillMount(),typeof L.UNSAFE_componentWillMount=="function"&&L.UNSAFE_componentWillMount()),typeof L.componentDidMount=="function"&&(p.flags|=4194308)):(typeof L.componentDidMount=="function"&&(p.flags|=4194308),p.memoizedProps=N,p.memoizedState=rt),L.props=N,L.state=rt,L.context=J,N=Le):(typeof L.componentDidMount=="function"&&(p.flags|=4194308),N=!1)}else{L=p.stateNode,ZN(h,p),J=p.memoizedProps,bt=Mh(_,J),L.props=bt,_t=p.pendingProps,st=L.context,rt=_.contextType,Le=hm,typeof rt=="object"&&rt!==null&&(Le=la(rt)),ge=_.getDerivedStateFromProps,(rt=typeof ge=="function"||typeof L.getSnapshotBeforeUpdate=="function")||typeof L.UNSAFE_componentWillReceiveProps!="function"&&typeof L.componentWillReceiveProps!="function"||(J!==_t||st!==Le)&&E5(p,L,N,Le),Tu=!1,st=p.memoizedState,L.state=st,Mx(p,N,L,P),Sx();var dt=p.memoizedState;J!==_t||st!==dt||Tu||h!==null&&h.dependencies!==null&&rv(h.dependencies)?(typeof ge=="function"&&(_E(p,_,ge,N),dt=p.memoizedState),(bt=Tu||N5(p,_,bt,N,st,dt,Le)||h!==null&&h.dependencies!==null&&rv(h.dependencies))?(rt||typeof L.UNSAFE_componentWillUpdate!="function"&&typeof L.componentWillUpdate!="function"||(typeof L.componentWillUpdate=="function"&&L.componentWillUpdate(N,dt,Le),typeof L.UNSAFE_componentWillUpdate=="function"&&L.UNSAFE_componentWillUpdate(N,dt,Le)),typeof L.componentDidUpdate=="function"&&(p.flags|=4),typeof L.getSnapshotBeforeUpdate=="function"&&(p.flags|=1024)):(typeof L.componentDidUpdate!="function"||J===h.memoizedProps&&st===h.memoizedState||(p.flags|=4),typeof L.getSnapshotBeforeUpdate!="function"||J===h.memoizedProps&&st===h.memoizedState||(p.flags|=1024),p.memoizedProps=N,p.memoizedState=dt),L.props=N,L.state=dt,L.context=Le,N=bt):(typeof L.componentDidUpdate!="function"||J===h.memoizedProps&&st===h.memoizedState||(p.flags|=4),typeof L.getSnapshotBeforeUpdate!="function"||J===h.memoizedProps&&st===h.memoizedState||(p.flags|=1024),N=!1)}return L=N,wv(h,p),N=(p.flags&128)!==0,L||N?(L=p.stateNode,_=N&&typeof _.getDerivedStateFromError!="function"?null:L.render(),p.flags|=1,h!==null&&N?(p.child=wh(p,h.child,null,P),p.child=wh(p,null,_,P)):ca(h,p,_,P),p.memoizedState=L.state,h=p.child):h=uc(h,p,P),h}function B5(h,p,_,N){return gh(),p.flags|=256,ca(h,p,_,N),p.child}var EE={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function TE(h){return{baseLanes:h,cachePool:kI()}}function AE(h,p,_){return h=h!==null?h.childLanes&~_:0,p&&(h|=Rs),h}function $5(h,p,_){var N=p.pendingProps,P=!1,L=(p.flags&128)!==0,J;if((J=L)||(J=h!==null&&h.memoizedState===null?!1:(oi.current&2)!==0),J&&(P=!0,p.flags&=-129),J=(p.flags&32)!==0,p.flags&=-33,h===null){if(Fn){if(P?ku(p):ju(),(h=Ar)?(h=YF(h,io),h=h!==null&&h.data!=="&"?h:null,h!==null&&(p.memoizedState={dehydrated:h,treeContext:Su!==null?{id:xl,overflow:bl}:null,retryLane:536870912,hydrationErrors:null},_=_I(h),_.return=p,p.child=_,oa=p,Ar=null)):h=null,h===null)throw Nu(p);return uT(h)?p.lanes=32:p.lanes=536870912,null}var ge=N.children;return N=N.fallback,P?(ju(),P=p.mode,ge=Sv({mode:"hidden",children:ge},P),N=ph(N,P,_,null),ge.return=p,N.return=p,ge.sibling=N,p.child=ge,N=p.child,N.memoizedState=TE(_),N.childLanes=AE(h,J,_),p.memoizedState=EE,Cx(null,N)):(ku(p),CE(p,ge))}var Le=h.memoizedState;if(Le!==null&&(ge=Le.dehydrated,ge!==null)){if(L)p.flags&256?(ku(p),p.flags&=-257,p=kE(h,p,_)):p.memoizedState!==null?(ju(),p.child=h.child,p.flags|=128,p=null):(ju(),ge=N.fallback,P=p.mode,N=Sv({mode:"visible",children:N.children},P),ge=ph(ge,P,_,null),ge.flags|=2,N.return=p,ge.return=p,N.sibling=ge,p.child=N,wh(p,h.child,null,_),N=p.child,N.memoizedState=TE(_),N.childLanes=AE(h,J,_),p.memoizedState=EE,p=Cx(null,N));else if(ku(p),uT(ge)){if(J=ge.nextSibling&&ge.nextSibling.dataset,J)var rt=J.dgst;J=rt,N=Error(r(419)),N.stack="",N.digest=J,xx({value:N,source:null,stack:null}),p=kE(h,p,_)}else if(pi||gm(h,p,_,!1),J=(_&h.childLanes)!==0,pi||J){if(J=br,J!==null&&(N=Kt(J,_),N!==0&&N!==Le.retryLane))throw Le.retryLane=N,mh(h,N),us(J,h,N),ME;cT(ge)||Pv(),p=kE(h,p,_)}else cT(ge)?(p.flags|=192,p.child=h.child,p=null):(h=Le.treeContext,Ar=so(ge.nextSibling),oa=p,Fn=!0,Mu=null,io=!1,h!==null&&MI(p,h),p=CE(p,N.children),p.flags|=4096);return p}return P?(ju(),ge=N.fallback,P=p.mode,Le=h.child,rt=Le.sibling,N=ic(Le,{mode:"hidden",children:N.children}),N.subtreeFlags=Le.subtreeFlags&65011712,rt!==null?ge=ic(rt,ge):(ge=ph(ge,P,_,null),ge.flags|=2),ge.return=p,N.return=p,N.sibling=ge,p.child=N,Cx(null,N),N=p.child,ge=h.child.memoizedState,ge===null?ge=TE(_):(P=ge.cachePool,P!==null?(Le=fi._currentValue,P=P.parent!==Le?{parent:Le,pool:Le}:P):P=kI(),ge={baseLanes:ge.baseLanes|_,cachePool:P}),N.memoizedState=ge,N.childLanes=AE(h,J,_),p.memoizedState=EE,Cx(h.child,N)):(ku(p),_=h.child,h=_.sibling,_=ic(_,{mode:"visible",children:N.children}),_.return=p,_.sibling=null,h!==null&&(J=p.deletions,J===null?(p.deletions=[h],p.flags|=16):J.push(h)),p.child=_,p.memoizedState=null,_)}function CE(h,p){return p=Sv({mode:"visible",children:p},h.mode),p.return=h,h.child=p}function Sv(h,p){return h=Cs(22,h,null,p),h.lanes=0,h}function kE(h,p,_){return wh(p,h.child,null,_),h=CE(p,p.pendingProps.children),h.flags|=2,p.memoizedState=null,h}function H5(h,p,_){h.lanes|=p;var N=h.alternate;N!==null&&(N.lanes|=p),GN(h.return,p,_)}function jE(h,p,_,N,P,L){var J=h.memoizedState;J===null?h.memoizedState={isBackwards:p,rendering:null,renderingStartTime:0,last:N,tail:_,tailMode:P,treeForkCount:L}:(J.isBackwards=p,J.rendering=null,J.renderingStartTime=0,J.last=N,J.tail=_,J.tailMode=P,J.treeForkCount=L)}function V5(h,p,_){var N=p.pendingProps,P=N.revealOrder,L=N.tail;N=N.children;var J=oi.current,ge=(J&2)!==0;if(ge?(J=J&1|2,p.flags|=128):J&=1,ae(oi,J),ca(h,p,N,_),N=Fn?gx:0,!ge&&h!==null&&(h.flags&128)!==0)e:for(h=p.child;h!==null;){if(h.tag===13)h.memoizedState!==null&&H5(h,_,p);else if(h.tag===19)H5(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(P){case"forwards":for(_=p.child,P=null;_!==null;)h=_.alternate,h!==null&&dv(h)===null&&(P=_),_=_.sibling;_=P,_===null?(P=p.child,p.child=null):(P=_.sibling,_.sibling=null),jE(p,!1,P,_,L,N);break;case"backwards":case"unstable_legacy-backwards":for(_=null,P=p.child,p.child=null;P!==null;){if(h=P.alternate,h!==null&&dv(h)===null){p.child=P;break}h=P.sibling,P.sibling=_,_=P,P=h}jE(p,!0,_,null,L,N);break;case"together":jE(p,!1,null,null,void 0,N);break;default:p.memoizedState=null}return p.child}function uc(h,p,_){if(h!==null&&(p.dependencies=h.dependencies),Du|=p.lanes,(_&p.childLanes)===0)if(h!==null){if(gm(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,_=ic(h,h.pendingProps),p.child=_,_.return=p;h.sibling!==null;)h=h.sibling,_=_.sibling=ic(h,h.pendingProps),_.return=p;_.sibling=null}return p.child}function PE(h,p){return(h.lanes&p)!==0?!0:(h=h.dependencies,!!(h!==null&&rv(h)))}function kie(h,p,_){switch(p.tag){case 3:Ee(p,p.stateNode.containerInfo),Eu(p,fi,h.memoizedState.cache),gh();break;case 27:case 5:Me(p);break;case 4:Ee(p,p.stateNode.containerInfo);break;case 10:Eu(p,p.type,p.memoizedProps.value);break;case 31:if(p.memoizedState!==null)return p.flags|=128,rE(p),null;break;case 13:var N=p.memoizedState;if(N!==null)return N.dehydrated!==null?(ku(p),p.flags|=128,null):(_&p.child.childLanes)!==0?$5(h,p,_):(ku(p),h=uc(h,p,_),h!==null?h.sibling:null);ku(p);break;case 19:var P=(h.flags&128)!==0;if(N=(_&p.childLanes)!==0,N||(gm(h,p,_,!1),N=(_&p.childLanes)!==0),P){if(N)return V5(h,p,_);p.flags|=128}if(P=p.memoizedState,P!==null&&(P.rendering=null,P.tail=null,P.lastEffect=null),ae(oi,oi.current),N)break;return null;case 22:return p.lanes=0,L5(h,p,_,p.pendingProps);case 24:Eu(p,fi,h.memoizedState.cache)}return uc(h,p,_)}function G5(h,p,_){if(h!==null)if(h.memoizedProps!==p.pendingProps)pi=!0;else{if(!PE(h,_)&&(p.flags&128)===0)return pi=!1,kie(h,p,_);pi=(h.flags&131072)!==0}else pi=!1,Fn&&(p.flags&1048576)!==0&&SI(p,gx,p.index);switch(p.lanes=0,p.tag){case 16:e:{var N=p.pendingProps;if(h=vh(p.elementType),p.type=h,typeof h=="function")IN(h)?(N=Mh(h,N),p.tag=1,p=z5(null,p,h,N,_)):(p.tag=0,p=NE(null,p,h,N,_));else{if(h!=null){var P=h.$$typeof;if(P===A){p.tag=11,p=R5(null,p,h,N,_);break e}else if(P===E){p.tag=14,p=D5(null,p,h,N,_);break e}}throw p=j(h)||h,Error(r(306,p,""))}}return p;case 0:return NE(h,p,p.type,p.pendingProps,_);case 1:return N=p.type,P=Mh(N,p.pendingProps),z5(h,p,N,P,_);case 3:e:{if(Ee(p,p.stateNode.containerInfo),h===null)throw Error(r(387));N=p.pendingProps;var L=p.memoizedState;P=L.element,ZN(h,p),Mx(p,N,null,_);var J=p.memoizedState;if(N=J.cache,Eu(p,fi,N),N!==L.cache&&WN(p,[fi],_,!0),Sx(),N=J.element,L.isDehydrated)if(L={element:N,isDehydrated:!1,cache:J.cache},p.updateQueue.baseState=L,p.memoizedState=L,p.flags&256){p=B5(h,p,N,_);break e}else if(N!==P){P=to(Error(r(424)),p),xx(P),p=B5(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(Ar=so(h.firstChild),oa=p,Fn=!0,Mu=null,io=!0,_=LI(p,null,N,_),p.child=_;_;)_.flags=_.flags&-3|4096,_=_.sibling}else{if(gh(),N===P){p=uc(h,p,_);break e}ca(h,p,N,_)}p=p.child}return p;case 26:return wv(h,p),h===null?(_=nU(p.type,null,p.pendingProps,null))?p.memoizedState=_:Fn||(_=p.type,h=p.pendingProps,N=Uv(me.current).createElement(_),N[Yt]=p,N[Er]=h,ua(N,_,h),Be(N),p.stateNode=N):p.memoizedState=nU(p.type,h.memoizedProps,p.pendingProps,h.memoizedState),null;case 27:return Me(p),h===null&&Fn&&(N=p.stateNode=JF(p.type,p.pendingProps,me.current),oa=p,io=!0,P=Ar,Uu(p.type)?(dT=P,Ar=so(N.firstChild)):Ar=P),ca(h,p,p.pendingProps.children,_),wv(h,p),h===null&&(p.flags|=4194304),p.child;case 5:return h===null&&Fn&&((P=N=Ar)&&(N=sae(N,p.type,p.pendingProps,io),N!==null?(p.stateNode=N,oa=p,Ar=so(N.firstChild),io=!1,P=!0):P=!1),P||Nu(p)),Me(p),P=p.type,L=p.pendingProps,J=h!==null?h.memoizedProps:null,N=L.children,sT(P,L)?N=null:J!==null&&sT(P,J)&&(p.flags|=32),p.memoizedState!==null&&(P=aE(h,p,_ie,null,null,_),Vx._currentValue=P),wv(h,p),ca(h,p,N,_),p.child;case 6:return h===null&&Fn&&((h=_=Ar)&&(_=oae(_,p.pendingProps,io),_!==null?(p.stateNode=_,oa=p,Ar=null,h=!0):h=!1),h||Nu(p)),null;case 13:return $5(h,p,_);case 4:return Ee(p,p.stateNode.containerInfo),N=p.pendingProps,h===null?p.child=wh(p,null,N,_):ca(h,p,N,_),p.child;case 11:return R5(h,p,p.type,p.pendingProps,_);case 7:return ca(h,p,p.pendingProps,_),p.child;case 8:return ca(h,p,p.pendingProps.children,_),p.child;case 12:return ca(h,p,p.pendingProps.children,_),p.child;case 10:return N=p.pendingProps,Eu(p,p.type,N.value),ca(h,p,N.children,_),p.child;case 9:return P=p.type._context,N=p.pendingProps.children,bh(p),P=la(P),N=N(P),p.flags|=1,ca(h,p,N,_),p.child;case 14:return D5(h,p,p.type,p.pendingProps,_);case 15:return O5(h,p,p.type,p.pendingProps,_);case 19:return V5(h,p,_);case 31:return Cie(h,p,_);case 22:return L5(h,p,_,p.pendingProps);case 24:return bh(p),N=la(fi),h===null?(P=XN(),P===null&&(P=br,L=qN(),P.pooledCache=L,L.refCount++,L!==null&&(P.pooledCacheLanes|=_),P=L),p.memoizedState={parent:N,cache:P},QN(p),Eu(p,fi,P)):((h.lanes&_)!==0&&(ZN(h,p),Mx(p,null,null,_),Sx()),P=h.memoizedState,L=p.memoizedState,P.parent!==N?(P={parent:N,cache:N},p.memoizedState=P,p.lanes===0&&(p.memoizedState=p.updateQueue.baseState=P),Eu(p,fi,N)):(N=L.cache,Eu(p,fi,N),N!==P.cache&&WN(p,[fi],_,!0))),ca(h,p,p.pendingProps.children,_),p.child;case 29:throw p.pendingProps}throw Error(r(156,p.tag))}function dc(h){h.flags|=4}function RE(h,p,_,N,P){if((p=(h.mode&32)!==0)&&(p=!1),p){if(h.flags|=16777216,(P&335544128)===P)if(h.stateNode.complete)h.flags|=8192;else if(bF())h.flags|=8192;else throw _h=ov,YN}else h.flags&=-16777217}function W5(h,p){if(p.type!=="stylesheet"||(p.state.loading&4)!==0)h.flags&=-16777217;else if(h.flags|=16777216,!oU(p))if(bF())h.flags|=8192;else throw _h=ov,YN}function Mv(h,p){p!==null&&(h.flags|=4),h.flags&16384&&(p=h.tag!==22?kt():536870912,h.lanes|=p,Am|=p)}function kx(h,p){if(!Fn)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 Cr(h){var p=h.alternate!==null&&h.alternate.child===h.child,_=0,N=0;if(p)for(var P=h.child;P!==null;)_|=P.lanes|P.childLanes,N|=P.subtreeFlags&65011712,N|=P.flags&65011712,P.return=h,P=P.sibling;else for(P=h.child;P!==null;)_|=P.lanes|P.childLanes,N|=P.subtreeFlags,N|=P.flags,P.return=h,P=P.sibling;return h.subtreeFlags|=N,h.childLanes=_,p}function jie(h,p,_){var N=p.pendingProps;switch(BN(p),p.tag){case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Cr(p),null;case 1:return Cr(p),null;case 3:return _=p.stateNode,N=null,h!==null&&(N=h.memoizedState.cache),p.memoizedState.cache!==N&&(p.flags|=2048),oc(fi),pe(),_.pendingContext&&(_.context=_.pendingContext,_.pendingContext=null),(h===null||h.child===null)&&(pm(p)?dc(p):h===null||h.memoizedState.isDehydrated&&(p.flags&256)===0||(p.flags|=1024,HN())),Cr(p),null;case 26:var P=p.type,L=p.memoizedState;return h===null?(dc(p),L!==null?(Cr(p),W5(p,L)):(Cr(p),RE(p,P,null,N,_))):L?L!==h.memoizedState?(dc(p),Cr(p),W5(p,L)):(Cr(p),p.flags&=-16777217):(h=h.memoizedProps,h!==N&&dc(p),Cr(p),RE(p,P,h,N,_)),null;case 27:if(ve(p),_=me.current,P=p.type,h!==null&&p.stateNode!=null)h.memoizedProps!==N&&dc(p);else{if(!N){if(p.stateNode===null)throw Error(r(166));return Cr(p),null}h=se.current,pm(p)?NI(p):(h=JF(P,N,_),p.stateNode=h,dc(p))}return Cr(p),null;case 5:if(ve(p),P=p.type,h!==null&&p.stateNode!=null)h.memoizedProps!==N&&dc(p);else{if(!N){if(p.stateNode===null)throw Error(r(166));return Cr(p),null}if(L=se.current,pm(p))NI(p);else{var J=Uv(me.current);switch(L){case 1:L=J.createElementNS("http://www.w3.org/2000/svg",P);break;case 2:L=J.createElementNS("http://www.w3.org/1998/Math/MathML",P);break;default:switch(P){case"svg":L=J.createElementNS("http://www.w3.org/2000/svg",P);break;case"math":L=J.createElementNS("http://www.w3.org/1998/Math/MathML",P);break;case"script":L=J.createElement("div"),L.innerHTML=" +