From 3d1360df364173ab809db5a0d5626b30fa78b29b Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 13:03:48 +0800 Subject: [PATCH 001/320] refactor: provider-aware LLM endpoint configuration and factory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 整改记录 #1/#2/#4: - LLM 配置模型支持 api_base/api_key/api_key_env,凭证校验认可配置内凭证 - _resolve_endpoint 透传端点字段,fallback 自动继承父节点端点 - 工厂收敛: get_provider_llm/get_default_deployment/get_default_deployment_llm, 删除 get_google_llm 等硬编码 Google 调用点, 全部改为配置继承 - 无 Google Key 时出厂默认为空(不指定任何端点), 解析时报清晰配置指引错误 - load_jsonc 注释剥离改为字符串感知(URL 中 // 不再被截断), engine.py 委托统一实现 - .env.example 补充端点字段与优先级说明 详见 changelogs.md #1 #2 #4 --- .env.example | 5 ++ artemis/agents/explorer/run_setup.py | 2 +- artemis/agents/flash/runner.py | 4 +- artemis/agents/flash/summarizer.py | 16 ++-- artemis/config/core/engine.py | 10 +-- artemis/config/llm.py | 118 ++++++++++++++++++++------- artemis/memory/chunking.py | 10 +-- artemis/services/llm.py | 117 ++++++++++++++++++++++++-- third_party/mobile_use/config/llm.py | 50 +++++++++--- third_party/mobile_use/utils/file.py | 18 +++- 10 files changed, 279 insertions(+), 71 deletions(-) diff --git a/.env.example b/.env.example index 8b23d0a53..3515a13ad 100644 --- a/.env.example +++ b/.env.example @@ -12,6 +12,11 @@ ANTHROPIC_API_KEY= OPEN_ROUTER_API_KEY= XAI_API_KEY= +# Custom endpoints: every node in config/artemis.jsonc (default/nodes/presets) +# accepts "api_base", "api_key" and "api_key_env". Priority: +# config api_base > OPENAI_BASE_URL below > provider official endpoint +# OPENAI_BASE_URL=http://127.0.0.1:1234/v1 + # Google Cloud Vision OCR (Optional - for advanced OCR processing) OCR_API_KEY= diff --git a/artemis/agents/explorer/run_setup.py b/artemis/agents/explorer/run_setup.py index a25c81feb..170cf6de5 100644 --- a/artemis/agents/explorer/run_setup.py +++ b/artemis/agents/explorer/run_setup.py @@ -225,7 +225,7 @@ def _resolve_model_params(self) -> tuple: fallback_model = None thinking_level = None if llm_cfg: - model_name = llm_cfg.model + model_name = llm_cfg.model or DEFAULT_EXPLORER_MODEL if "/" in model_name: model_name = model_name.split("/")[-1] if getattr(llm_cfg, "temperature", None) is not None: diff --git a/artemis/agents/flash/runner.py b/artemis/agents/flash/runner.py index 3ea3f6865..f57d45941 100644 --- a/artemis/agents/flash/runner.py +++ b/artemis/agents/flash/runner.py @@ -83,7 +83,7 @@ from artemis.services.llm import ( RobustChatModelWrapper, acomplete, - get_google_llm, + get_default_deployment_llm, get_llm, invoke_llm_with_timeout_message, ) @@ -284,7 +284,7 @@ def _init_llm(self): except Exception as e: logger.warning(f"Failed to get operator LLM from config, using default: {e}") - return RobustChatModelWrapper(get_google_llm(model_name="gemini-2.5-flash"), self.ctx) + return RobustChatModelWrapper(get_default_deployment_llm(), self.ctx) def _render_system_prompt(self, tools_declaration: list) -> str: """Renders the system prompt from the flash_runner.md template. diff --git a/artemis/agents/flash/summarizer.py b/artemis/agents/flash/summarizer.py index 5b8a3cf98..03606c2cd 100644 --- a/artemis/agents/flash/summarizer.py +++ b/artemis/agents/flash/summarizer.py @@ -36,7 +36,11 @@ from artemis.context import ArtemisContext from artemis.memory.step_memory import JobKey, StepMemoryService -from artemis.services.llm import RobustChatModelWrapper, get_google_llm, get_llm +from artemis.services.llm import ( + RobustChatModelWrapper, + get_default_deployment_llm, + get_llm, +) from artemis.services.token_meter import record_llm_usage from artemis.utils.task_tree import format_actions_clean from artemis.utils.visualization import draw_action_overlay_on_image @@ -166,11 +170,13 @@ def __init__( self._model_name = target_model try: if model_name: - self._llm = get_google_llm(model_name=target_model, temperature=0.0) + self._llm = get_default_deployment_llm( + model_name=target_model, temperature=0.0 + ) else: - self._llm = get_llm(ctx, name="summarizer", is_utils=True) + self._llm = get_llm(ctx, name="summarizer") except Exception: - self._llm = get_google_llm(model_name=target_model, temperature=0.0) + self._llm = get_default_deployment_llm(model_name=target_model, temperature=0.0) try: configured = getattr(self._llm, "model", None) or getattr(self._llm, "model_name", None) if isinstance(configured, str) and configured: @@ -341,7 +347,7 @@ def _meter_lens_call(self, response: Any) -> None: """Meter one raw-model lens call as an ``llm_usage`` trace, best-effort. Gateway-wrapped models already meter at the wrapper exit; only the raw - ``get_google_llm`` bypass needs explicit metering here. Lens prompts + ``get_default_deployment_llm`` bypass needs explicit metering here. Lens prompts are tiny and must not overwrite the session's ``last_prompt_tokens`` (the compaction thresholds' live context base), hence ``update_last_prompt=False``. diff --git a/artemis/config/core/engine.py b/artemis/config/core/engine.py index 656c9d5ed..02d83e944 100644 --- a/artemis/config/core/engine.py +++ b/artemis/config/core/engine.py @@ -30,15 +30,9 @@ def _strip_json_comments(text: str) -> str: """Strip // and /* */ comments from JSONC text while preserving string literals.""" - pattern = r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"' + from third_party.mobile_use.utils.file import strip_json_comments - def replacer(match: re.Match) -> str: - s = match.group(0) - if s.startswith("/"): - return "" - return s - - return re.sub(pattern, replacer, text, flags=re.DOTALL | re.MULTILINE) + return strip_json_comments(text) def _deep_merge(base: dict[str, Any], override: dict[str, Any]) -> dict[str, Any]: diff --git a/artemis/config/llm.py b/artemis/config/llm.py index 641d2e198..19577c970 100644 --- a/artemis/config/llm.py +++ b/artemis/config/llm.py @@ -14,6 +14,7 @@ """LLM provider, model hierarchy, fallback chaining, and configuration loaders.""" +import os from pathlib import Path from typing import Any @@ -23,6 +24,7 @@ AgentNode, ) from artemis.config.paths import ROOT_DIR, get_config_path +from artemis.config.settings import settings from artemis.utils.cython_compat import CyFunctionDetector from third_party.mobile_use.config import llm as base_llm_config from third_party.mobile_use.config.llm import ( @@ -39,7 +41,18 @@ logger = get_logger(__name__) +#: Built-in endpoint used when artemis.jsonc has no usable "default" entry. +FACTORY_DEFAULT_MODEL_CFG: dict[str, Any] = { + "provider": "google", + "model": "gemini-3.8-flash", + "fallback": { + "provider": "google", + "model": "gemini-3.7-flash", + }, +} + __all__ = [ + "FACTORY_DEFAULT_MODEL_CFG", "LLM", "AgentNodeWithFallback", "LLMUtilsNodeWithFallback", @@ -51,24 +64,64 @@ "get_default_llm_config", "initialize_llm_config", "lightweight_judge_default", + "load_default_model_cfg", "load_llm_config_override", "parse_llm_config", "validate_vertex_ai_credentials", ] +def _google_credentials_present() -> bool: + """Whether Google/Gemini credentials exist for the factory default endpoint.""" + return bool( + settings.GOOGLE_API_KEY + or os.environ.get("GEMINI_API_KEY") + or os.environ.get("GOOGLE_API_KEY") + ) + + +def _factory_default_cfg() -> dict[str, Any]: + """Factory default endpoint, or an empty one when it cannot work. + + The built-in default targets Google's official endpoint; without Google + credentials the deployment default stays empty (no endpoint specified) + and must be configured explicitly. + """ + if _google_credentials_present(): + return dict(FACTORY_DEFAULT_MODEL_CFG) + return {} + + def lightweight_judge_default() -> "LLMWithFallback": """Factory default for the lightweight judge nodes (pixel safety net and - planner validation): a flash-lite model at temperature 0.""" - return LLMWithFallback( - provider="google", - model="gemini-3.5-flash-lite", - temperature=0.0, - fallback=LLM( + planner validation): a flash-lite model at temperature 0. Without Google + credentials the judges inherit the deployment default endpoint instead.""" + if _google_credentials_present(): + return LLMWithFallback( provider="google", - model="gemini-3.1-flash-lite", + model="gemini-3.5-flash-lite", + temperature=0.0, + fallback=LLM( + provider="google", + model="gemini-3.1-flash-lite", + temperature=0.0, + ), + ) + cfg = load_default_model_cfg() + provider = cfg.get("provider") + model = cfg.get("model") + if provider and model: + return LLMWithFallback( + provider=provider, + model=model, temperature=0.0, - ), + fallback=LLM(provider=provider, model=model, temperature=0.0), + ) + return LLMWithFallback( + provider=None, + model=None, + temperature=0.0, + fallback=LLM(provider=None, model=None, temperature=0.0), ) @@ -130,22 +183,22 @@ def get_agent(self, item: AgentNode) -> LLMWithFallback: return val +def _resolve_llm_config_path() -> Path: + """Location of the active LLM config file (workspace artemis.jsonc, then fallbacks).""" + for candidate in ("artemis.jsonc", "artemis.json", LLM_CONFIG_FILENAME): + try: + return get_config_path(candidate) + except FileNotFoundError: + continue + return get_config_path(LLM_CONFIG_FILENAME, ROOT_DIR / LLM_CONFIG_FILENAME) + + def _expand_default_into_nodes(config_dict: dict) -> dict: """Expand unified config format with 'default' and 'nodes' into full LLMConfig schema.""" if "planner" in config_dict and "utils" in config_dict: return config_dict - default_model_cfg = config_dict.get( - "default", - { - "provider": "google", - "model": "gemini-3.8-flash", - "fallback": { - "provider": "google", - "model": "gemini-3.7-flash", - }, - }, - ) + default_model_cfg = dict(config_dict.get("default") or _factory_default_cfg()) nodes_override = config_dict.get("nodes", {}) @@ -197,18 +250,25 @@ def _expand_default_into_nodes(config_dict: dict) -> dict: return result +def load_default_model_cfg() -> dict[str, Any]: + """Raw "default" entry of artemis.jsonc — the endpoint inheritance base. + + Nodes that configure only a model name (no provider/endpoint of their own) + inherit from this entry. Falls back to the factory default when the config + file is missing or unreadable. + """ + try: + with open(_resolve_llm_config_path(), encoding="utf-8") as f: + config_dict = load_jsonc(f) + except Exception as e: # pylint: disable=broad-exception-caught + logger.error(f"Failed to load llm config: {_resolve_llm_config_path()}. Error: {e}") + return _factory_default_cfg() + return dict(config_dict.get("default") or _factory_default_cfg()) + + def parse_llm_config() -> LLMConfig: """Parse and instantiate LLMConfig from artemis.jsonc or llm-config.json.""" - config_path = None - for candidate in ("artemis.jsonc", "artemis.json", LLM_CONFIG_FILENAME): - try: - config_path = get_config_path(candidate) - break - except FileNotFoundError: - continue - - if not config_path: - config_path = get_config_path(LLM_CONFIG_FILENAME, ROOT_DIR / LLM_CONFIG_FILENAME) + config_path = _resolve_llm_config_path() try: with open(config_path, encoding="utf-8") as f: diff --git a/artemis/memory/chunking.py b/artemis/memory/chunking.py index c0c91ea07..161b72aed 100644 --- a/artemis/memory/chunking.py +++ b/artemis/memory/chunking.py @@ -323,17 +323,17 @@ def __init__( def _get_llm(self): if self._llm is None: - from artemis.services.llm import get_google_llm + from artemis.services.llm import get_default_deployment_llm - self._llm = get_google_llm(model_name=self._model_name, temperature=0.0) + self._llm = get_default_deployment_llm(self._model_name, temperature=0.0) return self._llm def _get_fallback_llm(self): if self._fallback_llm is None and self._fallback_model_name: - from artemis.services.llm import get_google_llm + from artemis.services.llm import get_default_deployment_llm - self._fallback_llm = get_google_llm( - model_name=self._fallback_model_name, temperature=0.0 + self._fallback_llm = get_default_deployment_llm( + self._fallback_model_name, temperature=0.0 ) return self._fallback_llm diff --git a/artemis/services/llm.py b/artemis/services/llm.py index ec91e6fa0..1bb36d2b0 100644 --- a/artemis/services/llm.py +++ b/artemis/services/llm.py @@ -22,8 +22,10 @@ from collections.abc import Awaitable, Callable, Iterator from contextlib import contextmanager from contextvars import ContextVar, Token +from dataclasses import dataclass import functools import logging +import os from pathlib import Path import re import sys @@ -870,18 +872,31 @@ async def acomplete_structured( ).__call__ +def _resolve_configured_api_key(api_key: str | None, api_key_env: str | None) -> str | None: + """Config api_key wins; otherwise the env var named by api_key_env.""" + if api_key: + return api_key + if api_key_env: + return os.environ.get(api_key_env) + return None + + # Backward compatible factory functions delegating to ModelFactory -def get_google_llm( - model_name: str = "gemini-3.8-flash", +def get_provider_llm( + model_name: str, + provider: str = "google", temperature: float | None = None, timeout: float | None = None, - thinking_budget: int | None = None, + thinking_budget: float | None = None, thinking_level: str | None = "medium", include_thoughts: bool | None = None, enable_grounding: bool = False, + api_base: str | None = None, + api_key: str | None = None, ) -> BaseChatModel: + """Build a chat model for an explicit model name on an explicit endpoint.""" ep = ModelEndpoint( - provider=ModelProvider.GOOGLE, + provider=ModelProvider.from_string(provider), model_name=model_name, temperature=temperature or 0.0, timeout_seconds=timeout or 60.0, @@ -889,10 +904,79 @@ def get_google_llm( thinking_level=thinking_level, include_thoughts=include_thoughts, enable_grounding=enable_grounding, + api_base=api_base, + api_key=api_key, ) return ModelFactory.create_model(ep) +@dataclass(frozen=True) +class DefaultDeployment: + """The endpoint every node that configures only a model name inherits. + + Empty ``provider``/``model`` mean no deployment default: without Google + credentials the built-in Google endpoint is not assumed and configuration + is required. + """ + + provider: str = "" + model: str = "" + api_base: str | None = None + api_key: str | None = None + api_key_env: str | None = None + + +def get_default_deployment() -> DefaultDeployment: + """Endpoint settings of the raw "default" entry in artemis.jsonc. + + Reads the unmerged entry (not a specific node), so per-node overrides can + never leak into the inheritance base. Returns an empty deployment when the + config provides no default and the factory default cannot work. + """ + try: + from artemis.config.llm import load_default_model_cfg + + cfg = load_default_model_cfg() + return DefaultDeployment( + provider=str(cfg.get("provider") or ""), + model=str(cfg.get("model") or ""), + api_base=cfg.get("api_base") or None, + api_key=cfg.get("api_key") or None, + api_key_env=cfg.get("api_key_env") or None, + ) + except Exception: # pylint: disable=broad-exception-caught + return DefaultDeployment() + + +def get_default_deployment_llm( + model_name: str | None = None, + temperature: float | None = None, + timeout: float | None = None, +) -> BaseChatModel: + """Build a model on the deployment's default endpoint, overriding only the model name. + + Single entry point for nodes that carry a bare model name in config (step + summarizer, history chunker) and for degraded-mode fallbacks. Never + hardcodes a provider: provider and endpoint come from artemis.jsonc. + """ + deployment = get_default_deployment() + if not deployment.provider or not deployment.model: + raise RuntimeError( + "No default model endpoint is configured. Set provider/model " + "(optionally api_base) under 'default' in config/artemis.jsonc, " + "or provide a provider API key such as GEMINI_API_KEY." + ) + return get_provider_llm( + model_name=model_name or deployment.model, + provider=deployment.provider, + temperature=temperature, + timeout=timeout, + thinking_level=None, + api_base=deployment.api_base, + api_key=_resolve_configured_api_key(deployment.api_key, deployment.api_key_env), + ) + + def _resolve_endpoint( ctx: ArtemisContext, name: str, @@ -915,7 +999,15 @@ def _resolve_endpoint( if use_fallback: if isinstance(cfg, LLMWithFallback) or (hasattr(cfg, "fallback") and cfg.fallback): - cfg = cfg.fallback + parent, cfg = cfg, cfg.fallback + # Endpoint overrides inherit into the fallback unless it declares its own. + inherited = { + field: getattr(parent, field) + for field in ("api_base", "api_key", "api_key_env") + if getattr(cfg, field, None) is None and getattr(parent, field, None) is not None + } + if inherited: + cfg = cfg.model_copy(update=inherited) else: raise ValueError(f"LLM configuration for '{name}' has no fallback!") @@ -923,8 +1015,15 @@ def _get_val(obj, attr, expected_type): val = getattr(obj, attr, None) return val if isinstance(val, expected_type) else None - provider_val = getattr(cfg, "provider", "google") - model_val = getattr(cfg, "model", "gemini-2.5-flash") + provider_val = getattr(cfg, "provider", None) + model_val = getattr(cfg, "model", None) + if not provider_val or not model_val: + raise RuntimeError( + f"No model endpoint configured for '{name}'. Set provider/model " + "(optionally api_base) for this node or 'default' in " + "config/artemis.jsonc, or provide a provider API key such as " + "GEMINI_API_KEY." + ) return ModelEndpoint( provider=ModelProvider.from_string(provider_val), @@ -936,6 +1035,10 @@ def _get_val(obj, attr, expected_type): reasoning_effort=_get_val(cfg, "reasoning_effort", str), include_thoughts=_get_val(cfg, "include_thoughts", bool), enable_grounding=_get_val(cfg, "enable_grounding", bool) or False, + api_base=_get_val(cfg, "api_base", str), + api_key=_resolve_configured_api_key( + _get_val(cfg, "api_key", str), _get_val(cfg, "api_key_env", str) + ), ) diff --git a/third_party/mobile_use/config/llm.py b/third_party/mobile_use/config/llm.py index be9f509a9..264a95ef2 100644 --- a/third_party/mobile_use/config/llm.py +++ b/third_party/mobile_use/config/llm.py @@ -52,50 +52,78 @@ def validate_vertex_ai_credentials() -> None: class LLM(BaseModel): - """Base model representing an LLM model provider and runtime parameters.""" + """Base model representing an LLM model provider and runtime parameters. + + An node may stay unconfigured (``provider``/``model`` unset): the factory + default endpoint only applies when its credentials exist, otherwise the + deployment default stays empty and must be configured explicitly. + """ model_config = {"ignored_types": (CyFunctionDetector,)} - provider: LLMProvider - model: str + provider: LLMProvider | None = None + model: str | None = None temperature: float | None = None thinking_budget: int | None = None thinking_level: Literal["minimal", "low", "medium", "high"] | None = None reasoning_effort: Literal["none", "low", "medium", "high"] | None = None include_thoughts: bool | None = None enable_grounding: bool | None = None + # Custom endpoint overrides. Unset fields inherit the deployment default + # (the "default" entry of artemis.jsonc); an explicit value wins over the + # provider's official endpoint and over environment variables. + api_base: str | None = None + api_key: str | None = None + api_key_env: str | None = None + + def _credential_present(self, settings_key: object) -> bool: + """Whether a usable credential exists: config api_key, its env var, or the provider env key.""" + if self.api_key: + return True + if self.api_key_env and os.environ.get(self.api_key_env): + return True + return bool(settings_key) def validate_provider(self, name: str) -> None: - """Ensure the required API key or credentials exist in settings for this provider.""" + """Ensure the required API key or credentials exist for this provider.""" + if not self.provider or not self.model: + return if self.provider == "openai": - if not settings.OPENAI_API_KEY: - raise Exception(f"{name} requires OPENAI_API_KEY in .env") + if not self._credential_present(settings.OPENAI_API_KEY): + raise Exception( + f"{name} requires OPENAI_API_KEY in .env " + "(or api_key/api_key_env on the LLM config node)" + ) elif self.provider == "google": - if not settings.GOOGLE_API_KEY: + if not self._credential_present(settings.GOOGLE_API_KEY): raise Exception(f"{name} requires GOOGLE_API_KEY in .env") elif self.provider == "vertexai": validate_vertex_ai_credentials() elif self.provider == "anthropic": - if not (settings.ANTHROPIC_API_KEY or os.environ.get("ANTHROPIC_API_KEY")): + if not self._credential_present(settings.ANTHROPIC_API_KEY): raise Exception(f"{name} requires ANTHROPIC_API_KEY in .env") elif self.provider == "openrouter": - if not settings.OPEN_ROUTER_API_KEY: + if not self._credential_present(settings.OPEN_ROUTER_API_KEY): raise Exception(f"{name} requires OPEN_ROUTER_API_KEY in .env") elif self.provider == "xai": - if not settings.XAI_API_KEY: + if not self._credential_present(settings.XAI_API_KEY): raise Exception(f"{name} requires XAI_API_KEY in .env") def __str__(self) -> str: + if not self.provider or not self.model: + return "unconfigured" return f"{self.provider}/{self.model}" class LLMWithFallback(LLM): """LLM configuration with automatic secondary fallback and timeout specs.""" - fallback: LLM + fallback: LLM | None = None fix_model: str | None = None timeout: float | None = None def __str__(self) -> str: + if not self.provider or not self.model: + return "unconfigured" return f"{self.provider}/{self.model} (fallback: {self.fallback})" diff --git a/third_party/mobile_use/utils/file.py b/third_party/mobile_use/utils/file.py index e7930014e..bf9eec4a5 100644 --- a/third_party/mobile_use/utils/file.py +++ b/third_party/mobile_use/utils/file.py @@ -22,9 +22,21 @@ def strip_json_comments(text: str) -> str: - text = re.sub(r"//.*?$", "", text, flags=re.MULTILINE) - text = re.sub(r"/\*.*?\*/", "", text, flags=re.DOTALL) - return text + """Strip // and /* */ comments from JSONC text while preserving string literals. + + String-aware: ``//`` inside a quoted value (e.g. an ``http://`` api_base + URL) must not start a comment, so quoted strings are matched and kept + verbatim before comment patterns get a chance. + """ + pattern = r"//.*?$|/\*.*?\*/|'(?:\\.|[^\\'])*'|\"(?:\\.|[^\\\"])*\"" + + def replacer(match: re.Match) -> str: + s = match.group(0) + if s.startswith("/"): + return "" + return s + + return re.sub(pattern, replacer, text, flags=re.DOTALL | re.MULTILINE) def load_jsonc(file: IO) -> dict: From 2e49b846f512a060c5762805d077d9a15495b89c Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 13:04:08 +0800 Subject: [PATCH 002/320] fix: surface task failure details and rebuild trace compilation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 整改记录 #3: - sessions 表新增 error_message 列, DataEngine.end_session 透传失败原因 - worker 三个收尾点(c cancelled/except/finalize)均写入错误信息 - CLI 失败时展示异常摘要并附带 trace view 与守护进程日志提示 - 新增 _materialize_session_trace_artifacts: 编译前从 SQLite/图片目录 物化步骤与截图帧, 修复编译产物恒为 0 步的问题; GIF 编译容错缺 ffmpeg - 附带: SDK 连接预热改为 provider 感知(#2 范围), 仅 google 时预热原生客户端 详见 changelogs.md #3 --- artemis/data_engine/engine.py | 7 +++- artemis/data_engine/models.py | 1 + artemis/data_engine/storage.py | 10 ++++- artemis/interfaces/cli/commands/run.py | 12 +++++- third_party/mobile_use/sdk/agent.py | 55 ++++++++++++++++++++++++-- 5 files changed, 76 insertions(+), 9 deletions(-) diff --git a/artemis/data_engine/engine.py b/artemis/data_engine/engine.py index 7850082bb..a914f5fa3 100644 --- a/artemis/data_engine/engine.py +++ b/artemis/data_engine/engine.py @@ -641,8 +641,8 @@ def start_session( self._publish("session_started", session.model_dump()) return session_id - def end_session(self, status: str = "completed"): - """End the current session, updating its status and end time.""" + def end_session(self, status: str = "completed", error_message: str | None = None): + """End the current session, updating its status, end time and failure reason.""" if not self.current_session_id: return @@ -677,6 +677,8 @@ def end_session(self, status: str = "completed"): if session: session.end_time = end_time session.status = status + if error_message: + session.error_message = error_message else: session = SessionMetadata( session_id=session_id, @@ -684,6 +686,7 @@ def end_session(self, status: str = "completed"): start_time=self.session_start_time or end_time, end_time=end_time, status=status, + error_message=error_message, device_info=self.ctx.device.model_dump() if getattr(self, "ctx", None) and self.ctx.device else {}, diff --git a/artemis/data_engine/models.py b/artemis/data_engine/models.py index bd937e576..b31377218 100644 --- a/artemis/data_engine/models.py +++ b/artemis/data_engine/models.py @@ -25,6 +25,7 @@ class SessionMetadata(BaseModel): start_time: float = Field(default_factory=time.time) end_time: float | None = None status: str = "running" # running, success, failed + error_message: str | None = None device_info: dict[str, Any] = Field(default_factory=dict) pid: int | None = None video_filepath: str | None = None diff --git a/artemis/data_engine/storage.py b/artemis/data_engine/storage.py index 581737c5f..c1fc941f9 100644 --- a/artemis/data_engine/storage.py +++ b/artemis/data_engine/storage.py @@ -124,6 +124,11 @@ def _init_db(self): except sqlite3.OperationalError: pass + try: + conn.execute("ALTER TABLE sessions ADD COLUMN error_message TEXT") + except sqlite3.OperationalError: + pass + conn.execute(""" CREATE TABLE IF NOT EXISTS images ( image_name TEXT PRIMARY KEY, @@ -303,8 +308,8 @@ def update_session(self, session: SessionMetadata): with self._get_connection() as conn: conn.execute( """ - UPDATE sessions - SET end_time = ?, status = ?, device_info = ?, video_filepath = ? + UPDATE sessions + SET end_time = ?, status = ?, device_info = ?, video_filepath = ?, error_message = ? WHERE session_id = ? """, ( @@ -312,6 +317,7 @@ def update_session(self, session: SessionMetadata): session.status, json.dumps(session.device_info), session.video_filepath, + session.error_message, str(session.session_id), ), ) diff --git a/artemis/interfaces/cli/commands/run.py b/artemis/interfaces/cli/commands/run.py index 89dca25ab..29b5a3f9c 100644 --- a/artemis/interfaces/cli/commands/run.py +++ b/artemis/interfaces/cli/commands/run.py @@ -366,8 +366,18 @@ def on_status(sess_info): ) return else: - err = final_res.get("error") or final_res.get("explanation") or "" + err = ( + final_res.get("error_message") + or final_res.get("error") + or final_res.get("explanation") + or "" + ) console.print(f"\n[bold red]✖ Task {final_st}[/bold red]: {err}") + if err: + console.print( + f"[dim]Worker output: `artemis trace view {target_sid}`; " + "daemon log: %LOCALAPPDATA%\\Artemis\\logs\\daemon-8000.log[/dim]" + ) raise SystemExit(1) except KeyboardInterrupt: console.print("\n[yellow]Stopping task on Daemon...[/yellow]") diff --git a/third_party/mobile_use/sdk/agent.py b/third_party/mobile_use/sdk/agent.py index c6a812031..a6bb8d6b0 100644 --- a/third_party/mobile_use/sdk/agent.py +++ b/third_party/mobile_use/sdk/agent.py @@ -23,6 +23,7 @@ """ import asyncio +import json import os try: @@ -733,7 +734,7 @@ async def _safe_stop_recording(): cancelled=True, ) if context.data_engine: - context.data_engine.end_session("cancelled") + context.data_engine.end_session("cancelled", error_message=err) raise except Exception as e: @@ -745,7 +746,7 @@ async def _safe_stop_recording(): error=err, ) if context.data_engine: - context.data_engine.end_session("failed") + context.data_engine.end_session("failed", error_message=err) raise finally: @@ -889,7 +890,10 @@ async def _finalize_tracing(self, task: Task, context: ArtemisContext): session_status = "failed" elif task.status == "cancelled": session_status = "cancelled" - context.data_engine.end_session(status=session_status) + task_error = task.result.error if task.result else None + context.data_engine.end_session( + status=session_status, error_message=task_error + ) exec_setup_ctx = context.execution_setup if not exec_setup_ctx: @@ -917,7 +921,12 @@ async def _finalize_tracing(self, task: Task, context: ArtemisContext): traces_output_path = Path(task.request.trace_path).resolve() logger.info(f"[{task_name}] Compiling trace FROM FOLDER: " + str(temp_trace_path)) - create_gif_from_trace_folder(temp_trace_path) + self._materialize_session_trace_artifacts(context, temp_trace_path) + try: + create_gif_from_trace_folder(temp_trace_path) + except Exception as e: + # The GIF needs ffmpeg; its absence must not cost us the steps.json. + logger.warning(f"[{task_name}] GIF compilation skipped: {e}") create_steps_json_from_trace_folder(temp_trace_path) logger.info(f"[{task_name}] Video created, removing dust...") @@ -932,6 +941,44 @@ async def _finalize_tracing(self, task: Task, context: ArtemisContext): if new_video_path.exists() and context.data_engine: context.data_engine.update_video_path(new_video_path) + def _materialize_session_trace_artifacts( + self, context: ArtemisContext, temp_trace_path: Path + ) -> None: + """Copy the session's screenshots and step payloads into the flat trace + layout the compilers expect (``.jpeg`` frames, ``.json`` steps). + + The DataEngine persists steps in SQLite and screenshots under + ``/images/`` while the legacy compilers only scan this temp + folder; without this step the compiled replay artifacts would always + come out empty. + """ + engine = getattr(context, "data_engine", None) + session_id = getattr(engine, "current_session_id", None) if engine else None + if not session_id: + return + try: + steps = engine.storage.get_steps(session_id) + images_dir = self._tmp_traces_dir / "images" + temp_trace_path.mkdir(parents=True, exist_ok=True) + for step in steps: + image_name = step.post_image_name or step.pre_image_name + if image_name: + src = images_dir / f"{image_name}.jpg" + if not src.exists(): + src = images_dir / f"{image_name}.jpeg" + if src.exists(): + shutil.copy(src, temp_trace_path / f"{step.step_number}.jpeg") + step_payload = json.dumps( + step.model_dump(mode="json"), + ensure_ascii=False, + default=str, + ) + step_path = temp_trace_path / f"{int(step.timestamp * 1000)}.json" + step_path.write_text(step_payload, encoding="utf-8") + logger.info(f"Materialized {len(steps)} session steps into the trace folder.") + except Exception as e: + logger.warning(f"Could not materialize session trace artifacts: {e}") + def _prepare_output_files(self, task: Task): if task.request.llm_output_path: _validate_and_prepare_file(file_path=task.request.llm_output_path) From 4cab5407c6518bdfbed04a89a1e656f495375a76 Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 13:04:19 +0800 Subject: [PATCH 003/320] fix: launch jupyter kernel without a blank console window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 整改记录 #5: - Windows 下向 start_kernel 显式传入 CREATE_NO_WINDOW|CREATE_NEW_PROCESS_GROUP - 根因: jupyter_client 仅在父进程为 pythonw.exe 时才加 CREATE_NO_WINDOW, 无控制台的 worker 拉起内核时 Windows 会分配空白可见控制台 - 内核输出仍落盘 session_dir/kernel.log 详见 changelogs.md #5 --- artemis/utils/python_executor.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/artemis/utils/python_executor.py b/artemis/utils/python_executor.py index b2a548ebb..a3cbaf076 100644 --- a/artemis/utils/python_executor.py +++ b/artemis/utils/python_executor.py @@ -17,6 +17,7 @@ from pathlib import Path import queue import subprocess +import sys import time from typing import IO @@ -73,7 +74,15 @@ def _start(self) -> None: kernel_output = self._kernel_log if self._kernel_log is not None else subprocess.DEVNULL self.km = jupyter_client.KernelManager(kernel_name="python3") - self.km.start_kernel(stdout=kernel_output, stderr=kernel_output) + extra_kwargs: dict = {} + if sys.platform == "win32": + # jupyter_client only sets CREATE_NO_WINDOW when the parent is + # pythonw.exe; spawned from a console-less daemon/worker the + # kernel would otherwise get a fresh, blank console window. + extra_kwargs["creationflags"] = ( + subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.CREATE_NO_WINDOW + ) + self.km.start_kernel(stdout=kernel_output, stderr=kernel_output, **extra_kwargs) self.kc = self.km.client() self.kc.start_channels() self.kc.wait_for_ready(timeout=KERNEL_STARTUP_TIMEOUT_S) From 47db037ef80939cb886cd6f53a0e7c142c82a8b2 Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 13:04:19 +0800 Subject: [PATCH 004/320] chore: point local test deployment at LM Studio endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - default 节点声明 api_base=http://127.0.0.1:1234/v1 + api_key(本地服务, Key 任意) - 新增 local-lmstudio 预设; local-ollama 预设补全 api_base - 本地实测配置, 部署到其他环境时按 changelogs #1 的优先级链覆盖 --- config/artemis.jsonc | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/config/artemis.jsonc b/config/artemis.jsonc index 517d73840..3cde6c723 100644 --- a/config/artemis.jsonc +++ b/config/artemis.jsonc @@ -7,12 +7,14 @@ // 1. Global Default Model (Applied to all sub-agents unless overridden below) // ------------------------------------------------------------------------------ "default": { - "provider": "google", - "model": "gemini-3.8-flash", + "provider": "openai", + "model": "qwen3.6-35b-a3b-mtp", + "api_base": "http://127.0.0.1:1234/v1", + "api_key": "lm-studio", "thinking_level": "medium", "fallback": { - "provider": "google", - "model": "gemini-3.7-flash", + "provider": "openai", + "model": "qwen3.6-35b-a3b-mtp", "thinking_level": "medium" } }, @@ -44,7 +46,15 @@ "local-ollama": { "provider": "openai", "model": "llama3.2-vision", + "api_base": "http://localhost:11434/v1", "fallback": { "provider": "openai", "model": "llama3.2-vision" } + }, + "local-lmstudio": { + "provider": "openai", + "model": "qwen3.6-35b-a3b-mtp", + "api_base": "http://127.0.0.1:1234/v1", + "api_key": "lm-studio", + "fallback": { "provider": "openai", "model": "qwen3.6-35b-a3b-mtp" } } }, @@ -75,10 +85,10 @@ // To achieve accurate [x, y] point and bounding box localization, this node MUST use specialized Gemini ER (Embodied Reasoning / Robotics) models: // e.g., "gemini-robotics-er-2-preview". Non-ER models will fail spatial coordinate detection. "object_detector": { - "model": "gemini-robotics-er-2-preview", + "model": "qwen3.6-35b-a3b-mtp", "fallback": { - "provider": "google", - "model": "gemini-robotics-er-2-preview" + "provider": "openai", + "model": "qwen3.6-35b-a3b-mtp" } }, @@ -95,10 +105,10 @@ // 🔽 Hopper: Fast lightweight package name locator "hopper": { - "model": "gemini-3.5-flash-lite", + "model": "qwen3.6-35b-a3b-mtp", "fallback": { - "provider": "google", - "model": "gemini-3.1-flash-lite" + "provider": "openai", + "model": "qwen3.6-35b-a3b-mtp" } }, @@ -145,7 +155,7 @@ // replacing images only after strictly objective, high-density summaries are ready. "step_summarizer": { "enabled": true, // Whether background step summarization is active - "model": "gemini-3.5-flash-lite", // Lightweight model for fast background inference + "model": "qwen3.6-35b-a3b-mtp", // Lightweight model for fast background inference "prune_history_xml": true // Prune outdated heavy XML trees from historical steps } }, @@ -246,7 +256,7 @@ // call each); milestone closes are exempt, the hard line waives it. "min_steps": 3, "target_source_tokens": 2000, - "model": "gemini-3.8-flash", + "model": "qwen3.6-35b-a3b-mtp", "max_chunks": 8 // "max_eras": 8 // independent era cap; omitted = follows max_chunks }, From 514c950cc2742d5aadf8f198b7e0729f4d47bb8f Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 13:04:26 +0800 Subject: [PATCH 005/320] docs: add changelogs with remediation records and verification log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 记录 #1 端点配置贯通 / #2 provider 硬编码收敛 / #3 失败可观测性 / #4 无 Google Key 时空默认 / #5 空白控制台窗口, 均含根因、方案与验收标准 - 附验证记录 7 轮(冒烟、故障注入、Flash/Pro 实测回归) --- changelogs.md | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 changelogs.md diff --git a/changelogs.md b/changelogs.md new file mode 100644 index 000000000..40171ad90 --- /dev/null +++ b/changelogs.md @@ -0,0 +1,194 @@ +# ARTEMIS 项目整改记录 + +> 本文档记录实测过程中发现的问题与整改点,作为后续逐步优化项目的依据。 +> 每完成一项,将「状态」更新为 ✅ 已完成,并补充整改说明(改动文件、验证方式)。 +> 后续新整改点按 #1 的格式在文末追加。 + +## 测试环境 + +| 项 | 说明 | +|---|---| +| 模拟器 | MuMu 模拟器(`adb connect 127.0.0.1:16384`,设备序列号已写入 `.env`) | +| 本地模型服务 | LM Studio,http://127.0.0.1:1234/v1(OpenAI 兼容);已加载 `qwen3.6-35b-a3b-mtp`(VLM + tool_use) | +| 平台 | Windows / Git Bash | + +## 整改后的预期形状(2026-10-06 已落地) + +- **端点即配置**:`artemis.jsonc` 的每个节点(`default` / `nodes` / `presets`)都可用 `api_base` + `api_key`(或 `api_key_env`)声明完整端点;只写 `model` 的节点自动继承部署默认端点(含 fallback)。 +- **优先级链**:配置显式指定 > 环境变量(`OPENAI_BASE_URL` 等)> 提供商官方默认端点。 +- **零硬编码**:代码中不存在任何按调用点写死的 provider/端点;所有模型构建收敛到 provider 感知工厂。 + +--- + +## 整改点列表 + +### #1 默认端点不应写死:应支持预设提供商与自定义端点 + +- **日期**: 2026-10-06 +- **状态**: ✅ 已完成 +- **优先级**: 高(曾阻塞本地模型实测) +- **来源**: 实测准备阶段 + +#### 问题描述 + +模型端点与提供商绑定写死,无法在配置中指定自定义推理端点(本地 LM Studio / Ollama / vLLM 或企业网关)。期望:既支持**预设提供商**(google / openai / anthropic / openrouter / xai,自动使用官方默认端点,零配置可用),也支持**自定义端点**(在配置中覆盖 base_url)。 + +#### 现状分析(整改前的代码依据) + +| 位置 | 整改前现状 | +|---|---| +| `artemis/llm/router.py:93` | `ModelEndpoint.api_base` / `api_key` 字段已存在且路由层优先使用——**底层能力具备,但配置层未暴露** | +| `artemis/services/llm.py`(`_resolve_endpoint`) | 仅透传 provider / model / temperature 等字段,不读取 `api_base` / `api_key` | +| `third_party/mobile_use/config/llm.py`(`LLM` 模型) | 无 `api_base` / `api_key` 字段;pydantic 默认忽略未知字段,配置写了会被**静默丢弃** | +| `third_party/mobile_use/utils/file.py`(`load_jsonc`) | **新发现**:注释剥离正则不感知字符串字面量,URL 中的 `//` 被当作注释截断(`"http://…"` → 解析报 `Invalid control character`)——即使补上字段,配置端点也落不了地 | +| `.env.example` | 未记载 `OPENAI_BASE_URL` 旁路 | + +#### 整改方案与实施 + +1. **配置模型层**(`third_party/mobile_use/config/llm.py`):`LLM` 新增 `api_base` / `api_key` / `api_key_env` 字段;`validate_provider` 认可配置内凭证(`api_key` 或 `api_key_env` 指向的环境变量),不再强制要求 `.env` 提供商 Key。 +2. **解析链路**(`artemis/services/llm.py` `_resolve_endpoint`):将 `api_base` / `api_key`(经 `api_key_env` 解析)映射进 `ModelEndpoint`;**fallback 端点继承**——fallback 未声明端点字段时自动继承父节点的 `api_base` / `api_key` / `api_key_env`。 +3. **继承基准提取**(`artemis/config/llm.py`):提取 `_resolve_llm_config_path()` 与出厂默认常量 `FACTORY_DEFAULT_MODEL_CFG`,新增 `load_default_model_cfg()` 读取**未被合并的**原始 `default` 条目,避免节点覆盖泄漏进继承基准;`parse_llm_config` 复用同一路径解析。 +4. **JSONC 解析修复**(`third_party/mobile_use/utils/file.py`):`strip_json_comments` 改为字符串感知模式(先匹配并原样保留字符串字面量,再剥离注释,与 `artemis/config/core/engine.py` 的成熟实现同款);`engine.py` 委托该实现,消除重复。 +5. **配置面**:`config/artemis.jsonc` 的 `default` 直接声明 `api_base` + `api_key`(fallback 演示继承);`local-lmstudio` / `local-ollama` 预设补全端点字段;`.env` 移除 `OPENAI_BASE_URL` 旁路;`.env.example` 补充字段说明与优先级链。 + +#### 验收标准 + +- [x] 在 `artemis.jsonc` 中为节点指定 `api_base` 后,请求确实发往该端点——冒烟 6 项全过 + Flash/Pro 实测,守护进程日志确认全部请求命中 `http://127.0.0.1:1234/v1/chat/completions` +- [x] 只配置 `model` 的节点(含 fallback)继承部署默认端点——冒烟 #3/#4 验证 operator 及其 fallback 均继承 `api_base` / `api_key` +- [x] `.env.example` 补充端点字段与优先级说明 +- [ ] 未指定 `api_base` 时走官方端点的线上回归——暂无 Google Key;机制上 `api_base` 缺省为 `None` 时路由回退官方端点(构造路径已被冒烟覆盖),待有 Key 后补一次回归 + +--- + +### #2 多处调用点硬编码 Google 客户端,配置中的 provider 被忽略 + +- **日期**: 2026-10-06 +- **状态**: ✅ 已完成 +- **优先级**: 高(非 Google 部署下 Flash 主链路直接崩溃) +- **来源**: 首次实测(任务启动即失败) + +#### 问题描述 + +`artemis.jsonc` 配置 `"provider": "openai"` 后,Flash 档主链路仍以 `ChatGoogleGenerativeAI` 实例化本地模型名(`API key required for Gemini Developer API`)。根因:`artemis/services/llm.py` 的 `get_google_llm()` 将 provider 硬编码为 `ModelProvider.GOOGLE`,部分节点只透传 model 名。 + +#### 影响范围与整改结果 + +| 调用点 | 整改前 | 结果 | +|---|---|---| +| `artemis/agents/flash/summarizer.py`(step_summarizer 显式 model 路径,首次实测崩溃点) | 硬编码 Google | ✅ 改走 `get_default_deployment_llm()`;顺带修复 else 分支误用 utils 访问器(`summarizer` 是 agent 节点,原 `is_utils=True` 必然 AttributeError) | +| `artemis/memory/chunking.py`(chunker 主/备模型) | 硬编码 Google | ✅ 同上 | +| `artemis/agents/flash/runner.py`(operator 构建失败的兜底模型) | 硬编码 `gemini-2.5-flash` + Google | ✅ 兜底改为部署默认端点的默认模型 | +| `artemis/sdk/agent.py`(连接预热) | 硬编码 `ChatGoogleGenerativeAI(gemini-3.8-flash)` | ✅ 预热改走默认端点;Google 专属的 Native GenAI 客户端预热仅在 provider=google 时执行 | + +#### 最终形状(工厂收敛) + +- 删除 `get_google_llm()` 与过渡期辅助 `get_default_provider()`(全仓 grep 零残留)。 +- 统一为三个 provider 感知入口(`artemis/services/llm.py`): + - `get_provider_llm(model_name, provider, ..., api_base, api_key)`:显式端点构建; + - `get_default_deployment() -> DefaultDeployment`:读取部署默认端点(provider / model / api_base / api_key / api_key_env); + - `get_default_deployment_llm(model_name=None, ...)`:**只覆盖模型名、继承默认端点**的唯一入口,供「配置里只有裸模型名」的节点(step_summarizer、chunker)与降级兜底使用。 + +#### 验收标准 + +- [x] 全仓 grep 确认无 `get_google_llm` 裸调用点与残留引用(仅剩新工厂自身) +- [x] `provider: openai` 配置下 Flash 档跑通真实任务(设置查电量,报告 80%→充电中) +- [x] Pro 档跑通真实任务(关于手机查 Android 版本,LangGraph 多智能体图 + checker 全链路走本地端点,status completed) +- [x] ruff 全部改动文件 lint 通过 + +--- + +### #3 失败可观测性不足:CLI 报错信息为空,trace 编译丢失步骤 + +- **日期**: 2026-10-06 +- **状态**: ✅ 已完成 +- **优先级**: 中(不影响功能,但显著拉高排障成本) +- **来源**: 首次实测排障过程 + +#### 问题描述 + +1. 任务失败时 CLI 仅输出 `✖ Task failed: `(空消息),真实异常只存在于守护进程日志 `%LOCALAPPDATA%\Artemis\logs\daemon-8000.log`,用户无从得知。 +2. 会话步骤实际落盘在 SQLite(`steps` 表)与 `/images/`,而 trace 编译器只扫描空的临时目录(遗留扁平布局),产物恒为 `Found 0 images / 0 steps`。 +3. 环境项:scrcpy 未安装导致录屏/回放不可用(`winget install Genymobile.scrcpy` 可解)。 +4. 追加观察:`artemis restart` 时 Showcase UI(Angular)增量构建报 `Failed to inline external stylesheet`(预编译产物仍可服务,疑似前端构建链问题,与后端整改无关,待排查)。 + +#### 整改方案与实施 + +1. **错误传播链贯通**:`sessions` 表新增 `error_message` 列(ALTER 迁移,`artemis/data_engine/storage.py`);`SessionMetadata` 增加同名字段并纳入 `update_session`;`DataEngine.end_session(status, error_message=None)` 透传;worker 侧三个收尾点全部写入错误(`third_party/mobile_use/sdk/agent.py` 的 cancelled / except 分支与 `_finalize_tracing`);CLI(`run.py`)优先读取 `error_message`,失败时附带 `artemis trace view ` 与守护进程日志路径提示。 +2. **编译产物修复**:新增 `_materialize_session_trace_artifacts`——编译前把 DataEngine 会话步骤(截图帧 `.jpeg` + 步骤载荷 `.json`)从 SQLite/图片目录物化进编译目录;GIF 编译改为容错(缺 ffmpeg 只跳过 GIF,不影响 steps.json)。 + +#### 验收标准 + +- [x] 故障注入(`api_base` 指向死端口 `127.0.0.1:9`):CLI 输出 `✖ Task failed: Error running automation: Connection error.` + 定位提示;DB `sessions.error_message` 持久化完整异常 +- [x] 正常任务编译产物包含全部步骤与帧(`Materialized N steps → Found N images / N steps → steps.json` 非空 + `trace.gif`) +- [x] 成功会话 `error_message` 保持 NULL,无残留 +- [ ] (可选)安装 scrcpy 后录屏回放可用 + +--- + +### #4 无 Google Key 时默认环境应为空,不指定任何端点 + +- **日期**: 2026-10-06 +- **状态**: ✅ 已完成 +- **优先级**: 中(影响首次部署体验与误导性报错) +- **来源**: 用户要求 + #1 验收遗留项 + +#### 问题描述 + +内置出厂默认(`FACTORY_DEFAULT_MODEL_CFG`)隐式指向 Google 官方端点。无 Google Key 的环境里,未显式配置模型时系统会默默构造 Gemini 客户端并以误导性的「API key required」报错失败。期望:无 Google 凭证时默认环境为**空**(不指定任何端点),解析时给出清晰、可操作的配置指引。 + +#### 整改方案与实施 + +1. **配置模型容忍空端点**(`third_party/mobile_use/config/llm.py`):`LLM.provider` / `model` 允许为 None,`LLMWithFallback.fallback` 允许为 None;`validate_provider` 对未配置节点直接跳过;`__str__` 显示 `unconfigured`。 +2. **出厂默认门控**(`artemis/config/llm.py`):新增 `_google_credentials_present()` 与 `_factory_default_cfg()`——仅当 Google 凭证存在时出厂默认才生效,否则默认环境为空;`load_default_model_cfg` / `_expand_default_into_nodes` 统一走该门控;`lightweight_judge_default`(像素安全网/计划校验判官)在无 Google 凭证时改为继承部署默认端点。 +3. **清晰报错**(`artemis/services/llm.py`):`DefaultDeployment` 空默认(provider/model 为空串);`get_default_deployment_llm` 与 `_resolve_endpoint` 在未配置时抛出带配置指引的 `RuntimeError`(指明设置 `default` 节点或提供 `GEMINI_API_KEY`),不再退回 Google 客户端。 +4. **连带修复**:`explorer/run_setup.py` 对未配置 explorer 节点的 `model=None` 兼容(回退 `DEFAULT_EXPLORER_MODEL`,避免 TypeError)。 + +#### 验收标准 + +- [x] 无 Google Key + 配置无 `default`:节点展开为未配置、`LLMConfig` 校验通过、解析时报清晰 `RuntimeError`(冒烟 1–4 通过) +- [x] 有显式 `default`(本环境 openai + api_base):行为完全不受影响(冒烟 5–7 + 实测回归通过) +- [x] Google Key 存在时保留原出厂默认零配置体验(逻辑门控保证,待有 Key 时回归) + +--- + +### #5 每次任务弹出空白 python 控制台窗口 + +- **日期**: 2026-10-06 +- **状态**: ✅ 已完成 +- **优先级**: 中(体验问题:任务运行时弹出一个内容全空的 `.venv\Scripts\python.exe` 终端) +- **来源**: 实测观察 + +#### 问题描述 + +每次任务运行都会弹出一个标题为 `D:\DEV\autoGamer\.venv\Scripts\python.exe` 的控制台窗口,且窗口内无任何输出。 + +#### 根因 + +该窗口是 **ImageProcessor 感知工具的 Jupyter 内核**(`ipykernel`,即 `.venv\Scripts\python.exe`)。jupyter_client 的 `launch_kernel` 只在父进程为 `pythonw.exe` 时才追加 `CREATE_NO_WINDOW`(`redirect_out = sys.executable.endswith("pythonw.exe")`);而 ARTEMIS 的 worker 进程本身是无控制台启动的(`CREATE_NO_WINDOW`),无控制台的父进程再拉起控制台程序时,Windows 会为其**分配一个新的可见控制台**——内核 stdout 又被重定向到 `kernel.log`,于是窗口永久空白。 + +#### 整改方案与实施 + +`artemis/utils/python_executor.py` 的 `_start()`:Windows 下向 `KernelManager.start_kernel` 显式传入 `creationflags = CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW`,经 `launch_kernel → Popen` 透传生效;内核输出仍按设计落盘到 `session_dir/kernel.log`(满足"或能出现正常 log"的备选预期)。 + +#### 验收标准 + +- [x] 从无控制台的父进程启动内核,系统可见窗口前后快照 diff 为空(不再弹窗) +- [x] 内核功能正常:`execute("print(2+3)")` 返回 `5`;输出落盘 `kernel.log` +- [x] ruff lint 通过 + +--- + + +## 验证记录 + +| 时间 | 项目 | 结果 | +|---|---|---| +| 10-06 首测 | Flash「设置查电量」 | ❌ 崩溃(`ChatGoogleGenerativeAI` 校验错误)→ 立出 #2 | +| 10-06 二测 | 同任务(#2 热修 + `OPENAI_BASE_URL` 旁路) | ✅ 3 回合,电量 80% 充电中,全程约 50s | +| 10-06 冒烟 | 端点贯通 6 项(原始 default / DefaultDeployment / 节点继承 / fallback 继承 / ChatOpenAI base_url / 实时调用) | ✅ 全过(此时 `.env` 旁路已移除,端点纯来自配置) | +| 10-06 三测 | Flash 同任务(纯配置端点) | ✅ 2 回合,电量 73%,全部请求命中 `127.0.0.1:1234` | +| 10-06 四测 | Pro「关于手机查 Android 版本」(纯配置端点) | ✅ LangGraph 全链路(planner/operator/checker)命中本地端点,status completed | +| 10-06 冒烟 | 空默认行为 4 项(无 google key 展开为空 / LLMConfig 校验 / 节点级清晰报错 / 真实配置不受影响) | ✅ 全过(#4) | +| 10-06 五测 | 故障注入:`api_base` 指向死端口 | ✅ CLI 显示 `Connection error.` + 定位提示;`sessions.error_message` 持久化(#3-1) | +| 10-06 六测 | Flash 回归(恢复配置)+ 编译产物 | ✅ 任务成功;`Materialized N steps`、`steps.json` 非空、`trace.gif` 生成;成功会话 error_message 为 NULL(#3-2) | +| 10-06 七测 | 无控制台父进程启动 Jupyter 内核 + 窗口快照 diff | ✅ 无新窗口弹出;内核执行正常(`print(2+3)`→`5`),输出落盘 `kernel.log`(#5) | From 7a34da8dea2ce16da6ef8ef526102099b6331532 Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 13:04:41 +0800 Subject: [PATCH 006/320] fix: make SDK LLM connection pre-warm provider-aware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 整改记录 #2 收尾: - 预热客户端改走 get_default_deployment_llm() 配置端点, 不再硬编码 ChatGoogleGenerativeAI(gemini-3.8-flash) - Google 专属的 Native GenAI 客户端预热仅在 provider=google 时执行 详见 changelogs.md #2 --- artemis/sdk/agent.py | 54 ++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/artemis/sdk/agent.py b/artemis/sdk/agent.py index c0c0da08b..73cafa632 100644 --- a/artemis/sdk/agent.py +++ b/artemis/sdk/agent.py @@ -22,7 +22,6 @@ from dotenv import load_dotenv from google import genai -from langchain_google_genai import ChatGoogleGenerativeAI from artemis.clients.screen_client_factory import ( describe_backend, @@ -34,6 +33,7 @@ run_tuning_for_profile, settings, ) +from artemis.services.llm import get_default_deployment, get_default_deployment_llm from artemis.context import ( ArtemisContext, DevicePlatform, @@ -137,34 +137,38 @@ async def _prewarm_llm_connections(self, api_key: str | None = None): publish_startup_progress( "model_warmup", "Warming the model connection", session_id=self._session_id ) - logger.info("Starting background pre-warming of Gemini API connection pools...") + deployment = get_default_deployment() + logger.info( + f"Starting background pre-warming of {deployment.provider} API connection pools..." + ) try: - key = api_key - if not key and settings.GOOGLE_API_KEY: - key = settings.GOOGLE_API_KEY.get_secret_value() - - if not key: - logger.warning("Skipping LLM pre-warming: No API key available.") - publish_startup_progress( - "model_ready", - "Model connection will initialize on first use", - session_id=self._session_id, + pings = [] + if deployment.provider == "google": + key = api_key or deployment.api_key + if not key and settings.GOOGLE_API_KEY: + key = settings.GOOGLE_API_KEY.get_secret_value() + + if not key: + logger.warning("Skipping LLM pre-warming: No API key available.") + publish_startup_progress( + "model_ready", + "Model connection will initialize on first use", + session_id=self._session_id, + ) + return + + # 1. Pre-warm Native GenAI SDK client (Google-only path) + client = genai.Client(api_key=key) + pings.append( + client.aio.models.count_tokens(model=deployment.model, contents="ping") ) - return - # 1. Pre-warm Native SDK client - client = genai.Client(api_key=key) + # 2. Pre-warm the LangChain client on the configured default endpoint + pings.append(get_default_deployment_llm().ainvoke("ping")) - # 2. Pre-warm LangChain client - chat = ChatGoogleGenerativeAI(model="gemini-3.8-flash", google_api_key=key) - - # Fire both calls concurrently in the background - await asyncio.gather( - client.aio.models.count_tokens(model="gemini-3.8-flash", contents="ping"), - chat.ainvoke("ping"), - return_exceptions=True, - ) - logger.success("Gemini API connection pools successfully pre-warmed.") + # Fire all calls concurrently in the background + await asyncio.gather(*pings, return_exceptions=True) + logger.success(f"{deployment.provider} API connection pools successfully pre-warmed.") publish_startup_progress( "model_ready", "Model connection is ready", session_id=self._session_id ) From 69a5017a655f223e02a4d3e63bf6a3ca9c26fb54 Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 13:13:56 +0800 Subject: [PATCH 007/320] docs: add Vue3 + Arco frontend migration research MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 现状盘点(Angular 22 规模/复杂度/通信方式)与 45+ 后端端点契约核实 - Vue3 + Vite + Pinia + Arco Design Vue 技术映射与构建托管集成方案 - 风险清单与 /v2 并行共存的分阶段迁移计划(M0-M6, 约 30-40 人日) - 本轮仅调研, 未修改任何前端代码 --- docs/research/vue3-arco-migration-research.md | 285 ++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 docs/research/vue3-arco-migration-research.md diff --git a/docs/research/vue3-arco-migration-research.md b/docs/research/vue3-arco-migration-research.md new file mode 100644 index 000000000..2ceb57c1e --- /dev/null +++ b/docs/research/vue3-arco-migration-research.md @@ -0,0 +1,285 @@ +# ARTEMIS Web 前端重构调研报告:Angular → Vue 3 + Arco Design Vue + +> 调研日期:2026-10-06 +> 调研范围:`apps/showcase_ui`(Angular 源码)、`artemis/resources/showcase_ui`(编译产物)、`apps/admin_console`(FastAPI 后端) +> 性质:探索性调研,本轮不修改任何现有代码。 + +--- + +## 1. 现状盘点 + +### 1.1 目录与托管关系澄清 + +| 路径 | 性质 | 说明 | +| --- | --- | --- | +| `D:\DEV\autoGamer\apps\showcase_ui` | **Angular 源码(真正的源)** | 含 `src/`、`package.json`、`angular.json`、`node_modules`、`.angular` 缓存 | +| `D:\DEV\autoGamer\artemis\resources\showcase_ui` | **仅编译产物** | 6 个文件:`index.html`、`main-BGAFACUZ.js`、`polyfills-5CFQRCPP.js`、`styles-CDJM3XQS.css`、`logo.png/svg`、`favicon.ico`。由 `artemis/resources/__init__.py` 的 `get_bundled_showcase_dist()` 在 wheel 安装态回退使用 | +| `D:\DEV\autoGamer\apps\admin_console\index.html` | 独立的 Admin Debug Console | 3787 行单文件 vanilla HTML/JS(无构建),挂在 `/admin`、`/debug` 路径,**不在本次重构范围** | + +### 1.2 技术栈与依赖(`apps/showcase_ui/package.json`) + +- Angular **22.1.4**(`@angular/core` 等 `^22.1.4`),`@angular/cdk ^22.1.5`,`@angular/build ^22.1.6`(esbuild 应用构建器),TypeScript `~6.0.3`,`zone.js ~0.15.0`,`rxjs ~7.8.0` +- **没有引入任何第三方 UI 组件库、图表库或播放器库**:界面全部手写(Material Symbols 图标走 Google Fonts CDN),Angular CDK 只用到 `overlay-prebuilt.css`(见 `src/styles.scss`) +- 测试:Karma + Jasmine,6 个 spec 文件(`agent.service.spec.ts` 418 行、`stream-aggregator.util.spec.ts` 640 行等) +- 构建:`@angular/build:application`,输出 `dist/frontend/browser`,`outputHashing: all`,预算 initial 2MB 警告 / 4MB 报错 + +### 1.3 代码规模(非测试源码共 31,030 行) + +| 文件 | 行数 | 职责 | +| --- | --- | --- | +| `src/app/services/agent.service.ts` | 2012 | 全局状态中枢:sessions 合并、状态轮询、SSE 流、视频回放状态机 | +| `src/app/utils/tool-formatter.util.ts` | 1419 | 工具调用卡片格式化 | +| `src/app/utils/stream-aggregator.util.ts` | 1021 | 步骤/流事件聚合为时间线块 | +| `src/app/utils/action-formatter.util.ts` | 1015 | 动作解析/文案 | +| `src/app/utils/image-overlay.util.ts` | 662 | 截图 canvas 坐标叠加 | +| `src/app/components/agent-stream/` | TS 2234 + HTML 1436 + SCSS 3973 | 核心时间线视图:任务下拉、notes、usage、阶段折叠、LLM 流打字机、暂停/重试卡片、Checker 面板 | +| `src/app/pages/home/` | TS 1111 + HTML 2103 + SCSS 5168 | 首页:诊断向导(readiness 三步引导)+ 任务启动器(flash/pro、Pro 调优滑杆、outputter 抽屉、智能任务推荐) | +| `src/app/components/floating-video-player/` | TS 631 + HTML 433 + SCSS 987 | 浮动播放器:视频分段播放、step 帧回放(pre/post)、canvas 坐标叠加、MJPEG 实时投屏、双时间轴 seek | +| `src/app/components/chat-interface/` | TS 269 + HTML 380 + SCSS 1171 | 任务队列/历史列表 + 输入框 | +| `src/app/pages/workspace/` | TS 323 + HTML 201 + SCSS 885 | 工作台:左时间线/右队列分栏(可拖拽)、浮动命令条(Ctrl+K) | +| `src/app/pages/legacy-workspace/` + `legacy-agent-stream/` | ~600 行 | `/check` 路由的旧版流视图(淘汰候选) | +| `src/app/core/models/` | 5 文件 ~560 行 | session / stream / system / pro-tuning / markdown 类型契约 | + +### 1.4 路由与页面清单(`src/app/app.routes.ts`) + +| 路由 | 组件 | 功能 | +| --- | --- | --- | +| `/` | `HomeComponent` | 双 Tab:System Setup(readiness 三步诊断、ADB/emulator/凭据配置)与 Task Launcher(任务提交、Pro 调优、智能推荐) | +| `/workspace` | `WorkspaceComponent` | 主工作台:AgentStream 时间线 + ChatInterface 队列 + FloatingVideoPlayer 浮层 | +| `/check` | `LegacyWorkspaceComponent` | 旧版流视图(legacy,仅维护) | + +全局导航为 `NavSwitcherComponent` 浮动切换按钮(`app.component.ts` 仅 30 行)。 + +### 1.5 状态管理与通信方式 + +- **状态管理**:无 NgRx/其他状态库。`AgentService`(`providedIn: 'root'`)与 `SystemService` 直接使用 **Angular Signals + computed** 作为全局状态;`sessionLogs`、`rawSessions`、`pendingQueue`、`activeTasks` 等信号承载全部数据。 +- **通信方式共 4 类**(`proxy.conf.json` 代理 `/api`、`/images`、`/videos`、`/local_file` 到 `:8000`): + 1. **REST 轮询**:`/api/status` 每 2s、`/api/sessions` 每 6s(`pollCounter % 3`)、`/api/system/readiness` 每 3s、emulator 启动期每 1s;均带签名去重(payload JSON 相同则跳过 setState)与 `visibilitychange` 暂停/恢复。 + 2. **SSE**:`new EventSource('/api/stream')` 单通道持久连接,在 `NgZone` 外注册,消费 17 种事件类型(见 §2.3)。`llm_stream` chunk 按 `execution_id|stream_type` 键合批(可见时 80ms / 后台 500ms flush),非流事件前强制 flush 保证顺序。 + 3. **MJPEG 流**:`` 实时投屏(video player 的 live 模式)。 + 4. **静态媒体**:`/images/{name}.jpg`(截图)、`/videos/{path}`(录像分段)、`/local_file?path=`。 +- **本地缓存**:`localStorage` 键 `artemis.sessions.v1`(会话列表冷启动快照)与 `artemis_selected_profile`。 +- **性能细节**(迁移时必须保留的语义):SSE 合批与事件顺序保证、快照(`/steps`)与 live 事件的 append-only 合并(`history_snapshot` 标记)、checks 快照幂等回填(`checks_snapshot`)、乐观更新 + 签名失效(`invalidateStatusSignatures`)、`WeakMap` 模板缓存。 + +### 1.6 构建产物如何被 FastAPI 托管 + +`apps/admin_console/server.py`: + +- `_get_showcase_dist()`(L245-260):依次探测 `apps/showcase_ui/dist/{frontend/browser, browser, frontend}` 下是否存在 `index.html`;否则回退 `artemis/resources/showcase_ui`(wheel 内置)。 +- Catch-all 路由 `serve_showcase_spa`(L281-390):拦截所有非 `api/`、`images/`、`videos/`、`local_file`、`docs`、`openapi.json`、`redoc` 前缀的路径 —— 静态文件精确命中 → `public/` 图标回退 → SPA `index.html` 回退。**天然适配任何 SPA(含 Vite)的 history 路由**。 +- `SameOriginBoundaryMiddleware`(`core/security.py`):校验 `Host`(防 DNS rebinding)与 `Origin`(防 CSRF),**无任何 CORS 放行**。非浏览器客户端(无 Origin 头)直接放行。 +- 自动构建链路:`artemis ui` CLI(`artemis/interfaces/cli/commands/ui.py` 的 `ensure_showcase_built()`,L192-229)按源码 mtime 判断是否需要 `npm install && npm run build`;`start.sh`(L264-365)与 `Makefile`(L40)有同样逻辑(含 Node 22 自动安装)。 + +--- + +## 2. API 契约梳理(以路由代码为准) + +### 2.1 前端实际消费的端点 + +来源:`agent.service.ts`、`system.service.ts` 中的全部 `http.get/post` 与 `EventSource` 调用。 + +**任务与会话**(`routers/tasks.py`、`routers/sessions.py`): + +| 端点 | 方法 | 前端用法 | 响应/请求形状 | +| --- | --- | --- | --- | +| `/api/sessions` | GET | 每 6s 轮询 | `Session[]`:`{session_id, initial_goal, start_time, end_time?, status?, video_url?, recording_status?, model_info?, device_serial?, device_info?}`(后端动态补齐 `device_id/device_serial/model_info/recording_status/video_url`,见 `sessions.py` L53-167) | +| `/api/sessions/{id}` | GET | 未被前端消费 | 单会话行 | +| `/api/sessions/{id}/usage` | GET | RunInfo 面板 | `SessionUsage`:`{llm_calls, prompt_tokens, completion_tokens, total_tokens, cached_tokens, operator_context_tokens, operator_context_window_tokens, profile?, run_tuning?}` | +| `/api/sessions/{id}/steps` | GET | 选中会话时回填快照 | `StepItemData[]`:`{step_id, step_number, timestamp, operator_native_thinking?, operator_raw_thinking?, action_taken?, generic_tools?, last_execution_result?, pre_image_name?, post_image_name?, token_usage?, duration?}` | +| `/api/sessions/{id}/startup_progress` | GET | 选中/提交时 | `StartupProgressEvent[]`:`{session_id?, stage, message, timestamp}` | +| `/api/sessions/{id}/notes` | GET | Notes 面板 | `{notes: Record}`(键为 `task_plan.md` 等) | +| `/api/sessions/{id}/checks` | GET | Checker 面板回填 | `{records[], streams: PersistedCheckerStream[], run_outcome}` | +| `/api/sessions/{id}/video` | GET | 打开播放器,轮询直到 ready | `{status: 'processing'|'ready'|'failed'|'unavailable', has_video, video_url, video_segments: [{url, start, duration, width, height, offset_ms?, duration_ms?}], retry_after_ms?, message?}`(`media.py` L110-176) | +| `/api/sessions/{id}/tree`、`/background_tasks` | GET | **前端当前未消费** | 轨迹树 / 后台任务 | +| `/api/sessions/{id}/delete` | POST | 单条删除 | `{status, message}` | +| `/api/cleanup` | POST | 清空全部历史 | `{status, message}` | +| `/api/status` | GET | 每 2s 轮询 | `{status: 'idle'|'running'|'paused', session_id, goal, pid, paused_error?, queue: (TaskQueueItem|string)[], background_tasks[], active_tasks: [{device_id, session_id, goal, pid, ingress, acquired_at}], model_info, ipc_port}`(`tasks.py` L250-383) | +| `/api/run` | POST | 提交任务 | `RunRequest`:`{goal | goals[], profile='flash', expected_output?, enable_outputter?, verification_level?, explorer_mode?, locked_app_package?, app_path?, device_serial?, ingress='frontend', session_id?, conversation_id?}` → `{status, tasks[], enqueued_count, total_queued}` | +| `/api/run/defaults` | GET | 启动器滑杆默认值 | `{verification_level, explorer_mode}` | +| `/api/stop` | POST | 停止(支持 query + body 双通道) | `{all: bool, session_id?, device_id?}` → `{status: 'stopped'|'no_running_task'}` | +| `/api/resume` | POST | 恢复暂停 | → `{status: 'resumed'|'not_paused'}` | +| `/api/tasks/presets`、`/api/tasks/catalog`、`/api/devices` | GET | **前端当前未消费**(Home 用的是本地 `smart-tasks.data.ts` 静态推荐) | — | + +**系统诊断**(`routers/system.py`,prefix `/api/system`,`system.service.ts` 消费): + +- `GET /api/system/readiness?force=` → `SystemReadinessReport`(`probes: ProbeResult[]`、`active_device`、`os_type`、`timestamp`) +- `GET /api/system/adb/server`、`POST /adb/server/probe|connect|local`(ADB server 端点切换) +- `POST /devices/select`、`POST /adb/restart`、`POST /adb/connect`(Wi-Fi ADB) +- `GET /emulator/status`、`POST /emulator/launch|stop|dismiss`(`EmulatorLaunchState`:`{avd_name, status, stage_message, progress_percent, logs[], can_retry}`) +- `GET /credentials`、`POST /credentials/test`、`POST /credentials`(LLM/OCR key) +- `GET /model-config-env`(`ModelConfigEnvResponse`:config 内容、presets、env_vars) +- 未消费:`/server-status`、`/restart`、`/shutdown`、`/adb/heal-keys` + +**流与媒体**(`routers/stream.py`、`routers/media.py`): + +- `GET /api/stream`(SSE,见下)、`GET /api/stream/device-live`(MJPEG `multipart/x-mixed-replace`)、`GET /api/stream/device-state` +- `GET /images/{name}`(截图 jpg)、`GET /videos/{path}`(mp4/webm/mkv,白名单后缀 + 路径越界防护)、`GET /local_file?path=` +- `GET /api/sessions/{id}/plan`(未消费) + +### 2.2 前端未消费、但 Vue 版可考虑接入的端点 + +`/api/sessions/{id}/tree`(轨迹树)、`/api/sessions/{id}/background_tasks`、`/api/tasks/presets|catalog`(服务端智能推荐,替代前端硬编码的 `smart-tasks.data.ts` 334 行)、`/api/steps/{step_id}/traces`、`/api/traces/{trace_id}` 以及 replay 组(`/api/replay/tools|config`、`replay_steps`、`steps/{n}/replay`)—— replay 组目前只被 `/admin` vanilla 控制台使用。 + +### 2.3 SSE 事件契约(`tasks.py` `stream_events` L386-517 与 `agent.service.ts` L786-802) + +单通道 `GET /api/stream`(支持 `/api/stream/{session_id}` 过滤),事件类型: + +`info`、`keep-alive`(5s 心跳)、`session_started`、`session_ended`、`startup_progress`、`step_recorded`、`step_updated`、`trace_recorded`、`llm_stream`、`llm_stream_reset`、`llm_retrying`、`task_paused`、`task_resumed`、`background_tasks_updated`、`recording_ready`、`recording_failed`、`checker_event`。 + +服务端还会在订阅 `all/active` 时重放当前会话的 `session_started` + `startup_progress` + 已落库 `step_recorded`(幂等快照语义)。前端按 `session_id` 过滤事件、按 trace_id 去重 `trace_recorded`。 + +--- + +## 3. Vue 3 + Arco Design Vue 技术映射 + +### 3.1 推荐技术栈 + +| 层 | 选型 | 版本建议 | 说明 | +| --- | --- | --- | --- | +| 构建 | Vite | 7.x | esbuild/rollup,产物 hash 与 Angular 对齐(`outputHashing` 等价于 Vite 默认) | +| 框架 | Vue | ^3.5 | ` + + diff --git a/apps/showcase_ui_v2/package-lock.json b/apps/showcase_ui_v2/package-lock.json new file mode 100644 index 000000000..b88d7d41c --- /dev/null +++ b/apps/showcase_ui_v2/package-lock.json @@ -0,0 +1,2991 @@ +{ + "name": "artemis-showcase-ui-v2", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "artemis-showcase-ui-v2", + "version": "0.1.0", + "dependencies": { + "@arco-design/web-vue": "~2.58.0", + "pinia": "^3.0.0", + "vue": "^3.5.13", + "vue-i18n": "^11.1.0", + "vue-router": "^4.5.0" + }, + "devDependencies": { + "@types/node": "^24.0.0", + "@vitejs/plugin-vue": "^6.0.0", + "@vue/test-utils": "^2.4.6", + "jsdom": "^30.0.0", + "typescript": "~5.9.0", + "vite": "^7.0.0", + "vitest": "^4.1.0", + "vue-tsc": "^3.0.0" + } + }, + "node_modules/@arco-design/color": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/@arco-design/color/-/color-0.4.0.tgz", + "integrity": "sha512-s7p9MSwJgHeL8DwcATaXvWT3m2SigKpxx4JA1BGPHL4gfvaQsmQfrLBDpjOJFJuJ2jG2dMt3R3P8Pm9E65q18g==", + "license": "MIT", + "dependencies": { + "color": "^3.1.3" + } + }, + "node_modules/@arco-design/web-vue": { + "version": "2.58.0", + "resolved": "https://registry.npmmirror.com/@arco-design/web-vue/-/web-vue-2.58.0.tgz", + "integrity": "sha512-b1vdPYOmjG5VAkVa7jlVwCb+WynBK+rnKN8zH3yKohpZObZbostRd3HgYNtjjZjGVU3OqR0Yy2FX7ftgF0bcOw==", + "license": "MIT", + "dependencies": { + "@arco-design/color": "^0.4.0", + "b-tween": "^0.3.3", + "b-validate": "^1.5.3", + "compute-scroll-into-view": "^1.0.20", + "dayjs": "^1.11.13", + "number-precision": "^1.6.0", + "resize-observer-polyfill": "^1.5.1", + "scroll-into-view-if-needed": "^2.2.31", + "vue": "^3.1.0" + }, + "peerDependencies": { + "vue": ">=3.1.0" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "7.1.3", + "resolved": "https://registry.npmmirror.com/@asamuzakjp/css-color/-/css-color-7.1.3.tgz", + "integrity": "sha512-1t1U8Cm3RBl9vh3RAZhjkPaduzLSvQJRToRrxpGR/eDRW99mOREleuu+mWfiFa795bUzjwht7NgphCKTs2ianQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^3.4.2", + "@csstools/css-color-parser": "^4.2.5", + "@csstools/css-parser-algorithms": "^4.0.2", + "@csstools/css-tokenizer": "^4.0.2", + "lru-cache": "^11.5.3" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "9.2.4", + "resolved": "https://registry.npmmirror.com/@asamuzakjp/dom-selector/-/dom-selector-9.2.4.tgz", + "integrity": "sha512-YnVzxDxLaqL0t7Q4wfcgHZjg55Wm6y5EaO7Bhu3q9J7wq/8iw3PhsnWiOQhYekx4VexnbkgWpTT6n+QIV7kczw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bidi-js": "^1.1.0", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.5.3" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.9", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bramus/specificity": { + "version": "2.4.3", + "resolved": "https://registry.npmmirror.com/@bramus/specificity/-/specificity-2.4.3.tgz", + "integrity": "sha512-0GEz8qJWokkUVYQYRukmkSHIFNoBH8QTreeHrAFbvz1XFYc3Y+puhMs8PQ5x8GNugiC2l5jvDBXKLbBIByeSBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.2.1" + }, + "bin": { + "specificity": "bin/cli.js" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "6.1.2", + "resolved": "https://registry.npmmirror.com/@csstools/color-helpers/-/color-helpers-6.1.2.tgz", + "integrity": "sha512-grhRy3OKmniaAEKXMjua5z/EODX0MSqBGjunw8+j/3HQjOnahs2AGhvEOIYVUWcU6ScApbhLhVrQTX8XqrMrow==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.4.3", + "resolved": "https://registry.npmmirror.com/@csstools/css-calc/-/css-calc-3.4.3.tgz", + "integrity": "sha512-iex20d8CHVkyvg6B7UKV7uHnI2Bqo9g+EFfT9E0y+GvTvhZ/DwONJ+9aKb1dlqm0ZiGsL5RXjp0fCoJYnkeDjA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.2", + "@csstools/css-tokenizer": "^4.0.2" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.2.6", + "resolved": "https://registry.npmmirror.com/@csstools/css-color-parser/-/css-color-parser-4.2.6.tgz", + "integrity": "sha512-iiPQ3iRWwnJkeEn6RIu6SJPr7hYrLz6XZ9s/QZl+2/LI5KQVjpl2fdmDSZKuD4xP6GMmMPgHFFXg6k1Wkz0Trg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.1.2", + "@csstools/css-calc": "^3.4.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.2", + "@csstools/css-tokenizer": "^4.0.2" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.2.tgz", + "integrity": "sha512-40cSKyMvK+tq4qz6Awrlye2WGuOKt3FwPgtGg6KTfbHOWNw+Rk1rzbAtZnZ6IBhsY491HLRnDXwoyBAijmmILA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.2" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.15", + "resolved": "https://registry.npmmirror.com/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.15.tgz", + "integrity": "sha512-J0u7HkVl2nzSlhsiTOp4AmwcUQ3D+mGEEKfBy/7To5/y7F2OHwyLrXfrhR0SMgr4p5Lo+eaMVSeai24zUcBIxA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@csstools/css-tokenizer/-/css-tokenizer-4.0.2.tgz", + "integrity": "sha512-OoKoR0f76dCY666JlcbhmVTs2drYj1GUXZTYTcbUgJjh9Nv41aFfZ21bPQTERm5+L5cBDo466NltB2lplS5GBw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@exodus/bytes": { + "version": "1.16.0", + "resolved": "https://registry.npmmirror.com/@exodus/bytes/-/bytes-1.16.0.tgz", + "integrity": "sha512-IcpW84uEn3N7ETtNZMlxKhfl6Pec8rUNGOTBtWbK1FKhJxIFAptZyVrvVRVBimAJxJCgc3PxepxkdWWG4DVzfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, + "node_modules/@intlify/core-base": { + "version": "11.4.13", + "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-11.4.13.tgz", + "integrity": "sha512-3qGv1/j0fl6ZSeehGaznE78A4i3hCaOeOyDh7jq7SV6ch/XGoy96xIrYuALTV3xhIqj2rktsIKcwlLZ3CbOhkA==", + "license": "MIT", + "dependencies": { + "@intlify/devtools-types": "11.4.13", + "@intlify/message-compiler": "11.4.13", + "@intlify/shared": "11.4.13" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/devtools-types": { + "version": "11.4.13", + "resolved": "https://registry.npmmirror.com/@intlify/devtools-types/-/devtools-types-11.4.13.tgz", + "integrity": "sha512-f38d2yvjNc1/c+BnTLsxTB0729clTtyy7kTxHu4FFlvI6FpmBOp7b9sLYtsKJpXSZ70kIEexvNwDSzLkIlYnlQ==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "11.4.13", + "@intlify/shared": "11.4.13" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "11.4.13", + "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-11.4.13.tgz", + "integrity": "sha512-cjKsDeWUD/i3mj0QtC8hydLCFP5mgZtTU1xZZaN9/O3FG94EXc0rTbecYpifglp26rpoJoIjSlW137VejLKsZw==", + "license": "MIT", + "dependencies": { + "@intlify/shared": "11.4.13", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "11.4.13", + "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-11.4.13.tgz", + "integrity": "sha512-ZjcNgEED1FtTCFb+ohWBdR21k5kvleKtM9peobQtLB83mNIfEhJK86dEbhfk+OcUrybrEbc4eDeE9UbFUVHsjQ==", + "license": "MIT", + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "license": "MIT" + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/@one-ini/wasm/-/wasm-0.2.1.tgz", + "integrity": "sha512-TUqERXGNTifZ9y2g3wPxQrw3HpHv/02DsW3D90T9x0hhonrL1ZqpSmNrU2XkoIq0fP1N6gZfVQzy2Fw1ZvGBNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.64.0.tgz", + "integrity": "sha512-FLLpX941CD/7aBvX3GqLGBM9OvY5PGXTryPJkG5r5/OuBpZpV5k45Uo3RxAvqd35tsyc3hH1bhtz921IKzoIzg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.64.0.tgz", + "integrity": "sha512-iI32XM/jnDYJsvx5ai/za/7gWO9XoSeFFtU06/ZCaRgyilfJOjaopD3nOpk2WrTCGOyeDt4hleUiGOAnd5tHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.64.0.tgz", + "integrity": "sha512-dRBZlbt2sEtF8Mn4MODThze9fIPdDoOhVSlXMAKy5dQbOYK9pOOoPY4Fat3OTtr0+8zbJo5TTZwlsfxY/kDNJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.64.0.tgz", + "integrity": "sha512-Y3whrJOMucfkhgNkvcM93M6j8C53iEAMmPMYD99C6G1kUy4ELigLWk9ar2/4aCBSRgsql0zdlOemLgW2m5GZgQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.64.0.tgz", + "integrity": "sha512-S6S1GEzPjFF6IONYJX3AKt/799+8RgBgCcwRnUo+Ep1IvBxUbw5M51iU0TDdK2NWWVnSvCQ8yi6Em0fGASMOng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.64.0.tgz", + "integrity": "sha512-Ed1DPoFENkXj4IGzSB12SesV40iP6LxCCrbTIkSGIQBpOOxpBM+0kj62lmaeIHfMWTDoddqTOtqc7s8LYfn+Pw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.64.0.tgz", + "integrity": "sha512-J/6xhutJPtFyIkmHdf4olOdHHKH5kOJNumojdWn+Elv5ICEYTVOa362Vw27TxsK0BLzb1le3EDlO3UbvFK1lnQ==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.64.0.tgz", + "integrity": "sha512-G4L/Nnx59d2LvDoV/P4S5lZ7oVLT6hodOHMacqjiq2LL2gts86KbkEBTYL53+fBt0odhf7XPIbIATGoYiJctxg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.64.0.tgz", + "integrity": "sha512-zF16pvJDEUksGYRbfnXne7pdklAyj2XDmJeYKgP93oq0cUyX9Y8O7lUo1R+IY1GagP/YBvCEDCe7eEcAKpw//g==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.64.0.tgz", + "integrity": "sha512-nIggWn8n+w12+R5lsV+PYYoUY8vuObxPAQqJI7WES+9v0qspYuAHoZMfYM0yLxlipasT5BY9ht5W8t5c/rSCkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.64.0.tgz", + "integrity": "sha512-WLOTiHPzszP0dxIMsHpFeDSOSB5I49Mj8K4+yKE3H1X/D0JRG5XZ5jrctJLMjnUc/LUzaKiwq6EHWNJ8pup8PA==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.64.0.tgz", + "integrity": "sha512-35RK9aRhh7g7Pmeu5gQ01aCvrhXzj9LoBE6xtUcEH1ns+nyTaSzxSpADmBQINu4QiTDGvmQYwo1j5hlg1rRXFw==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.64.0.tgz", + "integrity": "sha512-RqTfnpoTjuWfPAmqK5p2edt2AMCDJWm6oTn7sKfmyx+6tRga0ip05SJ977o6udTcIiDeF/CJMUfkaN4gtWt6Aw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.64.0.tgz", + "integrity": "sha512-RQjZPigjxFvFZDijG6rjlSXxhRaTf9zLYVpGK+lVcga64oMqP1GbgVqCb46eHTTceSIgp89Ja0y5aPe3GFBYHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.64.0.tgz", + "integrity": "sha512-tjL58mgQcTRnDRpeky+Sth1MKQeYi2Ct6r3Luq9E5aTSjnM/i/JbozqZkKqp9thM5+oDSZxo+05f9kdQedfTGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.64.0.tgz", + "integrity": "sha512-ictoRyVaoZ8C67myHef+8hhCa6IplXJJ/xUCkVCxziV4zxMZh+jvhkhGsPBLqj1S72fnqD0QH5zL4lcaa4X7DQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.64.0.tgz", + "integrity": "sha512-8aVvZ2hfr9RLFzBQkQNmYeHLDja8fLeQAmLt757zdKN/B+8L809KlLJKctQjS22wZotptV8G6o7fVPuAs8S1tQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.64.0.tgz", + "integrity": "sha512-2dEF8GAcDKwshUfydD+GhosppNyBzhVUHkdFF3CXd3FpOkzj/RZzF5aoEtzklujklT5qFVRU2GK/cFeLaTNKVg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.64.0.tgz", + "integrity": "sha512-3XHTvoo2hKkh0MiOfS7SkhHjMaaWF7P4F3drocZZaho/Z8w7h/jpnuBHm91BOQLfvrKHs1yR+zir4E8RI3XzTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.64.0.tgz", + "integrity": "sha512-HKtkzodL4a3KFWDXDoO61cRynAWTR3LnAE0oGtfG9lcNFpNuVYUFOByxDgNqEvic9rvaQbAj+SFwTEWDptRaIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.64.0.tgz", + "integrity": "sha512-JBsxqiY16uyyCujtoC3s7zL+SrYyNElptD7K4V+KUoJ2V8/XG3hPWpheK+SuPwNh1cikJvIZmIdsrYXvD6PLJw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.64.0.tgz", + "integrity": "sha512-S5Qrijh37qhnUYQ0ay8WN3LuWeKjow7wTUyCOPMZtnXiBXYXdsZETI6ZLfYnQAKovltckPLBFdNeD61P2rJc7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.64.0.tgz", + "integrity": "sha512-zbZ6iMmLFEsCtTdc2/y1F/cDFVNNCPF7Ae8PCT/wdPE//hGwYp6r+MyCLMFX+kOeIe09Pz6ASfnnfpSTN1FJQQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.64.0.tgz", + "integrity": "sha512-L6Hw69oNpuYaOr1zCG30v0/DqKYCSRwodPGwIcVZ/6f8SOzq9rxtL/xNVI5MO4wjli+Ko0ErK9uHJL3mNPt8wQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.64.0.tgz", + "integrity": "sha512-nl+CTWIgOGszQmUz/kanfgrfFZ4qiwxKIfT/ryl3N3Ewk5tqizmYtNXiqb7Bu/fDtNgu1kyxdFiAUJNur3iysg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmmirror.com/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.19.1", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-24.19.1.tgz", + "integrity": "sha512-aS3/DG0oM05K0RIXXP+hKjinGG5IgSSVGzswZxW3O0sS3pH4/fycXundUC9XsszgKCk4gHXylTEK6hyFxVxnoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.9", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-6.0.9.tgz", + "integrity": "sha512-rD/MORlhaZMlXWW0rEn4FB4wMinWC0z/D7Ye160S5+Rs1mC8ZDAdcDp4SjKfUhG5t8q1ktcPVw4xuTkPRlzrSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.11", + "resolved": "https://registry.npmmirror.com/@vitest/expect/-/expect-4.1.11.tgz", + "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.11", + "resolved": "https://registry.npmmirror.com/@vitest/mocker/-/mocker-4.1.11.tgz", + "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.11", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.11", + "resolved": "https://registry.npmmirror.com/@vitest/pretty-format/-/pretty-format-4.1.11.tgz", + "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.11", + "resolved": "https://registry.npmmirror.com/@vitest/runner/-/runner-4.1.11.tgz", + "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.11", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.11", + "resolved": "https://registry.npmmirror.com/@vitest/snapshot/-/snapshot-4.1.11.tgz", + "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.11", + "@vitest/utils": "4.1.11", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.11", + "resolved": "https://registry.npmmirror.com/@vitest/spy/-/spy-4.1.11.tgz", + "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.11", + "resolved": "https://registry.npmmirror.com/@vitest/utils/-/utils-4.1.11.tgz", + "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.11", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.43.tgz", + "integrity": "sha512-zdiLhnbe1QQqgDT8xZMpNmyqZ3qlI+/Q/FHQco57Kwl/b05HhCzN6eVGN9QU9rbga4CrS0H5SYY8VGHZCt/1Hg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.43", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.43.tgz", + "integrity": "sha512-PEZoAk3NQmsn/ejMzSOCyTYqwGqczrWm70PuhBKjjv1+TCoQAaO/zOqNwjV+honlNstT5ILxtc+8r8UUfj+iEQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.43", + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.43.tgz", + "integrity": "sha512-FCbrG3XNCRl+js3huuKx4IVHBLTvMkJhVepjbxSPu1gn4yWLaYtGNQdjJGZaMytXB6qb76qQDDmDSLy/vkmleQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/compiler-core": "3.5.43", + "@vue/compiler-dom": "3.5.43", + "@vue/compiler-ssr": "3.5.43", + "@vue/shared": "3.5.43", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.28", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.43.tgz", + "integrity": "sha512-GF62orf7KiJX9RqrHNGrYBudsQGD0OhJ5nDs90O8UiDuS40+YMYomiXu6w6EuvtXuRDc3MSNis3EaaSKAVSWpg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.43", + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.10", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.10.tgz", + "integrity": "sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.10" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.10", + "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.10.tgz", + "integrity": "sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.10", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.10", + "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.10.tgz", + "integrity": "sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/language-core": { + "version": "3.3.12", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-3.3.12.tgz", + "integrity": "sha512-k7uIKR0n4CBidk233y7cac9osnDQ5WRidTl6nsrNvpZ3nf8cx9iJxRVsRzVsoPRHbowT/iKgGMTS9RGov3jeIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.2.1", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.4" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.43.tgz", + "integrity": "sha512-G/c9GyOZNI2jVaaS6OX1EF1SSFSv7H0ERqNTl4+DTFMlZmB5eVAB53aLQNam/7NL2NPtaDD7RdVrzf8uJzMuOA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.43.tgz", + "integrity": "sha512-hU6U6VnVhBGQDpvlnnDlIB8ZGJBiOcgk2lh/0InltHiz3D8oSkluvuvY+do1G2H3+udeKFsmaBlgVYP7gXQzEw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.43", + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.43.tgz", + "integrity": "sha512-Bb2Jc0YjjJdMt1SJmb9b2L/IWd3I8lIT9x9eS/xvvP9CiVgna0ffua74xKRmt4/uSJ+0r4iN8ex1jrqkhQGWQw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.43", + "@vue/runtime-core": "3.5.43", + "@vue/shared": "3.5.43", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.43.tgz", + "integrity": "sha512-l2Ygjv9NehV94PSBxNWsAHC0j/eIIKbn92mBuWXAPGLnn6HfJ6MH5ubsd+Nk0YoZ5FRuxWI1P2VSoh+dbPQhCQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.43", + "@vue/runtime-dom": "3.5.43", + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.43.tgz", + "integrity": "sha512-uksS7YGMR5NZyr4JNq0Rp+QyLns0ueaz20KwzIPW9R0LH1Vnt4E+XUM29PNseEbf1www2gOuhuDi5AKOIXag9Q==", + "license": "MIT" + }, + "node_modules/@vue/test-utils": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@vue/test-utils/-/test-utils-2.5.1.tgz", + "integrity": "sha512-V/4a99odJ7hapr0bRt35XxljGk8hefq31gSOnlKTcEq2fUeoj2qb+FcpJYfQu4qfYhW9Ug+O2+CZ3QmZ7gXDzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-beautify": "^2.0.0", + "vue-component-type-helpers": "^3.0.0" + }, + "peerDependencies": { + "@vue/compiler-dom": "3.x", + "@vue/server-renderer": "3.x", + "vue": "3.x" + }, + "peerDependenciesMeta": { + "@vue/server-renderer": { + "optional": true + } + } + }, + "node_modules/abbrev": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-5.0.0.tgz", + "integrity": "sha512-/XrFJgzQQQHpti1raDJC6m4ws6aNktmjBlhk8Fdlk7LwCEuDoieEJJY9OFHjfiFJFFRM2tK+Ky/IsfbbmlMu1w==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/alien-signals": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-3.2.1.tgz", + "integrity": "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/b-tween": { + "version": "0.3.3", + "resolved": "https://registry.npmmirror.com/b-tween/-/b-tween-0.3.3.tgz", + "integrity": "sha512-oEHegcRpA7fAuc9KC4nktucuZn2aS8htymCPcP3qkEGPqiBH+GfqtqoG2l7LxHngg6O0HFM7hOeOYExl1Oz4ZA==", + "license": "MIT" + }, + "node_modules/b-validate": { + "version": "1.5.3", + "resolved": "https://registry.npmmirror.com/b-validate/-/b-validate-1.5.3.tgz", + "integrity": "sha512-iCvCkGFskbaYtfQ0a3GmcQCHl/Sv1GufXFGuUQ+FE+WJa7A/espLOuFIn09B944V8/ImPj71T4+rTASxO2PAuA==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/bidi-js": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/bidi-js/-/bidi-js-1.1.0.tgz", + "integrity": "sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.12", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/chai": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/chai/-/chai-6.3.0.tgz", + "integrity": "sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmmirror.com/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "1.0.20", + "resolved": "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", + "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==", + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmmirror.com/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-anything": { + "version": "4.1.5", + "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-4.1.5.tgz", + "integrity": "sha512-vePst2VLTSqPglW7Q98VwFpGiGpOHTyXIo81MO5VyLecA5zMbZw/P/V1vmwD1jksa2iJpn/YkDrJ3XhTfzUyhQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/data-urls/-/data-urls-8.0.0.tgz", + "integrity": "sha512-JQUCCK+/CAGbGGx618PlFZMXH81Jtj7t73CHv9dd/zVWvxgGT2zLFRjnKb+Ng46GIwcy+f7f88qd4duqllK+WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^17.1.2" + }, + "engines": { + "node": "^22.14.0 || >=24.0.0" + } + }, + "node_modules/dayjs": { + "version": "1.11.23", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.23.tgz", + "integrity": "sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==", + "license": "MIT" + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/editorconfig": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/editorconfig/-/editorconfig-3.0.2.tgz", + "integrity": "sha512-T0ix8GhtxyKVfUFEcvdNDt3YGqlwkFHbD4/5bgFUDgFmxhI/cSRAeJ87/Sz//Cq8Eam6JX/e23RkoFO71P7aAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@one-ini/wasm": "0.2.1", + "commander": "^14.0.3", + "minimatch": "~10.2.4", + "semver": "^7.7.4" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmmirror.com/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/html-encoding-sniffer": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-7.0.0.tgz", + "integrity": "sha512-UikN5yr7xsCDAq87Or5or0PAlD3HJJOKVzM05az588WnpDJ4Ux7a2A53Qi6gofGg2/EtvF/H4hCi/TXfCW4Y6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.15.1" + }, + "engines": { + "node": "^22.13.0 || >=24.0.0" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-beautify": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/js-beautify/-/js-beautify-2.0.3.tgz", + "integrity": "sha512-cyFbh3tkPhknnTD/0bLf0T0yy2ZIbqL05mttzbt4y1Zfr7NxqXQZ62dkBLKs3oHH/lpjmDRAnciJiSUyOy8XwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^3.0.2", + "glob": "^13.0.6", + "js-cookie": "^3.0.8", + "nopt": "^10.0.1" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-cookie": { + "version": "3.0.8", + "resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.8.tgz", + "integrity": "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "30.1.2", + "resolved": "https://registry.npmmirror.com/jsdom/-/jsdom-30.1.2.tgz", + "integrity": "sha512-0FFE/jE1rppmVfUrJUgxqXjcwolZYIGtAgj1pTussMhNZxIxi7W/PvfWaMNroGi2B36X1IKHbexpZ9DhkoOPiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^7.1.3", + "@asamuzakjp/dom-selector": "^9.2.4", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.15", + "@exodus/bytes": "^1.16.0", + "css-tree": "^3.2.1", + "data-urls": "^8.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^7.0.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.5.3", + "parse5": "^8.0.1", + "saxes": "^6.0.0", + "tough-cookie": "^6.0.2", + "undici": "^8.11.2", + "w3c-xmlserializer": "^6.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^17.2.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + }, + "peerDependencies": { + "canvas": "^3.2.3" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.20", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nopt": { + "version": "10.0.1", + "resolved": "https://registry.npmmirror.com/nopt/-/nopt-10.0.1.tgz", + "integrity": "sha512-df3sBr/6ax9hSGuC3CspvLlbnX8cP5L5nZwXF8cGN8l0zSWR6BvzmQ6jPUKjvo6+/xdpkNvEcucBNUdBeeV13g==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^5.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/number-precision": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/number-precision/-/number-precision-1.6.0.tgz", + "integrity": "sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==", + "license": "MIT" + }, + "node_modules/obug": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/obug/-/obug-2.2.1.tgz", + "integrity": "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "8.1.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-8.1.0.tgz", + "integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.29", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.29.tgz", + "integrity": "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.19", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "license": "ISC" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.64.0", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.64.0.tgz", + "integrity": "sha512-gjA/kFeDfffII8COoPsvLPvE16hWDTEc1+0QKQNKUkuV8iJjqsC4xXs8/FzuL0v9EV39kuxTbAgcFoTRyy2TGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.64.0", + "@rollup/rollup-android-arm64": "4.64.0", + "@rollup/rollup-darwin-arm64": "4.64.0", + "@rollup/rollup-darwin-x64": "4.64.0", + "@rollup/rollup-freebsd-arm64": "4.64.0", + "@rollup/rollup-freebsd-x64": "4.64.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.64.0", + "@rollup/rollup-linux-arm-musleabihf": "4.64.0", + "@rollup/rollup-linux-arm64-gnu": "4.64.0", + "@rollup/rollup-linux-arm64-musl": "4.64.0", + "@rollup/rollup-linux-loong64-gnu": "4.64.0", + "@rollup/rollup-linux-loong64-musl": "4.64.0", + "@rollup/rollup-linux-ppc64-gnu": "4.64.0", + "@rollup/rollup-linux-ppc64-musl": "4.64.0", + "@rollup/rollup-linux-riscv64-gnu": "4.64.0", + "@rollup/rollup-linux-riscv64-musl": "4.64.0", + "@rollup/rollup-linux-s390x-gnu": "4.64.0", + "@rollup/rollup-linux-x64-gnu": "4.64.0", + "@rollup/rollup-linux-x64-musl": "4.64.0", + "@rollup/rollup-openbsd-x64": "4.64.0", + "@rollup/rollup-openharmony-arm64": "4.64.0", + "@rollup/rollup-win32-arm64-msvc": "4.64.0", + "@rollup/rollup-win32-ia32-msvc": "4.64.0", + "@rollup/rollup-win32-x64-gnu": "4.64.0", + "@rollup/rollup-win32-x64-msvc": "4.64.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "2.2.31", + "resolved": "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", + "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^1.0.20" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmmirror.com/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmmirror.com/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/std-env/-/std-env-4.3.0.tgz", + "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==", + "dev": true, + "license": "MIT" + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.3.1.tgz", + "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/tinyrainbow/-/tinyrainbow-3.2.0.tgz", + "integrity": "sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "7.4.16", + "resolved": "https://registry.npmmirror.com/tldts/-/tldts-7.4.16.tgz", + "integrity": "sha512-QwBER5KMR86IIjpIiO7H/Z3IMJPsZ1A6RKPAqzTTgOyUQUSt9FdnKcqhTaJmkY6HVrgouZHZR0ncK5QxvmnQeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.4.16" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.4.16", + "resolved": "https://registry.npmmirror.com/tldts-core/-/tldts-core-7.4.16.tgz", + "integrity": "sha512-MDolfaSJtlSK5Y0A1xl3277ekubZwobpBjugknDizI9O5Rm60a1m8k4ICK+MRsCDzPygT81mp3BBf5RKDlFRfA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-6.0.2.tgz", + "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-7.0.0.tgz", + "integrity": "sha512-BcDSDW+SIGWVOns1Zm6Yg91q9AEj7eaID0QDY9oIqJD1A8dscNwMcl9Sms2DeuWCNov1X0/oXanHGYQBSLwZsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": "^22.14.0 || >=24.0.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "8.11.2", + "resolved": "https://registry.npmmirror.com/undici/-/undici-8.11.2.tgz", + "integrity": "sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.3.7", + "resolved": "https://registry.npmmirror.com/vite/-/vite-7.3.7.tgz", + "integrity": "sha512-AHEzTORMbi7/7aXp7w7KZ5+DCUdSeLsJz0grY8xHpc9DHdYb0vQu6DqJfm2tOw3gDExNgPgnJTXxM6syYFHaCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.1.11", + "resolved": "https://registry.npmmirror.com/vitest/-/vitest-4.1.11.tgz", + "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.11", + "@vitest/mocker": "4.1.11", + "@vitest/pretty-format": "4.1.11", + "@vitest/runner": "4.1.11", + "@vitest/snapshot": "4.1.11", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.11", + "@vitest/browser-preview": "4.1.11", + "@vitest/browser-webdriverio": "4.1.11", + "@vitest/coverage-istanbul": "4.1.11", + "@vitest/coverage-v8": "4.1.11", + "@vitest/ui": "4.1.11", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vscode-uri": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.2.0.tgz", + "integrity": "sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.43.tgz", + "integrity": "sha512-o5qZoksdnjIKvW1srZ3ab7pcDNYAerBjRe54D0LBLfRdCYFrSgBHVXokMas35czQc0//lmx4/tuY4ZNQ+Rf2Ng==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.43", + "@vue/compiler-sfc": "3.5.43", + "@vue/runtime-dom": "3.5.43", + "@vue/server-renderer": "3.5.43", + "@vue/shared": "3.5.43" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-component-type-helpers": { + "version": "3.3.12", + "resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.3.12.tgz", + "integrity": "sha512-HwCqmgTfLFskQc4P5TRnbduCMyPat2Ezu0elLWOGn0dD/6BKHP15B5bxce6aDi+E4kblPtru8amIBQzu0Di3qQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue-i18n": { + "version": "11.4.13", + "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-11.4.13.tgz", + "integrity": "sha512-2G7LC9XcdZ0IljFib7lKGHNiBBOTv6HO+2bnBaOiQgDYZ+uUnqSpuED5DbBo1t7su50o/WRGn+ZfDQTGd26xEw==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "11.4.13", + "@intlify/devtools-types": "11.4.13", + "@intlify/shared": "11.4.13", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-i18n/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/vue-router/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/vue-tsc": { + "version": "3.3.12", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-3.3.12.tgz", + "integrity": "sha512-kbpaz18O9jPVkXVHD1BEjpUXM6WhXSu+62L1sGGr6Wbzd8GbvkBQWjoj3KZ/C0aq2MZllce7UdtWzwCIYsBMGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.3.12" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/w3c-xmlserializer/-/w3c-xmlserializer-6.0.0.tgz", + "integrity": "sha512-4Nsy8K5Tr6SPDH9jhKJOHf7ChDrc1zufZTVSF7x72hwuEXBqxqk9G6cK+K2NRUtB3iELRJqjXb4JPDMBjMTl2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-url": { + "version": "17.2.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-17.2.0.tgz", + "integrity": "sha512-IhLIHNcBrzIixC5XXsbr4DxdjajyA5vQ5RwGZMtrUp+GbtE5Nrsge9QKau7jXrC0aTXLYGV0xiW7Tb4YS2aomw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.16.0", + "tr46": "^7.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^22.14.0 || >=24.0.0" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/apps/showcase_ui_v2/package.json b/apps/showcase_ui_v2/package.json new file mode 100644 index 000000000..aaad31e7f --- /dev/null +++ b/apps/showcase_ui_v2/package.json @@ -0,0 +1,32 @@ +{ + "name": "artemis-showcase-ui-v2", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "ARTEMIS showcase UI v2 - Vue 3 + Arco Design Vue rewrite (M0 scaffold)", + "scripts": { + "dev": "vite", + "build": "vue-tsc --noEmit && vite build", + "preview": "vite preview", + "test": "vitest run", + "test:watch": "vitest", + "typecheck": "vue-tsc --noEmit" + }, + "dependencies": { + "@arco-design/web-vue": "~2.58.0", + "pinia": "^3.0.0", + "vue": "^3.5.13", + "vue-i18n": "^11.1.0", + "vue-router": "^4.5.0" + }, + "devDependencies": { + "@types/node": "^24.0.0", + "@vitejs/plugin-vue": "^6.0.0", + "@vue/test-utils": "^2.4.6", + "jsdom": "^30.0.0", + "typescript": "~5.9.0", + "vite": "^7.0.0", + "vitest": "^4.1.0", + "vue-tsc": "^3.0.0" + } +} diff --git a/apps/showcase_ui_v2/src/App.vue b/apps/showcase_ui_v2/src/App.vue new file mode 100644 index 000000000..7c3cc2a82 --- /dev/null +++ b/apps/showcase_ui_v2/src/App.vue @@ -0,0 +1,24 @@ + + + diff --git a/apps/showcase_ui_v2/src/locales/en-US.ts b/apps/showcase_ui_v2/src/locales/en-US.ts new file mode 100644 index 000000000..86a41ec69 --- /dev/null +++ b/apps/showcase_ui_v2/src/locales/en-US.ts @@ -0,0 +1,25 @@ +/** + * en-US 文案(次要 locale,键集必须与 zh-CN 保持一致,由测试锁定)。 + */ +export default { + nav: { + launcher: 'Launcher', + workspace: 'Workspace', + }, + app: { + title: 'ARTEMIS Console', + }, + launcher: { + title: 'ARTEMIS Console (Vue Edition)', + description: + 'M0 scaffold placeholder for the Angular to Vue 3 + Arco Design Vue migration. The Angular app still serves the main path; the cutover happens at M6.', + ping: 'Test backend connection', + pingOk: 'Backend reachable (/api/status → 200)', + pingFail: 'Backend request failed: {reason}', + }, + workspace: { + title: 'Workspace', + description: + 'Workspace placeholder: the AgentStream timeline, task queue and floating player arrive in milestones M1-M4.', + }, +}; diff --git a/apps/showcase_ui_v2/src/locales/index.ts b/apps/showcase_ui_v2/src/locales/index.ts new file mode 100644 index 000000000..5eb599537 --- /dev/null +++ b/apps/showcase_ui_v2/src/locales/index.ts @@ -0,0 +1,22 @@ +import { createI18n } from 'vue-i18n'; + +import enUS from './en-US'; +import zhCN from './zh-CN'; + +/** 界面默认中文(决策 D3:对等迁移 + 中文界面)。 */ +export const DEFAULT_LOCALE = 'zh-CN' as const; + +export const SUPPORTED_LOCALES = ['zh-CN', 'en-US'] as const; +export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number]; + +const i18n = createI18n({ + legacy: false, + locale: DEFAULT_LOCALE, + fallbackLocale: DEFAULT_LOCALE, + messages: { + 'zh-CN': zhCN, + 'en-US': enUS, + }, +}); + +export default i18n; diff --git a/apps/showcase_ui_v2/src/locales/locales.spec.ts b/apps/showcase_ui_v2/src/locales/locales.spec.ts new file mode 100644 index 000000000..32e1b240c --- /dev/null +++ b/apps/showcase_ui_v2/src/locales/locales.spec.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from 'vitest'; + +import { DEFAULT_LOCALE } from './index'; +import enUS from './en-US'; +import zhCN from './zh-CN'; + +/** 递归收集文案对象的叶子 key 集合。 */ +function flattenKeys(obj: Record, prefix = ''): string[] { + return Object.entries(obj).flatMap(([key, value]) => { + const path = prefix ? `${prefix}.${key}` : key; + if (value && typeof value === 'object') { + return flattenKeys(value as Record, path); + } + return [path]; + }); +} + +describe('locales', () => { + it('defaults to zh-CN (decision D3: 中文界面)', () => { + expect(DEFAULT_LOCALE).toBe('zh-CN'); + }); + + it('contains the M0 skeleton keys', () => { + expect(zhCN.nav.launcher).toBe('启动器'); + expect(zhCN.nav.workspace).toBe('工作台'); + expect(enUS.nav.launcher).toBe('Launcher'); + expect(enUS.nav.workspace).toBe('Workspace'); + }); + + it('zh-CN and en-US share the exact same key set', () => { + expect(flattenKeys(zhCN).sort()).toEqual(flattenKeys(enUS).sort()); + }); +}); diff --git a/apps/showcase_ui_v2/src/locales/zh-CN.ts b/apps/showcase_ui_v2/src/locales/zh-CN.ts new file mode 100644 index 000000000..32ebda92d --- /dev/null +++ b/apps/showcase_ui_v2/src/locales/zh-CN.ts @@ -0,0 +1,25 @@ +/** + * zh-CN 文案(默认 locale)。M0 仅埋骨架 key,后续里程碑按模块补全。 + */ +export default { + nav: { + launcher: '启动器', + workspace: '工作台', + }, + app: { + title: 'ARTEMIS 控制台', + }, + launcher: { + title: 'ARTEMIS 控制台(Vue 版)', + description: + '这是 Angular 前端向 Vue 3 + Arco Design Vue 迁移的 M0 脚手架占位页。当前 Angular 版本仍在主路径服务,切换发生在 M6。', + ping: '测试后端连接', + pingOk: '后端连接正常(/api/status → 200)', + pingFail: '后端连接失败:{reason}', + }, + workspace: { + title: '工作台', + description: + '工作台占位页:AgentStream 时间线、任务队列与浮动播放器将在 M1-M4 里程碑实现。', + }, +}; diff --git a/apps/showcase_ui_v2/src/main.ts b/apps/showcase_ui_v2/src/main.ts new file mode 100644 index 000000000..206af667d --- /dev/null +++ b/apps/showcase_ui_v2/src/main.ts @@ -0,0 +1,23 @@ +import { createPinia } from 'pinia'; +import { createApp } from 'vue'; +import ArcoVue from '@arco-design/web-vue'; + +import App from './App.vue'; +import i18n from './locales'; +import router from './router'; + +import '@arco-design/web-vue/dist/arco.css'; +import './styles/index.css'; + +// 暗色主题:ConfigProvider 的 theme="dark" 覆盖组件树; +// body 上的 arco-theme 属性让 Arco 的全局 CSS 变量(页面背景等)切换到暗色。 +document.body.setAttribute('arco-theme', 'dark'); + +const app = createApp(App); + +app.use(createPinia()); +app.use(router); +app.use(i18n); +app.use(ArcoVue); + +app.mount('#app'); diff --git a/apps/showcase_ui_v2/src/router/index.ts b/apps/showcase_ui_v2/src/router/index.ts new file mode 100644 index 000000000..f3dd40bbc --- /dev/null +++ b/apps/showcase_ui_v2/src/router/index.ts @@ -0,0 +1,36 @@ +import { createRouter, createWebHistory } from 'vue-router'; + +/** + * 路由表与 Angular 版 app.routes.ts 的三条路由对齐: + * - `/` → LauncherView(原 HomeComponent:System Setup + Task Launcher) + * - `/workspace` → WorkspaceView(原 WorkspaceComponent) + * - `/check` → Angular 旧版流视图已淘汰(M3 后由 workspace 完整替代),重定向到 /workspace + * - catch-all → 重定向回 `/` + * + * history 模式由 FastAPI serve_showcase_spa 的 index.html 兜底天然支持。 + */ +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'launcher', + component: () => import('@/views/LauncherView.vue'), + }, + { + path: '/workspace', + name: 'workspace', + component: () => import('@/views/WorkspaceView.vue'), + }, + { + path: '/check', + redirect: '/workspace', + }, + { + path: '/:pathMatch(.*)*', + redirect: '/', + }, + ], +}); + +export default router; diff --git a/apps/showcase_ui_v2/src/stores/index.ts b/apps/showcase_ui_v2/src/stores/index.ts new file mode 100644 index 000000000..daa48393e --- /dev/null +++ b/apps/showcase_ui_v2/src/stores/index.ts @@ -0,0 +1,14 @@ +import { createPinia } from 'pinia'; + +/** + * 全局 Pinia 实例(替代 Angular 的两个 providedIn: 'root' service 信号状态)。 + * + * M0 仅注册 Pinia;M1 起按迁移方案拆分 store: + * - stores/session.ts(会话合并算法 + 轮询 + 乐观更新) + * - stores/stream.ts(SSE 连接与合批) + * - stores/player.ts(视频回放状态机) + * - stores/system.ts(系统诊断轮询) + */ +const pinia = createPinia(); + +export default pinia; diff --git a/apps/showcase_ui_v2/src/styles/index.css b/apps/showcase_ui_v2/src/styles/index.css new file mode 100644 index 000000000..c1d996e6b --- /dev/null +++ b/apps/showcase_ui_v2/src/styles/index.css @@ -0,0 +1,51 @@ +/* + * 全局样式入口 —— Arco Design Vue 暗色主题基调。 + * + * 暗色 CSS 变量来自 arco.css + body[arco-theme='dark'](main.ts 中设置)。 + * 页面级样式后续按 Arco token 重做,不逐像素复刻 Angular 版手写 SCSS。 + */ + +:root { + color-scheme: dark; +} + +html, +body, +#app { + height: 100%; +} + +body { + margin: 0; + background-color: var(--color-bg-1); + color: var(--color-text-1); + font-family: + Inter, + 'Segoe UI', + 'PingFang SC', + 'Hiragino Sans GB', + 'Microsoft YaHei', + sans-serif; + -webkit-font-smoothing: antialiased; +} + +/* 占位页通用布局(M1 起逐步替换为正式布局组件) */ +.page { + max-width: 960px; + margin: 0 auto; + padding: 32px 24px; +} + +.page-title { + margin: 0 0 12px; + font-size: 24px; + font-weight: 600; + color: var(--color-text-1); +} + +.page-desc { + margin: 0 0 20px; + font-size: 14px; + line-height: 1.7; + color: var(--color-text-2); +} diff --git a/apps/showcase_ui_v2/src/test/setup.ts b/apps/showcase_ui_v2/src/test/setup.ts new file mode 100644 index 000000000..79bd826e5 --- /dev/null +++ b/apps/showcase_ui_v2/src/test/setup.ts @@ -0,0 +1,28 @@ +/** + * Vitest 环境垫片:jsdom 缺少 Arco 部分组件依赖的浏览器 API。 + */ + +// ResizeObserver(a-space / a-tag 等弹层与布局组件使用) +if (!('ResizeObserver' in globalThis)) { + class ResizeObserverStub { + observe(): void {} + unobserve(): void {} + disconnect(): void {} + } + (globalThis as Record).ResizeObserver = ResizeObserverStub; +} + +// matchMedia +if (!('matchMedia' in globalThis)) { + (globalThis as Record).matchMedia = (query: string) => + ({ + matches: false, + media: query, + onchange: null, + addListener: (): void => {}, + removeListener: (): void => {}, + addEventListener: (): void => {}, + removeEventListener: (): void => {}, + dispatchEvent: (): boolean => false, + }) as unknown as MediaQueryList; +} diff --git a/apps/showcase_ui_v2/src/types/markdown.model.ts b/apps/showcase_ui_v2/src/types/markdown.model.ts new file mode 100644 index 000000000..10b9adddc --- /dev/null +++ b/apps/showcase_ui_v2/src/types/markdown.model.ts @@ -0,0 +1,43 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface MarkdownSegment { + text: string; + bold: boolean; + code?: boolean; +} + +export interface MarkdownLine { + type: 'h1' | 'h2' | 'h3' | 'checked' | 'progress' | 'unchecked' | 'list-item' | 'verify' | 'assert' | 'finding' | 'text' | 'empty'; + segments: MarkdownSegment[]; + indent: number; + checkKind?: 'verify' | 'assert' | 'finding'; + atEnd?: boolean; +} + +export interface NoteMilestone { + index: number; + type: 'checked' | 'progress' | 'unchecked'; + segments: MarkdownSegment[]; + subSteps: MarkdownLine[]; + checks: MarkdownLine[]; +} + +export interface ParsedNote { + title: string | null; + milestones: NoteMilestone[]; + otherLines: MarkdownLine[]; +} diff --git a/apps/showcase_ui_v2/src/types/models.spec.ts b/apps/showcase_ui_v2/src/types/models.spec.ts new file mode 100644 index 000000000..7af05a091 --- /dev/null +++ b/apps/showcase_ui_v2/src/types/models.spec.ts @@ -0,0 +1,119 @@ +import { describe, expect, it } from 'vitest'; + +import { + DEFAULT_EXPLORER_MODE, + DEFAULT_VERIFICATION_LEVEL, + EXPLORER_MODES, + VERIFICATION_LEVELS, + levelIndex, + notchPercent, +} from './pro-tuning.model'; +import { DEFAULT_STREAM_RESET_MESSAGE } from './stream.model'; +import type { + AgentStatusResponse, + Session, + SessionUsage, + TaskQueueItem, +} from './session.model'; +import type { CheckerBlockData, StepBlock, StepItemData } from './stream.model'; +import type { MarkdownLine, MarkdownSegment, ParsedNote } from './markdown.model'; +import type { SystemReadinessReport } from './system.model'; + +/** + * 类型平移冒烟测试:core/models 下的 5 个模型文件从 Angular 工程 + * 原样复制而来,此处验证其可在无 Angular 依赖的 Vue 工程中正常 + * 编译与执行(类型仅作编译期检查,运行时断言覆盖纯函数)。 + */ + +describe('pro-tuning.model (copied verbatim from Angular project)', () => { + it('exposes the documented defaults', () => { + expect(DEFAULT_VERIFICATION_LEVEL).toBe('final'); + expect(DEFAULT_EXPLORER_MODE).toBe('flash'); + expect(VERIFICATION_LEVELS.map((l) => l.id)).toEqual([ + 'off', + 'final', + 'checkpoints', + 'strict', + ]); + expect(EXPLORER_MODES.map((l) => l.id)).toEqual(['flash', 'pro', 'ultra']); + }); + + it('levelIndex resolves ids and falls back', () => { + expect(levelIndex(VERIFICATION_LEVELS, 'strict', DEFAULT_VERIFICATION_LEVEL)).toBe(3); + expect(levelIndex(VERIFICATION_LEVELS, 'unknown', DEFAULT_VERIFICATION_LEVEL)).toBe(1); + expect(levelIndex(EXPLORER_MODES, null, DEFAULT_EXPLORER_MODE)).toBe(0); + }); + + it('notchPercent maps an index onto 0-100', () => { + expect(notchPercent(0, 4)).toBe(0); + expect(notchPercent(3, 4)).toBe(100); + expect(notchPercent(1, 4)).toBeCloseTo(33.33, 1); + expect(notchPercent(2, 1)).toBe(0); + }); +}); + +describe('stream.model (copied verbatim)', () => { + it('exports the default stream reset message', () => { + expect(DEFAULT_STREAM_RESET_MESSAGE).toContain('Retrying automatically'); + }); +}); + +describe('type contracts compile without Angular dependencies', () => { + it('accepts wire-shaped payloads', () => { + const status: AgentStatusResponse = { + status: 'idle', + session_id: null, + queue: [], + }; + const session: Session = { + session_id: 's1', + initial_goal: 'demo', + start_time: 0, + }; + const queueItem: TaskQueueItem = { + session_id: 's1', + goal: 'demo', + status: 'pending', + }; + const usage: SessionUsage = { + session_id: 's1', + llm_calls: 0, + prompt_tokens: 0, + completion_tokens: 0, + total_tokens: 0, + cached_tokens: 0, + operator_context_tokens: null, + operator_context_window_tokens: 0, + }; + const step: StepItemData = { + step_id: 's1#1', + step_number: 1, + session_id: 's1', + timestamp: 0, + }; + const readiness: SystemReadinessReport = { + overall_ready: false, + blocker_count: 0, + passed_blocker_count: 0, + probes: [], + active_device: null, + timestamp: 0, + }; + const note: ParsedNote = { title: null, milestones: [], otherLines: [] }; + const segment: MarkdownSegment = { text: 'hi', bold: false }; + const line: MarkdownLine = { type: 'text', segments: [segment], indent: 0 }; + const block: StepBlock = { id: 'b1', type: 'step', timestamp: '0', data: step }; + const checker: CheckerBlockData = { phase: 'checkpoint', status: 'running' }; + + expect(status.status).toBe('idle'); + expect(session.initial_goal).toBe('demo'); + expect(queueItem.status).toBe('pending'); + expect(usage.total_tokens).toBe(0); + expect(step.step_number).toBe(1); + expect(readiness.probes).toHaveLength(0); + expect(note.otherLines).toHaveLength(0); + expect(line.segments[0]?.text).toBe('hi'); + expect(block.type).toBe('step'); + expect(checker.phase).toBe('checkpoint'); + }); +}); diff --git a/apps/showcase_ui_v2/src/types/pro-tuning.model.ts b/apps/showcase_ui_v2/src/types/pro-tuning.model.ts new file mode 100644 index 000000000..9e57c3eef --- /dev/null +++ b/apps/showcase_ui_v2/src/types/pro-tuning.model.ts @@ -0,0 +1,165 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Launcher options for `/api/run` (`verification_level`, `explorer_mode`). + * Keep ids in sync with `VERIFICATION_LEVEL_PRESETS` in `artemis/config/agent.py` + * and `EXPLORER_TIERS` in `artemis/agents/explorer/tiers.py`. + */ + +export type VerificationLevelId = 'off' | 'final' | 'checkpoints' | 'strict'; +export type ExplorerModeId = 'flash' | 'pro' | 'ultra'; + +/** One notch on a tuning slider. */ +export interface TuningLevel { + /** Wire value sent to the backend. */ + id: TId; + /** Short name shown next to the slider title and as the hover card heading. */ + label: string; + /** One-sentence summary shown in the hover card. */ + tagline: string; + /** Plain-language time cost, e.g. "no extra time". */ + latency: string; + /** Checks or searches performed at this level. */ + runs: string[]; + /** Checks or searches omitted at this level. */ + skips?: string[]; + /** When to pick this level. */ + bestFor: string; +} + +export const VERIFICATION_LEVELS: readonly TuningLevel[] = [ + { + id: 'off', + label: 'Off', + tagline: 'No checking. The run ends as soon as the task looks done.', + latency: 'no extra time', + runs: [ + 'Each step is treated as finished the moment it is carried out.', + 'You get the full action trace, but no pass / fail verdict.' + ], + skips: ['Nothing is double-checked and nothing is retried.'], + bestFor: 'Quick tries and demos, when you only want to watch what happens.' + }, + { + id: 'final', + label: 'At the end', + tagline: 'One check of the finished result against your goal. This is the default.', + latency: 'adds about 20–60 s at the end', + runs: [ + 'When the task finishes, the final screen, the step history and the device state are compared with what you asked for.', + 'If the result does not match, the task goes back and tries to fix it, up to 3 times.' + ], + skips: ['Nothing is checked while the task is still running.'], + bestFor: 'Everyday tasks: an honest pass / fail without slowing the run down.' + }, + { + id: 'checkpoints', + label: 'Every step', + tagline: 'Each step is checked as soon as it is done, plus the final check.', + latency: 'a short check after each step, done in the background', + runs: [ + 'Every step is checked right after it completes, using the screenshots from that moment.', + 'If a step went wrong, it gets fixed before moving on (up to 2 tries per step).', + 'A failed test condition is written down and the task keeps going.', + 'The final check still runs at the end.' + ], + bestFor: 'Long tasks where one early mistake would spoil everything after it.' + }, + { + id: 'strict', + label: 'Strict', + tagline: 'Every step is checked, with more retries. The first failed test stops the run.', + latency: 'slowest: more checks and more retries', + runs: [ + 'Each check takes longer and gets more attempts: 4 fixes per step and 5 at the end.', + 'The first failed test condition stops the run immediately, with the evidence attached.' + ], + bestFor: 'Release checks and regression runs, where a wrong pass is never acceptable.' + } +]; + +export const EXPLORER_MODES: readonly TuningLevel[] = [ + { + id: 'flash', + label: 'Quick glance', + tagline: 'Finds buttons and text on the screen in a single look.', + latency: '1 look per search', + runs: [ + 'Something on screen is asked for by name, icon or colour and its position comes back straight away.', + 'Several things can be looked up at once.' + ], + skips: ['No zooming in and no second try.'], + bestFor: 'Ordinary apps with clearly labelled buttons, icons and text.' + }, + { + id: 'pro', + label: 'Second look', + tagline: 'Takes up to 3 looks, thinking in between, before answering.', + latency: 'up to 3 looks per search', + runs: [ + 'The screen layout is read first, then the picture is searched.', + 'If the first try misses, a different approach is tried within the 3 looks.' + ], + skips: ['Still no zooming into small areas, to keep searches short.'], + bestFor: 'Things described by where they are ("the switch next to Wi-Fi") or with unclear labels.' + }, + { + id: 'ultra', + label: 'Close-up', + tagline: 'Zooms into parts of the screen and takes up to 8 looks.', + latency: 'up to 8 looks per search (slowest)', + runs: [ + 'Parts of the screen can be cropped and magnified to read tiny text and crowded layouts piece by piece.', + 'Later looks reuse the earlier ones, so they cost less time than they sound.' + ], + bestFor: 'Crowded screens, tiny targets, charts and drawings, and checks where exact placement matters.' + } +]; + +/** Per-run tuning sent with `/api/run` for the Pro profile. */ +export interface ProTuningOptions { + verificationLevel?: VerificationLevelId | string; + explorerMode?: ExplorerModeId | string; +} + +/** Effective defaults reported by `GET /api/run/defaults`. */ +export interface ProTuningDefaults { + verification_level?: string | null; + explorer_mode?: string | null; +} + +export const DEFAULT_VERIFICATION_LEVEL: VerificationLevelId = 'final'; +export const DEFAULT_EXPLORER_MODE: ExplorerModeId = 'flash'; + +/** Index of a level id within its ladder; falls back to the default when unknown. */ +export function levelIndex( + ladder: readonly TuningLevel[], + id: string | null | undefined, + fallback: TId +): number { + const wanted = String(id ?? '').trim().toLowerCase(); + const idx = ladder.findIndex((l) => l.id === wanted); + if (idx >= 0) return idx; + return Math.max(0, ladder.findIndex((l) => l.id === fallback)); +} + +/** Slider fill percentage for a notch index on a ladder of `count` notches. */ +export function notchPercent(index: number, count: number): number { + if (count <= 1) return 0; + const clamped = Math.min(Math.max(index, 0), count - 1); + return (clamped / (count - 1)) * 100; +} diff --git a/apps/showcase_ui_v2/src/types/session.model.ts b/apps/showcase_ui_v2/src/types/session.model.ts new file mode 100644 index 000000000..ef322d1cf --- /dev/null +++ b/apps/showcase_ui_v2/src/types/session.model.ts @@ -0,0 +1,85 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface ModelInfo { + name: string; + id: string; + provider: string; + architecture?: string; +} + +export interface TaskQueueItem { + session_id: string; + goal: string; + profile?: string; + status: 'pending' | 'running' | 'paused' | 'completed' | 'failed' | 'cancelled'; + created_at?: number; + start_time?: number; + device_serial?: string | null; + device_id?: string | null; +} + +export interface Session { + session_id: string; + initial_goal: string; + start_time: number; + end_time?: number; + status?: string; + video_url?: string; + recording_status?: 'recording' | 'finalizing' | 'processing' | 'ready' | 'failed' | 'unavailable'; + model_info?: ModelInfo; + device_serial?: string | null; + device_id?: string | null; + device_info?: any; +} + +export interface AgentStatusResponse { + status: 'idle' | 'running' | 'paused' | 'completed' | 'offline'; + session_id?: string | null; + goal?: string | null; + pid?: number | null; + queue?: (TaskQueueItem | string)[]; + background_tasks?: any[]; + model_info?: ModelInfo | null; + paused_error?: string | null; +} + +/** Per-run Pro tuning persisted with the session (`device_info.run_tuning`). */ +export interface SessionRunTuning { + verification_level?: string | null; + explorer_mode?: string | null; +} + +/** `GET /api/sessions/{id}/usage`: session-wide LLM usage and the live executor context. */ +export interface SessionUsage { + session_id: string; + llm_calls: number; + prompt_tokens: number; + completion_tokens: number; + total_tokens: number; + cached_tokens: number; + /** Prompt size of the latest Operator / Flash runner call; null before the first call. */ + operator_context_tokens: number | null; + operator_context_window_tokens: number; + operator_context_updated_at?: number | null; + profile?: string | null; + run_tuning?: SessionRunTuning | null; +} + +export type AgentStatus = 'idle' | 'running' | 'completed' | 'offline' | string; + +export type TaskStatus = 'running' | 'paused' | 'completed' | 'pending' | 'failed' | 'cancelled'; + diff --git a/apps/showcase_ui_v2/src/types/stream.model.ts b/apps/showcase_ui_v2/src/types/stream.model.ts new file mode 100644 index 000000000..86645f094 --- /dev/null +++ b/apps/showcase_ui_v2/src/types/stream.model.ts @@ -0,0 +1,246 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface ActionParam { + key: string; + value: string; +} + +export interface ActionExecution { + id?: string; + trace_id?: string; + agent?: string; + agent_name?: string; + action: string; + name?: string; + args?: Record; + params?: Record; + payload?: any; + pre_image_name?: string | null; + post_image_name?: string | null; + status?: 'success' | 'failed' | 'error' | 'running' | string; + duration?: number; + duration_ms?: number; + error?: string | null; + timestamp?: number; +} + +export interface StepEvent { + type: 'thinking' | 'text' | 'action' | 'tool'; + data: any; + timestamp?: number; +} + +export interface LLMStreamEventData { + execution_id: string; + step_id?: string; + session_id?: string; + text?: string; + chunk?: string; + stream_type?: 'thinking' | 'text' | string; + isCompleted?: boolean; + isReset?: boolean; + resetMessage?: string; +} + +export const DEFAULT_STREAM_RESET_MESSAGE = + 'A request error occurred during output generation, typically caused by lower API priority. Retrying automatically...'; + +export interface StreamResetNotice { + id: string; + message: string; + isWaiting: boolean; + streamType: string; +} + +export interface LLMStreamResetEventData { + stream_exec_id?: string; + stream_execution_id?: string; + step_id?: string; + session_id?: string; + action?: 'discard' | string; + reason?: string; + category?: string; + error?: string; + message?: string; + retry_attempt?: number; + timestamp?: number; +} + +export interface StepItemData { + step_id: string; + step_type?: string; + step_number: number; + session_id: string; + timestamp: number; + operator_native_thinking?: string; + operator_raw_thinking?: string; + action_taken?: any; + generic_tools?: any[]; + last_execution_result?: any; + pre_image_name?: string; + post_image_name?: string; + extra_metadata?: any; + token_usage?: { + prompt_tokens?: number; + completion_tokens?: number; + total_tokens?: number; + }; + total_tokens?: number; + duration?: number; +} + +export interface StepBlock { + id: string; + type: 'llm_stream' | 'step' | 'checker'; + timestamp: string; + data: any; +} + +export interface PhaseBlock { + id: string; + durationSeconds: number; + tokens?: number; + promptTokens?: number; + completionTokens?: number; + blocks: StepBlock[]; +} + +/** One check item's verdict as booked by the Checker (ledger record shape). */ +export interface CheckerVerdict { + item_text: string; + kind: 'verify' | 'assert' | string; + status: 'passed' | 'failed' | 'inconclusive' | 'superseded' | 'unchecked' | string; + evidence: string; + suggestion?: string; +} + +export interface CheckerCheckItem { + kind: string; + text: string; + when?: string; +} + +/** + * One streamed LLM turn of a multi-turn agent (the Checker's tool loop): + * the text of one execution id with the time its first chunk arrived, so the + * timeline can interleave it with the tool calls that followed. Live sessions + * build these from `llm_stream` chunks; historical sessions rebuild them from + * the persisted transcript (`PersistedCheckerStream`). + */ +export interface StreamSegment { + execution_id: string; + stream_type: 'thinking' | 'text'; + text: string; + timestamp: string; + isCompleted?: boolean; + isReset?: boolean; + resetMessage?: string; +} + +/** One persisted segment of a Checker attempt's streamed reasoning (backend `check_streams.jsonl`). */ +export interface PersistedStreamSegment { + execution_id: string; + /** `thought` is the model's reasoning stream, `answer` its visible text. */ + role: 'thought' | 'answer' | string; + /** Unix seconds of the segment's first chunk. */ + when: number; + text: string; +} + +/** + * One Checker attempt's persisted transcript as served by + * `GET /api/sessions/{id}/checks` (`streams[]`). Text is bounded server-side; + * `truncated` says the middle was cut out. + */ +export interface PersistedCheckerStream { + attempt_id: string; + checkpoint_id?: string; + phase?: string; + trace_id?: string | null; + ts?: number; + truncated?: boolean; + dropped_chars?: number; + segments: PersistedStreamSegment[]; +} + +/** + * Data of a `checker` timeline block: one Checker attempt (a midway checkpoint + * of a completed subgoal or the exit final review), or the run outcome + * (`phase: 'outcome'`). Streamed reasoning and tool traces land in the same + * `operator_*_thinking` / `generic_tools` fields as an Operator step so the + * timeline renders them with one code path. + */ +export interface CheckerBlockData { + event?: string; + attempt_id?: string; + checkpoint_id?: string; + phase: 'checkpoint' | 'final' | 'outcome' | string; + subgoal_text?: string; + status?: 'running' | 'done' | 'superseded' | 'unchecked' | 'error' | string; + trace_id?: string | null; + anchor_step_id?: string | null; + items?: CheckerCheckItem[]; + verdicts?: CheckerVerdict[]; + findings?: string[]; + unmet_subgoals?: string[]; + reverted?: boolean; + applicable?: boolean; + repairs_used?: number; + route?: string; + error?: string; + task_status?: 'completed' | 'partial' | 'blocked' | string; + tests?: { passed: number; failed: number; inconclusive: number; unchecked: number }; + last_findings?: string[]; + started_at?: number; + finished_at?: number; + duration?: number; + isCompleted?: boolean; + generic_tools?: any[]; + /** Per-turn stream segments (live chunks or the persisted transcript); the flat fields below hold the joined text. */ + stream_segments?: StreamSegment[]; + operator_native_thinking?: string; + operator_raw_thinking?: string; + [key: string]: any; +} + +/** @deprecated legacy JSON-in-stream checker verdict (pre-ledger); kept for the parser. */ +export interface CheckerResult { + success: boolean; + reason: string; +} + +export interface StepReplayFrame { + index: number; + stepNumber: number; + rawStepNumber?: number; + stepId?: string; + title: string; + imageUrl: string; + preImageUrl?: string | null; + postImageUrl?: string | null; + action?: any; + actionType?: string; + actionText?: string; + targetText?: string; + coords?: string; + status?: 'dispatched' | 'failed' | string; + isPost?: boolean; + timestamp?: number; + phaseId?: string; + summary?: string; +} + diff --git a/apps/showcase_ui_v2/src/types/system.model.ts b/apps/showcase_ui_v2/src/types/system.model.ts new file mode 100644 index 000000000..cf15406f0 --- /dev/null +++ b/apps/showcase_ui_v2/src/types/system.model.ts @@ -0,0 +1,118 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export type ProbeStatus = 'pass' | 'warn' | 'fail' | 'skipped'; + +export type ProbeCategory = 'device' | 'auth' | 'toolchain' | 'runtime'; + +export interface ProbeAction { + action_type: 'command' | 'hint' | 'link'; + label: string; + payload: string; +} + +export interface DeviceInfo { + serial: string; + state: string; + model: string | null; + product: string | null; + android_version: string | null; + screen_resolution: string | null; + is_locked: boolean | null; + is_emulator: boolean; + installed_packages?: string[]; +} + +export interface AdbServerEndpoint { + host: string; + port: number; + socket: string; + identity: string; + mode: 'local' | 'remote'; + is_local_default: boolean; +} + +export interface AdbServerDevice { + serial: string; + state: string; + model: string | null; + product: string | null; +} + +export interface AdbServerStatus { + endpoint: AdbServerEndpoint; +} + +export interface AdbServerConnectionResult { + success: boolean; + message: string; + endpoint: AdbServerEndpoint; + devices: AdbServerDevice[]; + persisted?: boolean; + persistence_error?: string | null; + error_code?: string; + output?: string; +} + +export interface AdbServerConnectionResponse { + connection_result: AdbServerConnectionResult; + report?: SystemReadinessReport; +} + +export interface ProbeResult { + id: string; + category: ProbeCategory; + title: string; + status: ProbeStatus; + is_blocker: boolean; + summary: string; + description: string; + metadata: Record; + actions: ProbeAction[]; +} + +export interface SystemReadinessReport { + overall_ready: boolean; + blocker_count: number; + passed_blocker_count: number; + probes: ProbeResult[]; + active_device: DeviceInfo | null; + os_type?: 'linux' | 'darwin' | 'windows' | string; + timestamp: number; +} + +export type EmulatorLaunchStage = + | 'idle' + | 'starting' + | 'waiting_for_adb' + | 'booting' + | 'ready' + | 'failed' + | 'stopped'; + +export interface EmulatorLaunchState { + avd_name: string | null; + status: EmulatorLaunchStage; + pid: number | null; + serial: string | null; + stage_message: string; + progress_percent: number; + started_at: number | null; + elapsed_seconds: number; + error: string | null; + logs: string[]; + can_retry: boolean; +} diff --git a/apps/showcase_ui_v2/src/views/LauncherView.spec.ts b/apps/showcase_ui_v2/src/views/LauncherView.spec.ts new file mode 100644 index 000000000..32abf9b71 --- /dev/null +++ b/apps/showcase_ui_v2/src/views/LauncherView.spec.ts @@ -0,0 +1,34 @@ +import { mount } from '@vue/test-utils'; +import ArcoVue from '@arco-design/web-vue'; +import { describe, expect, it } from 'vitest'; +import { createI18n } from 'vue-i18n'; + +import zhCN from '../locales/zh-CN'; +import LauncherView from './LauncherView.vue'; + +/** 组件冒烟:Arco 组件能在 Vue 版工程内正常渲染。 */ +const i18n = createI18n({ + legacy: false, + locale: 'zh-CN', + messages: { 'zh-CN': zhCN }, +}); + +function mountView() { + return mount(LauncherView, { + global: { + plugins: [ArcoVue, i18n], + }, + }); +} + +describe('LauncherView (M0 placeholder)', () => { + it('renders the M0 title', () => { + const wrapper = mountView(); + expect(wrapper.text()).toContain('ARTEMIS 控制台(Vue 版)'); + }); + + it('renders an Arco button', () => { + const wrapper = mountView(); + expect(wrapper.find('.arco-btn').exists()).toBe(true); + }); +}); diff --git a/apps/showcase_ui_v2/src/views/LauncherView.vue b/apps/showcase_ui_v2/src/views/LauncherView.vue new file mode 100644 index 000000000..bca428507 --- /dev/null +++ b/apps/showcase_ui_v2/src/views/LauncherView.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/apps/showcase_ui_v2/src/views/WorkspaceView.vue b/apps/showcase_ui_v2/src/views/WorkspaceView.vue new file mode 100644 index 000000000..6e8c1de3f --- /dev/null +++ b/apps/showcase_ui_v2/src/views/WorkspaceView.vue @@ -0,0 +1,17 @@ + + + diff --git a/apps/showcase_ui_v2/src/vite-env.d.ts b/apps/showcase_ui_v2/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/apps/showcase_ui_v2/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/showcase_ui_v2/tsconfig.json b/apps/showcase_ui_v2/tsconfig.json new file mode 100644 index 000000000..468575866 --- /dev/null +++ b/apps/showcase_ui_v2/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "jsx": "preserve", + "strict": true, + "noEmit": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "useDefineForClassFields": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "types": ["vite/client"], + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"], + "exclude": ["node_modules", "dist"] +} diff --git a/apps/showcase_ui_v2/tsconfig.node.json b/apps/showcase_ui_v2/tsconfig.node.json new file mode 100644 index 000000000..6059ff4ab --- /dev/null +++ b/apps/showcase_ui_v2/tsconfig.node.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ES2022"], + "strict": true, + "noEmit": true, + "isolatedModules": true, + "esModuleInterop": true, + "skipLibCheck": true, + "types": ["node"] + }, + "include": ["vite.config.ts"] +} diff --git a/apps/showcase_ui_v2/vite.config.ts b/apps/showcase_ui_v2/vite.config.ts new file mode 100644 index 000000000..21e018d64 --- /dev/null +++ b/apps/showcase_ui_v2/vite.config.ts @@ -0,0 +1,54 @@ +/// +import { fileURLToPath, URL } from 'node:url'; + +import vue from '@vitejs/plugin-vue'; +import { defineConfig } from 'vite'; + +/** + * ARTEMIS showcase UI v2 (M0). + * + * - `base: '/'` + `build.outDir: 'dist/browser'`: FastAPI `server.py:_get_showcase_dist()` + * 的候选列表已包含 `dist/browser`,CLI/start.sh 亦兼容,零后端改动即可托管。 + * - `server.proxy`: 与 Angular `proxy.conf.json` 对齐,代理 `/api`、`/images`、 + * `/videos`、`/local_file` 到本机 FastAPI(默认 127.0.0.1:8000)。 + * `/api` 必须移除浏览器 Origin:`SameOriginBoundaryMiddleware` 校验 Origin 与 + * Host 一致,Vite 代理(changeOrigin 改写 Host)转发的请求若带 + * `Origin: http://localhost:5173` 会被 403。见调研报告 §4.3。 + */ +export default defineConfig({ + base: '/', + plugins: [vue()], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + }, + }, + build: { + outDir: 'dist/browser', + emptyOutDir: true, + }, + server: { + port: 5173, + proxy: { + '/api': { + target: 'http://127.0.0.1:8000', + changeOrigin: true, + configure(proxy) { + proxy.on('proxyReq', (proxyReq) => { + // SameOriginBoundaryMiddleware: 去掉 Origin 后请求被视为非浏览器客户端而放行。 + // 同时覆盖 SSE(EventSource 同源请求会带 Origin 头)。 + proxyReq.removeHeader('origin'); + }); + }, + }, + '/images': { target: 'http://127.0.0.1:8000' }, + '/videos': { target: 'http://127.0.0.1:8000' }, + '/local_file': { target: 'http://127.0.0.1:8000' }, + }, + }, + test: { + environment: 'jsdom', + include: ['src/**/*.{test,spec}.ts'], + setupFiles: ['src/test/setup.ts'], + }, +}); From d217e2bd4a8ee7118aacdf55e7849ccb8093ac2e Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 14:33:44 +0800 Subject: [PATCH 010/320] feat(showcase-v2): session list, task queue and command dock (migration M1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 前端重构 M1, 依调研报告 §3.2/§3.3/§5.3 与决策 D1/D3: - agent.service.ts 逻辑平移: 会话合并 4 步算法(tracking 桥接)抽为框架无关 src/utils/session-merge.ts + 32 个单测; stores/session.ts 承接 2s/6s 双频轮询、 签名去重与失效、stop/delete/clearAll 乐观更新、localStorage 缓存、 页面隐藏暂停轮询(§3.3 条款 3/4/6, 逐条有测试) - TaskQueuePanel(队列/历史 tabs + 状态 tag + popconfirm 删除/清空)、 CommandDock(Ctrl+K 唤起, flash/pro 持久化)、LauncherView 最小可用、 AppNav + system store 最小连通性轮询 - i18n zh-CN/en-US 全量补 key, 键集一致性由既有测试锁定(D3) - 修复 E2E 中发现缺陷: Ctrl+K 折叠态空操作(输入未渲染时 focus 无效), 现先展开再 nextTick 聚焦 - 主代理校验: build/test 49 用例、合并算法与 Angular 原实现逐行对照、 浏览器 E2E 真实提交任务验证 提交→运行→完成 全链路无闪烁 Angular 仍在主路径服务, 切换发生在 M6(决策 D2) --- apps/showcase_ui_v2/README.md | 43 ++ apps/showcase_ui_v2/src/App.vue | 17 +- apps/showcase_ui_v2/src/components/AppNav.vue | 119 ++++ .../src/components/CommandDock.vue | 201 ++++++ .../src/components/TaskQueuePanel.vue | 297 +++++++++ apps/showcase_ui_v2/src/locales/en-US.ts | 56 +- apps/showcase_ui_v2/src/locales/zh-CN.ts | 57 +- apps/showcase_ui_v2/src/services/api.ts | 92 +++ apps/showcase_ui_v2/src/stores/index.ts | 14 +- .../showcase_ui_v2/src/stores/session.spec.ts | 405 ++++++++++++ apps/showcase_ui_v2/src/stores/session.ts | 598 ++++++++++++++++++ apps/showcase_ui_v2/src/stores/system.spec.ts | 60 ++ apps/showcase_ui_v2/src/stores/system.ts | 68 ++ .../src/utils/session-merge.spec.ts | 292 +++++++++ .../showcase_ui_v2/src/utils/session-merge.ts | 291 +++++++++ .../src/views/LauncherView.spec.ts | 33 +- .../showcase_ui_v2/src/views/LauncherView.vue | 168 ++++- .../src/views/WorkspaceView.vue | 141 ++++- 18 files changed, 2895 insertions(+), 57 deletions(-) create mode 100644 apps/showcase_ui_v2/src/components/AppNav.vue create mode 100644 apps/showcase_ui_v2/src/components/CommandDock.vue create mode 100644 apps/showcase_ui_v2/src/components/TaskQueuePanel.vue create mode 100644 apps/showcase_ui_v2/src/services/api.ts create mode 100644 apps/showcase_ui_v2/src/stores/session.spec.ts create mode 100644 apps/showcase_ui_v2/src/stores/session.ts create mode 100644 apps/showcase_ui_v2/src/stores/system.spec.ts create mode 100644 apps/showcase_ui_v2/src/stores/system.ts create mode 100644 apps/showcase_ui_v2/src/utils/session-merge.spec.ts create mode 100644 apps/showcase_ui_v2/src/utils/session-merge.ts diff --git a/apps/showcase_ui_v2/README.md b/apps/showcase_ui_v2/README.md index ebfb93647..a651f4586 100644 --- a/apps/showcase_ui_v2/README.md +++ b/apps/showcase_ui_v2/README.md @@ -72,3 +72,46 @@ src/ M0 脚手架(当前)→ M1 会话列表/队列 → M2 详情/轨迹 → M3 SSE 实时流 → M4 回放/投屏 → M5 系统诊断 → M6 i18n/主题/打包收尾与切换。 + +## M1 完成范围(骨架 + 会话列表/队列/任务提交) + +> 对应调研报告 §5.3 的 M1 行与 §3.3 运行时语义条款 3 / 4 / 6。 + +### 交付内容 + +| 模块 | 文件 | 说明 | +| --- | --- | --- | +| fetch 封装 | `src/services/api.ts` | `apiGet` / `apiPost`,JSON 解析与错误透传(`ApiError.detail` 对应 Angular `err.error?.detail`) | +| 会话合并纯函数 | `src/utils/session-merge.ts` | 4 步合并算法 `mergeSessions`、queue 映射 `mapPendingQueue`、状态推导 `getTaskStatus`、设备序列号 `resolveDeviceSerial`、轮询签名 `statusSignature`(框架无关,配 vitest 单测) | +| 会话 store | `src/stores/session.ts` | 从 Angular `AgentService` 逻辑平移:合并算法 + **2s/6s 双频轮询** + **轮询签名去重** + **停止/删除/清空乐观更新与签名失效** + **localStorage 会话缓存**(key 与 Angular 版一致)+ pin 语义的会话选择 + **页面隐藏暂停轮询 / visibilitychange 立即刷新** | +| 系统 store(最小) | `src/stores/system.ts` | 仅 `/api/status` 连通性轮询(5s)与顶栏小圆点;完整诊断功能留给 M5 | +| 工作台 | `src/views/WorkspaceView.vue` | `a-layout` + 可拖拽分栏(rAF 合帧)+ 时间线 M2 占位 | +| 任务队列面板 | `src/components/TaskQueuePanel.vue` | 队列/历史两个 tab(`a-badge` 计数),`a-list` + `a-tag` 状态色,运行中停止、历史 `a-popconfirm` 删除、`a-popconfirm` 清空历史,点击选中会话(pin 语义) | +| 命令条 | `src/components/CommandDock.vue` | Ctrl+K / ⌘K 唤起,`a-input` 回车提交 `/api/run`,flash/pro profile 持久化,错误 5s 自动消失 | +| 顶部导航 | `src/components/AppNav.vue` | 页面入口 + 连接小圆点 + 运行器状态 tag | +| 启动器 | `src/views/LauncherView.vue` | `a-textarea` 任务提交(复用同一 store 提交路径)+ 会话数摘要(`a-statistic`);诊断向导不做(M5) | +| i18n | `src/locales/{zh-CN,en-US}.ts` | 状态 / 连接 / 队列 / 命令条 / 启动器 key 全量补齐,键集一致性由 `locales.spec.ts` 锁定 | + +### 与后端的端点契约(与 Angular 版实际调用一致) + +- `GET /api/status`(2s 轮询)、`GET /api/sessions`(6s 轮询) +- `POST /api/run`(`{goal, profile}`,可选 `expected_output` / `enable_outputter` / `verification_level` / `explorer_mode`) +- `POST /api/stop?all=&session_id=`(query + body 双通道)、`POST /api/resume` +- `POST /api/sessions/{id}/delete`、`POST /api/cleanup` + +### 测试 + +- `src/utils/session-merge.spec.ts`:合并 4 步算法逐条覆盖(含 §3.3 条款 3 的 + 「队列→运行不闪烁」桥接用例)、queue 映射、状态推导、签名去重。 +- `src/stores/session.spec.ts`:平移自 `agent.service.spec.ts` 的停止/恢复/提交用例 + + 签名去重(payload 不变时响应式引用稳定)、签名失效(乐观更新后强制重新应用)、 + 轮询节奏(2s/6s)、visibilitychange 立即刷新(§3.3 条款 6)、localStorage 缓存恢复。 + +``` +src/ + ...(M0 部分不变) + services/ api.ts(fetch 封装) + utils/ session-merge.ts(会话合并纯函数)+ spec + stores/ session.ts / system.ts(M1) + components/ AppNav / TaskQueuePanel / CommandDock(M1) +``` diff --git a/apps/showcase_ui_v2/src/App.vue b/apps/showcase_ui_v2/src/App.vue index 7c3cc2a82..944643f3b 100644 --- a/apps/showcase_ui_v2/src/App.vue +++ b/apps/showcase_ui_v2/src/App.vue @@ -1,20 +1,35 @@ @@ -635,7 +701,7 @@ function resumePausedTask(): void { "{{ getAdbCwd(item.data) }}"
- Terminal ID + {{ t('workspace.timeline.terminalId') }} {{ getAdbTerminalId(item.data) }}
@@ -847,6 +913,15 @@ function resumePausedTask(): void { font-size: 11px; } +.video-pill { + color: rgb(var(--arcoblue-6)); +} + +.video-detail { + color: var(--color-text-3); + font-size: 11px; +} + .action-card { border: 1px solid var(--color-border-2); border-radius: var(--border-radius-medium); @@ -999,6 +1074,17 @@ function resumePausedTask(): void { font-size: 12.5px; } +.reset-row { + display: flex; + align-items: flex-start; + gap: 6px; + padding: 6px 8px; + border-radius: var(--border-radius-small); + background-color: rgb(var(--orange-1) / 60%); + color: rgb(var(--orange-6)); + font-size: 12.5px; +} + .failure-retries { display: flex; flex-direction: column; diff --git a/apps/showcase_ui_v2/src/locales/en-US.ts b/apps/showcase_ui_v2/src/locales/en-US.ts index 04a35049a..4d1571213 100644 --- a/apps/showcase_ui_v2/src/locales/en-US.ts +++ b/apps/showcase_ui_v2/src/locales/en-US.ts @@ -26,7 +26,13 @@ export default { launcher: { title: 'ARTEMIS Console (Vue Edition)', description: - 'Vue 3 + Arco Design Vue rewrite (M1): submit tasks, watch the queue and the session summary. The diagnostics wizard arrives in M5.', + 'Vue 3 + Arco Design Vue rewrite (M5): the three-step diagnostics wizard (environment / credentials / device) plus autonomous task launching.', + tabs: { + diagnostics: 'System Setup & Prerequisites', + launcher: 'Launch Autonomous Task', + }, + prerequisitesWarning: 'Prerequisites incomplete: runtime, credentials, or Android device is not ready. Click to open the setup guide.', + deviceLockedWarning: 'The Android device is locked. Unlock it and return to the home screen before running a task.', taskTitle: 'Submit a new task', goalLabel: 'Task goal', goalPlaceholder: 'Describe the task for ARTEMIS, e.g. open the clock and start a 1-minute countdown…', @@ -41,6 +47,205 @@ export default { pending: 'Queued', done: 'Finished', }, + // M5 diagnostics wizard (probe title/summary/description/errors are backend fields, passed through verbatim) + diagnostics: { + progressLabel: 'System readiness', + progressOf: '{passed}/{total} steps ready', + recheck: 'Re-check', + checking: 'Checking…', + skipCredentials: 'Skip credentials check', + copy: 'Copy', + copied: 'Copied', + status: { + pass: 'Pass', + warn: 'Warning', + fail: 'Failed', + skipped: 'Skipped', + }, + readyBanner: { + title: 'System ready for autonomous tasks', + desc: 'All dependencies, AI model credentials and the Android device are verified and ready to run.', + launch: 'Launch autonomous task', + }, + env: { + title: 'System & Environment', + desc: 'Core tools, the Android debug bridge and the screen-recording runtime', + installTitle: 'Automated dependency setup', + installDesc: 'Run the following commands in a terminal to install ADB, FFmpeg, scrcpy and project dependencies:', + checking: 'Checking…', + devicesTitle: 'Connected devices', + card: { + python_runtime: 'Python runtime', + android_adb: 'Android Platform-Tools', + system_config: 'System configuration', + toolchain: 'Video toolchain', + }, + }, + cred: { + title: 'AI Model Setup', + desc: 'Google Gemini or custom LLM providers (OpenAI, Claude, Ollama)', + modeGeminiTitle: 'Google Gemini', + modeGeminiTag: 'Recommended', + modeGeminiDesc: 'Fast multimodal reasoning with a free API key from Google AI Studio.', + modeCustomTitle: 'Custom Configuration', + modeCustomDesc: 'Define models in config/artemis.jsonc and keys in .env (OpenAI, Claude, Ollama).', + getKeyLink: 'Get a free API key (Google AI Studio)', + keyLabel: 'Enter Gemini API key:', + keyPlaceholder: 'Enter Gemini API key (e.g. AIzaSy...)', + showKey: 'Show plaintext', + hideKey: 'Hide plaintext', + testKey: 'Test key', + test: 'Test', + testing: 'Testing…', + save: 'Save key', + saveApply: 'Save & apply', + clear: 'Clear key', + savedOk: '✓ Gemini API key verified & saved.', + clearedOk: '✓ Gemini API key cleared.', + saveFail: 'Failed to update the Gemini API key.', + clearFail: 'Failed to clear the Gemini API key.', + testOk: '✓ The Gemini API key is valid!', + testFail: 'Gemini API key verification failed.', + testError: 'Gemini API key test failed.', + ocrTitle: 'Optional: Google Cloud Vision OCR', + ocrDesc: 'Provides screen text coordinate grounding to improve element detection and interaction accuracy on text-heavy apps.', + ocrConfigured: 'OCR configured', + ocrKeyPlaceholder: 'Enter Vision OCR API key (e.g. AIzaSy...)', + ocrSavedOk: '✓ Vision OCR API key verified & saved.', + ocrClearedOk: '✓ Vision OCR API key cleared.', + ocrSaveFail: 'Failed to update the Vision OCR key.', + ocrClearFail: 'Failed to clear the Vision OCR API key.', + ocrTestOk: '✓ The Vision OCR API key is valid!', + ocrTestFail: 'Vision OCR API key verification failed.', + ocrTestError: 'Vision OCR API key test failed.', + cfgTitle: 'Active model configuration', + cfgSubtitle: 'Defined in {path}', + copyPath: 'Copy path', + viewJsonc: 'View full JSONC config', + defaultModel: 'Default model', + fallbackModel: 'Fallback model', + thinkingLevel: 'Thinking level', + presetsTitle: 'Available presets (read-only)', + envTitle: 'Environment variables & API keys', + envSubtitle: 'Loaded from {path}', + envColName: 'Variable', + envColProvider: 'Provider', + envColStatus: 'Status', + envColPreview: 'Preview', + envColDesc: 'Description', + envSet: 'Configured', + envUnset: 'Not set', + notLoaded: 'The model configuration has not been loaded yet. Click "Re-check" above.', + }, + dev: { + title: 'Android Device & Emulator Connection', + desc: 'Local emulator, an attached phone, a wireless device or another ADB server', + changeConn: 'Change connection', + hideConn: 'Hide options', + restartAdb: 'Restart ADB', + refreshDevices: 'Refresh devices', + adbRefreshed: 'ADB refreshed ✓', + devicesRefreshed: 'Devices refreshed ✓', + restartFailed: 'Restart failed', + connected: 'Connected', + virtualDevice: 'Virtual device', + remoteVia: 'Remote via {host}:{port}', + selectDevice: 'Select active device:', + starting: 'Starting', + booting: 'OS booting', + launchingTitle: 'Launching Android emulator', + defaultAvd: 'Virtual device', + stage1: '1. Process start', + stage2: '2. ADB handshake', + stage3: '3. Android OS boot', + stage4: '4. Ready', + viewLogs: 'View boot logs', + hideLogs: 'Hide logs', + stop: 'Stop', + progressComplete: '{percent}% complete', + elapsed: 'Elapsed: {seconds}s', + bootTip: 'A cold boot of the Android virtual device usually takes 20-45 seconds. Live progress is tracked above — do not click launch repeatedly.', + logsTitle: 'Emulator console stream (stdout / stderr)', + copyLogs: 'Copy logs', + logsEmpty: 'Waiting for process output…', + failedTitle: 'Emulator launch failed', + failedDefault: 'The Android emulator process failed to start or crashed during initialization.', + failLogsTitle: 'Process output / failure logs:', + retry: 'Retry launch ({avd})', + retryRemoteDisabled: 'Retrying a local emulator launch is unavailable while a remote ADB server is active', + dismiss: 'Dismiss', + methodEmulator: 'Android emulator', + methodEmulatorDesc: 'Launch a local Android virtual device', + methodEmulatorCount: '{count} local virtual device(s) available', + methodUsb: 'USB cable', + methodUsbDesc: 'Connect a physical phone via USB', + methodWifi: 'Wireless ADB', + methodWifiDesc: 'Connect over the local Wi-Fi', + methodRemote: 'Remote computer', + methodRemoteDesc: 'The phone is connected to another computer', + remoteNotice: 'Artemis is currently using {endpoint}. Switch to local ADB before using a local emulator, USB cable or wireless ADB.', + useLocalAdb: 'Use local ADB', + switching: 'Switching…', + avdTitle: 'Installed virtual devices (AVD)', + avdCount: '{count} available', + launch: 'Launch', + avdEmptyTitle: 'No Android virtual devices (AVD) detected', + avdEmptyDesc: + 'Install Android Studio and create a virtual device in Device Manager (Pixel 8 / API 34 recommended), or create one via the sdkmanager / avdmanager command line. Artemis will detect and connect to it automatically.', + usbIntro: 'Connect your Android phone via USB cable and enable USB debugging:', + usb1Title: 'Connect the USB cable', + usb1Desc: 'Plug your Android phone into this computer with a data cable.', + usb2Title: 'Enable developer options', + usb2Desc: 'In phone Settings > About phone, tap Build number 7 times.', + usb3Title: 'Enable USB debugging', + usb3Desc: 'In Settings > Developer options, turn USB debugging ON.', + usb4Title: 'Authorize this computer', + usb4Desc: 'Check "Always allow" and tap Allow on the phone prompt.', + wifiIntro: 'Make sure the phone and the computer share the same Wi-Fi network:', + wifiHostLabel: 'Device IP address', + wifiHostPlaceholder: 'e.g. 192.168.1.108', + wifiPortLabel: 'Port', + wifiPortPlaceholder: '5555', + wifiConnect: 'Connect', + wifiConnecting: 'Connecting…', + wifiConnected: 'Connected to {host}:{port}!', + wifiFail: 'Connection failed. Please check the phone IP and Wi-Fi.', + wifiError: 'Failed to connect. Please check the ADB connection.', + wifiHint: 'Find the IP & port in phone Settings > Developer options > Wireless debugging.', + wifiRemoteBlock: 'Switch to local ADB before connecting a wireless ADB device.', + wifiInvalidHost: 'Please enter a valid IP address.', + remoteIntro: 'Enter the host and port of an ADB server endpoint this computer can access, so Artemis can discover and control a phone physically connected to another computer.', + remoteHostLabel: 'ADB server host', + remotePortLabel: 'ADB server port', + remoteHostPlaceholder: '127.0.0.1', + remotePortPlaceholder: '5038', + remoteTest: 'Test connection', + remoteTesting: 'Checking…', + remoteRemember: 'Remember this endpoint for future Artemis launches', + remoteUse: 'Use connection', + remoteUseAnyway: 'Use anyway', + remoteTestFirst: 'Test the endpoint before using it.', + remoteInvalidHost: 'Enter the host name or IP address of the ADB server.', + remoteInvalidPort: 'Enter a port between 1 and 65535.', + remoteTestError: 'Unable to test the ADB server endpoint.', + remoteUseError: 'Unable to use the ADB server endpoint.', + remoteSwitchError: 'Unable to switch back to the local ADB server.', + remoteExplain: + 'Artemis sends all ADB commands to this server instead of the default local server. Any phone visible to that server becomes available to Artemis.', + remoteReady: 'Ready', + lockedTitle: 'Device is locked', + lockUnknownTitle: 'Unable to verify lock state', + checkAgain: 'Check again', + unauthTitle: 'USB debugging authorization pending', + unauthDesc: 'Your Android device was detected, but it requires authorization. Please unlock the phone screen and tap "Allow USB debugging".', + unauthRestartLocal: 'Restart ADB & check', + adbMissingTitle: 'Android Platform Tools (adb) not found. Please install ADB for your operating system:', + osLinux: 'Linux (Ubuntu / Debian)', + osMac: 'macOS (Homebrew)', + osWin: 'Windows (WinGet)', + detected: 'Detected', + }, + }, }, workspace: { title: 'Workspace', @@ -93,6 +298,7 @@ export default { summary: 'Summary', command: 'Command', workingDir: 'Working directory', + terminalId: 'Terminal ID', reportFindings: 'Report & findings', finalVerifiedState: 'Final verified state', postVerification: 'Post verification', @@ -120,6 +326,12 @@ export default { backendSwitch: 'UI hierarchy source changed', continueTask: 'Continue task', resumeHint: 'Task paused · no steps are running', + // M3 live stream: planning loader / LLM retry banner / paused card + planning: 'Planning the next move…', + retrying: 'AI service is temporarily busy', + retryAttempt: ' (Attempt {attempt}/{max})', + retryDelay: '; retrying in {delay}s', + pausedTitle: 'Task paused', // Checker check: 'Check', finalCheck: 'Final check', @@ -165,5 +377,76 @@ export default { flashNote: 'No extra settings for Flash.', }, }, + // M4 floating player + player: { + // Window header + title: 'Screen Recording', + liveTitle: 'Live Device Screen', + stepReplayTitle: 'Step Replay ({current}/{total})', + preparingTitle: 'Preparing Recording', + minimize: 'Minimize', + restore: 'Restore', + theater: 'Theater Mode', + exitTheater: 'Exit Theater Mode', + close: 'Close', + // Live + liveBadge: 'LIVE', + refreshLive: 'Refresh live stream', + liveConnectingTitle: 'Device Stream Connecting', + liveConnectingDesc: 'Waiting for the ADB device screen stream…', + reconnect: 'Reconnect', + // Mode toggle + modeVideo: 'Video', + modeSteps: 'Steps', + // Status rows + processing: 'Preparing screen recording…', + finalizing: 'Finalizing the recording…', + failedTitle: 'Recording Playback Failed', + loadErrorDesc: 'The finalized recording could not be played.', + unavailableTitle: 'No Video Recording Available', + unavailableDesc: 'No screen recording was found for this task.', + retry: 'Retry', + switchToSteps: 'Switch to step replay', + stepUnavailableNotice: 'Screen recording unavailable. Replaying step-by-step screenshots.', + // Step replay + loadingScreenshot: 'Loading screenshot…', + imageError: 'Screenshot preview unavailable for this step', + prevFrame: 'Previous frame', + nextFrame: 'Next frame', + play: 'Play', + pause: 'Pause', + playSlideshow: 'Play slideshow', + replay: 'Replay from start', + preImage: 'Pre', + postImage: 'Post', + preImageTitle: 'View screen before the action (with touch coordinates)', + postImageTitle: 'View screen after the action', + pinCard: 'Pin details card', + unpinCard: 'Unpin details card', + // Dual timeline + sessionAxis: 'Session', + segmentAxis: 'Segment', + segmentLabel: 'Segment {index}/{total}', + // Controls + speedTitle: 'Speed: {rate}x (click to cycle)', + loopOn: 'Loop enabled', + loopOff: 'Enable loop', + mute: 'Mute', + unmute: 'Unmute', + openVideoTab: 'Open video in new tab', + openImageTab: 'Open image in new tab', + // Toolbar screen-recording toggle (per-state title) + recordBtnRunning: 'Task is currently running (Recording screen)', + recordBtnProcessing: 'Preparing screen recording…', + recordBtnPlay: 'Play Screen Recording Video', + recordBtnSteps: 'Play step-by-step screenshots replay', + recordBtnStepsFailed: 'Video recording failed — Click to replay step-by-step screenshots', + recordBtnFailed: 'Screen recording generation failed', + recordBtnDefault: 'Screen Recording', + // StepCard video analysis pill + screenRecording: 'Screen recording', + openAtRange: 'Open recording at {range}', + segmentsSaved: '{completed}/{total} segments saved', + }, }, }; diff --git a/apps/showcase_ui_v2/src/locales/zh-CN.ts b/apps/showcase_ui_v2/src/locales/zh-CN.ts index 1b37b3a43..044e7c0ae 100644 --- a/apps/showcase_ui_v2/src/locales/zh-CN.ts +++ b/apps/showcase_ui_v2/src/locales/zh-CN.ts @@ -27,7 +27,13 @@ export default { launcher: { title: 'ARTEMIS 控制台(Vue 版)', description: - 'Vue 3 + Arco Design Vue 重构版控制台(M1):提交任务、查看队列与会话摘要。诊断向导将在 M5 交付。', + 'Vue 3 + Arco Design Vue 重构版控制台(M5):系统诊断三步引导(环境 / 凭据 / 设备)与自主任务启动。', + tabs: { + diagnostics: '系统设置与前置条件', + launcher: '启动自主任务', + }, + prerequisitesWarning: '前置条件未完成:运行时、凭据或 Android 设备未就绪。点击打开设置引导。', + deviceLockedWarning: 'Android 设备已锁定。请解锁并回到主屏幕后再运行任务。', taskTitle: '提交新任务', goalLabel: '任务目标', goalPlaceholder: '描述你要让 ARTEMIS 完成的任务,例如:打开时钟并启动 1 分钟倒计时…', @@ -42,6 +48,205 @@ export default { pending: '排队中', done: '已完成', }, + // M5 诊断向导(probe 的 title/summary/description/错误为后端字段,原样透传不 i18n) + diagnostics: { + progressLabel: '系统就绪度', + progressOf: '{passed}/{total} 步已就绪', + recheck: '重新检测', + checking: '检测中…', + skipCredentials: '跳过凭据检查', + copy: '复制', + copied: '已复制', + status: { + pass: '通过', + warn: '警告', + fail: '未通过', + skipped: '已跳过', + }, + readyBanner: { + title: '系统已就绪,可以执行自主任务', + desc: '所有依赖、AI 模型凭据与 Android 设备均已验证就绪。', + launch: '启动自主任务', + }, + env: { + title: '系统与环境', + desc: '核心工具、Android 调试桥与录屏运行时', + installTitle: '自动依赖安装', + installDesc: '在终端运行以下命令安装 ADB、FFmpeg、scrcpy 与项目依赖:', + checking: '检测中…', + devicesTitle: '已连接设备', + card: { + python_runtime: 'Python 运行时', + android_adb: 'Android Platform-Tools', + system_config: '系统配置', + toolchain: '视频工具链', + }, + }, + cred: { + title: 'AI 模型配置', + desc: 'Google Gemini 或自定义 LLM 提供商(OpenAI、Claude、Ollama)', + modeGeminiTitle: 'Google Gemini', + modeGeminiTag: '推荐', + modeGeminiDesc: '多模态推理快速,可从 Google AI Studio 免费获取 API Key。', + modeCustomTitle: '自定义配置', + modeCustomDesc: '在 config/artemis.jsonc 中定义模型,并在 .env 中配置密钥(OpenAI、Claude、Ollama)。', + getKeyLink: '获取免费 API Key(Google AI Studio)', + keyLabel: '输入 Gemini API Key:', + keyPlaceholder: '输入 Gemini API Key(例如 AIzaSy...)', + showKey: '显示明文', + hideKey: '隐藏明文', + testKey: '测试密钥', + test: '测试', + testing: '测试中…', + save: '保存密钥', + saveApply: '保存并生效', + clear: '清除密钥', + savedOk: '✓ Gemini API key 已校验并保存。', + clearedOk: '✓ Gemini API key 已清除。', + saveFail: '保存 Gemini API key 失败。', + clearFail: '清除 Gemini API key 失败。', + testOk: '✓ Gemini API key 有效!', + testFail: 'Gemini API key 校验失败。', + testError: 'Gemini API key 测试失败。', + ocrTitle: '可选:Google Cloud Vision OCR', + ocrDesc: '提供屏幕文本坐标定位,提升文本密集型应用中的元素检测与交互精度。', + ocrConfigured: 'OCR 已配置', + ocrKeyPlaceholder: '输入 Vision OCR API Key(例如 AIzaSy...)', + ocrSavedOk: '✓ Vision OCR API key 已校验并保存。', + ocrClearedOk: '✓ Vision OCR API key 已清除。', + ocrSaveFail: '保存 Vision OCR key 失败。', + ocrClearFail: '清除 Vision OCR API key 失败。', + ocrTestOk: '✓ Vision OCR API key 有效!', + ocrTestFail: 'Vision OCR API key 校验失败。', + ocrTestError: 'Vision OCR API key 测试失败。', + cfgTitle: '当前模型配置', + cfgSubtitle: '定义于 {path}', + copyPath: '复制路径', + viewJsonc: '查看完整 JSONC 配置', + defaultModel: '默认模型', + fallbackModel: '回退模型', + thinkingLevel: '思考等级', + presetsTitle: '可用预设(只读)', + envTitle: '环境变量与 API Keys', + envSubtitle: '加载自 {path}', + envColName: '变量名', + envColProvider: '提供商', + envColStatus: '状态', + envColPreview: '预览', + envColDesc: '描述', + envSet: '已配置', + envUnset: '未设置', + notLoaded: '模型配置尚未加载,请点击顶部“重新检测”。', + }, + dev: { + title: 'Android 设备与模拟器连接', + desc: '本地模拟器、USB 手机、无线设备或其他 ADB 服务器', + changeConn: '切换连接方式', + hideConn: '收起连接方式', + restartAdb: '重启 ADB', + refreshDevices: '刷新设备', + adbRefreshed: 'ADB 已刷新 ✓', + devicesRefreshed: '设备已刷新 ✓', + restartFailed: '重启失败', + connected: '已连接', + virtualDevice: '虚拟设备', + remoteVia: '远程 {host}:{port}', + selectDevice: '选择活动设备:', + starting: '启动中', + booting: '系统启动中', + launchingTitle: '正在启动 Android 模拟器', + defaultAvd: '虚拟设备', + stage1: '1. 进程启动', + stage2: '2. ADB 握手', + stage3: '3. Android 系统启动', + stage4: '4. 就绪', + viewLogs: '查看启动日志', + hideLogs: '收起日志', + stop: '停止', + progressComplete: '{percent}% 完成', + elapsed: '已用时 {seconds}s', + bootTip: 'Android 虚拟设备冷启动通常需要 20-45 秒。上方正在实时跟踪进度——请勿重复点击启动。', + logsTitle: '模拟器控制台输出(stdout / stderr)', + copyLogs: '复制日志', + logsEmpty: '等待进程输出…', + failedTitle: '模拟器启动失败', + failedDefault: 'Android 模拟器进程启动失败或在初始化期间崩溃。', + failLogsTitle: '进程输出 / 失败日志:', + retry: '重试启动({avd})', + retryRemoteDisabled: '远程 ADB 模式下无法重试本地模拟器启动', + dismiss: '关闭', + methodEmulator: 'Android 模拟器', + methodEmulatorDesc: '启动本地 Android 虚拟设备', + methodEmulatorCount: '{count} 个本地虚拟设备可用', + methodUsb: 'USB 数据线', + methodUsbDesc: '通过 USB 连接实体手机', + methodWifi: '无线 ADB', + methodWifiDesc: '通过局域网 Wi-Fi 连接', + methodRemote: '远程电脑', + methodRemoteDesc: '手机连接在另一台电脑上', + remoteNotice: 'ARTEMIS 正在使用 {endpoint}。在使用本地模拟器、USB 或无线 ADB 前,请先切回本地 ADB。', + useLocalAdb: '使用本地 ADB', + switching: '切换中…', + avdTitle: '已安装虚拟设备 (AVD)', + avdCount: '{count} 个可用', + launch: '启动', + avdEmptyTitle: '未检测到 Android 虚拟设备 (AVD)', + avdEmptyDesc: + '安装 Android Studio 并在 Device Manager 中创建虚拟设备(推荐 Pixel 8 / API 34),或用命令行 sdkmanager / avdmanager 创建。创建后 ARTEMIS 会自动检测并连接。', + usbIntro: '用 USB 线连接 Android 手机并开启 USB 调试:', + usb1Title: '连接 USB 数据线', + usb1Desc: '用数据线将 Android 手机连接到本机。', + usb2Title: '开启开发者选项', + usb2Desc: '在手机 设置 > 关于手机 中连点 7 次“版本号”。', + usb3Title: '开启 USB 调试', + usb3Desc: '在 设置 > 开发者选项 中打开“USB 调试”。', + usb4Title: '授权本机', + usb4Desc: '在手机弹窗中勾选“一律允许”并点击“允许”。', + wifiIntro: '确保手机与电脑处于同一 Wi-Fi 网络:', + wifiHostLabel: '设备 IP 地址', + wifiHostPlaceholder: '例如 192.168.1.108', + wifiPortLabel: '端口', + wifiPortPlaceholder: '5555', + wifiConnect: '连接', + wifiConnecting: '连接中…', + wifiConnected: '已连接到 {host}:{port}!', + wifiFail: '连接失败。请检查手机 IP 与 Wi-Fi。', + wifiError: '连接失败,请检查 ADB 连接。', + wifiHint: '在手机 设置 > 开发者选项 > 无线调试 中查看 IP 与端口。', + wifiRemoteBlock: '请先切回本地 ADB,再连接无线 ADB 设备。', + wifiInvalidHost: '请输入有效的 IP 地址。', + remoteIntro: '输入本机可访问的 ADB 服务器地址与端口,ARTEMIS 将发现并控制连接在另一台电脑上的手机。', + remoteHostLabel: 'ADB 服务器主机', + remotePortLabel: 'ADB 服务器端口', + remoteHostPlaceholder: '127.0.0.1', + remotePortPlaceholder: '5038', + remoteTest: '测试连接', + remoteTesting: '检测中…', + remoteRemember: '记住此端点,供以后 ARTEMIS 启动使用', + remoteUse: '使用此连接', + remoteUseAnyway: '仍要使用', + remoteTestFirst: '请先测试端点再使用。', + remoteInvalidHost: '请输入 ADB 服务器的主机名或 IP 地址。', + remoteInvalidPort: '请输入 1-65535 之间的端口。', + remoteTestError: '无法测试 ADB 服务器端点。', + remoteUseError: '无法使用该 ADB 服务器端点。', + remoteSwitchError: '无法切回本地 ADB 服务器。', + remoteExplain: + 'ARTEMIS 会将所有 ADB 命令发送到该服务器而非默认本地服务器。该服务器可见的所有手机都对 ARTEMIS 可用。', + remoteReady: '就绪', + lockedTitle: '设备已锁定', + lockUnknownTitle: '无法确认锁定状态', + checkAgain: '重新检测', + unauthTitle: 'USB 调试授权待确认', + unauthDesc: '已检测到 Android 设备,但需要授权。请解锁手机屏幕并点击“允许 USB 调试”。', + unauthRestartLocal: '重启 ADB 并检测', + adbMissingTitle: '未找到 Android Platform Tools (adb)。请先为当前操作系统安装 ADB:', + osLinux: 'Linux (Ubuntu / Debian)', + osMac: 'macOS (Homebrew)', + osWin: 'Windows (WinGet)', + detected: '已检测', + }, + }, }, workspace: { title: '工作台', @@ -94,6 +299,7 @@ export default { summary: '摘要', command: '命令', workingDir: '工作目录', + terminalId: '终端 ID', reportFindings: '报告与发现', finalVerifiedState: '最终验证状态', postVerification: '验证后状态', @@ -121,6 +327,12 @@ export default { backendSwitch: 'UI 层级来源已切换', continueTask: '继续任务', resumeHint: '任务已暂停 · 没有正在执行的步骤', + // M3 实时流:planning loader / LLM 重试警示条 / 任务暂停卡 + planning: '正在规划下一步…', + retrying: 'AI 服务暂时繁忙', + retryAttempt: '(第 {attempt}/{max} 次尝试)', + retryDelay: ';将在 {delay}s 后重试', + pausedTitle: '任务已暂停', // Checker check: '结果核查', finalCheck: '最终核查', @@ -166,5 +378,76 @@ export default { flashNote: 'Flash 无额外设置。', }, }, + // M4 浮动播放器 + player: { + // 标题栏 + title: '屏幕录像', + liveTitle: '设备实时画面', + stepReplayTitle: '步骤回放({current}/{total})', + preparingTitle: '正在准备录像', + minimize: '最小化', + restore: '还原', + theater: '剧场模式', + exitTheater: '退出剧场模式', + close: '关闭', + // live + liveBadge: 'LIVE', + refreshLive: '刷新实时画面', + liveConnectingTitle: '设备画面连接中', + liveConnectingDesc: '正在等待 ADB 设备屏幕流…', + reconnect: '重新连接', + // 模式切换 + modeVideo: '录像', + modeSteps: '步骤', + // 状态条 + processing: '正在准备屏幕录像…', + finalizing: '正在生成最终录像…', + failedTitle: '录像播放失败', + loadErrorDesc: '无法播放已生成的录像。', + unavailableTitle: '暂无屏幕录像', + unavailableDesc: '没有找到此任务的屏幕录像。', + retry: '重试', + switchToSteps: '切换到步骤回放', + stepUnavailableNotice: '屏幕录像不可用,正在按步骤截图回放。', + // 步骤回放 + loadingScreenshot: '正在加载截图…', + imageError: '该步骤的截图预览不可用', + prevFrame: '上一帧', + nextFrame: '下一帧', + play: '播放', + pause: '暂停', + playSlideshow: '播放幻灯片', + replay: '从头回放', + preImage: '前', + postImage: '后', + preImageTitle: '查看动作前画面(含坐标标注)', + postImageTitle: '查看动作后画面', + pinCard: '固定详情卡', + unpinCard: '取消固定详情卡', + // 双时间轴 + sessionAxis: '整场', + segmentAxis: '段内', + segmentLabel: '第 {index}/{total} 段', + // 控制 + speedTitle: '速度:{rate}x(点击切换)', + loopOn: '循环已开启', + loopOff: '开启循环', + mute: '静音', + unmute: '取消静音', + openVideoTab: '在新标签页打开视频', + openImageTab: '在新标签页打开图片', + // 工具条录像开关按钮(各态 title) + recordBtnRunning: '任务运行中(正在录制屏幕)', + recordBtnProcessing: '正在准备屏幕录像…', + recordBtnPlay: '播放屏幕录像', + recordBtnSteps: '播放逐步截图回放', + recordBtnStepsFailed: '录像失败 · 点击逐步回放截图', + recordBtnFailed: '屏幕录像生成失败', + recordBtnDefault: '屏幕录像', + // StepCard 视频分析 pill + screenRecording: '屏幕录像', + openAtRange: '打开录像 {range}', + segmentsSaved: '{completed}/{total} 段已保存', + }, }, }; diff --git a/apps/showcase_ui_v2/src/stores/index.ts b/apps/showcase_ui_v2/src/stores/index.ts index a770e7940..1f16046ac 100644 --- a/apps/showcase_ui_v2/src/stores/index.ts +++ b/apps/showcase_ui_v2/src/stores/index.ts @@ -6,8 +6,6 @@ import { createPinia } from 'pinia'; * 已落地: * - stores/session.ts(会话合并 4 步算法 + 2s/6s 轮询 + 乐观更新 + localStorage 缓存,M1) * - stores/system.ts(最小 /api/status 连通性轮询,M1;完整诊断在 M5 扩展) - * - * 后续里程碑: * - stores/stream.ts(SSE 连接与合批,M3) * - stores/player.ts(视频回放状态机,M4) */ diff --git a/apps/showcase_ui_v2/src/stores/player.spec.ts b/apps/showcase_ui_v2/src/stores/player.spec.ts new file mode 100644 index 000000000..a986fa004 --- /dev/null +++ b/apps/showcase_ui_v2/src/stores/player.spec.ts @@ -0,0 +1,409 @@ +import { afterEach, beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; +import { createPinia, setActivePinia } from 'pinia'; + +vi.mock('@/services/api', () => ({ apiGet: vi.fn(), apiPost: vi.fn() })); + +import { apiGet } from '@/services/api'; +import { usePlayerStore } from './player'; +import { useSessionStore } from './session'; +import { useTimelineStore, type SessionLog } from './timeline'; +import type { Session } from '@/types/session.model'; + +const apiGetMock = apiGet as unknown as Mock; + +/** 按路径给出 GET 响应,未配置的路径返回 [](与 session.spec.ts 同风格)。 */ +function mockApiRoutes(routes: Record): void { + apiGetMock.mockImplementation((url: string) => + Promise.resolve(structuredClone(routes[url] ?? [])), + ); +} + +/** requestSessionVideo 的响应经 .then 微任务落库;10 轮足够链式微任务排空。 */ +async function flushMicrotasks(): Promise { + for (let i = 0; i < 10; i += 1) await Promise.resolve(); +} + +function completed(id: string): Session { + return { session_id: id, status: 'completed', initial_goal: `Goal ${id}`, start_time: 1 }; +} + +function running(id: string): Session { + return { session_id: id, status: 'running', initial_goal: `Goal ${id}`, start_time: 2 }; +} + +function processingPayload(retryAfterMs: number): Record { + return { + session_id: 'x', + status: 'processing', + has_video: false, + video_url: null, + video_segments: [], + retry_after_ms: retryAfterMs, + }; +} + +function readyPayload(url: string): Record { + return { + session_id: 'x', + status: 'ready', + has_video: true, + video_url: url, + video_segments: [ + { url: 'http://media/seg0.mp4', start: 0, duration: 5, width: 1080, height: 2400 }, + ], + }; +} + +/** 产生一个回放帧的最小步进日志(pre_image_name 经 formatImageUrl 可解析)。 */ +function stepLog(stepId: string, stepNumber: number, imageName: string): SessionLog { + return { + type: 'step_updated', + timestamp: new Date().toISOString(), + session_id: 's1', + data: { step_id: stepId, step_number: stepNumber, pre_image_name: imageName }, + }; +} + +describe('player store — openVideoPlayer', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('running/paused 会话 → live 态,不发起录像轮询', () => { + useSessionStore().$patch({ rawSessions: [running('s-live')] }); + const player = usePlayerStore(); + + player.openVideoPlayer('s-live'); + + expect(player.isVideoWindowOpen).toBe(true); + expect(player.isVideoMinimized).toBe(false); + expect(player.recordingPlaybackStatus).toBe('live'); + expect(player.isVideoLoading).toBe(false); + expect(player.activeVideoUrl).toBeNull(); + expect(apiGetMock).not.toHaveBeenCalled(); + }); + + it('历史会话无 video_url → processing + 轮询启动', () => { + useSessionStore().$patch({ rawSessions: [completed('s1')] }); + const player = usePlayerStore(); + + player.openVideoPlayer('s1'); + + expect(player.recordingPlaybackStatus).toBe('processing'); + expect(player.isVideoLoading).toBe(true); + expect(player.activeVideoUrl).toBeNull(); + expect(player.shouldAutoplayVideo).toBe(true); + expect(apiGetMock).toHaveBeenCalledWith('/api/sessions/s1/video'); + }); + + it('无 video_url 但当前会话有 step frames → playerMode 预置 steps(Angular L1824-1828)', () => { + const timeline = useTimelineStore(); + timeline.sessionLogs = [stepLog('st1', 1, '/pre.jpg')]; + useSessionStore().$patch({ rawSessions: [completed('s1')] }); + const player = usePlayerStore(); + + expect(player.hasCurrentSessionStepFrames).toBe(true); + player.openVideoPlayer('s1'); + + expect(player.playerMode).toBe('steps'); + expect(player.recordingPlaybackStatus).toBe('processing'); + }); +}); + +describe('player store — requestSessionVideo 四态', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('ready:segments 落库、url 更新,并同步 session store rawSessions(Angular L1892-1896)', async () => { + mockApiRoutes({ + '/api/sessions/s1/video': readyPayload('http://media/v.mp4?v=1'), + }); + const session = useSessionStore(); + session.$patch({ rawSessions: [completed('s1')] }); + const player = usePlayerStore(); + + player.openVideoPlayer('s1'); + await flushMicrotasks(); + + expect(player.recordingPlaybackStatus).toBe('ready'); + expect(player.activeVideoUrl).toBe('http://media/v.mp4?v=1'); + expect(player.activeVideoSegments).toHaveLength(1); + expect(player.isVideoLoading).toBe(false); + expect(player.recordingPlaybackMessage).toBe(''); + expect(player.playerMode).toBe('video'); + expect(session.rawSessions.find((s) => s.session_id === 's1')?.video_url).toBe('http://media/v.mp4?v=1'); + expect(session.rawSessions.find((s) => s.session_id === 's1')?.recording_status).toBe('ready'); + }); + + it('processing:按 retry_after_ms 重试并钳制到 [500, 3000]ms', async () => { + const session = useSessionStore(); + session.$patch({ rawSessions: [completed('s1'), completed('s2')] }); + const player = usePlayerStore(); + + // 钳制下限:retry_after_ms=100 → 500ms 后才重试 + mockApiRoutes({ '/api/sessions/s1/video': processingPayload(100) }); + player.openVideoPlayer('s1'); + await flushMicrotasks(); + expect(apiGetMock).toHaveBeenCalledTimes(1); + + await vi.advanceTimersByTimeAsync(499); + expect(apiGetMock).toHaveBeenCalledTimes(1); + await vi.advanceTimersByTimeAsync(1); + expect(apiGetMock).toHaveBeenCalledTimes(2); + + // 钳制上限:retry_after_ms=99999 → 3000ms 后才重试(打开新会话会取消旧重试链) + mockApiRoutes({ '/api/sessions/s2/video': processingPayload(99999) }); + player.openVideoPlayer('s2'); + await flushMicrotasks(); + const callsAfterOpen = apiGetMock.mock.calls.length; + + await vi.advanceTimersByTimeAsync(2999); + expect(apiGetMock.mock.calls.length).toBe(callsAfterOpen); + await vi.advanceTimersByTimeAsync(1); + expect(apiGetMock.mock.calls.length).toBe(callsAfterOpen + 1); + }); + + it('failed:message 透传;unavailable 无 message 时为空(文案由 UI i18n);有帧时 playerMode 转 steps', async () => { + const timeline = useTimelineStore(); + timeline.sessionLogs = [stepLog('st1', 1, '/pre.jpg')]; + useSessionStore().$patch({ rawSessions: [completed('s1'), completed('s3')] }); + const player = usePlayerStore(); + + mockApiRoutes({ + '/api/sessions/s1/video': { + session_id: 's1', status: 'failed', has_video: false, video_url: null, + video_segments: [], message: 'boom finalization', + }, + }); + player.openVideoPlayer('s1'); + await flushMicrotasks(); + + expect(player.recordingPlaybackStatus).toBe('failed'); + expect(player.recordingPlaybackMessage).toBe('boom finalization'); + expect(player.isVideoLoading).toBe(false); + expect(player.activeVideoUrl).toBeNull(); + expect(player.playerMode).toBe('steps'); + + mockApiRoutes({ + '/api/sessions/s3/video': { + session_id: 's3', status: 'unavailable', has_video: false, video_url: null, video_segments: [], + }, + }); + player.openVideoPlayer('s3'); + await flushMicrotasks(); + + expect(player.recordingPlaybackStatus).toBe('unavailable'); + expect(player.recordingPlaybackMessage).toBe(''); + }); + + it('HTTP 错误且 processing 中 → 1s 后重试而不判死', async () => { + apiGetMock.mockRejectedValue(new Error('network down')); + useSessionStore().$patch({ rawSessions: [completed('s1')] }); + const player = usePlayerStore(); + + player.openVideoPlayer('s1'); + await flushMicrotasks(); + + expect(player.recordingPlaybackStatus).toBe('processing'); + expect(apiGetMock).toHaveBeenCalledTimes(1); + + await vi.advanceTimersByTimeAsync(999); + expect(apiGetMock).toHaveBeenCalledTimes(1); + await vi.advanceTimersByTimeAsync(1); + expect(apiGetMock).toHaveBeenCalledTimes(2); + }); +}); + +describe('player store — 120s 超时', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('推进 fake timers 跨过 120s → failed(超时文案由 UI 按 status i18n)', async () => { + mockApiRoutes({ '/api/sessions/s1/video': processingPayload(3000) }); + useSessionStore().$patch({ rawSessions: [completed('s1')] }); + const player = usePlayerStore(); + + player.openVideoPlayer('s1'); + await flushMicrotasks(); + expect(player.recordingPlaybackStatus).toBe('processing'); + + let guard = 0; + while (player.recordingPlaybackStatus === 'processing' && guard < 60) { + await vi.advanceTimersByTimeAsync(3000); + guard += 1; + } + + expect(player.recordingPlaybackStatus).toBe('failed'); + expect(player.isVideoLoading).toBe(false); + expect(player.recordingPlaybackMessage).toBe(''); + // 120s 内一直在 3s 节奏上重试(约 41 轮),未提前放弃 + expect(guard).toBeLessThanOrEqual(45); + expect(apiGetMock.mock.calls.length).toBeGreaterThanOrEqual(40); + }); +}); + +describe('player store — generation 守卫', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + /** apiGet 返回手工 resolve 的挂起 Promise,按调用顺序捕获。 */ + function pendingResponses(): Array<(v: unknown) => void> { + const resolvers: Array<(v: unknown) => void> = []; + apiGetMock.mockImplementation(() => { + return new Promise((resolve) => { + resolvers.push(resolve); + }); + }); + return resolvers; + } + + it('openVideoPlayer 二次调用后旧 generation 的响应不落库', async () => { + useSessionStore().$patch({ rawSessions: [completed('s1')] }); + const player = usePlayerStore(); + const resolvers = pendingResponses(); + + player.openVideoPlayer('s1'); // gen1 + player.openVideoPlayer('s1'); // gen2(守卫递增) + expect(apiGetMock).toHaveBeenCalledTimes(2); + + resolvers[0](readyPayload('http://old/v.mp4')); + await flushMicrotasks(); + expect(player.activeVideoUrl).toBeNull(); + expect(player.recordingPlaybackStatus).toBe('processing'); + + resolvers[1](readyPayload('http://new/v.mp4')); + await flushMicrotasks(); + expect(player.activeVideoUrl).toBe('http://new/v.mp4'); + expect(player.recordingPlaybackStatus).toBe('ready'); + }); + + it('closeVideoPlayer 后响应不落库', async () => { + useSessionStore().$patch({ rawSessions: [completed('s1')] }); + const player = usePlayerStore(); + const resolvers = pendingResponses(); + + player.openVideoPlayer('s1'); + player.closeVideoPlayer(); + expect(player.isVideoWindowOpen).toBe(false); + + resolvers[0](readyPayload('http://x/v.mp4')); + await flushMicrotasks(); + expect(player.activeVideoUrl).toBeNull(); + expect(player.recordingPlaybackStatus).toBe('processing'); + }); +}); + +describe('player store — beginRecordingFinalization', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('非 active 会话直接 return(不请求、不改状态)', () => { + useSessionStore().$patch({ rawSessions: [completed('s1')] }); + const player = usePlayerStore(); + + player.beginRecordingFinalization('s1'); + + expect(apiGetMock).not.toHaveBeenCalled(); + expect(player.recordingPlaybackStatus).toBe('idle'); + expect(player.isVideoLoading).toBe(false); + }); + + it('active 会话:重置 url/segments、置 processing + autoplay 并重新轮询', async () => { + const session = useSessionStore(); + session.$patch({ + rawSessions: [completed('s1'), running('s-live')], + agentStatus: 'running', + runningSessionId: 's-live', + }); + const player = usePlayerStore(); + + player.openVideoPlayer('s-live'); + expect(player.recordingPlaybackStatus).toBe('live'); + expect(apiGetMock).not.toHaveBeenCalled(); + + mockApiRoutes({ '/api/sessions/s-live/video': processingPayload(750) }); + player.beginRecordingFinalization('s-live'); + + expect(player.recordingPlaybackStatus).toBe('processing'); + expect(player.isVideoLoading).toBe(true); + expect(player.shouldAutoplayVideo).toBe(true); + expect(player.activeVideoUrl).toBeNull(); + expect(player.activeVideoSegments).toEqual([]); + expect(apiGetMock).toHaveBeenCalledWith('/api/sessions/s-live/video'); + + await flushMicrotasks(); + await vi.advanceTimersByTimeAsync(750); + expect( + apiGetMock.mock.calls.filter((c) => c[0] === '/api/sessions/s-live/video').length, + ).toBeGreaterThanOrEqual(2); + }); +}); + +describe('player store — autoplay / seek 契约', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('consumeVideoAutoplay 消费后复位;requestVideoSeek/requestStepSeek 的 requestId 递增', () => { + useSessionStore().$patch({ rawSessions: [completed('s1')] }); + const player = usePlayerStore(); + + expect(player.consumeVideoAutoplay()).toBe(false); + player.openVideoPlayer('s1'); + expect(player.shouldAutoplayVideo).toBe(true); + expect(player.consumeVideoAutoplay()).toBe(true); + expect(player.shouldAutoplayVideo).toBe(false); + expect(player.consumeVideoAutoplay()).toBe(false); + + player.requestVideoSeek(5); + expect(player.videoSeekRequest).toEqual({ seconds: 5, requestId: 1 }); + player.requestVideoSeek(Number.NaN); // 非 finite 忽略 + expect(player.videoSeekRequest).toEqual({ seconds: 5, requestId: 1 }); + player.requestVideoSeek(-3); // 钳制为 0 + expect(player.videoSeekRequest).toEqual({ seconds: 0, requestId: 2 }); + + player.requestStepSeek(7); + expect(player.stepSeekRequest).toEqual({ index: 7, requestId: 1 }); + player.requestStepSeek(9); + expect(player.stepSeekRequest).toEqual({ index: 9, requestId: 2 }); + }); +}); + +describe('player store — currentSessionStepFrames 引用稳定语义', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('llm_stream 日志到达不触发帧重提取(等价 Angular stepLogsForReplay 的自定义 equal)', () => { + const timeline = useTimelineStore(); + const player = usePlayerStore(); + + timeline.sessionLogs = [stepLog('st1', 1, '/pre.jpg')]; + const frames1 = player.currentSessionStepFrames; + expect(frames1).toHaveLength(1); + + // 追加 llm_stream:sessionLogs 引用变化,但步进日志子列(长度 + 逐元素引用)不变 + timeline.sessionLogs = [...timeline.sessionLogs, { + type: 'llm_stream', + timestamp: new Date().toISOString(), + data: { execution_id: 'e1', text: 'hello', stream_type: 'text', isCompleted: false }, + }]; + const frames2 = player.currentSessionStepFrames; + expect(frames2).toBe(frames1); + + // 新步进日志到达 → 重提取 + timeline.sessionLogs = [...timeline.sessionLogs, stepLog('st2', 2, '/pre2.jpg')]; + const frames3 = player.currentSessionStepFrames; + expect(frames3).not.toBe(frames1); + expect(frames3).toHaveLength(2); + }); +}); + +/** 每个用例的公共环境:新 Pinia、fake timers(覆盖 Date.now)。 */ +function startEnv(): void { + setActivePinia(createPinia()); + vi.clearAllMocks(); + mockApiRoutes({}); + vi.useFakeTimers(); +} + +function stopEnv(): void { + vi.useRealTimers(); +} diff --git a/apps/showcase_ui_v2/src/stores/player.ts b/apps/showcase_ui_v2/src/stores/player.ts new file mode 100644 index 000000000..d3ec40fbd --- /dev/null +++ b/apps/showcase_ui_v2/src/stores/player.ts @@ -0,0 +1,394 @@ +/** + * 视频回放状态机 —— M4 自 Angular `AgentService` 的视频相关信号与方法平移 + * (agent.service.ts L236-278 / L1776-2011),保持全部时序语义: + * + * - generation 守卫:每次 open/close/finalization/refresh 递增,过期响应不落库; + * - /api/sessions/{id}/video 轮询四态(ready / processing / failed / unavailable), + * processing 按 retry_after_ms 重试并钳制到 500~3000ms,累计等待超 120s 判超时; + * - live 分支:running / paused 会话直接进入 MJPEG 投屏态,不做录像轮询; + * - ready 时同步 session store 的 rawSessions(video_url / recording_status='ready', + * Angular L1892-1896)。 + * + * 与 Angular 的有意偏差: + * - `recordingPlaybackMessage` 只存后端透传 message(res.message;recording_failed + * 的 error 由 stream store 传入)。固定提示文案(Loading / Finalizing / 超时 / + * HTTP 错误兜底)不放 store,由 UI 按 status 走 i18n。 + * - Angular 的 `stepLogsForReplay` computed 使用自定义 equal 在「步进日志长度 + + * 逐元素引用不变」时短路下游帧提取;Vue computed 无 equal 选项,这里用等价实现: + * 先算步进日志数组,其长度与引用均未变化时复用上一次帧数组(同一引用), + * Vue 的 computed 仅在值变化时向下游传播,语义一致。 + * - Angular 的 activeVideoSessionId 为 service 私有字段;Vue 版额外导出 + * `isVideoSession()` 判定方法供 stream / session store 接线比较(不暴露可变本体)。 + * + * 定时器与世代计数器为本 store 实例内普通 let 变量(非响应式,随 Pinia 实例 + * 生命周期存在,保证测试隔离);播放器按需打开、无全局轮询,故无 start/stop。 + */ + +import { computed, ref } from 'vue'; +import { defineStore } from 'pinia'; + +import { apiGet } from '@/services/api'; +import { useSessionStore } from '@/stores/session'; +import { useTimelineStore, type SessionLog } from '@/stores/timeline'; +import { extractStepReplayFrames } from '@/utils/action-formatter'; +import type { + RecordingPlaybackStatus, + SessionVideoResponse, + VideoSegment, +} from '@/types/session.model'; +import type { StepReplayFrame } from '@/types/stream.model'; + +export const usePlayerStore = defineStore('player', () => { + const sessionStore = useSessionStore(); + const timelineStore = useTimelineStore(); + + // ---- 响应式状态(对应 Angular 同名 signals,agent.service.ts L237-248)---- + const isVideoWindowOpen = ref(false); + const isVideoMinimized = ref(false); + const activeVideoUrl = ref(null); + const activeVideoSegments = ref([]); + const activeVideoTitle = ref(''); + const isVideoLoading = ref(false); + const recordingPlaybackStatus = ref('idle'); + /** 只存后端透传 message;固定提示文案由 UI 按 status 走 i18n(有意偏差,见文件头)。 */ + const recordingPlaybackMessage = ref(''); + const shouldAutoplayVideo = ref(false); + const videoSeekRequest = ref<{ seconds: number; requestId: number } | null>(null); + const stepSeekRequest = ref<{ index: number; requestId: number } | null>(null); + const playerMode = ref<'video' | 'steps'>('video'); + + // ---- 非响应式内部状态(对应 Angular service 私有字段,L250-255)---- + let activeVideoSessionId: string | null = null; + let videoSeekRequestId = 0; + let stepSeekRequestId = 0; + let videoRequestGeneration = 0; + let videoRetryTimer: ReturnType | null = null; + let videoWaitStartedAt = 0; + + // ---- 步帧提取(平移自 stepLogsForReplay + currentSessionStepFrames,L257-278)---- + + /** 上一次的步进日志数组与帧结果:引用/长度不变时复用帧数组(LLM 流更新不触发重提取)。 */ + let lastStepLogs: SessionLog[] | null = null; + let lastFrames: StepReplayFrame[] = []; + + /** + * Computed step replay frames from current session logs. + * 流式文本 chunk 无法改变回放帧:步进日志数组长度与逐元素引用不变时, + * 直接复用上次帧数组(等价于 Angular stepLogsForReplay 的自定义 equal 短路)。 + */ + const currentSessionStepFrames = computed(() => { + const stepLogs = timelineStore.sessionLogs.filter( + (log) => log && (log.type === 'step_updated' || log.type === 'step_recorded'), + ); + if ( + lastStepLogs + && lastStepLogs.length === stepLogs.length + && lastStepLogs.every((log, i) => log === stepLogs[i]) + ) { + return lastFrames; + } + lastStepLogs = stepLogs; + lastFrames = extractStepReplayFrames(stepLogs); + return lastFrames; + }); + + const hasCurrentSessionStepFrames = computed(() => currentSessionStepFrames.value.length > 0); + + // ---- 当前会话的录像视图(平移自 L347-360)---- + + const currentSessionVideoUrl = computed(() => { + const curId = sessionStore.currentSessionId; + if (!curId) return null; + const session = sessionStore.sessions.find((s) => s.session_id === curId); + return session?.video_url || null; + }); + + const currentSessionRecordingStatus = computed(() => { + const status = sessionStore.currentSession?.recording_status; + return status === 'recording' || status === 'finalizing' || status === 'processing' + ? 'processing' + : status; + }); + + // ---- 打开 / 关闭(平移自 openVideoPlayer L1776-1830、close/toggle L1995-2011)---- + + function openVideoPlayer( + sessionId?: string, + videoUrl?: string, + title?: string, + seekSeconds?: number, + stepIndex?: number, + ): void { + const targetSessionId = sessionId || sessionStore.currentSessionId || undefined; + const session = sessionStore.sessions.find((s) => s.session_id === targetSessionId); + const targetUrl = videoUrl || session?.video_url || null; + const goalTitle = title || session?.initial_goal + || (targetSessionId ? `Task: ${targetSessionId.slice(0, 8)}...` : 'Screen Recording'); + + activeVideoTitle.value = goalTitle; + isVideoWindowOpen.value = true; + isVideoMinimized.value = false; + activeVideoSessionId = targetSessionId || null; + cancelVideoRetry(); + videoRequestGeneration++; + shouldAutoplayVideo.value = false; + recordingPlaybackMessage.value = ''; + activeVideoSegments.value = []; + if (Number.isFinite(seekSeconds)) requestVideoSeek(Number(seekSeconds)); + if (Number.isFinite(stepIndex)) { + playerMode.value = 'steps'; + requestStepSeek(Number(stepIndex)); + } + if (!targetSessionId) { + activeVideoUrl.value = null; + isVideoLoading.value = false; + recordingPlaybackStatus.value = 'unavailable'; + return; + } + + // live 分支:运行 / 暂停中的会话直接 MJPEG 投屏,不做录像轮询(Angular L1809-1814)。 + if (session?.status === 'running' || session?.status === 'paused') { + activeVideoUrl.value = null; + isVideoLoading.value = false; + recordingPlaybackStatus.value = 'live'; + return; + } + + activeVideoUrl.value = targetUrl; + shouldAutoplayVideo.value = true; + videoWaitStartedAt = Date.now(); + isVideoLoading.value = true; + recordingPlaybackStatus.value = 'processing'; + // 有意偏差:Angular 此处 set 'Loading screen recording...',固定文案由 UI i18n。 + recordingPlaybackMessage.value = ''; + if (targetUrl) { + playerMode.value = 'video'; + } else if (hasCurrentSessionStepFrames.value) { + playerMode.value = 'steps'; + } else { + playerMode.value = 'video'; + } + requestSessionVideo(targetSessionId, videoRequestGeneration); + } + + function closeVideoPlayer(): void { + isVideoWindowOpen.value = false; + cancelVideoRetry(); + videoRequestGeneration++; + activeVideoSessionId = null; + } + + function toggleVideoPlayer(): void { + if (isVideoWindowOpen.value) { + isVideoWindowOpen.value = false; + } else { + openVideoPlayer(); + } + } + + function toggleVideoMinimized(): void { + isVideoMinimized.value = !isVideoMinimized.value; + } + + function setPlayerMode(mode: 'video' | 'steps'): void { + playerMode.value = mode; + } + + // ---- seek / autoplay(平移自 L1978-1990 与 L288-291)---- + + function consumeVideoAutoplay(): boolean { + const shouldAutoplay = shouldAutoplayVideo.value; + shouldAutoplayVideo.value = false; + return shouldAutoplay; + } + + function requestVideoSeek(seconds: number): void { + if (!Number.isFinite(seconds)) return; + videoSeekRequest.value = { + seconds: Math.max(0, seconds), + requestId: ++videoSeekRequestId, + }; + } + + function requestStepSeek(index: number): void { + stepSeekRequestId++; + stepSeekRequest.value = { index, requestId: stepSeekRequestId }; + } + + // ---- 录像轮询状态机(平移自 L1863-1976,generation 守卫与退避钳制保持一致)---- + + function beginRecordingFinalization(sessionId: string): void { + if (activeVideoSessionId !== sessionId) return; + cancelVideoRetry(); + videoRequestGeneration++; + videoWaitStartedAt = Date.now(); + activeVideoUrl.value = null; + activeVideoSegments.value = []; + shouldAutoplayVideo.value = true; + isVideoLoading.value = true; + recordingPlaybackStatus.value = 'processing'; + // 有意偏差:Angular 此处 set 'Finalizing screen recording...',文案由 UI i18n。 + recordingPlaybackMessage.value = ''; + requestSessionVideo(sessionId, videoRequestGeneration); + } + + function requestSessionVideo(sessionId: string, generation: number): void { + apiGet(`/api/sessions/${sessionId}/video`) + .then((res) => { + if (generation !== videoRequestGeneration || sessionId !== activeVideoSessionId) { + return; + } + const status = res.status || (res.has_video && res.video_url ? 'ready' : 'unavailable'); + if (status === 'ready' && res.video_url) { + cancelVideoRetry(); + isVideoLoading.value = false; + recordingPlaybackStatus.value = 'ready'; + recordingPlaybackMessage.value = ''; + activeVideoUrl.value = res.video_url; + activeVideoSegments.value = res.video_segments || []; + playerMode.value = 'video'; + // 同步会话列表,避免下次打开重复轮询(平移自 Angular L1892-1896 的 + // rawSessions.update;最小侵入:直接写 session store 的 rawSessions ref)。 + sessionStore.rawSessions = sessionStore.rawSessions.map((s) => + s.session_id === sessionId + ? { ...s, video_url: res.video_url || undefined, recording_status: 'ready' } + : s, + ); + return; + } + if (status === 'processing') { + activeVideoUrl.value = null; + activeVideoSegments.value = []; + isVideoLoading.value = true; + recordingPlaybackStatus.value = 'processing'; + // 有意偏差:Angular 此处 set 'Finalizing screen recording...',文案由 UI i18n。 + recordingPlaybackMessage.value = ''; + scheduleVideoRetry(sessionId, generation, res.retry_after_ms); + return; + } + + cancelVideoRetry(); + isVideoLoading.value = false; + activeVideoUrl.value = null; + activeVideoSegments.value = []; + recordingPlaybackStatus.value = status === 'failed' ? 'failed' : 'unavailable'; + // 有意偏差:Angular 的兜底文案('Recording finalization failed.' / + // 'No screen recording is available for this task.')由 UI 按 status i18n。 + recordingPlaybackMessage.value = res.message || ''; + if (hasCurrentSessionStepFrames.value) { + playerMode.value = 'steps'; + } + }) + .catch(() => { + if (generation !== videoRequestGeneration || sessionId !== activeVideoSessionId) { + return; + } + if (recordingPlaybackStatus.value === 'processing') { + scheduleVideoRetry(sessionId, generation, 1000); + return; + } + isVideoLoading.value = false; + recordingPlaybackStatus.value = 'failed'; + // 有意偏差:Angular 此处 set 'Unable to load the screen recording.',文案由 UI i18n。 + recordingPlaybackMessage.value = ''; + if (hasCurrentSessionStepFrames.value) { + playerMode.value = 'steps'; + } + }); + } + + function scheduleVideoRetry(sessionId: string, generation: number, retryAfterMs = 1000): void { + cancelVideoRetry(); + if (Date.now() - videoWaitStartedAt > 120_000) { + isVideoLoading.value = false; + recordingPlaybackStatus.value = 'failed'; + // 有意偏差:Angular 此处 set 'Recording finalization timed out...',文案由 UI i18n。 + recordingPlaybackMessage.value = ''; + return; + } + const delay = Math.max(500, Math.min(3000, retryAfterMs)); + videoRetryTimer = setTimeout(() => { + videoRetryTimer = null; + requestSessionVideo(sessionId, generation); + }, delay); + } + + function cancelVideoRetry(): void { + if (videoRetryTimer) { + clearTimeout(videoRetryTimer); + videoRetryTimer = null; + } + } + + function refreshActiveRecording(autoplay: boolean): void { + const sessionId = activeVideoSessionId; + if (!sessionId) return; + cancelVideoRetry(); + videoRequestGeneration++; + if (autoplay) shouldAutoplayVideo.value = true; + requestSessionVideo(sessionId, videoRequestGeneration); + } + + function retryVideoRecording(): void { + const sessionId = activeVideoSessionId; + if (!sessionId) return; + beginRecordingFinalization(sessionId); + } + + /** + * SSE recording_failed 的落库入口(stream store 调用;平移自 Angular L825-832, + * message 由调用方传入 parsedData.error 或兜底文案)。 + */ + function notifyRecordingFailed(message: string): void { + cancelVideoRetry(); + isVideoLoading.value = false; + activeVideoUrl.value = null; + activeVideoSegments.value = []; + recordingPlaybackStatus.value = 'failed'; + recordingPlaybackMessage.value = message; + } + + /** + * 判定给定会话是否为当前打开视频窗口的会话(替代 Angular 私有字段 + * activeVideoSessionId 的跨 store 比较;字符串化比较与 recording_ready/failed + * 分支的 String() 比较语义一致)。 + */ + function isVideoSession(sessionId: unknown): boolean { + return !!sessionId && !!activeVideoSessionId && String(sessionId) === String(activeVideoSessionId); + } + + return { + // state + isVideoWindowOpen, + isVideoMinimized, + activeVideoUrl, + activeVideoSegments, + activeVideoTitle, + isVideoLoading, + recordingPlaybackStatus, + recordingPlaybackMessage, + shouldAutoplayVideo, + videoSeekRequest, + stepSeekRequest, + playerMode, + // computed + currentSessionStepFrames, + hasCurrentSessionStepFrames, + currentSessionVideoUrl, + currentSessionRecordingStatus, + // actions + openVideoPlayer, + closeVideoPlayer, + toggleVideoPlayer, + toggleVideoMinimized, + setPlayerMode, + consumeVideoAutoplay, + requestVideoSeek, + requestStepSeek, + beginRecordingFinalization, + retryVideoRecording, + refreshActiveRecording, + notifyRecordingFailed, + isVideoSession, + }; +}); diff --git a/apps/showcase_ui_v2/src/stores/session.spec.ts b/apps/showcase_ui_v2/src/stores/session.spec.ts index 703d09d2b..90b90853c 100644 --- a/apps/showcase_ui_v2/src/stores/session.spec.ts +++ b/apps/showcase_ui_v2/src/stores/session.spec.ts @@ -103,6 +103,9 @@ describe('session store — 停止 / 恢复 / 提交(用例平移自 agent.ser rawSessions: [{ session_id: 'session-1', status: 'paused', initial_goal: '', start_time: 1 }], agentStatus: 'paused', runningSessionId: 'session-1', + // Angular 对应用例(agent.service.spec.ts L192)桩掉了 fetchStatus; + // 这里放行真实回查,需选中该会话避免自动跟随触发切换(M3 起切会话会重置暂停态)。 + currentSessionId: 'session-1', isPaused: true, pausedError: '503 unavailable', }); diff --git a/apps/showcase_ui_v2/src/stores/session.ts b/apps/showcase_ui_v2/src/stores/session.ts index bc9533dd4..651c179d6 100644 --- a/apps/showcase_ui_v2/src/stores/session.ts +++ b/apps/showcase_ui_v2/src/stores/session.ts @@ -7,7 +7,9 @@ * - localStorage 会话缓存(restore / persist,key 与 Angular 版一致) * - 页面隐藏时暂停轮询、visibilitychange 恢复时立即刷新(§3.3 条款 6) * - * 未平移部分(后续里程碑):SSE 流与 sessionLogs(M3)、视频状态机(M4)。 + * 未平移部分(后续里程碑):SSE 流与 sessionLogs 已由 M3 `stores/stream.ts` 承接; + * 视频状态机已由 M4 `stores/player.ts` 承接(本 store 在 finalization / 删除 / + * 切换会话时回调 player)。 * steps/notes/checks/usage 回填自 M2 起由 `stores/timeline.ts` 承接(跟随本 store * 的 currentSessionId 联动)。 * @@ -18,6 +20,8 @@ import { computed, ref } from 'vue'; import { defineStore } from 'pinia'; import { apiGet, apiPost } from '@/services/api'; +import { usePlayerStore } from '@/stores/player'; +import { useStreamStore } from '@/stores/stream'; import type { ModelInfo, Session, TaskQueueItem } from '@/types/session.model'; import { mapPendingQueue, @@ -209,9 +213,14 @@ export const useSessionStore = defineStore('session', () => { if (data.status === 'paused') { const pauseError = data.paused_error || pausedError.value || DEFAULT_PAUSE_ERROR; pausedError.value = pauseError; - // M3:暂停错误卡片追加到 sessionLogs(appendPausedErrorCard)随流状态接入。 + // 轮询兜底:与当前查看会话一致时补暂停错误卡(平移自 Angular L1527-1529)。 + if (data.session_id && currentSessionId.value === data.session_id) { + useStreamStore().appendPausedErrorCard(pauseError, data.session_id); + } } else { pausedError.value = null; + // 非暂停态清掉暂停卡去重键,允许后续新错误再次成卡(Angular L1532)。 + useStreamStore().clearPauseCard(); } // payload 未变化时跳过赋值:每 2s 生成新数组引用会迫使整条 sessions @@ -231,7 +240,19 @@ export const useSessionStore = defineStore('session', () => { void fetchSessions(); } - // M4:运行器由 active 转 idle 时的录像 finalization 联动随播放器状态机接入。 + // M4:运行器由 active 转 idle(或 paused→非 active)且正以 live 投屏查看 + // 该会话时,立即转入录像 finalization 轮询(平移自 Angular L1571-1580)。 + const playerStore = usePlayerStore(); + if ( + !isActive + && (oldStatus === 'running' || oldStatus === 'paused') + && oldRunningSessionId + && playerStore.isVideoWindowOpen + && playerStore.isVideoSession(oldRunningSessionId) + && playerStore.recordingPlaybackStatus === 'live' + ) { + playerStore.beginRecordingFinalization(oldRunningSessionId); + } // 用户未显式 pin 历史会话时,自动选中运行中的会话 if (isActive && data.session_id) { @@ -367,7 +388,13 @@ export const useSessionStore = defineStore('session', () => { pendingQueue.value = []; } - // M3:标记目标会话未完成的 llm_stream 为已结束(flushStreamChunks)随流状态接入。 + // M3:复位重试状态(平移自 Angular stopTask L529 的 isRetrying.set(false))。 + useStreamStore().resetRetryState(); + // 查看目标会话(或未指定目标)时:flush 缓冲并把未完成的 llm_stream 全部 + // 标记为已结束(平移自 Angular stopTask L536-549)。 + if (!targetSessionId || currentSessionId.value === targetSessionId) { + useStreamStore().markStoppedSessionStreamsCompleted(); + } // 乐观地从 activeTasks 移除 if (targetSessionId) { @@ -427,7 +454,11 @@ export const useSessionStore = defineStore('session', () => { if (currentSessionId.value === sessionId) { selectSession('', false); - // M4:关闭打开中的视频窗口随播放器状态机接入。 + // M4:被删会话正打开视频窗口时关闭播放器(平移自 Angular L639-641)。 + const playerStore = usePlayerStore(); + if (playerStore.isVideoWindowOpen) { + playerStore.closeVideoPlayer(); + } const runningId = runningSessionId.value; if (runningId && agentStatus.value === 'running') { selectSession(runningId, false); @@ -502,6 +533,14 @@ export const useSessionStore = defineStore('session', () => { return; } currentSessionId.value = sessionId; + // 切会话重置暂停状态(平移自 Angular selectSession L742-743)。 + isPaused.value = false; + pausedError.value = null; + // M4:视频窗口打开时随切换刷新为新会话的录像 / 投屏(平移自 Angular L747-750)。 + const playerStore = usePlayerStore(); + if (playerStore.isVideoWindowOpen) { + playerStore.openVideoPlayer(sessionId); + } // notes/checks/steps 快照拉取由 stores/timeline.ts 监听 currentSessionId 触发(M2)。 } @@ -595,5 +634,8 @@ export const useSessionStore = defineStore('session', () => { clearAllHistory, selectSession, clearUserPinnedSession, + // 供 stores/stream.ts(M3)延迟调用的内部方法 + setSessionStatus, + invalidateStatusSignatures, }; }); diff --git a/apps/showcase_ui_v2/src/stores/stream.spec.ts b/apps/showcase_ui_v2/src/stores/stream.spec.ts new file mode 100644 index 000000000..b95149e4e --- /dev/null +++ b/apps/showcase_ui_v2/src/stores/stream.spec.ts @@ -0,0 +1,558 @@ +import { afterEach, beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; +import { createPinia, setActivePinia } from 'pinia'; + +vi.mock('@/services/api', () => ({ apiGet: vi.fn(), apiPost: vi.fn() })); + +import { apiGet } from '@/services/api'; +import { useSessionStore } from './session'; +import { useTimelineStore } from './timeline'; +import { useStreamStore } from './stream'; +import { DEFAULT_STREAM_RESET_MESSAGE } from '@/types/stream.model'; + +const apiGetMock = apiGet as unknown as Mock; + +/** + * jsdom 无 EventSource:注入可编程的 Fake,捕获 type→listener 映射与 onerror, + * 暴露 emit() 驱动 SSE 事件;记录实例以断言 URL(/api/stream)与单例语义。 + */ +class FakeEventSource { + static instances: FakeEventSource[] = []; + url: string; + closed = false; + onerror: ((err: unknown) => void) | null = null; + private listeners = new Map void>>(); + + constructor(url: string) { + this.url = url; + FakeEventSource.instances.push(this); + } + + addEventListener(type: string, listener: (ev: MessageEvent) => void): void { + const arr = this.listeners.get(type) || []; + arr.push(listener); + this.listeners.set(type, arr); + } + + removeEventListener(): void {} + + close(): void { + this.closed = true; + } + + /** 模拟服务端推送:对象自动 JSON.stringify(与后端 SSE data 序列化一致)。 */ + emit(type: string, data: unknown): void { + const payload = typeof data === 'string' ? data : JSON.stringify(data); + for (const listener of [...(this.listeners.get(type) || [])]) { + listener({ data: payload } as MessageEvent); + } + } +} + +function lastInstance(): FakeEventSource { + return FakeEventSource.instances[FakeEventSource.instances.length - 1]; +} + +function startStream(): { stream: ReturnType; es: FakeEventSource } { + const stream = useStreamStore(); + stream.start(); + return { stream, es: lastInstance() }; +} + +/** 按路径给出 GET 响应,未配置的路径返回 [](与 session.spec.ts 同风格)。 */ +function mockApiRoutes(routes: Record): void { + apiGetMock.mockImplementation((url: string) => + Promise.resolve(structuredClone(routes[url] ?? [])), + ); +} + +describe('stream store — llm_stream 合批与顺序保证(§3.3 条款 1)', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('同一 execution_id+stream_type 的多个 chunk 在一次 flush 后合并为一条日志、text 顺序拼接(80ms 前台定时)', () => { + useSessionStore().selectSession('s1', false); + const { es } = startStream(); + const timeline = useTimelineStore(); + + es.emit('llm_stream', { execution_id: 'e1', stream_type: 'text', chunk: 'Hello' }); + es.emit('llm_stream', { execution_id: 'e1', stream_type: 'text', chunk: ' world' }); + expect(timeline.sessionLogs).toHaveLength(0); // 仍在缓冲 + + vi.advanceTimersByTime(79); + expect(timeline.sessionLogs).toHaveLength(0); + + vi.advanceTimersByTime(1); + expect(timeline.sessionLogs).toHaveLength(1); + const log = timeline.sessionLogs[0]; + expect(log.type).toBe('llm_stream'); + expect(log.data.execution_id).toBe('e1'); + expect(log.data.stream_type).toBe('text'); + expect(log.data.text).toBe('Hello world'); + expect(log.data.isCompleted).toBe(false); + }); + + it('document.hidden=true 时合批延时 500ms', () => { + useSessionStore().selectSession('s1', false); + const { es } = startStream(); + const timeline = useTimelineStore(); + Object.defineProperty(document, 'hidden', { configurable: true, value: true }); + + es.emit('llm_stream', { execution_id: 'e1', chunk: 'slow' }); + vi.advanceTimersByTime(80); + expect(timeline.sessionLogs).toHaveLength(0); + vi.advanceTimersByTime(420); // 累计 500ms + expect(timeline.sessionLogs).toHaveLength(1); + expect(timeline.sessionLogs[0].data.text).toBe('slow'); + + Object.defineProperty(document, 'hidden', { configurable: true, value: false }); + }); + + it('换道:不同 stream_type 各自成条;新 execution_id 只关闭同泳道的未完成流', () => { + useSessionStore().selectSession('s1', false); + const { es } = startStream(); + const timeline = useTimelineStore(); + const byExec = (id: string) => timeline.sessionLogs.filter((l) => l.data.execution_id === id); + + // thinking 与 text 各自成条 + es.emit('llm_stream', { execution_id: 'e1', stream_type: 'thinking', chunk: 'th' }); + es.emit('llm_stream', { execution_id: 'e1', stream_type: 'text', chunk: 'tx' }); + vi.advanceTimersByTime(80); + expect(timeline.sessionLogs).toHaveLength(2); + + // 新 execution_id(同 stream_type、同 parent 泳道)关闭 e1-text,不动 e1-thinking + es.emit('llm_stream', { execution_id: 'e2', stream_type: 'text', chunk: 'tx2' }); + vi.advanceTimersByTime(80); + expect(byExec('e1').find((l) => l.data.stream_type === 'text')?.data.isCompleted).toBe(true); + expect(byExec('e1').find((l) => l.data.stream_type === 'thinking')?.data.isCompleted).toBe(false); + expect(byExec('e2')[0].data.isCompleted).toBe(false); + + // 不同泳道(parent_trace_id 不同)互不关闭 + es.emit('llm_stream', { execution_id: 'e3', stream_type: 'text', parent_trace_id: 'checker', chunk: 'c1' }); + vi.advanceTimersByTime(80); + expect(byExec('e2')[0].data.isCompleted).toBe(false); // 无 parent 泳道仍开 + expect(byExec('e3')[0].data.isCompleted).toBe(false); + + es.emit('llm_stream', { execution_id: 'e4', stream_type: 'text', parent_trace_id: 'checker', chunk: 'c2' }); + vi.advanceTimersByTime(80); + expect(byExec('e3')[0].data.isCompleted).toBe(true); // 同泳道被关闭 + expect(byExec('e4')[0].data.isCompleted).toBe(false); + expect(byExec('e2')[0].data.isCompleted).toBe(false); // 异泳道不受影响 + }); + + it('顺序:非流事件到达时缓冲文本先落库再追加事件日志,且缓冲不重复落库', () => { + useSessionStore().selectSession('s1', false); + const { es } = startStream(); + const timeline = useTimelineStore(); + + es.emit('llm_stream', { execution_id: 'e1', chunk: 'buffered text' }); + es.emit('step_recorded', { step_id: 'st1', session_id: 's1', timestamp: 100 }); + + expect(timeline.sessionLogs.map((l) => l.type)).toEqual(['llm_stream', 'step_recorded']); + expect(timeline.sessionLogs[0].data.text).toBe('buffered text'); + // 非流事件落库时未完成的流被标记结束 + expect(timeline.sessionLogs[0].data.isCompleted).toBe(true); + + vi.advanceTimersByTime(500); + expect(timeline.sessionLogs).toHaveLength(2); // 缓冲已随 flush 清空 + }); +}); + +describe('stream store — llm_stream_reset / llm_retrying', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('llm_stream_reset:缓冲文本不残留未重置状态;已有日志标记 isReset/resetMessage', () => { + useSessionStore().selectSession('s1', false); + const { stream, es } = startStream(); + const timeline = useTimelineStore(); + + es.emit('llm_stream', { execution_id: 'e1', chunk: 'partial' }); + es.emit('llm_stream_reset', { stream_exec_id: 'e1', session_id: 's1', step_id: 'st1' }); + + expect(timeline.sessionLogs).toHaveLength(1); + expect(timeline.sessionLogs[0].data.text).toBe('partial'); + expect(timeline.sessionLogs[0].data.isReset).toBe(true); + expect(timeline.sessionLogs[0].data.resetMessage).toBe(DEFAULT_STREAM_RESET_MESSAGE); + expect(stream.streamResetEvent?.stream_exec_id).toBe('e1'); + expect(stream.streamResetEvent?.message).toBe(DEFAULT_STREAM_RESET_MESSAGE); + expect(stream.streamResetEvent?.action).toBe('discard'); + expect(stream.streamResetEvent?.reason).toBe('mid_stream_failure'); + + vi.advanceTimersByTime(500); + expect(timeline.sessionLogs).toHaveLength(1); // pending 已清空 + }); + + it('llm_stream_reset:无已有日志时追加合成重置日志,streamResetEvent 兼容 stream_execution_id 字段', () => { + useSessionStore().selectSession('s1', false); + const { stream, es } = startStream(); + const timeline = useTimelineStore(); + + es.emit('llm_stream_reset', { stream_execution_id: 'e9', session_id: 's1' }); + + expect(timeline.sessionLogs).toHaveLength(1); + const synth = timeline.sessionLogs[0]; + expect(synth.type).toBe('llm_stream'); + expect(synth.data.execution_id).toBe('e9'); + expect(synth.data.text).toBe(''); + expect(synth.data.isCompleted).toBe(false); + expect(synth.data.isReset).toBe(true); + expect(synth.data.resetMessage).toBe(DEFAULT_STREAM_RESET_MESSAGE); + expect(stream.streamResetEvent?.stream_execution_id).toBe('e9'); + }); + + it('llm_retrying:isRetrying/retryInfo 置位并追加重试 trace;同 request_id+scheduled_at 替换不新增', () => { + useSessionStore().selectSession('s1', false); + const { stream, es } = startStream(); + const timeline = useTimelineStore(); + + const retryEvent = { + session_id: 's1', + attempt: 2, + max_retries: 5, + delay: 1.5, + request_id: 'req-1', + scheduled_at: 1700000000, + timestamp: 1700000000, + error: 'rate limited', + }; + es.emit('llm_retrying', retryEvent); + + expect(stream.isRetrying).toBe(true); + expect(stream.retryInfo).toEqual({ attempt: 2, max_retries: 5, delay: 1.5 }); + + const traces = timeline.sessionLogs.filter((l) => l.type === 'trace_recorded'); + expect(traces).toHaveLength(1); + expect(traces[0].data.trace_id).toBe('llm-retry-live-req-1-1700000000'); + expect(traces[0].data.name).toBe('llm_retry'); + expect(traces[0].data.type).toBe('llm_call'); + expect(traces[0].data.status).toBe('retrying'); + expect(traces[0].data.payload.request_id).toBe('req-1'); + + es.emit('llm_retrying', { ...retryEvent, attempt: 3 }); + const afterRetry = timeline.sessionLogs.filter((l) => l.type === 'trace_recorded'); + expect(afterRetry).toHaveLength(1); // 原位替换 + expect(afterRetry[0].data.payload.attempt).toBe(3); + + // 收到 step 事件后 isRetrying 复位 + es.emit('step_updated', { session_id: 's1', step_id: 'st1' }); + expect(stream.isRetrying).toBe(false); + }); +}); + +describe('stream store — task_paused / task_resumed', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + function primePausedSession(): void { + const session = useSessionStore(); + session.$patch({ + rawSessions: [{ session_id: 's1', status: 'running', initial_goal: 'g', start_time: 1 }], + runningSessionId: 's1', + }); + session.selectSession('s1', false); + } + + it('task_paused:置暂停态并合成暂停卡;同 session+error 二次事件不重复追加', () => { + primePausedSession(); + const { stream, es } = startStream(); + const session = useSessionStore(); + const timeline = useTimelineStore(); + + es.emit('task_paused', { session_id: 's1', error: 'boom', timestamp: 1700000000, step_id: 'st9' }); + + expect(session.isPaused).toBe(true); + expect(stream.isRetrying).toBe(false); + expect(session.agentStatus).toBe('paused'); + expect(session.pausedError).toBe('boom'); + expect(session.runningSessionId).toBe('s1'); + expect(session.rawSessions[0].status).toBe('paused'); + + const cards = timeline.sessionLogs.filter((l) => l.type === 'trace_recorded'); + expect(cards).toHaveLength(1); + expect(cards[0].data.name).toBe('llm_pause'); + expect(cards[0].data.type).toBe('llm_call'); + expect(cards[0].data.status).toBe('failed'); + expect(cards[0].data.payload.error).toBe('boom'); + expect(cards[0].data.step_id).toBe('st9'); + expect(cards[0].data.trace_id).toBe('task-paused-s1-1700000000000'); + + es.emit('task_paused', { session_id: 's1', error: 'boom', timestamp: 1700000001 }); + expect(timeline.sessionLogs.filter((l) => l.type === 'trace_recorded')).toHaveLength(1); + }); + + it('task_paused:已存在同错误的 failed llm_call trace 时不追加', () => { + primePausedSession(); + const { es } = startStream(); + const session = useSessionStore(); + const timeline = useTimelineStore(); + timeline.sessionLogs = [{ + type: 'trace_recorded', + timestamp: new Date().toISOString(), + session_id: 's1', + data: { type: 'llm_call', status: 'failed', payload: { error: 'boom' } }, + }]; + + es.emit('task_paused', { session_id: 's1', error: 'boom' }); + + expect(timeline.sessionLogs).toHaveLength(1); + expect(session.pausedError).toBe('boom'); + expect(session.agentStatus).toBe('paused'); + }); + + it('task_resumed:复位暂停态并在 runningSessionId 匹配时置 running;暂停卡键清空后可再次成卡', () => { + primePausedSession(); + const { es } = startStream(); + const session = useSessionStore(); + const timeline = useTimelineStore(); + + es.emit('task_paused', { session_id: 's1', error: 'boom' }); + es.emit('task_resumed', { session_id: 's1' }); + + expect(session.isPaused).toBe(false); + expect(session.pausedError).toBeNull(); + expect(session.agentStatus).toBe('running'); + expect(session.rawSessions[0].status).toBe('running'); + + // 暂停卡键已随 resume 清空:清掉旧日志后同样的错误再次暂停会再次追加 + timeline.sessionLogs = []; + es.emit('task_paused', { session_id: 's1', error: 'boom' }); + expect(timeline.sessionLogs.filter((l) => l.type === 'trace_recorded')).toHaveLength(1); + }); +}); + +describe('stream store — session_started / session_ended', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('session_started:更新运行状态与目标;未 pin 时自动跟随', () => { + const session = useSessionStore(); + const { es } = startStream(); + + es.emit('session_started', { session_id: 'new-s', initial_goal: 'Do things' }); + + expect(session.agentStatus).toBe('running'); + expect(session.runningSessionId).toBe('new-s'); + expect(session.runningGoal).toBe('Do things'); + expect(session.currentSessionId).toBe('new-s'); + }); + + it('session_started:用户已 pin 时不抢走当前选择', () => { + const session = useSessionStore(); + session.$patch({ userPinnedSessionId: 'pinned', currentSessionId: 'pinned' }); + const { es } = startStream(); + + es.emit('session_started', { session_id: 'new-s', initial_goal: 'g' }); + + expect(session.runningSessionId).toBe('new-s'); + expect(session.currentSessionId).toBe('pinned'); + }); + + it('session_ended:status 映射三态(cancelled / failed / completed),未知状态不映射', () => { + const session = useSessionStore(); + session.$patch({ + rawSessions: ['a', 'b', 'c', 'd'].map((id) => ({ + session_id: id, + status: 'running', + initial_goal: 'g', + start_time: 1, + })), + }); + const { es } = startStream(); + + es.emit('session_ended', { session_id: 'a', status: 'failed' }); + es.emit('session_ended', { session_id: 'b', was_stopped_manually: true, status: 'running' }); + es.emit('session_ended', { session_id: 'c', status: 'success' }); + es.emit('session_ended', { session_id: 'd', status: 'weird' }); + + expect(session.rawSessions.find((s) => s.session_id === 'a')?.status).toBe('failed'); + expect(session.rawSessions.find((s) => s.session_id === 'b')?.status).toBe('cancelled'); + expect(session.rawSessions.find((s) => s.session_id === 'c')?.status).toBe('completed'); + expect(session.rawSessions.find((s) => s.session_id === 'd')?.status).toBe('running'); + }); + + it('session_ended:activeTasks 剔除、剩余任务提升 running、回查 sessions/status、当前会话回查 checks', () => { + const session = useSessionStore(); + session.$patch({ + rawSessions: [ + { session_id: 's1', status: 'running', initial_goal: 'g1', start_time: 1 }, + { session_id: 's2', status: 'running', initial_goal: 'g2', start_time: 2 }, + ], + activeTasks: [{ session_id: 's1', goal: 'g1' }, { session_id: 's2', goal: 'g2' }], + runningSessionId: 's1', + runningGoal: 'g1', + currentSessionId: 's1', + }); + const { es } = startStream(); + + es.emit('session_ended', { session_id: 's1', status: 'completed' }); + + expect(session.rawSessions.find((s) => s.session_id === 's1')?.status).toBe('completed'); + expect(session.activeTasks.map((at) => at.session_id)).toEqual(['s2']); + // 剩余 activeTasks → 全局保持 running 并切换到 s2 + expect(session.agentStatus).toBe('running'); + expect(session.runningSessionId).toBe('s2'); + expect(session.runningGoal).toBe('g2'); + expect(session.isPaused).toBe(false); + + expect(apiGetMock).toHaveBeenCalledWith('/api/sessions'); + expect(apiGetMock).toHaveBeenCalledWith('/api/status'); + expect(apiGetMock).toHaveBeenCalledWith('/api/sessions/s1/notes'); + expect(apiGetMock).toHaveBeenCalledWith('/api/sessions/s1/checks'); + }); + + it('session_ended:无剩余 activeTasks 时从 pending 队列队首提升;全空回 idle', () => { + const session = useSessionStore(); + session.$patch({ + activeTasks: [{ session_id: 's1', goal: 'g1' }], + pendingQueue: [{ session_id: 'q1', initial_goal: 'queued goal', start_time: 1, status: 'pending' }], + runningSessionId: 's1', + }); + const { es } = startStream(); + + es.emit('session_ended', { session_id: 's1', status: 'completed' }); + expect(session.agentStatus).toBe('running'); + expect(session.runningSessionId).toBe('q1'); + expect(session.runningGoal).toBe('queued goal'); + + // pending 队列为空 → 回 idle + session.$patch({ pendingQueue: [] }); + es.emit('session_ended', { session_id: 'q1', status: 'completed' }); + expect(session.agentStatus).toBe('idle'); + expect(session.runningSessionId).toBeNull(); + expect(session.runningGoal).toBeNull(); + }); +}); + +describe('stream store — 会话过滤与日志事件', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('会话过滤:其他会话的日志事件不入 sessionLogs', () => { + useSessionStore().selectSession('s1', false); + const { es } = startStream(); + const timeline = useTimelineStore(); + + es.emit('trace_recorded', { session_id: 'other', trace_id: 't1', name: 'x' }); + es.emit('step_recorded', { session_id: 'other', step_id: 'st' }); + + expect(timeline.sessionLogs).toHaveLength(0); + }); + + it('trace_recorded:同 trace_id 原位替换不新增;note 工具 trace 触发 fetchNotes', () => { + useSessionStore().selectSession('s1', false); + const { es } = startStream(); + const timeline = useTimelineStore(); + + es.emit('trace_recorded', { session_id: 's1', trace_id: 't1', name: 'action', status: 'running', timestamp: 100 }); + es.emit('trace_recorded', { session_id: 's1', trace_id: 't1', name: 'action', status: 'done', timestamp: 200 }); + + expect(timeline.sessionLogs).toHaveLength(1); + expect(timeline.sessionLogs[0].data.status).toBe('done'); + expect(timeline.sessionLogs[0].timestamp).toBe(new Date(200 * 1000).toISOString()); + + apiGetMock.mockClear(); + es.emit('trace_recorded', { session_id: 's1', trace_id: 't2', name: 'save_note' }); + expect(apiGetMock).toHaveBeenCalledWith('/api/sessions/s1/notes'); + }); + + it('info:对当前会话触发 steps 快照回填(断线重连对账)', () => { + useSessionStore().selectSession('s1', false); + const { es } = startStream(); + + es.emit('info', { message: 'subscribed' }); + + expect(apiGetMock).toHaveBeenCalledWith('/api/sessions/s1/steps'); + }); +}); + +describe('stream store — startup_progress 与停止语义', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('startup_progress:合入对应会话桶且按 stage 幂等;未 pin 且异会话时自动跟随', () => { + const session = useSessionStore(); + session.$patch({ currentSessionId: 's1' }); + const { es } = startStream(); + const timeline = useTimelineStore(); + + es.emit('startup_progress', { session_id: 'sX', stage: 'device_check', message: 'checking', timestamp: 1 }); + es.emit('startup_progress', { session_id: 'sX', stage: 'device_check', message: 'checking again', timestamp: 2 }); + es.emit('startup_progress', { session_id: 'sX', stage: 'device_ready', message: 'ready', timestamp: 3 }); + + expect(timeline.startupProgressBySession['sX']).toHaveLength(2); // 同 stage 幂等 + expect(timeline.startupProgressBySession['sX'][0].message).toBe('checking'); + // 未 pin 且异会话 → 自动跟随 + expect(session.agentStatus).toBe('running'); + expect(session.runningSessionId).toBe('sX'); + expect(session.currentSessionId).toBe('sX'); + }); + + it('startup_progress:已 pin 时不跟随', () => { + const session = useSessionStore(); + session.$patch({ currentSessionId: 's1', userPinnedSessionId: 's1' }); + const { es } = startStream(); + + es.emit('startup_progress', { session_id: 'sX', stage: 'device_check', message: 'm', timestamp: 1 }); + + expect(session.currentSessionId).toBe('s1'); + }); + + it('markStoppedSessionStreamsCompleted:flush 缓冲并把未完成流全部置 isCompleted;无未完成流时不产生新引用', () => { + useSessionStore().selectSession('s1', false); + const { stream, es } = startStream(); + const timeline = useTimelineStore(); + + es.emit('llm_stream', { execution_id: 'e1', chunk: 'a' }); + es.emit('llm_stream', { execution_id: 'e2', stream_type: 'thinking', chunk: 'b' }); + stream.markStoppedSessionStreamsCompleted(); + + expect(timeline.sessionLogs).toHaveLength(2); + expect(timeline.sessionLogs.every((l) => l.data.isCompleted)).toBe(true); + + const before = timeline.sessionLogs; + stream.markStoppedSessionStreamsCompleted(); + expect(timeline.sessionLogs).toBe(before); + }); +}); + +describe('stream store — 连接管理', () => { + beforeEach(startEnv); + afterEach(stopEnv); + + it('start 创建 /api/stream 单通道连接且幂等;stop 关闭并清空缓冲', () => { + const { stream, es } = startStream(); + + expect(FakeEventSource.instances).toHaveLength(1); + expect(es.url).toBe('/api/stream'); + + stream.start(); // 幂等:重复调用不重建连接 + expect(FakeEventSource.instances).toHaveLength(1); + + es.emit('llm_stream', { execution_id: 'e1', chunk: 'x' }); // 进入缓冲 + stream.stop(); + expect(es.closed).toBe(true); + + // 缓冲随 stop 清空:定时器不再触发落库 + vi.advanceTimersByTime(500); + expect(useTimelineStore().sessionLogs).toHaveLength(0); + + stream.start(); + expect(FakeEventSource.instances).toHaveLength(2); + }); +}); + +/** 每个用例的公共环境:新 Pinia、注入 FakeEventSource、fake timers。 */ +function startEnv(): void { + setActivePinia(createPinia()); + vi.clearAllMocks(); + mockApiRoutes({}); + FakeEventSource.instances = []; + (globalThis as Record).EventSource = FakeEventSource; + vi.useFakeTimers(); +} + +function stopEnv(): void { + useStreamStore().stop(); + vi.useRealTimers(); + delete (globalThis as Record).EventSource; +} diff --git a/apps/showcase_ui_v2/src/stores/stream.ts b/apps/showcase_ui_v2/src/stores/stream.ts new file mode 100644 index 000000000..2a80e1f10 --- /dev/null +++ b/apps/showcase_ui_v2/src/stores/stream.ts @@ -0,0 +1,738 @@ +/** + * SSE 实时流 store —— 从 Angular `AgentService.ensureLiveStream`(L762-1110)及 + * 合批 / 重试 trace / 暂停卡 / 终态映射(L1112-1212、L1319-1470、L529-549)平移的 M3 部分: + * + * - `/api/stream` 单通道 EventSource(幂等 start;onerror 只告警,浏览器原生自动 + * 重连,不手动重建连接——调研报告 §3.1 决策)。 + * - 17 种事件逐条平移:info 断线重连对账、session_started / session_ended 联动、 + * startup_progress 合并与自动跟随(pin 语义)、task_paused / task_resumed 状态机、 + * llm_retrying 重试 trace、llm_stream_reset 流重置、llm_stream 合批。 + * - 合批与顺序保证(§3.3 条款 1):llm_stream 按 key 缓冲,80ms(前台)/ 500ms + * (document.hidden)定时落库;任何非 llm_stream 事件先 flushStreamChunks() 再 + * 处理,保证缓冲文本先于事件日志落库。 + * - 泳道语义:新 execution_id 只关闭同 stream_type + 同 parent_trace_id 的未完成 + * 流,并发 agent(Operator vs Checker)互不关闭。 + * - 日志写入口:直接读写 timeline store 导出的 sessionLogs ref。 + * - recording_ready / recording_failed / session_ended 的录像 finalization 联动 + * 回调 stores/player.ts(M4)。 + * + * 与 Angular 版的有意差异:retryMessage 文案信号拆为结构化 retryInfo + * (attempt / max_retries / delay),文案由 UI 层用 i18n 组装。 + */ + +import { ref, watch } from 'vue'; +import { defineStore } from 'pinia'; + +import { useSessionStore } from '@/stores/session'; +import { usePlayerStore } from '@/stores/player'; +import { useTimelineStore, type SessionLog } from '@/stores/timeline'; +import type { Session } from '@/types/session.model'; +import { + DEFAULT_STREAM_RESET_MESSAGE, + type LLMStreamResetEventData, +} from '@/types/stream.model'; + +/** 待落库的 llm_stream 合批缓冲(key = `${execution_id}|${stream_type}`)。 */ +interface PendingStreamChunk { + execId: string; + stepId?: string; + sessionId: string | null; + /** 发出该流的 agent trace:泳道判定的依据(并发 agent 各自成道)。 */ + parentTraceId: string | null; + streamType: string; + chunk: string; +} + +/** 订阅的事件类型(info / keep-alive 有独立监听,不在此列)。 */ +const STREAM_EVENT_TYPES = [ + 'llm_stream', + 'llm_stream_reset', + 'trace_recorded', + 'step_recorded', + 'step_updated', + 'background_tasks_updated', + 'task_paused', + 'task_resumed', + 'llm_retrying', + 'startup_progress', + 'session_started', + 'session_ended', + 'recording_ready', + 'recording_failed', + 'checker_event', +] as const; + +export const useStreamStore = defineStore('stream', () => { + // ---- 响应式状态(对应 Angular 同名信号)---- + const isRetrying = ref(false); + /** 结构化重试信息:Angular 把文案拼在 service 里,v2 交由 UI 用 i18n 组装。 */ + const retryInfo = ref<{ attempt: number; max_retries: number; delay: number } | null>(null); + const streamResetEvent = ref(null); + + // ---- 非响应式内部状态 ---- + let eventSource: EventSource | null = null; + const pendingStreamChunks = new Map(); + let streamFlushTimer: ReturnType | null = null; + /** 暂停卡去重键(`${sessionId}:${errorText}`);task_resumed / 状态恢复时清空。 */ + let activePauseCardKey: string | null = null; + let stopSessionWatch: (() => void) | null = null; + + // ---- llm_stream 合批(平移自 Angular queueStreamChunk / flushStreamChunks)---- + + /** + * 缓冲一个 llm_stream chunk;同一 execution_id + stream_type 的 chunk 累加, + * 短窗口内最多落库一次(非流事件到来前也会立即 flush,保持相对顺序)。 + */ + function queueStreamChunk(parsedData: any): void { + const execId = parsedData.execution_id; + const stepId = parsedData.step_id; + const sessionId = parsedData.session_id || null; + const parentTraceId = parsedData.parent_trace_id || null; + const streamType = parsedData.stream_type || 'text'; + const key = `${execId}|${streamType}`; + const chunk = parsedData.chunk !== undefined ? parsedData.chunk : (parsedData.text || ''); + const pending = pendingStreamChunks.get(key); + if (pending) { + pending.chunk += chunk; + if (stepId) pending.stepId = stepId; + if (sessionId) pending.sessionId = sessionId; + if (parentTraceId) pending.parentTraceId = parentTraceId; + } else { + pendingStreamChunks.set(key, { execId, stepId, sessionId, parentTraceId, streamType, chunk }); + } + if (!streamFlushTimer) { + // 后台标签页降低刷新频率。 + const delay = typeof document !== 'undefined' && document.hidden ? 500 : 80; + streamFlushTimer = setTimeout(() => flushStreamChunks(), delay); + } + } + + /** 丢弃缓冲并清掉 flush 定时器(切会话 / stop 时调用)。 */ + function discardPendingStreamChunks(): void { + pendingStreamChunks.clear(); + if (streamFlushTimer) { + clearTimeout(streamFlushTimer); + streamFlushTimer = null; + } + } + + /** 把缓冲批量落库:命中既有 llm_stream 日志则追加文本,否则按泳道开新流。 */ + function flushStreamChunks(): void { + if (streamFlushTimer) { + clearTimeout(streamFlushTimer); + streamFlushTimer = null; + } + if (!pendingStreamChunks.size) return; + const batches = Array.from(pendingStreamChunks.values()); + pendingStreamChunks.clear(); + + const timelineStore = useTimelineStore(); + let next = [...timelineStore.sessionLogs]; + for (const batch of batches) { + const existingIndex = next.findIndex( + (l) => l.type === 'llm_stream' + && l.data.execution_id === batch.execId + && (l.data.stream_type || 'text') === batch.streamType, + ); + + if (existingIndex > -1) { + const existingLog = next[existingIndex]; + next[existingIndex] = { + ...existingLog, + session_id: batch.sessionId || existingLog.session_id, + data: { + ...existingLog.data, + session_id: batch.sessionId || existingLog.data?.session_id, + text: (existingLog.data.text || '') + batch.chunk, + step_id: batch.stepId || existingLog.data.step_id, + parent_trace_id: batch.parentTraceId || existingLog.data.parent_trace_id || null, + }, + }; + } else { + // 新 execution_id 只关闭同一 agent 泳道(同 stream_type + 同 parent_trace_id) + // 的未完成流;并发 agent(如 Checker)的流保持打开。 + next = next.map((l) => { + if (l.type === 'llm_stream' + && (l.data.stream_type || 'text') === batch.streamType + && !l.data.isCompleted + && (l.data.parent_trace_id || null) === (batch.parentTraceId || null)) { + return { ...l, data: { ...l.data, isCompleted: true } }; + } + return l; + }); + next.push({ + type: 'llm_stream', + timestamp: new Date().toISOString(), + session_id: batch.sessionId || undefined, + data: { + execution_id: batch.execId, + session_id: batch.sessionId || undefined, + step_id: batch.stepId, + parent_trace_id: batch.parentTraceId || null, + text: batch.chunk, + stream_type: batch.streamType, + isCompleted: false, + }, + }); + } + } + timelineStore.sessionLogs = next; + } + + /** + * 停止任务时把未完成的 llm_stream 全部标记结束(先 flush 缓冲,平移自 Angular + * stopTask L536-549);无未完成流时不产生新数组引用。 + */ + function markStoppedSessionStreamsCompleted(): void { + flushStreamChunks(); + const timelineStore = useTimelineStore(); + const logs = timelineStore.sessionLogs; + if (!logs.some((l) => l.type === 'llm_stream' && !l.data?.isCompleted)) { + return; + } + timelineStore.sessionLogs = logs.map((l) => { + if (l.type === 'llm_stream' && !l.data?.isCompleted) { + return { ...l, data: { ...l.data, isCompleted: true } }; + } + return l; + }); + } + + // ---- 重试 / 暂停卡片(平移自 Angular appendLiveLLMRetryTrace / appendPausedErrorCard)---- + + /** + * 把实时 llm_retrying 事件合成为与历史 API 相同形状的 trace 日志,实时流与 + * 刷新后渲染共用一套数据契约;同 trace_id 或同 request_id + scheduled_at + * 原位替换、不新增。 + */ + function appendLiveLLMRetryTrace(data: any, sessionId: string): void { + const timelineStore = useTimelineStore(); + const timestampSeconds = typeof data?.timestamp === 'number' + ? (data.timestamp > 1e11 ? data.timestamp / 1000 : data.timestamp) + : Date.now() / 1000; + const traceId = data?.trace_id + || `llm-retry-live-${data?.request_id || 'unknown'}-${timestampSeconds}`; + const payload = { + error: data?.error, + delay: data?.delay, + attempt: data?.attempt, + max_retries: data?.max_retries, + provider: data?.provider, + source: data?.source, + recoverable: data?.recoverable, + request_id: data?.request_id, + scheduled_at: data?.scheduled_at ?? timestampSeconds, + }; + const retryTrace = { + trace_id: traceId, + session_id: sessionId, + step_id: data?.step_id || null, + type: 'llm_call', + name: 'llm_retry', + timestamp: timestampSeconds, + status: 'retrying', + payload, + }; + + const retryLog: SessionLog = { + type: 'trace_recorded', + session_id: sessionId, + timestamp: new Date(timestampSeconds * 1000).toISOString(), + data: retryTrace, + }; + const logs = timelineStore.sessionLogs; + const existingIndex = logs.findIndex((log) => + log.type === 'trace_recorded' + && ( + log.data?.trace_id === traceId + || ( + data?.request_id + && log.data?.payload?.request_id === data.request_id + && Number(log.data?.payload?.scheduled_at) === Number(payload.scheduled_at) + ) + ), + ); + if (existingIndex < 0) { + timelineStore.sessionLogs = [...logs, retryLog]; + return; + } + const updatedLogs = [...logs]; + updatedLogs[existingIndex] = retryLog; + timelineStore.sessionLogs = updatedLogs; + } + + /** + * 暂停失败写入常规的 failed-LLM 卡片流:新 runner 先落持久 failed trace(由 + * alreadyRecorded 检查识别),这里同时兜底旧 runner 只带错误字符串的 + * task_paused;activePauseCardKey 对同 session + 同错误去重。 + */ + function appendPausedErrorCard( + error: unknown, + sessionId: string, + timestamp?: number | string, + stepId?: string | null, + details?: any, + ): void { + const timelineStore = useTimelineStore(); + const errorText = typeof error === 'string' ? error : JSON.stringify(error); + const pauseKey = `${sessionId}:${errorText}`; + if (activePauseCardKey === pauseKey) return; + + const logs = timelineStore.sessionLogs; + const alreadyRecorded = logs.some((log) => { + const traces = log?.type === 'trace_recorded' + ? [log.data] + : (Array.isArray(log?.data?.generic_tools) ? log.data.generic_tools : []); + return traces.some((trace: any) => + trace?.type === 'llm_call' + && trace?.status === 'failed' + && String(trace?.payload?.error ?? trace?.error ?? '') === errorText, + ); + }); + + if (!alreadyRecorded) { + // 未指定 step 时回退到最近一条 step 日志。 + const latestStepId = stepId || [...logs].reverse().find( + (log) => (log.type === 'step_updated' || log.type === 'step_recorded') && log.data?.step_id, + )?.data?.step_id || null; + const timestampMs = typeof timestamp === 'number' + ? (timestamp < 1e11 ? timestamp * 1000 : timestamp) + : (timestamp ? new Date(timestamp).getTime() : Date.now()); + + timelineStore.sessionLogs = [ + ...logs, + { + type: 'trace_recorded', + session_id: sessionId, + timestamp: new Date(timestampMs).toISOString(), + data: { + trace_id: `task-paused-${sessionId}-${timestampMs}`, + session_id: sessionId, + step_id: latestStepId, + type: 'llm_call', + name: 'llm_pause', + status: 'failed', + timestamp: timestampMs / 1000, + payload: { + error: errorText, + pause: true, + request_id: details?.request_id, + provider: details?.provider, + waited_seconds: details?.waited_seconds, + retries: Array.isArray(details?.retries) ? details.retries : [], + }, + }, + }, + ]; + } + activePauseCardKey = pauseKey; + } + + /** 清空暂停卡去重键(task_resumed / 状态轮询恢复非暂停态时)。 */ + function clearPauseCard(): void { + activePauseCardKey = null; + } + + /** 复位重试状态(平移自 Angular stopTask L529 的 isRetrying.set(false))。 */ + function resetRetryState(): void { + isRetrying.value = false; + retryInfo.value = null; + } + + // ---- session_ended 终态映射(平移自 Angular applySessionEndedStatus)---- + + function applySessionEndedStatus(sessionId: unknown, data: any): void { + if (!sessionId) return; + const sessionStore = useSessionStore(); + const reportedStatus = String(data?.status || '').toLowerCase(); + const status: Session['status'] | null = data?.was_stopped_manually || reportedStatus === 'cancelled' + ? 'cancelled' + : reportedStatus === 'failed' + ? 'failed' + : reportedStatus === 'completed' || reportedStatus === 'success' + ? 'completed' + : null; + + if (status) { + sessionStore.setSessionStatus(String(sessionId), status); + sessionStore.invalidateStatusSignatures(); + sessionStore.activeTasks = sessionStore.activeTasks.filter( + (at) => at.session_id !== String(sessionId), + ); + } + } + + // ---- 事件分发(逐条对齐 Angular ensureLiveStream L774-1104)---- + + function handleStreamEvent(eventType: string, event: MessageEvent): void { + const sessionStore = useSessionStore(); + const timelineStore = useTimelineStore(); + try { + const parsedData = JSON.parse(event.data); + const evtSessionId = parsedData?.session_id; + + // 顺序保证(§3.3 条款 1):缓冲中的流文本必须先于任何非流事件落库。 + if (eventType !== 'llm_stream') { + flushStreamChunks(); + } + + if (eventType === 'recording_ready' || eventType === 'recording_failed') { + // M4:录像 finalization 联动(平移自 Angular L816-836)。在会话过滤之前 + // 处理:视频窗口打开且事件属于正在回放的会话时驱动播放器状态机。 + const playerStore = usePlayerStore(); + if (playerStore.isVideoWindowOpen && evtSessionId && playerStore.isVideoSession(evtSessionId)) { + if (eventType === 'recording_ready') { + playerStore.refreshActiveRecording(true); + } else { + playerStore.notifyRecordingFailed( + parsedData?.error || 'Recording finalization failed.', + ); + } + } + return; + } + + if (eventType === 'background_tasks_updated') { + void sessionStore.fetchStatus(); + return; + } + + if (eventType === 'session_started') { + sessionStore.agentStatus = 'running'; + if (parsedData?.session_id) { + sessionStore.runningSessionId = parsedData.session_id; + } + if (parsedData?.initial_goal) { + sessionStore.runningGoal = parsedData.initial_goal; + } + void sessionStore.fetchSessions(); + + // 自动跟随:用户未显式 pin 历史会话时,切换视图到新运行会话。 + if (!sessionStore.userPinnedSessionId && parsedData?.session_id) { + sessionStore.selectSession(parsedData.session_id, false); + } + return; + } + + if (eventType === 'session_ended') { + const endedId = evtSessionId || sessionStore.runningSessionId; + if (endedId) { + applySessionEndedStatus(endedId, parsedData); + sessionStore.invalidateStatusSignatures(); + sessionStore.activeTasks = sessionStore.activeTasks.filter( + (at) => at.session_id !== endedId, + ); + } + // 按剩余 activeTasks / pending 队列推导全局运行状态。 + const remaining = sessionStore.activeTasks; + if (remaining.length > 0) { + sessionStore.agentStatus = 'running'; + sessionStore.runningSessionId = remaining[0].session_id || null; + sessionStore.runningGoal = remaining[0].goal || null; + } else if (sessionStore.pendingQueue.length > 0) { + const nextPending = sessionStore.pendingQueue[0]; + sessionStore.agentStatus = 'running'; + sessionStore.runningSessionId = nextPending.session_id; + sessionStore.runningGoal = nextPending.initial_goal || null; + } else { + sessionStore.agentStatus = 'idle'; + sessionStore.runningSessionId = null; + sessionStore.runningGoal = null; + } + resetRetryState(); + sessionStore.isPaused = false; + void sessionStore.fetchSessions(); + void sessionStore.fetchStatus(); + if (endedId) { + timelineStore.fetchNotes(endedId); + if (String(endedId) === String(sessionStore.currentSessionId || '')) { + // 退出终审 / 运行结果可能在流断连期间落库:从持久账本对账。 + timelineStore.fetchChecks(endedId); + } + // M4:live 投屏中的会话结束时立即转入录像 finalization 轮询 + // (平移自 Angular L893-899)。 + const playerStore = usePlayerStore(); + if ( + playerStore.isVideoWindowOpen + && playerStore.isVideoSession(endedId) + && playerStore.recordingPlaybackStatus === 'live' + ) { + playerStore.beginRecordingFinalization(String(endedId)); + } + } + return; + } + + if (eventType === 'startup_progress') { + const targetSid = evtSessionId || sessionStore.currentSessionId; + if (targetSid) { + timelineStore.appendStartupEvent(parsedData, targetSid); + const curId = sessionStore.currentSessionId; + if ( + !sessionStore.userPinnedSessionId + && (!curId + || String(targetSid).trim().toLowerCase() !== String(curId).trim().toLowerCase()) + ) { + sessionStore.agentStatus = 'running'; + sessionStore.runningSessionId = targetSid; + sessionStore.selectSession(targetSid, false); + } + } + return; + } + + // 其余日志类事件:其他会话的事件不写入当前日志。 + const curId = sessionStore.currentSessionId; + if ( + evtSessionId + && curId + && String(evtSessionId).trim().toLowerCase() !== String(curId).trim().toLowerCase() + ) { + return; + } + + if (eventType === 'llm_retrying') { + isRetrying.value = true; + retryInfo.value = { + attempt: Number(parsedData.attempt || 0), + max_retries: Number(parsedData.max_retries || 0), + delay: Number(parsedData.delay || 0), + }; + if (curId) { + appendLiveLLMRetryTrace(parsedData, curId); + } + return; + } + + if (eventType === 'task_paused') { + sessionStore.isPaused = true; + isRetrying.value = false; + sessionStore.agentStatus = 'paused'; + if (curId) { + sessionStore.runningSessionId = curId; + sessionStore.setSessionStatus(curId, 'paused'); + const pauseError = parsedData.error || 'AI call failed'; + sessionStore.pausedError = pauseError; + appendPausedErrorCard( + pauseError, + curId, + parsedData.timestamp, + parsedData.step_id, + parsedData, + ); + } + return; + } + + if (eventType === 'task_resumed') { + sessionStore.isPaused = false; + isRetrying.value = false; + sessionStore.pausedError = null; + if (curId && sessionStore.runningSessionId === curId) { + sessionStore.agentStatus = 'running'; + sessionStore.setSessionStatus(curId, 'running'); + } + activePauseCardKey = null; + return; + } + + if (eventType === 'step_updated' || eventType === 'step_recorded' || eventType === 'llm_stream') { + isRetrying.value = false; + } + + if (eventType === 'llm_stream_reset') { + const streamExecId = parsedData?.stream_exec_id || parsedData?.stream_execution_id; + if (streamExecId) { + for (const key of Array.from(pendingStreamChunks.keys())) { + if (key.startsWith(`${streamExecId}|`) || key === streamExecId) { + pendingStreamChunks.delete(key); + } + } + } + const resetMessage = parsedData?.message || DEFAULT_STREAM_RESET_MESSAGE; + streamResetEvent.value = { + stream_exec_id: streamExecId, + stream_execution_id: streamExecId, + step_id: parsedData?.step_id, + session_id: parsedData?.session_id, + action: parsedData?.action || 'discard', + reason: parsedData?.reason || 'mid_stream_failure', + category: parsedData?.category, + error: parsedData?.error, + message: resetMessage, + retry_attempt: parsedData?.retry_attempt, + timestamp: Date.now(), + }; + + // 已有同 execution_id 的流日志就地标记重置;完全没有时追加合成重置日志。 + const logs = timelineStore.sessionLogs; + let updated = false; + let next = logs.map((log) => { + if (log.type === 'llm_stream' && log.data?.execution_id === streamExecId) { + updated = true; + return { + ...log, + data: { ...log.data, isReset: true, resetMessage }, + }; + } + return log; + }); + if (!updated && streamExecId) { + next = [...next, { + type: 'llm_stream', + timestamp: new Date().toISOString(), + session_id: parsedData?.session_id, + data: { + execution_id: streamExecId, + step_id: parsedData?.step_id, + stream_type: 'text', + text: '', + isCompleted: false, + isReset: true, + resetMessage, + }, + }]; + } + timelineStore.sessionLogs = next; + return; + } + + if (eventType === 'llm_stream') { + queueStreamChunk(parsedData); + } else { + const logs = timelineStore.sessionLogs; + // 无未完成流时不复制日志数组;只重写真正变化的条目。 + const hasOpenStream = logs.some( + (l) => l.type === 'llm_stream' && !l.data.isCompleted, + ); + let updatedLogs = hasOpenStream + ? logs.map((l) => { + if (l.type === 'llm_stream' && !l.data.isCompleted) { + return { ...l, data: { ...l.data, isCompleted: true } }; + } + return l; + }) + : logs; + + const evtTime = typeof parsedData?.timestamp === 'number' + ? new Date(parsedData.timestamp * 1000).toISOString() + : new Date().toISOString(); + + const nextLog: SessionLog = { + type: eventType, + timestamp: evtTime, + data: parsedData, + }; + + let replacedInPlace = false; + if (eventType === 'trace_recorded' && parsedData?.trace_id) { + // 同 trace_id 的 trace 事件原位替换(重试 / 进度类 trace 会重复推送)。 + const existingTraceIndex = updatedLogs.findIndex( + (log) => log.type === 'trace_recorded' && log.data?.trace_id === parsedData.trace_id, + ); + if (existingTraceIndex > -1) { + const deduplicatedLogs = [...updatedLogs]; + deduplicatedLogs[existingTraceIndex] = nextLog; + updatedLogs = deduplicatedLogs; + replacedInPlace = true; + } + } + timelineStore.sessionLogs = replacedInPlace ? updatedLogs : [...updatedLogs, nextLog]; + } + + if (eventType === 'trace_recorded' && parsedData) { + // 笔记相关工具的 trace 落库后刷新笔记面板。 + const trName = parsedData.name || ''; + if (['save_note', 'read_note', 'update_note', 'append_note', 'list_notes', 'outputter'] + .includes(trName.toLowerCase())) { + if (curId) { + timelineStore.fetchNotes(curId); + } + } + } + } catch (e) { + console.error(`Failed to parse ${eventType} event data:`, e); + timelineStore.sessionLogs = [ + ...timelineStore.sessionLogs, + { + type: eventType, + timestamp: new Date().toISOString(), + data: event.data, + }, + ]; + } + } + + // ---- 连接管理 ---- + + /** 建立 `/api/stream` 单通道连接(幂等;对应 Angular ensureLiveStream)。 */ + function start(): void { + if (eventSource) return; + const sessionStore = useSessionStore(); + + eventSource = new EventSource('/api/stream'); + + // 断线重连后的快照对账(§3.3 条款 5 / R9):对当前会话重新回填 steps。 + eventSource.addEventListener('info', () => { + const curId = useSessionStore().currentSessionId; + if (curId) { + useTimelineStore().backfillSessionSteps(curId); + } + }); + + // 后端 5s keep-alive tick,无需处理。 + eventSource.addEventListener('keep-alive', () => {}); + + STREAM_EVENT_TYPES.forEach((eventType) => { + eventSource?.addEventListener( + eventType, + (event) => handleStreamEvent(eventType, event as MessageEvent), + ); + }); + + // 浏览器 EventSource 原生自动重连,不手动重建连接。 + eventSource.onerror = (err) => { + console.warn('Persistent live stream issue, browser will auto-reconnect:', err); + }; + + // 切会话时同步清理流缓冲与暂停卡(平移自 Angular selectSession L722/L741; + // 日志本体由 timeline store 的 adoptSession 重置)。 + stopSessionWatch = watch( + () => sessionStore.currentSessionId, + () => { + discardPendingStreamChunks(); + activePauseCardKey = null; + }, + ); + } + + /** 关闭连接、清空缓冲与定时器并移除内部 watch(App.vue onBeforeUnmount)。 */ + function stop(): void { + if (eventSource) { + eventSource.close(); + eventSource = null; + } + discardPendingStreamChunks(); + if (stopSessionWatch) { + stopSessionWatch(); + stopSessionWatch = null; + } + } + + return { + // state + isRetrying, + retryInfo, + streamResetEvent, + // lifecycle + start, + stop, + // actions + flushStreamChunks, + discardPendingStreamChunks, + markStoppedSessionStreamsCompleted, + appendPausedErrorCard, + clearPauseCard, + resetRetryState, + }; +}); diff --git a/apps/showcase_ui_v2/src/stores/system.spec.ts b/apps/showcase_ui_v2/src/stores/system.spec.ts index 2f31b2624..9adef33f6 100644 --- a/apps/showcase_ui_v2/src/stores/system.spec.ts +++ b/apps/showcase_ui_v2/src/stores/system.spec.ts @@ -1,18 +1,143 @@ -import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; import { createPinia, setActivePinia } from 'pinia'; vi.mock('@/services/api', () => ({ apiGet: vi.fn(), apiPost: vi.fn() })); -import { apiGet } from '@/services/api'; +import { apiGet, apiPost } from '@/services/api'; import { useSystemStore } from './system'; +import type { + DeviceInfo, + EmulatorLaunchState, + ModelConfigEnvResponse, + ProbeResult, + ProbeStatus, + SystemReadinessReport, +} from '@/types/system.model'; const apiGetMock = apiGet as unknown as Mock; +const apiPostMock = apiPost as unknown as Mock; + +const READINESS_URL = '/api/system/readiness'; +const EMULATOR_STATUS_URL = '/api/system/emulator/status'; + +const remoteEndpoint = { + host: '10.0.0.5', + port: 5037, + socket: '10.0.0.5:5037', + identity: 'remote', + mode: 'remote' as const, + is_local_default: false, +}; +const localEndpoint = { + host: '127.0.0.1', + port: 5037, + socket: '127.0.0.1:5037', + identity: 'local', + mode: 'local' as const, + is_local_default: true, +}; + +function makeProbe( + id: string, + status: ProbeStatus, + metadata: Record = {}, + isBlocker = true, +): ProbeResult { + return { + id, + category: 'runtime', + title: id, + status, + is_blocker: isBlocker, + summary: '', + description: '', + metadata, + actions: [], + }; +} + +function makeReport(overrides: Partial = {}): SystemReadinessReport { + return { + overall_ready: false, + blocker_count: 3, + passed_blocker_count: 0, + probes: [], + active_device: null, + os_type: 'win32', + timestamp: 1000, + ...overrides, + }; +} + +function makeEmulatorState(overrides: Partial = {}): EmulatorLaunchState { + return { + avd_name: 'Pixel_7', + status: 'starting', + pid: 4321, + serial: null, + stage_message: 'starting', + progress_percent: 30, + started_at: 1700000000, + elapsed_seconds: 1, + error: null, + logs: [], + can_retry: false, + ...overrides, + }; +} + +function makeDevice(overrides: Partial = {}): DeviceInfo { + return { + serial: 'emu-5554', + state: 'device', + model: 'Pixel_7', + product: null, + android_version: null, + screen_resolution: null, + is_locked: null, + is_emulator: true, + ...overrides, + }; +} + +function makeModelConfigEnv(): ModelConfigEnvResponse { + return { + config_path: '/cfg/artemis.jsonc', + config_filename: 'artemis.jsonc', + config_content: '{}', + default_model: { provider: 'google', model: 'gemini-2.0-flash' }, + presets: {}, + env_path: '/cfg/.env', + env_filename: '.env', + env_vars: [ + { + name: 'GEMINI_API_KEY', + provider: 'google', + is_set: true, + preview: '****abcd', + description: 'gemini key', + }, + ], + }; +} + +function emulatorStatusCallCount(): number { + return apiGetMock.mock.calls.filter((c) => c[0] === EMULATOR_STATUS_URL).length; +} + +function cleanupTimers(): void { + if (vi.isFakeTimers()) { + vi.clearAllTimers(); + vi.useRealTimers(); + } +} describe('system store — M1 最小连通性轮询', () => { beforeEach(() => { setActivePinia(createPinia()); vi.clearAllMocks(); }); + afterEach(cleanupTimers); it('后端可达时 online=true', async () => { apiGetMock.mockResolvedValue({ status: 'idle' }); @@ -42,19 +167,536 @@ describe('system store — M1 最小连通性轮询', () => { await vi.advanceTimersByTimeAsync(0); apiGetMock.mockClear(); - // 模拟页面隐藏 + // 模拟页面隐藏:连通性与 readiness 轮询均跳过 const hiddenSpy = vi.spyOn(document, 'hidden', 'get').mockReturnValue(true); await vi.advanceTimersByTimeAsync(10_000); expect(apiGetMock).not.toHaveBeenCalled(); - // 模拟恢复可见 → 立即刷新一次 + // 模拟恢复可见 → 立即刷新(M5 起 readiness 也会一并静默刷新) hiddenSpy.mockReturnValue(false); document.dispatchEvent(new Event('visibilitychange')); await vi.advanceTimersByTimeAsync(0); - expect(apiGetMock).toHaveBeenCalledTimes(1); + const statusCalls = apiGetMock.mock.calls.filter((c) => c[0] === '/api/status').length; + expect(statusCalls).toBe(1); + expect(apiGetMock).toHaveBeenCalledWith(READINESS_URL); store.stop(); vi.useRealTimers(); hiddenSpy.mockRestore(); }); }); + +describe('system store — M5 readiness', () => { + beforeEach(() => { + setActivePinia(createPinia()); + vi.clearAllMocks(); + }); + afterEach(cleanupTimers); + + it('fetchReadiness silent=true 不置 isLoading;非静默置位并在完成后复位', async () => { + let resolveFn!: (v: SystemReadinessReport) => void; + apiGetMock.mockImplementationOnce( + () => new Promise((res) => (resolveFn = res)), + ); + const store = useSystemStore(); + + const p = store.fetchReadiness(); + expect(store.isLoading).toBe(true); + resolveFn(makeReport()); + await p; + expect(store.isLoading).toBe(false); + + apiGetMock.mockResolvedValueOnce(makeReport()); + await store.fetchReadiness(true); + expect(store.isLoading).toBe(false); + }); + + it('forceRefresh 时请求带 ?force=true 的 URL', async () => { + apiGetMock.mockResolvedValue(makeReport()); + const store = useSystemStore(); + + await store.fetchReadiness(false, true); + expect(apiGetMock).toHaveBeenCalledWith(`${READINESS_URL}?force=true`); + + await store.fetchReadiness(true, false); + expect(apiGetMock).toHaveBeenLastCalledWith(READINESS_URL); + }); + + it('timestamp 单调守卫:旧报告被丢弃', async () => { + apiGetMock.mockResolvedValue( + makeReport({ timestamp: 2000, probes: [makeProbe('python_runtime', 'pass')] }), + ); + const store = useSystemStore(); + await store.fetchReadiness(); + const first = store.readinessReport; + + apiGetMock.mockResolvedValue(makeReport({ timestamp: 1000, probes: [] })); + await store.fetchReadiness(true); + + expect(store.readinessReport).toBe(first); + expect(store.readinessReport?.timestamp).toBe(2000); + }); + + it('内容签名去重:同内容不同 timestamp 不触发响应式更新(引用不变)', async () => { + apiGetMock.mockResolvedValue(makeReport({ timestamp: 1000 })); + const store = useSystemStore(); + await store.fetchReadiness(); + const first = store.readinessReport; + expect(first).not.toBeNull(); + + apiGetMock.mockResolvedValue(makeReport({ timestamp: 2000 })); + await store.fetchReadiness(true); + + expect(store.readinessReport).toBe(first); + }); + + it('并发多次 fetchReadiness 共享同一 in-flight 请求(只发一次)', async () => { + let resolveFn!: (v: SystemReadinessReport) => void; + apiGetMock.mockImplementation( + () => new Promise((res) => (resolveFn = res)), + ); + const store = useSystemStore(); + + const p1 = store.fetchReadiness(); + const p2 = store.fetchReadiness(true); + const p3 = store.fetchReadiness(); // 非静默加入同样共享 + resolveFn(makeReport()); + await Promise.all([p1, p2, p3]); + + expect(apiGetMock).toHaveBeenCalledTimes(1); + expect(store.isLoading).toBe(false); // finalize 复位 + }); + + it('startAutoPolling 每 3s 静默拉取 readiness', async () => { + vi.useFakeTimers(); + apiGetMock.mockResolvedValue(makeReport()); + const store = useSystemStore(); + store.startAutoPolling(); + await vi.advanceTimersByTimeAsync(0); + apiGetMock.mockClear(); + + await vi.advanceTimersByTimeAsync(3000); + expect(apiGetMock).toHaveBeenCalledTimes(1); + expect(apiGetMock).toHaveBeenCalledWith(READINESS_URL); + expect(store.isLoading).toBe(false); // 静默轮询不触发全局 loading + + store.stopAutoPolling(); + }); + + it('自动轮询在页面隐藏时跳过', async () => { + vi.useFakeTimers(); + apiGetMock.mockResolvedValue(makeReport()); + const store = useSystemStore(); + const hiddenSpy = vi.spyOn(document, 'hidden', 'get').mockReturnValue(true); + store.startAutoPolling(); + + await vi.advanceTimersByTimeAsync(9000); + expect(apiGetMock).not.toHaveBeenCalled(); + + hiddenSpy.mockRestore(); + store.stopAutoPolling(); + }); + + it('visibilitychange 恢复可见时静默刷新 readiness', async () => { + vi.useFakeTimers(); + apiGetMock.mockResolvedValue(makeReport()); + const store = useSystemStore(); + store.start(); + await vi.advanceTimersByTimeAsync(0); + apiGetMock.mockClear(); + + document.dispatchEvent(new Event('visibilitychange')); + await vi.advanceTimersByTimeAsync(0); + + expect(apiGetMock).toHaveBeenCalledWith(READINESS_URL); + expect(store.isLoading).toBe(false); + store.stop(); + }); + + it('fetchReadiness 失败联动 online=false,成功恢复 true(v2 增强)', async () => { + apiGetMock.mockRejectedValueOnce(new Error('down')); + const store = useSystemStore(); + + await expect(store.fetchReadiness(true)).rejects.toThrow('down'); + expect(store.online).toBe(false); + + apiGetMock.mockResolvedValue(makeReport()); + await store.fetchReadiness(true); + expect(store.online).toBe(true); + }); +}); + +describe('system store — M5 emulator', () => { + beforeEach(() => { + setActivePinia(createPinia()); + vi.clearAllMocks(); + }); + afterEach(cleanupTimers); + + it('launchEmulator 先置乐观初始态,POST 成功后开启 1s 轮询', async () => { + vi.useFakeTimers(); + apiPostMock.mockResolvedValue(makeEmulatorState({ status: 'starting' })); + const store = useSystemStore(); + + const p = store.launchEmulator('Pixel_7'); + // 乐观初始态同步可见(母本 L321-334) + expect(store.launchingAvd).toBe('Pixel_7'); + expect(store.emulatorLaunchState?.status).toBe('starting'); + expect(store.emulatorLaunchState?.progress_percent).toBe(15); + expect(store.emulatorLaunchState?.stage_message).toBe('Spawning emulator process...'); + expect(apiPostMock).toHaveBeenCalledWith('/api/system/emulator/launch', { + avd_name: 'Pixel_7', + }); + + await p; + apiGetMock.mockResolvedValue( + makeEmulatorState({ status: 'waiting_for_adb', progress_percent: 45 }), + ); + await vi.advanceTimersByTimeAsync(1000); + expect(emulatorStatusCallCount()).toBe(1); + expect(store.emulatorLaunchState?.progress_percent).toBe(45); + expect(store.launchingAvd).toBe('Pixel_7'); + + store.stopEmulatorStatusPolling(); + }); + + it('轮询中 status=ready → 停轮询并刷新 readiness', async () => { + vi.useFakeTimers(); + apiPostMock.mockResolvedValue(makeEmulatorState({ status: 'starting' })); + const store = useSystemStore(); + await store.launchEmulator('Pixel_7'); + + apiGetMock.mockImplementation((url: string) => + url === EMULATOR_STATUS_URL + ? Promise.resolve( + makeEmulatorState({ status: 'ready', serial: 'emu-5554', progress_percent: 100 }), + ) + : Promise.resolve(makeReport({ timestamp: 5000, overall_ready: true })), + ); + await vi.advanceTimersByTimeAsync(1000); + + expect(store.emulatorLaunchState?.status).toBe('ready'); + expect(store.launchingAvd).toBeNull(); + expect(store.isEmulatorLaunching).toBe(false); + expect(apiGetMock).toHaveBeenCalledWith(READINESS_URL); // ready 后刷新 readiness + + await vi.advanceTimersByTimeAsync(5000); + expect(emulatorStatusCallCount()).toBe(1); // 轮询已停 + }); + + it('轮询中 status=failed/stopped/idle → 停轮询', async () => { + vi.useFakeTimers(); + apiPostMock.mockResolvedValue(makeEmulatorState({ status: 'starting' })); + const store = useSystemStore(); + await store.launchEmulator('Pixel_7'); + + apiGetMock.mockResolvedValue(makeEmulatorState({ status: 'stopped' })); + await vi.advanceTimersByTimeAsync(1000); + + expect(store.launchingAvd).toBeNull(); + await vi.advanceTimersByTimeAsync(5000); + expect(emulatorStatusCallCount()).toBe(1); // 轮询已停 + }); + + it('POST 失败 → 合成失败态并透传错误', async () => { + apiPostMock.mockRejectedValue({ detail: 'AVD not found', message: 'HTTP 500' }); + const store = useSystemStore(); + + await expect(store.launchEmulator('Pixel_7')).rejects.toEqual({ + detail: 'AVD not found', + message: 'HTTP 500', + }); + expect(store.launchingAvd).toBeNull(); + expect(store.emulatorLaunchState?.status).toBe('failed'); + expect(store.emulatorLaunchState?.error).toBe('AVD not found'); // detail 优先于 message + expect(store.emulatorLaunchState?.progress_percent).toBe(0); + expect(store.emulatorLaunchState?.can_retry).toBe(true); + }); +}); + +describe('system store — M5 ADB', () => { + beforeEach(() => { + setActivePinia(createPinia()); + vi.clearAllMocks(); + }); + afterEach(cleanupTimers); + + it('connectAdbServer 成功时更新 adbServerStatus 与 report;失败时均不更新', async () => { + apiGetMock.mockResolvedValue(makeReport({ timestamp: 1000 })); + const store = useSystemStore(); + await store.fetchReadiness(); + expect(store.readinessReport?.timestamp).toBe(1000); + + // connection_result.success=false → 状态与报告均不更新 + apiPostMock.mockResolvedValue({ + connection_result: { + success: false, + message: 'refused', + endpoint: remoteEndpoint, + devices: [], + }, + }); + await store.connectAdbServer('10.0.0.5', 5037); + expect(store.adbServerStatus).toBeNull(); + expect(store.readinessReport?.timestamp).toBe(1000); + + // 成功 → 更新 endpoint + report + apiPostMock.mockResolvedValue({ + connection_result: { + success: true, + message: 'ok', + endpoint: remoteEndpoint, + devices: [], + }, + report: makeReport({ timestamp: 2000, overall_ready: true }), + }); + await store.connectAdbServer('10.0.0.5', 5037); + expect(store.adbServerStatus?.endpoint.mode).toBe('remote'); + expect(store.isRemoteAdbServer).toBe(true); + expect(store.readinessReport?.overall_ready).toBe(true); + }); + + it('useLocalAdbServer 以 query 传 persist 并更新 endpoint 与 report', async () => { + apiPostMock.mockResolvedValue({ + connection_result: { + success: true, + message: 'ok', + endpoint: localEndpoint, + devices: [], + }, + report: makeReport({ timestamp: 3000 }), + }); + const store = useSystemStore(); + + await store.useLocalAdbServer(false); + expect(apiPostMock).toHaveBeenCalledWith('/api/system/adb/server/local?persist=false', {}); + expect(store.adbServerStatus?.endpoint.mode).toBe('local'); + expect(store.isRemoteAdbServer).toBe(false); + expect(store.readinessReport?.timestamp).toBe(3000); + }); + + it('probeAdbServer 只测不切:不改任何状态', async () => { + apiPostMock.mockResolvedValue({ + connection_result: { + success: true, + message: 'ok', + endpoint: remoteEndpoint, + devices: [], + }, + }); + const store = useSystemStore(); + + const res = await store.probeAdbServer('10.0.0.5', 5037); + expect(apiPostMock).toHaveBeenCalledWith('/api/system/adb/server/probe', { + host: '10.0.0.5', + port: 5037, + persist: false, + }); + expect(res.connection_result.success).toBe(true); + expect(store.adbServerStatus).toBeNull(); + expect(store.readinessReport).toBeNull(); + }); +}); + +describe('system store — M5 凭据', () => { + beforeEach(() => { + setActivePinia(createPinia()); + vi.clearAllMocks(); + }); + afterEach(cleanupTimers); + + it('updateApiKey 成功后应用 report 并刷新 modelConfigEnv', async () => { + apiPostMock.mockResolvedValue({ + status: 'success', + report: makeReport({ timestamp: 2000, overall_ready: true }), + }); + apiGetMock.mockResolvedValue(makeModelConfigEnv()); + const store = useSystemStore(); + + await store.updateApiKey('google', 'key-123', false); + expect(apiPostMock).toHaveBeenCalledWith('/api/system/credentials', { + provider: 'google', + api_key: 'key-123', + persist_to_env: false, + }); + expect(store.readinessReport?.overall_ready).toBe(true); + expect(store.modelConfigEnv?.config_filename).toBe('artemis.jsonc'); + expect(store.modelConfigEnv?.env_vars[0]?.name).toBe('GEMINI_API_KEY'); + }); + + it('testApiKey 不落库且不改状态', async () => { + apiPostMock.mockResolvedValue({ valid: true, provider: 'google', message: 'ok' }); + const store = useSystemStore(); + + const res = await store.testApiKey('google', 'key-123', 'https://proxy.example'); + expect(apiPostMock).toHaveBeenCalledWith('/api/system/credentials/test', { + provider: 'google', + api_key: 'key-123', + base_url: 'https://proxy.example', + }); + expect(res.valid).toBe(true); + expect(store.readinessReport).toBeNull(); + expect(store.modelConfigEnv).toBeNull(); + }); + + it('skipCredentialsCheck 旁路 isCredentialsReady', async () => { + apiGetMock.mockResolvedValue(makeReport({ probes: [makeProbe('llm_api_key', 'fail')] })); + const store = useSystemStore(); + await store.fetchReadiness(); + + expect(store.isCredentialsReady).toBe(false); + store.skipCredentialsCheck(); + expect(store.isCredentialsReady).toBe(true); + store.setSkipCredentialsCheck(false); + expect(store.isCredentialsReady).toBe(false); + }); +}); + +describe('system store — M5 三步引导 computed', () => { + beforeEach(() => { + setActivePinia(createPinia()); + vi.clearAllMocks(); + }); + afterEach(cleanupTimers); + + it('全部 fail:passedStepCount=0、isReady=false', async () => { + apiGetMock.mockResolvedValue( + makeReport({ + timestamp: 1000, + probes: [ + makeProbe('python_runtime', 'fail'), + makeProbe('system_config', 'fail'), + makeProbe('toolchain', 'fail'), + makeProbe('android_adb', 'fail'), + makeProbe('llm_api_key', 'fail'), + ], + }), + ); + const store = useSystemStore(); + await store.fetchReadiness(); + + expect(store.totalStepCount).toBe(3); + expect(store.isEnvironmentReady).toBe(false); + expect(store.isCredentialsReady).toBe(false); + expect(store.isDeviceReady).toBe(false); + expect(store.passedStepCount).toBe(0); + expect(store.isReady).toBe(false); + }); + + it('isEnvironmentReady 四条件:py/cfg 通过但 adb installed=false 仍不就绪', async () => { + apiGetMock.mockResolvedValue( + makeReport({ + timestamp: 1000, + probes: [ + makeProbe('python_runtime', 'pass'), + makeProbe('system_config', 'pass'), + makeProbe('toolchain', 'pass'), + makeProbe('android_adb', 'pass', { installed: false }), + makeProbe('gemini_api_key', 'pass'), + ], + }), + ); + const store = useSystemStore(); + await store.fetchReadiness(); + + expect(store.isDeviceReady).toBe(true); // adb status=pass + expect(store.isCredentialsReady).toBe(true); + expect(store.isEnvironmentReady).toBe(false); // installed=false 拦下 + expect(store.passedStepCount).toBe(2); + }); + + it('toolchain warn 但 is_blocker=false 仍算通过 → 三步全就绪 + 元数据/osType 归一', async () => { + apiGetMock.mockResolvedValue( + makeReport({ + timestamp: 2000, + overall_ready: true, + probes: [ + makeProbe('python_runtime', 'pass'), + makeProbe('system_config', 'pass'), + makeProbe('toolchain', 'warn', {}, false), // is_blocker=false + makeProbe('android_adb', 'pass', { + installed: true, + devices: [makeDevice()], + installed_avds: ['Pixel_7'], + emulator_path: '/opt/emulator', + is_emulator_in_path: true, + }), + makeProbe('gemini_api_key', 'pass'), + makeProbe('vision_ocr_key', 'warn'), + ], + active_device: makeDevice(), + }), + ); + const store = useSystemStore(); + await store.fetchReadiness(true); + + expect(store.isEnvironmentReady).toBe(true); + expect(store.isCredentialsReady).toBe(true); + expect(store.isDeviceReady).toBe(true); + expect(store.passedStepCount).toBe(3); + expect(store.isReady).toBe(true); + expect(store.hasReadinessReport).toBe(true); + // 设备 / AVD 元数据(取自 adbProbe.metadata) + expect(store.connectedDevices).toHaveLength(1); + expect(store.installedAvds).toEqual(['Pixel_7']); + expect(store.emulatorPath).toBe('/opt/emulator'); + expect(store.isEmulatorInPath).toBe(true); + expect(store.activeDevice?.serial).toBe('emu-5554'); + expect(store.osType).toBe('windows'); // win32 → windows 归一 + }); + + it('llmProbe 双 id 兼容与 currentApiKey/apiKeysMap;ocrProbe 双 id 兼容', async () => { + apiGetMock.mockResolvedValue( + makeReport({ + timestamp: 1000, + probes: [ + makeProbe('gemini_api_key', 'pass', { + current_key: 'sk-abc', + api_keys: { google: 'sk-abc', ocr: 'ocr-1' }, + }), + ], + }), + ); + const store = useSystemStore(); + await store.fetchReadiness(); + + expect(store.llmProbe?.id).toBe('gemini_api_key'); + expect(store.currentApiKey).toBe('sk-abc'); + expect(store.apiKeysMap).toEqual({ google: 'sk-abc', ocr: 'ocr-1' }); + + // ocr 双 id:vision_ocr_key 或 ocr_api_key + apiGetMock.mockResolvedValue( + makeReport({ timestamp: 2000, probes: [makeProbe('ocr_api_key', 'fail')] }), + ); + await store.fetchReadiness(true); + expect(store.ocrProbe?.id).toBe('ocr_api_key'); + expect(store.currentApiKey).toBe(''); // 无 llm probe 时取 '' + expect(store.apiKeysMap).toEqual({}); + }); +}); + +describe('system store — 生命周期', () => { + beforeEach(() => { + setActivePinia(createPinia()); + vi.clearAllMocks(); + }); + afterEach(cleanupTimers); + + it('stop() 清空连通性 / readiness / emulator 全部定时器', async () => { + vi.useFakeTimers(); + apiGetMock.mockResolvedValue(makeReport()); + apiPostMock.mockResolvedValue(makeEmulatorState({ status: 'starting' })); + const store = useSystemStore(); + + store.start(); // 连通性 5s + readiness 3s + await vi.advanceTimersByTimeAsync(0); + await store.launchEmulator('Pixel_7'); // emulator 1s 轮询 + expect(emulatorStatusCallCount()).toBe(0); // 尚未到 1s + + apiGetMock.mockClear(); + store.stop(); + await vi.advanceTimersByTimeAsync(10_000); + + expect(apiGetMock).not.toHaveBeenCalled(); + }); +}); diff --git a/apps/showcase_ui_v2/src/stores/system.ts b/apps/showcase_ui_v2/src/stores/system.ts index ffffbc574..353af4144 100644 --- a/apps/showcase_ui_v2/src/stores/system.ts +++ b/apps/showcase_ui_v2/src/stores/system.ts @@ -1,27 +1,46 @@ /** - * 系统 store —— M1 最小实现。 + * 系统 store —— M5 完整平移 Angular SystemService + * (apps/showcase_ui/src/app/services/system.service.ts,610 行)。 * - * Angular SystemService(610 行)的完整职责(readiness 三步引导、ADB 管理、 - * emulator 生命周期、凭据配置)留给 M5 的 DiagnosticsWizard。M1 仅保留: - * - 轻量 `/api/status` 连通性轮询(5s,页面隐藏时暂停,visibilitychange 立即刷新) - * - 连接状态展示数据源(顶栏小圆点) + * M1 已交付的连通性契约保持兼容: + * - `online` / `lastCheckedAt` / `fetchStatus()` / `start()` / `stop()` 导出名不变; + * - `start()` 升级为:/api/status 连通性轮询(5s) + readiness 自动轮询(3s) + visibilitychange 恢复刷新; + * - `stop()` 清空全部定时器(连通性 + readiness + emulator 1s 轮询)。 + * + * 平移语义对照: + * - Angular signal/computed → ref/computed;Observable 管道 → async/await Promise; + * - `readinessRequest$ shareReplay(1)` → 共享 in-flight Promise(finalize 后仅当仍是当前请求才清空); + * - `applyReadinessReport` 的 timestamp 单调守卫 + 内容签名去重原样保留(母本 L249-263); + * - emulator 1s 轮询定时器非响应式(setup 内 let,母本 L52/L296-305); + * - v2 增强:fetchReadiness 成功恢复 online=true、失败置 online=false(联动 M1 顶栏小圆点,报告已注明)。 */ -import { ref } from 'vue'; +import { computed, ref } from 'vue'; import { defineStore } from 'pinia'; -import { apiGet } from '@/services/api'; +import { apiGet, apiPost } from '@/services/api'; +import type { ApiError } from '@/services/api'; +import type { + AdbServerConnectionResponse, + AdbServerStatus, + DeviceInfo, + EmulatorLaunchState, + ModelConfigEnvResponse, + SystemReadinessReport, +} from '@/types/system.model'; const POLL_INTERVAL_MS = 5000; +const READINESS_POLL_INTERVAL_MS = 3000; // 母本 L162/L181:startAutoPolling(3000) +const EMULATOR_POLL_INTERVAL_MS = 1000; // 母本 L296-305:1s 轮询 export const useSystemStore = defineStore('system', () => { + // --------------------------------------------------------------------------- + // M1 兼容:/api/status 连通性轮询(顶栏小圆点) + // --------------------------------------------------------------------------- /** 后端连通性(顶栏小圆点)。 */ const online = ref(true); const lastCheckedAt = ref(null); - let started = false; - let timer: ReturnType | null = null; - async function fetchStatus(): Promise { try { await apiGet('/api/status'); @@ -32,9 +51,491 @@ export const useSystemStore = defineStore('system', () => { } } + // --------------------------------------------------------------------------- + // M5 状态(母本 L37-53、L76、L527) + // --------------------------------------------------------------------------- + const readinessReport = ref(null); + const hasReadinessReport = computed(() => readinessReport.value !== null); + const isLoading = ref(false); + const isRestartingAdb = ref(false); + const adbServerStatus = ref(null); + const isRemoteAdbServer = computed(() => adbServerStatus.value?.endpoint.mode === 'remote'); + const launchingAvd = ref(null); + const emulatorLaunchState = ref(null); + const isEmulatorLaunching = computed(() => { + const s = emulatorLaunchState.value?.status; + return s === 'starting' || s === 'waiting_for_adb' || s === 'booting'; + }); + const lastCheckedTime = ref(null); + const isSkipCredentialsCheck = ref(false); + const modelConfigEnv = ref(null); + + // 非响应式定时器与 in-flight 缓存(母本 L52/L151-152/L154) + let connectivityTimer: ReturnType | null = null; + let readinessPollTimer: ReturnType | null = null; + let emulatorPollTimer: ReturnType | null = null; + let started = false; + let readinessInFlight: Promise | null = null; + let lastAppliedReportJson: string | null = null; + + // --------------------------------------------------------------------------- + // Probe lookups(母本 L55-61、L107) + // --------------------------------------------------------------------------- + const probes = computed(() => readinessReport.value?.probes ?? []); + const pythonProbe = computed(() => probes.value.find((p) => p.id === 'python_runtime') ?? null); + const configProbe = computed(() => probes.value.find((p) => p.id === 'system_config') ?? null); + const toolchainProbe = computed(() => probes.value.find((p) => p.id === 'toolchain') ?? null); + const adbProbe = computed(() => probes.value.find((p) => p.id === 'android_adb') ?? null); + // gemini_api_key || llm_api_key 双 id 兼容(母本 L59-60) + const llmProbe = computed( + () => probes.value.find((p) => p.id === 'gemini_api_key' || p.id === 'llm_api_key') ?? null, + ); + const geminiProbe = computed(() => llmProbe.value); // 母本 L60 别名 + const ocrProbe = computed( + () => probes.value.find((p) => p.id === 'vision_ocr_key' || p.id === 'ocr_api_key') ?? null, + ); + + // --------------------------------------------------------------------------- + // 三步引导 computed(母本 L64-114) + // --------------------------------------------------------------------------- + const isEnvironmentReady = computed(() => { + const py = pythonProbe.value; + const cfg = configProbe.value; + const adb = adbProbe.value; + const tc = toolchainProbe.value; + const pyOk = py?.status === 'pass'; + const cfgOk = cfg?.status === 'pass'; + const adbInstalled = adb?.metadata?.['installed'] ?? (adb?.status !== 'fail'); + const tcOk = tc?.status === 'pass' || tc?.is_blocker === false; + return pyOk && cfgOk && adbInstalled && tcOk; + }); + + const isCredentialsReady = computed(() => { + if (isSkipCredentialsCheck.value) { + return true; + } + return llmProbe.value?.status === 'pass'; + }); + + const isDeviceReady = computed(() => adbProbe.value?.status === 'pass'); + + const totalStepCount = computed(() => 3); + const passedStepCount = computed(() => { + let count = 0; + if (isEnvironmentReady.value) count++; + if (isCredentialsReady.value) count++; + if (isDeviceReady.value) count++; + return count; + }); + + const isReady = computed( + () => isEnvironmentReady.value && isCredentialsReady.value && isDeviceReady.value, + ); + const blockerCount = computed(() => totalStepCount.value); // 母本 L105 别名 + const passedBlockerCount = computed(() => passedStepCount.value); // 母本 L106 别名 + + // --------------------------------------------------------------------------- + // 其余派生数据(母本 L108-148、L519-525) + // --------------------------------------------------------------------------- + const activeDevice = computed(() => readinessReport.value?.active_device ?? null); + const osType = computed<'linux' | 'darwin' | 'windows'>(() => { + const raw = readinessReport.value?.os_type; + if (raw === 'windows' || raw === 'win32') return 'windows'; + if (raw === 'darwin' || raw === 'macos' || raw === 'mac') return 'darwin'; + return 'linux'; + }); + + const connectedDevices = computed(() => { + const meta = adbProbe.value?.metadata; + if (meta && Array.isArray(meta['devices'])) { + return meta['devices'] as DeviceInfo[]; + } + return []; + }); + + const installedAvds = computed(() => { + const meta = adbProbe.value?.metadata; + if (meta && Array.isArray(meta['installed_avds'])) { + return meta['installed_avds'] as string[]; + } + return []; + }); + + const emulatorPath = computed( + () => (adbProbe.value?.metadata?.['emulator_path'] as string) || null, + ); + + const isEmulatorInPath = computed( + () => (adbProbe.value?.metadata?.['is_emulator_in_path'] as boolean) ?? true, + ); + + const currentApiKey = computed( + () => (llmProbe.value?.metadata?.['current_key'] as string) || '', + ); + + const apiKeysMap = computed>( + () => (llmProbe.value?.metadata?.['api_keys'] as Record) || {}, + ); + + // --------------------------------------------------------------------------- + // Readiness(母本 L212-263) + // --------------------------------------------------------------------------- + /** 应用 readiness 报告:timestamp 单调守卫 + 内容签名去重(母本 L249-263)。 */ + function applyReadinessReport(report: SystemReadinessReport): void { + const current = readinessReport.value; + if (current && report.timestamp < current.timestamp) { + return; // 旧报告丢弃 + } + lastCheckedTime.value = new Date(report.timestamp * 1000); + // 3s 轮询通常返回同内容报告:timestamp 归零后签名一致则不 set,避免零意义的响应式抖动。 + const serialized = JSON.stringify({ ...report, timestamp: 0 }); + if (serialized === lastAppliedReportJson) { + return; + } + lastAppliedReportJson = serialized; + readinessReport.value = report; + } + + /** + * 拉取系统 readiness 报告(母本 L212-247)。 + * - silent=true 不触发 isLoading(轮询 / visibilitychange 用); + * - forceRefresh=true 加 `?force=true`(只留给手动刷新按钮); + * - 共享 in-flight:初始化/轮询/焦点/手动刷新共用同一请求,防止慢探针排队。 + * 错误透传给调用方;轮询等内部调用方自行静默 catch(console.error 已在链内执行)。 + */ + function fetchReadiness( + silent: boolean = false, + forceRefresh: boolean = false, + ): Promise { + if (!silent) { + isLoading.value = true; + } + if (readinessInFlight) { + return readinessInFlight; + } + const url = forceRefresh ? '/api/system/readiness?force=true' : '/api/system/readiness'; + const request: Promise = apiGet(url) + .then((report) => { + online.value = true; // v2 增强:readiness 成功即视为后端可达 + applyReadinessReport(report); + return report; + }) + .catch((err: unknown) => { + console.error('Failed to fetch system readiness:', err); + online.value = false; // v2 增强 + throw err; + }) + .finally(() => { + // shareReplay 语义:finalize 后仅当仍是当前请求才清空 in-flight + if (readinessInFlight === request) { + readinessInFlight = null; + } + isLoading.value = false; + }); + readinessInFlight = request; + return request; + } + + /** 启动 readiness 自动轮询(母本 L181-196):页面隐藏时跳过,默认 3s。 */ + function startAutoPolling(intervalMs: number = READINESS_POLL_INTERVAL_MS): void { + if (readinessPollTimer) { + clearInterval(readinessPollTimer); + } + readinessPollTimer = setInterval(() => { + if (typeof document !== 'undefined' && document.hidden) { + return; + } + void fetchReadiness(true).catch(() => {}); // 静默后台检查 + }, intervalMs); + } + + function stopAutoPolling(): void { + if (readinessPollTimer) { + clearInterval(readinessPollTimer); + readinessPollTimer = null; + } + } + + function skipCredentialsCheck(): void { + isSkipCredentialsCheck.value = true; + } + + function setSkipCredentialsCheck(skip: boolean): void { + isSkipCredentialsCheck.value = skip; + } + + // --------------------------------------------------------------------------- + // Emulator(母本 L268-397) + // --------------------------------------------------------------------------- + /** 拉取 emulator 启动进度快照(母本 L268-291)。 */ + async function fetchEmulatorStatus(): Promise { + try { + const state = await apiGet('/api/system/emulator/status'); + emulatorLaunchState.value = state; + if (state.status === 'ready') { + launchingAvd.value = null; + stopEmulatorStatusPolling(); + void fetchReadiness().catch(() => {}); // ready → 停轮询 + 刷新 readiness(母本 L276) + } else if ( + state.status === 'failed' || + state.status === 'stopped' || + state.status === 'idle' + ) { + launchingAvd.value = null; + stopEmulatorStatusPolling(); + } else if (state.avd_name) { + launchingAvd.value = state.avd_name; // 其余状态更新 launchingAvd + } + return state; + } catch (err) { + console.error('Failed to fetch emulator status:', err); + throw err; + } + } + + /** 1s 间隔轮询 emulator 启动进度(母本 L296-305)。 */ + function startEmulatorStatusPolling(): void { + if (emulatorPollTimer) { + clearInterval(emulatorPollTimer); + } + emulatorPollTimer = setInterval(() => { + void fetchEmulatorStatus().catch(() => {}); + }, EMULATOR_POLL_INTERVAL_MS); + } + + function stopEmulatorStatusPolling(): void { + if (emulatorPollTimer) { + clearInterval(emulatorPollTimer); + emulatorPollTimer = null; + } + } + + /** 后台启动 AVD 并持续跟踪启动进度(母本 L320-366)。 */ + async function launchEmulator(avdName: string): Promise { + // 乐观初始态(母本 L321-334) + launchingAvd.value = avdName; + emulatorLaunchState.value = { + avd_name: avdName, + status: 'starting', + pid: null, + serial: null, + stage_message: 'Spawning emulator process...', + progress_percent: 15, + started_at: Date.now() / 1000, + elapsed_seconds: 0, + error: null, + logs: [`Initiating launch for AVD: ${avdName}...`], + can_retry: true, + }; + try { + const state = await apiPost('/api/system/emulator/launch', { + avd_name: avdName, + }); + emulatorLaunchState.value = state; + if (state.status === 'failed') { + launchingAvd.value = null; + } else { + startEmulatorStatusPolling(); // 非失败即开轮询 + } + return state; + } catch (err) { + console.error('Failed to launch emulator:', err); + launchingAvd.value = null; + // 错误合成失败态(母本 L346-363) + const errorMsg = + (err as ApiError)?.detail || (err as Error)?.message || 'Failed to start emulator process.'; + emulatorLaunchState.value = { + avd_name: avdName, + status: 'failed', + pid: null, + serial: null, + stage_message: 'Failed to initiate launch.', + progress_percent: 0, + started_at: null, + elapsed_seconds: 0, + error: errorMsg, + logs: [errorMsg], + can_retry: true, + }; + throw err; + } + } + + /** 终止运行中的 emulator(母本 L371-382)。 */ + async function stopEmulator(): Promise { + const res = await apiPost('/api/system/emulator/stop', {}); + launchingAvd.value = null; + stopEmulatorStatusPolling(); + void fetchEmulatorStatus().catch(() => {}); + void fetchReadiness().catch(() => {}); + return res; + } + + /** 清除并关闭 emulator 启动跟踪状态(母本 L387-397)。 */ + async function dismissEmulatorStatus(): Promise { + const res = await apiPost('/api/system/emulator/dismiss', {}); + emulatorLaunchState.value = null; + launchingAvd.value = null; + stopEmulatorStatusPolling(); + return res; + } + + // --------------------------------------------------------------------------- + // ADB(母本 L402-517) + // --------------------------------------------------------------------------- + /** 重启本地 ADB 并应用返回的 readiness(母本 L402-418)。 */ + async function restartAdb(): Promise { + isRestartingAdb.value = true; + try { + const res = await apiPost('/api/system/adb/restart', {}); + if (res?.report) { + applyReadinessReport(res.report); + } + return res; + } catch (err) { + console.error('Failed to restart ADB server:', err); + throw err; + } finally { + isRestartingAdb.value = false; + } + } + + /** Wi-Fi 连接 Android 设备(母本 L423-433)。 */ + async function connectWirelessAdb(host: string, port: number = 5555): Promise { + const res = await apiPost('/api/system/adb/connect', { host, port }); + if (res?.report) { + applyReadinessReport(res.report); + } + return res; + } + + /** 拉取当前进程使用的 ADB server 端点(母本 L438-442)。 */ + async function fetchAdbServerStatus(): Promise { + const status = await apiGet('/api/system/adb/server'); + adbServerStatus.value = status; + return status; + } + + /** 只测不改:探测 ADB server 端点,persist:false(母本 L447-455)。 */ + function probeAdbServer( + host: string, + port: number, + ): Promise { + return apiPost('/api/system/adb/server/probe', { + host, + port, + persist: false, + }); + } + + /** 校验并激活 ADB server 端点:connection_result.success 时才更新状态与 report(母本 L460-478)。 */ + async function connectAdbServer( + host: string, + port: number, + persist: boolean = true, + ): Promise { + const response = await apiPost('/api/system/adb/server/connect', { + host, + port, + persist, + }); + if (response.connection_result.success) { + adbServerStatus.value = { endpoint: response.connection_result.endpoint }; + if (response.report) { + applyReadinessReport(response.report); + } + } + return response; + } + + /** 切回标准本地 ADB server;persist 走 query(母本 L483-496;v2 apiPost 无 params 故拼 URL)。 */ + async function useLocalAdbServer(persist: boolean = true): Promise { + const response = await apiPost( + `/api/system/adb/server/local?persist=${persist}`, + {}, + ); + adbServerStatus.value = { endpoint: response.connection_result.endpoint }; + if (response.report) { + applyReadinessReport(response.report); + } + return response; + } + + /** 选择活动设备串号:isLoading + 应用 report(母本 L501-517)。 */ + async function selectDevice(serial: string): Promise { + isLoading.value = true; + try { + const res = await apiPost('/api/system/devices/select', { serial }); + if (res?.report) { + applyReadinessReport(res.report); + } + return res; + } catch (err) { + console.error('Failed to select active device:', err); + throw err; + } finally { + isLoading.value = false; + } + } + + // --------------------------------------------------------------------------- + // 凭据与 model-config-env(母本 L519-578) + // --------------------------------------------------------------------------- + /** 拉取 artemis.jsonc 与 .env 状态(母本 L532-543)。 */ + async function fetchModelConfigEnv(): Promise { + try { + const data = await apiGet('/api/system/model-config-env'); + modelConfigEnv.value = data; + return data; + } catch (err) { + console.error('Failed to fetch model config and env:', err); + throw err; + } + } + + /** 不落库验证 API key(母本 L548-554)。 */ + function testApiKey( + provider: string, + apiKey: string, + baseUrl?: string, + ): Promise<{ valid: boolean; provider: string; message: string }> { + return apiPost<{ valid: boolean; provider: string; message: string }>( + '/api/system/credentials/test', + { provider, api_key: apiKey, base_url: baseUrl }, + ); + } + + /** 更新并配置 API key:成功应用 report + 刷新 modelConfigEnv(母本 L559-578)。 */ + async function updateApiKey( + provider: string, + apiKey: string, + persistToEnv: boolean = true, + ): Promise { + try { + const res = await apiPost('/api/system/credentials', { + provider, + api_key: apiKey, + persist_to_env: persistToEnv, + }); + if (res?.report) { + applyReadinessReport(res.report); + } + void fetchModelConfigEnv().catch(() => {}); // 刷新 model config & env + return res; + } catch (err) { + console.error(`Failed to update credentials for ${provider}:`, err); + throw err; + } + } + + // --------------------------------------------------------------------------- + // 生命周期(M1 兼容 + M5 readiness 轮询;母本 L155-206) + // --------------------------------------------------------------------------- const onVisibilityChange = () => { if (typeof document !== 'undefined' && !document.hidden) { void fetchStatus(); + // 恢复可见时静默刷新 readiness(母本 L155-159) + void fetchReadiness(true).catch(() => {}); } }; @@ -42,27 +543,99 @@ export const useSystemStore = defineStore('system', () => { if (started) return; started = true; void fetchStatus(); - timer = setInterval(() => { + connectivityTimer = setInterval(() => { if (typeof document !== 'undefined' && document.hidden) { return; } void fetchStatus(); }, intervalMs); + startAutoPolling(); // M5:readiness 3s 自动轮询(对应母本 L162 构造期启动) if (typeof document !== 'undefined') { document.addEventListener('visibilitychange', onVisibilityChange); } } function stop(): void { - if (timer) { - clearInterval(timer); - timer = null; + if (connectivityTimer) { + clearInterval(connectivityTimer); + connectivityTimer = null; } + stopAutoPolling(); + stopEmulatorStatusPolling(); if (typeof document !== 'undefined') { document.removeEventListener('visibilitychange', onVisibilityChange); } started = false; } - return { online, lastCheckedAt, fetchStatus, start, stop }; + return { + // M1 兼容 + online, + lastCheckedAt, + fetchStatus, + start, + stop, + // M5 状态 + readinessReport, + hasReadinessReport, + isLoading, + isRestartingAdb, + adbServerStatus, + isRemoteAdbServer, + launchingAvd, + emulatorLaunchState, + isEmulatorLaunching, + lastCheckedTime, + isSkipCredentialsCheck, + modelConfigEnv, + // probe lookups + probes, + pythonProbe, + configProbe, + toolchainProbe, + adbProbe, + llmProbe, + geminiProbe, + ocrProbe, + // 三步引导 + isEnvironmentReady, + isCredentialsReady, + isDeviceReady, + isReady, + passedStepCount, + totalStepCount, + blockerCount, + passedBlockerCount, + // 设备 / emulator / 凭据派生 + activeDevice, + osType, + connectedDevices, + installedAvds, + emulatorPath, + isEmulatorInPath, + currentApiKey, + apiKeysMap, + // actions + startAutoPolling, + stopAutoPolling, + skipCredentialsCheck, + setSkipCredentialsCheck, + fetchReadiness, + fetchEmulatorStatus, + startEmulatorStatusPolling, + stopEmulatorStatusPolling, + launchEmulator, + stopEmulator, + dismissEmulatorStatus, + restartAdb, + connectWirelessAdb, + fetchAdbServerStatus, + probeAdbServer, + connectAdbServer, + useLocalAdbServer, + selectDevice, + fetchModelConfigEnv, + testApiKey, + updateApiKey, + }; }); diff --git a/apps/showcase_ui_v2/src/stores/timeline.ts b/apps/showcase_ui_v2/src/stores/timeline.ts index 890d799fd..a64ea9d10 100644 --- a/apps/showcase_ui_v2/src/stores/timeline.ts +++ b/apps/showcase_ui_v2/src/stores/timeline.ts @@ -13,7 +13,9 @@ * - 会话切换的世代守卫(loadGeneration / snapshotRequestId / pendingSnapshotRequests), * 过期的快照响应不落库——平移自 Angular selectSession / backfillSessionSteps。 * - * 未平移部分(M3):SSE 连接与 llm_stream 合批、暂停/重试卡片、session_ended 联动。 + * SSE 连接、llm_stream 合批、暂停/重试卡片与 session_ended 联动已由 + * `stores/stream.ts`(M3)承接:其直接读写本 store 导出的 sessionLogs ref 作为 + * 日志写入口;实时 startup_progress 事件经 appendStartupEvent 幂等合入。 */ import { computed, ref, watch } from 'vue'; @@ -213,6 +215,14 @@ export const useTimelineStore = defineStore('timeline', () => { return merged; } + /** SSE 实时 startup_progress 事件按 stage 幂等合入对应会话桶(M3,stores/stream.ts 调用)。 */ + function appendStartupEvent(event: StartupProgressEvent, sessionId: string): void { + startupProgressBySession.value = { + ...startupProgressBySession.value, + [sessionId]: mergeStartupEvents(startupProgressBySession.value[sessionId] || [], [event]), + }; + } + // ---- checker 账本回填(§3.3 条款 2:checks_snapshot 幂等)---- /** @@ -426,6 +436,7 @@ export const useTimelineStore = defineStore('timeline', () => { fetchChecks, fetchNotes, fetchStartupProgress, + appendStartupEvent, loadRunUsage, selectNoteKey, buildCheckerSnapshotLogs, diff --git a/apps/showcase_ui_v2/src/types/session.model.ts b/apps/showcase_ui_v2/src/types/session.model.ts index ef322d1cf..9cd33c836 100644 --- a/apps/showcase_ui_v2/src/types/session.model.ts +++ b/apps/showcase_ui_v2/src/types/session.model.ts @@ -46,6 +46,39 @@ export interface Session { device_info?: any; } +/** 单段屏幕录像:scrcpy 重启(转屏 / 崩溃恢复)时录像切分为多段(M4,平移自 agent.service.ts L30-40)。 */ +export interface VideoSegment { + url: string; + /** Back-to-back playlist timeline start (seconds); gaps between segments are not represented. */ + start: number; + duration: number; + width: number; + height: number; + /** Session-relative first-frame offset in milliseconds (manifest v2). */ + offset_ms?: number; + duration_ms?: number; +} + +/** 视频播放器回放状态(M4,平移自 agent.service.ts L42-48 的 RecordingPlaybackStatus)。 */ +export type RecordingPlaybackStatus = + | 'idle' + | 'live' + | 'processing' + | 'ready' + | 'failed' + | 'unavailable'; + +/** `GET /api/sessions/{id}/video` 的响应契约(后端 apps/admin_console/routers/media.py L110-176)。 */ +export interface SessionVideoResponse { + session_id: string; + status?: 'processing' | 'ready' | 'failed' | 'unavailable'; + has_video: boolean; + video_url: string | null; + video_segments?: VideoSegment[]; + retry_after_ms?: number; + message?: string; +} + export interface AgentStatusResponse { status: 'idle' | 'running' | 'paused' | 'completed' | 'offline'; session_id?: string | null; diff --git a/apps/showcase_ui_v2/src/types/system.model.ts b/apps/showcase_ui_v2/src/types/system.model.ts index cf15406f0..f19e67051 100644 --- a/apps/showcase_ui_v2/src/types/system.model.ts +++ b/apps/showcase_ui_v2/src/types/system.model.ts @@ -116,3 +116,37 @@ export interface EmulatorLaunchState { logs: string[]; can_retry: boolean; } + +/** + * model-config-env 响应:artemis.jsonc 配置与 .env 凭据状态 + * (自 Angular system.service.ts L581-609 原样平移)。 + */ +export interface ModelConfigEnvResponse { + config_path: string; + config_filename: string; + config_content: string; + default_model: { + provider?: string; + model?: string; + thinking_level?: string; + fallback?: { + provider?: string; + model?: string; + thinking_level?: string; + }; + }; + presets: Record; + env_path: string; + env_filename: string; + env_vars: Array<{ + name: string; + provider: string; + is_set: boolean; + preview: string | null; + description: string; + }>; +} diff --git a/apps/showcase_ui_v2/src/utils/image-overlay.spec.ts b/apps/showcase_ui_v2/src/utils/image-overlay.spec.ts new file mode 100644 index 000000000..98a55d2a0 --- /dev/null +++ b/apps/showcase_ui_v2/src/utils/image-overlay.spec.ts @@ -0,0 +1,85 @@ +/** + * 平移自 Angular `utils/image-overlay.util.spec.ts` 的绘制相关用例 + * (叠加层为纯 DOM/SVG,无需真实 canvas 2D context,与 Angular spec 的 + * fake image 元素方式一致,jsdom 可直接运行)。 + */ +import { describe, expect, it } from 'vitest'; + +import { drawActionCoordinatesOnOverlay } from './image-overlay'; +import { unwrapTraceAction } from './image-coords'; + +// Trace records as the DataEngine publishes them in `generic_tools`. +const PRO_TAP_TRACE = { + trace_id: 'pro-tap', + type: 'action', + name: 'tap', + timestamp: 1788478482.05, + status: 'success', + payload: { + action: { + action: 'tap', + coordinates: [922, 1710], + coordinate_space: 'pixel', + normalized_coordinates: [854, 705], + target_text: 'YouTube' + }, + success: true, + post_screenshot: null + } +}; + +const FLASH_CLICK_TRACE = { + trace_id: 'flash-click', + type: 'action', + name: 'click', + timestamp: 1788478305.12, + status: 'success', + payload: { + args: { target: [618, 705], target_text: '相册' }, + result: '{"outcome": "Clicked"}' + } +}; + +function fakeImage(): HTMLImageElement { + return { naturalWidth: 1080, naturalHeight: 2424 } as unknown as HTMLImageElement; +} + +describe('unwrapTraceAction(平移:image-overlay.util.spec.ts)', () => { + it('flattens a Pro action trace (payload.action)', () => { + const act = unwrapTraceAction(PRO_TAP_TRACE); + expect(act.action).toBe('tap'); + expect(act.normalized_coordinates).toEqual([854, 705]); + expect(act.target_text).toBe('YouTube'); + expect(act.trace_id).toBe('pro-tap'); + expect(act.timestamp).toBe(1788478482.05); + }); + + it('flattens a Flash action trace (payload.args)', () => { + const act = unwrapTraceAction(FLASH_CLICK_TRACE); + expect(act.action).toBe('click'); + expect(act.target).toEqual([618, 705]); + expect(act.args.target).toEqual([618, 705]); + }); + + it('passes plain action objects through untouched', () => { + const plain = { action: 'tap', normalized_coordinates: [10, 20] }; + expect(unwrapTraceAction(plain)).toBe(plain); + }); +}); + +describe('drawActionCoordinatesOnOverlay(平移:image-overlay.util.spec.ts)', () => { + it('draws the tap marker for a Pro action trace', () => { + const overlay = document.createElement('div'); + drawActionCoordinatesOnOverlay(fakeImage(), overlay, PRO_TAP_TRACE); + const marker = overlay.querySelector('.action-point-marker') as HTMLElement; + expect(marker).not.toBeNull(); + expect(marker.style.left).toBe('85.4%'); + expect(marker.style.top).toBe('70.5%'); + }); + + it('draws the tap marker for a Flash action trace', () => { + const overlay = document.createElement('div'); + drawActionCoordinatesOnOverlay(fakeImage(), overlay, FLASH_CLICK_TRACE); + expect(overlay.querySelector('.action-point-marker')).not.toBeNull(); + }); +}); diff --git a/apps/showcase_ui_v2/src/utils/image-overlay.ts b/apps/showcase_ui_v2/src/utils/image-overlay.ts new file mode 100644 index 000000000..a60da2928 --- /dev/null +++ b/apps/showcase_ui_v2/src/utils/image-overlay.ts @@ -0,0 +1,529 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 帧回放的坐标叠加绘制(DOM/SVG marker,M4 自 Angular `utils/image-overlay.util.ts` + * 的 canvas 绘制部分平移,算法逐行一致;坐标解析函数复用 M2 的 `image-coords.ts`)。 + */ + +import { + extractNumbersFromCoordinateValue, + isPureDirectionString, + parseSequenceCoordinates, + unwrapTraceAction, +} from './image-coords'; + +/** + * Draw action coordinates (points, click sequence, swipe lines) onto the image overlay element + */ +export function drawActionCoordinatesOnOverlay( + img: HTMLImageElement, + overlay: HTMLElement, + actionObj: any +): void { + if (!img || !overlay || !actionObj) return; + overlay.innerHTML = ''; + + const actions = Array.isArray(actionObj) ? actionObj : [actionObj]; + const naturalWidth = img.naturalWidth || 1080; + const naturalHeight = img.naturalHeight || 2400; + + actions.forEach(record => { + const act = unwrapTraceAction(record); + if (!act || typeof act !== 'object') return; + const actionName = (act.action || act.name || 'tap').toLowerCase(); + const args = (act.args && typeof act.args === 'object') ? act.args : {}; + + // Filter out non-touch / system actions that do not operate via touch coordinates + const nonDrawingActions = [ + 'manage_app', 'launch_app', 'open_app', 'stop_app', 'close_app', + 'press_key', 'press_home', 'press_back', 'wait_for_delay', 'wait', 'delay', + 'report_task_status', 'report_failure_analysis' + ]; + if (nonDrawingActions.includes(actionName)) { + return; + } + + // 1. Multi-point click sequence (High priority for click_sequence / tap_sequence) + const isSequenceAction = actionName.includes('sequence') || Boolean(act.sequence || args.sequence || act.normalized_sequence || args.normalized_sequence); + const rawSeq = act.normalized_sequence || args.normalized_sequence || act.sequence || args.sequence || act.targets || args.targets || (Array.isArray(act.coordinates) && Array.isArray(act.coordinates[0]) ? act.coordinates : null) || (Array.isArray(args.coordinates) && Array.isArray(args.coordinates[0]) ? args.coordinates : null); + const seqPoints = parseSequenceCoordinates(rawSeq); + + if (seqPoints && seqPoints.length > 0 && (isSequenceAction || seqPoints.length > 1)) { + const isNormSeq = Boolean(act.normalized_sequence || args.normalized_sequence) || seqPoints.every(p => p[0] <= 1000 && p[1] <= 1000); + // Draw connecting lines between consecutive points + for (let i = 0; i < seqPoints.length - 1; i++) { + createSequenceConnector( + seqPoints[i][0], seqPoints[i][1], + seqPoints[i + 1][0], seqPoints[i + 1][1], + naturalWidth, naturalHeight, + overlay, + isNormSeq + ); + } + // Draw numbered markers for each point in the sequence + seqPoints.forEach((pt, idx) => { + createPointMarker( + pt[0], pt[1], + actionName, + naturalWidth, naturalHeight, + overlay, + isNormSeq, + idx + 1, + seqPoints.length + ); + }); + return; + } + + // Determine if this is a swipe/scroll/drag gesture + const isSwipeLike = actionName.includes('swipe') || actionName.includes('scroll') || actionName.includes('drag') || actionName.includes('slide'); + + // 2. Check separate start and end coordinate objects + const normStart = extractNumbersFromCoordinateValue(act.normalized_start_coordinates || args.normalized_start_coordinates); + const normEnd = extractNumbersFromCoordinateValue(act.normalized_end_coordinates || args.normalized_end_coordinates); + const startCoords = normStart || extractNumbersFromCoordinateValue(act.start_coordinates || act.start_point || act.start || act.from || + args.start_coordinates || args.start_point || args.start || args.from); + const endCoords = normEnd || extractNumbersFromCoordinateValue(act.end_coordinates || act.end_point || act.end || act.to || + args.end_coordinates || args.end_point || args.end || args.to); + + if (startCoords && endCoords && startCoords.length >= 2 && endCoords.length >= 2) { + createLineMarker( + startCoords[0], startCoords[1], + endCoords[0], endCoords[1], + naturalWidth, naturalHeight, + overlay, + Boolean(normStart && normEnd), + actionName + ); + return; + } + + // 3. Check 4-element coordinate array in coordinates, target, action, gesture, etc. + const normCoords = extractNumbersFromCoordinateValue(act.normalized_coordinates || args.normalized_coordinates); + const isNorm = Boolean(normCoords); + const rawCoords = normCoords || + extractNumbersFromCoordinateValue(act.coordinates) || + extractNumbersFromCoordinateValue(args.coordinates) || + extractNumbersFromCoordinateValue(act.coords) || + extractNumbersFromCoordinateValue(args.coords) || + extractNumbersFromCoordinateValue(act.target) || + extractNumbersFromCoordinateValue(args.target) || + (isSwipeLike ? extractNumbersFromCoordinateValue(args.action) : null) || + (isSwipeLike ? extractNumbersFromCoordinateValue(act.action) : null) || + (isSwipeLike ? extractNumbersFromCoordinateValue(args.gesture) : null) || + (isSwipeLike ? extractNumbersFromCoordinateValue(act.gesture) : null); + + if (rawCoords && Array.isArray(rawCoords)) { + if (rawCoords.length === 4) { + createLineMarker( + rawCoords[0], rawCoords[1], rawCoords[2], rawCoords[3], + naturalWidth, naturalHeight, + overlay, + isNorm, + actionName + ); + return; + } else if (rawCoords.length === 2 && !isSwipeLike) { + createPointMarker(rawCoords[0], rawCoords[1], actionName, naturalWidth, naturalHeight, overlay, isNorm); + return; + } + } + + // 4. Check for directional swipe/scroll/drag gestures ONLY when action is swipe-like + if (isSwipeLike) { + const rawDir = (typeof args.action === 'string' && isPureDirectionString(args.action) ? args.action : null) || + (typeof act.action === 'string' && act.action !== actionName && isPureDirectionString(act.action) ? act.action : null) || + (isPureDirectionString(args.direction) ? args.direction : null) || + (isPureDirectionString(act.direction) ? act.direction : null) || + (isPureDirectionString(args.gesture) ? args.gesture : null) || + (isPureDirectionString(act.gesture) ? act.gesture : null) || ''; + const dirStr = String(rawDir).toLowerCase().trim(); + + if (dirStr) { + let sx = 500, sy = 750, ex = 500, ey = 250; + let label = 'SWIPE'; + + if (dirStr.includes('up') || dirStr.includes('top') || actionName.includes('up')) { + sx = 500; sy = 750; ex = 500; ey = 250; + label = 'SWIPE UP'; + } else if (dirStr.includes('down') || dirStr.includes('bottom') || actionName.includes('down')) { + sx = 500; sy = 250; ex = 500; ey = 750; + label = 'SWIPE DOWN'; + } else if (dirStr.includes('left') || actionName.includes('left')) { + sx = 800; sy = 500; ex = 200; ey = 500; + label = 'SWIPE LEFT'; + } else if (dirStr.includes('right') || actionName.includes('right')) { + sx = 200; sy = 500; ex = 800; ey = 500; + label = 'SWIPE RIGHT'; + } + + createLineMarker(sx, sy, ex, ey, naturalWidth, naturalHeight, overlay, true, label); + return; + } + } + + // 5. Default tap/click coordinate fallback + if (rawCoords && Array.isArray(rawCoords) && rawCoords.length === 2) { + createPointMarker(rawCoords[0], rawCoords[1], actionName, naturalWidth, naturalHeight, overlay, isNorm); + } + }); +} + +/** + * Helper to create and position an animated red dot point marker with edge-aware label + */ +export function createPointMarker( + x: number, + y: number, + actionType: string, + naturalWidth: number, + naturalHeight: number, + overlay: HTMLElement, + isNormalized: boolean = false, + sequenceIndex?: number, + totalSequence?: number +): void { + let pctX: number; + let pctY: number; + + // Accurate 0-1000 scale resolution + if (isNormalized || (!isNormalized && x <= 1000 && y <= 1000)) { + pctX = x / 10; + pctY = y / 10; + } else { + pctX = (x / (naturalWidth || 1080)) * 100; + pctY = (y / (naturalHeight || 2400)) * 100; + } + + // Safety clamp within container boundaries + const clampedPctX = Math.max(1.5, Math.min(98.5, pctX)); + const clampedPctY = Math.max(1.5, Math.min(98.5, pctY)); + + const marker = document.createElement('div'); + marker.className = 'action-point-marker'; + marker.style.position = 'absolute'; + marker.style.left = `${clampedPctX}%`; + marker.style.top = `${clampedPctY}%`; + marker.style.transform = 'translate(-50%, -50%)'; + marker.style.pointerEvents = 'none'; + marker.style.zIndex = '10'; + + const dotSize = sequenceIndex !== undefined ? 20 : 14; + const dot = document.createElement('div'); + dot.style.width = `${dotSize}px`; + dot.style.height = `${dotSize}px`; + dot.style.borderRadius = '50%'; + dot.style.backgroundColor = '#ef4444'; + dot.style.border = '2px solid white'; + dot.style.boxShadow = '0 0 6px rgba(0,0,0,0.5)'; + if (sequenceIndex !== undefined) { + dot.style.display = 'flex'; + dot.style.alignItems = 'center'; + dot.style.justifyContent = 'center'; + dot.style.fontSize = '11px'; + dot.style.fontWeight = 'bold'; + dot.style.color = 'white'; + dot.innerText = String(sequenceIndex); + } + + const pulseSize = dotSize * 2; + const pulse = document.createElement('div'); + pulse.style.position = 'absolute'; + pulse.style.top = `-${dotSize / 2 + 2}px`; + pulse.style.left = `-${dotSize / 2 + 2}px`; + pulse.style.width = `${pulseSize}px`; + pulse.style.height = `${pulseSize}px`; + pulse.style.borderRadius = '50%'; + pulse.style.border = '2px solid #ef4444'; + pulse.style.animation = 'pulse-animation 1.5s infinite ease-out'; + pulse.style.pointerEvents = 'none'; + + const label = document.createElement('div'); + if (sequenceIndex !== undefined) { + label.innerText = totalSequence && totalSequence > 1 ? `#${sequenceIndex} TAP` : actionType.toUpperCase(); + } else { + label.innerText = actionType.toUpperCase(); + } + label.style.position = 'absolute'; + label.style.backgroundColor = 'rgba(15, 23, 42, 0.9)'; + label.style.color = 'white'; + label.style.padding = '1.5px 5px'; + label.style.borderRadius = '3px'; + label.style.fontSize = '9px'; + label.style.fontWeight = 'bold'; + label.style.letterSpacing = '0.5px'; + label.style.whiteSpace = 'nowrap'; + label.style.boxShadow = '0 1px 4px rgba(0,0,0,0.4)'; + label.style.border = '1px solid rgba(255,255,255,0.2)'; + + // Smart edge-aware vertical positioning + if (clampedPctY > 85) { + label.style.bottom = `${dotSize + 2}px`; + label.style.top = 'auto'; + } else { + label.style.top = `${dotSize + 2}px`; + label.style.bottom = 'auto'; + } + + // Smart edge-aware horizontal positioning + if (clampedPctX > 82) { + label.style.right = '0px'; + label.style.left = 'auto'; + label.style.transform = 'none'; + } else if (clampedPctX < 18) { + label.style.left = '0px'; + label.style.right = 'auto'; + label.style.transform = 'none'; + } else { + label.style.left = '50%'; + label.style.right = 'auto'; + label.style.transform = 'translateX(-50%)'; + } + + marker.appendChild(pulse); + marker.appendChild(dot); + marker.appendChild(label); + overlay.appendChild(marker); +} + +/** + * Helper to draw connecting line/arrow between points in a click sequence + */ +export function createSequenceConnector( + x1: number, + y1: number, + x2: number, + y2: number, + naturalWidth: number, + naturalHeight: number, + overlay: HTMLElement, + isNormalized: boolean = false +): void { + const isNormCoord = isNormalized || (x1 <= 1000 && y1 <= 1000 && x2 <= 1000 && y2 <= 1000); + const pctX1 = isNormCoord ? x1 / 10 : (x1 / (naturalWidth || 1080)) * 100; + const pctY1 = isNormCoord ? y1 / 10 : (y1 / (naturalHeight || 2400)) * 100; + const pctX2 = isNormCoord ? x2 / 10 : (x2 / (naturalWidth || 1080)) * 100; + const pctY2 = isNormCoord ? y2 / 10 : (y2 / (naturalHeight || 2400)) * 100; + + const clampedX1 = Math.max(1.5, Math.min(98.5, pctX1)); + const clampedY1 = Math.max(1.5, Math.min(98.5, pctY1)); + const clampedX2 = Math.max(1.5, Math.min(98.5, pctX2)); + const clampedY2 = Math.max(1.5, Math.min(98.5, pctY2)); + + let svg = overlay.querySelector('svg'); + if (!svg) { + svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('width', '100%'); + svg.setAttribute('height', '100%'); + svg.style.position = 'absolute'; + svg.style.top = '0'; + svg.style.left = '0'; + svg.style.pointerEvents = 'none'; + svg.style.overflow = 'visible'; + svg.style.zIndex = '5'; + overlay.appendChild(svg); + } + + let defs = svg.querySelector('defs'); + if (!defs) { + defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'); + svg.insertBefore(defs, svg.firstChild); + } + + const markerId = 'seq-arrow-' + Math.random().toString(36).substring(2, 9); + const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker'); + marker.setAttribute('id', markerId); + marker.setAttribute('viewBox', '0 0 12 12'); + marker.setAttribute('refX', '8'); + marker.setAttribute('refY', '6'); + marker.setAttribute('markerWidth', '6'); + marker.setAttribute('markerHeight', '6'); + marker.setAttribute('orient', 'auto'); + + const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + path.setAttribute('d', 'M 1 2 L 10 6 L 1 10 z'); + path.setAttribute('fill', '#ef4444'); + path.setAttribute('stroke', '#ffffff'); + path.setAttribute('stroke-width', '1'); + + marker.appendChild(path); + defs.appendChild(marker); + + // Background white contrast line + const bgLine = document.createElementNS('http://www.w3.org/2000/svg', 'line'); + bgLine.setAttribute('x1', `${clampedX1}%`); + bgLine.setAttribute('y1', `${clampedY1}%`); + bgLine.setAttribute('x2', `${clampedX2}%`); + bgLine.setAttribute('y2', `${clampedY2}%`); + bgLine.setAttribute('stroke', '#ffffff'); + bgLine.setAttribute('stroke-width', '4'); + bgLine.setAttribute('stroke-linecap', 'round'); + bgLine.setAttribute('opacity', '0.8'); + + // Main red dashed sequence line + const line = document.createElementNS('http://www.w3.org/2000/svg', 'line'); + line.setAttribute('x1', `${clampedX1}%`); + line.setAttribute('y1', `${clampedY1}%`); + line.setAttribute('x2', `${clampedX2}%`); + line.setAttribute('y2', `${clampedY2}%`); + line.setAttribute('stroke', '#ef4444'); + line.setAttribute('stroke-width', '2.5'); + line.setAttribute('stroke-linecap', 'round'); + line.setAttribute('marker-end', `url(#${markerId})`); + line.setAttribute('stroke-dasharray', '4,4'); + + svg.appendChild(bgLine); + svg.appendChild(line); +} + +/** + * Helper to create and position an SVG arrow, high-contrast dashed line, and badge for swipes/drags + */ +export function createLineMarker( + x1: number, + y1: number, + x2: number, + y2: number, + naturalWidth: number, + naturalHeight: number, + overlay: HTMLElement, + isNormalized: boolean = false, + actionType: string = 'swipe' +): void { + const isNormCoord = isNormalized || (x1 <= 1000 && y1 <= 1000 && x2 <= 1000 && y2 <= 1000); + const pctX1 = isNormCoord ? x1 / 10 : (x1 / (naturalWidth || 1080)) * 100; + const pctY1 = isNormCoord ? y1 / 10 : (y1 / (naturalHeight || 2400)) * 100; + const pctX2 = isNormCoord ? x2 / 10 : (x2 / (naturalWidth || 1080)) * 100; + const pctY2 = isNormCoord ? y2 / 10 : (y2 / (naturalHeight || 2400)) * 100; + + const clampedX1 = Math.max(1.5, Math.min(98.5, pctX1)); + const clampedY1 = Math.max(1.5, Math.min(98.5, pctY1)); + const clampedX2 = Math.max(1.5, Math.min(98.5, pctX2)); + const clampedY2 = Math.max(1.5, Math.min(98.5, pctY2)); + + let svg = overlay.querySelector('svg'); + if (!svg) { + svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('width', '100%'); + svg.setAttribute('height', '100%'); + svg.style.position = 'absolute'; + svg.style.top = '0'; + svg.style.left = '0'; + svg.style.pointerEvents = 'none'; + svg.style.overflow = 'visible'; + svg.style.zIndex = '5'; + overlay.appendChild(svg); + } + + let defs = svg.querySelector('defs'); + if (!defs) { + defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'); + svg.insertBefore(defs, svg.firstChild); + } + + const markerId = 'action-arrow-' + Math.random().toString(36).substring(2, 9); + const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker'); + marker.setAttribute('id', markerId); + marker.setAttribute('viewBox', '0 0 12 12'); + marker.setAttribute('refX', '8'); + marker.setAttribute('refY', '6'); + marker.setAttribute('markerWidth', '8'); + marker.setAttribute('markerHeight', '8'); + marker.setAttribute('orient', 'auto'); + + const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + path.setAttribute('d', 'M 1 2 L 10 6 L 1 10 z'); + path.setAttribute('fill', '#ef4444'); + path.setAttribute('stroke', '#ffffff'); + path.setAttribute('stroke-width', '1.5'); + path.setAttribute('stroke-linejoin', 'round'); + + marker.appendChild(path); + defs.appendChild(marker); + + // Background white contrast line + const bgLine = document.createElementNS('http://www.w3.org/2000/svg', 'line'); + bgLine.setAttribute('x1', `${clampedX1}%`); + bgLine.setAttribute('y1', `${clampedY1}%`); + bgLine.setAttribute('x2', `${clampedX2}%`); + bgLine.setAttribute('y2', `${clampedY2}%`); + bgLine.setAttribute('stroke', '#ffffff'); + bgLine.setAttribute('stroke-width', '6'); + bgLine.setAttribute('stroke-linecap', 'round'); + bgLine.setAttribute('opacity', '0.9'); + + // Main red dashed line + const line = document.createElementNS('http://www.w3.org/2000/svg', 'line'); + line.setAttribute('x1', `${clampedX1}%`); + line.setAttribute('y1', `${clampedY1}%`); + line.setAttribute('x2', `${clampedX2}%`); + line.setAttribute('y2', `${clampedY2}%`); + line.setAttribute('stroke', '#ef4444'); + line.setAttribute('stroke-width', '3.5'); + line.setAttribute('stroke-linecap', 'round'); + line.setAttribute('marker-end', `url(#${markerId})`); + line.setAttribute('stroke-dasharray', '6,4'); + + // Start touch point circle with white border + const startCircleOuter = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); + startCircleOuter.setAttribute('cx', `${clampedX1}%`); + startCircleOuter.setAttribute('cy', `${clampedY1}%`); + startCircleOuter.setAttribute('r', '6.5'); + startCircleOuter.setAttribute('fill', '#ef4444'); + startCircleOuter.setAttribute('stroke', 'white'); + startCircleOuter.setAttribute('stroke-width', '2'); + + const startCircleInner = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); + startCircleInner.setAttribute('cx', `${clampedX1}%`); + startCircleInner.setAttribute('cy', `${clampedY1}%`); + startCircleInner.setAttribute('r', '2.5'); + startCircleInner.setAttribute('fill', 'white'); + + svg.appendChild(bgLine); + svg.appendChild(line); + svg.appendChild(startCircleOuter); + svg.appendChild(startCircleInner); + + // Floating Action badge at midpoint of swipe + const midX = (clampedX1 + clampedX2) / 2; + const midY = (clampedY1 + clampedY2) / 2; + + const label = document.createElement('div'); + label.className = 'action-point-marker action-line-label'; + label.style.position = 'absolute'; + label.style.left = `${midX}%`; + label.style.top = `${midY}%`; + label.style.transform = 'translate(-50%, -50%)'; + label.style.pointerEvents = 'none'; + label.style.zIndex = '10'; + + const badge = document.createElement('div'); + badge.innerText = actionType.toUpperCase(); + badge.style.backgroundColor = 'rgba(15, 23, 42, 0.92)'; + badge.style.color = 'white'; + badge.style.padding = '2px 6px'; + badge.style.borderRadius = '4px'; + badge.style.fontSize = '9px'; + badge.style.fontWeight = 'bold'; + badge.style.letterSpacing = '0.5px'; + badge.style.whiteSpace = 'nowrap'; + badge.style.boxShadow = '0 2px 6px rgba(0,0,0,0.5)'; + badge.style.border = '1px solid rgba(255,255,255,0.3)'; + + label.appendChild(badge); + overlay.appendChild(label); +} diff --git a/apps/showcase_ui_v2/src/utils/recording-timeline.spec.ts b/apps/showcase_ui_v2/src/utils/recording-timeline.spec.ts new file mode 100644 index 000000000..b0a88d533 --- /dev/null +++ b/apps/showcase_ui_v2/src/utils/recording-timeline.spec.ts @@ -0,0 +1,112 @@ +/** + * 平移自 Angular `utils/recording-timeline.util.spec.ts`(用例全部保留)。 + */ +import { describe, expect, it } from 'vitest'; + +import { + hasSessionOffsets, + locateSessionTime, + locateTimelineTime, + sessionTimeToTimelineTime, + type TimelineSegment, +} from './recording-timeline'; + +describe('recording-timeline', () => { + // Recording started 1.2s after the session began. Segment 0 ran 10s, then + // scrcpy restarted for rotation (1.5s gap), segment 1 ran 5s, another 0.8s + // gap, and segment 2 ran 4s. + const v2Segments: TimelineSegment[] = [ + { start: 0, duration: 10, offset_ms: 1200, duration_ms: 10000 }, + { start: 10, duration: 5, offset_ms: 12700, duration_ms: 5000 }, + { start: 15, duration: 4, offset_ms: 18500, duration_ms: 4000 }, + ]; + + const legacySegments: TimelineSegment[] = [ + { start: 0, duration: 10 }, + { start: 10, duration: 5 }, + ]; + + describe('hasSessionOffsets', () => { + it('detects manifest v2 segments and rejects legacy or mixed lists', () => { + expect(hasSessionOffsets(v2Segments)).toBe(true); + expect(hasSessionOffsets(legacySegments)).toBe(false); + expect(hasSessionOffsets([v2Segments[0], legacySegments[0]])).toBe(false); + expect(hasSessionOffsets([])).toBe(false); + }); + }); + + describe('locateTimelineTime', () => { + it('maps back-to-back playlist times into segments', () => { + expect(locateTimelineTime(legacySegments, 3)).toEqual({ index: 0, localTime: 3, timelineTime: 3 }); + expect(locateTimelineTime(legacySegments, 10)).toEqual({ index: 1, localTime: 0, timelineTime: 10 }); + expect(locateTimelineTime(legacySegments, 12.5)).toEqual({ index: 1, localTime: 2.5, timelineTime: 12.5 }); + }); + + it('clamps out-of-range times into the first or last segment', () => { + expect(locateTimelineTime(legacySegments, -4)).toEqual({ index: 0, localTime: 0, timelineTime: 0 }); + expect(locateTimelineTime(legacySegments, 99)).toEqual({ index: 1, localTime: 5, timelineTime: 15 }); + expect(locateTimelineTime([], 3)).toBeNull(); + }); + }); + + describe('locateSessionTime', () => { + it('maps a session time inside a segment using its real offset', () => { + // T+4.2s is 3.0s into segment 0 (which started at T+1.2s). + const inFirst = locateSessionTime(v2Segments, 4.2)!; + expect(inFirst.index).toBe(0); + expect(inFirst.localTime).toBeCloseTo(3.0, 6); + expect(inFirst.timelineTime).toBeCloseTo(3.0, 6); + + // T+14.7s is 2.0s into segment 1 (started at T+12.7s), which sits at + // timeline 10s, so it must NOT drift to timeline 14.7s. + const inSecond = locateSessionTime(v2Segments, 14.7)!; + expect(inSecond.index).toBe(1); + expect(inSecond.localTime).toBeCloseTo(2.0, 6); + expect(inSecond.timelineTime).toBeCloseTo(12.0, 6); + + const inThird = locateSessionTime(v2Segments, 20.5)!; + expect(inThird.index).toBe(2); + expect(inThird.localTime).toBeCloseTo(2.0, 6); + expect(inThird.timelineTime).toBeCloseTo(17.0, 6); + }); + + it('snaps a time inside a restart gap to the start of the next segment', () => { + // Segment 0 ends at T+11.2s, segment 1 starts at T+12.7s. + expect(locateSessionTime(v2Segments, 11.9)).toEqual({ index: 1, localTime: 0, timelineTime: 10 }); + // Segment 1 ends at T+17.7s, segment 2 starts at T+18.5s. + expect(locateSessionTime(v2Segments, 18.0)).toEqual({ index: 2, localTime: 0, timelineTime: 15 }); + }); + + it('treats segment boundaries as inclusive of the end frame', () => { + const atEnd = locateSessionTime(v2Segments, 11.2)!; + expect(atEnd.index).toBe(0); + expect(atEnd.localTime).toBeCloseTo(10, 6); + expect(locateSessionTime(v2Segments, 12.7)).toEqual({ index: 1, localTime: 0, timelineTime: 10 }); + }); + + it('snaps times before the first frame and after the last frame', () => { + expect(locateSessionTime(v2Segments, 0)).toEqual({ index: 0, localTime: 0, timelineTime: 0 }); + expect(locateSessionTime(v2Segments, 0.5)).toEqual({ index: 0, localTime: 0, timelineTime: 0 }); + expect(locateSessionTime(v2Segments, 60)).toEqual({ index: 2, localTime: 4, timelineTime: 19 }); + expect(locateSessionTime(v2Segments, Number.NaN)).toEqual({ index: 0, localTime: 0, timelineTime: 0 }); + }); + + it('falls back to back-to-back timeline behaviour for legacy manifests', () => { + expect(locateSessionTime(legacySegments, 12.5)).toEqual({ index: 1, localTime: 2.5, timelineTime: 12.5 }); + expect(locateSessionTime([], 5)).toBeNull(); + }); + }); + + describe('sessionTimeToTimelineTime', () => { + it('returns the playlist position for a session time', () => { + expect(sessionTimeToTimelineTime(v2Segments, 14.7)).toBeCloseTo(12.0, 6); + expect(sessionTimeToTimelineTime(v2Segments, 11.9)).toBe(10); + expect(sessionTimeToTimelineTime(legacySegments, 7)).toBe(7); + }); + + it('passes the time through when no playlist is available', () => { + expect(sessionTimeToTimelineTime([], 7)).toBe(7); + expect(sessionTimeToTimelineTime([], -2)).toBe(0); + }); + }); +}); diff --git a/apps/showcase_ui_v2/src/utils/recording-timeline.ts b/apps/showcase_ui_v2/src/utils/recording-timeline.ts new file mode 100644 index 000000000..b4d5facaa --- /dev/null +++ b/apps/showcase_ui_v2/src/utils/recording-timeline.ts @@ -0,0 +1,125 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 多段屏幕录像的时间映射纯函数(M4 自 Angular `utils/recording-timeline.util.ts` + * 全文平移,算法逐行一致)。 + * + * A recording is split into segments whenever scrcpy restarts (device + * rotation, crash recovery). The player plays them back to back on a + * "timeline" axis (`start`/`duration`, no gaps), while step timestamps live + * on the "session" axis (seconds since the DataEngine session start). Manifest + * v2 segments carry `offset_ms`/`duration_ms` on the session axis, which lets + * a session time land in the right segment even after each restart gap. + */ + +/** 回放清单中的一段录像(与 `types/session.model.ts` 的 VideoSegment 同形状的时间子集)。 */ +export interface TimelineSegment { + /** Back-to-back playlist start in seconds. */ + start: number; + /** Segment length in seconds. */ + duration: number; + /** Session-relative first-frame offset in milliseconds (manifest v2). */ + offset_ms?: number; + /** Segment length in milliseconds (manifest v2). */ + duration_ms?: number; +} + +export interface SegmentLocation { + /** Index into the segment list. */ + index: number; + /** Seconds into that segment's own media. */ + localTime: number; + /** Equivalent position on the back-to-back playlist axis, in seconds. */ + timelineTime: number; +} + +const clamp = (value: number, min: number, max: number): number => Math.max(min, Math.min(max, value)); + +/** True when every segment carries the session-relative v2 fields. */ +export function hasSessionOffsets(segments: readonly TimelineSegment[]): boolean { + return segments.length > 0 && segments.every( + (segment) => Number.isFinite(segment.offset_ms) && Number.isFinite(segment.duration_ms) + ); +} + +/** + * Locate a position on the back-to-back playlist axis (what the scrubber uses). + * Times past the end clamp into the last segment. + */ +export function locateTimelineTime( + segments: readonly TimelineSegment[], + timelineSeconds: number +): SegmentLocation | null { + if (!segments.length) return null; + const total = segments.reduce((sum, segment) => sum + Math.max(0, segment.duration), 0); + const target = clamp(Number.isFinite(timelineSeconds) ? timelineSeconds : 0, 0, total); + let index = segments.findIndex((segment) => target < segment.start + segment.duration); + if (index < 0) index = segments.length - 1; + const segment = segments[index]; + const localTime = clamp(target - segment.start, 0, Math.max(0, segment.duration)); + return { index, localTime, timelineTime: segment.start + localTime }; +} + +/** + * Locate a session-relative time (seconds since session start, the axis step + * timestamps use). A time inside `[offset, offset + duration]` of a segment maps + * into that segment; a time in the gap between two segments (scrcpy restart) + * snaps to the start of the next segment; a time before the first frame snaps + * to the first frame; a time after the last frame clamps to the last frame. + * + * Segments without session offsets (legacy manifests) are treated as if the + * session axis were the back-to-back timeline axis. + */ +export function locateSessionTime( + segments: readonly TimelineSegment[], + sessionSeconds: number +): SegmentLocation | null { + if (!segments.length) return null; + if (!hasSessionOffsets(segments)) { + return locateTimelineTime(segments, sessionSeconds); + } + const targetMs = Number.isFinite(sessionSeconds) ? sessionSeconds * 1000 : 0; + for (let index = 0; index < segments.length; index++) { + const segment = segments[index]; + const offsetMs = segment.offset_ms as number; + const endMs = offsetMs + (segment.duration_ms as number); + if (targetMs < offsetMs) { + // Before this segment's first frame: either before the recording began + // or inside the restart gap after the previous segment. Snap forward. + return { index, localTime: 0, timelineTime: segment.start }; + } + if (targetMs <= endMs) { + const localTime = clamp((targetMs - offsetMs) / 1000, 0, Math.max(0, segment.duration)); + return { index, localTime, timelineTime: segment.start + localTime }; + } + } + const lastIndex = segments.length - 1; + const last = segments[lastIndex]; + const localTime = Math.max(0, last.duration); + return { index: lastIndex, localTime, timelineTime: last.start + localTime }; +} + +/** + * Convert a session-relative time into the back-to-back playlist time the + * player scrubber understands. Returns 0 when there are no segments. + */ +export function sessionTimeToTimelineTime( + segments: readonly TimelineSegment[], + sessionSeconds: number +): number { + return locateSessionTime(segments, sessionSeconds)?.timelineTime ?? Math.max(0, sessionSeconds || 0); +} diff --git a/apps/showcase_ui_v2/src/views/LauncherView.spec.ts b/apps/showcase_ui_v2/src/views/LauncherView.spec.ts index 67d82dbc9..c366bb96b 100644 --- a/apps/showcase_ui_v2/src/views/LauncherView.spec.ts +++ b/apps/showcase_ui_v2/src/views/LauncherView.spec.ts @@ -1,7 +1,8 @@ import { mount } from '@vue/test-utils'; import ArcoVue from '@arco-design/web-vue'; -import { describe, expect, it } from 'vitest'; +import { describe, expect, it, vi } from 'vitest'; import { createPinia } from 'pinia'; +import { reactive } from 'vue'; import { createI18n } from 'vue-i18n'; import { createMemoryHistory, createRouter } from 'vue-router'; @@ -9,9 +10,79 @@ import zhCN from '../locales/zh-CN'; import LauncherView from './LauncherView.vue'; /** - * 组件冒烟:LauncherView(M1 最小可用版)在 Vue 工程内正常渲染—— - * 标题、任务输入、提交按钮与会话数摘要。 + * 组件冒烟:LauncherView 在 Vue 工程内正常渲染——标题、diagnostics/launcher + * 双 tab、任务输入、提交按钮与会话数摘要;切换到诊断 tab 渲染三步向导。 + * system store 按导出契约 mock(M5 数据层并行重写中)。 */ + +const mockSystem = reactive({ + // M1 连接状态(AppNav 消费) + online: true, + lastCheckedAt: null, + fetchStatus: vi.fn(() => Promise.resolve()), + start: vi.fn(), + stop: vi.fn(), + // M5 契约(诊断向导消费) + readinessReport: null, + isLoading: false, + isRestartingAdb: false, + adbServerStatus: null, + launchingAvd: null, + emulatorLaunchState: null, + lastCheckedTime: null, + isSkipCredentialsCheck: false, + modelConfigEnv: null, + hasReadinessReport: false, + isRemoteAdbServer: false, + isEmulatorLaunching: false, + probes: [], + pythonProbe: null, + configProbe: null, + toolchainProbe: null, + adbProbe: null, + llmProbe: null, + ocrProbe: null, + isEnvironmentReady: false, + isCredentialsReady: false, + isDeviceReady: false, + isReady: false, + passedStepCount: 0, + totalStepCount: 3, + connectedDevices: [], + installedAvds: [], + emulatorPath: null, + isEmulatorInPath: true, + currentApiKey: '', + apiKeysMap: {}, + activeDevice: null, + osType: 'windows', + startAutoPolling: vi.fn(), + stopAutoPolling: vi.fn(), + fetchReadiness: vi.fn(() => Promise.resolve({})), + skipCredentialsCheck: vi.fn(), + setSkipCredentialsCheck: vi.fn(), + fetchEmulatorStatus: vi.fn(), + startEmulatorStatusPolling: vi.fn(), + stopEmulatorStatusPolling: vi.fn(), + launchEmulator: vi.fn(() => Promise.resolve({})), + stopEmulator: vi.fn(() => Promise.resolve({})), + dismissEmulatorStatus: vi.fn(() => Promise.resolve({})), + restartAdb: vi.fn(() => Promise.resolve({})), + connectWirelessAdb: vi.fn(() => Promise.resolve({})), + fetchAdbServerStatus: vi.fn(() => Promise.resolve({})), + probeAdbServer: vi.fn(() => Promise.resolve({})), + connectAdbServer: vi.fn(() => Promise.resolve({})), + useLocalAdbServer: vi.fn(() => Promise.resolve({})), + selectDevice: vi.fn(() => Promise.resolve({})), + fetchModelConfigEnv: vi.fn(() => Promise.resolve({})), + testApiKey: vi.fn(() => Promise.resolve({ valid: true, provider: 'google', message: 'ok' })), + updateApiKey: vi.fn(() => Promise.resolve({ message: 'saved' })), +}); + +vi.mock('@/stores/system', () => ({ + useSystemStore: () => mockSystem, +})); + const i18n = createI18n({ legacy: false, locale: 'zh-CN', @@ -40,6 +111,12 @@ describe('LauncherView (M1)', () => { expect(wrapper.text()).toContain('ARTEMIS 控制台(Vue 版)'); }); + it('renders the diagnostics / launcher mode tabs', () => { + const wrapper = mountView(); + expect(wrapper.text()).toContain('系统设置与前置条件'); + expect(wrapper.text()).toContain('启动自主任务'); + }); + it('renders a task textarea and a submit button', () => { const wrapper = mountView(); expect(wrapper.find('textarea').exists()).toBe(true); @@ -55,3 +132,20 @@ describe('LauncherView (M1)', () => { expect(wrapper.text()).toContain('已完成'); }); }); + +describe('LauncherView (M5 诊断 tab)', () => { + it('renders the diagnostics wizard after switching to the diagnostics tab', async () => { + const wrapper = mountView(); + // 默认 launcher tab:不渲染向导 + expect(wrapper.text()).not.toContain('系统与环境'); + + const diagTab = wrapper.findAll('.mode-tab-btn').find((b) => b.text().includes('系统设置与前置条件')); + expect(diagTab).toBeTruthy(); + await diagTab!.trigger('click'); + + // 三步向导渲染(顶部完成度 + STEP 1 标题) + expect(wrapper.text()).toContain('系统就绪度'); + expect(wrapper.text()).toContain('系统与环境'); + expect(wrapper.text()).toContain('重新检测'); + }); +}); diff --git a/apps/showcase_ui_v2/src/views/LauncherView.vue b/apps/showcase_ui_v2/src/views/LauncherView.vue index a99513d68..3a02bf8d1 100644 --- a/apps/showcase_ui_v2/src/views/LauncherView.vue +++ b/apps/showcase_ui_v2/src/views/LauncherView.vue @@ -1,18 +1,32 @@ + + + + + ARTEMIS 控制台 + + + + + + + +
+ diff --git a/artemis/resources/showcase_ui/main-BGAFACUZ.js b/artemis/resources/showcase_ui/main-BGAFACUZ.js deleted file mode 100644 index 8ae6a1db6..000000000 --- a/artemis/resources/showcase_ui/main-BGAFACUZ.js +++ /dev/null @@ -1,18 +0,0 @@ -var aO=Object.defineProperty,sO=Object.defineProperties;var cO=Object.getOwnPropertyDescriptors;var vm=Object.getOwnPropertySymbols;var lO=Object.prototype.hasOwnProperty,dO=Object.prototype.propertyIsEnumerable;var ym=(n,t,e)=>t in n?aO(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e,S=(n,t)=>{for(var e in t||={})lO.call(t,e)&&ym(n,e,t[e]);if(vm)for(var e of vm(t))dO.call(t,e)&&ym(n,e,t[e]);return n},F=(n,t)=>sO(n,cO(t));var be=(n,t,e)=>new Promise((o,i)=>{var r=c=>{try{s(e.next(c))}catch(p){i(p)}},a=c=>{try{s(e.throw(c))}catch(p){i(p)}},s=c=>c.done?o(c.value):Promise.resolve(c.value).then(r,a);s((e=e.apply(n,t)).next())});var mt=null,Ds=!1,$o=1,uO=null,nt=Symbol("SIGNAL");function Y(n){let t=mt;return mt=n,t}function Is(){return mt}var po={version:0,lastCleanEpoch:0,dirty:!1,producers:void 0,producersTail:void 0,consumers:void 0,consumersTail:void 0,recomputing:!1,consumerAllowSignalWrites:!1,consumerIsAlwaysLive:!1,kind:"unknown",producerMustRecompute:()=>!1,producerRecomputeValue:()=>{},consumerMarkedDirty:()=>{},consumerOnSignalRead:()=>{}};function Ho(n){if(Ds)throw new Error("");if(mt===null)return;mt.consumerOnSignalRead(n);let t=mt.producersTail;if(t!==void 0&&t.producer===n)return;let e,o=mt.recomputing;if(o&&(e=t!==void 0?t.nextProducer:mt.producers,e!==void 0&&e.producer===n)){mt.producersTail=e,e.lastReadVersion=n.version,e.knownValidAtEpoch=$o;return}let i=n.consumersTail;if(i!==void 0&&i.consumer===mt&&(!o||i.knownValidAtEpoch===$o))return;let r=$i(mt),a={producer:n,consumer:mt,nextProducer:e,prevConsumer:void 0,knownValidAtEpoch:$o,lastReadVersion:n.version,nextConsumer:void 0};mt.producersTail=a,t!==void 0?t.nextProducer=a:mt.producers=a,r&&km(n,a)}function xm(){$o++}function Uo(n){if(!($i(n)&&!n.dirty)&&!(!n.dirty&&n.lastCleanEpoch===$o)){if(!n.producerMustRecompute(n)&&!Wr(n)){ji(n);return}n.producerRecomputeValue(n),ji(n)}}function eu(n){if(n.consumers===void 0)return;let t=Ds;Ds=!0;try{for(let e=n.consumers;e!==void 0;e=e.nextConsumer){let o=e.consumer;o.dirty||gO(o)}}finally{Ds=t}}function tu(){return mt?.consumerAllowSignalWrites!==!1}function gO(n){n.dirty=!0,eu(n),n.consumerMarkedDirty?.(n)}function ji(n){n.dirty=!1,n.lastCleanEpoch=$o}function fo(n){return n&&wm(n),Y(n)}function wm(n){if(n.producersTail?.knownValidAtEpoch===$o){let t=n.producers;for(;t!==void 0;)t.knownValidAtEpoch=null,t=t.nextProducer}n.producersTail=void 0,n.recomputing=!0}function Go(n,t){Y(t),n&&Sm(n)}function Sm(n){n.recomputing=!1;let t=n.producersTail,e=t!==void 0?t.nextProducer:n.producers;if(e!==void 0){if($i(n))do e=nu(e);while(e!==void 0);t!==void 0?t.nextProducer=void 0:n.producers=void 0}}function Wr(n){for(let t=n.producers;t!==void 0;t=t.nextProducer){let e=t.producer,o=t.lastReadVersion;if(o!==e.version||(Uo(e),o!==e.version))return!0}return!1}function qo(n){if($i(n)){let t=n.producers;for(;t!==void 0;)t=nu(t)}n.producers=void 0,n.producersTail=void 0,n.consumers=void 0,n.consumersTail=void 0}function km(n,t){let e=n.consumersTail,o=$i(n);if(e!==void 0?(t.nextConsumer=e.nextConsumer,e.nextConsumer=t):(t.nextConsumer=void 0,n.consumers=t),t.prevConsumer=e,n.consumersTail=t,!o)for(let i=n.producers;i!==void 0;i=i.nextProducer)km(i.producer,i)}function nu(n){let t=n.producer,e=n.nextProducer,o=n.nextConsumer,i=n.prevConsumer;if(n.nextConsumer=void 0,n.prevConsumer=void 0,o!==void 0?o.prevConsumer=i:t.consumersTail=i,i!==void 0)i.nextConsumer=o;else if(t.consumers=o,!$i(t)){let r=t.producers;for(;r!==void 0;)r=nu(r)}return e}function $i(n){return n.consumerIsAlwaysLive||n.consumers!==void 0}function Kr(n){uO?.(n)}function Yr(n,t){return Object.is(n,t)}function Ts(n,t){let e=Object.create(pO);e.computation=n,t!==void 0&&(e.equal=t);let o=()=>{if(Uo(e),Ho(e),e.value===Cn)throw e.error;return e.value};return o[nt]=e,Kr(e),o}var zo=Symbol("UNSET"),Bo=Symbol("COMPUTING"),Cn=Symbol("ERRORED"),pO=F(S({},po),{value:zo,dirty:!0,error:null,equal:Yr,kind:"computed",producerMustRecompute(n){return n.value===zo||n.value===Bo},producerRecomputeValue(n){if(n.value===Bo)throw new Error("");let t=n.value;n.value=Bo;let e=fo(n),o,i=!1;try{o=n.computation(),Y(null),i=t!==zo&&t!==Cn&&o!==Cn&&n.equal(t,o)}catch(r){o=Cn,n.error=r}finally{Go(n,e)}if(i){n.value=t;return}n.value=o,n.version++}});function fO(){throw new Error}var Em=fO;function Dm(n){Em(n)}function ou(n){Em=n}var mO=null;function iu(n,t){let e=Object.create(Ns);e.value=n,t!==void 0&&(e.equal=t);let o=()=>Im(e);return o[nt]=e,Kr(e),[o,a=>Wo(e,a),a=>As(e,a)]}function Im(n){return Ho(n),n.value}function Wo(n,t){tu()||Dm(n),n.equal(n.value,t)||(n.value=t,_O(n))}function As(n,t){tu()||Dm(n),Wo(n,t(n.value))}var Ns=F(S({},po),{equal:Yr,value:void 0,kind:"signal"});function _O(n){n.version++,xm(),eu(n),mO?.(n)}var ru=F(S({},po),{consumerIsAlwaysLive:!0,consumerAllowSignalWrites:!0,dirty:!0,kind:"effect"});function au(n){if(n.dirty=!1,n.version>0&&!Wr(n))return;n.version++;let t=fo(n);try{n.cleanup(),n.fn()}finally{Go(n,t)}}var su;function Rs(){return su}function Mn(n){let t=su;return su=n,t}var Tm=Symbol("NotFound");function zi(n){return n===Tm||n?.name==="\u0275NotFound"}function cu(n,t,e){let o=Object.create(hO);o.source=n,o.computation=t,e!=null&&(o.equal=e);let r=()=>{if(Uo(o),Ho(o),o.value===Cn)throw o.error;return o.value};return r[nt]=o,Kr(o),r}function lu(n,t){Uo(n),Wo(n,t),ji(n)}function Am(n,t){if(Uo(n),n.value===Cn)throw n.error;As(n,t),ji(n)}var hO=F(S({},po),{value:zo,dirty:!0,error:null,equal:Yr,kind:"linkedSignal",producerMustRecompute(n){return n.value===zo||n.value===Bo},producerRecomputeValue(n){if(n.value===Bo)throw new Error("");let t=n.value;n.value=Bo;let e=fo(n),o,i=!1;try{let r=n.source(),a=t!==zo&&t!==Cn,s=a?{source:n.sourceValue,value:t}:void 0;o=n.computation(r,s),n.sourceValue=r,Y(null),i=a&&o!==Cn&&n.equal(t,o)}catch(r){o=Cn,n.error=r}finally{Go(n,e)}if(i){n.value=t;return}n.value=o,n.version++}});function Nm(n){let t=Y(null);try{return n()}finally{Y(t)}}function ae(n){return typeof n=="function"}function Bi(n){let e=n(o=>{Error.call(o),o.stack=new Error().stack});return e.prototype=Object.create(Error.prototype),e.prototype.constructor=e,e}var Fs=Bi(n=>function(e){n(this),this.message=e?`${e.length} errors occurred during unsubscription: -${e.map((o,i)=>`${i+1}) ${o.toString()}`).join(` - `)}`:"",this.name="UnsubscriptionError",this.errors=e});function Zr(n,t){if(n){let e=n.indexOf(t);0<=e&&n.splice(e,1)}}var Be=class n{constructor(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}unsubscribe(){let t;if(!this.closed){this.closed=!0;let{_parentage:e}=this;if(e)if(this._parentage=null,Array.isArray(e))for(let r of e)r.remove(this);else e.remove(this);let{initialTeardown:o}=this;if(ae(o))try{o()}catch(r){t=r instanceof Fs?r.errors:[r]}let{_finalizers:i}=this;if(i){this._finalizers=null;for(let r of i)try{Rm(r)}catch(a){t=t??[],a instanceof Fs?t=[...t,...a.errors]:t.push(a)}}if(t)throw new Fs(t)}}add(t){var e;if(t&&t!==this)if(this.closed)Rm(t);else{if(t instanceof n){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(e=this._finalizers)!==null&&e!==void 0?e:[]).push(t)}}_hasParent(t){let{_parentage:e}=this;return e===t||Array.isArray(e)&&e.includes(t)}_addParent(t){let{_parentage:e}=this;this._parentage=Array.isArray(e)?(e.push(t),e):e?[e,t]:t}_removeParent(t){let{_parentage:e}=this;e===t?this._parentage=null:Array.isArray(e)&&Zr(e,t)}remove(t){let{_finalizers:e}=this;e&&Zr(e,t),t instanceof n&&t._removeParent(this)}};Be.EMPTY=(()=>{let n=new Be;return n.closed=!0,n})();var du=Be.EMPTY;function Ls(n){return n instanceof Be||n&&"closed"in n&&ae(n.remove)&&ae(n.add)&&ae(n.unsubscribe)}function Rm(n){ae(n)?n():n.unsubscribe()}var en={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var Hi={setTimeout(n,t,...e){let{delegate:o}=Hi;return o?.setTimeout?o.setTimeout(n,t,...e):setTimeout(n,t,...e)},clearTimeout(n){let{delegate:t}=Hi;return(t?.clearTimeout||clearTimeout)(n)},delegate:void 0};function Vs(n){Hi.setTimeout(()=>{let{onUnhandledError:t}=en;if(t)t(n);else throw n})}function Qr(){}var Fm=uu("C",void 0,void 0);function Lm(n){return uu("E",void 0,n)}function Vm(n){return uu("N",n,void 0)}function uu(n,t,e){return{kind:n,value:t,error:e}}var Ko=null;function Ui(n){if(en.useDeprecatedSynchronousErrorHandling){let t=!Ko;if(t&&(Ko={errorThrown:!1,error:null}),n(),t){let{errorThrown:e,error:o}=Ko;if(Ko=null,e)throw o}}else n()}function jm(n){en.useDeprecatedSynchronousErrorHandling&&Ko&&(Ko.errorThrown=!0,Ko.error=n)}var Yo=class extends Be{constructor(t){super(),this.isStopped=!1,t?(this.destination=t,Ls(t)&&t.add(this)):this.destination=bO}static create(t,e,o){return new zn(t,e,o)}next(t){this.isStopped?pu(Vm(t),this):this._next(t)}error(t){this.isStopped?pu(Lm(t),this):(this.isStopped=!0,this._error(t))}complete(){this.isStopped?pu(Fm,this):(this.isStopped=!0,this._complete())}unsubscribe(){this.closed||(this.isStopped=!0,super.unsubscribe(),this.destination=null)}_next(t){this.destination.next(t)}_error(t){try{this.destination.error(t)}finally{this.unsubscribe()}}_complete(){try{this.destination.complete()}finally{this.unsubscribe()}}},CO=Function.prototype.bind;function gu(n,t){return CO.call(n,t)}var fu=class{constructor(t){this.partialObserver=t}next(t){let{partialObserver:e}=this;if(e.next)try{e.next(t)}catch(o){js(o)}}error(t){let{partialObserver:e}=this;if(e.error)try{e.error(t)}catch(o){js(o)}else js(t)}complete(){let{partialObserver:t}=this;if(t.complete)try{t.complete()}catch(e){js(e)}}},zn=class extends Yo{constructor(t,e,o){super();let i;if(ae(t)||!t)i={next:t??void 0,error:e??void 0,complete:o??void 0};else{let r;this&&en.useDeprecatedNextContext?(r=Object.create(t),r.unsubscribe=()=>this.unsubscribe(),i={next:t.next&&gu(t.next,r),error:t.error&&gu(t.error,r),complete:t.complete&&gu(t.complete,r)}):i=t}this.destination=new fu(i)}};function js(n){en.useDeprecatedSynchronousErrorHandling?jm(n):Vs(n)}function MO(n){throw n}function pu(n,t){let{onStoppedNotification:e}=en;e&&Hi.setTimeout(()=>e(n,t))}var bO={closed:!0,next:Qr,error:MO,complete:Qr};var Gi=typeof Symbol=="function"&&Symbol.observable||"@@observable";function tn(n){return n}function $s(...n){return mu(n)}function mu(n){return n.length===0?tn:n.length===1?n[0]:function(e){return n.reduce((o,i)=>i(o),e)}}var ie=class n{constructor(t){t&&(this._subscribe=t)}lift(t){let e=new n;return e.source=this,e.operator=t,e}subscribe(t,e,o){let i=OO(t)?t:new zn(t,e,o);return Ui(()=>{let{operator:r,source:a}=this;i.add(r?r.call(i,a):a?this._subscribe(i):this._trySubscribe(i))}),i}_trySubscribe(t){try{return this._subscribe(t)}catch(e){t.error(e)}}forEach(t,e){return e=$m(e),new e((o,i)=>{let r=new zn({next:a=>{try{t(a)}catch(s){i(s),r.unsubscribe()}},error:i,complete:o});this.subscribe(r)})}_subscribe(t){var e;return(e=this.source)===null||e===void 0?void 0:e.subscribe(t)}[Gi](){return this}pipe(...t){return mu(t)(this)}toPromise(t){return t=$m(t),new t((e,o)=>{let i;this.subscribe(r=>i=r,r=>o(r),()=>e(i))})}};ie.create=n=>new ie(n);function $m(n){var t;return(t=n??en.Promise)!==null&&t!==void 0?t:Promise}function PO(n){return n&&ae(n.next)&&ae(n.error)&&ae(n.complete)}function OO(n){return n&&n instanceof Yo||PO(n)&&Ls(n)}function vO(n){return ae(n?.lift)}function fe(n){return t=>{if(vO(t))return t.lift(function(e){try{return n(e,this)}catch(o){this.error(o)}});throw new TypeError("Unable to lift unknown Observable type")}}function _e(n,t,e,o,i){return new _u(n,t,e,o,i)}var _u=class extends Yo{constructor(t,e,o,i,r,a){super(t),this.onFinalize=r,this.shouldUnsubscribe=a,this._next=e?function(s){try{e(s)}catch(c){t.error(c)}}:super._next,this._error=i?function(s){try{i(s)}catch(c){t.error(c)}finally{this.unsubscribe()}}:super._error,this._complete=o?function(){try{o()}catch(s){t.error(s)}finally{this.unsubscribe()}}:super._complete}unsubscribe(){var t;if(!this.shouldUnsubscribe||this.shouldUnsubscribe()){let{closed:e}=this;super.unsubscribe(),!e&&((t=this.onFinalize)===null||t===void 0||t.call(this))}}};var zm=Bi(n=>function(){n(this),this.name="ObjectUnsubscribedError",this.message="object unsubscribed"});var ye=class extends ie{constructor(){super(),this.closed=!1,this.currentObservers=null,this.observers=[],this.isStopped=!1,this.hasError=!1,this.thrownError=null}lift(t){let e=new zs(this,this);return e.operator=t,e}_throwIfClosed(){if(this.closed)throw new zm}next(t){Ui(()=>{if(this._throwIfClosed(),!this.isStopped){this.currentObservers||(this.currentObservers=Array.from(this.observers));for(let e of this.currentObservers)e.next(t)}})}error(t){Ui(()=>{if(this._throwIfClosed(),!this.isStopped){this.hasError=this.isStopped=!0,this.thrownError=t;let{observers:e}=this;for(;e.length;)e.shift().error(t)}})}complete(){Ui(()=>{if(this._throwIfClosed(),!this.isStopped){this.isStopped=!0;let{observers:t}=this;for(;t.length;)t.shift().complete()}})}unsubscribe(){this.isStopped=this.closed=!0,this.observers=this.currentObservers=null}get observed(){var t;return((t=this.observers)===null||t===void 0?void 0:t.length)>0}_trySubscribe(t){return this._throwIfClosed(),super._trySubscribe(t)}_subscribe(t){return this._throwIfClosed(),this._checkFinalizedStatuses(t),this._innerSubscribe(t)}_innerSubscribe(t){let{hasError:e,isStopped:o,observers:i}=this;return e||o?du:(this.currentObservers=null,i.push(t),new Be(()=>{this.currentObservers=null,Zr(i,t)}))}_checkFinalizedStatuses(t){let{hasError:e,thrownError:o,isStopped:i}=this;e?t.error(o):i&&t.complete()}asObservable(){let t=new ie;return t.source=this,t}};ye.create=(n,t)=>new zs(n,t);var zs=class extends ye{constructor(t,e){super(),this.destination=t,this.source=e}next(t){var e,o;(o=(e=this.destination)===null||e===void 0?void 0:e.next)===null||o===void 0||o.call(e,t)}error(t){var e,o;(o=(e=this.destination)===null||e===void 0?void 0:e.error)===null||o===void 0||o.call(e,t)}complete(){var t,e;(e=(t=this.destination)===null||t===void 0?void 0:t.complete)===null||e===void 0||e.call(t)}_subscribe(t){var e,o;return(o=(e=this.source)===null||e===void 0?void 0:e.subscribe(t))!==null&&o!==void 0?o:du}};var st=class extends ye{constructor(t){super(),this._value=t}get value(){return this.getValue()}_subscribe(t){let e=super._subscribe(t);return!e.closed&&t.next(this._value),e}getValue(){let{hasError:t,thrownError:e,_value:o}=this;if(t)throw e;return this._throwIfClosed(),o}next(t){super.next(this._value=t)}};var hu={now(){return(hu.delegate||Date).now()},delegate:void 0};var Bs=class extends ye{constructor(t=1/0,e=1/0,o=hu){super(),this._bufferSize=t,this._windowTime=e,this._timestampProvider=o,this._buffer=[],this._infiniteTimeWindow=!0,this._infiniteTimeWindow=e===1/0,this._bufferSize=Math.max(1,t),this._windowTime=Math.max(1,e)}next(t){let{isStopped:e,_buffer:o,_infiniteTimeWindow:i,_timestampProvider:r,_windowTime:a}=this;e||(o.push(t),!i&&o.push(r.now()+a)),this._trimBuffer(),super.next(t)}_subscribe(t){this._throwIfClosed(),this._trimBuffer();let e=this._innerSubscribe(t),{_infiniteTimeWindow:o,_buffer:i}=this,r=i.slice();for(let a=0;an.complete());function Bm(n){return n&&ae(n.schedule)}function Hm(n){return n[n.length-1]}function Hs(n){return ae(Hm(n))?n.pop():void 0}function mo(n){return Bm(Hm(n))?n.pop():void 0}function Gm(n,t,e,o){function i(r){return r instanceof e?r:new e(function(a){a(r)})}return new(e||(e=Promise))(function(r,a){function s(f){try{p(o.next(f))}catch(_){a(_)}}function c(f){try{p(o.throw(f))}catch(_){a(_)}}function p(f){f.done?r(f.value):i(f.value).then(s,c)}p((o=o.apply(n,t||[])).next())})}function Um(n){var t=typeof Symbol=="function"&&Symbol.iterator,e=t&&n[t],o=0;if(e)return e.call(n);if(n&&typeof n.length=="number")return{next:function(){return n&&o>=n.length&&(n=void 0),{value:n&&n[o++],done:!n}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function Zo(n){return this instanceof Zo?(this.v=n,this):new Zo(n)}function qm(n,t,e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var o=e.apply(n,t||[]),i,r=[];return i=Object.create((typeof AsyncIterator=="function"?AsyncIterator:Object).prototype),s("next"),s("throw"),s("return",a),i[Symbol.asyncIterator]=function(){return this},i;function a(h){return function(P){return Promise.resolve(P).then(h,_)}}function s(h,P){o[h]&&(i[h]=function(T){return new Promise(function(A,N){r.push([h,T,A,N])>1||c(h,T)})},P&&(i[h]=P(i[h])))}function c(h,P){try{p(o[h](P))}catch(T){C(r[0][3],T)}}function p(h){h.value instanceof Zo?Promise.resolve(h.value.v).then(f,_):C(r[0][2],h)}function f(h){c("next",h)}function _(h){c("throw",h)}function C(h,P){h(P),r.shift(),r.length&&c(r[0][0],r[0][1])}}function Wm(n){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=n[Symbol.asyncIterator],e;return t?t.call(n):(n=typeof Um=="function"?Um(n):n[Symbol.iterator](),e={},o("next"),o("throw"),o("return"),e[Symbol.asyncIterator]=function(){return this},e);function o(r){e[r]=n[r]&&function(a){return new Promise(function(s,c){a=n[r](a),i(s,c,a.done,a.value)})}}function i(r,a,s,c){Promise.resolve(c).then(function(p){r({value:p,done:s})},a)}}var Us=(n=>n&&typeof n.length=="number"&&typeof n!="function");function Gs(n){return ae(n?.then)}function qs(n){return ae(n[Gi])}function Ws(n){return Symbol.asyncIterator&&ae(n?.[Symbol.asyncIterator])}function Ks(n){return new TypeError(`You provided ${n!==null&&typeof n=="object"?"an invalid object":`'${n}'`} where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`)}function yO(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Ys=yO();function Zs(n){return ae(n?.[Ys])}function Qs(n){return qm(this,arguments,function*(){let e=n.getReader();try{for(;;){let{value:o,done:i}=yield Zo(e.read());if(i)return yield Zo(void 0);yield yield Zo(o)}}finally{e.releaseLock()}})}function Js(n){return ae(n?.getReader)}function Re(n){if(n instanceof ie)return n;if(n!=null){if(qs(n))return xO(n);if(Us(n))return wO(n);if(Gs(n))return SO(n);if(Ws(n))return Km(n);if(Zs(n))return kO(n);if(Js(n))return EO(n)}throw Ks(n)}function xO(n){return new ie(t=>{let e=n[Gi]();if(ae(e.subscribe))return e.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function wO(n){return new ie(t=>{for(let e=0;e{n.then(e=>{t.closed||(t.next(e),t.complete())},e=>t.error(e)).then(null,Vs)})}function kO(n){return new ie(t=>{for(let e of n)if(t.next(e),t.closed)return;t.complete()})}function Km(n){return new ie(t=>{DO(n,t).catch(e=>t.error(e))})}function EO(n){return Km(Qs(n))}function DO(n,t){var e,o,i,r;return Gm(this,void 0,void 0,function*(){try{for(e=Wm(n);o=yield e.next(),!o.done;){let a=o.value;if(t.next(a),t.closed)return}}catch(a){i={error:a}}finally{try{o&&!o.done&&(r=e.return)&&(yield r.call(e))}finally{if(i)throw i.error}}t.complete()})}function Ot(n,t,e,o=0,i=!1){let r=t.schedule(function(){e(),i?n.add(this.schedule(null,o)):this.unsubscribe()},o);if(n.add(r),!i)return r}function Xs(n,t=0){return fe((e,o)=>{e.subscribe(_e(o,i=>Ot(o,n,()=>o.next(i),t),()=>Ot(o,n,()=>o.complete(),t),i=>Ot(o,n,()=>o.error(i),t)))})}function ec(n,t=0){return fe((e,o)=>{o.add(n.schedule(()=>e.subscribe(o),t))})}function Ym(n,t){return Re(n).pipe(ec(t),Xs(t))}function Zm(n,t){return Re(n).pipe(ec(t),Xs(t))}function Qm(n,t){return new ie(e=>{let o=0;return t.schedule(function(){o===n.length?e.complete():(e.next(n[o++]),e.closed||this.schedule())})})}function Jm(n,t){return new ie(e=>{let o;return Ot(e,t,()=>{o=n[Ys](),Ot(e,t,()=>{let i,r;try{({value:i,done:r}=o.next())}catch(a){e.error(a);return}r?e.complete():e.next(i)},0,!0)}),()=>ae(o?.return)&&o.return()})}function tc(n,t){if(!n)throw new Error("Iterable cannot be null");return new ie(e=>{Ot(e,t,()=>{let o=n[Symbol.asyncIterator]();Ot(e,t,()=>{o.next().then(i=>{i.done?e.complete():e.next(i.value)})},0,!0)})})}function Xm(n,t){return tc(Qs(n),t)}function e_(n,t){if(n!=null){if(qs(n))return Ym(n,t);if(Us(n))return Qm(n,t);if(Gs(n))return Zm(n,t);if(Ws(n))return tc(n,t);if(Zs(n))return Jm(n,t);if(Js(n))return Xm(n,t)}throw Ks(n)}function Fe(n,t){return t?e_(n,t):Re(n)}function se(...n){let t=mo(n);return Fe(n,t)}function Cu(n,t){let e=ae(n)?n:()=>n,o=i=>i.error(e());return new ie(t?i=>t.schedule(o,0,i):o)}function nc(n){return!!n&&(n instanceof ie||ae(n.lift)&&ae(n.subscribe))}var Qo=Bi(n=>function(){n(this),this.name="EmptyError",this.message="no elements in sequence"});function Pe(n,t){return fe((e,o)=>{let i=0;e.subscribe(_e(o,r=>{o.next(n.call(t,r,i++))}))})}var{isArray:IO}=Array;function TO(n,t){return IO(t)?n(...t):n(t)}function oc(n){return Pe(t=>TO(n,t))}var{isArray:AO}=Array,{getPrototypeOf:NO,prototype:RO,keys:FO}=Object;function ic(n){if(n.length===1){let t=n[0];if(AO(t))return{args:t,keys:null};if(LO(t)){let e=FO(t);return{args:e.map(o=>t[o]),keys:e}}}return{args:n,keys:null}}function LO(n){return n&&typeof n=="object"&&NO(n)===RO}function rc(n,t){return n.reduce((e,o,i)=>(e[o]=t[i],e),{})}function Mu(...n){let t=mo(n),e=Hs(n),{args:o,keys:i}=ic(n);if(o.length===0)return Fe([],t);let r=new ie(VO(o,t,i?a=>rc(i,a):tn));return e?r.pipe(oc(e)):r}function VO(n,t,e=tn){return o=>{t_(t,()=>{let{length:i}=n,r=new Array(i),a=i,s=i;for(let c=0;c{let p=Fe(n[c],t),f=!1;p.subscribe(_e(o,_=>{r[c]=_,f||(f=!0,s--),s||o.next(e(r.slice()))},()=>{--a||o.complete()}))},o)},o)}}function t_(n,t,e){n?Ot(e,n,t):t()}function n_(n,t,e,o,i,r,a,s){let c=[],p=0,f=0,_=!1,C=()=>{_&&!c.length&&!p&&t.complete()},h=T=>p{r&&t.next(T),p++;let A=!1;Re(e(T,f++)).subscribe(_e(t,N=>{i?.(N),r?h(N):t.next(N)},()=>{A=!0},void 0,()=>{if(A)try{for(p--;c.length&&pP(N)):P(N)}C()}catch(N){t.error(N)}}))};return n.subscribe(_e(t,h,()=>{_=!0,C()})),()=>{s?.()}}function ut(n,t,e=1/0){return ae(t)?ut((o,i)=>Pe((r,a)=>t(o,r,i,a))(Re(n(o,i))),e):(typeof t=="number"&&(e=t),fe((o,i)=>n_(o,i,n,e)))}function qi(n=1/0){return ut(tn,n)}function o_(){return qi(1)}function Wi(...n){return o_()(Fe(n,mo(n)))}function Jr(n){return new ie(t=>{Re(n()).subscribe(t)})}function bu(...n){let t=Hs(n),{args:e,keys:o}=ic(n),i=new ie(r=>{let{length:a}=e;if(!a){r.complete();return}let s=new Array(a),c=a,p=a;for(let f=0;f{_||(_=!0,p--),s[f]=C},()=>c--,void 0,()=>{(!c||!_)&&(p||r.next(o?rc(o,s):s),r.complete())}))}});return t?i.pipe(oc(t)):i}function Bt(n,t){return fe((e,o)=>{let i=0;e.subscribe(_e(o,r=>n.call(t,r,i++)&&o.next(r)))})}function Ki(n){return fe((t,e)=>{let o=null,i=!1,r;o=t.subscribe(_e(e,void 0,void 0,a=>{r=Re(n(a,Ki(n)(t))),o?(o.unsubscribe(),o=null,r.subscribe(e)):i=!0})),i&&(o.unsubscribe(),o=null,r.subscribe(e))})}function Jo(n,t){return ae(t)?ut(n,t,1):ut(n,1)}function i_(n){return fe((t,e)=>{let o=!1;t.subscribe(_e(e,i=>{o=!0,e.next(i)},()=>{o||e.next(n),e.complete()}))})}function Bn(n){return n<=0?()=>ct:fe((t,e)=>{let o=0;t.subscribe(_e(e,i=>{++o<=n&&(e.next(i),n<=o&&e.complete())}))})}function r_(n=jO){return fe((t,e)=>{let o=!1;t.subscribe(_e(e,i=>{o=!0,e.next(i)},()=>o?e.complete():e.error(n())))})}function jO(){return new Qo}function _o(n){return fe((t,e)=>{try{t.subscribe(e)}finally{e.add(n)}})}function Hn(n,t){let e=arguments.length>=2;return o=>o.pipe(n?Bt((i,r)=>n(i,r,o)):tn,Bn(1),e?i_(t):r_(()=>new Qo))}function ac(n){return n<=0?()=>ct:fe((t,e)=>{let o=[];t.subscribe(_e(e,i=>{o.push(i),n{for(let i of o)e.next(i);e.complete()},void 0,()=>{o=null}))})}function a_(n={}){let{connector:t=()=>new ye,resetOnError:e=!0,resetOnComplete:o=!0,resetOnRefCountZero:i=!0}=n;return r=>{let a,s,c,p=0,f=!1,_=!1,C=()=>{s?.unsubscribe(),s=void 0},h=()=>{C(),a=c=void 0,f=_=!1},P=()=>{let T=a;h(),T?.unsubscribe()};return fe((T,A)=>{p++,!_&&!f&&C();let N=c=c??t();A.add(()=>{p--,p===0&&!_&&!f&&(s=Pu(P,i))}),N.subscribe(A),!a&&p>0&&(a=new zn({next:E=>N.next(E),error:E=>{_=!0,C(),s=Pu(h,e,E),N.error(E)},complete:()=>{f=!0,C(),s=Pu(h,o),N.complete()}}),Re(T).subscribe(a))})(r)}}function Pu(n,t,...e){if(t===!0){n();return}if(t===!1)return;let o=new zn({next:()=>{o.unsubscribe(),n()}});return Re(t(...e)).subscribe(o)}function Ou(n,t,e){let o,i=!1;return n&&typeof n=="object"?{bufferSize:o=1/0,windowTime:t=1/0,refCount:i=!1,scheduler:e}=n:o=n??1/0,a_({connector:()=>new Bs(o,t,e),resetOnError:!0,resetOnComplete:!1,resetOnRefCountZero:i})}function vu(...n){let t=mo(n);return fe((e,o)=>{(t?Wi(n,e,t):Wi(n,e)).subscribe(o)})}function vt(n,t){return fe((e,o)=>{let i=null,r=0,a=!1,s=()=>a&&!i&&o.complete();e.subscribe(_e(o,c=>{i?.unsubscribe();let p=0,f=r++;Re(n(c,f)).subscribe(i=_e(o,_=>o.next(t?t(c,_,f,p++):_),()=>{i=null,s()}))},()=>{a=!0,s()}))})}function Xr(n){return fe((t,e)=>{Re(n).subscribe(_e(e,()=>e.complete(),Qr)),!e.closed&&t.subscribe(e)})}function xe(n,t,e){let o=ae(n)||t||e?{next:n,error:t,complete:e}:n;return o?fe((i,r)=>{var a;(a=o.subscribe)===null||a===void 0||a.call(o);let s=!0;i.subscribe(_e(r,c=>{var p;(p=o.next)===null||p===void 0||p.call(o,c),r.next(c)},()=>{var c;s=!1,(c=o.complete)===null||c===void 0||c.call(o),r.complete()},c=>{var p;s=!1,(p=o.error)===null||p===void 0||p.call(o,c),r.error(c)},()=>{var c,p;s&&((c=o.unsubscribe)===null||c===void 0||c.call(o)),(p=o.finalize)===null||p===void 0||p.call(o)}))}):tn}var pc="https://angular.dev/best-practices/security#preventing-cross-site-scripting-xss",z=class extends Error{code;constructor(t,e){super(Wn(t,e)),this.code=t}};function $O(n){return`NG0${Math.abs(n)}`}function Wn(n,t){return`${$O(n)}${t?": "+t:""}`}function he(n){for(let t in n)if(n[t]===he)return t;throw Error("")}function g_(n,t){for(let e in t)Object.hasOwn(t,e)&&!Object.hasOwn(n,e)&&(n[e]=t[e])}function aa(n){if(typeof n=="string")return n;if(Array.isArray(n))return`[${n.map(aa).join(", ")}]`;if(n==null)return""+n;let t=n.overriddenName||n.name;if(t)return`${t}`;let e=n.toString();if(e==null)return""+e;let o=e.indexOf(` -`);return o>=0?e.slice(0,o):e}function fc(n,t){return n?t?`${n} ${t}`:n:t||""}var zO=he({__forward_ref__:he});function on(n){return n.__forward_ref__=on,n}function lt(n){return Lu(n)?n():n}function Lu(n){return typeof n=="function"&&Object.hasOwn(n,zO)&&n.__forward_ref__===on}function te(n){return{token:n.token,providedIn:n.providedIn||null,factory:n.factory,value:void 0}}function Pn(n){return{providers:n.providers||[],imports:n.imports||[]}}function sa(n){return BO(n,mc)}function Vu(n){return sa(n)!==null}function BO(n,t){return Object.hasOwn(n,t)&&n[t]||null}function HO(n){let t=n?.[mc]??null;return t||null}function xu(n){return n&&Object.hasOwn(n,cc)?n[cc]:null}var mc=he({\u0275prov:he}),cc=he({\u0275inj:he}),B=class{_desc;ngMetadataName="InjectionToken";\u0275prov;constructor(t,e){this._desc=t,this.\u0275prov=void 0,typeof e=="number"?this.__NG_ELEMENT_ID__=e:e!==void 0&&(this.\u0275prov=te({token:this,providedIn:e.providedIn||"root",factory:e.factory}))}get multi(){return this}toString(){return`InjectionToken ${this._desc}`}};function ju(n){return n&&!!n.\u0275providers}var ca=he({\u0275cmp:he}),la=he({\u0275dir:he}),$u=he({\u0275pipe:he}),zu=he({\u0275mod:he}),na=he({\u0275fac:he}),oi=he({__NG_ELEMENT_ID__:he}),s_=he({__NG_ENV_ID__:he});function p_(n){return _c(n,"@NgModule"),n[zu]||null}function ii(n){return _c(n,"@Component"),n[ca]||null}function Bu(n){return _c(n,"@Directive"),n[la]||null}function f_(n){return _c(n,"@Pipe"),n[$u]||null}function _c(n,t){if(n==null)throw new z(-919,!1)}function rn(n){return typeof n=="string"?n:n==null?"":String(n)}var m_=he({ngErrorCode:he}),UO=he({ngErrorMessage:he}),GO=he({ngTokenPath:he});function Hu(n,t){return __("",-200,t)}function hc(n,t){throw new z(-201,!1)}function __(n,t,e){let o=new z(t,n);return o[m_]=t,o[UO]=n,e&&(o[GO]=e),o}function qO(n){return n[m_]}var wu;function h_(){return wu}function _t(n){let t=wu;return wu=n,t}function Uu(n,t,e){let o=sa(n);if(o&&o.providedIn=="root")return o.value===void 0?o.value=o.factory():o.value;if(e&8)return null;if(t!==void 0)return t;hc(n,"")}var an=globalThis;var WO={},Xo=WO,KO="__NG_DI_FLAG__",Su=class{injector;constructor(t){this.injector=t}retrieve(t,e){let o=ei(e)||0;try{return this.injector.get(t,o&8?null:Xo,o)}catch(i){if(zi(i))return i;throw i}}};function YO(n,t=0){let e=Rs();if(e===void 0)throw new z(-203,!1);if(e===null)return Uu(n,void 0,t);{let o=ZO(t),i=e.retrieve(n,o);if(zi(i)){if(o.optional)return null;throw i}return i}}function Q(n,t=0){return(h_()||YO)(lt(n),t)}function D(n,t){return Q(n,ei(t))}function ei(n){return typeof n>"u"||typeof n=="number"?n:0|(n.optional&&8)|(n.host&&1)|(n.self&&2)|(n.skipSelf&&4)}function ZO(n){return{optional:!!(n&8),host:!!(n&1),self:!!(n&2),skipSelf:!!(n&4)}}function ku(n){let t=[];for(let e=0;eArray.isArray(e)?Cc(e,t):t(e))}function Gu(n,t,e){t>=n.length?n.push(e):n.splice(t,0,e)}function da(n,t){return t>=n.length-1?n.pop():n.splice(t,1)[0]}function b_(n,t,e,o){let i=n.length;if(i==t)n.push(e,o);else if(i===1)n.push(o,n[0]),n[0]=e;else{for(i--,n.push(n[i-1],n[i]);i>t;){let r=i-2;n[i]=n[r],i--}n[t]=e,n[t+1]=o}}function Mc(n,t,e){let o=Ji(n,t);return o>=0?n[o|1]=e:(o=~o,b_(n,o,t,e)),o}function bc(n,t){let e=Ji(n,t);if(e>=0)return n[e|1]}function Ji(n,t){return JO(n,t,1)}function JO(n,t,e){let o=0,i=n.length>>e;for(;i!==o;){let r=o+(i-o>>1),a=n[r<t?i=r:o=r+1}return~(i<{e.push(a)};return Cc(t,a=>{let s=a;lc(s,r,[],o)&&(i||=[],i.push(s))}),i!==void 0&&O_(i,r),e}function O_(n,t){for(let e=0;e{t(r,o)})}}function lc(n,t,e,o){if(n=lt(n),!n)return!1;let i=null,r=xu(n),a=!r&&ii(n);if(!r&&!a){let c=n.ngModule;if(r=xu(c),r)i=c;else return!1}else{if(a&&!a.standalone)return!1;i=n}let s=o.has(i);if(a){if(s)return!1;if(o.add(i),a.dependencies){let c=typeof a.dependencies=="function"?a.dependencies():a.dependencies;for(let p of c)lc(p,t,e,o)}}else if(r){if(r.imports!=null&&!s){o.add(i);let p;Cc(r.imports,f=>{lc(f,t,e,o)&&(p||=[],p.push(f))}),p!==void 0&&O_(p,t)}if(!s){let p=Co(i)||(()=>new i);t({provide:i,useFactory:p,deps:ht},i),t({provide:qu,useValue:i,multi:!0},i),t({provide:ri,useValue:()=>Q(i),multi:!0},i)}let c=r.providers;if(c!=null&&!s){let p=n;Ku(c,f=>{t(f,p)})}}else return!1;return i!==n&&n.providers!==void 0}function Ku(n,t){for(let e of n)ju(e)&&(e=e.\u0275providers),Array.isArray(e)?Ku(e,t):t(e)}var XO=he({provide:String,useValue:he});function v_(n){return n!==null&&typeof n=="object"&&XO in n}function ev(n){return!!(n&&n.useExisting)}function tv(n){return!!(n&&n.useFactory)}function ti(n){return typeof n=="function"}function y_(n){return!!n.useClass}var ga=new B(""),sc={},c_={},yu;function pa(){return yu===void 0&&(yu=new Zi),yu}var Le=class{},ni=class extends Le{parent;source;scopes;records=new Map;_ngOnDestroyHooks=new Set;_onDestroyHooks=[];get destroyed(){return this._destroyed}_destroyed=!1;injectorDefTypes;constructor(t,e,o,i){super(),this.parent=e,this.source=o,this.scopes=i,Du(t,a=>this.processProvider(a)),this.records.set(ua,Yi(void 0,this)),i.has("environment")&&this.records.set(Le,Yi(void 0,this));let r=this.records.get(ga);r!=null&&typeof r.value=="string"&&this.scopes.add(r.value),this.injectorDefTypes=new Set(this.get(qu,ht,{self:!0}))}retrieve(t,e){let o=ei(e)||0;try{return this.get(t,Xo,o)}catch(i){if(zi(i))return i;throw i}}destroy(){ea(this),this._destroyed=!0;let t=Y(null);try{for(let o of this._ngOnDestroyHooks)o.ngOnDestroy();let e=this._onDestroyHooks;this._onDestroyHooks=[];for(let o of e)o()}finally{this.records.clear(),this._ngOnDestroyHooks.clear(),this.injectorDefTypes.clear(),Y(t)}}onDestroy(t){return ea(this),this._onDestroyHooks.push(t),()=>this.removeOnDestroy(t)}runInContext(t){ea(this);let e=Mn(this),o=_t(void 0),i;try{return t()}finally{Mn(e),_t(o)}}get(t,e=Xo,o){if(ea(this),Object.hasOwn(t,s_))return t[s_](this);let i=ei(o),r,a=Mn(this),s=_t(void 0);try{if(!(i&4)){let p=this.records.get(t);if(p===void 0){let f=av(t)&&sa(t);f&&this.injectableDefInScope(f)?p=Yi(Eu(t),sc):p=null,this.records.set(t,p)}if(p!=null)return this.hydrate(t,p,i)}let c=i&2?pa():this.parent;return e=i&8&&e===Xo?null:e,c.get(t,e)}catch(c){let p=qO(c);throw p===-200||p===-201?new z(p,null):c}finally{_t(s),Mn(a)}}resolveInjectorInitializers(){let t=Y(null),e=Mn(this),o=_t(void 0),i;try{let r=this.get(ri,ht,{self:!0});for(let a of r)a()}finally{Mn(e),_t(o),Y(t)}}toString(){return"R3Injector[...]"}processProvider(t){t=lt(t);let e=ti(t)?t:lt(t&&t.provide),o=ov(t);if(!ti(t)&&t.multi===!0){let i=this.records.get(e);i||(i=Yi(void 0,sc,!0),i.factory=()=>ku(i.multi),this.records.set(e,i)),e=t,i.multi.push(t)}this.records.set(e,o)}hydrate(t,e,o){let i=Y(null);try{if(e.value===c_)throw Hu("");return e.value===sc&&(e.value=c_,e.value=e.factory(void 0,o)),typeof e.value=="object"&&e.value&&rv(e.value)&&this._ngOnDestroyHooks.add(e.value),e.value}finally{Y(i)}}injectableDefInScope(t){if(!t.providedIn)return!1;let e=lt(t.providedIn);return typeof e=="string"?e==="any"||this.scopes.has(e):this.injectorDefTypes.has(e)}removeOnDestroy(t){let e=this._onDestroyHooks.indexOf(t);e!==-1&&this._onDestroyHooks.splice(e,1)}};function Eu(n){let t=sa(n),e=t!==null?t.factory:Co(n);if(e!==null)return e;if(n instanceof B)throw new z(-204,!1);if(n instanceof Function)return nv(n);throw new z(-204,!1)}function nv(n){if(n.length>0)throw new z(-204,!1);let e=HO(n);return e!==null?()=>e.factory(n):()=>new n}function ov(n){if(v_(n))return Yi(void 0,n.useValue);{let t=Yu(n);return Yi(t,sc)}}function Yu(n,t,e){let o;if(ti(n)){let i=lt(n);return Co(i)||Eu(i)}else if(v_(n))o=()=>lt(n.useValue);else if(tv(n))o=()=>n.useFactory(...ku(n.deps||[]));else if(ev(n))o=(i,r)=>Q(lt(n.useExisting),r!==void 0&&r&8?8:void 0);else{let i=lt(n&&(n.useClass||n.provide));if(iv(n))o=()=>new i(...ku(n.deps));else return Co(i)||Eu(i)}return o}function ea(n){if(n.destroyed)throw new z(-205,!1)}function Yi(n,t,e=!1){return{factory:n,value:t,multi:e?[]:void 0}}function iv(n){return!!n.deps}function rv(n){return n!==null&&typeof n=="object"&&typeof n.ngOnDestroy=="function"}function av(n){return typeof n=="function"||typeof n=="object"&&n.ngMetadataName==="InjectionToken"}function Du(n,t){for(let e of n)Array.isArray(e)?Du(e,t):e&&ju(e)?Du(e.\u0275providers,t):t(e)}function et(n,t){let e;n instanceof ni?(ea(n),e=n):e=new Su(n);let o,i=Mn(e),r=_t(void 0);try{return t()}finally{Mn(i),_t(r)}}function x_(){return h_()!==void 0||Rs()!=null}var sn=0,K=1,ee=2,Xe=3,Ht=4,yt=5,Xi=6,er=7,ze=8,On=9,cn=10,we=11,tr=12,Zu=13,Po=14,xt=15,Oo=16,ai=17,vn=18,yn=19,Qu=20,Un=21,Pc=22,Gn=23,Tt=24,si=25,xn=26,He=27,w_=1,Ju=6,ci=7,fa=8,li=9,Ve=10;function Kn(n){return Array.isArray(n)&&typeof n[w_]=="object"}function Ut(n){return Array.isArray(n)&&n[w_]===!0}function Xu(n){return(n.flags&4)!==0}function Yn(n){return n.componentOffset>-1}function Oc(n){return(n.flags&1)===1}function wn(n){return!!n.template}function nr(n){return(n[ee]&512)!==0}function di(n){return(n[ee]&256)===256}var Je=(function(n){return n[n.NONE=0]="NONE",n[n.HTML=1]="HTML",n[n.STYLE=2]="STYLE",n[n.SCRIPT=3]="SCRIPT",n[n.URL=4]="URL",n[n.RESOURCE_URL=5]="RESOURCE_URL",n[n.ATTRIBUTE_NO_BINDING=6]="ATTRIBUTE_NO_BINDING",n})(Je||{}),ta,Qi="svg",vc="math",S_="",l_="*",Iu=()=>Object.create(null);function sv(){return ta||(ta=Iu(),ho(Je.HTML,void 0,[["iframe",["srcdoc"]],["*",["innerHTML","outerHTML"]]]),ho(Je.STYLE,void 0,[["*",["style"]]]),ho(Je.URL,void 0,[["*",["formAction"]],["area",["href"]],["a",["href","xlink:href"]],["form",["action"]],["img",["src"]],["video",["src"]]]),ho(Je.URL,vc,[["*",["href","xlink:href"]]]),ho(Je.RESOURCE_URL,void 0,[["base",["href"]],["embed",["src"]],["frame",["src"]],["iframe",["src"]],["link",["href"]],["object",["codebase","data"]]]),ho(Je.URL,Qi,[["a",["href","xlink:href"]]]),ho(Je.ATTRIBUTE_NO_BINDING,Qi,[["animate",["attributeName","values","to","from"]],["set",["to","attributeName"]],["animateMotion",["attributeName"]],["animateTransform",["attributeName"]]]),ho(Je.ATTRIBUTE_NO_BINDING,void 0,[["unknown",["attributeName","values","to","from","sandbox","allow","allowFullscreen","referrerPolicy","csp","fetchPriority","credentialless"]],["iframe",["sandbox","allow","allowFullscreen","referrerPolicy","csp","fetchPriority","credentialless"]]]),ta)}function ho(n,t,e){let o=t??S_;for(let[i,r]of e){let a=i.toLowerCase();for(let s of r){let c=s.toLowerCase(),p=ta[c]??=Iu(),f=p[o]??=Iu();f[a]=n}}}function k_(n,t,e){let i=sv()[t.toLowerCase()];if(!i)return Je.NONE;let r=n.toLowerCase(),a;if(e){let s=i[e];s&&(a=s[r]??s[l_])}if(a===void 0){let s=i[S_];s&&(a=s[r]??s[l_])}return a??Je.NONE}function dt(n){for(;Array.isArray(n);)n=n[sn];return n}function eg(n,t){return dt(t[n])}function At(n,t){return dt(t[n.index])}function yc(n,t){return n.data[t]}function xc(n,t){return n[t]}function tg(n,t,e,o){e>=n.data.length&&(n.data[e]=null,n.blueprint[e]=null),t[e]=o}function Gt(n,t){let e=t[n];return Kn(e)?e:e[sn]}function E_(n){return(n[ee]&4)===4}function wc(n){return(n[ee]&128)===128}function D_(n){return Ut(n[Xe])}function Sn(n,t){return t==null?null:n[t]}function ng(n){n[ai]=0}function og(n){n[ee]&1024||(n[ee]|=1024,wc(n)&&ui(n))}function I_(n,t){for(;n>0;)t=t[Po],n--;return t}function ma(n){return!!(n[ee]&9216||n[Tt]?.dirty)}function Sc(n){n[cn].changeDetectionScheduler?.notify(8),n[ee]&64&&(n[ee]|=1024),ma(n)&&ui(n)}function ui(n){n[cn].changeDetectionScheduler?.notify(0);let t=qn(n);for(;t!==null&&!(t[ee]&8192||(t[ee]|=8192,!wc(t)));)t=qn(t)}function kc(n,t){if(di(n))throw new z(911,!1);n[Un]===null&&(n[Un]=[]),n[Un].push(t)}function T_(n,t){if(n[Un]===null)return;let e=n[Un].indexOf(t);e!==-1&&n[Un].splice(e,1)}function qn(n){let t=n[Xe];return Ut(t)?t[Xe]:t}function ig(n){return n[er]??=[]}function rg(n){return n.cleanup??=[]}function A_(n,t,e,o){let i=ig(t);i.push(e),n.firstCreatePass&&rg(n).push(o,i.length-1)}var ce={lFrame:W_(null),bindingsEnabled:!0,skipHydrationRootTNode:null};var Tu=!1;function N_(){return ce.lFrame.elementDepthCount}function R_(){ce.lFrame.elementDepthCount++}function ag(){ce.lFrame.elementDepthCount--}function F_(){return ce.bindingsEnabled}function L_(){return ce.skipHydrationRootTNode!==null}function sg(n){return ce.skipHydrationRootTNode===n}function cg(){ce.skipHydrationRootTNode=null}function Z(){return ce.lFrame.lView}function Ne(){return ce.lFrame.tView}function v(n){return ce.lFrame.contextLView=n,n[ze]}function y(n){return ce.lFrame.contextLView=null,n}function tt(){let n=lg();for(;n!==null&&n.type===64;)n=n.parent;return n}function lg(){return ce.lFrame.currentTNode}function V_(){let n=ce.lFrame,t=n.currentTNode;return n.isParent?t:t.parent}function or(n,t){let e=ce.lFrame;e.currentTNode=n,e.isParent=t}function dg(){return ce.lFrame.isParent}function j_(){ce.lFrame.isParent=!1}function $_(){return ce.lFrame.contextLView}function ug(){return Tu}function oa(n){let t=Tu;return Tu=n,t}function ir(){let n=ce.lFrame,t=n.bindingRootIndex;return t===-1&&(t=n.bindingRootIndex=n.tView.bindingStartIndex),t}function gg(){return ce.lFrame.bindingIndex}function z_(n){return ce.lFrame.bindingIndex=n}function Zn(){return ce.lFrame.bindingIndex++}function _a(n){let t=ce.lFrame,e=t.bindingIndex;return t.bindingIndex=t.bindingIndex+n,e}function B_(){return ce.lFrame.inI18n}function H_(n,t){let e=ce.lFrame;e.bindingIndex=e.bindingRootIndex=n,Ec(t)}function U_(){return ce.lFrame.currentDirectiveIndex}function Ec(n){ce.lFrame.currentDirectiveIndex=n}function G_(n){let t=ce.lFrame.currentDirectiveIndex;return t===-1?null:n[t]}function pg(){return ce.lFrame.currentQueryIndex}function Dc(n){ce.lFrame.currentQueryIndex=n}function cv(n){let t=n[K];return t.type===2?t.declTNode:t.type===1?n[yt]:null}function fg(n,t,e){if(e&4){let i=t,r=n;for(;i=i.parent,i===null&&!(e&1);)if(i=cv(r),i===null||(r=r[Po],i.type&10))break;if(i===null)return!1;t=i,n=r}let o=ce.lFrame=q_();return o.currentTNode=t,o.lView=n,!0}function Ic(n){let t=q_(),e=n[K];ce.lFrame=t,t.currentTNode=e.firstChild,t.lView=n,t.tView=e,t.contextLView=n,t.bindingIndex=e.bindingStartIndex,t.inI18n=!1}function q_(){let n=ce.lFrame,t=n===null?null:n.child;return t===null?W_(n):t}function W_(n){let t={currentTNode:null,isParent:!0,lView:null,tView:null,selectedIndex:-1,contextLView:null,elementDepthCount:0,currentNamespace:null,currentDirectiveIndex:-1,bindingRootIndex:-1,bindingIndex:-1,currentQueryIndex:0,parent:n,child:null,inI18n:!1};return n!==null&&(n.child=t),t}function K_(){let n=ce.lFrame;return ce.lFrame=n.parent,n.currentTNode=null,n.lView=null,n}var mg=K_;function Tc(){let n=K_();n.isParent=!0,n.tView=null,n.selectedIndex=-1,n.contextLView=null,n.elementDepthCount=0,n.currentDirectiveIndex=-1,n.currentNamespace=null,n.bindingRootIndex=-1,n.bindingIndex=-1,n.currentQueryIndex=0}function Y_(n){return(ce.lFrame.contextLView=I_(n,ce.lFrame.contextLView))[ze]}function qt(){return ce.lFrame.selectedIndex}function vo(n){ce.lFrame.selectedIndex=n}function gi(){let n=ce.lFrame;return yc(n.tView,n.selectedIndex)}function yo(){ce.lFrame.currentNamespace=Qi}function rr(){lv()}function lv(){ce.lFrame.currentNamespace=null}function _g(){return ce.lFrame.currentNamespace}var Z_=!0;function Ac(){return Z_}function Nc(n){Z_=n}function Au(n,t=null,e=null,o){let i=hg(n,t,e,o);return i.resolveInjectorInitializers(),i}function hg(n,t=null,e=null,o,i=new Set){let r=[e||ht,P_(n)],a;return new ni(r,t||pa(),a||null,i)}var Ct=class n{static THROW_IF_NOT_FOUND=Xo;static NULL=new Zi;static create(t,e){if(Array.isArray(t))return Au({name:""},e,t,"");{let o=t.name??"";return Au({name:o},t.parent,t.providers,o)}}static \u0275prov=te({token:n,providedIn:"any",factory:()=>Q(ua)});static __NG_ELEMENT_ID__=-1},Ue=new B(""),Ae=class{static __NG_ELEMENT_ID__=dv;static __NG_ENV_ID__=t=>t},dc=class extends Ae{_lView;constructor(t){super(),this._lView=t}get destroyed(){return di(this._lView)}onDestroy(t){let e=this._lView;return kc(e,t),()=>T_(e,t)}};function dv(){return new dc(Z())}var Cg=!1,Q_=new B(""),kn=(()=>{class n{taskId=0;pendingTasks=new Set;destroyed=!1;pendingTask=new st(!1);debugTaskTracker=D(Q_,{optional:!0});get hasPendingTasks(){return this.destroyed?!1:this.pendingTask.value}get hasPendingTasksObservable(){return this.destroyed?new ie(e=>{e.next(!1),e.complete()}):this.pendingTask}add(){!this.hasPendingTasks&&!this.destroyed&&this.pendingTask.next(!0);let e=this.taskId++;return this.pendingTasks.add(e),this.debugTaskTracker?.add(e),e}has(e){return this.pendingTasks.has(e)}remove(e){this.pendingTasks.delete(e),this.debugTaskTracker?.remove(e),this.pendingTasks.size===0&&this.hasPendingTasks&&this.pendingTask.next(!1)}ngOnDestroy(){this.pendingTasks.clear(),this.hasPendingTasks&&this.pendingTask.next(!1),this.destroyed=!0,this.pendingTask.unsubscribe()}static \u0275prov=te({token:n,providedIn:"root",factory:()=>new n})}return n})(),Nu=class extends ye{__isAsync;destroyRef=void 0;pendingTasks=void 0;constructor(t=!1){super(),this.__isAsync=t,x_()&&(this.destroyRef=D(Ae,{optional:!0})??void 0,this.pendingTasks=D(kn,{optional:!0})??void 0)}emit(t){let e=Y(null);try{super.next(t)}finally{Y(e)}}subscribe(t,e,o){let i=t,r=e||(()=>null),a=o;if(t&&typeof t=="object"){let c=t;i=c.next?.bind(c),r=c.error?.bind(c),a=c.complete?.bind(c)}this.__isAsync&&(r=this.wrapInTimeout(r),i&&(i=this.wrapInTimeout(i)),a&&(a=this.wrapInTimeout(a)));let s=super.subscribe({next:i,error:r,complete:a});return t instanceof Be&&t.add(s),s}wrapInTimeout(t){return e=>{let o=this.pendingTasks?.add();setTimeout(()=>{try{t(e)}finally{o!==void 0&&this.pendingTasks?.remove(o)}})}}},Ke=Nu;function uc(...n){}function Mg(n){let t,e;function o(){n=uc;try{e!==void 0&&typeof cancelAnimationFrame=="function"&&cancelAnimationFrame(e),t!==void 0&&clearTimeout(t)}catch(i){}}return t=setTimeout(()=>{n(),o()}),typeof requestAnimationFrame=="function"&&(e=requestAnimationFrame(()=>{n(),o()})),()=>o()}function J_(n){return queueMicrotask(()=>n()),()=>{n=uc}}var bg="isAngularZone",ia=bg+"_ID",uv=0,ge=class n{hasPendingMacrotasks=!1;hasPendingMicrotasks=!1;isStable=!0;onUnstable=new Ke(!1);onMicrotaskEmpty=new Ke(!1);onStable=new Ke(!1);onError=new Ke(!1);constructor(t){let{enableLongStackTrace:e=!1,shouldCoalesceEventChangeDetection:o=!1,shouldCoalesceRunChangeDetection:i=!1,scheduleInRootZone:r=Cg}=t;if(typeof Zone>"u")throw new z(908,!1);Zone.assertZonePatched();let a=this;a._nesting=0,a._outer=a._inner=Zone.current,Zone.TaskTrackingZoneSpec&&(a._inner=a._inner.fork(new Zone.TaskTrackingZoneSpec)),e&&Zone.longStackTraceZoneSpec&&(a._inner=a._inner.fork(Zone.longStackTraceZoneSpec)),a.shouldCoalesceEventChangeDetection=!i&&o,a.shouldCoalesceRunChangeDetection=i,a.callbackScheduled=!1,a.scheduleInRootZone=r,fv(a)}static isInAngularZone(){return typeof Zone<"u"&&Zone.current.get(bg)===!0}static assertInAngularZone(){if(!n.isInAngularZone())throw new z(909,!1)}static assertNotInAngularZone(){if(n.isInAngularZone())throw new z(909,!1)}run(t,e,o){return this._inner.run(t,e,o)}runTask(t,e,o,i){let r=this._inner,a=r.scheduleEventTask("NgZoneEvent: "+i,t,gv,uc,uc);try{return r.runTask(a,e,o)}finally{r.cancelTask(a)}}runGuarded(t,e,o){return this._inner.runGuarded(t,e,o)}runOutsideAngular(t){return this._outer.run(t)}},gv={};function Pg(n){if(n._nesting==0&&!n.hasPendingMicrotasks&&!n.isStable)try{n._nesting++,n.onMicrotaskEmpty.emit(null)}finally{if(n._nesting--,!n.hasPendingMicrotasks)try{n.runOutsideAngular(()=>n.onStable.emit(null))}finally{n.isStable=!0}}}function pv(n){if(n.isCheckStableRunning||n.callbackScheduled)return;n.callbackScheduled=!0;function t(){Mg(()=>{n.callbackScheduled=!1,Ru(n),n.isCheckStableRunning=!0,Pg(n),n.isCheckStableRunning=!1})}n.scheduleInRootZone?Zone.root.run(()=>{t()}):n._outer.run(()=>{t()}),Ru(n)}function fv(n){let t=()=>{pv(n)},e=uv++;n._inner=n._inner.fork({name:"angular",properties:{[bg]:!0,[ia]:e,[ia+e]:!0},onInvokeTask:(o,i,r,a,s,c)=>{if(mv(c))return o.invokeTask(r,a,s,c);try{return d_(n),o.invokeTask(r,a,s,c)}finally{(n.shouldCoalesceEventChangeDetection&&a.type==="eventTask"||n.shouldCoalesceRunChangeDetection)&&t(),u_(n)}},onInvoke:(o,i,r,a,s,c,p)=>{try{return d_(n),o.invoke(r,a,s,c,p)}finally{n.shouldCoalesceRunChangeDetection&&!n.callbackScheduled&&!_v(c)&&t(),u_(n)}},onHasTask:(o,i,r,a)=>{o.hasTask(r,a),i===r&&(a.change=="microTask"?(n._hasPendingMicrotasks=a.microTask,Ru(n),Pg(n)):a.change=="macroTask"&&(n.hasPendingMacrotasks=a.macroTask))},onHandleError:(o,i,r,a)=>(o.handleError(r,a),n.runOutsideAngular(()=>n.onError.emit(a)),!1)})}function Ru(n){n._hasPendingMicrotasks||(n.shouldCoalesceEventChangeDetection||n.shouldCoalesceRunChangeDetection)&&n.callbackScheduled===!0?n.hasPendingMicrotasks=!0:n.hasPendingMicrotasks=!1}function d_(n){n._nesting++,n.isStable&&(n.isStable=!1,n.onUnstable.emit(null))}function u_(n){n._nesting--,Pg(n)}var ra=class{hasPendingMicrotasks=!1;hasPendingMacrotasks=!1;isStable=!0;onUnstable=new Ke;onMicrotaskEmpty=new Ke;onStable=new Ke;onError=new Ke;run(t,e,o){return t.apply(e,o)}runGuarded(t,e,o){return t.apply(e,o)}runOutsideAngular(t){return t()}runTask(t,e,o,i){return t.apply(e,o)}};function mv(n){return X_(n,"__ignore_ng_zone__")}function _v(n){return X_(n,"__scheduler_tick__")}function X_(n,t){return!Array.isArray(n)||n.length!==1?!1:n[0]?.data?.[t]===!0}var nn=class{_console=console;handleError(t){this._console.error("ERROR",t)}},Nt=new B("",{factory:()=>{let n=D(ge),t=D(Le),e;return o=>{n.runOutsideAngular(()=>{t.destroyed&&!e?setTimeout(()=>{throw o}):(e??=t.get(nn),e.handleError(o))})}}}),eh={provide:ri,useValue:()=>{let n=D(nn,{optional:!0})},multi:!0};function x(n,t){let[e,o,i]=iu(n,t?.equal),r=e,a=r[nt];return r.set=o,r.update=i,r.asReadonly=Rc.bind(r),r}function Rc(){let n=this[nt];if(n.readonlyFn===void 0){let t=()=>this();t[nt]=n,n.readonlyFn=t}return n.readonlyFn}var ha=new B("",{factory:()=>hv}),hv="ng";var Fc=new B(""),Ca=new B("",{providedIn:"platform",factory:()=>"unknown"});var Ma=new B("",{factory:()=>D(Ue).body?.querySelector("[ngCspNonce]")?.getAttribute("ngCspNonce")||null});var ba=(()=>{class n{view;node;constructor(e,o){this.view=e,this.node=o}static __NG_ELEMENT_ID__=Cv}return n})();function Cv(){return new ba(Z(),tt())}var bn=class{},ar=new B("",{factory:()=>!0});var Lc=new B(""),Vc=(()=>{class n{static \u0275prov=te({token:n,providedIn:"root",factory:()=>new Fu})}return n})(),Fu=class{dirtyEffectCount=0;queues=new Map;add(t){this.enqueue(t),this.schedule(t)}schedule(t){t.dirty&&this.dirtyEffectCount++}remove(t){let e=t.zone,o=this.queues.get(e);o.has(t)&&(o.delete(t),t.dirty&&this.dirtyEffectCount--)}enqueue(t){let e=t.zone;this.queues.has(e)||this.queues.set(e,new Set);let o=this.queues.get(e);o.has(t)||o.add(t)}flush(){for(;this.dirtyEffectCount>0;){let t=!1;for(let[e,o]of this.queues)e===null?t||=this.flushQueue(o):t||=e.run(()=>this.flushQueue(o));t||(this.dirtyEffectCount=0)}}flushQueue(t){let e=!1;for(let o of t)o.dirty&&(this.dirtyEffectCount--,e=!0,o.run());return e}},gc=class{[nt];constructor(t){this[nt]=t}destroy(){this[nt].destroy()}};function Ye(n,t){let e=t?.injector??D(Ct),o=t?.manualCleanup!==!0?e.get(Ae):null,i,r=e.get(ba,null,{optional:!0}),a=e.get(bn);return r!==null?(i=Pv(r.view,a,n),o instanceof dc&&o._lView===r.view&&(o=null)):i=Ov(n,e.get(Vc),a),i.injector=e,o!==null&&(i.onDestroyFns=[o.onDestroy(()=>i.destroy())]),new gc(i)}var th=F(S({},ru),{cleanupFns:void 0,zone:null,onDestroyFns:null,run(){let n=oa(!1);try{au(this)}finally{oa(n)}},cleanup(){if(!this.cleanupFns?.length)return;let n=Y(null);try{for(;this.cleanupFns.length;)this.cleanupFns.pop()()}finally{this.cleanupFns=[],Y(n)}}}),Mv=F(S({},th),{consumerMarkedDirty(){this.scheduler.schedule(this),this.notifier.notify(12)},destroy(){if(qo(this),this.onDestroyFns!==null)for(let n of this.onDestroyFns)n();this.cleanup(),this.scheduler.remove(this)}}),bv=F(S({},th),{consumerMarkedDirty(){this.view[ee]|=8192,ui(this.view),this.notifier.notify(13)},destroy(){if(qo(this),this.onDestroyFns!==null)for(let n of this.onDestroyFns)n();this.cleanup(),this.view[Gn]?.delete(this)}});function Pv(n,t,e){let o=Object.create(bv);return o.view=n,o.zone=typeof Zone<"u"?Zone.current:null,o.notifier=t,o.fn=nh(o,e),n[Gn]??=new Set,n[Gn].add(o),o.consumerMarkedDirty(o),o}function Ov(n,t,e){let o=Object.create(Mv);return o.fn=nh(o,n),o.scheduler=t,o.notifier=e,o.zone=typeof Zone<"u"?Zone.current:null,o.scheduler.add(o),o.notifier.notify(12),o}function nh(n,t){return()=>{t(e=>(n.cleanupFns??=[]).push(e))}}function Pa(n){return typeof n=="function"&&n[nt]!==void 0}function jc(n){return Pa(n)&&typeof n.set=="function"}var Oa=(()=>{class n{internalPendingTasks=D(kn);scheduler=D(bn);errorHandler=D(Nt);add(){let e=this.internalPendingTasks.add();return()=>{this.internalPendingTasks.has(e)&&(this.scheduler.notify(11),this.internalPendingTasks.remove(e))}}run(e){let o=this.add();try{e().catch(this.errorHandler).finally(o)}catch(i){this.errorHandler(i),o()}}static \u0275prov=te({token:n,providedIn:"root",factory:()=>new n})}return n})();function Na(n){return{toString:n}.toString()}var pe=(function(n){return n[n.TemplateCreateStart=0]="TemplateCreateStart",n[n.TemplateCreateEnd=1]="TemplateCreateEnd",n[n.TemplateUpdateStart=2]="TemplateUpdateStart",n[n.TemplateUpdateEnd=3]="TemplateUpdateEnd",n[n.LifecycleHookStart=4]="LifecycleHookStart",n[n.LifecycleHookEnd=5]="LifecycleHookEnd",n[n.OutputStart=6]="OutputStart",n[n.OutputEnd=7]="OutputEnd",n[n.BootstrapApplicationStart=8]="BootstrapApplicationStart",n[n.BootstrapApplicationEnd=9]="BootstrapApplicationEnd",n[n.BootstrapComponentStart=10]="BootstrapComponentStart",n[n.BootstrapComponentEnd=11]="BootstrapComponentEnd",n[n.ChangeDetectionStart=12]="ChangeDetectionStart",n[n.ChangeDetectionEnd=13]="ChangeDetectionEnd",n[n.ChangeDetectionSyncStart=14]="ChangeDetectionSyncStart",n[n.ChangeDetectionSyncEnd=15]="ChangeDetectionSyncEnd",n[n.AfterRenderHooksStart=16]="AfterRenderHooksStart",n[n.AfterRenderHooksEnd=17]="AfterRenderHooksEnd",n[n.ComponentStart=18]="ComponentStart",n[n.ComponentEnd=19]="ComponentEnd",n[n.DeferBlockStateStart=20]="DeferBlockStateStart",n[n.DeferBlockStateEnd=21]="DeferBlockStateEnd",n[n.DynamicComponentStart=22]="DynamicComponentStart",n[n.DynamicComponentEnd=23]="DynamicComponentEnd",n[n.HostBindingsUpdateStart=24]="HostBindingsUpdateStart",n[n.HostBindingsUpdateEnd=25]="HostBindingsUpdateEnd",n})(pe||{}),Kc=class{previousValue;currentValue;firstChange;constructor(t,e,o){this.previousValue=t,this.currentValue=e,this.firstChange=o}isFirstChange(){return this.firstChange}};function Hh(n,t,e,o){t!==null?t.applyValueToInputSignal(t,o):n[e]=o}var Uh=null,In=(()=>{Uh=oh;let n=()=>oh;return n.ngInherit=!0,n})();function Iv(){return Uh}function oh(n){return n.type.prototype.ngOnChanges&&(n.setInput=Av),Tv}function Tv(){let n=Gh(this),t=n?.current;if(t){let e=n.previous;if(e===Mo)n.previous=t;else for(let o in t)e[o]=t[o];n.current=null,this.ngOnChanges(t)}}function Av(n,t,e,o,i){let r=this.declaredInputs[o],a=Gh(n)||Nv(n,{previous:Mo,current:null}),s=a.current||(a.current={}),c=a.previous,p=c[r];s[r]=new Kc(p&&p.currentValue,e,c===Mo),Hh(n,t,i,e)}var Ag="__ngSimpleChanges__";function Gh(n){return Object.hasOwn(n,Ag)&&n[Ag]||null}function Nv(n,t){return n[Ag]=t}var ih=[];var Ce=function(n,t=null,e){for(let o=0;o=o)break}else t[c]<0&&(n[ai]+=65536),(s>14>16&&(n[ee]&3)===t&&(n[ee]+=16384,rh(s,r)):rh(s,r)}var cr=-1,mi=class{factory;name;injectImpl;resolving=!1;canSeeViewProviders;multi;componentProviders;index;providerFactory;constructor(t,e,o,i){this.factory=t,this.name=i,this.canSeeViewProviders=e,this.injectImpl=o}};function Vv(n){return(n.flags&8)!==0}function jv(n){return(n.flags&16)!==0}function $v(n,t,e){let o=0;for(;ot){a=r-1;break}}}for(;r>16}function Zc(n,t){let e=Bv(n),o=t;for(;e>0;)o=o[Po],e--;return o}var Ng=!0;function Qc(n){let t=Ng;return Ng=n,t}var Hv=256,Yh=Hv-1,Zh=5,Uv=0,En={};function Gv(n,t,e){let o;typeof e=="string"?o=e.charCodeAt(0)||0:Object.hasOwn(e,oi)&&(o=e[oi]),o==null&&(o=e[oi]=Uv++);let i=o&Yh,r=1<>Zh)]|=r}function Jc(n,t){let e=Qh(n,t);if(e!==-1)return e;let o=t[K];o.firstCreatePass&&(n.injectorIndex=t.length,vg(o.data,n),vg(t,null),vg(o.blueprint,null));let i=dp(n,t),r=n.injectorIndex;if(Kh(i)){let a=Yc(i),s=Zc(i,t),c=s[K].data;for(let p=0;p<8;p++)t[r+p]=s[a+p]|c[a+p]}return t[r+8]=i,r}function vg(n,t){n.push(0,0,0,0,0,0,0,0,t)}function Qh(n,t){return n.injectorIndex===-1||n.parent&&n.parent.injectorIndex===n.injectorIndex||t[n.injectorIndex+8]===null?-1:n.injectorIndex}function dp(n,t){if(n.parent&&n.parent.injectorIndex!==-1)return n.parent.injectorIndex;let e=0,o=null,i=t;for(;i!==null;){if(o=nC(i),o===null)return cr;if(e++,i=i[Po],o.injectorIndex!==-1)return o.injectorIndex|e<<16}return cr}function Rg(n,t,e){Gv(n,t,e)}function qv(n,t){if(t==="class")return n.classes;if(t==="style")return n.styles;let e=n.attrs;if(e){let o=e.length,i=0;for(;i>20,_=o?s:s+f,C=i?s+f:p;for(let h=_;h=c&&P.type===e)return h}if(i){let h=a[c];if(h&&wn(h)&&h.type===e)return c}return null}function Sa(n,t,e,o,i){let r=n[e],a=t.data;if(r instanceof mi){let s=r;if(s.resolving)throw Hu("");let c=Qc(s.canSeeViewProviders);s.resolving=!0;let p=a[e].type||a[e],f,_=s.injectImpl?_t(s.injectImpl):null,C=fg(n,o,0);try{r=n[e]=s.factory(void 0,i,a,n,o),t.firstCreatePass&&e>=o.directiveStart&&Rv(e,a[e],t)}finally{_!==null&&_t(_),Qc(c),s.resolving=!1,mg()}}return r}function Kv(n){if(typeof n=="string")return n.charCodeAt(0)||0;let t=Object.hasOwn(n,oi)?n[oi]:void 0;return typeof t=="number"?t>=0?t&Yh:Yv:t}function sh(n,t,e){let o=1<>Zh)]&o)}function ch(n,t){return!(n&2)&&!(n&1&&t)}var xo=class{_tNode;_lView;constructor(t,e){this._tNode=t,this._lView=e}get(t,e,o){return eC(this._tNode,this._lView,t,ei(o),e)}};function Yv(){return new xo(tt(),Z())}function ko(n){return Na(()=>{let t=n.prototype.constructor,e=t[na]||Fg(t),o=Object.prototype,i=Object.getPrototypeOf(n.prototype).constructor;for(;i&&i!==o;){let r=i[na]||Fg(i);if(r&&r!==e)return r;i=Object.getPrototypeOf(i)}return r=>new r})}function Fg(n){return Lu(n)?()=>{let t=Fg(lt(n));return t&&t()}:Co(n)}function Zv(n,t,e,o,i){let r=n,a=t;for(;r!==null&&a!==null&&a[ee]&2048&&!nr(a);){let s=tC(r,a,e,o|2,En);if(s!==En)return s;let c=r.parent;if(!c){let p=a[Qu];if(p){let f=p.get(e,En,o&-5);if(f!==En)return f}c=nC(a),a=a[Po]}r=c}return i}function nC(n){let t=n[K],e=t.type;return e===2?t.declTNode:e===1?n[yt]:null}function Ra(n){return qv(tt(),n)}function Oe(n){return{token:n.token,providedIn:n.autoProvided===!1?null:"root",factory:n.factory,value:void 0}}function Qv(){return pr(tt(),Z())}function pr(n,t){return new Mt(At(n,t))}var Mt=(()=>{class n{nativeElement;constructor(e){this.nativeElement=e}static __NG_ELEMENT_ID__=Qv}return n})();function Jv(n){return n instanceof Mt?n.nativeElement:n}function Xv(){return this._results[Symbol.iterator]()}var Xc=class{_emitDistinctChangesOnly;dirty=!0;_onDirty=void 0;_results=[];_changesDetected=!1;_changes=void 0;length=0;first=void 0;last=void 0;get changes(){return this._changes??=new ye}constructor(t=!1){this._emitDistinctChangesOnly=t}get(t){return this._results[t]}map(t){return this._results.map(t)}filter(t){return this._results.filter(t)}find(t){return this._results.find(t)}reduce(t,e){return this._results.reduce(t,e)}forEach(t){this._results.forEach(t)}some(t){return this._results.some(t)}toArray(){return this._results.slice()}toString(){return this._results.toString()}reset(t,e){this.dirty=!1;let o=M_(t);(this._changesDetected=!C_(this._results,o,e))&&(this._results=o,this.length=o.length,this.last=o[this.length-1],this.first=o[0])}notifyOnChanges(){this._changes!==void 0&&(this._changesDetected||!this._emitDistinctChangesOnly)&&this._changes.next(this)}onDirty(t){this._onDirty=t}setDirty(){this.dirty=!0,this._onDirty?.()}destroy(){this._changes!==void 0&&(this._changes.complete(),this._changes.unsubscribe())}[Symbol.iterator]=Xv};function oC(n){return(n.flags&128)===128}var up=(function(n){return n[n.OnPush=0]="OnPush",n[n.Eager=1]="Eager",n[n.Default=1]="Default",n})(up||{}),iC=new Map,ey=0;function ty(){return ey++}function ny(n){iC.set(n[yn],n)}function Lg(n){iC.delete(n[yn])}var lh="__ngContext__";function dr(n,t){Kn(t)?(n[lh]=t[yn],ny(t)):n[lh]=t}function rC(n){return sC(n[tr])}function aC(n){return sC(n[Ht])}function sC(n){for(;n!==null&&!Ut(n);)n=n[Ht];return n}var Vg;function gp(n){Vg=n}function pp(){if(Vg!==void 0)return Vg;if(typeof document<"u")return document;throw new z(210,!1)}var cC="r";var lC="di";var dC=!1,uC=new B("",{factory:()=>dC});var dh=new WeakMap;function oy(n,t){if(n==null||typeof n!="object")return;let e=dh.get(n);e||(e=new WeakSet,dh.set(n,e)),e.add(t)}var iy=(n,t,e,o)=>{};function ry(n,t,e,o){iy(n,t,e,o)}function fp(n){return(n.flags&32)===32}var ay=()=>null;function gC(n,t,e=!1){return ay(n,t,e)}function pC(n,t){let e=n.contentQueries;if(e!==null){let o=Y(null);try{for(let i=0;in,createScript:n=>n,createScriptURL:n=>n})}catch(n){}return $c}function fl(n){return cy()?.createHTML(n)||n}var zc;function mC(){if(zc===void 0&&(zc=null,an.trustedTypes))try{zc=an.trustedTypes.createPolicy("angular#unsafe-bypass",{createHTML:n=>n,createScript:n=>n,createScriptURL:n=>n})}catch(n){}return zc}function uh(n){return mC()?.createHTML(n)||n}function gh(n){return mC()?.createScriptURL(n)||n}var el=class{changingThisBreaksApplicationSecurity;constructor(t){this.changingThisBreaksApplicationSecurity=t}toString(){return`SafeValue must use [property]=binding: ${this.changingThisBreaksApplicationSecurity} (see ${pc})`}};function _i(n){return n instanceof el?n.changingThisBreaksApplicationSecurity:n}function ml(n,t){let e=_C(n);if(e!=null&&e!==t){if(e==="ResourceURL"&&t==="URL")return!0;throw new Error(`Required a safe ${t}, got a ${e} (see ${pc})`)}return e===t}function _C(n){return n instanceof el&&n.getTypeName()||null}function ly(n){let t=new zg(n);return dy()?new $g(t):t}var $g=class{inertDocumentHelper;constructor(t){this.inertDocumentHelper=t}getInertBodyElement(t){t=""+t;try{let e=new window.DOMParser().parseFromString(fl(t),"text/html").body;return e===null?this.inertDocumentHelper.getInertBodyElement(t):(e.firstChild?.remove(),e)}catch(e){return null}}},zg=class{defaultDoc;inertDocument;constructor(t){this.defaultDoc=t,this.inertDocument=this.defaultDoc.implementation.createHTMLDocument("sanitization-inert")}getInertBodyElement(t){let e=this.inertDocument.createElement("template");return e.innerHTML=fl(t),e}};function dy(){try{return!!new window.DOMParser().parseFromString(fl(""),"text/html")}catch(n){return!1}}var uy=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\/?#]*(?:[\/?#]|$))/i;function mp(n){return n=String(n),n.match(uy)?n:"unsafe:"+n}function Qn(n){let t=Object.create(null);for(let e of n.split(","))t[e]=!0;return t}function Fa(...n){let t=Object.create(null);for(let e of n)for(let o in e)Object.hasOwn(e,o)&&(t[o]=!0);return t}var hC=Qn("area,br,col,hr,img,wbr"),CC=Qn("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),MC=Qn("rp,rt"),gy=Fa(MC,CC),py=Fa(CC,Qn("address,article,aside,blockquote,caption,center,del,details,dialog,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,main,map,menu,nav,ol,pre,section,summary,table,ul")),fy=Fa(MC,Qn("a,abbr,acronym,audio,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,picture,q,ruby,rp,rt,s,samp,small,source,span,strike,strong,sub,sup,time,track,tt,u,var,video")),ph=Fa(hC,py,fy,gy),bC=Qn("background,cite,href,itemtype,longdesc,poster,src,xlink:href"),my=Qn("abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,controls,coords,datetime,default,dir,download,face,headers,height,hidden,hreflang,hspace,ismap,itemscope,itemprop,kind,label,lang,language,loop,media,muted,nohref,nowrap,open,preload,rel,rev,role,rows,rowspan,rules,scope,scrolling,shape,size,sizes,span,srclang,srcset,start,summary,tabindex,target,title,translate,type,usemap,valign,value,vspace,width"),_y=Qn("aria-activedescendant,aria-atomic,aria-autocomplete,aria-busy,aria-checked,aria-colcount,aria-colindex,aria-colspan,aria-controls,aria-current,aria-describedby,aria-details,aria-disabled,aria-dropeffect,aria-errormessage,aria-expanded,aria-flowto,aria-grabbed,aria-haspopup,aria-hidden,aria-invalid,aria-keyshortcuts,aria-label,aria-labelledby,aria-level,aria-live,aria-modal,aria-multiline,aria-multiselectable,aria-orientation,aria-owns,aria-placeholder,aria-posinset,aria-pressed,aria-readonly,aria-relevant,aria-required,aria-roledescription,aria-rowcount,aria-rowindex,aria-rowspan,aria-selected,aria-setsize,aria-sort,aria-valuemax,aria-valuemin,aria-valuenow,aria-valuetext"),hy=Fa(bC,my,_y),Cy=Qn("script,style,template"),Bg=class{sanitizedSomething=!1;buf=[];sanitizeChildren(t){let e=t.firstChild,o=!0,i=[];for(;e;){if(e.nodeType===Node.ELEMENT_NODE?o=this.startElement(e):e.nodeType===Node.TEXT_NODE?this.chars(e.nodeValue):this.sanitizedSomething=!0,o&&e.firstChild){i.push(e),e=Py(e);continue}for(;e;){e.nodeType===Node.ELEMENT_NODE&&this.endElement(e);let r=by(e);if(r){e=r;break}e=i.pop()}}return this.buf.join("")}startElement(t){let e=fh(t).toLowerCase();if(!Object.hasOwn(ph,e))return this.sanitizedSomething=!0,!Object.hasOwn(Cy,e);this.buf.push("<"),this.buf.push(e);let o=t.attributes;for(let i=0;i"),!0}endElement(t){let e=fh(t).toLowerCase();Object.hasOwn(ph,e)&&!Object.hasOwn(hC,e)&&(this.buf.push(""))}chars(t){this.buf.push(mh(t))}};function My(n,t){return(n.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_CONTAINED_BY)!==Node.DOCUMENT_POSITION_CONTAINED_BY}function by(n){let t=n.nextSibling;if(t&&n!==t.previousSibling)throw PC(t);return t}function Py(n){let t=n.firstChild;if(t&&My(n,t))throw PC(t);return t}function fh(n){let t=n.nodeName;return typeof t=="string"?t:"FORM"}function PC(n){return new Error(`Failed to sanitize html because the element is clobbered: ${n.outerHTML}`)}var Oy=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,vy=/([^\#-~ |!])/g;function mh(n){return n.replace(/&/g,"&").replace(Oy,function(t){let e=t.charCodeAt(0),o=t.charCodeAt(1);return"&#"+((e-55296)*1024+(o-56320)+65536)+";"}).replace(vy,function(t){return"&#"+t.charCodeAt(0)+";"}).replace(//g,">")}var Bc;function OC(n,t){let e=null;try{Bc=Bc||ly(n);let o=t?String(t):"";e=Bc.getInertBodyElement(o);let i=5,r=o;do{if(i===0)throw new Error("Failed to sanitize html because the input is unstable");i--,o=r,r=e.innerHTML,e=Bc.getInertBodyElement(o)}while(o!==r);let s=new Bg().sanitizeChildren(_h(e)||e);return fl(s)}finally{if(e){let o=_h(e)||e;for(;o.firstChild;)o.firstChild.remove()}}}function _h(n){return"content"in n&&yy(n)?n.content:null}function yy(n){return n.nodeType===Node.ELEMENT_NODE&&n.nodeName==="TEMPLATE"}function xy(n,t){return n.createText(t)}function wy(n,t,e){n.setValue(t,e)}function vC(n,t,e){return n.createElement(t,e)}function pi(n,t,e,o,i){n.insertBefore(t,e,o,i)}function yC(n,t,e){n.appendChild(t,e)}function hh(n,t,e,o,i){o!==null?pi(n,t,e,o,i):yC(n,t,e)}function xC(n,t,e,o){n.removeChild(null,t,e,o)}function Sy(n,t,e){n.setAttribute(t,"style",e)}function ky(n,t,e){e===""?n.removeAttribute(t,"class"):n.setAttribute(t,"class",e)}function wC(n,t,e){let{mergedAttrs:o,classes:i,styles:r}=e;o!==null&&$v(n,t,o),i!==null&&ky(n,t,i),r!==null&&Sy(n,t,r)}function Ey(n,t=!0){if(n[0]!=":")return[null,n];let e=n.indexOf(":",1);if(e===-1){if(t)throw new Error(`Unsupported format "${n}" expecting ":namespace:name"`);return[null,n]}return[n.slice(1,e),n.slice(e+1)]}function Pi(n,t,e){if(t!==void 0&&e!==void 0&&kC(t,e)!==Je.HTML)return n;let o=hp();return o?uh(o.sanitize(Je.HTML,n)||""):ml(n,"HTML")?uh(_i(n)):OC(pp(),rn(n))}function kt(n){let t=hp();return t?t.sanitize(Je.URL,n)||"":ml(n,"URL")?_i(n):mp(rn(n))}function SC(n){let t=hp();if(t)return gh(t.sanitize(Je.RESOURCE_URL,n)||"");if(ml(n,"ResourceURL"))return gh(_i(n));throw new z(904,!1)}function Dy(n,t){switch(kC(n,t)){case Je.RESOURCE_URL:return SC;case Je.URL:return kt;default:return null}}function _p(n,t,e){return Dy(t,e)?.(n)??n}function hp(){let n=Z();return n&&n[cn].sanitizer}function kC(n,t){let[e,o]=Iy(n);return k_(o,t,e)}function Iy(n){n=n.toLowerCase();let t=Ey(n,!1);if(t[0])return t;let o=qt()===-1?null:gi(),i=o?.namespace;if(n==="#host"&&o?.type===2){let r=At(o,Z());if(r.tagName&&(n=r.tagName.toLowerCase()),i==null){let a=r.namespaceURI;i=a&&sy[a]}}return[i,n]}function _l(n){return n.ownerDocument.defaultView}function hl(n){return n.ownerDocument}function Ty(n){return n instanceof Function?n():n}function Ay(n,t,e){let o=n.length;for(;;){let i=n.indexOf(t,e);if(i===-1)return i;if(i===0||n.charCodeAt(i-1)<=32){let r=t.length;if(i+r===o||n.charCodeAt(i+r)<=32)return i}e=i+1}}var EC="ng-template";function Ny(n,t,e,o){let i=0;if(o){for(;i-1){let r;for(;++ir?_="":_=i[f+1].toLowerCase(),o&2&&p!==_){if(ln(o))return!1;a=!0}}}}return ln(o)||a}function ln(n){return(n&1)===0}function Ly(n,t,e,o){if(t===null)return-1;let i=0;if(o||!e){let r=!1;for(;i-1)for(e++;e0?'="'+s+'"':"")+"]"}else o&8?i+="."+a:o&4&&(i+=" "+a);else i!==""&&!ln(a)&&(t+=Ch(r,i),i=""),o=a,r=r||!ln(o);e++}return i!==""&&(t+=Ch(r,i)),t}function By(n){return n.map(zy).join(",")}function Hy(n){let t=[],e=[],o=1,i=2;for(;o=0;s--){let{el:c,declarationView:p}=o[s],f=c.parentNode;c===t?(o.splice(s,1),ya.add(c),c.dispatchEvent(new CustomEvent("animationend",{detail:{cancel:!0}}))):r&&c===r?(o.splice(s,1),c.dispatchEvent(new CustomEvent("animationend",{detail:{cancel:!0}})),c.parentNode?.removeChild(c)):f&&i&&f!==i&&(a===null||p===null||a===p)&&(o.splice(s,1),c.dispatchEvent(new CustomEvent("animationend",{detail:{cancel:!0}})),c.parentNode?.removeChild(c))}}function qy(n,t,e){let o=DC(e),i=Hg.get(n);i?i.some(r=>r.el===t)||i.push({el:t,declarationView:o}):Hg.set(n,[{el:t,declarationView:o}])}var Cl=(function(n){return n[n.CHANGE_DETECTION=0]="CHANGE_DETECTION",n[n.AFTER_NEXT_RENDER=1]="AFTER_NEXT_RENDER",n})(Cl||{}),Tn=new B(""),Mh=new Set;function An(n){Mh.has(n)||(Mh.add(n),performance?.mark?.("mark_feature_usage",{detail:{feature:n}}))}var bp=(()=>{class n{impl=null;execute(){this.impl?.execute()}static \u0275prov=te({token:n,providedIn:"root",factory:()=>new n})}return n})(),IC=[0,1,2,3],TC=(()=>{class n{ngZone=D(ge);scheduler=D(bn);errorHandler=D(nn,{optional:!0});sequences=new Set;deferredRegistrations=new Set;executing=!1;constructor(){D(Tn,{optional:!0})}execute(){let e=this.sequences.size>0;e&&Ce(pe.AfterRenderHooksStart),this.executing=!0;for(let o of IC)for(let i of this.sequences)if(!(i.erroredOrDestroyed||!i.hooks[o]))try{i.pipelinedValue=this.ngZone.runOutsideAngular(()=>this.maybeTrace(()=>{let r=i.hooks[o];return r(i.pipelinedValue)},i.snapshot))}catch(r){i.erroredOrDestroyed=!0,this.errorHandler?.handleError(r)}this.executing=!1;for(let o of this.sequences)o.afterRun(),o.once&&(this.sequences.delete(o),o.destroy());for(let o of this.deferredRegistrations)this.sequences.add(o);this.deferredRegistrations.size>0&&this.scheduler.notify(7),this.deferredRegistrations.clear(),e&&Ce(pe.AfterRenderHooksEnd)}register(e){let{view:o}=e;o!==void 0?((o[si]??=[]).push(e),ui(o),o[ee]|=8192):this.executing?this.deferredRegistrations.add(e):this.addSequence(e)}addSequence(e){this.sequences.add(e),this.scheduler.notify(7)}unregister(e){this.executing&&this.sequences.has(e)?(e.erroredOrDestroyed=!0,e.pipelinedValue=void 0,e.once=!0):(this.sequences.delete(e),this.deferredRegistrations.delete(e))}maybeTrace(e,o){return o?o.run(Cl.AFTER_NEXT_RENDER,e):e()}static \u0275prov=te({token:n,providedIn:"root",factory:()=>new n})}return n})(),tl=class{impl;hooks;view;once;snapshot;erroredOrDestroyed=!1;pipelinedValue=void 0;unregisterOnDestroy;constructor(t,e,o,i,r,a=null){this.impl=t,this.hooks=e,this.view=o,this.once=i,this.snapshot=a,this.unregisterOnDestroy=r?.onDestroy(()=>this.destroy())}afterRun(){this.erroredOrDestroyed=!1,this.pipelinedValue=void 0,this.snapshot?.dispose(),this.snapshot=null}destroy(){this.impl.unregister(this),this.unregisterOnDestroy?.();let t=this.view?.[si];t&&(this.view[si]=t.filter(e=>e!==this))}};function La(n,t){let e=t?.injector??D(Ct);return An("NgAfterNextRender"),Ky(n,e,t,!0)}function Wy(n){return n instanceof Function?[void 0,void 0,n,void 0]:[n.earlyRead,n.write,n.mixedReadWrite,n.read]}function Ky(n,t,e,o){let i=t.get(bp);i.impl??=t.get(TC);let r=t.get(Tn,null,{optional:!0}),a=e?.manualCleanup!==!0?t.get(Ae):null,s=t.get(ba,null,{optional:!0}),c=new tl(i.impl,Wy(n),s?.view,o,a,r?.snapshot(null));return i.impl.register(c),c}var Pp=new B("",{factory:()=>{let n=D(Le),t=new Set;return n.onDestroy(()=>t.clear()),{queue:t,isScheduled:!1,scheduler:null,injector:n}}});function AC(n,t,e){let o=n.get(Pp);if(Array.isArray(t))for(let i of t)o.queue.add(i),e?.detachedLeaveAnimationFns?.push(i);else o.queue.add(t),e?.detachedLeaveAnimationFns?.push(t);o.scheduler&&o.scheduler(n)}function Yy(n,t){let e=n.get(Pp);if(Array.isArray(t))for(let o of t)e.queue.delete(o);else e.queue.delete(t)}function Zy(n,t){let e=n.get(Pp);if(t.detachedLeaveAnimationFns){for(let o of t.detachedLeaveAnimationFns)e.queue.delete(o);t.detachedLeaveAnimationFns=void 0}}function Qy(n,t){for(let[e,o]of t)AC(n,o.animateFns)}function bh(n,t,e,o){let i=n?.[xn]?.enter;t!==null&&i&&i.has(e.index)&&Qy(o,i)}function Ph(n,t,e,o){try{e.get(ua)}catch(a){return o(!1)}let i=n?.[xn];i?.enter?.has(t.index)&&Yy(e,i.enter.get(t.index).animateFns);let r=Jy(n,t,i);if(r.size===0){let a=!1;if(n){let s=[];Ml(n,t,s),a=s.length>0}if(!a)return o(!1)}n&&wo.add(n[yn]),AC(e,()=>Xy(n,t,i||void 0,r,o),i||void 0)}function Jy(n,t,e){let o=new Map,i=e?.leave;if(i&&i.has(t.index)&&o.set(t.index,i.get(t.index)),n&&i)for(let[r,a]of i){if(o.has(r))continue;let c=n[K].data[r].parent;for(;c;){if(c===t){o.set(r,a);break}c=c.parent}}return o}function Xy(n,t,e,o,i){let r=[];if(e&&e.leave)for(let[a]of o){if(!e.leave.has(a))continue;let s=e.leave.get(a);for(let c of s.animateFns){let{promise:p}=c();r.push(p)}e.detachedLeaveAnimationFns=void 0}if(n&&Ml(n,t,r),r.length>0){let a=e||n?.[xn];if(a){let s=a.running;s&&r.push(s),a.running=Promise.allSettled(r),tx(n,a.running,i)}else Promise.allSettled(r).then(()=>{n&&wo.delete(n[yn]),i(!0)})}else n&&wo.delete(n[yn]),i(!1)}function Ml(n,t,e){if(t.type&12){let i=n[t.index];if(Ut(i))for(let r=Ve;r{n[xn]?.running===t&&(n[xn].running=void 0,wo.delete(n[yn])),e(!0)})}function sr(n,t,e,o,i,r,a,s){if(i!=null){let c,p=!1;Ut(i)?c=i:Kn(i)&&(p=!0,i=i[sn]);let f=dt(i);n===0&&o!==null?(bh(s,o,r,e),a==null?yC(t,o,f):pi(t,o,f,a||null,!0)):n===1&&o!==null?(bh(s,o,r,e),pi(t,o,f,a||null,!0),Gy(r,f,s)):n===2?(s?.[xn]?.leave?.has(r.index)&&qy(r,f,s),ya.delete(f),Ph(s,r,e,_=>{if(ya.has(f)){ya.delete(f);return}xC(t,f,p,_)})):n===3&&(ya.delete(f),Ph(s,r,e,()=>{t.destroyNode(f)})),c!=null&&fx(t,n,e,c,r,o,a)}}function nx(n,t){NC(n,t),t[sn]=null,t[yt]=null}function ox(n,t,e,o,i,r){o[sn]=i,o[yt]=t,Pl(n,o,e,1,i,r)}function NC(n,t){t[cn].changeDetectionScheduler?.notify(9),Pl(n,t,t[we],2,null,null)}function ix(n){let t=n[tr];if(!t)return yg(n[K],n);for(;t;){let e=null;if(Kn(t))e=t[tr];else{let o=t[Ve];o&&(e=o)}if(!e){for(;t&&!t[Ht]&&t!==n;)Kn(t)&&yg(t[K],t),t=t[Xe];t===null&&(t=n),Kn(t)&&yg(t[K],t),e=t&&t[Ht]}t=e}}function Op(n,t){let e=n[li],o=e.indexOf(t);e.splice(o,1)}function bl(n,t){if(di(t))return;let e=t[we];e.destroyNode&&Pl(n,t,e,3,null,null),ix(t)}function yg(n,t){if(di(t))return;let e=Y(null);try{t[ee]&=-129,t[ee]|=256,t[Tt]&&qo(t[Tt]),ax(n,t),rx(n,t),t[K].type===1&&t[we].destroy();let o=t[Oo];if(o!==null&&Ut(t[Xe])){o!==t[Xe]&&Op(o,t);let i=t[vn];i!==null&&i.detachView(n)}Lg(t)}finally{Y(e)}}function rx(n,t){let e=n.cleanup,o=t[er];if(e!==null)for(let a=0;a=0?o[s]():o[-s].unsubscribe(),a+=2}else{let s=o[e[a+1]];e[a].call(s)}o!==null&&(t[er]=null);let i=t[Un];if(i!==null){t[Un]=null;for(let a=0;aHe&&VC(n,t,He,!1);let s=a?pe.TemplateUpdateStart:pe.TemplateCreateStart;Ce(s,i,e),e(o,i)}finally{vo(r);let s=a?pe.TemplateUpdateEnd:pe.TemplateCreateEnd;Ce(s,i,e)}}function $C(n,t,e){yx(n,t,e),(e.flags&64)===64&&xx(n,t,e)}function kp(n,t,e=At){let o=t.localNames;if(o!==null){let i=t.index+1;for(let r=0;rnull;function Ox(n){return n==="class"?"className":n==="for"?"htmlFor":n==="formaction"?"formAction":n==="innerHtml"?"innerHTML":n==="readonly"?"readOnly":n==="tabindex"?"tabIndex":n}function zC(n,t,e,o,i,r){let a=t[K];if(Ep(n,a,t,e,o)){Yn(n)&&vx(t,n.index);return}n.type&3&&(e=Ox(e)),BC(n,t,e,o,i,r)}function BC(n,t,e,o,i,r){if(n.type&3){let a=At(n,t);o=r!=null?r(o,n.value||"",e):o,i.setProperty(a,e,o)}else n.type&12}function vx(n,t){let e=Gt(t,n);e[ee]&16||(e[ee]|=64)}function yx(n,t,e){let o=e.directiveStart,i=e.directiveEnd;Yn(e)&&Cx(t,e,n.data[o+e.componentOffset]),n.firstCreatePass||Jc(e,t);let r=e.initialInputs;for(let a=o;a=s&&h<=c){let P=t.data[h],T=_[C+1];hi(P,e[h],T,r),p=!0}else if(h>c)break}}return a!==null&&Object.hasOwn(o.inputs,i)&&(hi(o,e[a],i,r),p=!0),p}function Ax(n,t){let e=Gt(t,n),o=e[K];Nx(o,e);let i=e[sn];i!==null&&e[Xi]===null&&(e[Xi]=gC(i,e[On])),Ce(pe.ComponentStart);try{Dp(o,e,e[ze])}finally{Ce(pe.ComponentEnd,e[ze])}}function Nx(n,t){for(let e=t.length;e{ui(n.lView)},consumerOnSignalRead(){this.lView[Tt]=this}});function $x(n){let t=n[Tt]??Object.create(zx);return t.lView=n,t}var zx=F(S({},po),{consumerIsAlwaysLive:!0,kind:"template",consumerMarkedDirty:n=>{let t=qn(n.lView);for(;t&&!KC(t[K]);)t=qn(t);t&&og(t)},consumerOnSignalRead(){this.lView[Tt]=this}});function KC(n){return n.type!==2}function YC(n){if(n[Gn]===null)return;let t=!0;for(;t;){let e=!1;for(let o of n[Gn])if(o.dirty&&(e=!0,o.zone===null||Zone.current===o.zone?o.run():o.zone.run(()=>o.run()),n[Gn]===null))return;t=e&&!!(n[ee]&8192)}}var Bx=100;function ZC(n,t=0){let o=n[cn].rendererFactory,i=!1;i||o.begin?.();try{Hx(n,t)}finally{i||o.end?.()}}function Hx(n,t){let e=ug();try{oa(!0),Gg(n,t);let o=0;for(;ma(n);){if(o===Bx)throw new z(103,!1);o++,Gg(n,1)}}finally{oa(e)}}function Ux(n,t,e,o){if(di(t))return;let i=t[ee],r=!1,a=!1;Ic(t);let s=!0,c=null,p=null;r||(KC(n)?(p=Fx(t),c=fo(p)):Is()===null?(s=!1,p=$x(t),c=fo(p)):t[Tt]&&(qo(t[Tt]),t[Tt]=null));try{ng(t),z_(n.bindingStartIndex),e!==null&&jC(n,t,e,2,o);let f=(i&3)===3;if(!r)if(f){let h=n.preOrderCheckHooks;h!==null&&Uc(t,h,null)}else{let h=n.preOrderHooks;h!==null&&Gc(t,h,0,null),Og(t,0)}if(a||Gx(t),YC(t),QC(t,0),n.contentQueries!==null&&pC(n,t),!r)if(f){let h=n.contentCheckHooks;h!==null&&Uc(t,h)}else{let h=n.contentHooks;h!==null&&Gc(t,h,1),Og(t,1)}Wx(n,t);let _=n.components;_!==null&&XC(t,_,0);let C=n.viewQuery;if(C!==null&&jg(2,C,o),!r)if(f){let h=n.viewCheckHooks;h!==null&&Uc(t,h)}else{let h=n.viewHooks;h!==null&&Gc(t,h,2),Og(t,2)}if(n.firstUpdatePass===!0&&(n.firstUpdatePass=!1),t[Pc]){for(let h of t[Pc])h();t[Pc]=null}r||(qC(t),t[ee]&=-73)}catch(f){throw r||ui(t),f}finally{p!==null&&(Go(p,c),s&&Vx(p)),Tc()}}function QC(n,t){for(let e=rC(n);e!==null;e=aC(e))for(let o=Ve;o0&&(n[e-1][Ht]=o[Ht]);let r=da(n,Ve+t);nx(o[K],o);let a=r[vn];a!==null&&a.detachView(r[K]),o[Xe]=null,o[Ht]=null,o[ee]&=-129}return o}function Kx(n,t,e,o){let i=Ve+o,r=e.length;o>0&&(e[i-1][Ht]=t),o-1&&(Da(t,o),da(e,o))}this._attachedToViewContainer=!1}bl(this._lView[K],this._lView)}onDestroy(t){kc(this._lView,t)}markForCheck(){Ip(this._cdRefInjectingView||this._lView,4)}detach(){this._lView[ee]&=-129}reattach(){Sc(this._lView),this._lView[ee]|=128}detectChanges(){this._lView[ee]|=1024,ZC(this._lView)}checkNoChanges(){}attachToViewContainerRef(){if(this._appRef)throw new z(902,!1);this._attachedToViewContainer=!0}detachFromAppRef(){this._appRef=null;let t=nr(this._lView),e=this._lView[Oo];e!==null&&!t&&Op(e,this._lView),NC(this._lView[K],this._lView)}attachToAppRef(t){if(this._attachedToViewContainer)throw new z(902,!1);this._appRef=t;let e=nr(this._lView),o=this._lView[Oo];o!==null&&!e&&oM(o,this._lView),Sc(this._lView)}};var ur=(()=>{class n{_declarationLView;_declarationTContainer;elementRef;static __NG_ELEMENT_ID__=Yx;constructor(e,o,i){this._declarationLView=e,this._declarationTContainer=o,this.elementRef=i}get ssrId(){return this._declarationTContainer.tView?.ssrId||null}createEmbeddedView(e,o){return this.createEmbeddedViewImpl(e,o)}createEmbeddedViewImpl(e,o,i){let r=vl(this._declarationLView,this._declarationTContainer,e,{embeddedViewInjector:o,dehydratedView:i});return new So(r)}}return n})();function Yx(){return Tp(tt(),Z())}function Tp(n,t){return n.type&4?new ur(t,n,pr(n,t)):null}function xl(n,t,e,o,i){let r=n.data[t];if(r===null)r=Zx(n,t,e,o,i),B_()&&(r.flags|=32);else if(r.type&64){r.type=e,r.value=o,r.attrs=i;let a=V_();r.injectorIndex=a===null?-1:a.injectorIndex}return or(r,!0),r}function Zx(n,t,e,o,i){let r=lg(),a=dg(),s=a?r:r&&r.parent,c=n.data[t]=Jx(n,s,e,t,o,i);return Qx(n,c,r,a),c}function Qx(n,t,e,o){n.firstChild===null&&(n.firstChild=t),e!==null&&(o?e.child==null&&t.parent!==null&&(e.child=t):e.next===null&&(e.next=t,t.prev=e))}function Jx(n,t,e,o,i,r){let a=t?t.injectorIndex:-1,s=0;return L_()&&(s|=128),{type:e,index:o,insertBeforeIndex:null,injectorIndex:a,directiveStart:-1,directiveEnd:-1,directiveStylingLast:-1,componentOffset:-1,controlDirectiveIndex:-1,customControlIndex:-1,propertyBindings:null,flags:s,providerIndexes:0,value:i,namespace:_g(),attrs:r,mergedAttrs:null,localNames:null,initialInputs:null,inputs:null,hostDirectiveInputs:null,outputs:null,hostDirectiveOutputs:null,directiveToIndex:null,tView:null,next:null,prev:null,projectionNext:null,child:null,parent:t,projection:null,styles:null,stylesWithoutHost:null,residualStyles:void 0,classes:null,classesWithoutHost:null,residualClasses:void 0,classBindings:0,styleBindings:0}}function Xx(n){let t=n[Ju]??[],o=n[Xe][we],i=[];for(let r of t)r.data[lC]!==void 0?i.push(r):e1(r,o);n[Ju]=i}function e1(n,t){let e=0,o=n.firstChild;if(o){let i=n.data[cC];for(;enull,n1=()=>null;function qg(n,t){return t1(n,t)}function iM(n,t,e){return n1(n,t,e)}var rM=class{},Ci=class{},wt=class{destroyNode=null;static __NG_ELEMENT_ID__=()=>o1()};function o1(){let n=Z(),t=tt(),e=Gt(t.index,n);return(Kn(e)?e:n)[we]}var aM=(()=>{class n{static \u0275prov=te({token:n,providedIn:"root",factory:()=>null})}return n})();function sM(n){return n.debugInfo?.className||n.type.name||null}var Wc={},nl=class{injector;parentInjector;constructor(t,e){this.injector=t,this.parentInjector=e}get(t,e,o){let i=this.injector.get(t,Wc,o);return i!==Wc||e===Wc?i:this.parentInjector.get(t,e,o)}};function Ap(n,t,e){return n[t]=e}function i1(n,t){return n[t]}function St(n,t,e){if(e===ot)return!1;let o=n[t];return Object.is(o,e)?!1:(n[t]=e,!0)}function Np(n,t,e,o){let i=St(n,t,e);return St(n,t+1,o)||i}function r1(n,t,e,o,i){let r=Np(n,t,e,o);return St(n,t+2,i)||r}function fi(n,t,e){return function o(i){let r=o.__ngNativeEl__;r!==void 0&&oy(i,r);let a=Yn(n)?Gt(n.index,t):t;Ip(a,5);let s=t[ze],c=vh(t,s,e,i),p=o.__ngNextListenerFn__;for(;p;)c=vh(t,s,p,i)&&c,p=p.__ngNextListenerFn__;return c}}function vh(n,t,e,o){let i=Y(null);try{return Ce(pe.OutputStart,t,e),e(o)!==!1}catch(r){return Ix(n,r),!1}finally{Ce(pe.OutputEnd,t,e),Y(i)}}function Rp(n,t,e,o,i,r,a,s){let c=Oc(n),p=!1,f=null;if(!o&&c&&(f=s1(t,e,r,n.index)),f!==null){let _=f.__ngLastListenerFn__||f;_.__ngNextListenerFn__=a,f.__ngLastListenerFn__=a,p=!0}else{let _=At(n,e),C=o?o(_):_;ry(e,C,r,s),o||(s.__ngNativeEl__=_);let h=i.listen(C,r,s);if(!a1(r)){let P=o?T=>o(dt(T[n.index])):n.index;cM(P,t,e,r,s,h,!1)}}return p}function a1(n){return n.startsWith("animation")||n.startsWith("transition")}function s1(n,t,e,o){let i=n.cleanup;if(i!=null)for(let r=0;rc?s[c]:null}typeof a=="string"&&(r+=2)}return null}function cM(n,t,e,o,i,r,a){let s=t.firstCreatePass?rg(t):null,c=ig(e),p=c.length;c.push(i,r),s&&s.push(o,n,p,(p+1)*(a?-1:1))}function yh(n,t,e,o,i){let r=null,a=null,s=null,c=!1,p=n.directiveToIndex.get(e.type);if(typeof p=="number"?r=p:[r,a,s]=p,a!==null&&s!==null&&n.hostDirectiveOutputs&&Object.hasOwn(n.hostDirectiveOutputs,o)){let f=n.hostDirectiveOutputs[o];for(let _=0;_=a&&C<=s)c=!0,ol(n,t,C,f[_+1],o,i);else if(C>s)break}}return Object.hasOwn(e.outputs,o)&&(c=!0,ol(n,t,r,o,o,i)),c}function ol(n,t,e,o,i,r){let a=t[e],s=t[K],p=s.data[e].outputs[o],_=a[p].subscribe(r);cM(n.index,s,t,i,r,_,!0)}function Rt(){c1()}function c1(){let n=Z(),t=Ne(),e=tt();if(t.firstCreatePass&&d1(t,e),e.controlDirectiveIndex===-1)return;An("NgSignalForms");let o=n[e.controlDirectiveIndex];t.data[e.controlDirectiveIndex].controlDef.create(o,new il(n,t,e))}function Ft(){l1()}function l1(){let n=Z(),t=Ne(),e=gi();if(e.controlDirectiveIndex===-1)return;let o=t.data[e.controlDirectiveIndex].controlDef,i=n[e.controlDirectiveIndex];o.update(i,new il(n,t,e))}var il=class{lView;tView;tNode;hasPassThrough;constructor(t,e,o){this.lView=t,this.tView=e,this.tNode=o,this.hasPassThrough=!!(o.flags&4096)}get customControl(){return this.tNode.customControlIndex!==-1?this.lView[this.tNode.customControlIndex]:void 0}get nativeElement(){return At(this.tNode,this.lView)}get descriptor(){return`<${this.tNode.value}>`}listenToCustomControlOutput(t,e){let o=this.tView.data[this.tNode.customControlIndex];yh(this.tNode,this.lView,o,t,fi(this.tNode,this.lView,e))}listenToCustomControlModel(t){let e=this.tNode.flags&1024?"valueChange":"checkedChange",o=this.tView.data[this.tNode.customControlIndex];yh(this.tNode,this.lView,o,e,fi(this.tNode,this.lView,t))}listenToDom(t,e){Rp(this.tNode,this.tView,this.lView,void 0,this.lView[we],t,e,fi(this.tNode,this.lView,e))}setInputOnDirectives(t,e){let o=this.tNode.inputs?.[t],i=this.tNode.hostDirectiveInputs?.[t];if(!o&&!i)return!1;let r=!1;if(o)for(let a of o){if(a===this.tNode.controlDirectiveIndex)continue;let s=this.tView.data[a],c=this.lView[a];hi(s,c,t,e),r=!0}if(i)for(let a=0;a0;){let i=o.shift();if(typeof i!="function"){for(let a in i.inputs)e[i.inputs[a]]=!0;let r=xh(i.directive);r!==null&&o.push(...r);continue}for(let r of i()){if(typeof r=="function")continue;if(r.inputs)for(let s=0;s1){t.flags|=4096;return}u1(n,t)}function u1(n,t){for(let e=t.directiveStart;e{let r=t.hostDirectiveInputs[o],a=t.hostDirectiveOutputs[o+"Change"];if(!r||!a)return!1;for(let s=0;s=h&&c<=P)return t.flags|=i,t.customControlIndex=C,!0}}}return!1};if(e("value",1024)||e("checked",2048))return}}function wh(n,t){return g1(n,t)&&p1(n,t+"Change")}function g1(n,t){return t in n.inputs}function p1(n,t){return t in n.outputs}var Wg=Symbol("BINDING");var Oi=new B("");function rl(n,t,e){let o=e?n.styles:null,i=e?n.classes:null,r=0;if(t!==null)for(let a=0;a0&&(e.directiveToIndex=new Map);for(let C=0;C0;){let e=n[--t];if(typeof e=="number"&&e<0)return e}return 0}function O1(n,t,e){if(e){if(t.exportAs)for(let o=0;o{let[e,o,i]=n[t],r={propName:e,templateName:t,isSignal:(o&Ol.SignalBased)!==0};return i&&(r.transform=i),r})}function S1(n){return Object.keys(n).map(t=>({propName:n[t],templateName:t}))}function k1(n,t,e){let o=t instanceof Le?t:t?.injector;return o&&n.getStandaloneInjector!==null&&(o=n.getStandaloneInjector(o)||o),o?new nl(e,o):e}function E1(n){let t=n.get(Ci,null);if(t===null)throw new z(407,!1);let e=n.get(aM,null),o=n.get(bn,null),i=n.get(Tn,null,{optional:!0});return{rendererFactory:t,sanitizer:e,changeDetectionScheduler:o,ngReflect:!1,tracingService:i}}function D1(n,t,e){let o=pM(n);return vC(t,o,o==="svg"?Qi:o==="math"?vc:e)}function I1(n){if((n&&"localName"in n&&typeof n.localName=="string"?n.localName:n?.tagName)?.toLowerCase()==="script")throw new z(905,!1)}function pM(n){return(n.selectors[0][0]||"div").toLowerCase()}var Ia=class{componentDef;ngModule;selector;componentType;ngContentSelectors;isBoundToModule;cachedInputs=null;cachedOutputs=null;get inputs(){return this.cachedInputs??=w1(this.componentDef.inputs),this.cachedInputs}get outputs(){return this.cachedOutputs??=S1(this.componentDef.outputs),this.cachedOutputs}constructor(t,e){this.componentDef=t,this.ngModule=e,this.componentType=t.type,this.selector=By(t.selectors),this.ngContentSelectors=t.ngContentSelectors??[],this.isBoundToModule=!!e}create(t,e,o,i,r,a,s){Ce(pe.DynamicComponentStart);let c=Y(null);try{let p=this.componentDef,f=k1(p,i||this.ngModule,t),_=E1(f),C=_.tracingService;return C&&C.componentCreate?C.componentCreate(sM(p),()=>this.createComponentRef(_,f,e,o,r,a,s)):this.createComponentRef(_,f,e,o,r,a,s)}finally{Y(c)}}createComponentRef(t,e,o,i,r,a,s){let c=this.componentDef,p=T1(i,c,a,r),f=t.rendererFactory.createRenderer(null,c),_=i?Mx(f,i,c.encapsulation,e):D1(c,f,s??null);I1(_);let C=e.get(Oi,null),h=A1(_,()=>e.get(Ue,null)??pp());C&&C.addHost(h);let P=a?.some(Dh)||r?.some(N=>typeof N!="function"&&N.bindings.some(Dh)),T=wp(null,p,null,512|FC(c),null,null,t,f,e,null,gC(_,e,!0));C&&gM&&h instanceof ShadowRoot&&kc(T,()=>{C.removeHost(h)}),T[He]=_,Ic(T);let A=null;try{let N=dM(He,T,2,"#host",()=>p.directiveRegistry,!0,0);wC(f,_,N),dr(_,T),$C(p,T,N),fC(p,N,T),uM(p,N),o!==void 0&&R1(N,this.ngContentSelectors,o),A=Gt(N.index,T),T[ze]=A[ze],Dp(p,T,null)}catch(N){throw A!==null&&Lg(A),Lg(T),N}finally{Ce(pe.DynamicComponentEnd),Tc()}return new al(this.componentType,T,!!P)}};function T1(n,t,e,o){let i=n?["ng-version","22.1.4"]:Hy(t.selectors[0]),r=null,a=null,s=0;if(e)for(let f of e)s+=f[Wg].requiredVars,f.create&&(f.targetIdx=0,(r??=[]).push(f)),f.update&&(f.targetIdx=0,(a??=[]).push(f));if(o)for(let f=0;f{if(e&1&&n)for(let o of n)o.create();if(e&2&&t)for(let o of t)o.update()}}function Dh(n){let t=n[Wg].kind;return t==="input"||t==="twoWay"}var al=class extends rM{_rootLView;_hasInputBindings;instance;hostView;changeDetectorRef;componentType;location;previousInputValues=null;_tNode;constructor(t,e,o){super(),this._rootLView=e,this._hasInputBindings=o,this._tNode=yc(e[K],He),this.location=pr(this._tNode,e),this.instance=Gt(this._tNode.index,e)[ze],this.hostView=this.changeDetectorRef=new So(e,void 0),this.componentType=t}setInput(t,e){this._hasInputBindings;let o=this._tNode;if(this.previousInputValues??=new Map,this.previousInputValues.has(t)&&Object.is(this.previousInputValues.get(t),e))return;let i=this._rootLView,r=Ep(o,i[K],i,t,e);this.previousInputValues.set(t,e);let a=Gt(o.index,i);Ip(a,1)}get injector(){return new xo(this._tNode,this._rootLView)}destroy(){this.hostView.destroy()}onDestroy(t){this.hostView.onDestroy(t)}};function R1(n,t,e){let o=n.projection=[];for(let i=0;i{class n{static __NG_ELEMENT_ID__=F1}return n})();function F1(){let n=tt();return fM(n,Z())}var Kg=class n extends vi{_lContainer;_hostTNode;_hostLView;constructor(t,e,o){super(),this._lContainer=t,this._hostTNode=e,this._hostLView=o}get element(){return pr(this._hostTNode,this._hostLView)}get injector(){return new xo(this._hostTNode,this._hostLView)}get parentInjector(){let t=dp(this._hostTNode,this._hostLView);if(Kh(t)){let e=Zc(t,this._hostLView),o=Yc(t),i=e[K].data[o+8];return new xo(i,e)}else return new xo(null,this._hostLView)}clear(){for(;this.length>0;)this.remove(this.length-1)}get(t){let e=Ih(this._lContainer);return e!==null&&e[t]||null}get length(){return this._lContainer.length-Ve}createEmbeddedView(t,e,o){let i,r;typeof o=="number"?i=o:o!=null&&(i=o.index,r=o.injector);let a=qg(this._lContainer,t.ssrId),s=t.createEmbeddedViewImpl(e||{},r,a);return this.insertImpl(s,i,ka(this._hostTNode,a)),s}createComponent(t,e,o,i,r,a,s){let c,p=e||{};c=p.index,o=p.injector,i=p.projectableNodes,r=p.environmentInjector||p.ngModuleRef,a=p.directives,s=p.bindings;let f=new Ia(ii(t)),_=o||this.parentInjector;if(!r&&f.ngModule==null){let N=this.parentInjector.get(Le,null);N&&(r=N)}let C=ii(f.componentType??{}),h=qg(this._lContainer,C?.id??null),P=h?.firstChild??null,T=f.create(_,i,P,r,a,s,this._getHostElementNamespace());return this.insertImpl(T.hostView,c,ka(this._hostTNode,h)),T}_getHostElementNamespace(){if(this._hostTNode.type&2){let t=this._hostTNode.parent??this._hostLView[yt];return t!==null&&t.type&2&&typeof t.value=="string"&&t.value.toLowerCase()==="foreignobject"?null:t?.namespace??null}return this._hostTNode.namespace}insert(t,e){return this.insertImpl(t,e,!0)}insertImpl(t,e,o){let i=t._lView;if(D_(i)){let s=this.indexOf(t);if(s!==-1)this.detach(s);else{let c=i[Xe],p=new n(c,c[yt],c[Xe]);p.detach(p.indexOf(t))}}let r=this._adjustIndex(e),a=this._lContainer;return yl(a,i,r,o),t.attachToViewContainerRef(),Gu(xg(a),r,t),t}move(t,e){return this.insert(t,e)}indexOf(t){let e=Ih(this._lContainer);return e!==null?e.indexOf(t):-1}remove(t){let e=this._adjustIndex(t,-1),o=Da(this._lContainer,e);o&&(da(xg(this._lContainer),e),bl(o[K],o))}detach(t){let e=this._adjustIndex(t,-1),o=Da(this._lContainer,e);return o&&da(xg(this._lContainer),e)!=null?new So(o):null}_adjustIndex(t,e=0){return t??this.length+e}};function Ih(n){return n[fa]}function xg(n){return n[fa]||(n[fa]=[])}function fM(n,t){let e,o=t[n.index];return Ut(o)?e=o:(e=eM(o,t,null,n),t[n.index]=e,Sp(t,e)),V1(e,t,n,o),new Kg(e,n,t)}function L1(n,t){let e=n[we],o=e.createComment(""),i=At(t,n),r=e.parentNode(i);return pi(e,r,o,e.nextSibling(i),!1),o}var V1=z1,j1=()=>!1;function $1(n,t,e){return j1(n,t,e)}function z1(n,t,e,o){if(n[ci])return;let i;e.type&8?i=dt(o):i=L1(t,e),n[ci]=i}var Yg=class n{queryList;matches=null;constructor(t){this.queryList=t}clone(){return new n(this.queryList)}setDirty(){this.queryList.setDirty()}},Zg=class n{queries;constructor(t=[]){this.queries=t}createEmbeddedView(t){let e=t.queries;if(e!==null){let o=t.contentQueries!==null?t.contentQueries[0]:e.length,i=[];for(let r=0;r0)o.push(a[s/2]);else{let p=r[s+1],f=t[-c];for(let _=Ve;_t.trim())}function hM(n,t,e){n.queries===null&&(n.queries=new Qg),n.queries.track(new Jg(t,e))}function Z1(n,t){let e=n.contentQueries||(n.contentQueries=[]),o=e.length?e[e.length-1]:-1;t!==o&&e.push(n.queries.length-1,t)}function Fp(n,t){return n.queries.getByIndex(t)}function Q1(n,t){let e=n[K],o=Fp(e,t);return o.crossesNgTemplate?Xg(e,n,t,[]):mM(e,n,o,t)}function Eo(n){return!!n&&typeof n.then=="function"}function Lp(n){return!!n&&typeof n.subscribe=="function"}var Mi=class{},wl=class{};var cl=class extends Mi{ngModuleType;_parent;_bootstrapComponents=[];_r3Injector;instance;destroyCbs=[];constructor(t,e,o,i=!0){super(),this.ngModuleType=t,this._parent=e;let r=p_(t);this._bootstrapComponents=Ty(r.bootstrap),this._r3Injector=hg(t,e,[{provide:Mi,useValue:this},...o],aa(t),new Set(["environment"])),i&&this.resolveInjectorInitializers()}resolveInjectorInitializers(){this._r3Injector.resolveInjectorInitializers(),this.instance=this._r3Injector.get(this.ngModuleType)}get injector(){return this._r3Injector}destroy(){let t=this._r3Injector;!t.destroyed&&t.destroy(),this.destroyCbs.forEach(e=>e()),this.destroyCbs=null}onDestroy(t){this.destroyCbs.push(t)}},ll=class extends wl{moduleType;constructor(t){super(),this.moduleType=t}create(t){return new cl(this.moduleType,t,[])}};var Ta=class extends Mi{injector;instance=null;constructor(t){super();let e=new ni([...t.providers,{provide:Mi,useValue:this}],t.parent||pa(),t.debugName,new Set(["environment"]));this.injector=e,t.runEnvironmentInitializers&&e.resolveInjectorInitializers()}destroy(){this.injector.destroy()}onDestroy(t){this.injector.onDestroy(t)}};function Va(n,t,e=null){return new Ta({providers:n,parent:t,debugName:e,runEnvironmentInitializers:!0}).injector}var J1=(()=>{class n{_injector;cachedInjectors=new Map;constructor(e){this._injector=e}getOrCreateStandaloneInjector(e){if(!e.standalone)return null;if(!this.cachedInjectors.has(e)){let o=Wu(!1,e.type),i=o.length>0?Va([o],this._injector,""):null;this.cachedInjectors.set(e,i)}return this.cachedInjectors.get(e)}ngOnDestroy(){try{for(let e of this.cachedInjectors.values())e!==null&&e.destroy()}finally{this.cachedInjectors.clear()}}static \u0275prov=te({token:n,providedIn:"environment",factory:()=>new n(Q(Le))})}return n})();function Ge(n){return Na(()=>{let t=CM(n),e=F(S({},t),{decls:n.decls,vars:n.vars,template:n.template,consts:n.consts||null,ngContentSelectors:n.ngContentSelectors,onPush:n.changeDetection!==up.Eager,directiveDefs:null,pipeDefs:null,dependencies:t.standalone&&n.dependencies||null,getStandaloneInjector:t.standalone?i=>i.get(J1).getOrCreateStandaloneInjector(e):null,getExternalStyles:null,signals:n.signals??!1,data:n.data||{},encapsulation:n.encapsulation||un.Emulated,styles:n.styles||ht,_:null,schemas:n.schemas||null,tView:null,id:""});t.standalone&&An("NgStandalone"),MM(e);let o=n.dependencies;return e.directiveDefs=Th(o,X1),e.pipeDefs=Th(o,f_),e.id=nw(e),e})}function X1(n){return ii(n)||Bu(n)}function Jn(n){return Na(()=>({type:n.type,bootstrap:n.bootstrap||ht,declarations:n.declarations||ht,imports:n.imports||ht,exports:n.exports||ht,transitiveCompileScopes:null,schemas:n.schemas||null,id:n.id||null}))}function ew(n,t){if(n==null)return Mo;let e={};for(let o in n)if(Object.hasOwn(n,o)){let i=n[o],r,a,s,c;Array.isArray(i)?(s=i[0],r=i[1],a=i[2]??r,c=i[3]||null):(r=i,a=i,s=Ol.None,c=null),e[r]=[o,s,c],t[r]=a}return e}function tw(n){if(n==null)return Mo;let t={};for(let e in n)Object.hasOwn(n,e)&&(t[n[e]]=e);return t}function qe(n){return Na(()=>{let t=CM(n);return MM(t),t})}function Sl(n){return{type:n.type,name:n.name,factory:null,pure:n.pure!==!1,standalone:n.standalone??!0,onDestroy:n.type.prototype.ngOnDestroy||null}}function CM(n){let t={};return{type:n.type,providersResolver:null,viewProvidersResolver:null,factory:null,hostBindings:n.hostBindings||null,hostVars:n.hostVars||0,hostAttrs:n.hostAttrs||null,contentQueries:n.contentQueries||null,declaredInputs:t,inputConfig:n.inputs||Mo,exportAs:n.exportAs||null,standalone:n.standalone??!0,signals:n.signals===!0,selectors:n.selectors||ht,viewQuery:n.viewQuery||null,features:n.features||null,setInput:null,resolveHostDirectives:null,hostDirectives:null,controlDef:null,signalFormsInputPresence:null,inputs:ew(n.inputs,t),outputs:tw(n.outputs),debugInfo:null}}function MM(n){n.features?.forEach(t=>t(n))}function Th(n,t){return n?()=>{let e=typeof n=="function"?n():n,o=[];for(let i of e){let r=t(i);r!==null&&o.push(r)}return o}:null}function nw(n){let t=0,e=typeof n.consts=="function"?"":n.consts,o=[n.selectors,n.ngContentSelectors,n.hostVars,n.hostAttrs,e,n.vars,n.decls,n.encapsulation,n.standalone,n.signals,n.exportAs,JSON.stringify(n.inputs),JSON.stringify(n.outputs),Object.getOwnPropertyNames(n.type.prototype),!!n.contentQueries,!!n.viewQuery];for(let r of o.join("|"))t=Math.imul(31,t)+r.charCodeAt(0)<<0;return t+=2147483648,"c"+t}var bM=new B("");var Vp=(()=>{class n{resolve;reject;initialized=!1;done=!1;donePromise=new Promise((e,o)=>{this.resolve=e,this.reject=o});appInits=D(bM,{optional:!0})??[];injector=D(Ct);constructor(){}runInitializers(){if(this.initialized)return;let e=[];for(let i of this.appInits){let r=et(this.injector,i);if(Eo(r))e.push(r);else if(Lp(r)){let a=new Promise((s,c)=>{r.subscribe({complete:s,error:c})});e.push(a)}}let o=()=>{this.done=!0,this.resolve()};Promise.all(e).then(()=>{o()}).catch(i=>{this.reject(i)}),e.length===0&&o(),this.initialized=!0}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})();function jp(n){return t=>{t.controlDef={create:(e,o)=>{e?.\u0275ngControlCreate(o)},update:(e,o)=>{e?.\u0275ngControlUpdate?.(o)},passThroughInput:n}}}function ow(n){return Object.getPrototypeOf(n.prototype).constructor}function gn(n){let t=ow(n.type),e=!0,o=[n];for(;t&&t!==Function.prototype&&t!==Object.prototype;){let i,r=Object.hasOwn(t,ca)?t[ca]:void 0,a=Object.hasOwn(t,la)?t[la]:void 0;if(wn(n))i=r??a;else{if(r)throw new z(903,!1);i=a}if(i){if(e){o.push(i);let c=n;c.inputs=wg(n.inputs),c.declaredInputs=wg(n.declaredInputs),c.outputs=wg(n.outputs);let p=i.hostBindings;p&&cw(n,p);let f=i.viewQuery,_=i.contentQueries;if(f&&aw(n,f),_&&sw(n,_),iw(n,i),g_(n.outputs,i.outputs),wn(i)&&i.data.animation){let C=n.data;C.animation=(C.animation||[]).concat(i.data.animation)}}let s=i.features;if(s)for(let c=0;c=0;o--){let i=n[o];i.hostVars=t+=i.hostVars,i.hostAttrs=lr(i.hostAttrs,e=lr(e,i.hostAttrs))}}function wg(n){return n===Mo?{}:n===ht?[]:n}function aw(n,t){let e=n.viewQuery;e?n.viewQuery=(o,i)=>{t(o,i),e(o,i)}:n.viewQuery=t}function sw(n,t){let e=n.contentQueries;e?n.contentQueries=(o,i,r)=>{t(o,i,r),e(o,i,r)}:n.contentQueries=t}function cw(n,t){let e=n.hostBindings;e?n.hostBindings=(o,i)=>{t(o,i),e(o,i)}:n.hostBindings=t}function lw(n,t,e,o,i,r,a,s){if(e.firstCreatePass){n.mergedAttrs=lr(n.mergedAttrs,n.attrs);let f=n.tView=xp(2,n,i,r,a,e.directiveRegistry,e.pipeRegistry,null,e.schemas,e.consts,null);e.queries!==null&&(e.queries.template(e,n),f.queries=e.queries.embeddedTView(n))}s&&(n.flags|=s),or(n,!1);let c=dw(e,t,n,o);Ac()&&vp(e,t,c,n),dr(c,t);let p=eM(c,t,c,n);t[o+He]=p,Sp(t,p),$1(p,n,t)}function dl(n,t,e,o,i,r,a,s,c,p,f){let _=e+He,C;if(t.firstCreatePass){if(C=xl(t,_,4,a||null,s||null),p!=null){let h=Sn(t.consts,p);C.localNames=[];for(let P=0;P{class n{log(e){console.log(e)}warn(e){console.warn(e)}static \u0275fac=function(o){return new(o||n)};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"platform"})}return n})();var zp=new B("");var kl=new B("");function PM(){ou(()=>{let n="";throw new z(600,n)})}var gw=10;var Xn=(()=>{class n{_runningTick=!1;_destroyed=!1;_destroyListeners=[];_views=[];internalErrorHandler=D(Nt);afterRenderManager=D(bp);zonelessEnabled=D(ar);rootEffectScheduler=D(Vc);dirtyFlags=0;tracingSnapshot=null;allTestViews=new Set;autoDetectTestViews=new Set;includeAllTestViews=!1;afterTick=new ye;get allViews(){return[...(this.includeAllTestViews?this.allTestViews:this.autoDetectTestViews).keys(),...this._views]}get destroyed(){return this._destroyed}componentTypes=[];components=[];internalPendingTask=D(kn);get isStable(){return this.internalPendingTask.hasPendingTasksObservable.pipe(Pe(e=>!e))}constructor(){D(Tn,{optional:!0})}whenStable(){let e;return new Promise(o=>{e=this.isStable.subscribe({next:i=>{i&&o()}})}).finally(()=>{e.unsubscribe()})}_injector=D(Le);_rendererFactory=null;get injector(){return this._injector}bootstrap(e,o){return this.bootstrapImpl(e,o)}bootstrapImpl(e,o,i=Ct.NULL){return this._injector.get(ge).run(()=>{if(Ce(pe.BootstrapComponentStart),!this._injector.get(Vp).done){let N="";throw new z(405,N)}let s=ii(e),c=this._injector.get(Mi),p=new Ia(s,c);this.componentTypes.push(e);let{hostElement:f,directives:_,bindings:C}=pw(o),h=f||p.selector,P=p.create(i,[],h,c.injector,_,C),T=P.location.nativeElement,A=P.injector.get(zp,null);return A?.registerApplication(T),P.onDestroy(()=>{this.detachView(P.hostView),wa(this.components,P),A?.unregisterApplication(T)}),this._loadComponent(P),Ce(pe.BootstrapComponentEnd,P),P})}tick(){this.zonelessEnabled||(this.dirtyFlags|=1),this._tick()}_tick(){Ce(pe.ChangeDetectionStart),this.tracingSnapshot!==null?this.tracingSnapshot.run(Cl.CHANGE_DETECTION,this.tickImpl):this.tickImpl()}tickImpl=()=>{if(this._runningTick)throw Ce(pe.ChangeDetectionEnd),new z(101,!1);let e=Y(null);try{this._runningTick=!0,this.synchronize()}finally{this._runningTick=!1,this.tracingSnapshot?.dispose(),this.tracingSnapshot=null,Y(e),this.afterTick.next(),Ce(pe.ChangeDetectionEnd)}};synchronize(){this._rendererFactory===null&&!this._injector.destroyed&&(this._rendererFactory=this._injector.get(Ci,null,{optional:!0}));let e=0;for(;this.dirtyFlags!==0&&e++ma(e))){this.dirtyFlags|=2;return}else this.dirtyFlags&=-8}attachView(e){let o=e;this._views.push(o),o.attachToAppRef(this)}detachView(e){let o=e;wa(this._views,o),o.detachFromAppRef()}_loadComponent(e){this.attachView(e.hostView);try{this.tick()}catch(i){this.internalErrorHandler(i)}this.components.push(e),this._injector.get(kl,[]).forEach(i=>i(e))}ngOnDestroy(){if(!this._destroyed)try{this._destroyListeners.forEach(e=>e()),this._views.slice().forEach(e=>e.destroy())}finally{this._destroyed=!0,this._views=[],this._destroyListeners=[]}}onDestroy(e){return this._destroyListeners.push(e),()=>wa(this._destroyListeners,e)}destroy(){if(this._destroyed)throw new z(406,!1);let e=this._injector;e.destroy&&!e.destroyed&&e.destroy()}get viewCount(){return this._views.length}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})();function pw(n){return n===void 0||typeof n=="string"||n instanceof Element?{hostElement:n}:n}function wa(n,t){let e=n.indexOf(t);e>-1&&n.splice(e,1)}function Wt(n,t,e,o){let i=Z(),r=Zn();if(St(i,r,t)){let a=Ne(),s=gi();kx(s,i,n,t,e,o)}return Wt}function De(){return Z()[xt][ze]}var ep=class{destroy(t){}updateValue(t,e){}swap(t,e){let o=Math.min(t,e),i=Math.max(t,e),r=this.detach(i);if(i-o>1){let a=this.detach(o);this.attach(o,r),this.attach(i,a)}else this.attach(o,r)}move(t,e){this.attach(e,this.detach(t))}};function Sg(n,t,e,o,i){return n===e&&Object.is(t,o)?1:Object.is(i(n,t),i(e,o))?-1:0}function fw(n,t,e,o){let i,r,a=0,s=n.length-1,c=void 0;if(Array.isArray(t)){Y(o);let p=t.length-1;for(Y(null);a<=s&&a<=p;){let f=n.at(a),_=t[a],C=Sg(a,f,a,_,e);if(C!==0){C<0&&n.updateValue(a,_),a++;continue}let h=n.at(s),P=t[p],T=Sg(s,h,p,P,e);if(T!==0){T<0&&n.updateValue(s,P),s--,p--;continue}let A=e(a,f),N=e(s,h),E=e(a,_);if(Object.is(E,N)){let U=e(p,P);Object.is(U,A)?(n.swap(a,s),n.updateValue(s,P),p--,s--):n.move(s,a),n.updateValue(a,_),a++;continue}if(i??=new ul,r??=Nh(n,a,s,e),tp(n,i,a,E))n.updateValue(a,_),a++,s++;else if(r.has(E))i.set(A,n.detach(a)),s--;else{let U=n.create(a,t[a]);n.attach(a,U),a++,s++}}for(;a<=p;)Ah(n,i,e,a,t[a]),a++}else if(t!=null){Y(o);let p=t[Symbol.iterator]();Y(null);let f=p.next();for(;!f.done&&a<=s;){let _=n.at(a),C=f.value,h=Sg(a,_,a,C,e);if(h!==0)h<0&&n.updateValue(a,C),a++,f=p.next();else{i??=new ul,r??=Nh(n,a,s,e);let P=e(a,C);if(tp(n,i,a,P))n.updateValue(a,C),a++,s++,f=p.next();else if(!r.has(P))n.attach(a,n.create(a,C)),a++,s++,f=p.next();else{let T=e(a,_);i.set(T,n.detach(a)),s--}}}for(;!f.done;)Ah(n,i,e,n.length,f.value),f=p.next()}for(;a<=s;)n.destroy(n.detach(s--));i?.forEach(p=>{n.destroy(p)})}function tp(n,t,e,o){return t!==void 0&&t.has(o)?(n.attach(e,t.get(o)),t.delete(o),!0):!1}function Ah(n,t,e,o,i){if(tp(n,t,o,e(o,i)))n.updateValue(o,i);else{let r=n.create(o,i);n.attach(o,r)}}function Nh(n,t,e,o){let i=new Set;for(let r=t;r<=e;r++)i.add(o(r,n.at(r)));return i}var ul=class{kvMap=new Map;_vMap=void 0;has(t){return this.kvMap.has(t)}delete(t){if(!this.has(t))return!1;let e=this.kvMap.get(t);return this._vMap!==void 0&&this._vMap.has(e)?(this.kvMap.set(t,this._vMap.get(e)),this._vMap.delete(e)):this.kvMap.delete(t),!0}get(t){return this.kvMap.get(t)}set(t,e){if(this.kvMap.has(t)){let o=this.kvMap.get(t);this._vMap===void 0&&(this._vMap=new Map);let i=this._vMap;for(;i.has(o);)o=i.get(o);i.set(o,e)}else this.kvMap.set(t,e)}forEach(t){for(let[e,o]of this.kvMap)if(t(o,e),this._vMap!==void 0){let i=this._vMap;for(;i.has(o);)o=i.get(o),t(o,e)}}};function M(n,t,e,o,i,r,a,s){An("NgControlFlow");let c=Z(),p=Ne(),f=Sn(p.consts,r);return dl(c,p,n,t,e,o,i,f,256,a,s),Bp}function Bp(n,t,e,o,i,r,a,s){An("NgControlFlow");let c=Z(),p=Ne(),f=Sn(p.consts,r);return dl(c,p,n,t,e,o,i,f,512,a,s),Bp}function b(n,t){An("NgControlFlow");let e=Z(),o=Zn(),i=e[o]!==ot?e[o]:-1,r=i!==-1?gl(e,He+i):void 0,a=0;if(St(e,o,n)){let s=Y(null);try{if(r!==void 0&&nM(r,a),n!==-1){let c=He+n,p=gl(e,c),f=rp(e[K],c),_=iM(p,f,e),C=vl(e,f,t,{dehydratedView:_});yl(p,C,a,ka(f,_))}}finally{Y(s)}}else if(r!==void 0){let s=tM(r,a);s!==void 0&&(s[ze]=t)}}var np=class{lContainer;$implicit;$index;constructor(t,e,o){this.lContainer=t,this.$implicit=e,this.$index=o}get $count(){return this.lContainer.length-Ve}};function Do(n){return n}function Ie(n,t){return t}var op=class{hasEmptyBlock;trackByFn;liveCollection;constructor(t,e,o){this.hasEmptyBlock=t,this.trackByFn=e,this.liveCollection=o}};function G(n,t,e,o,i,r,a,s,c,p,f,_,C){An("NgControlFlow");let h=Z(),P=Ne(),T=c!==void 0,A=Z(),N=s?a.bind(A[xt][ze]):a,E=new op(T,N);A[He+n]=E,dl(h,P,n+1,t,e,o,i,Sn(P.consts,r),256),T&&dl(h,P,n+2,c,p,f,_,Sn(P.consts,C),512)}var ip=class extends ep{lContainer;hostLView;templateTNode;operationsCounter=void 0;needsIndexUpdate=!1;constructor(t,e,o){super(),this.lContainer=t,this.hostLView=e,this.templateTNode=o}get length(){return this.lContainer.length-Ve}at(t){return this.getLView(t)[ze].$implicit}attach(t,e){let o=e[Xi];this.needsIndexUpdate||=t!==this.length,yl(this.lContainer,e,t,ka(this.templateTNode,o)),mw(this.lContainer,t)}detach(t){return this.needsIndexUpdate||=t!==this.length-1,_w(this.lContainer,t),hw(this.lContainer,t)}create(t,e){let o=qg(this.lContainer,this.templateTNode.tView.ssrId);return vl(this.hostLView,this.templateTNode,new np(this.lContainer,e,t),{dehydratedView:o})}destroy(t){bl(t[K],t)}updateValue(t,e){this.getLView(t)[ze].$implicit=e}reset(){this.needsIndexUpdate=!1}updateIndexes(){if(this.needsIndexUpdate)for(let t=0;t0){let r=o[On];Zy(r,i),wo.delete(o[yn]),i.detachedLeaveAnimationFns=void 0}}function _w(n,t){if(n.length<=Ve)return;let e=Ve+t,o=n[e],i=o?o[xn]:void 0;i&&i.leave&&i.leave.size>0&&(i.detachedLeaveAnimationFns=[])}function hw(n,t){return Da(n,t)}function Cw(n,t){return tM(n,t)}function rp(n,t){return yc(n,t)}function R(n,t,e){let o=Z(),i=Zn();if(St(o,i,t)){let r=Ne(),a=gi();zC(a,o,n,t,o[we],e)}return R}function ap(n,t,e,o,i){Ep(t,n,e,i?"class":"style",o)}function l(n,t,e,o){let i=Z(),r=i[K],a=n+He,s=r.firstCreatePass?dM(a,i,2,t,Sx,F_(),e,o):r.data[a];if(Yn(s)){let c=i[cn].tracingService;if(c&&c.componentCreate){let p=r.data[s.directiveStart+s.componentOffset];return c.componentCreate(sM(p),()=>(Rh(n,t,i,s,o),l))}}return Rh(n,t,i,s,o),l}function Rh(n,t,e,o,i){if(HC(o,e,n,t,OM),Oc(o)){let r=e[K];$C(r,e,o),fC(r,o,e)}i!=null&&kp(e,o)}function d(){let n=Ne(),t=tt(),e=UC(t);return n.firstCreatePass&&uM(n,e),sg(e)&&cg(),ag(),e.classesWithoutHost!=null&&Vv(e)&&ap(n,e,Z(),e.classesWithoutHost,!0),e.stylesWithoutHost!=null&&jv(e)&&ap(n,e,Z(),e.stylesWithoutHost,!1),d}function $(n,t,e,o){return l(n,t,e,o),d(),$}function j(n,t,e,o){let i=Z(),r=i[K],a=n+He,s=r.firstCreatePass?y1(a,r,2,t,e,o):r.data[a];return HC(s,i,n,t,OM),o!=null&&kp(i,s),j}function H(){let n=tt(),t=UC(n);return sg(t)&&cg(),ag(),H}function yi(n,t,e,o){return j(n,t,e,o),H(),yi}var OM=(n,t,e,o,i)=>(Nc(!0),vC(t[we],o,_g()));function L(){return Z()}function je(n,t,e){let o=Z(),i=Zn();if(St(o,i,t)){let r=Ne(),a=gi();BC(a,o,n,t,o[we],e)}return je}var va=void 0;function Mw(n){let t=Math.floor(Math.abs(n)),e=n.toString().replace(/^[^.]*\.?/,"").length;return t===1&&e===0?1:5}var bw=["en",[["a","p"],["AM","PM"]],[["AM","PM"]],[["S","M","T","W","T","F","S"],["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],["Su","Mo","Tu","We","Th","Fr","Sa"]],va,[["J","F","M","A","M","J","J","A","S","O","N","D"],["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],["January","February","March","April","May","June","July","August","September","October","November","December"]],va,[["B","A"],["BC","AD"],["Before Christ","Anno Domini"]],0,[6,0],["M/d/yy","MMM d, y","MMMM d, y","EEEE, MMMM d, y"],["h:mm\u202Fa","h:mm:ss\u202Fa","h:mm:ss\u202Fa z","h:mm:ss\u202Fa zzzz"],["{1}, {0}",va,va,va],[".",",",";","%","+","-","E","\xD7","\u2030","\u221E","NaN",":"],["#,##0.###","#,##0%","\xA4#,##0.00","#E0"],"USD","$","US Dollar",{},"ltr",Mw],kg=Object.create(null);function Lt(n){let t=Pw(n),e=Fh(t);if(e)return e;let o=t.split("-")[0];if(e=Fh(o),e)return e;if(o==="en")return bw;throw new z(701,!1)}function Fh(n){if(!(n in kg)){let t=an.ng&&an.ng.common&&an.ng.common.locales&&an.ng.common.locales[n];return t!==void 0&&(kg[n]=t),t}return kg[n]}var Ze={LocaleId:0,DayPeriodsFormat:1,DayPeriodsStandalone:2,DaysFormat:3,DaysStandalone:4,MonthsFormat:5,MonthsStandalone:6,Eras:7,FirstDayOfWeek:8,WeekendRange:9,DateFormat:10,TimeFormat:11,DateTimeFormat:12,NumberSymbols:13,NumberFormats:14,CurrencyCode:15,CurrencySymbol:16,CurrencyName:17,Currencies:18,Directionality:19,PluralCase:20,ExtraData:21};function Pw(n){return n.toLowerCase().replace(/_/g,"-")}var ja="en-US";var Ow=ja;function vM(n){typeof n=="string"&&(Ow=n.toLowerCase().replace(/_/g,"-"))}function k(n,t,e){let o=Z(),i=Ne(),r=tt();return yM(i,o,o[we],r,n,t,e),k}function ue(n,t,e){let o=Z(),i=Ne(),r=tt();return(r.type&3||e)&&Rp(r,i,o,e,o[we],n,t,fi(r,o,t)),ue}function yM(n,t,e,o,i,r,a){let s=!0,c=null;if((o.type&3||a)&&(c??=fi(o,t,r),Rp(o,n,t,a,e,i,r,c)&&(s=!1)),s){let p=o.outputs?.[i],f=o.hostDirectiveOutputs?.[i];if(f&&f.length)for(let _=0;_>17&32767}function vw(n){return(n&2)==2}function yw(n,t){return n&131071|t<<17}function sp(n){return n|2}function gr(n){return(n&131068)>>2}function Eg(n,t){return n&-131069|t<<2}function xw(n){return(n&1)===1}function cp(n){return n|1}function ww(n,t,e,o,i,r){let a=r?t.classBindings:t.styleBindings,s=bi(a),c=gr(a);n[o]=e;let p=!1,f;if(Array.isArray(e)){let _=e;f=_[1],(f===null||Ji(_,f)>0)&&(p=!0)}else f=e;if(i)if(c!==0){let C=bi(n[s+1]);n[o+1]=Hc(C,s),C!==0&&(n[C+1]=Eg(n[C+1],o)),n[s+1]=yw(n[s+1],o)}else n[o+1]=Hc(s,0),s!==0&&(n[s+1]=Eg(n[s+1],o)),s=o;else n[o+1]=Hc(c,0),s===0?s=o:n[c+1]=Eg(n[c+1],o),c=o;p&&(n[o+1]=sp(n[o+1])),Lh(n,f,o,!0),Lh(n,f,o,!1),Sw(t,f,n,o,r),a=Hc(s,c),r?t.classBindings=a:t.styleBindings=a}function Sw(n,t,e,o,i){let r=i?n.residualClasses:n.residualStyles;r!=null&&typeof t=="string"&&Ji(r,t)>=0&&(e[o+1]=cp(e[o+1]))}function Lh(n,t,e,o){let i=n[e+1],r=t===null,a=o?bi(i):gr(i),s=!1;for(;a!==0&&(s===!1||r);){let c=n[a],p=n[a+1];kw(c,t)&&(s=!0,n[a+1]=o?cp(p):sp(p)),a=o?bi(p):gr(p)}s&&(n[e+1]=o?sp(i):cp(i))}function kw(n,t){return n===null||t==null||(Array.isArray(n)?n[1]:n)===t?!0:Array.isArray(n)&&typeof t=="string"?Ji(n,t)>=0:!1}var dn={textEnd:0,key:0,keyEnd:0,value:0,valueEnd:0};function Ew(n){return n.substring(dn.key,dn.keyEnd)}function Dw(n){return Iw(n),xM(n,wM(n,0,dn.textEnd))}function xM(n,t){let e=dn.textEnd;return e===t?-1:(t=dn.keyEnd=Tw(n,dn.key=t,e),wM(n,t,e))}function Iw(n){dn.key=0,dn.keyEnd=0,dn.value=0,dn.valueEnd=0,dn.textEnd=n.length}function wM(n,t,e){for(;t32;)t++;return t}function Se(n,t,e){return SM(n,t,e,!1),Se}function w(n,t){return SM(n,t,null,!0),w}function Dl(n){Nw($w,Aw,n,!0)}function Aw(n,t){for(let e=Dw(t);e>=0;e=xM(t,e))Mc(n,Ew(t),!0)}function SM(n,t,e,o){let i=Z(),r=Ne(),a=_a(2);if(r.firstUpdatePass&&EM(r,n,a,o),t!==ot&&St(i,a,t)){let s=r.data[qt()];DM(r,s,i,i[we],n,i[a+1]=Bw(t,e),o,a)}}function Nw(n,t,e,o){let i=Ne(),r=_a(2);i.firstUpdatePass&&EM(i,null,r,o);let a=Z();if(e!==ot&&St(a,r,e)){let s=i.data[qt()];if(IM(s,o)&&!kM(i,r)){let c=o?s.classesWithoutHost:s.stylesWithoutHost;c!==null&&(e=fc(c,e||"")),ap(i,s,a,e,o)}else zw(i,s,a,a[we],a[r+1],a[r+1]=jw(n,t,e),o,r)}}function kM(n,t){return t>=n.expandoStartIndex}function EM(n,t,e,o){let i=n.data;if(i[e+1]===null){let r=i[qt()],a=kM(n,e);IM(r,o)&&t===null&&!a&&(t=!1),t=Rw(i,r,t,o),ww(i,r,t,e,a,o)}}function Rw(n,t,e,o){let i=G_(n),r=o?t.residualClasses:t.residualStyles;if(i===null)(o?t.classBindings:t.styleBindings)===0&&(e=Dg(null,n,t,e,o),e=Aa(e,t.attrs,o),r=null);else{let a=t.directiveStylingLast;if(a===-1||n[a]!==i)if(e=Dg(i,n,t,e,o),r===null){let c=Fw(n,t,o);c!==void 0&&Array.isArray(c)&&(c=Dg(null,n,t,c[1],o),c=Aa(c,t.attrs,o),Lw(n,t,o,c))}else r=Vw(n,t,o)}return r!==void 0&&(o?t.residualClasses=r:t.residualStyles=r),e}function Fw(n,t,e){let o=e?t.classBindings:t.styleBindings;if(gr(o)!==0)return n[bi(o)]}function Lw(n,t,e,o){let i=e?t.classBindings:t.styleBindings;n[bi(i)]=o}function Vw(n,t,e){let o,i=t.directiveEnd;for(let r=1+t.directiveStylingLast;r0;){let c=n[i],p=Array.isArray(c),f=p?c[1]:c,_=f===null,C=e[i+1];C===ot&&(C=_?ht:void 0);let h=_?bc(C,o):f===o?C:void 0;if(p&&!pl(h)&&(h=bc(c,o)),pl(h)&&(s=h,a))return s;let P=n[i+1];i=a?bi(P):gr(P)}if(t!==null){let c=r?t.residualClasses:t.residualStyles;c!=null&&(s=bc(c,o))}return s}function pl(n){return n!==void 0}function Bw(n,t){return n==null||n===""||(typeof t=="string"?n=_i(n)+t:typeof n=="object"&&(n=aa(_i(n)))),n}function IM(n,t){return(n.flags&(t?8:16))!==0}function u(n,t=""){let e=Z(),o=Ne(),i=n+He,r=o.firstCreatePass?xl(o,i,1,t,null):o.data[i],a=Hw(o,e,r,t);e[i]=a,Ac()&&vp(o,e,a,r),or(r,!1)}var Hw=(n,t,e,o)=>(Nc(!0),xy(t[we],o));function Uw(n,t,e,o=""){return St(n,Zn(),e)?t+rn(e)+o:ot}function Gw(n,t,e,o,i,r=""){let a=gg(),s=Np(n,a,e,i);return _a(2),s?t+rn(e)+o+rn(i)+r:ot}function qw(n,t,e,o,i,r,a,s=""){let c=gg(),p=r1(n,c,e,i,a);return _a(3),p?t+rn(e)+o+rn(i)+r+rn(a)+s:ot}function O(n){return V("",n),O}function V(n,t,e){let o=Z(),i=Uw(o,n,t,e);return i!==ot&&Hp(o,qt(),i),V}function We(n,t,e,o,i){let r=Z(),a=Gw(r,n,t,e,o,i);return a!==ot&&Hp(r,qt(),a),We}function mr(n,t,e,o,i,r,a){let s=Z(),c=qw(s,n,t,e,o,i,r,a);return c!==ot&&Hp(s,qt(),c),mr}function Hp(n,t,e){let o=eg(t,n);wy(n[we],o,e)}function _r(n,t,e){jc(t)&&(t=t());let o=Z(),i=Zn();if(St(o,i,t)){let r=Ne(),a=gi();zC(a,o,n,t,o[we],e)}return _r}function $a(n,t){let e=jc(n);return e&&n.set(t),e}function hr(n,t){let e=Z(),o=Ne(),i=tt();return yM(o,e,e[we],i,n,t),hr}function xi(n){return St(Z(),Zn(),n)?rn(n):ot}function jh(n,t,e){let o=Ne();o.firstCreatePass&&TM(t,o.data,o.blueprint,wn(n),e)}function TM(n,t,e,o,i){if(n=lt(n),Array.isArray(n))for(let r=0;r>20;if(ti(n)||!n.multi){let h=new mi(p,i,le,null),P=Tg(c,t,i?f:f+C,_);P===-1?(Rg(Jc(s,a),r,c),Ig(r,n,t.length),t.push(c),s.directiveStart++,s.directiveEnd++,i&&(s.providerIndexes+=1048576),e.push(h),a.push(h)):(e[P]=h,a[P]=h)}else{let h=Tg(c,t,f+C,_),P=Tg(c,t,f,f+C),T=h>=0&&e[h],A=P>=0&&e[P];if(i&&!A||!i&&!T){Rg(Jc(s,a),r,c);let N=Yw(i?Kw:Ww,e.length,i,o,p,n);!i&&A&&(e[P].providerFactory=N),Ig(r,n,t.length,0),t.push(c),s.directiveStart++,s.directiveEnd++,i&&(s.providerIndexes+=1048576),e.push(N),a.push(N)}else{let N=AM(e[i?P:h],p,!i&&o);Ig(r,n,h>-1?h:P,N)}!i&&o&&A&&e[P].componentProviders++}}}function Ig(n,t,e,o){let i=ti(t),r=y_(t);if(i||r){let c=(r?lt(t.useClass):t).prototype.ngOnDestroy;if(c){let p=n.destroyHooks||(n.destroyHooks=[]);if(!i&&t.multi){let f=p.indexOf(e);f===-1?p.push(e,[o,c]):p[f+1].push(o,c)}else p.push(e,c)}}}function AM(n,t,e){return e&&n.componentProviders++,n.multi.push(t)-1}function Tg(n,t,e,o){for(let i=e;i{e.providersResolver=(o,i)=>jh(o,i?i(n):n,!1),t&&(e.viewProvidersResolver=(o,i)=>jh(o,i?i(t):t,!0))}}function za(n,t){let e=ir()+n,o=Z();return o[e]===ot?Ap(o,e,t()):i1(o,e)}function Up(n,t,e){return RM(Z(),ir(),n,t,e)}function Gp(n,t,e,o){return FM(Z(),ir(),n,t,e,o)}function NM(n,t){let e=n[t];return e===ot?void 0:e}function RM(n,t,e,o,i,r){let a=t+e;return St(n,a,i)?Ap(n,a+1,r?o.call(r,i):o(i)):NM(n,a+1)}function FM(n,t,e,o,i,r,a){let s=t+e;return Np(n,s,i,r)?Ap(n,s+2,a?o.call(a,i,r):o(i,r)):NM(n,s+2)}function it(n,t){let e=Ne(),o,i=n+He;e.firstCreatePass?(o=Zw(t,e.pipeRegistry),e.data[i]=o,o.onDestroy&&(e.destroyHooks??=[]).push(i,o.onDestroy)):o=e.data[i];let r=o.factory||(o.factory=Co(o.type,!0)),a,s=_t(le);try{let c=Qc(!1),p=r();return Qc(c),tg(e,Z(),i,p),p}finally{_t(s)}}function Zw(n,t){if(t)for(let e=t.length-1;e>=0;e--){let o=t[e];if(n===o.name)return o}}function wi(n,t,e){let o=n+He,i=Z(),r=xc(i,o);return LM(i,o)?RM(i,ir(),t,r.transform,e,r):r.transform(e)}function Et(n,t,e,o){let i=n+He,r=Z(),a=xc(r,i);return LM(r,i)?FM(r,ir(),t,a.transform,e,o,a):a.transform(e,o)}function LM(n,t){return n[K].data[t].pure}var VM=(()=>{class n{applicationErrorHandler=D(Nt);appRef=D(Xn);taskService=D(kn);ngZone=D(ge);zonelessEnabled=D(ar);tracing=D(Tn,{optional:!0});zoneIsDefined=typeof Zone<"u"&&!!Zone.root.run;schedulerTickApplyArgs=[{data:{__scheduler_tick__:!0}}];subscriptions=new Be;angularZoneId=this.zoneIsDefined?this.ngZone._inner?.get(ia):null;scheduleInRootZone=!this.zonelessEnabled&&this.zoneIsDefined&&(D(Lc,{optional:!0})??!1);cancelScheduledCallback=null;useMicrotaskScheduler=!1;runningTick=!1;pendingRenderTaskId=null;constructor(){this.subscriptions.add(this.appRef.afterTick.subscribe(()=>{let e=this.taskService.add();if(!this.runningTick&&(this.cleanup(),!this.zonelessEnabled||this.appRef.includeAllTestViews)){this.taskService.remove(e);return}this.switchToMicrotaskScheduler(),this.taskService.remove(e)})),this.subscriptions.add(this.ngZone.onUnstable.subscribe(()=>{this.runningTick||this.cleanup()}))}switchToMicrotaskScheduler(){this.ngZone.runOutsideAngular(()=>{let e=this.taskService.add();this.useMicrotaskScheduler=!0,queueMicrotask(()=>{this.useMicrotaskScheduler=!1,this.taskService.remove(e)})})}notify(e){if(!this.zonelessEnabled&&e===5)return;switch(e){case 0:case 2:{this.appRef.dirtyFlags|=2;break}case 3:case 4:case 5:case 1:{this.appRef.dirtyFlags|=4;break}case 6:{this.appRef.dirtyFlags|=2;break}case 12:{this.appRef.dirtyFlags|=16;break}case 13:{this.appRef.dirtyFlags|=2;break}case 11:break;default:this.appRef.dirtyFlags|=8}if(this.appRef.tracingSnapshot=this.tracing?.snapshot(this.appRef.tracingSnapshot)??null,!this.shouldScheduleTick())return;let o=this.useMicrotaskScheduler?J_:Mg;this.pendingRenderTaskId=this.taskService.add(),this.scheduleInRootZone?this.cancelScheduledCallback=Zone.root.run(()=>o(()=>this.tick())):this.cancelScheduledCallback=this.ngZone.runOutsideAngular(()=>o(()=>this.tick()))}shouldScheduleTick(){return!(this.appRef.destroyed||this.pendingRenderTaskId!==null||this.runningTick||this.appRef._runningTick||!this.zonelessEnabled&&this.zoneIsDefined&&Zone.current.get(ia+this.angularZoneId))}tick(){if(this.runningTick||this.appRef.destroyed)return;if(this.appRef.dirtyFlags===0){this.cleanup();return}!this.zonelessEnabled&&this.appRef.dirtyFlags&7&&(this.appRef.dirtyFlags|=1);let e=this.taskService.add();try{this.ngZone.run(()=>{this.runningTick=!0,this.appRef._tick()},void 0,this.schedulerTickApplyArgs)}catch(o){this.applicationErrorHandler(o)}finally{this.taskService.remove(e),this.cleanup()}}ngOnDestroy(){this.subscriptions.unsubscribe(),this.cleanup()}cleanup(){if(this.runningTick=!1,this.cancelScheduledCallback?.(),this.cancelScheduledCallback=null,this.pendingRenderTaskId!==null){let e=this.pendingRenderTaskId;this.pendingRenderTaskId=null,this.taskService.remove(e)}}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})();function jM(){return[{provide:bn,useExisting:VM},{provide:ge,useClass:ra},{provide:ar,useValue:!0}]}var qp=(()=>{class n{compileModuleSync(e){return new ll(e)}compileModuleAsync(e){return Promise.resolve(this.compileModuleSync(e))}clearCache(){}clearCacheFor(e){}getModuleId(e){}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})();function Qw(){return typeof $localize<"u"&&$localize.locale||ja}var Ba=new B("",{factory:()=>D(Ba,{optional:!0,skipSelf:!0})||Qw()});function I(n,t){return Ts(n,t?.equal)}function de(n){return Nm(n)}var $M=class n extends Error{_brand;constructor(t){super(t)}static IDLE=new n("IDLE");static LOADING=new n("LOADING")},Jw=n=>n;function Wp(n,t){if(typeof n=="function"){let e=cu(n,Jw,t?.equal);return zM(e,t?.debugName,t?.set)}else{let e=cu(n.source,n.computation,n.equal);return zM(e,n.debugName,n.set)}}function zM(n,t,e){let o=n[nt],i=n;if(e!==void 0){let r=a=>lu(o,a);i.set=a=>e(a,r),i.update=a=>e(a(de(n)),r)}else i.set=r=>lu(o,r),i.update=r=>Am(o,r);return i.asReadonly=Rc.bind(n),i}var UM=Symbol("InputSignalNode#UNSET"),fS=F(S({},Ns),{transformFn:void 0,applyValueToInputSignal(n,t){Wo(n,t)}});function GM(n,t){let e=Object.create(fS);e.value=n,e.transformFn=t?.transform;function o(){if(Ho(e),e.value===UM){let i=null;throw new z(-950,i)}return e.value}return o[nt]=e,o}var Tl=class{attributeName;constructor(t){this.attributeName=t}__NG_ELEMENT_ID__=()=>Ra(this.attributeName);toString(){return`HostAttributeToken ${this.attributeName}`}};function Yp(n){return mS(n)?n.default:n}function mS(n){return n&&typeof n=="object"&&"default"in n}function BM(n,t){return GM(n,t)}function _S(n){return GM(UM,n)}var Al=(BM.required=_S,BM);var hS=1e4;var EU=hS-1e3;var oo=(()=>{class n{static __NG_ELEMENT_ID__=CS}return n})();function CS(n){return MS(tt(),Z(),(n&16)===16)}function MS(n,t,e){if(Yn(n)&&!e){let o=Gt(n.index,t);return new So(o,o)}else if(n.type&175){let o=t[xt];return new So(o,t)}return null}var bS=(()=>{class n{zone=D(ge);changeDetectionScheduler=D(bn);applicationRef=D(Xn);applicationErrorHandler=D(Nt);_onMicrotaskEmptySubscription;initialize(){this._onMicrotaskEmptySubscription||(this._onMicrotaskEmptySubscription=this.zone.onMicrotaskEmpty.subscribe({next:()=>{this.changeDetectionScheduler.runningTick||this.zone.run(()=>{try{this.applicationRef.dirtyFlags|=1,this.applicationRef._tick()}catch(e){this.applicationErrorHandler(e)}})}}))}ngOnDestroy(){this._onMicrotaskEmptySubscription?.unsubscribe()}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})(),PS=new B("",{factory:()=>!1});function OS({ngZoneFactory:n,scheduleInRootZone:t}){return n??=()=>new ge(F(S({},WM()),{scheduleInRootZone:t})),[{provide:ar,useValue:!1},{provide:ge,useFactory:n},{provide:ri,multi:!0,useFactory:()=>{let e=D(bS,{optional:!0});return()=>e.initialize()}},{provide:ri,multi:!0,useFactory:()=>{let e=D(vS);return()=>{e.initialize()}}},{provide:Lc,useValue:t??Cg}]}function qM(n){let t=n?.scheduleInRootZone,e=OS({ngZoneFactory:()=>{let o=WM(n);return o.scheduleInRootZone=t,o.shouldCoalesceEventChangeDetection&&An("NgZone_CoalesceEvent"),new ge(o)},scheduleInRootZone:t});return bo([{provide:PS,useValue:!0},e])}function WM(n){return{enableLongStackTrace:!1,shouldCoalesceEventChangeDetection:n?.eventCoalescing??!1,shouldCoalesceRunChangeDetection:n?.runCoalescing??!1}}var vS=(()=>{class n{subscription=new Be;initialized=!1;zone=D(ge);pendingTasks=D(kn);initialize(){if(this.initialized)return;this.initialized=!0;let e=null;!this.zone.isStable&&!this.zone.hasPendingMacrotasks&&!this.zone.hasPendingMicrotasks&&(e=this.pendingTasks.add()),this.zone.runOutsideAngular(()=>{this.subscription.add(this.zone.onStable.subscribe(()=>{ge.assertNotInAngularZone(),queueMicrotask(()=>{e!==null&&!this.zone.hasPendingMacrotasks&&!this.zone.hasPendingMicrotasks&&(this.pendingTasks.remove(e),e=null)})}))}),this.subscription.add(this.zone.onUnstable.subscribe(()=>{ge.assertInAngularZone(),e??=this.pendingTasks.add()}))}ngOnDestroy(){this.subscription.unsubscribe()}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})();var Kp=new B(""),yS=new B("");function Ha(n){return!n.moduleRef}function xS(n){let t=Ha(n)?n.r3Injector:n.moduleRef.injector,e=t.get(ge);return e.run(()=>{Ha(n)?n.r3Injector.resolveInjectorInitializers():n.moduleRef.resolveInjectorInitializers();let o=t.get(Nt),i;if(e.runOutsideAngular(()=>{i=e.onError.subscribe({next:o})}),Ha(n)){let r=()=>t.destroy(),a=n.platformInjector.get(Kp);a.add(r),t.onDestroy(()=>{i.unsubscribe(),a.delete(r)})}else{let r=()=>n.moduleRef.destroy(),a=n.platformInjector.get(Kp);a.add(r),n.moduleRef.onDestroy(()=>{wa(n.allPlatformModules,n.moduleRef),i.unsubscribe(),a.delete(r)})}return SS(o,e,()=>{let r=t.get(kn),a=r.add(),s=t.get(Vp);return s.runInitializers(),s.donePromise.then(()=>{let c=t.get(Ba,ja);if(vM(c||ja),!t.get(yS,!0))return Ha(n)?t.get(Xn):(n.allPlatformModules.push(n.moduleRef),n.moduleRef);if(Ha(n)){let f=t.get(Xn);return n.rootComponent!==void 0&&f.bootstrap(n.rootComponent),f}else return wS?.(n.moduleRef,n.allPlatformModules),n.moduleRef}).finally(()=>{r.remove(a)})})})}var wS;function SS(n,t,e){try{let o=e();return Eo(o)?o.catch(i=>{throw t.runOutsideAngular(()=>n(i)),i}):o}catch(o){throw t.runOutsideAngular(()=>n(o)),o}}var Il=null;function kS(n=[],t){return Ct.create({name:t,providers:[{provide:ga,useValue:"platform"},{provide:Kp,useValue:new Set([()=>Il=null])},...n]})}function ES(n=[]){if(Il)return Il;let t=kS(n);return Il=t,PM(),DS(t),t}function DS(n){let t=n.get(Fc,null);et(n,()=>{t?.forEach(e=>e())})}function KM(n){let{rootComponent:t,appProviders:e,platformProviders:o,platformRef:i}=n;Ce(pe.BootstrapApplicationStart);try{let r=i?.injector??ES(o),a=[jM(),eh,...e||[]],s=new Ta({providers:a,parent:r,debugName:"",runEnvironmentInitializers:!1});return xS({r3Injector:s.injector,platformInjector:r,rootComponent:t})}catch(r){return Promise.reject(r)}finally{Ce(pe.BootstrapApplicationEnd)}}function Si(n){return typeof n=="boolean"?n:n!=null&&n!=="false"}var YM=null;function Kt(){return YM}function Zp(n){YM??=n}var Ua=class{},Cr=(()=>{class n{historyGo(e){throw new Error("")}static \u0275fac=function(o){return new(o||n)};static \u0275prov=te({token:n,factory:()=>D(ZM),providedIn:"platform"})}return n})();var ZM=(()=>{class n extends Cr{_location;_history;_doc=D(Ue);constructor(){super(),this._location=window.location,this._history=window.history}getBaseHrefFromDOM(){return Kt().getBaseHref(this._doc)}onPopState(e){let o=Kt().getGlobalEventTarget(this._doc,"window");return o.addEventListener("popstate",e,!1),()=>o.removeEventListener("popstate",e)}onHashChange(e){let o=Kt().getGlobalEventTarget(this._doc,"window");return o.addEventListener("hashchange",e,!1),()=>o.removeEventListener("hashchange",e)}get href(){return this._location.href}get protocol(){return this._location.protocol}get hostname(){return this._location.hostname}get port(){return this._location.port}get pathname(){return this._location.pathname}get search(){return this._location.search}get hash(){return this._location.hash}set pathname(e){this._location.pathname=e}pushState(e,o,i){this._history.pushState(e,o,i)}replaceState(e,o,i){this._history.replaceState(e,o,i)}forward(){this._history.forward()}back(){this._history.back()}historyGo(e=0){this._history.go(e)}getState(){return this._history.state}static \u0275fac=function(o){return new(o||n)};static \u0275prov=te({token:n,factory:()=>new n,providedIn:"platform"})}return n})();function XM(n,t){return n?t?n.endsWith("/")?t.startsWith("/")?n+t.slice(1):n+t:t.startsWith("/")?n+t:`${n}/${t}`:n:t}function QM(n){let t=n.search(/#|\?|$/);return n[t-1]==="/"?n.slice(0,t-1)+n.slice(t):n}function Ao(n){return n&&n[0]!=="?"?`?${n}`:n}var Mr=(()=>{class n{historyGo(e){throw new Error("")}static \u0275fac=function(o){return new(o||n)};static \u0275prov=te({token:n,factory:()=>D(TS),providedIn:"root"})}return n})(),IS=new B(""),TS=(()=>{class n extends Mr{_platformLocation;_baseHref;_removeListenerFns=[];constructor(e,o){super(),this._platformLocation=e,this._baseHref=o??this._platformLocation.getBaseHrefFromDOM()??D(Ue).location?.origin??""}ngOnDestroy(){for(;this._removeListenerFns.length;)this._removeListenerFns.pop()()}onPopState(e){this._removeListenerFns.push(this._platformLocation.onPopState(e),this._platformLocation.onHashChange(e))}getBaseHref(){return this._baseHref}prepareExternalUrl(e){return XM(this._baseHref,e)}path(e=!1){let o=this._platformLocation.pathname+Ao(this._platformLocation.search),i=this._platformLocation.hash;return i&&e?`${o}${i}`:o}pushState(e,o,i,r){let a=this.prepareExternalUrl(i+Ao(r));this._platformLocation.pushState(e,o,a)}replaceState(e,o,i,r){let a=this.prepareExternalUrl(i+Ao(r));this._platformLocation.replaceState(e,o,a)}forward(){this._platformLocation.forward()}back(){this._platformLocation.back()}getState(){return this._platformLocation.getState()}historyGo(e=0){this._platformLocation.historyGo?.(e)}static \u0275fac=function(o){return new(o||n)(Q(Cr),Q(IS,8))};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})}return n})();var br=(()=>{class n{_subject=new ye;_basePath;_locationStrategy;_urlChangeListeners=[];_urlChangeSubscription=null;constructor(e){this._locationStrategy=e;let o=this._locationStrategy.getBaseHref();this._basePath=RS(QM(JM(o))),this._locationStrategy.onPopState(i=>{this._subject.next({url:this.path(!0),pop:!0,state:i.state,type:i.type})})}ngOnDestroy(){this._urlChangeSubscription?.unsubscribe(),this._urlChangeListeners=[]}path(e=!1){return this.normalize(this._locationStrategy.path(e))}getState(){return this._locationStrategy.getState()}isCurrentPathEqualTo(e,o=""){return this.path()==this.normalize(e+Ao(o))}normalize(e){return n.stripTrailingSlash(NS(this._basePath,JM(e)))}prepareExternalUrl(e){return e&&e[0]!=="/"&&(e="/"+e),this._locationStrategy.prepareExternalUrl(e)}go(e,o="",i=null){this._locationStrategy.pushState(i,"",e,o),this._notifyUrlChangeListeners(this.prepareExternalUrl(e+Ao(o)),i)}replaceState(e,o="",i=null){this._locationStrategy.replaceState(i,"",e,o),this._notifyUrlChangeListeners(this.prepareExternalUrl(e+Ao(o)),i)}forward(){this._locationStrategy.forward()}back(){this._locationStrategy.back()}historyGo(e=0){this._locationStrategy.historyGo?.(e)}onUrlChange(e){return this._urlChangeListeners.push(e),this._urlChangeSubscription??=this.subscribe(o=>{this._notifyUrlChangeListeners(o.url,o.state)}),()=>{let o=this._urlChangeListeners.indexOf(e);this._urlChangeListeners.splice(o,1),this._urlChangeListeners.length===0&&(this._urlChangeSubscription?.unsubscribe(),this._urlChangeSubscription=null)}}_notifyUrlChangeListeners(e="",o){this._urlChangeListeners.forEach(i=>i(e,o))}subscribe(e,o,i){return this._subject.subscribe({next:e,error:o??void 0,complete:i??void 0})}static normalizeQueryParams=Ao;static joinWithSlash=XM;static stripTrailingSlash=QM;static \u0275fac=function(o){return new(o||n)(Q(Mr))};static \u0275prov=te({token:n,factory:()=>AS(),providedIn:"root"})}return n})();function AS(){return new br(Q(Mr))}function NS(n,t){if(!n||!t.startsWith(n))return t;let e=t.substring(n.length);return e===""||["/",";","?","#"].includes(e[0])?e:t}function JM(n){return n.replace(/\/index\.html$/,"")}function RS(n){if(new RegExp("^(https?:)?//").test(n)){let[,e]=n.split(/\/\/[^\/]+/);return e}return n}var gt=(function(n){return n[n.Format=0]="Format",n[n.Standalone=1]="Standalone",n})(gt||{}),ve=(function(n){return n[n.Narrow=0]="Narrow",n[n.Abbreviated=1]="Abbreviated",n[n.Wide=2]="Wide",n[n.Short=3]="Short",n})(ve||{}),Dt=(function(n){return n[n.Short=0]="Short",n[n.Medium=1]="Medium",n[n.Long=2]="Long",n[n.Full=3]="Full",n})(Dt||{}),ro={Decimal:0,Group:1,List:2,PercentSign:3,PlusSign:4,MinusSign:5,Exponential:6,SuperscriptingExponent:7,PerMille:8,Infinity:9,NaN:10,TimeSeparator:11,CurrencyDecimal:12,CurrencyGroup:13};function n0(n){return Lt(n)[Ze.LocaleId]}function o0(n,t,e){let o=Lt(n),i=[o[Ze.DayPeriodsFormat],o[Ze.DayPeriodsStandalone]],r=Yt(i,t);return Yt(r,e)}function i0(n,t,e){let o=Lt(n),i=[o[Ze.DaysFormat],o[Ze.DaysStandalone]],r=Yt(i,t);return Yt(r,e)}function r0(n,t,e){let o=Lt(n),i=[o[Ze.MonthsFormat],o[Ze.MonthsStandalone]],r=Yt(i,t);return Yt(r,e)}function a0(n,t){let o=Lt(n)[Ze.Eras];return Yt(o,t)}function Ga(n,t){let e=Lt(n);return Yt(e[Ze.DateFormat],t)}function qa(n,t){let e=Lt(n);return Yt(e[Ze.TimeFormat],t)}function Wa(n,t){let o=Lt(n)[Ze.DateTimeFormat];return Yt(o,t)}function Ka(n,t){let e=Lt(n),o=e[Ze.NumberSymbols][t];if(typeof o>"u"){if(t===ro.CurrencyDecimal)return e[Ze.NumberSymbols][ro.Decimal];if(t===ro.CurrencyGroup)return e[Ze.NumberSymbols][ro.Group]}return o}function s0(n){if(!n[Ze.ExtraData])throw new z(2303,!1)}function c0(n){let t=Lt(n);return s0(t),(t[Ze.ExtraData][2]||[]).map(o=>typeof o=="string"?Qp(o):[Qp(o[0]),Qp(o[1])])}function l0(n,t,e){let o=Lt(n);s0(o);let i=[o[Ze.ExtraData][0],o[Ze.ExtraData][1]],r=Yt(i,t)||[];return Yt(r,e)||[]}function Yt(n,t){for(let e=t;e>-1;e--)if(typeof n[e]<"u")return n[e];throw new z(2304,!1)}function Qp(n){let[t,e]=n.split(":");return{hours:+t,minutes:+e}}var FS=/^(\d{4,})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/,Nl=Object.create(null),LS=/((?:[^BEGHLMOSWYZabcdhmswyz']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|Y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|c{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/,VS=256;function d0(n,t,e,o){let i=KS(n);jS(t),t=io(e,t)||t;let a=[],s;for(;t;)if(s=LS.exec(t),s){a=a.concat(s.slice(1));let f=a.pop();if(!f)break;t=f}else{a.push(t);break}let c=i.getTimezoneOffset();o&&(c=g0(o,c),i=WS(i,o));let p="";return a.forEach(f=>{let _=GS(f);p+=_?_(i,e,c):f==="''"?"'":f.replace(/(^'|'$)/g,"").replace(/''/g,"'")}),p}function jS(n){if(n.length>VS)throw new z(2300,!1)}function jl(n,t,e){let o=new Date(0);return o.setFullYear(n,t,e),o.setHours(0,0,0),o}function io(n,t){let e=n0(n);if(Nl[e]??=Object.create(null),Nl[e][t])return Nl[e][t];let o="";switch(t){case"shortDate":o=Ga(n,Dt.Short);break;case"mediumDate":o=Ga(n,Dt.Medium);break;case"longDate":o=Ga(n,Dt.Long);break;case"fullDate":o=Ga(n,Dt.Full);break;case"shortTime":o=qa(n,Dt.Short);break;case"mediumTime":o=qa(n,Dt.Medium);break;case"longTime":o=qa(n,Dt.Long);break;case"fullTime":o=qa(n,Dt.Full);break;case"short":let i=io(n,"shortTime"),r=io(n,"shortDate");o=Rl(Wa(n,Dt.Short),[i,r]);break;case"medium":let a=io(n,"mediumTime"),s=io(n,"mediumDate");o=Rl(Wa(n,Dt.Medium),[a,s]);break;case"long":let c=io(n,"longTime"),p=io(n,"longDate");o=Rl(Wa(n,Dt.Long),[c,p]);break;case"full":let f=io(n,"fullTime"),_=io(n,"fullDate");o=Rl(Wa(n,Dt.Full),[f,_]);break}return o&&(Nl[e][t]=o),o}function Rl(n,t){return t&&(n=n.replace(/\{([^}]+)}/g,function(e,o){return Object.hasOwn(t,o)?t[o]:e})),n}function pn(n,t,e="-",o,i){let r="";(n<0||i&&n<=0)&&(i?n=-n+1:(n=-n,r=e));let a=String(n);for(;a.length0||s>-e)&&(s+=e),n===3)s===0&&e===-12&&(s=12);else if(n===6)return $S(s,t);let c=Ka(a,ro.MinusSign);return pn(s,t,c,o,i)}}function zS(n,t){switch(n){case 0:return t.getFullYear();case 1:return t.getMonth();case 2:return t.getDate();case 3:return t.getHours();case 4:return t.getMinutes();case 5:return t.getSeconds();case 6:return t.getMilliseconds();case 7:return t.getDay();default:throw new z(2301,!1)}}function Te(n,t,e=gt.Format,o=!1){return function(i,r){return BS(i,r,n,t,e,o)}}function BS(n,t,e,o,i,r){switch(e){case 2:return r0(t,i,o)[n.getMonth()];case 1:return i0(t,i,o)[n.getDay()];case 0:let a=n.getHours(),s=n.getMinutes();if(r){let p=c0(t),f=l0(t,i,o),_=p.findIndex(C=>{if(Array.isArray(C)){let[h,P]=C,T=a>=h.hours&&s>=h.minutes,A=a0?Math.floor(i/60):Math.ceil(i/60);switch(n){case 0:return(i>=0?"+":"")+pn(a,2,r)+pn(Math.abs(i%60),2,r);case 1:return"GMT"+(i>=0?"+":"")+pn(a,1,r);case 2:return"GMT"+(i>=0?"+":"")+pn(a,2,r)+":"+pn(Math.abs(i%60),2,r);case 3:return o===0?"Z":(i>=0?"+":"")+pn(a,2,r)+":"+pn(Math.abs(i%60),2,r);default:throw new z(2310,!1)}}}var HS=0,Vl=4;function US(n){let t=jl(n,HS,1).getDay();return jl(n,0,1+(t<=Vl?Vl:Vl+7)-t)}function u0(n){let t=n.getDay(),e=t===0?-3:Vl-t;return jl(n.getFullYear(),n.getMonth(),n.getDate()+e)}function Jp(n,t=!1){return function(e,o){let i;if(t){let r=new Date(e.getFullYear(),e.getMonth(),1).getDay()-1,a=e.getDate();i=1+Math.floor((a+r)/7)}else{let r=u0(e),a=US(r.getFullYear()),s=r.getTime()-a.getTime();i=1+Math.round(s/6048e5)}return pn(i,n,Ka(o,ro.MinusSign))}}function Ll(n,t=!1){return function(e,o){let r=u0(e).getFullYear();return pn(r,n,Ka(o,ro.MinusSign),t)}}var Xp=Object.create(null);function GS(n){if(Xp[n])return Xp[n];let t;switch(n){case"G":case"GG":case"GGG":t=Te(3,ve.Abbreviated);break;case"GGGG":t=Te(3,ve.Wide);break;case"GGGGG":t=Te(3,ve.Narrow);break;case"y":t=Qe(0,1,0,!1,!0);break;case"yy":t=Qe(0,2,0,!0,!0);break;case"yyy":t=Qe(0,3,0,!1,!0);break;case"yyyy":t=Qe(0,4,0,!1,!0);break;case"Y":t=Ll(1);break;case"YY":t=Ll(2,!0);break;case"YYY":t=Ll(3);break;case"YYYY":t=Ll(4);break;case"M":case"L":t=Qe(1,1,1);break;case"MM":case"LL":t=Qe(1,2,1);break;case"MMM":t=Te(2,ve.Abbreviated);break;case"MMMM":t=Te(2,ve.Wide);break;case"MMMMM":t=Te(2,ve.Narrow);break;case"LLL":t=Te(2,ve.Abbreviated,gt.Standalone);break;case"LLLL":t=Te(2,ve.Wide,gt.Standalone);break;case"LLLLL":t=Te(2,ve.Narrow,gt.Standalone);break;case"w":t=Jp(1);break;case"ww":t=Jp(2);break;case"W":t=Jp(1,!0);break;case"d":t=Qe(2,1);break;case"dd":t=Qe(2,2);break;case"c":case"cc":t=Qe(7,1);break;case"ccc":t=Te(1,ve.Abbreviated,gt.Standalone);break;case"cccc":t=Te(1,ve.Wide,gt.Standalone);break;case"ccccc":t=Te(1,ve.Narrow,gt.Standalone);break;case"cccccc":t=Te(1,ve.Short,gt.Standalone);break;case"E":case"EE":case"EEE":t=Te(1,ve.Abbreviated);break;case"EEEE":t=Te(1,ve.Wide);break;case"EEEEE":t=Te(1,ve.Narrow);break;case"EEEEEE":t=Te(1,ve.Short);break;case"a":case"aa":case"aaa":t=Te(0,ve.Abbreviated);break;case"aaaa":t=Te(0,ve.Wide);break;case"aaaaa":t=Te(0,ve.Narrow);break;case"b":case"bb":case"bbb":t=Te(0,ve.Abbreviated,gt.Standalone,!0);break;case"bbbb":t=Te(0,ve.Wide,gt.Standalone,!0);break;case"bbbbb":t=Te(0,ve.Narrow,gt.Standalone,!0);break;case"B":case"BB":case"BBB":t=Te(0,ve.Abbreviated,gt.Format,!0);break;case"BBBB":t=Te(0,ve.Wide,gt.Format,!0);break;case"BBBBB":t=Te(0,ve.Narrow,gt.Format,!0);break;case"h":t=Qe(3,1,-12);break;case"hh":t=Qe(3,2,-12);break;case"H":t=Qe(3,1);break;case"HH":t=Qe(3,2);break;case"m":t=Qe(4,1);break;case"mm":t=Qe(4,2);break;case"s":t=Qe(5,1);break;case"ss":t=Qe(5,2);break;case"S":t=Qe(6,1);break;case"SS":t=Qe(6,2);break;case"SSS":t=Qe(6,3);break;case"Z":case"ZZ":case"ZZZ":t=Fl(0);break;case"ZZZZZ":t=Fl(3);break;case"O":case"OO":case"OOO":case"z":case"zz":case"zzz":t=Fl(1);break;case"OOOO":case"ZZZZ":case"zzzz":t=Fl(2);break;default:return null}return Xp[n]=t,t}function g0(n,t){n=n.replace(/:/g,"");let e=Date.parse("Jan 01, 1970 00:00:00 "+n)/6e4;return isNaN(e)?t:e}function qS(n,t){return n=new Date(n.getTime()),n.setMinutes(n.getMinutes()+t),n}function WS(n,t,e){let i=n.getTimezoneOffset(),r=g0(t,i);return qS(n,-1*(r-i))}function KS(n){if(e0(n))return n;if(typeof n=="number"&&!isNaN(n))return new Date(n);if(typeof n=="string"){if(n=n.trim(),/^(\d{4}(-\d{1,2}(-\d{1,2})?)?)$/.test(n)){let[i,r=1,a=1]=n.split("-").map(s=>+s);return jl(i,r-1,a)}let e=parseFloat(n);if(!isNaN(n-e))return new Date(e);let o;if(o=n.match(FS))return YS(o)}let t=new Date(n);if(!e0(t))throw new z(2311,!1);return t}function YS(n){let t=new Date(0),e=0,o=0,i=n[8]?t.setUTCFullYear:t.setFullYear,r=n[8]?t.setUTCHours:t.setHours;n[9]&&(e=Number(n[9]+n[10]),o=Number(n[9]+n[11])),i.call(t,Number(n[1]),Number(n[2])-1,Number(n[3]));let a=Number(n[4]||0)-e,s=Number(n[5]||0)-o,c=Number(n[6]||0),p=Math.floor(parseFloat("0."+(n[7]||0))*1e3);return r.call(t,a,s,c,p),t}function e0(n){return n instanceof Date&&!isNaN(n.valueOf())}var ef=/\s+/,t0=[],ki=(()=>{class n{_ngEl;_renderer;initialClasses=t0;rawClass;stateMap=new Map;constructor(e,o){this._ngEl=e,this._renderer=o}set klass(e){this.initialClasses=e!=null?e.trim().split(ef):t0}set ngClass(e){this.rawClass=typeof e=="string"?e.trim().split(ef):e}ngDoCheck(){for(let o of this.initialClasses)this._updateState(o,!0);let e=this.rawClass;if(Array.isArray(e)||e instanceof Set)for(let o of e)this._updateState(o,!0);else if(e!=null)for(let o of Object.keys(e))this._updateState(o,!!e[o]);this._applyStateDiff()}_updateState(e,o){let i=this.stateMap.get(e);i!==void 0?(i.enabled!==o&&(i.changed=!0,i.enabled=o),i.touched=!0):this.stateMap.set(e,{enabled:o,changed:!0,touched:!0})}_applyStateDiff(){for(let e of this.stateMap){let o=e[0],i=e[1];i.changed?(this._toggleClass(o,i.enabled),i.changed=!1):i.touched||(i.enabled&&this._toggleClass(o,!1),this.stateMap.delete(o)),i.touched=!1}}_toggleClass(e,o){e=e.trim(),e.length>0&&e.split(ef).forEach(i=>{o?this._renderer.addClass(this._ngEl.nativeElement,i):this._renderer.removeClass(this._ngEl.nativeElement,i)})}static \u0275fac=function(o){return new(o||n)(le(Mt),le(wt))};static \u0275dir=qe({type:n,selectors:[["","ngClass",""]],inputs:{klass:[0,"class","klass"],ngClass:"ngClass"}})}return n})();function p0(n,t){return new z(2100,!1)}var Ya=(()=>{class n{transform(e){return e==null?null:(ZS(n,e),e.toUpperCase())}static \u0275fac=function(o){return new(o||n)};static \u0275pipe=Sl({name:"uppercase",type:n,pure:!0})}return n})();function ZS(n,t){if(typeof t!="string")throw p0(n,t)}var QS="mediumDate",f0=new B(""),m0=new B(""),Ei=(()=>{class n{locale;defaultTimezone;defaultOptions;constructor(e,o,i){this.locale=e,this.defaultTimezone=o,this.defaultOptions=i}transform(e,o,i,r){if(e==null||e===""||e!==e)return null;try{let a=o??this.defaultOptions?.dateFormat??QS,s=i??this.defaultOptions?.timezone??this.defaultTimezone??void 0;return d0(e,a,r||this.locale,s)}catch(a){throw p0(n,a.message)}}static \u0275fac=function(o){return new(o||n)(le(Ba,16),le(f0,24),le(m0,24))};static \u0275pipe=Sl({name:"date",type:n,pure:!0})}return n})();var No=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275mod=Jn({type:n});static \u0275inj=Pn({})}return n})();function Za(n,t){t=encodeURIComponent(t);for(let e of n.split(";")){let o=e.indexOf("="),[i,r]=o==-1?[e,""]:[e.slice(0,o),e.slice(o+1)];if(i.trim()!==t)continue;let a=r;try{a=decodeURIComponent(r)}catch(s){}return a.length>1&&a[0]==='"'&&a[a.length-1]==='"'&&(a=a.slice(1,-1)),a}return null}var JS=(()=>{class n{build(){return new XMLHttpRequest}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})(),tf=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275prov=te({token:n,factory:function(o){let i=null;return o?i=new(o||n):i=Q(JS),i},providedIn:"root"})}return n})();var _0="browser";var Qa=class{_doc;constructor(t){this._doc=t}manager},zl=(()=>{class n extends Qa{constructor(e){super(e)}supports(e){return!0}addEventListener(e,o,i,r){return e.addEventListener(o,i,r),()=>this.removeEventListener(e,o,i,r)}removeEventListener(e,o,i,r){return e.removeEventListener(o,i,r)}static \u0275fac=function(o){return new(o||n)(Q(Ue))};static \u0275prov=te({token:n,factory:n.\u0275fac})}return n})(),Ul=new B(""),af=(()=>{class n{_zone;_plugins;_eventNameToPlugin=new Map;constructor(e,o){this._zone=o,e.forEach(a=>{a.manager=this});let i=e.filter(a=>!(a instanceof zl));this._plugins=i.slice().reverse();let r=e.find(a=>a instanceof zl);r&&this._plugins.push(r)}addEventListener(e,o,i,r){return this._findPluginFor(o).addEventListener(e,o,i,r)}getZone(){return this._zone}_findPluginFor(e){let o=this._eventNameToPlugin.get(e);if(o)return o;if(o=this._plugins.find(r=>r.supports(e)),!o)throw new z(-5101,!1);return this._eventNameToPlugin.set(e,o),o}static \u0275fac=function(o){return new(o||n)(Q(Ul),Q(ge))};static \u0275prov=te({token:n,factory:n.\u0275fac})}return n})(),nf="ng-app-id";function h0(n){for(let t of n)t.remove()}function C0(n,t){let e=t.createElement("style");return e.textContent=n,e}function ek(n,t,e,o){let i=n.head?.querySelectorAll(`style[${nf}="${t}"],link[${nf}="${t}"]`);if(!i||i.length===0)return!1;for(let r of i)r.removeAttribute(nf),r instanceof HTMLLinkElement?o.set(r.href.slice(r.href.lastIndexOf("/")+1),{usage:0,elements:[r]}):r.textContent&&e.set(r.textContent,{usage:0,elements:[r]});return!0}function rf(n,t){let e=t.createElement("link");return e.setAttribute("rel","stylesheet"),e.setAttribute("href",n),e}var sf=(()=>{class n{doc;appId;nonce;inline=new Map;external=new Map;hosts=new Set;constructor(e,o,i,r={}){this.doc=e,this.appId=o,this.nonce=i,ek(e,o,this.inline,this.external)&&this.hosts.add(e.head)}addStyles(e,o){for(let i of e)this.addUsage(i,this.inline,C0);o?.forEach(i=>this.addUsage(i,this.external,rf))}removeStyles(e,o){for(let i of e)this.removeUsage(i,this.inline);o?.forEach(i=>this.removeUsage(i,this.external))}addUsage(e,o,i){let r=o.get(e);r?r.usage++:o.set(e,{usage:1,elements:[...this.hosts].map(a=>this.addElement(a,i(e,this.doc)))})}removeUsage(e,o){let i=o.get(e);i&&(i.usage--,i.usage<=0&&(h0(i.elements),o.delete(e)))}ngOnDestroy(){for(let[,{elements:e}]of[...this.inline,...this.external])h0(e);this.hosts.clear()}addHost(e){if(!this.hosts.has(e)){this.hosts.add(e);for(let[o,{elements:i}]of this.inline)i.push(this.addElement(e,C0(o,this.doc)));for(let[o,{elements:i}]of this.external)i.push(this.addElement(e,rf(o,this.doc)))}}removeHost(e){this.hosts.delete(e);for(let o of[...this.inline.values(),...this.external.values()]){let i=[];for(let r of o.elements)r.parentNode===e?r.remove():i.push(r);o.elements=i}}addElement(e,o){return this.nonce&&o.setAttribute("nonce",this.nonce),e.appendChild(o)}static \u0275fac=function(o){return new(o||n)(Q(Ue),Q(ha),Q(Ma,8),Q(Ca))};static \u0275prov=te({token:n,factory:n.\u0275fac})}return n})(),of={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/",math:"http://www.w3.org/1998/Math/MathML"},cf=/%COMP%/g;var b0="%COMP%",tk=`_nghost-${b0}`,nk=`_ngcontent-${b0}`,ok=!0,ik=new B("",{factory:()=>ok}),rk=new B("");function ak(n){return nk.replace(cf,n)}function sk(n){return tk.replace(cf,n)}function P0(n,t){return t.map(e=>e.replace(cf,n))}var lf=(()=>{class n{eventManager;sharedStylesHost;appId;removeStylesOnCompDestroy;doc;ngZone;nonce;tracingService;rendererByCompId=new Map;defaultRenderer;cssVarNamespace;constructor(e,o,i,r,a,s,c=null,p=null,f=null){this.eventManager=e,this.sharedStylesHost=o,this.appId=i,this.removeStylesOnCompDestroy=r,this.doc=a,this.ngZone=s,this.nonce=c,this.tracingService=p,this.cssVarNamespace=f??"",this.defaultRenderer=new Ja(e,a,s,this.tracingService,this.cssVarNamespace)}createRenderer(e,o){if(!e||!o)return this.defaultRenderer;let i=this.getOrCreateRenderer(e,o);return i instanceof Hl?i.applyToHost(e):i instanceof Xa&&i.applyStyles(),i}getOrCreateRenderer(e,o){let i=this.rendererByCompId,r=i.get(o.id);if(!r){let a=this.doc,s=this.ngZone,c=this.eventManager,p=this.sharedStylesHost,f=this.removeStylesOnCompDestroy,_=this.tracingService;switch(o.encapsulation){case un.Emulated:r=new Hl(c,p,o,this.appId,f,a,s,_,this.cssVarNamespace);break;case un.ShadowDom:return new Bl(c,e,o,a,s,this.nonce,_,this.cssVarNamespace,p);case un.ExperimentalIsolatedShadowDom:return new Bl(c,e,o,a,s,this.nonce,_,this.cssVarNamespace);default:r=new Xa(c,p,o,f,a,s,_,this.cssVarNamespace);break}i.set(o.id,r)}return r}ngOnDestroy(){this.rendererByCompId.clear()}componentReplaced(e){this.rendererByCompId.delete(e)}static \u0275fac=function(o){return new(o||n)(Q(af),Q(Oi),Q(ha),Q(ik),Q(Ue),Q(ge),Q(Ma),Q(Tn,8),Q(rk,8))};static \u0275prov=te({token:n,factory:n.\u0275fac})}return n})(),Ja=class{eventManager;doc;ngZone;tracingService;cssVarNamespace;data=Object.create(null);throwOnSyntheticProps=!0;constructor(t,e,o,i,r=""){this.eventManager=t,this.doc=e,this.ngZone=o,this.tracingService=i,this.cssVarNamespace=r}destroy(){}destroyNode=null;createElement(t,e){return e?this.doc.createElementNS(of[e]||e,t):this.doc.createElement(t)}createComment(t){return this.doc.createComment(t)}createText(t){return this.doc.createTextNode(t)}appendChild(t,e){(M0(t)?t.content:t).appendChild(e)}insertBefore(t,e,o){if(t){let i=M0(t)?t.content:t;if(o!=null&&o.parentNode!==i)throw new z(-5106,!1);i.insertBefore(e,o)}}removeChild(t,e){e.remove()}selectRootElement(t,e){let o=typeof t=="string"?this.doc.querySelector(t):t;if(!o)throw new z(-5104,!1);return e||(o.textContent=""),o}parentNode(t){return t.parentNode}nextSibling(t){return t.nextSibling}setAttribute(t,e,o,i){if(i){e=i+":"+e;let r=of[i];r?t.setAttributeNS(r,e,o):t.setAttribute(e,o)}else t.setAttribute(e,o)}removeAttribute(t,e,o){if(o){let i=of[o];i?t.removeAttributeNS(i,e):t.removeAttribute(`${o}:${e}`)}else t.removeAttribute(e)}addClass(t,e){t.classList.add(e)}removeClass(t,e){t.classList.remove(e)}setStyle(t,e,o,i){let r=e.startsWith("--");r&&(e=e.replace("%NS%",this.cssVarNamespace)),r||i&(Dn.DashCase|Dn.Important)?t.style.setProperty(e,o,i&Dn.Important?"important":""):t.style[e]=o}removeStyle(t,e,o){let i=e.startsWith("--");i&&(e=e.replace("%NS%",this.cssVarNamespace)),i||o&Dn.DashCase?t.style.removeProperty(e):t.style[e]=""}setProperty(t,e,o){t!=null&&(t[e]=o)}setValue(t,e){t.nodeValue=e}listen(t,e,o,i){if(typeof t=="string"&&(t=Kt().getGlobalEventTarget(this.doc,t),!t))throw new z(-5102,!1);let r=this.decoratePreventDefault(o);return this.tracingService?.wrapEventListener&&(r=this.tracingService.wrapEventListener(t,e,r)),this.eventManager.addEventListener(t,e,r,i)}decoratePreventDefault(t){return e=>{if(e==="__ngUnwrap__")return t;t(e)===!1&&e.preventDefault()}}};function M0(n){return n.tagName==="TEMPLATE"&&n.content!==void 0}var Bl=class extends Ja{hostEl;sharedStylesHost;shadowRoot;constructor(t,e,o,i,r,a,s,c,p){super(t,i,r,s,c),this.hostEl=e,this.sharedStylesHost=p,this.shadowRoot=e.attachShadow({mode:"open"}),this.sharedStylesHost&&this.sharedStylesHost.addHost(this.shadowRoot);let f=o.styles;f=P0(o.id,f).map(C=>C.replace(/%NS%/g,c));for(let C of f){let h=document.createElement("style");a&&h.setAttribute("nonce",a),h.textContent=C,this.shadowRoot.appendChild(h)}let _=o.getExternalStyles?.();if(_)for(let C of _){let h=rf(C,i);a&&h.setAttribute("nonce",a),this.shadowRoot.appendChild(h)}}nodeOrShadowRoot(t){return t===this.hostEl?this.shadowRoot:t}appendChild(t,e){return super.appendChild(this.nodeOrShadowRoot(t),e)}insertBefore(t,e,o){return super.insertBefore(this.nodeOrShadowRoot(t),e,o)}removeChild(t,e){return super.removeChild(null,e)}parentNode(t){return this.nodeOrShadowRoot(super.parentNode(this.nodeOrShadowRoot(t)))}destroy(){this.sharedStylesHost&&this.sharedStylesHost.removeHost(this.shadowRoot)}},Xa=class extends Ja{sharedStylesHost;removeStylesOnCompDestroy;styles;styleUrls;constructor(t,e,o,i,r,a,s,c,p){super(t,r,a,s,c),this.sharedStylesHost=e,this.removeStylesOnCompDestroy=i;let f=o.styles,_=p?P0(p,f):f;this.styles=_.map(C=>C.replace(/%NS%/g,c)),this.styleUrls=o.getExternalStyles?.(p)}applyStyles(){this.sharedStylesHost.addStyles(this.styles,this.styleUrls)}destroy(){this.removeStylesOnCompDestroy&&wo.size===0&&this.sharedStylesHost.removeStyles(this.styles,this.styleUrls)}},Hl=class extends Xa{contentAttr;hostAttr;constructor(t,e,o,i,r,a,s,c,p){let f=i+"-"+o.id;super(t,e,o,r,a,s,c,p,f),this.contentAttr=ak(f),this.hostAttr=sk(f)}applyToHost(t){this.applyStyles(),this.setAttribute(t,this.hostAttr,"")}createElement(t,e){let o=super.createElement(t,e);return super.setAttribute(o,this.contentAttr,""),o}};var Gl=class n extends Ua{supportsDOMEvents=!0;static makeCurrent(){Zp(new n)}onAndCancel(t,e,o,i){return t.addEventListener(e,o,i),()=>{t.removeEventListener(e,o,i)}}dispatchEvent(t,e){t.dispatchEvent(e)}remove(t){t.remove()}createElement(t,e){return e=e||this.getDefaultDocument(),e.createElement(t)}createHtmlDocument(){return document.implementation.createHTMLDocument("fakeTitle")}getDefaultDocument(){return document}isElementNode(t){return t.nodeType===Node.ELEMENT_NODE}isShadowRoot(t){return t instanceof DocumentFragment}getGlobalEventTarget(t,e){return e==="window"?window:e==="document"?t:e==="body"?t.body:null}getBaseHref(t){let e=ck();return e==null?null:lk(e)}resetBaseElement(){es=null}getUserAgent(){return window.navigator.userAgent}getCookie(t){return Za(document.cookie,t)}},es=null;function ck(){return es=es||document.head.querySelector("base"),es?es.getAttribute("href"):null}function lk(n){return new URL(n,document.baseURI).pathname}var O0=["alt","control","meta","shift"],dk={"\b":"Backspace"," ":"Tab","\x7F":"Delete","\x1B":"Escape",Del:"Delete",Esc:"Escape",Left:"ArrowLeft",Right:"ArrowRight",Up:"ArrowUp",Down:"ArrowDown",Menu:"ContextMenu",Scroll:"ScrollLock",Win:"OS"},uk={alt:n=>n.altKey,control:n=>n.ctrlKey,meta:n=>n.metaKey,shift:n=>n.shiftKey},v0=(()=>{class n extends Qa{constructor(e){super(e)}supports(e){return n.parseEventName(e)!=null}addEventListener(e,o,i,r){let a=n.parseEventName(o),s=n.eventCallback(a.fullKey,i,this.manager.getZone());return this.manager.getZone().runOutsideAngular(()=>Kt().onAndCancel(e,a.domEventName,s,r))}static parseEventName(e){let o=e.toLowerCase().split("."),i=o.shift();if(o.length===0||!(i==="keydown"||i==="keyup"))return null;let r=n._normalizeKey(o.pop()),a="",s=o.indexOf("code");if(s>-1&&(o.splice(s,1),a="code."),O0.forEach(p=>{let f=o.indexOf(p);f>-1&&(o.splice(f,1),a+=p+".")}),a+=r,o.length!=0||r.length===0)return null;let c={};return c.domEventName=i,c.fullKey=a,c}static matchEventFullKeyCode(e,o){let i=dk[e.key]||e.key,r="";return o.indexOf("code.")>-1&&(i=e.code,r="code."),i==null||!i?!1:(i=i.toLowerCase(),i===" "?i="space":i==="."&&(i="dot"),O0.forEach(a=>{if(a!==i){let s=uk[a];s(e)&&(r+=a+".")}}),r+=i,r===o)}static eventCallback(e,o,i){return r=>{n.matchEventFullKeyCode(r,e)&&i.runGuarded(()=>o(r))}}static _normalizeKey(e){return e==="esc"?"escape":e}static \u0275fac=function(o){return new(o||n)(Q(Ue))};static \u0275prov=te({token:n,factory:n.\u0275fac})}return n})();function df(n,t,e){return be(this,null,function*(){let o=S({rootComponent:n},gk(t,e));return KM(o)})}function gk(n,t){return{platformRef:t?.platformRef,appProviders:[...hk,...n?.providers??[]],platformProviders:_k}}function pk(){Gl.makeCurrent()}function fk(){return new nn}function mk(){return gp(document),document}var _k=[{provide:Ca,useValue:_0},{provide:Fc,useValue:pk,multi:!0},{provide:Ue,useFactory:mk}];var hk=[{provide:ga,useValue:"root"},{provide:nn,useFactory:fk},{provide:Ul,useClass:zl,multi:!0},{provide:Ul,useClass:v0,multi:!0},lf,{provide:Oi,useClass:sf},{provide:sf,useExisting:Oi},af,{provide:Ci,useExisting:lf},[]];var Fn=class n{headers;normalizedNames=new Map;lazyInit;lazyUpdate=null;constructor(t){t?typeof t=="string"?this.lazyInit=()=>{this.headers=new Map,t.split(` -`).forEach(e=>{let o=e.indexOf(":");if(o>0){let i=e.slice(0,o),r=e.slice(o+1).trim();this.addHeaderEntry(i,r)}})}:typeof Headers<"u"&&t instanceof Headers?(this.headers=new Map,t.forEach((e,o)=>{this.addHeaderEntry(o,e)})):this.lazyInit=()=>{this.headers=new Map,Object.entries(t).forEach(([e,o])=>{this.setHeaderEntries(e,o)})}:this.headers=new Map}has(t){return this.init(),this.headers.has(t.toLowerCase())}get(t){this.init();let e=this.headers.get(t.toLowerCase());return e&&e.length>0?e[0]:null}keys(){return this.init(),Array.from(this.normalizedNames.values())}getAll(t){return this.init(),this.headers.get(t.toLowerCase())||null}append(t,e){return this.clone({name:t,value:e,op:"a"})}set(t,e){return this.clone({name:t,value:e,op:"s"})}delete(t,e){return this.clone({name:t,value:e,op:"d"})}maybeSetNormalizedName(t,e){this.normalizedNames.has(e)||this.normalizedNames.set(e,t)}init(){this.lazyInit&&(this.lazyInit instanceof n?this.copyFrom(this.lazyInit):this.lazyInit(),this.lazyInit=null,this.lazyUpdate&&(this.lazyUpdate.forEach(t=>this.applyUpdate(t)),this.lazyUpdate=null))}copyFrom(t){t.init();for(let[e,o]of t.headers.entries())this.headers.set(e,o),this.normalizedNames.set(e,t.normalizedNames.get(e))}clone(t){let e=new n;return e.lazyInit=this.lazyInit&&this.lazyInit instanceof n?this.lazyInit:this,e.lazyUpdate=(this.lazyUpdate||[]).concat([t]),e}applyUpdate(t){let e=t.name.toLowerCase();switch(t.op){case"a":case"s":let o=t.value;if(typeof o=="string"&&(o=[o]),o.length===0)return;this.maybeSetNormalizedName(t.name,e);let i=t.op==="a"?(this.headers.get(e)||[]).slice():[];i.push(...o),this.headers.set(e,i);break;case"d":let r=t.value;if(r===void 0)this.headers.delete(e),this.normalizedNames.delete(e);else{let a=Array.isArray(r)?r:[r],s=this.headers.get(e);if(!s)return;s=s.filter(c=>a.indexOf(c)===-1),s.length===0?(this.headers.delete(e),this.normalizedNames.delete(e)):this.headers.set(e,s)}break}}addHeaderEntry(t,e){let o=t.toLowerCase();this.maybeSetNormalizedName(t,o),this.headers.has(o)?this.headers.get(o).push(e):this.headers.set(o,[e])}setHeaderEntries(t,e){let o=(Array.isArray(e)?e:[e]).map(r=>r.toString()),i=t.toLowerCase();this.headers.set(i,o),this.maybeSetNormalizedName(t,i)}forEach(t){this.init(),Array.from(this.normalizedNames.keys()).forEach(e=>t(this.normalizedNames.get(e),this.headers.get(e)))}};var Wl=class{map=new Map;set(t,e){return this.map.set(t,e),this}get(t){return this.map.has(t)||this.map.set(t,t.defaultValue()),this.map.get(t)}delete(t){return this.map.delete(t),this}has(t){return this.map.has(t)}keys(){return this.map.keys()}},Kl=class{encodeKey(t){return y0(t)}encodeValue(t){return y0(t)}decodeKey(t){return decodeURIComponent(t)}decodeValue(t){return decodeURIComponent(t)}};function Ck(n,t){let e=new Map;return n.length>0&&n.replace(/^\?/,"").split("&").forEach(i=>{let r=i.indexOf("="),[a,s]=r==-1?[t.decodeKey(i),""]:[t.decodeKey(i.slice(0,r)),t.decodeValue(i.slice(r+1))],c=e.get(a)||[];c.push(s),e.set(a,c)}),e}var Mk=/%(\d[a-f0-9])/gi,bk={40:"@","3A":":",24:"$","2C":",","3B":";","3D":"=","3F":"?","2F":"/"};function y0(n){return encodeURIComponent(n).replace(Mk,(t,e)=>bk[e]??t)}function ql(n){return`${n}`}var ao=class n{map;encoder;updates=null;cloneFrom=null;constructor(t={}){if(this.encoder=t.encoder||new Kl,t.fromString){if(t.fromObject)throw new z(2805,!1);this.map=Ck(t.fromString,this.encoder)}else t.fromObject?(this.map=new Map,Object.keys(t.fromObject).forEach(e=>{let o=t.fromObject[e],i=Array.isArray(o)?o.map(ql):[ql(o)];this.map.set(e,i)})):this.map=null}has(t){return this.init(),this.map.has(t)}get(t){this.init();let e=this.map.get(t);return e?e[0]:null}getAll(t){return this.init(),this.map.get(t)||null}keys(){return this.init(),Array.from(this.map.keys())}append(t,e){return this.clone({param:t,value:e,op:"a"})}appendAll(t){let e=[];return Object.keys(t).forEach(o=>{let i=t[o];Array.isArray(i)?i.forEach(r=>{e.push({param:o,value:r,op:"a"})}):e.push({param:o,value:i,op:"a"})}),this.clone(e)}set(t,e){return this.clone({param:t,value:e,op:"s"})}delete(t,e){return this.clone({param:t,value:e,op:"d"})}toString(){return this.init(),this.keys().map(t=>{let e=this.encoder.encodeKey(t);return this.map.get(t).map(o=>e+"="+this.encoder.encodeValue(o)).join("&")}).filter(t=>t!=="").join("&")}clone(t){let e=new n({encoder:this.encoder});return e.cloneFrom=this.cloneFrom||this,e.updates=(this.updates||[]).concat(t),e}init(){if(this.map===null&&(this.map=new Map),this.cloneFrom!==null){this.cloneFrom.init();for(let[t,e]of this.cloneFrom.map.entries())this.map.set(t,e);this.updates.forEach(t=>{switch(t.op){case"a":case"s":let e=t.op==="a"?(this.map.get(t.param)||[]).slice():[];e.push(ql(t.value)),this.map.set(t.param,e);break;case"d":if(t.value!==void 0){let o=(this.map.get(t.param)||[]).slice(),i=o.indexOf(ql(t.value));i!==-1&&o.splice(i,1),o.length>0?this.map.set(t.param,o):this.map.delete(t.param)}else{this.map.delete(t.param);break}}}),this.cloneFrom=this.updates=null}}};function Pk(n){switch(n){case"DELETE":case"GET":case"HEAD":case"OPTIONS":case"JSONP":return!1;default:return!0}}function x0(n){return typeof ArrayBuffer<"u"&&n instanceof ArrayBuffer}function w0(n){return typeof Blob<"u"&&n instanceof Blob}function S0(n){return typeof FormData<"u"&&n instanceof FormData}function Ok(n){return typeof URLSearchParams<"u"&&n instanceof URLSearchParams}var ts="Content-Type",Yl="Accept",D0="text/plain",I0="application/json",T0=`${I0}, ${D0}, */*`,Pr=class n{url;body=null;headers;context;reportProgress=!1;reportUploadProgress=!1;reportDownloadProgress=!1;withCredentials=!1;credentials;keepalive=!1;cache;priority;mode;redirect;referrer;integrity;referrerPolicy;responseType="json";method;params;urlWithParams;transferCache;timeout;constructor(t,e,o,i){this.url=e,this.method=t.toUpperCase();let r;if(Pk(this.method)||i?(this.body=o!==void 0?o:null,r=i):r=o,r){if(this.reportProgress=!!r.reportProgress,this.reportUploadProgress=!!r.reportUploadProgress,this.reportDownloadProgress=!!r.reportDownloadProgress,this.withCredentials=!!r.withCredentials,this.keepalive=!!r.keepalive,r.responseType&&(this.responseType=r.responseType),r.headers&&(this.headers=r.headers),r.context&&(this.context=r.context),r.params&&(this.params=r.params),r.priority&&(this.priority=r.priority),r.cache&&(this.cache=r.cache),r.credentials&&(this.credentials=r.credentials),typeof r.timeout=="number"){if(r.timeout<1||!Number.isInteger(r.timeout))throw new z(2822,"");this.timeout=r.timeout}r.mode&&(this.mode=r.mode),r.redirect&&(this.redirect=r.redirect),r.integrity&&(this.integrity=r.integrity),r.referrer!==void 0&&(this.referrer=r.referrer),r.referrerPolicy&&(this.referrerPolicy=r.referrerPolicy),this.transferCache=r.transferCache}if(this.headers??=new Fn,this.context??=new Wl,!this.params)this.params=new ao,this.urlWithParams=e;else{let a=this.params.toString();if(a.length===0)this.urlWithParams=e;else{let s=e,c="",p=e.indexOf("#");p!==-1&&(c=e.substring(p),s=e.substring(0,p));let f=s.indexOf("?"),_=f===-1?"?":fMe.set(Ee,t.setHeaders[Ee]),J)),t.setParams&&(X=Object.keys(t.setParams).reduce((Me,Ee)=>Me.set(Ee,t.setParams[Ee]),X)),new n(e,o,A,{params:X,headers:J,context:W,reportProgress:E,reportUploadProgress:U,reportDownloadProgress:ne,responseType:i,withCredentials:N,transferCache:P,keepalive:r,cache:s,priority:a,timeout:T,mode:c,redirect:p,credentials:f,referrer:_,integrity:C,referrerPolicy:h})}},Rn=(function(n){return n[n.Sent=0]="Sent",n[n.UploadProgress=1]="UploadProgress",n[n.ResponseHeader=2]="ResponseHeader",n[n.DownloadProgress=3]="DownloadProgress",n[n.Response=4]="Response",n[n.User=5]="User",n})(Rn||{}),Or=class{headers;status;statusText;url;ok;type;redirected;responseType;constructor(t,e=200,o="OK"){this.headers=t.headers||new Fn,this.status=t.status!==void 0?t.status:e,this.statusText=t.statusText||o,this.url=t.url||null,this.redirected=t.redirected,this.responseType=t.responseType,this.ok=this.status>=200&&this.status<300}},ns=class n extends Or{constructor(t={}){super(t)}type=Rn.ResponseHeader;clone(t={}){return new n({headers:t.headers||this.headers,status:t.status!==void 0?t.status:this.status,statusText:t.statusText||this.statusText,url:t.url||this.url||void 0})}},vr=class n extends Or{body;constructor(t={}){super(t),this.body=t.body!==void 0?t.body:null}type=Rn.Response;clone(t={}){return new n({body:t.body!==void 0?t.body:this.body,headers:t.headers||this.headers,status:t.status!==void 0?t.status:this.status,statusText:t.statusText||this.statusText,url:t.url||this.url||void 0,redirected:t.redirected??this.redirected,responseType:t.responseType??this.responseType})}},Nn=class extends Or{name="HttpErrorResponse";message;error;ok=!1;constructor(t){super(t,0,"Unknown Error"),this.status>=200&&this.status<300?this.message=`Http failure during parsing for ${t.url||"(unknown url)"}`:this.message=`Http failure response for ${t.url||"(unknown url)"}: ${t.status} ${t.statusText}`,this.error=t.error||null}},A0=200,vk=204;var yk=/^\)\]\}',?\n/,Dq=1024*1024,N0=new B("",{factory:()=>null}),Zl=(()=>{class n{fetchImpl=D(gf,{optional:!0})?.fetch??((...e)=>globalThis.fetch(...e));ngZone=D(ge);destroyRef=D(Ae);maxResponseSize=D(N0);handle(e){return new ie(o=>{let i=new AbortController,r=!1,a={next:c=>{c.type===Rn.Response&&(r=!0),o.next(c)},error:c=>{r=!0,o.error(c)},complete:()=>{r=!0,o.complete()}};this.doRequest(e,i.signal,a).then(pf,c=>a.error(new Nn({error:c})));let s;return e.timeout&&(s=this.ngZone.runOutsideAngular(()=>setTimeout(()=>{i.signal.aborted||i.abort(new DOMException("signal timed out","TimeoutError"))},e.timeout))),()=>{s!==void 0&&clearTimeout(s),!r&&!i.signal.aborted&&i.abort()}})}doRequest(e,o,i){return be(this,null,function*(){let r=this.createRequestInit(e),a;try{let A=this.ngZone.runOutsideAngular(()=>this.fetchImpl(e.urlWithParams,S({signal:o},r)));xk(A),i.next({type:Rn.Sent}),a=yield A}catch(A){i.error(new Nn({error:A,status:A.status??0,statusText:A.statusText,url:e.urlWithParams,headers:A.headers}));return}let s=new Fn(a.headers),c=a.statusText,p=a.url||e.urlWithParams,f=a.status,_=null,C=e.reportProgress||e.reportDownloadProgress;if(C&&i.next(new ns({headers:s,status:f,statusText:c,url:p})),a.body){let A=a.headers.get(ts)??"",N=a.headers.get("content-length"),E=N!==null?Number(N):NaN;this.maxResponseSize!==null&&Number.isFinite(E)&&E>this.maxResponseSize&&(yield a.body.cancel(),k0(this.maxResponseSize));let U=[],ne=a.body.getReader(),J=0,X,W,Me=typeof Zone<"u"&&Zone.current,Ee=!1;if(yield this.ngZone.runOutsideAngular(()=>be(this,null,function*(){for(;;){if(this.destroyRef.destroyed){yield ne.cancel(),Ee=!0;break}let{done:Jt,value:Xt}=yield ne.read();if(Jt)break;if(U.push(Xt),J+=Xt.length,this.maxResponseSize!==null&&J>this.maxResponseSize&&(yield ne.cancel(),k0(this.maxResponseSize)),C){W=e.responseType==="text"?(W??"")+(X??=E0(A)).decode(Xt,{stream:!0}):void 0;let $t=()=>i.next({type:Rn.DownloadProgress,total:Number.isFinite(E)?E:void 0,loaded:J,partialText:W});Me?Me.run($t):$t()}}})),Ee){i.complete();return}let ft=this.concatChunks(U,J);try{_=this.parseBody(e,ft,A,f)}catch(Jt){i.error(new Nn({error:Jt,headers:new Fn(a.headers),status:a.status,statusText:a.statusText,url:a.url||e.urlWithParams}));return}}f===0&&(f=_?A0:0);let h=f>=200&&f<300,P=a.redirected,T=a.type;h?(i.next(new vr({body:_,headers:s,status:f,statusText:c,url:p,redirected:P,responseType:T})),i.complete()):i.error(new Nn({error:_,headers:s,status:f,statusText:c,url:p,redirected:P,responseType:T}))})}parseBody(e,o,i,r){switch(e.responseType){case"json":let a=new TextDecoder().decode(o).replace(yk,"");if(a==="")return null;try{return JSON.parse(a)}catch(s){if(r<200||r>=300)return a;throw s}case"text":return E0(i).decode(o);case"blob":return new Blob([o],{type:i});case"arraybuffer":return o.buffer}}createRequestInit(e){if(e.reportUploadProgress)throw new z(2824,!1);let o={},i;if(i=e.credentials,e.withCredentials&&(i="include"),e.headers.forEach((r,a)=>o[r]=a.join(",")),e.headers.has(Yl)||(o[Yl]=T0),!e.headers.has(ts)){let r=e.detectContentTypeHeader();r!==null&&(o[ts]=r)}return{body:e.serializeBody(),method:e.method,headers:o,credentials:i,keepalive:e.keepalive,cache:e.cache,priority:e.priority,mode:e.mode,redirect:e.redirect,referrer:e.referrer,integrity:e.integrity,referrerPolicy:e.referrerPolicy}}concatChunks(e,o){let i=new Uint8Array(o),r=0;for(let a of e)i.set(a,r),r+=a.length;return i}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})(),gf=class{};function pf(){}function xk(n){n.then(pf,pf)}function k0(n){throw new z(-2825,!1)}var wk=/charset=\s*["']?([^;"'\s]+)["']?/i;function E0(n){let t=n.match(wk);if(t!==null)try{return new TextDecoder(t[1])}catch(e){}return new TextDecoder}var Sk=new B("",{factory:()=>!0}),kk="XSRF-TOKEN",Ek=new B("",{factory:()=>kk}),Dk="X-XSRF-TOKEN",Ik=new B("",{factory:()=>Dk}),Tk=(()=>{class n{cookieName=D(Ek);doc=D(Ue);lastCookieString="";lastToken=null;parseCount=0;getToken(){let e=this.doc.cookie||"";return e!==this.lastCookieString&&(this.parseCount++,this.lastToken=Za(e,this.cookieName),this.lastCookieString=e),this.lastToken}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})(),R0=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275prov=te({token:n,factory:function(o){let i=null;return o?i=new(o||n):i=Q(Tk),i},providedIn:"root"})}return n})();function F0(n,t){if(!D(Sk)||n.method==="GET"||n.method==="HEAD")return t(n);try{let i=D(Cr).href,{origin:r}=new URL(i),{origin:a}=new URL(n.url,r);if(r!==a)return t(n)}catch(i){return t(n)}let e=D(R0).getToken(),o=D(Ik);return e!=null&&!n.headers.has(o)&&(n=n.clone({headers:n.headers.set(o,e)})),t(n)}function Ak(n,t){return t(n)}function Nk(n,t,e){return(o,i)=>et(e,()=>t(o,r=>n(r,i)))}var L0=new B("",{factory:()=>[F0]}),V0=new B(""),j0=new B("",{factory:()=>!0});var Jl=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275prov=te({token:n,factory:function(o){let i=null;return o?i=new(o||n):i=Q(Zl),i},providedIn:"root"})}return n})();var Ql=(()=>{class n{backend;injector;chain=null;pendingTasks=D(Oa);contributeToStability=D(j0);constructor(e,o){this.backend=e,this.injector=o}handle(e){if(this.chain===null){let i=this.injector.get(Xl,null,{skipSelf:!0}),r=i!==null&&this.backend===i,a=this.injector.get(V0,[],r?{self:!0}:void 0),s=Array.from(new Set([...this.injector.get(L0),...a]));this.chain=s.reduceRight((c,p)=>Nk(c,p,this.injector),Ak)}let o=this.chain;if(this.contributeToStability){let i=this.pendingTasks.add();return de(()=>o(e,r=>this.backend.handle(r))).pipe(_o(i))}else return de(()=>o(e,i=>this.backend.handle(i)))}static \u0275fac=function(o){return new(o||n)(Q(Jl),Q(Le))};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})}return n})(),Xl=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275prov=te({token:n,factory:function(o){let i=null;return o?i=new(o||n):i=Q(Ql),i},providedIn:"root"})}return n})();function uf(n,t){return S({body:t},n)}var Ro=(()=>{class n{handler;constructor(e){this.handler=e}request(e,o,i={}){let r;if(e instanceof Pr)r=e;else{let c;i.headers instanceof Fn?c=i.headers:c=new Fn(i.headers);let p;i.params&&(i.params instanceof ao?p=i.params:p=new ao({fromObject:i.params})),r=new Pr(e,o,i.body!==void 0?i.body:null,{headers:c,context:i.context,params:p,reportProgress:i.reportProgress,reportUploadProgress:i.reportUploadProgress,reportDownloadProgress:i.reportDownloadProgress,responseType:i.responseType||"json",withCredentials:i.withCredentials,transferCache:i.transferCache,keepalive:i.keepalive,priority:i.priority,cache:i.cache,mode:i.mode,redirect:i.redirect,credentials:i.credentials,referrer:i.referrer,referrerPolicy:i.referrerPolicy,integrity:i.integrity,timeout:i.timeout})}let a=se(r).pipe(Jo(c=>this.handler.handle(c)));if(e instanceof Pr||i.observe==="events")return a;let s=a.pipe(Bt(c=>c instanceof vr));switch(i.observe||"body"){case"body":switch(r.responseType){case"arraybuffer":return s.pipe(Pe(c=>{if(c.body!==null&&!(c.body instanceof ArrayBuffer))throw new z(2806,!1);return c.body}));case"blob":return s.pipe(Pe(c=>{if(c.body!==null&&!(c.body instanceof Blob))throw new z(2807,!1);return c.body}));case"text":return s.pipe(Pe(c=>{if(c.body!==null&&typeof c.body!="string")throw new z(2808,!1);return c.body}));default:return s.pipe(Pe(c=>c.body))}case"response":return s;default:throw new z(2809,!1)}}delete(e,o={}){return this.request("DELETE",e,o)}get(e,o={}){return this.request("GET",e,o)}head(e,o={}){return this.request("HEAD",e,o)}jsonp(e,o){return this.request("JSONP",e,{params:new ao().append(o,"JSONP_CALLBACK"),observe:"body",responseType:"json"})}options(e,o={}){return this.request("OPTIONS",e,o)}patch(e,o,i={}){return this.request("PATCH",e,uf(i,o))}post(e,o,i={}){return this.request("POST",e,uf(i,o))}put(e,o,i={}){return this.request("PUT",e,uf(i,o))}static \u0275fac=function(o){return new(o||n)(Q(Xl))};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})}return n})();var Rk=/^\)\]\}',?\n/;var ff=(()=>{class n{xhrFactory;tracingService=D(Tn,{optional:!0});constructor(e){this.xhrFactory=e}maybePropagateTrace(e){return this.tracingService?.propagate?this.tracingService.propagate(e):e}handle(e){if(e.method==="JSONP")throw new z(-2800,!1);let o=this.xhrFactory;return se(null).pipe(vt(()=>new ie(r=>{let a=o.build();if(a.open(e.method,e.urlWithParams),e.withCredentials&&(a.withCredentials=!0),e.headers.forEach((E,U)=>a.setRequestHeader(E,U.join(","))),e.headers.has(Yl)||a.setRequestHeader(Yl,T0),!e.headers.has(ts)){let E=e.detectContentTypeHeader();E!==null&&a.setRequestHeader(ts,E)}if(e.timeout&&(a.timeout=e.timeout),e.responseType){let E=e.responseType.toLowerCase();a.responseType=E!=="json"?E:"text"}let s=e.serializeBody(),c=null,p=()=>{if(c!==null)return c;let E=a.statusText||"OK",U=new Fn(a.getAllResponseHeaders()),ne=a.responseURL||e.url;return c=new ns({headers:U,status:a.status,statusText:E,url:ne}),c},f=this.maybePropagateTrace(()=>{let{headers:E,status:U,statusText:ne,url:J}=p(),X=null;U!==vk&&(X=typeof a.response>"u"?a.responseText:a.response),U===0&&(U=X?A0:0);let W=U>=200&&U<300;if(e.responseType==="json"&&typeof X=="string"){let Me=X;X=X.replace(Rk,"");try{X=X!==""?JSON.parse(X):null}catch(Ee){X=Me,W&&(W=!1,X={error:Ee,text:X})}}W?(r.next(new vr({body:X,headers:E,status:U,statusText:ne,url:J||void 0})),r.complete()):r.error(new Nn({error:X,headers:E,status:U,statusText:ne,url:J||void 0}))}),_=this.maybePropagateTrace(E=>{let{url:U}=p(),ne=new Nn({error:E,status:a.status||0,statusText:a.statusText||"Unknown Error",url:U||void 0});r.error(ne)}),C=_;e.timeout&&(C=this.maybePropagateTrace(E=>{let{url:U}=p(),ne=new Nn({error:new DOMException("Request timed out","TimeoutError"),status:a.status||0,statusText:a.statusText||"Request timeout",url:U||void 0});r.error(ne)}));let h=!1,P=this.maybePropagateTrace(E=>{h||(r.next(p()),h=!0);let U={type:Rn.DownloadProgress,loaded:E.loaded};E.lengthComputable&&(U.total=E.total),e.responseType==="text"&&a.responseText&&(U.partialText=a.responseText),r.next(U)}),T=this.maybePropagateTrace(E=>{let U={type:Rn.UploadProgress,loaded:E.loaded};E.lengthComputable&&(U.total=E.total),r.next(U)});a.addEventListener("load",f),a.addEventListener("error",_),a.addEventListener("timeout",C),a.addEventListener("abort",_);let A=e.reportProgress||e.reportUploadProgress,N=e.reportProgress||e.reportDownloadProgress;return N&&a.addEventListener("progress",P),A&&s!==null&&a.upload&&a.upload.addEventListener("progress",T),a.send(s),r.next({type:Rn.Sent}),()=>{a.removeEventListener("error",_),a.removeEventListener("abort",_),a.removeEventListener("load",f),a.removeEventListener("timeout",C),N&&a.removeEventListener("progress",P),A&&s!==null&&a.upload&&a.upload.removeEventListener("progress",T),a.readyState!==a.DONE&&a.abort()}})))}static \u0275fac=function(o){return new(o||n)(Q(tf))};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})}return n})(),mf=(function(n){return n[n.Interceptors=0]="Interceptors",n[n.LegacyInterceptors=1]="LegacyInterceptors",n[n.CustomXsrfConfiguration=2]="CustomXsrfConfiguration",n[n.NoXsrfProtection=3]="NoXsrfProtection",n[n.JsonpSupport=4]="JsonpSupport",n[n.RequestsMadeViaParent=5]="RequestsMadeViaParent",n[n.Fetch=6]="Fetch",n[n.Xhr=7]="Xhr",n})(mf||{});function Fk(n,t){return{\u0275kind:n,\u0275providers:t}}function _f(...n){let t=[Ro,Zl,Ql,{provide:Xl,useExisting:Ql},{provide:Jl,useFactory:()=>D(Zl)},{provide:L0,useValue:F0,multi:!0}];for(let e of n)t.push(...e.\u0275providers);return bo(t)}function hf(){return Fk(mf.Xhr,[ff,{provide:Jl,useExisting:ff}])}var $0=(()=>{class n{_doc;constructor(e){this._doc=e}getTitle(){return this._doc.title}setTitle(e){this._doc.title=e||""}static \u0275fac=function(o){return new(o||n)(Q(Ue))};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})}return n})();var re="primary",_s=Symbol("RouteTitle"),Of=class{params;constructor(t){this.params=t||{}}has(t){return Object.hasOwn(this.params,t)}get(t){if(this.has(t)){let e=this.params[t];return Array.isArray(e)?e[0]:e}return null}getAll(t){if(this.has(t)){let e=this.params[t];return Array.isArray(e)?e:[e]}return[]}get keys(){return Object.keys(this.params)}};function Ii(n){return new Of(n)}function Cf(n,t,e){for(let o=0;on.length||e.pathMatch==="full"&&(t.hasChildren()||o.lengthn.length||e.pathMatch==="full"&&t.hasChildren()&&e.path!=="**")return null;let s={};return!Cf(r,n.slice(0,r.length),s)||!Cf(a,n.slice(n.length-a.length),s)?null:{consumed:n,posParams:s}}function rd(n){return new Promise((t,e)=>{n.pipe(Hn()).subscribe({next:o=>t(o),error:o=>e(o)})})}function jk(n,t){if(n.length!==t.length)return!1;for(let e=0;eo[r]===i)}else return n===t}function $k(n){return n.length>0?n[n.length-1]:null}function Ni(n){return nc(n)?n:Eo(n)?Fe(Promise.resolve(n)):se(n)}function Y0(n){return nc(n)?rd(n):Promise.resolve(n)}var zk={exact:Q0,subset:J0},Z0={exact:Bk,subset:Hk,ignored:()=>!0},Vf={paths:"exact",fragment:"ignored",matrixParams:"ignored",queryParams:"exact"},Sr={paths:"subset",fragment:"ignored",matrixParams:"ignored",queryParams:"subset"};function jf(n,t,e){let o=n instanceof bt?n:t.parseUrl(n);return I(()=>yf(t.lastSuccessfulNavigation()?.finalUrl??new bt,o,S(S({},Sr),e)))}function yf(n,t,e){return zk[e.paths](n.root,t.root,e.matrixParams)&&Z0[e.queryParams](n.queryParams,t.queryParams)&&!(e.fragment==="exact"&&n.fragment!==t.fragment)}function Bk(n,t){return Ln(n,t)}function Q0(n,t,e){if(!Di(n.segments,t.segments)||!nd(n.segments,t.segments,e)||n.numberOfChildren!==t.numberOfChildren)return!1;for(let o in t.children)if(!n.children[o]||!Q0(n.children[o],t.children[o],e))return!1;return!0}function Hk(n,t){return Object.keys(t).length<=Object.keys(n).length&&Object.keys(t).every(e=>K0(n[e],t[e]))}function J0(n,t,e){return X0(n,t,t.segments,e)}function X0(n,t,e,o){if(n.segments.length>e.length){let i=n.segments.slice(0,e.length);return!(!Di(i,e)||t.hasChildren()||!nd(i,e,o))}else if(n.segments.length===e.length){if(!Di(n.segments,e)||!nd(n.segments,e,o))return!1;for(let i in t.children)if(!n.children[i]||!J0(n.children[i],t.children[i],o))return!1;return!0}else{let i=e.slice(0,n.segments.length),r=e.slice(n.segments.length);return!Di(n.segments,i)||!nd(n.segments,i,o)||!n.children[re]?!1:X0(n.children[re],t,r,o)}}function nd(n,t,e){return t.every((o,i)=>Z0[e](n[i].parameters,o.parameters))}var bt=class{root;queryParams;fragment;_queryParamMap;constructor(t=new me([],{}),e={},o=null){this.root=t,this.queryParams=e,this.fragment=o}get queryParamMap(){return this._queryParamMap??=Ii(this.queryParams),this._queryParamMap}toString(){return qk.serialize(this)}},me=class{segments;children;parent=null;constructor(t,e){this.segments=t,this.children=e,Object.values(e).forEach(o=>o.parent=this)}hasChildren(){return this.numberOfChildren>0}get numberOfChildren(){return Object.keys(this.children).length}toString(){return od(this)}},Fo=class{path;parameters;_parameterMap;constructor(t,e){this.path=t,this.parameters=e}get parameterMap(){return this._parameterMap??=Ii(this.parameters),this._parameterMap}toString(){return tb(this)}};function Uk(n,t){return Di(n,t)&&n.every((e,o)=>Ln(e.parameters,t[o].parameters))}function Di(n,t){return n.length!==t.length?!1:n.every((e,o)=>e.path===t[o].path)}function Gk(n,t){let e=[];return Object.entries(n.children).forEach(([o,i])=>{o===re&&(e=e.concat(t(i,o)))}),Object.entries(n.children).forEach(([o,i])=>{o!==re&&(e=e.concat(t(i,o)))}),e}var Ar=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:()=>new Lo})}return n})(),Lo=class{parse(t){let e=new wf(t);return new bt(e.parseRootSegment(),e.parseQueryParams(),e.parseFragment())}serialize(t){let e=`/${os(t.root,!0)}`,o=Yk(t.queryParams),i=typeof t.fragment=="string"?`#${Wk(t.fragment)}`:"";return`${e}${o}${i}`}},qk=new Lo;function od(n){return n.segments.map(t=>tb(t)).join("/")}function os(n,t){if(!n.hasChildren())return od(n);if(t){let e=n.children[re]?os(n.children[re],!1):"",o=[];return Object.entries(n.children).forEach(([i,r])=>{i!==re&&o.push(`${i}:${os(r,!1)}`)}),o.length>0?`${e}(${o.join("//")})`:e}else{let e=Gk(n,(o,i)=>i===re?[os(n.children[re],!1)]:[`${i}:${os(o,!1)}`]);return Object.keys(n.children).length===1&&n.children[re]!=null?`${od(n)}/${e[0]}`:`${od(n)}/(${e.join("//")})`}}function eb(n){return encodeURIComponent(n).replace(/%40/g,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",")}function ed(n){return eb(n).replace(/%3B/gi,";")}function Wk(n){return encodeURI(n)}function xf(n){return eb(n).replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/%26/gi,"&")}function id(n){return decodeURIComponent(n)}function z0(n){return id(n.replace(/\+/g,"%20"))}function tb(n){return`${xf(n.path)}${Kk(n.parameters)}`}function Kk(n){return Object.entries(n).map(([t,e])=>`;${xf(t)}=${xf(e)}`).join("")}function Yk(n){let t=Object.entries(n).map(([e,o])=>Array.isArray(o)?o.map(i=>`${ed(e)}=${ed(i)}`).join("&"):`${ed(e)}=${ed(o)}`).filter(e=>e);return t.length?`?${t.join("&")}`:""}var Zk=/^[^\/()?;#]+/;function Mf(n){let t=n.match(Zk);return t?t[0]:""}var Qk=/^[^\/()?;=#]+/;function Jk(n){let t=n.match(Qk);return t?t[0]:""}var Xk=/^[^=?&#]+/;function e2(n){let t=n.match(Xk);return t?t[0]:""}var t2=/^[^&#]+/;function n2(n){let t=n.match(t2);return t?t[0]:""}var wf=class{url;remaining;constructor(t){this.url=t,this.remaining=t}parseRootSegment(){for(;this.consumeOptional("/"););return this.remaining===""||this.peekStartsWith("?")||this.peekStartsWith("#")?new me([],{}):new me([],this.parseChildren())}parseQueryParams(){let t={};if(this.consumeOptional("?"))do this.parseQueryParam(t);while(this.consumeOptional("&"));return t}parseFragment(){return this.consumeOptional("#")?decodeURIComponent(this.remaining):null}parseChildren(t=0){if(t>50)throw new z(4010,!1);if(this.remaining==="")return{};this.consumeOptional("/");let e=[];for(this.peekStartsWith("(")||e.push(this.parseSegment());this.peekStartsWith("/")&&!this.peekStartsWith("//")&&!this.peekStartsWith("/(");)this.capture("/"),e.push(this.parseSegment());let o={};this.peekStartsWith("/(")&&(this.capture("/"),o=this.parseParens(!0,t));let i={};return this.peekStartsWith("(")&&(i=this.parseParens(!1,t)),(e.length>0||Object.keys(o).length>0)&&(i[re]=new me(e,o)),i}parseSegment(){let t=Mf(this.remaining);if(t===""&&this.peekStartsWith(";"))throw new z(4009,!1);return this.capture(t),new Fo(id(t),this.parseMatrixParams())}parseMatrixParams(){let t={};for(;this.consumeOptional(";");)this.parseParam(t);return t}parseParam(t){let e=Jk(this.remaining);if(!e)return;this.capture(e);let o="";if(this.consumeOptional("=")){let i=Mf(this.remaining);i&&(o=i,this.capture(o))}t[id(e)]=id(o)}parseQueryParam(t){let e=e2(this.remaining);if(!e)return;this.capture(e);let o="";if(this.consumeOptional("=")){let a=n2(this.remaining);a&&(o=a,this.capture(o))}let i=z0(e),r=z0(o);if(Object.hasOwn(t,i)){let a=t[i];Array.isArray(a)||(a=[a],t[i]=a),a.push(r)}else t[i]=r}parseParens(t,e){let o=Object.create(null);for(this.capture("(");!this.consumeOptional(")")&&this.remaining.length>0;){let i=Mf(this.remaining),r=this.remaining[i.length];if(r!=="/"&&r!==")"&&r!==";")throw new z(4010,!1);let a;i.indexOf(":")>-1?(a=i.slice(0,i.indexOf(":")),this.capture(a),this.capture(":")):t&&(a=re);let s=this.parseChildren(e+1);o[a??re]=Object.keys(s).length===1&&s[re]?s[re]:new me([],s),this.consumeOptional("//")}return o}peekStartsWith(t){return this.remaining.startsWith(t)}consumeOptional(t){return this.peekStartsWith(t)?(this.remaining=this.remaining.substring(t.length),!0):!1}capture(t){if(!this.consumeOptional(t))throw new z(4011,!1)}};function nb(n){return n.segments.length>0?new me([],{[re]:n}):n}function ob(n){let t=Object.create(null);for(let[o,i]of Object.entries(n.children)){let r=ob(i);if(o===re&&r.segments.length===0&&r.hasChildren())for(let[a,s]of Object.entries(r.children))t[a]=s;else(r.segments.length>0||r.hasChildren())&&(t[o]=r)}let e=new me(n.segments,t);return o2(e)}function o2(n){if(n.numberOfChildren===1&&n.children[re]){let t=n.children[re];return new me(n.segments.concat(t.segments),t.children)}return n}function Vo(n){return n instanceof bt}function ib(n,t,e=null,o=null,i=new Lo){let r=rb(n);return ab(r,t,e,o,i)}function rb(n){let t;function e(r){let a={};for(let c of r.children){let p=e(c);a[c.outlet]=p}let s=new me(r.url,a);return r===n&&(t=s),s}let o=e(n.root),i=nb(o);return t??i}function ab(n,t,e,o,i){let r=n;for(;r.parent;)r=r.parent;if(t.length===0)return bf(r,r,r,e,o,i);let a=i2(t);if(a.toRoot())return bf(r,r,new me([],{}),e,o,i);let s=r2(a,r,n),c=s.processChildren?rs(s.segmentGroup,s.index,a.commands):cb(s.segmentGroup,s.index,a.commands);return bf(r,s.segmentGroup,c,e,o,i)}function ad(n){return typeof n=="object"&&n!=null&&!n.outlets&&!n.segmentPath}function cs(n){return typeof n=="object"&&n!=null&&n.outlets}function B0(n,t,e){n||="\u0275";let o=new bt;return o.queryParams={[n]:t},e.parse(e.serialize(o)).queryParams[n]}function bf(n,t,e,o,i,r){let a={};for(let[p,f]of Object.entries(o??{}))a[p]=Array.isArray(f)?f.map(_=>B0(p,_,r)):B0(p,f,r);let s;n===t?s=e:s=sb(n,t,e);let c=nb(ob(s));return new bt(c,a,i)}function sb(n,t,e){let o=Object.create(null);return Object.entries(n.children).forEach(([i,r])=>{r===t?o[i]=e:o[i]=sb(r,t,e)}),new me(n.segments,o)}var sd=class{isAbsolute;numberOfDoubleDots;commands;constructor(t,e,o){if(this.isAbsolute=t,this.numberOfDoubleDots=e,this.commands=o,t&&o.length>0&&ad(o[0]))throw new z(4003,!1);let i=o.find(cs);if(i&&i!==$k(o))throw new z(4004,!1)}toRoot(){return this.isAbsolute&&this.commands.length===1&&this.commands[0]=="/"}};function i2(n){if(typeof n[0]=="string"&&n.length===1&&n[0]==="/")return new sd(!0,0,n);let t=0,e=!1,o=n.reduce((i,r,a)=>{if(typeof r=="object"&&r!=null){if(r.outlets){let s={};return Object.entries(r.outlets).forEach(([c,p])=>{s[c]=typeof p=="string"?p.split("/"):p}),[...i,{outlets:s}]}if(r.segmentPath)return[...i,r.segmentPath]}return typeof r!="string"?[...i,r]:a===0?(r.split("/").forEach((s,c)=>{c==0&&s==="."||(c==0&&s===""?e=!0:s===".."?t++:s!=""&&i.push(s))}),i):[...i,r]},[]);return new sd(e,t,o)}var xr=class{segmentGroup;processChildren;index;constructor(t,e,o){this.segmentGroup=t,this.processChildren=e,this.index=o}};function r2(n,t,e){if(n.isAbsolute)return new xr(t,!0,0);if(!e)return new xr(t,!1,NaN);if(e.parent===null)return new xr(e,!0,0);let o=ad(n.commands[0])?0:1,i=e.segments.length-1+o;return a2(e,i,n.numberOfDoubleDots)}function a2(n,t,e){let o=n,i=t,r=e;for(;r>i;){if(r-=i,o=o.parent,!o)throw new z(4005,!1);i=o.segments.length}return new xr(o,!1,i-r)}function s2(n){return cs(n[0])?n[0].outlets:{[re]:n}}function cb(n,t,e){if(n??=new me([],{}),n.segments.length===0&&n.hasChildren())return rs(n,t,e);let o=c2(n,t,e),i=e.slice(o.commandIndex);if(o.match&&o.pathIndexr!==re)&&n.children[re]&&n.numberOfChildren===1&&n.children[re].segments.length===0){let r=rs(n.children[re],t,e);return new me(n.segments,r.children)}return Object.entries(o).forEach(([r,a])=>{typeof a=="string"&&(a=[a]),a!==null&&(i[r]=cb(n.children[r],t,a))}),Object.entries(n.children).forEach(([r,a])=>{o[r]===void 0&&(i[r]=a)}),new me(n.segments,i)}}function c2(n,t,e){let o=0,i=t,r={match:!1,pathIndex:0,commandIndex:0};for(;i=e.length)return r;let a=n.segments[i],s=e[o];if(cs(s))break;let c=`${s}`,p=o0&&c===void 0)break;if(c&&p&&typeof p=="object"&&p.outlets===void 0){if(!U0(c,p,a))return r;o+=2}else{if(!U0(c,{},a))return r;o++}i++}return{match:!0,pathIndex:i,commandIndex:o}}function Sf(n,t,e){let o=n.segments.slice(0,t),i=0;for(;i{typeof o=="string"&&(o=[o]),o!==null&&(t[e]=Sf(new me([],{}),0,o))}),t}function H0(n){let t={};return Object.entries(n).forEach(([e,o])=>t[e]=`${o}`),t}function U0(n,t,e){return n==e.path&&Ln(t,e.parameters)}var as="imperative",rt=(function(n){return n[n.NavigationStart=0]="NavigationStart",n[n.NavigationEnd=1]="NavigationEnd",n[n.NavigationCancel=2]="NavigationCancel",n[n.NavigationError=3]="NavigationError",n[n.RoutesRecognized=4]="RoutesRecognized",n[n.ResolveStart=5]="ResolveStart",n[n.ResolveEnd=6]="ResolveEnd",n[n.GuardsCheckStart=7]="GuardsCheckStart",n[n.GuardsCheckEnd=8]="GuardsCheckEnd",n[n.RouteConfigLoadStart=9]="RouteConfigLoadStart",n[n.RouteConfigLoadEnd=10]="RouteConfigLoadEnd",n[n.ChildActivationStart=11]="ChildActivationStart",n[n.ChildActivationEnd=12]="ChildActivationEnd",n[n.ActivationStart=13]="ActivationStart",n[n.ActivationEnd=14]="ActivationEnd",n[n.Scroll=15]="Scroll",n[n.NavigationSkipped=16]="NavigationSkipped",n})(rt||{}),jt=class{id;url;constructor(t,e){this.id=t,this.url=e}},Ti=class extends jt{type=rt.NavigationStart;navigationTrigger;restoredState;constructor(t,e,o="imperative",i=null){super(t,e),this.navigationTrigger=o,this.restoredState=i}toString(){return`NavigationStart(id: ${this.id}, url: '${this.url}')`}},mn=class extends jt{urlAfterRedirects;type=rt.NavigationEnd;constructor(t,e,o){super(t,e),this.urlAfterRedirects=o}toString(){return`NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`}},pt=(function(n){return n[n.Redirect=0]="Redirect",n[n.SupersededByNewNavigation=1]="SupersededByNewNavigation",n[n.NoDataFromResolver=2]="NoDataFromResolver",n[n.GuardRejected=3]="GuardRejected",n[n.Aborted=4]="Aborted",n})(pt||{}),ls=(function(n){return n[n.IgnoredSameUrlNavigation=0]="IgnoredSameUrlNavigation",n[n.IgnoredByUrlHandlingStrategy=1]="IgnoredByUrlHandlingStrategy",n})(ls||{}),Zt=class extends jt{reason;code;type=rt.NavigationCancel;constructor(t,e,o,i){super(t,e),this.reason=o,this.code=i}toString(){return`NavigationCancel(id: ${this.id}, url: '${this.url}')`}};function lb(n){return n instanceof Zt&&(n.code===pt.Redirect||n.code===pt.SupersededByNewNavigation)}var co=class extends jt{reason;code;type=rt.NavigationSkipped;constructor(t,e,o,i){super(t,e),this.reason=o,this.code=i}},Ai=class extends jt{error;target;type=rt.NavigationError;constructor(t,e,o,i){super(t,e),this.error=o,this.target=i}toString(){return`NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`}},ds=class extends jt{urlAfterRedirects;state;type=rt.RoutesRecognized;constructor(t,e,o,i){super(t,e),this.urlAfterRedirects=o,this.state=i}toString(){return`RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`}},cd=class extends jt{urlAfterRedirects;state;type=rt.GuardsCheckStart;constructor(t,e,o,i){super(t,e),this.urlAfterRedirects=o,this.state=i}toString(){return`GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`}},ld=class extends jt{urlAfterRedirects;state;shouldActivate;type=rt.GuardsCheckEnd;constructor(t,e,o,i,r){super(t,e),this.urlAfterRedirects=o,this.state=i,this.shouldActivate=r}toString(){return`GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`}},dd=class extends jt{urlAfterRedirects;state;type=rt.ResolveStart;constructor(t,e,o,i){super(t,e),this.urlAfterRedirects=o,this.state=i}toString(){return`ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`}},ud=class extends jt{urlAfterRedirects;state;type=rt.ResolveEnd;constructor(t,e,o,i){super(t,e),this.urlAfterRedirects=o,this.state=i}toString(){return`ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`}},gd=class{route;type=rt.RouteConfigLoadStart;constructor(t){this.route=t}toString(){return`RouteConfigLoadStart(path: ${this.route.path})`}},pd=class{route;type=rt.RouteConfigLoadEnd;constructor(t){this.route=t}toString(){return`RouteConfigLoadEnd(path: ${this.route.path})`}},fd=class{snapshot;type=rt.ChildActivationStart;constructor(t){this.snapshot=t}toString(){return`ChildActivationStart(path: '${this.snapshot.routeConfig&&this.snapshot.routeConfig.path||""}')`}},md=class{snapshot;type=rt.ChildActivationEnd;constructor(t){this.snapshot=t}toString(){return`ChildActivationEnd(path: '${this.snapshot.routeConfig&&this.snapshot.routeConfig.path||""}')`}},_d=class{snapshot;type=rt.ActivationStart;constructor(t){this.snapshot=t}toString(){return`ActivationStart(path: '${this.snapshot.routeConfig&&this.snapshot.routeConfig.path||""}')`}},hd=class{snapshot;type=rt.ActivationEnd;constructor(t){this.snapshot=t}toString(){return`ActivationEnd(path: '${this.snapshot.routeConfig&&this.snapshot.routeConfig.path||""}')`}};var kr=class{},us=class{},Er=class{url;navigationBehaviorOptions;constructor(t,e){this.url=t,this.navigationBehaviorOptions=e}};function d2(n){return!(n instanceof kr)&&!(n instanceof Er)&&!(n instanceof us)}var Cd=class{rootInjector;outlet=null;route=null;children;attachRef=null;get injector(){return this.route?.snapshot._environmentInjector??this.rootInjector}constructor(t){this.rootInjector=t,this.children=new Nr(this.rootInjector)}},Nr=(()=>{class n{rootInjector;contexts=new Map;constructor(e){this.rootInjector=e}onChildOutletCreated(e,o){let i=this.getOrCreateContext(e);i.outlet=o,this.contexts.set(e,i)}onChildOutletDestroyed(e){let o=this.getContext(e);o&&(o.outlet=null,o.attachRef=null)}onOutletDeactivated(){let e=this.contexts;return this.contexts=new Map,e}onOutletReAttached(e){this.contexts=e}getOrCreateContext(e){let o=this.getContext(e);return o||(o=new Cd(this.rootInjector),this.contexts.set(e,o)),o}getContext(e){return this.contexts.get(e)||null}static \u0275fac=function(o){return new(o||n)(Q(Le))};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})}return n})(),Md=class{_root;constructor(t){this._root=t}get root(){return this._root.value}parent(t){let e=this.pathFromRoot(t);return e.length>1?e[e.length-2]:null}children(t){let e=kf(t,this._root);return e?e.children.map(o=>o.value):[]}firstChild(t){let e=kf(t,this._root);return e&&e.children.length>0?e.children[0].value:null}siblings(t){let e=Ef(t,this._root);return e.length<2?[]:e[e.length-2].children.map(i=>i.value).filter(i=>i!==t)}pathFromRoot(t){return Ef(t,this._root).map(e=>e.value)}};function kf(n,t){if(n===t.value)return t;for(let e of t.children){let o=kf(n,e);if(o)return o}return null}function Ef(n,t){if(n===t.value)return[t];for(let e of t.children){let o=Ef(n,e);if(o.length)return o.unshift(t),o}return[]}var Vt=class{value;children;constructor(t,e){this.value=t,this.children=e}toString(){return`TreeNode(${this.value})`}};function yr(n){let t={};return n&&n.children.forEach(e=>t[e.value.outlet]=e),t}var gs=class extends Md{snapshot;constructor(t,e){super(t),this.snapshot=e,zf(this,t)}toString(){return this.snapshot.toString()}};function db(n,t){let e=u2(n,t),o=new st([new Fo("",{})]),i=new st({}),r=new st({}),a=new st({}),s=new st(""),c=new lo(o,i,a,s,r,re,n,e.root);return c.snapshot=e.root,new gs(new Vt(c,[]),e)}function u2(n,t){let e={},o={},i={},a=new Dr([],e,i,"",o,re,n,null,{},t);return new ps("",new Vt(a,[]))}var lo=class{urlSubject;paramsSubject;queryParamsSubject;fragmentSubject;dataSubject;outlet;component;snapshot;_futureSnapshot;_routerState;_paramMap;_queryParamMap;title;url;params;queryParams;fragment;data;resources;_localInjector;pending;paramsSignal;queryParamsSignal;paramMapSignal;queryParamMapSignal;fragmentSignal;dataSignal;constructor(t,e,o,i,r,a,s,c){this.urlSubject=t,this.paramsSubject=e,this.queryParamsSubject=o,this.fragmentSubject=i,this.dataSubject=r,this.outlet=a,this.component=s,this._futureSnapshot=c,this.title=this.dataSubject?.pipe(Pe(p=>p[_s]))??se(void 0),this.url=t,this.params=e,this.queryParams=o,this.fragment=i,this.data=r}get routeConfig(){return this._futureSnapshot.routeConfig}get root(){return this._routerState.root}get parent(){return this._routerState.parent(this)}get firstChild(){return this._routerState.firstChild(this)}get children(){return this._routerState.children(this)}get pathFromRoot(){return this._routerState.pathFromRoot(this)}get paramMap(){return this._paramMap??=this.params.pipe(Pe(t=>Ii(t))),this._paramMap}get queryParamMap(){return this._queryParamMap??=this.queryParams.pipe(Pe(t=>Ii(t))),this._queryParamMap}toString(){return this.snapshot?this.snapshot.toString():`Future(${this._futureSnapshot})`}_setPending(t){this._futureSnapshot=t,this.pending?.set(!0)}},g2="always";function $f(n,t,e){let o,{routeConfig:i}=n;return t!==null&&(e==="always"||i?.path===""||!t.component&&!t.routeConfig?.loadComponent)?o={params:S(S({},t.params),n.params),data:S(S({},t.data),n.data),resolve:S(S(S(S({},n.data),t.data),i?.data),n._resolvedData)}:o={params:S({},n.params),data:S({},n.data),resolve:S(S({},n.data),n._resolvedData??{})},i&&gb(i)&&(o.resolve[_s]=i.title),o}var Dr=class{url;params;queryParams;fragment;data;outlet;component;routeConfig;_resolve;_resolvedData;_routerState;_paramMap;_queryParamMap;_environmentInjector;resources;get title(){return this.data?.[_s]}constructor(t,e,o,i,r,a,s,c,p,f){this.url=t,this.params=e,this.queryParams=o,this.fragment=i,this.data=r,this.outlet=a,this.component=s,this.routeConfig=c,this._resolve=p,this._environmentInjector=f}get root(){return this._routerState.root}get parent(){return this._routerState.parent(this)}get firstChild(){return this._routerState.firstChild(this)}get children(){return this._routerState.children(this)}get pathFromRoot(){return this._routerState.pathFromRoot(this)}get paramMap(){return this._paramMap??=Ii(this.params),this._paramMap}get queryParamMap(){return this._queryParamMap??=Ii(this.queryParams),this._queryParamMap}toString(){let t=this.url.map(o=>o.toString()).join("/"),e=this.routeConfig?this.routeConfig.path:"";return`Route(url:'${t}', path:'${e}')`}},ps=class extends Md{url;constructor(t,e){super(e),this.url=t,zf(this,e)}toString(){return ub(this._root)}};function zf(n,t){t.value._routerState=n,t.children.forEach(e=>zf(n,e))}function ub(n){let t=n.children.length>0?` { ${n.children.map(ub).join(", ")} } `:"";return`${n.value}${t}`}function Pf(n){if(n.snapshot){let t=n.snapshot,e=n._futureSnapshot;n.snapshot=e,Ln(t.queryParams,e.queryParams)||n.queryParamsSubject.next(e.queryParams),t.fragment!==e.fragment&&n.fragmentSubject.next(e.fragment),Ln(t.params,e.params)||n.paramsSubject.next(e.params),jk(t.url,e.url)||n.urlSubject.next(e.url),Ln(t.data,e.data)||n.dataSubject.next(e.data)}else n.snapshot=n._futureSnapshot,n.dataSubject.next(n._futureSnapshot.data)}function Df(n,t){let e=Ln(n.params,t.params)&&Uk(n.url,t.url),o=!n.parent!=!t.parent;return e&&!o&&(!n.parent||Df(n.parent,t.parent))}function gb(n){return typeof n.title=="string"||n.title===null}var pb=new B(""),hs=(()=>{class n{activated=null;get activatedComponentRef(){return this.activated}_activatedRoute=null;name=re;activateEvents=new Ke;deactivateEvents=new Ke;attachEvents=new Ke;detachEvents=new Ke;routerOutletData=Al();parentContexts=D(Nr);location=D(vi);changeDetector=D(oo);inputBinder=D(vd,{optional:!0});supportsBindingToComponentInputs=!0;ngOnChanges(e){if(e.name){let{firstChange:o,previousValue:i}=e.name;if(o)return;this.isTrackedInParentContexts(i)&&(this.deactivate(),this.parentContexts.onChildOutletDestroyed(i)),this.initializeOutletWithName()}}ngOnDestroy(){this.isTrackedInParentContexts(this.name)&&this.parentContexts.onChildOutletDestroyed(this.name),this.inputBinder?.unsubscribeFromRouteData(this)}isTrackedInParentContexts(e){return this.parentContexts.getContext(e)?.outlet===this}ngOnInit(){this.initializeOutletWithName()}initializeOutletWithName(){if(this.parentContexts.onChildOutletCreated(this.name,this),this.activated)return;let e=this.parentContexts.getContext(this.name);e?.route&&(e.attachRef?this.attach(e.attachRef,e.route):this.activateWith(e.route,e.injector))}get isActivated(){return!!this.activated}get component(){if(!this.activated)throw new z(4012,!1);return this.activated.instance}get activatedRoute(){if(!this.activated)throw new z(4012,!1);return this._activatedRoute}get activatedRouteData(){return this._activatedRoute?this._activatedRoute.snapshot.data:{}}detach(){if(!this.activated)throw new z(4012,!1);this.location.detach();let e=this.activated;return this.activated=null,this._activatedRoute=null,this.detachEvents.emit(e.instance),e}attach(e,o){this.activated=e,this._activatedRoute=o,this.location.insert(e.hostView),this.inputBinder?.bindActivatedRouteToOutletComponent(this,this.location.injector),this.attachEvents.emit(e.instance)}deactivate(){if(this.activated){let e=this.component;this.activated.destroy(),this.activated=null,this._activatedRoute=null,this.deactivateEvents.emit(e)}}activateWith(e,o){if(this.isActivated)throw new z(4013,!1);this._activatedRoute=e;let i=this.location,a=e.snapshot.component,s=this.parentContexts.getOrCreateContext(this.name).children,c=new If(e,s,i.injector,this.routerOutletData);this.activated=i.createComponent(a,{index:i.length,injector:c,environmentInjector:o}),this.changeDetector.markForCheck(),this.inputBinder?.bindActivatedRouteToOutletComponent(this,this.location.injector),this.activateEvents.emit(this.activated.instance)}static \u0275fac=function(o){return new(o||n)};static \u0275dir=qe({type:n,selectors:[["router-outlet"]],inputs:{name:"name",routerOutletData:[1,"routerOutletData"]},outputs:{activateEvents:"activate",deactivateEvents:"deactivate",attachEvents:"attach",detachEvents:"detach"},exportAs:["outlet"],features:[In]})}return n})(),If=class{route;childContexts;parent;outletData;constructor(t,e,o,i){this.route=t,this.childContexts=e,this.parent=o,this.outletData=i}get(t,e){return t===lo?this.route:t===Nr?this.childContexts:t===pb?this.outletData:this.parent.get(t,e)}},vd=new B("");var Bf=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275cmp=Ge({type:n,selectors:[["ng-component"]],exportAs:["emptyRouterOutlet"],decls:1,vars:0,template:function(o,i){o&1&&$(0,"router-outlet")},dependencies:[hs],encapsulation:2,changeDetection:1})}return n})();function Hf(n){let t=n.children&&n.children.map(Hf),e=t?F(S({},n),{children:t}):S({},n);return!e.component&&!e.loadComponent&&(t||e.loadChildren)&&e.outlet&&e.outlet!==re&&(e.component=Bf),e}function p2(n,t,e){let o=new Set,i=fs(n,t._root,e?e._root:void 0,o);return{newlyCreatedRoutes:o,state:new gs(i,t)}}function fs(n,t,e,o){if(e&&n.shouldReuseRoute(t.value,e.value.snapshot)){let i=e.value;i._setPending(t.value);let r=f2(n,t,e,o);return new Vt(i,r)}else{if(n.shouldAttach(t.value)){let a=n.retrieve(t.value);if(a!==null){let s=a.route;return s.value._setPending(t.value),s.children=t.children.map(c=>fs(n,c,void 0,o)),s}}let i=m2(t.value);i._setPending(t.value),o.add(i);let r=t.children.map(a=>fs(n,a,void 0,o));return new Vt(i,r)}}function f2(n,t,e,o){return t.children.map(i=>{for(let r of e.children)if(n.shouldReuseRoute(i.value,r.value.snapshot))return fs(n,i,r,o);return fs(n,i,void 0,o)})}function m2(n){return new lo(new st(n.url),new st(n.params),new st(n.queryParams),new st(n.fragment),new st(n.data),n.outlet,n.component,n)}var Ir=class{redirectTo;navigationBehaviorOptions;constructor(t,e){this.redirectTo=t,this.navigationBehaviorOptions=e}},fb="ngNavigationCancelingError";function bd(n,t){let{redirectTo:e,navigationBehaviorOptions:o}=Vo(t)?{redirectTo:t,navigationBehaviorOptions:void 0}:t,i=mb(!1,pt.Redirect);return i.url=e,i.navigationBehaviorOptions=o,i}function mb(n,t){let e=new Error(`NavigationCancelingError: ${n||""}`);return e[fb]=!0,e.cancellationCode=t,e}function _2(n){return _b(n)&&Vo(n.url)}function _b(n){return!!n&&n[fb]}var Tf=class{routeReuseStrategy;futureState;currState;forwardEvent;inputBindingEnabled;constructor(t,e,o,i,r){this.routeReuseStrategy=t,this.futureState=e,this.currState=o,this.forwardEvent=i,this.inputBindingEnabled=r}activate(t){let e=this.futureState._root,o=this.currState?this.currState._root:null;this.deactivateChildRoutes(e,o,t),Pf(this.futureState.root),this.activateChildRoutes(e,o,t)}deactivateChildRoutes(t,e,o){let i=yr(e);t.children.forEach(r=>{let a=r.value.outlet;this.deactivateRoutes(r,i[a],o),delete i[a]}),Object.values(i).forEach(r=>{this.deactivateRouteAndItsChildren(r,o)})}deactivateRoutes(t,e,o){let i=t.value,r=e?e.value:null;if(i===r)if(i.component){let a=o.getContext(i.outlet);a&&this.deactivateChildRoutes(t,e,a.children)}else this.deactivateChildRoutes(t,e,o);else r&&this.deactivateRouteAndItsChildren(e,o)}deactivateRouteAndItsChildren(t,e){t.value.component&&this.routeReuseStrategy.shouldDetach(t.value.snapshot)?this.detachAndStoreRouteSubtree(t,e):this.deactivateRouteAndOutlet(t,e)}detachAndStoreRouteSubtree(t,e){let o=e.getContext(t.value.outlet),i=o&&t.value.component?o.children:e,r=yr(t);for(let a of Object.values(r))this.deactivateRouteAndItsChildren(a,i);if(o&&o.outlet){let a=o.outlet.detach(),s=o.children.onOutletDeactivated();this.routeReuseStrategy.store(t.value.snapshot,{componentRef:a,route:t,contexts:s})}}deactivateRouteAndOutlet(t,e){let o=e.getContext(t.value.outlet),i=o&&t.value.component?o.children:e,r=yr(t);for(let a of Object.values(r))this.deactivateRouteAndItsChildren(a,i);o&&(o.outlet&&(o.outlet.deactivate(),o.children.onOutletDeactivated()),o.attachRef=null,o.route=null),t.value._localInjector?.destroy()}activateChildRoutes(t,e,o){let i=yr(e);t.children.forEach(r=>{this.activateRoutes(r,i[r.value.outlet],o),this.forwardEvent(new hd(r.value.snapshot))}),t.children.length&&this.forwardEvent(new md(t.value.snapshot))}activateRoutes(t,e,o){let i=t.value,r=e?e.value:null;if(Pf(i),i===r)if(i.component){let a=o.getOrCreateContext(i.outlet);this.activateChildRoutes(t,e,a.children)}else this.activateChildRoutes(t,e,o);else if(i.component){let a=o.getOrCreateContext(i.outlet);if(this.routeReuseStrategy.shouldAttach(i.snapshot)){let s=this.routeReuseStrategy.retrieve(i.snapshot);this.routeReuseStrategy.store(i.snapshot,null),a.children.onOutletReAttached(s.contexts),a.attachRef=s.componentRef,a.route=s.route.value,a.outlet&&a.outlet.attach(s.componentRef,s.route.value),Pf(s.route.value),this.activateChildRoutes(t,null,a.children)}else a.attachRef=null,a.route=i,a.outlet&&a.outlet.activateWith(i,a.injector),this.activateChildRoutes(t,null,a.children)}else this.activateChildRoutes(t,null,o)}},Pd=class{path;route;constructor(t){this.path=t,this.route=this.path[this.path.length-1]}},wr=class{component;route;constructor(t,e){this.component=t,this.route=e}};function h2(n,t,e){let o=n._root,i=t?t._root:null;return is(o,i,e,[o.value])}function C2(n){let t=n.routeConfig?n.routeConfig.canActivateChild:null;return!t||t.length===0?null:{node:n,guards:t}}function Rr(n,t){let e=Symbol(),o=t.get(n,e);return o===e?typeof n=="function"&&!Vu(n)?n:t.get(n):o}function is(n,t,e,o,i={canDeactivateChecks:[],canActivateChecks:[]}){let r=yr(t);return n.children.forEach(a=>{M2(a,r[a.value.outlet],e,o.concat([a.value]),i),delete r[a.value.outlet]}),Object.entries(r).forEach(([a,s])=>ss(s,e.getContext(a),e,i)),i}function M2(n,t,e,o,i={canDeactivateChecks:[],canActivateChecks:[]}){let r=n.value,a=t?t.value:null,s=e?e.getContext(n.value.outlet):null;if(a&&r.routeConfig===a.routeConfig){let c=b2(a,r,r.routeConfig.runGuardsAndResolvers);c?i.canActivateChecks.push(new Pd(o)):(r.data=a.data,r._resolvedData=a._resolvedData),r.component?is(n,t,s?s.children:null,o,i):is(n,t,e,o,i),c&&s&&s.outlet&&s.outlet.isActivated&&i.canDeactivateChecks.push(new wr(s.outlet.component,a))}else a&&ss(t,s,e,i),i.canActivateChecks.push(new Pd(o)),r.component?is(n,null,s?s.children:null,o,i):is(n,null,e,o,i);return i}function b2(n,t,e){if(typeof e=="function")return et(t._environmentInjector,()=>e(n,t));switch(e){case"pathParamsChange":return!Di(n.url,t.url);case"pathParamsOrQueryParamsChange":return!Di(n.url,t.url)||!Ln(n.queryParams,t.queryParams);case"always":return!0;case"paramsOrQueryParamsChange":return!Df(n,t)||!Ln(n.queryParams,t.queryParams);default:return!Df(n,t)}}function ss(n,t,e,o){let i=yr(n),r=n.value;Object.entries(i).forEach(([a,s])=>{r.component?t?ss(s,t.children.getContext(a),t.children,o):ss(s,null,null,o):ss(s,e?e.getContext(a):null,e,o)}),r.component?t&&t.outlet&&t.outlet.isActivated?o.canDeactivateChecks.push(new wr(t.outlet.component,r)):o.canDeactivateChecks.push(new wr(null,r)):o.canDeactivateChecks.push(new wr(null,r))}function Cs(n){return typeof n=="function"}function P2(n){return typeof n=="boolean"}function O2(n){return n&&Cs(n.canLoad)}function v2(n){return n&&Cs(n.canActivate)}function y2(n){return n&&Cs(n.canActivateChild)}function x2(n){return n&&Cs(n.canDeactivate)}function w2(n){return n&&Cs(n.canMatch)}function hb(n){return n instanceof Qo||n?.name==="EmptyError"}var td=Symbol("INITIAL_VALUE");function Tr(){return vt(n=>Mu(n.map(t=>t.pipe(Bn(1),vu(td)))).pipe(Pe(t=>{for(let e of t)if(e!==!0){if(e===td)return td;if(e===!1||S2(e))return e}return!0}),Bt(t=>t!==td),Bn(1)))}function S2(n){return Vo(n)||n instanceof Ir}function Cb(n){return n.aborted?se(void 0).pipe(Bn(1)):new ie(t=>{let e=()=>{t.next(),t.complete()};return n.addEventListener("abort",e),()=>n.removeEventListener("abort",e)})}function Mb(n){return Xr(Cb(n))}function k2(n){return ut(t=>{let{targetSnapshot:e,currentSnapshot:o,guards:{canActivateChecks:i,canDeactivateChecks:r}}=t;return r.length===0&&i.length===0?se(F(S({},t),{guardsResult:!0})):E2(r,e,o).pipe(ut(a=>a&&P2(a)?D2(e,i,n):se(a)),Pe(a=>F(S({},t),{guardsResult:a})))})}function E2(n,t,e){return Fe(n).pipe(ut(o=>R2(o.component,o.route,e,t)),Hn(o=>o!==!0,!0))}function D2(n,t,e){return Fe(t).pipe(Jo(o=>Wi(T2(o.route.parent,e),I2(o.route,e),N2(n,o.path),A2(n,o.route))),Hn(o=>o!==!0,!0))}function I2(n,t){return n!==null&&t&&t(new _d(n)),se(!0)}function T2(n,t){return n!==null&&t&&t(new fd(n)),se(!0)}function A2(n,t){let e=t.routeConfig?t.routeConfig.canActivate:null;if(!e||e.length===0)return se(!0);let o=e.map(i=>Jr(()=>{let r=t._environmentInjector,a=Rr(i,r),s=v2(a)?a.canActivate(t,n):et(r,()=>a(t,n));return Ni(s).pipe(Hn())}));return se(o).pipe(Tr())}function N2(n,t){let e=t[t.length-1],i=t.slice(0,t.length-1).reverse().map(r=>C2(r)).filter(r=>r!==null).map(r=>Jr(()=>{let a=r.guards.map(s=>{let c=r.node._environmentInjector,p=Rr(s,c),f=y2(p)?p.canActivateChild(e,n):et(c,()=>p(e,n));return Ni(f).pipe(Hn())});return se(a).pipe(Tr())}));return se(i).pipe(Tr())}function R2(n,t,e,o){let i=t&&t.routeConfig?t.routeConfig.canDeactivate:null;if(!i||i.length===0)return se(!0);let r=i.map(a=>{let s=t._environmentInjector,c=Rr(a,s),p=x2(c)?c.canDeactivate(n,t,e,o):et(s,()=>c(n,t,e,o));return Ni(p).pipe(Hn())});return se(r).pipe(Tr())}function F2(n,t,e,o,i){let r=t.canLoad;if(r===void 0||r.length===0)return se(!0);let a=r.map(s=>{let c=Rr(s,n),p=O2(c)?c.canLoad(t,e):et(n,()=>c(t,e)),f=Ni(p);return i?f.pipe(Mb(i)):f});return se(a).pipe(Tr(),bb(o))}function bb(n){return $s(xe(t=>{if(typeof t!="boolean")throw bd(n,t)}),Pe(t=>t===!0))}function L2(n,t,e,o,i,r){let a=t.canMatch;if(!a||a.length===0)return se(!0);let s=a.map(c=>{let p=Rr(c,n),f=w2(p)?p.canMatch(t,e,i):et(n,()=>p(t,e,i));return Ni(f).pipe(Mb(r))});return se(s).pipe(Tr(),bb(o))}var so=class n extends Error{segmentGroup;constructor(t){super(),this.segmentGroup=t||null,Object.setPrototypeOf(this,n.prototype)}},ms=class n extends Error{urlTree;constructor(t){super(),this.urlTree=t,Object.setPrototypeOf(this,n.prototype)}};function V2(n){throw new z(4e3,!1)}function j2(n){throw mb(!1,pt.GuardRejected)}var Af=class{urlSerializer;urlTree;constructor(t,e){this.urlSerializer=t,this.urlTree=e}lineralizeSegments(t,e){return be(this,null,function*(){let o=[],i=e.root;for(;;){if(o=o.concat(i.segments),i.numberOfChildren===0)return o;if(i.numberOfChildren>1||!i.children[re])throw V2(`${t.redirectTo}`);i=i.children[re]}})}applyRedirectCommands(t,e,o,i,r){return be(this,null,function*(){let a=yield $2(e,i,r);if(a instanceof bt)throw new ms(a);let s=this.applyRedirectCreateUrlTree(a,this.urlSerializer.parse(a),t,o);if(a[0]==="/")throw new ms(s);return s})}applyRedirectCreateUrlTree(t,e,o,i){let r=this.createSegmentGroup(t,e.root,o,i);return new bt(r,this.createQueryParams(e.queryParams,this.urlTree.queryParams),e.fragment)}createQueryParams(t,e){let o={};return Object.entries(t).forEach(([i,r])=>{if(typeof r=="string"&&r[0]===":"){let s=r.substring(1);o[i]=e[s]}else o[i]=r}),o}createSegmentGroup(t,e,o,i){let r=this.createSegments(t,e.segments,o,i),a=Object.create(null);return Object.entries(e.children).forEach(([s,c])=>{a[s]=this.createSegmentGroup(t,c,o,i)}),new me(r,a)}createSegments(t,e,o,i){return e.map(r=>r.path[0]===":"?this.findPosParam(t,r,i):this.findOrReturn(r,o))}findPosParam(t,e,o){let i=o[e.path.substring(1)];if(!i)throw new z(4001,!1);return i}findOrReturn(t,e){let o=0;for(let i of e){if(i.path===t.path)return e.splice(o),i;o++}return t}};function $2(n,t,e){if(typeof n=="string")return Promise.resolve(n);let o=n;return rd(Ni(et(e,()=>o(t))))}function z2(n,t){return n.providers&&!n._injector&&(n._injector=Va(n.providers,t,`Route: ${n.path}`)),n._injector??t}function fn(n){return n.outlet||re}function B2(n,t){let e=n.filter(o=>fn(o)===t);return e.push(...n.filter(o=>fn(o)!==t)),e}var Nf={matched:!1,consumedSegments:[],remainingSegments:[],parameters:{},positionalParamSegments:{}};function Pb(n){return{routeConfig:n.routeConfig,url:n.url,params:n.params,queryParams:n.queryParams,fragment:n.fragment,data:n.data,outlet:n.outlet,title:n.title,paramMap:n.paramMap,queryParamMap:n.queryParamMap}}function H2(n,t,e,o,i,r,a){let s=Ob(n,t,e);if(!s.matched)return se(s);let c=Pb(r(s));return o=z2(t,o),L2(o,t,e,i,c,a).pipe(Pe(p=>p===!0?s:S({},Nf)))}function Ob(n,t,e){if(t.path==="")return t.pathMatch==="full"&&(n.hasChildren()||e.length>0)?S({},Nf):{matched:!0,consumedSegments:[],remainingSegments:e,parameters:{},positionalParamSegments:{}};let i=(t.matcher||W0)(e,n,t);if(!i)return S({},Nf);let r={};Object.entries(i.posParams??{}).forEach(([s,c])=>{r[s]=c.path});let a=i.consumed.length>0?S(S({},r),i.consumed[i.consumed.length-1].parameters):r;return{matched:!0,consumedSegments:i.consumed,remainingSegments:e.slice(i.consumed.length),parameters:a,positionalParamSegments:i.posParams??{}}}function G0(n,t,e,o,i){return e.length>0&&q2(n,e,o,i)?{segmentGroup:new me(t,G2(o,new me(e,n.children))),slicedSegments:[]}:e.length===0&&W2(n,e,o)?{segmentGroup:new me(n.segments,U2(n,e,o,n.children)),slicedSegments:e}:{segmentGroup:new me(n.segments,n.children),slicedSegments:e}}function U2(n,t,e,o){let i={};for(let r of e)if(yd(n,t,r)&&!o[fn(r)]){let a=new me([],{});i[fn(r)]=a}return S(S({},o),i)}function G2(n,t){let e={};e[re]=t;for(let o of n)if(o.path===""&&fn(o)!==re){let i=new me([],{});e[fn(o)]=i}return e}function q2(n,t,e,o){return e.some(i=>!yd(n,t,i)||!(fn(i)!==re)?!1:!(o!==void 0&&fn(i)===o))}function W2(n,t,e){return e.some(o=>yd(n,t,o))}function yd(n,t,e){return(n.hasChildren()||t.length>0)&&e.pathMatch==="full"?!1:e.path===""}function K2(n,t,e){return t.length===0&&!n.children[e]}var Rf=class{};function Y2(n,t,e,o,i,r,a,s){return be(this,null,function*(){return new Ff(n,t,e,o,i,a,r,s).recognize()})}var Z2=31,Ff=class{injector;configLoader;rootComponentType;config;urlTree;paramsInheritanceStrategy;urlSerializer;abortSignal;applyRedirects;absoluteRedirectCount=0;allowRedirects=!0;constructor(t,e,o,i,r,a,s,c){this.injector=t,this.configLoader=e,this.rootComponentType=o,this.config=i,this.urlTree=r,this.paramsInheritanceStrategy=a,this.urlSerializer=s,this.abortSignal=c,this.applyRedirects=new Af(this.urlSerializer,this.urlTree)}noMatchError(t){return new z(4002,`'${t.segmentGroup}'`)}recognize(){return be(this,null,function*(){let t=G0(this.urlTree.root,[],[],this.config).segmentGroup,{children:e,rootSnapshot:o}=yield this.match(t),i=new Vt(o,e),r=new ps("",i),a=ib(o,[],this.urlTree.queryParams,this.urlTree.fragment);return a.queryParams=this.urlTree.queryParams,r.url=this.urlSerializer.serialize(a),{state:r,tree:a}})}match(t){return be(this,null,function*(){let e=new Dr([],Object.freeze({}),Object.freeze(S({},this.urlTree.queryParams)),this.urlTree.fragment,Object.freeze({}),re,this.rootComponentType,null,{},this.injector);try{return{children:yield this.processSegmentGroup(this.injector,this.config,t,re,e),rootSnapshot:e}}catch(o){if(o instanceof ms)return this.urlTree=o.urlTree,this.match(o.urlTree.root);throw o instanceof so?this.noMatchError(o):o}})}processSegmentGroup(t,e,o,i,r){return be(this,null,function*(){if(o.segments.length===0&&o.hasChildren())return this.processChildren(t,e,o,r);let a=yield this.processSegment(t,e,o,o.segments,i,!0,r);return a instanceof Vt?[a]:[]})}processChildren(t,e,o,i){return be(this,null,function*(){let r=[];for(let c of Object.keys(o.children))c==="primary"?r.unshift(c):r.push(c);let a=[];for(let c of r){let p=o.children[c],f=B2(e,c),_=yield this.processSegmentGroup(t,f,p,c,i);a.push(..._)}let s=vb(a);return Q2(s),s})}processSegment(t,e,o,i,r,a,s){return be(this,null,function*(){for(let c of e)try{return yield this.processSegmentAgainstRoute(c._injector??t,e,c,o,i,r,a,s)}catch(p){if(p instanceof so||hb(p))continue;throw p}if(K2(o,i,r))return new Rf;throw new so(o)})}processSegmentAgainstRoute(t,e,o,i,r,a,s,c){return be(this,null,function*(){if(fn(o)!==a&&(a===re||!yd(i,r,o)))throw new so(i);if(o.redirectTo===void 0)return this.matchSegmentAgainstRoute(t,i,o,r,a,c);if(this.allowRedirects&&s)return this.expandSegmentAgainstRouteUsingRedirect(t,i,e,o,r,a,c);throw new so(i)})}expandSegmentAgainstRouteUsingRedirect(t,e,o,i,r,a,s){return be(this,null,function*(){let{matched:c,parameters:p,consumedSegments:f,positionalParamSegments:_,remainingSegments:C}=Ob(e,i,r);if(!c)throw new so(e);typeof i.redirectTo=="string"&&i.redirectTo[0]==="/"&&(this.absoluteRedirectCount++,this.absoluteRedirectCount>Z2&&(this.allowRedirects=!1));let h=this.createSnapshot(t,i,r,p,s);if(this.abortSignal.aborted)throw new Error(this.abortSignal.reason);let P=yield this.applyRedirects.applyRedirectCommands(f,i.redirectTo,_,Pb(h),t),T=yield this.applyRedirects.lineralizeSegments(i,P);return this.processSegment(t,o,e,T.concat(C),a,!1,s)})}createSnapshot(t,e,o,i,r){let a=new Dr(o,i,Object.freeze(S({},this.urlTree.queryParams)),this.urlTree.fragment,X2(e),fn(e),e.component??e._loadedComponent??null,e,eE(e),t),s=$f(a,r,this.paramsInheritanceStrategy);return a.params=Object.freeze(s.params),a.data=Object.freeze(s.data),a}matchSegmentAgainstRoute(t,e,o,i,r,a){return be(this,null,function*(){if(this.abortSignal.aborted)throw new Error(this.abortSignal.reason);let s=U=>this.createSnapshot(t,o,U.consumedSegments,U.parameters,a),c=yield rd(H2(e,o,i,t,this.urlSerializer,s,this.abortSignal));if(o.path==="**"&&(e.children={}),!c?.matched)throw new so(e);t=o._injector??t;let{routes:p}=yield this.getChildConfig(t,o,i),f=o._loadedInjector??t,{parameters:_,consumedSegments:C,remainingSegments:h}=c,P=this.createSnapshot(t,o,C,_,a),{segmentGroup:T,slicedSegments:A}=G0(e,C,h,p,r);if(A.length===0&&T.hasChildren()){let U=yield this.processChildren(f,p,T,P);return new Vt(P,U)}if(p.length===0&&A.length===0)return new Vt(P,[]);let N=fn(o)===r,E=yield this.processSegment(f,p,T,A,N?re:r,!0,P);return new Vt(P,E instanceof Vt?[E]:[])})}getChildConfig(t,e,o){return be(this,null,function*(){if(e.children)return{routes:e.children,injector:t};if(e.loadChildren){if(e._loadedRoutes!==void 0){let r=e._loadedNgModuleFactory;return r&&!e._loadedInjector&&(e._loadedInjector=r.create(t).injector),{routes:e._loadedRoutes,injector:e._loadedInjector}}if(this.abortSignal.aborted)throw new Error(this.abortSignal.reason);if(yield rd(F2(t,e,o,this.urlSerializer,this.abortSignal))){let r=yield this.configLoader.loadChildren(t,e);return e._loadedRoutes=r.routes,e._loadedInjector=r.injector,e._loadedNgModuleFactory=r.factory,r}throw j2(e)}return{routes:[],injector:t}})}};function Q2(n){n.sort((t,e)=>t.value.outlet===re?-1:e.value.outlet===re?1:t.value.outlet.localeCompare(e.value.outlet))}function J2(n){let t=n.value.routeConfig;return t&&t.path===""}function vb(n){let t=[],e=new Set;for(let o of n){if(!J2(o)){t.push(o);continue}let i=t.find(r=>o.value.routeConfig===r.value.routeConfig);i!==void 0?(i.children.push(...o.children),e.add(i)):t.push(o)}for(let o of e){let i=vb(o.children);t.push(new Vt(o.value,i))}return t.filter(o=>!e.has(o))}function X2(n){return n.data||{}}function eE(n){return n.resolve||{}}function tE(n,t,e,o,i,r,a){return ut(s=>be(null,null,function*(){let{state:c,tree:p}=yield Y2(n,t,e,o,s.extractedUrl,i,r,a);return F(S({},s),{targetSnapshot:c,urlAfterRedirects:p})}))}function nE(n){return ut(t=>{let{targetSnapshot:e,guards:{canActivateChecks:o}}=t;if(!o.length)return se(t);let i=new Set(o.map(s=>s.route)),r=new Set;for(let s of i)if(!r.has(s))for(let c of yb(s))r.add(c);let a=0;return Fe(r).pipe(Jo(s=>i.has(s)?oE(s,e,n):(s.data=$f(s,s.parent,n).resolve,se(void 0))),xe(()=>a++),ac(1),ut(s=>a===r.size?se(t):ct))})}function yb(n){let t=n.children.map(e=>yb(e)).flat();return[n,...t]}function oE(n,t,e){let o=n.routeConfig,i=n._resolve;return o?.title!==void 0&&!gb(o)&&(i[_s]=o.title),Jr(()=>(n.data=$f(n,n.parent,e).resolve,iE(i,n,t).pipe(Pe(r=>(n._resolvedData=r,n.data=S(S({},n.data),r),null)))))}function iE(n,t,e){let o=vf(n);if(o.length===0)return se({});let i={};return Fe(o).pipe(ut(r=>rE(n[r],t,e).pipe(Hn(),xe(a=>{if(a instanceof Ir)throw bd(new Lo,a);i[r]=a}))),ac(1),Pe(()=>i),Ki(r=>hb(r)?ct:Cu(r)))}function rE(n,t,e){let o=t._environmentInjector,i=Rr(n,o),r=i.resolve?i.resolve(t,e):et(o,()=>i(t,e));return Ni(r)}var xb=new B("");function Lf(n){return vt(t=>{let e=n(t);return e?Fe(e).pipe(Pe(()=>t)):se(t)})}var Uf=(()=>{class n{buildTitle(e){let o,i=e.root;for(;i!==void 0;)o=this.getResolvedTitleForRoute(i)??o,i=i.children.find(r=>r.outlet===re);return o}getResolvedTitleForRoute(e){return e.data[_s]}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:()=>D(wb)})}return n})(),wb=(()=>{class n extends Uf{title;constructor(e){super(),this.title=e}updateTitle(e){let o=this.buildTitle(e);o!==void 0&&this.title.setTitle(o)}static \u0275fac=function(o){return new(o||n)(Q($0))};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})}return n})(),Fr=new B("",{factory:()=>({})}),Ms=new B(""),Sb=(()=>{class n{componentLoaders=new WeakMap;childrenLoaders=new WeakMap;onLoadStartListener;onLoadEndListener;compiler=D(qp);loadComponent(e,o){return be(this,null,function*(){if(this.componentLoaders.get(o))return this.componentLoaders.get(o);if(o._loadedComponent)return Promise.resolve(o._loadedComponent);this.onLoadStartListener&&this.onLoadStartListener(o);let i=be(this,null,function*(){try{let r=yield Y0(et(e,()=>o.loadComponent())),a=yield Eb(Yp(r));return this.onLoadEndListener&&this.onLoadEndListener(o),o._loadedComponent=a,a}finally{this.componentLoaders.delete(o)}});return this.componentLoaders.set(o,i),i})}loadChildren(e,o){if(this.childrenLoaders.get(o))return this.childrenLoaders.get(o);if(o._loadedRoutes)return Promise.resolve({routes:o._loadedRoutes,injector:o._loadedInjector});this.onLoadStartListener&&this.onLoadStartListener(o);let i=be(this,null,function*(){try{let r=yield kb(o,this.compiler,e,this.onLoadEndListener);return o._loadedRoutes=r.routes,o._loadedInjector=r.injector,o._loadedNgModuleFactory=r.factory,r}finally{this.childrenLoaders.delete(o)}});return this.childrenLoaders.set(o,i),i}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})();function kb(n,t,e,o){return be(this,null,function*(){let i=yield Y0(et(e,()=>n.loadChildren())),r=yield Eb(Yp(i)),a;r instanceof wl||Array.isArray(r)?a=r:a=yield t.compileModuleAsync(r),o&&o(n);let s,c,p=!1,f;return Array.isArray(a)?(c=a,p=!0):(s=a.create(e).injector,f=a,c=s.get(Ms,[],{optional:!0,self:!0}).flat()),{routes:c.map(Hf),injector:s,factory:f}})}function Eb(n){return be(this,null,function*(){return n})}var xd=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:()=>D(aE)})}return n})(),aE=(()=>{class n{shouldProcessUrl(e){return!0}extract(e){return e}merge(e,o){return e}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})(),Db=new B("");var sE=()=>{},Ib=new B(""),Tb=(()=>{class n{currentNavigation=x(null,{equal:()=>!1});currentTransition=null;lastSuccessfulNavigation=x(null);events=new ye;transitionAbortWithErrorSubject=new ye;configLoader=D(Sb);environmentInjector=D(Le);destroyRef=D(Ae);urlSerializer=D(Ar);rootContexts=D(Nr);location=D(br);inputBindingEnabled=D(vd,{optional:!0})!==null;titleStrategy=D(Uf);options=D(Fr,{optional:!0})||{};paramsInheritanceStrategy=this.options.paramsInheritanceStrategy||g2;urlHandlingStrategy=D(xd);createViewTransition=D(Db,{optional:!0});navigationErrorHandler=D(Ib,{optional:!0});routerResourcesFeature=D(xb,{optional:!0});navigationId=0;get hasRequestedNavigation(){return this.navigationId!==0}transitions;afterPreactivation=()=>se(void 0);rootComponentType=null;destroyed=!1;constructor(){let e=i=>this.events.next(new gd(i)),o=i=>this.events.next(new pd(i));this.configLoader.onLoadEndListener=o,this.configLoader.onLoadStartListener=e,this.destroyRef.onDestroy(()=>{this.destroyed=!0})}complete(){this.transitions?.complete()}handleNavigationRequest(e){let o=++this.navigationId;de(()=>{this.transitions?.next(F(S({},e),{extractedUrl:this.urlHandlingStrategy.extract(e.rawUrl),targetSnapshot:null,targetRouterState:null,guards:{canActivateChecks:[],canDeactivateChecks:[]},guardsResult:null,id:o,routesRecognizeHandler:{},beforeActivateHandler:{}}))})}setupNavigations(e){return this.transitions=new st(null),this.transitions.pipe(Bt(o=>o!==null),vt(o=>{let i=!0,r=!1,a=new AbortController,s=()=>!r&&this.currentTransition?.id===o.id;return se(o).pipe(vt(c=>{if(this.navigationId>o.id)return this.cancelNavigationTransition(o,"",pt.SupersededByNewNavigation),ct;this.currentTransition=o;let p=this.lastSuccessfulNavigation();this.currentNavigation.set({id:c.id,initialUrl:c.rawUrl,extractedUrl:c.extractedUrl,targetBrowserUrl:typeof c.extras.browserUrl=="string"?this.urlSerializer.parse(c.extras.browserUrl):c.extras.browserUrl,trigger:c.source,extras:c.extras,previousNavigation:p?F(S({},p),{previousNavigation:null}):null,abort:()=>a.abort(),routesRecognizeHandler:c.routesRecognizeHandler,beforeActivateHandler:c.beforeActivateHandler});let f=!e.navigated||this.isUpdatingInternalState()||this.isUpdatedBrowserUrl(),_=c.extras.onSameUrlNavigation??e.onSameUrlNavigation;if(!f&&_!=="reload")return this.events.next(new co(c.id,this.urlSerializer.serialize(c.rawUrl),"",ls.IgnoredSameUrlNavigation)),c.resolve(!1),ct;if(this.urlHandlingStrategy.shouldProcessUrl(c.rawUrl))return se(c).pipe(vt(C=>(this.events.next(new Ti(C.id,this.urlSerializer.serialize(C.extractedUrl),C.source,C.restoredState)),C.id!==this.navigationId?ct:Promise.resolve(C))),tE(this.environmentInjector,this.configLoader,this.rootComponentType,e.config,this.urlSerializer,this.paramsInheritanceStrategy,a.signal),xe(C=>{o.targetSnapshot=C.targetSnapshot,o.urlAfterRedirects=C.urlAfterRedirects,this.currentNavigation.update(h=>(h.finalUrl=C.urlAfterRedirects,h)),this.events.next(new us)}),vt(C=>Fe(o.routesRecognizeHandler.deferredHandle??se(void 0)).pipe(Pe(()=>C))),xe(()=>{let C=new ds(c.id,this.urlSerializer.serialize(c.extractedUrl),this.urlSerializer.serialize(c.urlAfterRedirects),c.targetSnapshot);this.events.next(C)}));if(f&&this.urlHandlingStrategy.shouldProcessUrl(c.currentRawUrl)){let{id:C,extractedUrl:h,source:P,restoredState:T,extras:A}=c,N=new Ti(C,this.urlSerializer.serialize(h),P,T);this.events.next(N);let E=db(this.rootComponentType,this.environmentInjector).snapshot;return this.currentTransition=o=F(S({},c),{targetSnapshot:E,urlAfterRedirects:h,extras:F(S({},A),{skipLocationChange:!1,replaceUrl:!1})}),this.currentNavigation.update(U=>(U.finalUrl=h,U)),se(o)}else return this.events.next(new co(c.id,this.urlSerializer.serialize(c.extractedUrl),"",ls.IgnoredByUrlHandlingStrategy)),c.resolve(!1),ct}),Pe(c=>{let p=new cd(c.id,this.urlSerializer.serialize(c.extractedUrl),this.urlSerializer.serialize(c.urlAfterRedirects),c.targetSnapshot);return this.events.next(p),this.currentTransition=o=F(S({},c),{guards:h2(c.targetSnapshot,c.currentSnapshot,this.rootContexts)}),o}),k2(c=>this.events.next(c)),vt(c=>{if(o.guardsResult=c.guardsResult,c.guardsResult&&typeof c.guardsResult!="boolean")throw bd(this.urlSerializer,c.guardsResult);let p=new ld(c.id,this.urlSerializer.serialize(c.extractedUrl),this.urlSerializer.serialize(c.urlAfterRedirects),c.targetSnapshot,!!c.guardsResult);if(this.events.next(p),!s())return ct;if(!c.guardsResult)return this.cancelNavigationTransition(c,"",pt.GuardRejected),ct;if(c.guards.canActivateChecks.length===0)return se(c);let f=new dd(c.id,this.urlSerializer.serialize(c.extractedUrl),this.urlSerializer.serialize(c.urlAfterRedirects),c.targetSnapshot);if(this.events.next(f),!s())return ct;let _=!1;return se(c).pipe(nE(this.paramsInheritanceStrategy),xe({next:()=>{_=!0;let C=new ud(c.id,this.urlSerializer.serialize(c.extractedUrl),this.urlSerializer.serialize(c.urlAfterRedirects),c.targetSnapshot);this.events.next(C)},complete:()=>{_||this.cancelNavigationTransition(c,"",pt.NoDataFromResolver)}}))}),Lf(c=>{let p=_=>{let C=[];if(_.routeConfig?._loadedComponent)_.component=_.routeConfig?._loadedComponent;else if(_.routeConfig?.loadComponent){let h=_._environmentInjector;C.push(this.configLoader.loadComponent(h,_.routeConfig).then(P=>{_.component=P}))}for(let h of _.children)C.push(...p(h));return C},f=p(c.targetSnapshot.root);return f.length===0?se(c):Fe(Promise.all(f).then(()=>c))}),vt(c=>{let{newlyCreatedRoutes:p,state:f}=p2(e.routeReuseStrategy,c.targetSnapshot,c.currentRouterState);return this.currentTransition=o=c=F(S({},c),{targetRouterState:f,newlyCreatedRoutes:p}),this.currentNavigation.update(_=>(_.targetRouterState=f,_)),se(c)}),this.routerResourcesFeature?.setupAndRunResources(a.signal)??(c=>c),Lf(()=>this.afterPreactivation()),vt(()=>{let{currentSnapshot:c,targetSnapshot:p}=o,f=this.createViewTransition?.(this.environmentInjector,c.root,p.root);return f?Fe(f).pipe(Pe(()=>o)):se(o)}),Bn(1),vt(c=>{i=!1,this.events.next(new kr);let p=o.beforeActivateHandler.deferredHandle;return p?Fe(p.then(()=>c)):se(c)}),xe(c=>{new Tf(e.routeReuseStrategy,o.targetRouterState,o.currentRouterState,p=>this.events.next(p),this.inputBindingEnabled).activate(this.rootContexts),c.newlyCreatedRoutes?.clear(),s()&&(Ab(c.targetRouterState),r=!0,this.currentNavigation.update(p=>(p.abort=sE,p)),this.lastSuccessfulNavigation.set(de(this.currentNavigation)),this.events.next(new mn(c.id,this.urlSerializer.serialize(c.extractedUrl),this.urlSerializer.serialize(c.urlAfterRedirects))),this.titleStrategy?.updateTitle(c.targetRouterState.snapshot),c.resolve(!0))}),Xr(Cb(a.signal).pipe(Bt(()=>!r&&i),xe(()=>{this.cancelNavigationTransition(o,a.signal.reason+"",pt.Aborted)}))),xe({complete:()=>{r=!0}}),Xr(this.transitionAbortWithErrorSubject.pipe(xe(c=>{throw c}))),_o(()=>{a.abort(),r||this.cancelNavigationTransition(o,"",pt.SupersededByNewNavigation),this.currentTransition?.id===o.id&&(this.currentNavigation.set(null),this.currentTransition=null)}),Ki(c=>{if(r=!0,q0(o),this.destroyed)return o.resolve(!1),ct;if(_b(c))this.events.next(new Zt(o.id,this.urlSerializer.serialize(o.extractedUrl),c.message,c.cancellationCode)),_2(c)?this.events.next(new Er(c.url,c.navigationBehaviorOptions)):o.resolve(!1);else{let p=new Ai(o.id,this.urlSerializer.serialize(o.extractedUrl),c,o.targetSnapshot??void 0);try{let f=et(this.environmentInjector,()=>this.navigationErrorHandler?.(p));if(f instanceof Ir){let{message:_,cancellationCode:C}=bd(this.urlSerializer,f);this.events.next(new Zt(o.id,this.urlSerializer.serialize(o.extractedUrl),_,C)),this.events.next(new Er(f.redirectTo,f.navigationBehaviorOptions))}else throw this.events.next(p),c}catch(f){this.options.resolveNavigationPromiseOnError?o.resolve(!1):o.reject(f)}}return ct}))}))}cancelNavigationTransition(e,o,i){q0(e);let r=new Zt(e.id,this.urlSerializer.serialize(e.extractedUrl),o,i);this.events.next(r),e.resolve(!1)}isUpdatingInternalState(){return this.currentTransition?.extractedUrl.toString()!==this.currentTransition?.currentUrlTree.toString()}isUpdatedBrowserUrl(){let e=this.urlHandlingStrategy.extract(this.urlSerializer.parse(this.location.path(!0))),o=de(this.currentNavigation),i=o?.targetBrowserUrl??o?.extractedUrl;return e.toString()!==i?.toString()&&!o?.extras.skipLocationChange}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})();function cE(n){return n!==as}function q0(n){for(let t of n.newlyCreatedRoutes??[])t._localInjector?.destroy(),t._localInjector=void 0;Ab(n.targetRouterState)}function Ab(n){if(!n)return;let t=e=>{e.value.pending?.set(!1),e.children.forEach(t)};t(n._root)}var Nb=new B("");var Rb=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:()=>D(lE)})}return n})(),Od=class{shouldDetach(t){return!1}store(t,e){}shouldAttach(t){return!1}retrieve(t){return null}shouldReuseRoute(t,e){return t.routeConfig===e.routeConfig}shouldDestroyInjector(t){return!0}},lE=(()=>{class n extends Od{static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})(),wd=(()=>{class n{urlSerializer=D(Ar);options=D(Fr,{optional:!0})||{};canceledNavigationResolution=this.options.canceledNavigationResolution||"replace";location=D(br);urlHandlingStrategy=D(xd);urlUpdateStrategy=this.options.urlUpdateStrategy||"deferred";currentUrlTree=new bt;getCurrentUrlTree(){return this.currentUrlTree}rawUrlTree=this.currentUrlTree;getRawUrlTree(){return this.rawUrlTree}createBrowserPath({finalUrl:e,initialUrl:o,targetBrowserUrl:i}){let r=e!==void 0?this.urlHandlingStrategy.merge(e,o):o,a=i??r;return a instanceof bt?this.urlSerializer.serialize(a):a}routerUrlState(e){return e?.targetBrowserUrl===void 0||e?.finalUrl===void 0?{}:{\u0275routerUrl:this.urlSerializer.serialize(e.finalUrl)}}commitTransition({targetRouterState:e,finalUrl:o,initialUrl:i}){o&&e?(this.currentUrlTree=o,this.rawUrlTree=this.urlHandlingStrategy.merge(o,i),this.routerState=e):this.rawUrlTree=i}routerState=db(null,D(Le));getRouterState(){return this.routerState}_stateMemento=this.createStateMemento();get stateMemento(){return this._stateMemento}updateStateMemento(){this._stateMemento=this.createStateMemento()}createStateMemento(){return{rawUrlTree:this.rawUrlTree,currentUrlTree:this.currentUrlTree,routerState:this.routerState}}restoredState(){return this.location.getState()}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:()=>D(dE)})}return n})(),dE=(()=>{class n extends wd{currentPageId=0;lastSuccessfulId=-1;get browserPageId(){return this.canceledNavigationResolution!=="computed"?this.currentPageId:this.restoredState()?.\u0275routerPageId??this.currentPageId}registerNonRouterCurrentEntryChangeListener(e){return this.location.subscribe(o=>{o.type==="popstate"&&setTimeout(()=>{e(o.url,o.state,"popstate",{replaceUrl:!0})})})}handleRouterEvent(e,o){e instanceof Ti?this.updateStateMemento():e instanceof co?this.commitTransition(o):e instanceof ds?this.urlUpdateStrategy==="eager"&&(o.extras.skipLocationChange||this.setBrowserUrl(this.createBrowserPath(o),o)):e instanceof kr?(this.commitTransition(o),this.urlUpdateStrategy==="deferred"&&!o.extras.skipLocationChange&&this.setBrowserUrl(this.createBrowserPath(o),o)):e instanceof Zt&&!lb(e)?this.restoreHistory(o):e instanceof Ai?this.restoreHistory(o,!0):e instanceof mn&&(this.lastSuccessfulId=e.id,this.currentPageId=this.browserPageId)}setBrowserUrl(e,o){let{extras:i,id:r}=o,{replaceUrl:a,state:s}=i;if(this.location.isCurrentPathEqualTo(e)||a){let c=this.browserPageId,p=S(S({},s),this.generateNgRouterState(r,c,o));this.location.replaceState(e,"",p)}else{let c=S(S({},s),this.generateNgRouterState(r,this.browserPageId+1,o));this.location.go(e,"",c)}}restoreHistory(e,o=!1){if(this.canceledNavigationResolution==="computed"){let i=this.browserPageId,r=this.currentPageId-i;r!==0?this.location.historyGo(r):this.getCurrentUrlTree()===e.finalUrl&&r===0&&(this.resetInternalState(e),this.resetUrlToCurrentUrlTree())}else this.canceledNavigationResolution==="replace"&&(o&&this.resetInternalState(e),this.resetUrlToCurrentUrlTree())}resetInternalState({finalUrl:e}){this.routerState=this.stateMemento.routerState,this.currentUrlTree=this.stateMemento.currentUrlTree,this.rawUrlTree=this.urlHandlingStrategy.merge(this.currentUrlTree,e??this.rawUrlTree)}resetUrlToCurrentUrlTree(){this.location.replaceState(this.urlSerializer.serialize(this.getRawUrlTree()),"",this.generateNgRouterState(this.lastSuccessfulId,this.currentPageId))}generateNgRouterState(e,o,i){return this.canceledNavigationResolution==="computed"?S({navigationId:e,\u0275routerPageId:o},this.routerUrlState(i)):S({navigationId:e},this.routerUrlState(i))}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})();function Gf(n,t){n.events.pipe(Bt(e=>e instanceof mn||e instanceof Zt||e instanceof Ai||e instanceof co),Pe(e=>e instanceof mn||e instanceof co?0:(e instanceof Zt?e.code===pt.Redirect||e.code===pt.SupersededByNewNavigation:!1)?2:1),Bt(e=>e!==2),Bn(1)).subscribe(()=>{t()})}var uo=(()=>{class n{get currentUrlTree(){return this.stateManager.getCurrentUrlTree()}get rawUrlTree(){return this.stateManager.getRawUrlTree()}disposed=!1;nonRouterCurrentEntryChangeSubscription;console=D($p);stateManager=D(wd);options=D(Fr,{optional:!0})||{};pendingTasks=D(kn);urlUpdateStrategy=this.options.urlUpdateStrategy||"deferred";navigationTransitions=D(Tb);urlSerializer=D(Ar);location=D(br);urlHandlingStrategy=D(xd);injector=D(Le);_events=new ye;get events(){return this._events}get routerState(){return this.stateManager.getRouterState()}navigated=!1;routeReuseStrategy=D(Rb);injectorCleanup=D(Nb,{optional:!0});onSameUrlNavigation=this.options.onSameUrlNavigation||"ignore";config=D(Ms,{optional:!0})?.flat()??[];componentInputBindingEnabled=!!D(vd,{optional:!0});currentNavigation=this.navigationTransitions.currentNavigation.asReadonly();constructor(){this.resetConfig(this.config),this.navigationTransitions.setupNavigations(this).subscribe({error:e=>{}}),this.subscribeToNavigationEvents()}eventsSubscription=new Be;subscribeToNavigationEvents(){let e=this.navigationTransitions.events.subscribe(o=>{try{let i=this.navigationTransitions.currentTransition,r=de(this.navigationTransitions.currentNavigation);if(i!==null&&r!==null){if(this.stateManager.handleRouterEvent(o,r),o instanceof Zt&&o.code!==pt.Redirect&&o.code!==pt.SupersededByNewNavigation)this.navigated=!0;else if(o instanceof mn)this.navigated=!0,this.injectorCleanup?.(this.routeReuseStrategy,this.routerState,this.config);else if(o instanceof Er){let a=o.navigationBehaviorOptions,s=this.urlHandlingStrategy.merge(o.url,i.currentRawUrl),c=S({scroll:i.extras.scroll,browserUrl:i.extras.browserUrl,info:i.extras.info,skipLocationChange:i.extras.skipLocationChange,replaceUrl:i.extras.replaceUrl||this.urlUpdateStrategy==="eager"||cE(i.source)},a);this.scheduleNavigation(s,as,null,c,{resolve:i.resolve,reject:i.reject,promise:i.promise})}}d2(o)&&this._events.next(o)}catch(i){this.navigationTransitions.transitionAbortWithErrorSubject.next(i)}});this.eventsSubscription.add(e)}resetRootComponentType(e){this.routerState.root.component=e,this.navigationTransitions.rootComponentType=e}initialNavigation(){this.setUpLocationChangeListener(),this.navigationTransitions.hasRequestedNavigation||this.navigateToSyncWithBrowser(this.location.path(!0),as,this.stateManager.restoredState(),{replaceUrl:!0})}setUpLocationChangeListener(){this.nonRouterCurrentEntryChangeSubscription??=this.stateManager.registerNonRouterCurrentEntryChangeListener((e,o,i,r)=>{this.navigateToSyncWithBrowser(e,i,o,r)})}navigateToSyncWithBrowser(e,o,i,r){let a=i?.navigationId?i:null,s=i?.\u0275routerUrl??e;if(i?.\u0275routerUrl&&(r=F(S({},r),{browserUrl:e})),i){let p=S({},i);delete p.navigationId,delete p.\u0275routerPageId,delete p.\u0275routerUrl,Object.keys(p).length!==0&&(r.state=p)}let c=this.parseUrl(s);this.scheduleNavigation(c,o,a,r).catch(p=>{this.disposed||this.injector.get(Nt)(p)})}get url(){return this.serializeUrl(this.currentUrlTree)}getCurrentNavigation(){return de(this.navigationTransitions.currentNavigation)}get lastSuccessfulNavigation(){return this.navigationTransitions.lastSuccessfulNavigation}resetConfig(e){this.config=e.map(Hf),this.navigated=!1}ngOnDestroy(){this.dispose()}dispose(){this._events.unsubscribe(),this.navigationTransitions.complete(),this.nonRouterCurrentEntryChangeSubscription?.unsubscribe(),this.nonRouterCurrentEntryChangeSubscription=void 0,this.disposed=!0,this.eventsSubscription.unsubscribe()}createUrlTree(e,o={}){let{relativeTo:i,queryParams:r,fragment:a,queryParamsHandling:s,preserveFragment:c}=o,p=c?this.currentUrlTree.fragment:a,f=null;switch(s??this.options.defaultQueryParamsHandling){case"merge":f=S(S({},this.currentUrlTree.queryParams),r);break;case"preserve":f=this.currentUrlTree.queryParams;break;default:f=r||null}f!==null&&(f=this.removeEmptyProps(f));let _;try{let C=i?i.snapshot:this.routerState.snapshot.root;_=rb(C)}catch(C){(typeof e[0]!="string"||e[0][0]!=="/")&&(e=[]),_=this.currentUrlTree.root}return ab(_,e,f,p??null,this.urlSerializer)}navigateByUrl(e,o={skipLocationChange:!1}){let i=Vo(e)?e:this.parseUrl(e),r=this.urlHandlingStrategy.merge(i,this.rawUrlTree);return this.scheduleNavigation(r,as,null,o)}navigate(e,o={skipLocationChange:!1}){return uE(e),this.navigateByUrl(this.createUrlTree(e,o),o)}serializeUrl(e){return this.urlSerializer.serialize(e)}parseUrl(e){try{return this.urlSerializer.parse(e)}catch(o){return this.console.warn(Wn(4018,!1)),this.urlSerializer.parse("/")}}isActive(e,o){let i;if(o===!0?i=S({},Vf):o===!1?i=S({},Sr):i=S(S({},Sr),o),Vo(e))return yf(this.currentUrlTree,e,i);let r=this.parseUrl(e);return yf(this.currentUrlTree,r,i)}removeEmptyProps(e){return Object.entries(e).reduce((o,[i,r])=>(r!=null&&(o[i]=r),o),{})}scheduleNavigation(e,o,i,r,a){if(this.disposed)return Promise.resolve(!1);let s,c,p;a?(s=a.resolve,c=a.reject,p=a.promise):p=new Promise((_,C)=>{s=_,c=C});let f=this.pendingTasks.add();return Gf(this,()=>{queueMicrotask(()=>this.pendingTasks.remove(f))}),this.navigationTransitions.handleNavigationRequest({source:o,restoredState:i,currentUrlTree:this.currentUrlTree,currentRawUrl:this.currentUrlTree,rawUrl:e,extras:r,resolve:s,reject:c,promise:p,currentSnapshot:this.routerState.snapshot,currentRouterState:this.routerState}),p.catch(Promise.reject.bind(Promise))}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})();function uE(n){for(let t=0;t{class n{router=D(uo);stateManager=D(wd);fragment=x("");queryParams=x({});path=x("");serializer=D(Ar);constructor(){this.updateState(),this.router.events?.subscribe(e=>{e instanceof mn&&this.updateState()})}updateState(){let{fragment:e,root:o,queryParams:i}=this.stateManager.getCurrentUrlTree();this.fragment.set(e),this.queryParams.set(i),this.path.set(this.serializer.serialize(new bt(o)))}static \u0275fac=function(o){return new(o||n)};static \u0275prov=Oe({token:n,factory:n.\u0275fac})}return n})(),Lr=(()=>{class n{router;route;tabIndexAttribute;renderer;el;locationStrategy;hrefAttributeValue=D(new Tl("href"),{optional:!0});reactiveHref=Wp(()=>this.isAnchorElement?this.computeHref(this._urlTree()):this.hrefAttributeValue);get href(){return de(this.reactiveHref)}set href(e){this.reactiveHref.set(e)}set target(e){this._target.set(e)}get target(){return de(this._target)}_target=x(void 0);set queryParams(e){this._queryParams.set(e)}get queryParams(){return de(this._queryParams)}_queryParams=x(void 0,{equal:()=>!1});set fragment(e){this._fragment.set(e)}get fragment(){return de(this._fragment)}_fragment=x(void 0);set queryParamsHandling(e){this._queryParamsHandling.set(e)}get queryParamsHandling(){return de(this._queryParamsHandling)}_queryParamsHandling=x(void 0);set state(e){this._state.set(e)}get state(){return de(this._state)}_state=x(void 0,{equal:()=>!1});set info(e){this._info.set(e)}get info(){return de(this._info)}_info=x(void 0,{equal:()=>!1});set relativeTo(e){this._relativeTo.set(e)}get relativeTo(){return de(this._relativeTo)}_relativeTo=x(void 0);set preserveFragment(e){this._preserveFragment.set(e)}get preserveFragment(){return de(this._preserveFragment)}_preserveFragment=x(!1);set skipLocationChange(e){this._skipLocationChange.set(e)}get skipLocationChange(){return de(this._skipLocationChange)}_skipLocationChange=x(!1);set replaceUrl(e){this._replaceUrl.set(e)}get replaceUrl(){return de(this._replaceUrl)}_replaceUrl=x(!1);browserUrl=Al(void 0);isAnchorElement;onChanges=new ye;applicationErrorHandler=D(Nt);options=D(Fr,{optional:!0});reactiveRouterState=D(pE);constructor(e,o,i,r,a,s){this.router=e,this.route=o,this.tabIndexAttribute=i,this.renderer=r,this.el=a,this.locationStrategy=s;let c=a.nativeElement.tagName?.toLowerCase();this.isAnchorElement=c==="a"||c==="area"||!!(typeof customElements=="object"&&customElements.get(c)?.observedAttributes?.includes?.("href"))}setTabIndexIfNotOnNativeEl(e){this.tabIndexAttribute!=null||this.isAnchorElement||this.applyAttributeValue("tabindex",e)}ngOnChanges(e){this.onChanges.next(this)}routerLinkInput=x(null);set routerLink(e){e==null?(this.routerLinkInput.set(null),this.setTabIndexIfNotOnNativeEl(null)):(Vo(e)?this.routerLinkInput.set(e):this.routerLinkInput.set(Array.isArray(e)?e:[e]),this.setTabIndexIfNotOnNativeEl("0"))}onClick(e,o,i,r,a){let s=this._urlTree();if(s===null||this.isAnchorElement&&(e!==0||o||i||r||a||typeof this.target=="string"&&this.target!="_self"))return!0;let c=this.browserUrl(),p=S({skipLocationChange:this.skipLocationChange,replaceUrl:this.replaceUrl,state:this.state,info:this.info},c!==void 0&&{browserUrl:c});return this.router.navigateByUrl(s,p)?.catch(f=>{this.applicationErrorHandler(f)}),!this.isAnchorElement}ngOnDestroy(){}applyAttributeValue(e,o){let i=this.renderer,r=this.el.nativeElement;o!==null?i.setAttribute(r,e,o):i.removeAttribute(r,e)}_urlTree=I(()=>{this.reactiveRouterState.path(),this._preserveFragment()&&this.reactiveRouterState.fragment();let e=i=>i==="preserve"||i==="merge";(e(this._queryParamsHandling())||e(this.options?.defaultQueryParamsHandling))&&this.reactiveRouterState.queryParams();let o=this.routerLinkInput();return o===null||!this.router.createUrlTree?null:Vo(o)?o:this.router.createUrlTree(o,{relativeTo:this._relativeTo()!==void 0?this._relativeTo():this.route,queryParams:this._queryParams(),fragment:this._fragment(),queryParamsHandling:this._queryParamsHandling(),preserveFragment:this._preserveFragment()})},{equal:(e,o)=>this.computeHref(e)===this.computeHref(o)});get urlTree(){return de(this._urlTree)}computeHref(e){return e!==null&&this.locationStrategy?this.locationStrategy?.prepareExternalUrl(this.router.serializeUrl(e))??"":null}static \u0275fac=function(o){return new(o||n)(le(uo),le(lo),Ra("tabindex"),le(wt),le(Mt),le(Mr))};static \u0275dir=qe({type:n,selectors:[["","routerLink",""]],hostVars:2,hostBindings:function(o,i){o&1&&k("click",function(a){return i.onClick(a.button,a.ctrlKey,a.shiftKey,a.altKey,a.metaKey)}),o&2&&Wt("href",i.reactiveHref(),_p)("target",i._target())},inputs:{target:"target",queryParams:"queryParams",fragment:"fragment",queryParamsHandling:"queryParamsHandling",state:"state",info:"info",relativeTo:"relativeTo",preserveFragment:[2,"preserveFragment","preserveFragment",Si],skipLocationChange:[2,"skipLocationChange","skipLocationChange",Si],replaceUrl:[2,"replaceUrl","replaceUrl",Si],browserUrl:[1,"browserUrl"],routerLink:"routerLink"},features:[In]})}return n})(),qf=(()=>{class n{router;element;renderer;cdr;links;classes=[];routerEventsSubscription;linkInputChangesSubscription;_isActive=!1;get isActive(){return this._isActive}routerLinkActiveOptions={exact:!1};ariaCurrentWhenActive;isActiveChange=new Ke;link=D(Lr,{optional:!0});constructor(e,o,i,r){this.router=e,this.element=o,this.renderer=i,this.cdr=r,this.routerEventsSubscription=e.events.subscribe(a=>{a instanceof mn&&this.update()})}ngAfterContentInit(){se(this.links.changes,se(null)).pipe(qi()).subscribe(e=>{this.update(),this.subscribeToEachLinkOnChanges()})}subscribeToEachLinkOnChanges(){this.linkInputChangesSubscription?.unsubscribe();let e=[...this.links.toArray(),this.link].filter(o=>!!o).map(o=>o.onChanges);this.linkInputChangesSubscription=Fe(e).pipe(qi()).subscribe(o=>{this._isActive!==this.isLinkActive(this.router)(o)&&this.update()})}set routerLinkActive(e){if(e==null){this.classes=[];return}let o=Array.isArray(e)?e:e.split(" ");this.classes=o.filter(i=>!!i)}ngOnChanges(e){this.update()}ngOnDestroy(){this.routerEventsSubscription.unsubscribe(),this.linkInputChangesSubscription?.unsubscribe()}update(){!this.links||!this.router.navigated||this.routerLinkActiveOptions===null&&!this._isActive||queueMicrotask(()=>{let e=this.hasActiveLinks();this.classes.forEach(o=>{e?this.renderer.addClass(this.element.nativeElement,o):this.renderer.removeClass(this.element.nativeElement,o)}),e&&this.ariaCurrentWhenActive!==void 0?this.renderer.setAttribute(this.element.nativeElement,"aria-current",this.ariaCurrentWhenActive.toString()):this.renderer.removeAttribute(this.element.nativeElement,"aria-current"),this._isActive!==e&&(this._isActive=e,this.cdr.markForCheck(),this.isActiveChange.emit(e))})}isLinkActive(e){let o=this.routerLinkActiveOptions;if(o===null)return()=>!1;let i;return o===void 0?i=S({},Sr):fE(o)?i=o:o.exact??!1?i=S({},Vf):i=S({},Sr),r=>{let a=r.urlTree;return a?de(jf(a,e,i)):!1}}hasActiveLinks(){let e=this.isLinkActive(this.router);return this.link&&e(this.link)||this.links.some(e)}static \u0275fac=function(o){return new(o||n)(le(uo),le(Mt),le(wt),le(oo))};static \u0275dir=qe({type:n,selectors:[["","routerLinkActive",""]],contentQueries:function(o,i,r){if(o&1&&El(r,Lr,5),o&2){let a;eo(a=to())&&(i.links=a)}},inputs:{routerLinkActiveOptions:"routerLinkActiveOptions",ariaCurrentWhenActive:"ariaCurrentWhenActive",routerLinkActive:"routerLinkActive"},outputs:{isActiveChange:"isActiveChange"},exportAs:["routerLinkActive"],features:[In]})}return n})();function fE(n){let t=n;return!!(t.paths||t.matrixParams||t.queryParams||t.fragment)}var mE=new B("");function Wf(n,...t){return bo([{provide:Ms,multi:!0,useValue:n},{provide:lo,useFactory:_E},{provide:kl,multi:!0,useFactory:hE},t.map(e=>e.\u0275providers)])}function _E(){return D(uo).routerState.root}function hE(){let n=D(Ct);return t=>{let e=n.get(Xn);if(t!==e.components[0])return;let o=n.get(uo),i=n.get(CE);n.get(ME)===1&&o.initialNavigation(),n.get(bE,null,{optional:!0})?.setUpPreloading(),n.get(mE,null,{optional:!0})?.init(),o.resetRootComponentType(e.componentTypes[0]),i.closed||(i.next(),i.complete(),i.unsubscribe())}}var CE=new B("",{factory:()=>new ye}),ME=new B("",{factory:()=>1});var bE=new B("");var Gb=(()=>{class n{_renderer;_elementRef;onChange=e=>{};onTouched=()=>{};constructor(e,o){this._renderer=e,this._elementRef=o}setProperty(e,o){this._renderer.setProperty(this._elementRef.nativeElement,e,o)}registerOnTouched(e){this.onTouched=e}registerOnChange(e){this.onChange=e}setDisabledState(e){this.setProperty("disabled",e)}static \u0275fac=function(o){return new(o||n)(le(wt),le(Mt))};static \u0275dir=qe({type:n})}return n})(),Td=(()=>{class n extends Gb{static \u0275fac=(()=>{let e;return function(i){return(e||(e=ko(n)))(i||n)}})();static \u0275dir=qe({type:n,features:[gn]})}return n})(),xs=new B(""),PE={provide:xs,useExisting:on(()=>em),multi:!0},em=(()=>{class n extends Td{writeValue(e){this.setProperty("checked",e)}static \u0275fac=(()=>{let e;return function(i){return(e||(e=ko(n)))(i||n)}})();static \u0275dir=qe({type:n,selectors:[["input","type","checkbox","formControlName","",3,"ngNoCva",""],["input","type","checkbox","formControl","",3,"ngNoCva",""],["input","type","checkbox","ngModel","",3,"ngNoCva",""]],hostBindings:function(o,i){o&1&&k("change",function(a){return i.onChange(a.target.checked)})("blur",function(){return i.onTouched()})},standalone:!1,features:[To([PE]),gn]})}return n})(),OE={provide:xs,useExisting:on(()=>zr),multi:!0};function vE(){let n=Kt()?Kt().getUserAgent():"";return/android (\d+)/.test(n.toLowerCase())}var yE=new B(""),zr=(()=>{class n extends Gb{_compositionMode;_composing=!1;constructor(e,o,i){super(e,o),this._compositionMode=i,this._compositionMode==null&&(this._compositionMode=!vE())}writeValue(e){let o=e??"";this.setProperty("value",o)}_handleInput(e){(!this._compositionMode||this._compositionMode&&!this._composing)&&this.onChange(e)}_compositionStart(){this._composing=!0}_compositionEnd(e){this._composing=!1,this._compositionMode&&this.onChange(e)}static \u0275fac=function(o){return new(o||n)(le(wt),le(Mt),le(yE,8))};static \u0275dir=qe({type:n,selectors:[["input","formControlName","",3,"type","checkbox",3,"ngNoCva",""],["textarea","formControlName","",3,"ngNoCva",""],["input","formControl","",3,"type","checkbox",3,"ngNoCva",""],["textarea","formControl","",3,"ngNoCva",""],["input","ngModel","",3,"type","checkbox",3,"ngNoCva",""],["textarea","ngModel","",3,"ngNoCva",""],["","ngDefaultControl",""]],hostBindings:function(o,i){o&1&&k("input",function(a){return i._handleInput(a.target.value)})("blur",function(){return i.onTouched()})("compositionstart",function(){return i._compositionStart()})("compositionend",function(a){return i._compositionEnd(a.target.value)})},standalone:!1,features:[To([OE]),gn]})}return n})();function tm(n){return n==null||nm(n)===0}function nm(n){return n==null?null:Array.isArray(n)||typeof n=="string"?n.length:n instanceof Set?n.size:null}var qb=new B(""),xE=new B(""),wE=/^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,Kf=class{static min(t){return SE(t)}static max(t){return kE(t)}static required(t){return Wb(t)}static requiredTrue(t){return EE(t)}static email(t){return DE(t)}static minLength(t){return IE(t)}static maxLength(t){return TE(t)}static pattern(t){return AE(t)}static nullValidator(t){return kd()}static compose(t){return Xb(t)}static composeAsync(t){return tP(t)}};function SE(n){return t=>{if(t.value==null||n==null)return null;let e=parseFloat(t.value);return!isNaN(e)&&e{if(t.value==null||n==null)return null;let e=parseFloat(t.value);return!isNaN(e)&&e>n?{max:{max:n,actual:t.value}}:null}}function Wb(n){return tm(n.value)?{required:!0}:null}function EE(n){return n.value===!0?null:{required:!0}}function DE(n){return tm(n.value)||wE.test(n.value)?null:{email:!0}}function IE(n){return t=>{let e=t.value?.length??nm(t.value);return e===null||e===0?null:e{let e=t.value?.length??nm(t.value);return e!==null&&e>n?{maxlength:{requiredLength:n,actualLength:e}}:null}}function AE(n){if(!n)return kd;let t,e;return typeof n=="string"?(e="",n.charAt(0)!=="^"&&(e+="^"),e+=n,n.charAt(n.length-1)!=="$"&&(e+="$"),t=new RegExp(e)):(e=n.toString(),t=n),o=>{if(tm(o.value))return null;let i=o.value;return t.test(i)?null:{pattern:{requiredPattern:e,actualValue:i}}}}function kd(n){return null}function Kb(n){return n!=null}function Yb(n){return Eo(n)?Fe(n):n}function Zb(n){let t={};return n.forEach(e=>{t=e!=null?S(S({},t),e):t}),Object.keys(t).length===0?null:t}function Qb(n,t){return t.map(e=>e(n))}function NE(n){return!n.validate}function Jb(n){return n.map(t=>NE(t)?t:e=>t.validate(e))}function Xb(n){if(!n)return null;let t=n.filter(Kb);return t.length==0?null:function(e){return Zb(Qb(e,t))}}function eP(n){return n!=null?Xb(Jb(n)):null}function tP(n){if(!n)return null;let t=n.filter(Kb);return t.length==0?null:function(e){let o=Qb(e,t).map(Yb);return bu(o).pipe(Pe(Zb))}}function nP(n){return n!=null?tP(Jb(n)):null}function Fb(n,t){return n===null?[t]:Array.isArray(n)?[...n,t]:[n,t]}function RE(n){return n._rawValidators}function FE(n){return n._rawAsyncValidators}function Yf(n){return n?Array.isArray(n)?n:[n]:[]}function Ed(n,t){return Array.isArray(n)?n.includes(t):n===t}function Lb(n,t){let e=Yf(t);return Yf(n).forEach(i=>{Ed(e,i)||e.push(i)}),e}function Vb(n,t){return Yf(t).filter(e=>!Ed(n,e))}var Dd=class{get value(){return this.control?this.control.value:null}get valid(){return this.control?this.control.valid:null}get invalid(){return this.control?this.control.invalid:null}get pending(){return this.control?this.control.pending:null}get disabled(){return this.control?this.control.disabled:null}get enabled(){return this.control?this.control.enabled:null}get errors(){return this.control?this.control.errors:null}get pristine(){return this.control?this.control.pristine:null}get dirty(){return this.control?this.control.dirty:null}get touched(){return this.control?this.control.touched:null}get status(){return this.control?this.control.status:null}get untouched(){return this.control?this.control.untouched:null}get statusChanges(){return this.control?this.control.statusChanges:null}get valueChanges(){return this.control?this.control.valueChanges:null}get path(){return null}_composedValidatorFn;_composedAsyncValidatorFn;_rawValidators=[];_rawAsyncValidators=[];_setValidators(t){this._rawValidators=t||[],this._composedValidatorFn=eP(this._rawValidators)}_setAsyncValidators(t){this._rawAsyncValidators=t||[],this._composedAsyncValidatorFn=nP(this._rawAsyncValidators)}get validator(){return this._composedValidatorFn||null}get asyncValidator(){return this._composedAsyncValidatorFn||null}_onDestroyCallbacks=[];_registerOnDestroy(t){this._onDestroyCallbacks.push(t)}_invokeOnDestroyCallbacks(){this._onDestroyCallbacks.forEach(t=>t()),this._onDestroyCallbacks=[]}reset(t=void 0){this.control?.reset(t)}hasError(t,e){return this.control?this.control.hasError(t,e):!1}getError(t,e){return this.control?this.control.getError(t,e):null}},Zf=class extends Dd{name;get formDirective(){return null}get path(){return null}};var bs="VALID",Sd="INVALID",Vr="PENDING",Ps="DISABLED",Ri=class{},Id=class extends Ri{value;source;constructor(t,e){super(),this.value=t,this.source=e}},Os=class extends Ri{pristine;source;constructor(t,e){super(),this.pristine=t,this.source=e}},vs=class extends Ri{touched;source;constructor(t,e){super(),this.touched=t,this.source=e}},jr=class extends Ri{status;source;constructor(t,e){super(),this.status=t,this.source=e}};var ys=class extends Ri{source;constructor(t){super(),this.source=t}};function LE(n){return(Ad(n)?n.validators:n)||null}function VE(n){return Array.isArray(n)?eP(n):n||null}function jE(n,t){return(Ad(t)?t.asyncValidators:n)||null}function $E(n){return Array.isArray(n)?nP(n):n||null}function Ad(n){return n!=null&&!Array.isArray(n)&&typeof n=="object"}var Qf=class{_pendingDirty=!1;_hasOwnPendingAsyncValidator=null;_pendingTouched=!1;_onCollectionChange=()=>{};_updateOn;_hasRequired=x(!1);_parent=null;_asyncValidationSubscription;_composedValidatorFn;_composedAsyncValidatorFn;_rawValidators;_rawAsyncValidators;value;constructor(t,e){this._assignValidators(t),this._assignAsyncValidators(e)}get validator(){return this._composedValidatorFn}set validator(t){this._rawValidators=this._composedValidatorFn=t,this._updateHasRequiredValidator()}get asyncValidator(){return this._composedAsyncValidatorFn}set asyncValidator(t){this._rawAsyncValidators=this._composedAsyncValidatorFn=t}get parent(){return this._parent}get status(){return de(this.statusReactive)}set status(t){de(()=>this.statusReactive.set(t))}_status=I(()=>this.statusReactive());statusReactive=x(void 0);get valid(){return this.status===bs}get invalid(){return this.status===Sd}get pending(){return this.status===Vr}get disabled(){return this.status===Ps}get enabled(){return this.status!==Ps}errors;get pristine(){return de(this.pristineReactive)}set pristine(t){de(()=>this.pristineReactive.set(t))}_pristine=I(()=>this.pristineReactive());pristineReactive=x(!0);get dirty(){return!this.pristine}get touched(){return de(this.touchedReactive)}set touched(t){de(()=>this.touchedReactive.set(t))}_touched=I(()=>this.touchedReactive());touchedReactive=x(!1);get untouched(){return!this.touched}_events=new ye;events=this._events.asObservable();valueChanges;statusChanges;get updateOn(){return this._updateOn?this._updateOn:this.parent?this.parent.updateOn:"change"}setValidators(t){this._assignValidators(t)}setAsyncValidators(t){this._assignAsyncValidators(t)}addValidators(t){this.setValidators(Lb(t,this._rawValidators))}addAsyncValidators(t){this.setAsyncValidators(Lb(t,this._rawAsyncValidators))}removeValidators(t){this.setValidators(Vb(t,this._rawValidators))}removeAsyncValidators(t){this.setAsyncValidators(Vb(t,this._rawAsyncValidators))}hasValidator(t){return Ed(this._rawValidators,t)}hasAsyncValidator(t){return Ed(this._rawAsyncValidators,t)}clearValidators(){this.validator=null}clearAsyncValidators(){this.asyncValidator=null}markAsTouched(t={}){let e=this.touched===!1;this.touched=!0;let o=t.sourceControl??this;t.onlySelf||this._parent?.markAsTouched(F(S({},t),{sourceControl:o})),e&&t.emitEvent!==!1&&this._events.next(new vs(!0,o))}markAllAsDirty(t={}){this.markAsDirty({onlySelf:!0,emitEvent:t.emitEvent,sourceControl:this}),this._forEachChild(e=>e.markAllAsDirty(t))}markAllAsTouched(t={}){this.markAsTouched({onlySelf:!0,emitEvent:t.emitEvent,sourceControl:this}),this._forEachChild(e=>e.markAllAsTouched(t))}markAsUntouched(t={}){let e=this.touched===!0;this.touched=!1,this._pendingTouched=!1;let o=t.sourceControl??this;this._forEachChild(i=>{i.markAsUntouched({onlySelf:!0,emitEvent:t.emitEvent,sourceControl:o})}),t.onlySelf||this._parent?._updateTouched(t,o),e&&t.emitEvent!==!1&&this._events.next(new vs(!1,o))}markAsDirty(t={}){let e=this.pristine===!0;this.pristine=!1;let o=t.sourceControl??this;t.onlySelf||this._parent?.markAsDirty(F(S({},t),{sourceControl:o})),e&&t.emitEvent!==!1&&this._events.next(new Os(!1,o))}markAsPristine(t={}){let e=this.pristine===!1;this.pristine=!0,this._pendingDirty=!1;let o=t.sourceControl??this;this._forEachChild(i=>{i.markAsPristine({onlySelf:!0,emitEvent:t.emitEvent})}),t.onlySelf||this._parent?._updatePristine(t,o),e&&t.emitEvent!==!1&&this._events.next(new Os(!0,o))}markAsPending(t={}){this.status=Vr;let e=t.sourceControl??this;t.emitEvent!==!1&&(this._events.next(new jr(this.status,e)),this.statusChanges.emit(this.status)),t.onlySelf||this._parent?.markAsPending(F(S({},t),{sourceControl:e}))}disable(t={}){let e=this._parentMarkedDirty(t.onlySelf);this.status=Ps,this.errors=null,this._forEachChild(i=>{i.disable(F(S({},t),{onlySelf:!0}))}),this._updateValue();let o=t.sourceControl??this;t.emitEvent!==!1&&(this._events.next(new Id(this.value,o)),this._events.next(new jr(this.status,o)),this.valueChanges.emit(this.value),this.statusChanges.emit(this.status)),this._updateAncestors(F(S({},t),{skipPristineCheck:e}),this),this._onDisabledChange.forEach(i=>i(!0))}enable(t={}){let e=this._parentMarkedDirty(t.onlySelf);this.status=bs,this._forEachChild(o=>{o.enable(F(S({},t),{onlySelf:!0}))}),this.updateValueAndValidity({onlySelf:!0,emitEvent:t.emitEvent}),this._updateAncestors(F(S({},t),{skipPristineCheck:e}),this),this._onDisabledChange.forEach(o=>o(!1))}_updateAncestors(t,e){t.onlySelf||(this._parent?.updateValueAndValidity(t),t.skipPristineCheck||this._parent?._updatePristine({},e),this._parent?._updateTouched({},e))}setParent(t){this._parent=t}getRawValue(){return this.value}updateValueAndValidity(t={}){if(this._setInitialStatus(),this._updateValue(),this.enabled){let o=this._cancelExistingSubscription();this.errors=this._runValidator(),this.status=this._calculateStatus(),(this.status===bs||this.status===Vr)&&this._runAsyncValidator(o,t.emitEvent)}let e=t.sourceControl??this;t.emitEvent!==!1&&(this._events.next(new Id(this.value,e)),this._events.next(new jr(this.status,e)),this.valueChanges.emit(this.value),this.statusChanges.emit(this.status)),t.onlySelf||this._parent?.updateValueAndValidity(F(S({},t),{sourceControl:e}))}_updateTreeValidity(t={emitEvent:!0}){this._forEachChild(e=>e._updateTreeValidity(t)),this.updateValueAndValidity({onlySelf:!0,emitEvent:t.emitEvent})}_setInitialStatus(){this.status=this._allControlsDisabled()?Ps:bs}_runValidator(){return this.validator?this.validator(this):null}_runAsyncValidator(t,e){if(this.asyncValidator){this.status=Vr,this._hasOwnPendingAsyncValidator={emitEvent:e!==!1,shouldHaveEmitted:t!==!1};let o=Yb(this.asyncValidator(this));this._asyncValidationSubscription=o.subscribe(i=>{this._hasOwnPendingAsyncValidator=null,this.setErrors(i,{emitEvent:e,shouldHaveEmitted:t})})}}_cancelExistingSubscription(){if(this._asyncValidationSubscription){this._asyncValidationSubscription.unsubscribe();let t=(this._hasOwnPendingAsyncValidator?.emitEvent||this._hasOwnPendingAsyncValidator?.shouldHaveEmitted)??!1;return this._hasOwnPendingAsyncValidator=null,t}return!1}setErrors(t,e={}){this.errors=t,this._updateControlsErrors(e.emitEvent!==!1,this,e.shouldHaveEmitted)}get(t){let e=t;return e==null||(Array.isArray(e)||(e=e.split(".")),e.length===0)?null:e.reduce((o,i)=>o&&o._find(i),this)}getError(t,e){let o=e?this.get(e):this;return o?.errors?o.errors[t]:null}hasError(t,e){return!!this.getError(t,e)}get root(){let t=this;for(;t._parent;)t=t._parent;return t}_updateControlsErrors(t,e,o){this.status=this._calculateStatus(),t&&this.statusChanges.emit(this.status),(t||o)&&this._events.next(new jr(this.status,e)),this._parent&&this._parent._updateControlsErrors(t,e,o)}_initObservables(){this.valueChanges=new Ke,this.statusChanges=new Ke}_calculateStatus(){return this._allControlsDisabled()?Ps:this.errors?Sd:this._hasOwnPendingAsyncValidator||this._anyControlsHaveStatus(Vr)?Vr:this._anyControlsHaveStatus(Sd)?Sd:bs}_anyControlsHaveStatus(t){return this._anyControls(e=>e.status===t)}_anyControlsDirty(){return this._anyControls(t=>t.dirty)}_anyControlsTouched(){return this._anyControls(t=>t.touched)}_updatePristine(t,e){let o=!this._anyControlsDirty(),i=this.pristine!==o;this.pristine=o,t.onlySelf||this._parent?._updatePristine(t,e),i&&this._events.next(new Os(this.pristine,e))}_updateTouched(t={},e){this.touched=this._anyControlsTouched(),this._events.next(new vs(this.touched,e)),t.onlySelf||this._parent?._updateTouched(t,e)}_onDisabledChange=[];_registerOnCollectionChange(t){this._onCollectionChange=t}_setUpdateStrategy(t){Ad(t)&&t.updateOn!=null&&(this._updateOn=t.updateOn)}_parentMarkedDirty(t){return!t&&!!this._parent?.dirty&&!this._parent._anyControlsDirty()}_find(t){return null}_assignValidators(t){this._rawValidators=Array.isArray(t)?t.slice():t,this._composedValidatorFn=VE(this._rawValidators),this._updateHasRequiredValidator()}_assignAsyncValidators(t){this._rawAsyncValidators=Array.isArray(t)?t.slice():t,this._composedAsyncValidatorFn=$E(this._rawAsyncValidators)}_updateHasRequiredValidator(){de(()=>this._hasRequired.set(this.hasValidator(Kf.required)))}};function zE(n){return n.tagName==="INPUT"||n.tagName==="SELECT"||n.tagName==="TEXTAREA"}function BE(n,t,e,o){switch(e){case"name":n.setAttribute(t,e,o);break;case"disabled":case"readonly":case"required":o?n.setAttribute(t,e,""):n.removeAttribute(t,e);break;case"max":case"min":case"minLength":case"maxLength":o!==void 0?n.setAttribute(t,e,o.toString()):n.removeAttribute(t,e);break}}var Jf=class{kind;context;control;message;constructor({kind:t,context:e,control:o}){this.kind=t,this.context=e,this.control=o}};var HE=(()=>{class n{_validator=kd;_onChange;_enabled;ngOnChanges(e){if(this.inputName in e){let o=this.normalizeInput(e[this.inputName].currentValue);this._enabled=this.enabled(o),this._validator=this._enabled?this.createValidator(o):kd,this._onChange?.()}}validate(e){return this._validator(e)}registerOnValidatorChange(e){this._onChange=e}enabled(e){return e!=null}static \u0275fac=function(o){return new(o||n)};static \u0275dir=qe({type:n,features:[In]})}return n})();var UE={provide:qb,useExisting:on(()=>oP),multi:!0};var oP=(()=>{class n extends HE{required;inputName="required";normalizeInput=Si;createValidator=e=>Wb;enabled(e){return e}static \u0275fac=(()=>{let e;return function(i){return(e||(e=ko(n)))(i||n)}})();static \u0275dir=qe({type:n,selectors:[["","required","","formControlName","",3,"type","checkbox"],["","required","","formControl","",3,"type","checkbox"],["","required","","ngModel","",3,"type","checkbox"]],hostVars:1,hostBindings:function(o,i){o&2&&Wt("required",i._enabled?"":null)},inputs:{required:"required"},standalone:!1,features:[To([UE]),gn]})}return n})();var GE=new B(""),iP=new B("",{factory:()=>om}),om="always";function qE(n,t){return[...t.path,n]}function jb(n,t,e=om){KE(n,t),t.valueAccessor.writeValue(n.value),(n.disabled||e==="always")&&t.valueAccessor.setDisabledState?.(n.disabled),YE(n,t),QE(n,t),ZE(n,t),WE(n,t)}function $b(n,t){n.forEach(e=>{e.registerOnValidatorChange&&e.registerOnValidatorChange(t)})}function WE(n,t){if(t.valueAccessor.setDisabledState){let e=o=>{t.valueAccessor.setDisabledState(o)};n.registerOnDisabledChange(e),t._registerOnDestroy(()=>{n._unregisterOnDisabledChange(e)})}}function KE(n,t){let e=RE(n);t.validator!==null?n.setValidators(Fb(e,t.validator)):typeof e=="function"&&n.setValidators([e]);let o=FE(n);t.asyncValidator!==null?n.setAsyncValidators(Fb(o,t.asyncValidator)):typeof o=="function"&&n.setAsyncValidators([o]);let i=()=>n.updateValueAndValidity();$b(t._rawValidators,i),$b(t._rawAsyncValidators,i)}function YE(n,t){t.valueAccessor.registerOnChange(e=>{n._pendingValue=e,n._pendingChange=!0,n._pendingDirty=!0,n.updateOn==="change"&&rP(n,t)})}function ZE(n,t){t.valueAccessor.registerOnTouched(()=>{n._pendingTouched=!0,n.updateOn==="blur"&&n._pendingChange&&rP(n,t),n.updateOn!=="submit"&&n.markAsTouched()})}function rP(n,t){n._pendingDirty&&n.markAsDirty(),n.setValue(n._pendingValue,{emitModelToViewChange:!1}),t.viewToModelUpdate(n._pendingValue),n._pendingChange=!1}function QE(n,t){let e=(o,i)=>{t.valueAccessor.writeValue(o),i&&t.viewToModelUpdate(o)};n.registerOnChange(e),t._registerOnDestroy(()=>{n._unregisterOnChange(e)})}function JE(n,t){if(!Object.hasOwn(n,"model"))return!1;let e=n.model;return e.isFirstChange()?!0:!Object.is(t,e.currentValue)}function XE(n){return Object.getPrototypeOf(n.constructor)===Td}function eD(n,t){if(!t)return null;Array.isArray(t);let e,o,i;return t.forEach(r=>{r.constructor===zr?e=r:XE(r)?o=r:i=r}),i||o||e||null}var tD={provide:GE,useFactory:()=>{let n=D($r,{self:!0});return{setParseErrors:t=>{n.setParseErrorSource(t)},set onReset(t){n.onReset=t}}}},$r=class extends Dd{_parent=null;name=null;valueAccessor=null;isCustomControlBased=!1;userOnReset;resetSubscription;set onReset(t){this.userOnReset=t,this.resetSubscription?.unsubscribe(),this.resetSubscription=void 0,this.control&&(this.resetSubscription=this.control.events.subscribe(e=>{e instanceof ys&&this.control&&this.userOnReset?.(this.control.value)}),this.subscription?.add(this.resetSubscription))}isNativeFormElement=!1;rawValueAccessors;_selectedValueAccessor=null;get selectedValueAccessor(){return this._selectedValueAccessor??=eD(this,this.rawValueAccessors)}parseErrorsValidator=null;renderer;injector;requiredValidatorViaDi;subscription;customControlBindings=null;constructor(t,e,o){super(),this.injector=t,this.renderer=e,this.rawValueAccessors=o,this.injector?.get(Ae)?.onDestroy(()=>{this.removeParseErrorsValidator(this.control),this.subscription?.unsubscribe()})}setupCustomControl(){this.subscription?.unsubscribe();let t=this.injector?.get(oo);if(!this.control||!t)return;let e=t.markForCheck.bind(t);this.subscription=new Be,this.subscription.add(this.control.valueChanges.subscribe(e)),this.subscription.add(this.control.statusChanges.subscribe(e)),this.resetSubscription?.unsubscribe(),this.resetSubscription=void 0,this.userOnReset&&(this.resetSubscription=this.control.events.subscribe(o=>{o instanceof ys&&this.control&&this.userOnReset?.(this.control.value)}),this.subscription.add(this.resetSubscription)),this.parseErrorsValidator&&this.control.addValidators(this.parseErrorsValidator)}ngControlCreate(t){!t.nativeElement.hasAttribute?.("ngNoCva")&&(this.rawValueAccessors&&this.rawValueAccessors.length>0||this.valueAccessor!==null)||!t.customControl||(this.isCustomControlBased=!0,t.listenToCustomControlModel(i=>{this.control?.setValue(i,{emitModelToViewChange:!1}),this.control?.markAsDirty(),this.viewToModelUpdate(i)}),t.listenToCustomControlOutput("touch",()=>{this.control?.markAsTouched()}),this.customControlBindings={},this.isNativeFormElement=zE(t.nativeElement),this.requiredValidatorViaDi=this._rawValidators.find(i=>i instanceof oP))}ngControlUpdate(t,e){if(!this.isCustomControlBased)return;let o=this.control,i=this.customControlBindings;Object.is(i.value,o.value)||(i.value=o.value,t.setCustomControlModelInput(o.value)),this.bindControlProperty(t,i,"touched",o.touched),this.bindControlProperty(t,i,"dirty",o.dirty),this.bindControlProperty(t,i,"valid",o.valid),this.bindControlProperty(t,i,"invalid",o.invalid),this.bindControlProperty(t,i,"pending",o.pending),this.bindControlProperty(t,i,"disabled",o.disabled),this.shouldBindRequired&&this.bindControlProperty(t,i,"required",this.isRequired);let r=o.errors;if(i.errors!==r){i.errors=r;let a=this._convertErrors(r);t.setInputOnDirectives("errors",a)}}get isRequired(){return(this.requiredValidatorViaDi?._enabled||this.control?._hasRequired())??!1}get shouldBindRequired(){return!0}bindControlProperty(t,e,o,i){if(e[o]===i)return;e[o]=i;let r=t.setInputOnDirectives(o,i);this.isNativeFormElement&&!r&&(o==="disabled"||o==="required")&&this.renderer&&BE(this.renderer,t.nativeElement,o,i)}_convertErrors(t){if(t===null)return[];let e=this.control;return Object.entries(t).map(([o,i])=>new Jf({context:i,kind:o,control:e}))}setParseErrorSource(t){if(t===void 0)return;let e=null,o=I(()=>{let i=t();return i.length===0?null:i.reduce((r,a)=>(r[a.kind]=a,r),{})});this.parseErrorsValidator=(()=>e).bind(this),Ye(()=>{e=o(),this.control?.updateValueAndValidity({emitEvent:!1})},{injector:this.injector})}removeParseErrorsValidator(t){this.parseErrorsValidator&&(t?.removeValidators(this.parseErrorsValidator),t?.updateValueAndValidity({emitEvent:!1}))}},Xf=class{_cd;constructor(t){this._cd=t}get isTouched(){return this._cd?.control?._touched?.(),!!this._cd?.control?.touched}get isUntouched(){return!!this._cd?.control?.untouched}get isPristine(){return this._cd?.control?._pristine?.(),!!this._cd?.control?.pristine}get isDirty(){return!!this._cd?.control?.dirty}get isValid(){return this._cd?.control?._status?.(),!!this._cd?.control?.valid}get isInvalid(){return!!this._cd?.control?.invalid}get isPending(){return!!this._cd?.control?.pending}get isSubmitted(){return this._cd?._submitted?.(),!!this._cd?.submitted}};var Nd=(()=>{class n extends Xf{constructor(e){super(e)}static \u0275fac=function(o){return new(o||n)(le($r,2))};static \u0275dir=qe({type:n,selectors:[["","formControlName",""],["","ngModel",""],["","formControl",""]],hostVars:14,hostBindings:function(o,i){o&2&&w("ng-untouched",i.isUntouched)("ng-touched",i.isTouched)("ng-pristine",i.isPristine)("ng-dirty",i.isDirty)("ng-valid",i.isValid)("ng-invalid",i.isInvalid)("ng-pending",i.isPending)},standalone:!1,features:[gn]})}return n})();function zb(n,t){let e=n.indexOf(t);e>-1&&n.splice(e,1)}function Bb(n){return typeof n=="object"&&n!==null&&Object.keys(n).length===2&&"value"in n&&"disabled"in n}var nD=class extends Qf{defaultValue=null;_onChange=[];_pendingValue;_pendingChange=!1;constructor(t=null,e,o){super(LE(e),jE(o,e)),this._applyFormState(t),this._setUpdateStrategy(e),this._initObservables(),this.updateValueAndValidity({onlySelf:!0,emitEvent:!!this.asyncValidator}),Ad(e)&&(e.nonNullable||e.initialValueIsDefault)&&(Bb(t)?this.defaultValue=t.value:this.defaultValue=t)}setValue(t,e={}){de(()=>{this.value=this._pendingValue=t,this._onChange.length&&e.emitModelToViewChange!==!1&&this._onChange.forEach(o=>o(this.value,e.emitViewToModelChange!==!1)),this.updateValueAndValidity(e)})}patchValue(t,e={}){this.setValue(t,e)}reset(t=this.defaultValue,e={}){this._applyFormState(t),this.markAsPristine(e),this.markAsUntouched(e),this.setValue(this.value,e),e.overwriteDefaultValue&&(this.defaultValue=this.value),this._pendingChange=!1,e?.emitEvent!==!1&&this._events.next(new ys(this))}_updateValue(){}_anyControls(t){return!1}_allControlsDisabled(){return this.disabled}registerOnChange(t){this._onChange.push(t)}_unregisterOnChange(t){zb(this._onChange,t)}registerOnDisabledChange(t){this._onDisabledChange.push(t)}_unregisterOnDisabledChange(t){zb(this._onDisabledChange,t)}_forEachChild(t){}_syncPendingControls(){return this.updateOn==="submit"&&(this._pendingDirty&&this.markAsDirty(),this._pendingTouched&&this.markAsTouched(),this._pendingChange)?(this.setValue(this._pendingValue,{onlySelf:!0,emitModelToViewChange:!1}),!0):!1}_applyFormState(t){Bb(t)?(this.value=this._pendingValue=t.value,t.disabled?this.disable({onlySelf:!0,emitEvent:!1}):this.enable({onlySelf:!0,emitEvent:!1})):this.value=this._pendingValue=t}};var oD={provide:$r,useExisting:on(()=>ws)},Hb=Promise.resolve(),ws=(()=>{class n extends $r{_changeDetectorRef;callSetDisabledState;control=new nD;static ngAcceptInputType_isDisabled;_registered=!1;_ngModelInjector;viewModel;name="";isDisabled;model;options;update=new Ke;constructor(e,o,i,r,a,s,c,p){super(c,p,r),this._changeDetectorRef=a,this.callSetDisabledState=s,this._parent=e,this._setValidators(o),this._setAsyncValidators(i)}ngOnChanges(e){if(this._registered,this._checkForErrors(),!this._registered||"name"in e){if(this._registered&&(this._checkName(),this.formDirective)){let o=e.name.previousValue;this.formDirective.removeControl({name:o,path:this._getPath(o)})}this._setUpControl()}"isDisabled"in e&&this._updateDisabled(e),JE(e,this.viewModel)&&(this._updateValue(this.model),this.viewModel=this.model)}ngOnDestroy(){this.formDirective?.removeControl(this)}\u0275ngControlCreate(e){super.ngControlCreate(e)}\u0275ngControlUpdate(e){super.ngControlUpdate(e,!1)}get shouldBindRequired(){return!1}get path(){return this._getPath(this.name)}get formDirective(){return this._parent?this._parent.formDirective:null}viewToModelUpdate(e){this.viewModel=e,this.update.emit(e)}_setUpControl(){this._setUpdateStrategy(),this._isStandalone()?this._setUpStandalone():this.formDirective.addControl(this),this._registered=!0}_setUpdateStrategy(){this.options&&this.options.updateOn!=null&&(this.control._updateOn=this.options.updateOn)}_isStandalone(){return!this._parent||!!(this.options&&this.options.standalone)}_setUpStandalone(){this.isCustomControlBased?this.setupCustomControl():(this.valueAccessor??=this.selectedValueAccessor,jb(this.control,this,this.callSetDisabledState)),this.control.updateValueAndValidity({emitEvent:!1})}_setupWithForm(e){this.isCustomControlBased?this.setupCustomControl():(this.valueAccessor??=this.selectedValueAccessor,jb(this.control,this,e))}_checkForErrors(){this._checkName()}_checkName(){this.options&&this.options.name&&(this.name=this.options.name),!this._isStandalone()&&this.name}_updateValue(e){Hb.then(()=>{this.control.setValue(e,{emitViewToModelChange:!1}),this._changeDetectorRef?.markForCheck()})}_updateDisabled(e){let o=e.isDisabled.currentValue,i=o!==0&&Si(o);Hb.then(()=>{i&&!this.control.disabled?this.control.disable():!i&&this.control.disabled&&this.control.enable(),this._changeDetectorRef?.markForCheck()})}_getPath(e){return this._parent?qE(e,this._parent):[e]}static \u0275fac=function(o){return new(o||n)(le(Zf,9),le(qb,10),le(xE,10),le(xs,10),le(oo,8),le(iP,8),le(Ct,8),le(wt,8))};static \u0275dir=qe({type:n,selectors:[["","ngModel","",3,"formControlName","",3,"formControl",""]],inputs:{name:"name",isDisabled:[0,"disabled","isDisabled"],model:[0,"ngModel","model"],options:[0,"ngModelOptions","options"]},outputs:{update:"ngModelChange"},exportAs:["ngModel"],standalone:!1,features:[To([oD,tD]),gn,In,jp(null)]})}return n})();var iD={provide:xs,useExisting:on(()=>sP),multi:!0};function aP(n,t){return n==null?`${t}`:(t&&typeof t=="object"&&(t="Object"),`${n}: ${t}`.slice(0,50))}function rD(n){return n.split(":")[0]}var sP=(()=>{class n extends Td{value;_optionMap=new Map;_idCounter=0;set compareWith(e){this._compareWith=e}_compareWith=Object.is;appRefInjector=D(Xn).injector;destroyRef=D(Ae);cdr=D(oo);_queuedWrite=!1;_writeValueAfterRender(){this._queuedWrite||this.appRefInjector.destroyed||(this._queuedWrite=!0,La({write:()=>{this.destroyRef.destroyed||(this._queuedWrite=!1,this.writeValue(this.value))}},{injector:this.appRefInjector}))}writeValue(e){this.cdr.markForCheck(),this.value=e;let o=this._getOptionId(e),i=aP(o,e);this.setProperty("value",i)}registerOnChange(e){this.onChange=o=>{this.value=this._getOptionValue(o),e(this.value)}}_registerOption(){return(this._idCounter++).toString()}_getOptionId(e){for(let o of this._optionMap.keys())if(this._compareWith(this._optionMap.get(o),e))return o;return null}_getOptionValue(e){let o=rD(e);return this._optionMap.has(o)?this._optionMap.get(o):e}static \u0275fac=(()=>{let e;return function(i){return(e||(e=ko(n)))(i||n)}})();static \u0275dir=qe({type:n,selectors:[["select","formControlName","",3,"multiple","",3,"ngNoCva",""],["select","formControl","",3,"multiple","",3,"ngNoCva",""],["select","ngModel","",3,"multiple","",3,"ngNoCva",""]],hostBindings:function(o,i){o&1&&k("change",function(a){return i.onChange(a.target.value)})("blur",function(){return i.onTouched()})},inputs:{compareWith:"compareWith"},standalone:!1,features:[To([iD]),gn]})}return n})(),cP=(()=>{class n{_element;_renderer;_select;id;constructor(e,o,i){this._element=e,this._renderer=o,this._select=i,this._select&&(this.id=this._select._registerOption())}set ngValue(e){this._select!=null&&(this._select._optionMap.set(this.id,e),this._setElementValue(aP(this.id,e)),this._select._writeValueAfterRender())}set value(e){this._setElementValue(e),this._select?._writeValueAfterRender()}_setElementValue(e){this._renderer.setProperty(this._element.nativeElement,"value",e)}ngOnDestroy(){this._select?._optionMap.delete(this.id),this._select?._writeValueAfterRender()}static \u0275fac=function(o){return new(o||n)(le(Mt),le(wt),le(sP,9))};static \u0275dir=qe({type:n,selectors:[["option"]],inputs:{ngValue:"ngValue",value:"value"},standalone:!1})}return n})(),aD={provide:xs,useExisting:on(()=>lP),multi:!0};function Ub(n,t){return n==null?`${t}`:(typeof t=="string"&&(t=`'${t}'`),t&&typeof t=="object"&&(t="Object"),`${n}: ${t}`.slice(0,50))}function sD(n){return n.split(":")[0]}var lP=(()=>{class n extends Td{value;_optionMap=new Map;_idCounter=0;set compareWith(e){this._compareWith=e}_compareWith=Object.is;writeValue(e){this.value=e;let o;if(Array.isArray(e)){let i=e.map(r=>this._getOptionId(r));o=(r,a)=>{r._setSelected(i.indexOf(a)>-1)}}else o=i=>{i._setSelected(!1)};this._optionMap.forEach(o)}registerOnChange(e){this.onChange=o=>{let i=[],r=o.selectedOptions;if(r!==void 0){let a=r;for(let s=0;s{let e;return function(i){return(e||(e=ko(n)))(i||n)}})();static \u0275dir=qe({type:n,selectors:[["select","multiple","","formControlName","",3,"ngNoCva",""],["select","multiple","","formControl","",3,"ngNoCva",""],["select","multiple","","ngModel","",3,"ngNoCva",""]],hostBindings:function(o,i){o&1&&k("change",function(a){return i.onChange(a.target)})("blur",function(){return i.onTouched()})},inputs:{compareWith:"compareWith"},standalone:!1,features:[To([aD]),gn]})}return n})(),dP=(()=>{class n{_element;_renderer;_select;id;_value;constructor(e,o,i){this._element=e,this._renderer=o,this._select=i,this._select&&(this.id=this._select._registerOption(this))}set ngValue(e){this._select!=null&&(this._value=e,this._setElementValue(Ub(this.id,e)),this._select.writeValue(this._select.value))}set value(e){this._select?(this._value=e,this._setElementValue(Ub(this.id,e)),this._select.writeValue(this._select.value)):this._setElementValue(e)}_setElementValue(e){this._renderer.setProperty(this._element.nativeElement,"value",e)}_setSelected(e){this._renderer.setProperty(this._element.nativeElement,"selected",e)}ngOnDestroy(){this._select&&(this._select._optionMap.delete(this.id),this._select.writeValue(this._select.value))}static \u0275fac=function(o){return new(o||n)(le(Mt),le(wt),le(lP,9))};static \u0275dir=qe({type:n,selectors:[["option"]],inputs:{ngValue:"ngValue",value:"value"},standalone:!1})}return n})();var cD=(()=>{class n{static \u0275fac=function(o){return new(o||n)};static \u0275mod=Jn({type:n});static \u0275inj=Pn({})}return n})();var Qt=(()=>{class n{static withConfig(e){return{ngModule:n,providers:[{provide:iP,useValue:e.callSetDisabledState??om}]}}static \u0275fac=function(o){return new(o||n)};static \u0275mod=Jn({type:n});static \u0275inj=Pn({imports:[cD]})}return n})();function oe(n){if(n==null)return null;if(Array.isArray(n)){if(n.length===4&&n.every(e=>typeof e=="number"&&!isNaN(e))||n.length===2&&n.every(e=>typeof e=="number"&&!isNaN(e)))return n;if(n.length===2&&Array.isArray(n[0])&&Array.isArray(n[1])){let e=oe(n[0]),o=oe(n[1]);if(e&&o&&e.length===2&&o.length===2)return[e[0],e[1],o[0],o[1]]}let t=[];for(let e of n)if(typeof e=="number"&&!isNaN(e))t.push(e);else if(typeof e=="string"){let o=e.match(/-?\d+(?:\.\d+)?/g);o&&o.forEach(i=>t.push(Number(i)))}else if(Array.isArray(e)){let o=oe(e);o&&t.push(...o)}if(t.length===4||t.length===2)return t}if(typeof n=="string"){let t=n.trim();if(!t)return null;try{let o=JSON.parse(t),i=oe(o);if(i)return i}catch(o){}let e=t.match(/-?\d+(?:\.\d+)?/g);if(e&&(e.length===4||e.length===2))return e.map(o=>Number(o))}return null}function Br(n){if(!n)return null;if(typeof n=="string"){let t=n.trim();try{let r=JSON.parse(t),a=Br(r);if(a&&a.length>0)return a}catch(r){}let e=[],o=/\[\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\]/g,i;for(;(i=o.exec(t))!==null;)e.push([Number(i[1]),Number(i[2])]);if(e.length>0)return e}if(Array.isArray(n)){let t=[];for(let e of n){let o=oe(e);o&&o.length===2?t.push([o[0],o[1]]):Array.isArray(e)&&e.length>=2&&typeof e[0]=="number"&&typeof e[1]=="number"&&t.push([e[0],e[1]])}if(t.length>0)return t}return null}function Pt(n){if(typeof n!="string")return!1;let t=n.trim().toLowerCase();return/\d/.test(t)?!1:["up","down","left","right","swipe up","swipe down","swipe left","swipe right","scroll up","scroll down","scroll left","scroll right","top","bottom"].includes(t)}function Rd(n,t,e){if(!n||!t||!e)return;t.innerHTML="";let o=Array.isArray(e)?e:[e],i=n.naturalWidth||1080,r=n.naturalHeight||2400;o.forEach(a=>{if(!a||typeof a!="object")return;let s=(a.action||a.name||"tap").toLowerCase(),c=a.payload&&typeof a.payload=="object"?a.payload:{},p=c.args&&typeof c.args=="object"?c.args:a.args||{};if(["manage_app","launch_app","open_app","stop_app","close_app","press_key","press_home","press_back","wait_for_delay","wait","delay","report_task_status","report_failure_analysis"].includes(s))return;let _=s.includes("sequence")||!!(a.sequence||p.sequence||a.normalized_sequence||p.normalized_sequence),C=a.normalized_sequence||p.normalized_sequence||a.sequence||p.sequence||a.targets||p.targets||(Array.isArray(a.coordinates)&&Array.isArray(a.coordinates[0])?a.coordinates:null)||(Array.isArray(p.coordinates)&&Array.isArray(p.coordinates[0])?p.coordinates:null),h=Br(C);if(h&&h.length>0&&(_||h.length>1)){let X=!!(a.normalized_sequence||p.normalized_sequence)||h.every(W=>W[0]<=1e3&&W[1]<=1e3);for(let W=0;W{rm(W[0],W[1],s,i,r,t,X,Me+1,h.length)});return}let P=s.includes("swipe")||s.includes("scroll")||s.includes("drag")||s.includes("slide"),T=oe(a.normalized_start_coordinates||p.normalized_start_coordinates),A=oe(a.normalized_end_coordinates||p.normalized_end_coordinates),N=T||oe(a.start_coordinates||a.start_point||a.start||a.from||p.start_coordinates||p.start_point||p.start||p.from),E=A||oe(a.end_coordinates||a.end_point||a.end||a.to||p.end_coordinates||p.end_point||p.end||p.to);if(N&&E&&N.length>=2&&E.length>=2){am(N[0],N[1],E[0],E[1],i,r,t,!!(T&&A),s);return}let U=oe(a.normalized_coordinates||p.normalized_coordinates),ne=!!U,J=U||oe(a.coordinates)||oe(p.coordinates)||oe(a.coords)||oe(p.coords)||oe(a.target)||oe(p.target)||(P?oe(p.action):null)||(P?oe(a.action):null)||(P?oe(p.gesture):null)||(P?oe(a.gesture):null);if(J&&Array.isArray(J)){if(J.length===4){am(J[0],J[1],J[2],J[3],i,r,t,ne,s);return}else if(J.length===2&&!P){rm(J[0],J[1],s,i,r,t,ne);return}}if(P){let X=(typeof p.action=="string"&&Pt(p.action)?p.action:null)||(typeof a.action=="string"&&a.action!==s&&Pt(a.action)?a.action:null)||(Pt(p.direction)?p.direction:null)||(Pt(a.direction)?a.direction:null)||(Pt(p.gesture)?p.gesture:null)||(Pt(a.gesture)?a.gesture:null)||"",W=String(X).toLowerCase().trim();if(W){let Me=500,Ee=750,ft=500,Jt=250,Xt="SWIPE";W.includes("up")||W.includes("top")||s.includes("up")?(Me=500,Ee=750,ft=500,Jt=250,Xt="SWIPE UP"):W.includes("down")||W.includes("bottom")||s.includes("down")?(Me=500,Ee=250,ft=500,Jt=750,Xt="SWIPE DOWN"):W.includes("left")||s.includes("left")?(Me=800,Ee=500,ft=200,Jt=500,Xt="SWIPE LEFT"):(W.includes("right")||s.includes("right"))&&(Me=200,Ee=500,ft=800,Jt=500,Xt="SWIPE RIGHT"),am(Me,Ee,ft,Jt,i,r,t,!0,Xt);return}}J&&Array.isArray(J)&&J.length===2&&rm(J[0],J[1],s,i,r,t,ne)})}function rm(n,t,e,o,i,r,a=!1,s,c){let p,f;a||!a&&n<=1e3&&t<=1e3?(p=n/10,f=t/10):(p=n/(o||1080)*100,f=t/(i||2400)*100);let _=Math.max(1.5,Math.min(98.5,p)),C=Math.max(1.5,Math.min(98.5,f)),h=document.createElement("div");h.className="action-point-marker",h.style.position="absolute",h.style.left=`${_}%`,h.style.top=`${C}%`,h.style.transform="translate(-50%, -50%)",h.style.pointerEvents="none",h.style.zIndex="10";let P=s!==void 0?20:14,T=document.createElement("div");T.style.width=`${P}px`,T.style.height=`${P}px`,T.style.borderRadius="50%",T.style.backgroundColor="#ef4444",T.style.border="2px solid white",T.style.boxShadow="0 0 6px rgba(0,0,0,0.5)",s!==void 0&&(T.style.display="flex",T.style.alignItems="center",T.style.justifyContent="center",T.style.fontSize="11px",T.style.fontWeight="bold",T.style.color="white",T.innerText=String(s));let A=P*2,N=document.createElement("div");N.style.position="absolute",N.style.top=`-${P/2+2}px`,N.style.left=`-${P/2+2}px`,N.style.width=`${A}px`,N.style.height=`${A}px`,N.style.borderRadius="50%",N.style.border="2px solid #ef4444",N.style.animation="pulse-animation 1.5s infinite ease-out",N.style.pointerEvents="none";let E=document.createElement("div");s!==void 0?E.innerText=c&&c>1?`#${s} TAP`:e.toUpperCase():E.innerText=e.toUpperCase(),E.style.position="absolute",E.style.backgroundColor="rgba(15, 23, 42, 0.9)",E.style.color="white",E.style.padding="1.5px 5px",E.style.borderRadius="3px",E.style.fontSize="9px",E.style.fontWeight="bold",E.style.letterSpacing="0.5px",E.style.whiteSpace="nowrap",E.style.boxShadow="0 1px 4px rgba(0,0,0,0.4)",E.style.border="1px solid rgba(255,255,255,0.2)",C>85?(E.style.bottom=`${P+2}px`,E.style.top="auto"):(E.style.top=`${P+2}px`,E.style.bottom="auto"),_>82?(E.style.right="0px",E.style.left="auto",E.style.transform="none"):_<18?(E.style.left="0px",E.style.right="auto",E.style.transform="none"):(E.style.left="50%",E.style.right="auto",E.style.transform="translateX(-50%)"),h.appendChild(N),h.appendChild(T),h.appendChild(E),r.appendChild(h)}function lD(n,t,e,o,i,r,a,s=!1){let c=s||n<=1e3&&t<=1e3&&e<=1e3&&o<=1e3,p=c?n/10:n/(i||1080)*100,f=c?t/10:t/(r||2400)*100,_=c?e/10:e/(i||1080)*100,C=c?o/10:o/(r||2400)*100,h=Math.max(1.5,Math.min(98.5,p)),P=Math.max(1.5,Math.min(98.5,f)),T=Math.max(1.5,Math.min(98.5,_)),A=Math.max(1.5,Math.min(98.5,C)),N=a.querySelector("svg");N||(N=document.createElementNS("http://www.w3.org/2000/svg","svg"),N.setAttribute("width","100%"),N.setAttribute("height","100%"),N.style.position="absolute",N.style.top="0",N.style.left="0",N.style.pointerEvents="none",N.style.overflow="visible",N.style.zIndex="5",a.appendChild(N));let E=N.querySelector("defs");E||(E=document.createElementNS("http://www.w3.org/2000/svg","defs"),N.insertBefore(E,N.firstChild));let U="seq-arrow-"+Math.random().toString(36).substring(2,9),ne=document.createElementNS("http://www.w3.org/2000/svg","marker");ne.setAttribute("id",U),ne.setAttribute("viewBox","0 0 12 12"),ne.setAttribute("refX","8"),ne.setAttribute("refY","6"),ne.setAttribute("markerWidth","6"),ne.setAttribute("markerHeight","6"),ne.setAttribute("orient","auto");let J=document.createElementNS("http://www.w3.org/2000/svg","path");J.setAttribute("d","M 1 2 L 10 6 L 1 10 z"),J.setAttribute("fill","#ef4444"),J.setAttribute("stroke","#ffffff"),J.setAttribute("stroke-width","1"),ne.appendChild(J),E.appendChild(ne);let X=document.createElementNS("http://www.w3.org/2000/svg","line");X.setAttribute("x1",`${h}%`),X.setAttribute("y1",`${P}%`),X.setAttribute("x2",`${T}%`),X.setAttribute("y2",`${A}%`),X.setAttribute("stroke","#ffffff"),X.setAttribute("stroke-width","4"),X.setAttribute("stroke-linecap","round"),X.setAttribute("opacity","0.8");let W=document.createElementNS("http://www.w3.org/2000/svg","line");W.setAttribute("x1",`${h}%`),W.setAttribute("y1",`${P}%`),W.setAttribute("x2",`${T}%`),W.setAttribute("y2",`${A}%`),W.setAttribute("stroke","#ef4444"),W.setAttribute("stroke-width","2.5"),W.setAttribute("stroke-linecap","round"),W.setAttribute("marker-end",`url(#${U})`),W.setAttribute("stroke-dasharray","4,4"),N.appendChild(X),N.appendChild(W)}function am(n,t,e,o,i,r,a,s=!1,c="swipe"){let p=s||n<=1e3&&t<=1e3&&e<=1e3&&o<=1e3,f=p?n/10:n/(i||1080)*100,_=p?t/10:t/(r||2400)*100,C=p?e/10:e/(i||1080)*100,h=p?o/10:o/(r||2400)*100,P=Math.max(1.5,Math.min(98.5,f)),T=Math.max(1.5,Math.min(98.5,_)),A=Math.max(1.5,Math.min(98.5,C)),N=Math.max(1.5,Math.min(98.5,h)),E=a.querySelector("svg");E||(E=document.createElementNS("http://www.w3.org/2000/svg","svg"),E.setAttribute("width","100%"),E.setAttribute("height","100%"),E.style.position="absolute",E.style.top="0",E.style.left="0",E.style.pointerEvents="none",E.style.overflow="visible",E.style.zIndex="5",a.appendChild(E));let U=E.querySelector("defs");U||(U=document.createElementNS("http://www.w3.org/2000/svg","defs"),E.insertBefore(U,E.firstChild));let ne="action-arrow-"+Math.random().toString(36).substring(2,9),J=document.createElementNS("http://www.w3.org/2000/svg","marker");J.setAttribute("id",ne),J.setAttribute("viewBox","0 0 12 12"),J.setAttribute("refX","8"),J.setAttribute("refY","6"),J.setAttribute("markerWidth","8"),J.setAttribute("markerHeight","8"),J.setAttribute("orient","auto");let X=document.createElementNS("http://www.w3.org/2000/svg","path");X.setAttribute("d","M 1 2 L 10 6 L 1 10 z"),X.setAttribute("fill","#ef4444"),X.setAttribute("stroke","#ffffff"),X.setAttribute("stroke-width","1.5"),X.setAttribute("stroke-linejoin","round"),J.appendChild(X),U.appendChild(J);let W=document.createElementNS("http://www.w3.org/2000/svg","line");W.setAttribute("x1",`${P}%`),W.setAttribute("y1",`${T}%`),W.setAttribute("x2",`${A}%`),W.setAttribute("y2",`${N}%`),W.setAttribute("stroke","#ffffff"),W.setAttribute("stroke-width","6"),W.setAttribute("stroke-linecap","round"),W.setAttribute("opacity","0.9");let Me=document.createElementNS("http://www.w3.org/2000/svg","line");Me.setAttribute("x1",`${P}%`),Me.setAttribute("y1",`${T}%`),Me.setAttribute("x2",`${A}%`),Me.setAttribute("y2",`${N}%`),Me.setAttribute("stroke","#ef4444"),Me.setAttribute("stroke-width","3.5"),Me.setAttribute("stroke-linecap","round"),Me.setAttribute("marker-end",`url(#${ne})`),Me.setAttribute("stroke-dasharray","6,4");let Ee=document.createElementNS("http://www.w3.org/2000/svg","circle");Ee.setAttribute("cx",`${P}%`),Ee.setAttribute("cy",`${T}%`),Ee.setAttribute("r","6.5"),Ee.setAttribute("fill","#ef4444"),Ee.setAttribute("stroke","white"),Ee.setAttribute("stroke-width","2");let ft=document.createElementNS("http://www.w3.org/2000/svg","circle");ft.setAttribute("cx",`${P}%`),ft.setAttribute("cy",`${T}%`),ft.setAttribute("r","2.5"),ft.setAttribute("fill","white"),E.appendChild(W),E.appendChild(Me),E.appendChild(Ee),E.appendChild(ft);let Jt=(P+A)/2,Xt=(T+N)/2,$t=document.createElement("div");$t.className="action-point-marker action-line-label",$t.style.position="absolute",$t.style.left=`${Jt}%`,$t.style.top=`${Xt}%`,$t.style.transform="translate(-50%, -50%)",$t.style.pointerEvents="none",$t.style.zIndex="10";let zt=document.createElement("div");zt.innerText=c.toUpperCase(),zt.style.backgroundColor="rgba(15, 23, 42, 0.92)",zt.style.color="white",zt.style.padding="2px 6px",zt.style.borderRadius="4px",zt.style.fontSize="9px",zt.style.fontWeight="bold",zt.style.letterSpacing="0.5px",zt.style.whiteSpace="nowrap",zt.style.boxShadow="0 2px 6px rgba(0,0,0,0.5)",zt.style.border="1px solid rgba(255,255,255,0.3)",$t.appendChild(zt),a.appendChild($t)}var uP=new WeakMap;function at(n){if(!n)return{};if(typeof n=="object"){let t=uP.get(n);if(t!==void 0)return t;let e=gP(n);return uP.set(n,e),e}return gP(n)}function gP(n){if(n.payload){let t=n.payload;if(typeof t=="string")try{t=JSON.parse(t)}catch(e){}if(t&&typeof t=="object")return t.args&&typeof t.args=="object"?t.args:t}if(n.args){let t=n.args;if(typeof t=="string")try{t=JSON.parse(t)}catch(e){}if(t&&typeof t=="object")return t}return{}}function pP(n){if(!n||!n.name)return!1;let e=n.name.replace(/^(_)?(self\.)?exec_/,"").toLowerCase();return["save_note","read_note","list_notes","update_note","append_note"].includes(e)}function Fd(n){if(!n||!n.name)return!1;let e=n.name.replace(/^(_)?(self\.)?exec_/,"").toLowerCase();return["video_analysis","video_analyzer","video_analyzer_pure","spawn_sub_agent","analyze_audio_only"].includes(e)}function sm(n){if(!n||typeof n!="object")return null;let t=Number(n.start),e=Number(n.end);return!Number.isFinite(t)||!Number.isFinite(e)||e<=t?null:{start:t,end:e,category:n.category?String(n.category):void 0,retryable:n.retryable===!0}}function dD(n){let t=n.trim();return t?t.startsWith("CACHED VIDEO ANALYSIS:")?{outcome:"complete",reuse:"full",summary:t.replace(/^CACHED VIDEO ANALYSIS:\s*/,"")}:t.startsWith("PARTIAL VIDEO ANALYSIS")?{outcome:"partial",reuse:"partial",summary:t}:t.startsWith("All sub-agent chunks failed")||t.startsWith("Error:")?{outcome:"failed",summary:t}:t.includes("Analysis is already in progress in another video agent")?{outcome:"waiting",summary:"Another video agent is already analyzing this evidence."}:{outcome:"complete",summary:t}:{}}function Fi(n){if(!Fd(n))return null;let t=at(n),e=n?.payload&&typeof n.payload=="object"?n.payload:{},o=e.result??n.result??null,i=o&&typeof o=="object"?o:{},r=typeof o=="string"?dD(o):{},a=String(i.outcome||e.outcome||r.outcome||"").toLowerCase();["running","recovering","waiting","complete","partial","failed"].includes(a)||(a=n?.status==="failed"||n?.status==="error"?"failed":n?.status==="running"?"running":"complete");let s=i.recovering===!0||i.fallback_used===!0;a==="running"&&s&&(a="recovering");let c=Number(t.start_time??i.requested_range?.start),p=Number(t.end_time??i.requested_range?.end),f=Number.isFinite(c)&&Number.isFinite(p)&&p>c?{start:c,end:p}:sm(i.requested_range),_=Array.isArray(i.completed_ranges)?i.completed_ranges.map(sm).filter(A=>!!A):[],C=Array.isArray(i.failed_ranges)?i.failed_ranges.map(sm).filter(A=>!!A):[],h=Number(i.completed_count??_.length??0),P=Number(i.total_count??_.length+C.length),T={running:"Analyzing screen recording",recovering:"Analyzing unfinished recording segment",waiting:"Waiting for existing video analysis",complete:i.reuse==="full"||r.reuse==="full"?"Reused video analysis":"Analyzed screen recording",partial:"Video analysis partially completed",failed:"Video analysis returned no result"};return{outcome:a,title:T[a],query:String(t.specific_query||t.query||t.prompt||i.query||""),summary:String(i.summary||r.summary||""),reuse:i.reuse||r.reuse||"none",requestedRange:f,completedRanges:_,failedRanges:C,evidenceCount:Number(i.evidence_count||0),completedCount:Number.isFinite(h)?h:0,totalCount:Number.isFinite(P)?P:0,fallbackUsed:i.fallback_used===!0}}function cm(n){let t=Math.max(0,Number(n)||0),e=Math.floor(t/60),o=Math.floor(t%60);return`${String(e).padStart(2,"0")}:${String(o).padStart(2,"0")}`}function fP(n){if(!n)return null;let t=at(n);if(t.video_path||t.video_file||t.file_path||t.file){let e=String(t.video_path||t.video_file||t.file_path||t.file);return e.split("/").pop()||e}if(t.time_description)return String(t.time_description);if(t.start_time!==void 0||t.end_time!==void 0){let e=t.start_time??0,o=t.end_time?`${t.end_time}s`:"end";return`${e}s - ${o}`}return t.purpose?String(t.purpose):"screen_record.mp4"}var uD=new Set(["click","click_sequence","long_press","long_press_on","input","input_text","swipe","scroll","press_key","press_home","press_back","launch_app","manage_app","open_app","focus_and_input_text","focus_and_clear_text","tap","wait_for_delay","wait","run_adb_command","run_short_adb_command"]);function Ld(n){if(!n||!n.name||n.type==="llm_call")return!1;let t=n.name.replace(/^(_)?(self\.)?exec_/,"").toLowerCase();return uD.has(t)}function gD(n){if(!n||!n.name)return!0;let t=n.name.replace(/^(_)?(self\.)?exec_/,"").toLowerCase();return!!(t.includes("safety_net")||t==="report_task_status"||t==="report_status"||t==="submit_task_status")}function mP(n,t){if(!n||!n.name||n.type==="llm_call"||n.type==="agent"||gD(n))return!1;if(t&&t.action_taken&&jn(t.action_taken)&&Ld(n)){let e=(n.agent_name||n.agent||"").toLowerCase();if(!(e.includes("failure")||e.includes("analyzer")||e.includes("diagnos")||e&&e!=="operator"&&e!=="flashrunner"&&e!=="validator"))return!1}return!0}function _P(n){if(!n)return null;let t=(n.agent_name||n.agent||"").toLowerCase();return t.includes("failure")||t.includes("analyzer")?null:t.includes("outputter")?"Outputter":t.includes("validator")?"Validator":t.includes("diagnos")?"Diagnoser":t.includes("explorer")?"Explorer":null}function Vd(n){if(!n)return[];let t=n.filter(_=>_?.type==="llm_call"&&_?.status==="retrying"&&(_?.name==="llm_retry"||_?.name==="llm_retry_group")&&_?.payload?.source==="provider_sdk"&&["google","gemini"].includes(String(_?.payload?.provider||"").toLowerCase())),e=_=>String(_?.payload?.request_id||`legacy-${_?.step_id||"unassigned"}`),o=new Map;for(let _ of t){let C=e(_);o.set(C,[...o.get(C)||[],_])}let i=new Set(n.filter(_=>_?.type==="llm_call"&&_?.status==="failed").map(_=>_?.payload?.request_id).filter(_=>typeof _=="string"&&!!_)),r=_=>{let C=_[0],h=_[_.length-1];return F(S({},C),{trace_id:`llm-retry-group-${C?.payload?.request_id||C?.trace_id||C?.timestamp||"unknown"}`,name:"llm_retry_group",payload:F(S({},h?.payload||{}),{retry_count:_.length,total_delay:_.reduce((P,T)=>P+(Number(T?.payload?.delay)||0),0),retries:_.map(P=>({trace_id:P.trace_id,timestamp:P.timestamp,error:P?.payload?.error||P.error,delay:Number(P?.payload?.delay)||0,provider:P?.payload?.provider,source:P?.payload?.source,request_id:P?.payload?.request_id,scheduled_at:P?.payload?.scheduled_at}))})})},a=new Map;for(let _ of n)_&&_.trace_id&&a.set(_.trace_id,_);let s=_=>(_||"").replace(/^(_)?(self\.)?exec_/,"").toLowerCase().trim(),c=[],p=new Set,f=new Set;for(let _ of n){if(!_||!_.name||_.type==="agent")continue;if(_.type==="llm_call"&&_.status==="retrying"){let P=e(_),T=o.get(P),A=_?.payload?.request_id;T&&!f.has(P)&&!(A&&i.has(A))&&(c.push(r(T)),f.add(P));continue}if(_.type==="llm_call"&&_.status==="failed"){(_.name==="llm_pause"||_?.payload?.pause===!0)&&c.push(_);continue}let C=s(_.name),h=!1;if(_.parent_trace_id){let P=a.get(_.parent_trace_id);P&&s(P.name)===C&&(h=!0)}h||(_.trace_id?p.has(_.trace_id)||(p.add(_.trace_id),c.push(a.get(_.trace_id)||_)):c.push(_))}return pD(c)}function pD(n){let t=new Map,e=[];n.forEach((i,r)=>{if(!Fd(i)){e.push({index:r,tool:i});return}let a=String(i.name||"").replace(/^(_)?(self\.)?exec_/,"").toLowerCase(),s=String(a==="video_analyzer"||a==="video_analyzer_pure"?i.trace_id||i.parent_trace_id||`video-${r}`:i.parent_trace_id||i.trace_id||`video-${r}`),c=t.get(s);c?c.tools.push(i):t.set(s,{firstIndex:r,tools:[i]})});let o=[...e];for(let[i,r]of t){let a=r.tools.map(Fi).filter(E=>!!E);if(!a.length)continue;let s=a.some(E=>E.outcome==="running"||E.outcome==="recovering"),c=a.filter(E=>E.outcome==="complete"),p=a.some(E=>E.outcome==="partial"),f=a.filter(E=>E.outcome==="failed"),_=a.filter(E=>E.outcome==="waiting"),C;s?C=a.some(E=>E.outcome==="recovering")?"recovering":"running":p||c.length>0&&f.length>0?C="partial":c.length>0?C="complete":_.length>0?C="waiting":C="failed";let h=a.map(E=>E.requestedRange).filter(E=>!!E),P=h.length?{start:Math.min(...h.map(E=>E.start)),end:Math.max(...h.map(E=>E.end))}:null,T=c.length>0&&c.every(E=>E.reuse==="full")?"full":a.some(E=>E.reuse!=="none")?"partial":"none",A=r.tools[0],N={outcome:C,reuse:T,requested_range:P,completed_count:c.length,total_count:a.length,evidence_count:a.reduce((E,U)=>E+U.evidenceCount,0),query:a.find(E=>E.query)?.query||"",recovering:C==="recovering",fallback_used:a.some(E=>E.fallbackUsed)};o.push({index:r.firstIndex,tool:F(S({},A),{trace_id:`video-analysis-${i}`,name:"video_analysis",status:C==="running"||C==="recovering"?"running":"success",payload:F(S({},A.payload||{}),{args:F(S({},A.payload?.args||A.args||{}),{start_time:P?.start,end_time:P?.end}),result:N})})})}return o.sort((i,r)=>i.index-r.index),o.map(i=>i.tool)}function hP(n){if(!n||!n.name)return null;let e=(n.payload?.args||n.args)?.key;return e?e.toLowerCase().endsWith(".md")?e:`${e}.md`:null}function CP(n,t=!1){if(!n||!n.name)return"";let e=n.name.replace(/^(_)?exec_/,""),o=e.toLowerCase(),i=at(n);switch(o){case"manage_app":case"launch_app":{let r=i.app_name||i.package_name||i.app||"",a=r?r.charAt(0).toUpperCase()+r.slice(1):"Application",s=i.action?String(i.action).toLowerCase():"";return`${s==="launch"?"Launching":s==="stop"||s==="close"?"Stopping":"Managing"} "${a}"`}case"wait_for_delay":case"wait_delay":case"wait":{let r=i.delay_seconds||i.seconds||i.delay||i.duration;return r?`Waiting for ${r} second${Number(r)>1?"s":""}...`:"Waiting for delay..."}case"wait_for_text":{let r=i.text||i.target_text||"";return r?`Waiting for text "${r}" to appear on screen`:"Waiting for text on screen"}case"input_text":case"input":{let r=i.text||i.input_text||"";return r?`Entering text "${r}" into field`:"Entering text into input field"}case"focus_and_input_text":{let r=i.text||i.input_text||"";return r?`Focusing field and typing "${r}"`:"Focusing field and entering text"}case"focus_and_clear_text":return"Focusing and clearing field text";case"click":case"tap":{let r=i.target_text||i.text||i.query||"";return r?`Tapping on "${r}"`:"Tapping on screen element"}case"click_sequence":return"Executing click sequence";case"long_press":{let r=i.target_text||i.text||"";return r?`Long pressing on "${r}"`:"Long pressing screen element"}case"swipe":{let r=i.action||i.direction||"";return r?`Swiping ${String(r).toUpperCase()} on screen`:"Swiping screen"}case"press_key":{let r=i.key||i.keycode||"";return r?`Pressing key ${String(r).toUpperCase()}`:"Pressing hardware key"}case"save_note":return t?"Creating note":"Saving note";case"read_note":return"Reading note";case"list_notes":return"Browsing all saved notes";case"update_note":return"Updating note";case"append_note":return"Updating note";case"object_detection":{let r=Array.isArray(i.queries)?i.queries.join(", "):i.queries||"";return r?`Locating on screen: "${r}"`:"Locating elements on screen"}case"ask_explorer":{let r=i.query||i.prompt||"";return r?`Searching on screen: "${r}"`:"Searching on screen"}case"report_failure_analysis":{let r=i.reason||i.analysis||"";return r?`Investigating issue: ${r}`:"Investigating execution issue"}case"run_adb_command":case"run_short_adb_command":{let r=i.command||i.cmd||"";return r?`Running command: ${r}`:"Running system command"}case"search_logs":case"read_logs":{let r=i.query||i.filter||"";return r?`Searching logs for "${r}"`:"Analyzing system logs"}case"log_analyzer":case"output_analyzer":return"Analyzing logs";case"diagnoser":case"diagnose":return"Diagnosing issue";case"video_analyzer":case"video_analyzer_pure":return"Analyzing screen recording";case"extract_segment_metadata":{let r=i.start_time!==void 0?`${i.start_time}s`:"",a=i.end_time!==void 0?`${i.end_time}s`:"";return`Cropping screen recording segment${r&&a?` (${r} - ${a})`:r?` (from ${r})`:""}`}case"spawn_sub_agent":{let r=i.specific_query||i.query||i.prompt||"";return r?`Analyzing recording with sub-agent: "${r}"`:"Analyzing recording with sub-agent"}case"analyze_audio_only":{let r=i.specific_query||i.query||"";return r?`Analyzing audio track: "${r}"`:"Analyzing recording audio track"}case"get_step_detail":case"get_step_details":{let r=i.step_no??i.step_number??i.step;return r!==void 0&&r!==""?`Reviewing step ${r}`:"Reviewing step details"}case"get_step_screenshot":{let r=i.step_no??i.step_number??i.step,a=String(i.which||"").toLowerCase()==="post"?"after":"before";return r!==void 0&&r!==""?`Looking at the screen ${a} step ${r}`:"Looking at a step screenshot"}case"probe_device":{let r=i.kind?String(i.kind).replace(/_/g," "):"";return r?`Reading ${r} from the device`:"Reading device state"}case"search_history_for_text":{let r=i.text||i.query||"";return r?`Searching execution trace for "${r}"`:"Searching execution trace"}case"outputter":case"output_synthesis":return"Synthesizing output report";case"web_search":{let r=i.query||"";return r?`Searching web for "${r}"`:"Searching the web"}case"read_url":return"Fetching web page";default:return`Executing ${e.split("_").map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join(" ")}`}}function MP(n){if(!n||!n.name)return"settings";switch(n.name.toLowerCase().replace(/^(_)?exec_/,"")){case"click":case"tap":return"ads_click";case"click_sequence":case"long_press":return"touch_app";case"input_text":case"input":return"keyboard";case"swipe":return"swipe";case"press_key":return"keyboard_tab";case"manage_app":return"open_in_new";case"wait_for_delay":return"timer";case"wait_for_text":return"hourglass_empty";case"object_detection":return"search";case"ask_explorer":return"search";case"report_failure_analysis":return"assessment";case"run_adb_command":case"run_short_adb_command":return"terminal";case"web_search":return"travel_explore";case"read_url":return"language";case"search_logs":case"read_logs":case"log_analyzer":case"output_analyzer":return"receipt_long";case"diagnoser":case"diagnose":return"medical_services";case"video_analyzer":case"video_analyzer_pure":return"video_camera_back";case"extract_segment_metadata":return"crop";case"spawn_sub_agent":return"smart_toy";case"analyze_audio_only":return"graphic_eq";case"get_step_detail":case"get_step_details":return"manage_search";case"get_step_screenshot":return"image_search";case"probe_device":return"sensors";case"search_history_for_text":return"find_in_page";case"outputter":case"output_synthesis":return"assignment_turned_in";default:return"build"}}function bP(n){if(!n||!n.name)return"Tool Call";let t=n.name.replace(/^(_)?exec_/,"");switch(t.toLowerCase()){case"click":case"tap":return"Tapping Element";case"click_sequence":return"Executing Click Sequence";case"long_press":return"Long Pressing Element";case"input_text":case"input":return"Entering Text";case"swipe":case"scroll":{let o=at(n),i=o.direction||o.gesture||(typeof o.action=="string"?o.action:"");return i&&Pt(i)?`Swiping Screen (${String(i).toUpperCase()})`:"Swiping Screen"}case"drag":case"drag_and_drop":return"Dragging Screen";case"press_key":return"Pressing Hardware Key";case"manage_app":case"launch_app":{let o=at(n),i=o.action?String(o.action).toLowerCase():"";return i==="launch"?"Launching Application":i==="stop"||i==="close"?"Stopping Application":"Managing Application"}case"wait_for_delay":case"wait_delay":return"Waiting for Delay";case"wait_for_text":return"Waiting for Text";case"object_detection":return"Locating Elements";case"ask_explorer":return"Searching on Screen";case"report_failure_analysis":return"Investigating Issue";case"run_adb_command":case"run_short_adb_command":return"Running System Command";case"web_search":return"Web Search";case"read_url":return"Fetching Web Page";case"search_logs":case"read_logs":return"Searching Logs";case"log_analyzer":case"output_analyzer":return"Analyzing Logs";case"diagnoser":case"diagnose":return"Diagnosing Issue";case"video_analyzer":case"video_analyzer_pure":return"Analyzing Screen Recording";case"extract_segment_metadata":return"Cropping Screen Recording";case"spawn_sub_agent":return"Delegating Video Analysis";case"analyze_audio_only":return"Analyzing Audio Track";default:return t.replace(/_/g," ").replace(/\b\w/g,o=>o.toUpperCase())}}function lm(n){if(!n||!n.name)return"";let t=at(n),e=n.name.toLowerCase().replace(/^(_)?exec_/,"");if(e==="manage_app"||e==="launch_app"){let o=t.app_name||t.package_name||t.app||"",i=o?o.charAt(0).toUpperCase()+o.slice(1):"",r=t.action?String(t.action).toLowerCase():"",a=r?r.charAt(0).toUpperCase()+r.slice(1):"";return a&&i?`${a} ${i}`:i||a||""}return e==="swipe"&&typeof t.action=="string"&&Pt(t.action)?t.action:e==="wait_for_text"?t.text||"":e==="object_detection"?Array.isArray(t.queries)?t.queries.join(", "):t.queries||"":e==="ask_explorer"||e==="web_search"?t.query||t.prompt||"":e==="read_url"?t.url||"":e==="search_logs"||e==="read_logs"?t.query||t.filter||"":e==="report_failure_analysis"?t.status||t.reason||t.analysis||"":t.target&&typeof t.target=="string"?t.target:t.target&&typeof t.target=="number"?`Element #${t.target}`:t.index!==void 0?`Element #${t.index}`:t.target_text||t.target_class||t.element||t.element_text||(e!=="input_text"?t.text:"")||""}function PP(n){if(!n||!n.name)return"Input";let t=n.name.toLowerCase().replace(/^(_)?exec_/,"");if(t==="wait_for_delay"||t==="wait_delay"||t==="delay"||t==="wait")return"Duration";if(t==="swipe"||t==="scroll"||t==="drag"||t==="drag_and_drop"){let e=at(n),o=e.direction||e.gesture||(typeof e.action=="string"?e.action:"");return o&&Pt(o)?"Direction":"Input"}return t==="press_key"||t==="press_home"||t==="press_back"?"Key":t==="input_text"||t==="input"?"Input Text":"Input"}function dm(n){if(!n||!n.name)return"";let t=at(n),e=n.name.toLowerCase().replace(/^(_)?exec_/,"");if(e==="press_key")return t.key||t.keycode||"";if(e==="swipe"||e==="scroll"||e==="drag"||e==="drag_and_drop"){let o=t.direction||t.gesture||(typeof t.action=="string"?t.action:"");return o&&Pt(o)?String(o).toUpperCase():""}return e==="wait_for_delay"||e==="wait_delay"?t.time_in_ms?`${t.time_in_ms}ms`:t.delay_ms?`${t.delay_ms}ms`:t.time?`${t.time}`:"":e==="long_press"&&t.duration?`Duration: ${t.duration}ms`:e==="input_text"||e==="input"?t.text||t.input_text||"":t.input_text||""}function um(n){if(!n||!n.name)return"";let t=at(n),o=n.name.replace(/^(_)?exec_/,"").toLowerCase(),i=o==="click_sequence"||o==="tap_sequence"||!!(t.sequence||t.normalized_sequence),r=t.normalized_sequence||t.sequence||t.targets||(Array.isArray(t.coordinates)&&Array.isArray(t.coordinates[0])?t.coordinates:null),a=Br(r);if(a&&a.length>0&&(i||a.length>1))return a.map(f=>`[${f[0]}, ${f[1]}]`).join(" \u2192 ");let s=oe(t.normalized_start_coordinates||t.start_coordinates||t.start),c=oe(t.normalized_end_coordinates||t.end_coordinates||t.end);if(s&&c&&s.length===2&&c.length===2)return`[${s[0]}, ${s[1]}] \u2192 [${c[0]}, ${c[1]}]`;let p=oe(t.normalized_coordinates)||oe(t.coordinates)||oe(t.target)||oe(t.action)||oe(t.gesture)||oe(t.point);return p&&Array.isArray(p)?p.length===4?`[${p[0]}, ${p[1]}] \u2192 [${p[2]}, ${p[3]}]`:p.length===2?`[${p[0]}, ${p[1]}]`:p.join(", "):t.x!==void 0&&t.y!==void 0?`[${t.x}, ${t.y}]`:""}function gm(n){if(!n||!n.name)return"";let t=at(n);return t.analysis||t.reasoning||t.summary||""}function pm(n){if(!n||!n.name)return!1;let t=n.name.toLowerCase().replace(/^(_)?exec_/,"");return t==="run_adb_command"||t==="run_short_adb_command"}function OP(n){return at(n).CommandLine||""}function vP(n){return at(n).Cwd||""}function yP(n){return at(n).RequestedTerminalID||""}function xP(n){if(!n||pm(n)||lm(n)||dm(n)||um(n)||gm(n))return"";let t=at(n);if(!t||typeof t!="object")return"";let e=new Set(["state","controller","ctx","session_id","step_id","trace_id","parent_trace_id","times","delay_ms"]),o=Object.entries(t).filter(([i,r])=>!e.has(i)&&r!==void 0&&r!==null&&r!=="");return o.length===0?"":o.map(([i,r])=>`${i}: ${typeof r=="object"?JSON.stringify(r):r}`).join(", ")}function wP(n){if(!n)return!1;if(n.status==="failed"||n.status==="error")return!0;let t=at(n);return t.status==="failed"||t.status==="error"||t.status==="cannot_fix"}function SP(n){if(!n)return"Tool Failed";let t=at(n);return t.status==="cannot_fix"?"Status: cannot_fix":t.error||t.message||t.failure_reason?t.error||t.message||t.failure_reason:n.error||n.message?n.error||n.message:"Action Failed"}function kP(n,t){if(!n)return[];let e=n.payload||n.args||n;if(!e||typeof e!="object")return[];if(t&&t.has(e))return t.get(e);let o=new Set(["action","name","type","target_text","text","input_text","target","coordinates","coords","target_bounds","bounds","target_resource_id","resource_id","target_class","class_name","normalized_coordinates","pre_image_name","post_image_name","pre_screenshot","post_screenshot","before_screenshot","after_screenshot","status","success","timestamp","created_at","start_time","execution_id","controller","agent","session_id","step_id","app_name","package_name","app","key","keycode","time_in_ms","delay_ms","delay_seconds","duration","args","kwargs","parameters","extra_params","payload","trace_id","result","error","analysis","details","command","cwd","terminal_id"]),i=[],r=n.args||n.Args||n.kwargs||n.parameters||n.payload,a={};if(r){if(typeof r=="object")a=r;else if(typeof r=="string")try{a=JSON.parse(r)}catch(c){!r.includes("<")&&!r.includes("object at")&&(a={details:r})}}let s=S(S(S({},n),typeof e=="object"?e:{}),a);for(let[c,p]of Object.entries(s)){let f=c.toLowerCase();if(o.has(f)||p==null||p==="")continue;let _=String(p);if(_.includes("object at 0x")||_.startsWith("h.toUpperCase());(f==="time_in_ms"||f==="delay_ms")&&(C="Delay"),i.push({key:C,value:_})}return t&&t.set(e,i),i}function EP(n){if(!n)return!1;let t=n.trim();if(!t)return!1;if(t.startsWith("```")){let e=t.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);e&&(t=e[1].trim())}if(t.startsWith("{")||t.startsWith("["))return!1;try{let e=JSON.parse(t);if(typeof e=="object"&&e!==null)return!1}catch(e){}return!(/^\s*\{.*"label"\s*:.*"results"\s*:/s.test(t)||/^\s*\{.*"point"\s*:.*"label"\s*:/s.test(t)||/^\s*\{.*"action"\s*:/s.test(t)||/^\s*\{.*"name"\s*:/s.test(t)||/^\s*\{\s*"[^"]+"\s*:\s*/.test(t)||/^\s*\[\s*\{\s*"[^"]+"\s*:\s*/.test(t))}function Vn(n){if(typeof n=="object"&&n!==null){if(n.message&&typeof n.message=="string")return Vn(n.message);if(n.error?.message&&typeof n.error?.message=="string")return Vn(n.error.message);if(n.detail&&typeof n.detail=="string")return Vn(n.detail);try{return JSON.stringify(n)}catch(a){return String(n)}}let t=String(n).trim();if(!t)return"Unknown error";let e=t.match(/"message"\s*:\s*"((?:[^"\\]|\\.)*)"/i);if(e&&e[1]){let a=e[1].replace(/\\"/g,'"').replace(/\\n/g," ").trim();if(a)return a}let o=t.match(/'message'\s*:\s*['"]((?:[^'\\]|\\.)*)['"]/i);if(o&&o[1]){let a=o[1].replace(/\\'/g,"'").replace(/\\n/g," ").trim();if(a)return a}let i=t.match(/\{[\s\S]*\}/);if(i)try{let a=i[0].replace(/'/g,'"').replace(/True/g,"true").replace(/False/g,"false").replace(/None/g,"null"),s=JSON.parse(a);if(s?.message)return String(s.message);if(s?.error?.message)return String(s.error.message)}catch(a){}let r=t;return r.includes("=== Source Location Trace")&&(r=r.split("=== Source Location Trace")[0]),r.includes("[type.googleapis.com")&&(r=r.split("[type.googleapis.com")[0]),r=r.replace(/^Pre-execution validation failed:\s*/i,"").replace(/^Pixel-level validation failed:\s*/i,"").replace(/^Execution error:\s*/i,"").replace(/^ServerError:\s*/i,"").replace(/^(?:LLM\s+(?:Request\s+)?Error\s*:\s*)+/i,"").trim(),r||"Unknown error"}function ke(n){return n?Array.isArray(n)?n.length>0?n[0]:null:n:null}function jn(n){if(!n)return!1;let t="";if(typeof n=="string")t=n.toLowerCase();else{let e=ke(n);if(!e)return!1;t=(e.name||e.action||"").toLowerCase()}return["tap","click","click_sequence","input","input_text","swipe","scroll","press_key","press_home","press_back","launch_app","manage_app","open_app","focus_and_input_text","focus_and_clear_text","long_press","long_press_on","wait_for_delay","wait"].includes(t)}function jo(n){if(!n)return!1;let t="";if(typeof n=="string")t=n.toLowerCase();else{let e=ke(n);if(!e)return!1;t=(e.name||e.action||"").toLowerCase()}return t=t.replace(/^(_)?(self\.)?exec_/,""),t==="report_task_status"||t==="report_status"||t==="submit_task_status"}function TP(n){let t=ke(n);if(!t)return"completed";let o=(t.args&&typeof t.args=="object"?t.args:t.payload?.args||t.payload||t).status||t.status;return typeof o=="string"?o.toLowerCase():"completed"}function $d(n){let t=ke(n);if(!t)return"";let e=t.args&&typeof t.args=="object"?t.args:t.payload?.args||t.payload||t;return e.explanation||e.reason||e.summary||t.explanation||t.reason||t.summary||""}function zd(n){let t=ke(n);if(!t)return"ads_click";switch((t.name||t.action||"").toLowerCase()){case"tap":case"click":case"click_sequence":return"ads_click";case"input":case"input_text":case"focus_and_input_text":return"keyboard";case"focus_and_clear_text":case"clear_text":return"backspace";case"swipe":case"scroll":return"swipe";case"drag":case"drag_and_drop":return"drag_indicator";case"press_key":case"press_home":case"press_back":return"keyboard_tab";case"launch_app":case"manage_app":case"open_app":return"open_in_new";case"long_press":case"long_press_on":return"touch_app";case"wait_for_delay":case"delay":case"wait":return"hourglass_empty";default:return"settings"}}function mm(n){let t=ke(n);if(!t)return"Action";let e=(t.name||t.action||"").toLowerCase();switch(e){case"tap":case"click":case"tap_element":case"click_element":return"Tapping Element";case"input":case"input_text":case"focus_and_input_text":return"Entering Text";case"focus_and_clear_text":case"clear_text":return"Clearing Text";case"swipe":case"scroll":{let o=ke(n),i=o?.args&&typeof o.args=="object"?o.args:{},r=o?.direction||o?.gesture||i.direction||i.gesture||(typeof i.action=="string"?i.action:"")||(typeof o?.action=="string"&&o.action!==e?o.action:"");return r&&Pt(r)?`Swiping Screen (${String(r).toUpperCase()})`:"Swiping Screen"}case"drag":case"drag_and_drop":return"Dragging Screen";case"press_key":case"press_home":case"press_back":return"Pressing Hardware Key";case"launch_app":case"open_app":return"Launching Application";case"stop_app":case"close_app":return"Stopping Application";case"manage_app":{let o=ke(n),i=(o?.action||o?.args?.action||"").toLowerCase();return i==="launch"?"Launching Application":i==="stop"||i==="close"?"Stopping Application":"Managing Application"}case"wait_for_delay":case"delay":case"wait":return"Waiting for Delay";case"long_press":case"long_press_on":return"Long Pressing Element";case"click_sequence":return"Clicking Sequence";default:return e.replace(/_/g," ").replace(/\b\w/g,o=>o.toUpperCase())}}function _m(n){let t=ke(n);if(!t)return"";let e=(t.name||t.action||"").toLowerCase(),o=t.args&&typeof t.args=="object"?t.args:{};if(e.includes("app")){let i=t.app_name||t.package_name||t.app||o.app_name||o.package_name||o.app||"",r=i?i.charAt(0).toUpperCase()+i.slice(1):"",a=t.action||o.action||"",s=a?String(a).charAt(0).toUpperCase()+String(a).slice(1).toLowerCase():"";return s&&r?`${s} ${r}`:r||s||""}if(e.includes("delay")||e.includes("wait")){let i=t.time_in_ms||t.delay_ms||t.delay_seconds||o.time_in_ms||o.delay_ms||o.delay_seconds||o.duration;if(i)return`${i}ms`}return t.target_text||t.target_class||t.element_id||o.target_text||o.element_id||""}function AP(n){let t=ke(n);if(!t)return"Input";let e=(t.name||t.action||"").toLowerCase();if(e.includes("delay")||e.includes("wait"))return"Duration";if(e==="swipe"||e==="scroll"||e==="drag"||e==="drag_and_drop"){let o=ke(n),i=o?.args&&typeof o.args=="object"?o.args:{},r=o?.direction||o?.gesture||i.direction||i.gesture||(typeof i.action=="string"?i.action:"")||(typeof o?.action=="string"&&o.action!==e?o.action:"");return r&&Pt(r)?"Direction":"Input"}return e==="press_key"||e.includes("key")?"Key":e==="input_text"||e.includes("input")?"Input Text":"Input"}function NP(n){let t=ke(n);if(!t)return"";let e=(t.name||t.action||"").toLowerCase(),o=t.args&&typeof t.args=="object"?t.args:{};if(e==="press_key"||e.includes("key"))return t.key||t.keycode||o.key||o.keycode||"";if(e==="swipe"||e==="scroll"||e==="drag"||e==="drag_and_drop"){let i=t.direction||t.gesture||o.direction||o.gesture||(typeof o.action=="string"?o.action:"")||(typeof t.action=="string"&&t.action!==e?t.action:"");return i&&Pt(i)?String(i).toUpperCase():""}if(e.includes("delay")||e.includes("wait")){let i=t.time_in_ms||t.delay_ms||t.delay_seconds||o.time_in_ms||o.delay_ms||o.delay_seconds||o.duration;if(i)return`${i}ms`}return t.text||t.input_text||o.text||o.input_text||""}function hm(n){let t=ke(n);if(!t)return"";let e=t.args&&typeof t.args=="object"?t.args:{},o=(t.name||t.action||"").toLowerCase(),i=o==="click_sequence"||o==="tap_sequence"||!!(t.sequence||e.sequence||t.normalized_sequence||e.normalized_sequence),r=t.normalized_sequence||e.normalized_sequence||t.sequence||e.sequence||t.targets||e.targets||(Array.isArray(t.coordinates)&&Array.isArray(t.coordinates[0])?t.coordinates:null)||(Array.isArray(e.coordinates)&&Array.isArray(e.coordinates[0])?e.coordinates:null),a=Br(r);if(a&&a.length>0&&(i||a.length>1))return a.map(h=>`[${h[0]}, ${h[1]}]`).join(" \u2192 ");let s=oe(t.normalized_start_coordinates||e.normalized_start_coordinates),c=oe(t.normalized_end_coordinates||e.normalized_end_coordinates);if(s&&c&&s.length===2&&c.length===2)return`[${s[0]}, ${s[1]}] \u2192 [${c[0]}, ${c[1]}]`;let p=oe(t.start_coordinates||t.start_point||t.start||t.from||e.start_coordinates||e.start_point||e.start||e.from),f=oe(t.end_coordinates||t.end_point||t.end||t.to||e.end_coordinates||e.end_point||e.end||e.to);if(p&&f&&p.length===2&&f.length===2)return`[${p[0]}, ${p[1]}] \u2192 [${f[0]}, ${f[1]}]`;let C=oe(t.normalized_coordinates||e.normalized_coordinates)||oe(t.coordinates)||oe(e.coordinates)||oe(t.coords)||oe(e.coords)||oe(t.target)||oe(e.target)||oe(e.action)||oe(t.action)||oe(e.gesture)||oe(t.gesture);return C&&Array.isArray(C)?C.length===4?`[${C[0]}, ${C[1]}] \u2192 [${C[2]}, ${C[3]}]`:C.length===2?`[${C[0]}, ${C[1]}]`:C.join(", "):""}function Bd(n,t){let e=ke(n);if(e&&(e.status==="failed"||e.status==="error"||e.success===!1))return!0;if(t){if(t.status==="failed"||t.status==="error")return!0;if(t.last_execution_result){let o=typeof t.last_execution_result=="string"?(()=>{try{return JSON.parse(t.last_execution_result)}catch(i){return null}})():t.last_execution_result;if(o&&typeof o=="object"){if(o.status==="failed"||o.status==="error"||o.success===!1||o.is_successful===!1||o.repair_status==="fixed"||o.repair_status==="failed"||o.repair_status==="cannot_fix")return!0;if(Array.isArray(o.execution)&&o.execution.length>0){let i=o.execution[0];if(i&&(i.status==="failed"||i.status==="error"||i.error||Array.isArray(i.attempts)&&i.attempts.length>0))return!0}}}}return!1}function RP(n,t){let e=ke(n);if(e&&(e.error||e.message||e.failure_reason))return Vn(e.error||e.message||e.failure_reason);if(t&&t.last_execution_result){let o=typeof t.last_execution_result=="string"?(()=>{try{return JSON.parse(t.last_execution_result)}catch(i){return null}})():t.last_execution_result;if(o&&typeof o=="object"){if(Array.isArray(o.execution)&&o.execution.length>0){let i=o.execution[0];if(i){if(Array.isArray(i.attempts)&&i.attempts.length>0)return Vn(i.attempts[0]);if(i.error||i.failure_reason||i.message)return Vn(i.error||i.failure_reason||i.message)}}if(o.error||o.message||o.failure_reason)return Vn(o.error||o.message||o.failure_reason)}}return"Action Failed"}function FP(n){let t=ke(n);if(!t)return"";let e=t.target_bounds||t.bounds||t.args&&(t.args.target_bounds||t.args.bounds);return Array.isArray(e)?e.join(", "):e?String(e):""}function LP(n){let t=ke(n);return t&&(t.target_resource_id||t.resource_id||t.args&&(t.args.target_resource_id||t.args.resource_id))||""}function VP(n){let t=ke(n);return t&&(t.target_class||t.class_name||t.args&&(t.args.target_class||t.args.class_name))||""}function jP(n,t){let e=ke(n);if(!e||typeof e!="object")return[];if(t&&t.has(e))return t.get(e);let o=new Set(["action","name","type","target_text","text","input_text","target","coordinates","coords","target_bounds","bounds","target_resource_id","resource_id","target_class","class_name","normalized_coordinates","normalized_start_coordinates","normalized_end_coordinates","start_coordinates","end_coordinates","start","end","from","to","pre_image_name","post_image_name","pre_screenshot","post_screenshot","before_screenshot","after_screenshot","status","success","timestamp","created_at","start_time","execution_id","controller","agent","session_id","step_id","app_name","package_name","app","key","keycode","time_in_ms","delay_ms","delay_seconds","duration","args","kwargs","parameters","extra_params","direction","gesture"]),i=[],r=e.args||e.Args||e.kwargs||e.parameters,a={};if(r){if(typeof r=="object")a=r;else if(typeof r=="string")try{a=JSON.parse(r)}catch(p){!r.includes("<")&&!r.includes("object at")&&(a={details:r})}}let s=S(S({},e),a),c=s.duration||s.duration_ms;c!=null&&c!==""&&i.push({key:"Duration",value:typeof c=="number"?`${c}ms`:String(c)});for(let[p,f]of Object.entries(s)){let _=p.toLowerCase();if(o.has(_)||f==null||f==="")continue;let C=String(f);if(C.includes("object at 0x")||C.startsWith("P.toUpperCase());(_==="time_in_ms"||_==="delay_ms")&&(h="Delay"),i.push({key:h,value:C})}return t&&t.set(e,i),i}function fm(n){if(!n||n==="None"||n==="null"||n==="undefined"||typeof n!="string")return null;let t=n.trim();return!t||t==="None"||t==="null"||t==="undefined"?null:t.startsWith("data:")||t.startsWith("http://")||t.startsWith("https://")||t.startsWith("/local_file")||t.startsWith("/images/")||t.startsWith("/api/images/")?t:t.startsWith("file://")?`/local_file?path=${encodeURIComponent(t)}`:t.startsWith("/")?`/local_file?path=${encodeURIComponent("file://"+t)}`:`/images/${t}`}function fD(n,t){return!n||n===t?.action_taken||Array.isArray(t?.action_taken)&&(t.action_taken===n||t.action_taken.includes(n))||n.is_primary_step_action?!1:!!(n.trace_id||n.payload||n.type==="tool"||n.type==="action"&&n.trace_id)}var DP=new WeakMap;function go(n){if(typeof n=="string"&&(n.trim().startsWith("{")||n.trim().startsWith("[")))try{return JSON.parse(n)}catch(t){return n}return n}function $P(n){let t=ke(n);if(!t)return null;let e=go(t.payload),o=go(t.result||e?.result),i=go(t.args||e?.args),r=o?.pre_image_name||o?.pre_screenshot_name||o?.pre_screenshot||e?.pre_image_name||e?.pre_screenshot_name||e?.pre_screenshot||i?.pre_image_name||i?.pre_screenshot_name||i?.pre_screenshot||t.pre_image_name||t.pre_screenshot_name||t.pre_screenshot||t.before_screenshot||t.screenshot;return r?String(r):null}function jd(n){let t=ke(n);if(!t)return null;let e=go(t.payload),o=go(t.result||e?.result),i=go(t.args||e?.args),r=o?.post_image_name||o?.post_screenshot_name||o?.post_screenshot||e?.post_image_name||e?.post_screenshot_name||e?.post_screenshot||i?.post_image_name||i?.post_screenshot_name||i?.post_screenshot||t.post_image_name||t.post_screenshot_name||t.post_screenshot||t.after_screenshot;return r?String(r):null}function mD(n){if(!n)return null;if(n.failed_screenshot)return String(n.failed_screenshot);if(n.failure_screenshot)return String(n.failure_screenshot);if(n.failed_post_image_name)return String(n.failed_post_image_name);if(Array.isArray(n.generic_tools))for(let t of n.generic_tools){let e=ke(t),o=go(e?.payload),i=go(e?.args||o?.args),r=String(e?.name||e?.agent_name||"").toLowerCase();if(i?.post_screenshot_name)return String(i.post_screenshot_name);if(i?.post_screenshot&&(r.includes("failure")||r.includes("validator")||r.includes("diagnos")))return String(i.post_screenshot);if(e?.post_screenshot_name&&(r.includes("failure")||r.includes("validator")))return String(e.post_screenshot_name)}return null}function IP(n){if(!n)return 0;let t=n.timestamp??n.start_time??n.created_at;if(typeof t=="number")return t<1e11?t*1e3:t;if(typeof t=="string"){let e=new Date(t).getTime();if(!isNaN(e)&&e>0)return e}return 0}function _D(n){let t=new Map;if(!n||typeof n!="object")return t;let e=Array.isArray(n.generic_tools)?n.generic_tools.length:0,o=`${n.step_id||""}_${e}_${n.post_image_name||""}_${n.pre_image_name||""}`,i=DP.get(n);if(i&&i.key===o)return i.map;let r=new Map,a=[];n.action_taken&&a.push({item:n.action_taken,act:ke(n.action_taken),timestamp:IP(n.action_taken),isPrimary:!0}),Array.isArray(n.generic_tools)&&n.generic_tools.forEach(h=>{h&&a.push({item:h,act:ke(h),timestamp:IP(h),isPrimary:!1})}),a.sort((h,P)=>h.timestamp-P.timestamp);let s=mD(n),c=!!s||n.action_taken&&Bd(n.action_taken,n),p=a.some(h=>!h.isPrimary&&(jn(h.act)||!!jd(h.act))),f=null;for(let h=a.length-1;h>=0;h--){let P=a[h];if(jn(P.act)||jd(P.act)||P.isPrimary){f=P.item;break}}let _=n.pre_image_name||n.pre_screenshot||null,C=!1;for(let h of a){let P=h.act,T=$P(P),A=jd(P),N=String(P?.agent_name||P?.agent||go(P?.payload)?.agent_name||P?.name||"").toLowerCase(),E=N.includes("failure")||N.includes("analyzer")||N.includes("validator")||N.includes("diagnos");s&&!C&&(E||!h.isPrimary&&c)&&(_=s,C=!0);let U=T||_,ne=null,J=!1;A?(ne=A,J=!0):(h.isPrimary&&!c||h.item===f&&!c||h.item===f&&E)&&(ne=n.post_image_name||n.post_screenshot||null),ne&&(_=ne);let X={pre:U,post:ne,hasExplicitPost:J};r.set(h.item,X),P&&P!==h.item&&r.set(P,X),P?.trace_id&&r.set(P.trace_id,X)}return DP.set(n,{key:o,map:r}),r}function zP(n,t){let e=_D(n);if(!t)return{pre:n?.pre_image_name||n?.pre_screenshot||null,post:n?.post_image_name||n?.post_screenshot||null,hasExplicitPost:!!(n?.post_image_name||n?.post_screenshot)};let o=ke(t);if(e.has(t))return e.get(t);if(o&&e.has(o))return e.get(o);if(o?.trace_id&&e.has(o.trace_id))return e.get(o.trace_id);let i=$P(o),r=jd(o),a=i||n?.pre_image_name||n?.pre_screenshot||null,s=r||(fD(t,n)?null:n?.post_image_name||n?.post_screenshot||null);return{pre:a,post:s,hasExplicitPost:!!r}}function Cm(n,t){let e=zP(n,t);return fm(e.pre)}function Mm(n,t){let e=zP(n,t),o=fm(e.post),i=fm(e.pre);return o&&i&&o===i&&!e.hasExplicitPost?null:o}function BP(n){if(!Array.isArray(n)||n.length===0)return[];let t=[];for(let s of n)s&&((s.type==="step_updated"||s.type==="step_recorded"||s.type==="step")&&s.data?t.push(s.data):(s.step_number!==void 0||s.step_id!==void 0)&&t.push(s));let e=[],o=new Map,i=new Map;for(let s of t){let c=s.step_id!==void 0&&s.step_id!==null&&String(s.step_id).trim()!==""?String(s.step_id).trim():null,p=s.step_number!==void 0&&s.step_number!==null?Number(s.step_number):null,f=-1;if(c&&o.has(c)?f=o.get(c):p!==null&&i.has(p)&&(f=i.get(p)),f>=0){let _=e[f],C=_.action_taken,h=s.action_taken,P=C&&jn(C)&&jo(h),T=h&&jn(h)&&jo(C),A=p!==null?p:_.step_number,N=_.step_id||s.step_id,E=F(S(S({},_),s),{step_id:N,step_number:A,pre_image_name:P?_.pre_image_name:s.pre_image_name||_.pre_image_name,post_image_name:P?_.post_image_name||s.post_image_name:s.post_image_name||_.post_image_name,pre_screenshot:P?_.pre_screenshot:s.pre_screenshot||_.pre_screenshot,post_screenshot:P?_.post_screenshot||s.post_screenshot:s.post_screenshot||_.post_screenshot,action_taken:P?_.action_taken:T?h:s.action_taken||_.action_taken,last_execution_result:s.last_execution_result||_.last_execution_result,summary:P?_.summary||s.summary:s.summary||_.summary,operator_raw_thinking:s.operator_raw_thinking||_.operator_raw_thinking,operator_native_thinking:s.operator_native_thinking||_.operator_native_thinking,generic_tools:s.generic_tools||_.generic_tools,timestamp:_.timestamp||s.timestamp});e[f]=E,N&&o.set(String(N),f),A!=null&&i.set(Number(A),f)}else{let _=e.length;e.push(S({},s)),c&&o.set(c,_),p!==null&&i.set(p,_)}}let r=[];for(let s of e){let c=s.action_taken,p=Cm(s,c),f=Mm(s,c),_=p||f;_&&r.push({stepData:s,act:c,preUrl:p,postUrl:f,primaryImg:_})}r.sort((s,c)=>{let p=Number(s.stepData.step_number??99999),f=Number(c.stepData.step_number??99999);return p!==f?p-f:Number(s.stepData.timestamp??0)-Number(c.stepData.timestamp??0)});let a=[];for(let s=0;s{let t=this.rawSessions(),e=this.pendingQueue(),o=this.agentStatus(),i=this.runningGoal(),r=this.runningSessionId(),a=this.activeTasks(),s=new Map,c=new Map(e.map(f=>[f.session_id,f])),p=new Map(a.map(f=>[f.session_id,f]));if(t.forEach(f=>{let _=p.get(f.session_id),C=c.get(f.session_id),h=(o==="running"||o==="paused")&&r===f.session_id||!!_,P=f.status==="completed"||f.status==="success"||f.status==="failed"||f.status==="cancelled",T=f.status;P?T=f.status==="success"?"completed":f.status:T=h?o==="paused"?"paused":"running":!!C&&!h?"pending":f.status;let A=f.device_serial||f.device_id||_?.device_id||C?.device_serial||null;if(!A&&f.device_info)try{let E=typeof f.device_info=="string"?JSON.parse(f.device_info):f.device_info;A=E?.device_id||E?.device_serial||null}catch(E){}let N=F(S({},f),{status:T,device_serial:A,model_info:h&&this.activeModel()?this.activeModel():f.model_info});s.set(f.session_id,N),P?this.activeSessionTracking.delete(f.session_id):(T==="running"||T==="paused"||T==="pending")&&this.activeSessionTracking.set(f.session_id,N)}),e.forEach(f=>{if(!s.has(f.session_id)){let _=p.get(f.session_id),C=(o==="running"||o==="paused")&&r===f.session_id||!!_,h=F(S({},f),{status:C?o==="paused"?"paused":"running":f.status||"pending",device_serial:f.device_serial||f.device_id||_?.device_id||null});s.set(f.session_id,h),this.activeSessionTracking.set(f.session_id,h)}}),a.length>0)a.forEach(f=>{let _=f.session_id||`active-${f.device_id}`,C=s.get(_);if(C){if(C.status==="pending"){let h=F(S({},C),{status:"running",device_serial:f.device_id||C.device_serial});s.set(_,h),this.activeSessionTracking.set(_,h)}}else{let h={session_id:_,initial_goal:f.goal||i||"",start_time:f.acquired_at?new Date(f.acquired_at).getTime()/1e3:Date.now()/1e3,status:"running",model_info:this.activeModel()||void 0,device_serial:f.device_id||null};s.set(_,h),this.activeSessionTracking.set(_,h)}});else if((o==="running"||o==="paused")&&r&&!s.has(r)){let f={session_id:r,initial_goal:i||"",start_time:Date.now()/1e3,status:o,model_info:this.activeModel()||void 0};s.set(r,f),this.activeSessionTracking.set(r,f)}return this.activeSessionTracking.forEach((f,_)=>{s.has(_)||s.set(_,F(S({},f),{status:"running"}))}),Array.from(s.values()).sort((f,_)=>_.start_time-f.start_time)});currentSessionId=x(null);sessionLogs=x([]);isSessionContentLoading=x(!1);agentStatus=x("idle");runningSessionId=x(null);runningGoal=x(null);isPaused=x(!1);pausedError=x(null);isRetrying=x(!1);retryMessage=x(null);activeModel=x(null);userPinnedSessionId=x(null);startupProgressBySession=x({});pendingStartupProgress=x([]);currentStartupProgress=I(()=>{let t=this.currentSessionId();if(t){let e=String(t).trim().toLowerCase(),o=this.startupProgressBySession(),i=o[t];if(i?.length)return i;let r=Object.entries(o).find(([a])=>a.trim().toLowerCase()===e);if(r?.[1]?.length)return r[1]}return this.pendingStartupProgress()});currentNotes=x({});selectedNoteKey=x("task_plan.md");activeTab=x("tasks");isVideoWindowOpen=x(!1);isVideoMinimized=x(!1);activeVideoUrl=x(null);activeVideoSegments=x([]);activeVideoTitle=x("");isVideoLoading=x(!1);recordingPlaybackStatus=x("idle");recordingPlaybackMessage=x("");shouldAutoplayVideo=x(!1);videoSeekRequest=x(null);stepSeekRequest=x(null);playerMode=x("video");activeVideoSessionId=null;videoSeekRequestId=0;stepSeekRequestId=0;videoRequestGeneration=0;videoRetryTimer=null;videoWaitStartedAt=0;stepLogsForReplay=I(()=>this.sessionLogs().filter(t=>t&&(t.type==="step_updated"||t.type==="step_recorded")),{equal:(t,e)=>t.length===e.length&&t.every((o,i)=>o===e[i])});currentSessionStepFrames=I(()=>BP(this.stepLogsForReplay()));hasCurrentSessionStepFrames=I(()=>this.currentSessionStepFrames().length>0);setPlayerMode(t){this.playerMode.set(t)}togglePlayerMode(){this.playerMode.update(t=>t==="video"?"steps":"video")}requestStepSeek(t){this.stepSeekRequestId++,this.stepSeekRequest.set({index:t,requestId:this.stepSeekRequestId})}clearUserPinnedSession(){this.userPinnedSessionId.set(null)}currentSession=I(()=>{let t=this.currentSessionId();return t&&this.sessions().find(e=>e.session_id===t)||null});isCurrentSessionRunning=I(()=>{let t=this.currentSessionId();if(!t)return!1;let e=this.currentSession();return e?e.status==="running"||e.status==="paused":!!((this.agentStatus()==="running"||this.agentStatus()==="paused")&&this.runningSessionId()===t||this.activeTasks().some(i=>i.session_id===t))});currentSessionVideoUrl=I(()=>{let t=this.currentSessionId();return t&&this.sessions().find(o=>o.session_id===t)?.video_url||null});currentSessionRecordingStatus=I(()=>{let e=this.currentSession()?.recording_status;return e==="recording"||e==="finalizing"||e==="processing"?"processing":e});eventSource=null;statusInterval=null;sessionLoadGeneration=0;sessionSnapshotRequestId=0;sessionSnapshotAppliedId=0;pendingSnapshotRequests=new Set;pendingStreamChunks=new Map;streamFlushTimer=null;lastQueueSignature=null;lastActiveTasksSignature=null;lastPersistedSessionsJson=null;onVisibilityChange=()=>{typeof document<"u"&&!document.hidden&&(this.fetchStatus(),this.fetchSessions())};constructor(){this.restoreSessionsCache(),this.fetchSessions(),this.startStatusPolling(),this.ensureLiveStream(),typeof document<"u"&&document.addEventListener("visibilitychange",this.onVisibilityChange),D(Ae).onDestroy(()=>this.destroy())}isRunningTask=I(()=>this.agentStatus()==="running"||this.agentStatus()==="paused"?!0:this.sessions().some(t=>t.status==="running"||t.status==="paused"));getProTuningDefaults(){return this.http.get("/api/run/defaults")}runTask(t,e="flash",o,i,r){return new ie(a=>{let s={stage:"submitting",message:"Submitting the task",timestamp:Date.now()/1e3};this.pendingStartupProgress.set([s]);let c={goal:t,profile:e};o&&o.trim()&&(c.expected_output=o.trim()),i!==void 0&&(c.enable_outputter=i),r?.verificationLevel&&(c.verification_level=r.verificationLevel),r?.explorerMode&&(c.explorer_mode=r.explorerMode),this.clearUserPinnedSession(),this.http.post("/api/run",c).subscribe({next:p=>{if(p&&p.tasks&&p.tasks.length>0){let f=p.tasks[0].session_id;if(f){this.appendStartupProgress(F(S({},s),{session_id:f}),f),this.pendingStartupProgress.set([]);let _=this.agentStatus()==="running"||this.sessions().some(h=>h.status==="running"),C=this.runningSessionId()||this.sessions().find(h=>h.status==="running"||h.status==="paused")?.session_id;(!_||C===f)&&this.selectSession(f,!1)}}this.pendingStartupProgress.set([]),a.next(p),a.complete()},error:p=>{this.pendingStartupProgress.set([]),a.error(p)}})})}stopTask(t,e=!1){let o=null,i=e;typeof t=="boolean"?i=t:typeof t=="string"&&t.trim()?o=t.trim():o=this.currentSessionId()||this.runningSessionId()||null,!i&&!o&&(o=this.sessions().find(c=>c.status==="running"||c.status==="paused")?.session_id||null),o&&this.setSessionStatus(o,"cancelled");let r=this.sessions().filter(c=>(c.status==="running"||c.status==="paused")&&c.session_id!==o);i||r.length===0?(this.agentStatus.set("idle"),this.runningSessionId.set(null),this.runningGoal.set(null)):this.runningSessionId()===o&&(this.runningSessionId.set(r[0].session_id),this.runningGoal.set(r[0].initial_goal||null)),this.isPaused.set(!1),this.pausedError.set(null),this.isRetrying.set(!1),this.invalidateStatusSignatures(),i&&this.pendingQueue.set([]),(!o||this.currentSessionId()===o)&&(this.flushStreamChunks(),this.sessionLogs.update(c=>c.some(p=>p.type==="llm_stream"&&!p.data?.isCompleted)?c.map(p=>p.type==="llm_stream"&&!p.data?.isCompleted?F(S({},p),{data:F(S({},p.data),{isCompleted:!0})}):p):c)),o&&this.activeTasks.update(c=>c.filter(p=>p.session_id!==o));let a=`/api/stop?all=${i}`;!i&&o&&(a+=`&session_id=${encodeURIComponent(o)}`);let s={all:i};o&&(s.session_id=o),this.http.post(a,s).subscribe({next:()=>{this.fetchStatus(),this.fetchSessions()},error:c=>{console.error("Failed to stop task:",c),this.fetchSessions(),this.fetchStatus()}})}resumeTask(){this.http.post("/api/resume",{}).subscribe({next:t=>{if(t?.status!=="resumed"){this.fetchStatus();return}let e=this.runningSessionId();this.isPaused.set(!1),this.pausedError.set(null),this.agentStatus.set("running"),this.setSessionStatus(e,"running"),this.fetchStatus()},error:t=>{console.error("Failed to resume task:",t)}})}fetchSessions(){this.http.get("/api/sessions").subscribe({next:t=>{this.rawSessions.set(t),this.persistSessionsCache(t),this.updateModelForCurrentView(t),!this.currentSessionId()&&!this.userPinnedSessionId()&&this.agentStatus()!=="running"&&t.length>0&&this.selectSession(t[0].session_id,!1)},error:t=>{console.error("Failed to fetch sessions from backend:",t)}})}deleteSession(t){if(this.invalidateStatusSignatures(),this.rawSessions.update(e=>e.filter(o=>o.session_id!==t)),this.persistSessionsCache(this.rawSessions()),this.pendingQueue.update(e=>e.filter(o=>o.session_id!==t)),this.userPinnedSessionId()===t&&this.userPinnedSessionId.set(null),this.currentSessionId()===t){this.selectSession("",!1),this.isVideoWindowOpen()&&this.closeVideoPlayer();let e=this.runningSessionId();e&&this.agentStatus()==="running"&&this.selectSession(e,!1)}return new ie(e=>{this.http.post(`/api/sessions/${t}/delete`,{}).subscribe({next:o=>{this.fetchSessions(),this.fetchStatus(),e.next(o),e.complete()},error:o=>{console.error(`Failed to delete session ${t}:`,o),this.fetchSessions(),this.fetchStatus(),e.error(o)}})})}clearAllHistory(){return this.invalidateStatusSignatures(),this.userPinnedSessionId.set(null),this.rawSessions.set([]),this.clearSessionsCache(),this.pendingQueue.set([]),this.selectSession("",!1),this.isVideoWindowOpen()&&this.closeVideoPlayer(),new ie(t=>{this.http.post("/api/cleanup",{}).subscribe({next:e=>{this.fetchSessions(),this.fetchStatus(),t.next(e),t.complete()},error:e=>{console.error("Failed to cleanup history:",e),this.fetchSessions(),this.fetchStatus(),t.error(e)}})})}selectSession(t,e=!1){if(e&&(t&&t===this.runningSessionId()&&this.agentStatus()==="running"?this.userPinnedSessionId.set(null):t?this.userPinnedSessionId.set(t):this.userPinnedSessionId.set(null)),!t){this.sessionLoadGeneration++,this.pendingSnapshotRequests.clear(),this.discardPendingStreamChunks(),this.isSessionContentLoading.set(!1),this.currentSessionId.set(null),this.sessionLogs.set([]),this.currentNotes.set({});return}if(this.currentSessionId()===t)return;let o=++this.sessionLoadGeneration;this.pendingSnapshotRequests.clear(),this.discardPendingStreamChunks(),this.sessionSnapshotAppliedId=0,this.isSessionContentLoading.set(!0),this.currentSessionId.set(t),this.sessionLogs.set([]),this.activePauseCardKey=null,this.isPaused.set(!1),this.pausedError.set(null),this.fetchNotes(t),this.fetchChecks(t),this.updateModelForCurrentView(),this.isVideoWindowOpen()&&this.openVideoPlayer(t),console.debug(`Selecting session: ${t}`),this.backfillSessionSteps(t,o),this.ensureLiveStream()}ensureLiveStream(){this.eventSource||(console.debug("Establishing persistent unified live stream via /api/stream"),this.zone.runOutsideAngular(()=>{this.eventSource=new EventSource("/api/stream"),this.eventSource.addEventListener("info",()=>{let e=this.currentSessionId();e&&this.backfillSessionSteps(e)}),this.eventSource.addEventListener("keep-alive",()=>{}),["llm_stream","trace_recorded","step_recorded","step_updated","background_tasks_updated","task_paused","task_resumed","llm_retrying","startup_progress","session_started","session_ended","recording_ready","recording_failed","checker_event"].forEach(e=>{this.eventSource?.addEventListener(e,o=>{try{let i=JSON.parse(o.data),r=i?.session_id;if(e!=="llm_stream"&&this.flushStreamChunks(),e==="recording_ready"||e==="recording_failed"){this.isVideoWindowOpen()&&r&&String(r)===String(this.activeVideoSessionId)&&(e==="recording_ready"?this.refreshActiveRecording(!0):(this.cancelVideoRetry(),this.isVideoLoading.set(!1),this.activeVideoUrl.set(null),this.activeVideoSegments.set([]),this.recordingPlaybackStatus.set("failed"),this.recordingPlaybackMessage.set(i?.error||"Recording finalization failed.")));return}if(e==="background_tasks_updated"){this.fetchStatus();return}if(e==="session_started"){this.agentStatus.set("running"),i?.session_id&&this.runningSessionId.set(i.session_id),i?.initial_goal&&this.runningGoal.set(i.initial_goal),this.fetchSessions(),!this.userPinnedSessionId()&&i?.session_id&&this.selectSession(i.session_id,!1);return}if(e==="session_ended"){let s=r||this.runningSessionId();s&&(this.applySessionEndedStatus(s,i),this.invalidateStatusSignatures(),this.activeTasks.update(p=>p.filter(f=>f.session_id!==s)));let c=this.activeTasks();if(c.length>0)this.agentStatus.set("running"),this.runningSessionId.set(c[0].session_id),this.runningGoal.set(c[0].goal||null);else if(this.pendingQueue().length>0){let p=this.pendingQueue()[0];this.agentStatus.set("running"),this.runningSessionId.set(p.session_id),this.runningGoal.set(p.initial_goal||null)}else this.agentStatus.set("idle"),this.runningSessionId.set(null),this.runningGoal.set(null);this.isRetrying.set(!1),this.isPaused.set(!1),this.fetchSessions(),this.fetchStatus(),s&&(this.fetchNotes(s),String(s)===String(this.currentSessionId()||"")&&this.fetchChecks(s),this.isVideoWindowOpen()&&this.activeVideoSessionId===s&&this.recordingPlaybackStatus()==="live"&&this.beginRecordingFinalization(s)),this.updateModelForCurrentView();return}if(e==="startup_progress"){let s=r||this.currentSessionId();if(s){this.appendStartupProgress(i,s);let c=this.currentSessionId();!this.userPinnedSessionId()&&(!c||String(s).trim().toLowerCase()!==String(c).trim().toLowerCase())&&(this.agentStatus.set("running"),this.runningSessionId.set(s),this.selectSession(s,!1))}return}let a=this.currentSessionId();if(r&&a&&String(r).trim().toLowerCase()!==String(a).trim().toLowerCase())return;if(e==="llm_retrying"){this.isRetrying.set(!0);let s=Number(i.attempt||0),c=Number(i.max_retries||0),p=Number(i.delay||0),f=s&&c?` (Attempt ${s}/${c})`:"",_=p>0?`; retrying in ${p.toFixed(2).replace(/\.00$/,"")}s`:"";this.retryMessage.set(`AI service is temporarily busy${f}${_}...`),a&&this.appendLiveLLMRetryTrace(i,a);return}if(e==="task_paused"){if(this.isPaused.set(!0),this.isRetrying.set(!1),this.agentStatus.set("paused"),a){this.runningSessionId.set(a),this.setSessionStatus(a,"paused");let s=i.error||"AI call failed";this.pausedError.set(s),this.appendPausedErrorCard(s,a,i.timestamp,i.step_id,i)}return}if(e==="task_resumed"){this.isPaused.set(!1),this.isRetrying.set(!1),this.pausedError.set(null),a&&this.runningSessionId()===a&&(this.agentStatus.set("running"),this.setSessionStatus(a,"running")),this.activePauseCardKey=null;return}if((e==="step_updated"||e==="step_recorded"||e==="llm_stream")&&this.isRetrying.set(!1),e==="llm_stream"?this.queueStreamChunk(i):this.sessionLogs.update(s=>{let p=s.some(C=>C.type==="llm_stream"&&!C.data.isCompleted)?s.map(C=>C.type==="llm_stream"&&!C.data.isCompleted?F(S({},C),{data:F(S({},C.data),{isCompleted:!0})}):C):[...s],f=typeof i?.timestamp=="number"?new Date(i.timestamp*1e3).toISOString():new Date().toISOString(),_={type:e,timestamp:f,data:i};if(e==="trace_recorded"&&i?.trace_id){let C=p.findIndex(h=>h.type==="trace_recorded"&&h.data?.trace_id===i.trace_id);if(C>-1){let h=[...p];return h[C]=_,h}}return[...p,_]}),e==="trace_recorded"&&i){let s=i.name||"";if(["save_note","read_note","update_note","append_note","list_notes","outputter"].includes(s.toLowerCase())){let c=this.currentSessionId();c&&this.fetchNotes(c)}}}catch(i){console.error(`Failed to parse ${e} event data:`,i),this.sessionLogs.update(r=>[...r,{type:e,timestamp:new Date().toISOString(),data:o.data}])}})}),this.eventSource.onerror=e=>{console.warn("Persistent live stream issue, browser will auto-reconnect:",e)}}))}queueStreamChunk(t){let e=t.execution_id,o=t.step_id,i=t.parent_trace_id||null,r=t.stream_type||"text",a=`${e}|${r}`,s=this.pendingStreamChunks.get(a);if(s?(s.chunk+=t.chunk,o&&(s.stepId=o),i&&(s.parentTraceId=i)):this.pendingStreamChunks.set(a,{execId:e,stepId:o,parentTraceId:i,streamType:r,chunk:t.chunk}),!this.streamFlushTimer){let c=typeof document<"u"&&document.hidden?500:80;this.streamFlushTimer=setTimeout(()=>this.flushStreamChunks(),c)}}discardPendingStreamChunks(){this.pendingStreamChunks?.clear(),this.streamFlushTimer&&(clearTimeout(this.streamFlushTimer),this.streamFlushTimer=null)}flushStreamChunks(){if(this.streamFlushTimer&&(clearTimeout(this.streamFlushTimer),this.streamFlushTimer=null),!this.pendingStreamChunks?.size)return;let t=Array.from(this.pendingStreamChunks.values());this.pendingStreamChunks.clear(),this.sessionLogs.update(e=>{let o=[...e];for(let i of t){let r=o.findIndex(a=>a.type==="llm_stream"&&a.data.execution_id===i.execId&&(a.data.stream_type||"text")===i.streamType);if(r>-1){let a=o[r];o[r]=F(S({},a),{data:F(S({},a.data),{text:a.data.text+i.chunk,step_id:i.stepId||a.data.step_id,parent_trace_id:i.parentTraceId||a.data.parent_trace_id||null})})}else o=o.map(a=>a.type==="llm_stream"&&(a.data.stream_type||"text")===i.streamType&&!a.data.isCompleted&&(a.data.parent_trace_id||null)===(i.parentTraceId||null)?F(S({},a),{data:F(S({},a.data),{isCompleted:!0})}):a),o.push({type:"llm_stream",timestamp:new Date().toISOString(),data:{execution_id:i.execId,step_id:i.stepId,parent_trace_id:i.parentTraceId||null,text:i.chunk,stream_type:i.streamType,isCompleted:!1}})}return o})}backfillSessionSteps(t,e=this.sessionLoadGeneration){let o=++this.sessionSnapshotRequestId;this.pendingSnapshotRequests.add(o),this.http.get(`/api/sessions/${t}/steps`).subscribe({next:i=>{if(this.pendingSnapshotRequests.delete(o),this.currentSessionId()!==t||e!==this.sessionLoadGeneration||o({type:"step_updated",session_id:t,timestamp:new Date((a.timestamp||Date.now()/1e3)*1e3).toISOString(),data:a,history_snapshot:!0}));this.sessionLogs.update(a=>[...r,...a.filter(s=>!s.history_snapshot)]),this.isSessionContentLoading.set(!1)},error:i=>{this.pendingSnapshotRequests.delete(o),console.error("Failed to backfill session steps:",i),this.currentSessionId()===t&&e===this.sessionLoadGeneration&&this.pendingSnapshotRequests.size===0&&this.isSessionContentLoading.set(!1)}}),this.http.get(`/api/sessions/${t}/startup_progress`).subscribe({next:i=>{Array.isArray(i)&&i.length>0&&this.startupProgressBySession.update(r=>{let s=[...r[t]||[]];for(let c of i)s.some(p=>p.stage===c.stage)||s.push(c);return F(S({},r),{[t]:s})})},error:()=>{}})}restoreSessionsCache(){try{let t=localStorage.getItem(bm);if(!t)return;let e=JSON.parse(t);Array.isArray(e)&&(this.lastPersistedSessionsJson=t,this.rawSessions.set(e))}catch(t){this.clearSessionsCache()}}persistSessionsCache(t){try{let e=JSON.stringify(t);if(e===this.lastPersistedSessionsJson)return;this.lastPersistedSessionsJson=e,localStorage.setItem(bm,e)}catch(e){}}clearSessionsCache(){this.lastPersistedSessionsJson=null;try{localStorage.removeItem(bm)}catch(t){}}appendLiveLLMRetryTrace(t,e){let o=typeof t?.timestamp=="number"?t.timestamp>1e11?t.timestamp/1e3:t.timestamp:Date.now()/1e3,i=t?.trace_id||`llm-retry-live-${t?.request_id||"unknown"}-${o}`,r={error:t?.error,delay:t?.delay,attempt:t?.attempt,max_retries:t?.max_retries,provider:t?.provider,source:t?.source,recoverable:t?.recoverable,request_id:t?.request_id,scheduled_at:t?.scheduled_at??o},a={trace_id:i,session_id:e,step_id:t?.step_id||null,type:"llm_call",name:"llm_retry",timestamp:o,status:"retrying",payload:r};this.sessionLogs.update(s=>{let c=s.findIndex(_=>_.type==="trace_recorded"&&(_.data?.trace_id===i||t?.request_id&&_.data?.payload?.request_id===t.request_id&&Number(_.data?.payload?.scheduled_at)===Number(r.scheduled_at))),p={type:"trace_recorded",session_id:e,timestamp:new Date(o*1e3).toISOString(),data:a};if(c<0)return[...s,p];let f=[...s];return f[c]=p,f})}appendPausedErrorCard(t,e,o,i,r){let a=typeof t=="string"?t:JSON.stringify(t),s=`${e}:${a}`;this.activePauseCardKey!==s&&(this.sessionLogs.update(c=>{if(c.some(C=>(C?.type==="trace_recorded"?[C.data]:Array.isArray(C?.data?.generic_tools)?C.data.generic_tools:[]).some(P=>P?.type==="llm_call"&&P?.status==="failed"&&String(P?.payload?.error??P?.error??"")===a)))return c;let f=i||[...c].reverse().find(C=>(C.type==="step_updated"||C.type==="step_recorded")&&C.data?.step_id)?.data?.step_id||null,_=typeof o=="number"?o<1e11?o*1e3:o:o?new Date(o).getTime():Date.now();return[...c,{type:"trace_recorded",session_id:e,timestamp:new Date(_).toISOString(),data:{trace_id:`task-paused-${e}-${_}`,session_id:e,step_id:f,type:"llm_call",name:"llm_pause",status:"failed",timestamp:_/1e3,payload:{error:a,pause:!0,request_id:r?.request_id,provider:r?.provider,waited_seconds:r?.waited_seconds,retries:Array.isArray(r?.retries)?r.retries:[]}}}]}),this.activePauseCardKey=s)}pollCounter=0;setSessionStatus(t,e){t&&(this.invalidateStatusSignatures(),this.rawSessions.update(o=>o.map(i=>i.session_id===t?F(S({},i),{status:e}):i)),this.pendingQueue.update(o=>o.map(i=>i.session_id===t?F(S({},i),{status:e}):i)))}applySessionEndedStatus(t,e){if(!t)return;let o=String(e?.status||"").toLowerCase(),i=e?.was_stopped_manually||o==="cancelled"?"cancelled":o==="failed"?"failed":o==="completed"||o==="success"?"completed":null;i&&(this.activeSessionTracking.delete(String(t)),this.setSessionStatus(String(t),i),this.invalidateStatusSignatures(),this.activeTasks.update(r=>r.filter(a=>a.session_id!==String(t))))}startStatusPolling(){this.fetchStatus(),this.zone.runOutsideAngular(()=>{this.statusInterval=setInterval(()=>{typeof document<"u"&&document.hidden||(this.fetchStatus(),this.pollCounter++,this.pollCounter%3===0&&this.fetchSessions())},2e3)})}invalidateStatusSignatures(){this.lastQueueSignature=null,this.lastActiveTasksSignature=null}fetchStatus(){this.http.get("/api/status").subscribe({next:t=>{if(t&&t.status){let e=this.agentStatus(),o=this.runningSessionId(),i=t.status==="running"||t.status==="paused";if(this.agentStatus.set(t.status),this.runningSessionId.set(t.session_id||null),this.runningGoal.set(t.goal||null),t.model_info&&this.activeModel.set(t.model_info),this.isPaused.set(t.status==="paused"),t.status==="paused"){this.isRetrying.set(!1);let s=t.paused_error||this.pausedError()||"AI model request failed. The task is paused.";this.pausedError.set(s),t.session_id&&this.currentSessionId()===t.session_id&&this.appendPausedErrorCard(s,t.session_id)}else this.pausedError.set(null),this.activePauseCardKey=null;let r=JSON.stringify(t.queue||[]);if(r!==this.lastQueueSignature){this.lastQueueSignature=r;let s=(t.queue||[]).map((c,p)=>typeof c=="object"&&c!==null?{session_id:c.session_id||`pending-task-${p}`,initial_goal:c.goal||"",start_time:c.start_time||c.created_at||Date.now()/1e3+p,status:c.status||"pending",device_serial:c.device_serial||c.device_id||null}:{session_id:`task-queued-${p}`,initial_goal:String(c),start_time:Date.now()/1e3+p,status:"pending"});this.pendingQueue.set(s)}let a=JSON.stringify(t.active_tasks||[]);if(a!==this.lastActiveTasksSignature&&(this.lastActiveTasksSignature=a,this.activeTasks.set(t.active_tasks||[])),(e!==t.status||o!==t.session_id)&&this.fetchSessions(),!i&&(e==="running"||e==="paused")&&o&&this.isVideoWindowOpen()&&this.activeVideoSessionId===o&&this.recordingPlaybackStatus()==="live"&&this.beginRecordingFinalization(o),i&&t.session_id){let s=this.currentSessionId();(!s||!this.userPinnedSessionId()&&s!==t.session_id)&&this.selectSession(t.session_id,!1)}}},error:t=>{console.error("Failed to fetch status from backend:",t),this.agentStatus.set("offline"),this.runningSessionId.set(null),this.runningGoal.set(null)}})}updateModelForCurrentView(t){let e=this.currentSessionId(),o=t||this.sessions();if(e){let i=o.find(r=>r.session_id===e);if(i&&i.model_info){this.activeModel.set(i.model_info);return}}}destroy(){this.statusInterval&&(clearInterval(this.statusInterval),this.statusInterval=null),this.eventSource&&(this.eventSource.close(),this.eventSource=null),this.discardPendingStreamChunks(),typeof document<"u"&&document.removeEventListener("visibilitychange",this.onVisibilityChange),this.cancelVideoRetry()}fetchChecks(t){t&&this.http.get(`/api/sessions/${t}/checks`).subscribe({next:e=>{if(this.currentSessionId()!==t)return;let o=this.buildCheckerSnapshotLogs(t,e?.records||[],e?.run_outcome||null);this.sessionLogs.update(i=>[...i.filter(r=>!r.checks_snapshot),...o])},error:e=>{console.error(`Failed to fetch checks for session ${t}:`,e)}})}buildCheckerSnapshotLogs(t,e,o){let i=new Map;for(let a of e){if(!a||!a.attempt_id)continue;let s=String(a.attempt_id),c=String(a.checkpoint_id||""),p=i.get(s);p||(p={event:"attempt_finished",phase:c==="final"?"final":"checkpoint",attempt_id:s,checkpoint_id:c,subgoal_text:String(a.subgoal_text||(c==="final"?"Final review against the user's original goal":`Subgoal ${c.slice(0,8)}`)),anchor_step_id:a.anchor_step_id??null,trace_id:a.trace_id??null,status:"done",verdicts:[],findings:[],ts:typeof a.ts=="number"?a.ts:void 0,session_id:t},i.set(s,p)),typeof a.ts=="number"&&(p.ts=p.ts===void 0?a.ts:Math.min(p.ts,a.ts)),!p.trace_id&&a.trace_id&&(p.trace_id=a.trace_id),p.verdicts.push({item_text:String(a.item_text||""),kind:String(a.kind||""),status:String(a.status||""),evidence:String(a.evidence||""),suggestion:a.suggestion?String(a.suggestion):"",when:a.when?String(a.when):void 0})}let r=[];for(let a of i.values()){let s=new Set(a.verdicts.map(p=>p.status));if(s.size===1){let p=[...s][0];(p==="superseded"||p==="unchecked")&&(a.status=p)}let c=a.ts??Date.now()/1e3;a.timestamp=c,r.push({type:"checker_event",session_id:t,timestamp:new Date(c*1e3).toISOString(),checks_snapshot:!0,data:a})}if(o&&typeof o=="object"){let s=(r.length>0?Math.max(...r.map(c=>new Date(c.timestamp).getTime()/1e3)):Date.now()/1e3)+.001;r.push({type:"checker_event",session_id:t,timestamp:new Date(s*1e3).toISOString(),checks_snapshot:!0,data:F(S({event:"run_outcome",phase:"outcome"},o),{ts:s,timestamp:s,session_id:t})})}return r}fetchNotes(t){if(!t){this.currentNotes.set({});return}this.http.get(`/api/sessions/${t}/notes`).subscribe({next:e=>{if(e&&e.notes){this.currentNotes.set(e.notes);let o=Object.keys(e.notes);if(o.length>0){let i=this.selectedNoteKey();o.includes(i)||(o.includes("task_plan.md")?this.selectedNoteKey.set("task_plan.md"):this.selectedNoteKey.set(o[0]))}}},error:e=>{console.error(`Failed to fetch notes for session ${t}:`,e)}})}openVideoPlayer(t,e,o,i,r){let a=t||this.currentSessionId(),s=this.sessions().find(f=>f.session_id===a),c=e||s?.video_url||null,p=o||s?.initial_goal||(a?`Task: ${a.slice(0,8)}...`:"Screen Recording");if(this.activeVideoTitle.set(p),this.isVideoWindowOpen.set(!0),this.isVideoMinimized.set(!1),this.activeVideoSessionId=a,this.cancelVideoRetry(),this.videoRequestGeneration++,this.shouldAutoplayVideo.set(!1),this.recordingPlaybackMessage.set(""),this.activeVideoSegments.set([]),Number.isFinite(i)&&this.requestVideoSeek(Number(i)),Number.isFinite(r)&&(this.playerMode?.set("steps"),this.requestStepSeek(Number(r))),!a){this.activeVideoUrl.set(null),this.isVideoLoading.set(!1),this.recordingPlaybackStatus.set("unavailable");return}if(s?.status==="running"||s?.status==="paused"){this.activeVideoUrl.set(null),this.isVideoLoading.set(!1),this.recordingPlaybackStatus.set("live");return}this.activeVideoUrl.set(c),this.shouldAutoplayVideo.set(!0),this.videoWaitStartedAt=Date.now(),this.isVideoLoading.set(!0),this.recordingPlaybackStatus.set("processing"),this.recordingPlaybackMessage.set("Loading screen recording..."),c?this.playerMode?.set("video"):this.hasCurrentSessionStepFrames?.()?this.playerMode?.set("steps"):this.playerMode?.set("video"),this.requestSessionVideo(a,this.videoRequestGeneration)}appendStartupProgress(t,e){if(!t?.stage||!t?.message)return;let o=typeof t.timestamp=="number"?t.timestamp>1e11?t.timestamp/1e3:t.timestamp:Date.now()/1e3,i={session_id:String(t.session_id||e),stage:String(t.stage),message:String(t.message),timestamp:o},r=String(t.session_id||e).trim();this.startupProgressBySession.update(a=>{let s=[...a[r]||a[e]||[]],c=s.findIndex(f=>f.stage===i.stage);c>=0?s[c]=i:s.push(i),s.sort((f,_)=>f.timestamp-_.timestamp);let p=F(S({},a),{[r]:s});return e&&e!==r&&(p[e]=s),p})}beginRecordingFinalization(t){this.activeVideoSessionId===t&&(this.cancelVideoRetry(),this.videoRequestGeneration++,this.videoWaitStartedAt=Date.now(),this.activeVideoUrl.set(null),this.activeVideoSegments.set([]),this.shouldAutoplayVideo.set(!0),this.isVideoLoading.set(!0),this.recordingPlaybackStatus.set("processing"),this.recordingPlaybackMessage.set("Finalizing screen recording..."),this.requestSessionVideo(t,this.videoRequestGeneration))}requestSessionVideo(t,e){this.http.get(`/api/sessions/${t}/video`).subscribe({next:o=>{if(e!==this.videoRequestGeneration||t!==this.activeVideoSessionId)return;let i=o.status||(o.has_video&&o.video_url?"ready":"unavailable");if(i==="ready"&&o.video_url){this.cancelVideoRetry(),this.isVideoLoading.set(!1),this.recordingPlaybackStatus.set("ready"),this.recordingPlaybackMessage.set(""),this.activeVideoUrl.set(o.video_url),this.activeVideoSegments.set(o.video_segments||[]),this.playerMode?.set("video"),this.rawSessions.update(r=>r.map(a=>a.session_id===t?F(S({},a),{video_url:o.video_url||void 0,recording_status:"ready"}):a));return}if(i==="processing"){this.activeVideoUrl.set(null),this.activeVideoSegments.set([]),this.isVideoLoading.set(!0),this.recordingPlaybackStatus.set("processing"),this.recordingPlaybackMessage.set("Finalizing screen recording..."),this.scheduleVideoRetry(t,e,o.retry_after_ms);return}this.cancelVideoRetry(),this.isVideoLoading.set(!1),this.activeVideoUrl.set(null),this.activeVideoSegments.set([]),this.recordingPlaybackStatus.set(i==="failed"?"failed":"unavailable"),this.recordingPlaybackMessage.set(o.message||(i==="failed"?"Recording finalization failed.":"No screen recording is available for this task.")),this.hasCurrentSessionStepFrames?.()&&this.playerMode?.set("steps")},error:()=>{if(!(e!==this.videoRequestGeneration||t!==this.activeVideoSessionId)){if(this.recordingPlaybackStatus()==="processing"){this.scheduleVideoRetry(t,e,1e3);return}this.isVideoLoading.set(!1),this.recordingPlaybackStatus.set("failed"),this.recordingPlaybackMessage.set("Unable to load the screen recording."),this.hasCurrentSessionStepFrames?.()&&this.playerMode?.set("steps")}}})}scheduleVideoRetry(t,e,o=1e3){if(this.cancelVideoRetry(),Date.now()-this.videoWaitStartedAt>12e4){this.isVideoLoading.set(!1),this.recordingPlaybackStatus.set("failed"),this.recordingPlaybackMessage.set("Recording finalization timed out. You can retry.");return}let i=Math.max(500,Math.min(3e3,o));this.videoRetryTimer=setTimeout(()=>{this.videoRetryTimer=null,this.requestSessionVideo(t,e)},i)}cancelVideoRetry(){this.videoRetryTimer&&(clearTimeout(this.videoRetryTimer),this.videoRetryTimer=null)}refreshActiveRecording(t){let e=this.activeVideoSessionId;e&&(this.cancelVideoRetry(),this.videoRequestGeneration++,t&&this.shouldAutoplayVideo.set(!0),this.requestSessionVideo(e,this.videoRequestGeneration))}retryVideoRecording(){let t=this.activeVideoSessionId;t&&this.beginRecordingFinalization(t)}consumeVideoAutoplay(){let t=this.shouldAutoplayVideo();return this.shouldAutoplayVideo.set(!1),t}requestVideoSeek(t){Number.isFinite(t)&&this.videoSeekRequest.set({seconds:Math.max(0,t),requestId:++this.videoSeekRequestId})}toggleVideoPlayer(){this.isVideoWindowOpen()?this.isVideoWindowOpen.set(!1):this.openVideoPlayer()}closeVideoPlayer(){this.isVideoWindowOpen.set(!1),this.cancelVideoRetry(),this.videoRequestGeneration++,this.activeVideoSessionId=null}static \u0275fac=function(e){return new(e||n)};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})};var Hd=class n{http=D(Ro);readinessReport=x(null);hasReadinessReport=I(()=>this.readinessReport()!==null);isLoading=x(!1);isRestartingAdb=x(!1);adbServerStatus=x(null);isRemoteAdbServer=I(()=>this.adbServerStatus()?.endpoint.mode==="remote");launchingAvd=x(null);emulatorLaunchState=x(null);isEmulatorLaunching=I(()=>{let t=this.emulatorLaunchState()?.status;return t==="starting"||t==="waiting_for_adb"||t==="booting"});lastCheckedTime=x(null);emulatorPollTimer=null;pythonProbe=I(()=>this.probes().find(t=>t.id==="python_runtime")||null);configProbe=I(()=>this.probes().find(t=>t.id==="system_config")||null);toolchainProbe=I(()=>this.probes().find(t=>t.id==="toolchain")||null);adbProbe=I(()=>this.probes().find(t=>t.id==="android_adb")||null);llmProbe=I(()=>this.probes().find(t=>t.id==="gemini_api_key"||t.id==="llm_api_key")||null);geminiProbe=I(()=>this.llmProbe());ocrProbe=I(()=>this.probes().find(t=>t.id==="vision_ocr_key"||t.id==="ocr_api_key")||null);isEnvironmentReady=I(()=>{let t=this.pythonProbe(),e=this.configProbe(),o=this.adbProbe(),i=this.toolchainProbe(),r=t?.status==="pass",a=e?.status==="pass",s=o?.metadata?.installed??o?.status!=="fail",c=i?.status==="pass"||i?.is_blocker===!1;return r&&a&&s&&c});isSkipCredentialsCheck=x(!1);isCredentialsReady=I(()=>this.isSkipCredentialsCheck()?!0:this.llmProbe()?.status==="pass");isDeviceReady=I(()=>this.adbProbe()?.status==="pass");totalStepCount=I(()=>3);passedStepCount=I(()=>{let t=0;return this.isEnvironmentReady()&&t++,this.isCredentialsReady()&&t++,this.isDeviceReady()&&t++,t});isReady=I(()=>this.isEnvironmentReady()&&this.isCredentialsReady()&&this.isDeviceReady());blockerCount=I(()=>this.totalStepCount());passedBlockerCount=I(()=>this.passedStepCount());probes=I(()=>this.readinessReport()?.probes??[]);activeDevice=I(()=>this.readinessReport()?.active_device??null);osType=I(()=>{let t=this.readinessReport()?.os_type;return t==="windows"||t==="win32"?"windows":t==="darwin"||t==="macos"||t==="mac"?"darwin":"linux"});skipCredentialsCheck(){this.isSkipCredentialsCheck.set(!0)}setSkipCredentialsCheck(t){this.isSkipCredentialsCheck.set(t)}connectedDevices=I(()=>{let t=this.adbProbe()?.metadata;return t&&Array.isArray(t.devices)?t.devices:[]});installedAvds=I(()=>{let t=this.adbProbe()?.metadata;return t&&Array.isArray(t.installed_avds)?t.installed_avds:[]});emulatorPath=I(()=>this.adbProbe()?.metadata?.emulator_path||null);isEmulatorInPath=I(()=>this.adbProbe()?.metadata?.is_emulator_in_path??!0);pollingTimer=null;readinessRequest$=null;zone=D(ge);lastAppliedReportJson=null;onVisibilityChange=()=>{typeof document<"u"&&!document.hidden&&this.fetchReadiness(!0).subscribe({error:()=>{}})};constructor(){this.startAutoPolling(3e3),typeof document<"u"&&document.addEventListener("visibilitychange",this.onVisibilityChange),D(Ae).onDestroy(()=>{this.stopAutoPolling(),this.stopEmulatorStatusPolling(),typeof document<"u"&&document.removeEventListener("visibilitychange",this.onVisibilityChange)})}startAutoPolling(t=3e3){this.pollingTimer&&clearInterval(this.pollingTimer),this.zone.runOutsideAngular(()=>{this.pollingTimer=setInterval(()=>{typeof document<"u"&&document.hidden||this.fetchReadiness(!0).subscribe({error:()=>{}})},t)})}stopAutoPolling(){this.pollingTimer&&(clearInterval(this.pollingTimer),this.pollingTimer=null)}fetchReadiness(t=!1,e=!1){if(t||this.isLoading.set(!0),this.readinessRequest$)return this.readinessRequest$;let o=this.http.get("/api/system/readiness",{params:e?{force:!0}:{}}).pipe(xe({next:i=>{this.applyReadinessReport(i)},error:i=>{console.error("Failed to fetch system readiness:",i)}}),_o(()=>{this.readinessRequest$===o&&(this.readinessRequest$=null),this.isLoading.set(!1)}),Ou({bufferSize:1,refCount:!1}));return this.readinessRequest$=o,o}applyReadinessReport(t){let e=this.readinessReport();if(e&&t.timestamp{this.emulatorLaunchState.set(t),t.status==="ready"?(this.launchingAvd.set(null),this.stopEmulatorStatusPolling(),this.fetchReadiness().subscribe()):t.status==="failed"||t.status==="stopped"||t.status==="idle"?(this.launchingAvd.set(null),this.stopEmulatorStatusPolling()):t.avd_name&&this.launchingAvd.set(t.avd_name)},error:t=>{console.error("Failed to fetch emulator status:",t)}}))}startEmulatorStatusPolling(){this.emulatorPollTimer&&clearInterval(this.emulatorPollTimer),this.emulatorPollTimer=setInterval(()=>{this.fetchEmulatorStatus().subscribe({error:()=>{}})},1e3)}stopEmulatorStatusPolling(){this.emulatorPollTimer&&(clearInterval(this.emulatorPollTimer),this.emulatorPollTimer=null)}launchEmulator(t){return this.launchingAvd.set(t),this.emulatorLaunchState.set({avd_name:t,status:"starting",pid:null,serial:null,stage_message:"Spawning emulator process...",progress_percent:15,started_at:Date.now()/1e3,elapsed_seconds:0,error:null,logs:[`Initiating launch for AVD: ${t}...`],can_retry:!0}),this.http.post("/api/system/emulator/launch",{avd_name:t}).pipe(xe({next:e=>{this.emulatorLaunchState.set(e),e.status==="failed"?this.launchingAvd.set(null):this.startEmulatorStatusPolling()},error:e=>{console.error("Failed to launch emulator:",e),this.launchingAvd.set(null);let o=e?.error?.detail||e?.message||"Failed to start emulator process.";this.emulatorLaunchState.set({avd_name:t,status:"failed",pid:null,serial:null,stage_message:"Failed to initiate launch.",progress_percent:0,started_at:null,elapsed_seconds:0,error:o,logs:[o],can_retry:!0})}}))}stopEmulator(){return this.http.post("/api/system/emulator/stop",{}).pipe(xe({next:()=>{this.launchingAvd.set(null),this.stopEmulatorStatusPolling(),this.fetchEmulatorStatus().subscribe(),this.fetchReadiness().subscribe()}}))}dismissEmulatorStatus(){return this.http.post("/api/system/emulator/dismiss",{}).pipe(xe({next:()=>{this.emulatorLaunchState.set(null),this.launchingAvd.set(null),this.stopEmulatorStatusPolling()}}))}restartAdb(){return this.isRestartingAdb.set(!0),this.http.post("/api/system/adb/restart",{}).pipe(xe({next:t=>{t?.report&&this.applyReadinessReport(t.report),this.isRestartingAdb.set(!1)},error:t=>{console.error("Failed to restart ADB server:",t),this.isRestartingAdb.set(!1)}}))}connectWirelessAdb(t,e=5555){return this.http.post("/api/system/adb/connect",{host:t,port:e}).pipe(xe({next:o=>{o?.report&&this.applyReadinessReport(o.report)}}))}fetchAdbServerStatus(){return this.http.get("/api/system/adb/server").pipe(xe(t=>this.adbServerStatus.set(t)))}probeAdbServer(t,e){return this.http.post("/api/system/adb/server/probe",{host:t,port:e,persist:!1})}connectAdbServer(t,e,o=!0){return this.http.post("/api/system/adb/server/connect",{host:t,port:e,persist:o}).pipe(xe(i=>{i.connection_result.success&&(this.adbServerStatus.set({endpoint:i.connection_result.endpoint}),i.report&&this.applyReadinessReport(i.report))}))}useLocalAdbServer(t=!0){return this.http.post("/api/system/adb/server/local",{},{params:{persist:t}}).pipe(xe(e=>{this.adbServerStatus.set({endpoint:e.connection_result.endpoint}),e.report&&this.applyReadinessReport(e.report)}))}selectDevice(t){return this.isLoading.set(!0),this.http.post("/api/system/devices/select",{serial:t}).pipe(xe({next:e=>{e?.report&&this.applyReadinessReport(e.report),this.isLoading.set(!1)},error:e=>{console.error("Failed to select active device:",e),this.isLoading.set(!1)}}))}currentApiKey=I(()=>this.llmProbe()?.metadata?.current_key||"");apiKeysMap=I(()=>this.llmProbe()?.metadata?.api_keys||{});modelConfigEnv=x(null);fetchModelConfigEnv(){return this.http.get("/api/system/model-config-env").pipe(xe({next:t=>{this.modelConfigEnv.set(t)},error:t=>{console.error("Failed to fetch model config and env:",t)}}))}testApiKey(t,e,o){return this.http.post("/api/system/credentials/test",{provider:t,api_key:e,base_url:o})}updateApiKey(t,e,o=!0){return this.http.post("/api/system/credentials",{provider:t,api_key:e,persist_to_env:o}).pipe(xe({next:i=>{i?.report&&this.applyReadinessReport(i.report),this.fetchModelConfigEnv().subscribe()},error:i=>{console.error(`Failed to update credentials for ${t}:`,i)}}))}static \u0275fac=function(e){return new(e||n)};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})};var HP={"com.google.android.apps.maps":{name:"Maps",icon:"explore",pkg:"com.google.android.apps.maps",category:"navigation"},"com.google.android.gm":{name:"Gmail",icon:"mail",pkg:"com.google.android.gm",category:"productivity"},"com.android.chrome":{name:"Chrome",icon:"public",pkg:"com.android.chrome",category:"browser"},"com.google.android.youtube":{name:"YouTube",icon:"smart_display",pkg:"com.google.android.youtube",category:"entertainment"},"com.android.settings":{name:"Settings",icon:"settings",pkg:"com.android.settings",category:"system"},"com.google.android.deskclock":{name:"Clock",icon:"timer",pkg:"com.google.android.deskclock",category:"utility"},"com.android.deskclock":{name:"Clock",icon:"timer",pkg:"com.android.deskclock",category:"utility"},"com.google.android.calculator":{name:"Calculator",icon:"calculate",pkg:"com.google.android.calculator",category:"utility"},"com.android.calculator2":{name:"Calculator",icon:"calculate",pkg:"com.android.calculator2",category:"utility"},"com.google.android.apps.photos":{name:"Photos",icon:"photo_library",pkg:"com.google.android.apps.photos",category:"media"},"com.google.android.calendar":{name:"Calendar",icon:"calendar_month",pkg:"com.google.android.calendar",category:"productivity"},"com.google.android.keep":{name:"Keep Notes",icon:"note_alt",pkg:"com.google.android.keep",category:"productivity"},"com.android.vending":{name:"Play Store",icon:"storefront",pkg:"com.android.vending",category:"tools"},"com.google.android.apps.messaging":{name:"Messages",icon:"chat",pkg:"com.google.android.apps.messaging",category:"communication"},"com.tencent.mm":{name:"WeChat",icon:"forum",pkg:"com.tencent.mm",category:"social"},"com.xingin.xhs":{name:"Xiaohongshu",icon:"auto_stories",pkg:"com.xingin.xhs",category:"social"},"com.sankuai.meituan":{name:"Meituan",icon:"restaurant",pkg:"com.sankuai.meituan",category:"lifestyle"},"com.dianping.v1":{name:"Dianping",icon:"star",pkg:"com.dianping.v1",category:"lifestyle"},"tv.danmaku.bili":{name:"Bilibili",icon:"video_library",pkg:"tv.danmaku.bili",category:"entertainment"},"com.eg.android.AlipayGphone":{name:"Alipay",icon:"account_balance_wallet",pkg:"com.eg.android.AlipayGphone",category:"finance"},"com.netease.cloudmusic":{name:"NetEase Music",icon:"headphones",pkg:"com.netease.cloudmusic",category:"entertainment"},"com.spotify.music":{name:"Spotify",icon:"music_note",pkg:"com.spotify.music",category:"entertainment"}},UP=[{id:"maps_coffee",title:"Find Specialty Coffee",description:"Search nearby top-rated cafes in Google Maps",goal:"Open Google Maps, search for top-rated specialty coffee shops nearby, and view the top result details.",profile:"flash",category:"flash",tag:"Maps",apps:[{name:"Maps",icon:"explore",pkg:"com.google.android.apps.maps"}],requiredPackages:["com.google.android.apps.maps"],priority:95},{id:"pro_commute_share",title:"Commute ETA & Message Draft",description:"Check transit time on Maps and draft arrival ETA in Messages",goal:"Open Google Maps to check commute time to the International Airport, calculate arrival time, then open Messages and draft an ETA text message.",profile:"pro",category:"cross_app",tag:"Maps + Messages",apps:[{name:"Maps",icon:"explore",pkg:"com.google.android.apps.maps"},{name:"Messages",icon:"chat",pkg:"com.google.android.apps.messaging"}],requiredPackages:["com.google.android.apps.maps","com.google.android.apps.messaging"],matchMode:"all",priority:92},{id:"gmail_receipts",title:"Search Order Receipts",description:"Find recent flight or delivery confirmation emails in Gmail",goal:"Open Gmail and search for recent flight or package delivery confirmation emails.",profile:"flash",category:"flash",tag:"Gmail",apps:[{name:"Gmail",icon:"mail",pkg:"com.google.android.gm"}],requiredPackages:["com.google.android.gm"],priority:90},{id:"pro_email_to_calendar",title:"Email Itinerary to Calendar",description:"Extract flight or event dates from Gmail and schedule in Calendar",goal:"Open Gmail to find the latest event invitation or itinerary, extract dates and location, then open Google Calendar and create a corresponding calendar event.",profile:"pro",category:"cross_app",tag:"Gmail + Calendar",apps:[{name:"Gmail",icon:"mail",pkg:"com.google.android.gm"},{name:"Calendar",icon:"calendar_month",pkg:"com.google.android.calendar"}],requiredPackages:["com.google.android.gm"],priority:94},{id:"chrome_research",title:"Search AI News Breakthroughs",description:"Search latest multimodal AI developments in Chrome browser",goal:"Open Chrome browser and search for latest breakthroughs in multimodal mobile AI agents.",profile:"flash",category:"flash",tag:"Chrome",apps:[{name:"Chrome",icon:"public",pkg:"com.android.chrome"}],requiredPackages:["com.android.chrome"],priority:88},{id:"pro_research_keep",title:"Product Research & Notes Note",description:"Compare top 3 headphones on Chrome and record comparison in Keep",goal:"Open Chrome, research top 3 noise-cancelling headphones comparing price and battery life, then write a structured comparison summary note in Keep Notes.",profile:"pro",category:"pro",tag:"Chrome + Keep",apps:[{name:"Chrome",icon:"public",pkg:"com.android.chrome"},{name:"Keep Notes",icon:"note_alt",pkg:"com.google.android.keep"}],requiredPackages:["com.android.chrome"],priority:91},{id:"youtube_lofi",title:"Play Lo-Fi Music Radio",description:"Search and play a Lo-Fi hip hop live stream on YouTube",goal:'Open YouTube, search for "Lofi hip hop beats relaxing radio" and tap on the live stream.',profile:"flash",category:"flash",tag:"YouTube",apps:[{name:"YouTube",icon:"smart_display",pkg:"com.google.android.youtube"}],requiredPackages:["com.google.android.youtube"],priority:85},{id:"settings_display_wifi",title:"Dark Mode & Wi-Fi Check",description:"Toggle dark theme and verify network connection in Settings",goal:"Open Settings app, navigate to Display settings, ensure Dark theme is enabled, and check Wi-Fi connection status.",profile:"flash",category:"flash",tag:"Settings",apps:[{name:"Settings",icon:"settings",pkg:"com.android.settings"}],requiredPackages:["com.android.settings"],priority:87},{id:"pro_settings_qa",title:"Subsystem Health & Crash Probe",description:"Traverse Settings submenus to verify screens and check for crash dialogs",goal:"Explore Settings submenus (Network, Connected devices, Apps, Battery, Storage), verify each screen loads properly without ANR or crash dialogs, and summarize results.",profile:"pro",category:"monitor",tag:"Settings QA",apps:[{name:"Settings",icon:"settings",pkg:"com.android.settings"}],requiredPackages:["com.android.settings"],priority:93},{id:"clock_timer",title:"25-Min Pomodoro Timer",description:"Start a 25-minute focus countdown timer in Clock app",goal:"Open Clock app, switch to Timer tab, set 25 minutes and start the countdown timer.",profile:"flash",category:"flash",tag:"Clock",apps:[{name:"Clock",icon:"timer",pkg:"com.google.android.deskclock"}],requiredPackages:["com.google.android.deskclock","com.android.deskclock"],priority:86},{id:"calc_gratuity",title:"Split Bill & Calculate Tip",description:"Calculate 18% gratuity on $186.40 for 3 people in Calculator",goal:"Open Calculator and calculate 18% tip on a bill of $186.40, then divide by 3 people.",profile:"flash",category:"flash",tag:"Calculator",apps:[{name:"Calculator",icon:"calculate",pkg:"com.google.android.calculator"}],requiredPackages:["com.google.android.calculator","com.android.calculator2"],priority:84},{id:"photos_inspect",title:"Inspect Recent Screenshot",description:"Open Google Photos and review the latest screenshot taken",goal:"Open Google Photos and view the most recent screenshot in the screenshots album.",profile:"flash",category:"flash",tag:"Photos",apps:[{name:"Photos",icon:"photo_library",pkg:"com.google.android.apps.photos"}],requiredPackages:["com.google.android.apps.photos"],priority:82},{id:"wechat_browse",title:"Check WeChat Messages",description:"Open WeChat and view top recent chat conversations",goal:"Open WeChat and view the top recent chat messages.",profile:"flash",category:"flash",tag:"WeChat",apps:[{name:"WeChat",icon:"forum",pkg:"com.tencent.mm"}],requiredPackages:["com.tencent.mm"],priority:89},{id:"pro_wechat_to_calendar",title:"WeChat Notice to Calendar",description:"Extract meeting notice from WeChat chat and add to Calendar",goal:"Open WeChat, locate the latest meeting announcement or event message in the top chat, extract the time and topic, then open Calendar and schedule an event.",profile:"pro",category:"cross_app",tag:"WeChat + Calendar",apps:[{name:"WeChat",icon:"forum",pkg:"com.tencent.mm"},{name:"Calendar",icon:"calendar_month",pkg:"com.google.android.calendar"}],requiredPackages:["com.tencent.mm"],priority:93},{id:"xhs_coffee_guide",title:"RED Cafe Guide Search",description:"Search trending specialty cafe reviews on Xiaohongshu",goal:"Open Xiaohongshu, search for top-rated specialty coffee shops, and view the top post.",profile:"flash",category:"flash",tag:"Xiaohongshu",apps:[{name:"Xiaohongshu",icon:"auto_stories",pkg:"com.xingin.xhs"}],requiredPackages:["com.xingin.xhs"],priority:87},{id:"meituan_ramen_search",title:"Meituan Food Search",description:"Search top-rated Ramen nearby on Meituan or Dianping",goal:"Open Meituan or Dianping, search for top-rated Ramen nearby, and view top restaurant rating.",profile:"flash",category:"flash",tag:"Meituan",apps:[{name:"Meituan",icon:"restaurant",pkg:"com.sankuai.meituan"}],requiredPackages:["com.sankuai.meituan","com.dianping.v1"],priority:86},{id:"bilibili_stream",title:"Bilibili Tech Video",description:"Search and play an AI Agent tutorial video on Bilibili",goal:'Open Bilibili, search for "AI Agent Architecture", and play the top matching video.',profile:"flash",category:"flash",tag:"Bilibili",apps:[{name:"Bilibili",icon:"video_library",pkg:"tv.danmaku.bili"}],requiredPackages:["tv.danmaku.bili"],priority:85},{id:"pro_playstore_review",title:"Play Store App Review Study",description:"Compare top task management apps and ratings on Google Play",goal:"Open Google Play Store, search for top rated task management apps, compare ratings and latest user reviews of the top 2 candidates, and record recommendations.",profile:"pro",category:"pro",tag:"Play Store",apps:[{name:"Play Store",icon:"storefront",pkg:"com.android.vending"}],requiredPackages:["com.android.vending"],priority:88}];var Ud=class n{allTasks=UP;appRegistry=HP;isSuggestionOnDevice(t,e){return e.size===0?!1:!t.requiredPackages||t.requiredPackages.length===0?!0:t.matchMode==="all"?t.requiredPackages.every(o=>e.has(o)):t.requiredPackages.some(o=>e.has(o))}filterAndRankTasks(t,e,o=0){let i=t.size>0,a=this.allTasks.map(c=>{let p=this.isSuggestionOnDevice(c,t),f=c.priority??50;return i&&(p?(f+=100,c.requiredPackages&&c.requiredPackages.length>1&&c.matchMode==="all"&&(f+=30)):f-=40),{task:c,isMatched:p,score:f}}).filter(c=>e==="flash"?c.task.profile==="flash":e==="pro"?c.task.profile==="pro":e==="cross_app"?c.task.category==="cross_app":e==="monitor"?c.task.category==="monitor":!0);a.sort((c,p)=>p.score-c.score);let s=a.map(c=>c.task);if(o>0&&s.length>0){let c=o%s.length;s=[...s.slice(c),...s.slice(0,c)]}return s}static \u0275fac=function(e){return new(e||n)};static \u0275prov=te({token:n,factory:n.\u0275fac,providedIn:"root"})};var _n=[{id:"off",label:"Off",tagline:"No checking. The run ends as soon as the task looks done.",latency:"no extra time",runs:["Each step is treated as finished the moment it is carried out.","You get the full action trace, but no pass / fail verdict."],skips:["Nothing is double-checked and nothing is retried."],bestFor:"Quick tries and demos, when you only want to watch what happens."},{id:"final",label:"At the end",tagline:"One check of the finished result against your goal. This is the default.",latency:"adds about 20\u201360 s at the end",runs:["When the task finishes, the final screen, the step history and the device state are compared with what you asked for.","If the result does not match, the task goes back and tries to fix it, up to 3 times."],skips:["Nothing is checked while the task is still running."],bestFor:"Everyday tasks: an honest pass / fail without slowing the run down."},{id:"checkpoints",label:"Every step",tagline:"Each step is checked as soon as it is done, plus the final check.",latency:"a short check after each step, done in the background",runs:["Every step is checked right after it completes, using the screenshots from that moment.","If a step went wrong, it gets fixed before moving on (up to 2 tries per step).","A failed test condition is written down and the task keeps going.","The final check still runs at the end."],bestFor:"Long tasks where one early mistake would spoil everything after it."},{id:"strict",label:"Strict",tagline:"Every step is checked, with more retries. The first failed test stops the run.",latency:"slowest: more checks and more retries",runs:["Each check takes longer and gets more attempts: 4 fixes per step and 5 at the end.","The first failed test condition stops the run immediately, with the evidence attached."],bestFor:"Release checks and regression runs, where a wrong pass is never acceptable."}],hn=[{id:"flash",label:"Quick glance",tagline:"Finds buttons and text on the screen in a single look.",latency:"1 look per search",runs:["Something on screen is asked for by name, icon or colour and its position comes back straight away.","Several things can be looked up at once."],skips:["No zooming in and no second try."],bestFor:"Ordinary apps with clearly labelled buttons, icons and text."},{id:"pro",label:"Second look",tagline:"Takes up to 3 looks, thinking in between, before answering.",latency:"up to 3 looks per search",runs:["The screen layout is read first, then the picture is searched.","If the first try misses, a different approach is tried within the 3 looks."],skips:["Still no zooming into small areas, to keep searches short."],bestFor:'Things described by where they are ("the switch next to Wi-Fi") or with unclear labels.'},{id:"ultra",label:"Close-up",tagline:"Zooms into parts of the screen and takes up to 8 looks.",latency:"up to 8 looks per search (slowest)",runs:["Parts of the screen can be cropped and magnified to read tiny text and crowded layouts piece by piece.","Later looks reuse the earlier ones, so they cost less time than they sound."],bestFor:"Crowded screens, tiny targets, charts and drawings, and checks where exact placement matters."}],Hr="final",Ur="flash";function Li(n,t,e){let o=String(t??"").trim().toLowerCase(),i=n.findIndex(r=>r.id===o);return i>=0?i:Math.max(0,n.findIndex(r=>r.id===e))}function Gd(n,t){return t<=1?0:Math.min(Math.max(n,0),t-1)/(t-1)*100}var hD=()=>[],GP=(n,t)=>t.name,Pm=(n,t)=>t.serial,qP=(n,t)=>t.id,CD=(n,t)=>t.kind;function MD(n,t){n&1&&(l(0,"span",14),u(1,"check_circle"),d())}function bD(n,t){n&1&&(l(0,"span",15),u(1,"tune"),d())}function PD(n,t){n&1&&(l(0,"span",17),u(1,"lock"),d())}function OD(n,t){n&1&&(l(0,"span",15),u(1,"rocket_launch"),d())}function vD(n,t){n&1&&(l(0,"span",23),u(1,"check"),d())}function yD(n,t){n&1&&(l(0,"span"),u(1,"1"),d())}function xD(n,t){if(n&1){let e=L();l(0,"div",31)(1,"div",72)(2,"div",73)(3,"span",74),u(4,"bolt"),d()(),l(5,"div",75)(6,"div",76)(7,"div",77),u(8,"Automated Dependency Setup"),d(),l(9,"div",78)(10,"button",79),k("click",function(){v(e);let i=m(2);return y(i.setSelectedOs("linux"))}),u(11,"Linux"),d(),l(12,"button",79),k("click",function(){v(e);let i=m(2);return y(i.setSelectedOs("darwin"))}),u(13,"macOS"),d(),l(14,"button",79),k("click",function(){v(e);let i=m(2);return y(i.setSelectedOs("windows"))}),u(15,"Windows"),d()()(),l(16,"div",80),u(17,"Run in terminal to install ADB, FFmpeg, scrcpy, and project dependencies:"),d()()(),l(18,"div",81)(19,"code"),u(20),d(),l(21,"button",82),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard(i.oneClickSetupCmd(),"one_click_deps"))}),l(22,"span",29),u(23),d(),l(24,"span"),u(25),d()()()()}if(n&2){let e=m(2);g(10),w("active",e.effectiveOs()==="linux"),g(2),w("active",e.effectiveOs()==="darwin"),g(2),w("active",e.effectiveOs()==="windows"),g(6),O(e.oneClickSetupCmd()),g(),w("copied",e.copiedId()==="one_click_deps"),g(2),O(e.copiedId()==="one_click_deps"?"check":"content_copy"),g(2),O(e.copiedId()==="one_click_deps"?"Copied!":"Copy")}}function wD(n,t){if(n&1){let e=L();l(0,"div",42)(1,"div",83)(2,"div",81)(3,"span",84),u(4,"$"),d(),l(5,"code",85),u(6,"uv python install 3.12"),d(),l(7,"button",82),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard("uv python install 3.12","py_install"))}),l(8,"span",29),u(9),d(),l(10,"span"),u(11),d()()()()()}if(n&2){let e=m(2);g(7),w("copied",e.copiedId()==="py_install"),g(2),O(e.copiedId()==="py_install"?"check":"content_copy"),g(2),O(e.copiedId()==="py_install"?"Copied!":"Copy")}}function SD(n,t){if(n&1){let e=L();l(0,"div",42)(1,"div",83)(2,"div",81)(3,"span",84),u(4,"$"),d(),l(5,"code",85),u(6),d(),l(7,"button",82),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard(i.adbInstallCmd(),"env_adb_cmd"))}),l(8,"span",29),u(9),d(),l(10,"span"),u(11),d()()()()()}if(n&2){let e=m(2);g(6),O(e.adbInstallCmd()),g(),w("copied",e.copiedId()==="env_adb_cmd"),g(2),O(e.copiedId()==="env_adb_cmd"?"check":"content_copy"),g(2),O(e.copiedId()==="env_adb_cmd"?"Copied!":"Copy")}}function kD(n,t){if(n&1){let e=L();l(0,"div",42)(1,"div",83)(2,"div",81)(3,"span",84),u(4,"$"),d(),l(5,"code",85),u(6,"artemis init"),d(),l(7,"button",82),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard("artemis init","cfg_init"))}),l(8,"span",29),u(9),d(),l(10,"span"),u(11),d()()()()()}if(n&2){let e=m(2);g(7),w("copied",e.copiedId()==="cfg_init"),g(2),O(e.copiedId()==="cfg_init"?"check":"content_copy"),g(2),O(e.copiedId()==="cfg_init"?"Copied!":"Copy")}}function ED(n,t){if(n&1){let e=L();l(0,"div",42)(1,"div",83)(2,"div",81)(3,"span",84),u(4,"$"),d(),l(5,"code",85),u(6),d(),l(7,"button",82),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard(i.toolchainInstallCmd(),"install_toolchain"))}),l(8,"span",29),u(9),d(),l(10,"span"),u(11),d()()()()()}if(n&2){let e=m(2);g(6),O(e.toolchainInstallCmd()),g(),w("copied",e.copiedId()==="install_toolchain"),g(2),O(e.copiedId()==="install_toolchain"?"check":"content_copy"),g(2),O(e.copiedId()==="install_toolchain"?"Copied!":"Copy")}}function DD(n,t){n&1&&(l(0,"span",23),u(1,"check"),d())}function ID(n,t){n&1&&(l(0,"span"),u(1,"2"),d())}function TD(n,t){if(n&1){let e=L();l(0,"button",111),k("click",function(){v(e);let i=m(3);return y(i.copyToClipboard(i.geminiKeyInput(),"gemini_key_field"))}),l(1,"span",29),u(2),d()()}if(n&2){let e=m(3);g(),w("text-emerald",e.copiedId()==="gemini_key_field"),g(),V(" ",e.copiedId()==="gemini_key_field"?"check":"content_copy"," ")}}function AD(n,t){if(n&1&&(l(0,"span",112),u(1,"sync"),d(),l(2,"span"),u(3),d()),n&2){let e=m(3);g(3),O(e.geminiKeyInput().trim()?"Verifying & Saving...":"Clearing...")}}function ND(n,t){if(n&1&&(l(0,"span",29),u(1),d(),l(2,"span"),u(3),d()),n&2){let e=m(3);g(),O(e.geminiKeyInput().trim()?"save":"delete_outline"),g(2),O(e.geminiKeyInput().trim()?e.isGeminiModified()?"Save & Apply":"Save Key":"Clear Key")}}function RD(n,t){n&1&&(l(0,"span",112),u(1,"sync"),d(),l(2,"span"),u(3,"Testing..."),d())}function FD(n,t){n&1&&(l(0,"span",29),u(1,"network_check"),d(),l(2,"span"),u(3,"Test Key"),d())}function LD(n,t){if(n&1&&(l(0,"div",99)(1,"span",29),u(2,"check_circle"),d(),l(3,"span"),u(4),d()()),n&2){let e=m(3);g(4),O(e.geminiSaveMessage())}}function VD(n,t){if(n&1&&(l(0,"div",100)(1,"span",29),u(2,"error"),d(),l(3,"span"),u(4),d()()),n&2){let e=m(3);g(4),O(e.geminiSaveError())}}function jD(n,t){n&1&&$(0,"span",108)}function $D(n,t){if(n&1){let e=L();l(0,"button",111),k("click",function(){v(e);let i=m(4);return y(i.copyToClipboard(i.ocrKeyInput(),"ocr_key_field"))}),l(1,"span",29),u(2),d()()}if(n&2){let e=m(4);g(),w("text-emerald",e.copiedId()==="ocr_key_field"),g(),V(" ",e.copiedId()==="ocr_key_field"?"check":"content_copy"," ")}}function zD(n,t){if(n&1&&(l(0,"span",112),u(1,"sync"),d(),l(2,"span"),u(3),d()),n&2){let e=m(4);g(3),O(e.ocrKeyInput().trim()?"Verifying & Saving...":"Clearing...")}}function BD(n,t){if(n&1&&(l(0,"span",29),u(1),d(),l(2,"span"),u(3),d()),n&2){let e=m(4);g(),O(e.ocrKeyInput().trim()?"save":"delete_outline"),g(2),O(e.ocrKeyInput().trim()?e.isOcrModified()?"Save & Apply":"Save Key":"Clear Key")}}function HD(n,t){n&1&&(l(0,"span",112),u(1,"sync"),d(),l(2,"span"),u(3,"Testing..."),d())}function UD(n,t){n&1&&(l(0,"span",29),u(1,"network_check"),d(),l(2,"span"),u(3,"Test Key"),d())}function GD(n,t){if(n&1&&(l(0,"div",99)(1,"span",29),u(2,"check_circle"),d(),l(3,"span"),u(4),d()()),n&2){let e=m(4);g(4),O(e.ocrSaveMessage())}}function qD(n,t){if(n&1&&(l(0,"div",100)(1,"span",29),u(2,"error"),d(),l(3,"span"),u(4),d()()),n&2){let e=m(4);g(4),O(e.ocrSaveError())}}function WD(n,t){if(n&1){let e=L();l(0,"div",110)(1,"p",113),u(2," Provides screen text coordinate grounding to improve element detection and interaction accuracy on text-heavy apps. "),d(),l(3,"div",114)(4,"div",87)(5,"div",88)(6,"span",89),u(7,"key"),d(),l(8,"span"),u(9,"Cloud Vision API Key:"),d()()(),l(10,"div",91)(11,"div",92)(12,"span",93),u(13,"key"),d(),l(14,"input",115),k("ngModelChange",function(i){v(e);let r=m(3);return y(r.onOcrKeyChange(i))}),d(),Rt(),l(15,"button",95),k("click",function(){v(e);let i=m(3);return y(i.toggleOcrKeyVisibility())}),l(16,"span",29),u(17),d()(),M(18,$D,3,3,"button",96),d(),l(19,"button",97),k("click",function(){v(e);let i=m(3);return y(i.saveOcrKey())}),M(20,zD,4,1)(21,BD,4,2),d(),l(22,"button",116),k("click",function(){v(e);let i=m(3);return y(i.testOcrKey())}),M(23,HD,4,0)(24,UD,4,0),d()(),M(25,GD,5,1,"div",99),M(26,qD,5,1,"div",100),d()()}if(n&2){let e=m(3);g(14),w("is-masked",!e.showOcrKey()),R("type",e.showOcrKey()?"text":"password")("ngModel",e.ocrKeyInput()),Ft(),g(),R("title",e.showOcrKey()?"Mask Key":"Show Plaintext"),g(2),V(" ",e.showOcrKey()?"visibility_off":"visibility"," "),g(),b(e.ocrKeyInput()?18:-1),g(),w("btn-dirty",e.isOcrModified()),R("disabled",e.isSavingOcrKey()||e.isTestingOcrKey()||!e.isOcrModified()&&!e.ocrKeyInput().trim()),g(),b(e.isSavingOcrKey()?20:21),g(2),R("disabled",e.isTestingOcrKey()||e.isSavingOcrKey()||!e.ocrKeyInput().trim()),g(),b(e.isTestingOcrKey()?23:24),g(2),b(e.ocrSaveMessage()?25:-1),g(),b(e.ocrSaveError()?26:-1)}}function KD(n,t){if(n&1){let e=L();l(0,"div",86)(1,"div",87)(2,"div",88)(3,"span",89),u(4,"vpn_key"),d(),l(5,"span"),u(6,"Enter Gemini API Key:"),d()(),l(7,"a",90)(8,"span",29),u(9,"open_in_new"),d(),l(10,"span"),u(11,"Get Free API Key (Google AI Studio)"),d()()(),l(12,"div",91)(13,"div",92)(14,"span",93),u(15,"key"),d(),l(16,"input",94),k("ngModelChange",function(i){v(e);let r=m(2);return y(r.onGeminiKeyChange(i))}),d(),Rt(),l(17,"button",95),k("click",function(){v(e);let i=m(2);return y(i.toggleGeminiKeyVisibility())}),l(18,"span",29),u(19),d()(),M(20,TD,3,3,"button",96),d(),l(21,"button",97),k("click",function(){v(e);let i=m(2);return y(i.saveGeminiKey())}),M(22,AD,4,1)(23,ND,4,2),d(),l(24,"button",98),k("click",function(){v(e);let i=m(2);return y(i.testGeminiKey())}),M(25,RD,4,0)(26,FD,4,0),d()(),M(27,LD,5,1,"div",99),M(28,VD,5,1,"div",100),d(),l(29,"div",101)(30,"div",102),k("click",function(){v(e);let i=m(2);return y(i.toggleOcrConfig())}),l(31,"div",103)(32,"span",104),u(33,"document_scanner"),d(),l(34,"div",105)(35,"span",106),u(36,"Optional: Google Cloud Vision OCR"),d()()(),l(37,"div",107),M(38,jD,1,0,"span",108),l(39,"span",109),u(40),d()()(),M(41,WD,27,15,"div",110),d()}if(n&2){let e=m(2);g(16),w("is-masked",!e.showGeminiKey()),R("type",e.showGeminiKey()?"text":"password")("ngModel",e.geminiKeyInput()),Ft(),g(),R("title",e.showGeminiKey()?"Mask Key":"Show Plaintext"),g(2),V(" ",e.showGeminiKey()?"visibility_off":"visibility"," "),g(),b(e.geminiKeyInput()?20:-1),g(),w("btn-dirty",e.isGeminiModified()),R("disabled",e.isSavingGeminiKey()||e.isTestingGeminiKey()||!e.isGeminiModified()&&!e.geminiKeyInput().trim()),g(),b(e.isSavingGeminiKey()?22:23),g(2),R("disabled",e.isTestingGeminiKey()||e.isSavingGeminiKey()||!e.geminiKeyInput().trim()),g(),b(e.isTestingGeminiKey()?25:26),g(2),b(e.geminiSaveMessage()?27:-1),g(),b(e.geminiSaveError()?28:-1),g(10),b(e.isOcrConfigured()?38:-1),g(2),V(" ",e.showOcrConfig()?"expand_less":"expand_more"," "),g(),b(e.showOcrConfig()?41:-1)}}function YD(n,t){if(n&1&&(l(0,"div",128)(1,"span",129),u(2,"Fallback Model"),d(),l(3,"div",138)(4,"span"),u(5),d()()()),n&2){let e=m(3);g(5),We("",e.modelConfigEnv()?.default_model?.fallback?.provider,"/",e.modelConfigEnv()?.default_model?.fallback?.model)}}function ZD(n,t){if(n&1&&(l(0,"div",135)(1,"pre",139)(2,"code"),u(3),d()()()),n&2){let e=m(3);g(3),O(e.modelConfigEnv()?.config_content)}}function QD(n,t){if(n&1&&(l(0,"code",146),u(1),d()),n&2){let e=m(2).$implicit;g(),V("(",e.preview,")")}}function JD(n,t){if(n&1&&(l(0,"span",144)(1,"span",29),u(2,"check_circle"),d(),l(3,"span"),u(4,"Configured"),d(),M(5,QD,2,1,"code",146),d()),n&2){let e=m().$implicit;g(5),b(e.preview?5:-1)}}function XD(n,t){n&1&&(l(0,"span",145)(1,"span",29),u(2,"radio_button_unchecked"),d(),l(3,"span"),u(4,"Not Set"),d()())}function eI(n,t){if(n&1&&(l(0,"div",140)(1,"div",141)(2,"code",142),u(3),d()(),l(4,"div",143),M(5,JD,6,1,"span",144)(6,XD,5,0,"span",145),d()()),n&2){let e=t.$implicit;w("is-configured",e.is_set),g(3),O(e.name),g(2),b(e.is_set?5:6)}}function tI(n,t){if(n&1){let e=L();l(0,"div",61)(1,"div",117)(2,"div",118)(3,"div",119)(4,"span",120),u(5,"tune"),d(),l(6,"div",121)(7,"span",122),u(8,"Active Model Configuration"),d(),l(9,"span",123),u(10,"Defined in "),l(11,"code"),u(12),d()()()(),l(13,"div",124)(14,"button",125),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard(i.modelConfigEnv()?.config_path||"config/artemis.jsonc","config_path_btn"))}),l(15,"span",29),u(16),d(),l(17,"span"),u(18,"Copy Path"),d()(),l(19,"button",126),k("click",function(){v(e);let i=m(2);return y(i.toggleFullConfigFile())}),l(20,"span",29),u(21),d(),l(22,"span"),u(23),d()()()(),l(24,"div",127)(25,"div",128)(26,"span",129),u(27,"Default Model"),d(),l(28,"div",130),$(29,"span",131),l(30,"span",132),u(31),d(),l(32,"span",133),u(33,"/"),d(),l(34,"span",134),u(35),d()()(),M(36,YD,6,2,"div",128),d(),M(37,ZD,4,1,"div",135),d(),l(38,"div",117)(39,"div",118)(40,"div",119)(41,"span",120),u(42,"vpn_key"),d(),l(43,"div",121)(44,"span",122),u(45,"Environment Variables & API Keys"),d(),l(46,"span",123),u(47,"Loaded from "),l(48,"code"),u(49),d()()()(),l(50,"button",125),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard(i.modelConfigEnv()?.env_path||".env","env_path_btn"))}),l(51,"span",29),u(52),d(),l(53,"span"),u(54,"Copy Path"),d()()(),l(55,"div",136),G(56,eI,7,4,"div",137,GP),d()()()}if(n&2){let e=m(2);g(12),O(e.modelConfigEnv()?.config_path||"config/artemis.jsonc"),g(3),w("text-emerald",e.copiedId()==="config_path_btn"),g(),V(" ",e.copiedId()==="config_path_btn"?"check":"content_copy"," "),g(5),V(" ",e.showFullConfigFile()?"unfold_less":"code"," "),g(2),O(e.showFullConfigFile()?"Hide JSONC":"View JSONC"),g(8),O(e.modelConfigEnv()?.default_model?.provider||"google"),g(4),O(e.modelConfigEnv()?.default_model?.model||"gemini-3.8-flash"),g(),b(e.modelConfigEnv()?.default_model?.fallback?36:-1),g(),b(e.showFullConfigFile()?37:-1),g(12),O(e.modelConfigEnv()?.env_path||".env"),g(2),w("text-emerald",e.copiedId()==="env_path_btn"),g(),V(" ",e.copiedId()==="env_path_btn"?"check":"content_copy"," "),g(4),q(e.modelConfigEnv()?.env_vars||za(14,hD))}}function nI(n,t){n&1&&(l(0,"span",23),u(1,"check"),d())}function oI(n,t){n&1&&(l(0,"span"),u(1,"3"),d())}function iI(n,t){n&1&&(l(0,"span",147),u(1,"sync"),d(),l(2,"span"),u(3,"Restarting..."),d())}function rI(n,t){if(n&1&&(l(0,"span",148),u(1,"check"),d(),l(2,"span",149),u(3),d()),n&2){let e=m(2);g(3),O(e.adbRestartFeedback())}}function aI(n,t){if(n&1&&(l(0,"span",29),u(1,"sync"),d(),l(2,"span"),u(3),d()),n&2){let e=m(2);g(3),O(e.isRemoteAdbServer()?"Refresh Devices":"Restart ADB")}}function sI(n,t){n&1&&(l(0,"span"),u(1,"Virtual Device"),d(),l(2,"span",160),u(3,"\xB7"),d())}function cI(n,t){if(n&1&&(l(0,"span",160),u(1,"\xB7"),d(),l(2,"span"),u(3),d()),n&2){let e=m(3);g(3),O(e.activeDevice()?.screen_resolution)}}function lI(n,t){if(n&1&&(l(0,"span",160),u(1,"\xB7"),d(),l(2,"span"),u(3),d()),n&2){let e=m(3);g(3),V("Android ",e.activeDevice()?.android_version)}}function dI(n,t){if(n&1&&(l(0,"span",160),u(1,"\xB7"),d(),l(2,"span",161),u(3),d()),n&2){let e=m(3);g(3),We(" Remote via ",e.adbServerStatus()?.endpoint?.host,":",e.adbServerStatus()?.endpoint?.port," ")}}function uI(n,t){n&1&&(l(0,"span",167),u(1,"\u2713 Active"),d())}function gI(n,t){if(n&1){let e=L();l(0,"button",165),k("click",function(){let i=v(e).$implicit,r=m(4);return y(r.selectTargetDevice(i.serial))}),l(1,"span",166),u(2," phone_android "),d(),l(3,"span"),u(4),d(),M(5,uI,2,0,"span",167),d()}if(n&2){let e=t.$implicit,o=m(4);w("selected",e.serial===o.activeDevice()?.serial),g(4),O(e.model||e.serial),g(),b(e.serial===o.activeDevice()?.serial?5:-1)}}function pI(n,t){if(n&1&&(l(0,"div",159)(1,"span",162),u(2,"Select Active Device:"),d(),l(3,"div",163),G(4,gI,6,4,"button",164,Pm),d()()),n&2){let e=m(3);g(4),q(e.connectedDevices())}}function fI(n,t){if(n&1&&(l(0,"div",64)(1,"div",150)(2,"div",151)(3,"span",152),u(4," phone_android "),d()(),l(5,"div",153)(6,"div",154),u(7),d(),l(8,"div",155),M(9,sI,4,0),l(10,"span"),u(11),d(),M(12,cI,4,1),M(13,lI,4,1),M(14,dI,4,2),d()(),l(15,"div",156),$(16,"span",157),l(17,"span",158),u(18,"Connected"),d()()(),M(19,pI,6,0,"div",159),d()),n&2){let e=m(2);g(7),V(" ",e.activeDevice()?.model||e.activeDevice()?.serial," "),g(2),b(e.activeDevice()?.is_emulator?9:-1),g(2),O(e.activeDevice()?.serial),g(),b(e.activeDevice()?.screen_resolution?12:-1),g(),b(e.activeDevice()?.android_version?13:-1),g(),b(e.isRemoteAdbServer()?14:-1),g(5),b(e.connectedDevices().length>1?19:-1)}}function mI(n,t){n&1&&(l(0,"span",185),u(1,"check"),d())}function _I(n,t){n&1&&$(0,"span",186)}function hI(n,t){n&1&&(l(0,"span",185),u(1,"check"),d())}function CI(n,t){n&1&&$(0,"span",186)}function MI(n,t){n&1&&(l(0,"span"),u(1,"2"),d())}function bI(n,t){n&1&&(l(0,"span",185),u(1,"check"),d())}function PI(n,t){n&1&&$(0,"span",186)}function OI(n,t){n&1&&(l(0,"span"),u(1,"3"),d())}function vI(n,t){if(n&1&&(l(0,"div",204),u(1),d()),n&2){let e=t.$implicit;g(),O(e)}}function yI(n,t){if(n&1&&G(0,vI,2,1,"div",204,Ie),n&2){let e=m(4);q(e.emulatorLaunchState()?.logs)}}function xI(n,t){n&1&&(l(0,"div",203),u(1,"Waiting for process output..."),d())}function wI(n,t){if(n&1){let e=L();l(0,"div",198)(1,"div",199)(2,"div",200)(3,"span",29),u(4,"terminal"),d(),l(5,"span"),u(6,"Emulator Console Stream (stdout / stderr)"),d()(),l(7,"button",201),k("click",function(){v(e);let i=m(3);return y(i.copyToClipboard(i.emulatorLaunchState()?.logs?.join(` -`)||"","boot_logs"))}),l(8,"span",29),u(9),d(),l(10,"span"),u(11),d()()(),l(12,"pre",202),M(13,yI,2,0)(14,xI,2,0,"div",203),d()()}if(n&2){let e=m(3);g(9),O(e.copiedId()==="boot_logs"?"check":"content_copy"),g(2),O(e.copiedId()==="boot_logs"?"Copied":"Copy Logs"),g(2),b(e.emulatorLaunchState()?.logs?.length?13:14)}}function SI(n,t){if(n&1){let e=L();l(0,"div",65)(1,"div",168)(2,"div",169)(3,"div",170)(4,"div",171)(5,"span",172),u(6,"sync"),d()(),l(7,"div",173)(8,"div",174)(9,"h4",175),u(10," Launching Android Emulator: "),l(11,"span",176),u(12),d()(),l(13,"span",177),u(14),d()(),l(15,"p",178),u(16),d()()(),l(17,"div",179)(18,"button",180),k("click",function(){v(e);let i=m(2);return y(i.toggleLaunchLogs())}),l(19,"span",29),u(20,"terminal"),d(),l(21,"span"),u(22),d()(),l(23,"button",181),k("click",function(){v(e);let i=m(2);return y(i.stopEmulator())}),l(24,"span",29),u(25,"cancel"),d(),l(26,"span"),u(27,"Stop"),d()()()(),l(28,"div",182)(29,"div",183)(30,"div",184),M(31,mI,2,0,"span",185)(32,_I,1,0,"span",186),d(),l(33,"span",187),u(34,"1. Process Start"),d()(),$(35,"div",188),l(36,"div",183)(37,"div",184),M(38,hI,2,0,"span",185)(39,CI,1,0,"span",186)(40,MI,2,0,"span"),d(),l(41,"span",187),u(42,"2. ADB Handshake"),d()(),$(43,"div",188),l(44,"div",183)(45,"div",184),M(46,bI,2,0,"span",185)(47,PI,1,0,"span",186)(48,OI,2,0,"span"),d(),l(49,"span",187),u(50,"3. Android OS Boot"),d()(),$(51,"div",188),l(52,"div",183)(53,"div",184)(54,"span",185),u(55,"check_circle"),d()(),l(56,"span",187),u(57,"4. Ready"),d()()(),l(58,"div",189)(59,"div",190),$(60,"div",191),d(),l(61,"div",192)(62,"span",193),u(63),d(),l(64,"span",194)(65,"span",195),u(66,"timer"),d(),u(67),d()()(),l(68,"div",196)(69,"span",197),u(70,"info"),d(),l(71,"span"),u(72,"Android virtualization cold boot usually takes 20-45 seconds. Live progress is actively tracked above\u2014please do not click launch repeatedly."),d()(),M(73,wI,15,3,"div",198),d()()}if(n&2){let e=m(2);g(12),O(e.emulatorLaunchState()?.avd_name||e.activeDevice()?.serial||"Virtual Device"),g(2),O(e.emulatorLaunchState()?.status==="booting"?"OS Booting":"Starting"),g(2),O(e.emulatorLaunchState()?.stage_message||"Initializing Android Virtual Device..."),g(2),w("active",e.showLaunchLogs()),g(4),O(e.showLaunchLogs()?"Hide Logs":"View Boot Logs"),g(7),w("done",e.emulatorLaunchState()?.progress_percent>=35)("active",e.emulatorLaunchState()?.status==="starting"),g(2),b(e.emulatorLaunchState()?.progress_percent>=35?31:32),g(4),w("done",e.emulatorLaunchState()?.progress_percent>=35),g(),w("done",e.emulatorLaunchState()?.progress_percent>=65)("active",e.emulatorLaunchState()?.status==="waiting_for_adb"),g(2),b(e.emulatorLaunchState()?.progress_percent>=65?38:e.emulatorLaunchState()?.status==="waiting_for_adb"?39:40),g(5),w("done",e.emulatorLaunchState()?.progress_percent>=65),g(),w("done",e.emulatorLaunchState()?.status==="ready")("active",e.emulatorLaunchState()?.status==="booting"||e.adbProbe()?.summary==="Device Booting"),g(2),b(e.emulatorLaunchState()?.status==="ready"?46:e.emulatorLaunchState()?.status==="booting"||e.adbProbe()?.summary==="Device Booting"?47:48),g(5),w("done",e.emulatorLaunchState()?.status==="ready"),g(),w("done",e.emulatorLaunchState()?.status==="ready"),g(8),Se("width",e.emulatorLaunchState()?.progress_percent||25,"%"),g(3),V("",e.emulatorLaunchState()?.progress_percent||25,"% Complete"),g(4),V(" Elapsed: ",e.emulatorLaunchState()?.elapsed_seconds||0,"s "),g(6),b(e.showLaunchLogs()?73:-1)}}function kI(n,t){if(n&1&&(l(0,"div",204),u(1),d()),n&2){let e=t.$implicit;g(),O(e)}}function EI(n,t){if(n&1){let e=L();l(0,"div",214)(1,"div",199)(2,"span"),u(3,"Process Output / Failure Logs:"),d(),l(4,"button",201),k("click",function(){v(e);let i=m(3);return y(i.copyToClipboard(i.emulatorLaunchState()?.logs?.join(` -`)||"","fail_logs"))}),l(5,"span",29),u(6),d(),l(7,"span"),u(8),d()()(),l(9,"pre",219),G(10,kI,2,1,"div",204,Ie),d()()}if(n&2){let e=m(3);g(6),O(e.copiedId()==="fail_logs"?"check":"content_copy"),g(2),O(e.copiedId()==="fail_logs"?"Copied":"Copy Logs"),g(2),q(e.emulatorLaunchState()?.logs)}}function DI(n,t){if(n&1){let e=L();l(0,"button",220),k("click",function(){v(e);let i=m(3);return y(i.launchAvdEmulator(i.emulatorLaunchState().avd_name))}),l(1,"span",29),u(2,"refresh"),d(),l(3,"span"),u(4),d()()}if(n&2){let e=m(3);R("disabled",e.isRemoteAdbServer()),g(4),V("Retry Launch (",e.emulatorLaunchState()?.avd_name,")")}}function II(n,t){if(n&1){let e=L();l(0,"div",66)(1,"div",205)(2,"div",206)(3,"div",207)(4,"div",208)(5,"span",209),u(6,"error"),d()(),l(7,"div",210)(8,"h4",211),u(9,"Emulator Launch Failed"),d(),l(10,"p",212),u(11),d()()(),l(12,"button",213),k("click",function(){v(e);let i=m(2);return y(i.dismissEmulatorStatus())}),l(13,"span",29),u(14,"close"),d()()(),M(15,EI,12,2,"div",214),l(16,"div",215),M(17,DI,5,2,"button",216),l(18,"button",217),k("click",function(){v(e);let i=m(2);return y(i.restartAdbServer())}),l(19,"span",29),u(20,"sync"),d(),l(21,"span"),u(22,"Restart ADB Server"),d()(),l(23,"button",218),k("click",function(){v(e);let i=m(2);return y(i.dismissEmulatorStatus())}),l(24,"span"),u(25,"Dismiss"),d()()()()()}if(n&2){let e=m(2);g(11),O(e.emulatorLaunchState()?.error||"The Android emulator process failed to start or crashed during initialization."),g(4),b(e.emulatorLaunchState()?.logs?.length?15:-1),g(2),b(e.emulatorLaunchState()?.avd_name?17:-1)}}function TI(n,t){if(n&1&&u(0),n&2){let e=m(3);We(" ",e.installedAvds().length," local virtual device",e.installedAvds().length>1?"s":""," available ")}}function AI(n,t){n&1&&u(0," Launch a local Android Virtual Device ")}function NI(n,t){if(n&1){let e=L();l(0,"div",231)(1,"div",234)(2,"span",29),u(3,"hub"),d(),l(4,"span"),u(5," Artemis is currently using "),l(6,"strong"),u(7),d(),u(8,". Switch to local ADB before using a local emulator, USB cable, or Wireless ADB. "),d()(),l(9,"button",235),k("click",function(){v(e);let i=m(3);return y(i.switchToLocalAdbServer())}),l(10,"span",29),u(11,"sync"),d(),l(12,"span"),u(13),d()()()}if(n&2){let e=m(3);g(7),We("",e.adbServerStatus()?.endpoint?.host,":",e.adbServerStatus()?.endpoint?.port),g(2),R("disabled",e.isSwitchingToLocalAdb()),g(),w("spinning",e.isSwitchingToLocalAdb()),g(3),O(e.isSwitchingToLocalAdb()?"Switching...":"Use Local ADB")}}function RI(n,t){if(n&1&&($(0,"span",252),l(1,"span"),u(2),d()),n&2){let e=m(6);g(2),We("",e.emulatorLaunchState()?.status==="booting"?"Booting OS":"Starting"," (",e.emulatorLaunchState()?.elapsed_seconds||0,"s)")}}function FI(n,t){n&1&&(l(0,"span",253),u(1,"play_arrow"),d(),l(2,"span"),u(3,"Launch"),d())}function LI(n,t){if(n&1){let e=L();l(0,"div",243)(1,"div",244)(2,"div",245)(3,"span",29),u(4,"smartphone"),d()(),l(5,"div",246)(6,"div",247)(7,"span",248),u(8),d(),l(9,"span",249),u(10,"Virtual Device"),d()()()(),l(11,"div",250)(12,"button",251),k("click",function(){let i=v(e).$implicit,r=m(5);return y(r.launchAvdEmulator(i))}),M(13,RI,3,2)(14,FI,4,0),d()()()}if(n&2){let e=t.$implicit,o=m(5);g(8),O(e),g(4),w("launching",o.launchingAvd()===e||o.isEmulatorLaunching()&&o.emulatorLaunchState()?.avd_name===e),R("disabled",o.isEmulatorLaunching()||o.isRemoteAdbServer())("title",o.isEmulatorLaunching()?"An emulator is currently launching...":"Launch "+e),g(),b(o.launchingAvd()===e||o.isEmulatorLaunching()&&o.emulatorLaunchState()?.avd_name===e?13:14)}}function VI(n,t){if(n&1&&(l(0,"div",236)(1,"div",238)(2,"div",239)(3,"span",120),u(4,"devices"),d(),l(5,"span",240),u(6,"Installed Virtual Devices (AVD)"),d(),l(7,"span",241),u(8),d()()(),l(9,"div",242),G(10,LI,15,6,"div",243,Ie),d()()),n&2){let e=m(4);g(8),V("",e.installedAvds().length," Available"),g(2),q(e.installedAvds())}}function jI(n,t){if(n&1&&(l(0,"div",264)(1,"div",266)(2,"div",267)(3,"span",268),u(4,"1"),d(),l(5,"span",269),u(6,"download"),d()(),l(7,"div",270),u(8,"Install Android Studio"),d(),l(9,"div",271),u(10),l(11,"a",272),u(12,"developer.android.com/studio"),d(),u(13," and install. "),d()(),l(14,"div",266)(15,"div",267)(16,"span",268),u(17,"2"),d(),l(18,"span",269),u(19,"developer_mode"),d()(),l(20,"div",270),u(21,"Open Device Manager"),d(),l(22,"div",271),u(23," On Studio welcome screen, open "),l(24,"strong"),u(25,"More Actions > Virtual Device Manager"),d(),u(26," (or "),l(27,"strong"),u(28,"Tools > Device Manager"),d(),u(29,"). "),d()(),l(30,"div",266)(31,"div",267)(32,"span",268),u(33,"3"),d(),l(34,"span",269),u(35,"add_circle"),d()(),l(36,"div",270),u(37,"Create Virtual Device"),d(),l(38,"div",271),u(39," Click "),l(40,"strong"),u(41,"Create Device"),d(),u(42,", choose "),l(43,"strong"),u(44,"Pixel 8"),d(),u(45,", select "),l(46,"strong"),u(47,"Android 14 (API 34)"),d(),u(48,", and click "),l(49,"strong"),u(50,"Finish"),d(),u(51,". "),d()(),l(52,"div",266)(53,"div",267)(54,"span",268),u(55,"4"),d(),l(56,"span",269),u(57,"play_arrow"),d()(),l(58,"div",270),u(59,"Launch Emulator"),d(),l(60,"div",271),u(61," Click \u25B6 "),l(62,"strong"),u(63,"Play"),d(),u(64," in Device Manager. Artemis will detect and connect to it automatically! "),d()()()),n&2){let e=m(5);g(10),V(" Download for ",e.effectiveOs()==="darwin"?"macOS":e.effectiveOs()==="windows"?"Windows":"Linux"," from ")}}function $I(n,t){if(n&1){let e=L();l(0,"div",265)(1,"div",273)(2,"div",274),u(3,"1"),d(),l(4,"div",275)(5,"div",26),u(6),d(),l(7,"p",276),u(8),d(),l(9,"div",81)(10,"span",84),u(11),d(),l(12,"code",85),u(13),d(),l(14,"button",82),k("click",function(){v(e);let i=m(5);return y(i.copyToClipboard(i.emuHypervisorCmd(),"emu_kvm"))}),l(15,"span",29),u(16),d(),l(17,"span"),u(18),d()()()()(),l(19,"div",273)(20,"div",274),u(21,"2"),d(),l(22,"div",275)(23,"div",26),u(24,"Download Emulator & System Image (API 34)"),d(),l(25,"p",276),u(26,"Install Android 14 Google APIs system image using SDK Manager:"),d(),l(27,"div",81)(28,"span",84),u(29),d(),l(30,"code",85),u(31),d(),l(32,"button",82),k("click",function(){v(e);let i=m(5);return y(i.copyToClipboard(i.emuSdkInstallCmd(),"emu_sdk"))}),l(33,"span",29),u(34),d(),l(35,"span"),u(36),d()()()()(),l(37,"div",273)(38,"div",274),u(39,"3"),d(),l(40,"div",275)(41,"div",26),u(42,"Create Virtual Device (Pixel 8 AVD)"),d(),l(43,"p",276),u(44,"Initialize a new Android Virtual Device named "),l(45,"code"),u(46,"Pixel_8_API_34"),d(),u(47,":"),d(),l(48,"div",81)(49,"span",84),u(50),d(),l(51,"code",85),u(52),d(),l(53,"button",82),k("click",function(){v(e);let i=m(5);return y(i.copyToClipboard(i.emuCreateAvdCmd(),"emu_create"))}),l(54,"span",29),u(55),d(),l(56,"span"),u(57),d()()()()(),l(58,"div",273)(59,"div",274),u(60,"4"),d(),l(61,"div",275)(62,"div",26),u(63,"Start the Emulator"),d(),l(64,"p",276),u(65,"Launch the virtual device (or add "),l(66,"code"),u(67,"-no-window"),d(),u(68," for headless execution):"),d(),l(69,"div",81)(70,"span",84),u(71),d(),l(72,"code",85),u(73,"emulator -avd Pixel_8_API_34 -no-boot-anim"),d(),l(74,"button",82),k("click",function(){v(e);let i=m(5);return y(i.copyToClipboard("emulator -avd Pixel_8_API_34 -no-boot-anim","emu_run"))}),l(75,"span",29),u(76),d(),l(77,"span"),u(78),d()()()()()()}if(n&2){let e=m(5);g(6),O(e.emuHypervisorTitle()),g(2),O(e.emuHypervisorDesc()),g(3),O(e.effectiveOs()==="windows"?"PS>":"$"),g(2),O(e.emuHypervisorCmd()),g(),w("copied",e.copiedId()==="emu_kvm"),g(2),O(e.copiedId()==="emu_kvm"?"check":"content_copy"),g(2),O(e.copiedId()==="emu_kvm"?"Copied!":"Copy"),g(11),O(e.effectiveOs()==="windows"?"PS>":"$"),g(2),O(e.emuSdkInstallCmd()),g(),w("copied",e.copiedId()==="emu_sdk"),g(2),O(e.copiedId()==="emu_sdk"?"check":"content_copy"),g(2),O(e.copiedId()==="emu_sdk"?"Copied!":"Copy"),g(14),O(e.effectiveOs()==="windows"?"PS>":"$"),g(2),O(e.emuCreateAvdCmd()),g(),w("copied",e.copiedId()==="emu_create"),g(2),O(e.copiedId()==="emu_create"?"check":"content_copy"),g(2),O(e.copiedId()==="emu_create"?"Copied!":"Copy"),g(14),O(e.effectiveOs()==="windows"?"PS>":"$"),g(3),w("copied",e.copiedId()==="emu_run"),g(2),O(e.copiedId()==="emu_run"?"check":"content_copy"),g(2),O(e.copiedId()==="emu_run"?"Copied!":"Copy")}}function zI(n,t){if(n&1){let e=L();l(0,"div",237)(1,"div",254)(2,"div",255)(3,"div",256)(4,"span",29),u(5,"devices_off"),d()(),l(6,"div",257)(7,"div",258)(8,"h4",259),u(9,"No Android Virtual Devices (AVD) Detected"),d(),l(10,"div",78)(11,"button",79),k("click",function(){v(e);let i=m(4);return y(i.setSelectedOs("linux"))}),u(12,"Linux"),d(),l(13,"button",79),k("click",function(){v(e);let i=m(4);return y(i.setSelectedOs("darwin"))}),u(14,"macOS"),d(),l(15,"button",79),k("click",function(){v(e);let i=m(4);return y(i.setSelectedOs("windows"))}),u(16,"Windows"),d()()(),l(17,"p",260),u(18,"Follow the step-by-step instructions below to install and start an emulator:"),d()()(),l(19,"div",261)(20,"button",262),k("click",function(){v(e);let i=m(4);return y(i.setEmulatorSetupMode("studio"))}),l(21,"span",263),u(22,"desktop_windows"),d(),l(23,"span"),u(24,"Android Studio (GUI)"),d()(),l(25,"button",262),k("click",function(){v(e);let i=m(4);return y(i.setEmulatorSetupMode("cli"))}),l(26,"span",263),u(27,"terminal"),d(),l(28,"span"),u(29,"Command Line (CLI)"),d()()()(),M(30,jI,65,1,"div",264),M(31,$I,79,25,"div",265),d()}if(n&2){let e=m(4);g(11),w("active",e.effectiveOs()==="linux"),g(2),w("active",e.effectiveOs()==="darwin"),g(2),w("active",e.effectiveOs()==="windows"),g(5),w("active",e.emulatorSetupMode()==="studio"),g(5),w("active",e.emulatorSetupMode()==="cli"),g(5),b(e.emulatorSetupMode()==="studio"?30:-1),g(),b(e.emulatorSetupMode()==="cli"?31:-1)}}function BI(n,t){if(n&1&&(l(0,"div",232),M(1,VI,12,1,"div",236)(2,zI,32,12,"div",237),d()),n&2){let e=m(3);g(),b(e.installedAvds().length>0?1:2)}}function HI(n,t){n&1&&(l(0,"div",232)(1,"div",277)(2,"span",278),u(3,"cable"),d(),l(4,"span"),u(5,"Connect your Android phone via USB cable and enable USB Debugging:"),d()(),l(6,"div",279)(7,"div",266)(8,"div",267)(9,"span",268),u(10,"1"),d(),l(11,"span",269),u(12,"usb"),d()(),l(13,"div",270),u(14,"Connect USB Cable"),d(),l(15,"div",271),u(16,"Plug your Android phone into this computer with a data cable."),d()(),l(17,"div",266)(18,"div",267)(19,"span",268),u(20,"2"),d(),l(21,"span",269),u(22,"touch_app"),d()(),l(23,"div",270),u(24,"Enable Developer Options"),d(),l(25,"div",271),u(26,"In phone "),l(27,"strong"),u(28,"Settings > About Phone"),d(),u(29,", tap "),l(30,"strong"),u(31,"Build Number"),d(),u(32," 7 times."),d()(),l(33,"div",266)(34,"div",267)(35,"span",268),u(36,"3"),d(),l(37,"span",269),u(38,"toggle_on"),d()(),l(39,"div",270),u(40,"Enable USB Debugging"),d(),l(41,"div",271),u(42,"In "),l(43,"strong"),u(44,"Settings > Developer Options"),d(),u(45,", turn "),l(46,"strong"),u(47,"USB Debugging"),d(),u(48," ON. "),d()(),l(49,"div",266)(50,"div",267)(51,"span",268),u(52,"4"),d(),l(53,"span",269),u(54,"verified_user"),d()(),l(55,"div",270),u(56,"Authorize Computer"),d(),l(57,"div",271),u(58,"Check "),l(59,"strong"),u(60,'"Always allow"'),d(),u(61," and tap "),l(62,"strong"),u(63,"Allow"),d(),u(64," on the phone prompt. "),d()()()())}function UI(n,t){n&1&&(l(0,"span",147),u(1,"sync"),d(),l(2,"span"),u(3,"Connecting..."),d())}function GI(n,t){n&1&&(l(0,"span",29),u(1,"bolt"),d(),l(2,"span"),u(3,"Connect"),d())}function qI(n,t){if(n&1&&(l(0,"div",292)(1,"span",29),u(2,"check_circle"),d(),l(3,"span"),u(4),d()()),n&2){let e=m(4);g(4),O(e.wifiConnectMessage())}}function WI(n,t){if(n&1&&(l(0,"div",293)(1,"span",29),u(2,"error"),d(),l(3,"span"),u(4),d()()),n&2){let e=m(4);g(4),O(e.wifiConnectError())}}function KI(n,t){if(n&1){let e=L();l(0,"div",232)(1,"div",280)(2,"span",278),u(3,"wifi"),d(),l(4,"span"),u(5,"Connect your phone and computer on the same Wi-Fi network:"),d()(),l(6,"div",281)(7,"div",282)(8,"div",283)(9,"label",284),u(10,"Device IP Address"),d(),l(11,"div",285)(12,"span",286),u(13,"router"),d(),l(14,"input",287),k("ngModelChange",function(i){v(e);let r=m(3);return y(r.wifiHost.set(i))}),d(),Rt(),d()(),l(15,"div",288)(16,"label",284),u(17,"Port"),d(),l(18,"div",285)(19,"span",286),u(20,"tag"),d(),l(21,"input",289),k("ngModelChange",function(i){v(e);let r=m(3);return y(r.wifiPort.set(i))}),d(),Rt(),d()(),l(22,"div",290)(23,"button",291),k("click",function(){v(e);let i=m(3);return y(i.connectWifiDevice())}),M(24,UI,4,0)(25,GI,4,0),d()()(),M(26,qI,5,1,"div",292),M(27,WI,5,1,"div",293),d(),l(28,"div",294)(29,"span",295),u(30,"help_outline"),d(),l(31,"div",296),u(32," Find IP & port in phone "),l(33,"strong"),u(34,"Settings > Developer Options > Wireless Debugging"),d(),u(35,". "),d()()()}if(n&2){let e=m(3);g(14),R("ngModel",e.wifiHost()),Ft(),g(7),R("ngModel",e.wifiPort()),Ft(),g(2),R("disabled",e.isConnectingWifi()||e.isRemoteAdbServer()||!e.wifiHost().trim()),g(),b(e.isConnectingWifi()?24:25),g(2),b(e.wifiConnectMessage()?26:-1),g(),b(e.wifiConnectError()?27:-1)}}function YI(n,t){n&1&&(l(0,"span",147),u(1,"sync"),d(),l(2,"span"),u(3,"Checking..."),d())}function ZI(n,t){n&1&&(l(0,"span",29),u(1,"bolt"),d(),l(2,"span"),u(3,"Test Connection"),d())}function QI(n,t){if(n&1&&(l(0,"div",311)(1,"span",29),u(2,"check_circle"),d(),l(3,"span"),u(4),d()()),n&2){let e=m(4);g(4),O(e.remoteAdbMessage())}}function JI(n,t){if(n&1&&(l(0,"div",312)(1,"span",29),u(2,"error"),d(),l(3,"span"),u(4),d()()),n&2){let e=m(4);g(4),O(e.remoteAdbError())}}function XI(n,t){if(n&1&&(l(0,"div",316)(1,"span",29),u(2,"phone_android"),d(),l(3,"div",317)(4,"strong"),u(5),d(),l(6,"span"),u(7),d()(),l(8,"span",318),u(9),d()()),n&2){let e=t.$implicit;g(5),O(e.model||e.serial),g(2),O(e.serial),g(),w("ready",e.state==="device"),g(),V(" ",e.state==="device"?"Ready":e.state," ")}}function eT(n,t){if(n&1&&(l(0,"div",313),G(1,XI,10,5,"div",316,Pm),d()),n&2){let e=m(4);g(),q(e.remoteAdbDevices())}}function tT(n,t){n&1&&(l(0,"span",147),u(1,"sync"),d(),l(2,"span"),u(3,"Connecting..."),d())}function nT(n,t){if(n&1&&(l(0,"span",29),u(1,"check"),d(),l(2,"span"),u(3),d()),n&2){let e=m(5);g(3),O(e.remoteAdbHasReadyDevice()?"Use Connection":"Use Anyway")}}function oT(n,t){if(n&1){let e=L();l(0,"button",319),k("click",function(){v(e);let i=m(4);return y(i.activateRemoteAdbServer())}),M(1,tT,4,0)(2,nT,4,1),d()}if(n&2){let e=m(4);R("disabled",e.isActivatingRemoteAdb()),g(),b(e.isActivatingRemoteAdb()?1:2)}}function iT(n,t){if(n&1){let e=L();l(0,"div",233)(1,"div",297)(2,"span",278),u(3,"hub"),d(),l(4,"span"),u(5,"Enter the host and port of an ADB server endpoint that this computer can access, so Artemis can discover and control a phone physically connected to another computer."),d()(),l(6,"div",298)(7,"div",299)(8,"div",300)(9,"label",301),u(10,"ADB Server Host"),d(),l(11,"div",302)(12,"span",286),u(13,"dns"),d(),l(14,"input",303),k("ngModelChange",function(i){v(e);let r=m(3);return y(r.updateRemoteAdbHost(i))}),d(),Rt(),d()(),l(15,"div",304)(16,"label",305),u(17,"ADB Server Port"),d(),l(18,"div",302)(19,"span",286),u(20,"tag"),d(),l(21,"input",306),k("ngModelChange",function(i){v(e);let r=m(3);return y(r.updateRemoteAdbPort(i))}),d(),Rt(),d()(),l(22,"div",307)(23,"button",308),k("click",function(){v(e);let i=m(3);return y(i.connectRemoteAdbServer())}),M(24,YI,4,0)(25,ZI,4,0),d()()(),l(26,"label",309)(27,"input",310),k("ngModelChange",function(i){v(e);let r=m(3);return y(r.rememberRemoteAdb.set(i))}),d(),Rt(),l(28,"span"),u(29,"Remember this endpoint for future Artemis launches"),d()(),M(30,QI,5,1,"div",311),M(31,JI,5,1,"div",312),M(32,eT,3,0,"div",313),M(33,oT,3,2,"button",314),d(),l(34,"p",315),u(35," Artemis sends all ADB commands to this server instead of the default local server. Any phone visible to that server becomes available to Artemis. "),d()()}if(n&2){let e=m(3);g(14),R("ngModel",e.remoteAdbHost()),Ft(),g(7),R("ngModel",e.remoteAdbPort()),Ft(),g(2),R("disabled",e.isConnectingRemoteAdb()||e.isActivatingRemoteAdb()||!e.remoteAdbHost().trim()),g(),b(e.isConnectingRemoteAdb()?24:25),g(3),R("ngModel",e.rememberRemoteAdb()),Ft(),g(3),b(e.remoteAdbMessage()?30:-1),g(),b(e.remoteAdbError()?31:-1),g(),b(e.remoteAdbDevices().length>0?32:-1),g(),b(e.remoteAdbProbeResult()?.success&&!e.isProbedRemoteAdbActive()?33:-1)}}function rT(n,t){if(n&1){let e=L();l(0,"div",67)(1,"div",221)(2,"button",222),k("click",function(){v(e);let i=m(2);return y(i.setAdbGuideTab("emulator"))}),l(3,"div",223)(4,"div",224)(5,"span",29),u(6,"smartphone"),d()(),l(7,"div",225)(8,"div",226)(9,"span",227),u(10,"Android Emulator"),d()(),l(11,"span",228),M(12,TI,1,2)(13,AI,1,0),d()()(),l(14,"div",229),$(15,"span",230),d()(),l(16,"button",222),k("click",function(){v(e);let i=m(2);return y(i.setAdbGuideTab("usb"))}),l(17,"div",223)(18,"div",224)(19,"span",29),u(20,"usb"),d()(),l(21,"div",225)(22,"div",226)(23,"span",227),u(24,"USB Cable"),d()(),l(25,"span",228),u(26,"Connect physical phone via USB"),d()()(),l(27,"div",229),$(28,"span",230),d()(),l(29,"button",222),k("click",function(){v(e);let i=m(2);return y(i.setAdbGuideTab("wifi"))}),l(30,"div",223)(31,"div",224)(32,"span",29),u(33,"wifi"),d()(),l(34,"div",225)(35,"div",226)(36,"span",227),u(37,"Wireless ADB"),d()(),l(38,"span",228),u(39,"Connect over local Wi-Fi"),d()()(),l(40,"div",229),$(41,"span",230),d()(),l(42,"button",222),k("click",function(){v(e);let i=m(2);return y(i.setAdbGuideTab("remote"))}),l(43,"div",223)(44,"div",224)(45,"span",29),u(46,"devices"),d()(),l(47,"div",225)(48,"div",226)(49,"span",227),u(50,"Remote Computer"),d()(),l(51,"span",228),u(52,"Phone connected to another computer"),d()()(),l(53,"div",229),$(54,"span",230),d()()(),M(55,NI,14,6,"div",231),M(56,BI,3,1,"div",232),M(57,HI,65,0,"div",232),M(58,KI,36,6,"div",232),M(59,iT,36,9,"div",233),d()}if(n&2){let e=m(2);g(2),w("active",e.activeAdbGuideTab()==="emulator"),g(10),b(e.installedAvds().length>0?12:13),g(3),w("checked",e.activeAdbGuideTab()==="emulator"),g(),w("active",e.activeAdbGuideTab()==="usb"),g(12),w("checked",e.activeAdbGuideTab()==="usb"),g(),w("active",e.activeAdbGuideTab()==="wifi"),g(12),w("checked",e.activeAdbGuideTab()==="wifi"),g(),w("active",e.activeAdbGuideTab()==="remote"),g(12),w("checked",e.activeAdbGuideTab()==="remote"),g(),b(e.activeAdbGuideTab()!=="remote"&&e.isRemoteAdbServer()?55:-1),g(),b(e.activeAdbGuideTab()==="emulator"?56:-1),g(),b(e.activeAdbGuideTab()==="usb"?57:-1),g(),b(e.activeAdbGuideTab()==="wifi"?58:-1),g(),b(e.activeAdbGuideTab()==="remote"?59:-1)}}function aT(n,t){n&1&&(l(0,"span",167),u(1,"\u2713 Active"),d())}function sT(n,t){if(n&1){let e=L();l(0,"button",165),k("click",function(){let i=v(e).$implicit,r=m(4);return y(r.selectTargetDevice(i.serial))}),l(1,"span",166),u(2," phone_android "),d(),l(3,"span"),u(4),d(),M(5,aT,2,0,"span",167),d()}if(n&2){let e=t.$implicit,o=m(4);w("selected",e.serial===o.activeDevice()?.serial),g(4),O(e.model||e.serial),g(),b(e.serial===o.activeDevice()?.serial?5:-1)}}function cT(n,t){if(n&1&&(l(0,"div",326)(1,"span",162),u(2,"Select Active Device:"),d(),l(3,"div",163),G(4,sT,6,4,"button",164,Pm),d()()),n&2){let e=m(3);g(4),q(e.connectedDevices())}}function lT(n,t){if(n&1){let e=L();l(0,"div",68)(1,"div",320)(2,"span",321),u(3,"lock"),d(),l(4,"div",322)(5,"div",323),u(6),d(),l(7,"div",324),u(8),d()(),l(9,"button",325),k("click",function(){v(e);let i=m(2);return y(i.refreshReadiness())}),l(10,"span",29),u(11,"refresh"),d(),l(12,"span"),u(13),d()()(),M(14,cT,6,0,"div",326),d()}if(n&2){let e=m(2);g(6),V(" ",e.adbProbe()?.summary==="Device Locked"?"Device Is Locked":"Unable to Verify Lock State"," "),g(2),V(" ",e.adbProbe()?.description," "),g(),R("disabled",e.isRefreshingDiagnostics()),g(),w("spinning",e.isRefreshingDiagnostics()),g(3),O(e.isRefreshingDiagnostics()?"Checking...":"Check Again"),g(),b(e.connectedDevices().length>1?14:-1)}}function dT(n,t){if(n&1){let e=L();l(0,"div",69)(1,"div",327)(2,"span",321),u(3,"screen_lock_portrait"),d(),l(4,"div",328)(5,"div",329),u(6,"USB Debugging Authorization Pending"),d(),l(7,"div",330),u(8," Your Android device was detected, but it requires authorization. Please unlock your phone screen and tap "),l(9,"strong"),u(10,'"Allow USB Debugging"'),d(),u(11,". "),d()(),l(12,"button",331),k("click",function(){v(e);let i=m(2);return y(i.restartAdbServer())}),l(13,"span",29),u(14,"refresh"),d(),l(15,"span"),u(16),d()()()()}if(n&2){let e=m(2);g(16),O(e.isRemoteAdbServer()?"Refresh Devices":"Restart ADB & Check")}}function uT(n,t){n&1&&(l(0,"span",337),u(1,"Detected"),d())}function gT(n,t){n&1&&(l(0,"span",337),u(1,"Detected"),d())}function pT(n,t){n&1&&(l(0,"span",337),u(1,"Detected"),d())}function fT(n,t){if(n&1){let e=L();l(0,"div",70)(1,"div",332)(2,"span",333),u(3,"error"),d(),l(4,"div")(5,"strong"),u(6,"Android Platform Tools (adb) not found."),d(),u(7," Please install ADB on your operating system: "),d()(),l(8,"div",334)(9,"div",335)(10,"div",336)(11,"span"),u(12,"Linux (Ubuntu / Debian)"),d(),M(13,uT,2,0,"span",337),d(),l(14,"div",81)(15,"span",84),u(16,"$"),d(),l(17,"code",85),u(18,"sudo apt-get install -y adb"),d(),l(19,"button",82),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard("sudo apt-get install -y adb","linux_adb"))}),l(20,"span",29),u(21),d(),l(22,"span"),u(23),d()()()(),l(24,"div",335)(25,"div",336)(26,"span"),u(27,"macOS (Homebrew)"),d(),M(28,gT,2,0,"span",337),d(),l(29,"div",81)(30,"span",84),u(31,"$"),d(),l(32,"code",85),u(33,"brew install android-platform-tools"),d(),l(34,"button",82),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard("brew install android-platform-tools","mac_adb"))}),l(35,"span",29),u(36),d(),l(37,"span"),u(38),d()()()(),l(39,"div",335)(40,"div",336)(41,"span"),u(42,"Windows (WinGet)"),d(),M(43,pT,2,0,"span",337),d(),l(44,"div",81)(45,"span",84),u(46,">"),d(),l(47,"code",85),u(48,"winget install Google.PlatformTools"),d(),l(49,"button",82),k("click",function(){v(e);let i=m(2);return y(i.copyToClipboard("winget install Google.PlatformTools","win_adb"))}),l(50,"span",29),u(51),d(),l(52,"span"),u(53),d()()()()()()}if(n&2){let e=m(2);g(9),w("highlight-os",e.effectiveOs()==="linux"),g(4),b(e.effectiveOs()==="linux"?13:-1),g(6),w("copied",e.copiedId()==="linux_adb"),g(2),O(e.copiedId()==="linux_adb"?"check":"content_copy"),g(2),O(e.copiedId()==="linux_adb"?"Copied!":"Copy"),g(),w("highlight-os",e.effectiveOs()==="darwin"),g(4),b(e.effectiveOs()==="darwin"?28:-1),g(6),w("copied",e.copiedId()==="mac_adb"),g(2),O(e.copiedId()==="mac_adb"?"check":"content_copy"),g(2),O(e.copiedId()==="mac_adb"?"Copied!":"Copy"),g(),w("highlight-os",e.effectiveOs()==="windows"),g(4),b(e.effectiveOs()==="windows"?43:-1),g(6),w("copied",e.copiedId()==="win_adb"),g(2),O(e.copiedId()==="win_adb"?"check":"content_copy"),g(2),O(e.copiedId()==="win_adb"?"Copied!":"Copy")}}function mT(n,t){if(n&1){let e=L();l(0,"div",71)(1,"div",338)(2,"div",339)(3,"span",23),u(4,"check"),d()(),l(5,"div",340)(6,"h4",341),u(7,"System Ready for Autonomous Tasks"),d(),l(8,"p",342),u(9,"All dependencies, AI model credentials, and Android device are verified and ready to run."),d()()(),l(10,"button",343),k("click",function(){v(e);let i=m(2);return y(i.setTab("launcher"))}),l(11,"span"),u(12,"Launch Autonomous Task"),d(),l(13,"span",344),u(14,"rocket_launch"),d()()()}}function _T(n,t){if(n&1){let e=L();l(0,"section",18)(1,"div",20)(2,"div",21)(3,"div",22),M(4,vD,2,0,"span",23)(5,yD,2,0,"span"),d(),l(6,"div",24)(7,"div",25)(8,"h3",26),u(9,"System & Environment"),d()(),l(10,"p",27),u(11,"Core tools, Android debug bridge, and video recording runtime"),d()(),l(12,"button",28),k("click",function(){v(e);let i=m();return y(i.refreshReadiness())}),l(13,"span",29),u(14,"refresh"),d(),l(15,"span"),u(16),d()()(),l(17,"div",30),M(18,xD,26,11,"div",31),l(19,"div",32)(20,"div",33)(21,"div",34)(22,"div",35)(23,"span",36),u(24,"terminal"),d()(),l(25,"div",37)(26,"div",38),u(27,"Python Runtime"),d(),l(28,"div",39),u(29),d()(),l(30,"div",40),$(31,"span",41),d()(),M(32,wD,12,4,"div",42),d(),l(33,"div",33)(34,"div",34)(35,"div",35)(36,"span",36),u(37,"construction"),d()(),l(38,"div",37)(39,"div",38),u(40,"Android Platform-Tools"),d(),l(41,"div",39),u(42),d()(),l(43,"div",40),$(44,"span",41),d()(),M(45,SD,12,5,"div",42),d(),l(46,"div",33)(47,"div",34)(48,"div",35)(49,"span",36),u(50,"tune"),d()(),l(51,"div",37)(52,"div",38),u(53,"System Configuration"),d(),l(54,"div",39),u(55),d()(),l(56,"div",40),$(57,"span",41),d()(),M(58,kD,12,4,"div",42),d(),l(59,"div",33)(60,"div",34)(61,"div",35)(62,"span",36),u(63,"videocam"),d()(),l(64,"div",37)(65,"div",38),u(66,"Video Toolchain"),d(),l(67,"div",39),u(68),d()(),l(69,"div",40),$(70,"span",41),d()(),M(71,ED,12,5,"div",42),d()()()(),l(72,"div",20)(73,"div",21)(74,"div",22),M(75,DD,2,0,"span",23)(76,ID,2,0,"span"),d(),l(77,"div",24)(78,"div",25)(79,"h3",26),u(80,"AI Model Setup"),d()(),l(81,"p",27),u(82,"Google Gemini or custom LLM providers (OpenAI, Claude, Ollama)"),d()()(),l(83,"div",30)(84,"div",43)(85,"div",44),k("click",function(){v(e);let i=m();return y(i.setModelSetupMode("gemini"))}),l(86,"div",45)(87,"div",46),$(88,"span",47),d(),l(89,"div",48),yo(),l(90,"svg",49)(91,"defs")(92,"linearGradient",50),$(93,"stop",51)(94,"stop",52)(95,"stop",53),d()(),$(96,"path",54),d()(),rr(),l(97,"div",55)(98,"div",56)(99,"span",57),u(100,"Google Gemini"),d(),l(101,"span",58),u(102,"Recommended"),d()(),l(103,"p",59),u(104,"Fast multimodal reasoning with free API key from Google AI Studio."),d()()()(),l(105,"div",44),k("click",function(){v(e);let i=m();return y(i.setModelSetupMode("custom"))}),l(106,"div",45)(107,"div",46),$(108,"span",47),d(),l(109,"div",60)(110,"span",29),u(111,"tune"),d()(),l(112,"div",55)(113,"div",56)(114,"span",57),u(115,"Custom Configuration"),d()(),l(116,"p",59),u(117,"Define models in "),l(118,"code"),u(119,"config/artemis.jsonc"),d(),u(120," & keys in "),l(121,"code"),u(122,".env"),d(),u(123," (OpenAI, Claude, Ollama)."),d()()()()(),M(124,KD,42,18)(125,tI,58,15,"div",61),d()(),l(126,"div",20)(127,"div",21)(128,"div",22),M(129,nI,2,0,"span",23)(130,oI,2,0,"span"),d(),l(131,"div",24)(132,"div",25)(133,"h3",26),u(134,"Android Device & Emulator Connection"),d()(),l(135,"p",27),u(136,"Local emulator, attached phone, wireless device, or another ADB server"),d()(),l(137,"button",62),k("click",function(){v(e);let i=m();return y(i.toggleConnectionMethods())}),l(138,"span",29),u(139,"swap_horiz"),d(),l(140,"span"),u(141),d()(),l(142,"button",63),k("click",function(){v(e);let i=m();return y(i.restartAdbServer())}),M(143,iI,4,0)(144,rI,4,1)(145,aI,4,1),d()(),l(146,"div",30),M(147,fI,20,7,"div",64),M(148,SI,74,34,"div",65),M(149,II,26,3,"div",66),M(150,rT,60,22,"div",67),M(151,lT,15,7,"div",68),M(152,dT,17,1,"div",69),M(153,fT,54,21,"div",70),d()(),M(154,mT,15,0,"div",71),d()}if(n&2){let e=m();g(),w("card-pass",e.isEnvironmentReady())("card-warn",!e.isEnvironmentReady()),g(2),w("step-pass",e.isEnvironmentReady()),g(),b(e.isEnvironmentReady()?4:5),g(8),R("disabled",e.isRefreshingDiagnostics()),g(),w("spinning",e.isRefreshingDiagnostics()),g(3),O(e.isRefreshingDiagnostics()?"Checking...":"Re-check"),g(2),b(e.hasReadinessReport()&&!e.isEnvironmentReady()?18:-1),g(2),w("item-pass",e.pythonProbe()?.status==="pass")("item-fail",e.pythonProbe()?.status==="fail"),g(9),O(e.pythonProbe()?.summary||"Checking\u2026"),g(2),w("dot-pass",e.pythonProbe()?.status==="pass")("dot-fail",e.pythonProbe()?.status==="fail"),g(),b(e.pythonProbe()?.status==="fail"?32:-1),g(),w("item-pass",e.adbProbe()?.metadata?.installed)("item-fail",e.adbProbe()?.status==="fail"),g(9),O(e.adbProbe()?e.adbProbe()?.metadata?.installed?"ADB Installed":"ADB Missing":"Checking\u2026"),g(2),w("dot-pass",e.adbProbe()?.metadata?.installed)("dot-fail",e.adbProbe()?.status==="fail"),g(),b(e.adbProbe()?.status==="fail"?45:-1),g(),w("item-pass",e.configProbe()?.status==="pass")("item-fail",e.configProbe()?.status==="fail"),g(9),O(e.configProbe()?.summary||"Config Valid"),g(2),w("dot-pass",e.configProbe()?.status==="pass")("dot-fail",e.configProbe()?.status==="fail"),g(),b(e.configProbe()?.status==="fail"?58:-1),g(),w("item-pass",e.toolchainProbe()?.status==="pass")("item-fail",e.toolchainProbe()?.status!=="pass"),g(9),O(e.toolchainProbe()?.summary||"FFmpeg & scrcpy"),g(2),w("dot-pass",e.toolchainProbe()?.status==="pass")("dot-fail",e.toolchainProbe()?.status!=="pass"),g(),b(e.toolchainProbe()?.status!=="pass"?71:-1),g(),w("card-pass",e.isCredentialsReady())("card-warn",!e.isCredentialsReady()),g(2),w("step-pass",e.isCredentialsReady()),g(),b(e.isCredentialsReady()?75:76),g(10),w("selected",e.modelSetupMode()==="gemini"),g(3),w("checked",e.modelSetupMode()==="gemini"),g(17),w("selected",e.modelSetupMode()==="custom"),g(3),w("checked",e.modelSetupMode()==="custom"),g(16),b(e.modelSetupMode()==="gemini"?124:125),g(2),w("card-pass",e.isDeviceReady())("card-warn",!e.isDeviceReady()),g(2),w("step-pass",e.isDeviceReady()),g(),b(e.isDeviceReady()?129:130),g(12),O(e.showConnectionMethods()?"Hide Options":"Change Connection"),g(),R("disabled",e.isRestartingAdb())("title",e.isRemoteAdbServer()?"Refresh devices without stopping the remote ADB server":"Restart local ADB daemon"),g(),b(e.isRestartingAdb()?143:e.adbRestartFeedback()?144:145),g(4),b(e.isDeviceReady()?147:-1),g(),b(e.isEmulatorLaunching()||!e.isDeviceReady()&&e.adbProbe()?.summary==="Device Booting"?148:-1),g(),b(!e.isDeviceReady()&&!e.isEmulatorLaunching()&&e.emulatorLaunchState()?.status==="failed"?149:-1),g(),b(e.showConnectionMethods()||!e.isDeviceReady()&&!e.isEmulatorLaunching()&&e.adbProbe()?.summary!=="Device Booting"&&e.adbProbe()?.summary!=="Device Unauthorized"&&e.adbProbe()?.summary!=="Device Locked"&&e.adbProbe()?.summary!=="Lock State Unknown"&&e.adbProbe()?.status!=="fail"&&e.emulatorLaunchState()?.status!=="failed"?150:-1),g(),b(e.adbProbe()?.status==="warn"&&(e.adbProbe()?.summary==="Device Locked"||e.adbProbe()?.summary==="Lock State Unknown")?151:-1),g(),b(e.adbProbe()?.status==="warn"&&e.adbProbe()?.summary==="Device Unauthorized"?152:-1),g(),b(e.adbProbe()?.status==="fail"?153:-1),g(),b(e.isReady()?154:-1)}}function hT(n,t){if(n&1){let e=L();l(0,"div",381),k("click",function(){v(e);let i=m(2);return y(i.setTab("diagnostics"))}),l(1,"span",382),u(2),d(),l(3,"span"),u(4),d(),l(5,"span",383),u(6,"arrow_forward"),d()()}if(n&2){let e=m(2);g(2),O(e.adbProbe()?.summary==="Device Locked"?"lock":"warning"),g(2),V(" ",e.adbProbe()?.summary==="Device Locked"?"Android device is locked. Unlock it and enter the home screen before running a task.":"Prerequisites incomplete: runtime, credentials, or Android device is not ready. Click here to open Setup Guide."," ")}}function CT(n,t){if(n&1){let e=L();l(0,"div",347)(1,"div",384)(2,"span",385),u(3,"auto_awesome"),d(),l(4,"span",386),u(5," Continuous monitoring or complex task detected. Recommended: "),l(6,"strong"),u(7,"Pro Mode"),d()()(),l(8,"button",387),k("click",function(){v(e);let i=m(2);return y(i.setProfile("pro"))}),l(9,"span"),u(10,"Switch to Pro"),d(),l(11,"span",388),u(12,"arrow_forward"),d()()()}}function MT(n,t){n&1&&(l(0,"p",353)(1,"span",389),u(2,"Flash"),d(),l(3,"span",390),u(4,"\xB7"),d(),l(5,"span"),u(6,"Token-efficient, rapid "),l(7,"strong"),u(8,"3\u20135s/step"),d(),u(9," decisions straight from the live screen. Best for everyday tasks with a clear path, however long they run."),d(),l(10,"span",391),u(11,"(No plan, no result check, no ADB commands)"),d()())}function bT(n,t){n&1&&(l(0,"p",353)(1,"span",389),u(2,"Pro"),d(),l(3,"span",390),u(4,"\xB7"),d(),l(5,"span"),u(6,"Our most powerful mode. Plans first, checks its own results and recovers when a tap is blocked. Handles "),l(7,"strong"),u(8,"100+ step"),d(),u(9," workflows and live phone monitoring ("),l(10,"strong"),u(11,"15\u201340s"),d(),u(12," / step)."),d()())}function PT(n,t){if(n&1&&(l(0,"div",354)(1,"span",392),u(2,"error"),d(),l(3,"span"),u(4),d()()),n&2){let e=m(2);g(4),O(e.errorMessage())}}function OT(n,t){if(n&1&&(l(0,"span",363),u(1),d()),n&2){let e=m(2);g(),V("",e.taskGoal().length," chars")}}function vT(n,t){n&1&&($(0,"span",393),l(1,"span"),u(2,"Starting..."),d())}function yT(n,t){n&1&&(l(0,"span",394),u(1,"play_arrow"),d(),l(2,"span"),u(3,"Run Task"),d())}function xT(n,t){if(n&1){let e=L();l(0,"button",408),k("click",function(){v(e);let i=m(3);return y(i.expectedOutput.set(""))}),l(1,"span",29),u(2,"close"),d()()}}function wT(n,t){if(n&1){let e=L();l(0,"button",409),k("click",function(){v(e);let i=m(3);return y(i.resetTuning())}),u(1,"Reset"),d()}}function ST(n,t){if(n&1&&$(0,"span",422),n&2){let e=t.$index,o=m().$implicit,i=m(3);Se("--%NS%n",i.notchFraction(e,o.ladder.length)),w("reached",e<=o.index)}}function kT(n,t){if(n&1&&(yo(),$(0,"rect",426)),n&2){let e=t.$implicit;Se("opacity",e.opacity)("animation-delay",e.delay,"ms"),Wt("x",e.x+"%")("y",e.y)}}function ET(n,t){if(n&1&&($(0,"div",423),yo(),l(1,"svg",424),G(2,kT,1,6,":svg:rect",425,Do),d()),n&2){let e=m(4);g(2),q(e.ditherPixels)}}function DT(n,t){n&1&&$(0,"span",420)}function IT(n,t){if(n&1&&(l(0,"li"),u(1),d()),n&2){let e=t.$implicit;g(),O(e)}}function TT(n,t){if(n&1&&(l(0,"li"),u(1),d()),n&2){let e=t.$implicit;g(),O(e)}}function AT(n,t){if(n&1&&(l(0,"div",435)(1,"span",434),u(2,"Not included"),d(),l(3,"ul"),G(4,TT,2,1,"li",null,Do),d()()),n&2){let e=m(2).$implicit;g(4),q(e.level.skips)}}function NT(n,t){if(n&1&&($(0,"div",427),l(1,"div",428)(2,"div",429)(3,"span",430),u(4),d(),l(5,"span",431),u(6),d()(),l(7,"p",432),u(8),d(),l(9,"div",433)(10,"span",434),u(11,"What happens"),d(),l(12,"ul"),G(13,IT,2,1,"li",null,Do),d()(),M(15,AT,6,0,"div",435),l(16,"div",436)(17,"span",434),u(18,"Use it for"),d(),l(19,"span"),u(20),d()()()),n&2){let e=m().$implicit;g(4),O(e.level.label),g(2),O(e.level.latency),g(2),O(e.level.tagline),g(5),q(e.level.runs),g(2),b(e.level.skips?.length?15:-1),g(5),O(e.level.bestFor)}}function RT(n,t){if(n&1){let e=L();l(0,"div",410)(1,"div",411)(2,"span",412),u(3),d(),l(4,"span",413),u(5),d()(),l(6,"div",414)(7,"span"),u(8),d(),l(9,"span"),u(10),d()(),l(11,"div",415),k("pointerenter",function(){let i=v(e).$implicit,r=m(3);return y(r.showTuningTip(i.kind))})("pointerleave",function(){let i=v(e).$implicit,r=m(3);return y(r.hideTuningTip(i.kind))}),l(12,"div",416),$(13,"div",417),G(14,ST,1,4,"span",418,qP),M(16,ET,4,0),d(),$(17,"div",419),M(18,DT,1,0,"span",420),l(19,"input",421),k("input",function(i){let r=v(e).$implicit,a=m(3);return y(a.setTuningIndex(r.kind,i.target.value))})("focus",function(){let i=v(e).$implicit,r=m(3);return y(r.showTuningTip(i.kind))})("blur",function(){let i=v(e).$implicit,r=m(3);return y(r.hideTuningTip(i.kind))}),d(),M(20,NT,21,5),d()()}if(n&2){let e=t.$implicit,o=m(3);Se("--%NS%pct",e.fraction),w("verify",e.kind==="verify")("explore",e.kind==="explore")("dragging",o.activeTuningTip()===e.kind),g(3),O(e.name),g(2),O(e.level.label),g(3),O(e.ends[0]),g(2),O(e.ends[1]),g(4),q(e.ladder),g(2),b(e.index===e.ladder.length-1?16:-1),g(2),b(e.index===e.ladder.length-1?18:-1),g(),R("max",e.ladder.length-1)("value",e.index),Wt("aria-label",e.name)("aria-valuetext",e.level.label+": "+e.level.tagline),g(),b(o.activeTuningTip()===e.kind?20:-1)}}function FT(n,t){if(n&1){let e=L();l(0,"div",395)(1,"div",396)(2,"span",397),u(3,"Expected Output"),d(),l(4,"span",398),u(5,"(Optional)"),d()(),l(6,"div",399)(7,"input",400),k("ngModelChange",function(i){v(e);let r=m(2);return y(r.expectedOutput.set(i))}),d(),Rt(),M(8,xT,3,0,"button",401),d()(),l(9,"div",402)(10,"div",403)(11,"span",404),u(12,"Pro settings"),d(),M(13,wT,2,0,"button",405),d(),l(14,"div",406),G(15,RT,21,19,"div",407,CD),d()()}if(n&2){let e=m(2);g(7),R("ngModel",e.expectedOutput()),Ft(),g(),b(e.expectedOutput().trim()?8:-1),g(),w("tip-open",e.activeTuningTip()!==null),g(4),b(e.isTuningDefault()?-1:13),g(2),q(e.tuningSliders())}}function LT(n,t){if(n&1&&(l(0,"div",440)(1,"span",29),u(2),d()()),n&2){let e=t.$implicit;R("title",e.name),g(2),O(e.icon)}}function VT(n,t){if(n&1){let e=L();l(0,"div",437),k("click",function(){let i=v(e).$implicit,r=m(2);return y(r.applySuggestion(i))}),l(1,"div",438)(2,"div",439),G(3,LT,3,2,"div",440,GP),l(5,"span",441),u(6),d()(),l(7,"span",442),u(8),d()(),l(9,"div",443)(10,"h4",444),u(11),d(),l(12,"p",445),u(13),d()(),l(14,"div",446)(15,"span",447),u(16),d(),l(17,"div",448)(18,"span"),u(19,"Use"),d(),l(20,"span",449),u(21,"arrow_forward"),d()()()()}if(n&2){let e=t.$implicit,o=m(2);w("is-pro-card",e.profile==="pro")("is-flash-card",e.profile==="flash"),g(3),q(e.apps),g(3),O(o.getAppNamesDisplay(e.apps)),g(),w("mode-pro",e.profile==="pro")("mode-flash",e.profile==="flash"),R("title",e.profile==="pro"?"Uses ARTEMIS Pro (Multi-Agent Cognitive State Graph)":"Uses ARTEMIS Flash (Reactive Fast Loop)"),g(),V(" ",e.profile==="pro"?"Pro":"Flash"," "),g(3),O(e.title),g(2),O(e.description),g(3),O(e.tag)}}function jT(n,t){if(n&1){let e=L();l(0,"section",19),M(1,hT,7,2,"div",345),l(2,"div",346),M(3,CT,13,0,"div",347),l(4,"div",348)(5,"textarea",349),hr("ngModelChange",function(i){v(e);let r=m();return $a(r.taskGoal,i)||(r.taskGoal=i),y(i)}),k("keydown.control.enter",function(){v(e);let i=m();return y(i.runTask())})("keydown.meta.enter",function(){v(e);let i=m();return y(i.runTask())}),d(),Rt(),d(),l(6,"div",350)(7,"div",351)(8,"span",29),u(9),d()(),l(10,"div",352),M(11,MT,12,0,"p",353)(12,bT,13,0,"p",353),d()(),M(13,PT,5,1,"div",354),l(14,"div",355)(15,"div",356)(16,"div",357)(17,"button",358),k("click",function(){v(e);let i=m();return y(i.setProfile("flash"))}),l(18,"span",359),u(19,"bolt"),d(),l(20,"span",360),u(21,"Flash"),d()(),l(22,"button",361),k("click",function(){v(e);let i=m();return y(i.setProfile("pro"))}),l(23,"span",359),u(24,"psychology"),d(),l(25,"span",360),u(26,"Pro"),d()()()(),l(27,"div",362),M(28,OT,2,1,"span",363),l(29,"button",364),k("click",function(){v(e);let i=m();return y(i.runTask())}),M(30,vT,3,0)(31,yT,4,0),d()()()(),M(32,FT,17,5),l(33,"div",365)(34,"div",366)(35,"div",367)(36,"div",368)(37,"span",369),u(38,"auto_awesome"),d(),l(39,"span",370),u(40,"Recommended Tasks"),d()(),l(41,"div",371)(42,"button",372),k("click",function(){v(e);let i=m();return y(i.setCategory("all"))}),l(43,"span"),u(44,"All"),d()(),l(45,"button",373),k("click",function(){v(e);let i=m();return y(i.setCategory("flash"))}),l(46,"span",374),u(47,"bolt"),d(),l(48,"span"),u(49,"Flash"),d()(),l(50,"button",375),k("click",function(){v(e);let i=m();return y(i.setCategory("pro"))}),l(51,"span",374),u(52,"psychology"),d(),l(53,"span"),u(54,"Pro"),d()(),l(55,"button",372),k("click",function(){v(e);let i=m();return y(i.setCategory("cross_app"))}),l(56,"span",374),u(57,"sync_alt"),d(),l(58,"span"),u(59,"Multi-App"),d()(),l(60,"button",372),k("click",function(){v(e);let i=m();return y(i.setCategory("monitor"))}),l(61,"span",374),u(62,"monitoring"),d(),l(63,"span"),u(64,"Monitor"),d()()()(),l(65,"div",376)(66,"button",377),k("click",function(){v(e);let i=m();return y(i.shuffleSuggestions())}),l(67,"span",378),u(68,"shuffle"),d(),l(69,"span"),u(70,"Shuffle"),d()()()(),l(71,"div",379),G(72,VT,22,14,"div",380,qP),d()()()}if(n&2){let e=m();g(),b(e.hasReadinessReport()&&!e.isReady()?1:-1),g(),w("is-pro-active",e.selectedProfile()==="pro"),g(),b(e.showIntentSuggestion()?3:-1),g(2),_r("ngModel",e.taskGoal),R("disabled",e.isSubmitting()),Ft(),g(),w("is-pro",e.selectedProfile()==="pro"),g(3),O(e.selectedProfile()==="flash"?"bolt":"psychology"),g(2),b(e.selectedProfile()==="flash"?11:12),g(2),b(e.errorMessage()?13:-1),g(4),w("active",e.selectedProfile()==="flash"),g(5),w("active",e.selectedProfile()==="pro"),g(6),b(e.taskGoal().length>0?28:-1),g(),w("btn-run-pro",e.selectedProfile()==="pro"),R("disabled",!e.taskGoal().trim()||e.isSubmitting()||!e.isReady())("title",e.isReady()?"Run task":e.adbProbe()?.summary==="Device Locked"?"Unlock the Android device before running":"Complete System Setup before running"),g(),b(e.isSubmitting()?30:31),g(2),b(e.selectedProfile()==="pro"?32:-1),g(10),w("active",e.selectedCategory()==="all"),g(3),w("active",e.selectedCategory()==="flash"),g(5),w("active",e.selectedCategory()==="pro"),g(5),w("active",e.selectedCategory()==="cross_app"),g(5),w("active",e.selectedCategory()==="monitor"),g(12),q(e.filteredSuggestions())}}function $T(n=260,t=7){let e=t>>>0,o=()=>(e=Math.imul(e,1664525)+1013904223>>>0,e/4294967296),i=[];for(let r=0;rthis.systemService.modelConfigEnv());geminiKeyInput=x("");showGeminiKey=x(!1);isSavingGeminiKey=x(!1);isTestingGeminiKey=x(!1);geminiSaveMessage=x(null);geminiSaveError=x(null);isGeminiKeyEdited=x(!1);ocrKeyInput=x("");showOcrKey=x(!1);isSavingOcrKey=x(!1);isTestingOcrKey=x(!1);ocrSaveMessage=x(null);ocrSaveError=x(null);isOcrKeyEdited=x(!1);copiedId=x(null);isRefreshingDiagnostics=x(!1);wifiHost=x("192.168.1.100");wifiPort=x("5555");isConnectingWifi=x(!1);wifiConnectMessage=x(null);wifiConnectError=x(null);adbRestartFeedback=x(null);showConnectionMethods=x(!1);remoteAdbHost=x("127.0.0.1");remoteAdbPort=x("5038");rememberRemoteAdb=x(!0);isConnectingRemoteAdb=x(!1);isActivatingRemoteAdb=x(!1);isSwitchingToLocalAdb=x(!1);remoteAdbMessage=x(null);remoteAdbError=x(null);remoteAdbDevices=x([]);remoteAdbProbeResult=x(null);adbServerStatus=I(()=>this.systemService.adbServerStatus());isRemoteAdbServer=I(()=>this.systemService.isRemoteAdbServer());remoteAdbHasReadyDevice=I(()=>this.remoteAdbDevices().some(t=>t.state==="device"));isProbedRemoteAdbActive=I(()=>{let t=this.remoteAdbProbeResult()?.endpoint,e=this.adbServerStatus()?.endpoint;return!!t&&!!e&&t.identity===e.identity});wifiCommand=I(()=>{let t=this.wifiHost().trim()||"",e=this.wifiPort().trim()||"5555";return`adb connect ${t}:${e}`});selectedProfile=x("flash");taskGoal=x("");isSubmitting=x(!1);errorMessage=x(null);expectedOutput=x("");enableOutputter=x(!0);showOutputterDrawer=x(!1);verificationLevels=_n;explorerModes=hn;verificationIndex=x(Li(_n,Hr,Hr));explorerIndex=x(Li(hn,Ur,Ur));tuningDefaults=x({verification:Hr,explorer:Ur});tuningTouched=x(!1);activeTuningTip=x(null);ditherPixels=$T();verificationLevel=I(()=>_n[this.verificationIndex()]);explorerMode=I(()=>hn[this.explorerIndex()]);isTuningDefault=I(()=>{let t=this.tuningDefaults();return this.verificationLevel().id===t.verification&&this.explorerMode().id===t.explorer});tuningSliders=I(()=>{let t=this.verificationIndex(),e=this.explorerIndex();return[{kind:"verify",name:"Result check",ends:["Off","Strict"],ladder:_n,index:t,level:_n[t],fraction:Gd(t,_n.length)/100},{kind:"explore",name:"Screen reading",ends:["Faster","Sharper"],ladder:hn,index:e,level:hn[e],fraction:Gd(e,hn.length)/100}]});notchFraction(t,e){return Gd(t,e)/100}setTuningIndex(t,e){let o=Math.round(Number(e));if(!Number.isFinite(o))return;let i=t==="verify"?_n:hn,r=Math.min(Math.max(o,0),i.length-1);this.tuningTouched.set(!0),t==="verify"?this.verificationIndex.set(r):this.explorerIndex.set(r),this.activeTuningTip.set(t)}showTuningTip(t){this.activeTuningTip.set(t)}hideTuningTip(t){this.activeTuningTip()===t&&this.activeTuningTip.set(null)}resetTuning(){let t=this.tuningDefaults();this.verificationIndex.set(Li(_n,t.verification,Hr)),this.explorerIndex.set(Li(hn,t.explorer,Ur)),this.tuningTouched.set(!1)}loadProTuningDefaults(){this.agentService.getProTuningDefaults().subscribe({next:t=>{let e=Li(_n,t?.verification_level,Hr),o=Li(hn,t?.explorer_mode,Ur);this.tuningDefaults.set({verification:_n[e].id,explorer:hn[o].id}),this.tuningTouched()||(this.verificationIndex.set(e),this.explorerIndex.set(o))},error:()=>{}})}toggleOutputterDrawer(){this.showOutputterDrawer.update(t=>!t)}applyOutputPreset(t){this.expectedOutput()===t?this.expectedOutput.set(""):(this.expectedOutput.set(t),this.showOutputterDrawer.set(!0))}isIntentSuggestingPro=I(()=>{let t=this.taskGoal().toLowerCase();return t.trim()?["monitor","polling","poll","wait until","loop","keep watching","crash","logcat","troubleshoot","diagnose","debug","investigate","compare","extract","summarize","report","\u76D1\u63A7","\u8F6E\u8BE2","\u7B49\u5F85","\u4E00\u76F4","\u76F4\u5230","\u5D29\u6E83","\u95EA\u9000","\u6392\u67E5","\u5206\u6790\u65E5\u5FD7","\u5BF9\u6BD4","\u603B\u7ED3"].some(o=>t.includes(o)):!1});showIntentSuggestion=I(()=>this.isIntentSuggestingPro()&&this.selectedProfile()==="flash");isReady=I(()=>this.systemService.isReady());hasReadinessReport=I(()=>this.systemService.hasReadinessReport());isLoading=I(()=>this.systemService.isLoading());isRestartingAdb=I(()=>this.systemService.isRestartingAdb());launchingAvd=I(()=>this.systemService.launchingAvd());emulatorLaunchState=I(()=>this.systemService.emulatorLaunchState());isEmulatorLaunching=I(()=>this.systemService.isEmulatorLaunching());showLaunchLogs=x(!1);pythonProbe=I(()=>this.systemService.pythonProbe());configProbe=I(()=>this.systemService.configProbe());adbProbe=I(()=>this.systemService.adbProbe());llmProbe=I(()=>this.systemService.llmProbe());geminiProbe=I(()=>this.systemService.geminiProbe());ocrProbe=I(()=>this.systemService.ocrProbe());toolchainProbe=I(()=>this.systemService.toolchainProbe());isEnvironmentReady=I(()=>this.systemService.isEnvironmentReady());isCredentialsReady=I(()=>this.systemService.isCredentialsReady());isSkipCredentialsCheck=I(()=>this.systemService.isSkipCredentialsCheck());isDeviceReady=I(()=>this.systemService.isDeviceReady());activeDevice=I(()=>this.systemService.activeDevice());connectedDevices=I(()=>this.systemService.connectedDevices());installedAvds=I(()=>this.systemService.installedAvds());emulatorPath=I(()=>this.systemService.emulatorPath());isEmulatorInPath=I(()=>this.systemService.isEmulatorInPath());totalStepCount=I(()=>this.systemService.totalStepCount());passedStepCount=I(()=>this.systemService.passedStepCount());blockerCount=I(()=>this.systemService.blockerCount());passedBlockerCount=I(()=>this.systemService.passedBlockerCount());configuredLlmProviders=I(()=>{let t=this.llmProbe()?.metadata;return t&&Array.isArray(t.providers)?t.providers:[]});selectedOs=x(null);effectiveOs=I(()=>this.selectedOs()||this.systemService.osType());oneClickSetupCmd=I(()=>this.effectiveOs()==="windows"?"powershell -ExecutionPolicy Bypass -File scripts/install_deps.ps1":"bash scripts/install_deps.sh");adbInstallCmd=I(()=>{let t=this.effectiveOs();return t==="windows"?"winget install Google.PlatformTools":t==="darwin"?"brew install android-platform-tools":"sudo apt-get install -y adb"});toolchainInstallCmd=I(()=>{let t=this.effectiveOs();return t==="windows"?"winget install Gyan.FFmpeg Genymobile.scrcpy":t==="darwin"?"brew install ffmpeg scrcpy":"sudo apt-get install -y ffmpeg scrcpy"});emuHypervisorTitle=I(()=>{let t=this.effectiveOs();return t==="windows"?"Enable Windows Hypervisor Platform (WHPX)":t==="darwin"?"Verify macOS Hypervisor / Install Tools":"Enable KVM Hardware Acceleration (Linux)"});emuHypervisorDesc=I(()=>{let t=this.effectiveOs();return t==="windows"?"Enable Windows Hypervisor Platform in PowerShell (Run as Administrator):":t==="darwin"?"macOS uses native Hypervisor.framework. Install SDK tools via Homebrew (or Studio):":"Ensure virtualization permissions are granted to your user account:"});emuHypervisorCmd=I(()=>{let t=this.effectiveOs();return t==="windows"?"Enable-WindowsOptionalFeature -Online -FeatureName HypervisorPlatform":t==="darwin"?"brew install --cask android-commandlinetools":"sudo apt-get install -y qemu-kvm libvirt-daemon-system && sudo adduser $USER kvm"});emuSdkInstallCmd=I(()=>this.effectiveOs()==="darwin"?'sdkmanager --install "system-images;android-34;google_apis;arm64-v8a" "emulator" "platform-tools"':'sdkmanager --install "system-images;android-34;google_apis;x86_64" "emulator" "platform-tools"');emuCreateAvdCmd=I(()=>this.effectiveOs()==="darwin"?'avdmanager create avd -n Pixel_8_API_34 -k "system-images;android-34;google_apis;arm64-v8a" --device "pixel_8"':'avdmanager create avd -n Pixel_8_API_34 -k "system-images;android-34;google_apis;x86_64" --device "pixel_8"');isOcrConfigured=I(()=>this.ocrProbe()?.metadata?.configured===!0);currentApiKey=I(()=>this.systemService.currentApiKey());apiKeysMap=I(()=>this.systemService.apiKeysMap());savedGeminiKey=I(()=>this.apiKeysMap().google||this.currentApiKey()||"");isGeminiModified=I(()=>this.geminiKeyInput().trim()!==this.savedGeminiKey().trim());savedOcrKey=I(()=>this.apiKeysMap().ocr||"");isOcrModified=I(()=>this.ocrKeyInput().trim()!==this.savedOcrKey().trim());allSuggestions=this.taskRecService.allTasks;selectedCategory=x("all");shuffleOffset=x(0);installedPackages=I(()=>{let t=this.activeDevice()?.installed_packages;return t&&Array.isArray(t)?new Set(t):new Set});filteredSuggestions=I(()=>this.taskRecService.filterAndRankTasks(this.installedPackages(),this.selectedCategory(),this.shuffleOffset()));focusListener=()=>{this.systemService.fetchReadiness().subscribe()};constructor(){Ye(()=>{let t=this.systemService.apiKeysMap(),e=this.systemService.currentApiKey(),o=t.google||e||"",i=t.ocr||"";this.isGeminiKeyEdited()||this.geminiKeyInput.set(o),this.isOcrKeyEdited()||this.ocrKeyInput.set(i)})}ngOnInit(){this.loadProTuningDefaults(),this.systemService.fetchReadiness().subscribe(),this.systemService.fetchModelConfigEnv().subscribe(),this.systemService.fetchAdbServerStatus().subscribe({next:t=>{t.endpoint.mode==="remote"&&(this.remoteAdbHost.set(t.endpoint.host),this.remoteAdbPort.set(String(t.endpoint.port)),this.activeAdbGuideTab.set("remote"))},error:()=>{}}),window.addEventListener("focus",this.focusListener)}ngOnDestroy(){window.removeEventListener("focus",this.focusListener)}setTab(t){this.activeTab.set(t),t==="diagnostics"&&(this.systemService.fetchReadiness().subscribe(),this.systemService.fetchModelConfigEnv().subscribe())}setSelectedOs(t){this.selectedOs.set(t)}setAdbGuideTab(t){this.activeAdbGuideTab.set(t),this.remoteAdbError.set(null),this.remoteAdbMessage.set(null)}setEmulatorSetupMode(t){this.emulatorSetupMode.set(t)}setModelSetupMode(t){this.modelSetupMode.set(t),t==="custom"?(this.systemService.setSkipCredentialsCheck(!0),this.systemService.fetchModelConfigEnv().subscribe()):this.systemService.setSkipCredentialsCheck(!1)}toggleFullConfigFile(){this.showFullConfigFile.update(t=>!t)}toggleGeminiKeyVisibility(){this.showGeminiKey.update(t=>!t)}toggleOcrKeyVisibility(){this.showOcrKey.update(t=>!t)}toggleOcrConfig(){this.showOcrConfig.update(t=>!t)}onGeminiKeyChange(t){this.geminiKeyInput.set(t),this.isGeminiKeyEdited.set(!0),this.geminiSaveError.set(null),this.geminiSaveMessage.set(null)}onOcrKeyChange(t){this.ocrKeyInput.set(t),this.isOcrKeyEdited.set(!0),this.ocrSaveError.set(null),this.ocrSaveMessage.set(null)}saveGeminiKey(){let t=this.geminiKeyInput().trim();t&&(this.isSavingGeminiKey.set(!0),this.geminiSaveError.set(null),this.geminiSaveMessage.set(null),this.systemService.updateApiKey("google",t,!0).subscribe({next:e=>{this.isSavingGeminiKey.set(!1),this.isGeminiKeyEdited.set(!1),this.geminiSaveMessage.set(e?.message||"\u2713 Gemini API key verified & saved successfully."),setTimeout(()=>this.geminiSaveMessage.set(null),5e3)},error:e=>{this.isSavingGeminiKey.set(!1),this.geminiSaveError.set(e?.error?.detail||e?.message||"Failed to update Gemini API key.")}}))}clearGeminiKey(){this.geminiKeyInput.set(""),this.isGeminiKeyEdited.set(!1),this.geminiSaveError.set(null),this.geminiSaveMessage.set(null),this.savedGeminiKey().trim()?(this.isSavingGeminiKey.set(!0),this.systemService.updateApiKey("google","",!0).subscribe({next:t=>{this.isSavingGeminiKey.set(!1),this.geminiSaveMessage.set(t?.message||"\u2713 Gemini API key cleared."),setTimeout(()=>this.geminiSaveMessage.set(null),5e3)},error:t=>{this.isSavingGeminiKey.set(!1),this.geminiSaveError.set(t?.error?.detail||t?.message||"Failed to clear Gemini API key.")}})):(this.geminiSaveMessage.set("\u2713 Gemini API key cleared."),setTimeout(()=>this.geminiSaveMessage.set(null),3e3))}saveOcrKey(){let t=this.ocrKeyInput().trim();t&&(this.isSavingOcrKey.set(!0),this.ocrSaveError.set(null),this.ocrSaveMessage.set(null),this.systemService.updateApiKey("ocr",t,!0).subscribe({next:e=>{this.isSavingOcrKey.set(!1),this.isOcrKeyEdited.set(!1),this.ocrSaveMessage.set(e?.message||"\u2713 Vision OCR API key verified & saved."),setTimeout(()=>this.ocrSaveMessage.set(null),5e3)},error:e=>{this.isSavingOcrKey.set(!1),this.ocrSaveError.set(e?.error?.detail||e?.message||"Failed to update Vision OCR key.")}}))}clearOcrKey(){this.ocrKeyInput.set(""),this.isOcrKeyEdited.set(!1),this.ocrSaveError.set(null),this.ocrSaveMessage.set(null),this.savedOcrKey().trim()?(this.isSavingOcrKey.set(!0),this.systemService.updateApiKey("ocr","",!0).subscribe({next:t=>{this.isSavingOcrKey.set(!1),this.ocrSaveMessage.set(t?.message||"\u2713 Vision OCR API key cleared."),setTimeout(()=>this.ocrSaveMessage.set(null),5e3)},error:t=>{this.isSavingOcrKey.set(!1),this.ocrSaveError.set(t?.error?.detail||t?.message||"Failed to clear Vision OCR key.")}})):(this.ocrSaveMessage.set("\u2713 Vision OCR API key cleared."),setTimeout(()=>this.ocrSaveMessage.set(null),3e3))}testGeminiKey(){let t=this.geminiKeyInput().trim();t&&(this.isTestingGeminiKey.set(!0),this.geminiSaveError.set(null),this.geminiSaveMessage.set(null),this.systemService.testApiKey("google",t).subscribe({next:e=>{this.isTestingGeminiKey.set(!1),e?.valid?this.geminiSaveMessage.set(e?.message||"\u2713 Gemini API key is valid!"):this.geminiSaveError.set(e?.message||"Gemini API key verification failed."),setTimeout(()=>this.geminiSaveMessage.set(null),5e3)},error:e=>{this.isTestingGeminiKey.set(!1),this.geminiSaveError.set(e?.error?.detail||e?.message||"Gemini API key test failed.")}}))}testOcrKey(){let t=this.ocrKeyInput().trim();t&&(this.isTestingOcrKey.set(!0),this.ocrSaveError.set(null),this.ocrSaveMessage.set(null),this.systemService.testApiKey("ocr",t).subscribe({next:e=>{this.isTestingOcrKey.set(!1),e?.valid?this.ocrSaveMessage.set(e?.message||"\u2713 Vision OCR API key is valid!"):this.ocrSaveError.set(e?.message||"Vision OCR API key verification failed."),setTimeout(()=>this.ocrSaveMessage.set(null),5e3)},error:e=>{this.isTestingOcrKey.set(!1),this.ocrSaveError.set(e?.error?.detail||e?.message||"Vision OCR API key test failed.")}}))}getProviderDisplayName(t){switch(t){case"gemini":return"Gemini";case"ocr":return"Vision OCR";default:return t}}getProviderEnvVar(t){switch(t){case"gemini":return"GEMINI_API_KEY";case"ocr":return"GOOGLE_VISION_API_KEY";default:return"API_KEY"}}getProviderHint(t){switch(t){case"gemini":return"For a quick start, Google Gemini provides a free API key. Artemis also supports other models (OpenAI, Claude, OpenRouter, etc.)\u2014you can configure your own API keys directly in .env or your environment.";case"ocr":return"Google Cloud Vision API key for on-screen OCR text detection and UI grounding.";default:return"Configure your API key or use environment definitions."}}skipCredentialsCheck(){this.systemService.skipCredentialsCheck()}getApiKeyPlaceholder(t){switch(t){case"gemini":return"Enter Gemini API Key (e.g. AIzaSy...)";case"ocr":return"Enter Vision OCR API Key (e.g. AIzaSy...)";default:return"Enter API Key..."}}isTabProviderActive(t){if(t==="ocr")return this.isOcrConfigured();let e=t==="gemini"?"google":t;return this.configuredLlmProviders().some(i=>i.provider===e)}refreshReadiness(){this.isRefreshingDiagnostics.set(!0),this.systemService.fetchReadiness(!1,!0).subscribe({next:()=>{this.systemService.fetchModelConfigEnv().subscribe({next:()=>{setTimeout(()=>this.isRefreshingDiagnostics.set(!1),450)},error:()=>this.isRefreshingDiagnostics.set(!1)})},error:()=>this.isRefreshingDiagnostics.set(!1)})}restartAdbServer(){this.adbRestartFeedback.set(null),this.systemService.restartAdb().subscribe({next:t=>{this.adbRestartFeedback.set(t?.restart_result?.skipped?"Devices Refreshed \u2713":"ADB Refreshed \u2713"),setTimeout(()=>this.adbRestartFeedback.set(null),2500)},error:()=>{this.adbRestartFeedback.set("Restart Failed"),setTimeout(()=>this.adbRestartFeedback.set(null),3e3)}})}connectWifiDevice(){if(this.isRemoteAdbServer()){this.wifiConnectError.set("Switch to local ADB before connecting a Wireless ADB device.");return}let t=this.wifiHost().trim(),e=this.wifiPort().trim()||"5555",o=parseInt(e,10)||5555;if(!t){this.wifiConnectError.set("Please enter a valid IP address.");return}this.isConnectingWifi.set(!0),this.wifiConnectError.set(null),this.wifiConnectMessage.set(null),this.systemService.connectWirelessAdb(t,o).subscribe({next:i=>{this.isConnectingWifi.set(!1);let r=i?.connect_result;r?.success?(this.wifiConnectMessage.set(`Connected to ${t}:${o}!`),setTimeout(()=>this.wifiConnectMessage.set(null),4e3)):this.wifiConnectError.set(r?.message||"Connection failed. Please check phone IP & Wi-Fi.")},error:i=>{this.isConnectingWifi.set(!1),this.wifiConnectError.set(i?.error?.detail||"Failed to connect. Please check adb connection.")}})}connectRemoteAdbServer(){let t=this.remoteAdbHost().trim(),e=Number(this.remoteAdbPort().trim());if(!t){this.remoteAdbError.set("Enter the host name or IP address of the ADB server.");return}if(!Number.isInteger(e)||e<1||e>65535){this.remoteAdbError.set("Enter a port between 1 and 65535.");return}this.isConnectingRemoteAdb.set(!0),this.remoteAdbError.set(null),this.remoteAdbMessage.set(null),this.remoteAdbDevices.set([]),this.remoteAdbProbeResult.set(null),this.systemService.probeAdbServer(t,e).subscribe({next:o=>{this.isConnectingRemoteAdb.set(!1);let i=o.connection_result;i.success?(this.remoteAdbProbeResult.set(i),this.remoteAdbDevices.set(i.devices||[]),this.remoteAdbMessage.set(i.message)):this.remoteAdbError.set(i.message)},error:o=>{this.isConnectingRemoteAdb.set(!1),this.remoteAdbError.set(o?.error?.detail||"Unable to test the ADB server endpoint.")}})}activateRemoteAdbServer(){let t=this.remoteAdbProbeResult();if(!t?.success){this.remoteAdbError.set("Test the endpoint before using it.");return}this.isActivatingRemoteAdb.set(!0),this.remoteAdbError.set(null),this.systemService.connectAdbServer(t.endpoint.host,t.endpoint.port,this.rememberRemoteAdb()).subscribe({next:e=>{this.isActivatingRemoteAdb.set(!1);let o=e.connection_result;o.success?(this.remoteAdbProbeResult.set(o),this.remoteAdbDevices.set(o.devices||[]),this.remoteAdbMessage.set(o.message)):this.remoteAdbError.set(o.message)},error:e=>{this.isActivatingRemoteAdb.set(!1),this.remoteAdbError.set(e?.error?.detail||"Unable to use the ADB server endpoint.")}})}updateRemoteAdbHost(t){this.remoteAdbHost.set(t),this.clearRemoteAdbProbe()}updateRemoteAdbPort(t){this.remoteAdbPort.set(t),this.clearRemoteAdbProbe()}clearRemoteAdbProbe(){this.remoteAdbProbeResult.set(null),this.remoteAdbDevices.set([]),this.remoteAdbMessage.set(null),this.remoteAdbError.set(null)}switchToLocalAdbServer(){this.isSwitchingToLocalAdb.set(!0),this.remoteAdbError.set(null),this.systemService.useLocalAdbServer(!0).subscribe({next:t=>{this.isSwitchingToLocalAdb.set(!1),this.remoteAdbDevices.set([]),this.remoteAdbMessage.set(t.connection_result.message)},error:t=>{this.isSwitchingToLocalAdb.set(!1),this.remoteAdbError.set(t?.error?.detail||"Unable to switch back to the local ADB server.")}})}toggleConnectionMethods(){this.showConnectionMethods.update(t=>!t)}launchAvdEmulator(t){this.isRemoteAdbServer()||this.systemService.launchEmulator(t).subscribe()}toggleLaunchLogs(){this.showLaunchLogs.update(t=>!t)}stopEmulator(){this.systemService.stopEmulator().subscribe()}dismissEmulatorStatus(){this.systemService.dismissEmulatorStatus().subscribe()}selectTargetDevice(t){this.systemService.selectDevice(t).subscribe()}getEmulatorCommand(t){let e=this.emulatorPath();return`${this.isEmulatorInPath()?"emulator":e||"~/Android/Sdk/emulator/emulator"} -avd ${t}`}copyToClipboard(t,e){navigator.clipboard&&navigator.clipboard.writeText(t).then(()=>{this.copiedId.set(e),setTimeout(()=>{this.copiedId()===e&&this.copiedId.set(null)},2e3)})}setProfile(t){this.selectedProfile.set(t)}setCategory(t){this.selectedCategory.set(t)}shuffleSuggestions(){this.shuffleOffset.update(t=>t+3)}getAppNamesDisplay(t){return t.map(e=>e.name).join(" + ")}applySuggestion(t){this.taskGoal.set(t.goal),this.selectedProfile.set(t.profile),this.errorMessage.set(null)}applyQuickPrompt(t,e){this.taskGoal.set(t),e&&this.selectedProfile.set(e),this.errorMessage.set(null)}proceedToLauncher(){this.activeTab.set("launcher")}runTask(){let t=this.taskGoal().trim();if(!t){this.errorMessage.set("Please enter a task goal before running.");return}if(!this.isReady()){this.errorMessage.set("System prerequisites are not satisfied. Please review System Setup first."),this.activeTab.set("diagnostics");return}this.isSubmitting.set(!0),this.errorMessage.set(null),this.agentService.runTask(t,this.selectedProfile(),this.selectedProfile()==="pro"&&this.expectedOutput().trim()?this.expectedOutput().trim():void 0,this.selectedProfile()==="pro"?this.enableOutputter():void 0,this.selectedProfile()==="pro"?{verificationLevel:this.verificationLevel().id,explorerMode:this.explorerMode().id}:void 0).subscribe({next:()=>{this.isSubmitting.set(!1),this.router.navigate(["/workspace"])},error:e=>{console.error("Failed to submit task from home page:",e),this.isSubmitting.set(!1),this.errorMessage.set(e?.error?.detail||"Failed to submit task. Please check server connection.")}})}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=Ge({type:n,selectors:[["app-home"]],decls:26,vars:14,consts:[[1,"home-container"],[1,"aurora-background"],[1,"glow","glow-1"],[1,"glow","glow-2"],[1,"glow","glow-3"],[1,"glow","glow-pending"],[1,"glow","glow-ready"],[1,"glow","glow-pro"],[1,"home-content"],[1,"hero-section"],[1,"hero-title"],[1,"mode-tabs-container"],[1,"mode-tabs"],["type","button",1,"mode-tab-btn",3,"click"],[1,"material-symbols-outlined","tab-icon","icon-ready"],[1,"material-symbols-outlined","tab-icon"],[1,"tab-label"],[1,"material-symbols-outlined","tab-icon","icon-locked"],[1,"setup-guide-view"],[1,"task-launcher-view"],[1,"guide-card"],[1,"guide-card-header"],[1,"step-badge"],[1,"material-symbols-outlined","step-check-icon"],[1,"step-info"],[1,"step-title-row"],[1,"step-title"],[1,"step-desc"],["type","button","title","Re-check all system dependencies",1,"btn-header-action",3,"click","disabled"],[1,"material-symbols-outlined"],[1,"guide-card-body"],[1,"one-click-install-bar"],[1,"env-matrix-grid"],[1,"env-item-card"],[1,"item-header"],[1,"item-icon-box"],[1,"material-symbols-outlined","item-icon"],[1,"item-title-group"],[1,"item-name"],[1,"item-subtitle"],[1,"item-status"],[1,"status-dot"],[1,"item-body"],[1,"model-choice-cards-row"],[1,"choice-card",3,"click"],[1,"choice-card-top"],[1,"choice-radio"],[1,"radio-dot"],[1,"choice-icon-wrap"],["viewBox","0 0 24 24","fill","none",1,"brand-svg","gemini-svg"],["id","geminiChoiceGrad","x1","0%","y1","0%","x2","100%","y2","100%"],["offset","0%","stop-color","#4285F4"],["offset","50%","stop-color","#9B72CB"],["offset","100%","stop-color","#D96570"],["d","M12 2C12 7.523 7.523 12 2 12C7.523 12 12 16.477 12 22C12 16.477 16.477 12 22 12C16.477 12 12 7.523 12 2Z","fill","url(#geminiChoiceGrad)"],[1,"choice-text"],[1,"choice-title-row"],[1,"choice-title"],[1,"tag-badge","tag-rec"],[1,"choice-desc"],[1,"choice-icon-wrap","icon-gear"],[1,"custom-config-inspector"],["type","button",1,"btn-restart-adb","btn-connection-options",3,"click"],["type","button",1,"btn-restart-adb",3,"click","disabled","title"],[1,"connected-device-panel"],[1,"emulator-boot-tracker-container"],[1,"emulator-failed-container"],[1,"foolproof-guide-container"],[1,"device-locked-panel"],[1,"unauthorized-panel"],[1,"adb-missing-panel"],[1,"ready-banner-footer"],[1,"install-bar-left"],[1,"install-bar-icon-box"],[1,"material-symbols-outlined","bolt-icon"],[1,"install-bar-text"],[1,"install-bar-title-row"],[1,"install-bar-title"],[1,"os-selector-pills"],["type","button",1,"os-pill",3,"click"],[1,"install-bar-desc"],[1,"code-box","small-box"],["type","button",1,"btn-copy-code",3,"click"],[1,"item-action-box"],[1,"terminal-prefix"],[1,"code-text"],[1,"credentials-input-box"],[1,"input-box-header"],[1,"header-label"],[1,"material-symbols-outlined","label-icon"],["href","https://aistudio.google.com/app/apikey","target","_blank","rel","noopener noreferrer",1,"btn-header-link"],[1,"unified-key-row"],[1,"unified-key-wrapper"],[1,"material-symbols-outlined","key-prefix-icon"],["placeholder","Enter Gemini API Key (e.g. AIzaSy...)","spellcheck","false","autocomplete","off",1,"unified-key-input",3,"ngModelChange","type","ngModel"],["type","button",1,"btn-icon-action",3,"click","title"],["type","button","title","Copy API Key",1,"btn-icon-action"],["type","button",1,"btn-unified-save",3,"click","disabled"],["type","button","title","Test if Gemini API key is valid",1,"btn-unified-test",3,"click","disabled"],[1,"feedback-msg","success"],[1,"feedback-msg","error"],[1,"ocr-enhancement-card"],[1,"ocr-card-toggle-bar",3,"click"],[1,"toggle-bar-left"],[1,"material-symbols-outlined","icon-ocr"],[1,"toggle-bar-titles"],[1,"ocr-main-title"],[1,"toggle-bar-right"],["title","OCR Configured",1,"status-dot","dot-pass"],[1,"material-symbols-outlined","caret-icon"],[1,"ocr-content-body"],["type","button","title","Copy API Key",1,"btn-icon-action",3,"click"],[1,"material-symbols-outlined","spin"],[1,"ocr-help-desc"],[1,"credentials-input-box","ocr-box"],["placeholder","Enter Vision OCR API Key (e.g. AIzaSy...)","spellcheck","false","autocomplete","off",1,"unified-key-input",3,"ngModelChange","type","ngModel"],["type","button","title","Test if Vision OCR key is valid",1,"btn-unified-test",3,"click","disabled"],[1,"inspector-card"],[1,"inspector-card-header"],[1,"inspector-header-left"],[1,"material-symbols-outlined","header-icon"],[1,"inspector-header-titles"],[1,"inspector-title"],[1,"inspector-subtitle"],[1,"inspector-header-actions"],["type","button","title","Copy file path",1,"btn-file-action",3,"click"],["type","button",1,"btn-file-action","btn-toggle-code",3,"click"],[1,"inspector-summary-row"],[1,"summary-metric"],[1,"metric-label"],[1,"metric-val-pill"],[1,"provider-dot"],[1,"provider-name"],[1,"model-divider"],[1,"model-name"],[1,"jsonc-viewer-box"],[1,"env-keys-table"],[1,"env-key-row",3,"is-configured"],[1,"metric-val-pill","secondary"],[1,"jsonc-code"],[1,"env-key-row"],[1,"env-name-col"],[1,"env-key-name"],[1,"env-status-col"],[1,"badge-env-pass"],[1,"badge-env-unset"],[1,"key-preview"],[1,"material-symbols-outlined","spinning"],[1,"material-symbols-outlined","feedback-done"],[1,"feedback-text"],[1,"device-hero-card"],[1,"device-avatar"],[1,"material-symbols-outlined","device-hero-icon"],[1,"device-hero-details"],[1,"device-hero-name"],[1,"device-hero-meta"],[1,"device-hero-status"],[1,"status-dot","dot-pass"],[1,"status-text"],[1,"multi-device-switcher"],[1,"meta-dot"],[1,"remote-endpoint-label"],[1,"switcher-label"],[1,"switcher-chips"],["type","button",1,"device-chip-btn",3,"selected"],["type","button",1,"device-chip-btn",3,"click"],[1,"material-symbols-outlined","chip-icon"],[1,"active-check"],[1,"emulator-boot-tracker-card"],[1,"tracker-header"],[1,"tracker-title-group"],[1,"tracker-icon-box"],[1,"material-symbols-outlined","spinning-icon"],[1,"tracker-titles"],[1,"tracker-main-heading"],[1,"tracker-title"],[1,"avd-highlight"],[1,"stage-tag-badge"],[1,"tracker-subtitle"],[1,"tracker-actions"],["type","button",1,"btn-toggle-logs",3,"click"],["type","button","title","Terminate emulator process",1,"btn-stop-emu",3,"click"],[1,"boot-stepper"],[1,"step-item"],[1,"step-circle"],[1,"material-symbols-outlined","check-icon"],[1,"spinner-tiny"],[1,"step-label"],[1,"step-line"],[1,"progress-bar-container"],[1,"progress-bar-track"],[1,"progress-bar-fill"],[1,"progress-bar-meta"],[1,"progress-percent"],[1,"progress-timer"],[1,"material-symbols-outlined","timer-icon"],[1,"boot-tip-banner"],[1,"material-symbols-outlined","tip-icon"],[1,"boot-logs-drawer"],[1,"logs-header"],[1,"logs-header-left"],["type","button",1,"btn-copy-logs",3,"click"],[1,"logs-body"],[1,"log-empty"],[1,"log-line"],[1,"emulator-failed-card"],[1,"failed-header"],[1,"failed-header-left"],[1,"failed-icon-box"],[1,"material-symbols-outlined","failed-icon"],[1,"failed-titles"],[1,"failed-title"],[1,"failed-desc"],["type","button","title","Dismiss error",1,"btn-dismiss-failed",3,"click"],[1,"failed-logs-box"],[1,"failed-actions-bar"],["type","button",1,"btn-retry-launch",3,"disabled"],["type","button",1,"btn-restart-adb-sub",3,"click"],["type","button",1,"btn-dismiss-flat",3,"click"],[1,"failed-logs-pre"],["type","button",1,"btn-retry-launch",3,"click","disabled"],[1,"connection-methods-nav"],["type","button",1,"method-nav-card",3,"click"],[1,"method-card-left"],[1,"method-icon-box"],[1,"method-info"],[1,"method-title-row"],[1,"method-title"],[1,"method-desc"],[1,"method-card-right"],[1,"radio-indicator"],[1,"active-remote-notice"],[1,"method-details-panel"],[1,"method-details-panel","remote-adb-panel"],[1,"active-remote-copy"],["type","button",1,"btn-use-local-adb",3,"click","disabled"],[1,"avds-section"],[1,"emulator-setup-guide-container"],[1,"section-header-bar"],[1,"section-title-group"],[1,"section-title"],[1,"count-badge"],[1,"avds-list"],[1,"avd-card-item"],[1,"avd-item-main"],[1,"avd-avatar"],[1,"avd-meta"],[1,"avd-heading"],[1,"avd-name"],[1,"avd-type-pill"],[1,"avd-item-actions"],["type","button",1,"btn-avd-launch",3,"click","disabled","title"],[1,"spinner-icon"],[1,"material-symbols-outlined","action-icon"],[1,"empty-avd-banner"],[1,"banner-left"],[1,"empty-avd-icon-box"],[1,"banner-titles"],[1,"banner-title-row"],[1,"empty-title"],[1,"empty-desc"],[1,"mode-switch-pills"],["type","button",1,"pill-btn",3,"click"],[1,"material-symbols-outlined","pill-icon"],[1,"steps-flow-grid","emu-flow-grid"],[1,"cli-steps-list"],[1,"flow-step-card"],[1,"step-card-header"],[1,"step-number-badge"],[1,"material-symbols-outlined","step-card-icon"],[1,"step-card-title"],[1,"step-card-desc"],["href","https://developer.android.com/studio","target","_blank","rel","noopener",1,"guide-link"],[1,"cli-step-item"],[1,"step-badge-num"],[1,"step-content"],[1,"step-text"],[1,"usb-guide-intro"],[1,"material-symbols-outlined","intro-icon"],[1,"steps-flow-grid"],[1,"wifi-guide-intro"],[1,"wifi-interactive-box"],[1,"wifi-form-row"],[1,"wifi-input-col","ip-col"],[1,"wifi-label"],[1,"wifi-input-wrap"],[1,"material-symbols-outlined","wrap-icon"],["type","text","placeholder","e.g. 192.168.1.108","spellcheck","false",1,"wifi-input",3,"ngModelChange","ngModel"],[1,"wifi-input-col","port-col"],["type","text","placeholder","5555","spellcheck","false",1,"wifi-input",3,"ngModelChange","ngModel"],[1,"wifi-btn-col"],["type","button",1,"btn-wifi-connect",3,"click","disabled"],[1,"wifi-status-alert","success"],[1,"wifi-status-alert","error"],[1,"info-callout-box"],[1,"material-symbols-outlined","callout-icon"],[1,"callout-text"],[1,"remote-guide-intro"],[1,"remote-adb-interactive-box"],[1,"remote-adb-form-row"],[1,"remote-adb-input-col","host-col"],["for","remote-adb-host",1,"remote-adb-label"],[1,"remote-adb-input-wrap"],["id","remote-adb-host","type","text","placeholder","127.0.0.1","autocomplete","off","spellcheck","false",1,"remote-adb-input",3,"ngModelChange","ngModel"],[1,"remote-adb-input-col","port-col"],["for","remote-adb-port",1,"remote-adb-label"],["id","remote-adb-port","type","text","inputmode","numeric","placeholder","5038","autocomplete","off","spellcheck","false",1,"remote-adb-input",3,"ngModelChange","ngModel"],[1,"remote-adb-btn-col"],["type","button",1,"btn-remote-adb-connect",3,"click","disabled"],[1,"remember-remote-adb"],["type","checkbox",3,"ngModelChange","ngModel"],[1,"remote-adb-status-alert","success"],["role","alert",1,"remote-adb-status-alert","error"],[1,"remote-device-results"],["type","button",1,"btn-remote-adb-connect","btn-use-tested-endpoint",3,"disabled"],[1,"remote-adb-explanation"],[1,"remote-device-row"],[1,"remote-device-copy"],[1,"remote-device-state"],["type","button",1,"btn-remote-adb-connect","btn-use-tested-endpoint",3,"click","disabled"],[1,"device-locked-card"],[1,"material-symbols-outlined","alert-icon"],[1,"locked-details"],[1,"locked-title"],[1,"locked-desc"],["type","button",1,"btn-check-unlock",3,"click","disabled"],[1,"multi-device-switcher",2,"margin-top","12px"],[1,"unauthorized-card"],[1,"unauth-details"],[1,"unauth-title"],[1,"unauth-desc"],["type","button",1,"btn-retry-auth",3,"click"],[1,"error-msg-box"],[1,"material-symbols-outlined","err-icon"],[1,"install-commands-row"],[1,"install-card"],[1,"install-os"],[1,"detected-badge"],[1,"ready-banner-left"],[1,"step-badge","step-pass"],[1,"ready-text-group"],[1,"ready-title"],[1,"ready-desc"],["type","button",1,"btn-proceed-launch",3,"click"],[1,"material-symbols-outlined","rocket-icon"],[1,"launcher-warning-bar"],[1,"composer-card"],[1,"intent-suggestion-strip"],[1,"composer-input-area"],["id","task-input-field","rows","3","placeholder","Describe what you want to achieve on your phone (e.g. Open Gmail and search for latest emails)...",1,"composer-textarea",3,"ngModelChange","keydown.control.enter","keydown.meta.enter","ngModel","disabled"],[1,"composer-model-descriptor"],[1,"descriptor-icon-wrap"],[1,"descriptor-body"],[1,"desc-line"],[1,"error-banner"],[1,"composer-action-bar"],[1,"bar-left"],[1,"model-toggle-capsule"],["type","button","title","Flash: fast single-look loop for everyday app tasks (3\u20135s/step)",1,"model-toggle-btn","btn-flash",3,"click"],[1,"material-symbols-outlined","btn-icon"],[1,"btn-text"],["type","button","title","Pro: plans first, checks results and recovers from blocked steps. For long or complex tasks (15\u201340s/step)",1,"model-toggle-btn","btn-pro",3,"click"],[1,"bar-right"],[1,"char-count"],["type","button",1,"btn-run-composer",3,"click","disabled","title"],[1,"smart-suggestions-container"],[1,"suggestions-header-bar"],[1,"header-left"],[1,"section-label"],[1,"material-symbols-outlined","section-icon"],[1,"label-text"],[1,"category-tabs-group"],["type","button",1,"cat-tab-btn",3,"click"],["type","button",1,"cat-tab-btn","cat-flash",3,"click"],[1,"material-symbols-outlined","tab-mini-icon"],["type","button",1,"cat-tab-btn","cat-pro",3,"click"],[1,"header-right"],["type","button","title","Discover more tasks",1,"btn-shuffle-suggestions",3,"click"],[1,"material-symbols-outlined","shuffle-icon"],[1,"suggestions-cards-grid"],[1,"suggestion-card",3,"is-pro-card","is-flash-card"],[1,"launcher-warning-bar",3,"click"],[1,"material-symbols-outlined","warn-icon"],[1,"material-symbols-outlined","arrow"],[1,"suggestion-left"],[1,"material-symbols-outlined","sparkle-icon"],[1,"suggestion-text"],["type","button",1,"btn-switch-pro",3,"click"],[1,"material-symbols-outlined","btn-arrow"],[1,"mode-name"],[1,"bullet"],[1,"limitation-tag"],[1,"material-symbols-outlined","error-icon"],[1,"spinner"],[1,"material-symbols-outlined","run-icon"],[1,"pro-outputter-standalone-card"],[1,"outputter-card-header"],[1,"outputter-title"],[1,"outputter-optional-tag"],[1,"outputter-input-wrapper"],["type","text","placeholder","Specify expected output or schema (e.g. 'Extract SMS verification code as JSON' or 'Summary of discounts and total price')...","spellcheck","false",1,"outputter-standalone-input",3,"ngModelChange","ngModel"],["type","button","title","Clear expected output",1,"btn-clear-standalone"],[1,"pro-tuning-card"],[1,"tuning-card-header"],[1,"tuning-title"],["type","button","title","Back to the defaults",1,"btn-tuning-reset"],[1,"tuning-sliders"],[1,"tuning-slider",3,"verify","explore","dragging","--%NS%pct"],["type","button","title","Clear expected output",1,"btn-clear-standalone",3,"click"],["type","button","title","Back to the defaults",1,"btn-tuning-reset",3,"click"],[1,"tuning-slider"],[1,"slider-head"],[1,"slider-name"],[1,"slider-value"],["aria-hidden","true",1,"slider-ends"],[1,"slider-track-wrap",3,"pointerenter","pointerleave"],["aria-hidden","true",1,"slider-rail"],[1,"slider-fill"],[1,"slider-notch",3,"reached","--%NS%n"],["aria-hidden","true",1,"slider-thumb"],["aria-hidden","true",1,"thumb-ripple"],["type","range","min","0","step","1",1,"slider-input",3,"input","focus","blur","max","value"],[1,"slider-notch"],[1,"slider-solid"],["width","100%","height","6","aria-hidden","true",1,"slider-dither"],["width","2","height","2",3,"opacity","animation-delay"],["width","2","height","2"],["aria-hidden","true",1,"tuning-tip-arrow"],["role","tooltip",1,"tuning-tip"],[1,"tip-heading"],[1,"tip-title"],[1,"tip-latency"],[1,"tip-tagline"],[1,"tip-section"],[1,"tip-section-title"],[1,"tip-section","skips"],[1,"tip-best"],[1,"suggestion-card",3,"click"],[1,"card-top-row"],[1,"app-icons-cluster"],[1,"app-icon-badge",3,"title"],[1,"app-names-label"],[1,"mode-badge",3,"title"],[1,"card-body"],[1,"card-title"],[1,"card-desc"],[1,"card-footer-row"],[1,"tag-pill"],[1,"use-prompt-action"],[1,"material-symbols-outlined","action-arrow"]],template:function(e,o){e&1&&(l(0,"div",0)(1,"div",1),$(2,"div",2)(3,"div",3)(4,"div",4)(5,"div",5)(6,"div",6)(7,"div",7),d(),l(8,"main",8)(9,"section",9)(10,"h1",10),u(11," What would you like to do on your phone? "),d()(),l(12,"div",11)(13,"div",12)(14,"button",13),k("click",function(){return o.setTab("diagnostics")}),M(15,MD,2,0,"span",14)(16,bD,2,0,"span",15),l(17,"span",16),u(18,"System Setup & Prerequisites"),d()(),l(19,"button",13),k("click",function(){return o.setTab("launcher")}),M(20,PD,2,0,"span",17)(21,OD,2,0,"span",15),l(22,"span",16),u(23,"Launch Autonomous Task"),d()()()(),M(24,_T,155,87,"section",18),M(25,jT,74,32,"section",19),d()()),e&2&&(w("system-ready",o.isReady())("system-pending",!o.isReady())("pro-theme-active",o.selectedProfile()==="pro"),g(14),w("active",o.activeTab()==="diagnostics"),g(),b(o.isReady()?15:16),g(4),w("active",o.activeTab()==="launcher"),g(),b(o.isReady()?21:20),g(4),b(o.activeTab()==="diagnostics"?24:-1),g(),b(o.activeTab()==="launcher"?25:-1))},dependencies:[Qt,zr,em,Nd,ws],styles:['@charset "UTF-8";.os-selector-pills[_ngcontent-%COMP%]{display:inline-flex;align-items:center;padding:2px;gap:2px;background:#ffffffa6;border:1px solid rgba(226,232,240,.85);border-radius:8px;box-shadow:0 1px 3px #0f172a0a,inset 0 1px 1px #fffc;backdrop-filter:blur(12px) saturate(180%);-webkit-backdrop-filter:blur(12px) saturate(180%)}.os-selector-pills[_ngcontent-%COMP%] .os-pill[_ngcontent-%COMP%]{padding:3px 9px;border:0;border-radius:6px;background:transparent;color:#475569;font-family:inherit;font-size:11px;font-weight:600;line-height:1.35;cursor:pointer;transition:color .15s ease,background-color .15s ease,box-shadow .15s ease}.os-selector-pills[_ngcontent-%COMP%] .os-pill[_ngcontent-%COMP%]:hover{color:#0f172a;background:#ffffffb8}.os-selector-pills[_ngcontent-%COMP%] .os-pill.active[_ngcontent-%COMP%]{color:#fff;background:#1a73e8;box-shadow:0 1px 2px #0f172a1f}.os-selector-pills[_ngcontent-%COMP%] .os-pill[_ngcontent-%COMP%]:focus-visible{outline:2px solid rgba(26,115,232,.35);outline-offset:1px}[_nghost-%COMP%]{display:block;min-height:100vh;width:100%;background-color:#f8f9fa;font-family:Google Sans Text,Google Sans,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;color:#0f172a;box-sizing:border-box;-webkit-font-smoothing:antialiased}*[_ngcontent-%COMP%], *[_ngcontent-%COMP%]:before, *[_ngcontent-%COMP%]:after{box-sizing:border-box}.home-container[_ngcontent-%COMP%]{position:relative;min-height:100vh;display:flex;flex-direction:column;background-color:#f8f9fa;overflow-x:hidden}.home-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%]{display:block;position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:1;overflow:hidden;opacity:.9;transition:opacity .8s ease}.home-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow[_ngcontent-%COMP%]{position:absolute;border-radius:50%;transform:translateZ(0);will-change:transform,opacity;pointer-events:none}.home-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-1[_ngcontent-%COMP%]{top:-140px;left:10%;width:520px;height:520px;background:radial-gradient(circle,rgba(59,130,246,.12) 0%,rgba(99,102,241,.04) 45%,transparent 82%);animation:_ngcontent-%COMP%_floatGlow1 22s ease-in-out infinite alternate}.home-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-2[_ngcontent-%COMP%]{top:-100px;right:12%;width:560px;height:560px;background:radial-gradient(circle,rgba(147,51,234,.08) 0%,rgba(219,39,119,.03) 45%,transparent 82%);animation:_ngcontent-%COMP%_floatGlow2 26s ease-in-out infinite alternate}.home-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-3[_ngcontent-%COMP%]{top:280px;left:30%;width:460px;height:460px;background:radial-gradient(circle,rgba(6,182,212,.08) 0%,rgba(59,130,246,.03) 45%,transparent 82%);animation:_ngcontent-%COMP%_floatGlow3 20s ease-in-out infinite alternate}.home-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-pending[_ngcontent-%COMP%]{top:-120px;left:15%;right:15%;margin:0 auto;width:720px;height:520px;background:radial-gradient(circle,rgba(245,158,11,.09) 0%,rgba(217,119,6,.035) 38%,transparent 82%);opacity:0;transition:opacity .8s cubic-bezier(.4,0,.2,1);animation:_ngcontent-%COMP%_readyPulseGlow 9s ease-in-out infinite alternate;pointer-events:none}.home-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-ready[_ngcontent-%COMP%]{top:-120px;left:15%;right:15%;margin:0 auto;width:700px;height:520px;background:radial-gradient(circle,rgba(16,185,129,.14) 0%,rgba(6,182,212,.08) 38%,transparent 82%);opacity:0;transition:opacity 1s cubic-bezier(.4,0,.2,1);animation:_ngcontent-%COMP%_readyPulseGlow 7s ease-in-out infinite alternate;pointer-events:none}.home-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-pro[_ngcontent-%COMP%]{top:-100px;left:20%;right:20%;margin:0 auto;width:680px;height:520px;background:radial-gradient(circle,rgba(99,102,241,.18) 0%,rgba(147,51,234,.08) 38%,transparent 82%);opacity:0;transition:opacity .8s cubic-bezier(.4,0,.2,1);pointer-events:none}.home-container.system-pending[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-pending[_ngcontent-%COMP%]{opacity:1}.home-container.system-pending[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-1[_ngcontent-%COMP%]{background:radial-gradient(circle,rgba(245,158,11,.07) 0%,rgba(99,102,241,.03) 55%,transparent 75%)}.home-container.system-ready[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-pending[_ngcontent-%COMP%]{opacity:0}.home-container.system-ready[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-ready[_ngcontent-%COMP%]{opacity:1}.home-container.system-ready[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-1[_ngcontent-%COMP%]{background:radial-gradient(circle,rgba(16,185,129,.1) 0%,rgba(59,130,246,.05) 55%,transparent 75%)}.home-container.pro-theme-active[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-pro[_ngcontent-%COMP%]{opacity:1}.home-container.pro-theme-active[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-ready[_ngcontent-%COMP%]{opacity:.35}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%]{position:relative;z-index:5;max-width:960px;width:100%;margin:0 auto;padding:36px 24px 60px;display:flex;flex-direction:column;gap:18px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .hero-section[_ngcontent-%COMP%]{text-align:center;padding:16px 0 6px;margin:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .hero-section[_ngcontent-%COMP%] .hero-title[_ngcontent-%COMP%]{font-family:Outfit,Google Sans,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:32px;font-weight:600;letter-spacing:-.035em;line-height:1.2;color:#0f172a;margin:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .hero-section[_ngcontent-%COMP%] .hero-subtitle[_ngcontent-%COMP%]{font-size:14.5px;color:#64748b;font-weight:400;margin:8px 0 0;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%]{display:flex;justify-content:center;margin-bottom:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;width:100%;max-width:520px;box-sizing:border-box;background:#ffffffb8;backdrop-filter:blur(12px) saturate(180%);-webkit-backdrop-filter:blur(12px) saturate(180%);padding:3px;border-radius:9999px;border:1px solid rgba(226,232,240,.85);gap:3px;box-shadow:0 2px 8px -1px #0f172a0f,0 1px 2px #00000005,inset 0 1px 1px #ffffffe6;-webkit-user-select:none;user-select:none;font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;transition:background .25s cubic-bezier(.4,0,.2,1),box-shadow .25s cubic-bezier(.4,0,.2,1),border-color .25s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%]:hover{background:#ffffffd9;box-shadow:0 4px 14px -2px #0f172a14,0 2px 4px #00000005,inset 0 1px 1px #fff;border-color:#cbd5e1e6}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:32px;padding:0 14px;box-sizing:border-box;border:none;background:transparent;border-radius:9999px;cursor:pointer;font-family:inherit;font-size:13px;font-weight:600;color:#475569;line-height:1;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none;white-space:nowrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%] .tab-icon[_ngcontent-%COMP%]{font-size:16px;width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;color:#64748b;transition:color .15s ease,transform .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%] .tab-icon.icon-ready[_ngcontent-%COMP%]{color:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%] .tab-icon.icon-locked[_ngcontent-%COMP%]{color:#94a3b8;font-size:15px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%] .tab-label[_ngcontent-%COMP%]{color:#475569;transition:color .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%]:hover:not(.active){background:#ffffffb3;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%]:hover:not(.active) .tab-icon[_ngcontent-%COMP%]{color:#1e293b}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%]:hover:not(.active) .tab-icon.icon-ready[_ngcontent-%COMP%]{color:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%]:hover:not(.active) .tab-label[_ngcontent-%COMP%]{color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn.active[_ngcontent-%COMP%]{background:#fff!important;color:#0f172a!important;font-weight:700;box-shadow:0 2px 8px -1px #0f172a14,0 1px 2px #0000000a,inset 0 1px #fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn.active[_ngcontent-%COMP%] .tab-icon[_ngcontent-%COMP%]{color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn.active[_ngcontent-%COMP%] .tab-icon.icon-ready[_ngcontent-%COMP%]{color:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn.active[_ngcontent-%COMP%] .tab-label[_ngcontent-%COMP%]{color:#0f172a!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .mode-tabs-container[_ngcontent-%COMP%] .mode-tabs[_ngcontent-%COMP%] .mode-tab-btn[_ngcontent-%COMP%]:active{transform:scale(.98)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:16px;animation:_ngcontent-%COMP%_fadeIn .2s ease-out}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%]{background:#fff;border:1px solid #e2e8f0;border-radius:14px;box-shadow:0 1px 3px #00000008,0 4px 12px #00000005;overflow:hidden;transition:border-color .2s ease,box-shadow .2s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%]:hover{border-color:#cbd5e1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:16px 20px;border-bottom:1px solid #f1f5f9;background:#fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-badge[_ngcontent-%COMP%]{width:32px;height:32px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;font-size:13.5px;font-weight:700;background:#f1f5f9;color:#475569;flex-shrink:0;transition:all .2s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-badge[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-badge[_ngcontent-%COMP%] .step-check-icon[_ngcontent-%COMP%]{font-size:18px;font-weight:700;color:inherit}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-badge.step-pass[_ngcontent-%COMP%]{background:#ecfdf5;color:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-info[_ngcontent-%COMP%]{flex:1;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-info[_ngcontent-%COMP%] .step-title-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;margin-bottom:2px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-info[_ngcontent-%COMP%] .step-title-row[_ngcontent-%COMP%] .step-title[_ngcontent-%COMP%]{margin:0;font-size:15px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-info[_ngcontent-%COMP%] .step-title-row[_ngcontent-%COMP%] .status-pill[_ngcontent-%COMP%]{font-size:11px;font-weight:600;padding:2px 8px;border-radius:12px;line-height:1.3;height:22px;display:inline-flex;align-items:center}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-info[_ngcontent-%COMP%] .step-title-row[_ngcontent-%COMP%] .status-pill.pill-pass[_ngcontent-%COMP%]{background:#ecfdf5;color:#059669;border:1px solid #a7f3d0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-info[_ngcontent-%COMP%] .step-title-row[_ngcontent-%COMP%] .status-pill.pill-warn[_ngcontent-%COMP%]{background:#fffbeb;color:#b45309;border:1px solid #fde68a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-info[_ngcontent-%COMP%] .step-title-row[_ngcontent-%COMP%] .status-pill.pill-fail[_ngcontent-%COMP%]{background:#fef2f2;color:#b91c1c;border:1px solid #fecaca}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .step-info[_ngcontent-%COMP%] .step-desc[_ngcontent-%COMP%]{margin:0;font-size:12.5px;color:#475569;line-height:1.4}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;padding:0 13px;height:32px;background:#ffffffb8;backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(226,232,240,.88);box-shadow:0 2px 8px -1px #0f172a0d,inset 0 1px 1px #fffffff2;color:#475569;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%]:hover:not(:disabled), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%]:hover:not(:disabled){background:#ffffffeb;border-color:#bfdbfef2;color:#1a73e8;box-shadow:0 4px 12px -2px #0f172a14,inset 0 1px 1px #fff;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%]:hover:not(:disabled) .material-symbols-outlined[_ngcontent-%COMP%]:not(.feedback-done), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%]:hover:not(:disabled) .material-symbols-outlined[_ngcontent-%COMP%]:not(.feedback-done){color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%]:active:not(:disabled), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%]:disabled, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%]:disabled{opacity:.55;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%]{border-radius:8px;font-family:inherit;font-size:12px;font-weight:600;cursor:pointer;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px;color:#64748b;transition:transform .2s ease,color .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%] .feedback-done[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%] .feedback-done[_ngcontent-%COMP%]{color:#059669!important;font-size:16px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%] .feedback-text[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%] .feedback-text[_ngcontent-%COMP%]{color:#059669;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-restart-adb[_ngcontent-%COMP%] .spinning[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-header[_ngcontent-%COMP%] .btn-header-action[_ngcontent-%COMP%] .spinning[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_spin 1s linear infinite}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .guide-card[_ngcontent-%COMP%] .guide-card-body[_ngcontent-%COMP%]{padding:18px 20px;display:flex;flex-direction:column;gap:14px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%]{background:#f0f9ff;border:1px solid #bae6fd;border-radius:10px;padding:12px 16px;display:flex;align-items:center;justify-content:space-between;gap:14px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:12px;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-icon-box[_ngcontent-%COMP%]{width:32px;height:32px;border-radius:8px;background:#0284c7;color:#fff;display:flex;align-items:center;justify-content:center;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-icon-box[_ngcontent-%COMP%] .bolt-icon[_ngcontent-%COMP%]{font-size:18px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-text[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:2px;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-text[_ngcontent-%COMP%] .install-bar-title-row[_ngcontent-%COMP%]{display:flex;align-items:center;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-text[_ngcontent-%COMP%] .install-bar-title-row[_ngcontent-%COMP%] .install-bar-title[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-text[_ngcontent-%COMP%] .install-bar-title-row[_ngcontent-%COMP%] .os-selector-pills[_ngcontent-%COMP%]{display:inline-flex;align-items:center;background:#ffffffa6;backdrop-filter:blur(12px) saturate(180%);-webkit-backdrop-filter:blur(12px) saturate(180%);border:1px solid rgba(226,232,240,.85);border-radius:8px;padding:2px;gap:2px;box-shadow:0 1px 3px #0f172a0a,inset 0 1px 1px #fffc}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-text[_ngcontent-%COMP%] .install-bar-title-row[_ngcontent-%COMP%] .os-selector-pills[_ngcontent-%COMP%] .os-pill[_ngcontent-%COMP%]{border:none;background:transparent;font-size:11px;font-weight:600;color:#475569;padding:3px 9px;border-radius:6px;cursor:pointer;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-text[_ngcontent-%COMP%] .install-bar-title-row[_ngcontent-%COMP%] .os-selector-pills[_ngcontent-%COMP%] .os-pill[_ngcontent-%COMP%]:hover{color:#0f172a;background:#ffffff80}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-text[_ngcontent-%COMP%] .install-bar-title-row[_ngcontent-%COMP%] .os-selector-pills[_ngcontent-%COMP%] .os-pill.active[_ngcontent-%COMP%]{background:#1a73e8eb;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);color:#fff!important;box-shadow:0 2px 6px #1a73e84d,inset 0 1px 1px #ffffff59}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .install-bar-left[_ngcontent-%COMP%] .install-bar-text[_ngcontent-%COMP%] .install-bar-desc[_ngcontent-%COMP%]{font-size:12px;color:#475569;line-height:1.4;margin-top:2px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%]{margin:0;flex-shrink:0}@media(max-width:860px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .one-click-install-bar[_ngcontent-%COMP%]{flex-direction:column;align-items:stretch}}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}@media(max-width:640px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%]{grid-template-columns:1fr}}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%]{background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:12px 14px;display:flex;flex-direction:column;justify-content:center;gap:8px;transition:border-color .18s ease,box-shadow .18s ease;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%]:hover{border-color:#cbd5e1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-icon-box[_ngcontent-%COMP%]{width:32px;height:32px;border-radius:8px;background:#f8fafc;border:1px solid #e2e8f0;color:#475569;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-icon-box[_ngcontent-%COMP%] .item-icon[_ngcontent-%COMP%]{font-size:17px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-title-group[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-title-group[_ngcontent-%COMP%] .item-name[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#0f172a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-title-group[_ngcontent-%COMP%] .item-subtitle[_ngcontent-%COMP%]{font-size:11.5px;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-status[_ngcontent-%COMP%]{display:flex;align-items:center;margin-left:auto;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-status[_ngcontent-%COMP%] .status-dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-status[_ngcontent-%COMP%] .status-dot.dot-pass[_ngcontent-%COMP%]{background:#10b981}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-status[_ngcontent-%COMP%] .status-dot.dot-fail[_ngcontent-%COMP%]{background:#ef4444}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-status[_ngcontent-%COMP%] .status-dot.dot-warn[_ngcontent-%COMP%]{background:#f59e0b}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-body[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card[_ngcontent-%COMP%] .item-body[_ngcontent-%COMP%] .item-action-box[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:4px;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card.item-fail[_ngcontent-%COMP%]{background:#fff8f8;border-color:#fecaca}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .env-matrix-grid[_ngcontent-%COMP%] .env-item-card.item-fail[_ngcontent-%COMP%] .item-icon-box[_ngcontent-%COMP%]{background:#fef2f2;color:#dc2626;border-color:#fecaca}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%]{border:1px solid #e2e8f0;border-radius:10px;padding:14px 16px;background:#f8fafc;cursor:pointer;transition:all .18s ease;-webkit-user-select:none;user-select:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-radio[_ngcontent-%COMP%]{margin-top:2px;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-radio[_ngcontent-%COMP%] .radio-dot[_ngcontent-%COMP%]{display:block;width:16px;height:16px;border-radius:50%;border:1.5px solid #cbd5e1;background:#fff;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-radio[_ngcontent-%COMP%] .radio-dot.checked[_ngcontent-%COMP%]{border-color:#1a73e8;background:#1a73e8;box-shadow:inset 0 0 0 3px #fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-icon-wrap[_ngcontent-%COMP%]{width:34px;height:34px;border-radius:8px;background:#fff;border:1px solid #e2e8f0;display:flex;align-items:center;justify-content:center;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-icon-wrap[_ngcontent-%COMP%] .brand-svg[_ngcontent-%COMP%]{width:18px;height:18px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-icon-wrap.icon-gear[_ngcontent-%COMP%]{color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-icon-wrap.icon-gear[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:18px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-text[_ngcontent-%COMP%]{flex:1;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-text[_ngcontent-%COMP%] .choice-title-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-text[_ngcontent-%COMP%] .choice-title-row[_ngcontent-%COMP%] .choice-title[_ngcontent-%COMP%]{font-size:13.5px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-text[_ngcontent-%COMP%] .choice-title-row[_ngcontent-%COMP%] .tag-badge[_ngcontent-%COMP%]{font-size:10.5px;font-weight:600;padding:1px 7px;border-radius:10px;line-height:1.3}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-text[_ngcontent-%COMP%] .choice-title-row[_ngcontent-%COMP%] .tag-badge.tag-rec[_ngcontent-%COMP%]{background:#eff6ff;color:#1a73e8;border:1px solid #bfdbfe}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-text[_ngcontent-%COMP%] .choice-title-row[_ngcontent-%COMP%] .tag-badge.tag-ready[_ngcontent-%COMP%]{background:#ecfdf5;color:#059669;border:1px solid #a7f3d0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-text[_ngcontent-%COMP%] .choice-desc[_ngcontent-%COMP%]{margin:3px 0 0;font-size:12px;color:#475569;line-height:1.4}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%] .choice-card-top[_ngcontent-%COMP%] .choice-text[_ngcontent-%COMP%] .choice-desc[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;background:#fff;border:1px solid #e2e8f0;padding:1px 4px;border-radius:4px;color:#1557b0;font-size:11px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card[_ngcontent-%COMP%]:hover:not(.selected){border-color:#cbd5e1;background:#fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card.selected[_ngcontent-%COMP%]{border-color:#1a73e8;background:#fff;box-shadow:0 0 0 1px #1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card.selected[_ngcontent-%COMP%] .choice-icon-wrap[_ngcontent-%COMP%]{border-color:#bfdbfe}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .model-choice-cards-row[_ngcontent-%COMP%] .choice-card.selected[_ngcontent-%COMP%] .choice-icon-wrap.icon-gear[_ngcontent-%COMP%]{color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%]{background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:14px 16px;display:flex;flex-direction:column;gap:10px;animation:_ngcontent-%COMP%_fadeIn .15s ease-out}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box.ocr-box[_ngcontent-%COMP%]{background:#fff;border:1px solid #e2e8f0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .input-box-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .input-box-header[_ngcontent-%COMP%] .header-label[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;font-size:12.5px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .input-box-header[_ngcontent-%COMP%] .header-label[_ngcontent-%COMP%] .label-icon[_ngcontent-%COMP%]{font-size:16px;color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .input-box-header[_ngcontent-%COMP%] .btn-header-link[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;font-weight:600;color:#1a73e8;text-decoration:none;padding:3px 10px;height:26px;background:#eff6ffbf;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(191,219,254,.85);border-radius:6px;box-shadow:0 1px 3px #2563eb0f,inset 0 1px 1px #fffc;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .input-box-header[_ngcontent-%COMP%] .btn-header-link[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:13px;color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .input-box-header[_ngcontent-%COMP%] .btn-header-link[_ngcontent-%COMP%]:hover{background:#dbeafee6;color:#1557b0;border-color:#1a73e8;box-shadow:0 2px 6px #2563eb26;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%]{flex:1 1 260px;min-width:0;display:flex;align-items:center;background:#ffffffbf;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid #e2e8f0;border-radius:8px;padding:0 10px;height:36px;transition:border-color .15s ease,box-shadow .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%]:focus-within{border-color:#1a73e8;box-shadow:0 0 0 2px #1a73e81f}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%] .key-prefix-icon[_ngcontent-%COMP%]{font-size:16px;color:#94a3b8;margin-right:6px;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%] .unified-key-input[_ngcontent-%COMP%]{flex:1;min-width:0;border:none;outline:none;font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:12.5px;color:#0f172a;background:transparent;padding:4px 0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%] .unified-key-input.is-masked[_ngcontent-%COMP%]{letter-spacing:2px;font-weight:700;font-size:13px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%] .unified-key-input[_ngcontent-%COMP%]::placeholder{color:#94a3b8;font-family:Google Sans Text,Google Sans,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:12px;letter-spacing:normal;font-weight:400}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%] .btn-icon-action[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:center;width:26px;height:26px;background:transparent;border:none;border-radius:4px;color:#64748b;cursor:pointer;transition:all .15s ease;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%] .btn-icon-action[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%] .btn-icon-action[_ngcontent-%COMP%] .text-emerald[_ngcontent-%COMP%]{color:#059669!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .unified-key-wrapper[_ngcontent-%COMP%] .btn-icon-action[_ngcontent-%COMP%]:hover{background:#f1f5f9cc;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:5px;padding:0 18px;height:36px;background:linear-gradient(135deg,#1a73e8eb,#2563ebd9);backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(255,255,255,.28);box-shadow:0 4px 14px #1a73e852,inset 0 1px 1px #ffffff73;color:#fff!important;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%] .run-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%]:hover:not(:disabled){background:linear-gradient(135deg,#1a73e8,#2563ebf2);box-shadow:0 6px 20px #1a73e86b,inset 0 1px 1px #fff9;transform:translateY(-1px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97) translateY(0);box-shadow:0 2px 8px #1a73e859}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%]:disabled{background:#94a3b880;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);box-shadow:none;opacity:.65;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%]{border-radius:8px;font-family:inherit;font-size:12.5px;font-weight:600;cursor:pointer;white-space:nowrap;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:16px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-save[_ngcontent-%COMP%] .spin[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_spin 1s linear infinite}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-test[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:0 15px;height:36px;background:#eff6ffb3;backdrop-filter:blur(14px) saturate(180%);-webkit-backdrop-filter:blur(14px) saturate(180%);color:#1a73e8;border:1px solid rgba(191,219,254,.85);border-radius:8px;box-shadow:0 2px 6px -1px #2563eb14,inset 0 1px 1px #ffffffe6;font-family:inherit;font-size:12.5px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-test[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px;color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-test[_ngcontent-%COMP%]:hover:not(:disabled){background:#dbeafee6;border-color:#1a73e8;color:#1557b0;box-shadow:0 4px 12px -2px #2563eb26,inset 0 1px 1px #fff;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-test[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-test[_ngcontent-%COMP%]:disabled{opacity:.55;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .unified-key-row[_ngcontent-%COMP%] .btn-unified-test[_ngcontent-%COMP%] .spin[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_spin 1s linear infinite}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .feedback-msg[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;padding:6px 10px;border-radius:6px;font-size:12px;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .feedback-msg[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .feedback-msg.success[_ngcontent-%COMP%]{background:#ecfdf5;color:#047857;border:1px solid #a7f3d0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .credentials-input-box[_ngcontent-%COMP%] .feedback-msg.error[_ngcontent-%COMP%]{background:#fef2f2;color:#b91c1c;border:1px solid #fecaca}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%]{background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;margin-top:2px;transition:border-color .18s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:#fff;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%]:hover{background:#f8fafc}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%] .toggle-bar-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%] .toggle-bar-left[_ngcontent-%COMP%] .icon-ocr[_ngcontent-%COMP%]{font-size:18px;color:#1a73e8;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%] .toggle-bar-left[_ngcontent-%COMP%] .toggle-bar-titles[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%] .toggle-bar-left[_ngcontent-%COMP%] .toggle-bar-titles[_ngcontent-%COMP%] .ocr-main-title[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%] .toggle-bar-right[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%] .toggle-bar-right[_ngcontent-%COMP%] .status-dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%] .toggle-bar-right[_ngcontent-%COMP%] .status-dot.dot-pass[_ngcontent-%COMP%]{background:#10b981}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-card-toggle-bar[_ngcontent-%COMP%] .toggle-bar-right[_ngcontent-%COMP%] .caret-icon[_ngcontent-%COMP%]{font-size:18px;color:#64748b;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-content-body[_ngcontent-%COMP%]{padding:12px 14px;border-top:1px solid #f1f5f9;display:flex;flex-direction:column;gap:10px;background:#f8fafc;animation:_ngcontent-%COMP%_fadeIn .15s ease-out}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-content-body[_ngcontent-%COMP%] .ocr-help-desc[_ngcontent-%COMP%]{margin:0;font-size:12px;color:#475569;line-height:1.45}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ocr-enhancement-card[_ngcontent-%COMP%] .ocr-content-body[_ngcontent-%COMP%] .credentials-input-box.ocr-box[_ngcontent-%COMP%]{margin:0;padding:12px;background:#fff;border:1px solid #e2e8f0;border-radius:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px;animation:_ngcontent-%COMP%_fadeIn .15s ease-out}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%]{background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;padding:10px 14px;background:#fff;border-bottom:1px solid #f1f5f9}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .inspector-header-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .inspector-header-left[_ngcontent-%COMP%] .header-icon[_ngcontent-%COMP%]{font-size:18px;color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .inspector-header-left[_ngcontent-%COMP%] .inspector-header-titles[_ngcontent-%COMP%]{display:flex;flex-direction:column}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .inspector-header-left[_ngcontent-%COMP%] .inspector-header-titles[_ngcontent-%COMP%] .inspector-title[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .inspector-header-left[_ngcontent-%COMP%] .inspector-header-titles[_ngcontent-%COMP%] .inspector-subtitle[_ngcontent-%COMP%]{font-size:11.5px;color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .inspector-header-left[_ngcontent-%COMP%] .inspector-header-titles[_ngcontent-%COMP%] .inspector-subtitle[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;background:#f1f5f9;padding:1px 4px;border-radius:4px;color:#1557b0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .inspector-header-actions[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .btn-file-action[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:0 10px;height:28px;background:#ffffffb8;backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(226,232,240,.88);box-shadow:0 2px 8px -1px #0f172a0d,inset 0 1px 1px #fffffff2;color:#475569;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .btn-file-action[_ngcontent-%COMP%]:hover:not(:disabled){background:#ffffffeb;border-color:#bfdbfef2;color:#1a73e8;box-shadow:0 4px 12px -2px #0f172a14,inset 0 1px 1px #fff;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .btn-file-action[_ngcontent-%COMP%]:hover:not(:disabled) .material-symbols-outlined[_ngcontent-%COMP%]:not(.feedback-done){color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .btn-file-action[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .btn-file-action[_ngcontent-%COMP%]:disabled{opacity:.55;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .btn-file-action[_ngcontent-%COMP%]{border-radius:6px;font-family:inherit;font-size:11.5px;font-weight:600;cursor:pointer}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .btn-file-action[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:13px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .btn-file-action.btn-toggle-code[_ngcontent-%COMP%]{background:#eff6ffbf;color:#1a73e8;border-color:#bfdbfed9}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-card-header[_ngcontent-%COMP%] .btn-file-action.btn-toggle-code[_ngcontent-%COMP%]:hover{background:#dbeafee6;color:#1557b0;border-color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-summary-row[_ngcontent-%COMP%]{display:flex;flex-wrap:wrap;gap:12px;padding:12px 14px;background:#fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-summary-row[_ngcontent-%COMP%] .summary-metric[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:4px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-summary-row[_ngcontent-%COMP%] .summary-metric[_ngcontent-%COMP%] .metric-label[_ngcontent-%COMP%]{font-size:10.5px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:.5px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-summary-row[_ngcontent-%COMP%] .summary-metric[_ngcontent-%COMP%] .metric-val-pill[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;padding:4px 10px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:12px;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-summary-row[_ngcontent-%COMP%] .summary-metric[_ngcontent-%COMP%] .metric-val-pill[_ngcontent-%COMP%] .provider-dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%;background:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-summary-row[_ngcontent-%COMP%] .summary-metric[_ngcontent-%COMP%] .metric-val-pill[_ngcontent-%COMP%] .provider-name[_ngcontent-%COMP%]{font-weight:700;color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-summary-row[_ngcontent-%COMP%] .summary-metric[_ngcontent-%COMP%] .metric-val-pill[_ngcontent-%COMP%] .model-divider[_ngcontent-%COMP%]{color:#94a3b8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-summary-row[_ngcontent-%COMP%] .summary-metric[_ngcontent-%COMP%] .metric-val-pill[_ngcontent-%COMP%] .model-name[_ngcontent-%COMP%]{font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .inspector-summary-row[_ngcontent-%COMP%] .summary-metric[_ngcontent-%COMP%] .metric-val-pill.secondary[_ngcontent-%COMP%]{background:#f8fafc;color:#475569;font-size:11.5px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .jsonc-viewer-box[_ngcontent-%COMP%]{border-top:1px solid #e2e8f0;background:#0f172a;max-height:260px;overflow-y:auto;padding:12px 14px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .jsonc-viewer-box[_ngcontent-%COMP%] .jsonc-code[_ngcontent-%COMP%]{margin:0;font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:11.5px;line-height:1.5;color:#e2e8f0;white-space:pre-wrap;word-break:break-all}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%]{display:flex;flex-direction:column}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;padding:8px 14px;border-bottom:1px solid #f1f5f9;transition:background .12s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%]:last-child{border-bottom:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%]:hover{background:#f8fafc}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%] .env-name-col[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%] .env-name-col[_ngcontent-%COMP%] .env-key-name[_ngcontent-%COMP%]{font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:12px;font-weight:600;color:#0f172a;background:#f1f5f9;padding:2px 6px;border-radius:4px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%] .env-status-col[_ngcontent-%COMP%]{display:flex;align-items:center}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%] .env-status-col[_ngcontent-%COMP%] .badge-env-pass[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;color:#059669;background:#ecfdf5;border:1px solid #a7f3d0;padding:2px 7px;border-radius:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%] .env-status-col[_ngcontent-%COMP%] .badge-env-pass[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:13px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%] .env-status-col[_ngcontent-%COMP%] .badge-env-pass[_ngcontent-%COMP%] .key-preview[_ngcontent-%COMP%]{font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:10.5px;color:#047857;margin-left:2px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%] .env-status-col[_ngcontent-%COMP%] .badge-env-unset[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;color:#94a3b8;background:#f8fafc;border:1px solid #e2e8f0;padding:2px 7px;border-radius:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .custom-config-inspector[_ngcontent-%COMP%] .inspector-card[_ngcontent-%COMP%] .env-keys-table[_ngcontent-%COMP%] .env-key-row[_ngcontent-%COMP%] .env-status-col[_ngcontent-%COMP%] .badge-env-unset[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:13px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%]{display:flex;align-items:center;gap:16px;padding:16px 20px;background:#fff;border:1px solid #e2e8f0;border-radius:12px;box-shadow:0 1px 3px #00000005,0 4px 12px #00000005;transition:all .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%]:hover{border-color:#cbd5e1;box-shadow:0 2px 6px #0000000a,0 8px 18px #00000008}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%] .device-avatar[_ngcontent-%COMP%]{width:44px;height:44px;border-radius:10px;background:#f1f5f9;border:1px solid #e2e8f0;color:#334155;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .2s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%] .device-avatar[_ngcontent-%COMP%] .device-hero-icon[_ngcontent-%COMP%]{font-size:22px;color:#334155!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%] .device-hero-details[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%] .device-hero-details[_ngcontent-%COMP%] .device-hero-name[_ngcontent-%COMP%]{font-size:14.5px;font-weight:600;color:#0f172a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%] .device-hero-details[_ngcontent-%COMP%] .device-hero-meta[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;font-size:12px;color:#64748b;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%] .device-hero-details[_ngcontent-%COMP%] .device-hero-meta[_ngcontent-%COMP%] .meta-dot[_ngcontent-%COMP%]{color:#94a3b8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%] .device-hero-details[_ngcontent-%COMP%] .device-hero-meta[_ngcontent-%COMP%] .remote-endpoint-label[_ngcontent-%COMP%]{color:#1a73e8;font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:11px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%] .device-hero-status[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:500;color:#047857;margin-left:auto;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .device-hero-card[_ngcontent-%COMP%] .device-hero-status[_ngcontent-%COMP%] .status-dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%;background:#10b981;box-shadow:0 0 #10b981b3;animation:_ngcontent-%COMP%_statusDotPulse 2s infinite cubic-bezier(.4,0,.6,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .multi-device-switcher[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:5px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .multi-device-switcher[_ngcontent-%COMP%] .switcher-label[_ngcontent-%COMP%]{font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:.5px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .multi-device-switcher[_ngcontent-%COMP%] .switcher-chips[_ngcontent-%COMP%]{display:flex;flex-wrap:wrap;gap:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .multi-device-switcher[_ngcontent-%COMP%] .switcher-chips[_ngcontent-%COMP%] .device-chip-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;padding:0 10px;height:30px;background:#fff;border:1px solid #e2e8f0;border-radius:6px;font-family:inherit;font-size:11.5px;font-weight:600;color:#475569;cursor:pointer;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .multi-device-switcher[_ngcontent-%COMP%] .switcher-chips[_ngcontent-%COMP%] .device-chip-btn[_ngcontent-%COMP%] .chip-icon[_ngcontent-%COMP%]{font-size:14px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .multi-device-switcher[_ngcontent-%COMP%] .switcher-chips[_ngcontent-%COMP%] .device-chip-btn[_ngcontent-%COMP%] .active-check[_ngcontent-%COMP%]{color:#059669;font-size:10.5px;font-weight:700}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .multi-device-switcher[_ngcontent-%COMP%] .switcher-chips[_ngcontent-%COMP%] .device-chip-btn.selected[_ngcontent-%COMP%]{background:#ecfdf5;border-color:#059669;color:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .connected-device-panel[_ngcontent-%COMP%] .multi-device-switcher[_ngcontent-%COMP%] .switcher-chips[_ngcontent-%COMP%] .device-chip-btn[_ngcontent-%COMP%]:hover:not(.selected){background:#f8fafc;border-color:#cbd5e1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-container[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px;margin-bottom:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:16px;padding:20px;background:linear-gradient(180deg,#fff,#f8fafc);border:1.5px solid rgba(37,99,235,.25);border-radius:12px;box-shadow:0 4px 16px #2563eb0f}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%]{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-title-group[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:12px;flex:1;min-width:260px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-title-group[_ngcontent-%COMP%] .tracker-icon-box[_ngcontent-%COMP%]{width:36px;height:36px;border-radius:10px;background:#2563eb1a;color:#1a73e8;display:flex;align-items:center;justify-content:center;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-title-group[_ngcontent-%COMP%] .tracker-icon-box[_ngcontent-%COMP%] .spinning-icon[_ngcontent-%COMP%]{font-size:20px;animation:_ngcontent-%COMP%_spin 1.2s linear infinite}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-title-group[_ngcontent-%COMP%] .tracker-titles[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:4px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-title-group[_ngcontent-%COMP%] .tracker-titles[_ngcontent-%COMP%] .tracker-main-heading[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-title-group[_ngcontent-%COMP%] .tracker-titles[_ngcontent-%COMP%] .tracker-main-heading[_ngcontent-%COMP%] .tracker-title[_ngcontent-%COMP%]{margin:0;font-size:15px;font-weight:700;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-title-group[_ngcontent-%COMP%] .tracker-titles[_ngcontent-%COMP%] .tracker-main-heading[_ngcontent-%COMP%] .tracker-title[_ngcontent-%COMP%] .avd-highlight[_ngcontent-%COMP%]{color:#1a73e8;font-family:JetBrains Mono,monospace,sans-serif}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-title-group[_ngcontent-%COMP%] .tracker-titles[_ngcontent-%COMP%] .tracker-main-heading[_ngcontent-%COMP%] .stage-tag-badge[_ngcontent-%COMP%]{display:inline-flex;align-items:center;padding:2px 8px;border-radius:12px;background:#2563eb1f;color:#1a73e8;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-title-group[_ngcontent-%COMP%] .tracker-titles[_ngcontent-%COMP%] .tracker-subtitle[_ngcontent-%COMP%]{margin:0;font-size:13px;color:#475569;line-height:1.4}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-toggle-logs[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;padding:6px 13px;background:#ffffffb8;backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(226,232,240,.88);box-shadow:0 2px 8px -1px #0f172a0d,inset 0 1px 1px #fffffff2;color:#475569;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-toggle-logs[_ngcontent-%COMP%]:hover:not(:disabled){background:#ffffffeb;border-color:#bfdbfef2;color:#1a73e8;box-shadow:0 4px 12px -2px #0f172a14,inset 0 1px 1px #fff;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-toggle-logs[_ngcontent-%COMP%]:hover:not(:disabled) .material-symbols-outlined[_ngcontent-%COMP%]:not(.feedback-done){color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-toggle-logs[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-toggle-logs[_ngcontent-%COMP%]:disabled{opacity:.55;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-toggle-logs[_ngcontent-%COMP%]{border-radius:6px;font-size:12px;font-weight:600;cursor:pointer}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-toggle-logs[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-toggle-logs.active[_ngcontent-%COMP%]{background:#eff6ffe6;color:#1a73e8;border-color:#2563eb66;box-shadow:0 2px 6px #2563eb1f}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-stop-emu[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;padding:6px 13px;background:#fef2f2bf;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(254,202,202,.85);border-radius:6px;color:#dc2626;font-size:12px;font-weight:600;cursor:pointer;box-shadow:0 1px 3px #dc26260f,inset 0 1px 1px #fffc;transition:all .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-stop-emu[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-stop-emu[_ngcontent-%COMP%]:hover{background:#fee2e2f2;border-color:#dc2626;box-shadow:0 4px 12px -2px #dc262626;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .tracker-header[_ngcontent-%COMP%] .tracker-actions[_ngcontent-%COMP%] .btn-stop-emu[_ngcontent-%COMP%]:active{transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:#fff;border:1px solid #e2e8f0;border-radius:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-item[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:600;color:#64748b}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-item[_ngcontent-%COMP%] .step-circle[_ngcontent-%COMP%]{width:22px;height:22px;border-radius:50%;background:#f1f5f9;border:1.5px solid #e2e8f0;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;color:#64748b;transition:all .2s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-item[_ngcontent-%COMP%] .step-circle[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%]{font-size:14px;color:#fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-item[_ngcontent-%COMP%] .step-circle[_ngcontent-%COMP%] .spinner-tiny[_ngcontent-%COMP%]{width:11px;height:11px;border:2px solid rgba(37,99,235,.3);border-top-color:#1a73e8;border-radius:50%;animation:_ngcontent-%COMP%_spin .8s linear infinite}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-item[_ngcontent-%COMP%] .step-label[_ngcontent-%COMP%]{white-space:nowrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-item.active[_ngcontent-%COMP%]{color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-item.active[_ngcontent-%COMP%] .step-circle[_ngcontent-%COMP%]{border-color:#1a73e8;background:#2563eb1a;color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-item.done[_ngcontent-%COMP%]{color:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-item.done[_ngcontent-%COMP%] .step-circle[_ngcontent-%COMP%]{border-color:#059669;background:#059669;color:#fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-line[_ngcontent-%COMP%]{flex:1;height:2px;background:#e2e8f0;margin:0 10px;border-radius:2px;transition:all .3s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-stepper[_ngcontent-%COMP%] .step-line.done[_ngcontent-%COMP%]{background:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .progress-bar-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .progress-bar-container[_ngcontent-%COMP%] .progress-bar-track[_ngcontent-%COMP%]{width:100%;height:8px;background:#e2e8f0;border-radius:6px;overflow:hidden}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .progress-bar-container[_ngcontent-%COMP%] .progress-bar-track[_ngcontent-%COMP%] .progress-bar-fill[_ngcontent-%COMP%]{height:100%;background:linear-gradient(90deg,#3b82f6,#10b981);border-radius:6px;transition:width .4s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .progress-bar-container[_ngcontent-%COMP%] .progress-bar-meta[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;font-size:12px;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .progress-bar-container[_ngcontent-%COMP%] .progress-bar-meta[_ngcontent-%COMP%] .progress-percent[_ngcontent-%COMP%]{color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .progress-bar-container[_ngcontent-%COMP%] .progress-bar-meta[_ngcontent-%COMP%] .progress-timer[_ngcontent-%COMP%]{display:flex;align-items:center;gap:4px;color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .progress-bar-container[_ngcontent-%COMP%] .progress-bar-meta[_ngcontent-%COMP%] .progress-timer[_ngcontent-%COMP%] .timer-icon[_ngcontent-%COMP%]{font-size:14px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-tip-banner[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:8px 12px;background:#2563eb0d;border-left:3px solid #1a73e8;border-radius:0 6px 6px 0;font-size:12px;color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-tip-banner[_ngcontent-%COMP%] .tip-icon[_ngcontent-%COMP%]{font-size:16px;color:#1a73e8;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%]{display:flex;flex-direction:column;border:1px solid #1e293b;border-radius:8px;background:#0f172a;overflow:hidden}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%] .logs-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:#1e293b;color:#94a3b8;font-size:12px;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%] .logs-header[_ngcontent-%COMP%] .logs-header-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%] .logs-header[_ngcontent-%COMP%] .logs-header-left[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:14px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%] .logs-header[_ngcontent-%COMP%] .btn-copy-logs[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;background:#334155;border:none;border-radius:4px;color:#f8fafc;font-size:11px;font-weight:600;cursor:pointer}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%] .logs-header[_ngcontent-%COMP%] .btn-copy-logs[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%] .logs-header[_ngcontent-%COMP%] .btn-copy-logs[_ngcontent-%COMP%]:hover{background:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%] .logs-body[_ngcontent-%COMP%]{margin:0;padding:12px;max-height:180px;overflow-y:auto;font-family:JetBrains Mono,monospace,sans-serif;font-size:11px;line-height:1.5;color:#cbd5e1;white-space:pre-wrap;word-break:break-all}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%] .logs-body[_ngcontent-%COMP%] .log-line[_ngcontent-%COMP%]{margin-bottom:2px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-boot-tracker-card[_ngcontent-%COMP%] .boot-logs-drawer[_ngcontent-%COMP%] .logs-body[_ngcontent-%COMP%] .log-empty[_ngcontent-%COMP%]{color:#64748b;font-style:italic}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:14px;padding:18px 20px;background:#fff8f8;border:1.5px solid rgba(239,68,68,.3);border-radius:12px;box-shadow:0 4px 14px #ef44440f}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-header[_ngcontent-%COMP%]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-header[_ngcontent-%COMP%] .failed-header-left[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-header[_ngcontent-%COMP%] .failed-header-left[_ngcontent-%COMP%] .failed-icon-box[_ngcontent-%COMP%]{width:34px;height:34px;border-radius:8px;background:#ef44441f;color:#dc2626;display:flex;align-items:center;justify-content:center;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-header[_ngcontent-%COMP%] .failed-header-left[_ngcontent-%COMP%] .failed-icon-box[_ngcontent-%COMP%] .failed-icon[_ngcontent-%COMP%]{font-size:20px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-header[_ngcontent-%COMP%] .failed-header-left[_ngcontent-%COMP%] .failed-titles[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:2px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-header[_ngcontent-%COMP%] .failed-header-left[_ngcontent-%COMP%] .failed-titles[_ngcontent-%COMP%] .failed-title[_ngcontent-%COMP%]{margin:0;font-size:15px;font-weight:700;color:#dc2626}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-header[_ngcontent-%COMP%] .failed-header-left[_ngcontent-%COMP%] .failed-titles[_ngcontent-%COMP%] .failed-desc[_ngcontent-%COMP%]{margin:0;font-size:13px;color:#0f172a;line-height:1.4}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-header[_ngcontent-%COMP%] .btn-dismiss-failed[_ngcontent-%COMP%]{background:transparent;border:none;color:#64748b;cursor:pointer;padding:4px;border-radius:4px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-header[_ngcontent-%COMP%] .btn-dismiss-failed[_ngcontent-%COMP%]:hover{background:#0000000d;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-logs-box[_ngcontent-%COMP%]{display:flex;flex-direction:column;background:#1e1e2e;border-radius:8px;overflow:hidden}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-logs-box[_ngcontent-%COMP%] .logs-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;background:#282a36;color:#f55;font-size:11px;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-logs-box[_ngcontent-%COMP%] .logs-header[_ngcontent-%COMP%] .btn-copy-logs[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;background:#44475a;border:none;border-radius:4px;color:#f8fafc;font-size:10px;cursor:pointer}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-logs-box[_ngcontent-%COMP%] .failed-logs-pre[_ngcontent-%COMP%]{margin:0;padding:10px 12px;max-height:120px;overflow-y:auto;font-family:JetBrains Mono,monospace;font-size:11px;line-height:1.4;color:#f8f8f2;white-space:pre-wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;padding:6px 16px;background:linear-gradient(135deg,#1a73e8eb,#2563ebd9);backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(255,255,255,.28);box-shadow:0 4px 14px #1a73e852,inset 0 1px 1px #ffffff73;color:#fff!important;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%] .run-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%]:hover:not(:disabled){background:linear-gradient(135deg,#1a73e8,#2563ebf2);box-shadow:0 6px 20px #1a73e86b,inset 0 1px 1px #fff9;transform:translateY(-1px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97) translateY(0);box-shadow:0 2px 8px #1a73e859}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%]:disabled{background:#94a3b880;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);box-shadow:none;opacity:.65;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%]{border-radius:6px;font-size:12px;font-weight:600;cursor:pointer}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-retry-launch[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-restart-adb-sub[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;background:#ffffffb8;backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(226,232,240,.88);box-shadow:0 2px 8px -1px #0f172a0d,inset 0 1px 1px #fffffff2;color:#475569;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-restart-adb-sub[_ngcontent-%COMP%]:hover:not(:disabled){background:#ffffffeb;border-color:#bfdbfef2;color:#1a73e8;box-shadow:0 4px 12px -2px #0f172a14,inset 0 1px 1px #fff;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-restart-adb-sub[_ngcontent-%COMP%]:hover:not(:disabled) .material-symbols-outlined[_ngcontent-%COMP%]:not(.feedback-done){color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-restart-adb-sub[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-restart-adb-sub[_ngcontent-%COMP%]:disabled{opacity:.55;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-restart-adb-sub[_ngcontent-%COMP%]{border-radius:6px;font-size:12px;font-weight:600;cursor:pointer}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-restart-adb-sub[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-dismiss-flat[_ngcontent-%COMP%]{background:transparent;border:none;color:#475569;font-size:12px;font-weight:600;cursor:pointer;padding:6px 10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .emulator-failed-card[_ngcontent-%COMP%] .failed-actions-bar[_ngcontent-%COMP%] .btn-dismiss-flat[_ngcontent-%COMP%]:hover{text-decoration:underline}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}@media(max-width:1100px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%]{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:620px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%]{grid-template-columns:1fr}}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;cursor:pointer;text-align:left;transition:all .18s ease;outline:none;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-left[_ngcontent-%COMP%] .method-icon-box[_ngcontent-%COMP%]{width:32px;height:32px;border-radius:8px;background:#fff;border:1px solid #e2e8f0;color:#475569;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-left[_ngcontent-%COMP%] .method-icon-box[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:17px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-left[_ngcontent-%COMP%] .method-info[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-left[_ngcontent-%COMP%] .method-info[_ngcontent-%COMP%] .method-title-row[_ngcontent-%COMP%]{display:flex;align-items:center}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-left[_ngcontent-%COMP%] .method-info[_ngcontent-%COMP%] .method-title-row[_ngcontent-%COMP%] .method-title[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-left[_ngcontent-%COMP%] .method-info[_ngcontent-%COMP%] .method-desc[_ngcontent-%COMP%]{font-size:11.5px;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-right[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-left:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-right[_ngcontent-%COMP%] .radio-indicator[_ngcontent-%COMP%]{width:16px;height:16px;border-radius:50%;border:1.5px solid #cbd5e1;background:#fff;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%] .method-card-right[_ngcontent-%COMP%] .radio-indicator.checked[_ngcontent-%COMP%]{border-color:#1a73e8;background:#1a73e8;box-shadow:inset 0 0 0 3px #fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card.active[_ngcontent-%COMP%]{background:#fff;border-color:#1a73e8;box-shadow:0 0 0 1px #1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card.active[_ngcontent-%COMP%] .method-icon-box[_ngcontent-%COMP%]{background:#eff6ff;color:#1a73e8;border-color:#bfdbfe}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card.active[_ngcontent-%COMP%] .method-title[_ngcontent-%COMP%]{color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .connection-methods-nav[_ngcontent-%COMP%] .method-nav-card[_ngcontent-%COMP%]:hover:not(.active){background:#fff;border-color:#cbd5e1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;background:#fffbeb;border:1px solid #fde68a;border-radius:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .active-remote-copy[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;min-width:0;color:#78350f;font-size:11.5px;line-height:1.45}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .active-remote-copy[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{color:#d97706;font-size:17px;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .active-remote-copy[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .btn-use-local-adb[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;padding:0 12px;background:#ffffffb8;backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(226,232,240,.88);box-shadow:0 2px 8px -1px #0f172a0d,inset 0 1px 1px #fffffff2;color:#475569;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .btn-use-local-adb[_ngcontent-%COMP%]:hover:not(:disabled){background:#ffffffeb;border-color:#bfdbfef2;color:#1a73e8;box-shadow:0 4px 12px -2px #0f172a14,inset 0 1px 1px #fff;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .btn-use-local-adb[_ngcontent-%COMP%]:hover:not(:disabled) .material-symbols-outlined[_ngcontent-%COMP%]:not(.feedback-done){color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .btn-use-local-adb[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .btn-use-local-adb[_ngcontent-%COMP%]:disabled{opacity:.55;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .btn-use-local-adb[_ngcontent-%COMP%]{border-radius:6px;font-family:inherit;font-size:11.5px;font-weight:600;cursor:pointer;white-space:nowrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .btn-use-local-adb[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}@media(max-width:700px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%]{align-items:stretch;flex-direction:column}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .active-remote-notice[_ngcontent-%COMP%] .btn-use-local-adb[_ngcontent-%COMP%]{width:100%}}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%]{background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:14px 16px;display:flex;flex-direction:column;gap:12px;animation:_ngcontent-%COMP%_fadeIn .15s ease-out}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .section-header-bar[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:6px;padding-bottom:6px;border-bottom:1px solid #f1f5f9}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .section-header-bar[_ngcontent-%COMP%] .section-title-group[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .section-header-bar[_ngcontent-%COMP%] .section-title-group[_ngcontent-%COMP%] .header-icon[_ngcontent-%COMP%]{font-size:17px;color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .section-header-bar[_ngcontent-%COMP%] .section-title-group[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .section-header-bar[_ngcontent-%COMP%] .section-title-group[_ngcontent-%COMP%] .count-badge[_ngcontent-%COMP%]{font-size:10.5px;font-weight:600;padding:1.5px 6px;border-radius:6px;background:#f1f5f9;color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;gap:12px;min-width:0;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%]:hover{border-color:#cbd5e1;background:#fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-main[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-main[_ngcontent-%COMP%] .avd-avatar[_ngcontent-%COMP%]{width:32px;height:32px;border-radius:6px;background:#fff;border:1px solid #e2e8f0;color:#1a73e8;display:flex;align-items:center;justify-content:center;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-main[_ngcontent-%COMP%] .avd-avatar[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:17px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-main[_ngcontent-%COMP%] .avd-meta[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-main[_ngcontent-%COMP%] .avd-meta[_ngcontent-%COMP%] .avd-heading[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-main[_ngcontent-%COMP%] .avd-meta[_ngcontent-%COMP%] .avd-heading[_ngcontent-%COMP%] .avd-name[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#0f172a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-main[_ngcontent-%COMP%] .avd-meta[_ngcontent-%COMP%] .avd-heading[_ngcontent-%COMP%] .avd-type-pill[_ngcontent-%COMP%]{font-size:9.5px;font-weight:600;padding:1px 5px;border-radius:4px;background:#fff;border:1px solid #e2e8f0;color:#64748b;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:0 15px;height:30px;background:linear-gradient(135deg,#1a73e8eb,#2563ebd9);backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(255,255,255,.28);box-shadow:0 4px 14px #1a73e852,inset 0 1px 1px #ffffff73;color:#fff!important;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%] .run-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%]:hover:not(:disabled){background:linear-gradient(135deg,#1a73e8,#2563ebf2);box-shadow:0 6px 20px #1a73e86b,inset 0 1px 1px #fff9;transform:translateY(-1px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97) translateY(0);box-shadow:0 2px 8px #1a73e859}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%]:disabled{background:#94a3b880;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);box-shadow:none;opacity:.65;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%]{border-radius:6px;font-family:inherit;font-size:12px;font-weight:600;cursor:pointer}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{font-size:15px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .avds-section[_ngcontent-%COMP%] .avds-list[_ngcontent-%COMP%] .avd-card-item[_ngcontent-%COMP%] .avd-item-actions[_ngcontent-%COMP%] .btn-avd-launch[_ngcontent-%COMP%] .spinner-icon[_ngcontent-%COMP%]{width:13px;height:13px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:_ngcontent-%COMP%_spin .8s linear infinite}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;padding:12px 14px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .banner-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .banner-left[_ngcontent-%COMP%] .empty-avd-icon-box[_ngcontent-%COMP%]{width:34px;height:34px;border-radius:6px;background:#fff;border:1px solid #e2e8f0;color:#64748b;display:flex;align-items:center;justify-content:center;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .banner-left[_ngcontent-%COMP%] .empty-avd-icon-box[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:19px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .banner-left[_ngcontent-%COMP%] .banner-titles[_ngcontent-%COMP%] .banner-title-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .banner-left[_ngcontent-%COMP%] .banner-titles[_ngcontent-%COMP%] .banner-title-row[_ngcontent-%COMP%] .empty-title[_ngcontent-%COMP%]{margin:0;font-size:13px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .banner-left[_ngcontent-%COMP%] .banner-titles[_ngcontent-%COMP%] .empty-desc[_ngcontent-%COMP%]{margin:2px 0 0;font-size:12px;color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .mode-switch-pills[_ngcontent-%COMP%]{display:inline-flex;background:#fff;border:1px solid #e2e8f0;padding:2px;border-radius:6px;gap:2px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .mode-switch-pills[_ngcontent-%COMP%] .pill-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:4px;border:none;background:transparent;color:#475569;font-family:inherit;font-size:11.5px;font-weight:600;cursor:pointer;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .mode-switch-pills[_ngcontent-%COMP%] .pill-btn[_ngcontent-%COMP%] .pill-icon[_ngcontent-%COMP%]{font-size:14px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .mode-switch-pills[_ngcontent-%COMP%] .pill-btn[_ngcontent-%COMP%]:hover{color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .empty-avd-banner[_ngcontent-%COMP%] .mode-switch-pills[_ngcontent-%COMP%] .pill-btn.active[_ngcontent-%COMP%]{background:#1a73e8;color:#fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .emu-flow-grid[_ngcontent-%COMP%] .flow-step-card[_ngcontent-%COMP%] .guide-link[_ngcontent-%COMP%]{color:#1a73e8;font-weight:600;text-decoration:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .emu-flow-grid[_ngcontent-%COMP%] .flow-step-card[_ngcontent-%COMP%] .guide-link[_ngcontent-%COMP%]:hover{text-decoration:underline}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .cli-steps-list[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .cli-steps-list[_ngcontent-%COMP%] .cli-step-item[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .cli-steps-list[_ngcontent-%COMP%] .cli-step-item[_ngcontent-%COMP%] .step-badge-num[_ngcontent-%COMP%]{width:22px;height:22px;border-radius:50%;background:#eff6ff;color:#1a73e8;font-size:11.5px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .cli-steps-list[_ngcontent-%COMP%] .cli-step-item[_ngcontent-%COMP%] .step-content[_ngcontent-%COMP%]{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .cli-steps-list[_ngcontent-%COMP%] .cli-step-item[_ngcontent-%COMP%] .step-content[_ngcontent-%COMP%] .step-title[_ngcontent-%COMP%]{font-size:12.5px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .cli-steps-list[_ngcontent-%COMP%] .cli-step-item[_ngcontent-%COMP%] .step-content[_ngcontent-%COMP%] .step-text[_ngcontent-%COMP%]{margin:0;font-size:11.5px;color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .emulator-setup-guide-container[_ngcontent-%COMP%] .cli-steps-list[_ngcontent-%COMP%] .cli-step-item[_ngcontent-%COMP%] .step-content[_ngcontent-%COMP%] .small-box[_ngcontent-%COMP%]{margin-top:4px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .usb-guide-intro[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-guide-intro[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .remote-guide-intro[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:600;color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .usb-guide-intro[_ngcontent-%COMP%] .intro-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-guide-intro[_ngcontent-%COMP%] .intro-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .remote-guide-intro[_ngcontent-%COMP%] .intro-icon[_ngcontent-%COMP%]{font-size:17px;color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}@media(max-width:900px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%]{grid-template-columns:repeat(2,1fr)}}@media(max-width:520px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%]{grid-template-columns:1fr}}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%] .flow-step-card[_ngcontent-%COMP%]{background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:12px 14px;display:flex;flex-direction:column;gap:6px;min-width:0;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%] .flow-step-card[_ngcontent-%COMP%]:hover{border-color:#cbd5e1;background:#fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%] .flow-step-card[_ngcontent-%COMP%] .step-card-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%] .flow-step-card[_ngcontent-%COMP%] .step-card-header[_ngcontent-%COMP%] .step-number-badge[_ngcontent-%COMP%]{width:20px;height:20px;border-radius:4px;background:#1a73e8;color:#fff!important;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%] .flow-step-card[_ngcontent-%COMP%] .step-card-header[_ngcontent-%COMP%] .step-card-icon[_ngcontent-%COMP%]{font-size:17px;color:#94a3b8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%] .flow-step-card[_ngcontent-%COMP%] .step-card-title[_ngcontent-%COMP%]{font-size:12.5px;font-weight:600;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .steps-flow-grid[_ngcontent-%COMP%] .flow-step-card[_ngcontent-%COMP%] .step-card-desc[_ngcontent-%COMP%]{font-size:11.5px;color:#64748b;line-height:1.4}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%]{background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:12px 14px;display:flex;flex-direction:column;gap:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%]{display:flex;align-items:flex-end;gap:8px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-input-col[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:3px;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-input-col.ip-col[_ngcontent-%COMP%]{flex:1 1 180px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-input-col.port-col[_ngcontent-%COMP%]{flex:0 1 90px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-input-col[_ngcontent-%COMP%] .wifi-label[_ngcontent-%COMP%]{font-size:11px;font-weight:600;color:#64748b}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-input-col[_ngcontent-%COMP%] .wifi-input-wrap[_ngcontent-%COMP%]{display:flex;align-items:center;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:0 8px;height:34px;transition:border-color .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-input-col[_ngcontent-%COMP%] .wifi-input-wrap[_ngcontent-%COMP%]:focus-within{border-color:#1a73e8;box-shadow:0 0 0 2px #1a73e81a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-input-col[_ngcontent-%COMP%] .wifi-input-wrap[_ngcontent-%COMP%] .wrap-icon[_ngcontent-%COMP%]{font-size:15px;color:#94a3b8;margin-right:5px;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-input-col[_ngcontent-%COMP%] .wifi-input-wrap[_ngcontent-%COMP%] .wifi-input[_ngcontent-%COMP%]{flex:1;min-width:0;border:none;outline:none;background:transparent;font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:12px;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-input-col[_ngcontent-%COMP%] .wifi-input-wrap[_ngcontent-%COMP%] .wifi-input[_ngcontent-%COMP%]::placeholder{color:#94a3b8;font-family:Google Sans Text,Google Sans,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:11.5px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%]{flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:0 16px;height:34px;background:linear-gradient(135deg,#1a73e8eb,#2563ebd9);backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(255,255,255,.28);box-shadow:0 4px 14px #1a73e852,inset 0 1px 1px #ffffff73;color:#fff!important;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%] .run-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%]:hover:not(:disabled){background:linear-gradient(135deg,#1a73e8,#2563ebf2);box-shadow:0 6px 20px #1a73e86b,inset 0 1px 1px #fff9;transform:translateY(-1px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97) translateY(0);box-shadow:0 2px 8px #1a73e859}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%]:disabled{background:#94a3b880;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);box-shadow:none;opacity:.65;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%]{border-radius:6px;font-family:inherit;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:16px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-form-row[_ngcontent-%COMP%] .wifi-btn-col[_ngcontent-%COMP%] .btn-wifi-connect[_ngcontent-%COMP%] .spinning[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_spin 1s linear infinite}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-status-alert[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;padding:6px 10px;border-radius:6px;font-size:11.5px;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-status-alert[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-status-alert.success[_ngcontent-%COMP%]{background:#ecfdf5;color:#047857;border:1px solid #a7f3d0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .wifi-interactive-box[_ngcontent-%COMP%] .wifi-status-alert.error[_ngcontent-%COMP%]{background:#fef2f2;color:#b91c1c;border:1px solid #fecaca}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .info-callout-box[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:8px;padding:8px 12px;background:#eff6ff;border:1px solid #bfdbfe;border-radius:6px;font-size:11.5px;color:#1557b0;line-height:1.45}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel[_ngcontent-%COMP%] .info-callout-box[_ngcontent-%COMP%] .callout-icon[_ngcontent-%COMP%]{font-size:16px;color:#1a73e8;flex-shrink:0;margin-top:1px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px;padding:12px 14px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%]{display:flex;align-items:flex-end;gap:8px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:3px;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col.host-col[_ngcontent-%COMP%]{flex:1 1 220px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col.port-col[_ngcontent-%COMP%]{flex:0 1 120px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col[_ngcontent-%COMP%] .remote-adb-label[_ngcontent-%COMP%]{color:#64748b;font-size:11px;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col[_ngcontent-%COMP%] .remote-adb-input-wrap[_ngcontent-%COMP%]{display:flex;align-items:center;height:36px;padding:0 9px;background:#fff;border:1px solid #e2e8f0;border-radius:6px;transition:border-color .15s ease,box-shadow .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col[_ngcontent-%COMP%] .remote-adb-input-wrap[_ngcontent-%COMP%]:focus-within{border-color:#1a73e8;box-shadow:0 0 0 2px #1a73e81a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col[_ngcontent-%COMP%] .remote-adb-input-wrap[_ngcontent-%COMP%] .wrap-icon[_ngcontent-%COMP%]{margin-right:6px;color:#94a3b8;font-size:15px;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col[_ngcontent-%COMP%] .remote-adb-input-wrap[_ngcontent-%COMP%] .remote-adb-input[_ngcontent-%COMP%]{flex:1;min-width:0;border:0;outline:0;background:transparent;color:#0f172a;font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col[_ngcontent-%COMP%] .remote-adb-input-wrap[_ngcontent-%COMP%] .remote-adb-input[_ngcontent-%COMP%]::placeholder{color:#94a3b8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%]{flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:5px;height:36px;padding:0 16px;background:linear-gradient(135deg,#1a73e8eb,#2563ebd9);backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(255,255,255,.28);box-shadow:0 4px 14px #1a73e852,inset 0 1px 1px #ffffff73;color:#fff!important;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%] .run-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%]:hover:not(:disabled){background:linear-gradient(135deg,#1a73e8,#2563ebf2);box-shadow:0 6px 20px #1a73e86b,inset 0 1px 1px #fff9;transform:translateY(-1px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97) translateY(0);box-shadow:0 2px 8px #1a73e859}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%]:disabled{background:#94a3b880;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);box-shadow:none;opacity:.65;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%]{border-radius:6px;font-family:inherit;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:16px}@media(max-width:640px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%]{align-items:stretch;flex-direction:column}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col.host-col[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-input-col.port-col[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%]{flex:1 1 auto;width:100%}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-form-row[_ngcontent-%COMP%] .remote-adb-btn-col[_ngcontent-%COMP%] .btn-remote-adb-connect[_ngcontent-%COMP%]{width:100%}}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remember-remote-adb[_ngcontent-%COMP%]{display:inline-flex;align-items:center;align-self:flex-start;gap:7px;color:#475569;font-size:11.5px;cursor:pointer}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remember-remote-adb[_ngcontent-%COMP%] input[_ngcontent-%COMP%]{width:15px;height:15px;margin:0;accent-color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;align-self:flex-end;gap:5px;min-width:150px;height:36px;padding:0 16px;background:linear-gradient(135deg,#1a73e8eb,#2563ebd9);backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(255,255,255,.28);box-shadow:0 4px 14px #1a73e852,inset 0 1px 1px #ffffff73;color:#fff!important;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%] .run-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%]:hover:not(:disabled){background:linear-gradient(135deg,#1a73e8,#2563ebf2);box-shadow:0 6px 20px #1a73e86b,inset 0 1px 1px #fff9;transform:translateY(-1px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97) translateY(0);box-shadow:0 2px 8px #1a73e859}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%]:disabled{background:#94a3b880;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);box-shadow:none;opacity:.65;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%]{border-radius:6px;font-family:inherit;font-size:12px;font-weight:600;cursor:pointer}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .btn-use-tested-endpoint[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:16px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-status-alert[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:6px;padding:7px 10px;border-radius:6px;font-size:11.5px;font-weight:600;line-height:1.4}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-status-alert[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-status-alert.success[_ngcontent-%COMP%]{color:#047857;background:#ecfdf5;border:1px solid #a7f3d0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-adb-status-alert.error[_ngcontent-%COMP%]{color:#b91c1c;background:#fef2f2;border:1px solid #fecaca}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-device-results[_ngcontent-%COMP%]{display:flex;flex-direction:column;overflow:hidden;background:#fff;border:1px solid #e2e8f0;border-radius:7px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-device-results[_ngcontent-%COMP%] .remote-device-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:9px;min-width:0;padding:8px 10px;border-bottom:1px solid #f1f5f9}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-device-results[_ngcontent-%COMP%] .remote-device-row[_ngcontent-%COMP%]:last-child{border-bottom:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-device-results[_ngcontent-%COMP%] .remote-device-row[_ngcontent-%COMP%] > .material-symbols-outlined[_ngcontent-%COMP%]{color:#1a73e8;font-size:17px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-device-results[_ngcontent-%COMP%] .remote-device-row[_ngcontent-%COMP%] .remote-device-copy[_ngcontent-%COMP%]{display:flex;flex:1;flex-direction:column;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-device-results[_ngcontent-%COMP%] .remote-device-row[_ngcontent-%COMP%] .remote-device-copy[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:#0f172a;font-size:12px;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-device-results[_ngcontent-%COMP%] .remote-device-row[_ngcontent-%COMP%] .remote-device-copy[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{overflow:hidden;color:#64748b;font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:10.5px;text-overflow:ellipsis;white-space:nowrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-device-results[_ngcontent-%COMP%] .remote-device-row[_ngcontent-%COMP%] .remote-device-state[_ngcontent-%COMP%]{color:#b45309;font-size:10.5px;font-weight:600;text-transform:capitalize}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-interactive-box[_ngcontent-%COMP%] .remote-device-results[_ngcontent-%COMP%] .remote-device-row[_ngcontent-%COMP%] .remote-device-state.ready[_ngcontent-%COMP%]{color:#047857}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .foolproof-guide-container[_ngcontent-%COMP%] .method-details-panel.remote-adb-panel[_ngcontent-%COMP%] .remote-adb-explanation[_ngcontent-%COMP%]{margin:0;color:#64748b;font-size:11.5px;line-height:1.5}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%]{display:flex;align-items:center;gap:12px;padding:12px 16px;background:#fffbeb;border:1px solid #fde68a;border-radius:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .alert-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .alert-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .alert-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .alert-icon[_ngcontent-%COMP%]{font-size:24px;color:#d97706;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%]{flex:1;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .unauth-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .locked-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .unauth-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .locked-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .unauth-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .locked-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .unauth-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .locked-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .unauth-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .locked-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .unauth-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .locked-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .unauth-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .locked-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .unauth-title[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .locked-title[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#b45309;margin-bottom:2px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .unauth-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .locked-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .unauth-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .locked-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .unauth-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .locked-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .unauth-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .locked-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .unauth-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .locked-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .unauth-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .locked-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .unauth-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .unauth-details[_ngcontent-%COMP%] .locked-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .unauth-desc[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .locked-details[_ngcontent-%COMP%] .locked-desc[_ngcontent-%COMP%]{font-size:11.5px;color:#78350f;line-height:1.4}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:0 12px;height:30px;background:#fef3c7bf;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(253,230,138,.85);border-radius:6px;box-shadow:0 1px 3px #d9770614,inset 0 1px 1px #fffc;font-family:inherit;font-size:11.5px;font-weight:600;color:#b45309;cursor:pointer;flex-shrink:0;transition:all .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:hover:not(:disabled), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:hover:not(:disabled), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:hover:not(:disabled), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:hover:not(:disabled), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:hover:not(:disabled), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:hover:not(:disabled), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:hover:not(:disabled), .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:hover:not(:disabled){background:#fde68af2;border-color:#d97706;transform:translateY(-.5px);box-shadow:0 3px 8px #d9770626}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:active, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:active, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:active, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:active, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:active, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:active, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:active, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:active{transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:disabled, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:disabled, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:disabled, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .unauthorized-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:disabled, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:disabled, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .unauthorized-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:disabled, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-retry-auth[_ngcontent-%COMP%]:disabled, .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .device-locked-panel[_ngcontent-%COMP%] .device-locked-card[_ngcontent-%COMP%] .btn-check-unlock[_ngcontent-%COMP%]:disabled{cursor:not-allowed;opacity:.65}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .adb-missing-panel[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .adb-missing-panel[_ngcontent-%COMP%] .error-msg-box[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:10px 12px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;font-size:12px;color:#b91c1c}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .adb-missing-panel[_ngcontent-%COMP%] .error-msg-box[_ngcontent-%COMP%] .err-icon[_ngcontent-%COMP%]{font-size:17px;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .adb-missing-panel[_ngcontent-%COMP%] .install-commands-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .adb-missing-panel[_ngcontent-%COMP%] .install-commands-row[_ngcontent-%COMP%] .install-card[_ngcontent-%COMP%]{background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:6px;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .adb-missing-panel[_ngcontent-%COMP%] .install-commands-row[_ngcontent-%COMP%] .install-card.highlight-os[_ngcontent-%COMP%]{background:#eff6ff;border-color:#bfdbfe}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .adb-missing-panel[_ngcontent-%COMP%] .install-commands-row[_ngcontent-%COMP%] .install-card[_ngcontent-%COMP%] .install-os[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;font-size:11.5px;font-weight:600;color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .adb-missing-panel[_ngcontent-%COMP%] .install-commands-row[_ngcontent-%COMP%] .install-card[_ngcontent-%COMP%] .install-os[_ngcontent-%COMP%] .detected-badge[_ngcontent-%COMP%]{font-size:9.5px;font-weight:700;color:#1a73e8;background:#dbeafe;padding:1px 5px;border-radius:4px;text-transform:uppercase}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:16px 20px;background:#fff;border:1px solid #e2e8f0;border-radius:12px;box-shadow:0 1px 3px #00000008,0 4px 12px #00000005;transition:all .2s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%]:hover{border-color:#cbd5e1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .ready-banner-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:14px;min-width:0;flex:1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .ready-banner-left[_ngcontent-%COMP%] .step-badge[_ngcontent-%COMP%]{width:32px;height:32px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;font-size:13.5px;font-weight:700;background:#f1f5f9;color:#475569;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .ready-banner-left[_ngcontent-%COMP%] .step-badge[_ngcontent-%COMP%] .step-check-icon[_ngcontent-%COMP%]{font-size:18px;font-weight:700;color:inherit}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .ready-banner-left[_ngcontent-%COMP%] .step-badge.step-pass[_ngcontent-%COMP%]{background:#ecfdf5;color:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .ready-banner-left[_ngcontent-%COMP%] .ready-text-group[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:2px;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .ready-banner-left[_ngcontent-%COMP%] .ready-text-group[_ngcontent-%COMP%] .ready-title[_ngcontent-%COMP%]{margin:0;font-size:15px;font-weight:600;color:#0f172a;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .ready-banner-left[_ngcontent-%COMP%] .ready-text-group[_ngcontent-%COMP%] .ready-desc[_ngcontent-%COMP%]{margin:0;font-size:12.5px;color:#475569;line-height:1.4}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;padding:0 18px;height:36px;background:linear-gradient(135deg,#1a73e8eb,#2563ebd9);backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(255,255,255,.28);box-shadow:0 4px 14px #1a73e852,inset 0 1px 1px #ffffff73;color:#fff!important;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%] .run-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%]:hover:not(:disabled){background:linear-gradient(135deg,#1a73e8,#2563ebf2);box-shadow:0 6px 20px #1a73e86b,inset 0 1px 1px #fff9;transform:translateY(-1px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97) translateY(0);box-shadow:0 2px 8px #1a73e859}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%]:disabled{background:#94a3b880;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);box-shadow:none;opacity:.65;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%]{border-radius:8px;font-family:inherit;font-size:13px;font-weight:600;cursor:pointer;white-space:nowrap;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%] .rocket-icon[_ngcontent-%COMP%]{font-size:16px;transition:transform .2s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%]:hover:not(:disabled) .rocket-icon[_ngcontent-%COMP%]{transform:translate(2px) translateY(-2px)}@media(max-width:768px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%]{flex-direction:column;align-items:stretch}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .setup-guide-view[_ngcontent-%COMP%] .ready-banner-footer[_ngcontent-%COMP%] .btn-proceed-launch[_ngcontent-%COMP%]{justify-content:center}}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:space-between;gap:8px;padding:0 6px 0 10px;height:32px;background:#0f172a;color:#f8fafc;border-radius:6px;font-family:JetBrains Mono,Fira Code,Roboto Mono,SFMono-Regular,Consolas,monospace;font-size:11.5px;min-width:0;max-width:100%}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .terminal-prefix[_ngcontent-%COMP%]{color:#64748b;-webkit-user-select:none;user-select:none;flex-shrink:0;font-weight:700;font-size:11px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .code-text[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{flex:1;min-width:0;color:#38bdf8!important;font-family:inherit;background:transparent!important;border:none!important;padding:0!important;font-size:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .btn-copy-code[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:3px;padding:0 8px;height:22px;background:#ffffff24;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);color:#fff!important;border:1px solid rgba(255,255,255,.2);border-radius:5px;box-shadow:inset 0 1px 1px #fff3;font-family:Google Sans Text,Google Sans,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:10.5px;font-weight:600;cursor:pointer;transition:all .18s ease;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .btn-copy-code[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .btn-copy-code[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .btn-copy-code[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .btn-copy-code[_ngcontent-%COMP%]:hover{background:#ffffff42;border-color:#ffffff59;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .btn-copy-code[_ngcontent-%COMP%]:active{transform:scale(.96)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .btn-copy-code.copied[_ngcontent-%COMP%]{background:#10b98159;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-color:#10b98199;color:#34d399!important;box-shadow:0 0 10px #10b9814d,inset 0 1px 1px #fff6}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .btn-copy-code.copied[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box[_ngcontent-%COMP%] .btn-copy-code.copied[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:#34d399!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box.small-box[_ngcontent-%COMP%]{height:30px;font-size:11.5px;padding:0 6px 0 10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box.small-box[_ngcontent-%COMP%] .btn-copy-code[_ngcontent-%COMP%]{height:22px;padding:0 8px;font-size:10.5px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .code-box.small-box[_ngcontent-%COMP%] .btn-copy-code[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px;animation:_ngcontent-%COMP%_fadeIn .22s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .launcher-warning-bar[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;padding:10px 16px;background:#fffbeb;border:1px solid #fde68a;border-radius:12px;color:#92400e;font-size:13px;cursor:pointer;transition:all .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .launcher-warning-bar[_ngcontent-%COMP%] .warn-icon[_ngcontent-%COMP%]{font-size:18px;color:#d97706;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .launcher-warning-bar[_ngcontent-%COMP%] .arrow[_ngcontent-%COMP%]{font-size:16px;margin-left:auto}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .launcher-warning-bar[_ngcontent-%COMP%]:hover{background:#fef3c7;border-color:#fcd34d}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%]{background:#ffffffe0;backdrop-filter:blur(16px) saturate(190%);-webkit-backdrop-filter:blur(16px) saturate(190%);border:1px solid rgba(255,255,255,.95);box-shadow:0 20px 50px -12px #0f172a14,0 1px 3px #00000005,inset 0 1px 1px #fffffff2;border-radius:20px;padding:18px 20px 14px;transition:border-color .3s cubic-bezier(.4,0,.2,1),box-shadow .3s cubic-bezier(.4,0,.2,1),background .3s cubic-bezier(.4,0,.2,1);position:relative}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card.is-pro-active[_ngcontent-%COMP%]{border-color:#ddd6fef2;box-shadow:0 24px 60px -12px #6366f129,0 1px 3px #00000005,inset 0 1px 1px #fffffff2}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 12px;background:linear-gradient(135deg,#eef2fff2,#f5f3fff2);border:1px solid rgba(199,210,254,.85);border-radius:10px;margin-bottom:12px;animation:_ngcontent-%COMP%_slideUpFade .22s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%] .suggestion-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%] .suggestion-left[_ngcontent-%COMP%] .sparkle-icon[_ngcontent-%COMP%]{font-size:17px;color:#6366f1;flex-shrink:0;animation:_ngcontent-%COMP%_sparklePulse 2.5s ease-in-out infinite alternate}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%] .suggestion-left[_ngcontent-%COMP%] .suggestion-text[_ngcontent-%COMP%]{font-size:12.5px;color:#3730a3;line-height:1.4}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%] .suggestion-left[_ngcontent-%COMP%] .suggestion-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:#1e1b4b;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%] .btn-switch-pro[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:6px;border:none;background:#6366f1;color:#fff;font-family:inherit;font-size:11.5px;font-weight:600;cursor:pointer;flex-shrink:0;transition:all .18s cubic-bezier(.4,0,.2,1);box-shadow:0 1px 3px #6366f140}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%] .btn-switch-pro[_ngcontent-%COMP%] .btn-arrow[_ngcontent-%COMP%]{font-size:14px;transition:transform .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%] .btn-switch-pro[_ngcontent-%COMP%]:hover{background:#4f46e5;box-shadow:0 2px 6px #6366f159;transform:translateY(-.5px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%] .btn-switch-pro[_ngcontent-%COMP%]:hover .btn-arrow[_ngcontent-%COMP%]{transform:translate(2px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .intent-suggestion-strip[_ngcontent-%COMP%] .btn-switch-pro[_ngcontent-%COMP%]:active{transform:scale(.96)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-input-area[_ngcontent-%COMP%]{width:100%}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-input-area[_ngcontent-%COMP%] .composer-textarea[_ngcontent-%COMP%]{width:100%;border:none;outline:none;background:transparent;padding:0;margin:0;font-family:inherit;font-size:15.5px;line-height:1.6;color:#0f172a;resize:vertical;min-height:90px;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-input-area[_ngcontent-%COMP%] .composer-textarea[_ngcontent-%COMP%]::placeholder{color:#94a3b8;font-weight:400}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-input-area[_ngcontent-%COMP%] .composer-textarea[_ngcontent-%COMP%]:disabled{color:#94a3b8;cursor:not-allowed}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor[_ngcontent-%COMP%]{display:flex;align-items:center;gap:9px;padding:8px 12px;border-radius:9px;background:#f8fafcbf;border:1px solid rgba(241,245,249,.95);margin-top:10px;margin-bottom:12px;transition:all .25s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor[_ngcontent-%COMP%] .descriptor-icon-wrap[_ngcontent-%COMP%]{width:22px;height:22px;border-radius:6px;display:inline-flex;align-items:center;justify-content:center;background:#1a73e81a;color:#1a73e8;flex-shrink:0;transition:all .25s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor[_ngcontent-%COMP%] .descriptor-icon-wrap[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:14px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor[_ngcontent-%COMP%] .descriptor-body[_ngcontent-%COMP%]{flex:1;min-width:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor[_ngcontent-%COMP%] .descriptor-body[_ngcontent-%COMP%] .desc-line[_ngcontent-%COMP%]{margin:0;font-size:12.5px;line-height:1.45;color:#475569;letter-spacing:-.005em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor[_ngcontent-%COMP%] .descriptor-body[_ngcontent-%COMP%] .desc-line[_ngcontent-%COMP%] .mode-name[_ngcontent-%COMP%]{font-weight:700;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor[_ngcontent-%COMP%] .descriptor-body[_ngcontent-%COMP%] .desc-line[_ngcontent-%COMP%] .bullet[_ngcontent-%COMP%]{color:#94a3b8;margin:0 3px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor[_ngcontent-%COMP%] .descriptor-body[_ngcontent-%COMP%] .desc-line[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:#0f172a;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor[_ngcontent-%COMP%] .descriptor-body[_ngcontent-%COMP%] .desc-line[_ngcontent-%COMP%] .limitation-tag[_ngcontent-%COMP%]{color:#64748b;font-size:11.5px;margin-left:3px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor.is-pro[_ngcontent-%COMP%]{background:linear-gradient(135deg,#f5f3ffcc,#faf5ffcc);border-color:#ede9fef2}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor.is-pro[_ngcontent-%COMP%] .descriptor-icon-wrap[_ngcontent-%COMP%]{background:#7c3aed1f;color:#7c3aed}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor.is-pro[_ngcontent-%COMP%] .descriptor-body[_ngcontent-%COMP%] .desc-line[_ngcontent-%COMP%]{color:#334155}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor.is-pro[_ngcontent-%COMP%] .descriptor-body[_ngcontent-%COMP%] .desc-line[_ngcontent-%COMP%] .mode-name[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-model-descriptor.is-pro[_ngcontent-%COMP%] .descriptor-body[_ngcontent-%COMP%] .desc-line[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:#1e1b4b}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .error-banner[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;padding:8px 12px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;color:#b91c1c;font-size:12px;margin-bottom:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .error-banner[_ngcontent-%COMP%] .error-icon[_ngcontent-%COMP%]{font-size:16px;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding-top:10px;border-top:1px solid rgba(241,245,249,.95);gap:12px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%]{display:flex;align-items:center}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%]{display:inline-flex;align-items:center;background:#f1f5f9d9;padding:3px;border-radius:18px;gap:3px;border:1px solid rgba(226,232,240,.88);width:172px;box-sizing:border-box}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn[_ngcontent-%COMP%]{flex:1 1 0;width:50%;height:32px;padding:0 10px;border-radius:15px;border:none;background:transparent;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:6px;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none;box-sizing:border-box;white-space:nowrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn[_ngcontent-%COMP%] .btn-icon[_ngcontent-%COMP%]{font-size:16px;color:#64748b;flex-shrink:0;transition:color .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%]{font-size:13px;font-weight:500;color:#475569;line-height:1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn[_ngcontent-%COMP%]:hover:not(.active){background:#ffffffb3}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn[_ngcontent-%COMP%]:hover:not(.active) .btn-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn[_ngcontent-%COMP%]:hover:not(.active) .btn-text[_ngcontent-%COMP%]{color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn.active[_ngcontent-%COMP%]{background:#fff;box-shadow:0 1px 4px #00000014,0 1px 2px #0000000a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn.active[_ngcontent-%COMP%] .btn-icon[_ngcontent-%COMP%]{color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn.active[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%]{color:#0f172a;font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn.btn-pro.active[_ngcontent-%COMP%]{background:linear-gradient(135deg,#6366f1,#7c3aed);box-shadow:0 2px 8px #6366f159}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn.btn-pro.active[_ngcontent-%COMP%] .btn-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn.btn-pro.active[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-left[_ngcontent-%COMP%] .model-toggle-capsule[_ngcontent-%COMP%] .model-toggle-btn[_ngcontent-%COMP%]:active{transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%]{display:flex;align-items:center;gap:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .char-count[_ngcontent-%COMP%]{font-size:11.5px;color:#94a3b8;font-variant-numeric:tabular-nums}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:38px;padding:0 20px;background:linear-gradient(135deg,#1a73e8eb,#2563ebd9);backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(255,255,255,.28);box-shadow:0 4px 14px #1a73e852,inset 0 1px 1px #ffffff73;color:#fff!important;transition:background .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%] .run-icon[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{color:#fff!important}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%]:hover:not(:disabled){background:linear-gradient(135deg,#1a73e8,#2563ebf2);box-shadow:0 6px 20px #1a73e86b,inset 0 1px 1px #fff9;transform:translateY(-1px)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.97) translateY(0);box-shadow:0 2px 8px #1a73e859}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%]:disabled{background:#94a3b880;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);box-shadow:none;opacity:.65;cursor:not-allowed;transform:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%]{border-radius:12px;font-family:inherit;font-size:13.5px;font-weight:700;cursor:pointer;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer.btn-run-pro[_ngcontent-%COMP%]{background:linear-gradient(135deg,#6366f1eb,#7c3aedd9);box-shadow:0 4px 14px #6366f152,inset 0 1px 1px #ffffff73}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer.btn-run-pro[_ngcontent-%COMP%]:hover:not(:disabled){background:linear-gradient(135deg,#6366f1,#7c3aedf2);box-shadow:0 6px 20px #6366f16b,inset 0 1px 1px #fff9}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%] .run-icon[_ngcontent-%COMP%]{font-size:18px;line-height:1;transition:transform .2s cubic-bezier(.34,1.56,.64,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%]:hover:not(:disabled) .run-icon[_ngcontent-%COMP%]{transform:scale(1.15) rotate(15deg)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .composer-card[_ngcontent-%COMP%] .composer-action-bar[_ngcontent-%COMP%] .bar-right[_ngcontent-%COMP%] .btn-run-composer[_ngcontent-%COMP%] .spinner[_ngcontent-%COMP%]{width:14px;height:14px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:_ngcontent-%COMP%_spin .8s linear infinite}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%]{background:#ffffffe0;backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%);border:1px solid rgba(226,232,240,.95);border-radius:16px;padding:12px 18px 14px;box-shadow:0 1px 3px #00000005,0 8px 24px -6px #0f172a0a;display:flex;flex-direction:column;gap:8px;animation:_ngcontent-%COMP%_slideUpFade .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-card-header[_ngcontent-%COMP%]{display:flex;align-items:baseline;gap:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-card-header[_ngcontent-%COMP%] .outputter-title[_ngcontent-%COMP%]{font-size:13px;font-weight:700;color:#0f172a;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-card-header[_ngcontent-%COMP%] .outputter-optional-tag[_ngcontent-%COMP%]{font-size:11.5px;font-weight:500;color:#94a3b8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-input-wrapper[_ngcontent-%COMP%]{display:flex;align-items:center;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:0 12px;height:38px;transition:all .18s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-input-wrapper[_ngcontent-%COMP%]:focus-within{background:#fff;border-color:#7c3aed;box-shadow:0 0 0 3px #7c3aed1a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-input-wrapper[_ngcontent-%COMP%] .outputter-standalone-input[_ngcontent-%COMP%]{flex:1;border:none;outline:none;background:transparent;font-family:inherit;font-size:13px;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-input-wrapper[_ngcontent-%COMP%] .outputter-standalone-input[_ngcontent-%COMP%]::placeholder{color:#94a3b8;font-weight:400}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-input-wrapper[_ngcontent-%COMP%] .btn-clear-standalone[_ngcontent-%COMP%]{border:none;background:transparent;color:#94a3b8;cursor:pointer;padding:3px;border-radius:4px;display:flex;align-items:center;justify-content:center;transition:color .15s ease,background .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-input-wrapper[_ngcontent-%COMP%] .btn-clear-standalone[_ngcontent-%COMP%]:hover{color:#475569;background:#0000000d}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-outputter-standalone-card[_ngcontent-%COMP%] .outputter-input-wrapper[_ngcontent-%COMP%] .btn-clear-standalone[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:16px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%]{--%NS%tip-w: 320px;--%NS%thumb-w: 22px;--%NS%thumb-h: 14px;--%NS%col-gap: 28px;--%NS%accent: #6366f1;position:relative;background:#ffffffe0;backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%);border:1px solid rgba(226,232,240,.95);border-radius:16px;padding:12px 18px 14px;box-shadow:0 1px 3px #00000005,0 8px 24px -6px #0f172a0a;display:flex;flex-direction:column;gap:10px;animation:_ngcontent-%COMP%_slideUpFade .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card.tip-open[_ngcontent-%COMP%]{z-index:30}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-card-header[_ngcontent-%COMP%]{display:flex;align-items:baseline;justify-content:space-between;gap:10px;min-height:16px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-card-header[_ngcontent-%COMP%] .tuning-title[_ngcontent-%COMP%]{font-size:13px;font-weight:700;color:#0f172a;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-card-header[_ngcontent-%COMP%] .btn-tuning-reset[_ngcontent-%COMP%]{border:none;background:transparent;padding:0;font-family:inherit;font-size:12px;font-weight:500;color:#94a3b8;cursor:pointer;transition:color .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-card-header[_ngcontent-%COMP%] .btn-tuning-reset[_ngcontent-%COMP%]:hover{color:#475569}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-card-header[_ngcontent-%COMP%] .btn-tuning-reset[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--%NS%accent);outline-offset:3px;border-radius:3px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-sliders[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:4px var(--%NS%col-gap)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:4px;min-width:0;--%NS%tip-min: 0px;--%NS%tip-max: calc(100% - var(--%NS%tip-w))}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider.verify[_ngcontent-%COMP%]{--%NS%tip-max: calc(200% + var(--%NS%col-gap) - var(--%NS%tip-w))}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider.explore[_ngcontent-%COMP%]{--%NS%accent: #0ea5e9;--%NS%tip-min: calc(-100% - var(--%NS%col-gap))}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-head[_ngcontent-%COMP%]{display:flex;align-items:baseline;gap:8px;font-size:13px;line-height:18px;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-head[_ngcontent-%COMP%] .slider-name[_ngcontent-%COMP%]{font-weight:400;color:#334155}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-head[_ngcontent-%COMP%] .slider-value[_ngcontent-%COMP%]{font-weight:600}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-ends[_ngcontent-%COMP%]{display:flex;justify-content:space-between;font-size:11.5px;line-height:14px;color:#94a3b8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-track-wrap[_ngcontent-%COMP%]{position:relative;height:26px;display:flex;align-items:center}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-rail[_ngcontent-%COMP%]{position:relative;width:100%;height:6px;border-radius:3px;background:#e2e8f0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-fill[_ngcontent-%COMP%]{position:absolute;top:0;bottom:0;left:0;width:calc(var(--%NS%pct) * (100% - var(--%NS%thumb-w)) + var(--%NS%thumb-w) / 2);border-radius:3px;background:color-mix(in srgb,var(--%NS%accent) 24%,#e2e8f0);transition:width .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-notch[_ngcontent-%COMP%]{position:absolute;top:50%;left:calc(var(--%NS%n) * (100% - var(--%NS%thumb-w)) + var(--%NS%thumb-w) / 2);width:4px;height:4px;border-radius:50%;background:#94a3b8;transform:translate(-50%,-50%);transition:background .15s ease;z-index:1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-notch.reached[_ngcontent-%COMP%]{background:#fffffff2}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-thumb[_ngcontent-%COMP%]{position:absolute;top:50%;left:calc(var(--%NS%pct) * (100% - var(--%NS%thumb-w)) + var(--%NS%thumb-w) / 2);width:var(--%NS%thumb-w);height:var(--%NS%thumb-h);border-radius:5px;background:#fff;border:1px solid rgba(15,23,42,.1);box-shadow:0 1px 2px #0f172a1f,0 2px 6px #0f172a14;transform:translate(-50%,-50%);pointer-events:none;transition:left .15s ease,box-shadow .15s ease,border-color .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-solid[_ngcontent-%COMP%]{position:absolute;inset:0;border-radius:3px;background:var(--%NS%accent);transform-origin:right center;transform:scaleX(1);animation:_ngcontent-%COMP%_solidSweep 1s cubic-bezier(.4,0,.2,1) .2s both;pointer-events:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-dither[_ngcontent-%COMP%]{position:absolute;inset:0;display:block;overflow:hidden;border-radius:3px;pointer-events:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-dither[_ngcontent-%COMP%] rect[_ngcontent-%COMP%]{fill:var(--%NS%accent);animation:_ngcontent-%COMP%_ditherIn .3s ease-out both}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .thumb-ripple[_ngcontent-%COMP%]{position:absolute;top:50%;left:calc(var(--%NS%pct) * (100% - var(--%NS%thumb-w)) + var(--%NS%thumb-w) / 2);width:var(--%NS%thumb-w);height:var(--%NS%thumb-w);border-radius:50%;border:1.5px solid var(--%NS%accent);transform:translate(-50%,-50%) scale(.6);opacity:0;pointer-events:none;animation:_ngcontent-%COMP%_thumbRipple .6s ease-out forwards}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider.dragging[_ngcontent-%COMP%] .slider-thumb[_ngcontent-%COMP%]{border-color:color-mix(in srgb,var(--%NS%accent) 45%,transparent);box-shadow:0 1px 2px #0f172a1f,0 2px 8px #0f172a1a,0 0 0 4px color-mix(in srgb,var(--%NS%accent) 14%,transparent)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-input[_ngcontent-%COMP%]{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer;-webkit-appearance:none;appearance:none;background:transparent}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-input[_ngcontent-%COMP%]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:var(--%NS%thumb-w);height:26px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-input[_ngcontent-%COMP%]::-moz-range-thumb{width:var(--%NS%thumb-w);height:26px;border:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .slider-input[_ngcontent-%COMP%]:focus-visible ~ .slider-thumb[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%]:has(.slider-input:focus-visible) .slider-thumb[_ngcontent-%COMP%]{box-shadow:0 1px 2px #0f172a1f,0 0 0 2px #fff,0 0 0 4px var(--%NS%accent)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip-arrow[_ngcontent-%COMP%]{position:absolute;bottom:calc(100% + 2px);left:calc(var(--%NS%pct) * (100% - var(--%NS%thumb-w)) + var(--%NS%thumb-w) / 2);width:10px;height:10px;background:#fff;border-right:1px solid rgb(226,232,240);border-bottom:1px solid rgb(226,232,240);transform:translate(-50%,50%) rotate(45deg);z-index:41;pointer-events:none}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%]{position:absolute;bottom:calc(100% + 7px);left:clamp(var(--%NS%tip-min),var(--%NS%pct) * (100% - var(--%NS%thumb-w)) + var(--%NS%thumb-w) / 2 - var(--%NS%tip-w) / 2,var(--%NS%tip-max));width:var(--%NS%tip-w);max-width:calc(100vw - 32px);padding:12px 14px;background:#fff;border:1px solid rgb(226,232,240);border-radius:12px;box-shadow:0 12px 32px -8px #0f172a2e,0 2px 6px #0f172a0f;z-index:40;pointer-events:none;animation:_ngcontent-%COMP%_tipPop .16s ease-out;font-size:12px;line-height:1.5;color:#334155;display:flex;flex-direction:column;gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-heading[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:1px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-heading[_ngcontent-%COMP%] .tip-title[_ngcontent-%COMP%]{font-size:13.5px;font-weight:600;color:#0f172a;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-heading[_ngcontent-%COMP%] .tip-latency[_ngcontent-%COMP%]{font-size:11.5px;color:#94a3b8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-tagline[_ngcontent-%COMP%]{margin:0;color:#0f172a}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-section[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:2px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-section[_ngcontent-%COMP%] ul[_ngcontent-%COMP%]{margin:0;padding-left:16px;display:flex;flex-direction:column;gap:2px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-section[_ngcontent-%COMP%] li[_ngcontent-%COMP%]::marker{color:#cbd5e1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-section.skips[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{color:#64748b}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-section-title[_ngcontent-%COMP%]{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:#94a3b8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider[_ngcontent-%COMP%] .tuning-tip[_ngcontent-%COMP%] .tip-best[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:2px;color:#475569}@media(max-width:760px){.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-sliders[_ngcontent-%COMP%]{grid-template-columns:minmax(0,1fr);gap:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider.verify[_ngcontent-%COMP%], .home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .pro-tuning-card[_ngcontent-%COMP%] .tuning-slider.explore[_ngcontent-%COMP%]{--%NS%tip-min: 0px;--%NS%tip-max: calc(100% - var(--%NS%tip-w))}}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px;margin-top:10px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .section-label[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;font-family:inherit;font-size:13px;font-weight:700;color:#0f172a;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .section-label[_ngcontent-%COMP%] .section-icon[_ngcontent-%COMP%]{font-size:17px;color:#6366f1;animation:_ngcontent-%COMP%_sparklePulse 3s ease-in-out infinite alternate}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .section-label[_ngcontent-%COMP%] .device-context-pill[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:12px;background:#10b9811a;border:1px solid rgba(16,185,129,.25);color:#059669;font-size:11px;font-weight:600;line-height:1.3}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .section-label[_ngcontent-%COMP%] .device-context-pill[_ngcontent-%COMP%] .dev-icon[_ngcontent-%COMP%]{font-size:13px;color:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .category-tabs-group[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:3px;background:#ffffffa6;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);padding:3px;border-radius:16px;border:1px solid rgba(226,232,240,.85);box-shadow:0 1px 3px #00000005}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .category-tabs-group[_ngcontent-%COMP%] .cat-tab-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:12px;border:none;background:transparent;font-family:inherit;font-size:11.5px;font-weight:600;color:#64748b;cursor:pointer;transition:all .18s ease;white-space:nowrap}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .category-tabs-group[_ngcontent-%COMP%] .cat-tab-btn[_ngcontent-%COMP%] .tab-mini-icon[_ngcontent-%COMP%]{font-size:13px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .category-tabs-group[_ngcontent-%COMP%] .cat-tab-btn[_ngcontent-%COMP%]:hover:not(.active){color:#0f172a;background:#fff9}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .category-tabs-group[_ngcontent-%COMP%] .cat-tab-btn.active[_ngcontent-%COMP%]{color:#0f172a;background:#fff;box-shadow:0 2px 6px #0f172a14,inset 0 1px #fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .category-tabs-group[_ngcontent-%COMP%] .cat-tab-btn.active.cat-device[_ngcontent-%COMP%]{color:#059669}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .category-tabs-group[_ngcontent-%COMP%] .cat-tab-btn.active.cat-flash[_ngcontent-%COMP%]{color:#1a73e8}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .category-tabs-group[_ngcontent-%COMP%] .cat-tab-btn.active.cat-pro[_ngcontent-%COMP%]{color:#7c3aed}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-shuffle-suggestions[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:5px 12px;border-radius:14px;background:#ffffffb8;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid rgba(226,232,240,.85);color:#64748b;font-family:inherit;font-size:11.5px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-shuffle-suggestions[_ngcontent-%COMP%] .shuffle-icon[_ngcontent-%COMP%]{font-size:14px;transition:transform .2s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-shuffle-suggestions[_ngcontent-%COMP%]:hover{background:#fff;color:#0f172a;border-color:#cbd5e1e6;transform:translateY(-1px);box-shadow:0 2px 8px #0f172a0f}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-shuffle-suggestions[_ngcontent-%COMP%]:hover .shuffle-icon[_ngcontent-%COMP%]{transform:rotate(45deg)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-header-bar[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-shuffle-suggestions[_ngcontent-%COMP%]:active{transform:scale(.97)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fill,minmax(285px,1fr));gap:12px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;justify-content:space-between;padding:14px 16px;border-radius:16px;background:#ffffffb8;backdrop-filter:blur(10px) saturate(180%);-webkit-backdrop-filter:blur(10px) saturate(180%);border:1px solid rgba(226,232,240,.85);box-shadow:0 2px 8px -1px #0f172a0a,inset 0 1px 1px #fffffff2;cursor:pointer;transition:background .22s cubic-bezier(.4,0,.2,1),transform .22s cubic-bezier(.4,0,.2,1),box-shadow .22s cubic-bezier(.4,0,.2,1),border-color .22s cubic-bezier(.4,0,.2,1);-webkit-user-select:none;user-select:none;position:relative;overflow:hidden;min-height:128px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%]:hover{background:#fffffff2;transform:translateY(-2px);box-shadow:0 8px 24px -4px #0f172a14,0 2px 6px #00000005,inset 0 1px 1px #fff;border-color:#bfdbfef2}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card.is-pro-card[_ngcontent-%COMP%]:hover{border-color:#c7d2fef2;box-shadow:0 8px 24px -4px #6366f11f,inset 0 1px 1px #fff}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%]:active{transform:scale(.985)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-top-row[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:8px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-top-row[_ngcontent-%COMP%] .app-icons-cluster[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-top-row[_ngcontent-%COMP%] .app-icons-cluster[_ngcontent-%COMP%] .app-icon-badge[_ngcontent-%COMP%]{width:26px;height:26px;border-radius:8px;background:#f1f5f9;display:flex;align-items:center;justify-content:center;color:#475569;border:1px solid rgba(226,232,240,.9);flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-top-row[_ngcontent-%COMP%] .app-icons-cluster[_ngcontent-%COMP%] .app-icon-badge[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{font-size:14px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-top-row[_ngcontent-%COMP%] .app-icons-cluster[_ngcontent-%COMP%] .app-names-label[_ngcontent-%COMP%]{font-size:11.5px;font-weight:600;color:#475569;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:140px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-top-row[_ngcontent-%COMP%] .mode-badge[_ngcontent-%COMP%]{padding:2px 7px;border-radius:8px;font-size:10.5px;font-weight:700;line-height:1.2;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-top-row[_ngcontent-%COMP%] .mode-badge.mode-flash[_ngcontent-%COMP%]{background:#1a73e81a;color:#1a73e8;border:1px solid rgba(26,115,232,.2)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-top-row[_ngcontent-%COMP%] .mode-badge.mode-pro[_ngcontent-%COMP%]{background:#6366f11f;color:#6366f1;border:1px solid rgba(99,102,241,.25)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%]{margin:8px 0 6px}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%] .card-title[_ngcontent-%COMP%]{font-size:13.5px;font-weight:600;color:#0f172a;margin:0 0 3px;line-height:1.3;letter-spacing:-.01em}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%] .card-desc[_ngcontent-%COMP%]{font-size:12px;color:#64748b;margin:0;line-height:1.45;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:6px;margin-top:6px;padding-top:8px;border-top:1px solid rgba(241,245,249,.85)}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .tag-pill[_ngcontent-%COMP%]{font-size:11px;font-weight:600;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .use-prompt-action[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:3px;font-size:11.5px;font-weight:600;color:#1a73e8;opacity:.85;transition:all .15s ease;flex-shrink:0}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .use-prompt-action[_ngcontent-%COMP%] .action-arrow[_ngcontent-%COMP%]{font-size:13px;transition:transform .15s ease}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%]:hover .use-prompt-action[_ngcontent-%COMP%]{opacity:1}.home-container[_ngcontent-%COMP%] .home-content[_ngcontent-%COMP%] .task-launcher-view[_ngcontent-%COMP%] .smart-suggestions-container[_ngcontent-%COMP%] .suggestions-cards-grid[_ngcontent-%COMP%] .suggestion-card[_ngcontent-%COMP%]:hover .use-prompt-action[_ngcontent-%COMP%] .action-arrow[_ngcontent-%COMP%]{transform:translate(2px)}@keyframes _ngcontent-%COMP%_spin{to{transform:rotate(360deg)}}@keyframes _ngcontent-%COMP%_fadeIn{0%{opacity:0;transform:translateY(3px)}to{opacity:1;transform:translateY(0)}}@keyframes _ngcontent-%COMP%_slideUpFade{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes _ngcontent-%COMP%_slideDownFade{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}@keyframes _ngcontent-%COMP%_floatGlow1{0%{transform:translate(0) scale(1)}50%{transform:translate(35px,45px) scale(1.06)}to{transform:translate(-25px,25px) scale(.96)}}@keyframes _ngcontent-%COMP%_floatGlow2{0%{transform:translate(0) scale(1)}50%{transform:translate(-40px,40px) scale(1.08)}to{transform:translate(20px,60px) scale(.94)}}@keyframes _ngcontent-%COMP%_floatGlow3{0%{transform:translate(0) scale(1)}50%{transform:translate(25px,-30px) scale(1.04)}to{transform:translate(-30px,15px) scale(.97)}}@keyframes _ngcontent-%COMP%_readyPulseGlow{0%{transform:scale(.97)}50%{transform:scale(1.06)}to{transform:scale(.98)}}@keyframes _ngcontent-%COMP%_statusDotPulse{0%{transform:scale(.95);box-shadow:0 0 #10b981b3}70%{transform:scale(1);box-shadow:0 0 0 5px #10b98100}to{transform:scale(.95);box-shadow:0 0 #10b98100}}@keyframes _ngcontent-%COMP%_sparklePulse{0%{transform:scale(.92) rotate(0);opacity:.8}50%{transform:scale(1.12) rotate(8deg);opacity:1}to{transform:scale(.92) rotate(0);opacity:.8}}@media(prefers-reduced-motion:reduce){.home-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow[_ngcontent-%COMP%], .sparkle-icon[_ngcontent-%COMP%], .status-dot[_ngcontent-%COMP%], .slider-dither[_ngcontent-%COMP%] rect[_ngcontent-%COMP%], .slider-solid[_ngcontent-%COMP%], .thumb-ripple[_ngcontent-%COMP%]{animation:none!important}}@keyframes _ngcontent-%COMP%_ditherIn{0%{opacity:0}}@keyframes _ngcontent-%COMP%_solidSweep{0%{transform:scaleX(0)}to{transform:scaleX(1)}}@keyframes _ngcontent-%COMP%_thumbRipple{0%{opacity:.7;transform:translate(-50%,-50%) scale(.6)}to{opacity:0;transform:translate(-50%,-50%) scale(2.6)}}@keyframes _ngcontent-%COMP%_tipPop{0%{opacity:0;transform:translateY(6px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}'],changeDetection:1})};function $n(n){return n?n.split(/(\*\*.*?\*\*|`.*?`)/g).filter(e=>e!=="").map(e=>e.startsWith("**")&&e.endsWith("**")?{text:e.slice(2,-2),bold:!0,code:!1}:e.startsWith("`")&&e.endsWith("`")?{text:e.slice(1,-1),bold:!1,code:!0}:{text:e,bold:!1,code:!1}):[]}function Ss(n){return n?n.split(` -`).map(t=>{let e=t.trim(),o=t.length-t.trimStart().length;if(e.startsWith("- [x] ")||e.startsWith("- [X] ")){let a=e.substring(6);return{type:"checked",segments:$n(a),indent:o}}if(e.startsWith("- [/] ")){let a=e.substring(6);return{type:"progress",segments:$n(a),indent:o}}if(e.startsWith("- [ ] ")){let a=e.substring(6);return{type:"unchecked",segments:$n(a),indent:o}}let i=e.match(/^[-*]\s*(verify|assert)(@end)?\s*:\s*(.*)$/i);if(i){let a=i[1].toLowerCase(),s=!!i[2],c=i[3].trim();return{type:"verify",checkKind:a,atEnd:s,segments:$n(c),indent:o}}let r=e.match(/^[-*]\s*finding\s*:\s*(.*)$/i);if(r){let a=r[1].trim();return{type:"finding",checkKind:"finding",segments:$n(a),indent:o}}if(e.startsWith("- ")||e.startsWith("* ")){let a=e.substring(2);return{type:"list-item",segments:$n(a),indent:o}}if(e.startsWith("# ")){let a=e.substring(2);return{type:"h1",segments:$n(a),indent:o}}if(e.startsWith("## ")){let a=e.substring(3);return{type:"h2",segments:$n(a),indent:o}}if(e.startsWith("### ")){let a=e.substring(4);return{type:"h3",segments:$n(a),indent:o}}return e?{type:"text",segments:$n(t),indent:o}:{type:"empty",segments:[],indent:0}}):[]}function ks(n){let t=Ss(n),e=[],o=[],i=null,r=null,a=0;for(let s of t){if(s.type==="empty")continue;if((s.type==="h1"||s.type==="h2")&&!i){i=s.segments.map(p=>p.text).join("");continue}["checked","progress","unchecked"].includes(s.type)&&(!r||s.indent<=(r._indent??0))?(a++,r={index:a,type:s.type,segments:s.segments,subSteps:[],checks:[],_indent:s.indent},e.push(r)):r&&s.indent>(r._indent??0)?s.type==="verify"||s.type==="assert"||s.type==="finding"?r.checks.push(s):r.subSteps.push(s):o.push(s)}return{title:i,milestones:e,otherLines:o}}function WP(n){if(!n)return null;let t=n.trim();if(t.includes("```json")){let e=t.split("```json");e.length>1&&(t=e[1].split("```")[0].trim())}else if(t.includes("```")){let e=t.split("```");e.length>1&&(t=e[1].split("```")[0].trim())}try{let e=JSON.parse(t);if(e&&typeof e=="object"&&"success"in e)return{success:!!e.success,reason:e.reason||"No reason provided."}}catch(e){}return null}function Vi(n){return n?n.replace(/`([^`]+)`/g,'$1').replace(/\*\*\*([^*]+)\*\*\*/g,"$1").replace(/___([^_]+)___/g,"$1").replace(/\*\*([^*]+)\*\*/g,"$1").replace(/__([^_]+)__/g,"$1").replace(/\*([^*]+)\*/g,"$1").replace(/\b_([^_]+)_\b/g,"$1").replace(/~~([^~]+)~~/g,"$1"):""}function Om(n){if(!n)return"";let o=n.replace(/<\/?(thought|short_term_memory|strong_term_memory|reasoning|plan|task_plan|call_tool)[^\n>]*>?/gi,"").replace(/\r\n/g,` -`).replace(/\r/g,` -`).replace(/\n{3,}/g,` - -`).trim().replace(/&/g,"&").replace(//g,">").split(` -`),i=[],r=null,a=!1,s="",c=[],p=()=>{r&&(i.push(``),r=null)};for(let f=0;f${A}`),a=!1,c=[],s=""}else p(),a=!0,s=C.substring(3).trim(),c=[];continue}if(a){c.push(_);continue}let h=C.match(/^(#{1,6})\s+(.*)$/);if(h){p();let A=h[1].length,N=Vi(h[2]);i.push(`${N}`);continue}if(/^(\-{3,}|\*{3,}|_{3,})$/.test(C)){p(),i.push('
');continue}if(C.startsWith("> ")||C.startsWith(">")){p();let A=Vi(C.replace(/^>\s?/,""));i.push(`
${A}
`);continue}let P=_.match(/^(\s*)([\*\-])\s+(.*)$/);if(P){r!=="ul"&&(p(),r="ul",i.push("
    "));let A=P[1].length,E=Math.max(0,Math.floor((A-2)/2))*12,U=E?` style="margin-left: ${E}px"`:"",ne=P[3],J=ne.match(/^(verify|assert)(@end)?\s*:\s*(.*)$/i),X=ne.match(/^finding\s*:\s*(.*)$/i);if(J){let W=J[1].toLowerCase(),Me=J[2]?"@end":"",Ee=W==="assert"?" assert":"",ft=Vi(J[3].trim());i.push(`${W}${Me}${ft}`)}else if(X){let W=Vi(X[1].trim());i.push(`finding${W}`)}else{let W=Vi(ne);i.push(`${W}`)}continue}let T=_.match(/^(\s*)(\d+)\.\s+(.*)$/);if(T){r!=="ol"&&(p(),r="ol",i.push("
      "));let A=T[1].length,E=Math.max(0,Math.floor((A-2)/2))*12,U=E?` style="margin-left: ${E}px"`:"",ne=Vi(T[3]);i.push(`${ne}`);continue}if(p(),C==="")i.push('
      ');else{let A=Vi(_);i.push(`
      ${A}
      `)}}if(a){let f=c.join(` -`);i.push(`
      ${f}
      `)}return p(),i.join(` -`)}function Gr(n,t=0){if(n!=null){if(typeof n=="number")return n<1e11?n*1e3:n;let e=new Date(n).getTime();if(!isNaN(e)&&e>0)return e}return t}function KP(n,t){if(!t)return-1;let e=String(t);return n.findIndex(o=>o.type==="checker"&&o.data?.trace_id&&String(o.data.trace_id)===e)}function zT(n){for(let t=n.length-1;t>=0;t--)if(n[t].type==="checker"&&n[t].data?.isCompleted===!1)return t;return-1}function BT(n,t){let e=t.data||{};if(!e.event)return;if(e.event==="run_outcome"){let s="checker-outcome",c=n.findIndex(_=>_.id===s),p=F(S(S({},c>-1?n[c].data:{}),e),{phase:"outcome",status:"done",isCompleted:!0,generic_tools:[]}),f={id:s,type:"checker",timestamp:t.timestamp,data:p};c>-1?n[c]=f:n.push(f);return}if(!e.attempt_id)return;let o=`checker-${e.attempt_id}`,i=n.findIndex(s=>s.id===o),r=i>-1?n[i]:null,a=typeof e.ts=="number"?e.ts:t.timestamp?new Date(t.timestamp).getTime()/1e3:void 0;if(e.event==="attempt_started"){let s=F(S(S({},r?.data||{}),e),{status:r?.data?.isCompleted?r.data.status:"running",isCompleted:r?.data?.isCompleted??!1,started_at:r?.data?.started_at??a,verdicts:r?.data?.verdicts||[],findings:r?.data?.findings||[],generic_tools:r?.data?.generic_tools||[]}),c={id:o,type:"checker",timestamp:r?.timestamp||t.timestamp,data:s};r?n[i]=c:n.push(c);return}if(e.event==="attempt_finished"){let s=r?.data?.started_at??a,c=Array.isArray(e.verdicts)?e.verdicts:r?.data?.verdicts||[],p=r?.data?.items?.length?r.data.items:c.map(C=>({kind:C.kind,text:C.item_text,when:C.when})),f=F(S(S({},r?.data||{}),e),{status:e.status||"done",verdicts:c,items:p,findings:Array.isArray(e.findings)?e.findings:r?.data?.findings||[],generic_tools:r?.data?.generic_tools||[],started_at:s,finished_at:a,duration:s!==void 0&&a!==void 0?Math.max(0,a-s):void 0,isCompleted:!0}),_={id:o,type:"checker",timestamp:r?.timestamp||t.timestamp,data:f};r?n[i]=_:n.push(_)}}function HT(n){let t=new Map;n.forEach((e,o)=>{e.type==="checker"&&e.data?.trace_id&&t.set(String(e.data.trace_id),o)}),t.size!==0&&n.forEach((e,o)=>{if(e.type==="checker")return;let i=e.data?.generic_tools||[];if(i.length===0)return;let r=[],a=!1;for(let s of i){let c=s?.trace_id?String(s.trace_id):"",p=s?.parent_trace_id?String(s.parent_trace_id):"";if(c&&t.has(c)&&s?.type==="agent"){a=!0;continue}let f=p?t.get(p):void 0;if(f===void 0){r.push(s);continue}let _=n[f],C=_.data.generic_tools||[];C.some(h=>h.trace_id&&h.trace_id===s.trace_id)||(n[f]=F(S({},_),{data:F(S({},_.data),{generic_tools:[...C,s]})})),a=!0}a&&(n[o]=F(S({},e),{data:F(S({},e.data),{generic_tools:r})}))})}function ZP(n){if(!n||n.length===0)return[];let t=[];return n.forEach(e=>{if(e){if(e.type==="checker_event"){BT(t,e);return}if(e.type==="llm_stream"){let o=e.data?.execution_id||e.id,i=e.data?.step_id,r=e.data?.stream_type||"text",a=e.data?.text||"",s=e.data?.isCompleted??!1,c=KP(t,e.data?.parent_trace_id);if(c>-1){let f=t[c],_=S({},f.data),C=Array.isArray(_.stream_segments)?[..._.stream_segments]:[],h=C.findIndex(A=>A.execution_id===o&&A.stream_type===r),P={execution_id:o,stream_type:r==="thinking"?"thinking":"text",text:a,timestamp:h>-1?C[h].timestamp:e.timestamp,isCompleted:s};h>-1?C[h]=P:C.push(P),_.stream_segments=C;let T=A=>C.filter(N=>N.stream_type===A&&N.text.trim()).map(N=>N.text).join(` - -`);_.operator_native_thinking=T("thinking"),_.operator_raw_thinking=T("text"),r==="thinking"?_.operator_native_thinking_timestamp=_.operator_native_thinking_timestamp||e.timestamp:_.operator_raw_thinking_timestamp=_.operator_raw_thinking_timestamp||e.timestamp,o&&!_.execution_id&&(_.execution_id=o),t[c]=F(S({},f),{data:_});return}let p=-1;if(i&&(p=t.findIndex(f=>f.id===`step-${i}`||f.data?.step_id===i)),p===-1&&o&&(p=t.findIndex(f=>f.data?.execution_id===o||f.id===`stream-${o}`)),p>-1){let f=t[p],_=S({},f.data);r==="thinking"?(_.operator_native_thinking=a,_.operator_native_thinking_timestamp=_.operator_native_thinking_timestamp||e.timestamp):(_.operator_raw_thinking=a,_.operator_raw_thinking_timestamp=_.operator_raw_thinking_timestamp||e.timestamp),i&&!_.step_id&&(_.step_id=i),o&&!_.execution_id&&(_.execution_id=o),_.isCompleted=s,t[p]=F(S({},f),{data:_})}else{let f=i?`step-${i}`:`stream-${o}`,_={execution_id:o,step_id:i,isCompleted:s,generic_tools:[]};r==="thinking"?(_.operator_native_thinking=a,_.operator_native_thinking_timestamp=e.timestamp):(_.operator_raw_thinking=a,_.operator_raw_thinking_timestamp=e.timestamp),t.push({id:f,type:i?"step":"llm_stream",timestamp:e.timestamp,data:_})}}else if(e.type==="step_recorded"||e.type==="step_updated"){let o=e.data.step_id||e.data.step_number||"unknown",i=t.findIndex(r=>r.id===`step-${o}`||r.data?.step_id===o);if(i>-1){let r=t[i],a=r.data.generic_tools||[],s=e.data.generic_tools||[],c=[...a];s.forEach(f=>{let _=c.findIndex(C=>C.trace_id&&f.trace_id&&C.trace_id===f.trace_id);_>-1?c[_]=S(S({},c[_]),f):c.push(f)});let p=F(S(S({},r.data),e.data),{operator_native_thinking:e.data.operator_native_thinking||r.data.operator_native_thinking||void 0,operator_raw_thinking:e.data.operator_raw_thinking||r.data.operator_raw_thinking||void 0,operator_native_thinking_timestamp:r.data.operator_native_thinking_timestamp||e.data.operator_native_thinking_timestamp||(e.data.operator_native_thinking?e.timestamp:void 0),operator_raw_thinking_timestamp:r.data.operator_raw_thinking_timestamp||e.data.operator_raw_thinking_timestamp||(e.data.operator_raw_thinking?e.timestamp:void 0),action_taken:e.data.action_taken||r.data.action_taken||void 0,last_execution_result:e.data.last_execution_result||r.data.last_execution_result||void 0,generic_tools:c,isCompleted:!0});t[i]=F(S({},r),{id:`step-${o}`,type:"step",timestamp:r.timestamp||e.timestamp,data:p})}else t.push({id:`step-${o}`,type:"step",timestamp:e.timestamp,data:F(S({},e.data),{isCompleted:!0,operator_native_thinking_timestamp:e.data.operator_native_thinking_timestamp||(e.data.operator_native_thinking?e.timestamp:void 0),operator_raw_thinking_timestamp:e.data.operator_raw_thinking_timestamp||(e.data.operator_raw_thinking?e.timestamp:void 0),generic_tools:e.data.generic_tools||[]})})}else if(e.type==="trace_recorded"){let o=e.data.type==="action",i=e.data.type==="tool"||o,r=e.data.type==="llm_call"&&(e.data.status==="failed"||e.data.status==="retrying");if(!i&&!r)return;let a=e.data.step_id,s=-1,c=KP(t,e.data.parent_trace_id);if(c===-1&&String(e.data.agent_name||"").toLowerCase()==="checker"&&(c=zT(t)),c>-1&&(s=c),s===-1&&e.data.trace_id&&(s=t.findIndex(p=>p.data?.generic_tools?.some(f=>f.trace_id===e.data.trace_id))),s===-1&&a&&(s=t.findIndex(p=>p.id===`step-${a}`||p.data?.step_id===a)),s===-1&&!a&&(s=t.findIndex(p=>p.id==="step-pre-planning"||p.data?.step_id==="pre-planning")),s===-1&&!a){let p=e.timestamp?new Date(e.timestamp).getTime():0,f=-1;for(let _=0;_=f&&(f=h,s=_)}}if(s>-1){let p=t[s].data,f=p.generic_tools?[...p.generic_tools]:[],_=e.data.trace_id?f.findIndex(C=>C.trace_id===e.data.trace_id):-1;_>-1?f[_]=S(S({},f[_]),e.data):f.push(e.data),t[s]=F(S({},t[s]),{data:F(S({},p),{generic_tools:f})})}else{let p=a||"pre-planning";t.push({id:`step-${p}`,type:"step",timestamp:e.timestamp,data:{step_id:p,isCompleted:!0,generic_tools:[e.data]}})}}}}),HT(t),t.sort((e,o)=>{let i=e.timestamp?new Date(e.timestamp).getTime():0,r=o.timestamp?new Date(o.timestamp).getTime():0;if(Math.abs(i-r)>50)return i-r;let a=p=>p.data?.step_number!==void 0&&p.data.step_number!==null?Number(p.data.step_number):p.data?.step_id==="pre-planning"||p.data?.step_type==="planning"?0:99999,s=a(e),c=a(o);return s!==c&&s!==99999&&c!==99999?s-c:i-r}),t}var YP=new WeakMap;function UT(n){if(typeof n=="string")return{isImage:n.includes("data:image/")||n.includes("base64,"),length:n.length};if(n===null||typeof n!="object")return{isImage:!1,length:String(n).length};let t=YP.get(n);if(t)return t;let e="";try{e=JSON.stringify(n)||""}catch(i){e=String(n)}let o={isImage:e.includes("data:image/")||e.includes("base64,"),length:e.length};return YP.set(n,o),o}function GT(n){if(!n||!n.data)return{total:0,prompt:0,completion:0};let t=n.data;if(t.total_tokens!==void 0&&t.total_tokens!==null&&Number(t.total_tokens)>0){let s=t.token_usage?.prompt_tokens||t.token_usage?.input_tokens||0,c=t.token_usage?.completion_tokens||t.token_usage?.output_tokens||0;return{total:Number(t.total_tokens),prompt:Number(s),completion:Number(c)}}if(t.token_usage&&typeof t.token_usage=="object"){let s=t.token_usage.prompt_tokens||t.token_usage.input_tokens||0,c=t.token_usage.completion_tokens||t.token_usage.output_tokens||0,p=t.token_usage.total_tokens||s+c;if(p>0)return{total:Number(p),prompt:Number(s),completion:Number(c)}}if(t.extra_metadata?.token_usage&&typeof t.extra_metadata.token_usage=="object"){let s=t.extra_metadata.token_usage,c=s.prompt_tokens||s.prompt_token_count||s.input_tokens||0,p=s.completion_tokens||s.candidates_token_count||s.output_tokens||0,f=s.total_tokens||s.total_token_count||c+p;if(f>0)return{total:Number(f),prompt:Number(c),completion:Number(p)}}let e=0,o=0,i=0;if(t.generic_tools&&Array.isArray(t.generic_tools)&&t.generic_tools.forEach(s=>{if(s&&s.payload){let c=s.payload.token_usage||s.payload.usage_metadata;if(c){let p=c.prompt_tokens||c.prompt_token_count||c.input_tokens||0,f=c.completion_tokens||c.candidates_token_count||c.output_tokens||0,_=c.total_tokens||c.total_token_count||p+f;e+=Number(p),o+=Number(f),i+=Number(_)}}}),i>0)return{total:i,prompt:e,completion:o};let r=0,a=0;if(t.operator_native_thinking&&(r+=t.operator_native_thinking.length),t.operator_raw_thinking&&(r+=t.operator_raw_thinking.length),t.generic_tools&&Array.isArray(t.generic_tools)&&t.generic_tools.forEach(s=>{if(s.payload){let c=UT(s.payload);c.isImage?a+=1:r+=c.length}}),r>20||a>0){let s=Math.round(r/4)+a*258;return{total:s,prompt:0,completion:s}}return{total:0,prompt:0,completion:0}}function QP(n){return!n||n<=0?"0 tokens":n<1e3?`${n} tokens`:n<1e6?`${(n/1e3).toFixed(1).replace(/\.0$/,"")}k tokens`:`${(n/1e6).toFixed(2).replace(/\.?0+$/,"")}M tokens`}function JP(n,t){if(!n||n.length===0)return[];let e=[],o=t?t*1e3:0;return n.forEach((i,r)=>{let a=i.timestamp?new Date(i.timestamp).getTime():Date.now();o===0&&a>0&&(o=a);let s=0;i.data?.duration&&typeof i.data.duration=="number"&&i.data.duration>0?s=Math.max(1,Math.round(i.data.duration)):a>=o&&o>0?s=Math.max(1,Math.round((a-o)/1e3)):s=1;let c=GT(i);e.push({id:`phase-${i.id||r}`,durationSeconds:s,tokens:c.total>0?c.total:void 0,promptTokens:c.prompt>0?c.prompt:void 0,completionTokens:c.completion>0?c.completion:void 0,blocks:[i]}),o=a}),e}function XP(n,t){if(!n||typeof n!="object")return[];let e=n.generic_tools?n.generic_tools.length:0,o=n.action_taken?n.action_taken.timestamp||n.action_taken.start_time||n.action_taken.created_at:null,i=typeof n.operator_native_thinking=="string"?n.operator_native_thinking.trim():"",r=typeof n.operator_raw_thinking=="string"?n.operator_raw_thinking.trim():"",a=Array.isArray(n.stream_segments)&&n.stream_segments.length>0?n.stream_segments:null,s=[e,o??"",n.operator_native_thinking_timestamp??"",n.operator_raw_thinking_timestamp??"",i.length,r.length,a?a.map(h=>`${h.execution_id}:${h.stream_type}:${h.text.length}`).join(","):""].join("|");if(t){let h=t.get(n);if(h?.signature===s)return h.events}let c=[],p=Gr(n.timestamp,0),f=0;if(a?a.forEach(h=>{!h.text||!h.text.trim()||c.push({type:h.stream_type==="thinking"?"thinking":"text",data:{text:h.text,execution_id:h.execution_id,segment:!0},timestamp:Gr(h.timestamp,p),sequence:f++})}):(i&&c.push({type:"thinking",data:{text:n.operator_native_thinking},timestamp:Gr(n.operator_native_thinking_timestamp,p),sequence:f++}),r&&c.push({type:"text",data:{text:n.operator_raw_thinking},timestamp:Gr(n.operator_raw_thinking_timestamp,p),sequence:f++})),n.action_taken&&(jn(n.action_taken)||jo(n.action_taken))){let h=Gr(n.action_taken.timestamp??n.action_taken.start_time??n.action_taken.created_at,p);c.push({type:"action",data:n.action_taken,timestamp:h,sequence:f++})}Vd(n.generic_tools).forEach(h=>{let P=Gr(h.timestamp??h.start_time??h.created_at,p);c.push({type:"tool",data:h,timestamp:P,sequence:f++})}),c.sort((h,P)=>h.timestamp-P.timestamp||h.sequence-P.sequence);let C=c.map(h=>({type:h.type,data:h.data,timestamp:h.timestamp}));return t&&t.set(n,{signature:s,events:C}),C}function eO(n){if(!n||n.length===0)return"No logs available.";for(let t=n.length-1;t>=0;t--){let e=n[t];if(e.type==="session_ended"&&(e.data?.status==="cancelled"||e.data?.was_stopped_manually))return"Task stopped manually.";if(e.type==="llm_stream"&&e.data?.text){let o=e.data.text;if(o.includes("```json")&&o.includes('"success"'))return"Execution completed and verified by checker."}if(e.type==="step_recorded"||e.type==="step_updated"){let o=e.data?.action_taken;if(o&&jo(o)){let i=$d(o);if(i)return i}if(e.data?.status==="completed")return e.data.message||"Task completed successfully."}}return"Execution session in progress or ended."}function tO(n,t){if(!n||!t||t.length===0)return 0;let e=n*1e3,o=t[t.length-1],i=o?.timestamp?new Date(o.timestamp).getTime():Date.now();return Math.max(0,Math.round((i-e)/1e3))}function nO(n,t,e=!0){if(!t||!e)return!1;if(!n||n.length===0)return!0;for(let i=n.length-1;i>=Math.max(0,n.length-3);i--){let r=n[i];if(r.type==="session_ended")return!1;if(r.type==="step_recorded"||r.type==="step_updated"){let a=r.data?.action_taken;if(a&&(a.action==="report_task_status"||a==="report_task_status"||jo(a))||r.data?.status==="completed"||r.data?.status==="failed")return!1}}return!n.some(i=>i&&i.type==="llm_stream"&&i.data&&i.data.isCompleted===!1)}var qT=n=>[n];function WT(n,t){n&1&&(l(0,"div",25),u(1," No active or queued tasks "),d())}function KT(n,t){n&1&&$(0,"span",33)}function YT(n,t){if(n&1&&(l(0,"span",35)(1,"span",44),u(2,"phone_android"),d(),l(3,"span",45),u(4),d()()),n&2){let e=m().$implicit,o=m(2);R("title","Device: "+o.getDeviceSerial(e)),g(4),O(o.getDeviceSerial(e))}}function ZT(n,t){n&1&&(l(0,"span",36),u(1,"\xB7"),d())}function QT(n,t){if(n&1){let e=L();l(0,"button",46),k("click",function(i){v(e);let r=m().$implicit,a=m(2);return y(a.stopTask(r.session_id,i))}),l(1,"span",22),u(2,"stop_circle"),d()()}}function JT(n,t){if(n&1){let e=L();l(0,"button",47),k("click",function(i){v(e);let r=m().$implicit,a=m(2);return y(a.deleteTask(r.session_id,i))}),l(1,"span",22),u(2,"delete"),d()()}}function XT(n,t){if(n&1){let e=L();l(0,"div",30),k("click",function(i){let r=v(e).$implicit,a=m(2);return y(a.selectTask(r.session_id,i))}),l(1,"div",31)(2,"span",32),M(3,KT,1,0,"span",33),u(4),it(5,"uppercase"),d(),l(6,"div",34),M(7,YT,5,2,"span",35),M(8,ZT,2,0,"span",36),l(9,"span",37),u(10),it(11,"date"),d(),M(12,QT,3,0,"button",38),M(13,JT,3,0,"button",39),d()(),l(14,"div",40),u(15),d(),l(16,"div",41)(17,"span",42),u(18),d(),l(19,"span",43),u(20),it(21,"date"),d()()()}if(n&2){let e=t.$implicit,o=m(2);w("selected",o.agentService.currentSessionId()===e.session_id)("running",o.getTaskStatus(e)==="running"),g(2),R("ngClass",o.getTaskStatus(e)),g(),b(o.getTaskStatus(e)==="running"?3:-1),g(),V(" ",wi(5,18,o.getTaskStatus(e))," "),g(3),b(o.getDeviceSerial(e)?7:-1),g(),b(o.getDeviceSerial(e)?8:-1),g(2),O(Et(11,20,e.start_time*1e3,"shortTime")),g(2),b(o.getTaskStatus(e)==="running"||o.getTaskStatus(e)==="paused"?12:-1),g(),b(o.getTaskStatus(e)!=="running"&&o.getTaskStatus(e)!=="paused"?13:-1),g(),R("title",xi(e.initial_goal)),g(),V(" ",e.initial_goal||"Unnamed Task"," "),g(2),R("title",e.session_id),g(),V("ID: ",e.session_id),g(2),O(Et(21,23,e.start_time*1e3,"MM/dd/yy"))}}function eA(n,t){n&1&&(l(0,"div",25),u(1," No past task history "),d())}function tA(n,t){n&1&&$(0,"span",33)}function nA(n,t){if(n&1&&(l(0,"span",35)(1,"span",44),u(2,"phone_android"),d(),l(3,"span",45),u(4),d()()),n&2){let e=m().$implicit,o=m(2);R("title","Device: "+o.getDeviceSerial(e)),g(4),O(o.getDeviceSerial(e))}}function oA(n,t){n&1&&(l(0,"span",36),u(1,"\xB7"),d())}function iA(n,t){if(n&1){let e=L();l(0,"button",47),k("click",function(i){v(e);let r=m().$implicit,a=m(2);return y(a.deleteTask(r.session_id,i))}),l(1,"span",22),u(2,"delete"),d()()}}function rA(n,t){if(n&1){let e=L();l(0,"div",30),k("click",function(i){let r=v(e).$implicit,a=m(2);return y(a.selectTask(r.session_id,i))}),l(1,"div",31)(2,"span",32),M(3,tA,1,0,"span",33),u(4),it(5,"uppercase"),d(),l(6,"div",34),M(7,nA,5,2,"span",35),M(8,oA,2,0,"span",36),l(9,"span",37),u(10),it(11,"date"),d(),M(12,iA,3,0,"button",39),d()(),l(13,"div",40),u(14),d(),l(15,"div",41)(16,"span",42),u(17),d(),l(18,"span",43),u(19),it(20,"date"),d()()()}if(n&2){let e=t.$implicit,o=m(2);w("selected",o.agentService.currentSessionId()===e.session_id)("running",o.getTaskStatus(e)==="running"),g(2),R("ngClass",o.getTaskStatus(e)),g(),b(o.getTaskStatus(e)==="running"?3:-1),g(),V(" ",wi(5,17,o.getTaskStatus(e))," "),g(3),b(o.getDeviceSerial(e)?7:-1),g(),b(o.getDeviceSerial(e)?8:-1),g(2),O(Et(11,19,e.start_time*1e3,"shortTime")),g(2),b(o.getTaskStatus(e)!=="running"&&o.getTaskStatus(e)!=="paused"?12:-1),g(),R("title",xi(e.initial_goal)),g(),V(" ",e.initial_goal||"Unnamed Task"," "),g(2),R("title",e.session_id),g(),V("ID: ",e.session_id),g(2),O(Et(20,22,e.start_time*1e3,"MM/dd/yy"))}}function aA(n,t){if(n&1&&(l(0,"div",13)(1,"div",21)(2,"span",22),u(3,"list_alt"),d(),l(4,"span"),u(5,"Task Queue"),d()(),l(6,"div",23)(7,"span",24),u(8,"bolt"),d(),l(9,"span"),u(10),d()(),M(11,WT,2,0,"div",25),G(12,XT,22,26,"div",26,De().trackSession,!0),l(14,"div",27)(15,"span",28),u(16,"history"),d(),l(17,"span"),u(18),d()(),M(19,eA,2,0,"div",25),l(20,"div",29),G(21,rA,21,25,"div",26,De().trackSession,!0),d()()),n&2){let e=m();g(10),V("Active Queue (",e.activeQueue().length,")"),g(),b(e.activeQueue().length===0?11:-1),g(),q(e.activeQueue()),g(6),V("Past Runs & History (",e.historyTasks().length,")"),g(),b(e.historyTasks().length===0?19:-1),g(2),q(e.historyTasks())}}function sA(n,t){if(n&1){let e=L();l(0,"button",52),k("click",function(i){let r=v(e).$implicit,a=m(3);return y(a.selectNote(r,i))}),l(1,"span",53),u(2,"draft"),d(),u(3),d()}if(n&2){let e=t.$implicit,o=m(3);w("active",o.agentService.selectedNoteKey()===e),g(3),V(" ",e," ")}}function cA(n,t){if(n&1&&(l(0,"div",48)(1,"div",50),G(2,sA,4,3,"button",51,De().trackNoteKey,!0),d()()),n&2){let e=m(2);g(2),q(e.noteKeys())}}function lA(n,t){n&1&&(l(0,"div",25)(1,"span",54),u(2,"description"),d(),l(3,"span"),u(4,"No notes available for this session."),d()())}function dA(n,t){if(n&1&&(l(0,"h3",55),u(1),d()),n&2){let e=m(3);g(),O(e.parsedNote().title)}}function uA(n,t){n&1&&(l(0,"span",60),u(1,"check_box"),d())}function gA(n,t){n&1&&(l(0,"span",61),u(1,"indeterminate_check_box"),d())}function pA(n,t){n&1&&(l(0,"span",62),u(1,"check_box_outline_blank"),d())}function fA(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function mA(n,t){n&1&&(l(0,"span",69),u(1,"check_box"),d())}function _A(n,t){n&1&&(l(0,"span",70),u(1,"indeterminate_check_box"),d())}function hA(n,t){n&1&&(l(0,"span",71),u(1,"check_box_outline_blank"),d())}function CA(n,t){n&1&&(l(0,"span",72),u(1,"\u2022"),d())}function MA(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function bA(n,t){if(n&1&&(l(0,"span",73),G(1,MA,2,5,"span",64,Ie),d()),n&2){let e=m().$implicit;g(),q(e.segments)}}function PA(n,t){if(n&1&&(l(0,"div",68),M(1,mA,2,0,"span",69)(2,_A,2,0,"span",70)(3,hA,2,0,"span",71)(4,CA,2,0,"span",72),M(5,bA,3,0,"span",73),d()),n&2){let e,o=t.$implicit;Se("padding-left",o.indent>2?(o.indent-2)*12:0,"px"),R("ngClass",o.type),g(),b((e=o.type)==="checked"?1:e==="progress"?2:e==="unchecked"?3:e==="list-item"?4:-1),g(4),b(o.type!=="empty"?5:-1)}}function OA(n,t){if(n&1&&(l(0,"div",65),G(1,PA,6,5,"div",67,De().trackMarkdownLine,!0),d()),n&2){let e=m().$implicit;g(),q(e.subSteps)}}function vA(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function yA(n,t){if(n&1&&(l(0,"div",75)(1,"div",76)(2,"span",77),u(3),d()(),l(4,"div",78),G(5,vA,2,5,"span",64,Ie),d()()),n&2){let e=t.$implicit;Se("margin-left",e.indent>2?(e.indent-2)*12:0,"px"),R("ngClass",e.type),g(2),w("assert",e.checkKind==="assert"),g(),We("",e.checkKind||"verify","",e.atEnd?" @end":""),g(2),q(e.segments)}}function xA(n,t){if(n&1&&(l(0,"div",66),G(1,yA,7,7,"div",74,De().trackMarkdownLine,!0),d()),n&2){let e=m().$implicit;g(),q(e.checks)}}function wA(n,t){if(n&1&&(l(0,"div",58)(1,"div",59),M(2,uA,2,0,"span",60)(3,gA,2,0,"span",61)(4,pA,2,0,"span",62),l(5,"div",63),G(6,fA,2,5,"span",64,Ie),d()(),M(8,OA,3,0,"div",65),M(9,xA,3,0,"div",66),d()),n&2){let e,o=t.$implicit;R("ngClass",o.type),g(2),b((e=o.type)==="checked"?2:e==="progress"?3:e==="unchecked"?4:-1),g(4),q(o.segments),g(2),b(o.subSteps.length>0?8:-1),g(),b(o.checks.length>0?9:-1)}}function SA(n,t){if(n&1&&(l(0,"div",56),G(1,wA,10,4,"div",58,De().trackMilestone,!0),d()),n&2){let e=m(3);g(),q(e.parsedNote().milestones)}}function kA(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function EA(n,t){if(n&1&&(l(0,"div",81)(1,"div",76)(2,"span",77),u(3),d()(),l(4,"div",78),G(5,kA,2,5,"span",64,Ie),d()()),n&2){let e=m().$implicit;Se("margin-left",e.indent*12,"px"),R("ngClass",e.type),g(2),w("assert",e.checkKind==="assert"),g(),We("",e.checkKind||"verify","",e.atEnd?" @end":""),g(2),q(e.segments)}}function DA(n,t){n&1&&(l(0,"span",69),u(1,"check_box"),d())}function IA(n,t){n&1&&(l(0,"span",70),u(1,"indeterminate_check_box"),d())}function TA(n,t){n&1&&(l(0,"span",71),u(1,"check_box_outline_blank"),d())}function AA(n,t){n&1&&(l(0,"span",72),u(1,"\u2022"),d())}function NA(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function RA(n,t){if(n&1&&(l(0,"span",73),G(1,NA,2,5,"span",64,Ie),d()),n&2){let e=m(2).$implicit;g(),q(e.segments)}}function FA(n,t){if(n&1&&(l(0,"div",82),M(1,DA,2,0,"span",69)(2,IA,2,0,"span",70)(3,TA,2,0,"span",71)(4,AA,2,0,"span",72),M(5,RA,3,0,"span",73),d()),n&2){let e,o=m().$implicit;Se("margin-left",o.indent*12,"px"),R("ngClass",o.type),g(),b((e=o.type)==="checked"?1:e==="progress"?2:e==="unchecked"?3:e==="list-item"?4:-1),g(4),b(o.type!=="empty"?5:-1)}}function LA(n,t){if(n&1&&M(0,EA,7,7,"div",79)(1,FA,6,5,"div",80),n&2){let e=t.$implicit;b(e.type==="verify"||e.type==="finding"?0:1)}}function VA(n,t){if(n&1&&(l(0,"div",57),G(1,LA,2,1,null,null,De().trackMarkdownLine,!0),d()),n&2){let e=m(3);g(),q(e.parsedNote().otherLines)}}function jA(n,t){if(n&1&&(l(0,"div",49),M(1,dA,2,1,"h3",55),M(2,SA,3,0,"div",56),M(3,VA,3,0,"div",57),d()),n&2){let e=m(2);g(),b(e.parsedNote().title?1:-1),g(),b(e.parsedNote().milestones.length>0?2:-1),g(),b(e.parsedNote().otherLines.length>0?3:-1)}}function $A(n,t){if(n&1&&(l(0,"div",14)(1,"div",21)(2,"span",22),u(3,"description"),d(),l(4,"span"),u(5,"Notes & Plans"),d()(),M(6,cA,4,0,"div",48),M(7,lA,5,0,"div",25),M(8,jA,4,3,"div",49),d()),n&2){let e=m();g(6),b(e.noteKeys().length>1?6:-1),g(),b(e.noteKeys().length===0?7:-1),g(),b(e.noteKeys().length>0?8:-1)}}function zA(n,t){if(n&1&&(l(0,"div",83)(1,"span",93),u(2),d(),l(3,"span",94),u(4,"Architecture:"),d(),l(5,"span",95),u(6),d()()),n&2){let e=t,o=m(2);R("ngClass",o.getModelClass(e.name))("title",o.getArchitectureTooltip(e)),g(2),O(o.getModelIcon(e.name)),g(4),O(o.getModelDisplayName(e.name))}}function BA(n,t){n&1&&(l(0,"span",85),u(1," videocam "),d())}function HA(n,t){n&1&&(l(0,"span",86),u(1," progress_activity "),d())}function UA(n,t){n&1&&(l(0,"span",87),u(1," smart_display "),d())}function GA(n,t){n&1&&(l(0,"span",88),u(1," slideshow "),d())}function qA(n,t){n&1&&(l(0,"span",89),u(1," videocam_off "),d())}function WA(n,t){n&1&&(l(0,"span",85),u(1," videocam "),d())}function KA(n,t){n&1&&(l(0,"span",90),u(1,"Recording..."),d())}function YA(n,t){n&1&&(l(0,"span",90),u(1,"Preparing..."),d())}function ZA(n,t){n&1&&(l(0,"span",90),u(1,"Play Recording"),d())}function QA(n,t){n&1&&(l(0,"span",90),u(1,"Step Replay"),d())}function JA(n,t){n&1&&(l(0,"span",90),u(1,"Recording Failed"),d())}function XA(n,t){n&1&&(l(0,"span",90),u(1,"Screen Recording"),d())}function eN(n,t){n&1&&$(0,"span",91)}function tN(n,t){if(n&1&&(l(0,"span",92),u(1),d()),n&2){let e=m(2);g(),V(" ",e.agentService.currentSessionStepFrames().length," ")}}function nN(n,t){if(n&1){let e=L();l(0,"div",15),M(1,zA,7,4,"div",83),l(2,"button",84),k("click",function(){v(e);let i=m();return y(i.agentService.toggleVideoPlayer())}),M(3,BA,2,0,"span",85),M(4,HA,2,0,"span",86),M(5,UA,2,0,"span",87),M(6,GA,2,0,"span",88),M(7,qA,2,0,"span",89),M(8,WA,2,0,"span",85),M(9,KA,2,0,"span",90),M(10,YA,2,0,"span",90),M(11,ZA,2,0,"span",90),M(12,QA,2,0,"span",90),M(13,JA,2,0,"span",90),M(14,XA,2,0,"span",90),M(15,eN,1,0,"span",91),M(16,tN,2,1,"span",92),d()()}if(n&2){let e,o=m();g(),b((e=o.agentService.activeModel())?1:-1,e),g(),w("active",o.agentService.isVideoWindowOpen())("recording",o.agentService.isCurrentSessionRunning())("processing",!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()==="processing")("has-video",!o.agentService.isCurrentSessionRunning()&&!!o.agentService.currentSessionVideoUrl())("has-steps",!o.agentService.isCurrentSessionRunning()&&!o.agentService.currentSessionVideoUrl()&&o.agentService.hasCurrentSessionStepFrames())("failed",!o.agentService.isCurrentSessionRunning()&&!o.agentService.currentSessionVideoUrl()&&!o.agentService.hasCurrentSessionStepFrames()&&o.agentService.currentSessionRecordingStatus()==="failed"),R("title",o.getScreenRecordingButtonTitle()),g(),b(o.agentService.isCurrentSessionRunning()?3:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()==="processing"?4:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()!=="processing"&&o.agentService.currentSessionVideoUrl()?5:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()!=="processing"&&!o.agentService.currentSessionVideoUrl()&&o.agentService.hasCurrentSessionStepFrames()?6:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()!=="processing"&&!o.agentService.currentSessionVideoUrl()&&!o.agentService.hasCurrentSessionStepFrames()&&o.agentService.currentSessionRecordingStatus()==="failed"?7:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()!=="processing"&&!o.agentService.currentSessionVideoUrl()&&!o.agentService.hasCurrentSessionStepFrames()&&o.agentService.currentSessionRecordingStatus()!=="failed"?8:-1),g(),b(o.agentService.isCurrentSessionRunning()?9:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()==="processing"?10:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()!=="processing"&&o.agentService.currentSessionVideoUrl()?11:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()!=="processing"&&!o.agentService.currentSessionVideoUrl()&&o.agentService.hasCurrentSessionStepFrames()?12:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()!=="processing"&&!o.agentService.currentSessionVideoUrl()&&!o.agentService.hasCurrentSessionStepFrames()&&o.agentService.currentSessionRecordingStatus()==="failed"?13:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&o.agentService.currentSessionRecordingStatus()!=="processing"&&!o.agentService.currentSessionVideoUrl()&&!o.agentService.hasCurrentSessionStepFrames()&&o.agentService.currentSessionRecordingStatus()!=="failed"?14:-1),g(),b(o.agentService.isCurrentSessionRunning()?15:-1),g(),b(!o.agentService.isCurrentSessionRunning()&&!o.agentService.currentSessionVideoUrl()&&o.agentService.hasCurrentSessionStepFrames()?16:-1)}}function oN(n,t){n&1&&(l(0,"div",17)(1,"span",96),u(2,"progress_activity"),d(),l(3,"span"),u(4,"Loading run history..."),d()())}function iN(n,t){n&1&&(l(0,"div",18)(1,"div",97)(2,"span",22),u(3,"sensors"),d()(),l(4,"h3"),u(5,"No Stream Activity Selected"),d(),l(6,"p"),u(7,"Please select a session from the Task List on the right to view its real-time log payloads."),d()())}function rN(n,t){if(n&1&&(l(0,"div",109),$(1,"span",110),l(2,"div",111)(3,"span",112),u(4),d()()()),n&2){let e=t.$implicit;g(),w("streaming",e.isActive),g(3),mr(" ",e.message," \xB7 ",e.isActive?"Waiting ":"Waited ","",e.elapsed," ")}}function aN(n,t){if(n&1&&(l(0,"div",98)(1,"div",102)(2,"span",103),u(3),d()(),l(4,"div",104)(5,"div",105)(6,"div",106)(7,"div",107)(8,"div",108),G(9,rN,5,5,"div",109,Ie),d()()()()()()),n&2){let e=m(2);g(3),V("Worked for ",e.startupPreparationDuration(),"s"),g(6),q(e.startupWorkItems())}}function sN(n,t){if(n&1&&(l(0,"span",116)(1,"span",117),u(2,"\xB7"),d(),l(3,"span",118),u(4),d()()),n&2){let e=m(2).$implicit,o=m(2);R("title",o.getTokenTooltip(e)),g(4),O(o.formatTokenCount(e.tokens))}}function cN(n,t){if(n&1&&(l(0,"div",115)(1,"span",103),u(2),d(),M(3,sN,5,2,"span",116),d()),n&2){let e=m(),o=e.$implicit,i=e.$index,r=m(2);w("first-phase",i===0&&r.startupWorkItems().length===0),g(2),We("",r.isCheckerPhase(o)?"Checked":"Worked"," for ",o.durationSeconds,"s"),g(),b(o.tokens?3:-1)}}function lN(n,t){if(n&1&&(l(0,"span",124),u(1),d()),n&2){let e=m(3).$implicit;R("title",e.data.subgoal_text),g(),O(e.data.subgoal_text)}}function dN(n,t){if(n&1&&(l(0,"li",127)(1,"span",128),u(2),d(),l(3,"span",129),u(4),d(),l(5,"span",130),u(6),d()()),n&2){let e=t.$implicit,o=t.$index,i=m(4).$implicit,r=m(4);g(2),O(o+1),g(2),O(e.text),g(2),O(r.getCheckMethodLabel(e,i))}}function uN(n,t){if(n&1&&(l(0,"ol",126),G(1,dN,7,3,"li",127,Do),d()),n&2){let e=m(3).$implicit,o=m(4);g(),q(o.getCheckerItems(e))}}function gN(n,t){if(n&1&&(l(0,"div",120)(1,"div",122),$(2,"span",110),l(3,"span",123),u(4),d(),M(5,lN,2,2,"span",124),l(6,"span",125),u(7),d()(),M(8,uN,3,0,"ol",126),d()),n&2){let e=m(2).$implicit,o=m(4);R("ngClass","tone-"+o.getCheckerTone(e)),g(2),w("streaming",o.isBlockRunning(e)),g(2),O(o.getCheckerPhaseLabel(e)),g(),b(e.data.phase!=="outcome"&&e.data.subgoal_text?5:-1),g(2),O(o.getCheckerStatusLabel(e)),g(),b(!o.isCheckerMuted(e)&&o.getCheckerItems(e).length>0?8:-1)}}function pN(n,t){if(n&1){let e=L();l(0,"div",135)(1,"div",136),k("click",function(){v(e);let i=m().$index,r=m(3).$implicit,a=m(4);return y(a.toggleCheckerSegment(r,i))}),$(2,"span",110),u(3," Thought "),d(),l(4,"div",137)(5,"div",138),$(6,"div",139),d()()()}if(n&2){let e=m(),o=e.$implicit,i=e.$index,r=m(3).$implicit,a=m(4);w("is-running",a.isCheckerSegmentRunning(r,i))("collapsed",a.isCheckerSegmentCollapsed(r,i)),g(2),w("streaming",a.isCheckerSegmentRunning(r,i)),g(4),R("innerHTML",a.renderMarkdown(o.data.text,r.id+"-seg-"+i),Pi)}}function fN(n,t){if(n&1&&(l(0,"div",140)(1,"div",141),$(2,"span",110),u(3," Work "),d(),l(4,"div",142),$(5,"div",139),d()()),n&2){let e=m(),o=e.$implicit,i=e.$index,r=m(3).$implicit,a=m(4);w("is-running",a.isCheckerSegmentRunning(r,i)),g(2),w("streaming",a.isCheckerSegmentRunning(r,i)),g(3),R("innerHTML",a.renderMarkdown(o.data.text,r.id+"-seg-"+i),Pi)}}function mN(n,t){if(n&1){let e=L();l(0,"div",135)(1,"div",136),k("click",function(){v(e);let i=m(4).$implicit,r=m(4);return y(r.toggleCollapse(i.data.execution_id||i.data.step_id||i.id))}),$(2,"span",110),u(3," Thought "),d(),l(4,"div",137)(5,"div",138),$(6,"div",139),d()()()}if(n&2){let e=m().$implicit,o=m(3).$implicit,i=m(4);w("is-running",i.isBlockRunning(o))("collapsed",i.collapsedStreams().has(o.data.execution_id||o.data.step_id||o.id)),g(2),w("streaming",i.isBlockRunning(o)),g(4),R("innerHTML",i.renderMarkdown(i.typedTextsSignal()[o.id+"-native"]||e.data.text,o.id+"-native"),Pi)}}function _N(n,t){if(n&1&&(l(0,"div",140)(1,"div",141),$(2,"span",110),u(3," Work "),d(),l(4,"div",142),$(5,"div",139),d()()),n&2){let e=m().$implicit,o=m(3).$implicit,i=m(4);w("is-running",i.isBlockRunning(o)),g(2),w("streaming",i.isBlockRunning(o)),g(3),R("innerHTML",i.renderMarkdown(i.typedTextsSignal()[o.id]||e.data.text,o.id),Pi)}}function hN(n,t){if(n&1&&(l(0,"div",150)(1,"div",152)(2,"span",153),u(3,"Summary:"),d(),l(4,"span",154),u(5),d()()()),n&2){let e=m(2).$implicit,o=m(7);g(5),V('"',o.getReportStatusExplanation(e.data),'"')}}function CN(n,t){if(n&1&&(l(0,"div",157)(1,"span",159),u(2,"Report & Findings"),d(),$(3,"span",160),d()),n&2){let e=m(3).$index,o=m(3).$implicit,i=m(4);g(3),R("innerHTML",i.renderMarkdown(t,"report-"+o.id+"-"+e),Pi)}}function MN(n,t){if(n&1){let e=L();l(0,"div",161)(1,"span",162),u(2,"Final Verified State"),d(),l(3,"div",163),k("click",function(i){v(e);let r=m(4).$implicit,a=m(3).$implicit,s=m(4);return y(s.openImageModal(s.getStepPreImageUrl(a.data,r.data),r.data,i))}),l(4,"div",164),$(5,"img",165),d()()()}if(n&2){let e=m(4).$implicit,o=m(3).$implicit,i=m(4);g(5),R("src",i.getStepPreImageUrl(o.data,e.data),kt)}}function bN(n,t){if(n&1){let e=L();l(0,"div",161)(1,"span",162),u(2,"Post Verification"),d(),l(3,"div",163),k("click",function(i){v(e);let r=m(4).$implicit,a=m(3).$implicit,s=m(4);return y(s.openImageModal(s.getStepPostImageUrl(a.data,r.data),null,i))}),l(4,"div",164),$(5,"img",166),d()()()}if(n&2){let e=m(4).$implicit,o=m(3).$implicit,i=m(4);g(5),R("src",i.getStepPostImageUrl(o.data,e.data),kt)}}function PN(n,t){if(n&1&&(l(0,"div",158),M(1,MN,6,1,"div",161),M(2,bN,6,1,"div",161),d()),n&2){let e=m(3).$implicit,o=m(3).$implicit,i=m(4);g(),b(i.getStepPreImageUrl(o.data,e.data)?1:-1),g(),b(i.getStepPostImageUrl(o.data,e.data)?2:-1)}}function ON(n,t){if(n&1&&(l(0,"div",155),k("click",function(o){return o.stopPropagation()}),l(1,"div",156),M(2,CN,4,1,"div",157),d(),M(3,PN,3,2,"div",158),d()),n&2){let e,o=m(2).$implicit,i=m(3).$implicit,r=m(4);g(2),b((e=r.getReportStatusExplanation(o.data))?2:-1,e),g(),b(r.getStepPreImageUrl(i.data,o.data)||r.getStepPostImageUrl(i.data,o.data)?3:-1)}}function vN(n,t){if(n&1){let e=L();l(0,"div",143)(1,"div",144),k("click",function(i){v(e);let r=m().$index,a=m(3).$implicit,s=m(4);return y(s.toggleActionExpanded("action-"+a.id+"-"+r,i))}),l(2,"span",145),u(3),d(),l(4,"span",146),u(5),d(),l(6,"span",147)(7,"span",148),u(8),d(),u(9),d(),l(10,"span",149),u(11),d()(),M(12,hN,6,1,"div",150),M(13,ON,4,2,"div",151),d()}if(n&2){let e=m(),o=e.$implicit,i=e.$index,r=m(3).$implicit,a=m(4);w("is-completed",a.getReportStatusValue(o.data)==="completed"||a.getReportStatusValue(o.data)==="success")("is-failed",a.getReportStatusValue(o.data)==="failed")("is-expanded",a.isActionExpanded("action-"+r.id+"-"+i)),g(2),w("is-failed",a.getReportStatusValue(o.data)==="failed"),g(),V(" ",a.getReportStatusValue(o.data)==="failed"?"cancel":"task_alt"," "),g(2),V(" ",a.getReportStatusValue(o.data)==="failed"?"Task Execution Failed":"Task Completed"," "),g(),w("is-failed",a.getReportStatusValue(o.data)==="failed")("is-completed",a.getReportStatusValue(o.data)!=="failed"),g(2),V(" ",a.getReportStatusValue(o.data)==="failed"?"error":"check_circle"," "),g(),V(" ",a.getReportStatusValue(o.data)==="failed"?"Failed":"Completed"," "),g(2),V(" ",a.isActionExpanded("action-"+r.id+"-"+i)?"expand_less":"expand_more"," "),g(),b(!a.isActionExpanded("action-"+r.id+"-"+i)&&a.getReportStatusExplanation(o.data)?12:-1),g(),b(a.isActionExpanded("action-"+r.id+"-"+i)?13:-1)}}function yN(n,t){n&1&&(l(0,"span",169)(1,"span",148),u(2,"error"),d(),u(3," Failed "),d())}function xN(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2,"Target:"),d(),l(3,"span",154),u(4),d()()),n&2){let e=m(3).$implicit,o=m(7);g(4),V('"',o.getActionTargetText(e.data),'"')}}function wN(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2),d(),l(3,"span",154),u(4),d()()),n&2){let e=m(3).$implicit,o=m(7);g(2),V("",o.getActionInputLabel(e.data),":"),g(2),V('"',o.getActionInputText(e.data),'"')}}function SN(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2,"Coordinates:"),d(),l(3,"span",170),u(4),d()()),n&2){let e=m(3).$implicit,o=m(7);g(4),O(o.getActionCoords(e.data))}}function kN(n,t){if(n&1&&(l(0,"div",150),M(1,xN,5,1,"div",152),M(2,wN,5,2,"div",152),M(3,SN,5,1,"div",152),d()),n&2){let e=m(2).$implicit,o=m(7);g(),b(o.getActionTargetText(e.data)?1:-1),g(),b(o.getActionInputText(e.data)?2:-1),g(),b(o.getActionCoords(e.data)?3:-1)}}function EN(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Target"),d(),l(3,"span",173),u(4),d()()),n&2){let e=m(3).$implicit,o=m(7);g(4),V('"',o.getActionTargetText(e.data),'"')}}function DN(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2),d(),l(3,"span",173),u(4),d()()),n&2){let e=m(3).$implicit,o=m(7);g(2),O(o.getActionInputLabel(e.data)),g(2),V('"',o.getActionInputText(e.data),'"')}}function IN(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Coordinates"),d(),l(3,"span",174),u(4),d()()),n&2){let e=m(3).$implicit,o=m(7);g(4),O(o.getActionCoords(e.data))}}function TN(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Target Bounds"),d(),l(3,"span",174),u(4),d()()),n&2){let e=m(3).$implicit,o=m(7);g(4),V("[",o.getActionBounds(e.data),"]")}}function AN(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Target Class"),d(),l(3,"span",174),u(4),d()()),n&2){let e=m(3).$implicit,o=m(7);g(4),O(o.getActionClass(e.data))}}function NN(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2),d(),l(3,"span",174),u(4),d()()),n&2){let e=t.$implicit;g(2),O(e.key),g(2),O(e.value)}}function RN(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Action"),d(),l(3,"span",173),u(4),d()()),n&2){let e=m(3).$implicit,o=m(7);g(4),O(o.getActionTitle(e.data))}}function FN(n,t){if(n&1){let e=L();l(0,"div",161)(1,"span",162),u(2,"Pre-Action (Before)"),d(),l(3,"div",163),k("click",function(i){v(e);let r=m(4).$implicit,a=m(3).$implicit,s=m(4);return y(s.openImageModal(s.getStepPreImageUrl(a.data,r.data),r.data,i))}),l(4,"div",164)(5,"img",175,0),k("load",function(){v(e);let i=Io(6),r=Io(8),a=m(4).$implicit,s=m(7);return y(s.onImageLoad(i,r,a.data))}),d(),$(7,"div",176,1),d()()()}if(n&2){let e=m(4).$implicit,o=m(3).$implicit,i=m(4);g(5),R("src",i.getStepPreImageUrl(o.data,e.data),kt)}}function LN(n,t){if(n&1){let e=L();l(0,"div",161)(1,"span",162),u(2,"Post-Action (After)"),d(),l(3,"div",163),k("click",function(i){v(e);let r=m(4).$implicit,a=m(3).$implicit,s=m(4);return y(s.openImageModal(s.getStepPostImageUrl(a.data,r.data),null,i))}),l(4,"div",164),$(5,"img",177),d()()()}if(n&2){let e=m(4).$implicit,o=m(3).$implicit,i=m(4);g(5),R("src",i.getStepPostImageUrl(o.data,e.data),kt)}}function VN(n,t){if(n&1&&(l(0,"div",158),M(1,FN,9,1,"div",161),M(2,LN,6,1,"div",161),d()),n&2){let e=m(3).$implicit,o=m(3).$implicit,i=m(4);g(),b(i.getStepPreImageUrl(o.data,e.data)?1:-1),g(),b(i.getStepPostImageUrl(o.data,e.data)?2:-1)}}function jN(n,t){if(n&1&&(l(0,"div",172)(1,"span",178),u(2,"error"),d(),l(3,"span",179),u(4),d()()),n&2){let e=m(3).$implicit,o=m(3).$implicit,i=m(4);g(4),O(i.getActionErrorMessage(e.data,o.data))}}function $N(n,t){if(n&1&&(l(0,"div",155),k("click",function(o){return o.stopPropagation()}),l(1,"div",156),M(2,EN,5,1,"div",171),M(3,DN,5,2,"div",171),M(4,IN,5,1,"div",171),M(5,TN,5,1,"div",171),M(6,AN,5,1,"div",171),G(7,NN,5,2,"div",171,De().trackParam,!0),M(9,RN,5,1,"div",171),d(),M(10,VN,3,2,"div",158),M(11,jN,5,1,"div",172),d()),n&2){let e=m(2).$implicit,o=m(3).$implicit,i=m(4);g(2),b(i.getActionTargetText(e.data)?2:-1),g(),b(i.getActionInputText(e.data)?3:-1),g(),b(i.getActionCoords(e.data)?4:-1),g(),b(i.getActionBounds(e.data)?5:-1),g(),b(i.getActionClass(e.data)?6:-1),g(),q(i.getActionExtraParams(e.data)),g(2),b(!i.getActionTargetText(e.data)&&!i.getActionInputText(e.data)&&!i.getActionCoords(e.data)&&!i.getActionBounds(e.data)&&!i.getActionClass(e.data)&&i.getActionExtraParams(e.data).length===0?9:-1),g(),b(i.getStepPreImageUrl(o.data,e.data)||i.getStepPostImageUrl(o.data,e.data)?10:-1),g(),b(i.isActionFailed(e.data,o.data)?11:-1)}}function zN(n,t){if(n&1){let e=L();l(0,"div",167)(1,"div",144),k("click",function(i){v(e);let r=m().$index,a=m(3).$implicit,s=m(4);return y(s.toggleActionExpanded("action-"+a.id+"-"+r,i))}),l(2,"span",168),u(3),d(),l(4,"span",146),u(5),d(),M(6,yN,4,0,"span",169),l(7,"span",149),u(8),d()(),M(9,kN,4,3,"div",150),M(10,$N,12,8,"div",151),d()}if(n&2){let e=m(),o=e.$implicit,i=e.$index,r=m(3).$implicit,a=m(4);w("is-running",a.isItemRunning(o,r))("is-failed",a.isActionFailed(o.data,r.data))("is-expanded",a.isActionExpanded("action-"+r.id+"-"+i)),g(2),w("is-failed",a.isActionFailed(o.data,r.data)),g(),O(a.getActionIcon(o.data)),g(2),O(a.getActionTitle(o.data)),g(),b(a.isActionFailed(o.data,r.data)?6:-1),g(2),V(" ",a.isActionExpanded("action-"+r.id+"-"+i)?"expand_less":"expand_more"," "),g(),b(!a.isActionExpanded("action-"+r.id+"-"+i)&&(a.getActionTargetText(o.data)||a.getActionInputText(o.data)||a.getActionCoords(o.data))?9:-1),g(),b(a.isActionExpanded("action-"+r.id+"-"+i)?10:-1)}}function BN(n,t){n&1&&u(0),n&2&&V(" \xB7 Retrying in ",t,"\u2026 ")}function HN(n,t){if(n&1&&(l(0,"span",112),u(1," LLM temporarily unavailable "),M(2,BN,1,1),d(),l(3,"span",183),u(4," Frequent retries may indicate a low API rate limit. Consider increasing the limit or reducing request concurrency. "),d()),n&2){let e,o=m().$implicit,i=m(10);g(2),b((e=i.getLLMRetryEntryDelay(o))?2:-1,e)}}function UN(n,t){if(n&1&&(l(0,"span",112),u(1),d()),n&2){let e=m().$implicit,o=m(10);g(),V(" Retrying LLM request \xB7 Waited ",o.getLLMRetryEntryWaited(e)," ")}}function GN(n,t){if(n&1&&(l(0,"div",109),$(1,"span",110),l(2,"div",111),M(3,HN,5,1),M(4,UN,2,1,"span",112),d()()),n&2){let e=t.$implicit,o=t.$index,i=m(3).$implicit,r=m(7);g(),w("streaming",o===r.getLLMRetryEntries(i.data).length-1&&r.isLLMRetryEntryWaiting(e)),g(2),b(r.isLLMRetryEntryWaiting(e)?3:-1),g(),b(r.isLLMRetryEntryWaiting(e)?-1:4)}}function qN(n,t){if(n&1&&(l(0,"div",108),G(1,GN,5,4,"div",109,Ie),d()),n&2){let e=m(2).$implicit,o=m(7);g(),q(o.getLLMRetryEntries(e.data))}}function WN(n,t){n&1&&(l(0,"span",187)(1,"span",148),u(2,"pause_circle"),d(),u(3," Paused "),d())}function KN(n,t){n&1&&(l(0,"span",169)(1,"span",148),u(2,"warning"),d(),u(3," Failed "),d())}function YN(n,t){if(n&1&&(l(0,"span",149),u(1),d()),n&2){let e=m(3).$index,o=m(3).$implicit,i=m(4);g(),V(" ",i.isActionExpanded("llm-failure-"+o.id+"-"+e)?"expand_less":"expand_more"," ")}}function ZN(n,t){n&1&&(l(0,"div",152)(1,"span",153),u(2,"Waited:"),d(),l(3,"span",154),u(4),d()()),n&2&&(g(4),O(t))}function QN(n,t){if(n&1&&(l(0,"div",191)(1,"span"),u(2),d(),l(3,"span"),u(4),d()()),n&2){let e=t.$implicit,o=t.$index,i=m(11);g(2),V("Retry ",o+1),g(2),We(" Planned ",i.getLLMRetryEntryDelay(e)||"0s"," \xB7 Waited ",i.getLLMRetryEntryWaited(e)," ")}}function JN(n,t){if(n&1&&(l(0,"div",188)(1,"div",190),u(2,"Retry details"),d(),G(3,QN,5,3,"div",191,Ie),d()),n&2){let e=m(3).$implicit,o=m(7);g(3),q(o.getLLMFailureRetryEntries(e.data))}}function XN(n,t){if(n&1){let e=L();l(0,"div",189)(1,"button",192),k("click",function(i){v(e);let r=m(10);return y(r.resumePausedTask(i))}),l(2,"span",193),u(3,"play_arrow"),d(),l(4,"span"),u(5,"Continue task"),d(),l(6,"span",194),u(7,"arrow_forward"),d()(),l(8,"span",195),u(9,"Task paused \xB7 no steps are running"),d()()}}function eR(n,t){if(n&1){let e=L();l(0,"div",180)(1,"div",184),k("click",function(i){v(e);let r=m(2),a=r.$implicit,s=r.$index,c=m(3).$implicit,p=m(4);return y(p.hasLLMFailureRetryEntries(a.data)&&p.toggleActionExpanded("llm-failure-"+c.id+"-"+s,i))}),l(2,"div",185)(3,"span",186),u(4,"error"),d(),l(5,"span",146),u(6,"LLM Request Failed"),d(),M(7,WN,4,0,"span",187)(8,KN,4,0,"span",169),M(9,YN,2,1,"span",149),d(),l(10,"div",150)(11,"div",152)(12,"span",153),u(13,"What happened:"),d(),l(14,"span",154),u(15,"The AI request could not be completed after automatic retries."),d()(),l(16,"div",152)(17,"span",153),u(18,"Failure reason:"),d(),l(19,"span",154),u(20),d()(),M(21,ZN,5,1,"div",152),M(22,JN,5,0,"div",188),d()(),M(23,XN,10,0,"div",189),d()}if(n&2){let e,o=m(2),i=o.$implicit,r=o.$index,a=m(3).$implicit,s=m(4);g(),w("has-details",s.hasLLMFailureRetryEntries(i.data))("is-expanded",s.isActionExpanded("llm-failure-"+a.id+"-"+r)),g(6),b(s.isTerminalLLMFailure(i.data)?7:8),g(2),b(s.hasLLMFailureRetryEntries(i.data)?9:-1),g(11),O(s.getLLMErrorText(i.data)),g(),b((e=s.getLLMFailureWaited(i.data))?21:-1,e),g(),b(s.isActionExpanded("llm-failure-"+a.id+"-"+r)?22:-1),g(),b(s.isTerminalLLMFailure(i.data)?23:-1)}}function tR(n,t){if(n&1){let e=L();l(0,"span",200),k("click",function(){let i=v(e),r=m(10);return y(r.onToolKeyClick(i))}),l(1,"span",53),u(2,"draft"),d(),u(3),d()}n&2&&(g(3),V(" ",t," "))}function nR(n,t){n&1&&(l(0,"span",202),u(1),d()),n&2&&(g(),V("\xB7 ",t))}function oR(n,t){if(n&1){let e=L();l(0,"span",201),k("click",function(){v(e);let i=m(3).$implicit,r=m(7);return y(r.onVideoToolClick(i.data))}),l(1,"span",53),u(2,"videocam"),d(),u(3),d(),M(4,nR,2,1,"span",202)}if(n&2){let e,o=m(3).$implicit,i=m(7);R("title","Open recording at "+i.getVideoAnalysisRangeLabel(o.data)),g(3),V(" ",i.getVideoAnalysisRangeLabel(o.data)," "),g(),b((e=i.getVideoAnalysisDetail(o.data))?4:-1,e)}}function iR(n,t){if(n&1&&(l(0,"div",196)(1,"div",197),$(2,"span",110),l(3,"div",198)(4,"span"),u(5),d(),M(6,tR,4,1,"span",199),M(7,oR,5,3),d()()()),n&2){let e,o=m(2).$implicit,i=m(3).$implicit,r=m(4);w("is-running",r.isItemRunning(o,i))("is-note-tool",r.isNoteTool(o.data))("is-video-tool",r.isVideoTool(o.data))("is-video-attention",r.isVideoTool(o.data)&&r.isVideoAnalysisAttention(o.data)),g(2),w("streaming",r.isItemRunning(o,i)),g(3),We("",r.isVideoTool(o.data)?r.getVideoAnalysisLabel(o.data):r.getToolDisplayLabel(o.data),"",r.isNoteTool(o.data)&&r.getToolKey(o.data)||r.isVideoTool(o.data)?":":""),g(),b((e=r.isNoteTool(o.data)&&r.getToolKey(o.data))?6:-1,e),g(),b(r.isVideoTool(o.data)?7:-1)}}function rR(n,t){if(n&1&&(l(0,"span",205),u(1),d()),n&2){let e=m(3).$implicit,o=m(7);w("is-outputter",o.getToolAgentName(e.data)==="Outputter"),g(),O(o.getToolAgentName(e.data))}}function aR(n,t){n&1&&(l(0,"span",169)(1,"span",148),u(2,"error"),d(),u(3," Failed "),d())}function sR(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2,"Command:"),d(),l(3,"span",206)(4,"code"),u(5),d()()()),n&2){let e=m(5).$implicit,o=m(7);g(5),O(o.getAdbCommandLine(e.data))}}function cR(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2,"Cwd:"),d(),l(3,"span",154),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),V('"',o.getAdbCwd(e.data),'"')}}function lR(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2,"Terminal ID:"),d(),l(3,"span",154),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),V('"',o.getAdbTerminalId(e.data),'"')}}function dR(n,t){if(n&1&&(M(0,sR,6,1,"div",152),M(1,cR,5,1,"div",152),M(2,lR,5,1,"div",152)),n&2){let e=m(4).$implicit,o=m(7);b(o.getAdbCommandLine(e.data)?0:-1),g(),b(o.getAdbCwd(e.data)?1:-1),g(),b(o.getAdbTerminalId(e.data)?2:-1)}}function uR(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2,"Target:"),d(),l(3,"span",154),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),V('"',o.getToolTargetText(e.data),'"')}}function gR(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2),d(),l(3,"span",154),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(2),V("",o.getToolInputLabel(e.data),":"),g(2),V('"',o.getToolInputText(e.data),'"')}}function pR(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2,"Coordinates:"),d(),l(3,"span",170),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),O(o.getToolCoords(e.data))}}function fR(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2,"Analysis:"),d(),l(3,"span",154),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),V('"',o.getToolAnalysisText(e.data),'"')}}function mR(n,t){if(n&1&&(l(0,"div",152)(1,"span",153),u(2,"Details:"),d(),l(3,"span",154),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),V('"',o.getToolGenericDetails(e.data),'"')}}function _R(n,t){if(n&1&&(M(0,uR,5,1,"div",152),M(1,gR,5,2,"div",152),M(2,pR,5,1,"div",152),M(3,fR,5,1,"div",152),M(4,mR,5,1,"div",152)),n&2){let e=m(4).$implicit,o=m(7);b(o.getToolTargetText(e.data)?0:-1),g(),b(o.getToolInputText(e.data)?1:-1),g(),b(o.getToolCoords(e.data)?2:-1),g(),b(o.getToolAnalysisText(e.data)?3:-1),g(),b(o.getToolGenericDetails(e.data)?4:-1)}}function hR(n,t){if(n&1&&(l(0,"div",150),M(1,dR,3,3),M(2,_R,5,5),d()),n&2){let e=m(3).$implicit,o=m(7);g(),b(o.isAdbCommandTool(e.data)?1:-1),g(),b(o.isAdbCommandTool(e.data)?-1:2)}}function CR(n,t){if(n&1&&(l(0,"div",157)(1,"span",159),u(2,"Command"),d(),l(3,"span",207)(4,"code"),u(5),d()()()),n&2){let e=m(5).$implicit,o=m(7);g(5),O(o.getAdbCommandLine(e.data))}}function MR(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Working Directory"),d(),l(3,"span",173),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),V('"',o.getAdbCwd(e.data),'"')}}function bR(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Terminal ID"),d(),l(3,"span",174),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),O(o.getAdbTerminalId(e.data))}}function PR(n,t){if(n&1&&(M(0,CR,6,1,"div",157),M(1,MR,5,1,"div",171),M(2,bR,5,1,"div",171)),n&2){let e=m(4).$implicit,o=m(7);b(o.getAdbCommandLine(e.data)?0:-1),g(),b(o.getAdbCwd(e.data)?1:-1),g(),b(o.getAdbTerminalId(e.data)?2:-1)}}function OR(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Target"),d(),l(3,"span",173),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),V('"',o.getToolTargetText(e.data),'"')}}function vR(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2),d(),l(3,"span",173),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(2),O(o.getToolInputLabel(e.data)),g(2),V('"',o.getToolInputText(e.data),'"')}}function yR(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Coordinates"),d(),l(3,"span",174),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),O(o.getToolCoords(e.data))}}function xR(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Analysis"),d(),l(3,"span",173),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),V('"',o.getToolAnalysisText(e.data),'"')}}function wR(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2,"Details"),d(),l(3,"span",173),u(4),d()()),n&2){let e=m(5).$implicit,o=m(7);g(4),V('"',o.getToolGenericDetails(e.data),'"')}}function SR(n,t){if(n&1&&(l(0,"div",171)(1,"span",159),u(2),d(),l(3,"span",174),u(4),d()()),n&2){let e=t.$implicit;g(2),O(e.key),g(2),O(e.value)}}function kR(n,t){if(n&1&&(M(0,OR,5,1,"div",171),M(1,vR,5,2,"div",171),M(2,yR,5,1,"div",171),M(3,xR,5,1,"div",171),M(4,wR,5,1,"div",171),G(5,SR,5,2,"div",171,De().trackParam,!0)),n&2){let e=m(4).$implicit,o=m(7);b(o.getToolTargetText(e.data)?0:-1),g(),b(o.getToolInputText(e.data)?1:-1),g(),b(o.getToolCoords(e.data)?2:-1),g(),b(o.getToolAnalysisText(e.data)?3:-1),g(),b(o.getToolGenericDetails(e.data)?4:-1),g(),q(o.getToolExtraParams(e.data))}}function ER(n,t){if(n&1){let e=L();l(0,"div",161)(1,"span",162),u(2,"Pre-Action (Before)"),d(),l(3,"div",163),k("click",function(i){v(e);let r=m(5).$implicit,a=m(3).$implicit,s=m(4);return y(s.openImageModal(s.getStepPreImageUrl(a.data,r.data),r.data,i))}),l(4,"div",164)(5,"img",175,2),k("load",function(){v(e);let i=Io(6),r=Io(8),a=m(5).$implicit,s=m(7);return y(s.onImageLoad(i,r,a.data))}),d(),$(7,"div",176,3),d()()()}if(n&2){let e=m(5).$implicit,o=m(3).$implicit,i=m(4);g(5),R("src",i.getStepPreImageUrl(o.data,e.data),kt)}}function DR(n,t){if(n&1){let e=L();l(0,"div",161)(1,"span",162),u(2,"Post-Action (After)"),d(),l(3,"div",163),k("click",function(i){v(e);let r=m(5).$implicit,a=m(3).$implicit,s=m(4);return y(s.openImageModal(s.getStepPostImageUrl(a.data,r.data),null,i))}),l(4,"div",164),$(5,"img",177),d()()()}if(n&2){let e=m(5).$implicit,o=m(3).$implicit,i=m(4);g(5),R("src",i.getStepPostImageUrl(o.data,e.data),kt)}}function IR(n,t){if(n&1&&(l(0,"div",158),M(1,ER,9,1,"div",161),M(2,DR,6,1,"div",161),d()),n&2){let e=m(4).$implicit,o=m(3).$implicit,i=m(4);g(),b(i.getStepPreImageUrl(o.data,e.data)?1:-1),g(),b(i.getStepPostImageUrl(o.data,e.data)?2:-1)}}function TR(n,t){if(n&1&&(l(0,"div",172)(1,"span",178),u(2,"error"),d(),l(3,"span",179),u(4),d()()),n&2){let e=m(4).$implicit,o=m(7);g(4),O(o.getToolErrorMessage(e.data))}}function AR(n,t){if(n&1&&(l(0,"div",155),k("click",function(o){return o.stopPropagation()}),l(1,"div",156),M(2,PR,3,3),M(3,kR,7,5),d(),M(4,IR,3,2,"div",158),M(5,TR,5,1,"div",172),d()),n&2){let e=m(3).$implicit,o=m(3).$implicit,i=m(4);g(2),b(i.isAdbCommandTool(e.data)?2:-1),g(),b(i.isAdbCommandTool(e.data)?-1:3),g(),b(i.getStepPreImageUrl(o.data,e.data)||i.getStepPostImageUrl(o.data,e.data)?4:-1),g(),b(i.isToolFailed(e.data)?5:-1)}}function NR(n,t){if(n&1){let e=L();l(0,"div",203)(1,"div",144),k("click",function(i){v(e);let r=m(2).$index,a=m(3).$implicit,s=m(4);return y(s.toggleActionExpanded("tool-"+a.id+"-"+r,i))}),l(2,"span",168),u(3),d(),l(4,"span",146),u(5),d(),M(6,rR,2,3,"span",204),M(7,aR,4,0,"span",169),l(8,"span",149),u(9),d()(),M(10,hR,3,2,"div",150),M(11,AR,6,4,"div",151),d()}if(n&2){let e=m(2),o=e.$implicit,i=e.$index,r=m(3).$implicit,a=m(4);w("is-running",a.isItemRunning(o,r))("has-no-details",a.isAdbCommandTool(o.data)?!a.getAdbCommandLine(o.data):!a.getToolTargetText(o.data)&&!a.getToolInputText(o.data)&&!a.getToolCoords(o.data)&&!a.getToolAnalysisText(o.data)&&!a.getToolGenericDetails(o.data)&&a.getToolExtraParams(o.data).length===0)("is-failed",a.isToolFailed(o.data))("is-expanded",a.isActionExpanded("tool-"+r.id+"-"+i)),g(2),w("is-failed",a.isToolFailed(o.data)),g(),O(a.getToolIcon(o.data)),g(2),O(a.getToolTitle(o.data)),g(),b(a.getToolAgentName(o.data)?6:-1),g(),b(a.isToolFailed(o.data)?7:-1),g(2),V(" ",a.isActionExpanded("tool-"+r.id+"-"+i)?"expand_less":"expand_more"," "),g(),b(!a.isActionExpanded("tool-"+r.id+"-"+i)&&(a.isAdbCommandTool(o.data)?a.getAdbCommandLine(o.data):a.getToolTargetText(o.data)||a.getToolInputText(o.data)||a.getToolCoords(o.data)||a.getToolAnalysisText(o.data)||a.getToolGenericDetails(o.data))?10:-1),g(),b(a.isActionExpanded("tool-"+r.id+"-"+i)?11:-1)}}function RR(n,t){if(n&1&&(M(0,qN,3,0,"div",108),M(1,eR,24,10,"div",180),M(2,iR,8,14,"div",181),M(3,NR,12,17,"div",182)),n&2){let e=m().$implicit,o=m(3).$implicit,i=m(4);b(i.isLLMRetry(e.data)?0:-1),g(),b(i.isDisplayableLLMFailure(e.data)?1:-1),g(),b(i.shouldShowTool(e.data,o.data)&&!i.isDeviceActionTool(e.data)?2:-1),g(),b(i.shouldShowTool(e.data,o.data)&&i.isDeviceActionTool(e.data)?3:-1)}}function FR(n,t){if(n&1&&(M(0,pN,7,7,"div",131),M(1,fN,6,5,"div",132),M(2,mN,7,7,"div",131),M(3,_N,6,5,"div",132),M(4,vN,14,19,"div",133),M(5,zN,11,14,"div",134),M(6,RR,4,4)),n&2){let e=t.$implicit,o=m(3).$implicit,i=m(4);b(i.isCheckerBlock(o)&&e.type==="thinking"?0:-1),g(),b(i.isCheckerBlock(o)&&e.type==="text"&&i.isCheckerTextVisible(e)?1:-1),g(),b(!i.isCheckerBlock(o)&&e.type==="thinking"?2:-1),g(),b(!i.isCheckerBlock(o)&&e.type==="text"&&i.getRawThinking(o)?3:-1),g(),b(i.isReportStatusAction(e.data)?4:-1),g(),b(e.type==="action"&&i.isAndroidAction(e.data)?5:-1),g(),b(e.type==="tool"?6:-1)}}function LR(n,t){if(n&1&&(l(0,"div",107),G(1,FR,7,7,null,null,De().trackStepEvent,!0),d()),n&2){let e=m(2).$implicit,o=m(4);g(),q(o.getSortedStepEvents(e.data))}}function VR(n,t){if(n&1&&(l(0,"span",213),u(1),d()),n&2){let e=m().$implicit;g(),O(e.suggestion)}}function jR(n,t){if(n&1&&(l(0,"div",208)(1,"span",128),u(2),d(),l(3,"span",210),u(4),d(),l(5,"span",211)(6,"span",212),u(7),d(),M(8,VR,2,1,"span",213),d()()),n&2){let e=t.$implicit,o=t.$index,i=m(3).$implicit,r=m(4);R("ngClass",e.status),g(2),O(r.getVerdictItemNumber(i,e,o)),g(2),O(r.getVerdictIcon(e.status)),g(3),O(e.evidence||r.getVerdictStatusText(e.status)),g(),b(e.suggestion?8:-1)}}function $R(n,t){if(n&1&&(l(0,"div",209),u(1),d()),n&2){let e=t.$implicit;g(),O(e)}}function zR(n,t){if(n&1&&(l(0,"div",121),G(1,jR,9,5,"div",208,Do),G(3,$R,2,1,"div",209,Ie),d()),n&2){let e=m(2).$implicit,o=m(4);R("ngClass","tone-"+o.getCheckerTone(e)),g(),q(o.getCheckerVerdicts(e)),g(2),q(o.getCheckerNotes(e))}}function BR(n,t){if(n&1&&(l(0,"div",119)(1,"div",106),M(2,gN,9,7,"div",120),M(3,LR,3,0,"div",107),M(4,zR,5,1,"div",121),d()()),n&2){let e=m().$implicit,o=m(4);R("ngClass",Up(4,qT,"type-"+e.type)),g(2),b(o.isCheckerBlock(e)?2:-1),g(),b(o.getSortedStepEvents(e.data).length>0?3:-1),g(),b(o.hasCheckerResult(e)?4:-1)}}function HR(n,t){if(n&1&&M(0,BR,5,6,"div",119),n&2){let e=t.$implicit,o=m(4);b(o.hasVisibleContent(e)?0:-1)}}function UR(n,t){if(n&1&&(l(0,"div",114),G(1,HR,1,1,null,null,De().trackBlock,!0),d()),n&2){let e=m().$implicit;g(),q(e.blocks)}}function GR(n,t){if(n&1&&(l(0,"div",99),M(1,cN,4,5,"div",113),M(2,UR,3,0,"div",114),d()),n&2){let e=t.$implicit,o=m(2);g(),b(o.hasVisibleBlocks(e)?1:-1),g(),b(o.hasVisibleBlocks(e)?2:-1)}}function qR(n,t){if(n&1&&(l(0,"h3",222),u(1),d()),n&2){let e=m();g(),O(e.title)}}function WR(n,t){if(n&1&&(l(0,"strong"),u(1),d()),n&2){let e=m().$implicit;g(),O(e.text)}}function KR(n,t){if(n&1&&(l(0,"code"),u(1),d()),n&2){let e=m().$implicit;g(),O(e.text)}}function YR(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=m().$implicit;g(),O(e.text)}}function ZR(n,t){if(n&1&&(M(0,WR,2,1,"strong"),M(1,KR,2,1,"code"),M(2,YR,2,1,"span")),n&2){let e=t.$implicit;b(e.bold?0:-1),g(),b(e.code?1:-1),g(),b(!e.bold&&!e.code?2:-1)}}function QR(n,t){if(n&1&&(l(0,"div",226)(1,"span",148),u(2),d(),l(3,"span",63),G(4,ZR,3,3,null,null,Ie),d()()),n&2){let e=t.$implicit;Dl("status-"+e.type),g(2),V(" ",e.type==="checked"?"check_circle":e.type==="progress"?"pending":"radio_button_unchecked"," "),g(2),q(e.segments)}}function JR(n,t){if(n&1&&(l(0,"div",223),G(1,QR,6,3,"div",225,De().trackMilestone,!0),d()),n&2){let e=m();g(),q(e.milestones)}}function XR(n,t){if(n&1&&(l(0,"span",231),u(1),d()),n&2){let e=m().$implicit;w("assert",e.checkKind==="assert"),g(),We("",e.checkKind||"verify","",e.atEnd?"@end":"")}}function e3(n,t){n&1&&(l(0,"span",230),u(1,"finding"),d())}function t3(n,t){if(n&1&&(l(0,"strong"),u(1),d()),n&2){let e=m().$implicit;g(),O(e.text)}}function n3(n,t){if(n&1&&(l(0,"code"),u(1),d()),n&2){let e=m().$implicit;g(),O(e.text)}}function o3(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=m().$implicit;g(),O(e.text)}}function i3(n,t){if(n&1&&(M(0,t3,2,1,"strong"),M(1,n3,2,1,"code"),M(2,o3,2,1,"span")),n&2){let e=t.$implicit;b(e.bold?0:-1),g(),b(e.code?1:-1),g(),b(!e.bold&&!e.code?2:-1)}}function r3(n,t){if(n&1&&(l(0,"p",228),M(1,XR,2,4,"span",229),M(2,e3,2,0,"span",230),G(3,i3,3,3,null,null,Ie),d()),n&2){let e=t.$implicit;Dl("line-"+e.type),g(),b(e.type==="verify"?1:-1),g(),b(e.type==="finding"?2:-1),g(),q(e.segments)}}function a3(n,t){if(n&1&&(l(0,"div",224),G(1,r3,5,4,"p",227,De().trackMarkdownLine,!0),d()),n&2){let e=m();g(),q(e.otherLines)}}function s3(n,t){if(n&1&&(l(0,"div",221),M(1,qR,2,1,"h3",222),M(2,JR,3,0,"div",223),M(3,a3,3,0,"div",224),d()),n&2){let e=t;g(),b(e.title?1:-1),g(),b(e.milestones.length>0?2:-1),g(),b(e.otherLines.length>0?3:-1)}}function c3(n,t){if(n&1){let e=L();l(0,"div",100)(1,"div",214)(2,"div",215)(3,"span",216),u(4,"assignment_turned_in"),d(),l(5,"span",217),u(6,"Task Report"),d()(),l(7,"div",218)(8,"button",219),k("click",function(i){v(e);let r=m(2);return y(r.openOutputterNote(i))}),l(9,"span",22),u(10,"visibility"),d(),l(11,"span"),u(12,"View in Notes"),d()()()(),l(13,"div",220),M(14,s3,4,3,"div",221),d()()}if(n&2){let e,o=m(2);g(14),b((e=o.parsedOutputReport())?14:-1,e)}}function l3(n,t){if(n&1&&(l(0,"div",101)(1,"div",232)(2,"span",96),u(3,"progress_activity"),d(),l(4,"span",233),u(5),d()()()),n&2){let e=m(2);g(5),O(e.currentPlanningText())}}function d3(n,t){if(n&1&&(l(0,"div",19),M(1,aN,11,1,"div",98),G(2,GR,3,2,"div",99,De().trackPhase,!0),M(4,c3,15,1,"div",100),M(5,l3,6,1,"div",101),d()),n&2){let e,o=m();g(),b(o.startupWorkItems().length>0?1:-1),g(),q(o.phases()),g(2),b((e=o.outputterReport())?4:-1,e),g(),b(o.showPlanningLoader()&&(o.startupWorkItems().length===0||o.startupPreparationIsComplete()||o.consolidatedBlocks().length>0)?5:-1)}}function u3(n,t){if(n&1){let e=L();l(0,"div",234),k("click",function(i){v(e);let r=m();return y(r.closeImageModal(i))}),l(1,"div",235),k("click",function(i){return i.stopPropagation()}),l(2,"button",236),k("click",function(i){v(e);let r=m();return y(r.closeImageModal(i))}),l(3,"span",22),u(4,"close"),d()(),l(5,"div",164)(6,"img",237,4),k("load",function(){v(e);let i=Io(7),r=Io(9),a=m();return y(a.onImageLoad(i,r,a.selectedZoomAction()))}),d(),$(8,"div",176,5),d()()()}if(n&2){let e=m();g(6),R("src",e.selectedZoomImage(),kt)}}var Es=["Planning next step...","Analyzing screen coordinates...","Consulting neural network...","Formulating tactical action plan...","Deciphering UI state & elements...","Synthesizing decision pathways...","Calibrating next move...","Aligning logical vectors...","Evaluating optimal sub-goals...","Gathering sensory inputs...","Computing next interaction...","Optimizing execution strategy...","Simulating probable outcomes...","Summoning AI intuition...","Brewing the next command...","Strategizing tactical moves..."],oO=[{started:"device_check",completed:"device_ready",completedMessage:"Android device connected"},{started:"uiautomator",completed:"uiautomator_ready",completedMessage:"UI Automator is ready"},{started:"environment",completed:"environment_ready",completedMessage:"Device environment is ready"}];function g3(n){let t=Math.max(0,n);return t<10?`${t.toFixed(1)}s`:`${Math.round(t)}s`}function p3(n,t,e,o){let i=new Map(n.map(a=>[a.stage,a])),r=i.get("first_response");return oO.flatMap((a,s)=>{let c=i.get(a.started),p=i.get(a.completed);if(!c&&!p)return[];let f=oO.slice(s+1).map(A=>i.get(A.started)||i.get(A.completed)).find(A=>!!A),_=a.started==="environment"?r:f,C=p||_,h=!C&&!e&&o,P=c?.timestamp||p?.timestamp||t,T=C?.timestamp||(h?t:n[n.length-1]?.timestamp||P);return[F(S({},p||c),{message:p?.message||(C?a.completedMessage:c.message),isActive:h,elapsed:g3(T-P)})]})}var Wd=class n{agentService=D(It);http=D(Ro);destroyRef=D(Ae);zone=D(ge);isUserAtBottom=!0;resizeObserver=null;streamLogsContainer=null;autoScrollTimer=null;autoScrollStreamBoxes=!1;onContainerScroll=()=>{let t=this.streamLogsContainer;if(!t)return;let e=150,o=t.scrollHeight-t.scrollTop-t.clientHeight;this.isUserAtBottom=o<=e};currentPlanningText=x(Es[0]);planningIntervalId=null;currentPhraseIndex=0;isTaskDropdownOpen=x(!1);isNotesDropdownOpen=x(!1);selectedZoomImage=x(null);selectedZoomAction=x(null);collapsedStreams=x(new Set);scheduledCollapses=new Set;typedTextsSignal=x({});typingTargets=new Map;typingRafId=null;lastTypingTimestamp=0;static TYPING_CHARS_PER_SECOND=667;static TYPING_MIN_FRAME_MS=28;markdownHtmlCache=new Map;thinkingTextCache=new WeakMap;deviceSerialCache=new WeakMap;expandedActionCards=x(new Set);collapsedActionCards=x(new Set);retryClock=x(Date.now());actionParamsCache=new WeakMap;toolParamsCache=new WeakMap;sortedEventsCache=new WeakMap;activeQueue=I(()=>this.agentService.sessions().filter(e=>{let o=this.getTaskStatus(e);return o==="running"||o==="paused"||o==="pending"}).sort((e,o)=>{let i=this.getTaskStatus(e),r=this.getTaskStatus(o),a=i==="running"||i==="paused",s=r==="running"||r==="paused";return a&&!s?-1:!a&&s?1:(e.start_time||0)-(o.start_time||0)}));historyTasks=I(()=>this.agentService.sessions().filter(t=>{let e=this.getTaskStatus(t);return e==="completed"||e==="failed"||e==="cancelled"}));currentNoteContent=I(()=>{let t=this.agentService.currentNotes(),e=this.agentService.selectedNoteKey();return t[e]||""});noteKeys=I(()=>Object.keys(this.agentService.currentNotes()).filter(t=>t.toLowerCase().endsWith(".md")));outputterReport=I(()=>this.agentService.currentNotes()["output.md"]||null);parsedOutputReport=I(()=>{let t=this.outputterReport();return t?ks(t):null});parsedNote=I(()=>this.getParsedNote(this.currentNoteContent()));filteredLogs=I(()=>{let t=this.agentService.sessionLogs(),e=this.agentService.currentSessionId();return e?t.filter(o=>{let i=o.session_id||o.data?.session_id;return!i||i===e}):t});sessionSummary=I(()=>eO(this.filteredLogs()));showPlanningLoader=I(()=>{let t=this.agentService.agentStatus()==="running",e=this.agentService.currentSessionId(),o=this.agentService.runningSessionId(),i=!e||e===o;return nO(this.filteredLogs(),t,i)});isViewingPausedTask=I(()=>{if(!this.agentService.isPaused()||this.agentService.agentStatus()!=="paused")return!1;let t=this.agentService.currentSessionId(),e=this.agentService.runningSessionId();return!t||t===e});sessionDuration=I(()=>{let t=this.agentService.sessions().find(e=>e.session_id===this.agentService.currentSessionId());return tO(t?.start_time||0,this.filteredLogs())});consolidatedBlocks=I(()=>ZP(this.filteredLogs()));phases=I(()=>{let t=this.agentService.sessions().find(e=>e.session_id===this.agentService.currentSessionId());return JP(this.consolidatedBlocks(),t?.start_time||0)});startupWorkItems=I(()=>{this.retryClock();let t=this.agentService.currentStartupProgress(),e=["running","paused"].includes(this.agentService.agentStatus());return p3(t,Date.now()/1e3,this.consolidatedBlocks().length>0,e)});startupPreparationIsRunning=I(()=>this.startupWorkItems().some(t=>t.isActive));startupPreparationIsComplete=I(()=>{let t=this.startupWorkItems();return t.length>0&&!t.some(e=>e.isActive)});startupPreparationDuration=I(()=>{let t=this.startupWorkItems();if(t.length===0)return 0;let e=this.agentService.currentStartupProgress(),o=e[0]?.timestamp||t[0].timestamp,i=e.find(a=>a.stage==="environment_ready")?.timestamp||e.find(a=>a.stage==="first_response")?.timestamp,r=this.startupPreparationIsRunning()?Date.now()/1e3:i||Math.max(...t.map(a=>a.timestamp));return Math.max(1,Math.round(r-o))});retryablePauseTrace=I(()=>{if(!this.isViewingPausedTask())return null;let t=this.consolidatedBlocks();for(let e=t.length-1;e>=0;e--){let o=t[e]?.data?.generic_tools;if(Array.isArray(o))for(let i=o.length-1;i>=0;i--){let r=o[i];if(this.isDisplayableLLMFailure(r))return r}}return null});hasVisibleBlocks(t){return!t||!t.blocks?!1:t.blocks.some(e=>this.hasVisibleContent(e))}constructor(){this.zone.runOutsideAngular(()=>{let t=setInterval(()=>{let e=this.agentService.agentStatus();(e==="running"||e==="paused"||this.agentService.isRetrying())&&this.retryClock.set(Date.now())},1e3);this.destroyRef.onDestroy(()=>clearInterval(t))}),Ye(()=>{this.filteredLogs().find(o=>o.type==="llm_stream"&&!o.data?.isCompleted)&&this.scheduleAutoScroll(!0)}),Ye(()=>{this.consolidatedBlocks(),this.typedTextsSignal(),this.scheduleAutoScroll(!1)}),Ye(()=>{this.consolidatedBlocks().forEach(e=>{if(e.type==="checker")return;let o=e.id,i=this.getRawThinking(e)||"",r=this.getNativeThinking(e)||"";de(()=>{let a=this.typedTextsSignal();i&&(o in a?(a[o]||"").lengthF(S({},p),{[o]:i})):this.startTyping(o,i,!1)):e.data?.isCompleted?this.typedTextsSignal.update(c=>F(S({},c),{[o]:i})):(this.typedTextsSignal.update(c=>F(S({},c),{[o]:""})),this.startTyping(o,i,!1)));let s=o+"-native";if(r){let c=e.data?.execution_id||e.data?.step_id||o;s in a?(a[s]||"").lengthF(S({},f),{[s]:r})),this.collapsedStreams.update(f=>{let _=new Set(f);return _.add(c),_})):this.startTyping(s,r,!0,c)):e.data?.isCompleted?(this.typedTextsSignal.update(p=>F(S({},p),{[s]:r})),this.collapsedStreams.update(p=>{let f=new Set(p);return f.add(c),f})):(this.typedTextsSignal.update(p=>F(S({},p),{[s]:""})),this.startTyping(s,r,!0,c))}})})}),Ye(()=>{this.agentService.currentSessionId(),de(()=>{this.stopTypingLoop(),this.typedTextsSignal.set({}),this.markdownHtmlCache.clear(),this.scheduledCollapses.clear(),this.collapsedStreams.set(new Set),this.isUserAtBottom=!0,setTimeout(()=>{let t=document.querySelector(".stream-logs-content");t&&(t.scrollTop=t.scrollHeight)},100)})}),Ye(()=>{this.showPlanningLoader()?this.planningIntervalId||(this.currentPhraseIndex=Math.floor(Math.random()*Es.length),this.currentPlanningText.set(Es[this.currentPhraseIndex]),this.planningIntervalId=setInterval(()=>{this.currentPhraseIndex=(this.currentPhraseIndex+1)%Es.length,this.currentPlanningText.set(Es[this.currentPhraseIndex])},2800)):this.planningIntervalId&&(clearInterval(this.planningIntervalId),this.planningIntervalId=null)}),this.destroyRef.onDestroy(()=>{this.planningIntervalId&&(clearInterval(this.planningIntervalId),this.planningIntervalId=null),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.stopTypingLoop(),this.autoScrollTimer&&(clearTimeout(this.autoScrollTimer),this.autoScrollTimer=null),this.streamLogsContainer&&(this.streamLogsContainer.removeEventListener("scroll",this.onContainerScroll),this.streamLogsContainer=null)})}ngAfterViewInit(){let t=document.querySelector(".stream-logs-content");this.streamLogsContainer=t,t&&(this.zone.runOutsideAngular(()=>{t.addEventListener("scroll",this.onContainerScroll,{passive:!0})}),typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(()=>{this.isUserAtBottom&&this.scheduleAutoScroll(!1)}),this.resizeObserver.observe(t)))}scheduleAutoScroll(t){this.autoScrollStreamBoxes=this.autoScrollStreamBoxes||t,!this.autoScrollTimer&&this.zone.runOutsideAngular(()=>{this.autoScrollTimer=setTimeout(()=>{this.autoScrollTimer=null;let e=this.autoScrollStreamBoxes;this.autoScrollStreamBoxes=!1;let o=e?Array.from(document.getElementsByClassName("stream-box")):[],i=o.map(s=>s.scrollHeight),r=this.streamLogsContainer,a=r&&this.isUserAtBottom?r.scrollHeight:null;o.forEach((s,c)=>{s.scrollTop=i[c]}),r&&a!==null&&(r.scrollTop=a)},50)})}toggleTaskDropdown(t){t.stopPropagation(),this.isTaskDropdownOpen.update(e=>!e),this.isTaskDropdownOpen()&&this.isNotesDropdownOpen.set(!1)}toggleNotesDropdown(t){t.stopPropagation(),this.isNotesDropdownOpen.update(e=>!e),this.isNotesDropdownOpen()&&this.isTaskDropdownOpen.set(!1)}openOutputterNote(t){t&&t.stopPropagation(),this.agentService.selectedNoteKey.set("output.md"),this.isNotesDropdownOpen.set(!0),this.isTaskDropdownOpen.set(!1)}closeAllDropdowns(){this.isTaskDropdownOpen.set(!1),this.isNotesDropdownOpen.set(!1)}getTaskStatus(t){if(t.status){let e=t.status.toLowerCase();if(e==="completed"||e==="success"||e==="failed"||e==="cancelled")return e==="success"?"completed":e;if(e==="running"||e==="paused"||e==="pending")return e}return t.session_id===this.agentService.runningSessionId()&&(this.agentService.agentStatus()==="running"||this.agentService.agentStatus()==="paused")?this.agentService.agentStatus():"completed"}getDeviceSerial(t){if(this.deviceSerialCache.has(t))return this.deviceSerialCache.get(t)??null;let e=null,o=t.device_serial||t.device_id;if(o&&o!=="pending"&&o!=="null"&&o!=="undefined")e=o;else if(t.device_info)try{let i=typeof t.device_info=="string"?JSON.parse(t.device_info):t.device_info,r=i?.device_id||i?.device_serial;r&&r!=="pending"&&r!=="null"&&r!=="undefined"&&(e=r)}catch(i){}return this.deviceSerialCache.set(t,e),e}selectTask(t,e){e&&e.stopPropagation(),this.agentService.selectSession(t,!0),this.isTaskDropdownOpen.set(!1)}stopTask(t,e){e&&e.stopPropagation(),this.agentService.stopTask(t,!1)}deleteTask(t,e){e&&e.stopPropagation(),confirm("Are you sure you want to delete this task? This cannot be undone.")&&this.agentService.deleteSession(t).subscribe({error:o=>{console.error(`Failed to delete session ${t}:`,o)}})}selectNote(t,e){e&&e.stopPropagation(),this.agentService.selectedNoteKey.set(t)}getParsedNote(t){return ks(t)}getParsedNoteLines(t){return Ss(t)}startTyping(t,e,o=!1,i){let r=t.endsWith("-native")?t.replace("-native",""):t;this.typingTargets.set(t,{blockId:r,isThinking:o,execId:i,fallbackText:e}),this.ensureTypingLoop()}ensureTypingLoop(){this.typingRafId===null&&(this.lastTypingTimestamp=performance.now(),this.zone.runOutsideAngular(()=>{let t=e=>{this.typingRafId=null;let o=e-this.lastTypingTimestamp;o>=n.TYPING_MIN_FRAME_MS&&(this.lastTypingTimestamp=e,this.advanceTyping(o)),this.typingTargets.size>0&&(this.typingRafId=requestAnimationFrame(t))};this.typingRafId=requestAnimationFrame(t)}))}stopTypingLoop(){this.typingTargets.clear(),this.typingRafId!==null&&(cancelAnimationFrame(this.typingRafId),this.typingRafId=null)}advanceTyping(t){let e=de(()=>this.consolidatedBlocks()),o=de(()=>this.typedTextsSignal()),i=Math.max(1,Math.round(n.TYPING_CHARS_PER_SECOND*t/1e3)),r={},a=!1;for(let[s,c]of this.typingTargets){let p=e.find(C=>C.id===c.blockId),f=c.fallbackText;p&&(f=(c.isThinking?this.getNativeThinking(p):this.getRawThinking(p))||c.fallbackText);let _=o[s]||"";_.lengthS(S({},s),r))}triggerDelayedCollapse(t){this.scheduledCollapses.has(t)||(this.scheduledCollapses.add(t),setTimeout(()=>{this.collapsedStreams.update(e=>{let o=new Set(e);return o.add(t),o})},1e3))}onDetailsToggle(t,e){let i=t.target.open;this.collapsedStreams.update(r=>{let a=new Set(r);return i?a.delete(e):a.add(e),a})}toggleCollapse(t){this.collapsedStreams.update(e=>{let o=new Set(e);return o.has(t)?o.delete(t):o.add(t),o})}getActionObject(t){return ke(t)}isAndroidAction(t){return jn(t)}getActionIcon(t){return zd(t)}getActionTitle(t){return mm(t)}getActionTargetText(t){return _m(t)}getActionInputLabel(t){return AP(t)}getActionInputText(t){return NP(t)}getActionCoords(t){return hm(t)}isActionFailed(t,e){return Bd(t,e)}getActionErrorMessage(t,e){return RP(t,e)}isActionExpanded(t,e=!1){return this.collapsedActionCards().has(t)?!1:this.expandedActionCards().has(t)?!0:e}toggleActionExpanded(t,e,o=!1){e&&e.stopPropagation(),this.isActionExpanded(t,o)?(this.expandedActionCards.update(r=>{let a=new Set(r);return a.delete(t),a}),this.collapsedActionCards.update(r=>{let a=new Set(r);return a.add(t),a})):(this.collapsedActionCards.update(r=>{let a=new Set(r);return a.delete(t),a}),this.expandedActionCards.update(r=>{let a=new Set(r);return a.add(t),a}))}getActionBounds(t){return FP(t)}getActionResourceId(t){return LP(t)}getActionClass(t){return VP(t)}getActionExtraParams(t){return jP(t,this.actionParamsCache)}getToolExtraParams(t){return kP(t,this.toolParamsCache)}getStepPreImageUrl(t,e){return Cm(t,e)}getStepPostImageUrl(t,e){return Mm(t,e)}openImageModal(t,e,o){o&&o.stopPropagation(),this.selectedZoomImage.set(t),this.selectedZoomAction.set(e||null)}closeImageModal(t){t&&t.stopPropagation(),this.selectedZoomImage.set(null),this.selectedZoomAction.set(null)}onImageLoad(t,e,o){if(!(!t||!e))try{this.drawActionCoordinatesOnOverlay(t,e,o)}catch(i){console.warn("Failed to draw action overlay:",i)}}drawActionCoordinatesOnOverlay(t,e,o){Rd(t,e,o)}firstSaveNoteByKey=I(()=>{let t=new Map;for(let e of this.consolidatedBlocks())if(e.type==="step"&&e.data.generic_tools){for(let o of this.getUniqueGenericTools(e.data.generic_tools))if(o.name&&o.name.toLowerCase()==="save_note"){let i=this.getToolKey(o);i&&!t.has(i)&&t.set(i,o)}}return t});isFirstSaveNoteForKey(t){if(!t||!t.name||t.name.toLowerCase()!=="save_note")return!1;let e=this.getToolKey(t);if(!e)return!0;let o=this.firstSaveNoteByKey().get(e);return o?t.trace_id&&o.trace_id?t.trace_id===o.trace_id:t===o:!0}getToolDisplayLabel(t){return CP(t,this.isFirstSaveNoteForKey(t))}isNoteTool(t){return pP(t)}isVideoTool(t){return Fd(t)}getVideoToolTarget(t){return fP(t)}getVideoAnalysisLabel(t){return Fi(t)?.title||"Analyzing screen recording"}getVideoAnalysisRangeLabel(t){let e=Fi(t)?.requestedRange;return e?`${cm(e.start)}\u2013${cm(e.end)}`:"Screen recording"}getVideoAnalysisDetail(t){let e=Fi(t);return!e||e.totalCount<=1?"":e.outcome==="running"||e.outcome==="recovering"?e.completedCount>0?`${e.completedCount}/${e.totalCount} segments saved`:"":e.outcome==="partial"?`${e.completedCount}/${e.totalCount} segments saved`:""}isVideoAnalysisAttention(t){let e=Fi(t)?.outcome;return e==="partial"||e==="failed"}onVideoToolClick(t){let e=this.agentService.currentSessionId();if(e){let o=Fi(t)?.requestedRange?.start;this.agentService.openVideoPlayer(e,void 0,void 0,o)}}getScreenRecordingButtonTitle(){return this.agentService.isCurrentSessionRunning()?"Task is currently running (Recording screen)":this.agentService.currentSessionRecordingStatus()==="processing"?"Preparing screen recording...":this.agentService.currentSessionVideoUrl()?"Play Screen Recording Video":this.agentService.hasCurrentSessionStepFrames()?this.agentService.currentSessionRecordingStatus()==="failed"?"Video recording failed \u2014 Click to replay step-by-step screenshots":"Play step-by-step screenshots replay":this.agentService.currentSessionRecordingStatus()==="failed"?"Screen recording generation failed":"Screen Recording"}isDeviceActionTool(t){return Ld(t)}isFailureAnalyzerActionTool(t){return Ld(t)}getToolAgentName(t){return _P(t)}shouldShowTool(t,e){return mP(t,e)}getUniqueGenericTools(t){return Vd(t)}getSortedStepEvents(t){return XP(t,this.sortedEventsCache)}getThinkingTexts(t){let e=this.thinkingTextCache.get(t);if(!e){let o=t.operator_native_thinking||(t.stream_type==="thinking"?t.text:null),i=t.operator_raw_thinking||(t.stream_type==="text"?t.text:null);e={native:o&&o.trim()?o:null,raw:i&&i.trim()&&this.isHumanThinking(i)?i:null},this.thinkingTextCache.set(t,e)}return e}getNativeThinking(t){return!t||!t.data?null:this.getThinkingTexts(t.data).native}getRawThinking(t){return!t||!t.data?null:this.getThinkingTexts(t.data).raw}isCheckerBlock(t){return t?.type==="checker"}isCheckerPhase(t){let e=Array.isArray(t?.blocks)?t.blocks:[];return e.length>0&&e.every(o=>this.isCheckerBlock(o))}getCheckerPhaseLabel(t){switch(t?.data?.phase){case"final":return"Final check";case"outcome":return"Result";default:return"Check"}}getCheckerVerdicts(t){return Array.isArray(t?.data?.verdicts)?t.data.verdicts:[]}getCheckerItems(t){let e=t?.data||{};return Array.isArray(e.items)&&e.items.length>0?e.items:this.getCheckerVerdicts(t).map(o=>({kind:o.kind,text:o.item_text,when:o.when}))}getCheckMethodLabel(t,e){let o=[t?.kind==="assert"?"Test assertion":"Must pass"];return t?.when==="at_end"&&e?.data?.phase!=="final"&&o.push("at the end"),o.join(" \xB7 ")}isCheckerMuted(t){let e=t?.data?.status;return e==="superseded"||e==="unchecked"}getVerdictItemNumber(t,e,o){let i=this.getCheckerItems(t).findIndex(r=>r.text===e?.item_text);return(i>-1?i:o)+1}getVerdictStatusText(t){switch(t){case"passed":return"Passed";case"failed":return"Failed";case"inconclusive":return"Could not be confirmed";case"superseded":return"Superseded by a newer check";case"unchecked":return"Not checked";default:return t||""}}hasCheckerResult(t){return!this.isCheckerBlock(t)||this.isBlockRunning(t)||this.isCheckerMuted(t)?!1:t.data?.phase==="outcome"?this.getCheckerNotes(t).length>0:this.getCheckerVerdicts(t).length>0||this.getCheckerNotes(t).length>0}getCheckerNotes(t){let e=t?.data||{};if(e.phase==="outcome")return Array.isArray(e.last_findings)?e.last_findings:[];let o=[];if(Array.isArray(e.unmet_subgoals))for(let i of e.unmet_subgoals)o.push(`Not finished yet: ${i}`);return e.reverted&&o.push("The step was sent back to be redone."),e.error&&o.push(String(e.error)),o}openCheckSegments=x(new Set);isCheckerSegmentRunning(t,e){return this.isBlockRunning(t)?e===this.getSortedStepEvents(t.data).length-1:!1}isCheckerSegmentCollapsed(t,e){return this.isCheckerSegmentRunning(t,e)?!1:!this.openCheckSegments().has(`${t.id}-${e}`)}toggleCheckerSegment(t,e){let o=`${t.id}-${e}`;this.openCheckSegments.update(i=>{let r=new Set(i);return r.has(o)?r.delete(o):r.add(o),r})}isCheckerTextVisible(t){let e=t?.data?.text;return typeof e=="string"&&e.trim().length>0&&this.isHumanThinking(e)}getCheckerTone(t){let e=t?.data||{};if(e.phase==="outcome")return e.task_status==="completed"?"passed":e.task_status==="blocked"?"failed":"inconclusive";if(e.isCompleted===!1)return"running";if(e.status==="superseded"||e.status==="unchecked")return"muted";if(e.status==="error")return"inconclusive";let o=this.getCheckerVerdicts(t);return o.some(i=>i.status==="failed")?"failed":o.some(i=>i.status==="inconclusive")?"inconclusive":"passed"}getCheckerStatusLabel(t){let e=t?.data||{};if(e.phase==="outcome"){let r=e.tests||{},a=e.task_status==="completed"?"Goal completed":e.task_status==="blocked"?"Blocked":"Partially completed",s=[[r.passed,"passed"],[r.failed,"failed"],[r.inconclusive,"inconclusive"],[r.unchecked,"not checked"]].filter(([c])=>Number(c)>0).map(([c,p])=>`${c} ${p}`);return s.length>0?`${a} \xB7 ${s.join(" \xB7 ")}`:a}if(e.isCompleted===!1)return"Checking\u2026";switch(e.status){case"superseded":return"Superseded";case"unchecked":return"Not checked";case"error":return"No verdict"}let o=this.getCheckerVerdicts(t),i=o.filter(r=>r.status==="failed").length;return i>0?`${i} failed`:o.some(r=>r.status==="inconclusive")?"Inconclusive":o.length>0?"Passed":"Done"}getVerdictIcon(t){switch(t){case"passed":return"check_circle";case"failed":return"cancel";case"inconclusive":return"help";case"superseded":return"history";case"unchecked":return"radio_button_unchecked";default:return"pending"}}hasVisibleContent(t){if(!t)return!1;if(t.type==="checker")return!0;let e=!!this.getNativeThinking(t),o=!!this.getRawThinking(t),i=!!t.data?.generic_tools&&t.data.generic_tools.some(a=>this.shouldShowTool(a,t.data)||this.isDisplayableLLMFailure(a)||this.isLLMRetry(a)||this.isReportStatusAction(a)),r=!!t.data?.action_taken&&(this.isAndroidAction(t.data.action_taken)||this.isReportStatusAction(t.data.action_taken));return e||o||i||r}isReportStatusAction(t){return jo(t)}getReportStatusValue(t){return TP(t)}getReportStatusExplanation(t){return $d(t)}isHumanThinking(t){return EP(t)}isTerminalLLMFailure(t){return!!t&&this.retryablePauseTrace()===t}isDisplayableLLMFailure(t){return t?.type==="llm_call"&&t?.status==="failed"&&(t?.name==="llm_pause"||t?.payload?.pause===!0)}resumePausedTask(t){t.stopPropagation(),this.agentService.resumeTask()}getLLMErrorText(t){let e="The AI provider did not return error details after the request failed.";if(!t)return e;let o=t.payload?.error||t.error;if(!o)return e;let i=this.cleanErrorMessage(o);return i==="Unknown error"?e:i}isLLMRetry(t){return t?.type==="llm_call"&&t?.status==="retrying"&&t?.payload?.source==="provider_sdk"&&["google","gemini"].includes(String(t?.payload?.provider||"").toLowerCase())}getLLMRetryEntries(t){let e=t?.payload?.retries;return Array.isArray(e)&&e.length>0?e:[t?.payload||t]}getLLMFailureRetryEntries(t){let e=t?.payload?.retries;return Array.isArray(e)?e.filter(o=>o?.source==="provider_sdk"&&["google","gemini"].includes(String(o?.provider||"").toLowerCase())):[]}hasLLMFailureRetryEntries(t){return this.getLLMFailureRetryEntries(t).length>0}getLLMRetryEntryDelay(t){let e=Number(t?.delay);return!Number.isFinite(e)||e<=0?null:`${e.toFixed(2).replace(/\.00$/,"")}s`}getLLMRetryEntryWaited(t){let e=Number(t?.delay);if(!Number.isFinite(e)||e<=0)return"0s";let o=Number(t?.scheduled_at??t?.timestamp);if(!Number.isFinite(o)||o<=0)return this.formatLLMDuration(e);let i=o<1e11?o*1e3:o,r=Math.min(e,Math.max(0,(this.retryClock()-i)/1e3));return this.formatLLMDuration(r)}isLLMRetryEntryWaiting(t){let e=Number(t?.delay),o=Number(t?.scheduled_at??t?.timestamp);if(!Number.isFinite(e)||e<=0||!Number.isFinite(o))return!1;let i=o<1e11?o*1e3:o;return this.retryClock()r.session_id===e);return!(i&&(i.status==="completed"||i.status==="failed"||i.status==="cancelled"))}isItemRunning(t,e){if(!t||!t.data||!this.isCurrentSessionActive()||t.data.status==="success"||t.data.status==="failed"||t.data.status==="cancelled"||this.isReportStatusAction(t.data)||this.isReportStatusAction(t.data?.action_taken))return!1;if(t.data.status==="running")return!0;let o=this.consolidatedBlocks(),i=o.length>0?o[o.length-1]:null;if(i&&(i.id===e?.id||!e?.data?.isCompleted)){let r=this.getSortedStepEvents(e.data),a=r.length>0?r[r.length-1]:null;if(a&&(a.data?.trace_id===t.data?.trace_id||a===t))return!0}return!1}isBlockRunning(t){if(!t||!t.data||!this.isCurrentSessionActive())return!1;if(t.type==="checker")return t.data.isCompleted===!1;if(this.isReportStatusAction(t.data.action_taken)||t.data?.status==="completed"||t.data?.status==="failed"||t.data?.status==="cancelled")return!1;if(t.data.isCompleted===!1)return!0;let e=this.consolidatedBlocks();return(e.length>0?e[e.length-1]:null)?.id===t.id}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=Ge({type:n,selectors:[["app-agent-stream"]],decls:21,vars:11,consts:[["preImg",""],["preOverlay",""],["preImgTool",""],["preOverlayTool",""],["modalImg",""],["modalOverlay",""],[1,"agent-stream-container"],[1,"vscode-nav-header"],[1,"vscode-tab-container"],["title","Task Queue","aria-label","Task Queue",1,"vscode-tab-btn",3,"click"],[1,"material-symbols-outlined","tab-icon"],[1,"tab-label"],["title","Notes & Plans","aria-label","Notes & Plans",1,"vscode-tab-btn",3,"click"],[1,"vscode-dropdown-menu","task-dropdown"],[1,"vscode-dropdown-menu","notes-dropdown"],[1,"stream-floating-toolbar"],[1,"stream-logs-content"],["aria-live","polite",1,"session-loading-state"],[1,"empty-state"],[1,"logs-list-container"],[1,"image-modal-backdrop"],[1,"popover-title-header"],[1,"material-symbols-outlined"],[1,"dropdown-section-label"],[1,"material-symbols-outlined","icon-bolt"],[1,"dropdown-empty-state"],[1,"dropdown-item-card",3,"selected","running"],[1,"dropdown-section-label","history-label"],[1,"material-symbols-outlined","icon-history"],[1,"dropdown-history-list"],[1,"dropdown-item-card",3,"click"],[1,"item-header"],[1,"task-badge",3,"ngClass"],[1,"status-dot"],[1,"item-header-actions"],[1,"item-device",3,"title"],[1,"item-time-divider"],[1,"item-time"],["type","button","title","Stop this task","aria-label","Stop this task",1,"btn-stop-card"],["type","button","title","Delete this task","aria-label","Delete this task",1,"btn-delete-card"],[1,"item-goal",3,"title"],[1,"item-footer"],[1,"item-id",3,"title"],[1,"item-date"],[1,"material-symbols-outlined","device-icon"],[1,"device-name"],["type","button","title","Stop this task","aria-label","Stop this task",1,"btn-stop-card",3,"click"],["type","button","title","Delete this task","aria-label","Delete this task",1,"btn-delete-card",3,"click"],[1,"notes-selector-container"],[1,"dropdown-notes-content"],[1,"notes-selector-list"],[1,"note-selector-pill",3,"active"],[1,"note-selector-pill",3,"click"],[1,"material-symbols-outlined","pill-icon"],[1,"material-symbols-outlined","empty-icon"],[1,"note-title"],[1,"milestones-container"],[1,"other-lines-container"],[1,"milestone-block",3,"ngClass"],[1,"milestone-title-row"],[1,"material-symbols-outlined","milestone-status-icon","checked"],[1,"material-symbols-outlined","milestone-status-icon","progress"],[1,"material-symbols-outlined","milestone-status-icon","unchecked"],[1,"milestone-text"],[3,"bold-segment","code-segment"],[1,"milestone-substeps"],[1,"milestone-checks-container"],[1,"substep-row",3,"ngClass","padding-left"],[1,"substep-row",3,"ngClass"],[1,"material-symbols-outlined","check-icon","checked"],[1,"material-symbols-outlined","check-icon","progress"],[1,"material-symbols-outlined","check-icon","unchecked"],[1,"bullet"],[1,"line-text"],[1,"verification-card",3,"ngClass","margin-left"],[1,"verification-card",3,"ngClass"],[1,"card-header"],[1,"card-tag"],[1,"card-body"],[1,"verification-card","standalone",3,"ngClass","margin-left"],[1,"md-line",3,"ngClass","margin-left"],[1,"verification-card","standalone",3,"ngClass"],[1,"md-line",3,"ngClass"],[1,"model-info-chip",3,"ngClass","title"],[1,"btn-screen-recording",3,"click","title"],[1,"material-symbols-outlined","video-icon"],[1,"material-symbols-outlined","video-icon","spin-animation"],[1,"material-symbols-outlined","video-icon","play-icon"],[1,"material-symbols-outlined","video-icon","steps-icon"],[1,"material-symbols-outlined","video-icon","error-icon"],[1,"btn-text"],[1,"video-pulse-dot","red"],[1,"steps-count-badge"],[1,"material-symbols-outlined","model-icon"],[1,"model-label"],[1,"model-name"],[1,"material-symbols-outlined","spin-animation"],[1,"empty-icon"],["aria-live","polite",1,"phase-container","startup-phase"],[1,"phase-container"],[1,"outputter-synthesis-stream-card"],[1,"planning-loader-container"],[1,"phase-header","first-phase"],[1,"phase-worked-time"],["aria-label","Task startup progress",1,"phase-body"],[1,"block-item","type-stream"],[1,"step-body"],[1,"step-actions-container"],[1,"llm-retry-notes"],[1,"llm-retry-note"],[1,"stream-status-dot"],[1,"llm-retry-note-text"],[1,"llm-retry-status-line"],[1,"phase-header",3,"first-phase"],[1,"phase-body"],[1,"phase-header"],[1,"phase-token-usage",3,"title"],[1,"token-dot"],[1,"token-text"],[1,"block-item",3,"ngClass"],[1,"check-lane",3,"ngClass"],[1,"check-result",3,"ngClass"],[1,"check-header"],[1,"check-title"],[1,"check-subject",3,"title"],[1,"check-status"],[1,"check-items"],[1,"check-item"],[1,"check-index"],[1,"check-text"],[1,"check-method"],[1,"thinking-stream-details","native-thinking-details",3,"is-running","collapsed"],[1,"step-raw-thinking-message",3,"is-running"],[1,"step-android-action-card","task-report-card",3,"is-completed","is-failed","is-expanded"],[1,"step-android-action-card",3,"is-running","is-failed","is-expanded"],[1,"thinking-stream-details","native-thinking-details"],[1,"details-summary",3,"click"],[1,"details-content-wrapper"],[1,"details-content","stream-box"],[1,"stream-text",3,"innerHTML"],[1,"step-raw-thinking-message"],[1,"report-header"],[1,"report-content","stream-box"],[1,"step-android-action-card","task-report-card"],[1,"action-card-header",3,"click"],[1,"material-symbols-outlined","action-icon","report-icon"],[1,"action-title"],[1,"action-status-badge"],[1,"material-symbols-outlined","status-icon"],[1,"action-expand-icon","material-symbols-outlined"],[1,"action-card-body"],[1,"action-card-expanded-details"],[1,"action-detail-row"],[1,"detail-label"],[1,"detail-value"],[1,"action-card-expanded-details",3,"click"],[1,"expanded-grid"],[1,"grid-item","full-width"],[1,"expanded-screenshots-container"],[1,"grid-label"],[1,"grid-value","report-markdown-body",3,"innerHTML"],[1,"screenshot-column"],[1,"screenshot-label"],[1,"image-wrapper",3,"click"],[1,"img-relative-box"],["alt","Final Screen Screenshot",3,"src"],["alt","Post Screenshot",3,"src"],[1,"step-android-action-card"],[1,"material-symbols-outlined","action-icon"],[1,"action-status-badge","is-failed"],[1,"detail-value","coordinate-badge"],[1,"grid-item"],[1,"expanded-error-banner"],[1,"grid-value"],[1,"grid-value","code-pill"],["alt","Pre-Action Screenshot",3,"load","src"],[1,"overlay-layer"],["alt","Post-Action Screenshot",3,"src"],[1,"material-symbols-outlined","icon"],[1,"error-text"],[1,"llm-failure-stack"],[1,"step-generic-tool",3,"is-running","is-note-tool","is-video-tool","is-video-attention"],[1,"step-android-action-card","tool-action-card",3,"is-running","has-no-details","is-failed","is-expanded"],[1,"llm-retry-guidance"],[1,"step-android-action-card","tool-action-card","is-failed",3,"click"],[1,"action-card-header","llm-failure-header"],[1,"material-symbols-outlined","action-icon","is-failed"],[1,"action-status-badge","is-paused"],[1,"failure-retry-details"],[1,"llm-resume-row"],[1,"failure-retry-title"],[1,"failure-retry-row"],["type","button","title","Continue the paused task","aria-label","Continue the paused task",1,"btn-continue-task",3,"click"],[1,"material-symbols-outlined","continue-icon"],[1,"material-symbols-outlined","continue-arrow"],[1,"llm-resume-hint"],[1,"step-generic-tool"],[1,"tool-call-label"],[1,"tool-call-text"],["title","Click to view note content",1,"tool-key-pill"],["title","Click to view note content",1,"tool-key-pill",3,"click"],[1,"tool-key-pill",3,"click","title"],[1,"video-status-detail"],[1,"step-android-action-card","tool-action-card"],[1,"action-agent-badge",3,"is-outputter"],[1,"action-agent-badge"],[1,"detail-value","command-value"],[1,"grid-value","command-value"],[1,"check-verdict",3,"ngClass"],[1,"check-note"],[1,"material-symbols-outlined","verdict-icon"],[1,"verdict-body"],[1,"verdict-evidence"],[1,"verdict-suggestion"],[1,"synthesis-card-header"],[1,"header-left"],[1,"material-symbols-outlined","icon-sparkle"],[1,"main-title"],[1,"header-right"],["type","button",1,"btn-open-note",3,"click"],[1,"synthesis-card-preview"],[1,"parsed-note-container"],[1,"parsed-note-title"],[1,"parsed-milestones"],[1,"parsed-other-lines"],[1,"milestone-item",3,"class"],[1,"milestone-item"],[1,"other-line",3,"class"],[1,"other-line"],[1,"verify-badge",3,"assert"],[1,"finding-badge"],[1,"verify-badge"],[1,"planning-loader"],[1,"loader-text"],[1,"image-modal-backdrop",3,"click"],[1,"image-modal-content",3,"click"],["aria-label","Close image preview",1,"image-modal-close",3,"click"],["alt","Zoomed Screenshot",3,"load","src"]],template:function(e,o){e&1&&(l(0,"div",6)(1,"header",7)(2,"div",8)(3,"button",9),k("click",function(r){return o.toggleTaskDropdown(r)}),l(4,"span",10),u(5,"list_alt"),d(),l(6,"span",11),u(7,"Task Queue"),d()(),l(8,"button",12),k("click",function(r){return o.toggleNotesDropdown(r)}),l(9,"span",10),u(10,"description"),d(),l(11,"span",11),u(12,"Notes & Plans"),d()()(),M(13,aA,23,4,"div",13),M(14,$A,9,3,"div",14),d(),M(15,nN,17,28,"div",15),l(16,"main",16),M(17,oN,5,0,"div",17),M(18,iN,8,0,"div",18),M(19,d3,6,3,"div",19),d(),M(20,u3,10,1,"div",20),d()),e&2&&(g(3),w("active",o.isTaskDropdownOpen()),g(5),w("active",o.isNotesDropdownOpen()),g(5),b(o.isTaskDropdownOpen()?13:-1),g(),b(o.isNotesDropdownOpen()?14:-1),g(),b(o.consolidatedBlocks().length>0||o.showPlanningLoader()?15:-1),g(2),b(o.agentService.isSessionContentLoading()?17:-1),g(),b(!o.agentService.isSessionContentLoading()&&o.consolidatedBlocks().length===0&&!o.showPlanningLoader()&&o.startupWorkItems().length===0?18:-1),g(),b(!o.agentService.isSessionContentLoading()&&(o.phases().length>0||o.showPlanningLoader()||o.startupWorkItems().length>0)?19:-1),g(),b(o.selectedZoomImage()?20:-1))},dependencies:[No,ki,Qt,Ya,Ei],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.agent-stream-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;height:100%;background:#f8f9fa;box-sizing:border-box;position:relative}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%]{position:relative;height:60px;background:#fff;border-bottom:1px solid rgba(0,0,0,.08);display:flex;align-items:center;justify-content:flex-end;padding:0 16px;box-sizing:border-box;-webkit-user-select:none;user-select:none;box-shadow:none;z-index:10}@media(min-width:1151px){.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%]{display:none!important}}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-container[_ngcontent-%COMP%]{display:flex;height:36px;box-sizing:border-box;background:#f1f5f9b8;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(226,232,240,.85);border-radius:18px;padding:3px;gap:3px;align-items:center;flex-shrink:0;box-shadow:0 2px 8px -1px #0f172a0a,inset 0 1px 1px #fffc}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:30px;padding:0 14px;box-sizing:border-box;border:none;background:transparent;border-radius:15px;font-size:13px;font-weight:600;color:#64748b;font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;text-decoration:none;cursor:pointer;position:relative;line-height:1;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none;white-space:nowrap}@media(max-width:1150px){.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn[_ngcontent-%COMP%]{padding:0 9px;gap:0}}@media(max-width:1150px){.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn[_ngcontent-%COMP%] .tab-label[_ngcontent-%COMP%]{display:none!important}}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn[_ngcontent-%COMP%] .tab-icon[_ngcontent-%COMP%]{font-size:16px;color:inherit;transition:color .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn[_ngcontent-%COMP%] .badge-count[_ngcontent-%COMP%]{background:#2563eb;color:#fff;font-size:10px;font-weight:700;padding:1px 6px;border-radius:10px;line-height:1}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn[_ngcontent-%COMP%] .dropdown-chevron[_ngcontent-%COMP%]{font-size:16px;color:#94a3b8;margin-left:2px;transition:transform .2s ease,color .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn[_ngcontent-%COMP%] .dropdown-chevron.open[_ngcontent-%COMP%]{transform:rotate(180deg);color:#1e293b}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn[_ngcontent-%COMP%]:hover:not(.active){color:#0f172a;background:#fff9}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn.active[_ngcontent-%COMP%]{background:#fff;color:#2563eb;box-shadow:0 2px 8px #0000000f,0 1px 2px #00000005}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn.active[_ngcontent-%COMP%] .tab-icon[_ngcontent-%COMP%]{color:#2563eb}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn.video-replay-tab-btn[_ngcontent-%COMP%] .video-indicator-dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%;background:#10b981;box-shadow:0 0 6px #10b981;margin-left:-2px;flex-shrink:0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-tab-btn.video-replay-tab-btn.has-video[_ngcontent-%COMP%] .tab-icon[_ngcontent-%COMP%]{color:#0284c7}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .header-right-actions[_ngcontent-%COMP%]{margin-left:auto;display:flex;align-items:center}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .header-right-actions[_ngcontent-%COMP%] .btn-resume-task[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .header-right-actions[_ngcontent-%COMP%] .btn-stop-task[_ngcontent-%COMP%]{padding:5px 10px;background:#2563eb;border:1px solid #2563eb;border-radius:16px;font-size:13px;font-weight:600;color:#fff;cursor:pointer;display:flex;align-items:center;gap:4px;transition:all .2s;box-shadow:0 2px 4px #2563eb33}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .header-right-actions[_ngcontent-%COMP%] .btn-resume-task[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .header-right-actions[_ngcontent-%COMP%] .btn-stop-task[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px;color:inherit}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .header-right-actions[_ngcontent-%COMP%] .btn-resume-task[_ngcontent-%COMP%]:hover, .agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .header-right-actions[_ngcontent-%COMP%] .btn-stop-task[_ngcontent-%COMP%]:hover{background:#1d4ed8;border-color:#1d4ed8;box-shadow:0 4px 8px #2563eb4d}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .header-right-actions[_ngcontent-%COMP%] .btn-stop-task[_ngcontent-%COMP%]{background:#ef4444;border-color:#ef4444;box-shadow:0 2px 4px #ef444433}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .header-right-actions[_ngcontent-%COMP%] .btn-stop-task[_ngcontent-%COMP%]:hover{background:#dc2626;border-color:#dc2626;box-shadow:0 4px 8px #ef44444d}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%]{position:absolute;top:48px;right:12px;left:auto;width:360px;max-width:calc(100vw - 24px);max-height:480px;background:#fff;border:1px solid #cbd5e1;border-radius:12px;box-shadow:0 12px 32px #00000024,0 4px 12px #0000000d;z-index:100;overflow-y:auto;padding:14px;display:flex;flex-direction:column;gap:10px;animation:_ngcontent-%COMP%_dropdownFadeIn .15s cubic-bezier(.16,1,.3,1)}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .popover-title-header[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding-bottom:8px;border-bottom:1px solid #e2e8f0;font-size:14px;font-weight:700;color:#0f172a}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .popover-title-header[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:18px;color:#2563eb}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%]{right:12px;left:auto;width:380px;max-height:520px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:6px;margin-bottom:4px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%]{display:flex;flex-wrap:wrap;gap:6px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%] .note-selector-pill[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border:1px solid #e2e8f0;background:#fff;border-radius:16px;font-size:11.5px;font-weight:500;color:#475569;cursor:pointer;transition:all .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%] .note-selector-pill[_ngcontent-%COMP%] .pill-icon[_ngcontent-%COMP%]{font-size:14px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%] .note-selector-pill[_ngcontent-%COMP%]:hover{background:#f8fafc;border-color:#cbd5e1;color:#1e293b}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%] .note-selector-pill.active[_ngcontent-%COMP%]{background:#eff6ff;border-color:#bfdbfe;color:#1d4ed8;font-weight:600}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px;padding:4px 2px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .note-title[_ngcontent-%COMP%]{font-size:13.5px;font-weight:700;color:#1f1f1f;margin:0 0 4px;font-family:Google Sans,Google Sans Text,Inter,sans-serif}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .code-segment[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;background-color:#f1f3f4;color:#1967d2;padding:1px 5px;border-radius:4px;font-size:12px;margin:0 2px;word-break:break-all}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestones-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%]{display:flex;flex-direction:column}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block.checked[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon.checked[_ngcontent-%COMP%]{opacity:.7}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block.checked[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-text[_ngcontent-%COMP%]{color:#a1a1aa}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:8px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon[_ngcontent-%COMP%]{font-size:18px;-webkit-user-select:none;user-select:none;margin-top:2px;font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon.checked[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon.progress[_ngcontent-%COMP%]{color:#1a73e8}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon.unchecked[_ngcontent-%COMP%]{color:#cbd5e1}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-text[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,sans-serif;color:#1f1f1f;font-size:13px;line-height:1.5;word-break:break-word;flex:1}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%]{margin-top:4px;display:flex;flex-direction:column;gap:5px;padding-left:26px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:8px;font-family:Google Sans,Google Sans Text,Inter,sans-serif;color:#1f1f1f;font-size:12.5px;line-height:1.5}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.checked[_ngcontent-%COMP%]{color:#a1a1aa}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.checked[_ngcontent-%COMP%] .check-icon.checked[_ngcontent-%COMP%]{opacity:.7}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.verify[_ngcontent-%COMP%]{color:#334155;gap:8px;align-items:flex-start}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.verify[_ngcontent-%COMP%] .verify-badge[_ngcontent-%COMP%]{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-family:Google Sans Text,Inter,-apple-system,sans-serif;font-size:10.5px;font-weight:550;line-height:1.2;letter-spacing:.2px;text-transform:lowercase;color:#475569;background:#f1f5f9;border:1px solid #e2e8f0;border-radius:4px;padding:1.5px 6px;margin-top:1.5px;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.verify[_ngcontent-%COMP%] .verify-badge.assert[_ngcontent-%COMP%]{color:#0369a1;background:#f0f9ff;border-color:#e0f2fe}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.verify[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%]{color:#334155;font-size:12.5px;line-height:1.5}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.finding[_ngcontent-%COMP%]{color:#92400e;gap:8px;align-items:flex-start}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.finding[_ngcontent-%COMP%] .finding-badge[_ngcontent-%COMP%]{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-family:Google Sans Text,Inter,-apple-system,sans-serif;font-size:10.5px;font-weight:550;line-height:1.2;letter-spacing:.2px;text-transform:lowercase;color:#b45309;background:#fef3c7;border:1px solid #fde68a;border-radius:4px;padding:1.5px 6px;margin-top:1.5px;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.finding[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%]{color:#92400e;font-size:12.5px;line-height:1.5}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%]{font-size:16px;-webkit-user-select:none;user-select:none;margin-top:2px;font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .check-icon.checked[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .check-icon.progress[_ngcontent-%COMP%]{color:#1a73e8}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .check-icon.unchecked[_ngcontent-%COMP%]{color:#cbd5e1}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .bullet[_ngcontent-%COMP%]{color:#9ca3af;font-weight:700;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%]{word-break:break-word;color:inherit}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-checks-container[_ngcontent-%COMP%]{margin-top:6px;padding-left:26px;display:flex;flex-direction:column;gap:6px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%]{background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;padding:7px 10px;display:flex;flex-direction:column;gap:3px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card.standalone[_ngcontent-%COMP%]{margin-top:6px;margin-bottom:6px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%]{display:flex;align-items:center}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .card-tag[_ngcontent-%COMP%]{font-family:Google Sans Text,Inter,-apple-system,sans-serif;font-size:9.5px;font-weight:600;line-height:1;letter-spacing:.6px;text-transform:uppercase;color:#64748b}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .card-tag.assert[_ngcontent-%COMP%]{color:#0284c7}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%]{font-family:inherit;font-size:12px;line-height:1.5;color:#334155;word-break:break-word}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%] .bold-segment[_ngcontent-%COMP%]{font-weight:600;color:#1e293b}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%] .code-segment[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:11px;background:#f1f5f9;color:#0f172a;padding:1px 5px;border-radius:4px;border:1px solid #e2e8f0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card.finding[_ngcontent-%COMP%]{background:#fffbeb;border-color:#fef3c7}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card.finding[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .card-tag[_ngcontent-%COMP%]{color:#b45309}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .verification-card.finding[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%]{color:#92400e}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:6px;margin-top:6px;padding-top:6px;border-top:1px dashed #e2e8f0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:6px;font-size:12.5px;color:#334155;line-height:1.5}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu.notes-dropdown[_ngcontent-%COMP%] .dropdown-notes-content[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%]{word-break:break-word;color:inherit}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%]::-webkit-scrollbar{width:6px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%]::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:4px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding-bottom:8px;border-bottom:1px solid #e2e8f0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-header[_ngcontent-%COMP%] .dropdown-title[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:700;color:#0f172a}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-header[_ngcontent-%COMP%] .dropdown-title[_ngcontent-%COMP%] .icon-main[_ngcontent-%COMP%]{font-size:18px;color:#2563eb}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-section-label[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:700;color:#475569;text-transform:uppercase;letter-spacing:.5px;padding:4px 2px 2px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-section-label.history-label[_ngcontent-%COMP%]{margin-top:6px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-section-label[_ngcontent-%COMP%] .icon-bolt[_ngcontent-%COMP%]{font-size:15px;color:#d97706}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-section-label[_ngcontent-%COMP%] .icon-history[_ngcontent-%COMP%]{font-size:15px;color:#64748b}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-empty-state[_ngcontent-%COMP%]{padding:20px 14px;text-align:center;font-size:12px;color:#94a3b8;background:#f8fafc;border:1px dashed #e2e8f0;border-radius:6px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%]{font-size:22px;color:#94a3b8}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-history-list[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%]{padding:10px 12px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;cursor:pointer;transition:all .15s ease;display:flex;flex-direction:column;gap:6px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%]:hover{background:#f1f5f9;border-color:#cbd5e1;transform:translateY(-1px)}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%]:hover .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%]:has(.btn-delete-card) .item-time[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%]:hover .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%]:has(.btn-delete-card) .item-time-divider[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%]:hover .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%]:has(.btn-stop-card) .item-time[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%]:hover .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%]:has(.btn-stop-card) .item-time-divider[_ngcontent-%COMP%]{opacity:0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%]:hover .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .btn-delete-card[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%]:hover .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .btn-stop-card[_ngcontent-%COMP%]{opacity:1;pointer-events:auto}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card.selected[_ngcontent-%COMP%]{background:#eff6ff;border-color:#93c5fd;box-shadow:0 0 0 1px #2563eb}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card.selected[_ngcontent-%COMP%] .item-goal[_ngcontent-%COMP%]{color:#1e3a8a;font-weight:600}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card.running[_ngcontent-%COMP%]{border-left:3.5px solid #2563eb}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:8px;min-width:0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge[_ngcontent-%COMP%]{flex-shrink:0;display:inline-flex;align-items:center;font-size:10.5px;font-weight:700;padding:2px 5px;border-radius:4px;letter-spacing:.05em;border:1px solid #e2e8f0;background:#fafafa;color:#64748b}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge[_ngcontent-%COMP%]:before{content:"";width:4px;height:4px;border-radius:50%;display:inline-block;margin-right:4px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.running[_ngcontent-%COMP%]{background:#fafafa;color:#1f1f1f;border-color:#1f1f1f}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.running[_ngcontent-%COMP%]:before{background-color:#1f1f1f;animation:_ngcontent-%COMP%_pulse-black-dot-small 1.5s infinite ease-in-out}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.paused[_ngcontent-%COMP%]{background:#fff7ed;color:#c2410c;border-color:#fdba74}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.paused[_ngcontent-%COMP%]:before{background-color:#f97316}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.completed[_ngcontent-%COMP%]{background:#fafafa;color:#1f1f1f;border-color:#e2e8f0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.completed[_ngcontent-%COMP%]:before{background-color:#1f1f1f}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.pending[_ngcontent-%COMP%]{background:#fafafa;color:#64748b;border-color:#e2e8f0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.pending[_ngcontent-%COMP%]:before{background-color:#94a3b8}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.failed[_ngcontent-%COMP%]{background:#fafafa;color:#ef4444;border-color:#fee2e2}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.failed[_ngcontent-%COMP%]:before{background-color:#ef4444}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.cancelled[_ngcontent-%COMP%]{background:#fafafa;color:#d97706;border-color:#fef3c7}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge.cancelled[_ngcontent-%COMP%]:before{background-color:#f59e0b}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .task-badge[_ngcontent-%COMP%] .status-dot[_ngcontent-%COMP%]{display:none}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%]{display:flex;align-items:center;gap:4px;position:relative;min-width:0;flex-shrink:1;justify-content:flex-end}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .item-device[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:2.5px;min-width:0;flex-shrink:1;font-size:10.5px;color:#64748b;line-height:1;cursor:default;transition:color .15s ease,opacity .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .item-device[_ngcontent-%COMP%] .device-icon[_ngcontent-%COMP%]{font-size:12px;width:12px;height:12px;line-height:12px;color:#64748b;opacity:.75;flex-shrink:0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .item-device[_ngcontent-%COMP%] .device-name[_ngcontent-%COMP%]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:inherit;letter-spacing:-.15px}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .item-device[_ngcontent-%COMP%]:hover{color:#334155}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .item-device[_ngcontent-%COMP%]:hover .device-icon[_ngcontent-%COMP%]{color:#334155;opacity:1}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .item-time-divider[_ngcontent-%COMP%]{font-size:10px;color:#94a3b8;line-height:1;-webkit-user-select:none;user-select:none;flex-shrink:0;transition:opacity .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .item-time[_ngcontent-%COMP%]{font-size:11px;color:#64748b;white-space:nowrap;flex-shrink:0;line-height:1;transition:opacity .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .btn-delete-card[_ngcontent-%COMP%]{position:absolute;right:0;top:50%;transform:translateY(-50%);width:18px;height:18px;padding:0;border:none;background:transparent;border-radius:3px;color:#94a3b8;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:all .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .btn-delete-card[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:13px;line-height:1}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .btn-delete-card[_ngcontent-%COMP%]:hover{color:#ef4444;background:#fee2e2}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .btn-stop-card[_ngcontent-%COMP%]{position:absolute;right:0;top:50%;transform:translateY(-50%);width:18px;height:18px;padding:0;border:none;background:transparent;border-radius:3px;color:#ef4444;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:all .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .btn-stop-card[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:14px;line-height:1}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-header[_ngcontent-%COMP%] .item-header-actions[_ngcontent-%COMP%] .btn-stop-card[_ngcontent-%COMP%]:hover{color:#dc2626;background:#fee2e2;transform:translateY(-50%) scale(1.1)}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-goal[_ngcontent-%COMP%]{font-size:12.5px;color:#334155;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-footer[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:10.5px;color:#94a3b8}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-footer[_ngcontent-%COMP%] .item-id[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:10.5px;color:#94a3b8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex:1;transition:color .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-footer[_ngcontent-%COMP%] .item-id[_ngcontent-%COMP%]:hover{color:#475569}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-item-card[_ngcontent-%COMP%] .item-footer[_ngcontent-%COMP%] .item-date[_ngcontent-%COMP%]{flex-shrink:0}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-note-item[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:6px;cursor:pointer;font-size:13px;color:#334155;transition:background .15s ease}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-note-item[_ngcontent-%COMP%] .note-icon[_ngcontent-%COMP%]{font-size:18px;color:#64748b}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-note-item[_ngcontent-%COMP%] .note-key-text[_ngcontent-%COMP%]{flex:1;font-weight:500}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-note-item[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%]{font-size:18px;color:#2563eb}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-note-item[_ngcontent-%COMP%]:hover{background:#f1f5f9;color:#0f172a}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-note-item.selected[_ngcontent-%COMP%]{background:#eff6ff;color:#2563eb;font-weight:600}.agent-stream-container[_ngcontent-%COMP%] .vscode-nav-header[_ngcontent-%COMP%] .vscode-dropdown-menu[_ngcontent-%COMP%] .dropdown-note-item.selected[_ngcontent-%COMP%] .note-icon[_ngcontent-%COMP%]{color:#2563eb}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%]{position:absolute;top:12px;right:20px;height:36px;display:inline-flex;align-items:center;gap:8px;z-index:40;pointer-events:auto}@media(max-width:1150px){.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%]{top:72px}}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .model-info-chip[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;height:30px;padding:0 11px;box-sizing:border-box;background:#ffffffb8;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(226,232,240,.85);border-radius:15px;cursor:default;-webkit-user-select:none;user-select:none;box-shadow:0 2px 6px -1px #0f172a0d,inset 0 1px 1px #ffffffe6;font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;transition:all .2s cubic-bezier(.4,0,.2,1)}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .model-info-chip[_ngcontent-%COMP%] .model-icon[_ngcontent-%COMP%]{font-size:15px;width:15px;height:15px;display:inline-flex;align-items:center;justify-content:center;color:#64748b}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .model-info-chip[_ngcontent-%COMP%] .model-label[_ngcontent-%COMP%]{font-size:12px;font-weight:500;color:#64748b;line-height:1}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .model-info-chip[_ngcontent-%COMP%] .model-name[_ngcontent-%COMP%]{font-size:12px;font-weight:700;color:#1e293b;letter-spacing:.1px;line-height:1}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;height:30px;padding:0 12px;box-sizing:border-box;background:#ffffffb8;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(226,232,240,.85);border-radius:15px;box-shadow:0 2px 6px -1px #0f172a0d,inset 0 1px 1px #ffffffe6;cursor:pointer;transition:all .2s cubic-bezier(.16,1,.3,1);-webkit-user-select:none;user-select:none;outline:none;font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording[_ngcontent-%COMP%] .video-icon[_ngcontent-%COMP%]{font-size:15px;width:15px;height:15px;display:inline-flex;align-items:center;justify-content:center;color:#64748b;transition:transform .2s ease,color .2s ease}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%]{font-size:12px;font-weight:600;color:#475569;letter-spacing:.1px;line-height:1;transition:color .15s ease}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording[_ngcontent-%COMP%] .video-pulse-dot[_ngcontent-%COMP%]{width:6px;height:6px;border-radius:50%;background:#ef4444;box-shadow:0 0 6px #ef4444;animation:pulseRed 1.5s infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.recording[_ngcontent-%COMP%]{background:#fef2f2e6;border-color:#f8717199;box-shadow:0 2px 6px -1px #dc262626,inset 0 1px 1px #ffffffe6}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.recording[_ngcontent-%COMP%] .video-icon[_ngcontent-%COMP%]{color:#dc2626}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.recording[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%]{color:#b91c1c}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.processing[_ngcontent-%COMP%] .video-icon[_ngcontent-%COMP%]{color:#2563eb;animation:_ngcontent-%COMP%_spin 1s linear infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording[_ngcontent-%COMP%]:hover:not(.active){background:#ffffffe0;border-color:#cbd5e1f2;box-shadow:0 4px 12px -2px #0f172a14,inset 0 1px 1px #fff;color:#0f172a}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording[_ngcontent-%COMP%]:hover:not(.active) .video-icon[_ngcontent-%COMP%]{color:#1a73e8;transform:scale(1.08)}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording[_ngcontent-%COMP%]:hover:not(.active) .btn-text[_ngcontent-%COMP%]{color:#0f172a}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording[_ngcontent-%COMP%]:active{transform:translateY(0);box-shadow:0 1px 3px #0f172a14}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.has-steps[_ngcontent-%COMP%]{background:#f0fdfae6;border-color:#5eead4b3;box-shadow:0 2px 6px -1px #0d94881f,inset 0 1px 1px #ffffffe6}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.has-steps[_ngcontent-%COMP%] .steps-icon[_ngcontent-%COMP%]{color:#0d9488}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.has-steps[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%]{color:#0f766e}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.has-steps[_ngcontent-%COMP%]:hover:not(.active){background:#ccfbf1f2;border-color:#2dd4bfd9}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.has-steps[_ngcontent-%COMP%]:hover:not(.active) .steps-icon[_ngcontent-%COMP%]{color:#0f766e}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.failed[_ngcontent-%COMP%]{background:#fef2f2cc;border-color:#fecacae6}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.failed[_ngcontent-%COMP%] .error-icon[_ngcontent-%COMP%]{color:#ef4444}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.failed[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%]{color:#dc2626}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording[_ngcontent-%COMP%] .steps-count-badge[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;padding:1px 5px;border-radius:10px;background:#0d9488;color:#fff;font-size:10px;font-weight:700;line-height:1;margin-left:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.active[_ngcontent-%COMP%]{background:#1a73e8f2;border-color:#1a73e8f2;box-shadow:0 2px 8px #1a73e859}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.active[_ngcontent-%COMP%] .video-icon[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.active[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%]{color:#fff}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.active[_ngcontent-%COMP%] .video-pulse-dot[_ngcontent-%COMP%]{background:#fff;box-shadow:0 0 6px #ffffffe6}.agent-stream-container[_ngcontent-%COMP%] .stream-floating-toolbar[_ngcontent-%COMP%] .btn-screen-recording.active[_ngcontent-%COMP%] .steps-count-badge[_ngcontent-%COMP%]{background:#fff;color:#1a73e8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]{flex:1;overflow-y:auto;padding:72px 24px 100px;position:relative}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .session-loading-state[_ngcontent-%COMP%]{min-height:180px;display:flex;align-items:center;justify-content:center;gap:9px;color:#64748b;font-size:13px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .session-loading-state[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:18px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]{display:flex;flex-direction:column}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .floating-model-badge[_ngcontent-%COMP%]{position:sticky;top:0;float:right;margin-top:-2px;margin-right:4px;display:inline-flex;align-items:center;gap:4px;padding:3px 9px;background:#ffffffeb;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid rgba(99,102,241,.2);border-radius:12px;box-shadow:0 1px 4px #6366f114,0 1px 2px #0000000a;z-index:35;cursor:default;transition:all .2s ease;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .floating-model-badge[_ngcontent-%COMP%]:hover{background:#fff;border-color:#6366f166;box-shadow:0 2px 8px #6366f126;transform:translateY(-1px)}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .floating-model-badge[_ngcontent-%COMP%]:hover .model-icon[_ngcontent-%COMP%]{color:#4f46e5;transform:rotate(15deg) scale(1.05)}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .floating-model-badge[_ngcontent-%COMP%] .model-icon[_ngcontent-%COMP%]{font-size:13px;color:#6366f1;transition:all .3s ease}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .floating-model-badge[_ngcontent-%COMP%] .model-name[_ngcontent-%COMP%]{font-size:11px;font-weight:600;color:#334155;letter-spacing:normal;font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]::-webkit-scrollbar{width:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]::-webkit-scrollbar-track{background:transparent}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb{background:#00000026;border-radius:10px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover{background:#00000040}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%]{flex:1 1 auto;min-height:100%;width:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;box-sizing:border-box;padding:30px;margin:auto 0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%]{margin-bottom:12px;opacity:.8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:40px;color:#94a3b8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{margin:0 0 6px;font-size:12px;font-weight:600;color:#1f1f1f}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{margin:0;font-size:12px;color:#1f1f1f;max-width:320px;line-height:1.5}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list-container[_ngcontent-%COMP%]{display:flex;flex-direction:column}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list-container[_ngcontent-%COMP%] .planning-loader-container[_ngcontent-%COMP%]{display:flex;align-items:center;margin-top:10px;margin-bottom:10px;padding-left:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list-container[_ngcontent-%COMP%] .planning-loader-container[_ngcontent-%COMP%] .planning-loader[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:8px;color:#475569;font-size:13px;font-weight:500;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list-container[_ngcontent-%COMP%] .planning-loader-container[_ngcontent-%COMP%] .planning-loader[_ngcontent-%COMP%] .spin-animation[_ngcontent-%COMP%]{font-size:16px;width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;animation:_ngcontent-%COMP%_spin-loader 1s linear infinite;color:#2563eb;flex-shrink:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list-container[_ngcontent-%COMP%] .planning-loader-container[_ngcontent-%COMP%] .planning-loader[_ngcontent-%COMP%] .loader-text[_ngcontent-%COMP%]{color:#475569;font-size:13px;font-weight:500;line-height:1.4}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-container[_ngcontent-%COMP%]{display:flex;flex-direction:column}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-header[_ngcontent-%COMP%]{font-size:12px;font-weight:400;line-height:1.5;min-height:20px;box-sizing:border-box;color:#71717a;margin-top:16px;margin-bottom:8px;-webkit-user-select:none;user-select:none;display:flex;align-items:center;gap:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-header.first-phase[_ngcontent-%COMP%]{margin-top:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-header[_ngcontent-%COMP%] .phase-worked-time[_ngcontent-%COMP%]{color:#71717a;font-weight:400}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-header[_ngcontent-%COMP%] .phase-token-usage[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;color:#8e8e93;cursor:default}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-header[_ngcontent-%COMP%] .phase-token-usage[_ngcontent-%COMP%] .token-dot[_ngcontent-%COMP%]{color:#a1a1aa;font-weight:700}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-header[_ngcontent-%COMP%] .phase-token-usage[_ngcontent-%COMP%] .token-text[_ngcontent-%COMP%]{color:#71717a;font-variant-numeric:tabular-nums}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px;padding-left:12px;border-left:1px solid rgba(0,0,0,.04);margin-left:6px;position:relative;z-index:1}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%]{border-radius:8px;padding:0;overflow:visible;box-shadow:0 1px 3px #00000005;border:1px solid transparent;background:transparent;display:flex;flex-direction:column}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-content-wrapper[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-content-wrapper[_ngcontent-%COMP%]{display:grid;grid-template-rows:1fr;transition:grid-template-rows .3s cubic-bezier(.4,0,.2,1);overflow:hidden}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-content-wrapper[_ngcontent-%COMP%] .details-content[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-content-wrapper[_ngcontent-%COMP%] .details-content[_ngcontent-%COMP%]{min-height:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%]{border-color:transparent;background:transparent;box-shadow:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%]:not(.collapsed), .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%]:not(.collapsed){background:transparent}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{color:#71717a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:after, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:after{color:#d4d4d8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:hover, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:hover{color:#1f1f1f}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details.is-running[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details.is-running[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{background:linear-gradient(90deg,#71717a,#2563eb,#7c3aed,#0284c7,#71717a);background-size:200% 100%;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;animation:_ngcontent-%COMP%_subtle-color-flow 2.8s linear infinite;font-weight:500}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details.is-running[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details.is-running[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{background:#3b82f6;box-shadow:0 0 #3b82f673;animation:_ngcontent-%COMP%_pulse-stream-dot 1.8s cubic-bezier(.4,0,.6,1) infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{background:#d4d4d8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%]{background:#3b82f6;box-shadow:0 0 #3b82f673;animation:_ngcontent-%COMP%_pulse-stream-dot 1.8s cubic-bezier(.4,0,.6,1) infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.native-thinking-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%]{color:#1f1f1f}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%]{border-color:#dbeafe;background:#f8fafc}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%]:not(.collapsed), .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%]:not(.collapsed){background:#f8fafc}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{color:#1e40af}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:after, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:after{color:#93c5fd}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:hover, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:hover{color:#1e3a8a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{background:#93c5fd}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.raw-thinking-details[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%]{background:#2563eb;animation:_ngcontent-%COMP%_pulse-stream-blue 1.5s infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%]:not(.collapsed), .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%]:not(.collapsed){box-shadow:0 1px 3px #00000005}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%]:not(.collapsed) .details-summary[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%]:not(.collapsed) .details-summary[_ngcontent-%COMP%]{margin-bottom:8px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%]:not(.collapsed) .details-summary[_ngcontent-%COMP%]:after, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%]:not(.collapsed) .details-summary[_ngcontent-%COMP%]:after{transform:rotate(90deg)}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{padding:0;margin-bottom:0;font-family:Google Sans,Google Sans Text,Inter,Arial,sans-serif;font-weight:400;font-size:12px;line-height:1.5;min-height:20px;box-sizing:border-box;letter-spacing:.5px;cursor:pointer;-webkit-user-select:none;user-select:none;display:flex;align-items:center;gap:8px;outline:none;list-style:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]::-webkit-details-marker, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]::-webkit-details-marker{display:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:after, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:after{content:"\\276f";display:inline-block;font-size:9px;margin-left:6px;transition:transform .2s cubic-bezier(.4,0,.2,1),color .2s ease}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:hover .stream-status-dot[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:hover .stream-status-dot[_ngcontent-%COMP%]{transform:scale(1.25);background:#71717a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:hover:after, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:hover:after{transform:translate(3px);color:#71717a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;display:inline-block;transition:transform .2s cubic-bezier(.4,0,.2,1),background-color .2s ease}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]{max-height:250px;overflow-y:auto;background:transparent;padding:4px 0;box-sizing:border-box}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar{width:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-track, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-track{background:transparent}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-thumb, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-thumb{background:#00000014;border-radius:999px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover{background:#00000029}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%]{font-family:inherit;font-size:12.5px;line-height:1.65;color:#1f1f1f;white-space:normal;word-break:break-word}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{font-weight:600;color:#111827}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] div[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] p[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] div[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.65;color:#1f1f1f;margin:4px 0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h1[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h4[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h5[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h6[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h1[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h4[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h5[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h6[_ngcontent-%COMP%]{font-size:12.5px;font-weight:600;color:#1f1f1f;margin-top:8px;margin-bottom:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .inline-code[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .inline-code[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:11px;background:#f4f4f5;color:#b91c1c;padding:2px 6px;border-radius:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%]{margin:4px 0;padding-left:16px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.65;color:#1f1f1f;margin:4px 0;padding-left:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .md-para-gap[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .md-para-gap[_ngcontent-%COMP%]{height:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.collapsed[_ngcontent-%COMP%] .details-content-wrapper[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.collapsed[_ngcontent-%COMP%] .details-content-wrapper[_ngcontent-%COMP%]{grid-template-rows:0fr;display:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-details.collapsed[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-details.collapsed[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{margin-bottom:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%]{background:transparent;border:1px solid transparent;border-radius:8px;padding:0;margin-bottom:0;box-shadow:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,Arial,sans-serif;font-weight:400;font-size:12px;line-height:1.5;min-height:20px;box-sizing:border-box;letter-spacing:.5px;color:#71717a;margin-bottom:8px;-webkit-user-select:none;user-select:none;display:flex;align-items:center;gap:8px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;display:inline-block;background:#d4d4d8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%]{background:#71717a;animation:_ngcontent-%COMP%_pulse-stream-grey 1.5s infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.65;color:#1f1f1f}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]{max-height:250px;overflow-y:auto;background:transparent;padding:4px 0;box-sizing:border-box}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar{width:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-track, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-track{background:transparent}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-thumb, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-thumb{background:#00000014;border-radius:999px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover, .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-box[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover{background:#00000029}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%]{font-family:inherit;font-size:12.5px;line-height:1.65;color:#1f1f1f;white-space:normal;word-break:break-word}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{font-weight:600;color:#111827}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] div[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] p[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] div[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.65;color:#1f1f1f;margin:4px 0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h1[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h1[_ngcontent-%COMP%]{font-size:14px;font-weight:700;color:#0f172a;margin-top:12px;margin-bottom:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{font-size:13.5px;font-weight:700;color:#0f172a;margin-top:10px;margin-bottom:5px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#1e293b;margin-top:8px;margin-bottom:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h4[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h5[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h6[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h4[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h5[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] h6[_ngcontent-%COMP%]{font-size:12.5px;font-weight:600;color:#334155;margin-top:6px;margin-bottom:3px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] em[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] em[_ngcontent-%COMP%]{font-style:italic;color:inherit}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] blockquote[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] blockquote[_ngcontent-%COMP%]{margin:6px 0;padding:4px 10px;border-left:3px solid #cbd5e1;color:#475569;background:#f1f5f980;border-radius:0 4px 4px 0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .code-block[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .code-block[_ngcontent-%COMP%]{margin:6px 0;padding:8px 12px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;overflow-x:auto;font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:11.5px;line-height:1.5;color:#1e293b}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .md-hr[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .md-hr[_ngcontent-%COMP%]{border:none;border-top:1px solid #e2e8f0;margin:10px 0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .inline-code[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .inline-code[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:11px;background:#f4f4f5;color:#b91c1c;padding:2px 6px;border-radius:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%]{margin:4px 0;padding-left:16px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.65;color:#1f1f1f;margin:4px 0;padding-left:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li.md-verify-item[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li.md-verify-item[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li.md-verify-item[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li.md-verify-item[_ngcontent-%COMP%]{color:#334155}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li.md-finding-item[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li.md-finding-item[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li.md-finding-item[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li.md-finding-item[_ngcontent-%COMP%]{color:#92400e}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .md-para-gap[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .thinking-stream-flat-card[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%] .md-para-gap[_ngcontent-%COMP%]{height:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%]{background:#f5f3ff;border:1px solid #e9d5ff;border-radius:8px;padding:12px 16px;margin-bottom:8px;box-shadow:0 1px 3px #00000003}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,Arial,Liberation Sans,sans-serif;font-weight:700;font-size:12px;line-height:1.5;letter-spacing:.5px;color:#6b21a8;margin-bottom:8px;-webkit-user-select:none;user-select:none;display:flex;align-items:center;gap:8px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;display:inline-block;background:#c084fc}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%]{background:#a855f7;animation:_ngcontent-%COMP%_pulse-stream-purple 1.5s infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%]{font-size:12px;line-height:1.6;color:#27272a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] .stream-text[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:11.5px;white-space:pre-wrap;word-break:break-all;color:#5b21b6;background:#ffffff80;padding:8px;border-radius:6px;border:1px dashed rgba(168,85,247,.2)}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .checker-result-badge[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .checker-result-badge[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;font-weight:700;font-size:11.5px;padding:4px 10px;border-radius:6px;margin-bottom:10px;border:1px solid transparent}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .checker-result-badge.success[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .checker-result-badge.success[_ngcontent-%COMP%]{background:#ecfdf5;color:#065f46;border-color:#a7f3d0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .checker-result-badge.failed[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .checker-result-badge.failed[_ngcontent-%COMP%]{background:#fef2f2;color:#991b1b;border-color:#fca5a5}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .llm-stream-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .checker-reason[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .checker-stream-flat-card[_ngcontent-%COMP%] .checker-reason[_ngcontent-%COMP%]{font-size:12px;line-height:1.6;color:#3f3f46;font-weight:500}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%]{background:transparent;border:1px solid transparent;border-radius:8px;padding:0;margin-bottom:0;box-shadow:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message.is-running[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%]{background:linear-gradient(90deg,#71717a,#2563eb,#7c3aed,#0284c7,#71717a);background-size:200% 100%;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;animation:_ngcontent-%COMP%_subtle-color-flow 2.8s linear infinite;font-weight:500}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message.is-running[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{background:#3b82f6;box-shadow:0 0 #3b82f673;animation:_ngcontent-%COMP%_pulse-stream-dot 1.8s cubic-bezier(.4,0,.6,1) infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,Arial,sans-serif;font-weight:400;font-size:12px;line-height:1.5;min-height:20px;box-sizing:border-box;letter-spacing:.5px;color:#71717a;margin-bottom:8px;-webkit-user-select:none;user-select:none;display:flex;align-items:center;gap:8px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;display:inline-block;background:#d4d4d8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%]{background:#3b82f6;box-shadow:0 0 #3b82f673;animation:_ngcontent-%COMP%_pulse-stream-dot 1.8s cubic-bezier(.4,0,.6,1) infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.65;color:#1f1f1f}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{font-weight:600;color:#111827}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] div[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.65;color:#1f1f1f;margin:4px 0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] h1[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] h2[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] h4[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] h5[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] h6[_ngcontent-%COMP%]{font-size:12.5px;font-weight:600;color:#1f1f1f;margin-top:8px;margin-bottom:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] .inline-code[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:11px;background:#f4f4f5;color:#b91c1c;padding:2px 6px;border-radius:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] ol[_ngcontent-%COMP%]{margin:4px 0;padding-left:16px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.65;color:#1f1f1f;margin:4px 0;padding-left:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-raw-thinking-message[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] .md-para-gap[_ngcontent-%COMP%]{height:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%]{background:#f4fbf7;border:1px solid #d1fae5;border-radius:8px;padding:12px 16px;margin-bottom:8px;box-shadow:0 1px 3px #00000003}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%] .report-header[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,Arial,Liberation Sans,sans-serif;font-weight:700;font-size:12px;line-height:1.5;letter-spacing:.5px;color:#065f46;margin-bottom:8px;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%]{font-size:12px;line-height:1.6;color:#27272a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{font-weight:600;color:#09090b}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] .inline-code[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:11px;background:#e6f4ea;color:#137333;padding:2px 6px;border-radius:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] ol[_ngcontent-%COMP%]{margin:2px 0;padding-left:20px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{margin-bottom:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-action-summary-card[_ngcontent-%COMP%] .report-content[_ngcontent-%COMP%] .md-para-gap[_ngcontent-%COMP%]{height:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px;margin-top:0;margin-bottom:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-retry-notes[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px;padding:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-retry-notes[_ngcontent-%COMP%] .llm-retry-note[_ngcontent-%COMP%]{min-height:25px;box-sizing:border-box;display:flex;align-items:center;gap:8px;color:#71717a;font-family:Google Sans,Google Sans Text,Inter,Arial,sans-serif;font-size:12px;line-height:1.5;letter-spacing:.2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-retry-notes[_ngcontent-%COMP%] .llm-retry-note[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;background:#d4d4d8;flex:0 0 auto}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-retry-notes[_ngcontent-%COMP%] .llm-retry-note[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%]{background:#3b82f6;box-shadow:0 0 #3b82f673;animation:_ngcontent-%COMP%_pulse-stream-dot 1.8s cubic-bezier(.4,0,.6,1) infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-retry-notes[_ngcontent-%COMP%] .llm-retry-note[_ngcontent-%COMP%] .llm-retry-note-text[_ngcontent-%COMP%]{color:#71717a;display:flex;flex-direction:column;min-width:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-retry-notes[_ngcontent-%COMP%] .llm-retry-note[_ngcontent-%COMP%] .llm-retry-note-text[_ngcontent-%COMP%] .llm-retry-status-line[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-retry-notes[_ngcontent-%COMP%] .llm-retry-note[_ngcontent-%COMP%] .llm-retry-note-text[_ngcontent-%COMP%] .llm-retry-guidance[_ngcontent-%COMP%]{display:block}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-retry-notes[_ngcontent-%COMP%] .llm-retry-note[_ngcontent-%COMP%] .llm-retry-note-text[_ngcontent-%COMP%] .llm-retry-guidance[_ngcontent-%COMP%]{color:#a1a1aa}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%]{border:1px solid transparent}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool.is-video-attention[_ngcontent-%COMP%]:not(.is-running) .tool-call-label[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{background:#f59e0b;box-shadow:none;animation:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool.is-llm-error[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%]{display:flex;align-items:flex-start;color:#71717a;line-height:1.5;-webkit-user-select:text;user-select:text}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool.is-llm-error[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .error-icon[_ngcontent-%COMP%]{font-size:14px;color:#94a3b8;margin-top:1px;margin-left:-3px;margin-right:-3px;flex-shrink:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool.is-llm-error[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .tool-call-text[_ngcontent-%COMP%]{display:block;color:inherit}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool.is-llm-error[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .error-title-text[_ngcontent-%COMP%]{font-weight:500;color:#71717a;margin-right:4px;flex-shrink:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool.is-llm-error[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .error-message-text[_ngcontent-%COMP%]{color:#71717a;word-break:break-word}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool.is-running[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{background:#3b82f6;box-shadow:0 0 #3b82f673;animation:_ngcontent-%COMP%_pulse-stream-dot 1.8s cubic-bezier(.4,0,.6,1) infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool.is-running[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .tool-call-text[_ngcontent-%COMP%] > span[_ngcontent-%COMP%]:first-child{background:linear-gradient(90deg,#71717a,#2563eb,#7c3aed,#0284c7,#71717a);background-size:200% 100%;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;animation:_ngcontent-%COMP%_subtle-color-flow 2.8s linear infinite;font-weight:500}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%]{font-size:12px;font-weight:400;color:#71717a;font-family:Google Sans,Google Sans Text,Inter,Arial,sans-serif;letter-spacing:.5px;line-height:1.5;min-height:22px;box-sizing:border-box;display:inline-flex;align-items:center;gap:8px;-webkit-user-select:none;user-select:none;padding:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] span[_ngcontent-%COMP%]:not(.tool-key-pill){color:inherit}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;background:#d4d4d8;display:inline-block;flex-shrink:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%]{background:#3b82f6;box-shadow:0 0 #3b82f673;animation:_ngcontent-%COMP%_pulse-stream-dot 1.8s cubic-bezier(.4,0,.6,1) infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .is-failed-dot[_ngcontent-%COMP%]{font-size:13px;color:#94a3b8;display:inline-flex;align-items:center;justify-content:center;width:8px;height:8px;flex-shrink:0;line-height:1}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .tool-call-text[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:2px;color:inherit}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .tool-key-pill[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;border:none;background:transparent;font-size:12px;font-weight:500;color:#1a73e8;cursor:pointer;border-radius:4px;transition:all .2s ease;vertical-align:middle;text-decoration:none!important}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .tool-key-pill[_ngcontent-%COMP%] .pill-icon[_ngcontent-%COMP%]{font-size:14px;color:inherit}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .tool-key-pill[_ngcontent-%COMP%]:hover{color:#1557b0;background:#1a73e814}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-generic-tool[_ngcontent-%COMP%] .tool-call-label[_ngcontent-%COMP%] .video-status-detail[_ngcontent-%COMP%]{color:inherit;margin-left:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-llm-error-card[_ngcontent-%COMP%]{background:#fef2f2;border:1px solid #fecaca;border-radius:10px;padding:10px 12px;margin-top:0;margin-bottom:0;margin-left:-19px;box-shadow:0 4px 12px #ef444408;width:fit-content;min-width:260px;max-width:480px;display:flex;flex-direction:column;gap:8px;transition:all .2s ease;position:relative}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-llm-error-card[_ngcontent-%COMP%]:hover{border-color:#fca5a5;box-shadow:0 4px 16px #ef444414}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-llm-error-card[_ngcontent-%COMP%] .error-card-header[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;border-bottom:1px solid #fee2e2;padding-bottom:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-llm-error-card[_ngcontent-%COMP%] .error-card-header[_ngcontent-%COMP%] .error-icon[_ngcontent-%COMP%]{font-size:18px;color:#ef4444}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-llm-error-card[_ngcontent-%COMP%] .error-card-header[_ngcontent-%COMP%] .error-title[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,Arial,sans-serif;font-weight:700;font-size:12px;color:#991b1b}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-llm-error-card[_ngcontent-%COMP%] .error-card-body[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-llm-error-card[_ngcontent-%COMP%] .error-card-body[_ngcontent-%COMP%] .error-detail-row[_ngcontent-%COMP%]{display:flex;font-size:12px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-llm-error-card[_ngcontent-%COMP%] .error-card-body[_ngcontent-%COMP%] .error-detail-row[_ngcontent-%COMP%] .detail-value[_ngcontent-%COMP%]{color:#b91c1c;font-weight:500;word-break:break-word;line-height:1.4}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%]{width:380px;max-width:100%;margin-left:-19px;display:flex;flex-direction:column;align-items:flex-start;gap:10px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%]{width:100%;margin-left:0;box-sizing:border-box}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .llm-resume-row[_ngcontent-%COMP%]{min-height:36px;display:flex;align-items:center;gap:10px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .btn-continue-task[_ngcontent-%COMP%]{min-height:36px;padding:7px 12px 7px 10px;display:inline-flex;align-items:center;justify-content:center;gap:7px;box-sizing:border-box;border:1px solid #1d4ed8;border-radius:9px;background:#2563eb;color:#fff;font-family:inherit;font-size:12px;font-weight:700;line-height:1;cursor:pointer;box-shadow:0 2px 7px #2563eb38;transition:background .18s ease,border-color .18s ease,box-shadow .18s ease,transform .18s ease}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .btn-continue-task[_ngcontent-%COMP%] .continue-icon[_ngcontent-%COMP%]{width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;margin:-2px 0 -2px -2px;border-radius:50%;background:#ffffff29;font-size:16px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .btn-continue-task[_ngcontent-%COMP%] .continue-arrow[_ngcontent-%COMP%]{font-size:15px;opacity:.72;transition:transform .18s ease,opacity .18s ease}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .btn-continue-task[_ngcontent-%COMP%]:hover{background:#1d4ed8;border-color:#1e40af;box-shadow:0 4px 11px #2563eb47;transform:translateY(-1px)}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .btn-continue-task[_ngcontent-%COMP%]:hover .continue-arrow[_ngcontent-%COMP%]{opacity:1;transform:translate(2px)}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .btn-continue-task[_ngcontent-%COMP%]:active{box-shadow:0 1px 4px #2563eb33;transform:translateY(0) scale(.98)}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .btn-continue-task[_ngcontent-%COMP%]:focus-visible{outline:3px solid rgba(59,130,246,.25);outline-offset:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .llm-resume-hint[_ngcontent-%COMP%]{color:#94a3b8;font-size:11px;line-height:1.35;white-space:nowrap}@media(max-width:560px){.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .llm-resume-row[_ngcontent-%COMP%]{width:100%}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .btn-continue-task[_ngcontent-%COMP%]{flex:1}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .llm-failure-stack[_ngcontent-%COMP%] .llm-resume-hint[_ngcontent-%COMP%]{display:none}}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%]{background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:10px 12px;margin-top:0;margin-bottom:0;margin-left:-19px;box-shadow:0 4px 12px #00000005;width:380px;max-width:100%;display:flex;flex-direction:column;gap:8px;transition:all .25s cubic-bezier(.16,1,.3,1);position:relative;cursor:pointer;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.is-running[_ngcontent-%COMP%]{border-color:#3b82f659;box-shadow:0 2px 10px #3b82f614;animation:_ngcontent-%COMP%_subtle-card-glow 2.5s ease-in-out infinite alternate}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.is-running[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{color:#3b82f6}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.is-running[_ngcontent-%COMP%] .action-title[_ngcontent-%COMP%]{background:linear-gradient(90deg,#0f172a,#2563eb 30%,#7c3aed,#0284c7 70%,#0f172a);background-size:200% 100%;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;animation:_ngcontent-%COMP%_subtle-color-flow 2.8s linear infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%]:hover{border-color:#cbd5e1;box-shadow:0 4px 16px #0000000a;transform:translateY(-1px)}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%]:hover .action-expand-icon[_ngcontent-%COMP%]{color:#1e293b;background:#e2e8f0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.is-expanded[_ngcontent-%COMP%]{border-color:#94a3b8;background:#fff;box-shadow:0 8px 24px #0000000f}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.is-expanded[_ngcontent-%COMP%] .action-expand-icon[_ngcontent-%COMP%]{color:#0f172a;background:#e2e8f0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.is-failed[_ngcontent-%COMP%]{background:#f8fafc;border-color:#fca5a5}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.is-failed.has-details[_ngcontent-%COMP%]{cursor:pointer}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.is-failed[_ngcontent-%COMP%]:hover{border-color:#f87171}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.is-failed.is-expanded[_ngcontent-%COMP%]{background:#fff;border-color:#f87171}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card[_ngcontent-%COMP%]{background:#f0fdf4;border:1px solid #bbf7d0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card.is-completed[_ngcontent-%COMP%]{background:#f0fdf4;border-color:#86efac}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card.is-completed[_ngcontent-%COMP%] .report-icon[_ngcontent-%COMP%]{color:#16a34a;font-variation-settings:"FILL" 1}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card.is-completed[_ngcontent-%COMP%] .action-title[_ngcontent-%COMP%]{color:#14532d;font-weight:700}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card.is-completed[_ngcontent-%COMP%] .action-status-badge.is-completed[_ngcontent-%COMP%]{background:#dcfce7;color:#15803d;border:1px solid #bbf7d0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card.is-failed[_ngcontent-%COMP%]{background:#fef2f2;border-color:#fecaca}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card.is-failed[_ngcontent-%COMP%] .report-icon[_ngcontent-%COMP%]{color:#dc2626;font-variation-settings:"FILL" 1}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card.is-failed[_ngcontent-%COMP%] .action-title[_ngcontent-%COMP%]{color:#7f1d1d;font-weight:700}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card.is-failed[_ngcontent-%COMP%] .action-status-badge.is-failed[_ngcontent-%COMP%]{background:#fee2e2;color:#b91c1c;border:1px solid #fca5a5}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card[_ngcontent-%COMP%] .report-markdown-body[_ngcontent-%COMP%]{font-size:12px;line-height:1.5;color:#1f2937;font-weight:400;-webkit-user-select:text;user-select:text;word-break:break-word}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card[_ngcontent-%COMP%] .report-markdown-body[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{margin:3px 0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card[_ngcontent-%COMP%] .report-markdown-body[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{font-weight:600;color:#0f172a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card[_ngcontent-%COMP%] .report-markdown-body[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card[_ngcontent-%COMP%] .report-markdown-body[_ngcontent-%COMP%] ol[_ngcontent-%COMP%]{margin:3px 0;padding-left:18px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.task-report-card[_ngcontent-%COMP%] .report-markdown-body[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{font-family:Fira Code,monospace;background:#e2e8f0;color:#1f2937;padding:1px 4px;border-radius:4px;font-size:11px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.has-no-details[_ngcontent-%COMP%]{padding:8px 12px;gap:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card.has-no-details[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%]{border-bottom:none;padding-bottom:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;border-bottom:1px solid #f1f5f9;padding-bottom:6px;width:100%}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-icon[_ngcontent-%COMP%]{font-size:18px;color:#64748b}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-icon.is-failed[_ngcontent-%COMP%]{color:#ef4444}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-title[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,Arial,Liberation Sans,sans-serif;font-weight:700;font-size:12px;color:#0f172a;flex-grow:1}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-agent-badge[_ngcontent-%COMP%]{display:inline-flex;align-items:center;font-size:10px;font-weight:600;padding:1px 6px;border-radius:4px;background:#f0fdf4;color:#166534;border:1px solid #bbf7d0;letter-spacing:.2px;margin-right:6px;white-space:nowrap}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-agent-badge.is-outputter[_ngcontent-%COMP%]{background:linear-gradient(135deg,#f5f3fff2,#eef2fff2);color:#6d28d9;border-color:#c4b5fd}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-status-badge[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:3px;font-size:11px;font-weight:600;padding:1px 6px;border-radius:4px;margin-left:auto;white-space:nowrap}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-status-badge[_ngcontent-%COMP%] .status-icon[_ngcontent-%COMP%]{font-size:13px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-status-badge.is-failed[_ngcontent-%COMP%]{background:#fef2f2;color:#dc2626;border:1px solid #fee2e2}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-status-badge.is-failed[_ngcontent-%COMP%] .status-icon[_ngcontent-%COMP%]{color:#ef4444}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-status-badge.is-paused[_ngcontent-%COMP%]{background:#fff7ed;color:#c2410c;border:1px solid #fed7aa}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-status-badge.is-paused[_ngcontent-%COMP%] .status-icon[_ngcontent-%COMP%]{color:#f97316}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-header[_ngcontent-%COMP%] .action-expand-icon[_ngcontent-%COMP%]{font-size:18px;color:#94a3b8;margin-left:4px;padding:2px;border-radius:50%;transition:all .2s ease;display:flex;align-items:center;justify-content:center}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .action-detail-row[_ngcontent-%COMP%]{display:flex;align-items:baseline;font-size:12px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .action-detail-row[_ngcontent-%COMP%] .detail-label[_ngcontent-%COMP%]{color:#64748b;font-weight:500;width:85px;flex-shrink:0}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .action-detail-row[_ngcontent-%COMP%] .detail-value[_ngcontent-%COMP%]{color:#334155;font-weight:600;word-break:break-word}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .action-detail-row[_ngcontent-%COMP%] .detail-value.coordinate-badge[_ngcontent-%COMP%]{background:#e2e8f0;color:#475569;padding:2px 6px;border-radius:4px;font-family:Fira Code,monospace;font-size:11px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .action-detail-row[_ngcontent-%COMP%] .detail-value.command-value[_ngcontent-%COMP%]{font-family:Fira Code,Consolas,Monaco,monospace;background:#f1f5f9;border:1px solid #e2e8f0;padding:2px 6px;border-radius:4px;font-size:11px;font-weight:500;color:#0f172a;white-space:pre-wrap;word-break:break-all}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .action-detail-row[_ngcontent-%COMP%] .detail-value.command-value[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{font-family:inherit;font-size:inherit;color:inherit;background:none;padding:0;border:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .failure-retry-details[_ngcontent-%COMP%]{margin-top:4px;padding-top:9px;border-top:1px solid #fecaca;display:flex;flex-direction:column;gap:7px;animation:_ngcontent-%COMP%_fadeInDetails .2s ease-out}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .failure-retry-details[_ngcontent-%COMP%] .failure-retry-title[_ngcontent-%COMP%]{color:#991b1b;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.03em}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .failure-retry-details[_ngcontent-%COMP%] .failure-retry-row[_ngcontent-%COMP%]{display:flex;justify-content:space-between;gap:12px;color:#7f1d1d;font-size:10.5px;line-height:1.4}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-body[_ngcontent-%COMP%] .failure-retry-details[_ngcontent-%COMP%] .failure-retry-row[_ngcontent-%COMP%] span[_ngcontent-%COMP%]:last-child{color:#64748b;text-align:right}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px;padding-top:4px;animation:_ngcontent-%COMP%_fadeInDetails .2s ease-out}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;background:#f8fafc;padding:10px;border-radius:8px;border:1px solid #f1f5f9}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-grid[_ngcontent-%COMP%] .grid-item[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-grid[_ngcontent-%COMP%] .grid-item.full-width[_ngcontent-%COMP%]{grid-column:1/-1}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-grid[_ngcontent-%COMP%] .grid-item[_ngcontent-%COMP%] .grid-label[_ngcontent-%COMP%]{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:#64748b}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-grid[_ngcontent-%COMP%] .grid-item[_ngcontent-%COMP%] .grid-value[_ngcontent-%COMP%]{font-size:12px;font-weight:600;color:#1e293b;word-break:break-all}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-grid[_ngcontent-%COMP%] .grid-item[_ngcontent-%COMP%] .grid-value.code-pill[_ngcontent-%COMP%]{font-family:Roboto Mono,Fira Code,Consolas,monospace;font-size:11px;background:#e2e8f0;color:#334155;padding:2px 6px;border-radius:4px;display:inline-block;width:fit-content}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-grid[_ngcontent-%COMP%] .grid-item[_ngcontent-%COMP%] .grid-value.command-value[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{font-family:Roboto Mono,Fira Code,Consolas,monospace;font-size:11px;background:#0f172a;color:#38bdf8;padding:4px 8px;border-radius:4px;display:block;word-break:break-all;white-space:pre-wrap}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-screenshots-container[_ngcontent-%COMP%]{display:flex;flex-direction:row;flex-wrap:nowrap;gap:12px;margin-top:4px;justify-content:flex-start;width:100%}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-screenshots-container[_ngcontent-%COMP%] .screenshot-column[_ngcontent-%COMP%]{flex:1 1 0;min-width:0;max-width:320px;display:flex;flex-direction:column;gap:6px;align-items:center}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-screenshots-container[_ngcontent-%COMP%] .screenshot-column[_ngcontent-%COMP%] .screenshot-label[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,Arial,Liberation Sans,sans-serif;font-size:11.5px;font-weight:500;color:#64748b;letter-spacing:normal;text-transform:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-screenshots-container[_ngcontent-%COMP%] .screenshot-column[_ngcontent-%COMP%] .image-wrapper[_ngcontent-%COMP%]{display:inline-flex;justify-content:center;align-items:center;max-width:100%;border:1px solid #e2e8f0;border-radius:8px;background-color:#f8fafc;cursor:zoom-in;overflow:hidden;box-shadow:0 1px 3px #0000000d;transition:transform .15s ease,box-shadow .15s ease,border-color .15s ease}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-screenshots-container[_ngcontent-%COMP%] .screenshot-column[_ngcontent-%COMP%] .image-wrapper[_ngcontent-%COMP%]:hover{transform:translateY(-1px);box-shadow:0 4px 12px #00000014;border-color:#cbd5e1}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-screenshots-container[_ngcontent-%COMP%] .screenshot-column[_ngcontent-%COMP%] .image-wrapper[_ngcontent-%COMP%] .img-relative-box[_ngcontent-%COMP%]{position:relative;display:inline-block;max-width:100%}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-screenshots-container[_ngcontent-%COMP%] .screenshot-column[_ngcontent-%COMP%] .image-wrapper[_ngcontent-%COMP%] .img-relative-box[_ngcontent-%COMP%] img[_ngcontent-%COMP%]{display:block;max-width:100%;max-height:280px;width:auto;height:auto;margin:0 auto;border-radius:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-screenshots-container[_ngcontent-%COMP%] .screenshot-column[_ngcontent-%COMP%] .image-wrapper[_ngcontent-%COMP%] .img-relative-box[_ngcontent-%COMP%] .overlay-layer[_ngcontent-%COMP%]{position:absolute;inset:0;pointer-events:none;overflow:visible}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-error-banner[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;background:#fff1f2;border:1px solid #fecdd3;color:#be123c;padding:8px 12px;border-radius:6px;font-size:12px;font-weight:500}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .step-android-action-card[_ngcontent-%COMP%] .action-card-expanded-details[_ngcontent-%COMP%] .expanded-error-banner[_ngcontent-%COMP%] .icon[_ngcontent-%COMP%]{font-size:16px;color:#e11d48}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%]{padding:20px 24px;display:flex;flex-direction:column;gap:12px;background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:12px;box-shadow:0 4px 6px -1px #00000003,0 2px 4px -1px #00000002}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%] .final-summary-header[_ngcontent-%COMP%]{font-weight:500;font-size:12px;color:#71717a;display:flex;align-items:center;gap:6px;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%] .final-summary-body[_ngcontent-%COMP%]{font-size:12px;line-height:1.6;color:#27272a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%] .final-summary-body[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{font-weight:600;color:#09090b}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%] .final-summary-body[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%] .final-summary-body[_ngcontent-%COMP%] ol[_ngcontent-%COMP%]{margin:6px 0;padding-left:20px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%] .final-summary-body[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%] .final-summary-body[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{margin-bottom:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%] .final-summary-body[_ngcontent-%COMP%] div[_ngcontent-%COMP%]{margin-bottom:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item[_ngcontent-%COMP%] .step-body[_ngcontent-%COMP%] .step-actions-container[_ngcontent-%COMP%] .final-summary-card[_ngcontent-%COMP%] .final-summary-body[_ngcontent-%COMP%] .md-para-gap[_ngcontent-%COMP%]{height:8px}@keyframes _ngcontent-%COMP%_spin-loader{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes _ngcontent-%COMP%_pulse-green{0%{box-shadow:0 0 #10b98166}70%{box-shadow:0 0 0 6px #10b98100}to{box-shadow:0 0 #10b98100}}@keyframes _ngcontent-%COMP%_pulse-stream-blue{0%{box-shadow:0 0 #0ea5e966}70%{box-shadow:0 0 0 6px #0ea5e900}to{box-shadow:0 0 #0ea5e900}}@keyframes _ngcontent-%COMP%_pulse-stream-green{0%{box-shadow:0 0 #22c55e66}70%{box-shadow:0 0 0 6px #22c55e00}to{box-shadow:0 0 #22c55e00}}@keyframes _ngcontent-%COMP%_pulse-stream-purple{0%{box-shadow:0 0 #a855f766}70%{box-shadow:0 0 0 6px #a855f700}to{box-shadow:0 0 #a855f700}}@keyframes _ngcontent-%COMP%_pulse-stream-grey{0%{box-shadow:0 0 #71717a66}70%{box-shadow:0 0 0 6px #71717a00}to{box-shadow:0 0 #71717a00}}@keyframes _ngcontent-%COMP%_pulse-black-dot{0%{box-shadow:0 0 #0006}70%{box-shadow:0 0 0 5px #0000}to{box-shadow:0 0 #0000}}@keyframes _ngcontent-%COMP%_pulse-black-dot-small{0%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes _ngcontent-%COMP%_fadeInDetails{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}@keyframes _ngcontent-%COMP%_dropdownFadeIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}@keyframes _ngcontent-%COMP%_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.image-modal-backdrop[_ngcontent-%COMP%]{position:absolute;inset:0;width:100%;height:100%;background-color:#0f172abf;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;display:flex;align-items:center;justify-content:center;padding:24px;box-sizing:border-box;animation:_ngcontent-%COMP%_fadeInModal .2s ease-out}.image-modal-backdrop[_ngcontent-%COMP%] .image-modal-content[_ngcontent-%COMP%]{position:relative;max-width:calc(100% - 48px);max-height:calc(100% - 48px);background:#0f172a;border-radius:12px;padding:12px;box-shadow:0 20px 25px -5px #00000080,0 8px 10px -6px #00000080;display:flex;align-items:center;justify-content:center;box-sizing:border-box}.image-modal-backdrop[_ngcontent-%COMP%] .image-modal-content[_ngcontent-%COMP%] .image-modal-close[_ngcontent-%COMP%]{position:absolute;top:-12px;right:-12px;width:32px;height:32px;border-radius:50%;background:#ef4444;color:#fff;border:2px solid white;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 6px -1px #0000004d;transition:transform .15s ease,background-color .15s ease;z-index:20}.image-modal-backdrop[_ngcontent-%COMP%] .image-modal-content[_ngcontent-%COMP%] .image-modal-close[_ngcontent-%COMP%]:hover{transform:scale(1.1);background:#dc2626}.image-modal-backdrop[_ngcontent-%COMP%] .image-modal-content[_ngcontent-%COMP%] .image-modal-close[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:18px}.image-modal-backdrop[_ngcontent-%COMP%] .image-modal-content[_ngcontent-%COMP%] .img-relative-box[_ngcontent-%COMP%]{position:relative;display:inline-flex;align-items:center;justify-content:center;max-width:100%;max-height:100%}.image-modal-backdrop[_ngcontent-%COMP%] .image-modal-content[_ngcontent-%COMP%] .img-relative-box[_ngcontent-%COMP%] img[_ngcontent-%COMP%]{display:block;max-width:100%;max-height:calc(100vh - 140px);width:auto;height:auto;object-fit:contain;border-radius:6px}.image-modal-backdrop[_ngcontent-%COMP%] .image-modal-content[_ngcontent-%COMP%] .img-relative-box[_ngcontent-%COMP%] .overlay-layer[_ngcontent-%COMP%]{position:absolute;inset:0;pointer-events:none;overflow:visible;border-radius:6px}@keyframes _ngcontent-%COMP%_pulse-animation{0%{transform:scale(.5);opacity:1}to{transform:scale(1.8);opacity:0}}@keyframes _ngcontent-%COMP%_fadeInModal{0%{opacity:0}to{opacity:1}}@keyframes _ngcontent-%COMP%_subtle-color-flow{0%{background-position:0% 50%}to{background-position:200% 50%}}@keyframes _ngcontent-%COMP%_pulse-stream-dot{0%,to{transform:scale(1);box-shadow:0 0 #3b82f673}50%{transform:scale(1.15);box-shadow:0 0 0 4px #3b82f600}}@keyframes _ngcontent-%COMP%_subtle-card-glow{0%{border-color:#3b82f640;box-shadow:0 2px 8px #3b82f60d}to{border-color:#6366f173;box-shadow:0 4px 14px #6366f11f}}.outputter-synthesis-stream-card[_ngcontent-%COMP%]{margin:16px 0 12px;border-radius:12px;border:1px solid rgba(196,181,253,.85);background:linear-gradient(135deg,#f5f3fff2,#faf5fffa);box-shadow:0 4px 16px #7c3aed14,0 1px 3px #00000008;overflow:hidden;animation:_ngcontent-%COMP%_fadeInModal .25s ease-out}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#ede9fe99;border-bottom:1px solid rgba(196,181,253,.7);gap:12px;flex-wrap:wrap}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .icon-sparkle[_ngcontent-%COMP%]{font-size:22px;color:#7c3aed}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .main-title[_ngcontent-%COMP%]{font-size:14px;font-weight:700;color:#4338ca}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-open-note[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;padding:5px 12px;background:linear-gradient(135deg,#6366f1,#7c3aed);color:#fff;border:none;border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;transition:all .15s ease;box-shadow:0 2px 6px #6366f140}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-open-note[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-open-note[_ngcontent-%COMP%]:hover{background:linear-gradient(135deg,#4f46e5,#6d28d9);box-shadow:0 4px 10px #6366f159;transform:translateY(-1px)}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%]{padding:14px 16px}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-note-title[_ngcontent-%COMP%]{font-size:14px;font-weight:700;color:#1e1b4b;margin:0}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-milestones[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:6px}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-milestones[_ngcontent-%COMP%] .milestone-item[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:8px;font-size:12.5px;line-height:1.45;color:#374151}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-milestones[_ngcontent-%COMP%] .milestone-item[_ngcontent-%COMP%] .status-icon[_ngcontent-%COMP%]{font-size:16px;color:#7c3aed;margin-top:1px;flex-shrink:0}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-milestones[_ngcontent-%COMP%] .milestone-item.status-checked[_ngcontent-%COMP%] .status-icon[_ngcontent-%COMP%]{color:#10b981}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-milestones[_ngcontent-%COMP%] .milestone-item.status-progress[_ngcontent-%COMP%] .status-icon[_ngcontent-%COMP%]{color:#f59e0b}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-other-lines[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:4px}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-other-lines[_ngcontent-%COMP%] .other-line[_ngcontent-%COMP%]{margin:0;font-size:12.5px;line-height:1.5;color:#4b5563}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-other-lines[_ngcontent-%COMP%] .other-line[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:#1e1b4b}.outputter-synthesis-stream-card[_ngcontent-%COMP%] .synthesis-card-preview[_ngcontent-%COMP%] .parsed-note-container[_ngcontent-%COMP%] .parsed-other-lines[_ngcontent-%COMP%] .other-line[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{font-family:JetBrains Mono,monospace;background:#ffffffe6;border:1px solid #e5e7eb;padding:1px 4px;border-radius:4px;color:#6d28d9;font-size:11.5px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%]{border-left:2px solid #ddd6fe;padding-left:12px;margin-left:-14px;font-family:Google Sans,Google Sans Text,Inter,Arial,sans-serif}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-index[_ngcontent-%COMP%]{flex:0 0 14px;text-align:right;color:#a1a1aa;font-variant-numeric:tabular-nums;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px;margin-bottom:8px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-header[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;min-height:20px;font-size:12px;line-height:1.5;letter-spacing:.2px;color:#71717a;-webkit-user-select:none;user-select:none}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-header[_ngcontent-%COMP%] .stream-status-dot[_ngcontent-%COMP%]{flex:0 0 auto;width:8px;height:8px;border-radius:50%;display:inline-block;background:#d4d4d8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-header[_ngcontent-%COMP%] .stream-status-dot.streaming[_ngcontent-%COMP%]{background:#7c3aed;box-shadow:0 0 #7c3aed73;animation:_ngcontent-%COMP%_pulse-stream-dot 1.8s cubic-bezier(.4,0,.6,1) infinite}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-header[_ngcontent-%COMP%] .check-title[_ngcontent-%COMP%]{flex:0 0 auto;font-weight:500;color:#52525b}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-header[_ngcontent-%COMP%] .check-subject[_ngcontent-%COMP%]{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-header[_ngcontent-%COMP%] .check-status[_ngcontent-%COMP%]{flex:0 0 auto;margin-left:auto;font-weight:500;color:#52525b;white-space:nowrap}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane.tone-passed[_ngcontent-%COMP%] .check-status[_ngcontent-%COMP%]{color:#15803d}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane.tone-failed[_ngcontent-%COMP%] .check-status[_ngcontent-%COMP%]{color:#b91c1c}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane.tone-inconclusive[_ngcontent-%COMP%] .check-status[_ngcontent-%COMP%]{color:#b45309}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane.tone-running[_ngcontent-%COMP%] .check-status[_ngcontent-%COMP%]{color:#6d28d9}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane.tone-muted[_ngcontent-%COMP%]{opacity:.6}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-items[_ngcontent-%COMP%]{list-style:none;margin:0;padding:0 0 0 16px;display:flex;flex-direction:column;gap:2px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-items[_ngcontent-%COMP%] .check-item[_ngcontent-%COMP%]{display:flex;align-items:baseline;gap:8px;font-size:12px;line-height:1.5;color:#3f3f46}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-items[_ngcontent-%COMP%] .check-item[_ngcontent-%COMP%] .check-text[_ngcontent-%COMP%]{flex:1 1 auto;min-width:0;word-break:break-word}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-lane[_ngcontent-%COMP%] .check-items[_ngcontent-%COMP%] .check-item[_ngcontent-%COMP%] .check-method[_ngcontent-%COMP%]{flex:0 0 auto;color:#a1a1aa;white-space:nowrap}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:4px;margin-top:8px;padding-left:16px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:8px;font-size:12px;line-height:1.5;color:#52525b}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict[_ngcontent-%COMP%] .check-index[_ngcontent-%COMP%]{line-height:18px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict[_ngcontent-%COMP%] .verdict-icon[_ngcontent-%COMP%]{flex:0 0 auto;font-size:15px;line-height:18px;color:#a1a1aa}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict.passed[_ngcontent-%COMP%] .verdict-icon[_ngcontent-%COMP%]{color:#16a34a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict.failed[_ngcontent-%COMP%] .verdict-icon[_ngcontent-%COMP%]{color:#dc2626}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict.inconclusive[_ngcontent-%COMP%] .verdict-icon[_ngcontent-%COMP%]{color:#d97706}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict.superseded[_ngcontent-%COMP%], .agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict.unchecked[_ngcontent-%COMP%]{color:#a1a1aa}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict[_ngcontent-%COMP%] .verdict-body[_ngcontent-%COMP%]{flex:1 1 auto;min-width:0;word-break:break-word}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-verdict[_ngcontent-%COMP%] .verdict-suggestion[_ngcontent-%COMP%]{display:block;color:#1d4ed8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .phase-body[_ngcontent-%COMP%] .block-item.type-checker[_ngcontent-%COMP%] .check-result[_ngcontent-%COMP%] .check-note[_ngcontent-%COMP%]{font-size:12px;line-height:1.5;color:#71717a;padding-left:22px;word-break:break-word}']})};function f3(n,t){if(n&1){let e=L();l(0,"button",10),k("click",function(){v(e);let i=m();return y(i.clearHistory())}),l(1,"span",11),u(2,"delete"),d()()}if(n&2){let e=m();R("disabled",e.isSubmitting())}}function m3(n,t){n&1&&(l(0,"div",14),u(1," No active or queued tasks. "),d())}function _3(n,t){n&1&&$(0,"span",22)}function h3(n,t){if(n&1&&(l(0,"span",24)(1,"span",33),u(2,"phone_android"),d(),l(3,"span",34),u(4),d()()),n&2){let e=m().$implicit,o=m(2);R("title","Device: "+o.getDeviceSerial(e)),g(4),O(o.getDeviceSerial(e))}}function C3(n,t){n&1&&(l(0,"span",25),u(1,"\xB7"),d())}function M3(n,t){if(n&1){let e=L();l(0,"button",35),k("click",function(i){v(e);let r=m().$implicit,a=m(2);return y(a.stopTask(r.session_id,i))}),l(1,"span",11),u(2,"stop_circle"),d()()}}function b3(n,t){if(n&1){let e=L();l(0,"button",36),k("click",function(i){v(e);let r=m().$implicit,a=m(2);return y(a.deleteTask(r.session_id,i))}),l(1,"span",11),u(2,"delete"),d()()}if(n&2){let e=m(3);R("disabled",e.isSubmitting())}}function P3(n,t){if(n&1){let e=L();l(0,"div",19),k("click",function(){let i=v(e).$implicit,r=m(2);return y(r.selectTask(i.session_id))}),l(1,"div",20)(2,"span",21),M(3,_3,1,0,"span",22),u(4),it(5,"uppercase"),d(),l(6,"div",23),M(7,h3,5,2,"span",24),M(8,C3,2,0,"span",25),l(9,"span",26),u(10),it(11,"date"),d(),M(12,M3,3,0,"button",27),M(13,b3,3,1,"button",28),d()(),l(14,"div",29),u(15),d(),l(16,"div",30)(17,"span",31),u(18),d(),l(19,"span",32),u(20),it(21,"date"),d()()()}if(n&2){let e=t.$implicit,o=m(2);w("selected",o.agentService.currentSessionId()===e.session_id)("running",o.getTaskStatus(e)==="running"),g(2),R("ngClass",o.getTaskStatus(e)),g(),b(o.getTaskStatus(e)==="running"?3:-1),g(),V(" ",wi(5,18,o.getTaskStatus(e))," "),g(3),b(o.getDeviceSerial(e)?7:-1),g(),b(o.getDeviceSerial(e)?8:-1),g(2),O(Et(11,20,e.start_time*1e3,"shortTime")),g(2),b(o.getTaskStatus(e)==="running"||o.getTaskStatus(e)==="paused"?12:-1),g(),b(o.getTaskStatus(e)!=="running"&&o.getTaskStatus(e)!=="paused"?13:-1),g(),R("title",xi(e.initial_goal)),g(),V(" ",e.initial_goal||"Unnamed Task"," "),g(2),R("title",e.session_id),g(),V("ID: ",e.session_id),g(2),O(Et(21,23,e.start_time*1e3,"MM/dd/yy"))}}function O3(n,t){n&1&&(l(0,"div",14),u(1," No past tasks. "),d())}function v3(n,t){n&1&&$(0,"span",22)}function y3(n,t){if(n&1&&(l(0,"span",24)(1,"span",33),u(2,"phone_android"),d(),l(3,"span",34),u(4),d()()),n&2){let e=m().$implicit,o=m(2);R("title","Device: "+o.getDeviceSerial(e)),g(4),O(o.getDeviceSerial(e))}}function x3(n,t){n&1&&(l(0,"span",25),u(1,"\xB7"),d())}function w3(n,t){if(n&1){let e=L();l(0,"button",36),k("click",function(i){v(e);let r=m().$implicit,a=m(2);return y(a.deleteTask(r.session_id,i))}),l(1,"span",11),u(2,"delete"),d()()}if(n&2){let e=m(3);R("disabled",e.isSubmitting())}}function S3(n,t){if(n&1){let e=L();l(0,"div",19),k("click",function(){let i=v(e).$implicit,r=m(2);return y(r.selectTask(i.session_id))}),l(1,"div",20)(2,"span",21),M(3,v3,1,0,"span",22),u(4),it(5,"uppercase"),d(),l(6,"div",23),M(7,y3,5,2,"span",24),M(8,x3,2,0,"span",25),l(9,"span",26),u(10),it(11,"date"),d(),M(12,w3,3,1,"button",28),d()(),l(13,"div",29),u(14),d(),l(15,"div",30)(16,"span",31),u(17),d(),l(18,"span",32),u(19),it(20,"date"),d()()()}if(n&2){let e=t.$implicit,o=m(2);w("selected",o.agentService.currentSessionId()===e.session_id)("running",o.getTaskStatus(e)==="running"),g(2),R("ngClass",o.getTaskStatus(e)),g(),b(o.getTaskStatus(e)==="running"?3:-1),g(),V(" ",wi(5,17,o.getTaskStatus(e))," "),g(3),b(o.getDeviceSerial(e)?7:-1),g(),b(o.getDeviceSerial(e)?8:-1),g(2),O(Et(11,19,e.start_time*1e3,"shortTime")),g(2),b(o.getTaskStatus(e)!=="running"&&o.getTaskStatus(e)!=="paused"?12:-1),g(),R("title",xi(e.initial_goal)),g(),V(" ",e.initial_goal||"Unnamed Task"," "),g(2),R("title",e.session_id),g(),V("ID: ",e.session_id),g(2),O(Et(20,22,e.start_time*1e3,"MM/dd/yy"))}}function k3(n,t){if(n&1&&(l(0,"div",12)(1,"span",13),u(2,"bolt"),d(),u(3),d(),M(4,m3,2,0,"div",14),G(5,P3,22,26,"div",15,De().trackSession,!0),l(7,"details",16)(8,"summary",17)(9,"span",13),u(10,"history"),d(),u(11),d(),l(12,"div",18),M(13,O3,2,0,"div",14),G(14,S3,21,25,"div",15,De().trackSession,!0),d()()),n&2){let e=m();g(3),V(" Active Queue (",e.activeQueue().length,") "),g(),b(e.activeQueue().length===0?4:-1),g(),q(e.activeQueue()),g(6),V(" Past Runs & History (",e.historyTasks().length,") "),g(2),b(e.historyTasks().length===0?13:-1),g(),q(e.historyTasks())}}function E3(n,t){if(n&1){let e=L();l(0,"button",42),k("click",function(){let i=v(e).$implicit,r=m(3);return y(r.selectNote(i))}),l(1,"span",43),u(2,"draft"),d(),u(3),d()}if(n&2){let e=t.$implicit,o=m(3);w("active",o.agentService.selectedNoteKey()===e),g(3),V(" ",e," ")}}function D3(n,t){if(n&1&&(l(0,"div",37)(1,"div",40),G(2,E3,4,3,"button",41,De().trackNoteKey,!0),d()()),n&2){let e=m(2);g(2),q(e.noteKeys())}}function I3(n,t){n&1&&(l(0,"div",38)(1,"div",44)(2,"span",11),u(3,"description"),d()(),l(4,"h4",45),u(5,"No Notes & Plans"),d(),l(6,"p",46),u(7,"No notes or structured plans were recorded for this session."),d()())}function T3(n,t){if(n&1&&(l(0,"h2",47),u(1),d()),n&2){let e=m(3);g(),O(e.parsedNote().title)}}function A3(n,t){n&1&&(l(0,"span",52),u(1,"check_box"),d())}function N3(n,t){n&1&&(l(0,"span",53),u(1,"indeterminate_check_box"),d())}function R3(n,t){n&1&&(l(0,"span",54),u(1,"check_box_outline_blank"),d())}function F3(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function L3(n,t){n&1&&(l(0,"span",61),u(1,"check_box"),d())}function V3(n,t){n&1&&(l(0,"span",62),u(1,"indeterminate_check_box"),d())}function j3(n,t){n&1&&(l(0,"span",63),u(1,"check_box_outline_blank"),d())}function $3(n,t){n&1&&(l(0,"span",64),u(1,"\u2022"),d())}function z3(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function B3(n,t){if(n&1&&(l(0,"span",65),G(1,z3,2,5,"span",56,Ie),d()),n&2){let e=m().$implicit;g(),q(e.segments)}}function H3(n,t){if(n&1&&(l(0,"div",60),M(1,L3,2,0,"span",61)(2,V3,2,0,"span",62)(3,j3,2,0,"span",63)(4,$3,2,0,"span",64),M(5,B3,3,0,"span",65),d()),n&2){let e,o=t.$implicit;Se("padding-left",o.indent>2?(o.indent-2)*12:0,"px"),R("ngClass",o.type),g(),b((e=o.type)==="checked"?1:e==="progress"?2:e==="unchecked"?3:e==="list-item"?4:-1),g(4),b(o.type!=="empty"?5:-1)}}function U3(n,t){if(n&1&&(l(0,"div",57),G(1,H3,6,5,"div",59,De().trackMarkdownLine,!0),d()),n&2){let e=m().$implicit;g(),q(e.subSteps)}}function G3(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function q3(n,t){if(n&1&&(l(0,"div",67)(1,"div",68)(2,"span",69),u(3),d()(),l(4,"div",70),G(5,G3,2,5,"span",56,Ie),d()()),n&2){let e=t.$implicit;Se("margin-left",e.indent>2?(e.indent-2)*12:0,"px"),R("ngClass",e.type),g(2),w("assert",e.checkKind==="assert"),g(),We("",e.checkKind||"verify","",e.atEnd?" @end":""),g(2),q(e.segments)}}function W3(n,t){if(n&1&&(l(0,"div",58),G(1,q3,7,7,"div",66,De().trackMarkdownLine,!0),d()),n&2){let e=m().$implicit;g(),q(e.checks)}}function K3(n,t){if(n&1&&(l(0,"div",50)(1,"div",51),M(2,A3,2,0,"span",52)(3,N3,2,0,"span",53)(4,R3,2,0,"span",54),l(5,"div",55),G(6,F3,2,5,"span",56,Ie),d()(),M(8,U3,3,0,"div",57),M(9,W3,3,0,"div",58),d()),n&2){let e,o=t.$implicit;R("ngClass",o.type),g(2),b((e=o.type)==="checked"?2:e==="progress"?3:e==="unchecked"?4:-1),g(4),q(o.segments),g(2),b(o.subSteps.length>0?8:-1),g(),b(o.checks.length>0?9:-1)}}function Y3(n,t){if(n&1&&(l(0,"div",48),G(1,K3,10,4,"div",50,De().trackMilestone,!0),d()),n&2){let e=m(3);g(),q(e.parsedNote().milestones)}}function Z3(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function Q3(n,t){if(n&1&&(l(0,"div",73)(1,"div",68)(2,"span",69),u(3),d()(),l(4,"div",70),G(5,Z3,2,5,"span",56,Ie),d()()),n&2){let e=m().$implicit;Se("margin-left",e.indent*12,"px"),R("ngClass",e.type),g(2),w("assert",e.checkKind==="assert"),g(),We("",e.checkKind||"verify","",e.atEnd?" @end":""),g(2),q(e.segments)}}function J3(n,t){n&1&&(l(0,"span",61),u(1,"check_box"),d())}function X3(n,t){n&1&&(l(0,"span",62),u(1,"indeterminate_check_box"),d())}function e4(n,t){n&1&&(l(0,"span",63),u(1,"check_box_outline_blank"),d())}function t4(n,t){n&1&&(l(0,"span",64),u(1,"\u2022"),d())}function n4(n,t){if(n&1&&(l(0,"span"),u(1),d()),n&2){let e=t.$implicit;w("bold-segment",e.bold)("code-segment",e.code),g(),O(e.text)}}function o4(n,t){if(n&1&&(l(0,"span",65),G(1,n4,2,5,"span",56,Ie),d()),n&2){let e=m(2).$implicit;g(),q(e.segments)}}function i4(n,t){if(n&1&&(l(0,"div",74),M(1,J3,2,0,"span",61)(2,X3,2,0,"span",62)(3,e4,2,0,"span",63)(4,t4,2,0,"span",64),M(5,o4,3,0,"span",65),d()),n&2){let e,o=m().$implicit;Se("margin-left",o.indent*12,"px"),R("ngClass",o.type),g(),b((e=o.type)==="checked"?1:e==="progress"?2:e==="unchecked"?3:e==="list-item"?4:-1),g(4),b(o.type!=="empty"?5:-1)}}function r4(n,t){if(n&1&&M(0,Q3,7,7,"div",71)(1,i4,6,5,"div",72),n&2){let e=t.$implicit;b(e.type==="verify"||e.type==="finding"?0:1)}}function a4(n,t){if(n&1&&(l(0,"div",49),G(1,r4,2,1,null,null,De().trackMarkdownLine,!0),d()),n&2){let e=m(3);g(),q(e.parsedNote().otherLines)}}function s4(n,t){if(n&1&&(l(0,"div",39),M(1,T3,2,1,"h2",47),M(2,Y3,3,0,"div",48),M(3,a4,3,0,"div",49),d()),n&2){let e=m(2);g(),b(e.parsedNote().title?1:-1),g(),b(e.parsedNote().milestones.length>0?2:-1),g(),b(e.parsedNote().otherLines.length>0?3:-1)}}function c4(n,t){if(n&1&&(l(0,"div",9),M(1,D3,4,0,"div",37),M(2,I3,8,0,"div",38),M(3,s4,4,3,"div",39),d()),n&2){let e=m();g(),b(e.noteKeys().length>1?1:-1),g(),b(e.noteKeys().length===0?2:-1),g(),b(e.noteKeys().length>0?3:-1)}}var qr=class n{agentService=D(It);taskInput="";isSubmitting=x(!1);errorMessage=x(null);deviceSerialCache=new WeakMap;activeQueue=I(()=>this.agentService.sessions().filter(e=>{let o=this.getTaskStatus(e);return o==="running"||o==="paused"||o==="pending"}).sort((e,o)=>{let i=this.getTaskStatus(e),r=this.getTaskStatus(o),a=i==="running"||i==="paused",s=r==="running"||r==="paused";return a&&!s?-1:!a&&s?1:(e.start_time||0)-(o.start_time||0)}));historyTasks=I(()=>this.agentService.sessions().filter(t=>{let e=this.getTaskStatus(t);return e==="completed"||e==="failed"||e==="cancelled"}));submitTask(){let t=this.taskInput.trim();t&&(this.isSubmitting.set(!0),this.errorMessage.set(null),this.agentService.runTask(t).subscribe({next:e=>{this.taskInput="",this.isSubmitting.set(!1),this.agentService.fetchStatus()},error:e=>{console.error("Failed to submit task:",e),this.isSubmitting.set(!1),this.errorMessage.set(e.error?.detail||"The runner is busy. Please wait for the current task to finish."),setTimeout(()=>{this.errorMessage.set(null)},5e3)}}))}stopTask(t,e){e.stopPropagation(),this.isSubmitting.set(!0),this.errorMessage.set(null),this.agentService.stopTask(t,!1),setTimeout(()=>{this.isSubmitting.set(!1)},400)}stopTasks(t=!1){this.isSubmitting.set(!0),this.errorMessage.set(null),this.agentService.stopTask(t),setTimeout(()=>{this.isSubmitting.set(!1)},400)}clearHistory(){confirm("Are you sure you want to clear all tasks and history? This cannot be undone.")&&(this.isSubmitting.set(!0),this.errorMessage.set(null),this.agentService.clearAllHistory().subscribe({next:()=>{this.isSubmitting.set(!1)},error:t=>{console.error("Failed to clear history:",t),this.isSubmitting.set(!1),this.errorMessage.set(t.error?.detail||"Failed to clear history.")}}))}deleteTask(t,e){e.stopPropagation(),confirm("Are you sure you want to delete this task? This cannot be undone.")&&(this.isSubmitting.set(!0),this.errorMessage.set(null),this.agentService.deleteSession(t).subscribe({next:()=>{this.isSubmitting.set(!1)},error:o=>{console.error(`Failed to delete task ${t}:`,o),this.isSubmitting.set(!1),this.errorMessage.set(o.error?.detail||"Failed to delete task.")}}))}getTaskStatus(t){if(t.status){let e=t.status.toLowerCase();if(e==="completed"||e==="success"||e==="failed"||e==="cancelled")return e==="success"?"completed":e;if(e==="running"||e==="paused"||e==="pending")return e}return t.session_id===this.agentService.runningSessionId()&&(this.agentService.agentStatus()==="running"||this.agentService.agentStatus()==="paused")?this.agentService.agentStatus():"completed"}getDeviceSerial(t){if(this.deviceSerialCache.has(t))return this.deviceSerialCache.get(t)??null;let e=null,o=t.device_serial||t.device_id;if(o&&o!=="pending"&&o!=="null"&&o!=="undefined")e=o;else if(t.device_info)try{let i=typeof t.device_info=="string"?JSON.parse(t.device_info):t.device_info,r=i?.device_id||i?.device_serial;r&&r!=="pending"&&r!=="null"&&r!=="undefined"&&(e=r)}catch(i){}return this.deviceSerialCache.set(t,e),e}selectTask(t){this.agentService.selectSession(t,!0)}currentNoteContent=I(()=>{let t=this.agentService.currentNotes(),e=this.agentService.selectedNoteKey();return t[e]||""});noteKeys=I(()=>Object.keys(this.agentService.currentNotes()).filter(t=>t.toLowerCase().endsWith(".md")));parsedNote=I(()=>this.getParsedNote(this.currentNoteContent()));getParsedNote(t){return ks(t)}getParsedNoteLines(t){return Ss(t)}selectNote(t){this.agentService.selectedNoteKey.set(t)}trackSession(t,e){return e.session_id}trackNoteKey(t,e){return e}trackMilestone(t,e){return e.index}trackMarkdownLine(t,e){return t}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=Ge({type:n,selectors:[["app-chat-interface"]],decls:18,vars:7,consts:[[1,"chat-interface-container"],[1,"chat-header"],[1,"tab-selector-bar"],[1,"tab-selector-btn",3,"click"],[1,"material-symbols-outlined","tab-icon"],[1,"tab-text"],[1,"header-right"],["title","Clear all tasks and history","aria-label","Clear all tasks and history",1,"btn-clear-history",3,"disabled"],[1,"chat-messages"],[1,"notes-tab-content"],["title","Clear all tasks and history","aria-label","Clear all tasks and history",1,"btn-clear-history",3,"click","disabled"],[1,"material-symbols-outlined"],[1,"queue-section-header"],[1,"material-symbols-outlined","section-icon"],[1,"empty-section-placeholder"],[1,"task-card",3,"selected","running"],["open","",1,"history-section"],[1,"history-summary"],[1,"history-list-wrapper"],[1,"task-card",3,"click"],[1,"task-card-header"],[1,"task-badge",3,"ngClass"],[1,"status-dot"],[1,"task-card-header-actions"],[1,"task-device",3,"title"],[1,"task-time-divider"],[1,"task-time"],["type","button","title","Stop this task","aria-label","Stop this task",1,"btn-stop-card"],["type","button","title","Delete this task","aria-label","Delete this task",1,"btn-delete-card",3,"disabled"],[1,"task-goal",3,"title"],[1,"task-card-footer"],[1,"task-id",3,"title"],[1,"task-date"],[1,"material-symbols-outlined","device-icon"],[1,"device-name"],["type","button","title","Stop this task","aria-label","Stop this task",1,"btn-stop-card",3,"click"],["type","button","title","Delete this task","aria-label","Delete this task",1,"btn-delete-card",3,"click","disabled"],[1,"notes-selector-container"],[1,"empty-notes-container"],[1,"note-viewer-cards"],[1,"notes-selector-list"],[1,"note-selector-pill",3,"active"],[1,"note-selector-pill",3,"click"],[1,"material-symbols-outlined","pill-icon"],[1,"empty-notes-icon"],[1,"empty-notes-title"],[1,"empty-notes-subtitle"],[1,"note-title"],[1,"milestones-container"],[1,"other-lines-container"],[1,"milestone-block",3,"ngClass"],[1,"milestone-title-row"],[1,"material-symbols-outlined","milestone-status-icon","checked"],[1,"material-symbols-outlined","milestone-status-icon","progress"],[1,"material-symbols-outlined","milestone-status-icon","unchecked"],[1,"milestone-text"],[3,"bold-segment","code-segment"],[1,"milestone-substeps"],[1,"milestone-checks-container"],[1,"substep-row",3,"ngClass","padding-left"],[1,"substep-row",3,"ngClass"],[1,"material-symbols-outlined","check-icon","checked"],[1,"material-symbols-outlined","check-icon","progress"],[1,"material-symbols-outlined","check-icon","unchecked"],[1,"bullet"],[1,"line-text"],[1,"verification-card",3,"ngClass","margin-left"],[1,"verification-card",3,"ngClass"],[1,"card-header"],[1,"card-tag"],[1,"card-body"],[1,"verification-card","standalone",3,"ngClass","margin-left"],[1,"md-line",3,"ngClass","margin-left"],[1,"verification-card","standalone",3,"ngClass"],[1,"md-line",3,"ngClass"]],template:function(e,o){e&1&&(l(0,"div",0)(1,"header",1)(2,"div",2)(3,"button",3),k("click",function(){return o.agentService.activeTab.set("tasks")}),l(4,"span",4),u(5,"list_alt"),d(),l(6,"span",5),u(7,"Task Queue"),d()(),l(8,"button",3),k("click",function(){return o.agentService.activeTab.set("notes")}),l(9,"span",4),u(10,"description"),d(),l(11,"span",5),u(12,"Notes & Plans"),d()()(),l(13,"div",6),M(14,f3,3,1,"button",7),d()(),l(15,"main",8),M(16,k3,16,4),M(17,c4,4,3,"div",9),d()()),e&2&&(g(3),w("active",o.agentService.activeTab()==="tasks"),g(5),w("active",o.agentService.activeTab()==="notes"),g(6),b(o.agentService.sessions().length>0&&o.agentService.activeTab()==="tasks"?14:-1),g(2),b(o.agentService.activeTab()==="tasks"?16:-1),g(),b(o.agentService.activeTab()==="notes"?17:-1))},dependencies:[No,ki,Qt,Ya,Ei],styles:['[_nghost-%COMP%]{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.chat-interface-container[_ngcontent-%COMP%]{container-type:inline-size;display:flex;flex-direction:column;height:100%;background:#fff;box-sizing:border-box}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:16px;height:60px;padding:0 20px;border-bottom:1px solid rgba(0,0,0,.08);background:#fff;box-sizing:border-box}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%]{display:flex;height:36px;box-sizing:border-box;background:#f1f5f9b8;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(226,232,240,.85);border-radius:18px;padding:3px;gap:3px;align-items:center;flex-shrink:0;box-shadow:0 2px 8px -1px #0f172a0a,inset 0 1px 1px #fffc}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%] .tab-selector-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:30px;padding:0 14px;box-sizing:border-box;border:none;background:transparent;border-radius:15px;font-size:13px;font-weight:600;color:#64748b;cursor:pointer;line-height:1;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%] .tab-selector-btn[_ngcontent-%COMP%] .tab-icon[_ngcontent-%COMP%]{font-size:16px;width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%] .tab-selector-btn[_ngcontent-%COMP%]:hover:not(.active){color:#0f172a;background:#ffffffb3}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%] .tab-selector-btn.active[_ngcontent-%COMP%]{background:#fff;color:#2563eb;font-weight:700;box-shadow:0 2px 6px #0000000f,0 1px 2px #00000005}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:flex-end;flex:1 1 0;min-width:max-content;flex-shrink:0}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-resume-task[_ngcontent-%COMP%]{padding:6px 14px;background:linear-gradient(135deg,#2563ebeb,#1a73e8d9);backdrop-filter:blur(14px) saturate(180%);-webkit-backdrop-filter:blur(14px) saturate(180%);border:1px solid rgba(255,255,255,.35);border-radius:16px;font-size:13.5px;font-weight:600;color:#fff;cursor:pointer;display:flex;align-items:center;gap:5px;transition:all .2s cubic-bezier(.4,0,.2,1);margin-right:8px;box-shadow:0 4px 14px #2563eb4d,inset 0 1px 1px #ffffff73}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-resume-task[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:16px;color:inherit}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-resume-task[_ngcontent-%COMP%]:hover{background:linear-gradient(135deg,#2563eb,#1a73e8f2);border-color:#fff9;box-shadow:0 6px 18px #2563eb6b,inset 0 1px 1px #fff9;transform:translateY(-.5px)}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-resume-task[_ngcontent-%COMP%]:active{transform:scale(.97)}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-clear-history[_ngcontent-%COMP%]{width:32px;height:32px;padding:0;box-sizing:border-box;background:#ffffffb8;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(203,213,225,.85);border-radius:50%;color:#64748b;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px -1px #0f172a0a,inset 0 1px 1px #ffffffe6;transition:all .2s cubic-bezier(.4,0,.2,1)}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-clear-history[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:16px;color:inherit}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-clear-history[_ngcontent-%COMP%]:hover:not(:disabled){background:#fef2f2;color:#ef4444;border-color:#fca5a5;box-shadow:0 3px 10px #ef444426;transform:scale(1.05)}.chat-interface-container[_ngcontent-%COMP%] .chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-clear-history[_ngcontent-%COMP%]:disabled{opacity:.5;cursor:not-allowed}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%]{flex:1;overflow-y:auto;padding:12px 12px 100px;display:flex;flex-direction:column;gap:8px;background:#fff}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%]::-webkit-scrollbar{width:5px}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%]::-webkit-scrollbar-thumb{background:#94a3b84d;border-radius:4px}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .queue-section-header[_ngcontent-%COMP%]{font-size:11.5px;font-weight:700;color:#475569;margin:6px 0 2px;display:flex;align-items:center;gap:6px}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .queue-section-header[_ngcontent-%COMP%] .section-icon[_ngcontent-%COMP%]{font-size:14px;color:inherit}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .empty-section-placeholder[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:center;background:#f1f5f9;border:1px dashed #cbd5e1;border-radius:8px;padding:12px;color:#64748b;font-size:12px;text-align:center}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .history-section[_ngcontent-%COMP%]{margin-top:12px;border-top:1px solid rgba(226,232,240,.8);padding-top:12px}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .history-section[open][_ngcontent-%COMP%] .history-summary[_ngcontent-%COMP%]{margin-bottom:8px}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .history-section[_ngcontent-%COMP%] .history-summary[_ngcontent-%COMP%]{font-size:11.5px;font-weight:700;color:#475569;cursor:pointer;outline:none;-webkit-user-select:none;user-select:none;list-style:none;display:flex;align-items:center;gap:6px;padding:4px 6px;margin-left:-6px;border-radius:6px;transition:background .2s}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .history-section[_ngcontent-%COMP%] .history-summary[_ngcontent-%COMP%] .section-icon[_ngcontent-%COMP%]{font-size:14px;color:inherit}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .history-section[_ngcontent-%COMP%] .history-summary[_ngcontent-%COMP%]::-webkit-details-marker{display:none}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .history-section[_ngcontent-%COMP%] .history-summary[_ngcontent-%COMP%]:hover{background:#f1f5f9;color:#1e293b}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .history-section[_ngcontent-%COMP%] .history-list-wrapper[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%]{background:#fff;border:1px solid rgba(226,232,240,.8);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:6px;cursor:pointer;position:relative;transition:all .2s cubic-bezier(.4,0,.2,1);box-shadow:0 1px 3px #00000003}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%]:hover{transform:translateY(-1px);border-color:#cbd5e1;box-shadow:0 3px 8px #94a3b814}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%]:hover .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%]:has(.btn-delete-card) .task-time[_ngcontent-%COMP%], .chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%]:hover .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%]:has(.btn-delete-card) .task-time-divider[_ngcontent-%COMP%], .chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%]:hover .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%]:has(.btn-stop-card) .task-time[_ngcontent-%COMP%], .chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%]:hover .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%]:has(.btn-stop-card) .task-time-divider[_ngcontent-%COMP%]{opacity:0}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%]:hover .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-delete-card[_ngcontent-%COMP%], .chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%]:hover .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-stop-card[_ngcontent-%COMP%]{opacity:1;pointer-events:auto}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card.selected[_ngcontent-%COMP%]{border-color:#3b82f6;box-shadow:0 0 0 1px #3b82f6,0 4px 12px #3b82f614;background:#fff}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card.running[_ngcontent-%COMP%]{border-color:#10b981;box-shadow:0 0 0 1px #10b981,0 4px 12px #10b98114}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card.running.selected[_ngcontent-%COMP%]{border-color:#3b82f6;box-shadow:0 0 0 1px #3b82f6,0 4px 12px #3b82f614}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;gap:8px;min-width:0}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge[_ngcontent-%COMP%]{flex-shrink:0;display:inline-flex;align-items:center;font-size:10.5px;font-weight:700;padding:2px 5px;border-radius:4px;letter-spacing:.05em;border:1px solid #e2e8f0;background:#fafafa;color:#64748b}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge[_ngcontent-%COMP%]:before{content:"";width:4px;height:4px;border-radius:50%;display:inline-block;margin-right:4px}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.running[_ngcontent-%COMP%]{background:#fafafa;color:#1f1f1f;border-color:#1f1f1f}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.running[_ngcontent-%COMP%]:before{background-color:#1f1f1f;animation:_ngcontent-%COMP%_pulse-black-dot-small 1.5s infinite ease-in-out}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.paused[_ngcontent-%COMP%]{background:#fff7ed;color:#c2410c;border-color:#fdba74}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.paused[_ngcontent-%COMP%]:before{background-color:#f97316}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.completed[_ngcontent-%COMP%]{background:#fafafa;color:#1f1f1f;border-color:#e2e8f0}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.completed[_ngcontent-%COMP%]:before{background-color:#1f1f1f}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.pending[_ngcontent-%COMP%]{background:#fafafa;color:#64748b;border-color:#e2e8f0}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.pending[_ngcontent-%COMP%]:before{background-color:#94a3b8}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.failed[_ngcontent-%COMP%]{background:#fafafa;color:#ef4444;border-color:#fee2e2}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.failed[_ngcontent-%COMP%]:before{background-color:#ef4444}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.cancelled[_ngcontent-%COMP%]{background:#fafafa;color:#d97706;border-color:#fef3c7}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge.cancelled[_ngcontent-%COMP%]:before{background-color:#f59e0b}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-badge[_ngcontent-%COMP%] .status-dot[_ngcontent-%COMP%]{display:none}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%]{display:flex;align-items:center;gap:4px;position:relative;min-width:0;flex-shrink:1;justify-content:flex-end}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .task-device[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:2.5px;min-width:0;flex-shrink:1;font-size:11px;color:#94a3b8;line-height:1;cursor:default;transition:color .15s ease,opacity .15s ease}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .task-device[_ngcontent-%COMP%] .device-icon[_ngcontent-%COMP%]{font-size:12.5px;width:12.5px;height:12.5px;line-height:12.5px;color:#94a3b8;opacity:.75;flex-shrink:0}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .task-device[_ngcontent-%COMP%] .device-name[_ngcontent-%COMP%]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:inherit;letter-spacing:-.15px}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .task-device[_ngcontent-%COMP%]:hover{color:#64748b}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .task-device[_ngcontent-%COMP%]:hover .device-icon[_ngcontent-%COMP%]{color:#64748b;opacity:1}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .task-time-divider[_ngcontent-%COMP%]{font-size:10px;color:#cbd5e1;line-height:1;-webkit-user-select:none;user-select:none;flex-shrink:0;transition:opacity .15s ease}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .task-time[_ngcontent-%COMP%]{font-size:11.5px;color:#94a3b8;white-space:nowrap;flex-shrink:0;line-height:1;transition:opacity .15s ease}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-delete-card[_ngcontent-%COMP%]{position:absolute;right:0;top:50%;transform:translateY(-50%);width:20px;height:20px;padding:0;border:none;background:transparent;border-radius:4px;color:#94a3b8;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:all .15s ease}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-delete-card[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:14px;line-height:1}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-delete-card[_ngcontent-%COMP%]:hover:not(:disabled){color:#ef4444;background:#fee2e2}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-delete-card[_ngcontent-%COMP%]:disabled{opacity:.3;cursor:not-allowed}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-stop-card[_ngcontent-%COMP%]{position:absolute;right:0;top:50%;transform:translateY(-50%);width:20px;height:20px;padding:0;border:none;background:transparent;border-radius:4px;color:#ef4444;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:all .15s ease}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-stop-card[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px;line-height:1}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-stop-card[_ngcontent-%COMP%]:hover:not(:disabled){color:#dc2626;background:#fee2e2;transform:translateY(-50%) scale(1.1)}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-header[_ngcontent-%COMP%] .task-card-header-actions[_ngcontent-%COMP%] .btn-stop-card[_ngcontent-%COMP%]:disabled{opacity:.3;cursor:not-allowed}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-goal[_ngcontent-%COMP%]{font-size:12.5px;font-weight:500;color:#1e293b;line-height:1.4;word-break:break-word;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-footer[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;gap:12px;border-top:1px solid rgba(241,245,249,.8);padding-top:6px;font-size:11.5px;color:#94a3b8}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-footer[_ngcontent-%COMP%] .task-id[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:11px;color:#94a3b8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex:1;transition:color .15s ease}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-footer[_ngcontent-%COMP%] .task-id[_ngcontent-%COMP%]:hover{color:#475569}.chat-interface-container[_ngcontent-%COMP%] .chat-messages[_ngcontent-%COMP%] .task-card[_ngcontent-%COMP%] .task-card-footer[_ngcontent-%COMP%] .task-date[_ngcontent-%COMP%]{flex-shrink:0;font-size:11px;color:#94a3b8}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:16px;height:100%}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:8px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .selector-title[_ngcontent-%COMP%]{font-size:11px;font-weight:700;color:#94a3b8;letter-spacing:.05em}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%]{display:flex;flex-wrap:wrap;gap:8px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%] .note-selector-pill[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid #e2e8f0;background:#fff;border-radius:20px;font-size:13px;font-weight:500;color:#475569;cursor:pointer;transition:all .15s ease}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%] .note-selector-pill[_ngcontent-%COMP%] .pill-icon[_ngcontent-%COMP%]{font-size:15px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%] .note-selector-pill[_ngcontent-%COMP%]:hover{background:#f8fafc;border-color:#cbd5e1;color:#1e293b}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .notes-selector-container[_ngcontent-%COMP%] .notes-selector-list[_ngcontent-%COMP%] .note-selector-pill.active[_ngcontent-%COMP%]{background:#eff6ff;border-color:#bfdbfe;color:#1d4ed8;font-weight:600}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .empty-notes-container[_ngcontent-%COMP%]{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;margin:auto 0;text-align:center;-webkit-user-select:none;user-select:none;animation:_ngcontent-%COMP%_fadeIn .25s cubic-bezier(.16,1,.3,1)}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .empty-notes-container[_ngcontent-%COMP%] .empty-notes-icon[_ngcontent-%COMP%]{width:52px;height:52px;border-radius:50%;background:#f1f5f9;border:1px solid #e2e8f0;display:flex;align-items:center;justify-content:center;margin-bottom:14px;box-shadow:0 1px 3px #00000005}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .empty-notes-container[_ngcontent-%COMP%] .empty-notes-icon[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:26px;color:#94a3b8}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .empty-notes-container[_ngcontent-%COMP%] .empty-notes-title[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:14px;font-weight:600;color:#1e293b;margin:0 0 6px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .empty-notes-container[_ngcontent-%COMP%] .empty-notes-subtitle[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:12.5px;color:#64748b;line-height:1.5;max-width:240px;margin:0}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%]{display:flex;flex-direction:column;flex:1;padding:16px 8px;overflow-y:auto}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .note-title[_ngcontent-%COMP%]{font-size:14px;font-weight:700;color:#1f1f1f;margin-top:0;margin-bottom:20px;font-family:Google Sans,Google Sans Text,Inter,sans-serif}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .code-segment[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;background-color:#f1f3f4;color:#1967d2;padding:2px 6px;border-radius:4px;font-size:14px;margin:0 2px;word-break:break-all;font-weight:400}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .checked[_ngcontent-%COMP%] .code-segment[_ngcontent-%COMP%]{color:#a1a1aa;background-color:#f8f9fa}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestones-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:6px;margin-bottom:24px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%]{display:flex;flex-direction:column}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block.checked[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon.checked[_ngcontent-%COMP%]{opacity:.7}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block.checked[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-text[_ngcontent-%COMP%]{color:#a1a1aa}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:10px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon[_ngcontent-%COMP%]{font-size:20px;-webkit-user-select:none;user-select:none;margin-top:3px;font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon.checked[_ngcontent-%COMP%], .chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon.progress[_ngcontent-%COMP%]{color:#1a73e8}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-status-icon.unchecked[_ngcontent-%COMP%]{color:#cbd5e1}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-text[_ngcontent-%COMP%]{font-family:Google Sans,Google Sans Text,Inter,sans-serif;color:#1f1f1f;font-size:14px;line-height:1.8;font-weight:400;word-break:break-word;flex:1}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-text[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:inherit}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-title-row[_ngcontent-%COMP%] .milestone-text[_ngcontent-%COMP%] .bold-segment[_ngcontent-%COMP%]{font-weight:inherit;color:inherit}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%]{margin-top:8px;display:flex;flex-direction:column;gap:10px;padding-left:28px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:10px;font-family:Google Sans,Google Sans Text,Inter,sans-serif;color:#1f1f1f;font-size:14px;line-height:1.8}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:inherit}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.checked[_ngcontent-%COMP%]{color:#a1a1aa}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row.checked[_ngcontent-%COMP%] .check-icon.checked[_ngcontent-%COMP%]{opacity:.7}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%]{font-size:20px;-webkit-user-select:none;user-select:none;margin-top:3px;font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .check-icon.checked[_ngcontent-%COMP%], .chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .check-icon.progress[_ngcontent-%COMP%]{color:#1a73e8}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .check-icon.unchecked[_ngcontent-%COMP%]{color:#cbd5e1}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .bullet[_ngcontent-%COMP%]{color:#9ca3af;font-weight:700;-webkit-user-select:none;user-select:none;padding-left:2px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%]{word-break:break-word;color:inherit}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:inherit}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-substeps[_ngcontent-%COMP%] .substep-row[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%] .bold-segment[_ngcontent-%COMP%]{font-weight:inherit;color:inherit}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .milestone-block[_ngcontent-%COMP%] .milestone-checks-container[_ngcontent-%COMP%]{margin-top:8px;padding-left:28px;display:flex;flex-direction:column;gap:8px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%]{background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;padding:8px 12px;display:flex;flex-direction:column;gap:4px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card.standalone[_ngcontent-%COMP%]{margin-top:8px;margin-bottom:8px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%]{display:flex;align-items:center}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .card-tag[_ngcontent-%COMP%]{font-family:Google Sans Text,Inter,-apple-system,sans-serif;font-size:10.5px;font-weight:600;line-height:1;letter-spacing:.6px;text-transform:uppercase;color:#64748b}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .card-tag.assert[_ngcontent-%COMP%]{color:#0284c7}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%]{font-family:inherit;font-size:13.5px;line-height:1.6;color:#334155;word-break:break-word}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%] .bold-segment[_ngcontent-%COMP%]{font-weight:600;color:#1e293b}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%] .code-segment[_ngcontent-%COMP%]{font-family:Fira Code,Roboto Mono,Consolas,monospace;font-size:12px;background:#f1f5f9;color:#0f172a;padding:1.5px 6px;border-radius:4px;border:1px solid #e2e8f0}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card.finding[_ngcontent-%COMP%]{background:#fffbeb;border-color:#fef3c7}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card.finding[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .card-tag[_ngcontent-%COMP%]{color:#b45309}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .verification-card.finding[_ngcontent-%COMP%] .card-body[_ngcontent-%COMP%]{color:#92400e}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;padding:8px 4px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:10px;margin-bottom:14px;min-height:22px;font-family:Google Sans,Google Sans Text,Inter,sans-serif;color:#1f1f1f;font-size:14px;line-height:1.6}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line.empty[_ngcontent-%COMP%]{height:12px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line.h1[_ngcontent-%COMP%]{font-size:14px;font-weight:700;margin-top:24px;margin-bottom:12px;border-bottom:1px solid #e5e7eb;padding-bottom:6px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line.h2[_ngcontent-%COMP%]{font-size:14px;font-weight:700;margin-top:20px;margin-bottom:10px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line.h3[_ngcontent-%COMP%]{font-size:14px;font-weight:700;margin-top:14px;margin-bottom:8px}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line.checked[_ngcontent-%COMP%]{color:#a1a1aa}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line.checked[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%]{color:#1a73e8;opacity:.7}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line.progress[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%]{color:#1a73e8}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line.unchecked[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%]{color:#cbd5e1}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line.list-item[_ngcontent-%COMP%] .bullet[_ngcontent-%COMP%]{color:#9ca3af;font-weight:700;-webkit-user-select:none;user-select:none}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:inherit}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%]{font-size:20px;-webkit-user-select:none;user-select:none;margin-top:1px;font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%]{word-break:break-word;color:inherit}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:inherit}.chat-interface-container[_ngcontent-%COMP%] .notes-tab-content[_ngcontent-%COMP%] .note-viewer-cards[_ngcontent-%COMP%] .other-lines-container[_ngcontent-%COMP%] .md-line[_ngcontent-%COMP%] .line-text[_ngcontent-%COMP%] .bold-segment[_ngcontent-%COMP%]{font-weight:inherit;color:inherit}@keyframes _ngcontent-%COMP%_pulse{0%{transform:scale(.85);opacity:.6}50%{transform:scale(1.15);opacity:1}to{transform:scale(.85);opacity:.6}}@keyframes _ngcontent-%COMP%_bannerSlideIn{0%{transform:translateY(5px);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes _ngcontent-%COMP%_fadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes _ngcontent-%COMP%_pulse-black-dot-small{0%{box-shadow:0 0 #0006}70%{box-shadow:0 0 0 4px #0000}to{box-shadow:0 0 #0000}}@keyframes _ngcontent-%COMP%_pulse-blue-dot{0%{box-shadow:0 0 #2563eb66}70%{box-shadow:0 0 0 5px #2563eb00}to{box-shadow:0 0 #2563eb00}}@container (max-width: 380px){.chat-header[_ngcontent-%COMP%]{padding:0 8px;gap:6px;height:36px}.chat-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%]{display:none}.chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%]{padding:2px;gap:1px}.chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%] .tab-selector-btn[_ngcontent-%COMP%]{padding:5px 8px;font-size:12px;gap:4px}.chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%] .tab-selector-btn[_ngcontent-%COMP%] .tab-icon[_ngcontent-%COMP%]{font-size:14px}.chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-clear-history[_ngcontent-%COMP%]{height:24px;width:30px;padding:0;font-size:12px;gap:0;border-radius:16px;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center}.chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-clear-history[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:14px;line-height:1}.chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-clear-history[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%]{display:none}}@container (max-width: 340px){.chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%] .tab-selector-btn[_ngcontent-%COMP%]{padding:5px 6px}.chat-header[_ngcontent-%COMP%] .tab-selector-bar[_ngcontent-%COMP%] .tab-selector-btn[_ngcontent-%COMP%] .tab-text[_ngcontent-%COMP%]{display:none}.chat-header[_ngcontent-%COMP%] .header-right[_ngcontent-%COMP%] .btn-clear-history[_ngcontent-%COMP%]{width:26px}}']})};var l4=["videoRef"],d4=["stepImgRef"],u4=["stepOverlayRef"];function g4(n,t){if(n&1){let e=L();j(0,"div",5),ue("click",function(){v(e);let i=m();return y(i.isTheaterMode.set(!1))}),H()}}function p4(n,t){if(n&1){let e=L();j(0,"div",12)(1,"button",18),ue("click",function(){v(e);let i=m(2);return y(i.agentService.setPlayerMode("video"))}),j(2,"span",19),u(3,"videocam"),H(),j(4,"span"),u(5,"Video"),H()(),j(6,"button",20),ue("click",function(){v(e);let i=m(2);return y(i.agentService.setPlayerMode("steps"))}),j(7,"span",19),u(8,"slideshow"),H(),j(9,"span"),u(10,"Steps"),H()()()}if(n&2){let e=m(2);g(),w("active",e.agentService.playerMode()==="video"),g(5),w("active",e.agentService.playerMode()==="steps")}}function f4(n,t){if(n&1){let e=L();j(0,"button",21),ue("click",function(){v(e);let i=m(2);return y(i.toggleTheater())}),j(1,"span",14),u(2),H()()}if(n&2){let e=m(2);je("title",e.isTheaterMode()?"Exit Theater":"Theater Mode"),g(2),O(e.isTheaterMode()?"close_fullscreen":"open_in_full")}}function m4(n,t){if(n&1){let e=L();j(0,"div",22)(1,"img",24),ue("error",function(){v(e);let i=m(4);return y(i.onLiveStreamError())}),H(),j(2,"div",25)(3,"div",26),yi(4,"span",27),j(5,"span"),u(6,"LIVE"),H()(),j(7,"button",28),ue("click",function(){v(e);let i=m(4);return y(i.retryLiveStream())}),j(8,"span",14),u(9,"refresh"),H()()()()}if(n&2){let e=m(4);g(),je("src",e.liveStreamUrl(),kt)}}function _4(n,t){if(n&1){let e=L();j(0,"div",23)(1,"div",29)(2,"span",30),u(3,"phonelink_off"),H()(),j(4,"h4",31),u(5,"Device Stream Connecting"),H(),j(6,"p",32),u(7,"Waiting for ADB device screen stream..."),H(),j(8,"button",33),ue("click",function(){v(e);let i=m(4);return y(i.retryLiveStream())}),j(9,"span",14),u(10,"refresh"),H(),u(11," Reconnect "),H()()}}function h4(n,t){if(n&1&&(M(0,m4,10,1,"div",22),M(1,_4,12,0,"div",23)),n&2){let e=m(3);b(e.liveStreamError()?-1:0),g(),b(e.liveStreamError()?1:-1)}}function C4(n,t){if(n&1&&(j(0,"div",34)(1,"span",36),u(2,"progress_activity"),H(),j(3,"span"),u(4),H()()),n&2){let e=m(4);g(4),O(e.agentService.recordingPlaybackMessage()||"Preparing screen recording...")}}function M4(n,t){n&1&&(j(0,"div",37)(1,"span",60),u(2,"info"),H(),j(3,"span"),u(4,"Screen recording unavailable. Replaying step-by-step screenshots."),H()())}function b4(n,t){n&1&&(j(0,"div",39)(1,"span",36),u(2,"progress_activity"),H(),j(3,"span"),u(4,"Loading screenshot..."),H()())}function P4(n,t){n&1&&(j(0,"div",40)(1,"span",61),u(2,"broken_image"),H(),j(3,"span"),u(4,"Screenshot preview unavailable for this step"),H()())}function O4(n,t){if(n&1){let e=L();j(0,"div",41)(1,"img",62,0),ue("load",function(){v(e);let i=m(5);return y(i.onStepImageLoad())})("error",function(){v(e);let i=m(5);return y(i.onStepImageError())})("click",function(){v(e);let i=m(5);return y(i.openImageInNewTab())}),H(),yi(3,"div",63,1),H()}if(n&2){let e,o=m(5);g(),je("src",o.currentStepImageUrl(),kt)("alt",(e=o.currentStepFrame())==null?null:e.title),g(2),Se("display",o.viewMode()==="post"?"none":"block")}}function v4(n,t){if(n&1&&(j(0,"span",68),u(1),H()),n&2){let e=m(),o=m(5);g(),V(" ",o.getStepActionIcon(e.action)," ")}}function y4(n,t){if(n&1){let e=L();j(0,"div",70)(1,"button",72),ue("click",function(i){v(e);let r=m(6);return y(r.setStepViewMode("pre",i))}),u(2," Pre "),H(),j(3,"button",73),ue("click",function(i){v(e);let r=m(6);return y(r.setStepViewMode("post",i))}),u(4," Post "),H()()}if(n&2){let e=m(6);g(),w("active",e.viewMode()==="pre"),g(2),w("active",e.viewMode()==="post")}}function x4(n,t){if(n&1){let e=L();j(0,"div",64),ue("click",function(i){return i.stopPropagation()}),j(1,"div",65)(2,"span",66),u(3),H(),j(4,"span",67),M(5,v4,2,1,"span",68),u(6),H()(),j(7,"div",69),M(8,y4,5,4,"div",70),j(9,"button",71),ue("click",function(i){v(e);let r=m(5);return y(r.toggleCardPin(i))}),j(10,"span",14),u(11),H()()()()}if(n&2){let e=t,o=m(5);w("visible",o.isCardVisible()),g(3),V("Step ",e.stepNumber),g(),je("title",e.actionText||e.title),g(),b(e.action?5:-1),g(),V(" ",e.actionText||e.title," "),g(2),b(e.postImageUrl?8:-1),g(),w("pinned",o.isCardPinned()),je("title",o.isCardPinned()?"Unpin details card (auto-hide on mouse leave)":"Pin details card (keep always visible)"),g(2),O(o.isCardPinned()?"push_pin":"keep")}}function w4(n,t){if(n&1){let e=L();j(0,"span",75),ue("click",function(i){let r=v(e).$index;return m(6).seekStepFrame(r),y(i.stopPropagation())}),H()}if(n&2){let e=t.$implicit,o=t.$index,i=m(6);Se("left",o/(i.totalStepFrames()-1)*100,"%"),w("active",o===i.activeStepIndex())("passed",o1?11:-1),g(3),je("title",o.isStepPlaying()?"Pause":"Play Slideshow"),g(2),O(o.isStepPlaying()?"pause":"play_arrow"),g(),je("disabled",o.activeStepIndex()<=0),g(3),je("disabled",o.activeStepIndex()>=o.totalStepFrames()-1),g(7),We(" Step ",o.activeStepIndex()+1," / ",o.totalStepFrames()," "),g(2),je("title","Speed: "+o.playbackRate()+"x (Click to cycle)"),g(2),V("",o.playbackRate(),"x"),g(),w("active",o.isLooping()),je("title",o.isLooping()?"Loop enabled":"Enable loop")}}function E4(n,t){if(n&1){let e=L();j(0,"div",76)(1,"video",77,2),ue("loadedmetadata",function(){v(e);let i=m(5);return y(i.onLoadedMetadata())})("timeupdate",function(){v(e);let i=m(5);return y(i.onTimeUpdate())})("play",function(){v(e);let i=m(5);return y(i.onPlay())})("pause",function(){v(e);let i=m(5);return y(i.onPause())})("ended",function(){v(e);let i=m(5);return y(i.onEnded())})("error",function(){v(e);let i=m(5);return y(i.onError())})("click",function(){v(e);let i=m(5);return y(i.togglePlay())}),H()()}if(n&2){let e=m(5);g(),je("src",e.currentVideoUrl(),kt)}}function D4(n,t){if(n&1){let e=L();j(0,"div",43)(1,"div",44)(2,"input",45),ue("input",function(i){v(e);let r=m(5);return y(r.onScrub(i))}),H(),yi(3,"div",46),H(),j(4,"div",48)(5,"div",49)(6,"button",50),ue("click",function(){v(e);let i=m(5);return y(i.togglePlay())}),j(7,"span",14),u(8),H()(),j(9,"button",53),ue("click",function(){v(e);let i=m(5);return y(i.restart())}),j(10,"span",14),u(11,"replay"),H()(),j(12,"span",54),u(13),H()(),j(14,"div",55)(15,"button",56),ue("click",function(){v(e);let i=m(5);return y(i.cycleSpeed())}),j(16,"span",57),u(17),H()(),j(18,"button",58),ue("click",function(){v(e);let i=m(5);return y(i.toggleLoop())}),j(19,"span",14),u(20,"repeat"),H()(),j(21,"button",58),ue("click",function(){v(e);let i=m(5);return y(i.toggleMute())}),j(22,"span",14),u(23),H()(),j(24,"button",78),ue("click",function(){v(e);let i=m(5);return y(i.openInNewTab())}),j(25,"span",14),u(26,"open_in_new"),H()()()()()}if(n&2){let e=m(5);g(2),je("min",0)("max",e.duration()||100)("step",.1)("value",e.currentTime()),g(),Se("width",e.progressPercent(),"%"),g(3),je("title",e.isPlaying()?"Pause":"Play"),g(2),O(e.isPlaying()?"pause":"play_arrow"),g(5),We(" ",e.formatTime(e.currentTime())," / ",e.formatTime(e.duration())," "),g(2),je("title","Speed: "+e.playbackRate()+"x (Click to cycle)"),g(2),V("",e.playbackRate(),"x"),g(),w("active",e.isLooping()),je("title",e.isLooping()?"Loop enabled":"Enable loop"),g(3),je("title",e.isMuted()?"Unmute":"Mute"),g(2),O(e.isMuted()?"volume_off":"volume_up")}}function I4(n,t){if(n&1&&(M(0,E4,3,1,"div",76),M(1,D4,27,17,"div",43)),n&2){let e=m(4);b(e.videoLoadError()?-1:0),g(),b(e.videoLoadError()?-1:1)}}function T4(n,t){if(n&1){let e=L();j(0,"button",33),ue("click",function(){v(e);let i=m(5);return i.videoLoadError.set(!1),y(i.agentService.retryVideoRecording())}),j(1,"span",14),u(2,"refresh"),H(),u(3," Retry "),H()}}function A4(n,t){if(n&1&&(j(0,"div",23)(1,"div",29)(2,"span",30),u(3,"videocam_off"),H()(),j(4,"h4",31),u(5),H(),j(6,"p",32),u(7),H(),M(8,T4,4,0,"button",79),H()),n&2){let e=m(4);g(5),V(" ",e.agentService.recordingPlaybackStatus()==="failed"||e.videoLoadError()?"Recording Playback Failed":"No Video Recording Available"," "),g(2),V(" ",e.videoLoadError()?"The finalized recording could not be played.":e.agentService.recordingPlaybackMessage()||"No screen recording was found for this task."," "),g(),b(e.agentService.recordingPlaybackStatus()==="failed"||e.videoLoadError()?8:-1)}}function N4(n,t){if(n&1&&(M(0,C4,5,1,"div",34),M(1,k4,38,23,"div",35),M(2,I4,2,2),M(3,A4,9,3,"div",23)),n&2){let e,o=m(3);b(o.agentService.playerMode()==="video"&&(o.agentService.recordingPlaybackStatus()==="processing"||o.agentService.isVideoLoading())?0:-1),g(),b(o.agentService.playerMode()==="steps"&&o.totalStepFrames()>0?1:-1),g(),b((e=o.agentService.playerMode()==="video"&&o.agentService.recordingPlaybackStatus()==="ready"&&!o.agentService.isVideoLoading()&&o.agentService.activeVideoUrl())?2:-1,e),g(),b(!o.agentService.isVideoLoading()&&(o.agentService.playerMode()==="video"||o.totalStepFrames()===0)&&(o.agentService.recordingPlaybackStatus()==="failed"||o.agentService.recordingPlaybackStatus()==="unavailable"||o.videoLoadError())&&o.totalStepFrames()===0?3:-1)}}function R4(n,t){if(n&1&&(j(0,"div",17),M(1,h4,2,2),M(2,N4,4,4),H()),n&2){let e=m(2);g(),b(e.agentService.recordingPlaybackStatus()==="live"?1:-1),g(),b(e.agentService.recordingPlaybackStatus()!=="live"?2:-1)}}function F4(n,t){if(n&1){let e=L();j(0,"div",6)(1,"header",7),ue("mousedown",function(i){v(e);let r=m();return y(r.startDrag(i))}),j(2,"div",8)(3,"span",9),u(4),H(),j(5,"span",10),u(6),H()(),j(7,"div",11),ue("mousedown",function(i){return i.stopPropagation()}),M(8,p4,11,4,"div",12),j(9,"button",13),ue("click",function(){v(e);let i=m();return y(i.toggleMinimize())}),j(10,"span",14),u(11),H()(),M(12,f4,3,2,"button",15),j(13,"button",16),ue("click",function(){v(e);let i=m();return y(i.agentService.closeVideoPlayer())}),j(14,"span",14),u(15,"close"),H()()()(),M(16,R4,3,2,"div",17),H()}if(n&2){let e=m();Se("left",e.isTheaterMode()?null:e.posX(),"px")("top",e.isTheaterMode()?null:e.posY(),"px"),w("minimized",e.agentService.isVideoMinimized())("theater",e.isTheaterMode()),g(4),V(" ",e.agentService.recordingPlaybackStatus()==="live"?"sensors":e.agentService.playerMode()==="steps"?"slideshow":e.agentService.recordingPlaybackStatus()==="processing"?"progress_activity":"smart_display"," "),g(),je("title",e.agentService.activeVideoTitle()),g(),V(" ",e.agentService.recordingPlaybackStatus()==="live"?"Live Device Screen":e.agentService.playerMode()==="steps"?"Step Replay ("+(e.totalStepFrames()>0?e.activeStepIndex()+1+"/"+e.totalStepFrames():"0")+")":e.agentService.recordingPlaybackStatus()==="processing"?"Preparing Recording":e.agentService.activeVideoTitle()||"Screen Recording"," "),g(2),b(e.agentService.recordingPlaybackStatus()==="ready"&&e.agentService.hasCurrentSessionStepFrames()&&!e.agentService.isVideoMinimized()?8:-1),g(),je("title",e.agentService.isVideoMinimized()?"Restore":"Minimize"),g(2),O(e.agentService.isVideoMinimized()?"expand_less":"remove"),g(),b(e.agentService.isVideoMinimized()?-1:12),g(4),b(e.agentService.isVideoMinimized()?-1:16)}}var Kd=class n{agentService=D(It);zone=D(ge);videoRef;stepImgRef;stepOverlayRef;isPlaying=x(!1);playbackRate=x(1);isLooping=x(!1);currentTime=x(0);duration=x(0);isMuted=x(!1);isTheaterMode=x(!1);videoLoadError=x(!1);liveStreamUrl=x("/api/stream/device-live");liveStreamError=x(!1);activeSegmentIndex=x(0);currentVideoUrl=I(()=>this.agentService.activeVideoSegments()[this.activeSegmentIndex()]?.url||this.agentService.activeVideoUrl());pendingLocalTime=null;pendingAutoplay=!1;pendingAbsoluteSeek=null;activeStepIndex=x(0);isStepPlaying=x(!1);viewMode=x("pre");isCardHovered=x(!1);isCardPinned=x(!1);isCardVisible=I(()=>this.isCardHovered()||this.isCardPinned());isStepImageLoading=x(!1);stepImageError=x(!1);stepTimer=null;stepFrames=I(()=>this.agentService.currentSessionStepFrames());totalStepFrames=I(()=>this.stepFrames().length);currentStepFrame=I(()=>{let t=this.stepFrames(),e=this.activeStepIndex();return t[e]||null});currentStepImageUrl=I(()=>{let t=this.currentStepFrame();return t?this.viewMode()==="post"&&t.postImageUrl?t.postImageUrl:t.preImageUrl||t.imageUrl||"":""});stepProgressPercent=I(()=>{let t=this.totalStepFrames();return t<=1?0:this.activeStepIndex()/(t-1)*100});speedOptions=[.5,1,1.5,2,4];posX=x(typeof window<"u"?Math.max(20,window.innerWidth-420):100);posY=x(typeof window<"u"?Math.max(60,window.innerHeight-700):100);isDragging=!1;dragStartX=0;dragStartY=0;initialPosX=0;initialPosY=0;constructor(){Ye(()=>{let e=this.agentService.activeVideoUrl(),o=this.agentService.activeVideoSegments();this.videoLoadError.set(!1),this.activeSegmentIndex.set(0),this.currentTime.set(0),this.duration.set(o.reduce((i,r)=>i+r.duration,0)),this.isPlaying.set(!1)},{allowSignalWrites:!0});let t=null;Ye(()=>{let e=this.agentService.currentSessionId(),o=this.totalStepFrames();e!==t?(t=e,this.activeStepIndex.set(0),this.viewMode.set("pre"),this.pauseStepPlay()):o>0&&this.activeStepIndex()>=o&&this.activeStepIndex.set(o-1)},{allowSignalWrites:!0}),Ye(()=>{this.currentStepImageUrl()?(this.isStepImageLoading.set(!0),this.stepImageError.set(!1)):this.isStepImageLoading.set(!1)},{allowSignalWrites:!0}),Ye(()=>{this.activeStepIndex(),this.viewMode(),setTimeout(()=>this.drawStepOverlay(),40)}),Ye(()=>{let e=this.agentService.videoSeekRequest();if(!e||(this.pendingAbsoluteSeek=e.seconds,this.agentService.recordingPlaybackStatus()!=="ready"))return;let o=this.videoRef?.nativeElement;if(o&&o.readyState>=1){let i=this.pendingAbsoluteSeek;this.pendingAbsoluteSeek=null,this.seek(i,!0)}}),Ye(()=>{let e=this.agentService.stepSeekRequest();e&&this.seekStepFrame(e.index)})}onLiveStreamError(){this.liveStreamError.set(!0)}retryLiveStream(){this.liveStreamError.set(!1),this.liveStreamUrl.set(`/api/stream/device-live?t=${Date.now()}`)}formatTime(t){if(isNaN(t)||t<0)return"00:00";let e=Math.floor(t/60),o=Math.floor(t%60),i=e<10?"0"+e:String(e),r=o<10?"0"+o:String(o);return`${i}:${r}`}progressPercent=I(()=>{let t=this.duration();return t<=0?0:Math.min(100,Math.max(0,this.currentTime()/t*100))});startDrag(t){this.isTheaterMode()||(this.isDragging=!0,this.dragStartX=t.clientX,this.dragStartY=t.clientY,this.initialPosX=this.posX(),this.initialPosY=this.posY(),t.preventDefault(),this.zone.runOutsideAngular(()=>{document.addEventListener("mousemove",this.onDrag),document.addEventListener("mouseup",this.stopDrag)}))}onDrag=t=>{if(!this.isDragging)return;let e=t.clientX-this.dragStartX,o=t.clientY-this.dragStartY,i=10,r=10,a=Math.max(10,window.innerWidth-240),s=Math.max(10,window.innerHeight-80),c=Math.max(i,Math.min(a,this.initialPosX+e)),p=Math.max(r,Math.min(s,this.initialPosY+o));this.posX.set(c),this.posY.set(p)};stopDrag=()=>{this.isDragging=!1,document.removeEventListener("mousemove",this.onDrag),document.removeEventListener("mouseup",this.stopDrag)};onResize(){let t=Math.max(10,window.innerWidth-240),e=Math.max(10,window.innerHeight-80);this.posX()>t&&this.posX.set(t),this.posY()>e&&this.posY.set(e)}onKeyDown(t){this.agentService.isVideoWindowOpen()&&t.key==="Escape"&&(this.isTheaterMode()?this.isTheaterMode.set(!1):this.agentService.closeVideoPlayer())}onLoadedMetadata(){let t=this.videoRef?.nativeElement;if(t){let e=this.agentService.activeVideoSegments();if(e.length||this.duration.set(t.duration||0),this.videoLoadError.set(!1),t.playbackRate=this.playbackRate(),t.loop=this.isLooping()&&!e.length,t.muted=this.isMuted(),this.pendingAbsoluteSeek!==null){let o=this.pendingAbsoluteSeek;if(this.pendingAbsoluteSeek=null,this.seek(o,!0),this.pendingLocalTime!==null)return}this.pendingLocalTime!==null&&(t.currentTime=Math.max(0,Math.min(t.duration||this.pendingLocalTime,this.pendingLocalTime)),this.pendingLocalTime=null),this.pendingAutoplay&&(this.pendingAutoplay=!1,t.play().catch(()=>{})),this.agentService.consumeVideoAutoplay()&&(this.isMuted.set(!0),t.muted=!0,t.play().catch(()=>{this.isPlaying.set(!1)}))}}onTimeUpdate(){let t=this.videoRef?.nativeElement;if(t){let e=this.agentService.activeVideoSegments(),o=e[this.activeSegmentIndex()];this.currentTime.set((o?.start||0)+t.currentTime),!e.length&&t.duration&&t.duration!==this.duration()&&this.duration.set(t.duration)}}onPlay(){this.isPlaying.set(!0)}onPause(){this.isPlaying.set(!1)}onEnded(){let t=this.agentService.activeVideoSegments();if(t.length&&this.activeSegmentIndex()e+1);return}if(t.length&&this.isLooping()){this.seek(0,!0);return}this.isPlaying.set(!1)}onError(){this.videoLoadError.set(!0),this.isPlaying.set(!1)}togglePlay(){let t=this.videoRef?.nativeElement;t&&(t.paused?t.play().catch(()=>{}):t.pause())}restart(){this.seek(0,!0)}seek(t,e=!1){let o=this.videoRef?.nativeElement;if(!o)return;let i=Math.max(0,Math.min(this.duration(),t)),r=this.agentService.activeVideoSegments();if(!r.length){o.currentTime=i,e&&o.play().catch(()=>{});return}let a=r.findIndex(c=>i{})):(this.pendingLocalTime=s,this.pendingAutoplay=e||!o.paused,this.activeSegmentIndex.set(a)),this.currentTime.set(i)}onScrub(t){let e=t.target,o=parseFloat(e.value);this.seek(o)}setSpeed(t){this.playbackRate.set(t);let e=this.videoRef?.nativeElement;e&&(e.playbackRate=t),this.isStepPlaying()&&this.scheduleNextStepFrame()}toggleLoop(){let t=!this.isLooping();this.isLooping.set(t);let e=this.videoRef?.nativeElement;e&&(e.loop=t&&!this.agentService.activeVideoSegments().length)}toggleMute(){let t=!this.isMuted();this.isMuted.set(t);let e=this.videoRef?.nativeElement;e&&(e.muted=t)}toggleTheater(){this.isTheaterMode.set(!this.isTheaterMode())}toggleMinimize(){this.agentService.isVideoMinimized.set(!this.agentService.isVideoMinimized())}openInNewTab(){let t=this.agentService.activeVideoUrl();t&&window.open(t,"_blank")}toggleStepPlay(){this.isStepPlaying()?this.pauseStepPlay():this.startStepPlay()}startStepPlay(){this.totalStepFrames()<=0||(this.activeStepIndex()>=this.totalStepFrames()-1&&this.activeStepIndex.set(0),this.isStepPlaying.set(!0),this.scheduleNextStepFrame())}pauseStepPlay(){this.isStepPlaying.set(!1),this.stepTimer&&(clearTimeout(this.stepTimer),this.stepTimer=null)}scheduleNextStepFrame(){this.stepTimer&&clearTimeout(this.stepTimer);let t=Math.max(300,1500/this.playbackRate());this.stepTimer=setTimeout(()=>{this.isStepPlaying()&&(this.activeStepIndex()e+1),this.scheduleNextStepFrame()):this.isLooping()?(this.activeStepIndex.set(0),this.scheduleNextStepFrame()):this.pauseStepPlay())},t)}prevStepFrame(){this.pauseStepPlay(),this.viewMode.set("pre"),this.activeStepIndex.update(t=>Math.max(0,t-1))}nextStepFrame(){this.pauseStepPlay(),this.viewMode.set("pre"),this.activeStepIndex.update(t=>Math.min(this.totalStepFrames()-1,t+1))}seekStepFrame(t){this.viewMode.set("pre"),this.activeStepIndex.set(Math.max(0,Math.min(this.totalStepFrames()-1,t)))}onStepScrub(t){let e=t.target;this.seekStepFrame(parseInt(e.value,10))}restartStep(){this.seekStepFrame(0),this.startStepPlay()}setStepViewMode(t,e){e&&e.stopPropagation(),this.viewMode.set(t),setTimeout(()=>this.drawStepOverlay(),40)}toggleStepViewMode(t){t&&t.stopPropagation(),this.setStepViewMode(this.viewMode()==="pre"?"post":"pre")}onViewportMouseEnter(){this.isCardHovered.set(!0)}onViewportMouseLeave(){this.isCardHovered.set(!1)}toggleCardPin(t){t&&t.stopPropagation(),this.isCardPinned.update(e=>!e)}cycleSpeed(){let t=this.playbackRate(),o=(this.speedOptions.indexOf(t)+1)%this.speedOptions.length;this.setSpeed(this.speedOptions[o])}onStepImageLoad(){this.isStepImageLoading.set(!1),this.stepImageError.set(!1),this.drawStepOverlay()}onStepImageError(){this.isStepImageLoading.set(!1),this.stepImageError.set(!0)}drawStepOverlay(){let t=this.stepImgRef?.nativeElement,e=this.stepOverlayRef?.nativeElement;if(!t||!e||(e.innerHTML="",this.viewMode()==="post"))return;let o=this.currentStepFrame();if(!(!o||!o.action))try{Rd(t,e,o.action)}catch(i){console.warn("Failed to draw step coordinates overlay:",i)}}getStepActionIcon(t){return zd(t)}openImageInNewTab(){let t=this.currentStepImageUrl()||this.currentStepFrame()?.imageUrl;t&&window.open(t,"_blank")}trackStepFrame(t,e){return e.stepId||String(t)}ngOnDestroy(){this.stepTimer&&(clearTimeout(this.stepTimer),this.stepTimer=null),document.removeEventListener("mousemove",this.onDrag),document.removeEventListener("mouseup",this.stopDrag)}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=Ge({type:n,selectors:[["app-floating-video-player"]],viewQuery:function(e,o){if(e&1&&fr(l4,5)(d4,5)(u4,5),e&2){let i;eo(i=to())&&(o.videoRef=i.first),eo(i=to())&&(o.stepImgRef=i.first),eo(i=to())&&(o.stepOverlayRef=i.first)}},hostBindings:function(e,o){e&1&&k("resize",function(){return o.onResize()},_l)("keydown",function(r){return o.onKeyDown(r)},_l)},decls:2,vars:2,consts:[["stepImgRef",""],["stepOverlayRef",""],["videoRef",""],[1,"theater-backdrop"],[1,"floating-video-wrapper",3,"minimized","theater","left","top"],[1,"theater-backdrop",3,"click"],[1,"floating-video-wrapper"],[1,"window-header",3,"mousedown"],[1,"header-left"],[1,"material-symbols-outlined","header-icon"],[1,"header-title",3,"title"],[1,"header-actions",3,"mousedown"],[1,"mode-toggle-group"],["aria-label","Minimize",1,"header-btn",3,"click","title"],[1,"material-symbols-outlined"],["aria-label","Theater",1,"header-btn",3,"title"],["title","Close","aria-label","Close",1,"header-btn","close-btn",3,"click"],[1,"video-body"],["title","Video Recording",1,"mode-btn",3,"click"],[1,"material-symbols-outlined","mode-icon"],["title","Step Screenshot Replay",1,"mode-btn",3,"click"],["aria-label","Theater",1,"header-btn",3,"click","title"],[1,"live-stream-container"],[1,"empty-video-fallback"],["alt","Live Device Screen",1,"live-screen-img",3,"error","src"],[1,"live-status-overlay"],[1,"live-badge"],[1,"pulse-dot"],["title","Refresh Live Stream",1,"live-refresh-btn",3,"click"],[1,"fallback-icon-wrap"],[1,"material-symbols-outlined","fallback-icon"],[1,"fallback-title"],[1,"fallback-desc"],[1,"retry-btn",3,"click"],[1,"video-loading-state"],[1,"step-replay-container"],[1,"material-symbols-outlined","spinning-icon"],[1,"step-replay-notice"],[1,"step-image-viewport",3,"mouseenter","mouseleave"],[1,"step-image-loading-state"],[1,"step-image-error-state"],[1,"step-image-frame-wrap"],[1,"step-frame-badge",3,"visible"],[1,"video-controls-footer"],[1,"scrubber-bar-container"],["type","range",1,"scrubber-range",3,"input","min","max","step","value"],[1,"scrubber-progress-fill"],[1,"step-ticks-wrapper"],[1,"controls-row"],[1,"controls-left"],[1,"ctrl-btn","play-btn",3,"click","title"],["title","Previous Step",1,"ctrl-btn",3,"click","disabled"],["title","Next Step",1,"ctrl-btn",3,"click","disabled"],["title","Replay from start",1,"ctrl-btn",3,"click"],[1,"time-display"],[1,"controls-right"],[1,"ctrl-btn","speed-pill-btn",3,"click","title"],[1,"speed-label"],[1,"ctrl-btn",3,"click","title"],["title","Open image in new tab",1,"ctrl-btn",3,"click"],[1,"material-symbols-outlined","notice-icon"],[1,"material-symbols-outlined","broken-icon"],["title","Click to view image in new tab",1,"step-frame-img",3,"load","error","click","src","alt"],[1,"overlay-layer"],[1,"step-frame-badge",3,"click"],[1,"badge-content-left"],[1,"badge-step-no"],[1,"badge-action-desc",3,"title"],[1,"material-symbols-outlined","action-type-icon"],[1,"badge-actions-right"],[1,"pre-post-toggle"],[1,"pin-card-btn",3,"click","title"],["title","View screen before action (with touch coordinates)",1,"toggle-btn",3,"click"],["title","View resulting screen after action executed",1,"toggle-btn",3,"click"],[1,"step-tick",3,"active","passed","left","title"],[1,"step-tick",3,"click","title"],[1,"video-container"],["playsinline","",3,"loadedmetadata","timeupdate","play","pause","ended","error","click","src"],["title","Open video in new tab",1,"ctrl-btn",3,"click"],[1,"retry-btn"]],template:function(e,o){e&1&&(M(0,g4,1,0,"div",3),M(1,F4,17,16,"div",4)),e&2&&(b(o.agentService.isVideoWindowOpen()&&o.isTheaterMode()?0:-1),g(),b(o.agentService.isVideoWindowOpen()?1:-1))},dependencies:[Qt],styles:['.theater-backdrop[_ngcontent-%COMP%]{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#0f172a99;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);z-index:1040;animation:_ngcontent-%COMP%_fadeIn .15s ease-out}.floating-video-wrapper[_ngcontent-%COMP%]{position:fixed;width:400px;max-width:calc(100vw - 32px);background:#ffffffd6;backdrop-filter:blur(24px) saturate(180%);-webkit-backdrop-filter:blur(24px) saturate(180%);border:1px solid rgba(255,255,255,.85);border-radius:16px;box-shadow:0 20px 50px -10px #0f172a38,0 0 0 1px #e2e8f099,inset 0 1px 1px #ffffffe6;z-index:1050;overflow:hidden;display:flex;flex-direction:column;box-sizing:border-box;animation:_ngcontent-%COMP%_popIn .2s cubic-bezier(.16,1,.3,1);-webkit-user-select:none;user-select:none;font-family:Google Sans,Google Sans Text,Inter,system-ui,-apple-system,sans-serif}.floating-video-wrapper.minimized[_ngcontent-%COMP%]{width:280px;box-shadow:0 10px 25px -5px #0f172a2e}.floating-video-wrapper.minimized[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%]{border-bottom:none}.floating-video-wrapper.theater[_ngcontent-%COMP%]{left:50%!important;top:50%!important;transform:translate(-50%,-50%);width:85vw;max-width:960px;height:auto;max-height:88vh;box-shadow:0 24px 60px -12px #0f172a59}.floating-video-wrapper.theater[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%]{max-height:calc(88vh - 46px)}.floating-video-wrapper.theater[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-container[_ngcontent-%COMP%] video[_ngcontent-%COMP%]{max-height:calc(88vh - 120px)}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%]{height:44px;background:#ffffffbf;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);border-bottom:1px solid rgba(226,232,240,.75);display:flex;align-items:center;justify-content:space-between;padding:0 8px 0 12px;cursor:grab;gap:8px;flex-shrink:0}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%]:active{cursor:grabbing}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;overflow:hidden;flex:1}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .header-icon[_ngcontent-%COMP%]{font-size:18px;color:#2563eb;flex-shrink:0}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .header-title[_ngcontent-%COMP%]{font-size:13px;font-weight:600;color:#0f172a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.2px}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .mode-switcher-group[_ngcontent-%COMP%]{display:flex;align-items:center;background:#f1f5f9a6;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid rgba(226,232,240,.8);border-radius:8px;padding:2px;margin-left:4px;flex-shrink:0}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .mode-switcher-group[_ngcontent-%COMP%] .mode-btn[_ngcontent-%COMP%]{border:none;background:transparent;color:#475569;font-size:10px;font-weight:700;padding:2px 7px;border-radius:6px;cursor:pointer;transition:all .15s ease;display:flex;align-items:center;gap:4px}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .mode-switcher-group[_ngcontent-%COMP%] .mode-btn[_ngcontent-%COMP%] .pulse-dot-mini[_ngcontent-%COMP%]{width:5px;height:5px;border-radius:50%;background:#ef4444;animation:_ngcontent-%COMP%_pulseRed 1.2s infinite}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .mode-switcher-group[_ngcontent-%COMP%] .mode-btn[_ngcontent-%COMP%]:hover:not(:disabled){color:#0f172a;background:#fff9}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .mode-switcher-group[_ngcontent-%COMP%] .mode-btn.active[_ngcontent-%COMP%]{background:#0284c7;color:#fff;font-weight:700;box-shadow:0 1px 3px #0284c74d}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-left[_ngcontent-%COMP%] .mode-switcher-group[_ngcontent-%COMP%] .mode-btn[_ngcontent-%COMP%]:disabled{opacity:.4;cursor:not-allowed}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%]{display:flex;align-items:center;gap:4px;flex-shrink:0}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .mode-toggle-group[_ngcontent-%COMP%]{display:flex;align-items:center;background:#f1f5f9b3;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid rgba(226,232,240,.85);border-radius:8px;padding:2px;margin-right:4px;gap:2px}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .mode-toggle-group[_ngcontent-%COMP%] .mode-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:3px;border:none;background:transparent;color:#475569;font-size:11px;font-weight:600;padding:2px 7px;border-radius:6px;cursor:pointer;transition:all .15s ease}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .mode-toggle-group[_ngcontent-%COMP%] .mode-btn[_ngcontent-%COMP%] .mode-icon[_ngcontent-%COMP%]{font-size:13px}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .mode-toggle-group[_ngcontent-%COMP%] .mode-btn[_ngcontent-%COMP%]:hover:not(.active){color:#0f172a;background:#fffc}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .mode-toggle-group[_ngcontent-%COMP%] .mode-btn.active[_ngcontent-%COMP%]{background:#0284c7;color:#fff;box-shadow:0 1px 3px #0284c74d}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .speed-pill-group[_ngcontent-%COMP%]{display:flex;align-items:center;background:#f1f5f9a6;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid rgba(226,232,240,.8);border-radius:8px;padding:2px;margin-right:4px}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .speed-pill-group[_ngcontent-%COMP%] .speed-btn[_ngcontent-%COMP%]{border:none;background:transparent;color:#334155;font-size:11px;font-weight:700;padding:2px 6px;border-radius:4px;cursor:pointer;transition:all .15s ease}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .speed-pill-group[_ngcontent-%COMP%] .speed-btn[_ngcontent-%COMP%]:hover{color:#0f172a;background:#cbd5e1}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .speed-pill-group[_ngcontent-%COMP%] .speed-btn.active[_ngcontent-%COMP%]{background:#0284c7;color:#fff;font-weight:700;box-shadow:0 1px 3px #0284c74d}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .header-btn[_ngcontent-%COMP%]{background:#f1f5f9bf;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(226,232,240,.85);color:#1e293b;cursor:pointer;display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:7px;box-shadow:0 1px 3px #0f172a0a,inset 0 1px 1px #fffc;transition:all .2s cubic-bezier(.4,0,.2,1)}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .header-btn[_ngcontent-%COMP%]:hover{background:#fffffff2;color:#0f172a;border-color:#cbd5e1f2;transform:translateY(-.5px);box-shadow:0 2px 6px #0f172a14}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .header-btn.close-btn[_ngcontent-%COMP%]:hover{background:#fee2e2f2;color:#dc2626;border-color:#fca5a5e6;box-shadow:0 2px 6px #dc262626}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .header-btn[_ngcontent-%COMP%]:active{transform:scale(.96)}.floating-video-wrapper[_ngcontent-%COMP%] .window-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] .header-btn[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:17px;font-weight:600}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%]{position:relative;background:#fff;display:flex;flex-direction:column;align-items:stretch;justify-content:flex-start;overflow:hidden}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-loading-state[_ngcontent-%COMP%]{padding:36px 20px;display:flex;flex-direction:column;align-items:center;gap:10px;background:#fff;width:100%;box-sizing:border-box;color:#475569;font-size:13px;font-weight:500}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-loading-state[_ngcontent-%COMP%] .spinning-icon[_ngcontent-%COMP%]{font-size:28px;color:#2563eb;animation:_ngcontent-%COMP%_spin 1s linear infinite}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .live-stream-container[_ngcontent-%COMP%]{position:relative;width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#fff;min-height:260px;overflow:hidden}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .live-stream-container[_ngcontent-%COMP%] .live-screen-img[_ngcontent-%COMP%]{width:100%;max-height:520px;display:block;object-fit:contain;-webkit-user-select:none;user-select:none;background:#fff}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .live-stream-container[_ngcontent-%COMP%] .live-status-overlay[_ngcontent-%COMP%]{position:absolute;top:10px;left:12px;right:12px;display:flex;align-items:center;justify-content:space-between;pointer-events:none}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .live-stream-container[_ngcontent-%COMP%] .live-status-overlay[_ngcontent-%COMP%] .live-badge[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;background:#fef2f2;border:1px solid #fca5a5;color:#dc2626;font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:12px;letter-spacing:.5px;box-shadow:0 1px 4px #dc262626}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .live-stream-container[_ngcontent-%COMP%] .live-status-overlay[_ngcontent-%COMP%] .live-badge[_ngcontent-%COMP%] .pulse-dot[_ngcontent-%COMP%]{width:6px;height:6px;border-radius:50%;background:#ef4444;animation:_ngcontent-%COMP%_pulseRed 1.2s infinite}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .live-stream-container[_ngcontent-%COMP%] .live-status-overlay[_ngcontent-%COMP%] .live-refresh-btn[_ngcontent-%COMP%]{pointer-events:auto;background:#fffffff2;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border:1px solid #cbd5e1;color:#1e293b;cursor:pointer;display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;box-shadow:0 1px 3px #00000014;transition:all .15s ease}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .live-stream-container[_ngcontent-%COMP%] .live-status-overlay[_ngcontent-%COMP%] .live-refresh-btn[_ngcontent-%COMP%]:hover{background:#f1f5f9;color:#0f172a;border-color:#94a3b8;transform:rotate(90deg)}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .live-stream-container[_ngcontent-%COMP%] .live-status-overlay[_ngcontent-%COMP%] .live-refresh-btn[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:16px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;background:#fff;position:relative;width:100%;overflow:hidden}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-replay-notice[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;background:#fffbeb;color:#b45309;padding:6px 12px;font-size:11.5px;font-weight:500;border-bottom:1px solid #fde68a}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-replay-notice[_ngcontent-%COMP%] .notice-icon[_ngcontent-%COMP%]{font-size:14px;color:#d97706;flex-shrink:0}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:center;position:relative;background:#f8fafc;min-height:280px;max-height:520px;overflow:hidden;padding:10px 0}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-loading-state[_ngcontent-%COMP%], .floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-error-state[_ngcontent-%COMP%]{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;background:#f8fafc;color:#64748b;font-size:12px;font-weight:500;z-index:5}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-loading-state[_ngcontent-%COMP%] .spinning-icon[_ngcontent-%COMP%], .floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-error-state[_ngcontent-%COMP%] .spinning-icon[_ngcontent-%COMP%]{font-size:24px;color:#0284c7;animation:_ngcontent-%COMP%_spin 1s linear infinite}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-loading-state[_ngcontent-%COMP%] .broken-icon[_ngcontent-%COMP%], .floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-error-state[_ngcontent-%COMP%] .broken-icon[_ngcontent-%COMP%]{font-size:28px;color:#94a3b8}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-frame-wrap[_ngcontent-%COMP%]{position:relative;display:inline-flex;align-items:center;justify-content:center;max-width:92%;max-height:500px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-frame-wrap[_ngcontent-%COMP%] .step-frame-img[_ngcontent-%COMP%]{max-width:100%;max-height:500px;width:auto;height:auto;object-fit:contain;display:block;-webkit-user-select:none;user-select:none;cursor:pointer;border-radius:8px;box-shadow:0 4px 20px -2px #0f172a24,0 0 0 1px #e2e8f0e6;background:#fff;transition:opacity .15s ease}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-frame-wrap[_ngcontent-%COMP%] .step-frame-img[_ngcontent-%COMP%]:hover{opacity:.98}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-image-frame-wrap[_ngcontent-%COMP%] .overlay-layer[_ngcontent-%COMP%]{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:8}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%]:hover .step-frame-badge[_ngcontent-%COMP%]{opacity:1;transform:translateY(0);pointer-events:auto}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%]{position:absolute;bottom:12px;left:10px;right:10px;display:flex;align-items:center;justify-content:space-between;gap:8px;background:#0f172ae0;backdrop-filter:blur(14px) saturate(180%);-webkit-backdrop-filter:blur(14px) saturate(180%);border:1px solid rgba(255,255,255,.2);border-radius:10px;padding:6px 10px;color:#fff;box-shadow:0 8px 24px #00000080;opacity:0;transform:translateY(8px);pointer-events:none;transition:opacity .22s cubic-bezier(.16,1,.3,1),transform .22s cubic-bezier(.16,1,.3,1);z-index:15}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge.visible[_ngcontent-%COMP%]{opacity:1;transform:translateY(0);pointer-events:auto}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-content-left[_ngcontent-%COMP%]{display:flex;align-items:center;gap:7px;overflow:hidden;flex:1}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-content-left[_ngcontent-%COMP%] .badge-step-no[_ngcontent-%COMP%]{font-size:10.5px;font-weight:700;background:#0284c7;padding:2px 7px;border-radius:5px;letter-spacing:.3px;flex-shrink:0;box-shadow:0 1px 3px #0284c766}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-content-left[_ngcontent-%COMP%] .badge-action-desc[_ngcontent-%COMP%]{font-size:11.5px;font-weight:500;color:#f8fafc;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:4px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-content-left[_ngcontent-%COMP%] .badge-action-desc[_ngcontent-%COMP%] .action-type-icon[_ngcontent-%COMP%]{font-size:15px;color:#38bdf8;flex-shrink:0}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-actions-right[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;flex-shrink:0}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-actions-right[_ngcontent-%COMP%] .pre-post-toggle[_ngcontent-%COMP%]{display:inline-flex;align-items:center;background:#ffffff1f;border:1px solid rgba(255,255,255,.15);border-radius:6px;padding:2px;gap:2px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-actions-right[_ngcontent-%COMP%] .pre-post-toggle[_ngcontent-%COMP%] .toggle-btn[_ngcontent-%COMP%]{border:none;background:transparent;color:#ffffffb3;font-size:10.5px;font-weight:700;padding:2px 7px;border-radius:4px;cursor:pointer;transition:all .15s ease}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-actions-right[_ngcontent-%COMP%] .pre-post-toggle[_ngcontent-%COMP%] .toggle-btn[_ngcontent-%COMP%]:hover{color:#fff;background:#fff3}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-actions-right[_ngcontent-%COMP%] .pre-post-toggle[_ngcontent-%COMP%] .toggle-btn.active[_ngcontent-%COMP%]{background:#0284c7;color:#fff;box-shadow:0 1px 3px #0000004d}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-actions-right[_ngcontent-%COMP%] .pin-card-btn[_ngcontent-%COMP%]{background:transparent;border:none;color:#fff9;cursor:pointer;padding:3px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all .15s ease}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-actions-right[_ngcontent-%COMP%] .pin-card-btn[_ngcontent-%COMP%]:hover{color:#fff;background:#ffffff26}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-actions-right[_ngcontent-%COMP%] .pin-card-btn.pinned[_ngcontent-%COMP%]{color:#38bdf8;background:#38bdf833}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .step-replay-container[_ngcontent-%COMP%] .step-image-viewport[_ngcontent-%COMP%] .step-frame-badge[_ngcontent-%COMP%] .badge-actions-right[_ngcontent-%COMP%] .pin-card-btn[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:14px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-container[_ngcontent-%COMP%]{position:relative;width:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#fff}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-container[_ngcontent-%COMP%] video[_ngcontent-%COMP%]{width:100%;height:auto;max-height:520px;display:block;object-fit:contain;cursor:pointer;background:#fff}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%]{background:#ffffffd6;backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%);border-top:1px solid rgba(226,232,240,.75);padding:12px 14px;display:flex;flex-direction:column;gap:10px;flex-shrink:0;box-shadow:0 -4px 16px #0f172a0a,inset 0 1px 1px #ffffffe6}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .scrubber-bar-container[_ngcontent-%COMP%]{position:relative;width:100%;height:8px;display:flex;align-items:center;cursor:pointer}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .scrubber-bar-container[_ngcontent-%COMP%] .scrubber-range[_ngcontent-%COMP%]{position:absolute;width:100%;height:100%;opacity:0;cursor:pointer;z-index:5;margin:0}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .scrubber-bar-container[_ngcontent-%COMP%]:before{content:"";position:absolute;left:0;right:0;height:5px;background:#e2e8f0d9;border-radius:3px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .scrubber-bar-container[_ngcontent-%COMP%] .scrubber-progress-fill[_ngcontent-%COMP%]{position:absolute;left:0;height:5px;background:linear-gradient(90deg,#0284c7,#2563eb);border-radius:3px;pointer-events:none;box-shadow:0 0 8px #0284c766}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .scrubber-bar-container[_ngcontent-%COMP%] .step-ticks-wrapper[_ngcontent-%COMP%]{position:absolute;left:0;right:0;height:100%;pointer-events:none;display:flex;align-items:center;z-index:6}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .scrubber-bar-container[_ngcontent-%COMP%] .step-ticks-wrapper[_ngcontent-%COMP%] .step-tick[_ngcontent-%COMP%]{position:absolute;width:7px;height:7px;border-radius:50%;background:#ffffffe6;border:1.5px solid #94a3b8;transform:translate(-50%);pointer-events:auto;cursor:pointer;transition:all .15s ease}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .scrubber-bar-container[_ngcontent-%COMP%] .step-ticks-wrapper[_ngcontent-%COMP%] .step-tick[_ngcontent-%COMP%]:hover{transform:translate(-50%) scale(1.4);border-color:#0284c7;background:#fff}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .scrubber-bar-container[_ngcontent-%COMP%] .step-ticks-wrapper[_ngcontent-%COMP%] .step-tick.passed[_ngcontent-%COMP%]{background:#0284c7;border-color:#fff}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .scrubber-bar-container[_ngcontent-%COMP%] .step-ticks-wrapper[_ngcontent-%COMP%] .step-tick.active[_ngcontent-%COMP%]{background:#38bdf8;border-color:#fff;transform:translate(-50%) scale(1.3);box-shadow:0 0 6px #38bdf8cc}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .controls-left[_ngcontent-%COMP%], .floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .controls-right[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn[_ngcontent-%COMP%]{background:#f1f5f9bf;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(226,232,240,.85);box-shadow:0 1px 3px #0f172a0a,inset 0 1px 1px #ffffffd9;color:#0f172a;width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1)}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn[_ngcontent-%COMP%]:hover{background:#fffffff2;border-color:#bfdbfee6;color:#0284c7;transform:translateY(-.5px);box-shadow:0 3px 8px #0f172a14}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn[_ngcontent-%COMP%]:active{transform:scale(.96)}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn.active[_ngcontent-%COMP%]{color:#0284c7;background:#e0f2fed9;border-color:#38bdf8cc;box-shadow:0 2px 6px #0284c726}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn.play-btn[_ngcontent-%COMP%]{background:linear-gradient(135deg,#0284c7eb,#2563ebe0);backdrop-filter:blur(14px) saturate(180%);-webkit-backdrop-filter:blur(14px) saturate(180%);border:1px solid rgba(255,255,255,.35);color:#fff;width:36px;height:36px;border-radius:50%;box-shadow:0 4px 14px #0284c759,inset 0 1px 1px #ffffff80}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn.play-btn[_ngcontent-%COMP%]:hover{background:linear-gradient(135deg,#0284c7,#2563ebf2);box-shadow:0 6px 18px #0284c773,inset 0 1px 1px #fff9;transform:translateY(-1px) scale(1.04)}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn.play-btn[_ngcontent-%COMP%]:active{transform:scale(.96)}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn.play-btn[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:22px;color:#fff}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn.speed-pill-btn[_ngcontent-%COMP%]{width:auto;min-width:34px;padding:0 7px;font-size:11px;font-weight:700;font-family:JetBrains Mono,Roboto Mono,monospace;color:#334155;letter-spacing:-.2px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn.speed-pill-btn[_ngcontent-%COMP%]:hover{color:#0284c7;border-color:#bfdbfee6}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .ctrl-btn[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:18px;color:#1e293b}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .video-controls-footer[_ngcontent-%COMP%] .controls-row[_ngcontent-%COMP%] .time-display[_ngcontent-%COMP%]{font-size:12px;font-weight:700;font-family:JetBrains Mono,Roboto Mono,monospace;color:#1e293b;margin-left:4px;letter-spacing:.5px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .empty-video-fallback[_ngcontent-%COMP%]{background:#fff;padding:36px 20px;display:flex;flex-direction:column;align-items:center;text-align:center;box-sizing:border-box;width:100%}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .empty-video-fallback[_ngcontent-%COMP%] .fallback-icon-wrap[_ngcontent-%COMP%]{width:48px;height:48px;border-radius:50%;background:#fef2f2;border:1px solid #fee2e2;display:flex;align-items:center;justify-content:center;margin-bottom:12px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .empty-video-fallback[_ngcontent-%COMP%] .fallback-icon-wrap[_ngcontent-%COMP%] .fallback-icon[_ngcontent-%COMP%]{font-size:24px;color:#ef4444}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .empty-video-fallback[_ngcontent-%COMP%] .fallback-title[_ngcontent-%COMP%]{margin:0 0 6px;font-size:13.5px;font-weight:600;color:#0f172a}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .empty-video-fallback[_ngcontent-%COMP%] .fallback-desc[_ngcontent-%COMP%]{margin:0 0 12px;font-size:12px;color:#64748b;line-height:1.4;max-width:240px}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .empty-video-fallback[_ngcontent-%COMP%] .retry-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;background:#0284c7;color:#fff;border:none;border-radius:6px;padding:5px 12px;font-size:11.5px;font-weight:600;cursor:pointer;transition:all .15s ease}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .empty-video-fallback[_ngcontent-%COMP%] .retry-btn[_ngcontent-%COMP%]:hover{background:#0369a1;transform:translateY(-1px)}.floating-video-wrapper[_ngcontent-%COMP%] .video-body[_ngcontent-%COMP%] .empty-video-fallback[_ngcontent-%COMP%] .retry-btn[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}@keyframes _ngcontent-%COMP%_popIn{0%{opacity:0;transform:scale(.96) translateY(6px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes _ngcontent-%COMP%_fadeIn{0%{opacity:0}to{opacity:1}}@keyframes _ngcontent-%COMP%_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes _ngcontent-%COMP%_pulseRed{0%,to{opacity:1}50%{opacity:.5}} .action-point-marker{z-index:10;pointer-events:none}@keyframes _ngcontent-%COMP%_pulse-animation{0%{transform:scale(.6);opacity:1}to{transform:scale(2.2);opacity:0}}']})};var L4=["dockInput"];function V4(n,t){if(n&1){let e=L();l(0,"div",4)(1,"span",55),u(2,"error"),d(),l(3,"span",56),u(4),d(),l(5,"button",57),k("click",function(){v(e);let i=m();return y(i.errorMessage.set(null))}),l(6,"span",42),u(7,"close"),d()()()}if(n&2){let e=m();g(4),O(e.errorMessage())}}function j4(n,t){if(n&1){let e=L();l(0,"button",58),k("click",function(i){v(e);let r=m();return y(r.clearInput(i))}),l(1,"span",42),u(2,"close"),d()()}}function $4(n,t){if(n&1){let e=L();l(0,"button",59),k("click",function(i){v(e);let r=m();return y(r.stopTask(i))}),l(1,"span",42),u(2,"stop"),d()()}if(n&2){let e=m();R("disabled",e.isSubmitting())("title",e.stopButtonTitle()),Wt("aria-label",e.stopButtonTitle())}}function z4(n,t){n&1&&(l(0,"span",41),u(1,"sync"),d())}function B4(n,t){n&1&&(l(0,"span",42),u(1,"arrow_upward"),d())}function H4(n,t){if(n&1){let e=L();l(0,"button",60),k("click",function(i){v(e);let r=m();return y(r.stopTask(i))}),l(1,"span",42),u(2,"stop"),d()()}if(n&2){let e=m();R("disabled",e.isSubmitting())("title",e.stopButtonTitle()),Wt("aria-label",e.stopButtonTitle())}}var Yd=class n{agentService=D(It);zone=D(ge);destroyRef=D(Ae);rightPanelWidth=x(typeof window<"u"?Math.round(window.innerWidth/3):450);isDragging=x(!1);dragWidthRafId=null;pendingDragWidth=0;taskInputSignal=x("");get taskInput(){return this.taskInputSignal()}set taskInput(t){this.taskInputSignal.set(t)}isSubmitting=x(!1);errorMessage=x(null);selectedProfile=x("flash");isHoveringCard=x(!1);isInputFocused=x(!1);dockInputRef;ngOnInit(){if(typeof localStorage<"u"){let t=localStorage.getItem("artemis_selected_profile");(t==="flash"||t==="pro")&&this.selectedProfile.set(t)}this.zone.runOutsideAngular(()=>{window.addEventListener("keydown",this.onGlobalKeyDown)}),this.destroyRef.onDestroy(()=>{window.removeEventListener("keydown",this.onGlobalKeyDown),this.detachDragListeners()})}setProfile(t,e){e&&e.stopPropagation(),this.selectedProfile.set(t),typeof localStorage<"u"&&localStorage.setItem("artemis_selected_profile",t)}isTaskRunning=I(()=>this.agentService.isCurrentSessionRunning());stopButtonTitle=I(()=>{let t=this.agentService.currentSession();if(t?.initial_goal)return`Stop current task: "${t.initial_goal.length>45?t.initial_goal.substring(0,42)+"...":t.initial_goal}"`;let e=this.agentService.currentSessionId();return e?`Stop current task (${e})`:"Stop current running task"});isBarExpanded=I(()=>this.isHoveringCard()||this.isInputFocused()||this.taskInput.trim().length>0);onInputFocus(){this.isInputFocused.set(!0)}onInputBlur(){this.isInputFocused.set(!1)}onCardClick(t){let e=t.target;e.closest("button")||e.tagName.toLowerCase()==="textarea"||this.focusInput()}focusInput(){setTimeout(()=>{this.dockInputRef?.nativeElement?.focus()},30)}clearInput(t){t&&t.stopPropagation(),this.taskInput="",this.dockInputRef?.nativeElement&&(this.dockInputRef.nativeElement.style.height="auto",this.dockInputRef.nativeElement.focus())}onTextareaInput(t){let e=t.target;if(!e)return;e.style.height="auto";let o=Math.min(Math.max(e.scrollHeight,24),120);e.style.height=`${o}px`}onGlobalKeyDown=t=>{(t.metaKey||t.ctrlKey)&&t.key.toLowerCase()==="k"&&(t.preventDefault(),this.focusInput())};onKeyDown(t){t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),this.submitTask())}submitTask(){let t=this.taskInput.trim();!t||this.isSubmitting()||(this.isSubmitting.set(!0),this.errorMessage.set(null),this.dockInputRef?.nativeElement&&this.dockInputRef.nativeElement.blur(),this.isInputFocused.set(!1),this.agentService.runTask(t,this.selectedProfile()).subscribe({next:e=>{this.taskInput="",this.dockInputRef?.nativeElement&&(this.dockInputRef.nativeElement.style.height="auto"),this.isSubmitting.set(!1),this.agentService.fetchStatus()},error:e=>{console.error("Failed to submit task:",e),this.isSubmitting.set(!1),this.errorMessage.set(e.error?.detail||"The runner is busy. Please wait for current task to finish."),setTimeout(()=>{this.errorMessage.set(null)},5e3)}}))}stopTask(t){if(t&&t.stopPropagation(),!this.isTaskRunning())return;let e=this.agentService.currentSessionId();this.isSubmitting.set(!0),this.errorMessage.set(null),this.agentService.stopTask(e,!1),setTimeout(()=>{this.isSubmitting.set(!1)},400)}onDragStart(t){this.isDragging.set(!0),t.preventDefault(),this.zone.runOutsideAngular(()=>{document.addEventListener("mousemove",this.onMouseMove),document.addEventListener("mouseup",this.onMouseUp)})}onMouseMove=t=>{if(!this.isDragging())return;let e=window.innerWidth-t.clientX,o=250,i=window.innerWidth-300;e>=o&&e<=i&&(this.pendingDragWidth=e,this.dragWidthRafId===null&&(this.dragWidthRafId=requestAnimationFrame(()=>{this.dragWidthRafId=null,this.rightPanelWidth.set(this.pendingDragWidth)})))};onMouseUp=()=>{this.isDragging.set(!1),this.detachDragListeners()};detachDragListeners(){document.removeEventListener("mousemove",this.onMouseMove),document.removeEventListener("mouseup",this.onMouseUp),this.dragWidthRafId!==null&&(cancelAnimationFrame(this.dragWidthRafId),this.dragWidthRafId=null)}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=Ge({type:n,selectors:[["app-workspace"]],viewQuery:function(e,o){if(e&1&&fr(L4,5),e&2){let i;eo(i=to())&&(o.dockInputRef=i.first)}},decls:67,vars:33,consts:[["dockInput",""],[1,"workspace-container"],[1,"left-panel","glass-panel"],[1,"workspace-floating-bar-wrapper"],[1,"floating-dock-toast","error"],[1,"floating-dock-row"],[1,"floating-dock-card",3,"click","mouseenter","mouseleave"],[1,"dock-wave-container"],[1,"wave-glow-ambient"],[1,"wave-tracks-wrapper"],["viewBox","0 0 2400 80","preserveAspectRatio","none",1,"liquid-wave","wave-back"],["id","waveGradBack","x1","0%","y1","0%","x2","100%","y2","0%"],["offset","0%",1,"wave-stop-1"],["offset","25%",1,"wave-stop-2"],["offset","50%",1,"wave-stop-3"],["offset","75%",1,"wave-stop-4"],["offset","100%",1,"wave-stop-1"],["d","M 0,25 Q 300,55 600,20 T 1200,25 Q 1500,55 1800,20 T 2400,25 L 2400,80 L 0,80 Z","fill","url(#waveGradBack)"],["viewBox","0 0 2400 80","preserveAspectRatio","none",1,"liquid-wave","wave-mid"],["id","waveGradMid","x1","0%","y1","0%","x2","100%","y2","0%"],["offset","0%",1,"wave-stop-3"],["offset","35%",1,"wave-stop-1"],["offset","70%",1,"wave-stop-4"],["offset","100%",1,"wave-stop-3"],["d","M 0,35 Q 300,5 600,45 T 1200,35 Q 1500,5 1800,45 T 2400,35 L 2400,80 L 0,80 Z","fill","url(#waveGradMid)"],["viewBox","0 0 2400 80","preserveAspectRatio","none",1,"liquid-wave","wave-front"],["id","waveGradFront","x1","0%","y1","0%","x2","100%","y2","0%"],["offset","0%",1,"wave-stop-2"],["offset","30%",1,"wave-stop-4"],["offset","65%",1,"wave-stop-1"],["offset","100%",1,"wave-stop-2"],["d","M 0,18 Q 300,50 600,15 T 1200,18 Q 1500,50 1800,15 T 2400,18 L 2400,80 L 0,80 Z","fill","url(#waveGradFront)"],[1,"capsule-peek-view"],[1,"capsule-placeholder"],[1,"expanded-card-content"],[1,"card-main-input-row"],[1,"input-content-area"],["rows","1","spellcheck","false",1,"dock-textarea",3,"ngModelChange","input","keydown","focus","blur","ngModel","disabled","placeholder"],["type","button","title","Clear input text","aria-label","Clear input text",1,"dock-circle-btn","btn-clear"],["type","button",1,"dock-circle-btn","btn-stop",3,"disabled","title"],["type","button","aria-label","Start task",1,"dock-circle-btn","btn-send",3,"click","disabled","title"],[1,"material-symbols-outlined","spinning-icon"],[1,"material-symbols-outlined"],[1,"card-footer-row"],[1,"footer-left-group"],["role","group","aria-label","Select Agent Architecture",1,"model-profile-toggle"],["type","button","title","Flash: fast single-look loop for everyday app tasks (3\u20135s/step)",1,"profile-toggle-pill",3,"mousedown","click"],[1,"material-symbols-outlined","pill-icon","icon-flash"],[1,"pill-label"],["type","button","title","Pro: plans first, checks results and recovers from blocked steps. For long or complex tasks (15\u201340s/step)",1,"profile-toggle-pill",3,"mousedown","click"],[1,"material-symbols-outlined","pill-icon","icon-pro"],["type","button",1,"standalone-stop-btn",3,"disabled","title"],[1,"resizer",3,"mousedown"],[1,"resizer-handle"],[1,"right-panel"],[1,"material-symbols-outlined","toast-icon"],[1,"toast-text"],["type","button","aria-label","Close error message",1,"btn-toast-close",3,"click"],["type","button","title","Clear input text","aria-label","Clear input text",1,"dock-circle-btn","btn-clear",3,"click"],["type","button",1,"dock-circle-btn","btn-stop",3,"click","disabled","title"],["type","button",1,"standalone-stop-btn",3,"click","disabled","title"]],template:function(e,o){if(e&1){let i=L();l(0,"div",1)(1,"main",2),$(2,"app-agent-stream"),l(3,"div",3),M(4,V4,8,1,"div",4),l(5,"div",5)(6,"div",6),k("click",function(a){return o.onCardClick(a)})("mouseenter",function(){return o.isHoveringCard.set(!0)})("mouseleave",function(){return o.isHoveringCard.set(!1)}),l(7,"div",7),$(8,"div",8),l(9,"div",9),yo(),l(10,"svg",10)(11,"defs")(12,"linearGradient",11),$(13,"stop",12)(14,"stop",13)(15,"stop",14)(16,"stop",15)(17,"stop",16),d()(),$(18,"path",17),d(),l(19,"svg",18)(20,"defs")(21,"linearGradient",19),$(22,"stop",20)(23,"stop",21)(24,"stop",22)(25,"stop",23),d()(),$(26,"path",24),d(),l(27,"svg",25)(28,"defs")(29,"linearGradient",26),$(30,"stop",27)(31,"stop",28)(32,"stop",29)(33,"stop",30),d()(),$(34,"path",31),d()()(),rr(),l(35,"div",32)(36,"span",33),u(37,"Start a new task..."),d()(),l(38,"div",34)(39,"div",35)(40,"div",36)(41,"textarea",37,0),hr("ngModelChange",function(a){return v(i),$a(o.taskInput,a)||(o.taskInput=a),y(a)}),k("input",function(a){return o.onTextareaInput(a)})("keydown",function(a){return o.onKeyDown(a)})("focus",function(){return o.onInputFocus()})("blur",function(){return o.onInputBlur()}),d(),Rt(),d(),M(43,j4,3,0,"button",38),M(44,$4,3,3,"button",39),l(45,"button",40),k("click",function(){return o.submitTask()}),M(46,z4,2,0,"span",41),M(47,B4,2,0,"span",42),d()(),l(48,"div",43)(49,"div",44)(50,"div",45)(51,"button",46),k("mousedown",function(a){return a.preventDefault()})("click",function(a){return o.setProfile("flash",a)}),l(52,"span",47),u(53,"bolt"),d(),l(54,"span",48),u(55,"Flash"),d()(),l(56,"button",49),k("mousedown",function(a){return a.preventDefault()})("click",function(a){return o.setProfile("pro",a)}),l(57,"span",50),u(58,"psychology"),d(),l(59,"span",48),u(60,"Pro"),d()()()()()()(),M(61,H4,3,3,"button",51),d()()(),l(62,"div",52),k("mousedown",function(a){return o.onDragStart(a)}),$(63,"div",53),d(),l(64,"aside",54),$(65,"app-chat-interface"),d(),$(66,"app-floating-video-player"),d()}e&2&&(w("is-resizing",o.isDragging()),g(3),w("is-expanded",o.isBarExpanded())("is-dormant",!o.isBarExpanded())("is-focused",o.isInputFocused())("has-text",!!o.taskInput.trim())("is-running",o.isTaskRunning()),g(),b(o.errorMessage()?4:-1),g(3),w("is-pro",o.selectedProfile()==="pro"),g(34),_r("ngModel",o.taskInput),R("disabled",o.isSubmitting())("placeholder",o.selectedProfile()==="pro"?"Pro: plans first, checks results and recovers from blocked steps. For long or complex tasks":"Flash: fast single-look loop for everyday app tasks"),Ft(),g(2),b(o.taskInput.trim()&&!o.isSubmitting()?43:-1),g(),b(o.isTaskRunning()?44:-1),g(),w("has-content",!!o.taskInput.trim()),R("disabled",!o.taskInput.trim()||o.isSubmitting())("title",o.isSubmitting()?"Starting task...":"Start task (Enter)"),g(),b(o.isSubmitting()?46:-1),g(),b(o.isSubmitting()?-1:47),g(4),w("active",o.selectedProfile()==="flash"),g(5),w("active",o.selectedProfile()==="pro"),g(5),b(o.isTaskRunning()?61:-1),g(3),Se("width",o.rightPanelWidth(),"px"))},dependencies:[Qt,zr,Nd,ws,Wd,qr,Kd],styles:["[_nghost-%COMP%]{display:block;height:100vh;width:100vw;overflow:hidden;font-family:Google Sans Text,Google Sans,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif}.workspace-container[_ngcontent-%COMP%]{position:relative;display:flex;height:100vh;width:100vw;background-color:#e2e5ea;overflow:hidden}.workspace-container.is-resizing[_ngcontent-%COMP%]{cursor:col-resize;-webkit-user-select:none;user-select:none}.workspace-container[_ngcontent-%COMP%] .glass-panel[_ngcontent-%COMP%]{position:relative;z-index:1;background:#f4fafb;border:none;box-shadow:none}.workspace-container[_ngcontent-%COMP%] .left-panel[_ngcontent-%COMP%]{flex:1 0 500px;display:flex;flex-direction:column;overflow:hidden;background:#f4fafb;border-right:1px solid #e2e8f0;border-left:none;border-top:none;border-bottom:none;min-width:450px;height:100%}.workspace-container[_ngcontent-%COMP%] .right-panel[_ngcontent-%COMP%]{flex:0 1 auto;min-width:250px;max-width:100%;padding:0;border:none;background-color:#fff;box-shadow:-6px 0 24px #00000008;height:100%;display:flex;flex-direction:column;box-sizing:border-box;z-index:2}.workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%]{width:12px;cursor:col-resize;display:flex;align-items:center;justify-content:center;z-index:10;transition:background .2s ease;margin:0 -6px}.workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%]:hover, .workspace-container.is-resizing[_ngcontent-%COMP%] .workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%]{background:#ffffff26}.workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%]:hover .resizer-handle[_ngcontent-%COMP%], .workspace-container.is-resizing[_ngcontent-%COMP%] .workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%] .resizer-handle[_ngcontent-%COMP%]{background:#5e72e4cc;height:60px}.workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%] .resizer-handle[_ngcontent-%COMP%]{width:4px;height:40px;background:#00000026;border-radius:4px;transition:background .2s ease,height .2s ease}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%]{position:absolute;bottom:18px;left:50%;transform:translate(-50%);width:100%;max-width:min(680px,100% - 36px);z-index:50;display:flex;flex-direction:column;align-items:center;pointer-events:none;transition:all .25s cubic-bezier(.16,1,.3,1)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .floating-dock-toast[_ngcontent-%COMP%]{pointer-events:auto;margin-bottom:8px;display:flex;align-items:center;gap:8px;padding:7px 14px;border-radius:12px;font-size:12.5px;font-weight:500;box-shadow:0 8px 24px -4px #ef444426;animation:_ngcontent-%COMP%_slideUpFade .2s ease-out;max-width:90%}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .floating-dock-toast.error[_ngcontent-%COMP%]{background:#fef2f2e0;backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%);border:1px solid rgba(254,202,202,.9);color:#991b1b}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .floating-dock-toast.error[_ngcontent-%COMP%] .toast-icon[_ngcontent-%COMP%]{font-size:16px;color:#ef4444;flex-shrink:0}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .floating-dock-toast.error[_ngcontent-%COMP%] .toast-text[_ngcontent-%COMP%]{flex:1;line-height:1.4}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .floating-dock-toast.error[_ngcontent-%COMP%] .btn-toast-close[_ngcontent-%COMP%]{background:transparent;border:none;padding:2px;cursor:pointer;color:#991b1b;display:flex;align-items:center;justify-content:center;border-radius:4px;opacity:.7;transition:opacity .15s ease}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .floating-dock-toast.error[_ngcontent-%COMP%] .btn-toast-close[_ngcontent-%COMP%]:hover{opacity:1;background:#0000000d}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .floating-dock-toast.error[_ngcontent-%COMP%] .btn-toast-close[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:15px}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .floating-dock-row[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;pointer-events:none;transition:gap .32s cubic-bezier(.16,1,.3,1)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .standalone-stop-btn[_ngcontent-%COMP%]{pointer-events:auto;display:flex;align-items:center;justify-content:center;width:34px;height:34px;min-width:34px;border-radius:50%;border:1px solid rgba(255,255,255,.85);background:#ef4444e6;backdrop-filter:blur(24px) saturate(190%) brightness(105%);-webkit-backdrop-filter:blur(24px) saturate(190%) brightness(105%);color:#fff;box-shadow:0 6px 18px -2px #ef444466,inset 0 1px 1.5px #ffffffb3;cursor:pointer;outline:none;flex-shrink:0;transition:opacity .28s cubic-bezier(.16,1,.3,1),transform .28s cubic-bezier(.16,1,.3,1),width .28s cubic-bezier(.16,1,.3,1),min-width .28s cubic-bezier(.16,1,.3,1),margin .28s cubic-bezier(.16,1,.3,1),background .2s ease,box-shadow .2s ease;animation:_ngcontent-%COMP%_popIn .25s cubic-bezier(.16,1,.3,1)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .standalone-stop-btn[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:17px;line-height:1}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .standalone-stop-btn[_ngcontent-%COMP%]:hover:not(:disabled){background:#dc2626;transform:scale(1.1);box-shadow:0 8px 22px #ef44448c,inset 0 1px 1.5px #ffffffe6}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .standalone-stop-btn[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.93)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .standalone-stop-btn[_ngcontent-%COMP%]:disabled{opacity:.6;cursor:not-allowed}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%]{pointer-events:auto;position:relative;width:100%;border-radius:18px;box-sizing:border-box;overflow:hidden;transition:max-width .32s cubic-bezier(.16,1,.3,1),width .32s cubic-bezier(.16,1,.3,1),border-radius .28s cubic-bezier(.16,1,.3,1),box-shadow .28s ease,background .28s ease,transform .28s cubic-bezier(.16,1,.3,1),border-color .28s ease}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%]{position:absolute;bottom:0;left:0;right:0;height:100%;pointer-events:none;border-radius:inherit;overflow:hidden;z-index:0;opacity:.78;transition:opacity .35s ease,filter .35s ease}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-stop-1[_ngcontent-%COMP%]{stop-color:#3b82f6;stop-opacity:.65}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-stop-2[_ngcontent-%COMP%]{stop-color:#8b5cf6;stop-opacity:.7}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-stop-3[_ngcontent-%COMP%]{stop-color:#f59e0b;stop-opacity:.65}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-stop-4[_ngcontent-%COMP%]{stop-color:#06b6d4;stop-opacity:.6}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container.is-pro[_ngcontent-%COMP%] .wave-stop-1[_ngcontent-%COMP%]{stop-color:#7c3aed;stop-opacity:.7}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container.is-pro[_ngcontent-%COMP%] .wave-stop-2[_ngcontent-%COMP%]{stop-color:#ec4899;stop-opacity:.75}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container.is-pro[_ngcontent-%COMP%] .wave-stop-3[_ngcontent-%COMP%]{stop-color:#6366f1;stop-opacity:.65}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container.is-pro[_ngcontent-%COMP%] .wave-stop-4[_ngcontent-%COMP%]{stop-color:#a855f7;stop-opacity:.7}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-glow-ambient[_ngcontent-%COMP%]{position:absolute;bottom:-8px;left:5%;right:5%;height:30px;border-radius:50%;background:radial-gradient(ellipse at center,rgba(99,102,241,.4) 0%,rgba(245,158,11,.2) 50%,transparent 80%);filter:blur(16px);opacity:.7;animation:_ngcontent-%COMP%_glowBreathe 5s ease-in-out infinite alternate}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container.is-pro[_ngcontent-%COMP%] .wave-glow-ambient[_ngcontent-%COMP%]{background:radial-gradient(ellipse at center,rgba(168,85,247,.45) 0%,rgba(236,72,153,.25) 50%,transparent 80%)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-tracks-wrapper[_ngcontent-%COMP%]{position:absolute;bottom:0;left:0;width:100%;height:22px;overflow:hidden;mask-image:linear-gradient(to top,rgba(0,0,0,.9) 0%,rgba(0,0,0,.5) 60%,transparent 100%);-webkit-mask-image:linear-gradient(to top,rgba(0,0,0,.9) 0%,rgba(0,0,0,.5) 60%,transparent 100%)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-tracks-wrapper[_ngcontent-%COMP%] .liquid-wave[_ngcontent-%COMP%]{position:absolute;bottom:0;left:0;width:200%;height:100%;will-change:transform;filter:blur(8px)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-tracks-wrapper[_ngcontent-%COMP%] .liquid-wave.wave-back[_ngcontent-%COMP%]{opacity:.45;animation:_ngcontent-%COMP%_waveSlide 12s ease-in-out infinite alternate}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-tracks-wrapper[_ngcontent-%COMP%] .liquid-wave.wave-mid[_ngcontent-%COMP%]{opacity:.6;animation:_ngcontent-%COMP%_waveSlideReverse 9s ease-in-out infinite alternate}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-tracks-wrapper[_ngcontent-%COMP%] .liquid-wave.wave-front[_ngcontent-%COMP%]{opacity:.75;animation:_ngcontent-%COMP%_waveSlide 6.5s ease-in-out infinite alternate}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-dormant[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%]{max-width:160px;width:160px;margin:0;background:#ffffffa6;backdrop-filter:blur(26px) saturate(190%) brightness(104%);-webkit-backdrop-filter:blur(26px) saturate(190%) brightness(104%);border:1px solid rgba(255,255,255,.85);border-radius:17px;box-shadow:0 6px 18px -2px #0f172a12,inset 0 1px 1.5px #fffffff2,inset 0 -1px 1px #ffffff4d;cursor:pointer;opacity:.92;transform:translateY(2px)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-dormant[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%]{opacity:.78}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-dormant[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-tracks-wrapper[_ngcontent-%COMP%]{height:12px}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-dormant[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%]:hover{opacity:1;transform:translateY(0);background:#ffffffd1;border-color:#fff;box-shadow:0 8px 24px -2px #0f172a1f,inset 0 1px 1.5px #fff}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-dormant[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%]:hover .dock-wave-container[_ngcontent-%COMP%]{opacity:.95;filter:drop-shadow(0 0 6px rgba(99,102,241,.35))}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-dormant[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%] .capsule-peek-view[_ngcontent-%COMP%]{display:flex;opacity:1}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-dormant[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%]{display:none;opacity:0}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .capsule-peek-view[_ngcontent-%COMP%]{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;padding:6px 14px;min-height:34px;box-sizing:border-box;-webkit-user-select:none;user-select:none}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .capsule-peek-view[_ngcontent-%COMP%] .capsule-placeholder[_ngcontent-%COMP%]{color:#475569;font-size:12px;font-weight:500;letter-spacing:.1px;white-space:nowrap;text-align:center}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-expanded[_ngcontent-%COMP%] .floating-dock-row[_ngcontent-%COMP%]{gap:0}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-expanded[_ngcontent-%COMP%] .standalone-stop-btn[_ngcontent-%COMP%]{opacity:0;width:0;min-width:0;margin:0;padding:0;border-width:0;transform:scale(.5);pointer-events:none}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-expanded[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%]{max-width:100%;width:100%;background:#ffffffad;backdrop-filter:blur(32px) saturate(210%) brightness(105%);-webkit-backdrop-filter:blur(32px) saturate(210%) brightness(105%);border:1px solid rgba(255,255,255,.82);box-shadow:0 16px 44px -8px #0f172a1f,0 2px 8px #00000005,inset 0 1.5px 2px #fffffff2,inset 0 -1px 2px #ffffff4d;opacity:1;transform:translateY(0)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-expanded[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%]{opacity:.88}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-expanded[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%] .wave-tracks-wrapper[_ngcontent-%COMP%]{height:22px}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-expanded[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%] .capsule-peek-view[_ngcontent-%COMP%]{display:none;opacity:0}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-expanded[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%]{display:block;opacity:1;animation:_ngcontent-%COMP%_cardFadeIn .25s cubic-bezier(.16,1,.3,1)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-focused[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%]{background:#ffffffc7;backdrop-filter:blur(36px) saturate(220%) brightness(106%);-webkit-backdrop-filter:blur(36px) saturate(220%) brightness(106%);border-color:#3b82f68c;box-shadow:0 20px 48px -6px #2563eb29,0 0 0 2.5px #3b82f62e,inset 0 1.5px 2px #fff}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper.is-focused[_ngcontent-%COMP%] .floating-dock-card[_ngcontent-%COMP%] .dock-wave-container[_ngcontent-%COMP%]{opacity:1;filter:drop-shadow(0 0 8px rgba(59,130,246,.35))}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%]{position:relative;z-index:1;display:flex;flex-direction:column;width:100%}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;padding:8px 10px 3px 14px;min-height:48px;box-sizing:border-box}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .leading-status-icon[_ngcontent-%COMP%]{width:14px;height:14px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .leading-status-icon[_ngcontent-%COMP%] .pulse-indicator-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;background:#ef4444;box-shadow:0 0 #ef444499;animation:_ngcontent-%COMP%_pulseDot 1.4s infinite}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .input-content-area[_ngcontent-%COMP%]{flex:1;min-width:0;display:flex;align-items:center}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .input-content-area[_ngcontent-%COMP%] .dock-textarea[_ngcontent-%COMP%]{width:100%;border:none;outline:none;background:transparent;resize:none;font-family:inherit;font-size:13.5px;font-weight:450;line-height:1.5;color:#0f172a;padding:3px 0;max-height:120px;box-sizing:border-box;display:block}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .input-content-area[_ngcontent-%COMP%] .dock-textarea[_ngcontent-%COMP%]::placeholder{color:#64748b;font-size:12.5px;font-weight:400;transition:color .15s ease}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .input-content-area[_ngcontent-%COMP%] .dock-textarea[_ngcontent-%COMP%]:disabled{opacity:.6;cursor:not-allowed}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn[_ngcontent-%COMP%]{border-radius:50%;display:flex;align-items:center;justify-content:center;border:none;cursor:pointer;outline:none;flex-shrink:0;transition:background .18s cubic-bezier(.16,1,.3,1),color .18s cubic-bezier(.16,1,.3,1),transform .18s cubic-bezier(.16,1,.3,1),box-shadow .18s cubic-bezier(.16,1,.3,1),border-color .18s cubic-bezier(.16,1,.3,1)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn[_ngcontent-%COMP%] .material-symbols-outlined[_ngcontent-%COMP%]{font-size:18px;line-height:1}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn[_ngcontent-%COMP%] .spinning-icon[_ngcontent-%COMP%]{font-size:17px;animation:_ngcontent-%COMP%_spin 1s linear infinite}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-clear[_ngcontent-%COMP%]{width:26px;height:26px;background:#ffffff73;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.6);color:#64748b}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-clear[_ngcontent-%COMP%]:hover{background:#ffffffbf;color:#0f172a}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-stop[_ngcontent-%COMP%]{width:36px;height:36px;background:#ef4444e6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#fff;border:1px solid rgba(255,255,255,.35);box-shadow:0 4px 12px #ef44444d;animation:_ngcontent-%COMP%_popIn .2s cubic-bezier(.16,1,.3,1)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-stop[_ngcontent-%COMP%]:hover:not(:disabled){background:#dc2626;transform:scale(1.05);box-shadow:0 6px 16px #ef444466}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-stop[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.95)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-stop[_ngcontent-%COMP%]:disabled{opacity:.6;cursor:not-allowed}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-send[_ngcontent-%COMP%]{width:36px;height:36px;background:#0f172ae0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.25);color:#fff;box-shadow:0 4px 14px #0f172a33,inset 0 1px 1px #ffffff40}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-send[_ngcontent-%COMP%]:disabled{background:#e2e8f099;color:#94a3b8;cursor:not-allowed;box-shadow:none;border-color:#ffffff80;transform:none}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-send.has-content[_ngcontent-%COMP%]:not(:disabled){background:linear-gradient(135deg,#1e293bf2,#0f172afa);box-shadow:0 4px 14px #0f172a40,inset 0 1px 1px #ffffff4d}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-send.has-content[_ngcontent-%COMP%]:not(:disabled):hover{background:linear-gradient(135deg,#2563eb,#1d4ed8);transform:scale(1.05);box-shadow:0 6px 18px #2563eb59}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-main-input-row[_ngcontent-%COMP%] .dock-circle-btn.btn-send[_ngcontent-%COMP%]:active:not(:disabled){transform:scale(.95)}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding:3px 14px 8px;box-sizing:border-box}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-left-group[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-left-group[_ngcontent-%COMP%] .model-profile-toggle[_ngcontent-%COMP%]{display:inline-flex;align-items:center;background:#ffffff73;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border:1px solid rgba(255,255,255,.65);box-shadow:inset 0 1px 1px #fffc,0 1px 3px #00000008;border-radius:8px;padding:2px;gap:2px}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-left-group[_ngcontent-%COMP%] .model-profile-toggle[_ngcontent-%COMP%] .profile-toggle-pill[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:3.5px;width:62px;min-width:62px;height:22px;border-radius:6px;border:none;background:transparent;color:#64748b;font-family:inherit;font-size:11px;font-weight:550;cursor:pointer;transition:color .16s cubic-bezier(.16,1,.3,1),background .16s cubic-bezier(.16,1,.3,1),box-shadow .16s cubic-bezier(.16,1,.3,1);outline:none;-webkit-user-select:none;user-select:none;box-sizing:border-box}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-left-group[_ngcontent-%COMP%] .model-profile-toggle[_ngcontent-%COMP%] .profile-toggle-pill[_ngcontent-%COMP%] .pill-icon[_ngcontent-%COMP%]{font-size:13px;line-height:1;flex-shrink:0}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-left-group[_ngcontent-%COMP%] .model-profile-toggle[_ngcontent-%COMP%] .profile-toggle-pill[_ngcontent-%COMP%] .pill-label[_ngcontent-%COMP%]{line-height:1}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-left-group[_ngcontent-%COMP%] .model-profile-toggle[_ngcontent-%COMP%] .profile-toggle-pill[_ngcontent-%COMP%]:hover:not(.active){color:#1e293b;background:#ffffffa6}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-left-group[_ngcontent-%COMP%] .model-profile-toggle[_ngcontent-%COMP%] .profile-toggle-pill.active[_ngcontent-%COMP%]{background:#ffffffeb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#0f172a;font-weight:700;box-shadow:0 1.5px 4px #00000014,inset 0 1px 1.5px #fff}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-left-group[_ngcontent-%COMP%] .model-profile-toggle[_ngcontent-%COMP%] .profile-toggle-pill.active[_ngcontent-%COMP%] .icon-flash[_ngcontent-%COMP%]{color:#d97706}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-left-group[_ngcontent-%COMP%] .model-profile-toggle[_ngcontent-%COMP%] .profile-toggle-pill.active[_ngcontent-%COMP%] .icon-pro[_ngcontent-%COMP%]{color:#7c3aed}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-right-status[_ngcontent-%COMP%] .running-status-pill[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:4.5px;font-size:10.5px;font-weight:600;color:#dc2626;background:#fee2e2b3;padding:2px 7px;border-radius:10px}.workspace-container[_ngcontent-%COMP%] .workspace-floating-bar-wrapper[_ngcontent-%COMP%] .expanded-card-content[_ngcontent-%COMP%] .card-footer-row[_ngcontent-%COMP%] .footer-right-status[_ngcontent-%COMP%] .running-status-pill[_ngcontent-%COMP%] .running-pulse-dot[_ngcontent-%COMP%]{width:5.5px;height:5.5px;border-radius:50%;background:#ef4444;animation:_ngcontent-%COMP%_pulseDot 1.2s infinite}@media(max-width:1150px){.workspace-container[_ngcontent-%COMP%] .right-panel[_ngcontent-%COMP%], .workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%]{display:none!important}.workspace-container[_ngcontent-%COMP%] .left-panel[_ngcontent-%COMP%]{border-right:none!important;width:100%!important;flex:1 1 100%!important;min-width:0!important}}@keyframes _ngcontent-%COMP%_popIn{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes _ngcontent-%COMP%_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes _ngcontent-%COMP%_slideUpFade{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes _ngcontent-%COMP%_cardFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes _ngcontent-%COMP%_fadeIn{0%{opacity:0}to{opacity:1}}@keyframes _ngcontent-%COMP%_pulseDot{0%{transform:scale(.95);box-shadow:0 0 #ef4444b3}70%{transform:scale(1);box-shadow:0 0 0 6px #ef444400}to{transform:scale(.95);box-shadow:0 0 #ef444400}}@keyframes _ngcontent-%COMP%_waveSlide{0%{transform:translateZ(0)}to{transform:translate3d(-50%,0,0)}}@keyframes _ngcontent-%COMP%_waveSlideReverse{0%{transform:translate3d(-50%,0,0)}to{transform:translateZ(0)}}@keyframes _ngcontent-%COMP%_glowBreathe{0%{opacity:.55;transform:scaleX(.92)}to{opacity:.95;transform:scaleX(1.08)}}@media(prefers-reduced-motion:reduce){.liquid-wave[_ngcontent-%COMP%], .wave-glow-ambient[_ngcontent-%COMP%], .pulse-indicator-dot[_ngcontent-%COMP%], .running-pulse-dot[_ngcontent-%COMP%]{animation:none!important}}"]})};var U4=(n,t)=>[n,t];function G4(n,t){if(n&1&&(l(0,"option",8),u(1),it(2,"date"),d()),n&2){let e=t.$implicit;R("value",e.session_id),g(),mr(" ",e.initial_goal||"Unnamed Goal"," (",e.device_serial?e.device_serial+" \xB7 ":"","",Et(2,4,e.start_time*1e3,"short"),") ")}}function q4(n,t){n&1&&(l(0,"div",11)(1,"div",13),u(2,"\u{1F4E1}"),d(),l(3,"h3"),u(4,"No Stream Activity Selected"),d(),l(5,"p"),u(6,"Please select a running session from the dropdown above to view real-time log payloads."),d()())}function W4(n,t){if(n&1&&(l(0,"div",22)(1,"div",27),u(2,"\u{1F4AC} Message to User / Summary:"),d(),l(3,"div",28),u(4),d()()),n&2){let e=m(2).$implicit;g(4),O(e.data.summary)}}function K4(n,t){if(n&1&&(l(0,"details",23)(1,"summary",29),u(2,"\u{1F9E0} Model Thinking Process (Click to expand)"),d(),l(3,"div",30),u(4),d()()),n&2){let e=m(2).$implicit;g(4),O(e.data.operator_native_thinking)}}function Y4(n,t){if(n&1&&(l(0,"details",24)(1,"summary",29),u(2,"\u{1F4DD} Raw Plan / Thoughts (Click to expand)"),d(),l(3,"div",31),u(4),d()()),n&2){let e=m(2).$implicit;g(4),O(e.data.operator_raw_thinking)}}function Z4(n,t){if(n&1&&(l(0,"details",25)(1,"summary",29),u(2,"\u{1F6E0}\uFE0F Tool Call Details (Click to expand)"),d(),l(3,"div",32)(4,"pre",33)(5,"code"),u(6),d()()()()),n&2){let e=m(2).$implicit,o=m(2);R("open",o.isShortContent(e.data.action_taken)),g(6),O(o.formatJson(e.data.action_taken))}}function Q4(n,t){if(n&1&&(l(0,"details",26)(1,"summary",29),u(2,"\u2713 Execution Result (Click to expand)"),d(),l(3,"div",32)(4,"pre",33)(5,"code"),u(6),d()()()()),n&2){let e=m(2).$implicit,o=m(2);g(6),O(o.formatJson(e.data.last_execution_result))}}function J4(n,t){if(n&1&&(l(0,"div",20),M(1,W4,5,1,"div",22),M(2,K4,5,1,"details",23),M(3,Y4,5,1,"details",24),M(4,Z4,7,2,"details",25),M(5,Q4,7,1,"details",26),d()),n&2){let e=m().$implicit;g(),b(e.data.summary?1:-1),g(),b(e.data.operator_native_thinking?2:-1),g(),b(e.data.operator_raw_thinking?3:-1),g(),b(e.data.action_taken?4:-1),g(),b(e.data.last_execution_result?5:-1)}}function X4(n,t){if(n&1&&(l(0,"div",21)(1,"details",34)(2,"summary",29),u(3,"\u{1F4C4} Raw Payload Data (Click to expand)"),d(),l(4,"div",32)(5,"pre",33)(6,"code"),u(7),d()()()()()),n&2){let e=m().$implicit,o=m(2);g(),R("open",o.isShortContent(e.data)),g(6),O(o.formatJson(e.data))}}function e5(n,t){if(n&1&&(l(0,"div",14)(1,"div",15)(2,"div",16)(3,"span",17),u(4),d(),l(5,"span",18),u(6),d()(),l(7,"span",19),u(8),it(9,"date"),d()(),M(10,J4,6,5,"div",20),M(11,X4,8,2,"div",21),d()),n&2){let e=t.$implicit,o=t.$index,i=m(2);R("ngClass",Gp(10,U4,"type-"+e.type,i.isStepEvent(e.type)?"step-event-card":"raw-event-card")),g(4),V("#",o+1),g(),R("ngClass",e.type),g(),O(e.type),g(2),O(Et(9,7,e.timestamp,"HH:mm:ss.SSS")),g(2),b(i.isStepEvent(e.type)?10:-1),g(),b(i.isStepEvent(e.type)?-1:11)}}function t5(n,t){if(n&1&&(l(0,"div",12),G(1,e5,12,13,"div",14,Ie),d()),n&2){let e=m();g(),q(e.agentService.sessionLogs())}}var Zd=class n{agentService=D(It);onSessionChange(t){let o=t.target.value;o&&this.agentService.selectSession(o,!0)}isStepEvent(t){return t==="step_recorded"||t==="step_updated"}isShortContent(t){return t?(typeof t=="string"?t:JSON.stringify(t)).length<200:!0}formatJson(t){if(typeof t=="string")try{return JSON.stringify(JSON.parse(t),null,2)}catch(e){return t}return JSON.stringify(t,null,2)}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=Ge({type:n,selectors:[["app-legacy-agent-stream"]],decls:20,vars:3,consts:[[1,"agent-stream-container"],[1,"stream-header"],[1,"header-title"],[1,"subtitle"],[1,"session-selector-wrapper"],["for","session-select"],["id","session-select",1,"session-dropdown",3,"change","value"],["value","","disabled","","selected",""],[3,"value"],[1,"btn-refresh",3,"click"],[1,"stream-logs-content"],[1,"empty-state"],[1,"logs-list"],[1,"empty-icon"],[1,"log-card",3,"ngClass"],[1,"log-card-header"],[1,"badge-group"],[1,"index-badge"],[1,"type-badge",3,"ngClass"],[1,"timestamp"],[1,"log-card-body","step-body"],[1,"log-card-body","raw-body"],[1,"step-summary-section"],[1,"thinking-details"],[1,"planning-details"],[1,"tool-details",3,"open"],[1,"result-details"],[1,"section-title"],[1,"summary-bubble"],[1,"details-summary"],[1,"details-content","thinking-text"],[1,"details-content","planning-text"],[1,"details-content"],[1,"json-code"],[1,"raw-details",3,"open"]],template:function(e,o){e&1&&(l(0,"div",0)(1,"header",1)(2,"div",2)(3,"h2"),u(4,"\u{1F463} Real-time Agent Stream (Legacy Card View)"),d(),l(5,"p",3),u(6,"Select a session to monitor raw agent activity"),d()(),l(7,"div",4)(8,"label",5),u(9,"Active Session:"),d(),l(10,"select",6),k("change",function(r){return o.onSessionChange(r)}),l(11,"option",7),u(12,"-- Select a Session --"),d(),G(13,G4,3,7,"option",8,Ie),d(),l(15,"button",9),k("click",function(){return o.agentService.fetchSessions()}),u(16,"\u{1F504} Refresh"),d()()(),l(17,"main",10),M(18,q4,7,0,"div",11),M(19,t5,3,0,"div",12),d()()),e&2&&(g(10),R("value",o.agentService.currentSessionId()||""),g(3),q(o.agentService.sessions()),g(5),b(o.agentService.sessionLogs().length===0?18:-1),g(),b(o.agentService.sessionLogs().length>0?19:-1))},dependencies:[No,ki,Qt,cP,dP,Ei],styles:["[_nghost-%COMP%]{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.agent-stream-container[_ngcontent-%COMP%]{display:flex;flex-direction:column;height:100%;background:#fff6;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);box-sizing:border-box}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;padding:20px 24px;border-bottom:1px solid rgba(0,0,0,.08);background:#fff9;flex-wrap:wrap;gap:16px}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%] .header-title[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{margin:0 0 4px;font-size:20px;font-weight:700;color:#1f2937;letter-spacing:-.5px}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%] .header-title[_ngcontent-%COMP%] .subtitle[_ngcontent-%COMP%]{margin:0;font-size:13px;color:#4b5563}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%] .session-selector-wrapper[_ngcontent-%COMP%]{display:flex;align-items:center;gap:12px}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%] .session-selector-wrapper[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{font-size:13.5px;font-weight:600;color:#1f2937}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%] .session-selector-wrapper[_ngcontent-%COMP%] .session-dropdown[_ngcontent-%COMP%]{padding:8px 12px;border:1px solid rgba(0,0,0,.12);border-radius:8px;font-size:13.5px;background-color:#fff;outline:none;color:#1f2937;min-width:250px;max-width:400px;cursor:pointer;transition:border-color .2s}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%] .session-selector-wrapper[_ngcontent-%COMP%] .session-dropdown[_ngcontent-%COMP%]:focus{border-color:#3b82f6}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%] .session-selector-wrapper[_ngcontent-%COMP%] .btn-refresh[_ngcontent-%COMP%]{padding:8px 14px;background:#fff;border:1px solid rgba(0,0,0,.12);border-radius:8px;font-size:13px;font-weight:600;color:#1f2937;cursor:pointer;display:flex;align-items:center;gap:6px;transition:background .2s,transform .1s}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%] .session-selector-wrapper[_ngcontent-%COMP%] .btn-refresh[_ngcontent-%COMP%]:hover{background:#f3f4f6}.agent-stream-container[_ngcontent-%COMP%] .stream-header[_ngcontent-%COMP%] .session-selector-wrapper[_ngcontent-%COMP%] .btn-refresh[_ngcontent-%COMP%]:active{transform:scale(.98)}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]{flex:1;overflow-y:auto;padding:24px;background:#f9fafb4d}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]::-webkit-scrollbar{width:6px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]::-webkit-scrollbar-track{background:transparent}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb{background:#00000026;border-radius:10px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover{background:#00000040}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%]{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:40px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%]{font-size:48px;margin-bottom:16px;opacity:.8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{margin:0 0 8px;font-size:18px;font-weight:600;color:#1f2937}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{margin:0;font-size:14px;color:#4b5563;max-width:320px;line-height:1.5}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:16px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%]{background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:12px;padding:16px 20px;box-shadow:0 4px 6px -1px #00000003,0 2px 4px -1px #00000002;display:flex;flex-direction:column;gap:12px;transition:transform .2s,box-shadow .2s}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%]:hover{transform:translateY(-1px);box-shadow:0 10px 15px -3px #00000005,0 4px 6px -2px #00000003}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%] .badge-group[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%] .badge-group[_ngcontent-%COMP%] .index-badge[_ngcontent-%COMP%]{font-size:11px;font-weight:700;color:#9ca3af;font-family:monospace}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%] .badge-group[_ngcontent-%COMP%] .type-badge[_ngcontent-%COMP%]{font-size:10px;font-weight:800;text-transform:uppercase;padding:2.5px 7px;border-radius:9999px;letter-spacing:.5px;font-family:monospace}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%] .badge-group[_ngcontent-%COMP%] .type-badge.llm_stream[_ngcontent-%COMP%]{background:#e0f2fe;color:#0369a1}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%] .badge-group[_ngcontent-%COMP%] .type-badge.trace_recorded[_ngcontent-%COMP%]{background:#f3e8ff;color:#6b21a8}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%] .badge-group[_ngcontent-%COMP%] .type-badge.step_recorded[_ngcontent-%COMP%]{background:#ecfdf5;color:#047857}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%] .badge-group[_ngcontent-%COMP%] .type-badge.step_updated[_ngcontent-%COMP%]{background:#fef3c7;color:#b45309}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%] .badge-group[_ngcontent-%COMP%] .type-badge.background_tasks_updated[_ngcontent-%COMP%]{background:#fff1f2;color:#be123c}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-header[_ngcontent-%COMP%] .timestamp[_ngcontent-%COMP%]{font-size:11.5px;color:#9ca3af;font-family:monospace}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:16px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] .step-summary-section[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%]{font-size:11px;font-weight:700;color:#4b5563;margin-bottom:6px;text-transform:uppercase;letter-spacing:.5px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] .step-summary-section[_ngcontent-%COMP%] .summary-bubble[_ngcontent-%COMP%]{background:#f1f5f9;border:1px solid rgba(0,0,0,.05);border-left:4px solid #475569;border-radius:8px;padding:12px 16px;font-size:13.5px;line-height:1.5;color:#1e293b}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details[_ngcontent-%COMP%]{border:1px solid rgba(0,0,0,.06);border-radius:8px;background:#fafafa;overflow:hidden;transition:border-color .2s}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details[open][_ngcontent-%COMP%]{border-color:#0000001f}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details[open][_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{border-bottom:1px solid rgba(0,0,0,.06);background:#00000005}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{padding:10px 14px;font-size:12.5px;font-weight:700;color:#4b5563;cursor:pointer;-webkit-user-select:none;user-select:none;outline:none;background:#fff;transition:background .2s}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]:hover{background:#00000003}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details[_ngcontent-%COMP%] .details-content[_ngcontent-%COMP%]{padding:14px;font-size:13px;line-height:1.6;color:#334155}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details[_ngcontent-%COMP%] .details-content.thinking-text[_ngcontent-%COMP%]{background:#f0fdf4;color:#14532d;white-space:pre-wrap;font-family:inherit}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details[_ngcontent-%COMP%] .details-content.planning-text[_ngcontent-%COMP%]{background:#f8fafc;color:#334155;white-space:pre-wrap;font-family:inherit}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details.thinking-details[_ngcontent-%COMP%]{border-left:4px solid #16a34a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details.thinking-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{color:#16a34a}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details.planning-details[_ngcontent-%COMP%]{border-left:4px solid #4f46e5}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details.planning-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{color:#4f46e5}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details.tool-details[_ngcontent-%COMP%]{border-left:4px solid #2563eb}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details.tool-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{color:#2563eb}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details.result-details[_ngcontent-%COMP%]{border-left:4px solid #0891b2}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.step-body[_ngcontent-%COMP%] details.result-details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{color:#0891b2}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.raw-body[_ngcontent-%COMP%] details[_ngcontent-%COMP%]{border:1px solid rgba(0,0,0,.06);border-radius:8px;overflow:hidden}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.raw-body[_ngcontent-%COMP%] details[_ngcontent-%COMP%] .details-summary[_ngcontent-%COMP%]{padding:10px 14px;font-size:12px;font-weight:600;color:#4b5563;cursor:pointer;outline:none;background:#fff}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body.raw-body[_ngcontent-%COMP%] details[_ngcontent-%COMP%] .details-content[_ngcontent-%COMP%]{padding:12px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body[_ngcontent-%COMP%] .json-code[_ngcontent-%COMP%]{margin:0;background:#1e293b;color:#f8fafc;padding:14px 18px;border-radius:8px;font-family:Fira Code,Roboto Mono,monospace;font-size:12.5px;line-height:1.5;overflow-x:auto;white-space:pre-wrap;word-break:break-all}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body[_ngcontent-%COMP%] .json-code[_ngcontent-%COMP%]::-webkit-scrollbar{height:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body[_ngcontent-%COMP%] .json-code[_ngcontent-%COMP%]::-webkit-scrollbar-thumb{background:#fff3;border-radius:4px}.agent-stream-container[_ngcontent-%COMP%] .stream-logs-content[_ngcontent-%COMP%] .logs-list[_ngcontent-%COMP%] .log-card[_ngcontent-%COMP%] .log-card-body[_ngcontent-%COMP%] .json-code[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover{background:#ffffff4d}"],changeDetection:1})};var Qd=class n{rightPanelWidth=typeof window<"u"?Math.round(window.innerWidth/3):450;isDragging=!1;onDragStart(t){this.isDragging=!0,t.preventDefault()}onMouseMove(t){if(!this.isDragging)return;let e=window.innerWidth-t.clientX,o=300,i=window.innerWidth-300;e>=o&&e<=i&&(this.rightPanelWidth=e)}onMouseUp(){this.isDragging=!1}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=Ge({type:n,selectors:[["app-legacy-workspace"]],hostBindings:function(e,o){e&1&&k("mousemove",function(r){return o.onMouseMove(r)},hl)("mouseup",function(){return o.onMouseUp()},hl)},decls:11,vars:4,consts:[[1,"workspace-container"],[1,"aurora-background"],[1,"glow","glow-1"],[1,"glow","glow-2"],[1,"glow","glow-3"],[1,"left-panel","glass-panel"],[1,"resizer",3,"mousedown"],[1,"resizer-handle"],[1,"right-panel"]],template:function(e,o){e&1&&(l(0,"div",0)(1,"div",1),$(2,"div",2)(3,"div",3)(4,"div",4),d(),l(5,"main",5),$(6,"app-legacy-agent-stream"),d(),l(7,"div",6),k("mousedown",function(r){return o.onDragStart(r)}),$(8,"div",7),d(),l(9,"aside",8),$(10,"app-chat-interface"),d()()),e&2&&(w("is-resizing",o.isDragging),g(9),Se("width",o.rightPanelWidth,"px"))},dependencies:[Zd,qr],styles:[".workspace-container[_ngcontent-%COMP%]{position:relative;display:flex;height:100vh;width:100vw;background-color:#e2e5ea;overflow:hidden}.workspace-container.is-resizing[_ngcontent-%COMP%]{cursor:col-resize;-webkit-user-select:none;user-select:none}.workspace-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%]{position:absolute;top:0;left:0;width:100%;height:100%;z-index:0;overflow:hidden;background:linear-gradient(135deg,#e2e5ea,#cfd6df)}.workspace-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow[_ngcontent-%COMP%]{position:absolute;border-radius:50%;filter:blur(90px);opacity:.5;animation:_ngcontent-%COMP%_aurora-drift 22s infinite alternate ease-in-out}.workspace-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-1[_ngcontent-%COMP%]{width:55vw;height:55vh;background:#5e72e440;top:-15%;left:-5%;animation-delay:0s}.workspace-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-2[_ngcontent-%COMP%]{width:45vw;height:45vh;background:#2dce8933;bottom:-10%;left:30%;animation-delay:-5s}.workspace-container[_ngcontent-%COMP%] .aurora-background[_ngcontent-%COMP%] .glow-3[_ngcontent-%COMP%]{width:50vw;height:60vh;background:#ce68ac26;top:20%;right:-10%;animation-delay:-10s}.workspace-container[_ngcontent-%COMP%] .glass-panel[_ngcontent-%COMP%]{position:relative;z-index:1;background:#ffffff73;backdrop-filter:blur(24px) saturate(120%);-webkit-backdrop-filter:blur(24px) saturate(120%);border:1px solid rgba(255,255,255,.6);box-shadow:0 8px 32px #1f26870d}.workspace-container[_ngcontent-%COMP%] .left-panel[_ngcontent-%COMP%]{flex:1;display:flex;flex-direction:column;overflow:hidden;background:#ffffff59;border-right:1px solid rgba(255,255,255,.8);border-left:none;border-top:none;border-bottom:none}.workspace-container[_ngcontent-%COMP%] .right-panel[_ngcontent-%COMP%]{min-width:300px;flex-shrink:0;padding:0;border:none;background-color:#fff;box-shadow:-6px 0 24px #00000008;height:100%;display:flex;flex-direction:column;box-sizing:border-box;z-index:2}.workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%]{width:12px;cursor:col-resize;display:flex;align-items:center;justify-content:center;z-index:10;transition:background .2s ease;margin:0 -6px}.workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%]:hover, .workspace-container.is-resizing[_ngcontent-%COMP%] .workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%]{background:#ffffff26}.workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%]:hover .resizer-handle[_ngcontent-%COMP%], .workspace-container.is-resizing[_ngcontent-%COMP%] .workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%] .resizer-handle[_ngcontent-%COMP%]{background:#5e72e4cc;height:60px}.workspace-container[_ngcontent-%COMP%] .resizer[_ngcontent-%COMP%] .resizer-handle[_ngcontent-%COMP%]{width:4px;height:40px;background:#00000026;border-radius:4px;transition:all .2s ease}@keyframes _ngcontent-%COMP%_aurora-drift{0%{transform:translate(0) scale(1)}50%{transform:translate(5%,3%) scale(1.05)}to{transform:translate(-2%,-5%) scale(.95)}}"],changeDetection:1})};var iO=[{path:"",component:qd},{path:"workspace",component:Yd},{path:"check",component:Qd},{path:"**",redirectTo:""}];var rO={providers:[qM({eventCoalescing:!0}),Wf(iO),_f(hf())]};var n5=()=>({exact:!0}),Jd=class n{static \u0275fac=function(e){return new(e||n)};static \u0275cmp=Ge({type:n,selectors:[["app-nav-switcher"]],decls:11,vars:2,consts:[["aria-label","Main Navigation",1,"floating-nav-switcher"],["routerLink","/","routerLinkActive","active","title","Return to Home Launcher to start a new task",1,"nav-tab-btn",3,"routerLinkActiveOptions"],[1,"material-symbols-outlined","tab-icon"],[1,"tab-label"],["routerLink","/workspace","routerLinkActive","active","title","Open Workspace",1,"nav-tab-btn"]],template:function(e,o){e&1&&(l(0,"nav",0)(1,"a",1)(2,"span",2),u(3,"add_task"),d(),l(4,"span",3),u(5,"New / Home"),d()(),l(6,"a",4)(7,"span",2),u(8,"space_dashboard"),d(),l(9,"span",3),u(10,"Workspace"),d()()()),e&2&&(g(),R("routerLinkActiveOptions",za(1,n5)))},dependencies:[Lr,qf],styles:[".floating-nav-switcher[_ngcontent-%COMP%]{position:fixed;top:12px;left:24px;z-index:1100;height:36px;box-sizing:border-box;display:inline-flex;align-items:center;background:#ffffffb8;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(226,232,240,.85);border-radius:18px;padding:3px;gap:3px;box-shadow:0 2px 8px -1px #0f172a0f,0 1px 2px #00000005,inset 0 1px 1px #ffffffe6;-webkit-user-select:none;user-select:none;font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;transition:background .25s cubic-bezier(.4,0,.2,1),box-shadow .25s cubic-bezier(.4,0,.2,1),border-color .25s cubic-bezier(.4,0,.2,1)}.floating-nav-switcher[_ngcontent-%COMP%]:hover{background:#ffffffd9;box-shadow:0 4px 14px -2px #0f172a1a,0 2px 4px #00000008,inset 0 1px 1px #fff;border-color:#cbd5e1e6}.floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:30px;padding:0 14px;box-sizing:border-box;border-radius:15px;font-size:13px;font-weight:600;color:#475569;text-decoration:none;cursor:pointer;line-height:1;transition:background .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1);outline:none;white-space:nowrap}.floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn[_ngcontent-%COMP%] .tab-icon[_ngcontent-%COMP%]{font-size:16px;width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;color:#64748b;transition:color .15s ease,transform .15s ease}.floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn[_ngcontent-%COMP%] .tab-label[_ngcontent-%COMP%]{color:#475569;transition:color .15s ease}.floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn[_ngcontent-%COMP%]:hover:not(.active){background:#ffffffb3;color:#0f172a}.floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn[_ngcontent-%COMP%]:hover:not(.active) .tab-icon[_ngcontent-%COMP%]{color:#1a73e8}.floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn[_ngcontent-%COMP%]:hover:not(.active) .tab-label[_ngcontent-%COMP%]{color:#0f172a}.floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn.active[_ngcontent-%COMP%]{background:#1a73e8f2!important;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);color:#fff!important;font-weight:700;box-shadow:0 2px 8px #1a73e859,inset 0 1px 1px #ffffff59}.floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn.active[_ngcontent-%COMP%] .tab-icon[_ngcontent-%COMP%], .floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn.active[_ngcontent-%COMP%] .tab-label[_ngcontent-%COMP%], .floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn.active[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:#fff!important}.floating-nav-switcher[_ngcontent-%COMP%] .nav-tab-btn[_ngcontent-%COMP%]:active{transform:scale(.97)}"],changeDetection:1})};var Xd=class n{title="frontend";static \u0275fac=function(e){return new(e||n)};static \u0275cmp=Ge({type:n,selectors:[["app-root"]],decls:2,vars:0,template:function(e,o){e&1&&$(0,"app-nav-switcher")(1,"router-outlet")},dependencies:[hs,Jd],encapsulation:2,changeDetection:1})};df(Xd,rO).catch(n=>console.error(n)); diff --git a/artemis/resources/showcase_ui/polyfills-5CFQRCPP.js b/artemis/resources/showcase_ui/polyfills-5CFQRCPP.js deleted file mode 100644 index b237b5ebf..000000000 --- a/artemis/resources/showcase_ui/polyfills-5CFQRCPP.js +++ /dev/null @@ -1,2 +0,0 @@ -var ce=globalThis;function te(t){return(ce.__Zone_symbol_prefix||"__zone_symbol__")+t}function ht(){let t=ce.performance;function n(I){t&&t.mark&&t.mark(I)}function a(I,s){t&&t.measure&&t.measure(I,s)}n("Zone");class e{static __symbol__=te;static assertZonePatched(){if(ce.Promise!==S.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")}static get root(){let s=e.current;for(;s.parent;)s=s.parent;return s}static get current(){return b.zone}static get currentTask(){return D}static __load_patch(s,i,r=!1){if(S.hasOwnProperty(s)){let E=ce[te("forceDuplicateZoneCheck")]===!0;if(!r&&E)throw Error("Already loaded patch: "+s)}else if(!ce["__Zone_disable_"+s]){let E="Zone:"+s;n(E),S[s]=i(ce,e,R),a(E,E)}}get parent(){return this._parent}get name(){return this._name}_parent;_name;_properties;_zoneDelegate;constructor(s,i){this._parent=s,this._name=i?i.name||"unnamed":"",this._properties=i&&i.properties||{},this._zoneDelegate=new f(this,this._parent&&this._parent._zoneDelegate,i)}get(s){let i=this.getZoneWith(s);if(i)return i._properties[s]}getZoneWith(s){let i=this;for(;i;){if(i._properties.hasOwnProperty(s))return i;i=i._parent}return null}fork(s){if(!s)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,s)}wrap(s,i){if(typeof s!="function")throw new Error("Expecting function got: "+s);let r=this._zoneDelegate.intercept(this,s,i),E=this;return function(){return E.runGuarded(r,this,arguments,i)}}run(s,i,r,E){b={parent:b,zone:this};try{return this._zoneDelegate.invoke(this,s,i,r,E)}finally{b=b.parent}}runGuarded(s,i=null,r,E){b={parent:b,zone:this};try{try{return this._zoneDelegate.invoke(this,s,i,r,E)}catch(x){if(this._zoneDelegate.handleError(this,x))throw x}}finally{b=b.parent}}runTask(s,i,r){if(s.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(s.zone||J).name+"; Execution: "+this.name+")");let E=s,{type:x,data:{isPeriodic:ee=!1,isRefreshable:M=!1}={}}=s;if(s.state===q&&(x===U||x===k))return;let he=s.state!=A;he&&E._transitionTo(A,d);let _e=D;D=E,b={parent:b,zone:this};try{x==k&&s.data&&!ee&&!M&&(s.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,E,i,r)}catch(Q){if(this._zoneDelegate.handleError(this,Q))throw Q}}finally{let Q=s.state;if(Q!==q&&Q!==X)if(x==U||ee||M&&Q===p)he&&E._transitionTo(d,A,p);else{let Te=E._zoneDelegates;this._updateTaskCount(E,-1),he&&E._transitionTo(q,A,q),M&&(E._zoneDelegates=Te)}b=b.parent,D=_e}}scheduleTask(s){if(s.zone&&s.zone!==this){let r=this;for(;r;){if(r===s.zone)throw Error(`can not reschedule task to ${this.name} which is descendants of the original zone ${s.zone.name}`);r=r.parent}}s._transitionTo(p,q);let i=[];s._zoneDelegates=i,s._zone=this;try{s=this._zoneDelegate.scheduleTask(this,s)}catch(r){throw s._transitionTo(X,p,q),this._zoneDelegate.handleError(this,r),r}return s._zoneDelegates===i&&this._updateTaskCount(s,1),s.state==p&&s._transitionTo(d,p),s}scheduleMicroTask(s,i,r,E){return this.scheduleTask(new g(F,s,i,r,E,void 0))}scheduleMacroTask(s,i,r,E,x){return this.scheduleTask(new g(k,s,i,r,E,x))}scheduleEventTask(s,i,r,E,x){return this.scheduleTask(new g(U,s,i,r,E,x))}cancelTask(s){if(s.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(s.zone||J).name+"; Execution: "+this.name+")");if(!(s.state!==d&&s.state!==A)){s._transitionTo(V,d,A);try{this._zoneDelegate.cancelTask(this,s)}catch(i){throw s._transitionTo(X,V),this._zoneDelegate.handleError(this,i),i}return this._updateTaskCount(s,-1),s._transitionTo(q,V),s.runCount=-1,s}}_updateTaskCount(s,i){let r=s._zoneDelegates;i==-1&&(s._zoneDelegates=null);for(let E=0;EI.hasTask(i,r),onScheduleTask:(I,s,i,r)=>I.scheduleTask(i,r),onInvokeTask:(I,s,i,r,E,x)=>I.invokeTask(i,r,E,x),onCancelTask:(I,s,i,r)=>I.cancelTask(i,r)};class f{get zone(){return this._zone}_zone;_taskCounts={microTask:0,macroTask:0,eventTask:0};_parentDelegate;_forkDlgt;_forkZS;_forkCurrZone;_interceptDlgt;_interceptZS;_interceptCurrZone;_invokeDlgt;_invokeZS;_invokeCurrZone;_handleErrorDlgt;_handleErrorZS;_handleErrorCurrZone;_scheduleTaskDlgt;_scheduleTaskZS;_scheduleTaskCurrZone;_invokeTaskDlgt;_invokeTaskZS;_invokeTaskCurrZone;_cancelTaskDlgt;_cancelTaskZS;_cancelTaskCurrZone;_hasTaskDlgt;_hasTaskDlgtOwner;_hasTaskZS;_hasTaskCurrZone;constructor(s,i,r){this._zone=s,this._parentDelegate=i,this._forkZS=r&&(r&&r.onFork?r:i._forkZS),this._forkDlgt=r&&(r.onFork?i:i._forkDlgt),this._forkCurrZone=r&&(r.onFork?this._zone:i._forkCurrZone),this._interceptZS=r&&(r.onIntercept?r:i._interceptZS),this._interceptDlgt=r&&(r.onIntercept?i:i._interceptDlgt),this._interceptCurrZone=r&&(r.onIntercept?this._zone:i._interceptCurrZone),this._invokeZS=r&&(r.onInvoke?r:i._invokeZS),this._invokeDlgt=r&&(r.onInvoke?i:i._invokeDlgt),this._invokeCurrZone=r&&(r.onInvoke?this._zone:i._invokeCurrZone),this._handleErrorZS=r&&(r.onHandleError?r:i._handleErrorZS),this._handleErrorDlgt=r&&(r.onHandleError?i:i._handleErrorDlgt),this._handleErrorCurrZone=r&&(r.onHandleError?this._zone:i._handleErrorCurrZone),this._scheduleTaskZS=r&&(r.onScheduleTask?r:i._scheduleTaskZS),this._scheduleTaskDlgt=r&&(r.onScheduleTask?i:i._scheduleTaskDlgt),this._scheduleTaskCurrZone=r&&(r.onScheduleTask?this._zone:i._scheduleTaskCurrZone),this._invokeTaskZS=r&&(r.onInvokeTask?r:i._invokeTaskZS),this._invokeTaskDlgt=r&&(r.onInvokeTask?i:i._invokeTaskDlgt),this._invokeTaskCurrZone=r&&(r.onInvokeTask?this._zone:i._invokeTaskCurrZone),this._cancelTaskZS=r&&(r.onCancelTask?r:i._cancelTaskZS),this._cancelTaskDlgt=r&&(r.onCancelTask?i:i._cancelTaskDlgt),this._cancelTaskCurrZone=r&&(r.onCancelTask?this._zone:i._cancelTaskCurrZone),this._hasTaskZS=null,this._hasTaskDlgt=null,this._hasTaskDlgtOwner=null,this._hasTaskCurrZone=null;let E=r&&r.onHasTask,x=i&&i._hasTaskZS;(E||x)&&(this._hasTaskZS=E?r:c,this._hasTaskDlgt=i,this._hasTaskDlgtOwner=this,this._hasTaskCurrZone=this._zone,r.onScheduleTask||(this._scheduleTaskZS=c,this._scheduleTaskDlgt=i,this._scheduleTaskCurrZone=this._zone),r.onInvokeTask||(this._invokeTaskZS=c,this._invokeTaskDlgt=i,this._invokeTaskCurrZone=this._zone),r.onCancelTask||(this._cancelTaskZS=c,this._cancelTaskDlgt=i,this._cancelTaskCurrZone=this._zone))}fork(s,i){return this._forkZS?this._forkZS.onFork(this._forkDlgt,this.zone,s,i):new e(s,i)}intercept(s,i,r){return this._interceptZS?this._interceptZS.onIntercept(this._interceptDlgt,this._interceptCurrZone,s,i,r):i}invoke(s,i,r,E,x){return this._invokeZS?this._invokeZS.onInvoke(this._invokeDlgt,this._invokeCurrZone,s,i,r,E,x):i.apply(r,E)}handleError(s,i){return this._handleErrorZS?this._handleErrorZS.onHandleError(this._handleErrorDlgt,this._handleErrorCurrZone,s,i):!0}scheduleTask(s,i){let r=i;if(this._scheduleTaskZS)this._hasTaskZS&&r._zoneDelegates.push(this._hasTaskDlgtOwner),r=this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt,this._scheduleTaskCurrZone,s,i),r||(r=i);else if(i.scheduleFn)i.scheduleFn(i);else if(i.type==F)z(i);else throw new Error("Task is missing scheduleFn.");return r}invokeTask(s,i,r,E){return this._invokeTaskZS?this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt,this._invokeTaskCurrZone,s,i,r,E):i.callback.apply(r,E)}cancelTask(s,i){let r;if(this._cancelTaskZS)r=this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt,this._cancelTaskCurrZone,s,i);else{if(!i.cancelFn)throw Error("Task is not cancelable");r=i.cancelFn(i)}return r}hasTask(s,i){try{this._hasTaskZS&&this._hasTaskZS.onHasTask(this._hasTaskDlgt,this._hasTaskCurrZone,s,i)}catch(r){this.handleError(s,r)}}_updateTaskCount(s,i){let r=this._taskCounts,E=r[s],x=r[s]=E+i;if(x<0)throw new Error("More tasks executed then were scheduled.");if(E==0||x==0){let ee={microTask:r.microTask>0,macroTask:r.macroTask>0,eventTask:r.eventTask>0,change:s};this.hasTask(this._zone,ee)}}}class g{type;source;invoke;callback;data;scheduleFn;cancelFn;_zone=null;runCount=0;_zoneDelegates=null;_state="notScheduled";constructor(s,i,r,E,x,ee){if(this.type=s,this.source=i,this.data=E,this.scheduleFn=x,this.cancelFn=ee,!r)throw new Error("callback is not defined");this.callback=r;let M=this;s===U&&E&&E.useG?this.invoke=g.invokeTask:this.invoke=function(){return g.invokeTask.call(ce,M,this,arguments)}}static invokeTask(s,i,r){s||(s=this),K++;try{return s.runCount++,s.zone.runTask(s,i,r)}finally{K==1&&$(),K--}}get zone(){return this._zone}get state(){return this._state}cancelScheduleRequest(){this._transitionTo(q,p)}_transitionTo(s,i,r){if(this._state===i||this._state===r)this._state=s,s==q&&(this._zoneDelegates=null);else throw new Error(`${this.type} '${this.source}': can not transition to '${s}', expecting state '${i}'${r?" or '"+r+"'":""}, was '${this._state}'.`)}toString(){return this.data&&typeof this.data.handleId<"u"?this.data.handleId.toString():Object.prototype.toString.call(this)}toJSON(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}}}let T=te("setTimeout"),y=te("Promise"),w=te("then"),_=[],P=!1,L;function H(I){if(L||ce[y]&&(L=ce[y].resolve(0)),L){let s=L[w];s||(s=L.then),s.call(L,I)}else ce[T](I,0)}function z(I){K===0&&_.length===0&&H($),I&&_.push(I)}function $(){if(!P){for(P=!0;_.length;){let I=_;_=[];for(let s=0;sb,onUnhandledError:W,microtaskDrainDone:W,scheduleMicroTask:z,showUncaughtError:()=>!e[te("ignoreConsoleErrorUncaughtError")],patchEventTarget:()=>[],patchOnProperties:W,patchMethod:()=>W,bindArguments:()=>[],patchThen:()=>W,patchMacroTask:()=>W,patchEventPrototype:()=>W,isIEOrEdge:()=>!1,getGlobalObjects:()=>{},ObjectDefineProperty:()=>W,ObjectGetOwnPropertyDescriptor:()=>{},ObjectCreate:()=>{},ArraySlice:()=>[],patchClass:()=>W,wrapWithCurrentZone:()=>W,filterProperties:()=>[],attachOriginToPatched:()=>W,_redefineProperty:()=>W,patchCallbacks:()=>W,nativeScheduleMicroTask:H},b={parent:null,zone:new e(null,null)},D=null,K=0;function W(){}return a("Zone","Zone"),e}function dt(){let t=globalThis,n=t[te("forceDuplicateZoneCheck")]===!0;if(t.Zone&&(n||typeof t.Zone.__symbol__!="function"))throw new Error("Zone already loaded.");return t.Zone??=ht(),t.Zone}var pe=Object.getOwnPropertyDescriptor,Me=Object.defineProperty,Ae=Object.getPrototypeOf,_t=Object.create,Tt=Array.prototype.slice,je="addEventListener",He="removeEventListener",Ne=te(je),Ze=te(He),ae="true",le="false",ve=te("");function Ve(t,n){return Zone.current.wrap(t,n)}function xe(t,n,a,e,c){return Zone.current.scheduleMacroTask(t,n,a,e,c)}var j=te,we=typeof window<"u",be=we?window:void 0,Y=we&&be||globalThis,Et="removeAttribute";function Fe(t,n){for(let a=t.length-1;a>=0;a--)typeof t[a]=="function"&&(t[a]=Ve(t[a],n+"_"+a));return t}function gt(t,n){let a=t.constructor.name;for(let e=0;e{let y=function(){return T.apply(this,Fe(arguments,a+"."+c))};return fe(y,T),y})(f)}}}function et(t){return t?t.writable===!1?!1:!(typeof t.get=="function"&&typeof t.set>"u"):!0}var tt=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope,De=!("nw"in Y)&&typeof Y.process<"u"&&Y.process.toString()==="[object process]",Ge=!De&&!tt&&!!(we&&be.HTMLElement),nt=typeof Y.process<"u"&&Y.process.toString()==="[object process]"&&!tt&&!!(we&&be.HTMLElement),Ce={},kt=j("enable_beforeunload"),Xe=function(t){if(t=t||Y.event,!t)return;let n=Ce[t.type];n||(n=Ce[t.type]=j("ON_PROPERTY"+t.type));let a=this||t.target||Y,e=a[n],c;if(Ge&&a===be&&t.type==="error"){let f=t;c=e&&e.call(this,f.message,f.filename,f.lineno,f.colno,f.error),c===!0&&t.preventDefault()}else c=e&&e.apply(this,arguments),t.type==="beforeunload"&&Y[kt]&&typeof c=="string"?t.returnValue=c:c!=null&&!c&&t.preventDefault();return c};function Ye(t,n,a){let e=pe(t,n);if(!e&&a&&pe(a,n)&&(e={enumerable:!0,configurable:!0}),!e||!e.configurable)return;let c=j("on"+n+"patched");if(t.hasOwnProperty(c)&&t[c])return;delete e.writable,delete e.value;let f=e.get,g=e.set,T=n.slice(2),y=Ce[T];y||(y=Ce[T]=j("ON_PROPERTY"+T)),e.set=function(w){let _=this;if(!_&&t===Y&&(_=Y),!_)return;typeof _[y]=="function"&&_.removeEventListener(T,Xe),g?.call(_,null),_[y]=w,typeof w=="function"&&_.addEventListener(T,Xe,!1)},e.get=function(){let w=this;if(!w&&t===Y&&(w=Y),!w)return null;let _=w[y];if(_)return _;if(f){let P=f.call(this);if(P)return e.set.call(this,P),typeof w[Et]=="function"&&w.removeAttribute(n),P}return null},Me(t,n,e),t[c]=!0}function rt(t,n,a){if(n)for(let e=0;efunction(g,T){let y=a(g,T);return y.cbIdx>=0&&typeof T[y.cbIdx]=="function"?xe(y.name,T[y.cbIdx],y,c):f.apply(g,T)})}function fe(t,n){t[j("OriginalDelegate")]=n}var $e=!1,Le=!1;function yt(){if($e)return Le;$e=!0;try{let t=be.navigator.userAgent;(t.indexOf("MSIE ")!==-1||t.indexOf("Trident/")!==-1||t.indexOf("Edge/")!==-1)&&(Le=!0)}catch{}return Le}function Je(t){return typeof t=="function"}function Ke(t){return typeof t=="number"}var pt={useG:!0},ne={},ot={},st=new RegExp("^"+ve+"(\\w+)(true|false)$"),it=j("propagationStopped");function ct(t,n){let a=(n?n(t):t)+le,e=(n?n(t):t)+ae,c=ve+a,f=ve+e;ne[t]={},ne[t][le]=c,ne[t][ae]=f}function vt(t,n,a,e){let c=e&&e.add||je,f=e&&e.rm||He,g=e&&e.listeners||"eventListeners",T=e&&e.rmAll||"removeAllListeners",y=j(c),w="."+c+":",_="prependListener",P="."+_+":",L=function(p,d,A){if(p.isRemoved)return;let V=p.callback;typeof V=="object"&&V.handleEvent&&(p.callback=k=>V.handleEvent(k),p.originalDelegate=V);let X;try{p.invoke(p,d,[A])}catch(k){X=k}let F=p.options;if(F&&typeof F=="object"&&F.once){let k=p.originalDelegate?p.originalDelegate:p.callback;d[f].call(d,A.type,k,F)}return X};function H(p,d,A){if(d=d||t.event,!d)return;let V=p||d.target||t,X=V[ne[d.type][A?ae:le]];if(X){let F=[];if(X.length===1){let k=L(X[0],V,d);k&&F.push(k)}else{let k=X.slice();for(let U=0;U{throw U})}}}let z=function(p){return H(this,p,!1)},$=function(p){return H(this,p,!0)};function J(p,d){if(!p)return!1;let A=!0;d&&d.useG!==void 0&&(A=d.useG);let V=d&&d.vh,X=!0;d&&d.chkDup!==void 0&&(X=d.chkDup);let F=!1;d&&d.rt!==void 0&&(F=d.rt);let k=p;for(;k&&!k.hasOwnProperty(c);)k=Ae(k);if(!k&&p[c]&&(k=p),!k||k[y])return!1;let U=d&&d.eventNameToString,S={},R=k[y]=k[c],b=k[j(f)]=k[f],D=k[j(g)]=k[g],K=k[j(T)]=k[T],W;d&&d.prepend&&(W=k[j(d.prepend)]=k[d.prepend]);function I(o,u){return u?typeof o=="boolean"?{capture:o,passive:!0}:o?typeof o=="object"&&o.passive!==!1?{...o,passive:!0}:o:{passive:!0}:o}let s=function(o){if(!S.isExisting)return R.call(S.target,S.eventName,S.capture?$:z,S.options)},i=function(o){if(!o.isRemoved){let u=ne[o.eventName],v;u&&(v=u[o.capture?ae:le]);let C=v&&o.target[v];if(C){for(let m=0;mre.zone.cancelTask(re);o.call(Ee,"abort",ie,{once:!0}),re.removeAbortListener=()=>Ee.removeEventListener("abort",ie)}if(S.target=null,me&&(me.taskData=null),Be&&(S.options.once=!0),typeof re.options!="boolean"&&(re.options=se),re.target=N,re.capture=Se,re.eventName=Z,B&&(re.originalDelegate=G),O?ge.unshift(re):ge.push(re),m)return N}};return k[c]=l(R,w,ee,M,F),W&&(k[_]=l(W,P,E,M,F,!0)),k[f]=function(){let o=this||t,u=arguments[0];d&&d.transferEventName&&(u=d.transferEventName(u));let v=arguments[2],C=v?typeof v=="boolean"?!0:v.capture:!1,m=arguments[1];if(!m)return b.apply(this,arguments);if(V&&!V(b,m,o,arguments))return;let O=ne[u],N;O&&(N=O[C?ae:le]);let Z=N&&o[N];if(Z)for(let G=0;Gfunction(c,f){c[it]=!0,e&&e.apply(c,f)})}function Pt(t,n){n.patchMethod(t,"queueMicrotask",a=>function(e,c){Zone.current.scheduleMicroTask("queueMicrotask",c[0])})}var Re=j("zoneTask");function ke(t,n,a,e){let c=null,f=null;n+=e,a+=e;let g={};function T(w){let _=w.data;_.args[0]=function(){return w.invoke.apply(this,arguments)};let P=c.apply(t,_.args);return Ke(P)?_.handleId=P:(_.handle=P,_.isRefreshable=Je(P.refresh)),w}function y(w){let{handle:_,handleId:P}=w.data;return f.call(t,_??P)}c=ue(t,n,w=>function(_,P){if(Je(P[0])){let L={isRefreshable:!1,isPeriodic:e==="Interval",delay:e==="Timeout"||e==="Interval"?P[1]||0:void 0,args:P},H=P[0];P[0]=function(){try{return H.apply(this,arguments)}finally{let{handle:A,handleId:V,isPeriodic:X,isRefreshable:F}=L;!X&&!F&&(V?delete g[V]:A&&(A[Re]=null))}};let z=xe(n,P[0],L,T,y);if(!z)return z;let{handleId:$,handle:J,isRefreshable:q,isPeriodic:p}=z.data;if($)g[$]=z;else if(J&&(J[Re]=z,q&&!p)){let d=J.refresh;J.refresh=function(){let{zone:A,state:V}=z;return V==="notScheduled"?(z._state="scheduled",A._updateTaskCount(z,1)):V==="running"&&(z._state="scheduling"),d.call(this)}}return J??$??z}else return w.apply(t,P)}),f=ue(t,a,w=>function(_,P){let L=P[0],H;Ke(L)?(H=g[L],delete g[L]):(H=L?.[Re],H?L[Re]=null:H=L),H?.type?H.cancelFn&&H.zone.cancelTask(H):w.apply(t,P)})}function Rt(t,n){let{isBrowser:a,isMix:e}=n.getGlobalObjects();if(!a&&!e||!t.customElements||!("customElements"in t))return;let c=["connectedCallback","disconnectedCallback","adoptedCallback","attributeChangedCallback","formAssociatedCallback","formDisabledCallback","formResetCallback","formStateRestoreCallback"];n.patchCallbacks(n,t.customElements,"customElements","define",c)}function Ct(t,n){if(Zone[n.symbol("patchEventTarget")])return;let{eventNames:a,zoneSymbolEventNames:e,TRUE_STR:c,FALSE_STR:f,ZONE_SYMBOL_PREFIX:g}=n.getGlobalObjects();for(let y=0;yf.target===t);if(e.length===0)return n;let c=e[0].ignoreProperties;return n.filter(f=>c.indexOf(f)===-1)}function Qe(t,n,a,e){if(!t)return;let c=lt(t,n,a);rt(t,c,e)}function Ie(t){return Object.getOwnPropertyNames(t).filter(n=>n.startsWith("on")&&n.length>2).map(n=>n.substring(2))}function Dt(t,n){if(De&&!nt||Zone[t.symbol("patchEvents")])return;let a=n.__Zone_ignore_on_properties,e=[];if(Ge){let c=window;e=e.concat(["Document","SVGElement","Element","HTMLElement","HTMLBodyElement","HTMLMediaElement","HTMLFrameSetElement","HTMLFrameElement","HTMLIFrameElement","HTMLMarqueeElement","Worker"]);let f=[];Qe(c,Ie(c),a&&a.concat(f),Ae(c))}e=e.concat(["XMLHttpRequest","XMLHttpRequestEventTarget","IDBIndex","IDBRequest","IDBOpenDBRequest","IDBDatabase","IDBTransaction","IDBCursor","WebSocket"]);for(let c=0;c{let a=n[t.__symbol__("legacyPatch")];a&&a()}),t.__load_patch("timers",n=>{let e="clear";ke(n,"set",e,"Timeout"),ke(n,"set",e,"Interval"),ke(n,"set",e,"Immediate")}),t.__load_patch("requestAnimationFrame",n=>{ke(n,"request","cancel","AnimationFrame"),ke(n,"mozRequest","mozCancel","AnimationFrame"),ke(n,"webkitRequest","webkitCancel","AnimationFrame")}),t.__load_patch("blocking",(n,a)=>{let e=["alert","prompt","confirm"];for(let c=0;cfunction(w,_){return a.current.run(g,n,_,y)})}}),t.__load_patch("EventTarget",(n,a,e)=>{wt(n,e),Ct(n,e);let c=n.XMLHttpRequestEventTarget;c&&c.prototype&&e.patchEventTarget(n,e,[c.prototype])}),t.__load_patch("MutationObserver",(n,a,e)=>{ye("MutationObserver"),ye("WebKitMutationObserver")}),t.__load_patch("IntersectionObserver",(n,a,e)=>{ye("IntersectionObserver")}),t.__load_patch("FileReader",(n,a,e)=>{ye("FileReader")}),t.__load_patch("on_property",(n,a,e)=>{Dt(e,n)}),t.__load_patch("customElements",(n,a,e)=>{Rt(n,e)}),t.__load_patch("XHR",(n,a)=>{w(n);let e=j("xhrTask"),c=j("xhrSync"),f=j("xhrListener"),g=j("xhrScheduled"),T=j("xhrURL"),y=j("xhrErrorBeforeScheduled");function w(_){let P=_.XMLHttpRequest;if(!P)return;let L=P.prototype;function H(R){return R[e]}let z=L[Ne],$=L[Ze];if(!z){let R=_.XMLHttpRequestEventTarget;if(R){let b=R.prototype;z=b[Ne],$=b[Ze]}}let J="readystatechange",q="scheduled";function p(R){let b=R.data,D=b.target;D[g]=!1,D[y]=!1;let K=D[f];z||(z=D[Ne],$=D[Ze]),K&&$.call(D,J,K);let W=D[f]=()=>{if(D.readyState===D.DONE)if(!b.aborted&&D[g]&&R.state===q){let s=D[a.__symbol__("loadfalse")];if(D.status!==0&&s&&s.length>0){let i=R.invoke;R.invoke=function(){let r=D[a.__symbol__("loadfalse")];for(let E=0;Efunction(R,b){return R[c]=b[2]==!1,R[T]=b[1],V.apply(R,b)}),X="XMLHttpRequest.send",F=j("fetchTaskAborting"),k=j("fetchTaskScheduling"),U=ue(L,"send",()=>function(R,b){if(a.current[k]===!0||R[c])return U.apply(R,b);{let D={target:R,url:R[T],isPeriodic:!1,args:b,aborted:!1},K=xe(X,d,D,p,A);R&&R[y]===!0&&!D.aborted&&K.state===q&&K.invoke()}}),S=ue(L,"abort",()=>function(R,b){let D=H(R);if(D&&typeof D.type=="string"){if(D.cancelFn==null||D.data&&D.data.aborted)return;D.zone.cancelTask(D)}else if(a.current[F]===!0)return S.apply(R,b)})}}),t.__load_patch("geolocation",n=>{n.navigator&&n.navigator.geolocation&>(n.navigator.geolocation,["getCurrentPosition","watchPosition"])}),t.__load_patch("PromiseRejectionEvent",(n,a)=>{function e(c){return function(f){at(n,c).forEach(T=>{let y=n.PromiseRejectionEvent;if(y){let w=new y(c,{promise:f.promise,reason:f.rejection});T.invoke(w)}})}}n.PromiseRejectionEvent&&(a[j("unhandledPromiseRejectionHandler")]=e("unhandledrejection"),a[j("rejectionHandledHandler")]=e("rejectionhandled"))}),t.__load_patch("queueMicrotask",(n,a,e)=>{Pt(n,e)})}function Ot(t){t.__load_patch("ZoneAwarePromise",(n,a,e)=>{let c=Object.getOwnPropertyDescriptor,f=Object.defineProperty;function g(h){if(h&&h.toString===Object.prototype.toString){let l=h.constructor&&h.constructor.name;return(l||"")+": "+JSON.stringify(h)}return h?h.toString():Object.prototype.toString.call(h)}let T=e.symbol,y=[],w=n[T("DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION")]!==!1,_=T("Promise"),P=T("then"),L="__creationTrace__";e.onUnhandledError=h=>{if(e.showUncaughtError()){let l=h&&h.rejection;l?console.error("Unhandled Promise rejection:",l instanceof Error?l.message:l,"; Zone:",h.zone.name,"; Task:",h.task&&h.task.source,"; Value:",l,l instanceof Error?l.stack:void 0):console.error(h)}},e.microtaskDrainDone=()=>{for(;y.length;){let h=y.shift();try{h.zone.runGuarded(()=>{throw h.throwOriginal?h.rejection:h})}catch(l){z(l)}}};let H=T("unhandledPromiseRejectionHandler");function z(h){e.onUnhandledError(h);try{let l=a[H];typeof l=="function"&&l.call(this,h)}catch{}}function $(h){return h&&typeof h.then=="function"}function J(h){return h}function q(h){return M.reject(h)}let p=T("state"),d=T("value"),A=T("finally"),V=T("parentPromiseValue"),X=T("parentPromiseState"),F="Promise.then",k=null,U=!0,S=!1,R=0;function b(h,l){return o=>{try{I(h,l,o)}catch(u){I(h,!1,u)}}}let D=function(){let h=!1;return function(o){return function(){h||(h=!0,o.apply(null,arguments))}}},K="Promise resolved with itself",W=T("currentTaskTrace");function I(h,l,o){let u=D();if(h===o)throw new TypeError(K);if(h[p]===k){let v=null;try{(typeof o=="object"||typeof o=="function")&&(v=o&&o.then)}catch(C){return u(()=>{I(h,!1,C)})(),h}if(l!==S&&o instanceof M&&o.hasOwnProperty(p)&&o.hasOwnProperty(d)&&o[p]!==k)i(o),I(h,o[p],o[d]);else if(l!==S&&typeof v=="function")try{v.call(o,u(b(h,l)),u(b(h,!1)))}catch(C){u(()=>{I(h,!1,C)})()}else{h[p]=l;let C=h[d];if(h[d]=o,h[A]===A&&l===U&&(h[p]=h[X],h[d]=h[V]),l===S&&o instanceof Error){let m=a.currentTask&&a.currentTask.data&&a.currentTask.data[L];m&&f(o,W,{configurable:!0,enumerable:!1,writable:!0,value:m})}for(let m=0;m{try{let O=h[d],N=!!o&&A===o[A];N&&(o[V]=O,o[X]=C);let Z=l.run(m,void 0,N&&m!==q&&m!==J?[]:[O]);I(o,!0,Z)}catch(O){I(o,!1,O)}},o)}let E="function ZoneAwarePromise() { [native code] }",x=function(){},ee=n.AggregateError;class M{static toString(){return E}static resolve(l){return l instanceof M?l:I(new this(null),U,l)}static reject(l){return I(new this(null),S,l)}static withResolvers(){let l={};return l.promise=new M((o,u)=>{l.resolve=o,l.reject=u}),l}static any(l){if(!l||typeof l[Symbol.iterator]!="function")return Promise.reject(new ee([],"All promises were rejected"));let o=[],u=0;try{for(let m of l)u++,o.push(M.resolve(m))}catch{return Promise.reject(new ee([],"All promises were rejected"))}if(u===0)return Promise.reject(new ee([],"All promises were rejected"));let v=!1,C=[];return new M((m,O)=>{for(let N=0;N{v||(v=!0,m(Z))},Z=>{C.push(Z),u--,u===0&&(v=!0,O(new ee(C,"All promises were rejected")))})})}static race(l){let o,u,v=new this((O,N)=>{o=O,u=N});function C(O){o(O)}function m(O){u(O)}for(let O of l)$(O)||(O=this.resolve(O)),O.then(C,m);return v}static all(l){return M.allWithCallback(l)}static allSettled(l){return(this&&this.prototype instanceof M?this:M).allWithCallback(l,{thenCallback:u=>({status:"fulfilled",value:u}),errorCallback:u=>({status:"rejected",reason:u})})}static allWithCallback(l,o){let u,v,C=new this((Z,G)=>{u=Z,v=G}),m=2,O=0,N=[];for(let Z of l){$(Z)||(Z=this.resolve(Z));let G=O;try{Z.then(B=>{N[G]=o?o.thenCallback(B):B,m--,m===0&&u(N)},B=>{o?(N[G]=o.errorCallback(B),m--,m===0&&u(N)):v(B)})}catch(B){v(B)}m++,O++}return m-=2,m===0&&u(N),C}constructor(l){let o=this;if(!(o instanceof M))throw new Error("Must be an instanceof Promise.");o[p]=k,o[d]=[];try{let u=D();l&&l(u(b(o,U)),u(b(o,S)))}catch(u){I(o,!1,u)}}get[Symbol.toStringTag](){return"Promise"}get[Symbol.species](){return M}then(l,o){let u=this.constructor?.[Symbol.species];(!u||typeof u!="function")&&(u=this.constructor||M);let v=new u(x),C=a.current;return this[p]==k?this[d].push(C,v,l,o):r(this,C,v,l,o),v}catch(l){return this.then(null,l)}finally(l){let o=this.constructor?.[Symbol.species];(!o||typeof o!="function")&&(o=M);let u=new o(x);u[A]=A;let v=a.current;return this[p]==k?this[d].push(v,u,l,l):r(this,v,u,l,l),u}}M.resolve=M.resolve,M.reject=M.reject,M.race=M.race,M.all=M.all;let he=n[_]=n.Promise;n.Promise=M;let _e=T("thenPatched");function Q(h){let l=h.prototype,o=c(l,"then");if(o&&(o.writable===!1||!o.configurable))return;let u=l.then;l[P]=u,h.prototype.then=function(v,C){return new M((O,N)=>{u.call(this,O,N)}).then(v,C)},h[_e]=!0}e.patchThen=Q;function Te(h){return function(l,o){let u=h.apply(l,o);if(u instanceof M)return u;let v=u.constructor;return v[_e]||Q(v),u}}return he&&(Q(he),ue(n,"fetch",h=>Te(h))),Promise[a.__symbol__("uncaughtPromiseErrors")]=y,M})}function Nt(t){t.__load_patch("toString",n=>{let a=Function.prototype.toString,e=j("OriginalDelegate"),c=j("Promise"),f=j("Error"),g=function(){if(typeof this=="function"){let _=this[e];if(_)return typeof _=="function"?a.call(_):Object.prototype.toString.call(_);if(this===Promise){let P=n[c];if(P)return a.call(P)}if(this===Error){let P=n[f];if(P)return a.call(P)}}return a.call(this)};g[e]=a,Function.prototype.toString=g;let T=Object.prototype.toString,y="[object Promise]";Object.prototype.toString=function(){return typeof Promise=="function"&&this instanceof Promise?y:T.call(this)}})}function Zt(t,n,a,e,c){let f=Zone.__symbol__(e);if(n[f])return;let g=n[f]=n[e];n[e]=function(T,y,w){return y&&y.prototype&&c.forEach(function(_){let P=`${a}.${e}::`+_,L=y.prototype;try{if(L.hasOwnProperty(_)){let H=t.ObjectGetOwnPropertyDescriptor(L,_);H&&H.value?(H.value=t.wrapWithCurrentZone(H.value,P),t._redefineProperty(y.prototype,_,H)):L[_]&&(L[_]=t.wrapWithCurrentZone(L[_],P))}else L[_]&&(L[_]=t.wrapWithCurrentZone(L[_],P))}catch{}}),g.call(n,T,y,w)},t.attachOriginToPatched(n[e],g)}function Lt(t){t.__load_patch("util",(n,a,e)=>{let c=Ie(n);e.patchOnProperties=rt,e.patchMethod=ue,e.bindArguments=Fe,e.patchMacroTask=mt;let f=a.__symbol__("BLACK_LISTED_EVENTS"),g=a.__symbol__("UNPATCHED_EVENTS");n[g]&&(n[f]=n[g]),n[f]&&(a[f]=a[g]=n[f]),e.patchEventPrototype=bt,e.patchEventTarget=vt,e.isIEOrEdge=yt,e.ObjectDefineProperty=Me,e.ObjectGetOwnPropertyDescriptor=pe,e.ObjectCreate=_t,e.ArraySlice=Tt,e.patchClass=ye,e.wrapWithCurrentZone=Ve,e.filterProperties=lt,e.attachOriginToPatched=fe,e._redefineProperty=Object.defineProperty,e.patchCallbacks=Zt,e.getGlobalObjects=()=>({globalSources:ot,zoneSymbolEventNames:ne,eventNames:c,isBrowser:Ge,isMix:nt,isNode:De,TRUE_STR:ae,FALSE_STR:le,ZONE_SYMBOL_PREFIX:ve,ADD_EVENT_LISTENER_STR:je,REMOVE_EVENT_LISTENER_STR:He})})}function It(t){Ot(t),Nt(t),Lt(t)}var ut=dt();It(ut);St(ut); diff --git a/artemis/resources/showcase_ui/styles-CDJM3XQS.css b/artemis/resources/showcase_ui/styles-CDJM3XQS.css deleted file mode 100644 index a0a5f1514..000000000 --- a/artemis/resources/showcase_ui/styles-CDJM3XQS.css +++ /dev/null @@ -1 +0,0 @@ -@font-face{font-family:Inter;font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v20/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Outfit;font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJuktqQ4E.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Outfit;font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJtEtq.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Outfit;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJuktqQ4E.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Outfit;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJtEtq.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Outfit;font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJuktqQ4E.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Outfit;font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJtEtq.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Outfit;font-style:normal;font-weight:600;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJuktqQ4E.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Outfit;font-style:normal;font-weight:600;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJtEtq.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Outfit;font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJuktqQ4E.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Outfit;font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJtEtq.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3GUBGEe.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3iUBGEe.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3CUBGEe.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3-UBGEe.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMawCUBGEe.woff2) format("woff2");unicode-range:U+0302-0303,U+0305,U+0307-0308,U+0310,U+0312,U+0315,U+031A,U+0326-0327,U+032C,U+032F-0330,U+0332-0333,U+0338,U+033A,U+0346,U+034D,U+0391-03A1,U+03A3-03A9,U+03B1-03C9,U+03D1,U+03D5-03D6,U+03F0-03F1,U+03F4-03F5,U+2016-2017,U+2034-2038,U+203C,U+2040,U+2043,U+2047,U+2050,U+2057,U+205F,U+2070-2071,U+2074-208E,U+2090-209C,U+20D0-20DC,U+20E1,U+20E5-20EF,U+2100-2112,U+2114-2115,U+2117-2121,U+2123-214F,U+2190,U+2192,U+2194-21AE,U+21B0-21E5,U+21F1-21F2,U+21F4-2211,U+2213-2214,U+2216-22FF,U+2308-230B,U+2310,U+2319,U+231C-2321,U+2336-237A,U+237C,U+2395,U+239B-23B7,U+23D0,U+23DC-23E1,U+2474-2475,U+25AF,U+25B3,U+25B7,U+25BD,U+25C1,U+25CA,U+25CC,U+25FB,U+266D-266F,U+27C0-27FF,U+2900-2AFF,U+2B0E-2B11,U+2B30-2B4C,U+2BFE,U+3030,U+FF5B,U+FF5D,U+1D400-1D7FF,U+1EE00-1EEFF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMaxKUBGEe.woff2) format("woff2");unicode-range:U+0001-000C,U+000E-001F,U+007F-009F,U+20DD-20E0,U+20E2-20E4,U+2150-218F,U+2190,U+2192,U+2194-2199,U+21AF,U+21E6-21F0,U+21F3,U+2218-2219,U+2299,U+22C4-22C6,U+2300-243F,U+2440-244A,U+2460-24FF,U+25A0-27BF,U+2800-28FF,U+2921-2922,U+2981,U+29BF,U+29EB,U+2B00-2BFF,U+4DC0-4DFF,U+FFF9-FFFB,U+10140-1018E,U+10190-1019C,U+101A0,U+101D0-101FD,U+102E0-102FB,U+10E60-10E7E,U+1D2C0-1D2D3,U+1D2E0-1D37F,U+1F000-1F0FF,U+1F100-1F1AD,U+1F1E6-1F1FF,U+1F30D-1F30F,U+1F315,U+1F31C,U+1F31E,U+1F320-1F32C,U+1F336,U+1F378,U+1F37D,U+1F382,U+1F393-1F39F,U+1F3A7-1F3A8,U+1F3AC-1F3AF,U+1F3C2,U+1F3C4-1F3C6,U+1F3CA-1F3CE,U+1F3D4-1F3E0,U+1F3ED,U+1F3F1-1F3F3,U+1F3F5-1F3F7,U+1F408,U+1F415,U+1F41F,U+1F426,U+1F43F,U+1F441-1F442,U+1F444,U+1F446-1F449,U+1F44C-1F44E,U+1F453,U+1F46A,U+1F47D,U+1F4A3,U+1F4B0,U+1F4B3,U+1F4B9,U+1F4BB,U+1F4BF,U+1F4C8-1F4CB,U+1F4D6,U+1F4DA,U+1F4DF,U+1F4E3-1F4E6,U+1F4EA-1F4ED,U+1F4F7,U+1F4F9-1F4FB,U+1F4FD-1F4FE,U+1F503,U+1F507-1F50B,U+1F50D,U+1F512-1F513,U+1F53E-1F54A,U+1F54F-1F5FA,U+1F610,U+1F650-1F67F,U+1F687,U+1F68D,U+1F691,U+1F694,U+1F698,U+1F6AD,U+1F6B2,U+1F6B9-1F6BA,U+1F6BC,U+1F6C6-1F6CF,U+1F6D3-1F6D7,U+1F6E0-1F6EA,U+1F6F0-1F6F3,U+1F6F7-1F6FC,U+1F700-1F7FF,U+1F800-1F80B,U+1F810-1F847,U+1F850-1F859,U+1F860-1F887,U+1F890-1F8AD,U+1F8B0-1F8BB,U+1F8C0-1F8C1,U+1F900-1F90B,U+1F93B,U+1F946,U+1F984,U+1F996,U+1F9E9,U+1FA00-1FA6F,U+1FA70-1FA7C,U+1FA80-1FA89,U+1FA8F-1FAC6,U+1FACE-1FADC,U+1FADF-1FAE9,U+1FAF0-1FAF8,U+1FB00-1FBFF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3OUBGEe.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3GUBGEe.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3iUBGEe.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3CUBGEe.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3-UBGEe.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMawCUBGEe.woff2) format("woff2");unicode-range:U+0302-0303,U+0305,U+0307-0308,U+0310,U+0312,U+0315,U+031A,U+0326-0327,U+032C,U+032F-0330,U+0332-0333,U+0338,U+033A,U+0346,U+034D,U+0391-03A1,U+03A3-03A9,U+03B1-03C9,U+03D1,U+03D5-03D6,U+03F0-03F1,U+03F4-03F5,U+2016-2017,U+2034-2038,U+203C,U+2040,U+2043,U+2047,U+2050,U+2057,U+205F,U+2070-2071,U+2074-208E,U+2090-209C,U+20D0-20DC,U+20E1,U+20E5-20EF,U+2100-2112,U+2114-2115,U+2117-2121,U+2123-214F,U+2190,U+2192,U+2194-21AE,U+21B0-21E5,U+21F1-21F2,U+21F4-2211,U+2213-2214,U+2216-22FF,U+2308-230B,U+2310,U+2319,U+231C-2321,U+2336-237A,U+237C,U+2395,U+239B-23B7,U+23D0,U+23DC-23E1,U+2474-2475,U+25AF,U+25B3,U+25B7,U+25BD,U+25C1,U+25CA,U+25CC,U+25FB,U+266D-266F,U+27C0-27FF,U+2900-2AFF,U+2B0E-2B11,U+2B30-2B4C,U+2BFE,U+3030,U+FF5B,U+FF5D,U+1D400-1D7FF,U+1EE00-1EEFF}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMaxKUBGEe.woff2) format("woff2");unicode-range:U+0001-000C,U+000E-001F,U+007F-009F,U+20DD-20E0,U+20E2-20E4,U+2150-218F,U+2190,U+2192,U+2194-2199,U+21AF,U+21E6-21F0,U+21F3,U+2218-2219,U+2299,U+22C4-22C6,U+2300-243F,U+2440-244A,U+2460-24FF,U+25A0-27BF,U+2800-28FF,U+2921-2922,U+2981,U+29BF,U+29EB,U+2B00-2BFF,U+4DC0-4DFF,U+FFF9-FFFB,U+10140-1018E,U+10190-1019C,U+101A0,U+101D0-101FD,U+102E0-102FB,U+10E60-10E7E,U+1D2C0-1D2D3,U+1D2E0-1D37F,U+1F000-1F0FF,U+1F100-1F1AD,U+1F1E6-1F1FF,U+1F30D-1F30F,U+1F315,U+1F31C,U+1F31E,U+1F320-1F32C,U+1F336,U+1F378,U+1F37D,U+1F382,U+1F393-1F39F,U+1F3A7-1F3A8,U+1F3AC-1F3AF,U+1F3C2,U+1F3C4-1F3C6,U+1F3CA-1F3CE,U+1F3D4-1F3E0,U+1F3ED,U+1F3F1-1F3F3,U+1F3F5-1F3F7,U+1F408,U+1F415,U+1F41F,U+1F426,U+1F43F,U+1F441-1F442,U+1F444,U+1F446-1F449,U+1F44C-1F44E,U+1F453,U+1F46A,U+1F47D,U+1F4A3,U+1F4B0,U+1F4B3,U+1F4B9,U+1F4BB,U+1F4BF,U+1F4C8-1F4CB,U+1F4D6,U+1F4DA,U+1F4DF,U+1F4E3-1F4E6,U+1F4EA-1F4ED,U+1F4F7,U+1F4F9-1F4FB,U+1F4FD-1F4FE,U+1F503,U+1F507-1F50B,U+1F50D,U+1F512-1F513,U+1F53E-1F54A,U+1F54F-1F5FA,U+1F610,U+1F650-1F67F,U+1F687,U+1F68D,U+1F691,U+1F694,U+1F698,U+1F6AD,U+1F6B2,U+1F6B9-1F6BA,U+1F6BC,U+1F6C6-1F6CF,U+1F6D3-1F6D7,U+1F6E0-1F6EA,U+1F6F0-1F6F3,U+1F6F7-1F6FC,U+1F700-1F7FF,U+1F800-1F80B,U+1F810-1F847,U+1F850-1F859,U+1F860-1F887,U+1F890-1F8AD,U+1F8B0-1F8BB,U+1F8C0-1F8C1,U+1F900-1F90B,U+1F93B,U+1F946,U+1F984,U+1F996,U+1F9E9,U+1FA00-1FA6F,U+1FA70-1FA7C,U+1FA80-1FA89,U+1FA8F-1FAC6,U+1FACE-1FADC,U+1FADF-1FAE9,U+1FAF0-1FAF8,U+1FB00-1FBFF}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3OUBGEe.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3GUBGEe.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3iUBGEe.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3CUBGEe.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3-UBGEe.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMawCUBGEe.woff2) format("woff2");unicode-range:U+0302-0303,U+0305,U+0307-0308,U+0310,U+0312,U+0315,U+031A,U+0326-0327,U+032C,U+032F-0330,U+0332-0333,U+0338,U+033A,U+0346,U+034D,U+0391-03A1,U+03A3-03A9,U+03B1-03C9,U+03D1,U+03D5-03D6,U+03F0-03F1,U+03F4-03F5,U+2016-2017,U+2034-2038,U+203C,U+2040,U+2043,U+2047,U+2050,U+2057,U+205F,U+2070-2071,U+2074-208E,U+2090-209C,U+20D0-20DC,U+20E1,U+20E5-20EF,U+2100-2112,U+2114-2115,U+2117-2121,U+2123-214F,U+2190,U+2192,U+2194-21AE,U+21B0-21E5,U+21F1-21F2,U+21F4-2211,U+2213-2214,U+2216-22FF,U+2308-230B,U+2310,U+2319,U+231C-2321,U+2336-237A,U+237C,U+2395,U+239B-23B7,U+23D0,U+23DC-23E1,U+2474-2475,U+25AF,U+25B3,U+25B7,U+25BD,U+25C1,U+25CA,U+25CC,U+25FB,U+266D-266F,U+27C0-27FF,U+2900-2AFF,U+2B0E-2B11,U+2B30-2B4C,U+2BFE,U+3030,U+FF5B,U+FF5D,U+1D400-1D7FF,U+1EE00-1EEFF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMaxKUBGEe.woff2) format("woff2");unicode-range:U+0001-000C,U+000E-001F,U+007F-009F,U+20DD-20E0,U+20E2-20E4,U+2150-218F,U+2190,U+2192,U+2194-2199,U+21AF,U+21E6-21F0,U+21F3,U+2218-2219,U+2299,U+22C4-22C6,U+2300-243F,U+2440-244A,U+2460-24FF,U+25A0-27BF,U+2800-28FF,U+2921-2922,U+2981,U+29BF,U+29EB,U+2B00-2BFF,U+4DC0-4DFF,U+FFF9-FFFB,U+10140-1018E,U+10190-1019C,U+101A0,U+101D0-101FD,U+102E0-102FB,U+10E60-10E7E,U+1D2C0-1D2D3,U+1D2E0-1D37F,U+1F000-1F0FF,U+1F100-1F1AD,U+1F1E6-1F1FF,U+1F30D-1F30F,U+1F315,U+1F31C,U+1F31E,U+1F320-1F32C,U+1F336,U+1F378,U+1F37D,U+1F382,U+1F393-1F39F,U+1F3A7-1F3A8,U+1F3AC-1F3AF,U+1F3C2,U+1F3C4-1F3C6,U+1F3CA-1F3CE,U+1F3D4-1F3E0,U+1F3ED,U+1F3F1-1F3F3,U+1F3F5-1F3F7,U+1F408,U+1F415,U+1F41F,U+1F426,U+1F43F,U+1F441-1F442,U+1F444,U+1F446-1F449,U+1F44C-1F44E,U+1F453,U+1F46A,U+1F47D,U+1F4A3,U+1F4B0,U+1F4B3,U+1F4B9,U+1F4BB,U+1F4BF,U+1F4C8-1F4CB,U+1F4D6,U+1F4DA,U+1F4DF,U+1F4E3-1F4E6,U+1F4EA-1F4ED,U+1F4F7,U+1F4F9-1F4FB,U+1F4FD-1F4FE,U+1F503,U+1F507-1F50B,U+1F50D,U+1F512-1F513,U+1F53E-1F54A,U+1F54F-1F5FA,U+1F610,U+1F650-1F67F,U+1F687,U+1F68D,U+1F691,U+1F694,U+1F698,U+1F6AD,U+1F6B2,U+1F6B9-1F6BA,U+1F6BC,U+1F6C6-1F6CF,U+1F6D3-1F6D7,U+1F6E0-1F6EA,U+1F6F0-1F6F3,U+1F6F7-1F6FC,U+1F700-1F7FF,U+1F800-1F80B,U+1F810-1F847,U+1F850-1F859,U+1F860-1F887,U+1F890-1F8AD,U+1F8B0-1F8BB,U+1F8C0-1F8C1,U+1F900-1F90B,U+1F93B,U+1F946,U+1F984,U+1F996,U+1F9E9,U+1FA00-1FA6F,U+1FA70-1FA7C,U+1FA80-1FA89,U+1FA8F-1FAC6,U+1FACE-1FADC,U+1FADF-1FAE9,U+1FAF0-1FAF8,U+1FB00-1FBFF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3OUBGEe.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Material Symbols Outlined;font-style:normal;font-weight:100 700;src:url(https://fonts.gstatic.com/s/materialsymbolsoutlined/v368/kJEhBvYX7BgnkSrUwT8OhrdQw4oELdPIeeII9v6oFsI.woff2) format("woff2")}.material-symbols-outlined{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:"liga";-webkit-font-smoothing:antialiased}*,*:before,*:after{box-sizing:border-box;font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif}.material-symbols-outlined{font-family:Material Symbols Outlined!important;font-weight:400;font-style:normal;font-size:20px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;font-feature-settings:"liga";font-variation-settings:"FILL" 0,"wght" 300,"GRAD" 0,"opsz" 20}body,input,button,select,textarea{font-family:Google Sans,Google Sans Text,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif}body{margin:0;padding:0;color:#1e293b;background-color:#f8f9fa;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} diff --git a/scripts/check_dependency_sources.py b/scripts/check_dependency_sources.py index 64f1709a3..91b44e393 100644 --- a/scripts/check_dependency_sources.py +++ b/scripts/check_dependency_sources.py @@ -52,7 +52,7 @@ def check_url(label: str, url: str, host: str) -> None: for artifact in artifacts: check_url(f"{label}: artifact", artifact.get("url", ""), "files.pythonhosted.org") - npm_lock = json.loads((ROOT / "apps/showcase_ui/package-lock.json").read_text(encoding="utf-8")) + npm_lock = json.loads((ROOT / "apps/showcase_ui_v2/package-lock.json").read_text(encoding="utf-8")) for name, package in npm_lock["packages"].items(): if "resolved" in package: check_url(f"package-lock.json: {name}", package["resolved"], "registry.npmjs.org") diff --git a/scripts/install_deps.ps1 b/scripts/install_deps.ps1 index b6fc71681..ff5281a80 100644 --- a/scripts/install_deps.ps1 +++ b/scripts/install_deps.ps1 @@ -229,9 +229,10 @@ function Test-NodeCompatible { if ($parts.Count -ge 2) { $major = [int]$parts[0] $minor = [int]$parts[1] - if ($major -ge 26) { return $true } - if ($major -eq 24 -and $minor -ge 15) { return $true } - if ($major -eq 22 -and $minor -ge 22) { return $true } + # Vite 7 requires Node.js ^20.19.0 || >= 22.12.0 + if ($major -ge 23) { return $true } + if ($major -eq 22 -and $minor -ge 12) { return $true } + if ($major -eq 20 -and $minor -ge 19) { return $true } } } catch { return $false @@ -394,16 +395,15 @@ if (-not (Test-Path ".env")) { Write-Host " [OK] .env configuration file exists." -ForegroundColor Green } -# 5. Check and Build Showcase UI (Angular) -Write-Host "`n5. Checking Showcase UI Build (Angular)..." -ForegroundColor Yellow -$ShowcaseIndex = "$RootDir\apps\showcase_ui\dist\frontend\browser\index.html" -$ShowcaseIndexAlt1 = "$RootDir\apps\showcase_ui\dist\browser\index.html" -$ShowcaseIndexAlt2 = "$RootDir\apps\showcase_ui\dist\index.html" -if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1)) -and (-not (Test-Path $ShowcaseIndexAlt2))) { +# 5. Check and Build Showcase UI (Vue 3 + Vite) +Write-Host "`n5. Checking Showcase UI Build (Vue 3 + Vite)..." -ForegroundColor Yellow +$ShowcaseIndex = "$RootDir\apps\showcase_ui_v2\dist\browser\index.html" +$ShowcaseIndexAlt1 = "$RootDir\apps\showcase_ui_v2\dist\index.html" +if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1))) { if (-not (Test-NodeCompatible)) { if (Test-CommandExists "node") { $curVer = (& node -v 2>$null) - Write-Host " [WARN] Detected Node.js $curVer, but Angular CLI requires Node.js >= v22.22.0." -ForegroundColor Yellow + Write-Host " [WARN] Detected Node.js $curVer, but Vite requires Node.js ^20.19.0 || >= v22.12.0." -ForegroundColor Yellow } else { Write-Host " [WARN] Node.js/npm not found (required for Showcase UI)." -ForegroundColor Cyan } @@ -446,8 +446,8 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1)) if (Test-NodeCompatible) { $nodeVer = (& node -v 2>$null) Write-Host " [OK] Node.js $nodeVer is ready." -ForegroundColor Green - Write-Host " [INFO] Compiling Angular Showcase UI..." -ForegroundColor Cyan - Push-Location "$RootDir\apps\showcase_ui" + Write-Host " [INFO] Compiling Showcase UI (vite build)..." -ForegroundColor Cyan + Push-Location "$RootDir\apps\showcase_ui_v2" try { $npmExec = if (Test-CommandExists "npm.cmd") { "npm.cmd" } else { "npm" } Write-Host " [INFO] Installing frontend npm dependencies..." -ForegroundColor Cyan @@ -456,11 +456,7 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1)) Write-Host " [WARN] npm install returned exit code $LASTEXITCODE. Trying silent install..." -ForegroundColor DarkYellow & $npmExec install --silent } - $cliNodeVersion = "$RootDir\apps\showcase_ui\node_modules\@angular\cli\src\utilities\node-version.js" - if (Test-Path $cliNodeVersion) { - (Get-Content $cliNodeVersion) -replace '22\.22\.3', '22.22.0' | Set-Content $cliNodeVersion - } - Write-Host " [INFO] Building Angular frontend application..." -ForegroundColor Cyan + Write-Host " [INFO] Building frontend application (vite build)..." -ForegroundColor Cyan & $npmExec run build if (Test-Path $ShowcaseIndex) { Write-Host " [OK] Showcase UI compiled successfully." -ForegroundColor Green @@ -475,7 +471,7 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1)) Pop-Location } } else { - Write-Host " [WARN] Could not configure compatible Node.js (>= 22.22.0). Showcase UI will show fallback notice on launch." -ForegroundColor DarkYellow + Write-Host " [WARN] Could not configure compatible Node.js (^20.19.0 || >= 22.12.0). Showcase UI will show fallback notice on launch." -ForegroundColor DarkYellow } } else { Write-Host " [OK] Showcase UI build already exists." -ForegroundColor Green diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 553f6d8aa..4a29eaccb 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -116,7 +116,7 @@ request_sudo() { return 1 } -# Helper to check if Node.js & npm meet Angular CLI 22 requirement (>= 22.22.0, >= 24.15.0, or >= 26.0.0) +# Helper to check if Node.js & npm meet the Vite 7 requirement (^20.19.0 || >= 22.12.0) is_node_compatible() { if ! has_cmd node || ! has_cmd npm; then return 1 @@ -127,12 +127,12 @@ is_node_compatible() { local major minor major="$(echo "${node_ver}" | cut -d. -f1)" minor="$(echo "${node_ver}" | cut -d. -f2)" - if [ "${major}" -ge 26 ] 2>/dev/null; then + if [ "${major}" -ge 23 ] 2>/dev/null; then return 0 - elif [ "${major}" -ge 24 ] 2>/dev/null; then - [ "${minor}" -ge 15 ] 2>/dev/null && return 0 - elif [ "${major}" -ge 22 ] 2>/dev/null; then - [ "${minor}" -ge 22 ] 2>/dev/null && return 0 + elif [ "${major}" -eq 22 ] 2>/dev/null; then + [ "${minor}" -ge 12 ] 2>/dev/null && return 0 + elif [ "${major}" -eq 20 ] 2>/dev/null; then + [ "${minor}" -ge 19 ] 2>/dev/null && return 0 fi return 1 } @@ -378,11 +378,10 @@ setup_env_file() { # Function to check and build Showcase UI setup_showcase_ui() { - echo -e "\n${BOLD}6. Checking Showcase UI Build (Angular)...${NC}" - local SHOWCASE_INDEX="${ROOT_DIR}/apps/showcase_ui/dist/frontend/browser/index.html" - local SHOWCASE_INDEX_ALT1="${ROOT_DIR}/apps/showcase_ui/dist/browser/index.html" - local SHOWCASE_INDEX_ALT2="${ROOT_DIR}/apps/showcase_ui/dist/index.html" - if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ] && [ ! -f "${SHOWCASE_INDEX_ALT2}" ]; then + echo -e "\n${BOLD}6. Checking Showcase UI Build (Vue 3 + Vite)...${NC}" + local SHOWCASE_INDEX="${ROOT_DIR}/apps/showcase_ui_v2/dist/browser/index.html" + local SHOWCASE_INDEX_ALT1="${ROOT_DIR}/apps/showcase_ui_v2/dist/index.html" + if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ]; then # Try loading nvm if available in user environment export NVM_DIR="${HOME}/.nvm" if [ -s "${NVM_DIR}/nvm.sh" ]; then @@ -401,7 +400,7 @@ setup_showcase_ui() { if ! is_node_compatible; then if has_cmd node; then local current_node="$(node -v 2>/dev/null)" - echo -e " ${YELLOW}⚡ Detected Node.js ${current_node}, but Angular CLI requires Node.js >= v22.22.0. Upgrading Node.js...${NC}" + echo -e " ${YELLOW}⚡ Detected Node.js ${current_node}, but Vite requires Node.js ^20.19.0 || >= v22.12.0. Upgrading Node.js...${NC}" else echo -e " ${YELLOW}⚡ Node.js/npm not found. Auto-installing Node.js 22 LTS for Showcase UI compilation...${NC}" fi @@ -420,7 +419,7 @@ setup_showcase_ui() { # 3. Try Linux package managers with sudo / root if ! is_node_compatible && [ "${OS_TYPE}" = "Linux" ]; then - if request_sudo "install or upgrade Node.js to >= 22.22.0"; then + if request_sudo "install or upgrade Node.js to >= 22.12.0"; then local SUDO_PREFIX="" if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi if has_cmd apt-get; then @@ -465,23 +464,15 @@ setup_showcase_ui() { if is_node_compatible; then echo -e " ${GREEN}✓ Node.js $(node -v 2>/dev/null) and npm $(npm -v 2>/dev/null) ready.${NC}" - echo -e " ${YELLOW}🎨 Building Angular Showcase UI...${NC}" + echo -e " ${YELLOW}🎨 Building Showcase UI (vite build)...${NC}" ( - cd "${ROOT_DIR}/apps/showcase_ui" + cd "${ROOT_DIR}/apps/showcase_ui_v2" npm install --silent - CLI_NODE_VERSION="${ROOT_DIR}/apps/showcase_ui/node_modules/@angular/cli/src/utilities/node-version.js" - if [ -f "${CLI_NODE_VERSION}" ]; then - if [ "${OS_TYPE}" = "Darwin" ]; then - sed -i '' 's/22\.22\.3/22.22.0/g' "${CLI_NODE_VERSION}" 2>/dev/null || true - else - sed -i 's/22\.22\.3/22.22.0/g' "${CLI_NODE_VERSION}" 2>/dev/null || true - fi - fi npm run build ) echo -e " ${GREEN}✓ Showcase UI compiled successfully.${NC}" else - echo -e " ${YELLOW}⚠ Could not configure compatible Node.js (>= 22.22.0). Showcase UI will show fallback notice on launch.${NC}" + echo -e " ${YELLOW}⚠ Could not configure compatible Node.js (^20.19.0 || >= 22.12.0). Showcase UI will show fallback notice on launch.${NC}" fi else echo -e " ${GREEN}✓ Showcase UI build already exists.${NC}" diff --git a/scripts/start.ps1 b/scripts/start.ps1 index 1dd832af6..2e07810ed 100644 --- a/scripts/start.ps1 +++ b/scripts/start.ps1 @@ -224,9 +224,10 @@ function Test-NodeCompatible { if ($parts.Count -ge 2) { $major = [int]$parts[0] $minor = [int]$parts[1] - if ($major -ge 26) { return $true } - if ($major -eq 24 -and $minor -ge 15) { return $true } - if ($major -eq 22 -and $minor -ge 22) { return $true } + # Vite 7 requires Node.js ^20.19.0 || >= 22.12.0 + if ($major -ge 23) { return $true } + if ($major -eq 22 -and $minor -ge 12) { return $true } + if ($major -eq 20 -and $minor -ge 19) { return $true } } } catch { return $false @@ -370,14 +371,13 @@ Write-Host " [INFO] Synchronizing Python runtime and project dependencies..." uv sync --quiet # 6. Check and build Showcase UI if not already compiled -$ShowcaseIndex = "$RootDir\apps\showcase_ui\dist\frontend\browser\index.html" -$ShowcaseIndexAlt1 = "$RootDir\apps\showcase_ui\dist\browser\index.html" -$ShowcaseIndexAlt2 = "$RootDir\apps\showcase_ui\dist\index.html" -if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1)) -and (-not (Test-Path $ShowcaseIndexAlt2))) { +$ShowcaseIndex = "$RootDir\apps\showcase_ui_v2\dist\browser\index.html" +$ShowcaseIndexAlt1 = "$RootDir\apps\showcase_ui_v2\dist\index.html" +if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1))) { if (-not (Test-NodeCompatible)) { if (Test-CommandExists "node") { $curVer = (& node -v 2>$null) - Write-Host " [INFO] Detected Node.js $curVer, but Angular CLI requires Node.js >= v22.22.0." -ForegroundColor Yellow + Write-Host " [INFO] Detected Node.js $curVer, but Vite requires Node.js ^20.19.0 || >= v22.12.0." -ForegroundColor Yellow } else { Write-Host " [INFO] Node.js/npm not found (required for Showcase UI)." -ForegroundColor Cyan } @@ -395,7 +395,7 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1)) $useWinGetNode = $false if (Test-CommandExists "winget") { if ([Console]::IsInputRedirected -eq $false) { - Write-Host " [INFO] Node.js >= v22.22.0 required for Showcase UI." -ForegroundColor Cyan + Write-Host " [INFO] Node.js ^20.19.0 || >= v22.12.0 required for Showcase UI." -ForegroundColor Cyan $ans = Read-Host " Install/Upgrade Node.js via WinGet (may require Administrator)? [Y/n]" if ($ans -eq "" -or $ans -match "^[Yy]") { $useWinGetNode = $true @@ -421,8 +421,8 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1)) if (Test-NodeCompatible) { $nodeVer = (& node -v 2>$null) Write-Host " [OK] Node.js $nodeVer is ready." -ForegroundColor Green - Write-Host " [INFO] Showcase UI build not found. Compiling Angular Showcase UI..." -ForegroundColor Yellow - Push-Location "$RootDir\apps\showcase_ui" + Write-Host " [INFO] Showcase UI build not found. Compiling Showcase UI (vite build)..." -ForegroundColor Yellow + Push-Location "$RootDir\apps\showcase_ui_v2" try { $npmExec = if (Test-CommandExists "npm.cmd") { "npm.cmd" } else { "npm" } Write-Host " [INFO] Installing frontend npm dependencies..." -ForegroundColor Cyan @@ -431,11 +431,7 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1)) Write-Host " [WARN] npm install returned exit code $LASTEXITCODE. Trying silent install..." -ForegroundColor DarkYellow & $npmExec install --silent } - $cliNodeVersion = "$RootDir\apps\showcase_ui\node_modules\@angular\cli\src\utilities\node-version.js" - if (Test-Path $cliNodeVersion) { - (Get-Content $cliNodeVersion) -replace '22\.22\.3', '22.22.0' | Set-Content $cliNodeVersion - } - Write-Host " [INFO] Building Angular frontend application..." -ForegroundColor Cyan + Write-Host " [INFO] Building frontend application (vite build)..." -ForegroundColor Cyan & $npmExec run build if (Test-Path $ShowcaseIndex) { Write-Host " [OK] Showcase UI compiled successfully." -ForegroundColor Green @@ -450,7 +446,7 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1)) Pop-Location } } else { - Write-Host " [WARN] Node.js >= v22.22.0 not found. Showcase UI will show fallback notice on launch." -ForegroundColor DarkYellow + Write-Host " [WARN] Node.js ^20.19.0 || >= v22.12.0 not found. Showcase UI will show fallback notice on launch." -ForegroundColor DarkYellow } } diff --git a/setup.py b/setup.py index 054260cbc..eab6f7b54 100644 --- a/setup.py +++ b/setup.py @@ -24,12 +24,10 @@ def _showcase_dist(source_root: Path) -> Path | None: - """Locate a complete Angular browser build in a source or sdist tree.""" - base_dist = source_root / "apps" / "showcase_ui" / "dist" + """Locate a complete Vite browser build in a source or sdist tree.""" + base_dist = source_root / "apps" / "showcase_ui_v2" / "dist" candidates = ( - base_dist / "frontend" / "browser", base_dist / "browser", - base_dist / "frontend", base_dist, source_root / "artemis" / "resources" / "showcase_ui", ) @@ -50,8 +48,8 @@ def _copy_release_resources(source_root: Path, resource_root: Path) -> None: if showcase_source is None: raise RuntimeError( "Cannot build an Artemis distribution without the Showcase UI. " - "Run `npm ci --prefix apps/showcase_ui` and " - "`npm run build --prefix apps/showcase_ui` first." + "Run `npm ci --prefix apps/showcase_ui_v2` and " + "`npm run build --prefix apps/showcase_ui_v2` first." ) config_target = resource_root / "config" config_target.mkdir(parents=True, exist_ok=True) @@ -72,7 +70,7 @@ def run(self) -> None: if self.editable_mode: return # Older builds may have copied frontend sources and node_modules here. - excluded_showcase = Path(self.build_lib) / "apps" / "showcase_ui" + excluded_showcase = Path(self.build_lib) / "apps" / "showcase_ui_v2" if excluded_showcase.exists(): shutil.rmtree(excluded_showcase) _copy_release_resources( @@ -86,15 +84,19 @@ class sdist(_sdist): def make_release_tree(self, base_dir: str, files: list[str]) -> None: # Old egg-info manifests may include Python packages from node_modules. + frontend_prefixes = ("apps/showcase_ui/", "apps/showcase_ui_v2/") filtered_files = [ - path for path in files if not Path(path).as_posix().startswith("apps/showcase_ui/") + path + for path in files + if not Path(path).as_posix().startswith(frontend_prefixes) ] super().make_release_tree(base_dir, filtered_files) # Protect local rebuilds from stale egg-info/SOURCES.txt manifests # generated before package discovery was narrowed. - excluded_showcase = Path(base_dir) / "apps" / "showcase_ui" - if excluded_showcase.exists(): - shutil.rmtree(excluded_showcase) + for excluded_name in ("showcase_ui", "showcase_ui_v2"): + excluded_showcase = Path(base_dir) / "apps" / excluded_name + if excluded_showcase.exists(): + shutil.rmtree(excluded_showcase) _copy_release_resources( Path.cwd(), Path(base_dir) / "artemis" / "resources", diff --git a/start.sh b/start.sh index e288f329d..8c85c73a6 100755 --- a/start.sh +++ b/start.sh @@ -95,7 +95,7 @@ request_sudo() { return 1 } -# Helper to check if Node.js & npm meet Angular CLI 22 requirement (>= 22.22.0, >= 24.15.0, or >= 26.0.0) +# Helper to check if Node.js & npm meet the Vite 7 requirement (^20.19.0 || >= 22.12.0) is_node_compatible() { if ! command -v node >/dev/null 2>&1 || ! command -v npm >/dev/null 2>&1; then return 1 @@ -106,12 +106,12 @@ is_node_compatible() { local major minor major="$(echo "${node_ver}" | cut -d. -f1)" minor="$(echo "${node_ver}" | cut -d. -f2)" - if [ "${major}" -ge 26 ] 2>/dev/null; then + if [ "${major}" -ge 23 ] 2>/dev/null; then return 0 - elif [ "${major}" -ge 24 ] 2>/dev/null; then - [ "${minor}" -ge 15 ] 2>/dev/null && return 0 - elif [ "${major}" -ge 22 ] 2>/dev/null; then - [ "${minor}" -ge 22 ] 2>/dev/null && return 0 + elif [ "${major}" -eq 22 ] 2>/dev/null; then + [ "${minor}" -ge 12 ] 2>/dev/null && return 0 + elif [ "${major}" -eq 20 ] 2>/dev/null; then + [ "${minor}" -ge 19 ] 2>/dev/null && return 0 fi return 1 } @@ -261,10 +261,9 @@ echo -e " ${BLUE}📦 Synchronizing Python runtime and project dependencies... uv sync --quiet # 6. Check and build Showcase UI if not already compiled -SHOWCASE_INDEX="${SCRIPT_DIR}/apps/showcase_ui/dist/frontend/browser/index.html" -SHOWCASE_INDEX_ALT1="${SCRIPT_DIR}/apps/showcase_ui/dist/browser/index.html" -SHOWCASE_INDEX_ALT2="${SCRIPT_DIR}/apps/showcase_ui/dist/index.html" -if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ] && [ ! -f "${SHOWCASE_INDEX_ALT2}" ]; then +SHOWCASE_INDEX="${SCRIPT_DIR}/apps/showcase_ui_v2/dist/browser/index.html" +SHOWCASE_INDEX_ALT1="${SCRIPT_DIR}/apps/showcase_ui_v2/dist/index.html" +if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ]; then # First: Try loading existing nvm or user-installed node in environment export NVM_DIR="${HOME}/.nvm" if [ -s "${NVM_DIR}/nvm.sh" ]; then @@ -283,7 +282,7 @@ if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ] && [ ! -f " if ! is_node_compatible; then OS_NAME="$(uname -s)" if command -v node >/dev/null 2>&1; then - echo -e " ${YELLOW}⚡ Detected Node.js $(node -v 2>/dev/null), but Angular CLI requires Node.js >= v22.22.0. Upgrading Node.js...${NC}" + echo -e " ${YELLOW}⚡ Detected Node.js $(node -v 2>/dev/null), but Vite requires Node.js ^20.19.0 || >= v22.12.0. Upgrading Node.js...${NC}" else echo -e " ${YELLOW}⚡ Node.js/npm not found. Auto-installing Node.js 22 LTS for Showcase UI compilation...${NC}" fi @@ -302,7 +301,7 @@ if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ] && [ ! -f " # 3. Try Linux package managers with sudo / root if ! is_node_compatible && [ "${OS_NAME}" = "Linux" ]; then - if request_sudo "install or upgrade Node.js to >= 22.22.0"; then + if request_sudo "install or upgrade Node.js to >= 22.12.0"; then SUDO_PREFIX="" if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi if command -v apt-get >/dev/null 2>&1; then @@ -347,23 +346,14 @@ if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ] && [ ! -f " if is_node_compatible; then echo -e " ${GREEN}✓ Node.js $(node -v 2>/dev/null) and npm $(npm -v 2>/dev/null) ready.${NC}" - echo -e " ${YELLOW}🎨 Showcase UI build not found. Compiling Angular Showcase UI...${NC}" + echo -e " ${YELLOW}🎨 Showcase UI build not found. Compiling Showcase UI (vite build)...${NC}" ( - cd "${SCRIPT_DIR}/apps/showcase_ui" + cd "${SCRIPT_DIR}/apps/showcase_ui_v2" npm install --silent - # Auto-patch Angular CLI node version constraint if running on Node 22.22.x (e.g. Cloudtop / Debian) - CLI_NODE_VERSION="${SCRIPT_DIR}/apps/showcase_ui/node_modules/@angular/cli/src/utilities/node-version.js" - if [ -f "${CLI_NODE_VERSION}" ]; then - if [ "$(uname -s)" = "Darwin" ]; then - sed -i '' 's/22\.22\.3/22.22.0/g' "${CLI_NODE_VERSION}" 2>/dev/null || true - else - sed -i 's/22\.22\.3/22.22.0/g' "${CLI_NODE_VERSION}" 2>/dev/null || true - fi - fi npm run build ) else - echo -e " ${YELLOW}⚠ Could not configure compatible Node.js (>= 22.22.0). Showcase UI will serve fallback build notice.${NC}" + echo -e " ${YELLOW}⚠ Could not configure compatible Node.js (^20.19.0 || >= 22.12.0). Showcase UI will serve fallback build notice.${NC}" fi fi diff --git a/tests/unit/admin_console/test_showcase_dist.py b/tests/unit/admin_console/test_showcase_dist.py new file mode 100644 index 000000000..d9c56790d --- /dev/null +++ b/tests/unit/admin_console/test_showcase_dist.py @@ -0,0 +1,53 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for the Showcase UI dist discovery in the unified server.""" + +import apps.admin_console.server as server_module +from apps.admin_console.server import _get_showcase_dist + + +def _write_index(directory): + directory.mkdir(parents=True, exist_ok=True) + (directory / "index.html").write_text("", encoding="utf-8") + return directory + + +def test_get_showcase_dist_prefers_vite_browser_build(tmp_path, monkeypatch): + browser_dist = _write_index(tmp_path / "apps" / "showcase_ui_v2" / "dist" / "browser") + monkeypatch.setattr(server_module, "_workspace_root", tmp_path) + + assert _get_showcase_dist() == browser_dist + + +def test_get_showcase_dist_falls_back_to_dist_root(tmp_path, monkeypatch): + dist_root = _write_index(tmp_path / "apps" / "showcase_ui_v2" / "dist") + monkeypatch.setattr(server_module, "_workspace_root", tmp_path) + + assert _get_showcase_dist() == dist_root + + +def test_get_showcase_dist_falls_back_to_bundled_wheel_resources(tmp_path, monkeypatch): + monkeypatch.setattr(server_module, "_workspace_root", tmp_path) + bundled = _write_index(tmp_path / "wheel" / "artemis" / "resources" / "showcase_ui") + monkeypatch.setattr(server_module, "get_bundled_showcase_dist", lambda: bundled) + + assert _get_showcase_dist() == bundled + + +def test_get_showcase_dist_last_resort_points_at_vite_browser_dist(tmp_path, monkeypatch): + monkeypatch.setattr(server_module, "_workspace_root", tmp_path) + monkeypatch.setattr(server_module, "get_bundled_showcase_dist", lambda: None) + + assert _get_showcase_dist() == tmp_path / "apps" / "showcase_ui_v2" / "dist" / "browser" diff --git a/tests/unit/test_packaging_resources.py b/tests/unit/test_packaging_resources.py index 2dd4b74d0..cdd27c14b 100644 --- a/tests/unit/test_packaging_resources.py +++ b/tests/unit/test_packaging_resources.py @@ -14,11 +14,43 @@ """Contract tests for release metadata and bundled runtime resources.""" +import ast +from fnmatch import fnmatch from importlib.metadata import version +from pathlib import Path import artemis from artemis import resources +SETUP_PY = Path(__file__).resolve().parents[2] / "setup.py" + + +def _setup_call_keyword(keyword_name): + """Extract a literal keyword argument from the ``setup()`` call in setup.py.""" + tree = ast.parse(SETUP_PY.read_text(encoding="utf-8")) + for node in ast.walk(tree): + if isinstance(node, ast.Call) and getattr(node.func, "id", "") == "setup": + for keyword in node.keywords: + if keyword.arg == keyword_name: + return ast.literal_eval(keyword.value) + raise AssertionError(f"setup() keyword {keyword_name!r} not found in setup.py") + + +def _load_setup_showcase_dist(): + """Load ``_showcase_dist`` from setup.py without executing ``setup()``.""" + tree = ast.parse(SETUP_PY.read_text(encoding="utf-8")) + module = ast.Module( + body=[ + node + for node in tree.body + if isinstance(node, ast.FunctionDef) and node.name == "_showcase_dist" + ], + type_ignores=[], + ) + namespace = {"Path": Path} + exec(compile(module, str(SETUP_PY), "exec"), namespace) + return namespace["_showcase_dist"] + def test_public_version_comes_from_distribution_metadata(): assert artemis.__version__ == version("artemis") @@ -32,6 +64,49 @@ def test_source_tree_contains_complete_release_resources(): assert showcase_path is not None and (showcase_path / "index.html").is_file() +def test_bundled_showcase_dist_supports_vite_asset_tree(tmp_path, monkeypatch): + resource_root = tmp_path / "resources" + showcase_dir = resource_root / "showcase_ui" + (showcase_dir / "assets").mkdir(parents=True) + (showcase_dir / "index.html").write_text("", encoding="utf-8") + (showcase_dir / "assets" / "index-CMeBErSD.js").write_text("js", encoding="utf-8") + + monkeypatch.setattr(resources, "files", lambda _package: resource_root) + + assert resources.get_bundled_showcase_dist() == showcase_dir + + +def test_setup_showcase_dist_prefers_vite_source_build(tmp_path): + showcase_dist = _load_setup_showcase_dist() + browser_dist = tmp_path / "apps" / "showcase_ui_v2" / "dist" / "browser" + browser_dist.mkdir(parents=True) + (browser_dist / "index.html").write_text("", encoding="utf-8") + + assert showcase_dist(tmp_path) == browser_dist + + +def test_setup_showcase_dist_falls_back_to_bundled_resources(tmp_path): + showcase_dist = _load_setup_showcase_dist() + bundled = tmp_path / "artemis" / "resources" / "showcase_ui" + bundled.mkdir(parents=True) + (bundled / "index.html").write_text("", encoding="utf-8") + + assert showcase_dist(tmp_path) == bundled + + +def test_package_data_patterns_cover_vite_asset_tree(): + package_data = _setup_call_keyword("package_data") + patterns = package_data["artemis.resources"] + + assert "showcase_ui/*" in patterns + assert "showcase_ui/**/*" in patterns + # Vite output shape: entry document at the root, hashed bundles under assets/. + assert fnmatch("showcase_ui/index.html", "showcase_ui/*") + assert fnmatch("showcase_ui/favicon.ico", "showcase_ui/*") + assert fnmatch("showcase_ui/assets/index-CMeBErSD.js", "showcase_ui/**/*") + assert fnmatch("showcase_ui/assets/index-8cJomhOD.css", "showcase_ui/**/*") + + def test_bundled_resource_accessors_require_complete_assets(tmp_path, monkeypatch): resource_root = tmp_path / "resources" config_dir = resource_root / "config" diff --git a/tests/unit/test_ui_command.py b/tests/unit/test_ui_command.py index a00b334a5..644ea26d4 100644 --- a/tests/unit/test_ui_command.py +++ b/tests/unit/test_ui_command.py @@ -46,9 +46,9 @@ def test_resolve_npm_executable_uses_npm_on_posix(monkeypatch): def test_showcase_build_required_when_source_is_newer(tmp_path): - showcase_dir = tmp_path / "showcase_ui" - source_file = showcase_dir / "src" / "app" / "agent.service.ts" - built_index = showcase_dir / "dist" / "frontend" / "browser" / "index.html" + showcase_dir = tmp_path / "showcase_ui_v2" + source_file = showcase_dir / "src" / "stores" / "system.ts" + built_index = showcase_dir / "dist" / "browser" / "index.html" source_file.parent.mkdir(parents=True) built_index.parent.mkdir(parents=True) source_file.write_text("source", encoding="utf-8") @@ -61,9 +61,9 @@ def test_showcase_build_required_when_source_is_newer(tmp_path): def test_showcase_build_not_required_when_build_is_current(tmp_path): - showcase_dir = tmp_path / "showcase_ui" - source_file = showcase_dir / "src" / "app" / "agent.service.ts" - built_index = showcase_dir / "dist" / "frontend" / "browser" / "index.html" + showcase_dir = tmp_path / "showcase_ui_v2" + source_file = showcase_dir / "src" / "stores" / "system.ts" + built_index = showcase_dir / "dist" / "browser" / "index.html" source_file.parent.mkdir(parents=True) built_index.parent.mkdir(parents=True) source_file.write_text("source", encoding="utf-8") @@ -75,6 +75,24 @@ def test_showcase_build_not_required_when_build_is_current(tmp_path): assert _showcase_build_required(showcase_dir) is False +def test_showcase_build_required_when_vite_config_is_newer(tmp_path): + showcase_dir = tmp_path / "showcase_ui_v2" + source_file = showcase_dir / "src" / "main.ts" + vite_config = showcase_dir / "vite.config.ts" + built_index = showcase_dir / "dist" / "browser" / "index.html" + source_file.parent.mkdir(parents=True) + built_index.parent.mkdir(parents=True) + source_file.write_text("source", encoding="utf-8") + vite_config.write_text("export default {}", encoding="utf-8") + built_index.write_text("build", encoding="utf-8") + + os.utime(source_file, (100, 100)) + os.utime(built_index, (200, 200)) + os.utime(vite_config, (300, 300)) + + assert _showcase_build_required(showcase_dir) is True + + def _showcase_with_manifests(tmp_path, *, stamp_mtime=None): showcase_dir = tmp_path / "showcase_ui" showcase_dir.mkdir() @@ -121,7 +139,7 @@ def test_ensure_showcase_built_skips_install_when_deps_current(monkeypatch): ensure_showcase_built(console) - assert [label for label, _ in steps] == ["② ng build"] + assert [label for label, _ in steps] == ["② vite build"] assert steps[0][1] == ["npm", "run", "build"] assert "Showcase UI built in" in console.file.getvalue() @@ -137,7 +155,7 @@ def test_ensure_showcase_built_runs_install_first_when_deps_changed(monkeypatch) ensure_showcase_built(_recording_console()) - assert [label for label, _ in steps] == ["① npm install (dependencies changed)", "② ng build"] + assert [label for label, _ in steps] == ["① npm install (dependencies changed)", "② vite build"] assert steps[0][1] == ["npm", "install", "--no-audit", "--no-fund", "--loglevel=warn"] @@ -164,11 +182,11 @@ def test_run_build_step_streams_child_output_and_raises_on_failure(tmp_path): cmd = [sys.executable, "-c", "print('hello from child'); import sys; sys.exit(3)"] with pytest.raises(subprocess.CalledProcessError) as excinfo: - _run_build_step(console, "② ng build", cmd, tmp_path) + _run_build_step(console, "② vite build", cmd, tmp_path) assert excinfo.value.returncode == 3 output = console.file.getvalue() - assert "② ng build" in output + assert "② vite build" in output assert "hello from child" in output From e7b9e493f6ac4d1cbd8a8cd265c8e42fa4d6d271 Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 19:38:07 +0800 Subject: [PATCH 015/320] chore: post-migration cleanup (legacy alias, engines, release-ui) + changelog - drop the Angular-era `filter_event_for_angular` alias in ipc_service (zero callers since the Angular app was removed) - declare engines node>=20.19.0 in showcase_ui_v2 (aligns with the Vite 7 requirement already enforced by start.sh and CI) - add `make release-ui` to build the Vue frontend and sync it into the wheel fallback resources in one step - record the completed Angular -> Vue migration in changelogs.md --- Makefile | 7 +++++- apps/admin_console/services/ipc_service.py | 3 --- apps/showcase_ui_v2/package.json | 3 +++ changelogs.md | 29 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 907fd2f68..7c076b52c 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -.PHONY: help test test-integration test-device test-all install install-deps setup start ui restart stop status build-ui doctor clean precommit-install precommit lint format typecheck quality-ratchet +.PHONY: help test test-integration test-device test-all install install-deps setup start ui restart stop status build-ui release-ui doctor clean precommit-install precommit lint format typecheck quality-ratchet help: ## Show this help message @echo 'Usage: make [target]' @@ -39,6 +39,11 @@ build-ui: ## Build the Showcase UI (Vue 3 + Vite) frontend @echo "🎨 Building Showcase UI..." @cd apps/showcase_ui_v2 && npm install && npm run build +release-ui: ## Build the Showcase UI and sync it into the wheel fallback resources + @echo "🚀 Releasing Showcase UI resources..." + @$(MAKE) build-ui + @cd apps/showcase_ui_v2 && npm run sync:resources + doctor: ## Run system, device, and toolchain diagnostics @uv run artemis doctor diff --git a/apps/admin_console/services/ipc_service.py b/apps/admin_console/services/ipc_service.py index 712b1d805..1dfaaeba3 100644 --- a/apps/admin_console/services/ipc_service.py +++ b/apps/admin_console/services/ipc_service.py @@ -133,9 +133,6 @@ def sanitize_event_data(cls, event_type: str, data: Any) -> Any: return data - # Backward compatibility alias - filter_event_for_angular = sanitize_event_data - @classmethod async def start_server(cls): async def handle_client(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): diff --git a/apps/showcase_ui_v2/package.json b/apps/showcase_ui_v2/package.json index a13098b45..fb6673bf3 100644 --- a/apps/showcase_ui_v2/package.json +++ b/apps/showcase_ui_v2/package.json @@ -4,6 +4,9 @@ "private": true, "type": "module", "description": "ARTEMIS showcase UI v2 - Vue 3 + Arco Design Vue rewrite (M0 scaffold)", + "engines": { + "node": ">=20.19.0" + }, "scripts": { "dev": "vite", "build": "vue-tsc --noEmit && vite build", diff --git a/changelogs.md b/changelogs.md index 40171ad90..fc82621ea 100644 --- a/changelogs.md +++ b/changelogs.md @@ -192,3 +192,32 @@ | 10-06 五测 | 故障注入:`api_base` 指向死端口 | ✅ CLI 显示 `Connection error.` + 定位提示;`sessions.error_message` 持久化(#3-1) | | 10-06 六测 | Flash 回归(恢复配置)+ 编译产物 | ✅ 任务成功;`Materialized N steps`、`steps.json` 非空、`trace.gif` 生成;成功会话 error_message 为 NULL(#3-2) | | 10-06 七测 | 无控制台父进程启动 Jupyter 内核 + 窗口快照 diff | ✅ 无新窗口弹出;内核执行正常(`print(2+3)`→`5`),输出落盘 `kernel.log`(#5) | + +--- + +### #6 前端 Web 控制台重构迁移完成(Angular 22 → Vue 3 + Arco Design Vue) + +- **日期**: 2026-10-06 +- **状态**: ✅ 已完成 +- **优先级**: 高(Web 控制台前端工程整体一次性替换) +- **来源**: 前端迁移专项(M0–M6 里程碑收官) + +#### 迁移内容 + +旧 Angular 22 工程(`apps/showcase_ui`)已删除,由 Vue 3 + Arco Design Vue 新工程 +(`apps/showcase_ui_v2`)完整承接,M0–M6 全部里程碑完成: + +- **SSE 实时流**:任务时间线 / 截图 / 工具调用事件实时推送渲染,替代旧轮询与增量构建链路。 +- **回放投屏**:会话回放视图与投屏(cast)桥接层按编译期结构断言对齐真实契约。 +- **系统诊断**:连通性 / 就绪度(readiness)诊断接入,联动顶栏在线状态指示。 +- **托管切换(决策 D2,一次性替换)**:`server.py` 的静态产物探测候选指向 + `apps/showcase_ui_v2/dist/browser`(源码树托管);wheel 回退产物 + `artemis/resources/showcase_ui` 经 `npm run sync:resources` 同步为 Vite 产物 + (发布流程可 `make release-ui` 一键构建 + 同步);无 /v2 并行子路径。 + +#### 验收标准 + +- [x] 前端:vitest 198 用例全绿 + vue-tsc 零错误 + 生产构建通过 +- [x] 后端:托管链路 66 用例全绿 +- [x] 打包:`uv build --wheel` 解包确认 `showcase_ui` 资源完整 + From 7007cf609e6b9cbbdcbb24b41db119f4a4a35778 Mon Sep 17 00:00:00 2001 From: giveUphope Date: Tue, 6 Oct 2026 19:38:16 +0800 Subject: [PATCH 016/320] feat(showcase-v2): deep i18n, typewriter polish and tree/presets/replay panels - deep i18n: 89 user-facing strings in tool-formatter/action-formatter move to tools.*/actions.* keys (157 keys x 2 locales) via a tUtil wrapper on the global vue-i18n instance; en-US output stays byte-identical and util specs assert against en-US. - typewriter: useTypewriter composable ports the Angular typedTexts semantics (text/thought lanes, 667 chars/s, single rewind on stream reset, zero timers for historical sessions); planning loader rotates 16 localized phrases every 2.8s while visible. - new session-extras panels wired to previously unconsumed endpoints: task preset chips on the launcher (GET /api/tasks/presets, click fills the input), session trace tree drawer (GET /api/sessions/{id}/tree) and a step replay debug drawer (replay tools/config/steps/traces with an explicit confirm dialog before the sandboxed execution). - README: known-boundary notes updated, post-migration increments documented. --- apps/showcase_ui_v2/README.md | 29 +- .../session-extras/ReplayDrawer.spec.ts | 258 +++++++ .../session-extras/ReplayDrawer.vue | 627 ++++++++++++++++++ .../session-extras/SessionTreeDrawer.spec.ts | 138 ++++ .../session-extras/SessionTreeDrawer.vue | 131 ++++ .../session-extras/TaskPresets.spec.ts | 128 ++++ .../components/session-extras/TaskPresets.vue | 98 +++ .../components/timeline/AgentTimeline.spec.ts | 39 +- .../src/components/timeline/AgentTimeline.vue | 82 ++- .../src/components/timeline/StepCard.vue | 78 ++- .../components/timeline/useTypewriter.spec.ts | 156 +++++ .../src/components/timeline/useTypewriter.ts | 183 +++++ apps/showcase_ui_v2/src/locales/en-US.ts | 293 ++++++++ apps/showcase_ui_v2/src/locales/zh-CN.ts | 293 ++++++++ .../src/utils/action-formatter.spec.ts | 87 +++ .../src/utils/action-formatter.ts | 55 +- apps/showcase_ui_v2/src/utils/i18n.ts | 10 + .../src/utils/tool-formatter.spec.ts | 219 ++++++ .../src/utils/tool-formatter.ts | 230 +++---- .../showcase_ui_v2/src/views/LauncherView.vue | 4 + 20 files changed, 2972 insertions(+), 166 deletions(-) create mode 100644 apps/showcase_ui_v2/src/components/session-extras/ReplayDrawer.spec.ts create mode 100644 apps/showcase_ui_v2/src/components/session-extras/ReplayDrawer.vue create mode 100644 apps/showcase_ui_v2/src/components/session-extras/SessionTreeDrawer.spec.ts create mode 100644 apps/showcase_ui_v2/src/components/session-extras/SessionTreeDrawer.vue create mode 100644 apps/showcase_ui_v2/src/components/session-extras/TaskPresets.spec.ts create mode 100644 apps/showcase_ui_v2/src/components/session-extras/TaskPresets.vue create mode 100644 apps/showcase_ui_v2/src/components/timeline/useTypewriter.spec.ts create mode 100644 apps/showcase_ui_v2/src/components/timeline/useTypewriter.ts create mode 100644 apps/showcase_ui_v2/src/utils/action-formatter.spec.ts create mode 100644 apps/showcase_ui_v2/src/utils/i18n.ts create mode 100644 apps/showcase_ui_v2/src/utils/tool-formatter.spec.ts diff --git a/apps/showcase_ui_v2/README.md b/apps/showcase_ui_v2/README.md index a6b46a099..74a2f200d 100644 --- a/apps/showcase_ui_v2/README.md +++ b/apps/showcase_ui_v2/README.md @@ -215,9 +215,9 @@ src/ ### 已知边界(M4/M6 接入) - ~~`recording_ready` / `recording_failed` 事件分支已预留~~ —— 播放器联动已随 **M4** 接入(见下节)。 -- 逐字符打字机动画与流重置 rewind(Angular typedTexts/rewind 系统)未做:流文本随 - 80ms 合批 flush 增长,M6 打磨期再评估。 -- 重试延时文案保留 1 位小数(Angular 为 2 位);planning loader 未平移 Angular 的轮换短语。 +- ~~逐字符打字机动画与流重置 rewind~~ —— 已随**迁移后增量**补齐(见文末"迁移后增量迭代")。 +- 重试延时文案保留 1 位小数(Angular 为 2 位);~~planning loader 未平移 Angular 的 + 轮换短语~~ —— 16 条轮换短语已随**迁移后增量**补齐。 ## M4 完成范围(回放 / 投屏) @@ -326,6 +326,7 @@ src/ (含 `assets/` 子目录与 `public/` 拷入的 favicon/logo)→ 打印同步文件清单摘要。 - 用法:发布流程为 `npm run build && npm run sync:resources`。`sync:resources` 是**发布动作,手动执行**,有意不挂进 `build`(避免日常构建误改 wheel 回退目录)。 + 也可在仓库根目录用 `make release-ui` 一键完成构建 + 同步。 - 目标目录判定:`artemis/resources/showcase_ui` 是 wheel 安装态的回退产物 (`artemis/resources/__init__.py::get_bundled_showcase_dist` 以 `index.html` 存在为准)。同步后旧 Angular 平铺文件在 git 状态中显示为 deleted,属预期变更。 @@ -361,10 +362,22 @@ src/ ### 已知边界(长期) -- `src/utils/**` 生成的语义文案(如动作描述 "Tapping Element"、probe 的 - title/summary 等后端字段)保持原样不 i18n——自 M2 起明确的边界:它们是 - 面向协议/调试的语义标签而非界面文案,深度 i18n 不做。 -- 逐字符打字机动画与流重置 rewind(Angular typedTexts/rewind 系统)未平移 - (M3 已知边界,流文本以 80ms 合批增长替代)。 +- ~~`src/utils/**` 生成的语义文案不 i18n~~ —— **已完成深度 i18n**(迁移后增量): + tool-formatter/action-formatter 共 89 处用户可见文案迁入 `tools.*` / `actions.*` + 键(157 键 ×2 locale,经 `utils/i18n.ts` 的 `tUtil` 走 vue-i18n 全局实例, + en-US 输出与迁移前逐字节一致,util spec 以 en-US 断言锁定)。仅保留非 i18n + 对象:后端字段透传(probe title/summary 等)、协议 token、专有名词。 +- ~~逐字符打字机动画与流重置 rewind 未平移~~ —— 已补齐(迁移后增量)。 - 主 bundle 超过 Vite 500 kB 分包提示(Arco 全量注册所致),gzip 后约 327 kB, 保持全量引入以对齐 Angular 版能力,不做按需拆分优化。 + +## 迁移后增量迭代 + +M0–M6 之外的挂起项收尾(对应各里程碑已知边界与调研报告 §2.2 的"未消费端点")。 + +| 项 | 内容 | +| --- | --- | +| 工程收尾 | `ipc_service.py` 删除 Angular 时代遗留别名 `filter_event_for_angular`;`package.json` 补 `engines: node>=20.19.0`(对齐 Vite 7 要求与 start.sh 校验);`make release-ui` 一键构建 + 同步 wheel 回退资源;`changelogs.md` 补迁移完成记录 | +| 深度 i18n | 见上文 M6 已知边界的修订说明 | +| 打字机与轮换短语 | `useTypewriter` composable(双泳道 text/thought、母本节奏 667 chars/s 等价移植、live 判定零常驻定时器、`isReset` 单次 rewind);planning loader 16 条轮换短语(2800ms,loader 可见才轮转) | +| 未消费端点接入 | `GET /api/tasks/presets` → 启动器推荐任务 chips(点击填入不直接提交,失败静默);`GET /api/sessions/{id}/tree` → 时间线工具条"轨迹树"抽屉(a-tree,按 trace 树节点归一渲染);回放调试组(`/api/replay/tools|config`、`replay_steps`、`steps/{n}/replay`、`replay_traces`)→ 时间线工具条"步骤回放"抽屉(设备/工具选择 + **真实执行二次确认** + 结果折叠展示) | diff --git a/apps/showcase_ui_v2/src/components/session-extras/ReplayDrawer.spec.ts b/apps/showcase_ui_v2/src/components/session-extras/ReplayDrawer.spec.ts new file mode 100644 index 000000000..a72d37237 --- /dev/null +++ b/apps/showcase_ui_v2/src/components/session-extras/ReplayDrawer.spec.ts @@ -0,0 +1,258 @@ +import { flushPromises, mount } from '@vue/test-utils'; +import ArcoVue from '@arco-design/web-vue'; +import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; +import { createI18n } from 'vue-i18n'; + +import zhCN from '../../locales/zh-CN'; +import ReplayDrawer from './ReplayDrawer.vue'; + +/** + * 组件测试:ReplayDrawer(B6 步骤回放调试)。 + * vi.mock('@/services/api')(保留真实 ApiError),参照 DiagnosticsWizard.spec 风格。 + * 覆盖:replay_steps 404 空态、步骤/设备/工具渲染、确认弹窗拦截 POST(取消不发请求、 + * 确认后才 POST 且 body 含 device_id/user_submits/tool_name/replay_id)、 + * 无设备时回放按钮禁用、查看上次结果。抽屉与弹窗 teleport 到 body。 + */ + +vi.mock('@/services/api', async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, apiGet: vi.fn(), apiPost: vi.fn() }; +}); + +import { apiGet, apiPost } from '@/services/api'; + +const apiGetMock = apiGet as unknown as Mock; +const apiPostMock = apiPost as unknown as Mock; + +const i18n = createI18n({ + legacy: false, + locale: 'zh-CN', + messages: { 'zh-CN': zhCN }, +}); + +// 形状对齐 replay_manager.get_replay_steps / list_devices / get_replay_tools / get_replay_config。 +const STEPS = [ + { + step_id: 's3', + step_number: 3, + timestamp: 1756152003, + summary: '点击设置应用图标', + action_taken: [], + query: '', + param_defaults: { ask_explorer: { instruction: '打开设置并查看电量' } }, + pre_screenshot: null, + post_screenshot: null, + operator_raw_thinking: null, + operator_native_thinking: null, + is_replayed: true, + }, + { + step_id: 's4', + step_number: 4, + timestamp: 1756152010, + summary: '滑动屏幕查看更多选项', + action_taken: [], + query: '', + param_defaults: {}, + pre_screenshot: null, + post_screenshot: null, + operator_raw_thinking: null, + operator_native_thinking: null, + is_replayed: false, + }, +]; + +const DEVICES = [{ serial: 'dev-1', status: 'online' }]; +const TOOLS = [ + { name: 'ask_explorer', display_name: 'Ask Explorer', description: 'Explore the screen' }, +]; +const TOOL_CONFIG = [ + { name: 'instruction', default: '', input_type: 'textarea' }, + { name: 'max_steps', default: 5, input_type: 'number' }, +]; + +/** 按 URL mock GET;replay_steps 404 场景由用例覆写。 */ +function mockBackend(overrides: { steps?: unknown; devices?: unknown } = {}) { + apiGetMock.mockImplementation((url: string) => { + if (url === '/api/devices') return Promise.resolve(overrides.devices ?? DEVICES); + if (url === '/api/replay/tools') return Promise.resolve(TOOLS); + if (url === '/api/replay/config') return Promise.resolve(TOOL_CONFIG); + if (url === '/api/sessions/s1/replay_steps') return Promise.resolve(overrides.steps ?? STEPS); + if (url === '/api/sessions/s1/steps/3/replay_traces') { + return Promise.resolve({ success: true, live: [{ trace_id: 'r1', name: 'ask_explorer' }], preloaded: [] }); + } + return Promise.resolve({}); + }); +} + +function mountDrawer() { + return mount(ReplayDrawer, { + props: { visible: true, sessionId: 's1' }, + global: { + plugins: [ArcoVue, i18n], + }, + }); +} + +function findModalButton(text: string): HTMLButtonElement | undefined { + return Array.from(document.querySelectorAll('.arco-modal-footer button')).find( + (btn) => (btn.textContent || '').includes(text), + ); +} + +/** + * a-modal 关闭后 DOM(v-show)仍保留在 body:隐藏样式分布在 + * `.arco-modal-container` / `.arco-modal` 上,任一处于 display:none 即视为关闭; + * 若实现改为卸载式渲染(元素不存在)同样视为关闭。 + */ +function isModalHidden(): boolean { + const els = Array.from(document.querySelectorAll('.arco-modal-container, .arco-modal')); + if (els.length === 0) return true; + return els.some((el) => el.style.display === 'none'); +} + +/** 步骤卡上的"回放"按钮(位于 .step-actions,文本恰为"回放",不匹配"开始回放/查看上次结果")。 */ +function findReplayButtons(): HTMLButtonElement[] { + return Array.from(document.querySelectorAll('.step-actions button')).filter( + (btn) => (btn.textContent || '').trim() === '回放', + ); +} + +/** 步骤卡上的"查看上次结果"按钮。 */ +function findLastResultButtons(): HTMLButtonElement[] { + return Array.from(document.querySelectorAll('.step-actions button')).filter( + (btn) => (btn.textContent || '').includes('查看上次结果'), + ); +} + +describe('ReplayDrawer (B6)', () => { + beforeEach(() => { + vi.clearAllMocks(); + apiGetMock.mockReset(); + apiPostMock.mockReset(); + document.body.innerHTML = ''; + }); + + it('shows the empty state when replay_steps returns 404', async () => { + const { ApiError } = await import('@/services/api'); + mockBackend(); + apiGetMock.mockImplementation((url: string) => { + if (url === '/api/sessions/s1/replay_steps') { + return Promise.reject(new ApiError(404, 'HTTP 404', { detail: 'no chunked data' })); + } + if (url === '/api/devices') return Promise.resolve(DEVICES); + if (url === '/api/replay/tools') return Promise.resolve(TOOLS); + if (url === '/api/replay/config') return Promise.resolve(TOOL_CONFIG); + return Promise.resolve({}); + }); + + mountDrawer(); + await flushPromises(); + + const body = document.body.textContent || ''; + expect(body).toContain('该会话没有可回放的步骤数据'); + expect(body).not.toContain('点击设置应用图标'); + }); + + it('renders devices, tools, tool params and replay steps', async () => { + mockBackend(); + mountDrawer(); + await flushPromises(); + + const body = document.body.textContent || ''; + expect(body).toContain('步骤回放调试'); + expect(body).toContain('工具参数说明'); + expect(body).toContain('instruction'); + expect(body).toContain('textarea'); + expect(body).toContain('步骤 3'); + expect(body).toContain('点击设置应用图标'); + expect(body).toContain('已回放'); + // 步骤回放按钮可用(设备/工具就绪) + const replayBtn = findReplayButtons()[0]!; + expect(replayBtn.hasAttribute('disabled')).toBe(false); + }); + + it('blocks the POST behind the confirm modal: cancel sends nothing', async () => { + mockBackend(); + mountDrawer(); + await flushPromises(); + + findReplayButtons()[0]!.click(); + await flushPromises(); + + const body = document.body.textContent || ''; + expect(body).toContain('确认执行回放'); + expect(body).toContain('将在设备 dev-1 上真实执行第 3 步的沙箱回放'); + expect(apiPostMock).not.toHaveBeenCalled(); + + const cancelBtn = findModalButton('取消'); + expect(cancelBtn).toBeTruthy(); + cancelBtn!.click(); + await flushPromises(); + + expect(apiPostMock).not.toHaveBeenCalled(); + expect(isModalHidden()).toBe(true); + }); + + it('posts the replay only after confirming, then renders the result collapse', async () => { + mockBackend(); + apiPostMock.mockResolvedValue({ + success: true, + preloaded: [{ trace_id: 'p1', name: 'preloaded' }], + live: [{ trace_id: 'l1', name: 'ask_explorer' }], + replay_id: 'rp-1', + }); + mountDrawer(); + await flushPromises(); + + findReplayButtons()[0]!.click(); + await flushPromises(); + + const okBtn = findModalButton('开始回放'); + expect(okBtn).toBeTruthy(); + okBtn!.click(); + await flushPromises(); + + expect(apiPostMock).toHaveBeenCalledTimes(1); + expect(apiPostMock).toHaveBeenCalledWith('/api/sessions/s1/steps/3/replay', { + device_id: 'dev-1', + user_submits: { instruction: '打开设置并查看电量' }, + tool_name: 'ask_explorer', + replay_id: null, + }); + + const body = document.body.textContent || ''; + expect(body).toContain('第 3 步回放结果'); + expect(body).toContain('实时轨迹(1 条)'); + expect(body).toContain('预载轨迹(1 条)'); + }); + + it('disables the replay button when no device is available', async () => { + mockBackend({ devices: [] }); + mountDrawer(); + await flushPromises(); + + expect((document.body.textContent || '')).toContain('未检测到可用设备'); + const replayBtn = findReplayButtons()[0]!; + expect(replayBtn.hasAttribute('disabled')).toBe(true); + replayBtn.click(); + await flushPromises(); + expect(apiPostMock).not.toHaveBeenCalled(); + expect(isModalHidden()).toBe(true); + }); + + it('loads the last replay result via replay_traces', async () => { + mockBackend(); + mountDrawer(); + await flushPromises(); + + const lastBtns = findLastResultButtons(); + lastBtns[0]!.click(); + await flushPromises(); + + expect(apiGetMock).toHaveBeenCalledWith('/api/sessions/s1/steps/3/replay_traces', { + params: { tool_name: 'ask_explorer' }, + }); + expect((document.body.textContent || '')).toContain('历史结果'); + }); +}); diff --git a/apps/showcase_ui_v2/src/components/session-extras/ReplayDrawer.vue b/apps/showcase_ui_v2/src/components/session-extras/ReplayDrawer.vue new file mode 100644 index 000000000..e5fc714de --- /dev/null +++ b/apps/showcase_ui_v2/src/components/session-extras/ReplayDrawer.vue @@ -0,0 +1,627 @@ + + + + + diff --git a/apps/showcase_ui_v2/src/components/session-extras/SessionTreeDrawer.spec.ts b/apps/showcase_ui_v2/src/components/session-extras/SessionTreeDrawer.spec.ts new file mode 100644 index 000000000..cef39b57d --- /dev/null +++ b/apps/showcase_ui_v2/src/components/session-extras/SessionTreeDrawer.spec.ts @@ -0,0 +1,138 @@ +import { flushPromises, mount } from '@vue/test-utils'; +import ArcoVue from '@arco-design/web-vue'; +import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; +import { createI18n } from 'vue-i18n'; + +import zhCN from '../../locales/zh-CN'; +import SessionTreeDrawer from './SessionTreeDrawer.vue'; + +/** + * 组件测试:SessionTreeDrawer(B6 轨迹树抽屉)。 + * vi.mock('@/services/api')(保留真实 ApiError),参照 DiagnosticsWizard.spec 风格。 + * 覆盖:关闭状态不拉取(仅点击时拉取)、节点摘要渲染、空态、加载失败(detail 透传)、 + * 会话切换重开重拉。抽屉内容 teleport 到 body,断言走 document.body。 + */ + +vi.mock('@/services/api', async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, apiGet: vi.fn(), apiPost: vi.fn() }; +}); + +import { apiGet } from '@/services/api'; + +const apiGetMock = apiGet as unknown as Mock; + +const i18n = createI18n({ + legacy: false, + locale: 'zh-CN', + messages: { 'zh-CN': zhCN }, +}); + +// 节点形状对齐 trace_repo.get_trace_tree(trace_repository.py)。 +const TREE = [ + { + trace_id: 't1', + parent_trace_id: null, + type: 'span', + name: 'operator', + status: 'success', + timestamp: 1756152001, + duration: 1.234, + payload: null, + children: [ + { + trace_id: 't2', + parent_trace_id: 't1', + type: 'tool', + name: 'tap', + status: 'success', + timestamp: 1756152002, + duration: 0.5, + payload: { args: { target: '设置' } }, + children: [], + }, + ], + }, + { + trace_id: 't3', + parent_trace_id: null, + type: 'span', + name: 'validator', + status: 'failed', + timestamp: 1756152003, + duration: 0.25, + payload: null, + children: [], + }, +]; + +function mountDrawer(props: { visible: boolean; sessionId: string | null }) { + return mount(SessionTreeDrawer, { + props, + global: { + plugins: [ArcoVue, i18n], + }, + }); +} + +describe('SessionTreeDrawer (B6)', () => { + beforeEach(() => { + vi.clearAllMocks(); + apiGetMock.mockReset(); + document.body.innerHTML = ''; + }); + + it('does not fetch while closed (no auto fetch)', async () => { + const wrapper = mountDrawer({ visible: false, sessionId: 'sess-1' }); + await flushPromises(); + expect(apiGetMock).not.toHaveBeenCalled(); + + await wrapper.setProps({ visible: true }); + await flushPromises(); + expect(apiGetMock).toHaveBeenCalledTimes(1); + expect(apiGetMock).toHaveBeenCalledWith('/api/sessions/sess-1/tree'); + }); + + it('renders normalized trace nodes as tree titles', async () => { + apiGetMock.mockResolvedValue(TREE); + mountDrawer({ visible: true, sessionId: 'sess-1' }); + await flushPromises(); + + const body = document.body.textContent || ''; + // title 摘要 = name · type · status · duration + expect(body).toContain('会话轨迹树'); + expect(body).toContain('operator · span · success · 1234ms'); + expect(body).toContain('validator · span · failed · 250ms'); + }); + + it('shows the empty state for an empty tree payload', async () => { + apiGetMock.mockResolvedValue([]); + mountDrawer({ visible: true, sessionId: 'sess-1' }); + await flushPromises(); + + expect(document.body.textContent || '').toContain('该会话暂无轨迹数据'); + }); + + it('shows the backend detail when loading fails', async () => { + const { ApiError } = await import('@/services/api'); + apiGetMock.mockRejectedValue(new ApiError(500, 'HTTP 500', { detail: 'db broken' })); + mountDrawer({ visible: true, sessionId: 'sess-1' }); + await flushPromises(); + + const body = document.body.textContent || ''; + expect(body).toContain('轨迹树加载失败'); + expect(body).toContain('db broken'); + }); + + it('re-fetches when the session changes while the drawer stays open', async () => { + apiGetMock.mockResolvedValue(TREE); + const wrapper = mountDrawer({ visible: true, sessionId: 'sess-1' }); + await flushPromises(); + expect(apiGetMock).toHaveBeenCalledTimes(1); + + await wrapper.setProps({ sessionId: 'sess-2' }); + await flushPromises(); + expect(apiGetMock).toHaveBeenCalledTimes(2); + expect(apiGetMock).toHaveBeenLastCalledWith('/api/sessions/sess-2/tree'); + }); +}); diff --git a/apps/showcase_ui_v2/src/components/session-extras/SessionTreeDrawer.vue b/apps/showcase_ui_v2/src/components/session-extras/SessionTreeDrawer.vue new file mode 100644 index 000000000..f87a747ca --- /dev/null +++ b/apps/showcase_ui_v2/src/components/session-extras/SessionTreeDrawer.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/apps/showcase_ui_v2/src/components/session-extras/TaskPresets.spec.ts b/apps/showcase_ui_v2/src/components/session-extras/TaskPresets.spec.ts new file mode 100644 index 000000000..b9837e4d2 --- /dev/null +++ b/apps/showcase_ui_v2/src/components/session-extras/TaskPresets.spec.ts @@ -0,0 +1,128 @@ +import { flushPromises, mount } from '@vue/test-utils'; +import ArcoVue from '@arco-design/web-vue'; +import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; +import { createI18n } from 'vue-i18n'; + +import zhCN from '../../locales/zh-CN'; +import TaskPresets from './TaskPresets.vue'; + +/** + * 组件测试:TaskPresets(B6 推荐任务 chips)。 + * api mock 参照 DiagnosticsWizard.spec:vi.mock('@/services/api')。 + * 覆盖:presets chips 渲染、点击 emit select(goal 填入由父组件完成)、 + * 空列表 / 加载失败时整区静默隐藏。 + */ + +vi.mock('@/services/api', () => ({ apiGet: vi.fn(), apiPost: vi.fn() })); + +import { apiGet } from '@/services/api'; + +const apiGetMock = apiGet as unknown as Mock; + +const i18n = createI18n({ + legacy: false, + locale: 'zh-CN', + messages: { 'zh-CN': zhCN }, +}); + +// 条目形状对齐后端 TaskPreset.model_dump()(task_preset_catalog.py)。 +const PRESETS = [ + { + id: 'clock-countdown', + title: '打开时钟倒计时', + description: '启动时钟应用并开始 1 分钟倒计时', + goal: '打开时钟应用并启动 1 分钟倒计时', + tag: 'system', + apps: [], + profile: 'flash', + category: 'flash', + required_packages: [], + match_mode: 'any', + priority: 50, + is_device_matched: true, + }, + { + id: 'photo-search', + title: '拍照搜索', + description: '打开相机拍摄并搜索', + goal: '打开相机应用,拍摄一张照片并进行搜索', + tag: 'media', + apps: [], + profile: 'pro', + category: 'cross_app', + required_packages: [], + match_mode: 'any', + priority: 40, + is_device_matched: false, + }, +]; + +function mountPresets() { + return mount(TaskPresets, { + global: { + plugins: [ArcoVue, i18n], + }, + }); +} + +describe('TaskPresets (B6)', () => { + beforeEach(() => { + vi.clearAllMocks(); + apiGetMock.mockReset(); + }); + + it('fetches recommended presets on mount and renders chips', async () => { + apiGetMock.mockResolvedValue(PRESETS); + const wrapper = mountPresets(); + await flushPromises(); + + expect(apiGetMock).toHaveBeenCalledWith('/api/tasks/presets', { + params: { category: 'recommended', packages: '', limit: 8 }, + }); + expect(wrapper.text()).toContain('推荐任务'); + expect(wrapper.text()).toContain('打开时钟倒计时'); + expect(wrapper.text()).toContain('拍照搜索'); + expect(wrapper.findAll('.preset-chip')).toHaveLength(2); + }); + + it('emits select with the preset goal (fill input, no direct submit)', async () => { + apiGetMock.mockResolvedValue(PRESETS); + const wrapper = mountPresets(); + await flushPromises(); + + const chips = wrapper.findAll('.preset-chip'); + await chips[0]!.trigger('click'); + await chips[1]!.trigger('click'); + + const emitted = wrapper.emitted('select'); + expect(emitted).toHaveLength(2); + expect(emitted?.[0]).toEqual(['打开时钟应用并启动 1 分钟倒计时']); + expect(emitted?.[1]).toEqual(['打开相机应用,拍摄一张照片并进行搜索']); + }); + + it('hides the whole section when the payload is empty', async () => { + apiGetMock.mockResolvedValue([]); + const wrapper = mountPresets(); + await flushPromises(); + + expect(wrapper.find('.presets-card').exists()).toBe(false); + expect(wrapper.text()).not.toContain('推荐任务'); + }); + + it('hides the whole section silently when the request fails', async () => { + apiGetMock.mockRejectedValue(new Error('network down')); + const wrapper = mountPresets(); + await flushPromises(); + + expect(wrapper.find('.presets-card').exists()).toBe(false); + expect(wrapper.text()).not.toContain('推荐任务'); + }); + + it('hides the whole section when the payload is not an array', async () => { + apiGetMock.mockResolvedValue({ detail: 'unexpected' }); + const wrapper = mountPresets(); + await flushPromises(); + + expect(wrapper.find('.presets-card').exists()).toBe(false); + }); +}); diff --git a/apps/showcase_ui_v2/src/components/session-extras/TaskPresets.vue b/apps/showcase_ui_v2/src/components/session-extras/TaskPresets.vue new file mode 100644 index 000000000..141d7df49 --- /dev/null +++ b/apps/showcase_ui_v2/src/components/session-extras/TaskPresets.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/apps/showcase_ui_v2/src/components/timeline/AgentTimeline.spec.ts b/apps/showcase_ui_v2/src/components/timeline/AgentTimeline.spec.ts index cc877e6cd..feea73cdc 100644 --- a/apps/showcase_ui_v2/src/components/timeline/AgentTimeline.spec.ts +++ b/apps/showcase_ui_v2/src/components/timeline/AgentTimeline.spec.ts @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import type { VueWrapper } from '@vue/test-utils'; import ArcoVue from '@arco-design/web-vue'; import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; import { createPinia, setActivePinia } from 'pinia'; @@ -6,6 +7,7 @@ import { reactive } from 'vue'; import { createI18n } from 'vue-i18n'; import zhCN from '../../locales/zh-CN'; +import appI18n from '@/locales'; import { useSessionStore } from '../../stores/session'; import { useTimelineStore } from '../../stores/timeline'; import type { LLMStreamResetEventData } from '../../types/stream.model'; @@ -40,6 +42,19 @@ const i18n = createI18n({ messages: { 'zh-CN': zhCN }, }); +// 动作标题等由 util 生成的语义文案走 app 级 i18n 实例(src/utils/i18n.ts)。 +// 本 spec 将该实例固定在 en-US,使 util 产出的英文断言与迁移前行为逐字节一致; +// 组件自身的界面文案仍使用上方 zh-CN 实例,不受影响。 +appI18n.global.locale.value = 'en-US'; + +// B5:planning loader 轮换短语(zh-CN 消息)——loader 文案断言不再依赖单一静态文案 +const PLANNING_PHRASES: string[] = zhCN.workspace.timeline.planningPhrases ?? []; + +function planningLoaderText(wrapper: VueWrapper): string { + const loader = wrapper.find('.planning-loader'); + return loader.exists() ? loader.text().trim() : ''; +} + function mountTimeline() { return mount(AgentTimeline, { global: { @@ -162,7 +177,7 @@ describe('AgentTimeline (M2)', () => { it('renders step cards with action details from the steps snapshot', async () => { const wrapper = await mountWithSession(); // 动作卡与目标 / 坐标(来自 /steps 的 action_taken 实际字段; - // 动作标题由 util 生成,保持与 Angular 一致的英文文案) + // 动作标题由 util 生成——app 级 i18n 实例在本 spec 中固定 en-US,保持迁移前英文断言) await vi.waitFor(() => expect(wrapper.text()).toContain('Tapping Element')); expect(wrapper.text()).toContain('设置应用图标'); expect(wrapper.text()).toContain('[319, 909]'); @@ -217,12 +232,22 @@ describe('AgentTimeline (M3 实时流)', () => { it('shows the planning loader while running with no logs', async () => { const wrapper = await mountRunningEmptySession(); - await vi.waitFor(() => expect(wrapper.text()).toContain('正在规划下一步…')); + // B5:loader 文案为轮换短语之一,断言容器出现即可,不依赖具体短语 + await vi.waitFor(() => expect(wrapper.find('.planning-loader').exists()).toBe(true)); + wrapper.unmount(); + }); + + it('displays one of the rotating planning phrases in the loader', async () => { + const wrapper = await mountRunningEmptySession(); + await vi.waitFor(() => expect(wrapper.find('.planning-loader').exists()).toBe(true)); + // B5:随机起点 + 2.8s 轮换的可见结果——起始文案必为 planningPhrases 之一 + expect(PLANNING_PHRASES).toContain(planningLoaderText(wrapper)); + wrapper.unmount(); }); it('hides the planning loader while an llm_stream chunk is incomplete', async () => { const wrapper = await mountRunningEmptySession(); - await vi.waitFor(() => expect(wrapper.text()).toContain('正在规划下一步…')); + await vi.waitFor(() => expect(wrapper.find('.planning-loader').exists()).toBe(true)); const timelineStore = useTimelineStore(); timelineStore.sessionLogs.push({ type: 'llm_stream', @@ -230,12 +255,13 @@ describe('AgentTimeline (M3 实时流)', () => { session_id: 'sess-empty', data: { execution_id: 'e1', text: 'partial answer', stream_type: 'text', isCompleted: false }, }); - await vi.waitFor(() => expect(wrapper.text()).not.toContain('正在规划下一步…')); + await vi.waitFor(() => expect(wrapper.find('.planning-loader').exists()).toBe(false)); + wrapper.unmount(); }); it('hides the planning loader after session_ended', async () => { const wrapper = await mountRunningEmptySession(); - await vi.waitFor(() => expect(wrapper.text()).toContain('正在规划下一步…')); + await vi.waitFor(() => expect(wrapper.find('.planning-loader').exists()).toBe(true)); const timelineStore = useTimelineStore(); timelineStore.sessionLogs.push({ type: 'session_ended', @@ -243,7 +269,8 @@ describe('AgentTimeline (M3 实时流)', () => { session_id: 'sess-empty', data: {}, }); - await vi.waitFor(() => expect(wrapper.text()).not.toContain('正在规划下一步…')); + await vi.waitFor(() => expect(wrapper.find('.planning-loader').exists()).toBe(false)); + wrapper.unmount(); }); it('shows the paused card with resume action while viewing the paused task', async () => { diff --git a/apps/showcase_ui_v2/src/components/timeline/AgentTimeline.vue b/apps/showcase_ui_v2/src/components/timeline/AgentTimeline.vue index fc3c417c3..7c60dbb32 100644 --- a/apps/showcase_ui_v2/src/components/timeline/AgentTimeline.vue +++ b/apps/showcase_ui_v2/src/components/timeline/AgentTimeline.vue @@ -6,8 +6,10 @@ import { IconCheckCircle, IconEye, IconFile, + IconHistory, IconImage, IconLiveBroadcast, + IconMindMapping, IconPauseCircle, IconPlayArrow, IconSync, @@ -22,6 +24,8 @@ import { checkPlanningLoader, formatTokenCount } from '@/utils/stream-aggregator import { isAndroidAction, isReportStatusAction } from '@/utils/action-formatter'; import { parseNote } from '@/utils/markdown'; import type { PhaseBlock, StepBlock } from '@/types/stream.model'; +import ReplayDrawer from '@/components/session-extras/ReplayDrawer.vue'; +import SessionTreeDrawer from '@/components/session-extras/SessionTreeDrawer.vue'; import CheckerPanel from './CheckerPanel.vue'; import NoteDocument from './NoteDocument.vue'; import NotesPanel from './NotesPanel.vue'; @@ -38,7 +42,7 @@ import StepCard from './StepCard.vue'; * - M3 实时流:planning loader、LLM 重试警示条、任务暂停卡 + 恢复、 * 自动滚动(接近底部才跟随,平移自 Angular scheduleAutoScroll)。 */ -const { t } = useI18n(); +const { t, tm } = useI18n(); const sessionStore = useSessionStore(); const streamStore = useStreamStore(); const timelineStore = useTimelineStore(); @@ -49,6 +53,10 @@ timelineStore.start(); const notesPopoverOpen = ref(false); const scrollContainer = ref(null); +// ---- B6 轨迹树 / 步骤回放抽屉(仅点击时打开,抽屉自行按需拉取) ---- +const treeDrawerVisible = ref(false); +const replayDrawerVisible = ref(false); + // ---- 启动准备(平移自 startupWorkItems computed) ---- const startupWorkItems = computed(() => { const agentIsActive = ['running', 'paused'].includes(sessionStore.agentStatus); @@ -123,6 +131,59 @@ const showPlanningRow = computed(() => || timelineStore.consolidatedBlocks.length > 0), ); +// ---- B5 planning loader 轮换短语(平移自 PLANNING_LOADER_PHRASES 16 条 + 轮换 effect) ---- + +/** vue-i18n `tm()` 取数组消息:条目可能是字符串或编译 AST(含 source),统一归一为字符串。 */ +function normalizeMessageValue(value: unknown): string { + if (typeof value === 'string') return value; + if (value && typeof value === 'object' && 'source' in value) { + return String((value as { source?: unknown }).source ?? ''); + } + return ''; +} + +const planningPhrases = computed(() => { + const messages: unknown = tm('workspace.timeline.planningPhrases'); + if (!Array.isArray(messages)) return []; + return messages.map(normalizeMessageValue).filter((text) => text.length > 0); +}); + +/** 轮换间隔(母本 2800ms,游戏加载提示式轮换)。 */ +const PLANNING_ROTATE_MS = 2800; +let planningPhraseIndex = 0; +let planningRotateTimer: ReturnType | null = null; +const currentPlanningText = ref(''); + +function stopPlanningRotation(): void { + if (planningRotateTimer !== null) { + clearInterval(planningRotateTimer); + planningRotateTimer = null; + } +} + +/** 仅 loader 可见时轮转(watch 启停 interval,避免常驻定时器;不可见 / 卸载时清理)。 */ +watch( + showPlanningLoader, + (visible) => { + if (visible) { + const phrases = planningPhrases.value; + if (phrases.length === 0 || planningRotateTimer) return; + // 随机起点(母本:Math.floor(Math.random() * length)) + planningPhraseIndex = Math.floor(Math.random() * phrases.length); + currentPlanningText.value = phrases[planningPhraseIndex] ?? t('workspace.timeline.planning'); + planningRotateTimer = setInterval(() => { + const list = planningPhrases.value; + if (list.length === 0) return; + planningPhraseIndex = (planningPhraseIndex + 1) % list.length; + currentPlanningText.value = list[planningPhraseIndex] ?? t('workspace.timeline.planning'); + }, PLANNING_ROTATE_MS); + } else { + stopPlanningRotation(); + } + }, + { immediate: true }, +); + /** LLM 重试警示文案(组装自 stream store 的 retryInfo,语义对齐 Angular agent.service L932-933)。 */ const retryMessage = computed(() => { if (!streamStore.isRetrying) return null; @@ -216,6 +277,7 @@ onBeforeUnmount(() => { clearTimeout(autoScrollTimer); autoScrollTimer = null; } + stopPlanningRotation(); scrollContainer.value?.removeEventListener('scroll', onScrollContainerScroll); }); @@ -303,6 +365,15 @@ const isRecordBtnProcessing = computed( {{ t('workspace.player.recordBtnDefault') }} + + + + {{ t('workspace.tree.button') }} + + + + {{ t('workspace.replay.button') }} +
      @@ -368,10 +439,11 @@ const isRecordBtnProcessing = computed( - +
      - {{ t('workspace.timeline.planning') }} + {{ currentPlanningText || t('workspace.timeline.planning') }}
      @@ -408,6 +480,10 @@ const isRecordBtnProcessing = computed(
      + + + + diff --git a/apps/showcase_ui_v2/src/components/timeline/StepCard.vue b/apps/showcase_ui_v2/src/components/timeline/StepCard.vue index bcc30a0ed..cc5af03b2 100644 --- a/apps/showcase_ui_v2/src/components/timeline/StepCard.vue +++ b/apps/showcase_ui_v2/src/components/timeline/StepCard.vue @@ -1,5 +1,5 @@ + + + + diff --git a/apps/showcase_ui_v2/src/components/diagnostics/CredentialsStep.vue b/apps/showcase_ui_v2/src/components/diagnostics/CredentialsStep.vue index 9d1f8cf3b..498e152b2 100644 --- a/apps/showcase_ui_v2/src/components/diagnostics/CredentialsStep.vue +++ b/apps/showcase_ui_v2/src/components/diagnostics/CredentialsStep.vue @@ -1,188 +1,31 @@