diff --git a/ogscope/config.py b/ogscope/config.py index c358291..eac98eb 100644 --- a/ogscope/config.py +++ b/ogscope/config.py @@ -138,8 +138,8 @@ class Settings(BaseSettings): description="大尺度背景减除:小图长边上限(像素),越小越快 / Large-scale BG downsample max side", ) star_analysis_target_fps: float = Field( - default=1.5, - description="星空分析目标帧率(1–2),仅用于前端节流 / Target star-analysis FPS for UI throttle", + default=2 / 3, + description="星空分析目标帧率(约 1.5 秒 1 帧),仅用于前端节流 / Target star-analysis FPS for UI throttle (~1.5s per frame)", ) model_config = SettingsConfigDict( diff --git a/ogscope/web/api/analysis/routes.py b/ogscope/web/api/analysis/routes.py index 0166848..35383e8 100644 --- a/ogscope/web/api/analysis/routes.py +++ b/ogscope/web/api/analysis/routes.py @@ -2,6 +2,7 @@ 素材分析路由 / Asset analysis routes """ +import json import mimetypes from fastapi import APIRouter, File, Form, HTTPException, Query, UploadFile @@ -268,6 +269,40 @@ async def solve_analysis_frame(body: AnalysisSolveVideoFrameRequest): raise HTTPException(status_code=404, detail=str(exc)) from exc except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc + + +@router.post("/analysis/solve/frame_upload") +async def solve_uploaded_frame( + file: UploadFile = File(...), + payload: str = Form( + ..., + description="JSON 字符串,字段与 AnalysisSolveImageRequest 对齐 / JSON payload aligned with AnalysisSolveImageRequest", + ), +): + """上传单帧 JPEG/PNG 并解算 / Solve a single uploaded frame (multipart).""" + try: + raw = await file.read() + obj = json.loads(payload) + if not isinstance(obj, dict): + raise ValueError("payload 必须为 JSON 对象 / payload must be a JSON object") + topn = obj.get("overlay_topn_count") + enable_polar = obj.get("enable_polar_guide") + obj.pop("overlay_topn_count", None) + obj.pop("enable_polar_guide", None) + # 前端调试元数据,不参与 Pydantic 模型 / Client metadata not in schema + obj.pop("time_sec", None) + obj.pop("frame_width", None) + obj.pop("frame_height", None) + obj.setdefault("input_name", "__frame_upload__.jpg") + data = AnalysisSolveImageRequest.model_validate(obj) + return await analysis_service.solve_uploaded_frame( + image_bytes=raw, + solve_params=data, + overlay_topn_count=topn, + enable_polar_guide=enable_polar, + ) + except HTTPException: + raise except Exception as exc: # noqa: BLE001 raise HTTPException(status_code=400, detail=str(exc)) from exc diff --git a/ogscope/web/api/analysis/services.py b/ogscope/web/api/analysis/services.py index 76514f8..3613cf2 100644 --- a/ogscope/web/api/analysis/services.py +++ b/ogscope/web/api/analysis/services.py @@ -6,6 +6,7 @@ import asyncio import json +import math import shutil import time import uuid @@ -16,6 +17,7 @@ from typing import Any import cv2 +import numpy as np from ogscope.algorithms.plate_solve import ( CentroidExtractionParams, @@ -161,6 +163,135 @@ def __init__(self) -> None: self.default_hint_dec = settings.solver_hint_dec_deg self._jobs: dict[str, AnalysisJob] = {} self._lab = AnalysisLabStore(settings) + self._overlay_topn_default = 3 + self._polar_guide_default = True + + def _build_topn_labels( + self, + row: dict[str, Any], + *, + topn_count: int, + ) -> list[dict[str, Any]]: + """从 matched 星点构建 Top-N 标注 / Build Top-N labels from matched stars.""" + overlay = row.get("solve_overlay") + if not isinstance(overlay, dict): + return [] + matched = overlay.get("stars_matched") + if not isinstance(matched, list): + return [] + labels: list[dict[str, Any]] = [] + for star in matched: + if not isinstance(star, dict): + continue + mag_raw = star.get("mag") + try: + mag_val = float(mag_raw) if mag_raw is not None else None + except (TypeError, ValueError): + mag_val = None + cat_id = star.get("cat_id") + if isinstance(cat_id, list): + cat_id_text = "-".join(str(v) for v in cat_id if v is not None) + elif cat_id is None: + cat_id_text = "" + else: + cat_id_text = str(cat_id) + # 目前基于 Tetra3 匹配 ID 提供可读名占位,后续可接入正式星表映射 + # Build readable placeholder name from Tetra3 cat_id; can be replaced by real catalog lookup later. + name = f"CAT-{cat_id_text}" if cat_id_text else "Unnamed" + item = { + "x": star.get("x"), + "y": star.get("y"), + "name": name, + "mag": mag_val, + "ra_deg": star.get("ra_deg"), + "dec_deg": star.get("dec_deg"), + } + labels.append(item) + labels.sort( + key=lambda x: ( + x["mag"] is None, + float(x["mag"]) if x["mag"] is not None else 999.0, + ) + ) + n = max(1, int(topn_count)) + return labels[:n] + + def _build_polar_guide(self, row: dict[str, Any]) -> dict[str, Any] | None: + """构建极轴引导向量 / Build polar guide vector from solve center.""" + overlay = row.get("solve_overlay") + if not isinstance(overlay, dict): + return None + frame_shape = overlay.get("frame_shape") + if ( + not isinstance(frame_shape, list) + or len(frame_shape) < 2 + or frame_shape[0] in (None, 0) + or frame_shape[1] in (None, 0) + ): + return None + try: + h = float(frame_shape[0]) + w = float(frame_shape[1]) + ra_center = float(row.get("ra_deg")) + dec_center = float(row.get("dec_deg")) + except (TypeError, ValueError): + return None + fov_deg = row.get("fov_deg") + roll_deg = row.get("roll_deg") + if fov_deg is None: + return None + try: + fov = float(fov_deg) + except (TypeError, ValueError): + return None + roll = 0.0 + try: + if roll_deg is not None: + roll = float(roll_deg) + except (TypeError, ValueError): + roll = 0.0 + + # 北天极近似目标:RA 与当前中心相同,Dec=+90,减少 RA wrap 影响 + # Approximate north celestial pole target with same RA and Dec=+90. + target_ra = ra_center + target_dec = 90.0 + d_ra = target_ra - ra_center + while d_ra > 180.0: + d_ra -= 360.0 + while d_ra < -180.0: + d_ra += 360.0 + d_dec = target_dec - dec_center + east_deg = d_ra * math.cos(math.radians(dec_center)) + north_deg = d_dec + roll_rad = math.radians(roll) + x_deg = east_deg * math.cos(roll_rad) + north_deg * math.sin(roll_rad) + y_deg = -east_deg * math.sin(roll_rad) + north_deg * math.cos(roll_rad) + + px_per_deg = (min(w, h) / max(fov, 1e-6)) if fov > 0 else 1.0 + dx_px = x_deg * px_per_deg + dy_px = -y_deg * px_per_deg + cx = w * 0.5 + cy = h * 0.5 + tx = cx + dx_px + ty = cy + dy_px + + c_dec = math.radians(dec_center) + t_dec = math.radians(target_dec) + d_ra_rad = math.radians(d_ra) + cos_ang = ( + math.sin(c_dec) * math.sin(t_dec) + + math.cos(c_dec) * math.cos(t_dec) * math.cos(d_ra_rad) + ) + cos_ang = max(-1.0, min(1.0, cos_ang)) + angular_sep_deg = math.degrees(math.acos(cos_ang)) + + return { + "target_kind": "north_celestial_pole", + "frame_center": {"x": cx, "y": cy, "ra_deg": ra_center, "dec_deg": dec_center}, + "target": {"x": tx, "y": ty, "ra_deg": target_ra, "dec_deg": target_dec}, + "delta_px": {"dx": dx_px, "dy": dy_px}, + "angular_sep_deg": angular_sep_deg, + } def _centroid_params_from_payload( self, payload: CentroidParamsPayload | None @@ -213,6 +344,22 @@ def resolve_upload_path(self, filename: str) -> Path: raise ValueError("路径非法 / Invalid path") from exc return path + def _resolve_frame_source_path(self, input_name: str) -> Path: + """单帧视频解算源路径:优先素材池,其次调试录制目录 / Resolve frame-solve source path.""" + name = Path(input_name.strip()).name + if not name or name != input_name.strip(): + raise ValueError("文件名无效 / Invalid filename") + try: + up = self.resolve_upload_path(name) + if up.is_file(): + return up + except ValueError: + pass + dbg = Path.home() / "dev_captures" / name + if dbg.is_file(): + return dbg + raise FileNotFoundError("上传文件不存在 / Uploaded file not found") + def get_upload_file_info(self, filename: str) -> dict[str, Any]: """从上传目录读取文件与 stem.txt 侧车 / File + optional sidecar from upload pool.""" path = self.resolve_upload_path(filename) @@ -612,6 +759,76 @@ def delete_upload( self._lab.remove_manifest_entry(path.name) return {"success": True, "filename": path.name, "deleted_experiments": n_exp} + async def solve_uploaded_frame( + self, + *, + image_bytes: bytes, + solve_params: AnalysisSolveImageRequest, + overlay_topn_count: int | None = None, + enable_polar_guide: bool | None = None, + ) -> dict[str, Any]: + """解析上传的单帧图像并解算 / Solve a single uploaded frame (multipart).""" + if not image_bytes: + raise ValueError("空图像数据 / Empty image payload") + buf = np.frombuffer(image_bytes, dtype=np.uint8) + frame = cv2.imdecode(buf, cv2.IMREAD_COLOR) + if frame is None: + raise ValueError("无法解码图像 / Cannot decode image") + + centroid_params, max_stars, timeout_ms, effective_profile = ( + self._resolve_solve_profile( + solve_params.solve_profile, + solve_params.centroid, + solve_params.solve_timeout_ms, + ) + ) + loop = asyncio.get_running_loop() + + def _run() -> dict[str, Any]: + return self._solve_bgr_to_row( + frame, + solve_params.hint_ra_deg, + solve_params.hint_dec_deg, + solve_params.fov_estimate, + solve_params.fov_max_error, + timeout_ms, + centroid_params, + solve_params.max_image_side, + max_stars, + bool(solve_params.large_scale_bg_subtract), + ) + + row = await loop.run_in_executor(self._solver_executor, _run) + # 统一 overlay_ext 结构,便于前端复用渲染逻辑 + topn = ( + int(overlay_topn_count) + if overlay_topn_count is not None + else self._overlay_topn_default + ) + enable_polar = ( + bool(enable_polar_guide) + if enable_polar_guide is not None + else self._polar_guide_default + ) + overlay_ext: dict[str, Any] = {} + try: + overlay_ext["labels_topn"] = self._build_topn_labels( + row, topn_count=topn + ) + except Exception: + overlay_ext["labels_topn"] = [] + if enable_polar: + try: + overlay_ext["polar_guide"] = self._build_polar_guide(row) + except Exception: + overlay_ext["polar_guide"] = None + row["overlay_ext"] = overlay_ext + row["solve_profile"] = effective_profile + detail_level = getattr(solve_params, "detail_level", None) or "summary" + if detail_level != "full": + row.pop("tetra", None) + return {"success": True, "result": row} + def delete_experiment(self, experiment_id: str) -> None: """删除一条实验记录 / Delete one experiment record.""" self._lab.delete_experiment(experiment_id) @@ -828,9 +1045,7 @@ async def solve_video_frame( raise ValueError( "需要 input_name / input_name required for file source" ) - path = self.resolve_upload_path(body.input_name) - if not path.is_file(): - raise FileNotFoundError("上传文件不存在 / Uploaded file not found") + path = self._resolve_frame_source_path(body.input_name) t_decode = time.perf_counter() cap = cv2.VideoCapture(str(path)) if not cap.isOpened(): @@ -868,6 +1083,29 @@ def _run() -> dict[str, Any]: ) row = await loop.run_in_executor(self._solver_executor, _run) + # 二次分析与极轴引导(失败降级,不影响基础解算) + topn = ( + int(body.overlay_topn_count) + if getattr(body, "overlay_topn_count", None) is not None + else self._overlay_topn_default + ) + enable_polar = ( + bool(body.enable_polar_guide) + if getattr(body, "enable_polar_guide", None) is not None + else self._polar_guide_default + ) + overlay_ext: dict[str, Any] = {} + try: + overlay_ext["labels_topn"] = self._build_topn_labels(row, topn_count=topn) + except Exception: + overlay_ext["labels_topn"] = [] + if enable_polar: + try: + overlay_ext["polar_guide"] = self._build_polar_guide(row) + except Exception: + overlay_ext["polar_guide"] = None + row["overlay_ext"] = overlay_ext + if t_open_decode_ms is not None: row["t_open_decode_ms"] = round(t_open_decode_ms, 3) row["t_backend_total_ms"] = round((time.perf_counter() - t_total) * 1000.0, 3) diff --git a/ogscope/web/api/models/schemas.py b/ogscope/web/api/models/schemas.py index f97428b..a92f9f5 100644 --- a/ogscope/web/api/models/schemas.py +++ b/ogscope/web/api/models/schemas.py @@ -242,10 +242,12 @@ class AnalysisSolveVideoFrameRequest(BaseModel): model_config = ConfigDict(extra="forbid") + # 基本输入来源 / Basic input source source: Literal["camera", "file"] input_name: Optional[str] = None frame_index: int = 0 time_sec: Optional[float] = None + # 解算参数 / Solve parameters hint_ra_deg: Optional[float] = None hint_dec_deg: Optional[float] = None fov_estimate: Optional[float] = None @@ -257,6 +259,16 @@ class AnalysisSolveVideoFrameRequest(BaseModel): large_scale_bg_subtract: Optional[bool] = False detail_level: Optional[Literal["summary", "full"]] = "summary" + # 叠加与引导选项(可选,未提供则使用后端默认)/ Optional overlay & guidance options + overlay_topn_count: Optional[int] = Field( + default=None, + description="自动标注的星点数量上限(Top-N),未填用服务器默认 / Max number of stars to label (Top-N); server default if omitted", + ) + enable_polar_guide: Optional[bool] = Field( + default=None, + description="是否计算极轴引导信息;未填用服务器默认 / Whether to compute polar guide info; server default if omitted", + ) + class ImportFromDebugRequest(BaseModel): """从调试采集目录导入到分析素材池 / Import capture into analysis pool.""" diff --git a/tests/unit/test_analysis_api.py b/tests/unit/test_analysis_api.py index 030ef65..f3a93be 100644 --- a/tests/unit/test_analysis_api.py +++ b/tests/unit/test_analysis_api.py @@ -2,6 +2,7 @@ 分析 API 测试 / Analysis API tests """ +import json from pathlib import Path import cv2 @@ -281,3 +282,95 @@ def test_analysis_delete_upload_and_experiment( er = client.delete(f"/api/analysis/experiments/{eid}") assert er.status_code == 200 assert not (temp_analysis_dir / "experiments" / f"{eid}.json").is_file() + + +@pytest.mark.unit +def test_analysis_solve_video_frame_overlay_ext( + client, temp_analysis_dir, mock_plate_solve, tmp_path: Path +): + """单帧视频解算返回扩展叠加字段 / Frame solve returns overlay extension.""" + video_path = tmp_path / "frame_ext.mp4" + _build_test_video(video_path) + with video_path.open("rb") as f: + up = client.post( + "/api/analysis/upload", + files={"file": ("frame_ext.mp4", f, "video/mp4")}, + ) + assert up.status_code == 200 + + resp = client.post( + "/api/analysis/solve/frame", + json={ + "source": "file", + "input_name": "frame_ext.mp4", + "time_sec": 0.1, + "overlay_topn_count": 2, + "enable_polar_guide": True, + }, + ) + assert resp.status_code == 200 + data = resp.json() + assert data.get("success") is True + row = data.get("result") or {} + ext = row.get("overlay_ext") or {} + labels = ext.get("labels_topn") or [] + assert isinstance(labels, list) + assert len(labels) >= 1 + assert "name" in labels[0] + guide = ext.get("polar_guide") + assert isinstance(guide, dict) + assert "delta_px" in guide + + +@pytest.mark.unit +def test_analysis_solve_video_frame_from_debug_capture( + client, temp_analysis_dir, mock_plate_solve, monkeypatch, tmp_path: Path +): + """调试录制目录的视频也可直接单帧解算 / Frame solve supports debug-capture videos.""" + video_path = tmp_path / "dev_captures" / "debug_cam.mp4" + video_path.parent.mkdir(parents=True, exist_ok=True) + _build_test_video(video_path) + monkeypatch.setattr("ogscope.web.api.analysis.services.Path.home", lambda: tmp_path) + + resp = client.post( + "/api/analysis/solve/frame", + json={ + "source": "file", + "input_name": "debug_cam.mp4", + "time_sec": 0.0, + }, + ) + assert resp.status_code == 200 + data = resp.json() + assert data.get("success") is True + result = data.get("result") or {} + assert "status" in result + + +@pytest.mark.unit +def test_analysis_solve_frame_upload_endpoint( + client, temp_analysis_dir, mock_plate_solve, tmp_path: Path +): + """浏览器提帧上传接口可解算 / Browser frame-upload endpoint solves frame.""" + image_path = tmp_path / "frame_upload.jpg" + _build_star_image(image_path) + payload = { + "hint_ra_deg": 45.0, + "hint_dec_deg": 75.0, + "solve_profile": "balanced", + "overlay_topn_count": 2, + "enable_polar_guide": True, + } + with image_path.open("rb") as f: + resp = client.post( + "/api/analysis/solve/frame_upload", + files={"file": ("frame.jpg", f, "image/jpeg")}, + data={"payload": json.dumps(payload)}, + ) + assert resp.status_code == 200 + data = resp.json() + assert data.get("success") is True + row = data.get("result") or {} + assert "status" in row + ext = row.get("overlay_ext") or {} + assert "labels_topn" in ext diff --git a/web/analysis-ui/src/App.tsx b/web/analysis-ui/src/App.tsx index 1cd2470..03c4865 100644 --- a/web/analysis-ui/src/App.tsx +++ b/web/analysis-ui/src/App.tsx @@ -24,6 +24,7 @@ import { fetchDebugFileInfo, fetchDebugFiles, fetchExperiments, + fetchLabSettings, fetchPresets, fetchSystemInfo, fetchUploadExperimentCount, @@ -33,11 +34,13 @@ import { saveExperiment, saveUserPreset, solveBatch, + solveFrameFromBlob, solveImage, solveVideoFrame, uploadFile, uploadFileUrl, type DebugFileRow, + type LabPublicSettings, type SolveParams, type UploadFileRow, } from "./api"; @@ -153,6 +156,11 @@ export default function App() { const [cameraPreviewUrl, setCameraPreviewUrl] = useState(null); const [videoPreviewError, setVideoPreviewError] = useState(null); const [cameraSolveRunning, setCameraSolveRunning] = useState(false); + const [fileSolveRunning, setFileSolveRunning] = useState(false); + const [autoHoldEnabled, setAutoHoldEnabled] = useState(true); + const [isFrozen, setIsFrozen] = useState(false); + const [frozenFrameId, setFrozenFrameId] = useState(null); + const [frozenImageUrl, setFrozenImageUrl] = useState(null); const [meta, setMeta] = useState | null>(null); const [metaLoading, setMetaLoading] = useState(false); const [batchRawOpen, setBatchRawOpen] = useState>({}); @@ -167,9 +175,18 @@ export default function App() { const cameraPreviewImgRef = useRef(null); const lastCameraFrameIdRef = useRef(null); const cameraSolveTimerRef = useRef(null); + const fileSolveTimerRef = useRef(null); const cameraSolveInFlightRef = useRef(false); + const fileSolveInFlightRef = useRef(false); const cvRef = useRef(null); const [sysOverview, setSysOverview] = useState(null); + const [labSettings, setLabSettings] = useState(null); + + const starAnalysisIntervalMs = useMemo(() => { + const fps = labSettings?.star_analysis_target_fps ?? 2 / 3; + const clampedFps = Math.min(Math.max(fps, 0.2), 5.0); + return Math.round(1000 / clampedFps); + }, [labSettings]); const loadLists = useCallback(async () => { const [u, o, usr] = await Promise.all([ @@ -188,6 +205,12 @@ export default function App() { .catch(() => setDebugFiles([])); }, []); + useEffect(() => { + fetchLabSettings() + .then((s) => setLabSettings(s)) + .catch(() => setLabSettings(null)); + }, []); + useEffect(() => { loadLists().catch((e) => setErr(String(e))); }, [loadLists]); @@ -253,7 +276,10 @@ export default function App() { const overlay = useMemo(() => { const r = lastResult?.result as Record | undefined; if (!r) return null; - return (r.solve_overlay || null) as SolveOverlay | null; + const base = (r.solve_overlay || null) as SolveOverlay | null; + if (!base) return null; + const ext = (r.overlay_ext || null) as SolveOverlay["overlay_ext"] | null; + return { ...base, overlay_ext: ext || undefined }; }, [lastResult]); const resultRow = useMemo(() => { @@ -315,7 +341,7 @@ export default function App() { if (view !== "lab_video" || videoPreviewMode !== "camera") return; let cancelled = false; const poll = async () => { - if (cancelled) return; + if (cancelled || isFrozen) return; try { const qs = lastCameraFrameIdRef.current ? `?since_frame_id=${encodeURIComponent(lastCameraFrameIdRef.current)}` @@ -346,7 +372,7 @@ export default function App() { }); lastCameraFrameIdRef.current = null; }; - }, [view, videoPreviewMode]); + }, [view, videoPreviewMode, isFrozen]); useEffect(() => { const img = imgRef.current; @@ -445,40 +471,71 @@ export default function App() { const onCameraSolve = async () => { if (cameraSolveInFlightRef.current) return; setErr(null); - setBusy(true); cameraSolveInFlightRef.current = true; const t0 = performance.now(); try { const out = await solveVideoFrame({ source: "camera", + overlay_topn_count: 3, + enable_polar_guide: true, + solve_timeout_ms: Math.min((labSettings?.solver_timeout_ms ?? 1500) * 0.6, 1200), ...params, }); setLastResult(out as Record); setBatchPack(null); setLastSolveSource("camera"); setVideoPreviewMode("camera"); + const outResult = (out as { result?: Record }).result; + const solveStatus = + typeof outResult?.status === "string" ? String(outResult.status) : ""; + if (autoHoldEnabled && solveStatus === "MATCH_FOUND") { + setIsFrozen(true); + setFrozenFrameId( + (out as { frame_id?: number }).frame_id != null + ? String((out as { frame_id?: number }).frame_id) + : null, + ); + setFrozenImageUrl(cameraPreviewUrl); + stopCameraSolveLoop(); + } setLastRoundTripMs(performance.now() - t0); } catch (e) { setErr(String(e)); setLastRoundTripMs(null); } finally { cameraSolveInFlightRef.current = false; - setBusy(false); } }; const onVideoFileSolve = async () => { + if (fileSolveInFlightRef.current) return; if (!selected) return; + const vd = videoRef.current; + if (!vd || vd.videoWidth < 2 || vd.videoHeight < 2 || videoPreviewError) return; setErr(null); - setBusy(true); + fileSolveInFlightRef.current = true; const t0 = performance.now(); try { - const vd = videoRef.current; - const out = await solveVideoFrame({ - source: "file", - input_name: selected, - time_sec: vd?.currentTime ?? 0, + const canvas = document.createElement("canvas"); + canvas.width = vd.videoWidth; + canvas.height = vd.videoHeight; + const ctx = canvas.getContext("2d"); + if (!ctx) { + throw new Error("无法创建画布上下文 / Cannot create canvas context"); + } + ctx.drawImage(vd, 0, 0, canvas.width, canvas.height); + const frameBlob = await new Promise((resolve, reject) => { + canvas.toBlob( + (b) => (b ? resolve(b) : reject(new Error("帧编码失败 / Frame encode failed"))), + "image/jpeg", + 0.92, + ); + }); + const out = await solveFrameFromBlob(frameBlob, { ...params, + solve_timeout_ms: Math.min((labSettings?.solver_timeout_ms ?? 1500) * 0.6, 1200), + overlay_topn_count: 3, + enable_polar_guide: true, }); setLastResult(out as Record); setBatchPack(null); @@ -488,17 +545,42 @@ export default function App() { setErr(String(e)); setLastRoundTripMs(null); } finally { - setBusy(false); + fileSolveInFlightRef.current = false; + } + }; + + const startFileSolveLoop = () => { + if (fileSolveRunning || !selected) return; + setFileSolveRunning(true); + void onVideoFileSolve(); + fileSolveTimerRef.current = window.setInterval(() => { + void onVideoFileSolve(); + }, starAnalysisIntervalMs); + }; + + const canSolveVideoFile = useMemo(() => { + if (view !== "lab_video" || videoPreviewMode !== "file") return false; + if (!selected) return false; + if (videoPreviewError) return false; + return videoNatural.w > 1 && videoNatural.h > 1; + }, [view, videoPreviewMode, selected, videoPreviewError, videoNatural.w, videoNatural.h]); + + const stopFileSolveLoop = () => { + setFileSolveRunning(false); + if (fileSolveTimerRef.current != null) { + window.clearInterval(fileSolveTimerRef.current); + fileSolveTimerRef.current = null; } }; const startCameraSolveLoop = () => { if (cameraSolveRunning) return; + if (isFrozen) return; setCameraSolveRunning(true); void onCameraSolve(); cameraSolveTimerRef.current = window.setInterval(() => { void onCameraSolve(); - }, 1200); + }, starAnalysisIntervalMs); }; const stopCameraSolveLoop = () => { @@ -509,6 +591,12 @@ export default function App() { } }; + const resumeLivePreview = () => { + setIsFrozen(false); + setFrozenFrameId(null); + setFrozenImageUrl(null); + }; + const togglePreset = (id: string) => { setSelectedPresetIds((prev) => { const n = new Set(prev); @@ -636,12 +724,25 @@ export default function App() { useEffect(() => { if (view !== "lab_video" || videoPreviewMode !== "camera") { stopCameraSolveLoop(); + setIsFrozen(false); + setFrozenFrameId(null); + setFrozenImageUrl(null); + } + if (view !== "lab_video" || videoPreviewMode !== "file") { + stopFileSolveLoop(); } }, [view, videoPreviewMode]); + useEffect(() => { + if (!selected) { + stopFileSolveLoop(); + } + }, [selected]); + useEffect(() => { return () => { stopCameraSolveLoop(); + stopFileSolveLoop(); }; }, []); @@ -930,10 +1031,10 @@ export default function App() { {view === "lab_video" && videoPreviewMode === "camera" ? (
- {cameraPreviewUrl ? ( + {((isFrozen && frozenImageUrl) || cameraPreviewUrl) ? ( @@ -1026,7 +1127,6 @@ export default function App() { autoPlay muted preload="metadata" - controls className="max-h-[70vh] w-full max-w-full object-contain" onError={() => setVideoPreviewError(t("lab.videoPreviewFailed"))} onLoadedData={() => { @@ -1568,21 +1668,39 @@ export default function App() { {view === "lab_video" && (
{videoPreviewMode === "file" ? ( - + <> + + + + ) : ( <> @@ -1598,10 +1716,32 @@ export default function App() { type="button" className="w-full rounded bg-secondary/80 py-2.5 font-semibold text-on-secondary disabled:opacity-40" onClick={() => void onCameraSolve()} - disabled={busy} + disabled={busy || isFrozen} > {t("lab.solveCameraFrame")} + + {isFrozen && ( + + )} + {isFrozen && ( +
+ 已冻结帧 / Frozen frame {frozenFrameId ?? "-"} +
+ )} )}
diff --git a/web/analysis-ui/src/api.ts b/web/analysis-ui/src/api.ts index 2580c4e..dc3c22b 100644 --- a/web/analysis-ui/src/api.ts +++ b/web/analysis-ui/src/api.ts @@ -273,7 +273,11 @@ export async function solveVideoFrame(payload: { input_name?: string | null; frame_index?: number; time_sec?: number | null; -} & SolveParams): Promise<{ success: boolean; result?: Record }> { + /** 自动标注 Top-N 星点(省略则用后端默认) / Auto-label top-N stars (server default if omitted) */ + overlay_topn_count?: number | null; + /** 是否启用极轴引导信息(省略则用后端默认) / Whether to enable polar guide info (server default if omitted) */ + enable_polar_guide?: boolean | null; +} & SolveParams): Promise<{ success: boolean; result?: Record; frame_id?: number | null; frame_ts?: string | null }> { const r = await fetch(`${API}/analysis/solve/frame`, { method: "POST", headers: { "Content-Type": "application/json" }, @@ -281,6 +285,25 @@ export async function solveVideoFrame(payload: { }); const data = await parseJson(r); if (!r.ok) throw new Error(String((data as { detail?: string }).detail || r.status)); + return data as { success: boolean; result?: Record; frame_id?: number | null; frame_ts?: string | null }; +} + +export async function solveFrameFromBlob( + frameBlob: Blob, + payload: SolveParams & { + overlay_topn_count?: number | null; + enable_polar_guide?: boolean | null; + }, +): Promise<{ success: boolean; result?: Record }> { + const fd = new FormData(); + fd.append("file", frameBlob, "frame.jpg"); + fd.append("payload", JSON.stringify(payload)); + const r = await fetch(`${API}/analysis/solve/frame_upload`, { + method: "POST", + body: fd, + }); + const data = await parseJson(r); + if (!r.ok) throw new Error(String((data as { detail?: string }).detail || r.status)); return data as { success: boolean; result?: Record }; } diff --git a/web/analysis-ui/src/drawOverlay.ts b/web/analysis-ui/src/drawOverlay.ts index dc4e39c..7cbe814 100644 --- a/web/analysis-ui/src/drawOverlay.ts +++ b/web/analysis-ui/src/drawOverlay.ts @@ -10,6 +10,23 @@ export type SolveOverlay = { stars_all_centroids?: Array<{ x: number; y: number }>; stars_pattern?: Array<{ x: number; y: number }>; stars_matched?: Array<{ x: number; y: number; mag?: number }>; + overlay_ext?: { + labels_topn?: Array<{ + x: number; + y: number; + name?: string; + mag?: number | null; + ra_deg?: number | null; + dec_deg?: number | null; + }>; + polar_guide?: { + target_kind?: string; + frame_center?: { x: number; y: number }; + target?: { x: number; y: number }; + delta_px?: { dx: number; dy: number }; + angular_sep_deg?: number; + } | null; + }; }; function drawOverlayCore( @@ -53,6 +70,43 @@ function drawOverlayCore( } } } + const ext = overlay.overlay_ext; + if (Array.isArray(ext?.labels_topn) && ext.labels_topn.length > 0) { + ctx.fillStyle = "rgba(96, 165, 250, 0.95)"; + ctx.font = "12px system-ui, sans-serif"; + for (const s of ext.labels_topn) { + if (typeof s?.x !== "number" || typeof s?.y !== "number") continue; + const magText = typeof s.mag === "number" ? ` m${s.mag.toFixed(1)}` : ""; + const title = `${s.name ?? "Star"}${magText}`; + ctx.fillText(title, s.x + 8, s.y + 14); + } + } + const guide = ext?.polar_guide; + if ( + guide && + typeof guide.frame_center?.x === "number" && + typeof guide.frame_center?.y === "number" && + typeof guide.target?.x === "number" && + typeof guide.target?.y === "number" + ) { + const cx = guide.frame_center.x; + const cy = guide.frame_center.y; + const tx = guide.target.x; + const ty = guide.target.y; + ctx.strokeStyle = "rgba(244, 63, 94, 0.95)"; + ctx.fillStyle = "rgba(244, 63, 94, 0.95)"; + ctx.lineWidth = 2; + ctx.beginPath(); + ctx.moveTo(cx, cy); + ctx.lineTo(tx, ty); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(tx, ty, 6, 0, Math.PI * 2); + ctx.stroke(); + const ang = typeof guide.angular_sep_deg === "number" ? guide.angular_sep_deg.toFixed(2) : "-"; + ctx.font = "12px system-ui, sans-serif"; + ctx.fillText(`Polar ${ang}deg`, tx + 10, ty - 6); + } } export function drawSolveOverlay( diff --git a/web/static/analysis-lab/assets/index-B7lY1o6d.js b/web/static/analysis-lab/assets/index-B7lY1o6d.js new file mode 100644 index 0000000..a045142 --- /dev/null +++ b/web/static/analysis-lab/assets/index-B7lY1o6d.js @@ -0,0 +1,125 @@ +(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))r(l);new MutationObserver(l=>{for(const o of l)if(o.type==="childList")for(const a of o.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&r(a)}).observe(document,{childList:!0,subtree:!0});function n(l){const o={};return l.integrity&&(o.integrity=l.integrity),l.referrerPolicy&&(o.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?o.credentials="include":l.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(l){if(l.ep)return;l.ep=!0;const o=n(l);fetch(l.href,o)}})();function Pf(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Ku={exports:{}},Jl={},Gu={exports:{}},F={};/** + * @license React + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var zr=Symbol.for("react.element"),Mf=Symbol.for("react.portal"),zf=Symbol.for("react.fragment"),Tf=Symbol.for("react.strict_mode"),Rf=Symbol.for("react.profiler"),Lf=Symbol.for("react.provider"),Ff=Symbol.for("react.context"),Of=Symbol.for("react.forward_ref"),If=Symbol.for("react.suspense"),Df=Symbol.for("react.memo"),Uf=Symbol.for("react.lazy"),Ei=Symbol.iterator;function $f(e){return e===null||typeof e!="object"?null:(e=Ei&&e[Ei]||e["@@iterator"],typeof e=="function"?e:null)}var Yu={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Xu=Object.assign,Ju={};function Dn(e,t,n){this.props=e,this.context=t,this.refs=Ju,this.updater=n||Yu}Dn.prototype.isReactComponent={};Dn.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};Dn.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function Zu(){}Zu.prototype=Dn.prototype;function ss(e,t,n){this.props=e,this.context=t,this.refs=Ju,this.updater=n||Yu}var is=ss.prototype=new Zu;is.constructor=ss;Xu(is,Dn.prototype);is.isPureReactComponent=!0;var bi=Array.isArray,qu=Object.prototype.hasOwnProperty,us={current:null},ec={key:!0,ref:!0,__self:!0,__source:!0};function tc(e,t,n){var r,l={},o=null,a=null;if(t!=null)for(r in t.ref!==void 0&&(a=t.ref),t.key!==void 0&&(o=""+t.key),t)qu.call(t,r)&&!ec.hasOwnProperty(r)&&(l[r]=t[r]);var i=arguments.length-2;if(i===1)l.children=n;else if(1>>1,Z=b[H];if(0>>1;H<_e;){var Ke=2*(H+1)-1,rt=b[Ke],Ce=Ke+1,lt=b[Ce];if(0>l(rt,R))Cel(lt,rt)?(b[H]=lt,b[Ce]=R,H=Ce):(b[H]=rt,b[Ke]=R,H=Ke);else if(Cel(lt,R))b[H]=lt,b[Ce]=R,H=Ce;else break e}}return T}function l(b,T){var R=b.sortIndex-T.sortIndex;return R!==0?R:b.id-T.id}if(typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var a=Date,i=a.now();e.unstable_now=function(){return a.now()-i}}var u=[],f=[],v=1,h=null,y=3,k=!1,j=!1,_=!1,$=typeof setTimeout=="function"?setTimeout:null,p=typeof clearTimeout=="function"?clearTimeout:null,d=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function m(b){for(var T=n(f);T!==null;){if(T.callback===null)r(f);else if(T.startTime<=b)r(f),T.sortIndex=T.expirationTime,t(u,T);else break;T=n(f)}}function g(b){if(_=!1,m(b),!j)if(n(u)!==null)j=!0,rn(N);else{var T=n(f);T!==null&&Ut(g,T.startTime-b)}}function N(b,T){j=!1,_&&(_=!1,p(z),z=-1),k=!0;var R=y;try{for(m(T),h=n(u);h!==null&&(!(h.expirationTime>T)||b&&!le());){var H=h.callback;if(typeof H=="function"){h.callback=null,y=h.priorityLevel;var Z=H(h.expirationTime<=T);T=e.unstable_now(),typeof Z=="function"?h.callback=Z:h===n(u)&&r(u),m(T)}else r(u);h=n(u)}if(h!==null)var _e=!0;else{var Ke=n(f);Ke!==null&&Ut(g,Ke.startTime-T),_e=!1}return _e}finally{h=null,y=R,k=!1}}var M=!1,E=null,z=-1,U=5,L=-1;function le(){return!(e.unstable_now()-Lb||125H?(b.sortIndex=R,t(f,b),n(u)===null&&b===n(f)&&(_?(p(z),z=-1):_=!0,Ut(g,R-H))):(b.sortIndex=Z,t(u,b),j||k||(j=!0,rn(N))),b},e.unstable_shouldYield=le,e.unstable_wrapCallback=function(b){var T=y;return function(){var R=y;y=T;try{return b.apply(this,arguments)}finally{y=R}}}})(ac);oc.exports=ac;var Zf=oc.exports;/** + * @license React + * react-dom.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var qf=w,Me=Zf;function S(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),ma=Object.prototype.hasOwnProperty,ep=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,Mi={},zi={};function tp(e){return ma.call(zi,e)?!0:ma.call(Mi,e)?!1:ep.test(e)?zi[e]=!0:(Mi[e]=!0,!1)}function np(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function rp(e,t,n,r){if(t===null||typeof t>"u"||np(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function ge(e,t,n,r,l,o,a){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=l,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=a}var ue={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){ue[e]=new ge(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];ue[t]=new ge(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){ue[e]=new ge(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){ue[e]=new ge(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){ue[e]=new ge(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){ue[e]=new ge(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){ue[e]=new ge(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){ue[e]=new ge(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){ue[e]=new ge(e,5,!1,e.toLowerCase(),null,!1,!1)});var ds=/[\-:]([a-z])/g;function fs(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(ds,fs);ue[t]=new ge(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(ds,fs);ue[t]=new ge(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(ds,fs);ue[t]=new ge(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){ue[e]=new ge(e,1,!1,e.toLowerCase(),null,!1,!1)});ue.xlinkHref=new ge("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){ue[e]=new ge(e,1,!1,e.toLowerCase(),null,!0,!0)});function ps(e,t,n,r){var l=ue.hasOwnProperty(t)?ue[t]:null;(l!==null?l.type!==0:r||!(2i||l[a]!==o[i]){var u=` +`+l[a].replace(" at new "," at ");return e.displayName&&u.includes("")&&(u=u.replace("",e.displayName)),u}while(1<=a&&0<=i);break}}}finally{Oo=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?tr(e):""}function lp(e){switch(e.tag){case 5:return tr(e.type);case 16:return tr("Lazy");case 13:return tr("Suspense");case 19:return tr("SuspenseList");case 0:case 2:case 15:return e=Io(e.type,!1),e;case 11:return e=Io(e.type.render,!1),e;case 1:return e=Io(e.type,!0),e;default:return""}}function ga(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case pn:return"Fragment";case fn:return"Portal";case ha:return"Profiler";case ms:return"StrictMode";case va:return"Suspense";case ya:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case uc:return(e.displayName||"Context")+".Consumer";case ic:return(e._context.displayName||"Context")+".Provider";case hs:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case vs:return t=e.displayName||null,t!==null?t:ga(e.type)||"Memo";case wt:t=e._payload,e=e._init;try{return ga(e(t))}catch{}}return null}function op(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return ga(t);case 8:return t===ms?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function Lt(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function dc(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function ap(e){var t=dc(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var l=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return l.call(this)},set:function(a){r=""+a,o.call(this,a)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(a){r=""+a},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function Jr(e){e._valueTracker||(e._valueTracker=ap(e))}function fc(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=dc(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function Cl(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function xa(e,t){var n=t.checked;return Y({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function Ri(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=Lt(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function pc(e,t){t=t.checked,t!=null&&ps(e,"checked",t,!1)}function wa(e,t){pc(e,t);var n=Lt(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Sa(e,t.type,n):t.hasOwnProperty("defaultValue")&&Sa(e,t.type,Lt(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function Li(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function Sa(e,t,n){(t!=="number"||Cl(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var nr=Array.isArray;function jn(e,t,n,r){if(e=e.options,t){t={};for(var l=0;l"+t.valueOf().toString()+"",t=Zr.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function hr(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var or={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},sp=["Webkit","ms","Moz","O"];Object.keys(or).forEach(function(e){sp.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),or[t]=or[e]})});function yc(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||or.hasOwnProperty(e)&&or[e]?(""+t).trim():t+"px"}function gc(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,l=yc(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,l):e[n]=l}}var ip=Y({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function ja(e,t){if(t){if(ip[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(S(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(S(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(S(61))}if(t.style!=null&&typeof t.style!="object")throw Error(S(62))}}function _a(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var Ca=null;function ys(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var Ea=null,_n=null,Cn=null;function Ii(e){if(e=Lr(e)){if(typeof Ea!="function")throw Error(S(280));var t=e.stateNode;t&&(t=no(t),Ea(e.stateNode,e.type,t))}}function xc(e){_n?Cn?Cn.push(e):Cn=[e]:_n=e}function wc(){if(_n){var e=_n,t=Cn;if(Cn=_n=null,Ii(e),t)for(e=0;e>>=0,e===0?32:31-(xp(e)/wp|0)|0}var qr=64,el=4194304;function rr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function Ml(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,l=e.suspendedLanes,o=e.pingedLanes,a=n&268435455;if(a!==0){var i=a&~l;i!==0?r=rr(i):(o&=a,o!==0&&(r=rr(o)))}else a=n&~l,a!==0?r=rr(a):o!==0&&(r=rr(o));if(r===0)return 0;if(t!==0&&t!==r&&!(t&l)&&(l=r&-r,o=t&-t,l>=o||l===16&&(o&4194240)!==0))return t;if(r&4&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Tr(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-Ve(t),e[t]=n}function jp(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=sr),Qi=" ",Ki=!1;function $c(e,t){switch(e){case"keyup":return Zp.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Hc(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var mn=!1;function em(e,t){switch(e){case"compositionend":return Hc(t);case"keypress":return t.which!==32?null:(Ki=!0,Qi);case"textInput":return e=t.data,e===Qi&&Ki?null:e;default:return null}}function tm(e,t){if(mn)return e==="compositionend"||!_s&&$c(e,t)?(e=Dc(),vl=ks=jt=null,mn=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=Ji(n)}}function Wc(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Wc(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Qc(){for(var e=window,t=Cl();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=Cl(e.document)}return t}function Cs(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function cm(e){var t=Qc(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&Wc(n.ownerDocument.documentElement,n)){if(r!==null&&Cs(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var l=n.textContent.length,o=Math.min(r.start,l);r=r.end===void 0?o:Math.min(r.end,l),!e.extend&&o>r&&(l=r,r=o,o=l),l=Zi(n,o);var a=Zi(n,r);l&&a&&(e.rangeCount!==1||e.anchorNode!==l.node||e.anchorOffset!==l.offset||e.focusNode!==a.node||e.focusOffset!==a.offset)&&(t=t.createRange(),t.setStart(l.node,l.offset),e.removeAllRanges(),o>r?(e.addRange(t),e.extend(a.node,a.offset)):(t.setEnd(a.node,a.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,hn=null,Ra=null,ur=null,La=!1;function qi(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;La||hn==null||hn!==Cl(r)||(r=hn,"selectionStart"in r&&Cs(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),ur&&Sr(ur,r)||(ur=r,r=Rl(Ra,"onSelect"),0gn||(e.current=$a[gn],$a[gn]=null,gn--)}function A(e,t){gn++,$a[gn]=e.current,e.current=t}var Ft={},pe=It(Ft),ke=It(!1),Yt=Ft;function Tn(e,t){var n=e.type.contextTypes;if(!n)return Ft;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var l={},o;for(o in n)l[o]=t[o];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=l),l}function Ne(e){return e=e.childContextTypes,e!=null}function Fl(){V(ke),V(pe)}function au(e,t,n){if(pe.current!==Ft)throw Error(S(168));A(pe,t),A(ke,n)}function td(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var l in r)if(!(l in t))throw Error(S(108,op(e)||"Unknown",l));return Y({},n,r)}function Ol(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Ft,Yt=pe.current,A(pe,e),A(ke,ke.current),!0}function su(e,t,n){var r=e.stateNode;if(!r)throw Error(S(169));n?(e=td(e,t,Yt),r.__reactInternalMemoizedMergedChildContext=e,V(ke),V(pe),A(pe,e)):V(ke),A(ke,n)}var ut=null,ro=!1,Jo=!1;function nd(e){ut===null?ut=[e]:ut.push(e)}function km(e){ro=!0,nd(e)}function Dt(){if(!Jo&&ut!==null){Jo=!0;var e=0,t=D;try{var n=ut;for(D=1;e>=a,l-=a,ct=1<<32-Ve(t)+l|n<z?(U=E,E=null):U=E.sibling;var L=y(p,E,m[z],g);if(L===null){E===null&&(E=U);break}e&&E&&L.alternate===null&&t(p,E),d=o(L,d,z),M===null?N=L:M.sibling=L,M=L,E=U}if(z===m.length)return n(p,E),W&&At(p,z),N;if(E===null){for(;zz?(U=E,E=null):U=E.sibling;var le=y(p,E,L.value,g);if(le===null){E===null&&(E=U);break}e&&E&&le.alternate===null&&t(p,E),d=o(le,d,z),M===null?N=le:M.sibling=le,M=le,E=U}if(L.done)return n(p,E),W&&At(p,z),N;if(E===null){for(;!L.done;z++,L=m.next())L=h(p,L.value,g),L!==null&&(d=o(L,d,z),M===null?N=L:M.sibling=L,M=L);return W&&At(p,z),N}for(E=r(p,E);!L.done;z++,L=m.next())L=k(E,p,z,L.value,g),L!==null&&(e&&L.alternate!==null&&E.delete(L.key===null?z:L.key),d=o(L,d,z),M===null?N=L:M.sibling=L,M=L);return e&&E.forEach(function(nt){return t(p,nt)}),W&&At(p,z),N}function $(p,d,m,g){if(typeof m=="object"&&m!==null&&m.type===pn&&m.key===null&&(m=m.props.children),typeof m=="object"&&m!==null){switch(m.$$typeof){case Xr:e:{for(var N=m.key,M=d;M!==null;){if(M.key===N){if(N=m.type,N===pn){if(M.tag===7){n(p,M.sibling),d=l(M,m.props.children),d.return=p,p=d;break e}}else if(M.elementType===N||typeof N=="object"&&N!==null&&N.$$typeof===wt&&cu(N)===M.type){n(p,M.sibling),d=l(M,m.props),d.ref=Jn(p,M,m),d.return=p,p=d;break e}n(p,M);break}else t(p,M);M=M.sibling}m.type===pn?(d=Gt(m.props.children,p.mode,g,m.key),d.return=p,p=d):(g=jl(m.type,m.key,m.props,null,p.mode,g),g.ref=Jn(p,d,m),g.return=p,p=g)}return a(p);case fn:e:{for(M=m.key;d!==null;){if(d.key===M)if(d.tag===4&&d.stateNode.containerInfo===m.containerInfo&&d.stateNode.implementation===m.implementation){n(p,d.sibling),d=l(d,m.children||[]),d.return=p,p=d;break e}else{n(p,d);break}else t(p,d);d=d.sibling}d=oa(m,p.mode,g),d.return=p,p=d}return a(p);case wt:return M=m._init,$(p,d,M(m._payload),g)}if(nr(m))return j(p,d,m,g);if(Qn(m))return _(p,d,m,g);sl(p,m)}return typeof m=="string"&&m!==""||typeof m=="number"?(m=""+m,d!==null&&d.tag===6?(n(p,d.sibling),d=l(d,m),d.return=p,p=d):(n(p,d),d=la(m,p.mode,g),d.return=p,p=d),a(p)):n(p,d)}return $}var Ln=ad(!0),sd=ad(!1),Ul=It(null),$l=null,Sn=null,Ms=null;function zs(){Ms=Sn=$l=null}function Ts(e){var t=Ul.current;V(Ul),e._currentValue=t}function Ba(e,t,n){for(;e!==null;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,r!==null&&(r.childLanes|=t)):r!==null&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function bn(e,t){$l=e,Ms=Sn=null,e=e.dependencies,e!==null&&e.firstContext!==null&&(e.lanes&t&&(Se=!0),e.firstContext=null)}function De(e){var t=e._currentValue;if(Ms!==e)if(e={context:e,memoizedValue:t,next:null},Sn===null){if($l===null)throw Error(S(308));Sn=e,$l.dependencies={lanes:0,firstContext:e}}else Sn=Sn.next=e;return t}var Wt=null;function Rs(e){Wt===null?Wt=[e]:Wt.push(e)}function id(e,t,n,r){var l=t.interleaved;return l===null?(n.next=n,Rs(t)):(n.next=l.next,l.next=n),t.interleaved=n,ht(e,r)}function ht(e,t){e.lanes|=t;var n=e.alternate;for(n!==null&&(n.lanes|=t),n=e,e=e.return;e!==null;)e.childLanes|=t,n=e.alternate,n!==null&&(n.childLanes|=t),n=e,e=e.return;return n.tag===3?n.stateNode:null}var St=!1;function Ls(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function ud(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function ft(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Mt(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,O&2){var l=r.pending;return l===null?t.next=t:(t.next=l.next,l.next=t),r.pending=t,ht(e,n)}return l=r.interleaved,l===null?(t.next=t,Rs(r)):(t.next=l.next,l.next=t),r.interleaved=t,ht(e,n)}function gl(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194240)!==0)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,xs(e,n)}}function du(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var l=null,o=null;if(n=n.firstBaseUpdate,n!==null){do{var a={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};o===null?l=o=a:o=o.next=a,n=n.next}while(n!==null);o===null?l=o=t:o=o.next=t}else l=o=t;n={baseState:r.baseState,firstBaseUpdate:l,lastBaseUpdate:o,shared:r.shared,effects:r.effects},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function Hl(e,t,n,r){var l=e.updateQueue;St=!1;var o=l.firstBaseUpdate,a=l.lastBaseUpdate,i=l.shared.pending;if(i!==null){l.shared.pending=null;var u=i,f=u.next;u.next=null,a===null?o=f:a.next=f,a=u;var v=e.alternate;v!==null&&(v=v.updateQueue,i=v.lastBaseUpdate,i!==a&&(i===null?v.firstBaseUpdate=f:i.next=f,v.lastBaseUpdate=u))}if(o!==null){var h=l.baseState;a=0,v=f=u=null,i=o;do{var y=i.lane,k=i.eventTime;if((r&y)===y){v!==null&&(v=v.next={eventTime:k,lane:0,tag:i.tag,payload:i.payload,callback:i.callback,next:null});e:{var j=e,_=i;switch(y=t,k=n,_.tag){case 1:if(j=_.payload,typeof j=="function"){h=j.call(k,h,y);break e}h=j;break e;case 3:j.flags=j.flags&-65537|128;case 0:if(j=_.payload,y=typeof j=="function"?j.call(k,h,y):j,y==null)break e;h=Y({},h,y);break e;case 2:St=!0}}i.callback!==null&&i.lane!==0&&(e.flags|=64,y=l.effects,y===null?l.effects=[i]:y.push(i))}else k={eventTime:k,lane:y,tag:i.tag,payload:i.payload,callback:i.callback,next:null},v===null?(f=v=k,u=h):v=v.next=k,a|=y;if(i=i.next,i===null){if(i=l.shared.pending,i===null)break;y=i,i=y.next,y.next=null,l.lastBaseUpdate=y,l.shared.pending=null}}while(!0);if(v===null&&(u=h),l.baseState=u,l.firstBaseUpdate=f,l.lastBaseUpdate=v,t=l.shared.interleaved,t!==null){l=t;do a|=l.lane,l=l.next;while(l!==t)}else o===null&&(l.shared.lanes=0);Zt|=a,e.lanes=a,e.memoizedState=h}}function fu(e,t,n){if(e=t.effects,t.effects=null,e!==null)for(t=0;tn?n:4,e(!0);var r=qo.transition;qo.transition={};try{e(!1),t()}finally{D=n,qo.transition=r}}function Cd(){return Ue().memoizedState}function Cm(e,t,n){var r=Tt(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},Ed(e))bd(t,n);else if(n=id(e,t,n,r),n!==null){var l=ve();We(n,e,r,l),Pd(n,t,r)}}function Em(e,t,n){var r=Tt(e),l={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(Ed(e))bd(t,l);else{var o=e.alternate;if(e.lanes===0&&(o===null||o.lanes===0)&&(o=t.lastRenderedReducer,o!==null))try{var a=t.lastRenderedState,i=o(a,n);if(l.hasEagerState=!0,l.eagerState=i,Qe(i,a)){var u=t.interleaved;u===null?(l.next=l,Rs(t)):(l.next=u.next,u.next=l),t.interleaved=l;return}}catch{}finally{}n=id(e,t,l,r),n!==null&&(l=ve(),We(n,e,r,l),Pd(n,t,r))}}function Ed(e){var t=e.alternate;return e===G||t!==null&&t===G}function bd(e,t){cr=Bl=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Pd(e,t,n){if(n&4194240){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,xs(e,n)}}var Vl={readContext:De,useCallback:ce,useContext:ce,useEffect:ce,useImperativeHandle:ce,useInsertionEffect:ce,useLayoutEffect:ce,useMemo:ce,useReducer:ce,useRef:ce,useState:ce,useDebugValue:ce,useDeferredValue:ce,useTransition:ce,useMutableSource:ce,useSyncExternalStore:ce,useId:ce,unstable_isNewReconciler:!1},bm={readContext:De,useCallback:function(e,t){return Je().memoizedState=[e,t===void 0?null:t],e},useContext:De,useEffect:mu,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,wl(4194308,4,Sd.bind(null,t,e),n)},useLayoutEffect:function(e,t){return wl(4194308,4,e,t)},useInsertionEffect:function(e,t){return wl(4,2,e,t)},useMemo:function(e,t){var n=Je();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=Je();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=Cm.bind(null,G,e),[r.memoizedState,e]},useRef:function(e){var t=Je();return e={current:e},t.memoizedState=e},useState:pu,useDebugValue:As,useDeferredValue:function(e){return Je().memoizedState=e},useTransition:function(){var e=pu(!1),t=e[0];return e=_m.bind(null,e[1]),Je().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=G,l=Je();if(W){if(n===void 0)throw Error(S(407));n=n()}else{if(n=t(),ae===null)throw Error(S(349));Jt&30||pd(r,t,n)}l.memoizedState=n;var o={value:n,getSnapshot:t};return l.queue=o,mu(hd.bind(null,r,o,e),[e]),r.flags|=2048,Pr(9,md.bind(null,r,o,n,t),void 0,null),n},useId:function(){var e=Je(),t=ae.identifierPrefix;if(W){var n=dt,r=ct;n=(r&~(1<<32-Ve(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=Er++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=a.createElement(n,{is:r.is}):(e=a.createElement(n),n==="select"&&(a=e,r.multiple?a.multiple=!0:r.size&&(a.size=r.size))):e=a.createElementNS(e,n),e[Ze]=t,e[jr]=r,Ud(e,t,!1,!1),t.stateNode=e;e:{switch(a=_a(n,r),n){case"dialog":B("cancel",e),B("close",e),l=r;break;case"iframe":case"object":case"embed":B("load",e),l=r;break;case"video":case"audio":for(l=0;lIn&&(t.flags|=128,r=!0,Zn(o,!1),t.lanes=4194304)}else{if(!r)if(e=Al(a),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),Zn(o,!0),o.tail===null&&o.tailMode==="hidden"&&!a.alternate&&!W)return de(t),null}else 2*ee()-o.renderingStartTime>In&&n!==1073741824&&(t.flags|=128,r=!0,Zn(o,!1),t.lanes=4194304);o.isBackwards?(a.sibling=t.child,t.child=a):(n=o.last,n!==null?n.sibling=a:t.child=a,o.last=a)}return o.tail!==null?(t=o.tail,o.rendering=t,o.tail=t.sibling,o.renderingStartTime=ee(),t.sibling=null,n=K.current,A(K,r?n&1|2:n&1),t):(de(t),null);case 22:case 23:return Gs(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&t.mode&1?Ee&1073741824&&(de(t),t.subtreeFlags&6&&(t.flags|=8192)):de(t),null;case 24:return null;case 25:return null}throw Error(S(156,t.tag))}function Om(e,t){switch(bs(t),t.tag){case 1:return Ne(t.type)&&Fl(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Fn(),V(ke),V(pe),Is(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 5:return Os(t),null;case 13:if(V(K),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(S(340));Rn()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return V(K),null;case 4:return Fn(),null;case 10:return Ts(t.type._context),null;case 22:case 23:return Gs(),null;case 24:return null;default:return null}}var ul=!1,fe=!1,Im=typeof WeakSet=="function"?WeakSet:Set,P=null;function kn(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){J(e,t,r)}else n.current=null}function Za(e,t,n){try{n()}catch(r){J(e,t,r)}}var _u=!1;function Dm(e,t){if(Fa=zl,e=Qc(),Cs(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var l=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break e}var a=0,i=-1,u=-1,f=0,v=0,h=e,y=null;t:for(;;){for(var k;h!==n||l!==0&&h.nodeType!==3||(i=a+l),h!==o||r!==0&&h.nodeType!==3||(u=a+r),h.nodeType===3&&(a+=h.nodeValue.length),(k=h.firstChild)!==null;)y=h,h=k;for(;;){if(h===e)break t;if(y===n&&++f===l&&(i=a),y===o&&++v===r&&(u=a),(k=h.nextSibling)!==null)break;h=y,y=h.parentNode}h=k}n=i===-1||u===-1?null:{start:i,end:u}}else n=null}n=n||{start:0,end:0}}else n=null;for(Oa={focusedElem:e,selectionRange:n},zl=!1,P=t;P!==null;)if(t=P,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,P=e;else for(;P!==null;){t=P;try{var j=t.alternate;if(t.flags&1024)switch(t.tag){case 0:case 11:case 15:break;case 1:if(j!==null){var _=j.memoizedProps,$=j.memoizedState,p=t.stateNode,d=p.getSnapshotBeforeUpdate(t.elementType===t.type?_:He(t.type,_),$);p.__reactInternalSnapshotBeforeUpdate=d}break;case 3:var m=t.stateNode.containerInfo;m.nodeType===1?m.textContent="":m.nodeType===9&&m.documentElement&&m.removeChild(m.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(S(163))}}catch(g){J(t,t.return,g)}if(e=t.sibling,e!==null){e.return=t.return,P=e;break}P=t.return}return j=_u,_u=!1,j}function dr(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var l=r=r.next;do{if((l.tag&e)===e){var o=l.destroy;l.destroy=void 0,o!==void 0&&Za(t,n,o)}l=l.next}while(l!==r)}}function ao(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function qa(e){var t=e.ref;if(t!==null){var n=e.stateNode;switch(e.tag){case 5:e=n;break;default:e=n}typeof t=="function"?t(e):t.current=e}}function Ad(e){var t=e.alternate;t!==null&&(e.alternate=null,Ad(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[Ze],delete t[jr],delete t[Ua],delete t[wm],delete t[Sm])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function Bd(e){return e.tag===5||e.tag===3||e.tag===4}function Cu(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Bd(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function es(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=Ll));else if(r!==4&&(e=e.child,e!==null))for(es(e,t,n),e=e.sibling;e!==null;)es(e,t,n),e=e.sibling}function ts(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(ts(e,t,n),e=e.sibling;e!==null;)ts(e,t,n),e=e.sibling}var se=null,Ae=!1;function xt(e,t,n){for(n=n.child;n!==null;)Vd(e,t,n),n=n.sibling}function Vd(e,t,n){if(qe&&typeof qe.onCommitFiberUnmount=="function")try{qe.onCommitFiberUnmount(Zl,n)}catch{}switch(n.tag){case 5:fe||kn(n,t);case 6:var r=se,l=Ae;se=null,xt(e,t,n),se=r,Ae=l,se!==null&&(Ae?(e=se,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):se.removeChild(n.stateNode));break;case 18:se!==null&&(Ae?(e=se,n=n.stateNode,e.nodeType===8?Xo(e.parentNode,n):e.nodeType===1&&Xo(e,n),xr(e)):Xo(se,n.stateNode));break;case 4:r=se,l=Ae,se=n.stateNode.containerInfo,Ae=!0,xt(e,t,n),se=r,Ae=l;break;case 0:case 11:case 14:case 15:if(!fe&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){l=r=r.next;do{var o=l,a=o.destroy;o=o.tag,a!==void 0&&(o&2||o&4)&&Za(n,t,a),l=l.next}while(l!==r)}xt(e,t,n);break;case 1:if(!fe&&(kn(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(i){J(n,t,i)}xt(e,t,n);break;case 21:xt(e,t,n);break;case 22:n.mode&1?(fe=(r=fe)||n.memoizedState!==null,xt(e,t,n),fe=r):xt(e,t,n);break;default:xt(e,t,n)}}function Eu(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new Im),t.forEach(function(r){var l=Km.bind(null,e,r);n.has(r)||(n.add(r),r.then(l,l))})}}function $e(e,t){var n=t.deletions;if(n!==null)for(var r=0;rl&&(l=a),r&=~o}if(r=l,r=ee()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*$m(r/1960))-r,10e?16:e,_t===null)var r=!1;else{if(e=_t,_t=null,Kl=0,O&6)throw Error(S(331));var l=O;for(O|=4,P=e.current;P!==null;){var o=P,a=o.child;if(P.flags&16){var i=o.deletions;if(i!==null){for(var u=0;uee()-Qs?Kt(e,0):Ws|=n),je(e,t)}function Zd(e,t){t===0&&(e.mode&1?(t=el,el<<=1,!(el&130023424)&&(el=4194304)):t=1);var n=ve();e=ht(e,t),e!==null&&(Tr(e,t,n),je(e,n))}function Qm(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Zd(e,n)}function Km(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,l=e.memoizedState;l!==null&&(n=l.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(S(314))}r!==null&&r.delete(t),Zd(e,n)}var qd;qd=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||ke.current)Se=!0;else{if(!(e.lanes&n)&&!(t.flags&128))return Se=!1,Lm(e,t,n);Se=!!(e.flags&131072)}else Se=!1,W&&t.flags&1048576&&rd(t,Dl,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;Sl(e,t),e=t.pendingProps;var l=Tn(t,pe.current);bn(t,n),l=Us(null,t,r,e,l,n);var o=$s();return t.flags|=1,typeof l=="object"&&l!==null&&typeof l.render=="function"&&l.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,Ne(r)?(o=!0,Ol(t)):o=!1,t.memoizedState=l.state!==null&&l.state!==void 0?l.state:null,Ls(t),l.updater=oo,t.stateNode=l,l._reactInternals=t,Wa(t,r,e,n),t=Ga(null,t,r,!0,o,n)):(t.tag=0,W&&o&&Es(t),he(null,t,l,n),t=t.child),t;case 16:r=t.elementType;e:{switch(Sl(e,t),e=t.pendingProps,l=r._init,r=l(r._payload),t.type=r,l=t.tag=Ym(r),e=He(r,e),l){case 0:t=Ka(null,t,r,e,n);break e;case 1:t=ku(null,t,r,e,n);break e;case 11:t=wu(null,t,r,e,n);break e;case 14:t=Su(null,t,r,He(r.type,e),n);break e}throw Error(S(306,r,""))}return t;case 0:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:He(r,l),Ka(e,t,r,l,n);case 1:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:He(r,l),ku(e,t,r,l,n);case 3:e:{if(Od(t),e===null)throw Error(S(387));r=t.pendingProps,o=t.memoizedState,l=o.element,ud(e,t),Hl(t,r,null,n);var a=t.memoizedState;if(r=a.element,o.isDehydrated)if(o={element:r,isDehydrated:!1,cache:a.cache,pendingSuspenseBoundaries:a.pendingSuspenseBoundaries,transitions:a.transitions},t.updateQueue.baseState=o,t.memoizedState=o,t.flags&256){l=On(Error(S(423)),t),t=Nu(e,t,r,n,l);break e}else if(r!==l){l=On(Error(S(424)),t),t=Nu(e,t,r,n,l);break e}else for(be=Pt(t.stateNode.containerInfo.firstChild),Pe=t,W=!0,Be=null,n=sd(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(Rn(),r===l){t=vt(e,t,n);break e}he(e,t,r,n)}t=t.child}return t;case 5:return cd(t),e===null&&Aa(t),r=t.type,l=t.pendingProps,o=e!==null?e.memoizedProps:null,a=l.children,Ia(r,l)?a=null:o!==null&&Ia(r,o)&&(t.flags|=32),Fd(e,t),he(e,t,a,n),t.child;case 6:return e===null&&Aa(t),null;case 13:return Id(e,t,n);case 4:return Fs(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=Ln(t,null,r,n):he(e,t,r,n),t.child;case 11:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:He(r,l),wu(e,t,r,l,n);case 7:return he(e,t,t.pendingProps,n),t.child;case 8:return he(e,t,t.pendingProps.children,n),t.child;case 12:return he(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,l=t.pendingProps,o=t.memoizedProps,a=l.value,A(Ul,r._currentValue),r._currentValue=a,o!==null)if(Qe(o.value,a)){if(o.children===l.children&&!ke.current){t=vt(e,t,n);break e}}else for(o=t.child,o!==null&&(o.return=t);o!==null;){var i=o.dependencies;if(i!==null){a=o.child;for(var u=i.firstContext;u!==null;){if(u.context===r){if(o.tag===1){u=ft(-1,n&-n),u.tag=2;var f=o.updateQueue;if(f!==null){f=f.shared;var v=f.pending;v===null?u.next=u:(u.next=v.next,v.next=u),f.pending=u}}o.lanes|=n,u=o.alternate,u!==null&&(u.lanes|=n),Ba(o.return,n,t),i.lanes|=n;break}u=u.next}}else if(o.tag===10)a=o.type===t.type?null:o.child;else if(o.tag===18){if(a=o.return,a===null)throw Error(S(341));a.lanes|=n,i=a.alternate,i!==null&&(i.lanes|=n),Ba(a,n,t),a=o.sibling}else a=o.child;if(a!==null)a.return=o;else for(a=o;a!==null;){if(a===t){a=null;break}if(o=a.sibling,o!==null){o.return=a.return,a=o;break}a=a.return}o=a}he(e,t,l.children,n),t=t.child}return t;case 9:return l=t.type,r=t.pendingProps.children,bn(t,n),l=De(l),r=r(l),t.flags|=1,he(e,t,r,n),t.child;case 14:return r=t.type,l=He(r,t.pendingProps),l=He(r.type,l),Su(e,t,r,l,n);case 15:return Rd(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:He(r,l),Sl(e,t),t.tag=1,Ne(r)?(e=!0,Ol(t)):e=!1,bn(t,n),Md(t,r,l),Wa(t,r,l,n),Ga(null,t,r,!0,e,n);case 19:return Dd(e,t,n);case 22:return Ld(e,t,n)}throw Error(S(156,t.tag))};function ef(e,t){return Ec(e,t)}function Gm(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Oe(e,t,n,r){return new Gm(e,t,n,r)}function Xs(e){return e=e.prototype,!(!e||!e.isReactComponent)}function Ym(e){if(typeof e=="function")return Xs(e)?1:0;if(e!=null){if(e=e.$$typeof,e===hs)return 11;if(e===vs)return 14}return 2}function Rt(e,t){var n=e.alternate;return n===null?(n=Oe(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function jl(e,t,n,r,l,o){var a=2;if(r=e,typeof e=="function")Xs(e)&&(a=1);else if(typeof e=="string")a=5;else e:switch(e){case pn:return Gt(n.children,l,o,t);case ms:a=8,l|=8;break;case ha:return e=Oe(12,n,t,l|2),e.elementType=ha,e.lanes=o,e;case va:return e=Oe(13,n,t,l),e.elementType=va,e.lanes=o,e;case ya:return e=Oe(19,n,t,l),e.elementType=ya,e.lanes=o,e;case cc:return io(n,l,o,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case ic:a=10;break e;case uc:a=9;break e;case hs:a=11;break e;case vs:a=14;break e;case wt:a=16,r=null;break e}throw Error(S(130,e==null?e:typeof e,""))}return t=Oe(a,n,t,l),t.elementType=e,t.type=r,t.lanes=o,t}function Gt(e,t,n,r){return e=Oe(7,e,r,t),e.lanes=n,e}function io(e,t,n,r){return e=Oe(22,e,r,t),e.elementType=cc,e.lanes=n,e.stateNode={isHidden:!1},e}function la(e,t,n){return e=Oe(6,e,null,t),e.lanes=n,e}function oa(e,t,n){return t=Oe(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Xm(e,t,n,r,l){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Uo(0),this.expirationTimes=Uo(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Uo(0),this.identifierPrefix=r,this.onRecoverableError=l,this.mutableSourceEagerHydrationData=null}function Js(e,t,n,r,l,o,a,i,u){return e=new Xm(e,t,n,i,u),t===1?(t=1,o===!0&&(t|=8)):t=0,o=Oe(3,null,null,t),e.current=o,o.stateNode=e,o.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Ls(o),e}function Jm(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(lf)}catch(e){console.error(e)}}lf(),lc.exports=ze;var nh=lc.exports,Fu=nh;pa.createRoot=Fu.createRoot,pa.hydrateRoot=Fu.hydrateRoot;/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const rh=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),of=(...e)=>e.filter((t,n,r)=>!!t&&t.trim()!==""&&r.indexOf(t)===n).join(" ").trim();/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */var lh={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const oh=w.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:n=2,absoluteStrokeWidth:r,className:l="",children:o,iconNode:a,...i},u)=>w.createElement("svg",{ref:u,...lh,width:t,height:t,stroke:e,strokeWidth:r?Number(n)*24/Number(t):n,className:of("lucide",l),...i},[...a.map(([f,v])=>w.createElement(f,v)),...Array.isArray(o)?o:[o]]));/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Re=(e,t)=>{const n=w.forwardRef(({className:r,...l},o)=>w.createElement(oh,{ref:o,iconNode:t,className:of(`lucide-${rh(e)}`,r),...l}));return n.displayName=`${e}`,n};/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const er=Re("ChevronDown",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ah=Re("Database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const sh=Re("FlaskConical",[["path",{d:"M10 2v7.527a2 2 0 0 1-.211.896L4.72 20.55a1 1 0 0 0 .9 1.45h12.76a1 1 0 0 0 .9-1.45l-5.069-10.127A2 2 0 0 1 14 9.527V2",key:"pzvekw"}],["path",{d:"M8.5 2h7",key:"csnxdl"}],["path",{d:"M7 16h10",key:"wp8him"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ou=Re("Grid3x3",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M3 9h18",key:"1pudct"}],["path",{d:"M3 15h18",key:"5xshup"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"M15 3v18",key:"14nvp0"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ih=Re("History",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M12 7v5l4 2",key:"1fdv2h"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const uh=Re("House",[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"1d0kgt"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const aa=Re("LoaderCircle",[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ch=Re("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Iu=Re("RotateCcw",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Du=Re("Trash2",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const dh=Re("Upload",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"17 8 12 3 7 8",key:"t8dd8p"}],["line",{x1:"12",x2:"12",y1:"3",y2:"15",key:"widbto"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Uu=Re("ZoomIn",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"11",x2:"11",y1:"8",y2:"14",key:"1vmskp"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]]);/** + * @license lucide-react v0.460.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const $u=Re("ZoomOut",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]]),X="/api";async function tt(e){if((e.headers.get("content-type")||"").includes("application/json"))return e.json();const n=await e.text();throw new Error(n||`HTTP ${e.status}`)}async function fh(){const e=await fetch(`${X}/analysis/uploads`);if(!e.ok)throw new Error(await e.text());return e.json()}async function ph(e,t){const n=new URLSearchParams;t!=null&&t.deleteExperiments&&n.set("delete_experiments","true");const r=n.toString(),l=await fetch(`${X}/analysis/uploads/${encodeURIComponent(e)}${r?`?${r}`:""}`,{method:"DELETE"});if(!l.ok)throw new Error(await l.text());return await l.json().catch(()=>({}))}async function mh(e,t="analysis_upload"){const n=new FormData;n.append("file",e),n.append("source",t);const r=await fetch(`${X}/analysis/upload`,{method:"POST",body:n}),l=await tt(r);if(!r.ok)throw new Error(String(l.detail||r.status));return l}async function hh(e){const t=await fetch(`${X}/analysis/uploads/import_from_debug`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filename:e})}),n=await tt(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}async function vh(e,t){const n=await fetch(`${X}/analysis/solve/image`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input_name:e,...t})}),r=await tt(n);if(!n.ok)throw new Error(String(r.detail||n.status));return r}async function yh(e,t){const n=await fetch(`${X}/analysis/solve/batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input_name:e,runs:t})}),r=await tt(n);if(!n.ok)throw new Error(String(r.detail||n.status));return r}async function sa(e){const t=await fetch(`${X}/analysis/presets?scope=${e}`);if(!t.ok)throw new Error(await t.text());return t.json()}async function gh(e,t){const n=await fetch(`${X}/analysis/presets`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e,params:t})}),r=await tt(n);if(!n.ok)throw new Error(String(r.detail||n.status));return r}async function ia(e){const t=await fetch(`${X}/analysis/experiments`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}),n=await tt(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}async function xh(e){const t=await fetch(`${X}/analysis/experiments/${encodeURIComponent(e)}`,{method:"DELETE"});if(!t.ok)throw new Error(await t.text())}async function ua(e,t,n=30){const r=new URLSearchParams({page:String(t),page_size:String(n)});e&&r.set("q",e);const l=await fetch(`${X}/analysis/experiments?${r}`);if(!l.ok)throw new Error(await l.text());return l.json()}async function wh(){const e=await fetch(`${X}/debug/files`);if(!e.ok)throw new Error(await e.text());return e.json()}function Sh(e){return`${X}/debug/files/${encodeURIComponent(e)}`}async function Hu(e){const t=await fetch(`${X}/debug/files/${encodeURIComponent(e)}/info`),n=await tt(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}async function kh(e){const t=await fetch(`${X}/analysis/uploads/${encodeURIComponent(e)}/info`),n=await tt(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}function Nh(e){return`${X}/analysis/uploads/file?filename=${encodeURIComponent(e)}`}async function Au(e){const t=await fetch(`${X}/analysis/experiments/export?format=${e}`);if(!t.ok)throw new Error(await t.text());return t.text()}async function jh(e){const t=await fetch(`${X}/analysis/uploads/${encodeURIComponent(e)}/experiment_count`);if(!t.ok)throw new Error(await t.text());return t.json()}async function _h(){const e=await fetch(`${X}/analysis/settings`);if(!e.ok)throw new Error(await e.text());return e.json()}async function Ch(e){const t=await fetch(`${X}/analysis/solve/frame`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}),n=await tt(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}async function Eh(e,t){const n=new FormData;n.append("file",e,"frame.jpg"),n.append("payload",JSON.stringify(t));const r=await fetch(`${X}/analysis/solve/frame_upload`,{method:"POST",body:n}),l=await tt(r);if(!r.ok)throw new Error(String(l.detail||r.status));return l}function bh(e){return`${X}/analysis/experiments/${encodeURIComponent(e)}/asset`}async function Ph(){const e=await fetch(`${X}/system/info`);if(!e.ok)throw new Error(await e.text());return e.json()}function af(e,t,n,r,l){var i,u,f,v;if(!r)return;if(e.clearRect(0,0,t,n),l.all&&Array.isArray(r.stars_all_centroids)){e.fillStyle="rgba(156, 163, 175, 0.85)";for(const h of r.stars_all_centroids)e.beginPath(),e.arc(h.x,h.y,2.4,0,Math.PI*2),e.fill()}if(l.pattern&&Array.isArray(r.stars_pattern)){e.strokeStyle="rgba(251, 146, 60, 0.95)",e.lineWidth=2;for(const h of r.stars_pattern)e.beginPath(),e.arc(h.x,h.y,6,0,Math.PI*2),e.stroke()}if(l.matched&&Array.isArray(r.stars_matched)){e.strokeStyle="rgba(34, 197, 94, 0.95)",e.fillStyle="rgba(34, 197, 94, 0.95)",e.lineWidth=2,e.font="11px system-ui, sans-serif";for(const h of r.stars_matched)e.beginPath(),e.arc(h.x,h.y,7,0,Math.PI*2),e.stroke(),h.mag!=null&&e.fillText(`m${Number(h.mag).toFixed(1)}`,h.x+4,h.y-4)}const o=r.overlay_ext;if(Array.isArray(o==null?void 0:o.labels_topn)&&o.labels_topn.length>0){e.fillStyle="rgba(96, 165, 250, 0.95)",e.font="12px system-ui, sans-serif";for(const h of o.labels_topn){if(typeof(h==null?void 0:h.x)!="number"||typeof(h==null?void 0:h.y)!="number")continue;const y=typeof h.mag=="number"?` m${h.mag.toFixed(1)}`:"",k=`${h.name??"Star"}${y}`;e.fillText(k,h.x+8,h.y+14)}}const a=o==null?void 0:o.polar_guide;if(a&&typeof((i=a.frame_center)==null?void 0:i.x)=="number"&&typeof((u=a.frame_center)==null?void 0:u.y)=="number"&&typeof((f=a.target)==null?void 0:f.x)=="number"&&typeof((v=a.target)==null?void 0:v.y)=="number"){const h=a.frame_center.x,y=a.frame_center.y,k=a.target.x,j=a.target.y;e.strokeStyle="rgba(244, 63, 94, 0.95)",e.fillStyle="rgba(244, 63, 94, 0.95)",e.lineWidth=2,e.beginPath(),e.moveTo(h,y),e.lineTo(k,j),e.stroke(),e.beginPath(),e.arc(k,j,6,0,Math.PI*2),e.stroke();const _=typeof a.angular_sep_deg=="number"?a.angular_sep_deg.toFixed(2):"-";e.font="12px system-ui, sans-serif",e.fillText(`Polar ${_}deg`,k+10,j-6)}}function Bu(e,t,n,r){if(!n)return;const l=t.naturalWidth||1,o=t.naturalHeight||1;e.width=l,e.height=o,e.style.width=`${t.clientWidth}px`,e.style.height=`${t.clientHeight}px`;const a=e.getContext("2d");a&&af(a,l,o,n,r)}function Mh(e,t,n,r){if(!n)return;const l=t.videoWidth||1,o=t.videoHeight||1;if(l<2||o<2)return;e.width=l,e.height=o,e.style.width=`${t.clientWidth}px`,e.style.height=`${t.clientHeight}px`;const a=e.getContext("2d");a&&af(a,l,o,n,r)}const zh={"app.title":"OGScope Plate Solve Console","nav.lab":"Lab","nav.labImage":"Image solve","nav.labVideo":"Video solve","delete.uploadCascade":"Delete {n} linked experiment record(s) as well?","lab.solveCurrentFrame":"Solve current frame (file)","lab.solveFileStart":"Start continuous file solve","lab.solveFileStop":"Stop continuous file solve","lab.cameraPreviewLoading":"Connecting to shared preview…","lab.solveCameraFrame":"Solve live camera frame","lab.solveCameraStart":"Start camera solve","lab.solveCameraStop":"Stop camera solve","lab.videoPreviewFailed":"This video format may be unsupported by the browser. Try MP4 (H.264) or WebM.","lab.previewModeFile":"Pool file","lab.previewModeCamera":"Device camera","lab.videoLiveIntro":"Shares the same camera as Camera Debug — preview and solve live frames here without opening debug. Both pages can run together.","lab.cameraSnapshotName":"ogscope_camera_live","lab.metric.probRaw":"Raw Prob","lab.systemLoad":"System load","results.saveBatchAll":"Save all to records","nav.pool":"Assets","nav.history":"Records","nav.cameraDebug":"Camera Debug","nav.home":"Home","lang.zh":"中文","lang.en":"EN","sidebar.assets":"Uploaded assets","sidebar.upload":"Upload","sidebar.refresh":"Refresh","sidebar.debugCaptures":"Debug console media","sidebar.assetTypeImage":"Image","sidebar.assetTypeVideo":"Video","sidebar.debugEmpty":"No debug files","sidebar.importToPool":"Import to pool","sidebar.debugPage":"Page {cur} / {total}","sidebar.batchPresets":"Batch presets","sidebar.batchHint":"Check presets, then use Batch solve to compare multiple param sets.","lab.selectOrUpload":"Pick an uploaded or imported asset from the left","lab.selectOrUploadVideo":"Pick a pool video to preview, or use the button above for the live camera frame.","lab.file":"File","lab.source":"Source","lab.layers":"Layers","lab.layer.matched":"Matched","lab.layer.pattern":"Pattern","lab.layer.all":"All centroids","lab.grid":"Grid","lab.zoomIn":"Zoom in","lab.zoomOut":"Zoom out","lab.zoomReset":"Reset","lab.resolution":"Resolution","lab.fwhm":"FWHM","lab.starsDetected":"Stars detected","lab.meta.title":"Capture & file info","lab.meta.noSidecar":"No sidecar (not from debug capture)","lab.meta.partial":"No detailed sidecar; file info only.","lab.solveSection":"Solve","lab.imageSection":"Image","lab.metric.solveMs":"Time","lab.metric.solveComputeMs":"Solve compute","lab.metric.solveComputeHelp":"Server-side Tetra3 + star extraction only (no network).","lab.metric.solveRoundTripMs":"End-to-end","lab.metric.solveRoundTripHelp":"From request start to UI updated: network + JSON + render.","lab.metric.backendTotalMs":"Backend total","lab.metric.openDecodeMs":"Open/decode","lab.metric.preprocessMs":"Preprocess","lab.metric.extractMs":"Extract","lab.metric.solveOnlyMs":"Solve match","lab.metric.probHelp":"Solver confidence (0–1); higher means a more trustworthy plate match.","lab.metric.probRawHelp":"Raw Tetra3 Prob (e.g. log-likelihood); compare with the normalized line above.","lab.metric.radec":"RA / Dec","lab.metric.matches":"Matches","lab.metric.rmse":"RMSE","lab.metric.prob":"Prob.","lab.metric.status":"Status","meta.exposure":"Exposure","meta.gain":"Gain","meta.fps":"FPS","meta.sensor":"Sensor","meta.colorMode":"Color","meta.outputResolution":"Output size","meta.fileTime":"File time","meta.fileSize":"File size","results.viewRaw":"Raw JSON","results.hideRaw":"Hide","params.title":"Solve parameters","params.blockSolveIntro":"Plate-solve (Tetra3): FOV, timeout, and coarse sky hints. FOV should match your lens.","params.centroid":"Star detection","params.blockCentroidIntro":"Star detection: threshold, blob area, and local background window for centroids.","params.fov":"FOV estimate (°)","params.fovHelp":"Horizontal field of view for lost-in-space solve.","params.fovErr":"FOV max error (°)","params.fovErrHelp":"Search range around estimated FOV.","params.timeout":"Timeout (ms)","params.timeoutHelp":"Max wait time per solve.","params.solveProfile":"Solve profile","params.solveProfileHelp":"Speed/Balanced/Robust tune timeout, centroid thresholds, and matching star count together.","params.solveProfileSpeed":"Speed first","params.solveProfileBalanced":"Balanced","params.solveProfileRobust":"Robust first","params.ra":"RA hint (°)","params.raHelp":"Approximate right ascension in degrees.","params.dec":"Dec hint (°)","params.decHelp":"Approximate declination in degrees.","params.maxSide":"Max long side before extract (px)","params.maxSideHelp":"Downscale long edge for faster centroid extraction.","params.detailLevelFull":"Include full Tetra3 raw block (larger payload, for debugging only).","params.largeScaleBg":"Large-scale background flattening","params.largeScaleBgHelp":"Before centroiding, estimate a low-frequency background on a downscaled image and correct uneven illumination (e.g. corner glow). Off by default to match legacy behavior.","params.sigma":"σ threshold","params.sigmaHelp":"Multiplier over background noise for star candidates.","params.maxArea":"max_area","params.maxAreaHelp":"Max connected component area in pixels.","params.minArea":"min_area","params.minAreaHelp":"Min connected component area in pixels.","params.filtsize":"filtsize (odd)","params.filtsizeHelp":"Local filter window size, must be odd.","btn.solveOne":"Solve once","btn.solveBatch":"Batch solve (presets)","btn.applyPresets":"Apply preset to form","btn.savePreset":"Save","placeholder.newPreset":"New preset name","pool.title":"Server asset pool","pool.col.name":"Filename","pool.col.source":"Source","pool.col.size":"Size","pool.col.time":"Modified","pool.delete":"Delete","history.title":"Experiment records","history.intro":"Saved solve snapshots from the Lab. After a solve, use Save to records in the Lab main panel (Result comparison), or Save on each batch result card. Search by filename or preset; export JSON/CSV for backup.","history.search":"Search…","history.searchBtn":"Search","history.exportJson":"Export JSON","history.exportCsv":"Export CSV","history.total":"Total {n}","history.preset":"Preset","history.metrics":"Metrics","history.detail":"Details","history.collapse":"Collapse","history.prev":"Prev","history.next":"Next","history.delete":"Delete","delete.uploadFirst":'Delete "{name}" from the asset pool?',"delete.uploadSecond":"This cannot be undone. Confirm again?","delete.experimentFirst":"Delete this experiment record?","delete.experimentSecond":"This cannot be undone. Confirm again?","results.title":"Results","results.saveCurrent":"Save to records","results.saveRow":"Save","results.expand":"Expand","results.collapseJson":"Collapse","err.selectFile":"Select a file","err.selectPresets":"Select at least one preset","common.placeholder":"—"},Th={"app.title":"OGScope 星空解算控制台","nav.lab":"解算台","nav.labImage":"图片解算","nav.labVideo":"视频解算","nav.pool":"素材池","nav.history":"实验记录","nav.cameraDebug":"相机调试控制台","nav.home":"首页","lang.zh":"中文","lang.en":"EN","sidebar.assets":"自行上传素材","sidebar.upload":"上传文件","sidebar.refresh":"刷新列表","sidebar.debugCaptures":"调试控制台素材","sidebar.assetTypeImage":"图片","sidebar.assetTypeVideo":"视频","sidebar.debugEmpty":"暂无调试文件","sidebar.importToPool":"导入到素材池","sidebar.debugPage":"第 {cur} / {total} 页","sidebar.batchPresets":"批量预设","sidebar.batchHint":"勾选后点击「批量解算」可一次用多组参数对比结果。","lab.selectOrUpload":"从左侧选择自行上传或已导入的素材","lab.selectOrUploadVideo":"从左侧选择视频素材预览;或使用上方按钮解算设备相机实时帧。","lab.file":"文件","lab.source":"来源","lab.layers":"叠加层","lab.layer.matched":"匹配星","lab.layer.pattern":"图案星","lab.layer.all":"全部质心","lab.grid":"网格","lab.zoomIn":"放大","lab.zoomOut":"缩小","lab.zoomReset":"复位","lab.resolution":"分辨率","lab.fwhm":"FWHM","lab.starsDetected":"检测星点","lab.meta.title":"拍摄与文件信息","lab.meta.noSidecar":"无侧车信息(非调试采集或仅本地上传)","lab.meta.partial":"暂无侧车详细字段,仅显示文件信息。","lab.solveSection":"解算","lab.imageSection":"图像","lab.metric.solveMs":"用时","lab.metric.solveComputeMs":"解算计算用时","lab.metric.solveComputeHelp":"服务端 Tetra3 与提星等纯计算耗时(与网络无关)。","lab.metric.solveRoundTripMs":"全链路用时","lab.metric.solveRoundTripHelp":"从本页发起请求到收到结果并完成界面刷新的总耗时,含网络往返与浏览器渲染。","lab.metric.backendTotalMs":"后端总用时","lab.metric.openDecodeMs":"读取/解码","lab.metric.preprocessMs":"预处理","lab.metric.extractMs":"提星","lab.metric.solveOnlyMs":"匹配解算","lab.metric.probHelp":"由解算器给出的匹配置信度(0–1),越高表示星图与天区匹配越可信。","lab.metric.probRawHelp":"Tetra3 返回的原始 Prob 字段,可能为对数似然等内部量;与上一行换算后的百分比对照查看即可。","lab.metric.radec":"RA / Dec","lab.metric.matches":"匹配","lab.metric.rmse":"RMSE","lab.metric.prob":"置信","lab.metric.status":"状态","meta.exposure":"曝光","meta.gain":"增益","meta.fps":"帧率","meta.sensor":"传感器","meta.colorMode":"色彩","meta.outputResolution":"输出分辨率","meta.fileTime":"文件时间","meta.fileSize":"文件大小","results.viewRaw":"原始 JSON","results.hideRaw":"收起","params.title":"解算参数","params.blockSolveIntro":"以下为板块求解(Tetra3)搜索天区、超时与粗略指向提示;FOV 需与镜头视场大致一致。","params.centroid":"提星","params.blockCentroidIntro":"以下为星点检测:阈值、连通域面积与局部背景窗口,用于从图像中提取星点质心。","params.fov":"FOV 估计 (°)","params.fovHelp":"水平视场角估计值,用于 lost-in-space 解算。","params.fovErr":"FOV 允许误差 (°)","params.fovErrHelp":"允许 Tetra3 在估计 FOV 附近的搜索范围。","params.timeout":"超时 (ms)","params.timeoutHelp":"单次解算最长等待时间。","params.solveProfile":"解算档位","params.solveProfileHelp":"速度/平衡/稳健三档会同时调整超时、提星阈值与参与匹配星点数。","params.solveProfileSpeed":"速度优先","params.solveProfileBalanced":"平衡","params.solveProfileRobust":"稳健优先","params.ra":"RA 提示 (°)","params.raHelp":"大致天球赤经,缩小搜索范围(度)。","params.dec":"Dec 提示 (°)","params.decHelp":"大致天球赤纬(度)。","params.maxSide":"提星前长边上界 (px)","params.maxSideHelp":"降采样长边上限,大图可加速提星。","params.detailLevelFull":"包含完整 Tetra3 原始结果(体积略大,仅调试时开启)","params.largeScaleBg":"大尺度背景减除","params.largeScaleBgHelp":"在提星前用低分辨率平滑估计并校正大尺度亮度不均,可减轻角部光晕导致的假星;默认关闭以保持与过往行为一致。","params.sigma":"σ(阈值倍数)","params.sigmaHelp":"高于背景噪声倍数的区域视为星点候选。","params.maxArea":"max_area","params.maxAreaHelp":"连通域最大像素面积。","params.minArea":"min_area","params.minAreaHelp":"连通域最小像素面积。","params.filtsize":"filtsize(奇数)","params.filtsizeHelp":"局部背景滤波窗口边长,须为奇数。","btn.solveOne":"单张解算","btn.solveBatch":"批量解算(勾选预设)","btn.applyPresets":"应用预设到表单","btn.savePreset":"保存","placeholder.newPreset":"新预设名称","pool.title":"服务器素材池","pool.col.name":"文件名","pool.col.source":"来源","pool.col.size":"大小","pool.col.time":"修改时间","pool.delete":"删除","history.title":"实验记录","history.intro":"此处展示你在解算台完成解算后手动保存的快照。用法:在「解算台」主栏「结果对比」中,单张解算后点「保存当前到实验记录」,或批量解算后在某张结果卡片上点「保存记录」。本页可按文件名或预设名搜索,支持导出 JSON/CSV 备份。","history.search":"搜索…","history.searchBtn":"搜索","history.exportJson":"导出 JSON","history.exportCsv":"导出 CSV","history.total":"共 {n} 条","history.preset":"预设","history.metrics":"指标","history.detail":"详情","history.collapse":"收起","history.prev":"上一页","history.next":"下一页","history.delete":"删除","delete.uploadFirst":"确定要从素材池删除「{name}」吗?","delete.uploadSecond":"此操作不可恢复,再次确认删除?","delete.experimentFirst":"确定要删除这条实验记录吗?","delete.experimentSecond":"此操作不可恢复,再次确认删除?","results.title":"结果对比","results.saveCurrent":"保存当前到实验记录","results.saveRow":"保存记录","results.expand":"展开","results.collapseJson":"收起","err.selectFile":"请选择素材","err.selectPresets":"请勾选至少一个预设","common.placeholder":"—","delete.uploadCascade":"该素材有 {n} 条实验记录,是否一并删除?","lab.solveCurrentFrame":"解算当前帧(文件)","lab.solveFileStart":"开始文件连续解算","lab.solveFileStop":"停止文件连续解算","lab.cameraPreviewLoading":"正在连接共享预览…","lab.solveCameraFrame":"解算相机当前帧","lab.solveCameraStart":"开始相机解算","lab.solveCameraStop":"停止相机解算","lab.videoPreviewFailed":"该视频格式可能不受浏览器支持,建议使用 MP4(H.264) 或 WebM。","lab.previewModeFile":"素材文件","lab.previewModeCamera":"设备相机","lab.videoLiveIntro":"与调试控制台共用同一相机;此处可预览并解算实时帧,无需单独打开调试页。两页可同时使用。","lab.cameraSnapshotName":"ogscope_camera_live","lab.metric.probRaw":"原始 Prob","lab.systemLoad":"系统负载","results.saveBatchAll":"保存全部到实验记录"},sf=w.createContext(null),Vu={zh:Th,en:zh};function Rh({children:e}){const[t,n]=w.useState("zh"),[r,l]=w.useState(Vu.zh);w.useEffect(()=>{l(Vu[t])},[t]);const o=w.useMemo(()=>(i,u)=>{let f=r[i]??i;if(u)for(const[v,h]of Object.entries(u))f=f.replace(new RegExp(`\\{${v}\\}`,"g"),String(h));return f},[r]),a=w.useMemo(()=>({locale:t,setLocale:n,t:o}),[t,o]);return s.jsx(sf.Provider,{value:a,children:e})}function uf(){const e=w.useContext(sf);if(!e)throw new Error("useI18n must be used within I18nProvider");return e}function as(e){return e==null||Number.isNaN(e)?"—":e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(2)} MB`}function _l(e,t){if(!e)return"—";try{const n=new Date(e);return new Intl.DateTimeFormat(t==="en"?"en-GB":"zh-CN",{dateStyle:"short",timeStyle:"medium"}).format(n)}catch{return e}}function Ht(e){return e==null?null:typeof e=="string"&&e.trim()?e.trim():typeof e=="number"&&!Number.isNaN(e)?String(e):null}function Lh(e){return typeof e!="number"||e<=0?null:e>=1e6?`${(e/1e6).toFixed(2)} s`:e>=1e3?`${(e/1e3).toFixed(0)} ms`:`${e} µs`}function Fh(e,t){if(!e)return[];const n=[],r=Lh(e.exposure_us);r&&n.push({key:"meta.exposure",value:r});const l=Ht(e.analogue_gain),o=Ht(e.digital_gain);if(l||o){const y=[l?`A ${l}`:"",o?`D ${o}`:""].filter(Boolean);n.push({key:"meta.gain",value:y.join(" · ")})}const a=Ht(e.fps);a&&n.push({key:"meta.fps",value:a});const i=Ht(e.sensor);i&&n.push({key:"meta.sensor",value:i});const u=Ht(e.color_mode);u&&n.push({key:"meta.colorMode",value:u});const f=Ht(e.resolution);f&&n.push({key:"meta.outputResolution",value:f});const v=Ht(e.modified);v&&n.push({key:"meta.fileTime",value:_l(v,t)});const h=e.size;return typeof h=="number"&&h>0&&n.push({key:"meta.fileSize",value:as(h)}),n}function cf(e){const t=n=>typeof n=="number"&&!Number.isNaN(n)?n:null;return e?{tSolveMs:t(e.t_solve_ms),tExtractMs:t(e.t_extract_ms),tPreprocessMs:t(e.t_preprocess_ms),tOpenDecodeMs:t(e.t_open_decode_ms),tBackendTotalMs:t(e.t_backend_total_ms),raDeg:t(e.ra_deg),decDeg:t(e.dec_deg),matches:t(e.matches),rmseArcsec:t(e.rmse_arcsec),prob:t(e.prob),status:typeof e.status=="string"?e.status:null}:{tSolveMs:null,tExtractMs:null,tPreprocessMs:null,tOpenDecodeMs:null,tBackendTotalMs:null,raDeg:null,decDeg:null,matches:null,rmseArcsec:null,prob:null,status:null}}function Xl(e){return e==null?"—":`${e.toFixed(4)}°`}function Oh(e){return e==null?"—":e>=0&&e<=1?`${(e*100).toFixed(1)}%`:String(e)}function Ih(e){if(e==null)return"—";if(typeof e=="number"&&!Number.isNaN(e)){const t=Math.abs(e);return t>0&&t<.001?e.toExponential(4):t>=0&&t<=1?`${(e*100).toFixed(4)}%`:String(e)}return String(e)}function Mn(e,t){const n=t==null?void 0:t.tetra,r=n?n.Prob??n.prob:void 0;let l=Oh(e);e!=null&&e>=0&&e<=1&&e>0&&e<1e-4&&(l=`${(e*100).toExponential(2)}%`),e===0&&r!==void 0&&r!==null&&(l="—");const o=r!=null?Ih(r):null;return{line:l,rawLine:o}}const ca=()=>({hint_ra_deg:45,hint_dec_deg:80,fov_estimate:11,fov_max_error:void 0,solve_timeout_ms:1500,solve_profile:"balanced",max_image_side:1600,large_scale_bg_subtract:!1,detail_level:"summary",centroid:{sigma:2.5,max_area:400,min_area:5,filtsize:25,binary_open:!0,max_axis_ratio:void 0}});function da(e){return e?{matches:e.matches,rmse_arcsec:e.rmse_arcsec,status:e.status,prob:e.prob,t_solve_ms:e.t_solve_ms}:{}}function Dh(e){var n,r;if(!e)return null;const t=e.solve_overlay;return(n=t==null?void 0:t.stars_matched)!=null&&n.length?t.stars_matched.length:(r=t==null?void 0:t.stars_all_centroids)!=null&&r.length?t.stars_all_centroids.length:typeof e.matches=="number"?e.matches:null}const fl=30,fa=6;function Wu(e){return/\.(jpe?g|png|webp|bmp|gif|fits?)$/i.test(e)}function dn(e){return/\.(mp4|mov|webm|mkv|avi)$/i.test(e)}function Uh(){var xi,wi,Si,ki,Ni,ji,_i,Ci;const{t:e,locale:t,setLocale:n}=uf(),[r,l]=w.useState("lab_image"),[o,a]=w.useState([]),[i,u]=w.useState(null),[f,v]=w.useState(ca),[h,y]=w.useState([]),[k,j]=w.useState([]),[_,$]=w.useState(new Set),[p,d]=w.useState(!1),[m,g]=w.useState(null),[N,M]=w.useState(null),[E,z]=w.useState(null),[U,L]=w.useState(""),[le,nt]=w.useState(1),[me,nn]=w.useState(null),[Or,rn]=w.useState(null),[Ut,b]=w.useState(""),[T,R]=w.useState({matched:!0,pattern:!0,all:!0}),[H,Z]=w.useState([]),[_e,Ke]=w.useState(null),[rt,Ce]=w.useState(1),[lt,ti]=w.useState(!1),[ln,mo]=w.useState(1),[ni,df]=w.useState({w:0,h:0}),[on,ff]=w.useState({w:0,h:0}),[ri,pf]=w.useState({w:0,h:0}),[q,Ir]=w.useState("file"),[Dr,li]=w.useState(null),[Hn,ho]=w.useState(null),[vo,oi]=w.useState(!1),[Ur,ai]=w.useState(!1),[si,mf]=w.useState(!0),[ot,yo]=w.useState(!1),[hf,go]=w.useState(null),[ii,xo]=w.useState(null),[wo,$r]=w.useState(null),[So,ui]=w.useState(!1),[vf,ko]=w.useState({}),[ci,No]=w.useState(!1),[jo,at]=w.useState(null),[yf,An]=w.useState(null),_o=w.useRef(null),Bn=w.useRef(null),di=w.useRef(null),Hr=w.useRef(null),Ar=w.useRef(null),Br=w.useRef(null),Co=w.useRef(!1),Eo=w.useRef(!1),an=w.useRef(null),[Vr,gf]=w.useState(null),[Ge,fi]=w.useState(null),pi=w.useMemo(()=>{const c=(Ge==null?void 0:Ge.star_analysis_target_fps)??.6666666666666666,x=Math.min(Math.max(c,.2),5);return Math.round(1e3/x)},[Ge]),$t=w.useCallback(async()=>{const[c,x,C]=await Promise.all([fh(),sa("official"),sa("user")]);a(c.files),y(x.presets),j(C.presets)},[]),bo=w.useCallback(()=>{wh().then(c=>Z(c.files)).catch(()=>Z([]))},[]);w.useEffect(()=>{_h().then(c=>fi(c)).catch(()=>fi(null))},[]),w.useEffect(()=>{$t().catch(c=>g(String(c)))},[$t]),w.useEffect(()=>{bo()},[bo]),w.useEffect(()=>{r==="history"&&ua(U,le,fl).then(nn).catch(c=>g(String(c)))},[r,U,le]),w.useEffect(()=>{if(!i){$r(null);return}let c=!1;return ui(!0),(async()=>{try{const x=await kh(i);if(c)return;let C={...x};try{C={...await Hu(i),...x}}catch{}$r(C)}catch{try{const x=await Hu(i);c||$r(x)}catch{c||$r(null)}}finally{c||ui(!1)}})(),()=>{c=!0}},[i]),w.useEffect(()=>{M(null),z(null),ko({}),No(!1),at(null),An(null),Ir("file"),ho(null)},[i]);const st=w.useMemo(()=>{const c=N==null?void 0:N.result;if(!c)return null;const x=c.solve_overlay||null;if(!x)return null;const C=c.overlay_ext||null;return{...x,overlay_ext:C||void 0}},[N]),gt=w.useMemo(()=>(N==null?void 0:N.result)??null,[N]),mi=w.useMemo(()=>Dh(gt),[gt]),Po=w.useMemo(()=>r==="lab_image"?ni:r==="lab_video"?q==="file"?on:ri:{w:0,h:0},[r,q,ni,on,ri]),Wr=i?Nh(i):"";w.useEffect(()=>{if(r!=="lab_image")return;const c=_o.current,x=an.current;if(!c||!x||!st||!i)return;const C=()=>Bu(x,c,st,T);c.complete?C():c.onload=C},[st,i,N,T,r]),w.useEffect(()=>{if(r!=="lab_video"||q!=="file")return;const c=Bn.current,x=an.current;if(!c||!x||!st||!i)return;const C=()=>Mh(x,c,st,T);return c.addEventListener("loadeddata",C),c.addEventListener("seeked",C),c.readyState>=2&&C(),()=>{c.removeEventListener("loadeddata",C),c.removeEventListener("seeked",C)}},[st,T,r,q,i,N]),w.useEffect(()=>{if(r!=="lab_video"||q!=="camera")return;const c=di.current,x=an.current;if(!c||!x||!st)return;const C=()=>Bu(x,c,st,T);c.complete?C():c.onload=C},[st,T,r,q,N,Dr]),w.useEffect(()=>{if(r!=="lab_video"||q!=="camera")return;let c=!1;const x=async()=>{if(!(c||ot))try{const Q=Hr.current?`?since_frame_id=${encodeURIComponent(Hr.current)}`:"",xe=await fetch(`/api/camera/preview${Q}`,{cache:"no-store"});if(xe.status===304||!xe.ok)return;const un=xe.headers.get("X-Frame-Id");un!=null&&(Hr.current=un);const To=await xe.blob(),Ro=URL.createObjectURL(To);li(Wn=>(Wn&&URL.revokeObjectURL(Wn),Ro))}catch{}};x();const C=window.setInterval(()=>void x(),180);return()=>{c=!0,clearInterval(C),li(Q=>(Q&&URL.revokeObjectURL(Q),null)),Hr.current=null}},[r,q,ot]),w.useEffect(()=>{const c=_o.current;if(!c)return;const x=()=>df({w:c.naturalWidth||0,h:c.naturalHeight||0});return x(),c.addEventListener("load",x),()=>c.removeEventListener("load",x)},[i,Wr]),w.useEffect(()=>{const c=Bn.current;if(!c)return;const x=()=>ff({w:c.videoWidth||0,h:c.videoHeight||0});return c.addEventListener("loadedmetadata",x),c.addEventListener("loadeddata",x),x(),()=>{c.removeEventListener("loadedmetadata",x),c.removeEventListener("loadeddata",x)}},[i,Wr,r]);const xf=c=>{v({...ca(),...c,centroid:{...ca().centroid,...c.centroid}})},wf=async()=>{if(!i){g(e("err.selectFile"));return}g(null),d(!0);const c=performance.now();try{const x=await vh(i,f);M(x),z(null),An("file"),at(performance.now()-c)}catch(x){g(String(x)),at(null)}finally{d(!1)}},Sf=async()=>{if(!i){g(e("err.selectFile"));return}const c=[];for(const C of _){const xe=[...h,...k].find(un=>un.id===C);xe&&c.push({label:xe.name,params:structuredClone(xe.params)})}if(c.length===0){g(e("err.selectPresets"));return}g(null),d(!0);const x=performance.now();try{const C=await yh(i,c);z({results:C.results}),M(null),ko({}),An("file"),at(performance.now()-x)}catch(C){g(String(C)),at(null)}finally{d(!1)}},Mo=async()=>{if(Co.current)return;g(null),Co.current=!0;const c=performance.now();try{const x=await Ch({source:"camera",overlay_topn_count:3,enable_polar_guide:!0,solve_timeout_ms:Math.min(((Ge==null?void 0:Ge.solver_timeout_ms)??1500)*.6,1200),...f});M(x),z(null),An("camera"),Ir("camera");const C=x.result,Q=typeof(C==null?void 0:C.status)=="string"?String(C.status):"";si&&Q==="MATCH_FOUND"&&(yo(!0),go(x.frame_id!=null?String(x.frame_id):null),xo(Dr),Kr()),at(performance.now()-c)}catch(x){g(String(x)),at(null)}finally{Co.current=!1}},zo=async()=>{if(Eo.current||!i)return;const c=Bn.current;if(!c||c.videoWidth<2||c.videoHeight<2||Hn)return;g(null),Eo.current=!0;const x=performance.now();try{const C=document.createElement("canvas");C.width=c.videoWidth,C.height=c.videoHeight;const Q=C.getContext("2d");if(!Q)throw new Error("无法创建画布上下文 / Cannot create canvas context");Q.drawImage(c,0,0,C.width,C.height);const xe=await new Promise((To,Ro)=>{C.toBlob(Wn=>Wn?To(Wn):Ro(new Error("帧编码失败 / Frame encode failed")),"image/jpeg",.92)}),un=await Eh(xe,{...f,solve_timeout_ms:Math.min(((Ge==null?void 0:Ge.solver_timeout_ms)??1500)*.6,1200),overlay_topn_count:3,enable_polar_guide:!0});M(un),z(null),An("file"),at(performance.now()-x)}catch(C){g(String(C)),at(null)}finally{Eo.current=!1}},kf=()=>{Ur||!i||(ai(!0),zo(),Br.current=window.setInterval(()=>{zo()},pi))},hi=w.useMemo(()=>r!=="lab_video"||q!=="file"||!i||Hn?!1:on.w>1&&on.h>1,[r,q,i,Hn,on.w,on.h]),Qr=()=>{ai(!1),Br.current!=null&&(window.clearInterval(Br.current),Br.current=null)},Nf=()=>{vo||ot||(oi(!0),Mo(),Ar.current=window.setInterval(()=>{Mo()},pi))},Kr=()=>{oi(!1),Ar.current!=null&&(window.clearInterval(Ar.current),Ar.current=null)},jf=()=>{yo(!1),go(null),xo(null)},_f=c=>{$(x=>{const C=new Set(x);return C.has(c)?C.delete(c):C.add(c),C})},vi=async c=>{if(!window.confirm(e("delete.uploadFirst",{name:c})))return;let x=0;try{x=(await jh(c)).count}catch{x=0}if(x>0){if(!window.confirm(e("delete.uploadCascade",{n:x})))return}else if(!window.confirm(e("delete.uploadSecond")))return;d(!0),g(null);try{await ph(c,{deleteExperiments:x>0}),await $t(),i===c&&u(null)}catch(C){g(String(C))}finally{d(!1)}},Cf=async c=>{if(window.confirm(e("delete.experimentFirst"))&&window.confirm(e("delete.experimentSecond"))){d(!0),g(null);try{await xh(c),Or===c&&rn(null);const x=await ua(U,le,fl);nn(x)}catch(x){g(String(x))}finally{d(!1)}}},Gr=c=>mo(Math.min(4,Math.max(.5,c))),yi=Math.max(1,Math.ceil(((me==null?void 0:me.total)??0)/fl)),sn=w.useMemo(()=>r==="lab_image"?H.filter(c=>c.type==="image"||Wu(c.name)):r==="lab_video"?H.filter(c=>c.type==="video"||dn(c.name)):H,[H,r]),Vn=Math.max(1,Math.ceil(sn.length/fa)),Ef=w.useMemo(()=>{const c=(rt-1)*fa;return sn.slice(c,c+fa)},[sn,rt]);w.useEffect(()=>{Ce(1)},[r]),w.useEffect(()=>{Ce(c=>Math.min(c,Vn))},[Vn]),w.useEffect(()=>{_e&&!sn.some(c=>c.name===_e)&&Ke(null)},[sn,_e]);const gi=w.useMemo(()=>Fh(wo,t),[wo,t]),bf=w.useMemo(()=>r==="lab_image"?o.filter(c=>Wu(c.filename)):r==="lab_video"?o.filter(c=>dn(c.filename)):o,[o,r]),I=w.useMemo(()=>cf(gt),[gt]);return w.useEffect(()=>{No(!1)},[N]),w.useEffect(()=>{if(r!=="lab_video")return;let c;const x=()=>{Ph().then(gf).catch(()=>{})};return x(),c=setInterval(x,1500),()=>{c&&clearInterval(c)}},[r]),w.useEffect(()=>{(r!=="lab_video"||q!=="camera")&&(Kr(),yo(!1),go(null),xo(null)),(r!=="lab_video"||q!=="file")&&Qr()},[r,q]),w.useEffect(()=>{i||Qr()},[i]),w.useEffect(()=>()=>{Kr(),Qr()},[]),s.jsxs("div",{className:"flex min-h-full flex-col bg-surface text-on-surface",children:[s.jsxs("header",{className:"flex h-12 shrink-0 items-center justify-between border-b border-outline-variant/20 px-4",children:[s.jsxs("div",{className:"flex items-center gap-6",children:[s.jsx("span",{className:"font-headline text-sm font-bold tracking-wide text-on-surface",children:e("app.title")}),s.jsxs("nav",{className:"flex flex-wrap gap-3 text-xs",children:[s.jsx("button",{type:"button",className:r==="lab_image"?"text-primary":"text-on-surface-variant",onClick:()=>l("lab_image"),children:e("nav.labImage")}),s.jsx("button",{type:"button",className:r==="lab_video"?"text-primary":"text-on-surface-variant",onClick:()=>l("lab_video"),children:e("nav.labVideo")}),s.jsx("button",{type:"button",className:r==="pool"?"text-primary":"text-on-surface-variant",onClick:()=>l("pool"),children:e("nav.pool")}),s.jsx("button",{type:"button",className:r==="history"?"text-primary":"text-on-surface-variant",onClick:()=>l("history"),children:e("nav.history")})]})]}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsxs("div",{className:"mr-2 flex gap-1 text-[10px]",children:[s.jsx("button",{type:"button",className:`rounded px-2 py-0.5 ${t==="zh"?"bg-primary-container text-on-primary-container":"text-on-surface-variant"}`,onClick:()=>n("zh"),children:e("lang.zh")}),s.jsx("button",{type:"button",className:`rounded px-2 py-0.5 ${t==="en"?"bg-primary-container text-on-primary-container":"text-on-surface-variant"}`,onClick:()=>n("en"),children:e("lang.en")})]}),s.jsxs("a",{className:"flex items-center gap-1 rounded border border-outline-variant/30 px-2 py-1 text-xs text-on-surface-variant hover:bg-surface-container",href:"/debug",children:[s.jsx(sh,{className:"h-3.5 w-3.5"})," ",e("nav.cameraDebug")]}),s.jsxs("a",{className:"flex items-center gap-1 rounded border border-outline-variant/30 px-2 py-1 text-xs text-on-surface-variant hover:bg-surface-container",href:"/",children:[s.jsx(uh,{className:"h-3.5 w-3.5"})," ",e("nav.home")]})]})]}),s.jsxs("div",{className:"flex min-h-0 flex-1",children:[s.jsxs("aside",{className:"w-64 shrink-0 border-r border-outline-variant/15 bg-surface-container-lowest p-3 text-xs",children:[s.jsx("div",{className:"mb-3 font-semibold text-on-surface-variant",children:e("sidebar.assets")}),s.jsxs("label",{className:"mb-3 flex cursor-pointer items-center gap-2 rounded bg-primary-container/30 px-2 py-2 text-on-primary-container",children:[s.jsx(dh,{className:"h-4 w-4"}),s.jsx("span",{children:e("sidebar.upload")}),s.jsx("input",{type:"file",accept:"image/*,video/*",className:"hidden",onChange:async c=>{var C;const x=(C=c.target.files)==null?void 0:C[0];if(x){d(!0),g(null);try{const Q=await mh(x);await $t(),u(Q.filename)}catch(Q){g(String(Q))}finally{d(!1),c.target.value=""}}}})]}),s.jsxs("button",{type:"button",className:"mb-2 flex w-full items-center gap-1 text-left text-on-surface-variant hover:text-on-surface",onClick:()=>{$t().catch(c=>g(String(c))),Ce(1),bo()},children:[s.jsx(ch,{className:"h-3 w-3"})," ",e("sidebar.refresh")]}),s.jsx("div",{className:"max-h-36 overflow-y-auto border-t border-outline-variant/10 pt-2",children:bf.map(c=>s.jsxs("div",{className:`mb-1 flex items-center gap-0.5 rounded px-1 ${i===c.filename?"bg-surface-container":""}`,children:[s.jsxs("button",{type:"button",className:`min-w-0 flex-1 truncate rounded px-1 py-1 text-left ${i===c.filename?"text-primary":""}`,title:c.filename,onClick:()=>{u(c.filename),l(dn(c.filename)?"lab_video":"lab_image")},children:[s.jsx("span",{className:"block truncate",children:c.filename}),s.jsx("span",{className:"block text-[9px] text-on-surface-variant/90",children:dn(c.filename)?e("sidebar.assetTypeVideo"):e("sidebar.assetTypeImage")})]}),s.jsx("button",{type:"button",className:"shrink-0 rounded p-1 text-on-surface-variant hover:bg-surface-container-high hover:text-error",title:e("pool.delete"),"aria-label":e("pool.delete"),onClick:x=>{x.stopPropagation(),vi(c.filename)},children:s.jsx(Du,{className:"h-3.5 w-3.5"})})]},c.filename))}),s.jsxs("div",{className:"mt-3 border-t border-outline-variant/10 pt-3",children:[s.jsxs("div",{className:"mb-2 flex items-start justify-between gap-2",children:[s.jsx("div",{className:"min-w-0 font-semibold leading-tight text-on-surface-variant",children:e("sidebar.debugCaptures")}),s.jsx("button",{type:"button",className:"shrink-0 rounded bg-primary px-2 py-1 text-[10px] font-medium text-on-primary disabled:opacity-40",disabled:!_e,title:_e??void 0,onClick:async()=>{if(_e){d(!0);try{const c=await hh(_e);await $t(),u(c.filename),l(dn(c.filename)?"lab_video":"lab_image")}catch(c){g(String(c))}finally{d(!1)}}},children:e("sidebar.importToPool")})]}),sn.length===0?s.jsx("p",{className:"text-[10px] text-on-surface-variant",children:e("sidebar.debugEmpty")}):s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"max-h-[min(22rem,55vh)] space-y-1.5 overflow-y-auto pr-0.5",children:Ef.map(c=>s.jsxs("button",{type:"button",className:`flex w-full items-center gap-2 rounded-md border px-2 py-1.5 text-left transition-colors ${_e===c.name?"border-primary bg-primary-container/20":"border-outline-variant/25 hover:bg-surface-container"}`,onClick:()=>Ke(c.name),children:[c.type==="image"?s.jsx("img",{src:Sh(c.name),alt:"",className:"h-11 w-11 shrink-0 rounded object-cover"}):s.jsx("div",{className:"flex h-11 w-11 shrink-0 items-center justify-center rounded bg-surface-container-high text-[9px] text-on-surface-variant",children:"video"}),s.jsxs("div",{className:"min-w-0 flex-1",children:[s.jsx("div",{className:"truncate font-mono text-[10px] text-on-surface",title:c.name,children:c.name}),s.jsxs("div",{className:"text-[9px] text-on-surface-variant",children:[c.type==="video"||dn(c.name)?e("sidebar.assetTypeVideo"):e("sidebar.assetTypeImage")," ","· ",_l(c.modified,t)," · ",as(c.size)]})]})]},c.name))}),s.jsxs("div",{className:"mt-2 flex items-center justify-between gap-1 text-[10px] text-on-surface-variant",children:[s.jsx("button",{type:"button",className:"rounded border border-outline-variant/30 px-2 py-0.5 disabled:opacity-40",disabled:rt<=1,onClick:()=>Ce(c=>Math.max(1,c-1)),children:e("history.prev")}),s.jsx("span",{className:"tabular-nums",children:e("sidebar.debugPage",{cur:rt,total:Vn})}),s.jsx("button",{type:"button",className:"rounded border border-outline-variant/30 px-2 py-0.5 disabled:opacity-40",disabled:rt>=Vn,onClick:()=>Ce(c=>Math.min(Vn,c+1)),children:e("history.next")})]})]})]})]}),(r==="lab_image"||r==="lab_video")&&s.jsxs("div",{className:"flex min-h-0 min-w-0 flex-1",children:[s.jsxs("main",{className:"min-h-0 min-w-0 flex-1 overflow-y-auto p-4",children:[m&&s.jsx("div",{className:"mb-2 rounded border border-error/40 bg-error-container/20 px-3 py-2 text-xs text-error",children:m}),r==="lab_video"&&s.jsxs("div",{className:"mb-3 max-w-5xl rounded-lg border border-outline-variant/25 bg-surface-container-low/80 p-3 text-[11px] leading-relaxed text-on-surface",children:[s.jsx("p",{className:"text-[10px] text-on-surface-variant",children:e("lab.videoLiveIntro")}),s.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[s.jsx("button",{type:"button",className:`rounded px-3 py-1.5 text-[11px] font-medium ${q==="file"?"bg-primary text-on-primary-container":"border border-outline-variant/40 bg-surface-container text-on-surface"}`,onClick:()=>Ir("file"),children:e("lab.previewModeFile")}),s.jsx("button",{type:"button",className:`rounded px-3 py-1.5 text-[11px] font-medium ${q==="camera"?"bg-primary text-on-primary-container":"border border-outline-variant/40 bg-surface-container text-on-surface"}`,onClick:()=>Ir("camera"),children:e("lab.previewModeCamera")})]})]}),s.jsxs("div",{className:"relative aspect-video w-full max-w-5xl overflow-hidden rounded-lg border border-outline-variant/20 bg-surface-container-lowest",children:[r==="lab_video"&&q==="camera"?s.jsx("div",{className:"relative flex h-full min-h-[220px] flex-col items-center justify-center gap-3 bg-black p-2",children:s.jsxs("div",{className:"relative inline-block max-h-[70vh] max-w-full",children:[ot&&ii||Dr?s.jsx("img",{ref:di,src:ot&&ii||Dr||"",alt:"",className:"max-h-[70vh] w-full min-h-[120px] object-contain",onLoad:c=>pf({w:c.currentTarget.naturalWidth,h:c.currentTarget.naturalHeight})}):s.jsxs("div",{className:"flex min-h-[200px] w-full min-w-[280px] flex-col items-center justify-center gap-2 text-[11px] text-on-surface-variant",children:[s.jsx(aa,{className:"h-8 w-8 animate-spin text-primary"}),s.jsx("span",{children:e("lab.cameraPreviewLoading")})]}),s.jsx("canvas",{ref:an,className:"pointer-events-none absolute left-0 top-0"})]})}):i?s.jsx("div",{className:"relative h-full min-h-[200px] overflow-auto",children:r==="lab_video"?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"absolute left-2 top-2 z-20 flex flex-wrap gap-1",children:[s.jsxs("button",{type:"button",title:e("lab.grid"),className:`rounded border px-2 py-1 text-[10px] ${lt?"border-primary bg-primary/20":"border-white/30 bg-black/40"} text-white`,onClick:()=>ti(c=>!c),children:[s.jsx(Ou,{className:"mr-1 inline h-3 w-3"}),e("lab.grid")]}),s.jsx("button",{type:"button",title:e("lab.zoomOut"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>Gr(ln-.25),children:s.jsx($u,{className:"inline h-3 w-3"})}),s.jsx("button",{type:"button",title:e("lab.zoomIn"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>Gr(ln+.25),children:s.jsx(Uu,{className:"inline h-3 w-3"})}),s.jsx("button",{type:"button",title:e("lab.zoomReset"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>mo(1),children:s.jsx(Iu,{className:"inline h-3 w-3"})})]}),s.jsxs("div",{className:"flex min-h-[200px] flex-col items-center justify-center gap-2 bg-black py-2",children:[s.jsx("div",{className:"inline-block origin-top-left transition-transform",style:{transform:`scale(${ln})`},children:s.jsxs("div",{className:"relative inline-block",children:[lt&&s.jsx("div",{className:"pointer-events-none absolute inset-0 z-[1]",style:{backgroundImage:["linear-gradient(to right, rgba(255,255,255,0.12) 1px, transparent 1px)","linear-gradient(to bottom, rgba(255,255,255,0.12) 1px, transparent 1px)"].join(","),backgroundSize:"48px 48px"}}),s.jsx("video",{ref:Bn,src:Wr,loop:!0,playsInline:!0,autoPlay:!0,muted:!0,preload:"metadata",className:"max-h-[70vh] w-full max-w-full object-contain",onError:()=>ho(e("lab.videoPreviewFailed")),onLoadedData:()=>{ho(null);const c=Bn.current;c&&c.play().catch(()=>{})}}),s.jsx("canvas",{ref:an,className:"pointer-events-none absolute left-0 top-0"})]})}),Hn&&s.jsx("div",{className:"rounded border border-error/40 bg-error-container/20 px-3 py-1.5 text-[11px] text-error",children:Hn})]})]}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"absolute left-2 top-2 z-20 flex flex-wrap gap-1",children:[s.jsxs("button",{type:"button",title:e("lab.grid"),className:`rounded border px-2 py-1 text-[10px] ${lt?"border-primary bg-primary/20":"border-white/30 bg-black/40"} text-white`,onClick:()=>ti(c=>!c),children:[s.jsx(Ou,{className:"mr-1 inline h-3 w-3"}),e("lab.grid")]}),s.jsx("button",{type:"button",title:e("lab.zoomOut"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>Gr(ln-.25),children:s.jsx($u,{className:"inline h-3 w-3"})}),s.jsx("button",{type:"button",title:e("lab.zoomIn"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>Gr(ln+.25),children:s.jsx(Uu,{className:"inline h-3 w-3"})}),s.jsx("button",{type:"button",title:e("lab.zoomReset"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>mo(1),children:s.jsx(Iu,{className:"inline h-3 w-3"})})]}),s.jsx("div",{className:"inline-block origin-top-left transition-transform",style:{transform:`scale(${ln})`},children:s.jsxs("div",{className:"relative inline-block",children:[lt&&s.jsx("div",{className:"pointer-events-none absolute inset-0 z-[1]",style:{backgroundImage:["linear-gradient(to right, rgba(255,255,255,0.12) 1px, transparent 1px)","linear-gradient(to bottom, rgba(255,255,255,0.12) 1px, transparent 1px)"].join(","),backgroundSize:"48px 48px"}}),s.jsx("img",{ref:_o,src:Wr,alt:"preview",className:"max-h-[70vh] w-full object-contain"}),s.jsx("canvas",{ref:an,className:"pointer-events-none absolute left-0 top-0"})]})})]})}):s.jsx("div",{className:"flex h-full items-center justify-center px-4 text-center text-on-surface-variant",children:e(r==="lab_video"?"lab.selectOrUploadVideo":"lab.selectOrUpload")}),p&&s.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-black/40",children:s.jsx(aa,{className:"h-8 w-8 animate-spin text-primary"})})]}),(i&&r==="lab_image"||r==="lab_video"&&(q==="file"&&i||q==="camera"))&&s.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-3 rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90 px-3 py-2 text-xs text-on-surface",children:[s.jsx("span",{className:"shrink-0 font-medium text-on-surface-variant",children:e("lab.layers")}),s.jsx("div",{className:"flex flex-wrap gap-x-4 gap-y-1",children:["matched","pattern","all"].map(c=>s.jsxs("label",{className:"flex cursor-pointer items-center gap-1",children:[s.jsx("input",{type:"checkbox",className:"accent-primary",checked:T[c],onChange:x=>R(C=>({...C,[c]:x.target.checked}))}),s.jsx("span",{children:e(c==="matched"?"lab.layer.matched":c==="pattern"?"lab.layer.pattern":"lab.layer.all")})]},c))})]}),(i||r==="lab_video"&&q==="camera")&&s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"mt-2 grid gap-2 sm:grid-cols-2",children:[s.jsxs("details",{open:!0,className:"rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-2 px-3 py-2 text-xs font-semibold text-on-surface [&::-webkit-details-marker]:hidden",children:[e("lab.solveSection"),s.jsx(er,{className:"h-4 w-4 shrink-0 text-on-surface-variant"})]}),s.jsx("div",{className:"border-t border-outline-variant/15 px-3 py-2 text-[10px]",children:gt?s.jsxs("div",{className:"space-y-1 text-on-surface",children:[I.tSolveMs!=null&&s.jsxs("div",{className:"space-y-0.5",children:[s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.solveComputeMs")}),s.jsxs("span",{className:"font-mono tabular-nums",children:[I.tSolveMs.toFixed(0)," ms"]})]}),s.jsx("p",{className:"text-[8px] leading-snug text-on-surface-variant/90",children:e("lab.metric.solveComputeHelp")})]}),jo!=null&&s.jsxs("div",{className:"space-y-0.5 border-t border-outline-variant/10 pt-1",children:[s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.solveRoundTripMs")}),s.jsxs("span",{className:"font-mono tabular-nums",children:[jo.toFixed(0)," ms"]})]}),s.jsx("p",{className:"text-[8px] leading-snug text-on-surface-variant/90",children:e("lab.metric.solveRoundTripHelp")})]}),(I.tBackendTotalMs!=null||I.tOpenDecodeMs!=null||I.tPreprocessMs!=null||I.tExtractMs!=null||I.tSolveMs!=null)&&s.jsxs("div",{className:"space-y-0.5 border-t border-outline-variant/10 pt-1",children:[s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.backendTotalMs")}),s.jsx("span",{className:"font-mono tabular-nums",children:I.tBackendTotalMs!=null?`${I.tBackendTotalMs.toFixed(0)} ms`:e("common.placeholder")})]}),s.jsxs("div",{className:"flex flex-wrap gap-x-2 gap-y-0.5 text-[8px] text-on-surface-variant/90",children:[s.jsxs("span",{children:[e("lab.metric.openDecodeMs"),":"," ",I.tOpenDecodeMs!=null?`${I.tOpenDecodeMs.toFixed(0)} ms`:e("common.placeholder")]}),s.jsxs("span",{children:[e("lab.metric.preprocessMs"),":"," ",I.tPreprocessMs!=null?`${I.tPreprocessMs.toFixed(0)} ms`:e("common.placeholder")]}),s.jsxs("span",{children:[e("lab.metric.extractMs"),":"," ",I.tExtractMs!=null?`${I.tExtractMs.toFixed(0)} ms`:e("common.placeholder")]}),s.jsxs("span",{children:[e("lab.metric.solveOnlyMs"),":"," ",I.tSolveMs!=null?`${I.tSolveMs.toFixed(0)} ms`:e("common.placeholder")]})]})]}),(I.raDeg!=null||I.decDeg!=null)&&s.jsxs("div",{className:"leading-tight",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.radec")}),s.jsxs("div",{className:"mt-0.5 font-mono text-[9px]",children:["α ",Xl(I.raDeg)," · δ"," ",Xl(I.decDeg)]})]}),s.jsxs("div",{className:"flex flex-wrap gap-x-2 gap-y-0.5 text-[9px]",children:[I.matches!=null&&s.jsxs("span",{children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.matches")})," ",s.jsx("span",{className:"font-mono",children:I.matches})]}),I.rmseArcsec!=null&&s.jsxs("span",{children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.rmse")})," ",s.jsxs("span",{className:"font-mono",children:[I.rmseArcsec.toFixed(2),"″"]})]}),I.prob!=null&&s.jsxs("span",{className:"inline-flex max-w-full flex-col gap-0.5",children:[s.jsxs("span",{children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.prob")})," ",s.jsx("span",{className:"font-mono",children:Mn(I.prob,gt??void 0).line})]}),s.jsx("span",{className:"text-[8px] leading-snug text-on-surface-variant/90",children:e("lab.metric.probHelp")}),Mn(I.prob,gt??void 0).rawLine&&s.jsxs(s.Fragment,{children:[s.jsxs("span",{className:"text-[8px] text-on-surface-variant",children:[e("lab.metric.probRaw"),":"," ",Mn(I.prob,gt??void 0).rawLine]}),s.jsx("span",{className:"text-[8px] leading-snug text-on-surface-variant/90",children:e("lab.metric.probRawHelp")})]})]})]}),I.status&&s.jsxs("div",{className:"border-t border-outline-variant/15 pt-1 text-[9px]",children:[s.jsxs("span",{className:"text-on-surface-variant",children:[e("lab.metric.status")," "]}),s.jsx("span",{className:"font-mono text-secondary",children:I.status})]})]}):s.jsx("p",{className:"text-on-surface-variant",children:e("common.placeholder")})})]}),s.jsxs("details",{open:!0,className:"rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-2 px-3 py-2 text-xs font-semibold text-on-surface [&::-webkit-details-marker]:hidden",children:[e("lab.imageSection"),s.jsx(er,{className:"h-4 w-4 shrink-0 text-on-surface-variant"})]}),s.jsxs("div",{className:"space-y-0.5 border-t border-outline-variant/15 px-3 py-2 text-[10px]",children:[s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.resolution")}),s.jsx("span",{className:"font-mono tabular-nums",children:Po.w>0?`${Po.w}×${Po.h}`:e("common.placeholder")})]}),s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.starsDetected")}),s.jsx("span",{className:"font-mono tabular-nums",children:mi??e("common.placeholder")})]}),s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.fwhm")}),s.jsx("span",{children:e("common.placeholder")})]})]})]})]}),i&&s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"mt-2 flex flex-wrap gap-4 text-xs text-on-surface-variant",children:[s.jsxs("span",{children:[e("lab.file"),":"," ",s.jsx("span",{className:"font-mono text-on-surface",children:i})]}),((xi=o.find(c=>c.filename===i))==null?void 0:xi.source)&&s.jsxs("span",{className:"rounded bg-surface-container-high px-2 py-0.5",children:[e("lab.source"),":"," ",(wi=o.find(c=>c.filename===i))==null?void 0:wi.source]})]}),s.jsxs("details",{open:!0,className:"mt-2 rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90 text-xs shadow-sm",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center gap-2 px-3 py-2 font-semibold text-on-surface [&::-webkit-details-marker]:hidden",children:[e("lab.meta.title"),So&&s.jsx(aa,{className:"h-3.5 w-3.5 animate-spin"}),s.jsx(er,{className:"ml-auto h-4 w-4 shrink-0 text-on-surface-variant"})]}),s.jsx("div",{className:"border-t border-outline-variant/15 p-3 pt-2",children:gi.length>0?s.jsx("dl",{className:"grid grid-cols-2 gap-x-4 gap-y-2 sm:grid-cols-3",children:gi.map(c=>s.jsxs("div",{children:[s.jsx("dt",{className:"text-[10px] text-on-surface-variant",children:e(c.key)}),s.jsx("dd",{className:"text-[11px] font-medium text-on-surface",children:c.value})]},`${c.key}-${c.value}`))}):wo&&!So?s.jsx("p",{className:"text-[10px] leading-relaxed text-on-surface-variant",children:e("lab.meta.partial")}):So?null:s.jsx("p",{className:"text-[10px] text-on-surface-variant",children:e("lab.meta.noSidecar")})})]})]})]}),(i||r==="lab_video"&&q==="camera")&&(N||E)&&s.jsxs("section",{className:"mt-3 max-h-[min(50vh,28rem)] rounded-lg border border-outline-variant/25 bg-surface-container-lowest/95",children:[s.jsxs("div",{className:"flex h-9 shrink-0 items-center justify-between border-b border-outline-variant/15 px-3 text-[10px] uppercase text-on-surface-variant",children:[s.jsx("span",{children:e("results.title")}),s.jsxs("div",{className:"flex gap-3",children:[(Si=E==null?void 0:E.results)!=null&&Si.length?s.jsx("button",{type:"button",className:"rounded bg-surface-container px-2 py-0.5 normal-case",onClick:async()=>{if(!(!i||!E)){for(const c of E.results){if(!c.success)continue;const x=c.result;await ia({input_name:i,preset_label:String(c.label),result_json:c,metrics:da(x??null),replay:{layers:T,params:f}})}g(null)}},children:e("results.saveBatchAll")}):null,N&&s.jsx("button",{type:"button",className:"rounded bg-surface-container px-2 py-0.5 normal-case",onClick:async()=>{if(!i&&yf!=="camera")return;const c=N.result;await ia({input_name:i??e("lab.cameraSnapshotName"),preset_label:"manual",result_json:N,metrics:da(c??null),replay:{layers:T,params:f}}),g(null)},children:e("results.saveCurrent")})]})]}),s.jsx("div",{className:"min-h-0 overflow-y-auto p-3",children:s.jsxs("div",{className:"flex gap-3 overflow-x-auto text-xs",children:[E==null?void 0:E.results.map((c,x)=>{const C=c.result,Q=vf[x]??!1;return s.jsxs("div",{className:"min-w-[15rem] max-w-sm shrink-0 rounded-lg border border-outline-variant/25 bg-surface-container p-3 shadow-sm",children:[s.jsx("div",{className:"border-b border-outline-variant/15 pb-2 font-semibold text-secondary",children:String(c.label)}),c.success?s.jsxs(s.Fragment,{children:[s.jsx(Qu,{result:C,t:e,roundTripMs:null}),s.jsx("button",{type:"button",className:"mt-2 text-[10px] text-primary hover:underline",onClick:()=>ko(xe=>({...xe,[x]:!Q})),children:e(Q?"results.hideRaw":"results.viewRaw")}),Q&&s.jsx("pre",{className:"mt-1 max-h-40 overflow-auto rounded bg-surface-container-highest p-2 text-[9px] text-on-surface-variant",children:JSON.stringify(c,null,2)})]}):s.jsx("div",{className:"mt-2 text-[10px] text-error",children:String(c.error)}),c.success&&i&&s.jsx("button",{type:"button",className:"mt-3 w-full rounded bg-surface-container-high py-1.5 text-[10px] font-medium",onClick:()=>ia({input_name:i,preset_label:String(c.label),result_json:c,metrics:da(C??null),replay:{layers:T,params:f}}).catch(xe=>g(String(xe))),children:e("results.saveRow")})]},x)}),N&&!E&&s.jsxs("div",{className:"min-w-[16rem] max-w-md shrink-0 rounded-lg border border-outline-variant/25 bg-surface-container p-3 shadow-sm",children:[s.jsx("div",{className:"border-b border-outline-variant/15 pb-2 text-[10px] font-semibold uppercase text-on-surface-variant",children:e("results.title")}),s.jsx(Qu,{result:N.result,t:e,roundTripMs:jo}),s.jsx("button",{type:"button",className:"mt-2 text-[10px] text-primary hover:underline",onClick:()=>No(c=>!c),children:e(ci?"results.hideRaw":"results.viewRaw")}),ci&&s.jsx("pre",{className:"mt-1 max-h-48 overflow-auto rounded bg-surface-container-highest p-2 text-[9px] text-on-surface-variant",children:JSON.stringify(N,null,2)})]})]})})]})]}),s.jsxs("aside",{className:"flex w-80 shrink-0 flex-col border-l border-outline-variant/15 bg-surface-container-low text-xs min-h-0",children:[r!=="lab_video"&&s.jsxs("div",{className:"shrink-0 space-y-2 border-b border-outline-variant/20 p-4 pb-3",children:[s.jsx("button",{type:"button",className:"w-full rounded bg-primary py-2.5 font-semibold text-on-primary-container",onClick:wf,disabled:p,children:e("btn.solveOne")}),s.jsx("button",{type:"button",className:"w-full rounded bg-secondary/80 py-2.5 font-semibold text-on-secondary",onClick:Sf,disabled:p,children:e("btn.solveBatch")})]}),r==="lab_video"&&s.jsx("div",{className:"shrink-0 space-y-2 border-b border-outline-variant/20 p-4 pb-3",children:q==="file"?s.jsxs(s.Fragment,{children:[s.jsx("button",{type:"button",className:"w-full rounded bg-primary py-2.5 font-semibold text-on-primary-container disabled:opacity-40",onClick:()=>kf(),disabled:p||!hi||Ur,children:e("lab.solveFileStart")}),s.jsx("button",{type:"button",className:"w-full rounded bg-error/80 py-2.5 font-semibold text-on-error disabled:opacity-40",onClick:()=>Qr(),disabled:!Ur,children:e("lab.solveFileStop")}),s.jsx("button",{type:"button",className:"w-full rounded bg-secondary/80 py-2.5 font-semibold text-on-secondary disabled:opacity-40",onClick:()=>void zo(),disabled:p||!hi||Ur,children:e("lab.solveCurrentFrame")})]}):s.jsxs(s.Fragment,{children:[s.jsx("button",{type:"button",className:"w-full rounded bg-primary py-2.5 font-semibold text-on-primary-container disabled:opacity-40",onClick:()=>Nf(),disabled:p||vo||ot,children:e("lab.solveCameraStart")}),s.jsx("button",{type:"button",className:"w-full rounded bg-error/80 py-2.5 font-semibold text-on-error disabled:opacity-40",onClick:()=>Kr(),disabled:!vo,children:e("lab.solveCameraStop")}),s.jsx("button",{type:"button",className:"w-full rounded bg-secondary/80 py-2.5 font-semibold text-on-secondary disabled:opacity-40",onClick:()=>void Mo(),disabled:p||ot,children:e("lab.solveCameraFrame")}),s.jsxs("label",{className:"flex items-center gap-2 rounded border border-outline-variant/25 px-2 py-1.5 text-[11px]",children:[s.jsx("input",{type:"checkbox",checked:si,onChange:c=>mf(c.target.checked)}),s.jsx("span",{children:"自动保持(解算成功后冻结) / Auto Hold"})]}),ot&&s.jsx("button",{type:"button",className:"w-full rounded bg-tertiary/80 py-2.5 font-semibold text-on-tertiary disabled:opacity-40",onClick:()=>jf(),children:"继续实时 / Resume Live"}),ot&&s.jsxs("div",{className:"text-[10px] text-on-surface-variant",children:["已冻结帧 / Frozen frame ",hf??"-"]})]})}),r==="lab_video"&&Vr&&s.jsxs("div",{className:"shrink-0 border-b border-outline-variant/20 px-4 py-2 text-[10px] text-on-surface-variant",children:[s.jsx("div",{className:"font-medium text-on-surface",children:e("lab.systemLoad")}),s.jsxs("div",{children:["CPU ",Vr.cpu_usage,"% · RAM ",Vr.memory_usage,"% ·"," ",Vr.temperature,"°C"]})]}),s.jsxs("div",{className:"min-h-0 flex-1 overflow-y-auto p-4",children:[s.jsxs("details",{open:!0,className:"rounded-lg border border-outline-variant/20 bg-surface-container-highest/30",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-2 px-3 py-2 font-semibold text-on-surface-variant [&::-webkit-details-marker]:hidden",children:[e("params.title"),s.jsx(er,{className:"h-4 w-4 shrink-0"})]}),s.jsxs("div",{className:"border-t border-outline-variant/15 p-3 pt-2",children:[s.jsx("p",{className:"mb-3 text-[10px] leading-relaxed text-on-surface-variant/90",children:e("params.blockSolveIntro")}),s.jsxs("div",{className:"space-y-2",children:[s.jsxs("label",{className:"block",children:[s.jsx("span",{className:"text-[10px] font-medium text-on-surface-variant",children:e("params.solveProfile")}),s.jsx("p",{className:"mb-1 mt-0.5 text-[9px] leading-snug text-on-surface-variant/85",children:e("params.solveProfileHelp")}),s.jsxs("select",{className:"w-full rounded bg-surface-container-highest px-2 py-1",value:f.solve_profile??"balanced",onChange:c=>v(x=>({...x,solve_profile:c.target.value})),children:[s.jsx("option",{value:"speed",children:e("params.solveProfileSpeed")}),s.jsx("option",{value:"balanced",children:e("params.solveProfileBalanced")}),s.jsx("option",{value:"robust",children:e("params.solveProfileRobust")})]})]}),s.jsx(Xe,{label:e("params.fov"),helpKey:"params.fovHelp",value:f.fov_estimate??"",onChange:c=>v(x=>({...x,fov_estimate:c}))}),s.jsx(Xe,{label:e("params.fovErr"),helpKey:"params.fovErrHelp",value:f.fov_max_error??"",onChange:c=>v(x=>({...x,fov_max_error:c}))}),s.jsx(Xe,{label:e("params.timeout"),helpKey:"params.timeoutHelp",value:f.solve_timeout_ms??"",onChange:c=>v(x=>({...x,solve_timeout_ms:c}))}),s.jsx(Xe,{label:e("params.ra"),helpKey:"params.raHelp",value:f.hint_ra_deg??"",onChange:c=>v(x=>({...x,hint_ra_deg:c}))}),s.jsx(Xe,{label:e("params.dec"),helpKey:"params.decHelp",value:f.hint_dec_deg??"",onChange:c=>v(x=>({...x,hint_dec_deg:c}))}),s.jsx(Xe,{label:e("params.maxSide"),helpKey:"params.maxSideHelp",value:f.max_image_side??"",onChange:c=>v(x=>({...x,max_image_side:c}))}),s.jsxs("label",{className:"mt-1.5 flex cursor-pointer items-center gap-2",children:[s.jsx("input",{type:"checkbox",className:"accent-primary",checked:f.detail_level==="full",onChange:c=>v(x=>({...x,detail_level:c.target.checked?"full":"summary"}))}),s.jsx("span",{className:"text-[10px] text-on-surface-variant",children:e("params.detailLevelFull")})]}),s.jsxs("label",{className:"mt-1.5 flex cursor-pointer items-start gap-2",children:[s.jsx("input",{type:"checkbox",className:"accent-primary mt-0.5",checked:!!f.large_scale_bg_subtract,onChange:c=>v(x=>({...x,large_scale_bg_subtract:c.target.checked}))}),s.jsxs("span",{children:[s.jsx("span",{className:"text-[10px] text-on-surface-variant",children:e("params.largeScaleBg")}),s.jsx("p",{className:"mt-0.5 text-[9px] leading-snug text-on-surface-variant/85",children:e("params.largeScaleBgHelp")})]})]})]})]})]}),s.jsxs("details",{open:!0,className:"mt-3 rounded-lg border border-outline-variant/20 bg-surface-container-highest/30",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-2 px-3 py-2 font-semibold text-on-surface-variant [&::-webkit-details-marker]:hidden",children:[e("params.centroid"),s.jsx(er,{className:"h-4 w-4 shrink-0"})]}),s.jsxs("div",{className:"border-t border-outline-variant/15 p-3 pt-2",children:[s.jsx("p",{className:"mb-3 text-[10px] leading-relaxed text-on-surface-variant/90",children:e("params.blockCentroidIntro")}),s.jsxs("div",{className:"space-y-2",children:[s.jsx(Xe,{label:e("params.sigma"),helpKey:"params.sigmaHelp",step:.1,value:((ki=f.centroid)==null?void 0:ki.sigma)??"",onChange:c=>v(x=>({...x,centroid:{...x.centroid,sigma:c}}))}),s.jsx(Xe,{label:e("params.maxArea"),helpKey:"params.maxAreaHelp",value:((Ni=f.centroid)==null?void 0:Ni.max_area)??"",onChange:c=>v(x=>({...x,centroid:{...x.centroid,max_area:c}}))}),s.jsx(Xe,{label:e("params.minArea"),helpKey:"params.minAreaHelp",value:((ji=f.centroid)==null?void 0:ji.min_area)??"",onChange:c=>v(x=>({...x,centroid:{...x.centroid,min_area:c}}))}),s.jsx(Xe,{label:e("params.filtsize"),helpKey:"params.filtsizeHelp",step:2,value:((_i=f.centroid)==null?void 0:_i.filtsize)??"",onChange:c=>v(x=>({...x,centroid:{...x.centroid,filtsize:c}}))})]})]})]}),s.jsxs("div",{className:"mt-4 rounded-md border border-outline-variant/20 bg-surface-container-highest/40 p-3",children:[s.jsx("div",{className:"mb-2 font-semibold text-on-surface-variant",children:e("sidebar.batchPresets")}),s.jsx("p",{className:"mb-2 text-[10px] leading-snug text-on-surface-variant",children:e("sidebar.batchHint")}),s.jsx("div",{className:"max-h-36 space-y-1.5 overflow-y-auto",children:[...h,...k].map(c=>s.jsxs("label",{className:"flex cursor-pointer items-center gap-2",children:[s.jsx("input",{type:"checkbox",checked:_.has(c.id),onChange:()=>_f(c.id)}),s.jsx("span",{className:"truncate",children:c.name})]},c.id))})]}),s.jsxs("div",{className:"mt-6 border-t border-outline-variant/20 pt-4",children:[s.jsx("div",{className:"mb-2 font-semibold",children:e("btn.applyPresets")}),s.jsx("div",{className:"max-h-24 space-y-1 overflow-y-auto",children:[...h,...k].map(c=>s.jsx("button",{type:"button",className:"block w-full truncate text-left text-primary hover:underline",onClick:()=>xf(c.params),children:c.name},c.id))}),s.jsxs("div",{className:"mt-3 flex gap-1",children:[s.jsx("input",{className:"flex-1 rounded bg-surface-container-highest px-2 py-1",placeholder:e("placeholder.newPreset"),value:Ut,onChange:c=>b(c.target.value)}),s.jsx("button",{type:"button",className:"rounded bg-surface-container-high px-2",onClick:async()=>{if(Ut.trim()){d(!0);try{await gh(Ut.trim(),f),b(""),await $t();const c=await sa("user");j(c.presets)}catch(c){g(String(c))}finally{d(!1)}}},children:e("btn.savePreset")})]})]})]})]})]}),r==="pool"&&s.jsxs("main",{className:"flex-1 overflow-auto p-4",children:[s.jsxs("h2",{className:"mb-4 flex items-center gap-2 text-lg font-semibold",children:[s.jsx(ah,{className:"h-5 w-5"})," ",e("pool.title")]}),s.jsxs("table",{className:"w-full text-left text-xs",children:[s.jsx("thead",{children:s.jsxs("tr",{className:"border-b border-outline-variant/30 text-on-surface-variant",children:[s.jsx("th",{className:"py-2",children:e("pool.col.name")}),s.jsx("th",{className:"py-2",children:e("pool.col.source")}),s.jsx("th",{className:"py-2",children:e("pool.col.size")}),s.jsx("th",{className:"py-2",children:e("pool.col.time")}),s.jsx("th",{className:"w-16 py-2 text-center",children:e("pool.delete")})]})}),s.jsx("tbody",{children:o.map(c=>s.jsxs("tr",{className:"border-b border-outline-variant/10",children:[s.jsx("td",{className:"py-2 font-mono",children:c.filename}),s.jsx("td",{className:"py-2",children:c.source??e("common.placeholder")}),s.jsx("td",{className:"py-2",children:as(c.size)}),s.jsx("td",{className:"py-2",children:_l(c.modified_at,t)}),s.jsx("td",{className:"py-2 text-center",children:s.jsx("button",{type:"button",className:"inline-flex rounded p-1 text-on-surface-variant hover:bg-error-container/30 hover:text-error",title:e("pool.delete"),"aria-label":e("pool.delete"),onClick:()=>void vi(c.filename),children:s.jsx(Du,{className:"h-3.5 w-3.5"})})})]},c.filename))})]})]}),r==="history"&&s.jsxs("main",{className:"flex-1 overflow-auto p-4",children:[s.jsx("p",{className:"mb-4 rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90 p-3 text-xs leading-relaxed text-on-surface-variant",children:e("history.intro")}),s.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-4",children:[s.jsxs("h2",{className:"flex items-center gap-2 text-lg font-semibold",children:[s.jsx(ih,{className:"h-5 w-5"})," ",e("history.title")]}),s.jsx("input",{className:"rounded bg-surface-container-highest px-2 py-1 text-xs",placeholder:e("history.search"),value:U,onChange:c=>L(c.target.value)}),s.jsx("button",{type:"button",className:"rounded bg-surface-container px-2 py-1 text-xs",onClick:()=>ua(U,1,fl).then(c=>{nt(1),nn(c)}),children:e("history.searchBtn")}),s.jsx("button",{type:"button",className:"rounded bg-primary-container/50 px-2 py-1 text-xs",onClick:()=>Au("json").then(c=>{const x=new Blob([c],{type:"application/json"}),C=document.createElement("a");C.href=URL.createObjectURL(x),C.download="experiments.json",C.click()}),children:e("history.exportJson")}),s.jsx("button",{type:"button",className:"rounded bg-primary-container/50 px-2 py-1 text-xs",onClick:()=>Au("csv").then(c=>{const x=new Blob([c],{type:"text/csv"}),C=document.createElement("a");C.href=URL.createObjectURL(x),C.download="experiments.csv",C.click()}),children:e("history.exportCsv")})]}),s.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-xs text-on-surface-variant",children:[s.jsx("span",{children:e("history.total",{n:(me==null?void 0:me.total)??0})}),s.jsx("button",{type:"button",className:"rounded border border-outline-variant/30 px-2 py-0.5 disabled:opacity-40",disabled:le<=1,onClick:()=>nt(c=>Math.max(1,c-1)),children:e("history.prev")}),s.jsxs("span",{children:[le," / ",yi]}),s.jsx("button",{type:"button",className:"rounded border border-outline-variant/30 px-2 py-0.5 disabled:opacity-40",disabled:le>=yi,onClick:()=>nt(c=>c+1),children:e("history.next")})]}),s.jsx("ul",{className:"mt-2 space-y-2",children:(Ci=me==null?void 0:me.items)==null?void 0:Ci.map(c=>{const x=String(c.id??""),C=c.metrics,Q=Or===x;return s.jsxs("li",{className:"rounded border border-outline-variant/20 p-2 text-[11px]",children:[s.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-2 font-mono",children:[s.jsxs("div",{children:[s.jsxs("div",{className:"text-on-surface",children:[_l(String(c.created_at??""),t)," —"," ",String(c.input_name)," — ",String(c.preset_label)]}),s.jsxs("div",{className:"mt-1 text-on-surface-variant",children:[e("history.preset"),": ",String(c.preset_label)," · ",e("history.metrics"),":"," ","matches=",String((C==null?void 0:C.matches)??"—")," rmse=",String((C==null?void 0:C.rmse_arcsec)??"—")]})]}),s.jsxs("div",{className:"flex shrink-0 gap-1",children:[s.jsx("button",{type:"button",className:"rounded bg-surface-container px-2 py-0.5 text-[10px]",onClick:()=>rn(Q?null:x),children:e(Q?"history.collapse":"history.detail")}),s.jsx("button",{type:"button",className:"rounded px-2 py-0.5 text-[10px] text-error hover:bg-error-container/20",title:e("history.delete"),onClick:()=>void Cf(x),children:e("history.delete")})]})]}),Q&&s.jsxs("div",{className:"mt-2 space-y-2",children:[c.asset_snapshot_relpath?s.jsx("img",{src:bh(x),alt:"",className:"max-h-48 max-w-full rounded border border-outline-variant/20 object-contain"}):null,s.jsx("pre",{className:"max-h-64 overflow-auto rounded bg-surface-container p-2 text-[10px]",children:JSON.stringify(c.result_json,null,2)})]})]},x)})})]})]})]})}function Qu({result:e,t,roundTripMs:n}){const r=cf(e??void 0);return e?s.jsxs("div",{className:"mt-2 space-y-2 text-[10px]",children:[s.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[r.tBackendTotalMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.backendTotalMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tBackendTotalMs.toFixed(0)," ms"]})]}),r.tSolveMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.solveComputeMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tSolveMs.toFixed(0)," ms"]})]}),r.tOpenDecodeMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.openDecodeMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tOpenDecodeMs.toFixed(0)," ms"]})]}),r.tPreprocessMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.preprocessMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tPreprocessMs.toFixed(0)," ms"]})]}),r.tExtractMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.extractMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tExtractMs.toFixed(0)," ms"]})]}),n!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.solveRoundTripMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[n.toFixed(0)," ms"]})]}),r.matches!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.matches")}),s.jsx("div",{className:"font-semibold tabular-nums text-on-surface",children:r.matches})]}),r.rmseArcsec!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.rmse")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.rmseArcsec.toFixed(2),"″"]})]}),r.prob!=null&&s.jsxs("div",{className:"col-span-2",children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.prob")}),s.jsx("div",{className:"font-semibold text-on-surface",children:Mn(r.prob,e).line}),s.jsx("p",{className:"mt-0.5 text-[9px] leading-snug text-on-surface-variant/90",children:t("lab.metric.probHelp")}),Mn(r.prob,e).rawLine&&s.jsxs("div",{className:"mt-1 text-[9px] text-on-surface-variant",children:[t("lab.metric.probRaw"),": ",Mn(r.prob,e).rawLine,s.jsx("p",{className:"mt-0.5 text-[8px] leading-snug opacity-90",children:t("lab.metric.probRawHelp")})]})]})]}),s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.radec")}),s.jsxs("div",{className:"font-mono text-[9px] text-on-surface",children:["α ",Xl(r.raDeg)," · δ ",Xl(r.decDeg)]})]}),r.status&&s.jsxs("div",{className:"rounded bg-surface-container-high px-2 py-1 text-[9px] font-mono text-on-surface",children:[t("lab.metric.status"),": ",r.status]})]}):s.jsx("p",{className:"mt-2 text-[10px] text-on-surface-variant",children:"—"})}function Xe({label:e,helpKey:t,value:n,onChange:r,type:l="number",step:o}){const{t:a}=uf(),i=t?a(t):void 0;return s.jsxs("label",{className:"block",children:[s.jsx("span",{className:"text-[10px] font-medium text-on-surface-variant",children:e}),i&&s.jsx("p",{className:"mb-1 mt-0.5 text-[9px] leading-snug text-on-surface-variant/85",children:i}),s.jsx("input",{type:l,step:o,className:"w-full rounded bg-surface-container-highest px-2 py-1",value:n===""?"":n,onChange:u=>{const f=u.target.value;r(f===""?void 0:Number(f))}})]})}pa.createRoot(document.getElementById("root")).render(s.jsx(Wf.StrictMode,{children:s.jsx(Rh,{children:s.jsx(Uh,{})})})); diff --git a/web/static/analysis-lab/assets/index-CjfavI3Q.js b/web/static/analysis-lab/assets/index-CjfavI3Q.js deleted file mode 100644 index 02926e1..0000000 --- a/web/static/analysis-lab/assets/index-CjfavI3Q.js +++ /dev/null @@ -1,125 +0,0 @@ -(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))r(l);new MutationObserver(l=>{for(const o of l)if(o.type==="childList")for(const a of o.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&r(a)}).observe(document,{childList:!0,subtree:!0});function n(l){const o={};return l.integrity&&(o.integrity=l.integrity),l.referrerPolicy&&(o.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?o.credentials="include":l.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(l){if(l.ep)return;l.ep=!0;const o=n(l);fetch(l.href,o)}})();function df(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Mu={exports:{}},Hl={},zu={exports:{}},O={};/** - * @license React - * react.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var _r=Symbol.for("react.element"),ff=Symbol.for("react.portal"),pf=Symbol.for("react.fragment"),mf=Symbol.for("react.strict_mode"),hf=Symbol.for("react.profiler"),vf=Symbol.for("react.provider"),yf=Symbol.for("react.context"),gf=Symbol.for("react.forward_ref"),xf=Symbol.for("react.suspense"),wf=Symbol.for("react.memo"),Sf=Symbol.for("react.lazy"),ui=Symbol.iterator;function kf(e){return e===null||typeof e!="object"?null:(e=ui&&e[ui]||e["@@iterator"],typeof e=="function"?e:null)}var Ru={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Tu=Object.assign,Lu={};function Ln(e,t,n){this.props=e,this.context=t,this.refs=Lu,this.updater=n||Ru}Ln.prototype.isReactComponent={};Ln.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};Ln.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function Ou(){}Ou.prototype=Ln.prototype;function Qa(e,t,n){this.props=e,this.context=t,this.refs=Lu,this.updater=n||Ru}var Ka=Qa.prototype=new Ou;Ka.constructor=Qa;Tu(Ka,Ln.prototype);Ka.isPureReactComponent=!0;var ci=Array.isArray,Fu=Object.prototype.hasOwnProperty,Ga={current:null},Iu={key:!0,ref:!0,__self:!0,__source:!0};function Du(e,t,n){var r,l={},o=null,a=null;if(t!=null)for(r in t.ref!==void 0&&(a=t.ref),t.key!==void 0&&(o=""+t.key),t)Fu.call(t,r)&&!Iu.hasOwnProperty(r)&&(l[r]=t[r]);var i=arguments.length-2;if(i===1)l.children=n;else if(1>>1,X=E[H];if(0>>1;Hl(tt,T))_el(nt,tt)?(E[H]=nt,E[_e]=T,H=_e):(E[H]=tt,E[Ke]=T,H=Ke);else if(_el(nt,T))E[H]=nt,E[_e]=T,H=_e;else break e}}return R}function l(E,R){var T=E.sortIndex-R.sortIndex;return T!==0?T:E.id-R.id}if(typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var a=Date,i=a.now();e.unstable_now=function(){return a.now()-i}}var u=[],f=[],h=1,y=null,v=3,N=!1,j=!1,_=!1,$=typeof setTimeout=="function"?setTimeout:null,p=typeof clearTimeout=="function"?clearTimeout:null,d=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function m(E){for(var R=n(f);R!==null;){if(R.callback===null)r(f);else if(R.startTime<=E)r(f),R.sortIndex=R.expirationTime,t(u,R);else break;R=n(f)}}function g(E){if(_=!1,m(E),!j)if(n(u)!==null)j=!0,tn(k);else{var R=n(f);R!==null&&It(g,R.startTime-E)}}function k(E,R){j=!1,_&&(_=!1,p(M),M=-1),N=!0;var T=v;try{for(m(R),y=n(u);y!==null&&(!(y.expirationTime>R)||E&&!ne());){var H=y.callback;if(typeof H=="function"){y.callback=null,v=y.priorityLevel;var X=H(y.expirationTime<=R);R=e.unstable_now(),typeof X=="function"?y.callback=X:y===n(u)&&r(u),m(R)}else r(u);y=n(u)}if(y!==null)var je=!0;else{var Ke=n(f);Ke!==null&&It(g,Ke.startTime-R),je=!1}return je}finally{y=null,v=T,N=!1}}var b=!1,C=null,M=-1,U=5,L=-1;function ne(){return!(e.unstable_now()-LE||125H?(E.sortIndex=T,t(f,E),n(u)===null&&E===n(f)&&(_?(p(M),M=-1):_=!0,It(g,T-H))):(E.sortIndex=X,t(u,E),j||N||(j=!0,tn(k))),E},e.unstable_shouldYield=ne,e.unstable_wrapCallback=function(E){var R=v;return function(){var T=v;v=R;try{return E.apply(this,arguments)}finally{v=T}}}})(Bu);Au.exports=Bu;var Lf=Au.exports;/** - * @license React - * react-dom.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Of=S,be=Lf;function w(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),qo=Object.prototype.hasOwnProperty,Ff=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,fi={},pi={};function If(e){return qo.call(pi,e)?!0:qo.call(fi,e)?!1:Ff.test(e)?pi[e]=!0:(fi[e]=!0,!1)}function Df(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function Uf(e,t,n,r){if(t===null||typeof t>"u"||Df(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function ge(e,t,n,r,l,o,a){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=l,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=a}var ue={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){ue[e]=new ge(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];ue[t]=new ge(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){ue[e]=new ge(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){ue[e]=new ge(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){ue[e]=new ge(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){ue[e]=new ge(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){ue[e]=new ge(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){ue[e]=new ge(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){ue[e]=new ge(e,5,!1,e.toLowerCase(),null,!1,!1)});var Xa=/[\-:]([a-z])/g;function Ja(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(Xa,Ja);ue[t]=new ge(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(Xa,Ja);ue[t]=new ge(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(Xa,Ja);ue[t]=new ge(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){ue[e]=new ge(e,1,!1,e.toLowerCase(),null,!1,!1)});ue.xlinkHref=new ge("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){ue[e]=new ge(e,1,!1,e.toLowerCase(),null,!0,!0)});function Za(e,t,n,r){var l=ue.hasOwnProperty(t)?ue[t]:null;(l!==null?l.type!==0:r||!(2i||l[a]!==o[i]){var u=` -`+l[a].replace(" at new "," at ");return e.displayName&&u.includes("")&&(u=u.replace("",e.displayName)),u}while(1<=a&&0<=i);break}}}finally{So=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?Yn(e):""}function $f(e){switch(e.tag){case 5:return Yn(e.type);case 16:return Yn("Lazy");case 13:return Yn("Suspense");case 19:return Yn("SuspenseList");case 0:case 2:case 15:return e=ko(e.type,!1),e;case 11:return e=ko(e.type.render,!1),e;case 1:return e=ko(e.type,!0),e;default:return""}}function ra(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case un:return"Fragment";case sn:return"Portal";case ea:return"Profiler";case qa:return"StrictMode";case ta:return"Suspense";case na:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Qu:return(e.displayName||"Context")+".Consumer";case Wu:return(e._context.displayName||"Context")+".Provider";case es:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case ts:return t=e.displayName||null,t!==null?t:ra(e.type)||"Memo";case gt:t=e._payload,e=e._init;try{return ra(e(t))}catch{}}return null}function Hf(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return ra(t);case 8:return t===qa?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function Rt(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function Gu(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function Af(e){var t=Gu(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var l=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return l.call(this)},set:function(a){r=""+a,o.call(this,a)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(a){r=""+a},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function Hr(e){e._valueTracker||(e._valueTracker=Af(e))}function Yu(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=Gu(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function vl(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function la(e,t){var n=t.checked;return G({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function hi(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=Rt(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function Xu(e,t){t=t.checked,t!=null&&Za(e,"checked",t,!1)}function oa(e,t){Xu(e,t);var n=Rt(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?aa(e,t.type,n):t.hasOwnProperty("defaultValue")&&aa(e,t.type,Rt(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function vi(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function aa(e,t,n){(t!=="number"||vl(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var Xn=Array.isArray;function wn(e,t,n,r){if(e=e.options,t){t={};for(var l=0;l"+t.valueOf().toString()+"",t=Ar.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function ur(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var qn={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Bf=["Webkit","ms","Moz","O"];Object.keys(qn).forEach(function(e){Bf.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),qn[t]=qn[e]})});function ec(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||qn.hasOwnProperty(e)&&qn[e]?(""+t).trim():t+"px"}function tc(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,l=ec(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,l):e[n]=l}}var Vf=G({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function ua(e,t){if(t){if(Vf[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(w(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(w(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(w(61))}if(t.style!=null&&typeof t.style!="object")throw Error(w(62))}}function ca(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var da=null;function ns(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var fa=null,Sn=null,kn=null;function xi(e){if(e=Pr(e)){if(typeof fa!="function")throw Error(w(280));var t=e.stateNode;t&&(t=Ql(t),fa(e.stateNode,e.type,t))}}function nc(e){Sn?kn?kn.push(e):kn=[e]:Sn=e}function rc(){if(Sn){var e=Sn,t=kn;if(kn=Sn=null,xi(e),t)for(e=0;e>>=0,e===0?32:31-(tp(e)/np|0)|0}var Br=64,Vr=4194304;function Jn(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function wl(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,l=e.suspendedLanes,o=e.pingedLanes,a=n&268435455;if(a!==0){var i=a&~l;i!==0?r=Jn(i):(o&=a,o!==0&&(r=Jn(o)))}else a=n&~l,a!==0?r=Jn(a):o!==0&&(r=Jn(o));if(r===0)return 0;if(t!==0&&t!==r&&!(t&l)&&(l=r&-r,o=t&-t,l>=o||l===16&&(o&4194240)!==0))return t;if(r&4&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Cr(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-Ve(t),e[t]=n}function ap(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=tr),Pi=" ",bi=!1;function Nc(e,t){switch(e){case"keyup":return Lp.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function jc(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var cn=!1;function Fp(e,t){switch(e){case"compositionend":return jc(t);case"keypress":return t.which!==32?null:(bi=!0,Pi);case"textInput":return e=t.data,e===Pi&&bi?null:e;default:return null}}function Ip(e,t){if(cn)return e==="compositionend"||!cs&&Nc(e,t)?(e=Sc(),al=ss=kt=null,cn=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=Ti(n)}}function Pc(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Pc(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function bc(){for(var e=window,t=vl();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=vl(e.document)}return t}function ds(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function Qp(e){var t=bc(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&Pc(n.ownerDocument.documentElement,n)){if(r!==null&&ds(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var l=n.textContent.length,o=Math.min(r.start,l);r=r.end===void 0?o:Math.min(r.end,l),!e.extend&&o>r&&(l=r,r=o,o=l),l=Li(n,o);var a=Li(n,r);l&&a&&(e.rangeCount!==1||e.anchorNode!==l.node||e.anchorOffset!==l.offset||e.focusNode!==a.node||e.focusOffset!==a.offset)&&(t=t.createRange(),t.setStart(l.node,l.offset),e.removeAllRanges(),o>r?(e.addRange(t),e.extend(a.node,a.offset)):(t.setEnd(a.node,a.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,dn=null,ga=null,rr=null,xa=!1;function Oi(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;xa||dn==null||dn!==vl(r)||(r=dn,"selectionStart"in r&&ds(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),rr&&hr(rr,r)||(rr=r,r=Nl(ga,"onSelect"),0mn||(e.current=_a[mn],_a[mn]=null,mn--)}function A(e,t){mn++,_a[mn]=e.current,e.current=t}var Tt={},pe=Ot(Tt),Se=Ot(!1),Kt=Tt;function Pn(e,t){var n=e.type.contextTypes;if(!n)return Tt;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var l={},o;for(o in n)l[o]=t[o];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=l),l}function ke(e){return e=e.childContextTypes,e!=null}function _l(){V(Se),V(pe)}function Ai(e,t,n){if(pe.current!==Tt)throw Error(w(168));A(pe,t),A(Se,n)}function Dc(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var l in r)if(!(l in t))throw Error(w(108,Hf(e)||"Unknown",l));return G({},n,r)}function Cl(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Tt,Kt=pe.current,A(pe,e),A(Se,Se.current),!0}function Bi(e,t,n){var r=e.stateNode;if(!r)throw Error(w(169));n?(e=Dc(e,t,Kt),r.__reactInternalMemoizedMergedChildContext=e,V(Se),V(pe),A(pe,e)):V(Se),A(Se,n)}var at=null,Kl=!1,Fo=!1;function Uc(e){at===null?at=[e]:at.push(e)}function lm(e){Kl=!0,Uc(e)}function Ft(){if(!Fo&&at!==null){Fo=!0;var e=0,t=D;try{var n=at;for(D=1;e>=a,l-=a,st=1<<32-Ve(t)+l|n<M?(U=C,C=null):U=C.sibling;var L=v(p,C,m[M],g);if(L===null){C===null&&(C=U);break}e&&C&&L.alternate===null&&t(p,C),d=o(L,d,M),b===null?k=L:b.sibling=L,b=L,C=U}if(M===m.length)return n(p,C),W&&$t(p,M),k;if(C===null){for(;MM?(U=C,C=null):U=C.sibling;var ne=v(p,C,L.value,g);if(ne===null){C===null&&(C=U);break}e&&C&&ne.alternate===null&&t(p,C),d=o(ne,d,M),b===null?k=ne:b.sibling=ne,b=ne,C=U}if(L.done)return n(p,C),W&&$t(p,M),k;if(C===null){for(;!L.done;M++,L=m.next())L=y(p,L.value,g),L!==null&&(d=o(L,d,M),b===null?k=L:b.sibling=L,b=L);return W&&$t(p,M),k}for(C=r(p,C);!L.done;M++,L=m.next())L=N(C,p,M,L.value,g),L!==null&&(e&&L.alternate!==null&&C.delete(L.key===null?M:L.key),d=o(L,d,M),b===null?k=L:b.sibling=L,b=L);return e&&C.forEach(function(et){return t(p,et)}),W&&$t(p,M),k}function $(p,d,m,g){if(typeof m=="object"&&m!==null&&m.type===un&&m.key===null&&(m=m.props.children),typeof m=="object"&&m!==null){switch(m.$$typeof){case $r:e:{for(var k=m.key,b=d;b!==null;){if(b.key===k){if(k=m.type,k===un){if(b.tag===7){n(p,b.sibling),d=l(b,m.props.children),d.return=p,p=d;break e}}else if(b.elementType===k||typeof k=="object"&&k!==null&&k.$$typeof===gt&&Qi(k)===b.type){n(p,b.sibling),d=l(b,m.props),d.ref=Wn(p,b,m),d.return=p,p=d;break e}n(p,b);break}else t(p,b);b=b.sibling}m.type===un?(d=Qt(m.props.children,p.mode,g,m.key),d.return=p,p=d):(g=ml(m.type,m.key,m.props,null,p.mode,g),g.ref=Wn(p,d,m),g.return=p,p=g)}return a(p);case sn:e:{for(b=m.key;d!==null;){if(d.key===b)if(d.tag===4&&d.stateNode.containerInfo===m.containerInfo&&d.stateNode.implementation===m.implementation){n(p,d.sibling),d=l(d,m.children||[]),d.return=p,p=d;break e}else{n(p,d);break}else t(p,d);d=d.sibling}d=Vo(m,p.mode,g),d.return=p,p=d}return a(p);case gt:return b=m._init,$(p,d,b(m._payload),g)}if(Xn(m))return j(p,d,m,g);if($n(m))return _(p,d,m,g);Jr(p,m)}return typeof m=="string"&&m!==""||typeof m=="number"?(m=""+m,d!==null&&d.tag===6?(n(p,d.sibling),d=l(d,m),d.return=p,p=d):(n(p,d),d=Bo(m,p.mode,g),d.return=p,p=d),a(p)):n(p,d)}return $}var Mn=Bc(!0),Vc=Bc(!1),bl=Ot(null),Ml=null,yn=null,hs=null;function vs(){hs=yn=Ml=null}function ys(e){var t=bl.current;V(bl),e._currentValue=t}function Pa(e,t,n){for(;e!==null;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,r!==null&&(r.childLanes|=t)):r!==null&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function jn(e,t){Ml=e,hs=yn=null,e=e.dependencies,e!==null&&e.firstContext!==null&&(e.lanes&t&&(we=!0),e.firstContext=null)}function De(e){var t=e._currentValue;if(hs!==e)if(e={context:e,memoizedValue:t,next:null},yn===null){if(Ml===null)throw Error(w(308));yn=e,Ml.dependencies={lanes:0,firstContext:e}}else yn=yn.next=e;return t}var Bt=null;function gs(e){Bt===null?Bt=[e]:Bt.push(e)}function Wc(e,t,n,r){var l=t.interleaved;return l===null?(n.next=n,gs(t)):(n.next=l.next,l.next=n),t.interleaved=n,ft(e,r)}function ft(e,t){e.lanes|=t;var n=e.alternate;for(n!==null&&(n.lanes|=t),n=e,e=e.return;e!==null;)e.childLanes|=t,n=e.alternate,n!==null&&(n.childLanes|=t),n=e,e=e.return;return n.tag===3?n.stateNode:null}var xt=!1;function xs(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Qc(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function ut(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Pt(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,F&2){var l=r.pending;return l===null?t.next=t:(t.next=l.next,l.next=t),r.pending=t,ft(e,n)}return l=r.interleaved,l===null?(t.next=t,gs(r)):(t.next=l.next,l.next=t),r.interleaved=t,ft(e,n)}function il(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194240)!==0)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ls(e,n)}}function Ki(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var l=null,o=null;if(n=n.firstBaseUpdate,n!==null){do{var a={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};o===null?l=o=a:o=o.next=a,n=n.next}while(n!==null);o===null?l=o=t:o=o.next=t}else l=o=t;n={baseState:r.baseState,firstBaseUpdate:l,lastBaseUpdate:o,shared:r.shared,effects:r.effects},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function zl(e,t,n,r){var l=e.updateQueue;xt=!1;var o=l.firstBaseUpdate,a=l.lastBaseUpdate,i=l.shared.pending;if(i!==null){l.shared.pending=null;var u=i,f=u.next;u.next=null,a===null?o=f:a.next=f,a=u;var h=e.alternate;h!==null&&(h=h.updateQueue,i=h.lastBaseUpdate,i!==a&&(i===null?h.firstBaseUpdate=f:i.next=f,h.lastBaseUpdate=u))}if(o!==null){var y=l.baseState;a=0,h=f=u=null,i=o;do{var v=i.lane,N=i.eventTime;if((r&v)===v){h!==null&&(h=h.next={eventTime:N,lane:0,tag:i.tag,payload:i.payload,callback:i.callback,next:null});e:{var j=e,_=i;switch(v=t,N=n,_.tag){case 1:if(j=_.payload,typeof j=="function"){y=j.call(N,y,v);break e}y=j;break e;case 3:j.flags=j.flags&-65537|128;case 0:if(j=_.payload,v=typeof j=="function"?j.call(N,y,v):j,v==null)break e;y=G({},y,v);break e;case 2:xt=!0}}i.callback!==null&&i.lane!==0&&(e.flags|=64,v=l.effects,v===null?l.effects=[i]:v.push(i))}else N={eventTime:N,lane:v,tag:i.tag,payload:i.payload,callback:i.callback,next:null},h===null?(f=h=N,u=y):h=h.next=N,a|=v;if(i=i.next,i===null){if(i=l.shared.pending,i===null)break;v=i,i=v.next,v.next=null,l.lastBaseUpdate=v,l.shared.pending=null}}while(!0);if(h===null&&(u=y),l.baseState=u,l.firstBaseUpdate=f,l.lastBaseUpdate=h,t=l.shared.interleaved,t!==null){l=t;do a|=l.lane,l=l.next;while(l!==t)}else o===null&&(l.shared.lanes=0);Xt|=a,e.lanes=a,e.memoizedState=y}}function Gi(e,t,n){if(e=t.effects,t.effects=null,e!==null)for(t=0;tn?n:4,e(!0);var r=Do.transition;Do.transition={};try{e(!1),t()}finally{D=n,Do.transition=r}}function ud(){return Ue().memoizedState}function im(e,t,n){var r=Mt(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},cd(e))dd(t,n);else if(n=Wc(e,t,n,r),n!==null){var l=ve();We(n,e,r,l),fd(n,t,r)}}function um(e,t,n){var r=Mt(e),l={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(cd(e))dd(t,l);else{var o=e.alternate;if(e.lanes===0&&(o===null||o.lanes===0)&&(o=t.lastRenderedReducer,o!==null))try{var a=t.lastRenderedState,i=o(a,n);if(l.hasEagerState=!0,l.eagerState=i,Qe(i,a)){var u=t.interleaved;u===null?(l.next=l,gs(t)):(l.next=u.next,u.next=l),t.interleaved=l;return}}catch{}finally{}n=Wc(e,t,l,r),n!==null&&(l=ve(),We(n,e,r,l),fd(n,t,r))}}function cd(e){var t=e.alternate;return e===K||t!==null&&t===K}function dd(e,t){lr=Tl=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function fd(e,t,n){if(n&4194240){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ls(e,n)}}var Ll={readContext:De,useCallback:ce,useContext:ce,useEffect:ce,useImperativeHandle:ce,useInsertionEffect:ce,useLayoutEffect:ce,useMemo:ce,useReducer:ce,useRef:ce,useState:ce,useDebugValue:ce,useDeferredValue:ce,useTransition:ce,useMutableSource:ce,useSyncExternalStore:ce,useId:ce,unstable_isNewReconciler:!1},cm={readContext:De,useCallback:function(e,t){return Xe().memoizedState=[e,t===void 0?null:t],e},useContext:De,useEffect:Xi,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,cl(4194308,4,ld.bind(null,t,e),n)},useLayoutEffect:function(e,t){return cl(4194308,4,e,t)},useInsertionEffect:function(e,t){return cl(4,2,e,t)},useMemo:function(e,t){var n=Xe();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=Xe();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=im.bind(null,K,e),[r.memoizedState,e]},useRef:function(e){var t=Xe();return e={current:e},t.memoizedState=e},useState:Yi,useDebugValue:Es,useDeferredValue:function(e){return Xe().memoizedState=e},useTransition:function(){var e=Yi(!1),t=e[0];return e=sm.bind(null,e[1]),Xe().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=K,l=Xe();if(W){if(n===void 0)throw Error(w(407));n=n()}else{if(n=t(),ae===null)throw Error(w(349));Yt&30||Xc(r,t,n)}l.memoizedState=n;var o={value:n,getSnapshot:t};return l.queue=o,Xi(Zc.bind(null,r,o,e),[e]),r.flags|=2048,Nr(9,Jc.bind(null,r,o,n,t),void 0,null),n},useId:function(){var e=Xe(),t=ae.identifierPrefix;if(W){var n=it,r=st;n=(r&~(1<<32-Ve(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=Sr++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=a.createElement(n,{is:r.is}):(e=a.createElement(n),n==="select"&&(a=e,r.multiple?a.multiple=!0:r.size&&(a.size=r.size))):e=a.createElementNS(e,n),e[Je]=t,e[gr]=r,kd(e,t,!1,!1),t.stateNode=e;e:{switch(a=ca(n,r),n){case"dialog":B("cancel",e),B("close",e),l=r;break;case"iframe":case"object":case"embed":B("load",e),l=r;break;case"video":case"audio":for(l=0;lTn&&(t.flags|=128,r=!0,Qn(o,!1),t.lanes=4194304)}else{if(!r)if(e=Rl(a),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),Qn(o,!0),o.tail===null&&o.tailMode==="hidden"&&!a.alternate&&!W)return de(t),null}else 2*J()-o.renderingStartTime>Tn&&n!==1073741824&&(t.flags|=128,r=!0,Qn(o,!1),t.lanes=4194304);o.isBackwards?(a.sibling=t.child,t.child=a):(n=o.last,n!==null?n.sibling=a:t.child=a,o.last=a)}return o.tail!==null?(t=o.tail,o.rendering=t,o.tail=t.sibling,o.renderingStartTime=J(),t.sibling=null,n=Q.current,A(Q,r?n&1|2:n&1),t):(de(t),null);case 22:case 23:return Ts(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&t.mode&1?Ce&1073741824&&(de(t),t.subtreeFlags&6&&(t.flags|=8192)):de(t),null;case 24:return null;case 25:return null}throw Error(w(156,t.tag))}function gm(e,t){switch(ps(t),t.tag){case 1:return ke(t.type)&&_l(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return zn(),V(Se),V(pe),ks(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 5:return Ss(t),null;case 13:if(V(Q),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(w(340));bn()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return V(Q),null;case 4:return zn(),null;case 10:return ys(t.type._context),null;case 22:case 23:return Ts(),null;case 24:return null;default:return null}}var qr=!1,fe=!1,xm=typeof WeakSet=="function"?WeakSet:Set,P=null;function gn(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){Y(e,t,r)}else n.current=null}function Ia(e,t,n){try{n()}catch(r){Y(e,t,r)}}var su=!1;function wm(e,t){if(wa=Sl,e=bc(),ds(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var l=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break e}var a=0,i=-1,u=-1,f=0,h=0,y=e,v=null;t:for(;;){for(var N;y!==n||l!==0&&y.nodeType!==3||(i=a+l),y!==o||r!==0&&y.nodeType!==3||(u=a+r),y.nodeType===3&&(a+=y.nodeValue.length),(N=y.firstChild)!==null;)v=y,y=N;for(;;){if(y===e)break t;if(v===n&&++f===l&&(i=a),v===o&&++h===r&&(u=a),(N=y.nextSibling)!==null)break;y=v,v=y.parentNode}y=N}n=i===-1||u===-1?null:{start:i,end:u}}else n=null}n=n||{start:0,end:0}}else n=null;for(Sa={focusedElem:e,selectionRange:n},Sl=!1,P=t;P!==null;)if(t=P,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,P=e;else for(;P!==null;){t=P;try{var j=t.alternate;if(t.flags&1024)switch(t.tag){case 0:case 11:case 15:break;case 1:if(j!==null){var _=j.memoizedProps,$=j.memoizedState,p=t.stateNode,d=p.getSnapshotBeforeUpdate(t.elementType===t.type?_:He(t.type,_),$);p.__reactInternalSnapshotBeforeUpdate=d}break;case 3:var m=t.stateNode.containerInfo;m.nodeType===1?m.textContent="":m.nodeType===9&&m.documentElement&&m.removeChild(m.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(w(163))}}catch(g){Y(t,t.return,g)}if(e=t.sibling,e!==null){e.return=t.return,P=e;break}P=t.return}return j=su,su=!1,j}function or(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var l=r=r.next;do{if((l.tag&e)===e){var o=l.destroy;l.destroy=void 0,o!==void 0&&Ia(t,n,o)}l=l.next}while(l!==r)}}function Xl(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function Da(e){var t=e.ref;if(t!==null){var n=e.stateNode;switch(e.tag){case 5:e=n;break;default:e=n}typeof t=="function"?t(e):t.current=e}}function _d(e){var t=e.alternate;t!==null&&(e.alternate=null,_d(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[Je],delete t[gr],delete t[ja],delete t[nm],delete t[rm])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function Cd(e){return e.tag===5||e.tag===3||e.tag===4}function iu(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Cd(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Ua(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=jl));else if(r!==4&&(e=e.child,e!==null))for(Ua(e,t,n),e=e.sibling;e!==null;)Ua(e,t,n),e=e.sibling}function $a(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for($a(e,t,n),e=e.sibling;e!==null;)$a(e,t,n),e=e.sibling}var se=null,Ae=!1;function yt(e,t,n){for(n=n.child;n!==null;)Ed(e,t,n),n=n.sibling}function Ed(e,t,n){if(Ze&&typeof Ze.onCommitFiberUnmount=="function")try{Ze.onCommitFiberUnmount(Al,n)}catch{}switch(n.tag){case 5:fe||gn(n,t);case 6:var r=se,l=Ae;se=null,yt(e,t,n),se=r,Ae=l,se!==null&&(Ae?(e=se,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):se.removeChild(n.stateNode));break;case 18:se!==null&&(Ae?(e=se,n=n.stateNode,e.nodeType===8?Oo(e.parentNode,n):e.nodeType===1&&Oo(e,n),pr(e)):Oo(se,n.stateNode));break;case 4:r=se,l=Ae,se=n.stateNode.containerInfo,Ae=!0,yt(e,t,n),se=r,Ae=l;break;case 0:case 11:case 14:case 15:if(!fe&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){l=r=r.next;do{var o=l,a=o.destroy;o=o.tag,a!==void 0&&(o&2||o&4)&&Ia(n,t,a),l=l.next}while(l!==r)}yt(e,t,n);break;case 1:if(!fe&&(gn(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(i){Y(n,t,i)}yt(e,t,n);break;case 21:yt(e,t,n);break;case 22:n.mode&1?(fe=(r=fe)||n.memoizedState!==null,yt(e,t,n),fe=r):yt(e,t,n);break;default:yt(e,t,n)}}function uu(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new xm),t.forEach(function(r){var l=bm.bind(null,e,r);n.has(r)||(n.add(r),r.then(l,l))})}}function $e(e,t){var n=t.deletions;if(n!==null)for(var r=0;rl&&(l=a),r&=~o}if(r=l,r=J()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*km(r/1960))-r,10e?16:e,Nt===null)var r=!1;else{if(e=Nt,Nt=null,Il=0,F&6)throw Error(w(331));var l=F;for(F|=4,P=e.current;P!==null;){var o=P,a=o.child;if(P.flags&16){var i=o.deletions;if(i!==null){for(var u=0;uJ()-zs?Wt(e,0):Ms|=n),Ne(e,t)}function Od(e,t){t===0&&(e.mode&1?(t=Vr,Vr<<=1,!(Vr&130023424)&&(Vr=4194304)):t=1);var n=ve();e=ft(e,t),e!==null&&(Cr(e,t,n),Ne(e,n))}function Pm(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Od(e,n)}function bm(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,l=e.memoizedState;l!==null&&(n=l.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(w(314))}r!==null&&r.delete(t),Od(e,n)}var Fd;Fd=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||Se.current)we=!0;else{if(!(e.lanes&n)&&!(t.flags&128))return we=!1,vm(e,t,n);we=!!(e.flags&131072)}else we=!1,W&&t.flags&1048576&&$c(t,Pl,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;dl(e,t),e=t.pendingProps;var l=Pn(t,pe.current);jn(t,n),l=js(null,t,r,e,l,n);var o=_s();return t.flags|=1,typeof l=="object"&&l!==null&&typeof l.render=="function"&&l.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,ke(r)?(o=!0,Cl(t)):o=!1,t.memoizedState=l.state!==null&&l.state!==void 0?l.state:null,xs(t),l.updater=Yl,t.stateNode=l,l._reactInternals=t,Ma(t,r,e,n),t=Ta(null,t,r,!0,o,n)):(t.tag=0,W&&o&&fs(t),he(null,t,l,n),t=t.child),t;case 16:r=t.elementType;e:{switch(dl(e,t),e=t.pendingProps,l=r._init,r=l(r._payload),t.type=r,l=t.tag=zm(r),e=He(r,e),l){case 0:t=Ra(null,t,r,e,n);break e;case 1:t=lu(null,t,r,e,n);break e;case 11:t=nu(null,t,r,e,n);break e;case 14:t=ru(null,t,r,He(r.type,e),n);break e}throw Error(w(306,r,""))}return t;case 0:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:He(r,l),Ra(e,t,r,l,n);case 1:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:He(r,l),lu(e,t,r,l,n);case 3:e:{if(xd(t),e===null)throw Error(w(387));r=t.pendingProps,o=t.memoizedState,l=o.element,Qc(e,t),zl(t,r,null,n);var a=t.memoizedState;if(r=a.element,o.isDehydrated)if(o={element:r,isDehydrated:!1,cache:a.cache,pendingSuspenseBoundaries:a.pendingSuspenseBoundaries,transitions:a.transitions},t.updateQueue.baseState=o,t.memoizedState=o,t.flags&256){l=Rn(Error(w(423)),t),t=ou(e,t,r,n,l);break e}else if(r!==l){l=Rn(Error(w(424)),t),t=ou(e,t,r,n,l);break e}else for(Ee=Et(t.stateNode.containerInfo.firstChild),Pe=t,W=!0,Be=null,n=Vc(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(bn(),r===l){t=pt(e,t,n);break e}he(e,t,r,n)}t=t.child}return t;case 5:return Kc(t),e===null&&Ea(t),r=t.type,l=t.pendingProps,o=e!==null?e.memoizedProps:null,a=l.children,ka(r,l)?a=null:o!==null&&ka(r,o)&&(t.flags|=32),gd(e,t),he(e,t,a,n),t.child;case 6:return e===null&&Ea(t),null;case 13:return wd(e,t,n);case 4:return ws(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=Mn(t,null,r,n):he(e,t,r,n),t.child;case 11:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:He(r,l),nu(e,t,r,l,n);case 7:return he(e,t,t.pendingProps,n),t.child;case 8:return he(e,t,t.pendingProps.children,n),t.child;case 12:return he(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,l=t.pendingProps,o=t.memoizedProps,a=l.value,A(bl,r._currentValue),r._currentValue=a,o!==null)if(Qe(o.value,a)){if(o.children===l.children&&!Se.current){t=pt(e,t,n);break e}}else for(o=t.child,o!==null&&(o.return=t);o!==null;){var i=o.dependencies;if(i!==null){a=o.child;for(var u=i.firstContext;u!==null;){if(u.context===r){if(o.tag===1){u=ut(-1,n&-n),u.tag=2;var f=o.updateQueue;if(f!==null){f=f.shared;var h=f.pending;h===null?u.next=u:(u.next=h.next,h.next=u),f.pending=u}}o.lanes|=n,u=o.alternate,u!==null&&(u.lanes|=n),Pa(o.return,n,t),i.lanes|=n;break}u=u.next}}else if(o.tag===10)a=o.type===t.type?null:o.child;else if(o.tag===18){if(a=o.return,a===null)throw Error(w(341));a.lanes|=n,i=a.alternate,i!==null&&(i.lanes|=n),Pa(a,n,t),a=o.sibling}else a=o.child;if(a!==null)a.return=o;else for(a=o;a!==null;){if(a===t){a=null;break}if(o=a.sibling,o!==null){o.return=a.return,a=o;break}a=a.return}o=a}he(e,t,l.children,n),t=t.child}return t;case 9:return l=t.type,r=t.pendingProps.children,jn(t,n),l=De(l),r=r(l),t.flags|=1,he(e,t,r,n),t.child;case 14:return r=t.type,l=He(r,t.pendingProps),l=He(r.type,l),ru(e,t,r,l,n);case 15:return vd(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:He(r,l),dl(e,t),t.tag=1,ke(r)?(e=!0,Cl(t)):e=!1,jn(t,n),pd(t,r,l),Ma(t,r,l,n),Ta(null,t,r,!0,e,n);case 19:return Sd(e,t,n);case 22:return yd(e,t,n)}throw Error(w(156,t.tag))};function Id(e,t){return cc(e,t)}function Mm(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Fe(e,t,n,r){return new Mm(e,t,n,r)}function Os(e){return e=e.prototype,!(!e||!e.isReactComponent)}function zm(e){if(typeof e=="function")return Os(e)?1:0;if(e!=null){if(e=e.$$typeof,e===es)return 11;if(e===ts)return 14}return 2}function zt(e,t){var n=e.alternate;return n===null?(n=Fe(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function ml(e,t,n,r,l,o){var a=2;if(r=e,typeof e=="function")Os(e)&&(a=1);else if(typeof e=="string")a=5;else e:switch(e){case un:return Qt(n.children,l,o,t);case qa:a=8,l|=8;break;case ea:return e=Fe(12,n,t,l|2),e.elementType=ea,e.lanes=o,e;case ta:return e=Fe(13,n,t,l),e.elementType=ta,e.lanes=o,e;case na:return e=Fe(19,n,t,l),e.elementType=na,e.lanes=o,e;case Ku:return Zl(n,l,o,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case Wu:a=10;break e;case Qu:a=9;break e;case es:a=11;break e;case ts:a=14;break e;case gt:a=16,r=null;break e}throw Error(w(130,e==null?e:typeof e,""))}return t=Fe(a,n,t,l),t.elementType=e,t.type=r,t.lanes=o,t}function Qt(e,t,n,r){return e=Fe(7,e,r,t),e.lanes=n,e}function Zl(e,t,n,r){return e=Fe(22,e,r,t),e.elementType=Ku,e.lanes=n,e.stateNode={isHidden:!1},e}function Bo(e,t,n){return e=Fe(6,e,null,t),e.lanes=n,e}function Vo(e,t,n){return t=Fe(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Rm(e,t,n,r,l){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=jo(0),this.expirationTimes=jo(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=jo(0),this.identifierPrefix=r,this.onRecoverableError=l,this.mutableSourceEagerHydrationData=null}function Fs(e,t,n,r,l,o,a,i,u){return e=new Rm(e,t,n,i,u),t===1?(t=1,o===!0&&(t|=8)):t=0,o=Fe(3,null,null,t),e.current=o,o.stateNode=e,o.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},xs(o),e}function Tm(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(Hd)}catch(e){console.error(e)}}Hd(),Hu.exports=Me;var Dm=Hu.exports,yu=Dm;Zo.createRoot=yu.createRoot,Zo.hydrateRoot=yu.hydrateRoot;/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Um=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),Ad=(...e)=>e.filter((t,n,r)=>!!t&&t.trim()!==""&&r.indexOf(t)===n).join(" ").trim();/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */var $m={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Hm=S.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:n=2,absoluteStrokeWidth:r,className:l="",children:o,iconNode:a,...i},u)=>S.createElement("svg",{ref:u,...$m,width:t,height:t,stroke:e,strokeWidth:r?Number(n)*24/Number(t):n,className:Ad("lucide",l),...i},[...a.map(([f,h])=>S.createElement(f,h)),...Array.isArray(o)?o:[o]]));/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Re=(e,t)=>{const n=S.forwardRef(({className:r,...l},o)=>S.createElement(Hm,{ref:o,iconNode:t,className:Ad(`lucide-${Um(e)}`,r),...l}));return n.displayName=`${e}`,n};/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Gn=Re("ChevronDown",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Am=Re("Database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Bm=Re("FlaskConical",[["path",{d:"M10 2v7.527a2 2 0 0 1-.211.896L4.72 20.55a1 1 0 0 0 .9 1.45h12.76a1 1 0 0 0 .9-1.45l-5.069-10.127A2 2 0 0 1 14 9.527V2",key:"pzvekw"}],["path",{d:"M8.5 2h7",key:"csnxdl"}],["path",{d:"M7 16h10",key:"wp8him"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const gu=Re("Grid3x3",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M3 9h18",key:"1pudct"}],["path",{d:"M3 15h18",key:"5xshup"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"M15 3v18",key:"14nvp0"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Vm=Re("History",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M12 7v5l4 2",key:"1fdv2h"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Wm=Re("House",[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"1d0kgt"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Wo=Re("LoaderCircle",[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Qm=Re("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const xu=Re("RotateCcw",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const wu=Re("Trash2",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Km=Re("Upload",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"17 8 12 3 7 8",key:"t8dd8p"}],["line",{x1:"12",x2:"12",y1:"3",y2:"15",key:"widbto"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Su=Re("ZoomIn",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"11",x2:"11",y1:"8",y2:"14",key:"1vmskp"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]]);/** - * @license lucide-react v0.460.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const ku=Re("ZoomOut",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]]),Z="/api";async function ht(e){if((e.headers.get("content-type")||"").includes("application/json"))return e.json();const n=await e.text();throw new Error(n||`HTTP ${e.status}`)}async function Gm(){const e=await fetch(`${Z}/analysis/uploads`);if(!e.ok)throw new Error(await e.text());return e.json()}async function Ym(e,t){const n=new URLSearchParams;t!=null&&t.deleteExperiments&&n.set("delete_experiments","true");const r=n.toString(),l=await fetch(`${Z}/analysis/uploads/${encodeURIComponent(e)}${r?`?${r}`:""}`,{method:"DELETE"});if(!l.ok)throw new Error(await l.text());return await l.json().catch(()=>({}))}async function Xm(e,t="analysis_upload"){const n=new FormData;n.append("file",e),n.append("source",t);const r=await fetch(`${Z}/analysis/upload`,{method:"POST",body:n}),l=await ht(r);if(!r.ok)throw new Error(String(l.detail||r.status));return l}async function Jm(e){const t=await fetch(`${Z}/analysis/uploads/import_from_debug`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filename:e})}),n=await ht(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}async function Zm(e,t){const n=await fetch(`${Z}/analysis/solve/image`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input_name:e,...t})}),r=await ht(n);if(!n.ok)throw new Error(String(r.detail||n.status));return r}async function qm(e,t){const n=await fetch(`${Z}/analysis/solve/batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input_name:e,runs:t})}),r=await ht(n);if(!n.ok)throw new Error(String(r.detail||n.status));return r}async function Qo(e){const t=await fetch(`${Z}/analysis/presets?scope=${e}`);if(!t.ok)throw new Error(await t.text());return t.json()}async function eh(e,t){const n=await fetch(`${Z}/analysis/presets`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e,params:t})}),r=await ht(n);if(!n.ok)throw new Error(String(r.detail||n.status));return r}async function Ko(e){const t=await fetch(`${Z}/analysis/experiments`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}),n=await ht(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}async function th(e){const t=await fetch(`${Z}/analysis/experiments/${encodeURIComponent(e)}`,{method:"DELETE"});if(!t.ok)throw new Error(await t.text())}async function Go(e,t,n=30){const r=new URLSearchParams({page:String(t),page_size:String(n)});e&&r.set("q",e);const l=await fetch(`${Z}/analysis/experiments?${r}`);if(!l.ok)throw new Error(await l.text());return l.json()}async function nh(){const e=await fetch(`${Z}/debug/files`);if(!e.ok)throw new Error(await e.text());return e.json()}function rh(e){return`${Z}/debug/files/${encodeURIComponent(e)}`}async function Nu(e){const t=await fetch(`${Z}/debug/files/${encodeURIComponent(e)}/info`),n=await ht(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}async function lh(e){const t=await fetch(`${Z}/analysis/uploads/${encodeURIComponent(e)}/info`),n=await ht(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}function oh(e){return`${Z}/analysis/uploads/file?filename=${encodeURIComponent(e)}`}async function ju(e){const t=await fetch(`${Z}/analysis/experiments/export?format=${e}`);if(!t.ok)throw new Error(await t.text());return t.text()}async function ah(e){const t=await fetch(`${Z}/analysis/uploads/${encodeURIComponent(e)}/experiment_count`);if(!t.ok)throw new Error(await t.text());return t.json()}async function _u(e){const t=await fetch(`${Z}/analysis/solve/frame`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}),n=await ht(t);if(!t.ok)throw new Error(String(n.detail||t.status));return n}function sh(e){return`${Z}/analysis/experiments/${encodeURIComponent(e)}/asset`}async function ih(){const e=await fetch(`${Z}/system/info`);if(!e.ok)throw new Error(await e.text());return e.json()}function Bd(e,t,n,r,l){if(r){if(e.clearRect(0,0,t,n),l.all&&Array.isArray(r.stars_all_centroids)){e.fillStyle="rgba(156, 163, 175, 0.85)";for(const o of r.stars_all_centroids)e.beginPath(),e.arc(o.x,o.y,2.4,0,Math.PI*2),e.fill()}if(l.pattern&&Array.isArray(r.stars_pattern)){e.strokeStyle="rgba(251, 146, 60, 0.95)",e.lineWidth=2;for(const o of r.stars_pattern)e.beginPath(),e.arc(o.x,o.y,6,0,Math.PI*2),e.stroke()}if(l.matched&&Array.isArray(r.stars_matched)){e.strokeStyle="rgba(34, 197, 94, 0.95)",e.fillStyle="rgba(34, 197, 94, 0.95)",e.lineWidth=2,e.font="11px system-ui, sans-serif";for(const o of r.stars_matched)e.beginPath(),e.arc(o.x,o.y,7,0,Math.PI*2),e.stroke(),o.mag!=null&&e.fillText(`m${Number(o.mag).toFixed(1)}`,o.x+4,o.y-4)}}}function Cu(e,t,n,r){if(!n)return;const l=t.naturalWidth||1,o=t.naturalHeight||1;e.width=l,e.height=o,e.style.width=`${t.clientWidth}px`,e.style.height=`${t.clientHeight}px`;const a=e.getContext("2d");a&&Bd(a,l,o,n,r)}function uh(e,t,n,r){if(!n)return;const l=t.videoWidth||1,o=t.videoHeight||1;if(l<2||o<2)return;e.width=l,e.height=o,e.style.width=`${t.clientWidth}px`,e.style.height=`${t.clientHeight}px`;const a=e.getContext("2d");a&&Bd(a,l,o,n,r)}const ch={"app.title":"OGScope Plate Solve Console","nav.lab":"Lab","nav.labImage":"Image solve","nav.labVideo":"Video solve","delete.uploadCascade":"Delete {n} linked experiment record(s) as well?","lab.solveCurrentFrame":"Solve current frame (file)","lab.cameraPreviewLoading":"Connecting to shared preview…","lab.solveCameraFrame":"Solve live camera frame","lab.solveCameraStart":"Start camera solve","lab.solveCameraStop":"Stop camera solve","lab.videoPreviewFailed":"This video format may be unsupported by the browser. Try MP4 (H.264) or WebM.","lab.previewModeFile":"Pool file","lab.previewModeCamera":"Device camera","lab.videoLiveIntro":"Shares the same camera as Camera Debug — preview and solve live frames here without opening debug. Both pages can run together.","lab.cameraSnapshotName":"ogscope_camera_live","lab.metric.probRaw":"Raw Prob","lab.systemLoad":"System load","results.saveBatchAll":"Save all to records","nav.pool":"Assets","nav.history":"Records","nav.cameraDebug":"Camera Debug","nav.home":"Home","lang.zh":"中文","lang.en":"EN","sidebar.assets":"Uploaded assets","sidebar.upload":"Upload","sidebar.refresh":"Refresh","sidebar.debugCaptures":"Debug console media","sidebar.assetTypeImage":"Image","sidebar.assetTypeVideo":"Video","sidebar.debugEmpty":"No debug files","sidebar.importToPool":"Import to pool","sidebar.debugPage":"Page {cur} / {total}","sidebar.batchPresets":"Batch presets","sidebar.batchHint":"Check presets, then use Batch solve to compare multiple param sets.","lab.selectOrUpload":"Pick an uploaded or imported asset from the left","lab.selectOrUploadVideo":"Pick a pool video to preview, or use the button above for the live camera frame.","lab.file":"File","lab.source":"Source","lab.layers":"Layers","lab.layer.matched":"Matched","lab.layer.pattern":"Pattern","lab.layer.all":"All centroids","lab.grid":"Grid","lab.zoomIn":"Zoom in","lab.zoomOut":"Zoom out","lab.zoomReset":"Reset","lab.resolution":"Resolution","lab.fwhm":"FWHM","lab.starsDetected":"Stars detected","lab.meta.title":"Capture & file info","lab.meta.noSidecar":"No sidecar (not from debug capture)","lab.meta.partial":"No detailed sidecar; file info only.","lab.solveSection":"Solve","lab.imageSection":"Image","lab.metric.solveMs":"Time","lab.metric.solveComputeMs":"Solve compute","lab.metric.solveComputeHelp":"Server-side Tetra3 + star extraction only (no network).","lab.metric.solveRoundTripMs":"End-to-end","lab.metric.solveRoundTripHelp":"From request start to UI updated: network + JSON + render.","lab.metric.backendTotalMs":"Backend total","lab.metric.openDecodeMs":"Open/decode","lab.metric.preprocessMs":"Preprocess","lab.metric.extractMs":"Extract","lab.metric.solveOnlyMs":"Solve match","lab.metric.probHelp":"Solver confidence (0–1); higher means a more trustworthy plate match.","lab.metric.probRawHelp":"Raw Tetra3 Prob (e.g. log-likelihood); compare with the normalized line above.","lab.metric.radec":"RA / Dec","lab.metric.matches":"Matches","lab.metric.rmse":"RMSE","lab.metric.prob":"Prob.","lab.metric.status":"Status","meta.exposure":"Exposure","meta.gain":"Gain","meta.fps":"FPS","meta.sensor":"Sensor","meta.colorMode":"Color","meta.outputResolution":"Output size","meta.fileTime":"File time","meta.fileSize":"File size","results.viewRaw":"Raw JSON","results.hideRaw":"Hide","params.title":"Solve parameters","params.blockSolveIntro":"Plate-solve (Tetra3): FOV, timeout, and coarse sky hints. FOV should match your lens.","params.centroid":"Star detection","params.blockCentroidIntro":"Star detection: threshold, blob area, and local background window for centroids.","params.fov":"FOV estimate (°)","params.fovHelp":"Horizontal field of view for lost-in-space solve.","params.fovErr":"FOV max error (°)","params.fovErrHelp":"Search range around estimated FOV.","params.timeout":"Timeout (ms)","params.timeoutHelp":"Max wait time per solve.","params.solveProfile":"Solve profile","params.solveProfileHelp":"Speed/Balanced/Robust tune timeout, centroid thresholds, and matching star count together.","params.solveProfileSpeed":"Speed first","params.solveProfileBalanced":"Balanced","params.solveProfileRobust":"Robust first","params.ra":"RA hint (°)","params.raHelp":"Approximate right ascension in degrees.","params.dec":"Dec hint (°)","params.decHelp":"Approximate declination in degrees.","params.maxSide":"Max long side before extract (px)","params.maxSideHelp":"Downscale long edge for faster centroid extraction.","params.detailLevelFull":"Include full Tetra3 raw block (larger payload, for debugging only).","params.largeScaleBg":"Large-scale background flattening","params.largeScaleBgHelp":"Before centroiding, estimate a low-frequency background on a downscaled image and correct uneven illumination (e.g. corner glow). Off by default to match legacy behavior.","params.sigma":"σ threshold","params.sigmaHelp":"Multiplier over background noise for star candidates.","params.maxArea":"max_area","params.maxAreaHelp":"Max connected component area in pixels.","params.minArea":"min_area","params.minAreaHelp":"Min connected component area in pixels.","params.filtsize":"filtsize (odd)","params.filtsizeHelp":"Local filter window size, must be odd.","btn.solveOne":"Solve once","btn.solveBatch":"Batch solve (presets)","btn.applyPresets":"Apply preset to form","btn.savePreset":"Save","placeholder.newPreset":"New preset name","pool.title":"Server asset pool","pool.col.name":"Filename","pool.col.source":"Source","pool.col.size":"Size","pool.col.time":"Modified","pool.delete":"Delete","history.title":"Experiment records","history.intro":"Saved solve snapshots from the Lab. After a solve, use Save to records in the Lab main panel (Result comparison), or Save on each batch result card. Search by filename or preset; export JSON/CSV for backup.","history.search":"Search…","history.searchBtn":"Search","history.exportJson":"Export JSON","history.exportCsv":"Export CSV","history.total":"Total {n}","history.preset":"Preset","history.metrics":"Metrics","history.detail":"Details","history.collapse":"Collapse","history.prev":"Prev","history.next":"Next","history.delete":"Delete","delete.uploadFirst":'Delete "{name}" from the asset pool?',"delete.uploadSecond":"This cannot be undone. Confirm again?","delete.experimentFirst":"Delete this experiment record?","delete.experimentSecond":"This cannot be undone. Confirm again?","results.title":"Results","results.saveCurrent":"Save to records","results.saveRow":"Save","results.expand":"Expand","results.collapseJson":"Collapse","err.selectFile":"Select a file","err.selectPresets":"Select at least one preset","common.placeholder":"—"},dh={"app.title":"OGScope 星空解算控制台","nav.lab":"解算台","nav.labImage":"图片解算","nav.labVideo":"视频解算","nav.pool":"素材池","nav.history":"实验记录","nav.cameraDebug":"相机调试控制台","nav.home":"首页","lang.zh":"中文","lang.en":"EN","sidebar.assets":"自行上传素材","sidebar.upload":"上传文件","sidebar.refresh":"刷新列表","sidebar.debugCaptures":"调试控制台素材","sidebar.assetTypeImage":"图片","sidebar.assetTypeVideo":"视频","sidebar.debugEmpty":"暂无调试文件","sidebar.importToPool":"导入到素材池","sidebar.debugPage":"第 {cur} / {total} 页","sidebar.batchPresets":"批量预设","sidebar.batchHint":"勾选后点击「批量解算」可一次用多组参数对比结果。","lab.selectOrUpload":"从左侧选择自行上传或已导入的素材","lab.selectOrUploadVideo":"从左侧选择视频素材预览;或使用上方按钮解算设备相机实时帧。","lab.file":"文件","lab.source":"来源","lab.layers":"叠加层","lab.layer.matched":"匹配星","lab.layer.pattern":"图案星","lab.layer.all":"全部质心","lab.grid":"网格","lab.zoomIn":"放大","lab.zoomOut":"缩小","lab.zoomReset":"复位","lab.resolution":"分辨率","lab.fwhm":"FWHM","lab.starsDetected":"检测星点","lab.meta.title":"拍摄与文件信息","lab.meta.noSidecar":"无侧车信息(非调试采集或仅本地上传)","lab.meta.partial":"暂无侧车详细字段,仅显示文件信息。","lab.solveSection":"解算","lab.imageSection":"图像","lab.metric.solveMs":"用时","lab.metric.solveComputeMs":"解算计算用时","lab.metric.solveComputeHelp":"服务端 Tetra3 与提星等纯计算耗时(与网络无关)。","lab.metric.solveRoundTripMs":"全链路用时","lab.metric.solveRoundTripHelp":"从本页发起请求到收到结果并完成界面刷新的总耗时,含网络往返与浏览器渲染。","lab.metric.backendTotalMs":"后端总用时","lab.metric.openDecodeMs":"读取/解码","lab.metric.preprocessMs":"预处理","lab.metric.extractMs":"提星","lab.metric.solveOnlyMs":"匹配解算","lab.metric.probHelp":"由解算器给出的匹配置信度(0–1),越高表示星图与天区匹配越可信。","lab.metric.probRawHelp":"Tetra3 返回的原始 Prob 字段,可能为对数似然等内部量;与上一行换算后的百分比对照查看即可。","lab.metric.radec":"RA / Dec","lab.metric.matches":"匹配","lab.metric.rmse":"RMSE","lab.metric.prob":"置信","lab.metric.status":"状态","meta.exposure":"曝光","meta.gain":"增益","meta.fps":"帧率","meta.sensor":"传感器","meta.colorMode":"色彩","meta.outputResolution":"输出分辨率","meta.fileTime":"文件时间","meta.fileSize":"文件大小","results.viewRaw":"原始 JSON","results.hideRaw":"收起","params.title":"解算参数","params.blockSolveIntro":"以下为板块求解(Tetra3)搜索天区、超时与粗略指向提示;FOV 需与镜头视场大致一致。","params.centroid":"提星","params.blockCentroidIntro":"以下为星点检测:阈值、连通域面积与局部背景窗口,用于从图像中提取星点质心。","params.fov":"FOV 估计 (°)","params.fovHelp":"水平视场角估计值,用于 lost-in-space 解算。","params.fovErr":"FOV 允许误差 (°)","params.fovErrHelp":"允许 Tetra3 在估计 FOV 附近的搜索范围。","params.timeout":"超时 (ms)","params.timeoutHelp":"单次解算最长等待时间。","params.solveProfile":"解算档位","params.solveProfileHelp":"速度/平衡/稳健三档会同时调整超时、提星阈值与参与匹配星点数。","params.solveProfileSpeed":"速度优先","params.solveProfileBalanced":"平衡","params.solveProfileRobust":"稳健优先","params.ra":"RA 提示 (°)","params.raHelp":"大致天球赤经,缩小搜索范围(度)。","params.dec":"Dec 提示 (°)","params.decHelp":"大致天球赤纬(度)。","params.maxSide":"提星前长边上界 (px)","params.maxSideHelp":"降采样长边上限,大图可加速提星。","params.detailLevelFull":"包含完整 Tetra3 原始结果(体积略大,仅调试时开启)","params.largeScaleBg":"大尺度背景减除","params.largeScaleBgHelp":"在提星前用低分辨率平滑估计并校正大尺度亮度不均,可减轻角部光晕导致的假星;默认关闭以保持与过往行为一致。","params.sigma":"σ(阈值倍数)","params.sigmaHelp":"高于背景噪声倍数的区域视为星点候选。","params.maxArea":"max_area","params.maxAreaHelp":"连通域最大像素面积。","params.minArea":"min_area","params.minAreaHelp":"连通域最小像素面积。","params.filtsize":"filtsize(奇数)","params.filtsizeHelp":"局部背景滤波窗口边长,须为奇数。","btn.solveOne":"单张解算","btn.solveBatch":"批量解算(勾选预设)","btn.applyPresets":"应用预设到表单","btn.savePreset":"保存","placeholder.newPreset":"新预设名称","pool.title":"服务器素材池","pool.col.name":"文件名","pool.col.source":"来源","pool.col.size":"大小","pool.col.time":"修改时间","pool.delete":"删除","history.title":"实验记录","history.intro":"此处展示你在解算台完成解算后手动保存的快照。用法:在「解算台」主栏「结果对比」中,单张解算后点「保存当前到实验记录」,或批量解算后在某张结果卡片上点「保存记录」。本页可按文件名或预设名搜索,支持导出 JSON/CSV 备份。","history.search":"搜索…","history.searchBtn":"搜索","history.exportJson":"导出 JSON","history.exportCsv":"导出 CSV","history.total":"共 {n} 条","history.preset":"预设","history.metrics":"指标","history.detail":"详情","history.collapse":"收起","history.prev":"上一页","history.next":"下一页","history.delete":"删除","delete.uploadFirst":"确定要从素材池删除「{name}」吗?","delete.uploadSecond":"此操作不可恢复,再次确认删除?","delete.experimentFirst":"确定要删除这条实验记录吗?","delete.experimentSecond":"此操作不可恢复,再次确认删除?","results.title":"结果对比","results.saveCurrent":"保存当前到实验记录","results.saveRow":"保存记录","results.expand":"展开","results.collapseJson":"收起","err.selectFile":"请选择素材","err.selectPresets":"请勾选至少一个预设","common.placeholder":"—","delete.uploadCascade":"该素材有 {n} 条实验记录,是否一并删除?","lab.solveCurrentFrame":"解算当前帧(文件)","lab.cameraPreviewLoading":"正在连接共享预览…","lab.solveCameraFrame":"解算相机当前帧","lab.solveCameraStart":"开始相机解算","lab.solveCameraStop":"停止相机解算","lab.videoPreviewFailed":"该视频格式可能不受浏览器支持,建议使用 MP4(H.264) 或 WebM。","lab.previewModeFile":"素材文件","lab.previewModeCamera":"设备相机","lab.videoLiveIntro":"与调试控制台共用同一相机;此处可预览并解算实时帧,无需单独打开调试页。两页可同时使用。","lab.cameraSnapshotName":"ogscope_camera_live","lab.metric.probRaw":"原始 Prob","lab.systemLoad":"系统负载","results.saveBatchAll":"保存全部到实验记录"},Vd=S.createContext(null),Eu={zh:dh,en:ch};function fh({children:e}){const[t,n]=S.useState("zh"),[r,l]=S.useState(Eu.zh);S.useEffect(()=>{l(Eu[t])},[t]);const o=S.useMemo(()=>(i,u)=>{let f=r[i]??i;if(u)for(const[h,y]of Object.entries(u))f=f.replace(new RegExp(`\\{${h}\\}`,"g"),String(y));return f},[r]),a=S.useMemo(()=>({locale:t,setLocale:n,t:o}),[t,o]);return s.jsx(Vd.Provider,{value:a,children:e})}function Wd(){const e=S.useContext(Vd);if(!e)throw new Error("useI18n must be used within I18nProvider");return e}function Wa(e){return e==null||Number.isNaN(e)?"—":e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(2)} MB`}function hl(e,t){if(!e)return"—";try{const n=new Date(e);return new Intl.DateTimeFormat(t==="en"?"en-GB":"zh-CN",{dateStyle:"short",timeStyle:"medium"}).format(n)}catch{return e}}function Ut(e){return e==null?null:typeof e=="string"&&e.trim()?e.trim():typeof e=="number"&&!Number.isNaN(e)?String(e):null}function ph(e){return typeof e!="number"||e<=0?null:e>=1e6?`${(e/1e6).toFixed(2)} s`:e>=1e3?`${(e/1e3).toFixed(0)} ms`:`${e} µs`}function mh(e,t){if(!e)return[];const n=[],r=ph(e.exposure_us);r&&n.push({key:"meta.exposure",value:r});const l=Ut(e.analogue_gain),o=Ut(e.digital_gain);if(l||o){const v=[l?`A ${l}`:"",o?`D ${o}`:""].filter(Boolean);n.push({key:"meta.gain",value:v.join(" · ")})}const a=Ut(e.fps);a&&n.push({key:"meta.fps",value:a});const i=Ut(e.sensor);i&&n.push({key:"meta.sensor",value:i});const u=Ut(e.color_mode);u&&n.push({key:"meta.colorMode",value:u});const f=Ut(e.resolution);f&&n.push({key:"meta.outputResolution",value:f});const h=Ut(e.modified);h&&n.push({key:"meta.fileTime",value:hl(h,t)});const y=e.size;return typeof y=="number"&&y>0&&n.push({key:"meta.fileSize",value:Wa(y)}),n}function Qd(e){const t=n=>typeof n=="number"&&!Number.isNaN(n)?n:null;return e?{tSolveMs:t(e.t_solve_ms),tExtractMs:t(e.t_extract_ms),tPreprocessMs:t(e.t_preprocess_ms),tOpenDecodeMs:t(e.t_open_decode_ms),tBackendTotalMs:t(e.t_backend_total_ms),raDeg:t(e.ra_deg),decDeg:t(e.dec_deg),matches:t(e.matches),rmseArcsec:t(e.rmse_arcsec),prob:t(e.prob),status:typeof e.status=="string"?e.status:null}:{tSolveMs:null,tExtractMs:null,tPreprocessMs:null,tOpenDecodeMs:null,tBackendTotalMs:null,raDeg:null,decDeg:null,matches:null,rmseArcsec:null,prob:null,status:null}}function $l(e){return e==null?"—":`${e.toFixed(4)}°`}function hh(e){return e==null?"—":e>=0&&e<=1?`${(e*100).toFixed(1)}%`:String(e)}function vh(e){if(e==null)return"—";if(typeof e=="number"&&!Number.isNaN(e)){const t=Math.abs(e);return t>0&&t<.001?e.toExponential(4):t>=0&&t<=1?`${(e*100).toFixed(4)}%`:String(e)}return String(e)}function Cn(e,t){const n=t==null?void 0:t.tetra,r=n?n.Prob??n.prob:void 0;let l=hh(e);e!=null&&e>=0&&e<=1&&e>0&&e<1e-4&&(l=`${(e*100).toExponential(2)}%`),e===0&&r!==void 0&&r!==null&&(l="—");const o=r!=null?vh(r):null;return{line:l,rawLine:o}}const Yo=()=>({hint_ra_deg:45,hint_dec_deg:80,fov_estimate:11,fov_max_error:void 0,solve_timeout_ms:1500,solve_profile:"balanced",max_image_side:1600,large_scale_bg_subtract:!1,detail_level:"summary",centroid:{sigma:2.5,max_area:400,min_area:5,filtsize:25,binary_open:!0,max_axis_ratio:void 0}});function Xo(e){return e?{matches:e.matches,rmse_arcsec:e.rmse_arcsec,status:e.status,prob:e.prob,t_solve_ms:e.t_solve_ms}:{}}function yh(e){var n,r;if(!e)return null;const t=e.solve_overlay;return(n=t==null?void 0:t.stars_matched)!=null&&n.length?t.stars_matched.length:(r=t==null?void 0:t.stars_all_centroids)!=null&&r.length?t.stars_all_centroids.length:typeof e.matches=="number"?e.matches:null}const nl=30,Jo=6;function Pu(e){return/\.(jpe?g|png|webp|bmp|gif|fits?)$/i.test(e)}function an(e){return/\.(mp4|mov|webm|mkv|avi)$/i.test(e)}function gh(){var ei,ti,ni,ri,li,oi,ai,si;const{t:e,locale:t,setLocale:n}=Wd(),[r,l]=S.useState("lab_image"),[o,a]=S.useState([]),[i,u]=S.useState(null),[f,h]=S.useState(Yo),[y,v]=S.useState([]),[N,j]=S.useState([]),[_,$]=S.useState(new Set),[p,d]=S.useState(!1),[m,g]=S.useState(null),[k,b]=S.useState(null),[C,M]=S.useState(null),[U,L]=S.useState(""),[ne,et]=S.useState(1),[me,en]=S.useState(null),[Mr,tn]=S.useState(null),[It,E]=S.useState(""),[R,T]=S.useState({matched:!0,pattern:!0,all:!0}),[H,X]=S.useState([]),[je,Ke]=S.useState(null),[tt,_e]=S.useState(1),[nt,$s]=S.useState(!1),[nn,ro]=S.useState(1),[Hs,Kd]=S.useState({w:0,h:0}),[As,Gd]=S.useState({w:0,h:0}),[Bs,Yd]=S.useState({w:0,h:0}),[re,zr]=S.useState("file"),[lo,Vs]=S.useState(null),[Ws,oo]=S.useState(null),[ao,Qs]=S.useState(!1),[so,Rr]=S.useState(null),[io,Ks]=S.useState(!1),[Xd,uo]=S.useState({}),[Gs,co]=S.useState(!1),[fo,rt]=S.useState(null),[Jd,In]=S.useState(null),po=S.useRef(null),Dn=S.useRef(null),Ys=S.useRef(null),Tr=S.useRef(null),Lr=S.useRef(null),mo=S.useRef(!1),rn=S.useRef(null),[Or,Zd]=S.useState(null),Dt=S.useCallback(async()=>{const[c,x,z]=await Promise.all([Gm(),Qo("official"),Qo("user")]);a(c.files),v(x.presets),j(z.presets)},[]),ho=S.useCallback(()=>{nh().then(c=>X(c.files)).catch(()=>X([]))},[]);S.useEffect(()=>{Dt().catch(c=>g(String(c)))},[Dt]),S.useEffect(()=>{ho()},[ho]),S.useEffect(()=>{r==="history"&&Go(U,ne,nl).then(en).catch(c=>g(String(c)))},[r,U,ne]),S.useEffect(()=>{if(!i){Rr(null);return}let c=!1;return Ks(!0),(async()=>{try{const x=await lh(i);if(c)return;let z={...x};try{z={...await Nu(i),...x}}catch{}Rr(z)}catch{try{const x=await Nu(i);c||Rr(x)}catch{c||Rr(null)}}finally{c||Ks(!1)}})(),()=>{c=!0}},[i]),S.useEffect(()=>{b(null),M(null),uo({}),co(!1),rt(null),In(null),zr("file"),oo(null)},[i]);const lt=S.useMemo(()=>{const c=k==null?void 0:k.result;return c&&c.solve_overlay||null},[k]),vt=S.useMemo(()=>(k==null?void 0:k.result)??null,[k]),Xs=S.useMemo(()=>yh(vt),[vt]),vo=S.useMemo(()=>r==="lab_image"?Hs:r==="lab_video"?re==="file"?As:Bs:{w:0,h:0},[r,re,Hs,As,Bs]),Fr=i?oh(i):"";S.useEffect(()=>{if(r!=="lab_image")return;const c=po.current,x=rn.current;if(!c||!x||!lt||!i)return;const z=()=>Cu(x,c,lt,R);c.complete?z():c.onload=z},[lt,i,k,R,r]),S.useEffect(()=>{if(r!=="lab_video"||re!=="file")return;const c=Dn.current,x=rn.current;if(!c||!x||!lt||!i)return;const z=()=>uh(x,c,lt,R);return c.addEventListener("loadeddata",z),c.addEventListener("seeked",z),c.readyState>=2&&z(),()=>{c.removeEventListener("loadeddata",z),c.removeEventListener("seeked",z)}},[lt,R,r,re,i,k]),S.useEffect(()=>{if(r!=="lab_video"||re!=="camera")return;const c=Ys.current,x=rn.current;if(!c||!x||!lt)return;const z=()=>Cu(x,c,lt,R);c.complete?z():c.onload=z},[lt,R,r,re,k,lo]),S.useEffect(()=>{if(r!=="lab_video"||re!=="camera")return;let c=!1;const x=async()=>{if(!c)try{const le=Tr.current?`?since_frame_id=${encodeURIComponent(Tr.current)}`:"",Te=await fetch(`/api/camera/preview${le}`,{cache:"no-store"});if(Te.status===304||!Te.ok)return;const Dr=Te.headers.get("X-Frame-Id");Dr!=null&&(Tr.current=Dr);const uf=await Te.blob(),cf=URL.createObjectURL(uf);Vs(ii=>(ii&&URL.revokeObjectURL(ii),cf))}catch{}};x();const z=window.setInterval(()=>void x(),180);return()=>{c=!0,clearInterval(z),Vs(le=>(le&&URL.revokeObjectURL(le),null)),Tr.current=null}},[r,re]),S.useEffect(()=>{const c=po.current;if(!c)return;const x=()=>Kd({w:c.naturalWidth||0,h:c.naturalHeight||0});return x(),c.addEventListener("load",x),()=>c.removeEventListener("load",x)},[i,Fr]),S.useEffect(()=>{const c=Dn.current;if(!c)return;const x=()=>Gd({w:c.videoWidth||0,h:c.videoHeight||0});return c.addEventListener("loadedmetadata",x),c.addEventListener("loadeddata",x),x(),()=>{c.removeEventListener("loadedmetadata",x),c.removeEventListener("loadeddata",x)}},[i,Fr,r]);const qd=c=>{h({...Yo(),...c,centroid:{...Yo().centroid,...c.centroid}})},ef=async()=>{if(!i){g(e("err.selectFile"));return}g(null),d(!0);const c=performance.now();try{const x=await Zm(i,f);b(x),M(null),In("file"),rt(performance.now()-c)}catch(x){g(String(x)),rt(null)}finally{d(!1)}},tf=async()=>{if(!i){g(e("err.selectFile"));return}const c=[];for(const z of _){const Te=[...y,...N].find(Dr=>Dr.id===z);Te&&c.push({label:Te.name,params:structuredClone(Te.params)})}if(c.length===0){g(e("err.selectPresets"));return}g(null),d(!0);const x=performance.now();try{const z=await qm(i,c);M({results:z.results}),b(null),uo({}),In("file"),rt(performance.now()-x)}catch(z){g(String(z)),rt(null)}finally{d(!1)}},yo=async()=>{if(mo.current)return;g(null),d(!0),mo.current=!0;const c=performance.now();try{const x=await _u({source:"camera",...f});b(x),M(null),In("camera"),zr("camera"),rt(performance.now()-c)}catch(x){g(String(x)),rt(null)}finally{mo.current=!1,d(!1)}},nf=async()=>{if(!i)return;g(null),d(!0);const c=performance.now();try{const x=Dn.current,z=await _u({source:"file",input_name:i,time_sec:(x==null?void 0:x.currentTime)??0,...f});b(z),M(null),In("file"),rt(performance.now()-c)}catch(x){g(String(x)),rt(null)}finally{d(!1)}},rf=()=>{ao||(Qs(!0),yo(),Lr.current=window.setInterval(()=>{yo()},1200))},go=()=>{Qs(!1),Lr.current!=null&&(window.clearInterval(Lr.current),Lr.current=null)},lf=c=>{$(x=>{const z=new Set(x);return z.has(c)?z.delete(c):z.add(c),z})},Js=async c=>{if(!window.confirm(e("delete.uploadFirst",{name:c})))return;let x=0;try{x=(await ah(c)).count}catch{x=0}if(x>0){if(!window.confirm(e("delete.uploadCascade",{n:x})))return}else if(!window.confirm(e("delete.uploadSecond")))return;d(!0),g(null);try{await Ym(c,{deleteExperiments:x>0}),await Dt(),i===c&&u(null)}catch(z){g(String(z))}finally{d(!1)}},of=async c=>{if(window.confirm(e("delete.experimentFirst"))&&window.confirm(e("delete.experimentSecond"))){d(!0),g(null);try{await th(c),Mr===c&&tn(null);const x=await Go(U,ne,nl);en(x)}catch(x){g(String(x))}finally{d(!1)}}},Ir=c=>ro(Math.min(4,Math.max(.5,c))),Zs=Math.max(1,Math.ceil(((me==null?void 0:me.total)??0)/nl)),ln=S.useMemo(()=>r==="lab_image"?H.filter(c=>c.type==="image"||Pu(c.name)):r==="lab_video"?H.filter(c=>c.type==="video"||an(c.name)):H,[H,r]),Un=Math.max(1,Math.ceil(ln.length/Jo)),af=S.useMemo(()=>{const c=(tt-1)*Jo;return ln.slice(c,c+Jo)},[ln,tt]);S.useEffect(()=>{_e(1)},[r]),S.useEffect(()=>{_e(c=>Math.min(c,Un))},[Un]),S.useEffect(()=>{je&&!ln.some(c=>c.name===je)&&Ke(null)},[ln,je]);const qs=S.useMemo(()=>mh(so,t),[so,t]),sf=S.useMemo(()=>r==="lab_image"?o.filter(c=>Pu(c.filename)):r==="lab_video"?o.filter(c=>an(c.filename)):o,[o,r]),I=S.useMemo(()=>Qd(vt),[vt]);return S.useEffect(()=>{co(!1)},[k]),S.useEffect(()=>{if(r!=="lab_video")return;let c;const x=()=>{ih().then(Zd).catch(()=>{})};return x(),c=setInterval(x,1500),()=>{c&&clearInterval(c)}},[r]),S.useEffect(()=>{(r!=="lab_video"||re!=="camera")&&go()},[r,re]),S.useEffect(()=>()=>{go()},[]),s.jsxs("div",{className:"flex min-h-full flex-col bg-surface text-on-surface",children:[s.jsxs("header",{className:"flex h-12 shrink-0 items-center justify-between border-b border-outline-variant/20 px-4",children:[s.jsxs("div",{className:"flex items-center gap-6",children:[s.jsx("span",{className:"font-headline text-sm font-bold tracking-wide text-on-surface",children:e("app.title")}),s.jsxs("nav",{className:"flex flex-wrap gap-3 text-xs",children:[s.jsx("button",{type:"button",className:r==="lab_image"?"text-primary":"text-on-surface-variant",onClick:()=>l("lab_image"),children:e("nav.labImage")}),s.jsx("button",{type:"button",className:r==="lab_video"?"text-primary":"text-on-surface-variant",onClick:()=>l("lab_video"),children:e("nav.labVideo")}),s.jsx("button",{type:"button",className:r==="pool"?"text-primary":"text-on-surface-variant",onClick:()=>l("pool"),children:e("nav.pool")}),s.jsx("button",{type:"button",className:r==="history"?"text-primary":"text-on-surface-variant",onClick:()=>l("history"),children:e("nav.history")})]})]}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsxs("div",{className:"mr-2 flex gap-1 text-[10px]",children:[s.jsx("button",{type:"button",className:`rounded px-2 py-0.5 ${t==="zh"?"bg-primary-container text-on-primary-container":"text-on-surface-variant"}`,onClick:()=>n("zh"),children:e("lang.zh")}),s.jsx("button",{type:"button",className:`rounded px-2 py-0.5 ${t==="en"?"bg-primary-container text-on-primary-container":"text-on-surface-variant"}`,onClick:()=>n("en"),children:e("lang.en")})]}),s.jsxs("a",{className:"flex items-center gap-1 rounded border border-outline-variant/30 px-2 py-1 text-xs text-on-surface-variant hover:bg-surface-container",href:"/debug",children:[s.jsx(Bm,{className:"h-3.5 w-3.5"})," ",e("nav.cameraDebug")]}),s.jsxs("a",{className:"flex items-center gap-1 rounded border border-outline-variant/30 px-2 py-1 text-xs text-on-surface-variant hover:bg-surface-container",href:"/",children:[s.jsx(Wm,{className:"h-3.5 w-3.5"})," ",e("nav.home")]})]})]}),s.jsxs("div",{className:"flex min-h-0 flex-1",children:[s.jsxs("aside",{className:"w-64 shrink-0 border-r border-outline-variant/15 bg-surface-container-lowest p-3 text-xs",children:[s.jsx("div",{className:"mb-3 font-semibold text-on-surface-variant",children:e("sidebar.assets")}),s.jsxs("label",{className:"mb-3 flex cursor-pointer items-center gap-2 rounded bg-primary-container/30 px-2 py-2 text-on-primary-container",children:[s.jsx(Km,{className:"h-4 w-4"}),s.jsx("span",{children:e("sidebar.upload")}),s.jsx("input",{type:"file",accept:"image/*,video/*",className:"hidden",onChange:async c=>{var z;const x=(z=c.target.files)==null?void 0:z[0];if(x){d(!0),g(null);try{const le=await Xm(x);await Dt(),u(le.filename)}catch(le){g(String(le))}finally{d(!1),c.target.value=""}}}})]}),s.jsxs("button",{type:"button",className:"mb-2 flex w-full items-center gap-1 text-left text-on-surface-variant hover:text-on-surface",onClick:()=>{Dt().catch(c=>g(String(c))),_e(1),ho()},children:[s.jsx(Qm,{className:"h-3 w-3"})," ",e("sidebar.refresh")]}),s.jsx("div",{className:"max-h-36 overflow-y-auto border-t border-outline-variant/10 pt-2",children:sf.map(c=>s.jsxs("div",{className:`mb-1 flex items-center gap-0.5 rounded px-1 ${i===c.filename?"bg-surface-container":""}`,children:[s.jsxs("button",{type:"button",className:`min-w-0 flex-1 truncate rounded px-1 py-1 text-left ${i===c.filename?"text-primary":""}`,title:c.filename,onClick:()=>{u(c.filename),l(an(c.filename)?"lab_video":"lab_image")},children:[s.jsx("span",{className:"block truncate",children:c.filename}),s.jsx("span",{className:"block text-[9px] text-on-surface-variant/90",children:an(c.filename)?e("sidebar.assetTypeVideo"):e("sidebar.assetTypeImage")})]}),s.jsx("button",{type:"button",className:"shrink-0 rounded p-1 text-on-surface-variant hover:bg-surface-container-high hover:text-error",title:e("pool.delete"),"aria-label":e("pool.delete"),onClick:x=>{x.stopPropagation(),Js(c.filename)},children:s.jsx(wu,{className:"h-3.5 w-3.5"})})]},c.filename))}),s.jsxs("div",{className:"mt-3 border-t border-outline-variant/10 pt-3",children:[s.jsxs("div",{className:"mb-2 flex items-start justify-between gap-2",children:[s.jsx("div",{className:"min-w-0 font-semibold leading-tight text-on-surface-variant",children:e("sidebar.debugCaptures")}),s.jsx("button",{type:"button",className:"shrink-0 rounded bg-primary px-2 py-1 text-[10px] font-medium text-on-primary disabled:opacity-40",disabled:!je,title:je??void 0,onClick:async()=>{if(je){d(!0);try{const c=await Jm(je);await Dt(),u(c.filename),l(an(c.filename)?"lab_video":"lab_image")}catch(c){g(String(c))}finally{d(!1)}}},children:e("sidebar.importToPool")})]}),ln.length===0?s.jsx("p",{className:"text-[10px] text-on-surface-variant",children:e("sidebar.debugEmpty")}):s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"max-h-[min(22rem,55vh)] space-y-1.5 overflow-y-auto pr-0.5",children:af.map(c=>s.jsxs("button",{type:"button",className:`flex w-full items-center gap-2 rounded-md border px-2 py-1.5 text-left transition-colors ${je===c.name?"border-primary bg-primary-container/20":"border-outline-variant/25 hover:bg-surface-container"}`,onClick:()=>Ke(c.name),children:[c.type==="image"?s.jsx("img",{src:rh(c.name),alt:"",className:"h-11 w-11 shrink-0 rounded object-cover"}):s.jsx("div",{className:"flex h-11 w-11 shrink-0 items-center justify-center rounded bg-surface-container-high text-[9px] text-on-surface-variant",children:"video"}),s.jsxs("div",{className:"min-w-0 flex-1",children:[s.jsx("div",{className:"truncate font-mono text-[10px] text-on-surface",title:c.name,children:c.name}),s.jsxs("div",{className:"text-[9px] text-on-surface-variant",children:[c.type==="video"||an(c.name)?e("sidebar.assetTypeVideo"):e("sidebar.assetTypeImage")," ","· ",hl(c.modified,t)," · ",Wa(c.size)]})]})]},c.name))}),s.jsxs("div",{className:"mt-2 flex items-center justify-between gap-1 text-[10px] text-on-surface-variant",children:[s.jsx("button",{type:"button",className:"rounded border border-outline-variant/30 px-2 py-0.5 disabled:opacity-40",disabled:tt<=1,onClick:()=>_e(c=>Math.max(1,c-1)),children:e("history.prev")}),s.jsx("span",{className:"tabular-nums",children:e("sidebar.debugPage",{cur:tt,total:Un})}),s.jsx("button",{type:"button",className:"rounded border border-outline-variant/30 px-2 py-0.5 disabled:opacity-40",disabled:tt>=Un,onClick:()=>_e(c=>Math.min(Un,c+1)),children:e("history.next")})]})]})]})]}),(r==="lab_image"||r==="lab_video")&&s.jsxs("div",{className:"flex min-h-0 min-w-0 flex-1",children:[s.jsxs("main",{className:"min-h-0 min-w-0 flex-1 overflow-y-auto p-4",children:[m&&s.jsx("div",{className:"mb-2 rounded border border-error/40 bg-error-container/20 px-3 py-2 text-xs text-error",children:m}),r==="lab_video"&&s.jsxs("div",{className:"mb-3 max-w-5xl rounded-lg border border-outline-variant/25 bg-surface-container-low/80 p-3 text-[11px] leading-relaxed text-on-surface",children:[s.jsx("p",{className:"text-[10px] text-on-surface-variant",children:e("lab.videoLiveIntro")}),s.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[s.jsx("button",{type:"button",className:`rounded px-3 py-1.5 text-[11px] font-medium ${re==="file"?"bg-primary text-on-primary-container":"border border-outline-variant/40 bg-surface-container text-on-surface"}`,onClick:()=>zr("file"),children:e("lab.previewModeFile")}),s.jsx("button",{type:"button",className:`rounded px-3 py-1.5 text-[11px] font-medium ${re==="camera"?"bg-primary text-on-primary-container":"border border-outline-variant/40 bg-surface-container text-on-surface"}`,onClick:()=>zr("camera"),children:e("lab.previewModeCamera")})]})]}),s.jsxs("div",{className:"relative aspect-video w-full max-w-5xl overflow-hidden rounded-lg border border-outline-variant/20 bg-surface-container-lowest",children:[r==="lab_video"&&re==="camera"?s.jsx("div",{className:"relative flex h-full min-h-[220px] flex-col items-center justify-center gap-3 bg-black p-2",children:s.jsxs("div",{className:"relative inline-block max-h-[70vh] max-w-full",children:[lo?s.jsx("img",{ref:Ys,src:lo,alt:"",className:"max-h-[70vh] w-full min-h-[120px] object-contain",onLoad:c=>Yd({w:c.currentTarget.naturalWidth,h:c.currentTarget.naturalHeight})}):s.jsxs("div",{className:"flex min-h-[200px] w-full min-w-[280px] flex-col items-center justify-center gap-2 text-[11px] text-on-surface-variant",children:[s.jsx(Wo,{className:"h-8 w-8 animate-spin text-primary"}),s.jsx("span",{children:e("lab.cameraPreviewLoading")})]}),s.jsx("canvas",{ref:rn,className:"pointer-events-none absolute left-0 top-0"})]})}):i?s.jsx("div",{className:"relative h-full min-h-[200px] overflow-auto",children:r==="lab_video"?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"absolute left-2 top-2 z-20 flex flex-wrap gap-1",children:[s.jsxs("button",{type:"button",title:e("lab.grid"),className:`rounded border px-2 py-1 text-[10px] ${nt?"border-primary bg-primary/20":"border-white/30 bg-black/40"} text-white`,onClick:()=>$s(c=>!c),children:[s.jsx(gu,{className:"mr-1 inline h-3 w-3"}),e("lab.grid")]}),s.jsx("button",{type:"button",title:e("lab.zoomOut"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>Ir(nn-.25),children:s.jsx(ku,{className:"inline h-3 w-3"})}),s.jsx("button",{type:"button",title:e("lab.zoomIn"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>Ir(nn+.25),children:s.jsx(Su,{className:"inline h-3 w-3"})}),s.jsx("button",{type:"button",title:e("lab.zoomReset"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>ro(1),children:s.jsx(xu,{className:"inline h-3 w-3"})})]}),s.jsxs("div",{className:"flex min-h-[200px] flex-col items-center justify-center gap-2 bg-black py-2",children:[s.jsx("div",{className:"inline-block origin-top-left transition-transform",style:{transform:`scale(${nn})`},children:s.jsxs("div",{className:"relative inline-block",children:[nt&&s.jsx("div",{className:"pointer-events-none absolute inset-0 z-[1]",style:{backgroundImage:["linear-gradient(to right, rgba(255,255,255,0.12) 1px, transparent 1px)","linear-gradient(to bottom, rgba(255,255,255,0.12) 1px, transparent 1px)"].join(","),backgroundSize:"48px 48px"}}),s.jsx("video",{ref:Dn,src:Fr,loop:!0,playsInline:!0,autoPlay:!0,muted:!0,preload:"metadata",controls:!0,className:"max-h-[70vh] w-full max-w-full object-contain",onError:()=>oo(e("lab.videoPreviewFailed")),onLoadedData:()=>{oo(null);const c=Dn.current;c&&c.play().catch(()=>{})}}),s.jsx("canvas",{ref:rn,className:"pointer-events-none absolute left-0 top-0"})]})}),Ws&&s.jsx("div",{className:"rounded border border-error/40 bg-error-container/20 px-3 py-1.5 text-[11px] text-error",children:Ws})]})]}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"absolute left-2 top-2 z-20 flex flex-wrap gap-1",children:[s.jsxs("button",{type:"button",title:e("lab.grid"),className:`rounded border px-2 py-1 text-[10px] ${nt?"border-primary bg-primary/20":"border-white/30 bg-black/40"} text-white`,onClick:()=>$s(c=>!c),children:[s.jsx(gu,{className:"mr-1 inline h-3 w-3"}),e("lab.grid")]}),s.jsx("button",{type:"button",title:e("lab.zoomOut"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>Ir(nn-.25),children:s.jsx(ku,{className:"inline h-3 w-3"})}),s.jsx("button",{type:"button",title:e("lab.zoomIn"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>Ir(nn+.25),children:s.jsx(Su,{className:"inline h-3 w-3"})}),s.jsx("button",{type:"button",title:e("lab.zoomReset"),className:"rounded border border-white/30 bg-black/40 px-2 py-1 text-[10px] text-white",onClick:()=>ro(1),children:s.jsx(xu,{className:"inline h-3 w-3"})})]}),s.jsx("div",{className:"inline-block origin-top-left transition-transform",style:{transform:`scale(${nn})`},children:s.jsxs("div",{className:"relative inline-block",children:[nt&&s.jsx("div",{className:"pointer-events-none absolute inset-0 z-[1]",style:{backgroundImage:["linear-gradient(to right, rgba(255,255,255,0.12) 1px, transparent 1px)","linear-gradient(to bottom, rgba(255,255,255,0.12) 1px, transparent 1px)"].join(","),backgroundSize:"48px 48px"}}),s.jsx("img",{ref:po,src:Fr,alt:"preview",className:"max-h-[70vh] w-full object-contain"}),s.jsx("canvas",{ref:rn,className:"pointer-events-none absolute left-0 top-0"})]})})]})}):s.jsx("div",{className:"flex h-full items-center justify-center px-4 text-center text-on-surface-variant",children:e(r==="lab_video"?"lab.selectOrUploadVideo":"lab.selectOrUpload")}),p&&s.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-black/40",children:s.jsx(Wo,{className:"h-8 w-8 animate-spin text-primary"})})]}),(i&&r==="lab_image"||r==="lab_video"&&(re==="file"&&i||re==="camera"))&&s.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-3 rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90 px-3 py-2 text-xs text-on-surface",children:[s.jsx("span",{className:"shrink-0 font-medium text-on-surface-variant",children:e("lab.layers")}),s.jsx("div",{className:"flex flex-wrap gap-x-4 gap-y-1",children:["matched","pattern","all"].map(c=>s.jsxs("label",{className:"flex cursor-pointer items-center gap-1",children:[s.jsx("input",{type:"checkbox",className:"accent-primary",checked:R[c],onChange:x=>T(z=>({...z,[c]:x.target.checked}))}),s.jsx("span",{children:e(c==="matched"?"lab.layer.matched":c==="pattern"?"lab.layer.pattern":"lab.layer.all")})]},c))})]}),(i||r==="lab_video"&&re==="camera")&&s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"mt-2 grid gap-2 sm:grid-cols-2",children:[s.jsxs("details",{open:!0,className:"rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-2 px-3 py-2 text-xs font-semibold text-on-surface [&::-webkit-details-marker]:hidden",children:[e("lab.solveSection"),s.jsx(Gn,{className:"h-4 w-4 shrink-0 text-on-surface-variant"})]}),s.jsx("div",{className:"border-t border-outline-variant/15 px-3 py-2 text-[10px]",children:vt?s.jsxs("div",{className:"space-y-1 text-on-surface",children:[I.tSolveMs!=null&&s.jsxs("div",{className:"space-y-0.5",children:[s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.solveComputeMs")}),s.jsxs("span",{className:"font-mono tabular-nums",children:[I.tSolveMs.toFixed(0)," ms"]})]}),s.jsx("p",{className:"text-[8px] leading-snug text-on-surface-variant/90",children:e("lab.metric.solveComputeHelp")})]}),fo!=null&&s.jsxs("div",{className:"space-y-0.5 border-t border-outline-variant/10 pt-1",children:[s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.solveRoundTripMs")}),s.jsxs("span",{className:"font-mono tabular-nums",children:[fo.toFixed(0)," ms"]})]}),s.jsx("p",{className:"text-[8px] leading-snug text-on-surface-variant/90",children:e("lab.metric.solveRoundTripHelp")})]}),(I.tBackendTotalMs!=null||I.tOpenDecodeMs!=null||I.tPreprocessMs!=null||I.tExtractMs!=null||I.tSolveMs!=null)&&s.jsxs("div",{className:"space-y-0.5 border-t border-outline-variant/10 pt-1",children:[s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.backendTotalMs")}),s.jsx("span",{className:"font-mono tabular-nums",children:I.tBackendTotalMs!=null?`${I.tBackendTotalMs.toFixed(0)} ms`:e("common.placeholder")})]}),s.jsxs("div",{className:"flex flex-wrap gap-x-2 gap-y-0.5 text-[8px] text-on-surface-variant/90",children:[s.jsxs("span",{children:[e("lab.metric.openDecodeMs"),":"," ",I.tOpenDecodeMs!=null?`${I.tOpenDecodeMs.toFixed(0)} ms`:e("common.placeholder")]}),s.jsxs("span",{children:[e("lab.metric.preprocessMs"),":"," ",I.tPreprocessMs!=null?`${I.tPreprocessMs.toFixed(0)} ms`:e("common.placeholder")]}),s.jsxs("span",{children:[e("lab.metric.extractMs"),":"," ",I.tExtractMs!=null?`${I.tExtractMs.toFixed(0)} ms`:e("common.placeholder")]}),s.jsxs("span",{children:[e("lab.metric.solveOnlyMs"),":"," ",I.tSolveMs!=null?`${I.tSolveMs.toFixed(0)} ms`:e("common.placeholder")]})]})]}),(I.raDeg!=null||I.decDeg!=null)&&s.jsxs("div",{className:"leading-tight",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.radec")}),s.jsxs("div",{className:"mt-0.5 font-mono text-[9px]",children:["α ",$l(I.raDeg)," · δ"," ",$l(I.decDeg)]})]}),s.jsxs("div",{className:"flex flex-wrap gap-x-2 gap-y-0.5 text-[9px]",children:[I.matches!=null&&s.jsxs("span",{children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.matches")})," ",s.jsx("span",{className:"font-mono",children:I.matches})]}),I.rmseArcsec!=null&&s.jsxs("span",{children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.rmse")})," ",s.jsxs("span",{className:"font-mono",children:[I.rmseArcsec.toFixed(2),"″"]})]}),I.prob!=null&&s.jsxs("span",{className:"inline-flex max-w-full flex-col gap-0.5",children:[s.jsxs("span",{children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.metric.prob")})," ",s.jsx("span",{className:"font-mono",children:Cn(I.prob,vt??void 0).line})]}),s.jsx("span",{className:"text-[8px] leading-snug text-on-surface-variant/90",children:e("lab.metric.probHelp")}),Cn(I.prob,vt??void 0).rawLine&&s.jsxs(s.Fragment,{children:[s.jsxs("span",{className:"text-[8px] text-on-surface-variant",children:[e("lab.metric.probRaw"),":"," ",Cn(I.prob,vt??void 0).rawLine]}),s.jsx("span",{className:"text-[8px] leading-snug text-on-surface-variant/90",children:e("lab.metric.probRawHelp")})]})]})]}),I.status&&s.jsxs("div",{className:"border-t border-outline-variant/15 pt-1 text-[9px]",children:[s.jsxs("span",{className:"text-on-surface-variant",children:[e("lab.metric.status")," "]}),s.jsx("span",{className:"font-mono text-secondary",children:I.status})]})]}):s.jsx("p",{className:"text-on-surface-variant",children:e("common.placeholder")})})]}),s.jsxs("details",{open:!0,className:"rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-2 px-3 py-2 text-xs font-semibold text-on-surface [&::-webkit-details-marker]:hidden",children:[e("lab.imageSection"),s.jsx(Gn,{className:"h-4 w-4 shrink-0 text-on-surface-variant"})]}),s.jsxs("div",{className:"space-y-0.5 border-t border-outline-variant/15 px-3 py-2 text-[10px]",children:[s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.resolution")}),s.jsx("span",{className:"font-mono tabular-nums",children:vo.w>0?`${vo.w}×${vo.h}`:e("common.placeholder")})]}),s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.starsDetected")}),s.jsx("span",{className:"font-mono tabular-nums",children:Xs??e("common.placeholder")})]}),s.jsxs("div",{className:"flex justify-between gap-2",children:[s.jsx("span",{className:"text-on-surface-variant",children:e("lab.fwhm")}),s.jsx("span",{children:e("common.placeholder")})]})]})]})]}),i&&s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"mt-2 flex flex-wrap gap-4 text-xs text-on-surface-variant",children:[s.jsxs("span",{children:[e("lab.file"),":"," ",s.jsx("span",{className:"font-mono text-on-surface",children:i})]}),((ei=o.find(c=>c.filename===i))==null?void 0:ei.source)&&s.jsxs("span",{className:"rounded bg-surface-container-high px-2 py-0.5",children:[e("lab.source"),":"," ",(ti=o.find(c=>c.filename===i))==null?void 0:ti.source]})]}),s.jsxs("details",{open:!0,className:"mt-2 rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90 text-xs shadow-sm",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center gap-2 px-3 py-2 font-semibold text-on-surface [&::-webkit-details-marker]:hidden",children:[e("lab.meta.title"),io&&s.jsx(Wo,{className:"h-3.5 w-3.5 animate-spin"}),s.jsx(Gn,{className:"ml-auto h-4 w-4 shrink-0 text-on-surface-variant"})]}),s.jsx("div",{className:"border-t border-outline-variant/15 p-3 pt-2",children:qs.length>0?s.jsx("dl",{className:"grid grid-cols-2 gap-x-4 gap-y-2 sm:grid-cols-3",children:qs.map(c=>s.jsxs("div",{children:[s.jsx("dt",{className:"text-[10px] text-on-surface-variant",children:e(c.key)}),s.jsx("dd",{className:"text-[11px] font-medium text-on-surface",children:c.value})]},`${c.key}-${c.value}`))}):so&&!io?s.jsx("p",{className:"text-[10px] leading-relaxed text-on-surface-variant",children:e("lab.meta.partial")}):io?null:s.jsx("p",{className:"text-[10px] text-on-surface-variant",children:e("lab.meta.noSidecar")})})]})]})]}),(i||r==="lab_video"&&re==="camera")&&(k||C)&&s.jsxs("section",{className:"mt-3 max-h-[min(50vh,28rem)] rounded-lg border border-outline-variant/25 bg-surface-container-lowest/95",children:[s.jsxs("div",{className:"flex h-9 shrink-0 items-center justify-between border-b border-outline-variant/15 px-3 text-[10px] uppercase text-on-surface-variant",children:[s.jsx("span",{children:e("results.title")}),s.jsxs("div",{className:"flex gap-3",children:[(ni=C==null?void 0:C.results)!=null&&ni.length?s.jsx("button",{type:"button",className:"rounded bg-surface-container px-2 py-0.5 normal-case",onClick:async()=>{if(!(!i||!C)){for(const c of C.results){if(!c.success)continue;const x=c.result;await Ko({input_name:i,preset_label:String(c.label),result_json:c,metrics:Xo(x??null),replay:{layers:R,params:f}})}g(null)}},children:e("results.saveBatchAll")}):null,k&&s.jsx("button",{type:"button",className:"rounded bg-surface-container px-2 py-0.5 normal-case",onClick:async()=>{if(!i&&Jd!=="camera")return;const c=k.result;await Ko({input_name:i??e("lab.cameraSnapshotName"),preset_label:"manual",result_json:k,metrics:Xo(c??null),replay:{layers:R,params:f}}),g(null)},children:e("results.saveCurrent")})]})]}),s.jsx("div",{className:"min-h-0 overflow-y-auto p-3",children:s.jsxs("div",{className:"flex gap-3 overflow-x-auto text-xs",children:[C==null?void 0:C.results.map((c,x)=>{const z=c.result,le=Xd[x]??!1;return s.jsxs("div",{className:"min-w-[15rem] max-w-sm shrink-0 rounded-lg border border-outline-variant/25 bg-surface-container p-3 shadow-sm",children:[s.jsx("div",{className:"border-b border-outline-variant/15 pb-2 font-semibold text-secondary",children:String(c.label)}),c.success?s.jsxs(s.Fragment,{children:[s.jsx(bu,{result:z,t:e,roundTripMs:null}),s.jsx("button",{type:"button",className:"mt-2 text-[10px] text-primary hover:underline",onClick:()=>uo(Te=>({...Te,[x]:!le})),children:e(le?"results.hideRaw":"results.viewRaw")}),le&&s.jsx("pre",{className:"mt-1 max-h-40 overflow-auto rounded bg-surface-container-highest p-2 text-[9px] text-on-surface-variant",children:JSON.stringify(c,null,2)})]}):s.jsx("div",{className:"mt-2 text-[10px] text-error",children:String(c.error)}),c.success&&i&&s.jsx("button",{type:"button",className:"mt-3 w-full rounded bg-surface-container-high py-1.5 text-[10px] font-medium",onClick:()=>Ko({input_name:i,preset_label:String(c.label),result_json:c,metrics:Xo(z??null),replay:{layers:R,params:f}}).catch(Te=>g(String(Te))),children:e("results.saveRow")})]},x)}),k&&!C&&s.jsxs("div",{className:"min-w-[16rem] max-w-md shrink-0 rounded-lg border border-outline-variant/25 bg-surface-container p-3 shadow-sm",children:[s.jsx("div",{className:"border-b border-outline-variant/15 pb-2 text-[10px] font-semibold uppercase text-on-surface-variant",children:e("results.title")}),s.jsx(bu,{result:k.result,t:e,roundTripMs:fo}),s.jsx("button",{type:"button",className:"mt-2 text-[10px] text-primary hover:underline",onClick:()=>co(c=>!c),children:e(Gs?"results.hideRaw":"results.viewRaw")}),Gs&&s.jsx("pre",{className:"mt-1 max-h-48 overflow-auto rounded bg-surface-container-highest p-2 text-[9px] text-on-surface-variant",children:JSON.stringify(k,null,2)})]})]})})]})]}),s.jsxs("aside",{className:"flex w-80 shrink-0 flex-col border-l border-outline-variant/15 bg-surface-container-low text-xs min-h-0",children:[r!=="lab_video"&&s.jsxs("div",{className:"shrink-0 space-y-2 border-b border-outline-variant/20 p-4 pb-3",children:[s.jsx("button",{type:"button",className:"w-full rounded bg-primary py-2.5 font-semibold text-on-primary-container",onClick:ef,disabled:p,children:e("btn.solveOne")}),s.jsx("button",{type:"button",className:"w-full rounded bg-secondary/80 py-2.5 font-semibold text-on-secondary",onClick:tf,disabled:p,children:e("btn.solveBatch")})]}),r==="lab_video"&&s.jsx("div",{className:"shrink-0 space-y-2 border-b border-outline-variant/20 p-4 pb-3",children:re==="file"?s.jsx("button",{type:"button",className:"w-full rounded bg-secondary/80 py-2.5 font-semibold text-on-secondary disabled:opacity-40",onClick:()=>void nf(),disabled:p||!i,children:e("lab.solveCurrentFrame")}):s.jsxs(s.Fragment,{children:[s.jsx("button",{type:"button",className:"w-full rounded bg-primary py-2.5 font-semibold text-on-primary-container disabled:opacity-40",onClick:()=>rf(),disabled:p||ao,children:e("lab.solveCameraStart")}),s.jsx("button",{type:"button",className:"w-full rounded bg-error/80 py-2.5 font-semibold text-on-error disabled:opacity-40",onClick:()=>go(),disabled:!ao,children:e("lab.solveCameraStop")}),s.jsx("button",{type:"button",className:"w-full rounded bg-secondary/80 py-2.5 font-semibold text-on-secondary disabled:opacity-40",onClick:()=>void yo(),disabled:p,children:e("lab.solveCameraFrame")})]})}),r==="lab_video"&&Or&&s.jsxs("div",{className:"shrink-0 border-b border-outline-variant/20 px-4 py-2 text-[10px] text-on-surface-variant",children:[s.jsx("div",{className:"font-medium text-on-surface",children:e("lab.systemLoad")}),s.jsxs("div",{children:["CPU ",Or.cpu_usage,"% · RAM ",Or.memory_usage,"% ·"," ",Or.temperature,"°C"]})]}),s.jsxs("div",{className:"min-h-0 flex-1 overflow-y-auto p-4",children:[s.jsxs("details",{open:!0,className:"rounded-lg border border-outline-variant/20 bg-surface-container-highest/30",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-2 px-3 py-2 font-semibold text-on-surface-variant [&::-webkit-details-marker]:hidden",children:[e("params.title"),s.jsx(Gn,{className:"h-4 w-4 shrink-0"})]}),s.jsxs("div",{className:"border-t border-outline-variant/15 p-3 pt-2",children:[s.jsx("p",{className:"mb-3 text-[10px] leading-relaxed text-on-surface-variant/90",children:e("params.blockSolveIntro")}),s.jsxs("div",{className:"space-y-2",children:[s.jsxs("label",{className:"block",children:[s.jsx("span",{className:"text-[10px] font-medium text-on-surface-variant",children:e("params.solveProfile")}),s.jsx("p",{className:"mb-1 mt-0.5 text-[9px] leading-snug text-on-surface-variant/85",children:e("params.solveProfileHelp")}),s.jsxs("select",{className:"w-full rounded bg-surface-container-highest px-2 py-1",value:f.solve_profile??"balanced",onChange:c=>h(x=>({...x,solve_profile:c.target.value})),children:[s.jsx("option",{value:"speed",children:e("params.solveProfileSpeed")}),s.jsx("option",{value:"balanced",children:e("params.solveProfileBalanced")}),s.jsx("option",{value:"robust",children:e("params.solveProfileRobust")})]})]}),s.jsx(Ye,{label:e("params.fov"),helpKey:"params.fovHelp",value:f.fov_estimate??"",onChange:c=>h(x=>({...x,fov_estimate:c}))}),s.jsx(Ye,{label:e("params.fovErr"),helpKey:"params.fovErrHelp",value:f.fov_max_error??"",onChange:c=>h(x=>({...x,fov_max_error:c}))}),s.jsx(Ye,{label:e("params.timeout"),helpKey:"params.timeoutHelp",value:f.solve_timeout_ms??"",onChange:c=>h(x=>({...x,solve_timeout_ms:c}))}),s.jsx(Ye,{label:e("params.ra"),helpKey:"params.raHelp",value:f.hint_ra_deg??"",onChange:c=>h(x=>({...x,hint_ra_deg:c}))}),s.jsx(Ye,{label:e("params.dec"),helpKey:"params.decHelp",value:f.hint_dec_deg??"",onChange:c=>h(x=>({...x,hint_dec_deg:c}))}),s.jsx(Ye,{label:e("params.maxSide"),helpKey:"params.maxSideHelp",value:f.max_image_side??"",onChange:c=>h(x=>({...x,max_image_side:c}))}),s.jsxs("label",{className:"mt-1.5 flex cursor-pointer items-center gap-2",children:[s.jsx("input",{type:"checkbox",className:"accent-primary",checked:f.detail_level==="full",onChange:c=>h(x=>({...x,detail_level:c.target.checked?"full":"summary"}))}),s.jsx("span",{className:"text-[10px] text-on-surface-variant",children:e("params.detailLevelFull")})]}),s.jsxs("label",{className:"mt-1.5 flex cursor-pointer items-start gap-2",children:[s.jsx("input",{type:"checkbox",className:"accent-primary mt-0.5",checked:!!f.large_scale_bg_subtract,onChange:c=>h(x=>({...x,large_scale_bg_subtract:c.target.checked}))}),s.jsxs("span",{children:[s.jsx("span",{className:"text-[10px] text-on-surface-variant",children:e("params.largeScaleBg")}),s.jsx("p",{className:"mt-0.5 text-[9px] leading-snug text-on-surface-variant/85",children:e("params.largeScaleBgHelp")})]})]})]})]})]}),s.jsxs("details",{open:!0,className:"mt-3 rounded-lg border border-outline-variant/20 bg-surface-container-highest/30",children:[s.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-2 px-3 py-2 font-semibold text-on-surface-variant [&::-webkit-details-marker]:hidden",children:[e("params.centroid"),s.jsx(Gn,{className:"h-4 w-4 shrink-0"})]}),s.jsxs("div",{className:"border-t border-outline-variant/15 p-3 pt-2",children:[s.jsx("p",{className:"mb-3 text-[10px] leading-relaxed text-on-surface-variant/90",children:e("params.blockCentroidIntro")}),s.jsxs("div",{className:"space-y-2",children:[s.jsx(Ye,{label:e("params.sigma"),helpKey:"params.sigmaHelp",step:.1,value:((ri=f.centroid)==null?void 0:ri.sigma)??"",onChange:c=>h(x=>({...x,centroid:{...x.centroid,sigma:c}}))}),s.jsx(Ye,{label:e("params.maxArea"),helpKey:"params.maxAreaHelp",value:((li=f.centroid)==null?void 0:li.max_area)??"",onChange:c=>h(x=>({...x,centroid:{...x.centroid,max_area:c}}))}),s.jsx(Ye,{label:e("params.minArea"),helpKey:"params.minAreaHelp",value:((oi=f.centroid)==null?void 0:oi.min_area)??"",onChange:c=>h(x=>({...x,centroid:{...x.centroid,min_area:c}}))}),s.jsx(Ye,{label:e("params.filtsize"),helpKey:"params.filtsizeHelp",step:2,value:((ai=f.centroid)==null?void 0:ai.filtsize)??"",onChange:c=>h(x=>({...x,centroid:{...x.centroid,filtsize:c}}))})]})]})]}),s.jsxs("div",{className:"mt-4 rounded-md border border-outline-variant/20 bg-surface-container-highest/40 p-3",children:[s.jsx("div",{className:"mb-2 font-semibold text-on-surface-variant",children:e("sidebar.batchPresets")}),s.jsx("p",{className:"mb-2 text-[10px] leading-snug text-on-surface-variant",children:e("sidebar.batchHint")}),s.jsx("div",{className:"max-h-36 space-y-1.5 overflow-y-auto",children:[...y,...N].map(c=>s.jsxs("label",{className:"flex cursor-pointer items-center gap-2",children:[s.jsx("input",{type:"checkbox",checked:_.has(c.id),onChange:()=>lf(c.id)}),s.jsx("span",{className:"truncate",children:c.name})]},c.id))})]}),s.jsxs("div",{className:"mt-6 border-t border-outline-variant/20 pt-4",children:[s.jsx("div",{className:"mb-2 font-semibold",children:e("btn.applyPresets")}),s.jsx("div",{className:"max-h-24 space-y-1 overflow-y-auto",children:[...y,...N].map(c=>s.jsx("button",{type:"button",className:"block w-full truncate text-left text-primary hover:underline",onClick:()=>qd(c.params),children:c.name},c.id))}),s.jsxs("div",{className:"mt-3 flex gap-1",children:[s.jsx("input",{className:"flex-1 rounded bg-surface-container-highest px-2 py-1",placeholder:e("placeholder.newPreset"),value:It,onChange:c=>E(c.target.value)}),s.jsx("button",{type:"button",className:"rounded bg-surface-container-high px-2",onClick:async()=>{if(It.trim()){d(!0);try{await eh(It.trim(),f),E(""),await Dt();const c=await Qo("user");j(c.presets)}catch(c){g(String(c))}finally{d(!1)}}},children:e("btn.savePreset")})]})]})]})]})]}),r==="pool"&&s.jsxs("main",{className:"flex-1 overflow-auto p-4",children:[s.jsxs("h2",{className:"mb-4 flex items-center gap-2 text-lg font-semibold",children:[s.jsx(Am,{className:"h-5 w-5"})," ",e("pool.title")]}),s.jsxs("table",{className:"w-full text-left text-xs",children:[s.jsx("thead",{children:s.jsxs("tr",{className:"border-b border-outline-variant/30 text-on-surface-variant",children:[s.jsx("th",{className:"py-2",children:e("pool.col.name")}),s.jsx("th",{className:"py-2",children:e("pool.col.source")}),s.jsx("th",{className:"py-2",children:e("pool.col.size")}),s.jsx("th",{className:"py-2",children:e("pool.col.time")}),s.jsx("th",{className:"w-16 py-2 text-center",children:e("pool.delete")})]})}),s.jsx("tbody",{children:o.map(c=>s.jsxs("tr",{className:"border-b border-outline-variant/10",children:[s.jsx("td",{className:"py-2 font-mono",children:c.filename}),s.jsx("td",{className:"py-2",children:c.source??e("common.placeholder")}),s.jsx("td",{className:"py-2",children:Wa(c.size)}),s.jsx("td",{className:"py-2",children:hl(c.modified_at,t)}),s.jsx("td",{className:"py-2 text-center",children:s.jsx("button",{type:"button",className:"inline-flex rounded p-1 text-on-surface-variant hover:bg-error-container/30 hover:text-error",title:e("pool.delete"),"aria-label":e("pool.delete"),onClick:()=>void Js(c.filename),children:s.jsx(wu,{className:"h-3.5 w-3.5"})})})]},c.filename))})]})]}),r==="history"&&s.jsxs("main",{className:"flex-1 overflow-auto p-4",children:[s.jsx("p",{className:"mb-4 rounded-lg border border-outline-variant/25 bg-surface-container-lowest/90 p-3 text-xs leading-relaxed text-on-surface-variant",children:e("history.intro")}),s.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-4",children:[s.jsxs("h2",{className:"flex items-center gap-2 text-lg font-semibold",children:[s.jsx(Vm,{className:"h-5 w-5"})," ",e("history.title")]}),s.jsx("input",{className:"rounded bg-surface-container-highest px-2 py-1 text-xs",placeholder:e("history.search"),value:U,onChange:c=>L(c.target.value)}),s.jsx("button",{type:"button",className:"rounded bg-surface-container px-2 py-1 text-xs",onClick:()=>Go(U,1,nl).then(c=>{et(1),en(c)}),children:e("history.searchBtn")}),s.jsx("button",{type:"button",className:"rounded bg-primary-container/50 px-2 py-1 text-xs",onClick:()=>ju("json").then(c=>{const x=new Blob([c],{type:"application/json"}),z=document.createElement("a");z.href=URL.createObjectURL(x),z.download="experiments.json",z.click()}),children:e("history.exportJson")}),s.jsx("button",{type:"button",className:"rounded bg-primary-container/50 px-2 py-1 text-xs",onClick:()=>ju("csv").then(c=>{const x=new Blob([c],{type:"text/csv"}),z=document.createElement("a");z.href=URL.createObjectURL(x),z.download="experiments.csv",z.click()}),children:e("history.exportCsv")})]}),s.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-xs text-on-surface-variant",children:[s.jsx("span",{children:e("history.total",{n:(me==null?void 0:me.total)??0})}),s.jsx("button",{type:"button",className:"rounded border border-outline-variant/30 px-2 py-0.5 disabled:opacity-40",disabled:ne<=1,onClick:()=>et(c=>Math.max(1,c-1)),children:e("history.prev")}),s.jsxs("span",{children:[ne," / ",Zs]}),s.jsx("button",{type:"button",className:"rounded border border-outline-variant/30 px-2 py-0.5 disabled:opacity-40",disabled:ne>=Zs,onClick:()=>et(c=>c+1),children:e("history.next")})]}),s.jsx("ul",{className:"mt-2 space-y-2",children:(si=me==null?void 0:me.items)==null?void 0:si.map(c=>{const x=String(c.id??""),z=c.metrics,le=Mr===x;return s.jsxs("li",{className:"rounded border border-outline-variant/20 p-2 text-[11px]",children:[s.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-2 font-mono",children:[s.jsxs("div",{children:[s.jsxs("div",{className:"text-on-surface",children:[hl(String(c.created_at??""),t)," —"," ",String(c.input_name)," — ",String(c.preset_label)]}),s.jsxs("div",{className:"mt-1 text-on-surface-variant",children:[e("history.preset"),": ",String(c.preset_label)," · ",e("history.metrics"),":"," ","matches=",String((z==null?void 0:z.matches)??"—")," rmse=",String((z==null?void 0:z.rmse_arcsec)??"—")]})]}),s.jsxs("div",{className:"flex shrink-0 gap-1",children:[s.jsx("button",{type:"button",className:"rounded bg-surface-container px-2 py-0.5 text-[10px]",onClick:()=>tn(le?null:x),children:e(le?"history.collapse":"history.detail")}),s.jsx("button",{type:"button",className:"rounded px-2 py-0.5 text-[10px] text-error hover:bg-error-container/20",title:e("history.delete"),onClick:()=>void of(x),children:e("history.delete")})]})]}),le&&s.jsxs("div",{className:"mt-2 space-y-2",children:[c.asset_snapshot_relpath?s.jsx("img",{src:sh(x),alt:"",className:"max-h-48 max-w-full rounded border border-outline-variant/20 object-contain"}):null,s.jsx("pre",{className:"max-h-64 overflow-auto rounded bg-surface-container p-2 text-[10px]",children:JSON.stringify(c.result_json,null,2)})]})]},x)})})]})]})]})}function bu({result:e,t,roundTripMs:n}){const r=Qd(e??void 0);return e?s.jsxs("div",{className:"mt-2 space-y-2 text-[10px]",children:[s.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[r.tBackendTotalMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.backendTotalMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tBackendTotalMs.toFixed(0)," ms"]})]}),r.tSolveMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.solveComputeMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tSolveMs.toFixed(0)," ms"]})]}),r.tOpenDecodeMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.openDecodeMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tOpenDecodeMs.toFixed(0)," ms"]})]}),r.tPreprocessMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.preprocessMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tPreprocessMs.toFixed(0)," ms"]})]}),r.tExtractMs!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.extractMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.tExtractMs.toFixed(0)," ms"]})]}),n!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.solveRoundTripMs")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[n.toFixed(0)," ms"]})]}),r.matches!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.matches")}),s.jsx("div",{className:"font-semibold tabular-nums text-on-surface",children:r.matches})]}),r.rmseArcsec!=null&&s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.rmse")}),s.jsxs("div",{className:"font-semibold tabular-nums text-on-surface",children:[r.rmseArcsec.toFixed(2),"″"]})]}),r.prob!=null&&s.jsxs("div",{className:"col-span-2",children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.prob")}),s.jsx("div",{className:"font-semibold text-on-surface",children:Cn(r.prob,e).line}),s.jsx("p",{className:"mt-0.5 text-[9px] leading-snug text-on-surface-variant/90",children:t("lab.metric.probHelp")}),Cn(r.prob,e).rawLine&&s.jsxs("div",{className:"mt-1 text-[9px] text-on-surface-variant",children:[t("lab.metric.probRaw"),": ",Cn(r.prob,e).rawLine,s.jsx("p",{className:"mt-0.5 text-[8px] leading-snug opacity-90",children:t("lab.metric.probRawHelp")})]})]})]}),s.jsxs("div",{children:[s.jsx("div",{className:"text-on-surface-variant",children:t("lab.metric.radec")}),s.jsxs("div",{className:"font-mono text-[9px] text-on-surface",children:["α ",$l(r.raDeg)," · δ ",$l(r.decDeg)]})]}),r.status&&s.jsxs("div",{className:"rounded bg-surface-container-high px-2 py-1 text-[9px] font-mono text-on-surface",children:[t("lab.metric.status"),": ",r.status]})]}):s.jsx("p",{className:"mt-2 text-[10px] text-on-surface-variant",children:"—"})}function Ye({label:e,helpKey:t,value:n,onChange:r,type:l="number",step:o}){const{t:a}=Wd(),i=t?a(t):void 0;return s.jsxs("label",{className:"block",children:[s.jsx("span",{className:"text-[10px] font-medium text-on-surface-variant",children:e}),i&&s.jsx("p",{className:"mb-1 mt-0.5 text-[9px] leading-snug text-on-surface-variant/85",children:i}),s.jsx("input",{type:l,step:o,className:"w-full rounded bg-surface-container-highest px-2 py-1",value:n===""?"":n,onChange:u=>{const f=u.target.value;r(f===""?void 0:Number(f))}})]})}Zo.createRoot(document.getElementById("root")).render(s.jsx(Ef.StrictMode,{children:s.jsx(fh,{children:s.jsx(gh,{})})})); diff --git a/web/static/analysis-lab/index.html b/web/static/analysis-lab/index.html index e75f3b8..aaba632 100644 --- a/web/static/analysis-lab/index.html +++ b/web/static/analysis-lab/index.html @@ -4,7 +4,7 @@ OGScope 星空解算控制台 - + diff --git a/web/static/i18n/analysis.en.json b/web/static/i18n/analysis.en.json index d542658..46a9cc0 100644 --- a/web/static/i18n/analysis.en.json +++ b/web/static/i18n/analysis.en.json @@ -5,6 +5,8 @@ "nav.labVideo": "Video solve", "delete.uploadCascade": "Delete {n} linked experiment record(s) as well?", "lab.solveCurrentFrame": "Solve current frame (file)", + "lab.solveFileStart": "Start continuous file solve", + "lab.solveFileStop": "Stop continuous file solve", "lab.cameraPreviewLoading": "Connecting to shared preview…", "lab.solveCameraFrame": "Solve live camera frame", "lab.solveCameraStart": "Start camera solve", diff --git a/web/static/i18n/analysis.zh.json b/web/static/i18n/analysis.zh.json index be43e88..3514822 100644 --- a/web/static/i18n/analysis.zh.json +++ b/web/static/i18n/analysis.zh.json @@ -138,6 +138,8 @@ "common.placeholder": "—", "delete.uploadCascade": "该素材有 {n} 条实验记录,是否一并删除?", "lab.solveCurrentFrame": "解算当前帧(文件)", + "lab.solveFileStart": "开始文件连续解算", + "lab.solveFileStop": "停止文件连续解算", "lab.cameraPreviewLoading": "正在连接共享预览…", "lab.solveCameraFrame": "解算相机当前帧", "lab.solveCameraStart": "开始相机解算",