import {
  Globe,
  LayoutDashboard,
  LineChart as LineChartIcon,
  Settings,
  Bell,
  Play,
  Square,
  CheckCircle2,
  AlertCircle,
  ShieldAlert,
  Save,
  RotateCcw,
  MessageSquare,
  Cpu,
  Key,
  Activity,
  TrendingUp,
  DatabaseZap,
  Clock,
  Terminal,
  FolderOpen,
  Gamepad2,
  Shield,
  Crosshair,
  Search,
  AlertTriangle,
} from "lucide-react";
import { useState, useEffect, useRef } from "react";
import {
  LineChart,
  Line,
  ResponsiveContainer,
  XAxis,
  YAxis,
  Tooltip,
  CartesianGrid,
} from "recharts";
import { resolveBackendUrl } from "./backendUrl";
import ZenWorkspace from "./ZenWorkspace";
import CommercialGate from "./components/CommercialGate";

const GUI_VERSION = "5.9.3";

function formatDisplayTimestamp(value: unknown): string {
  if (value === null || value === undefined) {
    return "";
  }
  const raw = String(value).trim();
  if (!raw) {
    return "";
  }
  const parsed = Date.parse(raw);
  if (!Number.isNaN(parsed)) {
    return new Date(parsed).toLocaleString("zh-CN", {
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
      hour12: false,
    });
  }
  const numeric = Number(raw);
  if (Number.isFinite(numeric) && numeric > 0) {
    const epochMs = numeric > 1e12 ? numeric : numeric * 1000;
    return new Date(epochMs).toLocaleString("zh-CN", {
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
      hour12: false,
    });
  }
  return raw;
}

function selectVisibleOpenPositions(
  primary: unknown,
  secondary: unknown,
): any[] {
  if (Array.isArray(primary) && primary.length > 0) {
    return primary;
  }
  if (Array.isArray(secondary) && secondary.length > 0) {
    return secondary;
  }
  return [];
}

function App() {
  const [apiBase, setApiBase] = useState("http://127.0.0.1:18790");
  const [backendProbeReady, setBackendProbeReady] = useState(false);
  const [status, setStatus] = useState({
    isRunning: false,
    mt5Online: false,
    bridgeOk: true,
    priceAge: 0,
    priceSource: "unknown",
    bid: 0,
    ask: 0,
    spread: 0,
    riskLevel: "未知",
    light: "YELLOW",
    agent_dir: "NEUTRAL",
    regime: "UNKNOWN",
    is_defensive: false,
    risk_block: {
      exists: false,
      rawReason: "",
      categoryCode: "NONE",
      categoryLabel: "无阻断",
      summary: "",
      time: "",
      line: "",
    },
    final_reject: {
      reason: "",
      stage: "",
      ts: 0,
    },
    overlap_budget: {
      effective_attempts: 0,
      last_reason: "",
      updated_at: 0,
    },
    overlap_budget_target: 2,
    soft_limits: [] as any[],
    tradesCount: 0,
    todayTrades: 0,
    todayPnl: 0.0,
    account_total_loss_stop_pct: 30,
    account_total_loss_current_pct: 0,
    account_total_loss_stop_active: false,
    account_total_loss_stop_source: "NONE",
    positionOpen: false,
    positionSide: "",
    positionEntry: 0,
    positions: [] as any[],
    system_stats: {
      mt5_latency: -1,
    },
  });
  const [backendConnected, setBackendConnected] = useState(false);

  const [actionLoading, setActionLoading] = useState<string | null>(null);
  const [toast, setToast] = useState<{
    msg: string;
    type: "success" | "error" | "warning";
  } | null>(null);
  const [decisionPolicyForm, setDecisionPolicyForm] = useState({
    profile: "agent_guided_multi_strategy",
    macroRole: "directional_gate",
    macroAlignedScale: 1.1,
    macroCountertrendScale: 0.35,
    macroNeutralScale: 1.0,
    macroDegradedPolicy: "soften_to_neutral",
    interpreterRole: "execution_bias_only",
    interpreterBuyScale: 1.0,
    interpreterSellScale: 1.0,
    interpreterLimitCountertrendScale: 0.5,
    interpreterBlockCountertrendScale: 0.0,
    riskRole: "veto_only",
    executionAggregation: "weighted_net_confidence",
    executionMinConfidence: 0.15,
  });
  const [decisionPolicySaving, setDecisionPolicySaving] = useState(false);
  const [confirmModal, setConfirmModal] = useState<{
    title: string;
    message: string;
    onConfirm: () => void;
  } | null>(null);
  const [trainingStatus, setTrainingStatus] = useState({
    isTraining: false,
    progress: 0,
    currentBar: 0,
    totalBars: 0,
    currentEpoch: 0,
    totalEpochs: 0,
    winRate: 0,
    pnl: 0,
    drawdown: 0,
    totalTrades: 0,
    shadowClosedTrades: 0,
    shadowMaxDrawdownAbs: 0,
    activeDataset: "-",
    activeModel: "",
    analysisModel: "",
    readyForTraining: false,
    blockedReasons: [] as string[],
    closureCoveragePct: 0,
    criticalAnomalies: 0,
    recoveredClosedRatioPct: 0,
    naturalClosedRatioPct: 0,
    naturalClosedTransitions: 0,
    recoveredClosedTransitions: 0,
    repairCycle: {} as Record<string, unknown>,
    trainingEngine: {} as Record<string, unknown>,
    autoPilotEnabled: false,
    autoPilotStage: "idle",
    autoPilotMessage: "",
    autoPilotLastError: "",
    errorDispatch: {} as Record<string, unknown>,
    metricsSource: "training_status",
    metricsUpdatedAt: "",
    approvalSummary: {} as Record<string, unknown>,
  });

  const [governanceReport, setGovernanceReport] = useState({
    qualityGate: {} as Record<string, unknown>,
    governanceContext: {} as Record<string, unknown>,
    governanceAdvice: "",
    paramLearner: {} as Record<string, unknown>,
  });
  const [approvalChain, setApprovalChain] = useState({
    stage: "NO_SUGGESTION",
    suggestion: {} as Record<string, unknown>,
    appliedSuggestion: {} as Record<string, unknown>,
    effectiveParams: {} as Record<string, unknown>,
    effectiveOfflineParams: {} as Record<string, unknown>,
    evolutionReport: {} as Record<string, unknown>,
    paramLearner: {} as Record<string, unknown>,
    shadowLearner: {} as Record<string, unknown>,
    liveLearner: {} as Record<string, unknown>,
    autoGovernance: {} as Record<string, unknown>,
    phaseReadiness: {} as Record<string, unknown>,
    rollbackState: {} as Record<string, unknown>,
    decision: {} as Record<string, unknown>,
  });
  const [governanceLifecycle, setGovernanceLifecycle] = useState({
    activeSignals: [] as Array<Record<string, unknown>>,
    recentSignals: [] as Array<Record<string, unknown>>,
    audit: {} as Record<string, unknown>,
    repairCycle: {} as Record<string, unknown>,
    closureLifecycle: {} as Record<string, unknown>,
    trainingLifecycle: {} as Record<string, unknown>,
    shadowLearner: {} as Record<string, unknown>,
    liveLearner: {} as Record<string, unknown>,
    rollbackEvidence: {} as Record<string, unknown>,
    autoGovernance: {} as Record<string, unknown>,
    phaseReadiness: {} as Record<string, unknown>,
  });
  const [runtimeObservability, setRuntimeObservability] = useState({
    gateway: {} as Record<string, unknown>,
    interpreter: {} as Record<string, unknown>,
    performance: {
      topBuckets: {
        session: [] as Array<Record<string, unknown>>,
        regime: [] as Array<Record<string, unknown>>,
        strategy: [] as Array<Record<string, unknown>>,
        interpreter: [] as Array<Record<string, unknown>>,
      },
    } as Record<string, unknown>,
    trainingGate: {} as Record<string, unknown>,
    autoGovernance: {} as Record<string, unknown>,
    goalTargets: {} as Record<string, unknown>,
    evolutionEvidence: {} as Record<string, unknown>,
    autonomyLoop: {} as Record<string, unknown>,
    sessionRiskLens: {} as Record<string, unknown>,
    directionQuality: {} as Record<string, unknown>,
    macroPolling: {} as Record<string, unknown>,
    confidenceCalibration: {} as Record<string, unknown>,
    trailingTelemetry: {} as Record<string, unknown>,
  });
  const [runtimeConsole, setRuntimeConsole] = useState({
    runtimeInstances: [] as Array<Record<string, unknown>>,
    runtimeScheduler: {} as Record<string, unknown>,
    runtimeExplain: {} as Record<string, unknown>,
    runtimeAgentDiagnostics: {} as Record<string, unknown>,
    runtimeBridgeQueue: {} as Record<string, unknown>,
    runtimeBridgeRequests: [] as Array<Record<string, unknown>>,
    runtimeExecutionFocus: [] as Array<Record<string, unknown>>,
    runtimeBridgeHealth: {} as Record<string, unknown>,
    runtimeStatus: {} as Record<string, unknown>,
    orchestrationSnapshot: {} as Record<string, unknown>,
  });
  const [runtimeAiGoal, setRuntimeAiGoal] = useState("提高胜率并减少互搏");
  const [runtimeAiEvaluation, setRuntimeAiEvaluation] = useState<
    Record<string, unknown>
  >({});
  const [runtimeAiHistory, setRuntimeAiHistory] = useState<
    Array<Record<string, unknown>>
  >([]);
  const [runtimeAiLoading, setRuntimeAiLoading] = useState(false);
  const [runtimeAiSimpleExpanded, setRuntimeAiSimpleExpanded] = useState(false);
  const [strategyMarketplaceView, setStrategyMarketplaceView] = useState<
    "simple" | "pro"
  >("simple");
  const [marketplaceExpandedStrategyId, setMarketplaceExpandedStrategyId] =
    useState<string | null>(null);
  const statusFetchInFlight = useRef(false);
  const lightweightStatusInFlight = useRef(false);
  const trainingStatusInFlight = useRef(false);
  const governanceReportInFlight = useRef(false);
  const approvalChainInFlight = useRef(false);
  const governanceLifecycleInFlight = useRef(false);
  const systemMessagesInFlight = useRef(false);
  const runtimeObservabilityInFlight = useRef(false);
  const runtimeConsoleInFlight = useRef(false);
  const lastSetupStatusFetchTs = useRef(0);
  const statusFailStreakRef = useRef(0);
  const lastBackendHeartbeatTs = useRef(0);
  const lastStatusSuccessTs = useRef(0);
  const mailboxScrollRef = useRef<HTMLDivElement | null>(null);
  const lifecycleRepairCycle = governanceLifecycle.repairCycle;
  const lifecycleAudit = governanceLifecycle.audit;
  const closureLifecycle = governanceLifecycle.closureLifecycle;
  const trainingLifecycle = governanceLifecycle.trainingLifecycle;
  const shadowLearnerLifecycle = governanceLifecycle.shadowLearner;
  const liveLearnerLifecycle = governanceLifecycle.liveLearner;
  const rollbackEvidence = governanceLifecycle.rollbackEvidence;
  const autoGovernanceLifecycle = governanceLifecycle.autoGovernance;
  const phaseReadiness = governanceLifecycle.phaseReadiness;
  const lifecycleRecovery =
    (lifecycleRepairCycle.recovery as Record<string, unknown>) || {};
  const lifecycleTransitionCounts =
    (lifecycleRepairCycle.transition_counts as Record<string, unknown>) || {};
  const lifecycleCoverage =
    (lifecycleAudit.coverage as Record<string, unknown>) || {};
  const lifecycleAnomalies =
    (lifecycleAudit.anomalies as Record<string, unknown>) || {};
  const recentClosures =
    (closureLifecycle.recentClosures as Array<Record<string, unknown>>) || [];
  const recentShadowDecisions =
    (shadowLearnerLifecycle.recentDecisions as Array<
      Record<string, unknown>
    >) || [];
  const recentLiveSelections =
    (liveLearnerLifecycle.recentSelections as Array<Record<string, unknown>>) ||
    [];
  const pendingRepairDecisions =
    (closureLifecycle.pendingRepairDecisions as Array<
      Record<string, unknown>
    >) || [];

  const isTrainingPollingActive = () => {
    const currentView = drawerPanel || activeMenu;
    return currentView === "training" || currentView === "dashboard";
  };

  const normalizeBlackboardPreview = (raw: {
    Macro_Commander?: {
      bias?: unknown;
      confidence?: unknown;
      daily_calls?: unknown;
      trigger_reason?: unknown;
    };
    Micro_Sniper?: {
      is_defensive_env?: unknown;
      knife_catching_risk?: unknown;
      ny_session_active?: unknown;
      current_regime?: unknown;
      override_counter?: unknown;
      override_threshold?: unknown;
    };
    Risk_Commissar?: {
      position_multiplier?: unknown;
    };
    Scheduler_Runtime?: {
      selected_strategy_id?: unknown;
      selected_instance_id?: unknown;
      active_strategy_ids?: unknown;
      active_instance_ids?: unknown;
      route_family?: unknown;
      allowed_side?: unknown;
      candidate_strategy_ids?: unknown;
      router_weights?: unknown;
      direction_guard?: unknown;
      route?: unknown;
    };
    Execution_Arbitration?: {
      final_action?: unknown;
      hold_mode?: unknown;
      blocked_reasons?: unknown;
      selected_strategy_id?: unknown;
      selected_instance_id?: unknown;
    };
    Risk_Protocol?: {
      global_state?: unknown;
      governor_blockers?: unknown;
      active_strategy_ids?: unknown;
      active_instance_ids?: unknown;
    };
  }) => ({
    Macro_Commander: {
      bias: raw?.Macro_Commander?.bias,
      confidence: raw?.Macro_Commander?.confidence,
      daily_calls: raw?.Macro_Commander?.daily_calls,
      trigger_reason: raw?.Macro_Commander?.trigger_reason,
    },
    Micro_Sniper: {
      is_defensive_env: raw?.Micro_Sniper?.is_defensive_env,
      knife_catching_risk: raw?.Micro_Sniper?.knife_catching_risk,
      ny_session_active: raw?.Micro_Sniper?.ny_session_active,
      current_regime: raw?.Micro_Sniper?.current_regime,
      override_counter: raw?.Micro_Sniper?.override_counter,
      override_threshold: raw?.Micro_Sniper?.override_threshold,
    },
    Risk_Commissar: {
      position_multiplier: raw?.Risk_Commissar?.position_multiplier,
    },
    Scheduler_Runtime: {
      selected_strategy_id: raw?.Scheduler_Runtime?.selected_strategy_id,
      selected_instance_id: raw?.Scheduler_Runtime?.selected_instance_id,
      active_strategy_ids: raw?.Scheduler_Runtime?.active_strategy_ids,
      active_instance_ids: raw?.Scheduler_Runtime?.active_instance_ids,
      route_family: raw?.Scheduler_Runtime?.route_family,
      allowed_side: raw?.Scheduler_Runtime?.allowed_side,
      candidate_strategy_ids: raw?.Scheduler_Runtime?.candidate_strategy_ids,
      router_weights: raw?.Scheduler_Runtime?.router_weights,
      direction_guard: raw?.Scheduler_Runtime?.direction_guard,
      route: raw?.Scheduler_Runtime?.route,
    },
    Execution_Arbitration: {
      final_action: raw?.Execution_Arbitration?.final_action,
      hold_mode: raw?.Execution_Arbitration?.hold_mode,
      blocked_reasons: raw?.Execution_Arbitration?.blocked_reasons,
      selected_strategy_id: raw?.Execution_Arbitration?.selected_strategy_id,
      selected_instance_id: raw?.Execution_Arbitration?.selected_instance_id,
    },
    Risk_Protocol: {
      global_state: raw?.Risk_Protocol?.global_state,
      governor_blockers: raw?.Risk_Protocol?.governor_blockers,
      active_strategy_ids: raw?.Risk_Protocol?.active_strategy_ids,
      active_instance_ids: raw?.Risk_Protocol?.active_instance_ids,
    },
  });

  const [pnlHistory, setPnlHistory] = useState<
    { epoch: number; loss: number }[]
  >([]);

  useEffect(() => {
    let cancelled = false;
    void resolveBackendUrl()
      .then((url) => {
        if (!cancelled) {
          setApiBase(url);
        }
      })
      .catch(() => {
        // 保持默认端口回退，避免初始化阶段直接中断页面加载
      })
      .finally(() => {
        if (!cancelled) {
          setBackendProbeReady(true);
        }
      });
    return () => {
      cancelled = true;
    };
  }, []);
  const [selectedTrainingModel, setSelectedTrainingModel] = useState("");
  const [selectedTrainingDataset, setSelectedTrainingDataset] = useState("");
  const [availableTrainingDatasets, setAvailableTrainingDatasets] = useState<
    { id: string; label: string }[]
  >([]);

  // 真实获取离线训练进度
  const fetchTrainingStatus = async () => {
    if (
      !isTrainingPollingActive() ||
      document.hidden ||
      trainingStatusInFlight.current
    ) {
      return;
    }
    trainingStatusInFlight.current = true;
    try {
      const res = await fetch(`${apiBase}/api/training_status`);
      if (res.ok) {
        const data = await res.json();
        if (Array.isArray(data.pnlHistory)) {
          setPnlHistory(data.pnlHistory);
        } else if (data.isTraining && typeof data.currentBar === "number") {
          setPnlHistory((prev) =>
            prev.some((item) => item.epoch === data.currentBar)
              ? prev
              : [...prev, { epoch: data.currentBar, loss: data.pnl }],
          );
        }
        if (typeof data.analysisModel === "string" && data.analysisModel) {
          setSelectedTrainingModel(data.analysisModel);
        } else if (typeof data.activeModel === "string" && data.activeModel) {
          setSelectedTrainingModel(data.activeModel);
        }
        if (typeof data.activeDataset === "string" && data.activeDataset) {
          setSelectedTrainingDataset(data.activeDataset);
        }
        setTrainingStatus(data);
      }
    } catch {
      console.warn("Failed to fetch training status");
    } finally {
      trainingStatusInFlight.current = false;
    }
  };

  const fetchTrainingDatasets = async () => {
    try {
      const res = await fetch(`${apiBase}/api/training/datasets`);
      if (res.ok) {
        const data = await res.json();
        const datasets = Array.isArray(data.datasets) ? data.datasets : [];
        setAvailableTrainingDatasets(
          datasets.map((item: { id?: string; label?: string }) => ({
            id: String(item.id || item.label || ""),
            label: String(item.label || item.id || ""),
          })),
        );
        if (
          !selectedTrainingDataset &&
          typeof data.defaultDataset === "string"
        ) {
          setSelectedTrainingDataset(data.defaultDataset);
        }
      }
    } catch {
      console.warn("Failed to fetch training datasets");
    }
  };

  const fetchGovernanceReport = async () => {
    if (
      !isTrainingPollingActive() ||
      document.hidden ||
      governanceReportInFlight.current
    ) {
      return;
    }
    governanceReportInFlight.current = true;
    try {
      const res = await fetch(`${apiBase}/api/training/governance`);
      if (res.ok) {
        const data = await res.json();
        setGovernanceReport({
          qualityGate: data.qualityGate || {},
          governanceContext: data.governanceContext || {},
          governanceAdvice: data.governanceAdvice || "",
          paramLearner: data.paramLearner || {},
        });
      }
    } catch {
      console.warn("Failed to fetch governance report");
    } finally {
      governanceReportInFlight.current = false;
    }
  };

  const fetchApprovalChain = async () => {
    const currentView = drawerPanel || activeMenu;
    if (
      (!isTrainingPollingActive() && currentView !== "webchat") ||
      document.hidden ||
      approvalChainInFlight.current
    ) {
      return;
    }
    approvalChainInFlight.current = true;
    try {
      const res = await fetch(`${apiBase}/api/training/approval_chain`);
      if (res.ok) {
        const data = await res.json();
        setApprovalChain({
          stage: data.stage || "NO_SUGGESTION",
          suggestion: data.suggestion || {},
          appliedSuggestion: data.appliedSuggestion || {},
          effectiveParams: data.effectiveParams || {},
          effectiveOfflineParams: data.effectiveOfflineParams || {},
          evolutionReport: data.evolutionReport || {},
          paramLearner: data.paramLearner || {},
          shadowLearner: data.shadowLearner || {},
          liveLearner: data.liveLearner || {},
          autoGovernance: data.autoGovernance || {},
          phaseReadiness: data.phaseReadiness || {},
          rollbackState: data.rollbackState || {},
          decision: data.decision || {},
        });
      }
    } catch {
      console.warn("Failed to fetch approval chain");
    } finally {
      approvalChainInFlight.current = false;
    }
  };

  const fetchGovernanceLifecycle = async () => {
    if (
      !isTrainingPollingActive() ||
      document.hidden ||
      governanceLifecycleInFlight.current
    ) {
      return;
    }
    governanceLifecycleInFlight.current = true;
    try {
      const res = await fetch(`${apiBase}/api/governance/lifecycle`);
      if (res.ok) {
        const data = await res.json();
        setGovernanceLifecycle({
          activeSignals: data.activeSignals || [],
          recentSignals: data.recentSignals || [],
          audit: data.audit || {},
          repairCycle: data.repairCycle || {},
          closureLifecycle: data.closureLifecycle || {},
          trainingLifecycle: data.trainingLifecycle || {},
          shadowLearner: data.shadowLearner || {},
          liveLearner: data.liveLearner || {},
          rollbackEvidence: data.rollbackEvidence || {},
          autoGovernance: data.autoGovernance || {},
          phaseReadiness: data.phaseReadiness || {},
        });
      }
    } catch {
      console.warn("Failed to fetch governance lifecycle");
    } finally {
      governanceLifecycleInFlight.current = false;
    }
  };

  const fetchRuntimeObservability = async () => {
    const currentView = drawerPanel || activeMenu;
    if (
      (!isTrainingPollingActive() && currentView !== "webchat") ||
      document.hidden
    ) {
      return;
    }
    if (runtimeObservabilityInFlight.current) {
      return;
    }
    runtimeObservabilityInFlight.current = true;
    const controller = new AbortController();
    const timer = window.setTimeout(() => controller.abort(), 20000);
    try {
      const res = await fetch(`${apiBase}/api/runtime/observability`, {
        signal: controller.signal,
      });
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          setRuntimeObservability({
            gateway: data.gateway || {},
            interpreter: data.interpreter || {},
            performance: data.performance || { topBuckets: {} },
            trainingGate: data.trainingGate || {},
            autoGovernance: data.autoGovernance || {},
            goalTargets: data.goalTargets || {},
            evolutionEvidence: data.evolutionEvidence || {},
            autonomyLoop: data.autonomyLoop || {},
            sessionRiskLens: data.sessionRiskLens || {},
            directionQuality: data.directionQuality || {},
            macroPolling: data.macroPolling || {},
            confidenceCalibration: data.confidenceCalibration || {},
            trailingTelemetry: data.trailingTelemetry || {},
          });
        }
      }
    } catch {
      console.warn("Failed to fetch runtime observability");
    } finally {
      window.clearTimeout(timer);
      runtimeObservabilityInFlight.current = false;
    }
  };

  const postJsonWithTimeout = async (
    path: string,
    options?: RequestInit,
    timeoutMs: number = 15000,
  ) => {
    const controller = new AbortController();
    const timer = window.setTimeout(() => controller.abort(), timeoutMs);
    try {
      const res = await fetch(`${apiBase}${path}`, {
        ...options,
        signal: controller.signal,
      });
      const data = await res.json();
      return { res, data };
    } finally {
      window.clearTimeout(timer);
    }
  };

  const handleRegenerateGovernanceAnalysis = async () => {
    showToast("正在生成 Agent 分析报告，请稍候...", "success");
    try {
      const res = await fetch(`${apiBase}/api/training/analyze`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ model: selectedTrainingModel }),
      });
      const data = await res.json();
      if (data.success) {
        await fetchGovernanceReport();
        await fetchApprovalChain();
        await fetchTrainingStatus();
        showToast("治理分析已更新", "success");
      } else {
        showToast("生成分析报告失败: " + (data.error || "未知错误"), "error");
      }
    } catch {
      showToast("请求失败，请检查后端服务是否运行", "error");
    }
  };

  const handlePromotionPrecheck = async () => {
    try {
      const res = await fetch(`${apiBase}/api/training/promotion_check`, {
        method: "POST",
      });
      const data = await res.json();
      if (data.success) {
        await fetchApprovalChain();
        showToast(
          String(data.message || "Promotion 前校验完成"),
          data.decision?.canPromote ? "success" : "error",
        );
      } else {
        showToast("Promotion 前校验失败", "error");
      }
    } catch {
      showToast("Promotion 前校验请求失败", "error");
    }
  };

  const handleRunTrainingEvolution = async () => {
    showToast("正在生成新的训练进化建议，请稍候...", "success");
    try {
      const res = await fetch(`${apiBase}/api/training/evolve`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ model: selectedTrainingModel }),
      });
      const data = await res.json();
      if (data.success) {
        await fetchGovernanceReport();
        await fetchApprovalChain();
        await fetchTrainingStatus();
        showToast(String(data.message || "训练进化建议已生成"), "success");
      } else {
        showToast(
          String(data.error || data.message || "训练进化执行失败"),
          "error",
        );
      }
    } catch {
      showToast("训练进化请求失败", "error");
    }
  };

  const handleAutoGovernanceTick = async () => {
    setActionLoading("training:auto-governance");
    try {
      const { data } = await postJsonWithTimeout(
        "/api/governance/auto_tick",
        { method: "POST" },
        20000,
      );
      if (data.success) {
        showToast(String(data.result?.action || "AUTO_TICK"), "success");
        await fetchApprovalChain();
        await fetchGovernanceLifecycle();
      } else {
        showToast(String(data.error || "自动治理执行失败"), "error");
      }
    } catch (e) {
      const isTimeout = e instanceof DOMException && e.name === "AbortError";
      showToast(
        isTimeout ? "自动治理请求超时，请稍后重试" : "自动治理请求失败",
        "error",
      );
    } finally {
      setActionLoading(null);
    }
  };

  const handleCompleteTrainingReview = async () => {
    setActionLoading("training:review");
    try {
      const { data } = await postJsonWithTimeout(
        "/api/training/manual_review/complete",
        { method: "POST" },
        20000,
      );
      if (data.success) {
        showToast(String(data.message || "人工复核已完成"), "success");
        await fetchApprovalChain();
      } else {
        showToast(
          String(data.error || data.message || "人工复核失败"),
          "error",
        );
      }
    } catch (e) {
      const isTimeout = e instanceof DOMException && e.name === "AbortError";
      showToast(
        isTimeout ? "人工复核请求超时，请稍后重试" : "人工复核请求失败",
        "error",
      );
    } finally {
      setActionLoading(null);
    }
  };

  const handleRollbackTrainingReview = async () => {
    setActionLoading("training:rollback");
    try {
      const { data } = await postJsonWithTimeout(
        "/api/training/manual_review/rollback",
        { method: "POST" },
        20000,
      );
      if (data.success) {
        showToast(String(data.message || "已回滚到上一版稳定参数"), "success");
        await fetchApprovalChain();
        await fetchGovernanceLifecycle();
      } else {
        showToast(
          String(data.error || data.message || "训练参数回滚失败"),
          "error",
        );
      }
    } catch (e) {
      const isTimeout = e instanceof DOMException && e.name === "AbortError";
      showToast(
        isTimeout ? "回滚请求超时，请稍后重试" : "训练参数回滚失败",
        "error",
      );
    } finally {
      setActionLoading(null);
    }
  };

  /*
  const handleToggleTraining = async () => {
    const endpoint = trainingStatus.isTraining ? "/api/training/stop" : "/api/training/start";
    try {
      const res = await fetch(`http://localhost:18790${endpoint}`, { method: "POST" });
      const data = await res.json();
      if (data.success) {
        showToast(data.message, "success");
        if (!trainingStatus.isTraining) {
          setPnlHistory([]); // 重新开始清空图表
        }
        fetchTrainingStatus();
      } else {
        showToast(data.error || data.message, "error");
      }
    } catch (e) {
      showToast("操作失败", "error");
    }
  };
  */
  const [activeMenu, setActiveMenu] = useState("dashboard");
  const [robotDashboardView, setRobotDashboardView] = useState<
    "pro" | "simple"
  >("simple");
  const [drawerPanel, setDrawerPanel] = useState<string | null>(null);
  const [mailboxLogs, setMailboxLogs] = useState<any[]>([]);
  const [blackboardState, setBlackboardState] = useState<any>(null);
  const [logsByTab, setLogsByTab] = useState<Record<string, string[]>>({
    system: [],
    daemon: [],
  });
  const [logSourceByTab, setLogSourceByTab] = useState<Record<string, string>>({
    system: "",
    daemon: "",
  });
  const [alerts, setAlerts] = useState<any[]>([]);
  const [systemMessages, setSystemMessages] = useState<any[]>([]);
  const [systemMessageSummary, setSystemMessageSummary] = useState<any>({
    total: 0,
    publishCount: 0,
    rollbackCount: 0,
    templateCount: 0,
    repairCount: 0,
  });
  const lastFileRepairAlertIdRef = useRef<string>("");
  const [updateStatus, setUpdateStatus] = useState<any>({
    version: { version: "0.0.0" },
    currentRelease: {},
    candidateRelease: {},
    updateState: {},
    quality: { runtime: {}, learning: {}, blockers: [], safe_to_switch: true },
  });
  const [updateConfig, setUpdateConfig] = useState({ update_manifest_url: "" });
  const [updateLoading, setUpdateLoading] = useState(false);
  const [activeLogTab, setActiveLogTab] = useState("system");
  const logRequestSeqRef = useRef<Record<string, number>>({
    system: 0,
    daemon: 0,
  });
  const clearedLogHeadByTabRef = useRef<Record<string, string | null>>({
    system: null,
    daemon: null,
  });
  const activeLogs = logsByTab[activeLogTab] || [];
  const activeLogSource = String(logSourceByTab[activeLogTab] || "");
  const logTabMeta: Record<
    string,
    {
      label: string;
      title: string;
      description: string;
      empty: string;
      exportName: string;
    }
  > = {
    system: {
      label: "pipeline.log",
      title: "Pipeline 决策链",
      description:
        "展示 pipeline.py 对这笔单能不能下的真实裁决，包括策略信号、宏观约束、执行建议与最终拒绝原因。",
      empty: "暂无新的 Pipeline 决策日志...",
      exportName: "pipeline-decision",
    },
    daemon: {
      label: "gold_trader.log",
      title: "MT5 执行回报",
      description:
        "展示 gold_trader.py 的桥接执行与 EA 回报，包括是否到达 MT5、是否成交、部分平仓与持仓监控结果。",
      empty: "暂无新的 gold_trader 执行/回报日志...",
      exportName: "gold-trader-execution",
    },
  };
  const activeLogMeta = logTabMeta[activeLogTab] || logTabMeta.system;
  const [pendingSignals, setPendingSignals] = useState<any[]>([]);
  const [compositeName, setCompositeName] = useState("");
  const [compositeComponents, setCompositeComponents] = useState<string[]>([]);
  const [customStrategyName, setCustomStrategyName] = useState("");
  const [customStrategyDocument, setCustomStrategyDocument] = useState("");
  const [customOptimized, setCustomOptimized] = useState<
    Record<string, unknown>
  >({});
  const [customEvaluation, setCustomEvaluation] = useState<
    Record<string, unknown>
  >({});
  const [customDraftStatus, setCustomDraftStatus] = useState<
    "saved" | "syncing" | "unsaved"
  >("saved");
  const [customDraftSavedAt, setCustomDraftSavedAt] = useState("");
  const [customActionLoading, setCustomActionLoading] = useState<
    null | "optimize" | "evaluate" | "generate"
  >(null);
  const [templateEditorOpen, setTemplateEditorOpen] = useState(false);
  const [templateStrategy, setTemplateStrategy] = useState<any>(null);
  const [templateSaveBusy, setTemplateSaveBusy] = useState(false);
  const [templateSaveMessage, setTemplateSaveMessage] = useState<{
    text: string;
    type: "success" | "error";
  } | null>(null);
  const [templateBaseFields, setTemplateBaseFields] = useState({
    timeframe: "M5",
    risk_per_trade: 0.01,
    atr_sl_mult: 1.8,
    tp_rr: 2,
    max_positions: 1,
    reduce_only: false,
    strategy_style: "trend",
    execution_role: "primary",
    applicable_markets: ["TRENDING"] as string[],
    applicable_sessions: ["LONDON", "NEW_YORK"] as string[],
    conflict_groups: ["trend"] as string[],
    coordination_tags: ["TREND"] as string[],
    max_active_strategies: 2,
    conflict_hold_threshold: 0.35,
    allow_same_group_stack: false,
    allow_counter_style_mix: false,
  });
  const [templateAdvancedRaw, setTemplateAdvancedRaw] = useState("{}");
  const [templateAdvancedError, setTemplateAdvancedError] = useState("");
  const [strategyWorkbench, setStrategyWorkbench] = useState<any>({
    execution: {
      summary: {},
      openPositions: [],
      pendingSignals: [],
      activeSignals: [],
      recentSignals: [],
    },
    risk: {
      summary: {},
      governor: {},
      blackboard: {},
      trainingLifecycle: {},
      rollbackEvidence: {},
      autoGovernance: {},
      phaseReadiness: {},
      sessionRiskLens: {},
      macroPolling: {},
      confidenceCalibration: {},
    },
    marketplace: {
      current: {},
      switching: {},
      strategyRules: {},
      strategies: [],
      manifestSource: {},
    },
  });
  const [agentModels, setAgentModels] = useState<any[]>([]);
  const [availableModels, setAvailableModels] = useState<string[]>([]);
  const [showTrainingAdvanced, setShowTrainingAdvanced] = useState(false);
  const [showAuditSummaryExpanded, setShowAuditSummaryExpanded] =
    useState(false);
  const trainingEngine = trainingStatus.trainingEngine || {};
  const approvalDecision = approvalChain.decision;
  const approvalRecommendedActions = Array.isArray(
    approvalDecision.recommendedActions,
  )
    ? approvalDecision.recommendedActions.map((action) => String(action))
    : [];
  const approvalForbiddenActions = Array.isArray(
    approvalDecision.forbiddenActions,
  )
    ? approvalDecision.forbiddenActions.map((action) => String(action))
    : [];
  const approvalMissingConditions = Array.isArray(
    approvalDecision.missingConditions,
  )
    ? approvalDecision.missingConditions.map((item) => String(item))
    : [];
  const canCompleteTrainingReview = approvalRecommendedActions.includes(
    "complete_manual_review",
  );
  const canApproveTrainingSuggestion =
    approvalRecommendedActions.includes("approve_to_shadow");
  const canRepairTraining =
    approvalRecommendedActions.some(
      (action) =>
        action.startsWith("repair:") ||
        action.startsWith("wait_or_improve:") ||
        action === "rebuild_shadow_params",
    ) || Number(closureLifecycle.pendingRepairCount || 0) > 0;
  const canPromoteTraining = Boolean(approvalDecision.canPromote);
  const effectiveQualityContext =
    (approvalChain.effectiveParams?.quality_context as Record<
      string,
      unknown
    >) ||
    (approvalDecision.qualityContext as Record<string, unknown>) ||
    (approvalChain.suggestion?.quality_context as Record<string, unknown>) ||
    (approvalChain.appliedSuggestion?.quality_context as Record<
      string,
      unknown
    >) ||
    {};
  const effectiveOfflineParams =
    approvalChain.effectiveOfflineParams ||
    (approvalChain.effectiveParams?.offline_params as Record<
      string,
      unknown
    >) ||
    (approvalChain.suggestion?.suggested_params as Record<string, unknown>) ||
    (approvalChain.appliedSuggestion?.suggested_params as Record<
      string,
      unknown
    >) ||
    {};
  const paramLearnerReport =
    approvalChain.paramLearner || governanceReport.paramLearner || {};
  const paramLearnerComparison =
    (paramLearnerReport.offline_comparison as Record<string, unknown>) || {};
  const paramLearnerDelta =
    (paramLearnerComparison.delta as Record<string, unknown>) || {};
  const paramLearnerCandidate =
    (paramLearnerReport.candidate_policy as Record<string, unknown>) || {};
  const approvalShadowLearner = approvalChain.shadowLearner || {};
  const approvalLiveLearner = approvalChain.liveLearner || {};
  const approvalPhaseReadiness = approvalChain.phaseReadiness || {};
  const approvalRollbackState = approvalChain.rollbackState || {};
  const trainingApprovalSummary = trainingStatus.approvalSummary || {};
  const runtimeGateway = runtimeObservability.gateway || {};
  const runtimeDecisionContract =
    (runtimeGateway.decisionContract as Record<string, unknown>) || {};
  const runtimeDecisionContractLineage =
    (runtimeDecisionContract.lineage as Record<string, unknown>) || {};
  const runtimeDecisionContractUpdatedAt = String(
    runtimeDecisionContract.updatedAt || "",
  );
  const runtimeDecisionContractUpdatedAtLabel =
    formatDisplayTimestamp(runtimeDecisionContractUpdatedAt) ||
    runtimeDecisionContractUpdatedAt;
  const runtimeDecisionContractHealthStatus = String(
    runtimeDecisionContract.healthStatus || "UNKNOWN",
  ).toUpperCase();
  const runtimeDecisionContractHealthLabel = String(
    runtimeDecisionContract.healthLabel || "合同状态未知",
  );
  const runtimeDecisionContractMissingLineage = Array.isArray(
    runtimeDecisionContract.missingLineage,
  )
    ? (runtimeDecisionContract.missingLineage as unknown[]).map((item) =>
        String(item || ""),
      )
    : [];
  const runtimeInterpreter = runtimeObservability.interpreter || {};
  const runtimeInterpreterUpdatedAt = String(
    runtimeInterpreter.updatedAt || "",
  );
  const runtimePerformance = runtimeObservability.performance || {};
  const runtimeTrainingGate = runtimeObservability.trainingGate || {};
  const runtimeAutoGovernance = runtimeObservability.autoGovernance || {};
  const runtimeGoalSnapshot =
    (runtimeAutoGovernance.goalGateSnapshot as Record<string, unknown>) || {};
  const runtimeLatestGoalAction =
    (runtimeAutoGovernance.latestGoalAction as Record<string, unknown>) || {};
  const runtimeLatestGoalActionAt = String(
    runtimeLatestGoalAction.timestamp ||
      runtimeLatestGoalAction.generated_at ||
      "",
  );
  const runtimeGoalTargets = runtimeObservability.goalTargets || {};
  const runtimeEvolutionEvidence = runtimeObservability.evolutionEvidence || {};
  const runtimeAutonomyLoop = runtimeObservability.autonomyLoop || {};
  const runtimeSessionRiskLens = runtimeObservability.sessionRiskLens || {};
  const runtimeDirectionQuality = runtimeObservability.directionQuality || {};
  const runtimeMacroPolling = runtimeObservability.macroPolling || {};
  const runtimeConfidenceCalibration =
    runtimeObservability.confidenceCalibration || {};
  const runtimeTrailingTelemetry = runtimeObservability.trailingTelemetry || {};
  const workbenchExecution =
    (strategyWorkbench.execution as Record<string, any>) || {};
  const workbenchExecutionSummary =
    (workbenchExecution.summary as Record<string, any>) || {};
  const visibleOpenPositions = selectVisibleOpenPositions(
    workbenchExecution.openPositions,
    status.positions,
  );
  const signalReviewQueue = Array.isArray(
    workbenchExecution.signalReviewSignals,
  )
    ? workbenchExecution.signalReviewSignals
    : pendingSignals;
  const signalReviewPendingCount = Number(
    workbenchExecution.signalReviewPendingCount ??
      workbenchExecutionSummary.signalReviewPendingCount ??
      workbenchExecutionSummary.pendingReviews ??
      signalReviewQueue.length ??
      0,
  );
  const workbenchRisk = (strategyWorkbench.risk as Record<string, any>) || {};
  const workbenchRiskSummary =
    (workbenchRisk.summary as Record<string, any>) || {};
  const workbenchGovernor =
    (workbenchRisk.governor as Record<string, any>) || {};
  const workbenchMarketplace =
    (strategyWorkbench.marketplace as Record<string, any>) || {};
  const workbenchMarketplaceCurrent =
    (workbenchMarketplace.current as Record<string, any>) || {};
  const workbenchDecisionPolicy =
    (workbenchMarketplace.decisionPolicy as Record<string, any>) || {};
  const syncDecisionPolicyForm = (policy: Record<string, any>) => {
    const macro =
      policy && typeof policy.macro === "object" ? policy.macro : {};
    const interpreter =
      policy && typeof policy.interpreter === "object"
        ? policy.interpreter
        : {};
    const risk = policy && typeof policy.risk === "object" ? policy.risk : {};
    const execution =
      policy && typeof policy.execution === "object" ? policy.execution : {};
    setDecisionPolicyForm({
      profile: String(policy?.profile || "agent_guided_multi_strategy"),
      macroRole: String(macro.role || "directional_gate"),
      macroAlignedScale: Number(macro.aligned_scale || 1.1),
      macroCountertrendScale: Number(macro.countertrend_scale || 0.35),
      macroNeutralScale: Number(macro.neutral_scale || 1.0),
      macroDegradedPolicy: String(macro.degraded_policy || "soften_to_neutral"),
      interpreterRole: String(interpreter.role || "execution_bias_only"),
      interpreterBuyScale: Number(interpreter.buy_scale || 1.0),
      interpreterSellScale: Number(interpreter.sell_scale || 1.0),
      interpreterLimitCountertrendScale: Number(
        interpreter.limit_countertrend_scale || 0.5,
      ),
      interpreterBlockCountertrendScale: Number(
        interpreter.block_countertrend_scale || 0.0,
      ),
      riskRole: String(risk.role || "veto_only"),
      executionAggregation: String(
        execution.aggregation || "weighted_net_confidence",
      ),
      executionMinConfidence: Number(execution.min_confidence || 0.15),
    });
  };
  const runtimeOpsInstances = Array.isArray(runtimeConsole.runtimeInstances)
    ? runtimeConsole.runtimeInstances
    : [];
  const runtimeOpsScheduler =
    (runtimeConsole.runtimeScheduler as Record<string, any>) || {};
  const runtimeOpsSchedulerSummary =
    (runtimeOpsScheduler.summary as Record<string, any>) || {};
  const runtimeOpsExplain =
    (runtimeConsole.runtimeExplain as Record<string, any>) || {};
  const runtimeOpsArbitration =
    (runtimeOpsExplain.arbitration as Record<string, any>) || {};
  const runtimeOpsArbitrationSummary =
    (runtimeOpsArbitration.summary as Record<string, any>) || {};
  const runtimeOpsCurrent =
    (runtimeOpsExplain.current as Record<string, any>) || {};
  const runtimeOpsDecisionPolicy =
    (runtimeOpsExplain.decisionPolicy as Record<string, any>) || {};
  const runtimeOpsDiagnostics =
    (runtimeConsole.runtimeAgentDiagnostics as Record<string, any>) || {};
  const runtimeOpsDiagnosticsSummary =
    (runtimeOpsDiagnostics.summary as Record<string, any>) || {};
  const runtimeOpsSuppressions = Array.isArray(
    runtimeOpsDiagnostics.suppressions,
  )
    ? runtimeOpsDiagnostics.suppressions
    : [];
  const currentRuntimeStrategyId = String(
    workbenchExecutionSummary.runtimeSelectedStrategyId ||
      runtimeOpsScheduler.selectedStrategyId ||
      workbenchMarketplaceCurrent.selectedStrategyId ||
      workbenchMarketplaceCurrent.strategyId ||
      "-",
  );
  const currentRuntimeStrategyName = String(
    workbenchExecutionSummary.runtimeSelectedStrategyName ||
      workbenchMarketplaceCurrent.strategyName ||
      "未知策略",
  );
  const currentRuntimeStrategyIds = Array.isArray(
    workbenchExecutionSummary.runtimeActiveStrategyIds,
  )
    ? workbenchExecutionSummary.runtimeActiveStrategyIds
    : Array.isArray(runtimeOpsScheduler.activeStrategyIds)
      ? runtimeOpsScheduler.activeStrategyIds
      : [];
  const currentRuntimeMode = String(
    workbenchExecutionSummary.runtimeMode ||
      runtimeOpsScheduler.mode ||
      "single_active",
  );
  const currentRuntimeArbiter = String(
    workbenchExecutionSummary.runtimeArbiter ||
      runtimeOpsScheduler.arbiter ||
      "allocation-weighted",
  );
  const runtimeOpsProfileWarnings = Array.isArray(
    runtimeOpsDiagnostics.profileWarnings,
  )
    ? runtimeOpsDiagnostics.profileWarnings
    : [];
  const runtimeOpsOverrideWarnings = Array.isArray(
    runtimeOpsDiagnostics.overrideWarnings,
  )
    ? runtimeOpsDiagnostics.overrideWarnings
    : [];
  const runtimeOpsBridgeQueue =
    (runtimeConsole.runtimeBridgeQueue as Record<string, any>) || {};
  const runtimeOpsBridgeRequests = Array.isArray(
    runtimeConsole.runtimeBridgeRequests,
  )
    ? runtimeConsole.runtimeBridgeRequests
    : [];
  const runtimeOpsExecutionFocus = Array.isArray(
    runtimeConsole.runtimeExecutionFocus,
  )
    ? runtimeConsole.runtimeExecutionFocus
    : [];
  const runtimeOpsBridgeHealth =
    (runtimeConsole.runtimeBridgeHealth as Record<string, any>) || {};
  const runtimeOpsStatus =
    (runtimeConsole.runtimeStatus as Record<string, any>) || {};
  const runtimeOpsGateway =
    (runtimeOpsStatus.gateway as Record<string, any>) || {};
  const runtimeOpsMarket =
    (runtimeOpsStatus.market as Record<string, any>) || {};
  const runtimeOpsPerformance =
    (runtimeOpsStatus.performance as Record<string, any>) || {};
  const runtimeOpsRiskGovernor =
    (runtimeOpsStatus.riskGovernor as Record<string, any>) || {};
  const runtimeOpsRiskSummary =
    (runtimeOpsRiskGovernor.summary as Record<string, any>) || {};
  const runtimeOpsRiskGovernorState =
    (runtimeOpsRiskGovernor.governor as Record<string, any>) || {};
  const runtimeOpsOrchestration =
    (runtimeConsole.orchestrationSnapshot as Record<string, any>) || {};
  const runtimeAiRecommendations = Array.isArray(
    runtimeAiEvaluation.recommendations,
  )
    ? runtimeAiEvaluation.recommendations
    : [];
  const runtimeAiRiskWarnings = Array.isArray(runtimeAiEvaluation.riskWarnings)
    ? runtimeAiEvaluation.riskWarnings
    : [];
  const runtimeAiApplyAvailable = Boolean(
    runtimeAiEvaluation.applySuggestionAvailable,
  );
  const runtimeAiLatestHistory =
    runtimeAiHistory.length > 0 ? runtimeAiHistory[0] : null;
  const runtimeAiSummaryVerdict = String(
    runtimeAiEvaluation.currentConclusion ||
      runtimeAiLatestHistory?.verdictLabel ||
      "尚未进行 AI 组合评估",
  );
  const runtimeAiSummaryCombo = String(
    runtimeAiEvaluation.recommendedComboLabel ||
      runtimeAiLatestHistory?.recommendedComboLabel ||
      "保持当前组合",
  );
  const runtimeAiSummaryHint = String(
    runtimeAiEvaluation.rationale ||
      runtimeAiEvaluation.applySuggestionReason ||
      "默认隐藏详细建议，需要时再展开查看完整评估。",
  );
  const runtimeOpsContributors = Array.isArray(
    runtimeOpsArbitration.contributors,
  )
    ? [...runtimeOpsArbitration.contributors].toSorted(
        (a: any, b: any) =>
          Number(Math.abs(b.signedScore || 0)) -
          Number(Math.abs(a.signedScore || 0)),
      )
    : [];
  const contributorTone = (item: Record<string, any>) => {
    if (item.wasSelected) {
      return "border-primary/50 bg-primary/10";
    }
    if (item.wasSuppressed) {
      return "border-warning/40 bg-warning/10";
    }
    const classification = String(item.classification || "neutral");
    if (classification === "support_buy") {
      return "border-success/40 bg-success/10";
    }
    if (classification === "support_sell") {
      return "border-danger/40 bg-danger/10";
    }
    return "border-slate-700 bg-[#0A0E17]";
  };
  const contributorScoreTone = (score: number) => {
    if (score > 0) {
      return "text-success";
    }
    if (score < 0) {
      return "text-danger";
    }
    return "text-slate-300";
  };
  const runtimePillTone = (tone: "ok" | "warn" | "danger" | "neutral") => {
    if (tone === "ok") {
      return "border-success/30 bg-success/10 text-success";
    }
    if (tone === "warn") {
      return "border-warning/30 bg-warning/10 text-warning";
    }
    if (tone === "danger") {
      return "border-danger/30 bg-danger/10 text-danger";
    }
    return "border-slate-700 bg-slate-800/70 text-slate-200";
  };
  const formatNumberValue = (value: unknown, digits = 2) => {
    const num = Number(value ?? 0);
    return Number.isFinite(num) ? num.toFixed(digits) : "0.00";
  };
  const formatPercentPoints = (value: unknown, digits = 1) =>
    `${formatNumberValue(value, digits)}%`;
  const formatRatioPercent = (value: unknown, digits = 1) =>
    `${formatNumberValue(Number(value ?? 0) * 100, digits)}%`;
  const formatSignedNumber = (value: unknown, digits = 2) => {
    const num = Number(value ?? 0);
    if (!Number.isFinite(num)) {
      return "0.00";
    }
    return `${num >= 0 ? "+" : ""}${num.toFixed(digits)}`;
  };
  const formatValueOrFallback = (value: unknown, fallback = "暂无") => {
    const text = String(value ?? "").trim();
    return text || fallback;
  };
  const runtimeCardTone = (instance: Record<string, any>) => {
    const risk = (instance.risk as Record<string, any>) || {};
    if (String(risk.status || "") === "blocked") {
      return "border-danger/35 bg-danger/5";
    }
    if (!instance.active) {
      return "border-warning/30 bg-warning/5";
    }
    if (instance.selected) {
      return "border-primary/35 bg-primary/5";
    }
    return "border-slate-800 bg-[#0A0E17]";
  };
  const reservedTemplateKeys = new Set([
    "strategy_id",
    "version",
    "runtime_scheduler",
  ]);
  const isReservedTemplateKey = (key: string) => reservedTemplateKeys.has(key);
  const stripReservedTemplateKeys = (value: Record<string, unknown>) => {
    const sanitized: Record<string, unknown> = {};
    Object.entries(value).forEach(([key, item]) => {
      if (!isReservedTemplateKey(key)) {
        sanitized[key] = item;
      }
    });
    return sanitized;
  };
  const parsedAdvancedParams = (() => {
    const raw = String(templateAdvancedRaw || "").trim();
    if (!raw) {
      return {
        ok: true,
        value: {} as Record<string, unknown>,
        sanitizedValue: {} as Record<string, unknown>,
        strippedKeys: [] as string[],
        error: "",
      };
    }
    try {
      const parsed = JSON.parse(raw);
      if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
        return {
          ok: false,
          value: {},
          sanitizedValue: {},
          strippedKeys: [],
          error: "高级参数必须是 JSON 对象",
        };
      }
      const value = parsed as Record<string, unknown>;
      const strippedKeys = Object.keys(value).filter((key) =>
        isReservedTemplateKey(key),
      );
      return {
        ok: true,
        value,
        sanitizedValue: stripReservedTemplateKeys(value),
        strippedKeys,
        error: "",
      };
    } catch {
      return {
        ok: false,
        value: {},
        sanitizedValue: {},
        strippedKeys: [],
        error: "高级参数 JSON 格式错误",
      };
    }
  })();
  const normalizedApplicableMarkets = templateBaseFields.applicable_markets;
  const normalizedApplicableSessions = templateBaseFields.applicable_sessions;
  const normalizedConflictGroups = templateBaseFields.conflict_groups;
  const normalizedCoordinationTags = templateBaseFields.coordination_tags;
  const mergedTemplatePreview = {
    ...parsedAdvancedParams.sanitizedValue,
    ...templateBaseFields,
    applicable_markets: normalizedApplicableMarkets,
    applicable_sessions: normalizedApplicableSessions,
    conflict_groups: normalizedConflictGroups,
    coordination_tags: normalizedCoordinationTags,
    contract_version: "1",
    template_kind: "strategy_runtime_contract",
    execution_baseline: {
      timeframe: templateBaseFields.timeframe,
      risk_per_trade: templateBaseFields.risk_per_trade,
      atr_sl_mult: templateBaseFields.atr_sl_mult,
      tp_rr: templateBaseFields.tp_rr,
      max_positions: templateBaseFields.max_positions,
      reduce_only: templateBaseFields.reduce_only,
    },
    runtime_context: {
      applicable_markets: normalizedApplicableMarkets,
      applicable_sessions: normalizedApplicableSessions,
    },
    coordination_contract: {
      strategy_style: templateBaseFields.strategy_style,
      execution_role: templateBaseFields.execution_role,
      conflict_groups: normalizedConflictGroups,
      coordination_tags: normalizedCoordinationTags,
      max_active_strategies: templateBaseFields.max_active_strategies,
      conflict_hold_threshold: templateBaseFields.conflict_hold_threshold,
      allow_same_group_stack: templateBaseFields.allow_same_group_stack,
      allow_counter_style_mix: templateBaseFields.allow_counter_style_mix,
    },
  };
  const workbenchRiskBlackboard =
    (workbenchRisk.blackboard as Record<string, any>) || {};
  const runtimeTechnicalTrendData =
    (runtimeGateway.technicalTrendData as Record<string, unknown>) || {};
  const runtimeMacroDirectionData =
    (runtimeGateway.macroDirectionData as Record<string, unknown>) || {};
  const decisionContractSources = [
    {
      key: "macro",
      label: "Macro",
      value: String(runtimeDecisionContractLineage.macro || "unknown"),
    },
    {
      key: "interpreter",
      label: "Interpreter",
      value: String(runtimeDecisionContractLineage.interpreter || "unknown"),
    },
    {
      key: "decision_policy",
      label: "Policy",
      value: String(
        runtimeDecisionContractLineage.decision_policy || "unknown",
      ),
    },
  ];
  const decisionContractHealth = (() => {
    if (runtimeDecisionContractHealthStatus === "READY") {
      return {
        badge: "bg-success/10 text-success border-success/30",
        label: runtimeDecisionContractHealthLabel,
      };
    }
    if (runtimeDecisionContractHealthStatus === "LEGACY_FALLBACK") {
      return {
        badge: "bg-warning/10 text-warning border-warning/30",
        label: runtimeDecisionContractHealthLabel,
      };
    }
    if (runtimeDecisionContractHealthStatus === "MISSING_LINEAGE") {
      return {
        badge: "bg-warning/10 text-warning border-warning/30",
        label: runtimeDecisionContractHealthLabel,
      };
    }
    return {
      badge: "bg-slate-500/10 text-slate-300 border-slate-500/30",
      label: runtimeDecisionContractHealthLabel,
    };
  })();
  const activeMacroDirection = String(
    runtimeDecisionContract.bindingDirection ||
      runtimeGateway.bindingDirection ||
      runtimeMacroDirectionData.binding_direction ||
      runtimeMacroDirectionData.direction ||
      runtimeGateway.agentDirection ||
      status.agent_dir ||
      "NEUTRAL",
  ).toUpperCase();
  const activeExecutionAdvice = String(
    runtimeDecisionContract.executionAdvice ||
      runtimeInterpreter.executionAdvice ||
      "UNKNOWN",
  ).toUpperCase();
  const activeDecisionProfile = String(
    runtimeDecisionContract.profile ||
      workbenchDecisionPolicy.profile ||
      decisionPolicyForm.profile ||
      "unknown",
  );
  const technicalTrendBias = String(
    runtimeGateway.technicalTrendBias || "NEUTRAL",
  ).toUpperCase();
  const technicalTrendTone = (() => {
    if (technicalTrendBias === "LONG") {
      return {
        badge: "bg-success/10 text-success border-success/30",
        label: "LONG",
      };
    }
    if (technicalTrendBias === "SHORT") {
      return {
        badge: "bg-danger/10 text-danger border-danger/30",
        label: "SHORT",
      };
    }
    return {
      badge: "bg-warning/10 text-warning border-warning/30",
      label: "NEUTRAL",
    };
  })();
  const trailingOpportunityState = String(
    runtimeTrailingTelemetry.opportunity_state || "UNKNOWN",
  ).toUpperCase();
  const trailingStateTone = (() => {
    if (trailingOpportunityState === "PROFIT_EXPANDING") {
      return {
        badge: "bg-success/10 text-success border-success/30",
        label: "利润扩张",
      };
    }
    if (trailingOpportunityState === "PROFIT_EXHAUSTING") {
      return {
        badge: "bg-warning/10 text-warning border-warning/30",
        label: "波段衰竭",
      };
    }
    if (trailingOpportunityState === "PROFIT_GIVEBACK") {
      return {
        badge: "bg-danger/10 text-danger border-danger/30",
        label: "利润回吐",
      };
    }
    if (trailingOpportunityState === "EARLY_PROFIT") {
      return {
        badge: "bg-primary/10 text-primary border-primary/30",
        label: "早期盈利",
      };
    }
    if (trailingOpportunityState.startsWith("LOSS_")) {
      return {
        badge: "bg-danger/10 text-danger border-danger/30",
        label: "亏损阶段",
      };
    }
    return {
      badge: "bg-slate-900 text-slate-300 border-slate-700",
      label: "等待识别",
    };
  })();
  const runtimeAsiaLondonRule =
    (runtimeSessionRiskLens.asiaLondonOverlap as Record<string, unknown>) || {};
  const runtimeLondonNyRule =
    (runtimeSessionRiskLens.londonNyOverlap as Record<string, unknown>) || {};
  const sessionActionTone = (rule: Record<string, unknown>) => {
    const action = String(rule.action || "neutral").toLowerCase();
    const blocked = Boolean(rule.block);
    if (blocked || action === "avoid") {
      return { dot: "bg-danger", text: "text-danger", label: "DEFENSIVE" };
    }
    if (action === "favor") {
      return { dot: "bg-success", text: "text-success", label: "OPPORTUNITY" };
    }
    return { dot: "bg-warning", text: "text-warning", label: "NEUTRAL" };
  };
  const asiaLondonTone = sessionActionTone(runtimeAsiaLondonRule);
  const londonNyTone = sessionActionTone(runtimeLondonNyRule);
  const runtimeGoalMonth =
    (runtimeGoalTargets.window_month as Record<string, unknown>) || {};
  const runtimeGoalGates =
    (runtimeGoalTargets.gates as Record<string, unknown>) || {};
  const runtimeDrawdownGate =
    (runtimeGoalGates.max_drawdown_pct as Record<string, unknown>) || {};
  const runtimeAutonomyGate =
    (runtimeGoalGates.autonomy_rate_pct as Record<string, unknown>) || {};
  const runtimeEvidenceSamples =
    (runtimeEvolutionEvidence.samples as Record<string, unknown>) || {};
  const runtimeEvidenceLearner =
    (runtimeEvidenceSamples.learner_live as Record<string, unknown>) || {};
  const runtimeEvidenceBaseline =
    (runtimeEvidenceSamples.baseline as Record<string, unknown>) || {};
  const runtimeEvidenceTests =
    (runtimeEvolutionEvidence.significance_tests as Record<string, unknown>) ||
    {};
  const runtimeEvidencePnlTest =
    (runtimeEvidenceTests.pnl_mean_diff as Record<string, unknown>) || {};
  const runtimeEvidenceVerdict =
    (runtimeEvolutionEvidence.verdict as Record<string, unknown>) || {};
  const runtimeTopBuckets =
    (runtimePerformance.topBuckets as Record<
      string,
      Array<Record<string, unknown>>
    >) || {};
  const runtimeTopSessions = Array.isArray(runtimeTopBuckets.session)
    ? runtimeTopBuckets.session
    : [];
  const runtimeTopRegimes = Array.isArray(runtimeTopBuckets.regime)
    ? runtimeTopBuckets.regime
    : [];
  const runtimeTopStrategies = Array.isArray(runtimeTopBuckets.strategy)
    ? runtimeTopBuckets.strategy
    : [];
  const runtimeTopInterpreters = Array.isArray(runtimeTopBuckets.interpreter)
    ? runtimeTopBuckets.interpreter
    : [];
  const qualitySamplePolicy =
    (effectiveQualityContext.sample_policy as Record<string, unknown>) || {};
  const quickSampleCount = Number(
    trainingStatus.shadowClosedTrades || trainingStatus.totalTrades || 0,
  );
  const quickSampleThreshold = Number(
    qualitySamplePolicy.min_usable_trade_count ||
      effectiveQualityContext.min_usable_trade_count ||
      0,
  );
  const quickWinRate = Number(trainingStatus.winRate || 0);
  const quickDrawdown = Number(
    trainingStatus.drawdown ||
      approvalShadowLearner.max_shadow_max_drawdown_abs ||
      trainingStatus.shadowMaxDrawdownAbs ||
      approvalShadowLearner.shadowMaxDrawdownAbs ||
      0,
  );
  const trainingMetricsSource = String(
    trainingStatus.metricsSource || "training_status",
  );
  const trainingMetricsUpdatedAt = String(
    trainingStatus.metricsUpdatedAt || "",
  );
  const readinessLabel = trainingStatus.readyForTraining ? "可推进" : "需改进";
  const readinessReason = trainingStatus.readyForTraining
    ? "训练门槛已满足，可执行系统建议动作。"
    : trainingStatus.blockedReasons.join("，") || "门槛未满足，先处理阻断项。";
  const autoPilotStage = String(trainingStatus.autoPilotStage || "");
  const summaryTrainingReviewPending = Boolean(
    trainingApprovalSummary.trainingReviewPending ??
    trainingApprovalSummary.reviewPending,
  );
  const summaryTrainingReviewBlocked = Boolean(
    trainingApprovalSummary.trainingReviewBlocked ??
    trainingApprovalSummary.reviewBlocked,
  );
  const summaryHasEffectiveParams = Boolean(
    trainingApprovalSummary.hasEffectiveParams,
  );
  const summaryCanRollback = Boolean(
    trainingApprovalSummary.canRollback ||
    trainingApprovalSummary.rollbackAvailable,
  );
  const hasSuggestion =
    String(approvalChain.stage || "NO_SUGGESTION") !== "NO_SUGGESTION" ||
    summaryTrainingReviewPending ||
    summaryHasEffectiveParams ||
    autoPilotStage === "await_manual_review";
  const hasShadow = Boolean(approvalDecision.shadowExists);
  const trainingReviewPending =
    Boolean(
      approvalDecision.trainingReviewPending ?? approvalDecision.reviewPending,
    ) ||
    summaryTrainingReviewPending ||
    autoPilotStage === "await_manual_review";
  const hasEffectiveParams =
    Object.keys(effectiveOfflineParams).length > 0 || summaryHasEffectiveParams;
  const canRollbackTraining = Boolean(
    approvalDecision.canRollback ||
    approvalRollbackState.available ||
    summaryCanRollback,
  );
  const rollbackAvailable = Boolean(approvalRollbackState.available);
  const rollbackLastAt = String(
    approvalRollbackState.lastRollbackAt ||
      approvalRollbackState.lastActionAt ||
      approvalRollbackState.latestBackupAt ||
      "",
  );
  const rollbackSource = String(
    approvalRollbackState.lastRollbackSource ||
      approvalRollbackState.latestBackupSource ||
      "",
  );
  const auditSummaryText = String(
    governanceReport.governanceAdvice ||
      approvalChain.suggestion?.evolution_reason ||
      approvalChain.appliedSuggestion?.evolution_reason ||
      approvalDecision.nextStep ||
      "系统正在等待新的训练证据，请先生成分析报告。",
  );
  const approvalVerdict = canCompleteTrainingReview
    ? "待人工复核后决定是否继续推进"
    : canApproveTrainingSuggestion
      ? "建议先进入可回滚观察态，再做人工复核"
      : canPromoteTraining
        ? `已满足条件，可推进到 ${String(approvalDecision.promotionTarget || "下一阶段")}`
        : trainingStatus.readyForTraining
          ? "训练门槛已满足，等待生成或刷新进化建议"
          : "训练门槛未满足，当前不建议应用到实盘";
  const rollbackHintText = rollbackAvailable
    ? `已保留稳定快照${rollbackLastAt ? ` · ${rollbackLastAt}` : ""}${rollbackSource ? ` · ${rollbackSource}` : ""}`
    : "当前还没有稳定快照，需先有一版已应用参数后才能回滚";
  const flowItems: Array<{
    id: string;
    label: string;
    hint: string;
    status: "done" | "active" | "waiting";
  }> = [
    {
      id: "suggestion",
      label: "训练建议",
      hint: hasSuggestion ? "已生成" : "待生成",
      status: hasSuggestion ? "done" : "waiting",
    },
    {
      id: "shadow",
      label: "影子参数",
      hint: hasShadow ? "已写入" : "待批准",
      status: hasShadow ? "done" : hasSuggestion ? "active" : "waiting",
    },
    {
      id: "review",
      label: "人工复核",
      hint: summaryTrainingReviewBlocked
        ? "待回滚"
        : trainingReviewPending
          ? "待复核"
          : hasEffectiveParams
            ? "已完成"
            : "未开始",
      status: trainingReviewPending
        ? "active"
        : hasEffectiveParams
          ? "done"
          : "waiting",
    },
    {
      id: "promote",
      label: "阶段推进",
      hint: canPromoteTraining ? "可推进" : "待满足门槛",
      status: canPromoteTraining ? "active" : "waiting",
    },
  ];
  const actionLabelMap: Record<string, string> = {
    complete_manual_review: "手动完成人工复核",
    approve_to_shadow: "自动推进到观察态",
    rollback_to_previous_effective: "手动回滚到上一稳定参数",
    rebuild_shadow_params: "自动重建影子参数",
  };
  const humanizeTrainingAction = (action: string) => {
    if (actionLabelMap[action]) {
      return actionLabelMap[action];
    }
    if (action.startsWith("wait_or_improve:")) {
      return "继续训练并等待门槛改善";
    }
    if (action.startsWith("repair:")) {
      return "手动修复阻断项";
    }
    if (action.startsWith("promote_to_")) {
      return "手动推进到下一阶段";
    }
    return action;
  };
  const statusBlackboard = (((status as unknown as Record<string, unknown>)
    .blackboard as Record<string, unknown>) || {}) as Record<string, any>;
  const blackboardExecution =
    (blackboardState?.Execution_Arbitration as Record<string, any>) ||
    (statusBlackboard.Execution_Arbitration as Record<string, any>) ||
    {};
  const blackboardRiskProtocol =
    (blackboardState?.Risk_Protocol as Record<string, any>) ||
    (statusBlackboard.Risk_Protocol as Record<string, any>) ||
    {};
  const blackboardScheduler =
    (blackboardState?.Scheduler_Runtime as Record<string, any>) ||
    (statusBlackboard.Scheduler_Runtime as Record<string, any>) ||
    {};
  const nonRiskHoldMarkers = [
    "AGGREGATED_HOLD_LOW_NET_SCORE",
    "AGGREGATED_HOLD_NO_ACTIONABLE_SIGNAL",
  ];
  const runtimeGovernorBlockers = Array.from(
    new Set(
      (Array.isArray(blackboardRiskProtocol.governor_blockers)
        ? blackboardRiskProtocol.governor_blockers
        : []
      )
        .map((item) => String(item || "").trim())
        .filter(
          (reason) =>
            !nonRiskHoldMarkers.some((marker) => reason.includes(marker)),
        )
        .filter(Boolean),
    ),
  );
  const runtimeSignalHoldReasons = Array.from(
    new Set(
      (Array.isArray(blackboardExecution.blocked_reasons)
        ? blackboardExecution.blocked_reasons
        : []
      )
        .map((item) => String(item || "").trim())
        .filter(Boolean),
    ),
  );
  const approvalDecisionStatus = String(approvalDecision.status || "NO_ACTION");
  const approvalStage = String(approvalChain.stage || "NO_SUGGESTION");
  const approvalNextStep = String(
    approvalDecision.nextStep || auditSummaryText || "等待新的审批结论",
  );
  const decisionHallApprovalTone = (() => {
    if (
      approvalDecisionStatus === "ROLLBACK_REQUIRED" ||
      approvalDecisionStatus === "BLOCKED"
    ) {
      return "danger";
    }
    if (
      approvalDecisionStatus === "WAIT_APPROVAL" ||
      approvalDecisionStatus === "WAIT_HUMAN_REVIEW"
    ) {
      return "warning";
    }
    if (approvalDecisionStatus === "READY_TO_PROMOTE") {
      return "success";
    }
    return "info";
  })();
  const decisionToneClass = (tone: string) => {
    if (tone === "danger") {
      return "border-danger/30 bg-danger/10";
    }
    if (tone === "warning") {
      return "border-warning/30 bg-warning/10";
    }
    if (tone === "success") {
      return "border-success/30 bg-success/10";
    }
    return "border-primary/25 bg-primary/10";
  };
  const decisionLabelClass = (tone: string) => {
    if (tone === "danger") {
      return "text-danger";
    }
    if (tone === "warning") {
      return "text-warning";
    }
    if (tone === "success") {
      return "text-success";
    }
    return "text-primary";
  };
  const decisionHallMessages: Array<{
    id: string;
    tone: string;
    title: string;
    body: string;
    chips: string[];
    source: string;
    timestamp: string;
    actor: string;
    actorTone: string;
    sortTs: number;
    priority: number;
  }> = [
    {
      id: "approval_chain",
      tone: decisionHallApprovalTone,
      title: "审批链结论",
      body: approvalNextStep,
      chips: [
        `stage:${approvalStage}`,
        `status:${approvalDecisionStatus}`,
        ...approvalRecommendedActions
          .slice(0, 2)
          .map((action) => humanizeTrainingAction(action)),
        ...approvalMissingConditions.slice(0, 2),
      ].filter(Boolean),
      source: "approval_chain",
      timestamp: String(
        (approvalChain as Record<string, unknown>).updatedAt ||
          (approvalChain as Record<string, unknown>).generatedAt ||
          approvalRollbackState.lastActionAt ||
          "",
      ),
      actor: "Approval_Chain",
      actorTone: "text-warning",
      sortTs: Date.parse(
        String(
          (approvalChain as Record<string, unknown>).updatedAt ||
            (approvalChain as Record<string, unknown>).generatedAt ||
            approvalRollbackState.lastActionAt ||
            "",
        ),
      ),
      priority: 90,
    },
  ];
  const decisionHallFreshnessAnchorMs = Math.max(
    Date.parse(runtimeDecisionContractUpdatedAt || ""),
    Date.parse(runtimeInterpreterUpdatedAt || ""),
    0,
  );
  const decisionHallMessageMaxAgeMs =
    decisionHallFreshnessAnchorMs > 0
      ? 30 * 60 * 1000
      : Number.POSITIVE_INFINITY;
  if (signalReviewPendingCount > 0) {
    signalReviewQueue.slice(0, 2).forEach((signal: any) => {
      decisionHallMessages.push({
        id: `pending_${String(signal.id || signal.signal_id || "")}`,
        tone: "warning",
        title: "待人工审批信号",
        body: String(signal.reason || "低置信度，等待人工复核"),
        chips: [
          String(signal.side || "UNKNOWN"),
          `${(Number(signal.confidence || 0) * 100).toFixed(0)}%`,
          String(signal.signal_id || signal.id || ""),
        ].filter(Boolean),
        source: "signal_review_queue",
        timestamp: "",
        actor: "Review_Queue",
        actorTone: "text-warning",
        sortTs: Date.now(),
        priority: 80,
      });
    });
  }
  if (status.risk_block?.exists) {
    decisionHallMessages.push({
      id: "risk_block",
      tone: "danger",
      title: "运行阻断",
      body: String(
        status.risk_block.summary ||
          status.risk_block.rawReason ||
          "当前存在运行阻断",
      ),
      chips: [
        String(status.risk_block.categoryLabel || "未分类"),
        formatDisplayTimestamp(status.risk_block.time) ||
          String(status.risk_block.time || ""),
      ].filter(Boolean),
      source: "risk_block",
      timestamp: String(status.risk_block.time || ""),
      actor: "Risk_Commissar",
      actorTone: "text-warning",
      sortTs: Date.parse(String(status.risk_block.time || "")),
      priority: 100,
    });
  }
  if (status.final_reject?.reason) {
    decisionHallMessages.push({
      id: "final_reject",
      tone: "warning",
      title: "最终拒绝",
      body: String(status.final_reject.reason || ""),
      chips: [
        String(status.final_reject.stage || "unknown"),
        String(blackboardExecution.final_action || "HOLD"),
      ].filter(Boolean),
      source: "execution_arbitration",
      timestamp: String(status.final_reject.ts || ""),
      actor: "Risk_Commissar",
      actorTone: "text-danger",
      sortTs: Number(status.final_reject.ts || 0) * 1000,
      priority: 95,
    });
  }
  if (runtimeGovernorBlockers.length > 0) {
    decisionHallMessages.push({
      id: "governor_blockers",
      tone: "danger",
      title: "风控阻断集合",
      body: runtimeGovernorBlockers.slice(0, 3).join("，"),
      chips: [
        String(blackboardRiskProtocol.global_state || "blocked"),
        `${runtimeGovernorBlockers.length} 项`,
      ],
      source: "risk_protocol",
      timestamp: "",
      actor: "Risk_Commissar",
      actorTone: "text-warning",
      sortTs: Date.now() - 1000,
      priority: 92,
    });
  }
  if (
    runtimeGovernorBlockers.length === 0 &&
    String(blackboardExecution.hold_mode || "") === "signal_hold" &&
    runtimeSignalHoldReasons.length > 0
  ) {
    decisionHallMessages.push({
      id: "signal_hold_reasons",
      tone: "warning",
      title: "信号观望原因",
      body: runtimeSignalHoldReasons.slice(0, 3).join("，"),
      chips: [
        String(blackboardExecution.hold_mode || "signal_hold"),
        `${runtimeSignalHoldReasons.length} 项`,
      ],
      source: "execution_arbitration",
      timestamp: "",
      actor: "Execution_Arbitration",
      actorTone: "text-warning",
      sortTs: Date.now() - 900,
      priority: 91,
    });
  }
  const decisionHallMailboxLogs = mailboxLogs
    .filter((log: any) => {
      const sender = String(log?.sender || "");
      const content = String(log?.content || "");
      const tsRaw = String(log?.eventTimestamp || log?.timestamp || "");
      const tsMs = Date.parse(tsRaw);
      if (!["Risk_Commissar", "Micro_Sniper"].includes(sender)) {
        return false;
      }
      if (content.startsWith("探明最新报价")) {
        return false;
      }
      if (
        decisionHallFreshnessAnchorMs > 0 &&
        (!Number.isFinite(tsMs) ||
          tsMs <= 0 ||
          decisionHallFreshnessAnchorMs - tsMs > decisionHallMessageMaxAgeMs)
      ) {
        return false;
      }
      return true;
    })
    .slice(0, 5);
  decisionHallMailboxLogs.forEach((log: any, idx: number) => {
    decisionHallMessages.push({
      id: `mailbox_${String(log.eventId || idx)}`,
      tone: "info",
      title: `黑板消息 · ${String(log.sender || "System")}`,
      body: String(log.content || ""),
      chips: [],
      source: "mailbox",
      timestamp: String(log.eventTimestamp || log.timestamp || ""),
      actor: String(log.sender || "System"),
      actorTone: String(log.sender || "").includes("Risk")
        ? "text-warning"
        : String(log.sender || "").includes("Micro")
          ? "text-danger"
          : "text-primary",
      sortTs: Date.parse(String(log.eventTimestamp || log.timestamp || "")),
      priority: 40,
    });
  });
  systemMessages
    .filter((message: any) => {
      const rawTs = Number(message?.ts || 0);
      const tsMs =
        rawTs > 0 ? rawTs * 1000 : Date.parse(String(message?.time || ""));
      if (
        decisionHallFreshnessAnchorMs > 0 &&
        (!Number.isFinite(tsMs) ||
          tsMs <= 0 ||
          decisionHallFreshnessAnchorMs - tsMs > decisionHallMessageMaxAgeMs)
      ) {
        return false;
      }
      return true;
    })
    .slice(0, 2)
    .forEach((message: any, idx: number) => {
      decisionHallMessages.push({
        id: `system_${String(message.id || idx)}`,
        tone:
          String(message.kind || "") === "rollback"
            ? "warning"
            : String(message.kind || "") === "publish"
              ? "success"
              : "info",
        title: String(message.title || "系统消息"),
        body: String(message.desc || ""),
        chips: [
          String(message.kind || "system"),
          String(message.source || "system"),
        ],
        source: "system_messages",
        timestamp: String(message.ts || message.time || ""),
        actor: "System",
        actorTone: "text-primary",
        sortTs:
          Number(message.ts || 0) > 0
            ? Number(message.ts || 0) * 1000
            : Date.parse(String(message.time || "")),
        priority: 50,
      });
    });
  const sortedDecisionHallMessages = [...decisionHallMessages].toSorted(
    (left, right) => {
      const leftTs = Number.isFinite(left.sortTs) ? left.sortTs : 0;
      const rightTs = Number.isFinite(right.sortTs) ? right.sortTs : 0;
      if (rightTs !== leftTs) {
        return rightTs - leftTs;
      }
      return right.priority - left.priority;
    },
  );
  const trainingActionBusy = Boolean(
    actionLoading && actionLoading.startsWith("training:"),
  );
  const hasVisibleManualReviewAction =
    trainingReviewPending ||
    canRollbackTraining ||
    hasSuggestion ||
    trainingActionBusy;
  const trainingRefreshHint =
    "系统会自动刷新样本、胜率、回撤、审批链和治理状态。";
  const trainingActionHint =
    "01 修阻断、02 进入观察态由系统自动完成；你只需要在这里做人工作业的复核与回滚。";
  const autoRepairRunning =
    trainingActionBusy && actionLoading === "training:repair";
  const autoApproveRunning =
    trainingActionBusy && actionLoading === "training:approve";
  const autoRepairDone =
    !canRepairTraining &&
    (hasSuggestion ||
      canApproveTrainingSuggestion ||
      trainingReviewPending ||
      canRollbackTraining);
  const autoApproveDone = trainingReviewPending || canRollbackTraining;
  const autoRepairStatusText = autoRepairRunning
    ? "系统正在自动修复阻断并补跑建议"
    : autoRepairDone
      ? "阻断修复与建议补跑已完成"
      : canRepairTraining
        ? "检测到阻断项，系统会自动处理"
        : "当前无需修阻断项";
  const autoApproveStatusText = autoApproveRunning
    ? "系统正在自动推进到观察态"
    : autoApproveDone
      ? "已进入观察态，等待人工复核"
      : canApproveTrainingSuggestion
        ? "已有待批建议，系统会自动推进到观察态"
        : hasSuggestion
          ? "等待系统自动推进观察态"
          : "当前还没有可推进的建议";
  const trainingErrorDispatch = trainingStatus.errorDispatch || {};
  const trainingErrorTicket =
    (trainingErrorDispatch.ticket as Record<string, unknown>) || {};
  const trainingErrorPlan =
    (trainingErrorDispatch.plan as Record<string, unknown>) || {};
  const trainingErrorDelivery =
    (trainingErrorDispatch.openclaw_delivery as Record<string, unknown>) || {};
  const trainingErrorReplyTemplate =
    (trainingErrorDispatch.openclawReplyTemplate as Record<string, unknown>) ||
    {};
  const trainingErrorCandidate =
    (trainingErrorTicket.candidate_value as Record<string, unknown>) || {};
  const trainingErrorStatus = String(trainingErrorDispatch.status || "");
  const trainingErrorContinueMode = String(
    trainingErrorDispatch.continue_mode || "",
  );
  const trainingErrorFingerprint = String(
    trainingErrorDispatch.fingerprint || "",
  );
  const trainingErrorTicketId = String(trainingErrorTicket.ticket_id || "");
  const trainingErrorMessage = String(trainingErrorDispatch.message || "");
  const trainingErrorUpdatedAt = String(trainingErrorDispatch.updated_at || "");
  const trainingErrorSessionKey = String(
    trainingErrorDelivery.session_key || "",
  );
  const trainingErrorMessageId = String(trainingErrorDelivery.message_id || "");
  const trainingErrorDeliveryOk = Boolean(trainingErrorDelivery.ok);
  const trainingErrorReplyRecommendedJson = String(
    trainingErrorReplyTemplate.recommendedJson || "",
  ).trim();
  const trainingErrorReplyStatusOptions = Array.isArray(
    trainingErrorReplyTemplate.statusOptions,
  )
    ? trainingErrorReplyTemplate.statusOptions
        .map((value) => String(value || "").trim())
        .filter((value): value is string => Boolean(value))
    : [];
  const trainingErrorReplyContinueModeOptions = Array.isArray(
    trainingErrorReplyTemplate.continueModeOptions,
  )
    ? trainingErrorReplyTemplate.continueModeOptions
        .map((value) => String(value || "").trim())
        .filter((value): value is string => Boolean(value))
    : [];
  const trainingErrorReadyForReview = Boolean(
    trainingErrorCandidate.ready_for_manual_review,
  );
  const trainingErrorHasValue = Boolean(trainingErrorCandidate.has_value);
  const trainingErrorBlockedReasons = Array.isArray(
    trainingErrorTicket.blocked_reasons,
  )
    ? trainingErrorTicket.blocked_reasons
        .map((reason) => String(reason || "").trim())
        .filter((reason): reason is string => Boolean(reason))
    : [];
  const trainingErrorActions = Array.isArray(trainingErrorPlan.actions)
    ? trainingErrorPlan.actions
        .map((action) => String(action || "").trim())
        .filter((action): action is string => Boolean(action))
    : [];
  const trainingErrorExecutedActions = Array.isArray(
    trainingErrorDispatch.executed_actions,
  )
    ? trainingErrorDispatch.executed_actions
        .map((action) => String(action || "").trim())
        .filter((action): action is string => Boolean(action))
    : [];
  const hasTrainingErrorDispatch = Boolean(
    trainingErrorStatus ||
    trainingErrorFingerprint ||
    trainingErrorMessage ||
    trainingErrorBlockedReasons.length > 0,
  );
  const trainingErrorToneClass =
    trainingErrorStatus === "error"
      ? "border-danger/35 bg-danger/10 text-danger"
      : trainingErrorDeliveryOk
        ? "border-primary/30 bg-primary/10 text-primary"
        : "border-warning/30 bg-warning/10 text-warning";
  const dispatchActionLabelMap: Record<string, string> = {
    RUN_REPAIR_BLOCKERS: "修复阻断项",
    REBUILD_QUALITY_SNAPSHOT: "重建质量快照",
    ROLLBACK_INVALID_EFFECTIVE: "回滚无效 effective",
    REJECT_INVALID_SUGGESTION: "拒绝无效建议",
    WAIT_NEW_EVIDENCE: "等待新证据",
    NOTHING: "无需动作",
  };
  const humanizeDispatchAction = (action: string) =>
    dispatchActionLabelMap[action] || action;

  const analysisModelOptions = Array.from(
    new Set(
      [
        trainingStatus.analysisModel,
        trainingStatus.activeModel,
        selectedTrainingModel,
      ]
        .concat(
          availableModels.filter((model) => model.startsWith("deepseek/")),
        )
        .filter((model): model is string => Boolean(model)),
    ),
  );

  const [showSetupWizard, setShowSetupWizard] = useState(false);
  const [setupForm, setSetupForm] = useState({ apiKey: "", mt5Path: "" });
  const [timelineEvents, setTimelineEvents] = useState<any[]>([]);
  const [timelineSources, setTimelineSources] = useState<any[]>([]);
  const [isZenMode, setIsZenMode] = useState(false);

  // 模拟时间轴数据获取
  const fetchMailbox = async () => {
    const currentView = drawerPanel || activeMenu;
    if (currentView !== "webchat" && currentView !== "dashboard") {
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/mailbox?_=${Date.now()}`, {
        cache: "no-store",
      });
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          setMailboxLogs(data.logs);
        }
      }
    } catch (e) {
      console.warn("Failed to fetch mailbox");
    }
  };

  const fetchTimeline = async () => {
    if (activeMenu !== "timeline" && drawerPanel !== "timeline") {
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/timeline`);
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          setTimelineEvents(data.events);
          setTimelineSources(Array.isArray(data.sources) ? data.sources : []);
        }
      }
    } catch (e) {
      console.warn("Failed to fetch timeline");
    }
  };

  const fetchStrategyWorkbench = async () => {
    const currentView = drawerPanel || activeMenu;
    if (
      currentView !== "positions" &&
      currentView !== "settings" &&
      currentView !== "strategyMarketplace" &&
      currentView !== "robotDashboard" &&
      currentView !== "strategyCustom"
    ) {
      return;
    }
    const lightweightOnly =
      currentView === "strategyMarketplace" ||
      currentView === "robotDashboard" ||
      currentView === "strategyCustom";
    const controller = new AbortController();
    const timer = window.setTimeout(
      () => controller.abort(),
      lightweightOnly ? 6500 : 7000,
    );
    try {
      const endpoint = lightweightOnly
        ? `${apiBase}/api/workbench/strategy/marketplace`
        : `${apiBase}/api/workbench/strategy`;
      const res = await fetch(endpoint, {
        signal: controller.signal,
      });
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          if (lightweightOnly) {
            setStrategyWorkbench((prev: any) => ({
              ...prev,
              success: true,
              marketplace:
                data && typeof data.marketplace === "object" && data.marketplace
                  ? data.marketplace
                  : {},
            }));
          } else {
            setStrategyWorkbench(data);
            if (Array.isArray(data.execution?.pendingSignals)) {
              setPendingSignals(data.execution.pendingSignals);
            }
          }
        }
      }
    } catch (e) {
      if (e instanceof DOMException && e.name === "AbortError") {
        return;
      }
      console.warn("Failed to fetch strategy workbench");
    } finally {
      window.clearTimeout(timer);
    }
  };
  const fetchRuntimeOperations = async () => {
    const currentView = drawerPanel || activeMenu;
    if (currentView !== "robotDashboard") {
      return;
    }
    if (document.hidden || runtimeConsoleInFlight.current) {
      return;
    }
    runtimeConsoleInFlight.current = true;
    const controller = new AbortController();
    const timer = window.setTimeout(() => controller.abort(), 7000);
    try {
      const res = await fetch(`${apiBase}/api/strategy/runtime/instances`, {
        signal: controller.signal,
      });
      if (!res.ok) {
        return;
      }
      const data = await res.json();
      if (!data?.success) {
        return;
      }
      setRuntimeConsole({
        runtimeInstances: Array.isArray(data.runtimeInstances)
          ? data.runtimeInstances
          : [],
        runtimeScheduler:
          data &&
          typeof data.runtimeScheduler === "object" &&
          data.runtimeScheduler
            ? data.runtimeScheduler
            : {},
        runtimeExplain:
          data && typeof data.runtimeExplain === "object" && data.runtimeExplain
            ? data.runtimeExplain
            : {},
        runtimeAgentDiagnostics:
          data &&
          typeof data.runtimeAgentDiagnostics === "object" &&
          data.runtimeAgentDiagnostics
            ? data.runtimeAgentDiagnostics
            : {},
        runtimeBridgeQueue:
          data &&
          typeof data.runtimeBridgeQueue === "object" &&
          data.runtimeBridgeQueue
            ? data.runtimeBridgeQueue
            : {},
        runtimeBridgeRequests: Array.isArray(data.runtimeBridgeRequests)
          ? data.runtimeBridgeRequests
          : [],
        runtimeExecutionFocus: Array.isArray(data.runtimeExecutionFocus)
          ? data.runtimeExecutionFocus
          : [],
        runtimeBridgeHealth:
          data &&
          typeof data.runtimeBridgeHealth === "object" &&
          data.runtimeBridgeHealth
            ? data.runtimeBridgeHealth
            : {},
        runtimeStatus:
          data && typeof data.runtimeStatus === "object" && data.runtimeStatus
            ? data.runtimeStatus
            : {},
        orchestrationSnapshot:
          data &&
          typeof data.orchestrationSnapshot === "object" &&
          data.orchestrationSnapshot
            ? data.orchestrationSnapshot
            : {},
      });
    } catch (e) {
      if (!(e instanceof DOMException && e.name === "AbortError")) {
        console.warn("Failed to fetch runtime operations");
      }
    } finally {
      window.clearTimeout(timer);
      runtimeConsoleInFlight.current = false;
    }
  };
  const fetchRuntimeAiEvaluation = async () => {
    const currentView = drawerPanel || activeMenu;
    if (currentView !== "robotDashboard") {
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/strategy/runtime/evaluate`);
      if (!res.ok) {
        return;
      }
      const data = await res.json();
      if (!data?.success) {
        return;
      }
      const evaluation =
        data.evaluation && typeof data.evaluation === "object"
          ? data.evaluation
          : {};
      const history = Array.isArray(data.history) ? data.history : [];
      setRuntimeAiEvaluation(evaluation);
      setRuntimeAiHistory(history);
      if (String((evaluation as Record<string, unknown>).target || "").trim()) {
        setRuntimeAiGoal(
          String((evaluation as Record<string, unknown>).target || ""),
        );
      }
    } catch {
      console.warn("Failed to fetch runtime AI evaluation");
    }
  };
  const handleEvaluateRuntimeAi = async () => {
    setRuntimeAiLoading(true);
    try {
      const res = await fetch(`${apiBase}/api/strategy/runtime/evaluate`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          goal: runtimeAiGoal.trim(),
        }),
      });
      const data = await res.json();
      if (data.success) {
        const evaluation =
          data.evaluation && typeof data.evaluation === "object"
            ? data.evaluation
            : {};
        const history = Array.isArray(data.history) ? data.history : [];
        setRuntimeAiEvaluation(evaluation);
        setRuntimeAiHistory(history);
        showToast("AI 组合评估完成", "success");
      } else {
        showToast(String(data.error || "AI 组合评估失败"), "error");
      }
    } catch {
      showToast("AI 组合评估请求失败", "error");
    } finally {
      setRuntimeAiLoading(false);
    }
  };

  const fetchAlerts = async () => {
    try {
      const res = await fetch(`${apiBase}/api/alerts`);
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          setAlerts(data.alerts);
          const latestFileRepair = Array.isArray(data.alerts)
            ? data.alerts.find((item: any) => item?.kind === "file_repair")
            : null;
          const latestFileRepairTs = Number(latestFileRepair?.ts || 0);
          if (
            latestFileRepair &&
            latestFileRepair.id &&
            latestFileRepair.id !== lastFileRepairAlertIdRef.current &&
            latestFileRepairTs > Date.now() / 1000 - 180
          ) {
            lastFileRepairAlertIdRef.current = String(latestFileRepair.id);
            showToast(
              String(latestFileRepair.desc || "系统刚完成一次自动修复"),
              "warning",
            );
          }
        }
      }
    } catch (e) {
      console.warn("Failed to fetch alerts");
    }
  };

  const fetchSystemMessages = async () => {
    const currentView = drawerPanel || activeMenu;
    if (
      currentView !== "notify" &&
      currentView !== "dashboard" &&
      currentView !== "webchat"
    ) {
      return;
    }
    if (document.hidden || systemMessagesInFlight.current) {
      return;
    }
    const emptySummary = {
      total: 0,
      publishCount: 0,
      rollbackCount: 0,
      templateCount: 0,
      repairCount: 0,
    };
    systemMessagesInFlight.current = true;
    const controller = new AbortController();
    const timer = window.setTimeout(() => controller.abort(), 2500);
    try {
      const res = await fetch(`${apiBase}/api/system_messages?limit=60`, {
        signal: controller.signal,
      });
      if (res.ok) {
        const raw = await res.json();
        const data =
          raw && typeof raw === "object"
            ? (raw as {
                success?: boolean;
                messages?: unknown;
                summary?: unknown;
              })
            : null;
        if (data?.success) {
          setSystemMessages(Array.isArray(data.messages) ? data.messages : []);
          setSystemMessageSummary(
            typeof data.summary === "object" && data.summary
              ? data.summary
              : emptySummary,
          );
        } else {
          setSystemMessages([]);
          setSystemMessageSummary(emptySummary);
        }
      }
    } catch {
      // system_messages 是补充型面板；网络抖动时静默降级，保留已有内容
    } finally {
      window.clearTimeout(timer);
      systemMessagesInFlight.current = false;
    }
  };

  useEffect(() => {
    if (!backendProbeReady || !backendConnected) {
      return;
    }
    fetchAlerts();
    fetchSystemMessages();
    const timer = setInterval(() => {
      fetchAlerts();
      fetchSystemMessages();
    }, 10000);
    return () => clearInterval(timer);
  }, [backendProbeReady, backendConnected, apiBase, activeMenu, drawerPanel]);

  useEffect(() => {
    // 页面初次加载时检查是否需要显示向导
    const hasSeenWizard = localStorage.getItem("hasSeenWizard");
    if (!hasSeenWizard) {
      setShowSetupWizard(true);
    }
  }, []);

  const handleFinishWizard = async () => {
    if (setupForm.apiKey.trim()) {
      try {
        const res = await fetch(`${apiBase}/api/settings/apikey`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ api_key: setupForm.apiKey.trim() }),
        });
        if (res.ok) {
          showToast("API Key 已保存", "success");
        } else {
          showToast("API Key 保存失败", "warning");
        }
      } catch {
        showToast("无法连接后端，Key 未保存", "warning");
      }
    }
    if (setupForm.mt5Path.trim()) {
      try {
        await fetch(`${apiBase}/api/settings/mt5path`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ mt5_data_dir: setupForm.mt5Path.trim() }),
        });
      } catch {}
    }
    localStorage.setItem("hasSeenWizard", "true");
    setShowSetupWizard(false);
  };

  const fetchAgentModels = async () => {
    if (
      activeMenu !== "models" &&
      activeMenu !== "training" &&
      drawerPanel !== "models" &&
      drawerPanel !== "training"
    ) {
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/agent_models`);
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          setAgentModels(data.agents);
          if (data.available_models) {
            setAvailableModels(data.available_models);
          }
        }
      }
    } catch {
      console.warn("Failed to fetch agent models");
    }
  };

  const formatModelLabel = (modelId: string) => {
    if (!modelId) {
      return "";
    }
    if (!modelId.includes("/")) {
      return modelId;
    }
    const [provider, model] = modelId.split("/", 2);
    return `${model} (${provider})`;
  };

  const formatAgeLabel = (value: unknown) => {
    const seconds = Number(value);
    if (!Number.isFinite(seconds) || seconds < 0) {
      return "未知";
    }
    if (seconds < 60) {
      return `${Math.round(seconds)}s`;
    }
    if (seconds < 3600) {
      return `${Math.round(seconds / 60)}m`;
    }
    if (seconds < 86400) {
      return `${Math.round(seconds / 3600)}h`;
    }
    return `${Math.round(seconds / 86400)}d`;
  };

  const [riskParams, setRiskParams] = useState({
    risk_level: "balanced",
    max_position_size: 0.1,
    max_open_positions: 1,
    sl_pips: 40,
    tp_pips: 80,
    human_in_the_loop: true,
    min_confidence: 70,
    account_total_loss_stop_pct: 30,
  });

  const fetchRiskParams = async () => {
    if (activeMenu !== "settings" && drawerPanel !== "settings") {
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/params`);
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          setRiskParams(data.params);
        }
      }
    } catch (e) {
      console.warn("Failed to fetch risk params");
    }
  };

  const fetchUpdateStatus = async () => {
    if (
      activeMenu !== "settings" &&
      activeMenu !== "dashboard" &&
      drawerPanel !== "settings" &&
      drawerPanel !== "dashboard"
    ) {
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/update/status`);
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          setUpdateStatus(data);
        }
      }
    } catch (e) {
      console.warn("Failed to fetch update status");
    }
  };

  const fetchUpdateConfig = async () => {
    if (activeMenu !== "settings" && drawerPanel !== "settings") {
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/update/config`);
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          setUpdateConfig({
            update_manifest_url: data.update_manifest_url || "",
          });
        }
      }
    } catch (e) {
      console.warn("Failed to fetch update config");
    }
  };

  const handleSaveUpdateConfig = async () => {
    try {
      setUpdateLoading(true);
      const res = await fetch(`${apiBase}/api/update/config`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(updateConfig),
      });
      const data = await res.json();
      if (data.success) {
        showToast("更新源地址已保存", "success");
      } else {
        showToast("保存更新源失败", "error");
      }
    } catch (e) {
      showToast("保存更新源失败", "error");
    } finally {
      setUpdateLoading(false);
      fetchUpdateConfig();
    }
  };

  const handleCheckUpdates = async () => {
    try {
      setUpdateLoading(true);
      const res = await fetch(`${apiBase}/api/update/check`, {
        method: "POST",
      });
      const data = await res.json();
      if (data.success) {
        setUpdateStatus((prev: any) => ({
          ...prev,
          updateState: data,
          quality: data.quality || prev.quality,
        }));
        showToast(
          data.status === "update_available"
            ? `发现新版本 ${data.target_version}`
            : "当前已是最新版本",
          "success",
        );
      } else {
        showToast("检查更新失败", "error");
      }
    } catch (e) {
      showToast("检查更新失败", "error");
    } finally {
      setUpdateLoading(false);
      fetchUpdateStatus();
    }
  };

  const handleApplyUpdate = async () => {
    try {
      setUpdateLoading(true);
      const res = await fetch(`${apiBase}/api/update/apply`, {
        method: "POST",
      });
      const data = await res.json();
      if (data.success) {
        showToast(
          data.status === "apply_started" || data.status === "candidate_ready"
            ? "候选版本已准备，等待晋升"
            : "更新状态已刷新",
          "success",
        );
      } else {
        showToast(
          data.status === "blocked"
            ? "当前有持仓或待处理请求，暂不允许切换版本"
            : "应用更新失败",
          "error",
        );
      }
    } catch (e) {
      showToast("应用更新失败", "error");
    } finally {
      setUpdateLoading(false);
      fetchUpdateStatus();
    }
  };

  const handlePromoteUpdate = async () => {
    try {
      setUpdateLoading(true);
      const res = await fetch(`${apiBase}/api/update/promote`, {
        method: "POST",
      });
      const data = await res.json();
      if (data.success) {
        showToast("候选版本已晋升为当前版本", "success");
      } else {
        showToast(
          data.status === "promotion_blocked"
            ? "当前状态不允许晋升候选版本"
            : "晋升候选版本失败",
          "error",
        );
      }
    } catch (e) {
      showToast("晋升候选版本失败", "error");
    } finally {
      setUpdateLoading(false);
      fetchUpdateStatus();
    }
  };

  const handleRollbackUpdate = async () => {
    try {
      setUpdateLoading(true);
      const res = await fetch(`${apiBase}/api/update/rollback`, {
        method: "POST",
      });
      const data = await res.json();
      if (data.success) {
        showToast("已回滚到上一稳定版本", "success");
      } else {
        showToast("当前没有可回滚版本", "error");
      }
    } catch (e) {
      showToast("回滚失败", "error");
    } finally {
      setUpdateLoading(false);
      fetchUpdateStatus();
    }
  };

  const handleRiskLevelChange = (level: string) => {
    const newParams = { ...riskParams, risk_level: level };
    if (level === "conservative") {
      newParams.max_position_size = 0.05;
      newParams.max_open_positions = 1;
      newParams.sl_pips = 20;
      newParams.tp_pips = 40;
      newParams.min_confidence = 80;
    } else if (level === "balanced") {
      newParams.max_position_size = 0.1;
      newParams.max_open_positions = 2;
      newParams.sl_pips = 40;
      newParams.tp_pips = 80;
      newParams.min_confidence = 70;
    } else if (level === "aggressive") {
      newParams.max_position_size = 0.2;
      newParams.max_open_positions = 3;
      newParams.sl_pips = 60;
      newParams.tp_pips = 120;
      newParams.min_confidence = 60;
    }
    setRiskParams(newParams);
  };

  const handleSaveParams = async () => {
    try {
      const res = await fetch(`${apiBase}/api/params`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(riskParams),
      });
      const data = await res.json();
      if (data.success) {
        if (data.params) {
          setRiskParams(data.params);
        }
        showToast(data.message, "success");
        await fetchRiskParams();
        await fetchStrategyWorkbench();
      } else {
        showToast(data.error || "保存失败", "error");
      }
    } catch (e) {
      showToast("网络请求失败", "error");
    }
  };

  const fetchPendingSignals = async () => {
    const currentView = drawerPanel || activeMenu;
    if (
      currentView !== "positions" &&
      currentView !== "dashboard" &&
      currentView !== "webchat"
    ) {
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/pending_signals`);
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          setPendingSignals(data.signals);
        }
      }
    } catch (e) {
      console.warn("Failed to fetch pending signals");
    }
  };

  const handleSignalAction = async (
    signalId: string,
    action: "approve" | "reject",
  ) => {
    try {
      const res = await fetch(`${apiBase}/api/signals/${signalId}/${action}`, {
        method: "POST",
      });
      const data = await res.json();
      if (data.success) {
        showToast(data.message, "success");
        fetchPendingSignals();
      } else {
        showToast(data.message, "error");
      }
    } catch (e) {
      showToast("操作失败", "error");
    }
  };

  const handleResetParams = async () => {
    try {
      const res = await fetch(`${apiBase}/api/params/reset`, {
        method: "POST",
      });
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          showToast("已恢复为系统自动参数模式（即删除手动配置）", "success");
          await fetchRiskParams();
          await fetchStrategyWorkbench();
        } else {
          showToast("恢复失败: " + data.error, "error");
        }
      }
    } catch (e) {
      showToast("请求失败，请检查后端是否启动", "error");
    }
  };

  const handleApplyBestParams = async () => {
    if (!confirm("将用离线训练最优参数覆盖当前参数，确定继续？")) {
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/params/apply_best`, {
        method: "POST",
      });
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          const s = data.stats;
          showToast(
            `已应用训练最优参数：${s.total_trades || 0}笔 / 胜率${s.win_rate?.toFixed(1) || 0}% / PnL $${s.total_pnl?.toFixed(0) || 0}`,
            "success",
          );
          await fetchRiskParams();
          await fetchStrategyWorkbench();
          await fetchApprovalChain();
          await fetchGovernanceReport();
        } else {
          showToast("应用失败: " + data.error, "error");
        }
      }
    } catch {
      showToast("请求失败，请检查后端是否启动", "error");
    }
  };

  const openTemplateEditorForStrategy = (strategy: any) => {
    const template =
      strategy?.template && typeof strategy.template === "object"
        ? strategy.template
        : {};
    const timeframe = String(template.timeframe || "M5");
    const riskPerTrade = Number(
      template.risk_per_trade ??
        (template.risk_multiplier != null
          ? Number(template.risk_multiplier) * 0.01
          : 0.01),
    );
    const atrSlMult = Number(
      template.atr_sl_mult ??
        (template.sl_multiplier != null
          ? Number(template.sl_multiplier) * 1.8
          : 1.8),
    );
    const tpRr = Number(
      template.tp_rr ??
        (template.tp_multiplier != null
          ? Number(template.tp_multiplier) * 2
          : 2),
    );
    const maxPositions = Number(template.max_positions ?? 1);
    const reduceOnly = Boolean(template.reduce_only ?? false);
    const runtimeContext =
      template.runtime_context && typeof template.runtime_context === "object"
        ? template.runtime_context
        : {};
    const coordinationContract =
      template.coordination_contract &&
      typeof template.coordination_contract === "object"
        ? template.coordination_contract
        : {};
    const strategyStyle = String(
      template.strategy_style || coordinationContract.strategy_style || "trend",
    );
    const executionRole = String(
      template.execution_role ||
        coordinationContract.execution_role ||
        "primary",
    );
    const applicableMarkets = Array.isArray(template.applicable_markets)
      ? template.applicable_markets
      : Array.isArray(runtimeContext.applicable_markets)
        ? runtimeContext.applicable_markets
        : ["TRENDING"];
    const applicableSessions = Array.isArray(template.applicable_sessions)
      ? template.applicable_sessions
      : Array.isArray(runtimeContext.applicable_sessions)
        ? runtimeContext.applicable_sessions
        : ["LONDON", "NEW_YORK"];
    const conflictGroups = Array.isArray(template.conflict_groups)
      ? template.conflict_groups
      : Array.isArray(coordinationContract.conflict_groups)
        ? coordinationContract.conflict_groups
        : [strategyStyle];
    const coordinationTags = Array.isArray(template.coordination_tags)
      ? template.coordination_tags
      : Array.isArray(coordinationContract.coordination_tags)
        ? coordinationContract.coordination_tags
        : [String(strategyStyle || "TREND").toUpperCase()];
    const maxActiveStrategies = Number(
      template.max_active_strategies ??
        coordinationContract.max_active_strategies ??
        2,
    );
    const conflictHoldThreshold = Number(
      template.conflict_hold_threshold ??
        coordinationContract.conflict_hold_threshold ??
        0.35,
    );
    const allowSameGroupStack = Boolean(
      template.allow_same_group_stack ??
      coordinationContract.allow_same_group_stack ??
      false,
    );
    const allowCounterStyleMix = Boolean(
      template.allow_counter_style_mix ??
      coordinationContract.allow_counter_style_mix ??
      false,
    );
    const advanced: Record<string, unknown> = {};
    Object.entries(template).forEach(([key, value]) => {
      if (
        !isReservedTemplateKey(key) &&
        key !== "timeframe" &&
        key !== "risk_per_trade" &&
        key !== "risk_multiplier" &&
        key !== "atr_sl_mult" &&
        key !== "sl_multiplier" &&
        key !== "tp_rr" &&
        key !== "tp_multiplier" &&
        key !== "max_positions" &&
        key !== "reduce_only" &&
        key !== "strategy_style" &&
        key !== "execution_role" &&
        key !== "applicable_markets" &&
        key !== "applicable_sessions" &&
        key !== "conflict_groups" &&
        key !== "coordination_tags" &&
        key !== "max_active_strategies" &&
        key !== "conflict_hold_threshold" &&
        key !== "allow_same_group_stack" &&
        key !== "allow_counter_style_mix" &&
        key !== "execution_baseline" &&
        key !== "runtime_context" &&
        key !== "coordination_contract" &&
        key !== "contract_version" &&
        key !== "template_kind"
      ) {
        advanced[key] = value;
      }
    });
    const sanitizedAdvanced = stripReservedTemplateKeys(advanced);
    setTemplateStrategy(strategy);
    setTemplateBaseFields({
      timeframe,
      risk_per_trade: Number.isFinite(riskPerTrade) ? riskPerTrade : 0.01,
      atr_sl_mult: Number.isFinite(atrSlMult) ? atrSlMult : 1.8,
      tp_rr: Number.isFinite(tpRr) ? tpRr : 2,
      max_positions: Number.isFinite(maxPositions)
        ? Math.round(maxPositions)
        : 1,
      reduce_only: reduceOnly,
      strategy_style: strategyStyle,
      execution_role: executionRole,
      applicable_markets: applicableMarkets
        .map((item: unknown) => String(item ?? "").trim())
        .filter(Boolean),
      applicable_sessions: applicableSessions
        .map((item: unknown) => String(item ?? "").trim())
        .filter(Boolean),
      conflict_groups: conflictGroups
        .map((item: unknown) => String(item ?? "").trim())
        .filter(Boolean),
      coordination_tags: coordinationTags
        .map((item: unknown) => String(item ?? "").trim())
        .filter(Boolean),
      max_active_strategies: Number.isFinite(maxActiveStrategies)
        ? Math.round(maxActiveStrategies)
        : 2,
      conflict_hold_threshold: Number.isFinite(conflictHoldThreshold)
        ? conflictHoldThreshold
        : 0.35,
      allow_same_group_stack: allowSameGroupStack,
      allow_counter_style_mix: allowCounterStyleMix,
    });
    setTemplateAdvancedRaw(JSON.stringify(sanitizedAdvanced, null, 2));
    setTemplateAdvancedError("");
    setTemplateSaveMessage(null);
    setTemplateEditorOpen(true);
  };

  const saveTemplateFromEditor = async () => {
    const failTemplateSave = (message: string) => {
      setTemplateSaveMessage({ text: message, type: "error" });
      showToast(message, "error");
    };
    if (!templateStrategy) {
      failTemplateSave("缺少策略上下文");
      return;
    }
    if (!parsedAdvancedParams.ok) {
      setTemplateAdvancedError(parsedAdvancedParams.error);
      failTemplateSave(parsedAdvancedParams.error);
      return;
    }
    if (parsedAdvancedParams.strippedKeys.length > 0) {
      setTemplateAdvancedRaw(
        JSON.stringify(parsedAdvancedParams.sanitizedValue, null, 2),
      );
      setTemplateAdvancedError("");
    }
    if (
      templateBaseFields.risk_per_trade < 0.001 ||
      templateBaseFields.risk_per_trade > 0.05
    ) {
      failTemplateSave("单笔风险必须在 0.001 到 0.05 之间");
      return;
    }
    if (
      templateBaseFields.atr_sl_mult < 0.8 ||
      templateBaseFields.atr_sl_mult > 4
    ) {
      failTemplateSave("ATR止损倍数必须在 0.8 到 4.0 之间");
      return;
    }
    if (templateBaseFields.tp_rr < 0.5 || templateBaseFields.tp_rr > 5) {
      failTemplateSave("止盈风险比必须在 0.5 到 5.0 之间");
      return;
    }
    if (
      templateBaseFields.max_positions < 1 ||
      templateBaseFields.max_positions > 10
    ) {
      failTemplateSave("最大持仓必须在 1 到 10 之间");
      return;
    }
    if (
      templateBaseFields.max_active_strategies < 1 ||
      templateBaseFields.max_active_strategies > 10
    ) {
      failTemplateSave("最大并发策略数必须在 1 到 10 之间");
      return;
    }
    if (
      templateBaseFields.conflict_hold_threshold < 0 ||
      templateBaseFields.conflict_hold_threshold > 1
    ) {
      failTemplateSave("冲突 HOLD 阈值必须在 0 到 1 之间");
      return;
    }
    if (templateBaseFields.applicable_markets.length === 0) {
      failTemplateSave("至少声明一个适用市场");
      return;
    }
    if (templateBaseFields.applicable_sessions.length === 0) {
      failTemplateSave("至少声明一个适用时段");
      return;
    }
    try {
      setTemplateSaveBusy(true);
      setTemplateSaveMessage(null);
      const res = await fetch(`${apiBase}/api/strategy/template`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          strategy_id: String(templateStrategy.id),
          template: mergedTemplatePreview,
        }),
      });
      const data = await res.json();
      if (data.success) {
        setTemplateSaveMessage({
          text: String(data.message || "模板已保存"),
          type: "success",
        });
        showToast(String(data.message || "模板已保存"), "success");
        setTemplateEditorOpen(false);
        setTemplateStrategy(null);
        await fetchStrategyWorkbench();
        await fetchSystemMessages();
      } else {
        failTemplateSave(String(data.error || "模板保存失败"));
      }
    } catch {
      failTemplateSave("模板保存请求失败");
    } finally {
      setTemplateSaveBusy(false);
    }
  };

  const handleMarketplaceAction = async (
    action: "deploy" | "disable" | "publish" | "rollback" | "template",
    strategy: any,
  ) => {
    const strategyId = String(strategy?.id || "");
    if (!strategyId) {
      showToast("缺少策略 ID", "error");
      return;
    }
    try {
      if (action === "deploy") {
        const res = await fetch(`${apiBase}/api/strategy/deploy`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            strategy_id: strategyId,
            allocation: 1.0,
            activate: true,
          }),
        });
        const data = await res.json();
        if (data.success) {
          showToast(String(data.message || "部署成功"), "success");
          await fetchStrategyWorkbench();
          await fetchRuntimeOperations();
          await fetchStatus();
          await fetchSystemMessages();
        } else {
          showToast(String(data.error || "部署失败"), "error");
        }
        return;
      }
      if (action === "disable") {
        const nextDisabled = Boolean(strategy.enabled);
        const res = await fetch(`${apiBase}/api/strategy/disable`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            strategy_id: strategyId,
            disabled: nextDisabled,
          }),
        });
        const data = await res.json();
        if (data.success) {
          showToast(String(data.message || "状态已更新"), "success");
          await fetchStrategyWorkbench();
          await fetchRuntimeOperations();
          await fetchSystemMessages();
        } else {
          showToast(String(data.error || "停用失败"), "error");
        }
        return;
      }
      if (action === "publish") {
        const note = window.prompt("发布备注（可选）", "manual publish") || "";
        const res = await fetch(`${apiBase}/api/strategy/publish`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ strategy_id: strategyId, note }),
        });
        const data = await res.json();
        if (data.success) {
          showToast(String(data.message || "发布成功"), "success");
          await fetchStrategyWorkbench();
          await fetchRuntimeOperations();
          await fetchSystemMessages();
        } else {
          showToast(String(data.error || "发布失败"), "error");
        }
        return;
      }
      if (action === "rollback") {
        const confirmed = window.confirm(
          `确认将策略 ${strategyId} 回滚到上一版本？`,
        );
        if (!confirmed) {
          return;
        }
        const res = await fetch(`${apiBase}/api/strategy/rollback`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ strategy_id: strategyId }),
        });
        const data = await res.json();
        if (data.success) {
          showToast(String(data.message || "回滚成功"), "success");
          await fetchStrategyWorkbench();
          await fetchRuntimeOperations();
          await fetchSystemMessages();
        } else {
          showToast(String(data.error || "回滚失败"), "error");
        }
        return;
      }

      openTemplateEditorForStrategy(strategy);
    } catch {
      showToast("策略操作请求失败", "error");
    }
  };

  const handleCreateComposite = async () => {
    const name = compositeName.trim();
    if (name.length < 2) {
      showToast("组合名称至少 2 个字符", "error");
      return;
    }
    if (compositeComponents.length < 2) {
      showToast("请至少选择 2 个策略组件", "error");
      return;
    }
    try {
      const res = await fetch(`${apiBase}/api/strategy/composite/create`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name,
          components: compositeComponents,
        }),
      });
      const data = await res.json();
      if (data.success) {
        showToast(String(data.message || "组合策略创建成功"), "success");
        setCompositeName("");
        setCompositeComponents([]);
        await fetchStrategyWorkbench();
      } else {
        showToast(String(data.error || "创建组合失败"), "error");
      }
    } catch {
      showToast("创建组合请求失败", "error");
    }
  };

  const handleRuntimeInstanceAction = async (
    instanceId: string,
    action:
      | "pause"
      | "resume"
      | "remove"
      | "allocation"
      | "clear_overrides"
      | "restore_defaults",
    allocation?: number,
  ) => {
    try {
      const res = await fetch(`${apiBase}/api/strategy/instance/action`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          instance_id: instanceId,
          action,
          allocation,
        }),
      });
      const data = await res.json();
      if (data.success) {
        showToast(String(data.message || "实例操作成功"), "success");
        await fetchStrategyWorkbench();
        await fetchRuntimeOperations();
        await fetchStatus();
      } else {
        showToast(String(data.error || "实例操作失败"), "error");
      }
    } catch {
      showToast("实例操作请求失败", "error");
    }
  };

  const handleSaveDecisionPolicy = async () => {
    setDecisionPolicySaving(true);
    try {
      const res = await fetch(`${apiBase}/api/strategy/decision_policy`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          profile: decisionPolicyForm.profile,
          macro: {
            role: decisionPolicyForm.macroRole,
            aligned_scale: decisionPolicyForm.macroAlignedScale,
            countertrend_scale: decisionPolicyForm.macroCountertrendScale,
            neutral_scale: decisionPolicyForm.macroNeutralScale,
            degraded_policy: decisionPolicyForm.macroDegradedPolicy,
          },
          interpreter: {
            role: decisionPolicyForm.interpreterRole,
            buy_scale: decisionPolicyForm.interpreterBuyScale,
            sell_scale: decisionPolicyForm.interpreterSellScale,
            limit_countertrend_scale:
              decisionPolicyForm.interpreterLimitCountertrendScale,
            block_countertrend_scale:
              decisionPolicyForm.interpreterBlockCountertrendScale,
          },
          risk: {
            role: decisionPolicyForm.riskRole,
          },
          execution: {
            aggregation: decisionPolicyForm.executionAggregation,
            min_confidence: decisionPolicyForm.executionMinConfidence,
          },
        }),
      });
      const data = await res.json();
      if (data.success) {
        showToast(String(data.message || "协同协议已保存"), "success");
        await fetchStrategyWorkbench();
      } else {
        showToast(String(data.error || "协同协议保存失败"), "error");
      }
    } catch {
      showToast("协同协议保存请求失败", "error");
    } finally {
      setDecisionPolicySaving(false);
    }
  };

  const fetchStrategyCustomState = async () => {
    try {
      const res = await fetch(`${apiBase}/api/strategy/custom/state`);
      if (!res.ok) {
        return;
      }
      const data = await res.json();
      if (!data.success) {
        return;
      }
      const draft =
        data.draft && typeof data.draft === "object" ? data.draft : {};
      setCustomStrategyName(String(draft.name || ""));
      setCustomStrategyDocument(String(draft.document || ""));
      setCustomOptimized(
        draft.optimized && typeof draft.optimized === "object"
          ? draft.optimized
          : {},
      );
      setCustomEvaluation(
        draft.evaluation && typeof draft.evaluation === "object"
          ? draft.evaluation
          : {},
      );
      const state = String(draft.saveState || "saved");
      setCustomDraftStatus(
        state === "syncing" || state === "unsaved" ? state : "saved",
      );
      setCustomDraftSavedAt(String(draft.lastSavedAt || ""));
    } catch {
      // best effort
    }
  };

  const saveStrategyCustomDraft = async (
    next?: Partial<{
      name: string;
      document: string;
      optimized: Record<string, unknown>;
      evaluation: Record<string, unknown>;
    }>,
  ) => {
    setCustomDraftStatus("syncing");
    try {
      const payload = {
        name: next?.name ?? customStrategyName,
        document: next?.document ?? customStrategyDocument,
        optimized: next?.optimized ?? customOptimized,
        evaluation: next?.evaluation ?? customEvaluation,
      };
      const res = await fetch(`${apiBase}/api/strategy/custom/save`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      const data = await res.json();
      if (data.success) {
        setCustomDraftStatus("saved");
        setCustomDraftSavedAt(String(data.lastSavedAt || ""));
      } else {
        setCustomDraftStatus("unsaved");
      }
    } catch {
      setCustomDraftStatus("unsaved");
    }
  };

  const handleOptimizeCustomStrategy = async () => {
    const name = customStrategyName.trim();
    const documentText = customStrategyDocument.trim();
    if (name.length < 2) {
      showToast("请先填写策略名称", "error");
      return;
    }
    if (documentText.length < 12) {
      showToast("策略文档过短，请补充关键规则", "error");
      return;
    }
    setCustomActionLoading("optimize");
    try {
      const res = await fetch(`${apiBase}/api/strategy/custom/optimize`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name, document: documentText }),
      });
      const data = await res.json();
      if (data.success) {
        const optimized =
          data.optimized && typeof data.optimized === "object"
            ? data.optimized
            : {};
        setCustomOptimized(optimized);
        await saveStrategyCustomDraft({
          name,
          document: documentText,
          optimized,
        });
        showToast("AI 优化完成", "success");
      } else {
        showToast(String(data.error || "AI 优化失败"), "error");
      }
    } catch {
      showToast("AI 优化请求失败", "error");
    } finally {
      setCustomActionLoading(null);
    }
  };

  const handleEvaluateCustomStrategy = async () => {
    const name = customStrategyName.trim();
    const documentText = customStrategyDocument.trim();
    setCustomActionLoading("evaluate");
    try {
      const res = await fetch(`${apiBase}/api/strategy/custom/evaluate`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name,
          document: documentText,
          optimized: customOptimized,
        }),
      });
      const data = await res.json();
      if (data.success) {
        const evaluation =
          data.evaluation && typeof data.evaluation === "object"
            ? data.evaluation
            : {};
        setCustomEvaluation(evaluation);
        await saveStrategyCustomDraft({
          name,
          document: documentText,
          evaluation,
        });
        showToast("AI 评估完成", "success");
      } else {
        showToast(String(data.error || "AI 评估失败"), "error");
      }
    } catch {
      showToast("AI 评估请求失败", "error");
    } finally {
      setCustomActionLoading(null);
    }
  };

  const handleGenerateCustomStrategy = async () => {
    const name = customStrategyName.trim();
    const documentText = customStrategyDocument.trim();
    if (name.length < 2) {
      showToast("请先填写策略名称", "error");
      return;
    }
    if (documentText.length < 12) {
      showToast("请先补充策略文档", "error");
      return;
    }
    if (!customOptimized || Object.keys(customOptimized).length === 0) {
      showToast("请先执行 AI 优化", "error");
      return;
    }
    setCustomActionLoading("generate");
    try {
      const res = await fetch(`${apiBase}/api/strategy/custom/generate`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name,
          document: documentText,
          optimized: customOptimized,
          evaluation: customEvaluation,
        }),
      });
      const data = await res.json();
      if (data.success) {
        showToast(String(data.message || "策略生成成功"), "success");
        await fetchStrategyWorkbench();
        await saveStrategyCustomDraft();
      } else {
        showToast(String(data.error || "策略生成失败"), "error");
      }
    } catch {
      showToast("策略生成请求失败", "error");
    } finally {
      setCustomActionLoading(null);
    }
  };

  const fetchLogs = async (targetTab = activeLogTab) => {
    if (activeMenu !== "logs" && drawerPanel !== "logs") {
      return;
    }
    const requestSeq = (logRequestSeqRef.current[targetTab] || 0) + 1;
    logRequestSeqRef.current[targetTab] = requestSeq;
    try {
      const res = await fetch(`${apiBase}/api/logs/${targetTab}?lines=240`);
      if (res.ok) {
        const data = await res.json();
        if (data.success) {
          if (logRequestSeqRef.current[targetTab] !== requestSeq) {
            return;
          }
          const filteredLines = (
            Array.isArray(data.lines) ? data.lines : []
          ).filter(
            (line: string) =>
              !String(line || "").startsWith(`[${targetTab}] source:`),
          );
          const freshLogs = filteredLines.slice(-140).toReversed();
          const clearedHead = clearedLogHeadByTabRef.current[targetTab];
          let visibleLogs = freshLogs;
          if (clearedHead) {
            const clearedMarkerIndex = freshLogs.indexOf(clearedHead);
            if (clearedMarkerIndex === 0) {
              visibleLogs = [];
            } else if (clearedMarkerIndex > 0) {
              visibleLogs = freshLogs.slice(0, clearedMarkerIndex);
            } else {
              clearedLogHeadByTabRef.current[targetTab] = null;
            }
          }
          setLogsByTab((prev) => ({ ...prev, [targetTab]: visibleLogs }));
          setLogSourceByTab((prev) => ({
            ...prev,
            [targetTab]: String(data.source || ""),
          }));
        }
      }
    } catch (e) {
      console.warn("Failed to fetch logs");
    }
  };

  const getLogLineToneClass = (line: string) => {
    const normalized = String(line || "");
    if (
      normalized.includes("[ERROR]") ||
      normalized.includes("[CRITICAL]") ||
      normalized.includes(" BLOCKED") ||
      normalized.includes("阻断") ||
      normalized.includes("拒绝")
    ) {
      return "text-danger";
    }
    if (normalized.includes("[WARN]")) {
      return "text-warning";
    }
    if (normalized.includes("[INFO]")) {
      return "text-slate-300";
    }
    return "text-slate-400";
  };

  const handleClearLogScreen = () => {
    const currentHead = activeLogs[0] || null;
    clearedLogHeadByTabRef.current[activeLogTab] = currentHead;
    setLogsByTab((prev) => ({ ...prev, [activeLogTab]: [] }));
  };

  const handleExportLogs = () => {
    if (activeLogs.length === 0) {
      showToast("当前没有可导出的日志", "warning");
      return;
    }
    try {
      const payload = activeLogs.join("\n");
      const blob = new Blob([payload], { type: "text/plain;charset=utf-8" });
      const url = window.URL.createObjectURL(blob);
      const anchor = document.createElement("a");
      const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
      anchor.href = url;
      anchor.download = `${activeLogMeta.exportName}-${timestamp}.log`;
      document.body.appendChild(anchor);
      anchor.click();
      document.body.removeChild(anchor);
      window.URL.revokeObjectURL(url);
      showToast("日志已导出", "success");
    } catch {
      showToast("导出日志失败", "error");
    }
  };

  const showToast = (
    msg: string,
    type: "success" | "error" | "warning" = "success",
  ) => {
    setToast({ msg, type });
    setTimeout(() => setToast(null), 3000);
  };

  const handleCopyTrainingErrorReplyTemplate = async () => {
    if (!trainingErrorReplyRecommendedJson) {
      showToast("当前没有可复制的 OpenClaw 标准回复模板", "warning");
      return;
    }
    if (!navigator.clipboard?.writeText) {
      showToast("当前环境不支持剪贴板复制，请手动复制模板", "warning");
      return;
    }
    try {
      await navigator.clipboard.writeText(trainingErrorReplyRecommendedJson);
      showToast("已复制 OpenClaw 标准回复模板");
    } catch (_error) {
      showToast("复制失败，请手动复制模板", "error");
    }
  };

  const [showPanicModal, setShowPanicModal] = useState(false);

  const handlePanicAction = async () => {
    setActionLoading("panic");
    try {
      const res = await fetch(`${apiBase}/api/action/panic`, {
        method: "POST",
      });
      const data = await res.json();
      if (res.ok && data.success) {
        showToast(
          String(data.message || "系统已紧急阻断！所有仓位平仓指令已发送。"),
          "error",
        );
        fetchStatus();
      } else {
        showToast(String(data.message || "阻断执行失败"), "error");
      }
    } catch {
      showToast("阻断请求发送失败", "error");
    } finally {
      setActionLoading(null);
      setShowPanicModal(false);
    }
  };

  const [priceHistory, setPriceHistory] = useState<
    { time: string; price: number }[]
  >([]);

  const markBackendAlive = () => {
    const now = Date.now();
    lastBackendHeartbeatTs.current = now;
    setBackendConnected(true);
  };

  const maybeMarkBackendDisconnected = () => {
    const now = Date.now();
    const lastHealthyTs = Math.max(
      lastBackendHeartbeatTs.current,
      lastStatusSuccessTs.current,
    );
    if (lastHealthyTs > 0 && now - lastHealthyTs < 45000) {
      return;
    }
    setBackendConnected(false);
  };

  const tryBackendPing = async (): Promise<boolean> => {
    const controller = new AbortController();
    const timer = window.setTimeout(() => controller.abort(), 1800);
    try {
      const res = await fetch(`${apiBase}/api/ping`, {
        signal: controller.signal,
      });
      if (!res.ok) {
        return false;
      }
      const data = await res.json();
      if (data?.ok) {
        markBackendAlive();
        return true;
      }
      return false;
    } catch {
      return false;
    } finally {
      window.clearTimeout(timer);
    }
  };

  const mergeLightweightStatus = (data: any) => {
    if (!data || typeof data !== "object") {
      return;
    }
    setStatus((prev: any) => ({
      ...prev,
      isRunning:
        typeof data.isRunning === "boolean" ? data.isRunning : prev.isRunning,
      mt5Online:
        typeof data.mt5Online === "boolean" ? data.mt5Online : prev.mt5Online,
      bridgeOk:
        typeof data.bridgeOk === "boolean" ? data.bridgeOk : prev.bridgeOk,
      light: typeof data.light === "string" ? data.light : prev.light,
      priceSource:
        typeof data.priceSource === "string"
          ? data.priceSource
          : prev.priceSource,
      priceAge:
        typeof data.priceAge === "number" ? data.priceAge : prev.priceAge,
      system_stats: {
        ...prev?.system_stats,
        mt5_latency:
          typeof data.mt5Latency === "number"
            ? data.mt5Latency
            : (prev?.system_stats?.mt5_latency ?? -1),
      },
    }));
  };

  const fetchLightweightStatus = async () => {
    if (document.hidden || lightweightStatusInFlight.current) {
      return;
    }
    lightweightStatusInFlight.current = true;
    const controller = new AbortController();
    const timer = window.setTimeout(() => controller.abort(), 2000);
    try {
      const res = await fetch(`${apiBase}/api/lightweight-status`, {
        signal: controller.signal,
      });
      if (!res.ok) {
        const pingOk = await tryBackendPing();
        if (!pingOk) {
          maybeMarkBackendDisconnected();
        }
        return;
      }
      const data = await res.json();
      if (data?.ok) {
        markBackendAlive();
        mergeLightweightStatus(data);
      } else {
        const pingOk = await tryBackendPing();
        if (!pingOk) {
          maybeMarkBackendDisconnected();
        }
      }
    } catch {
      const pingOk = await tryBackendPing();
      if (!pingOk) {
        maybeMarkBackendDisconnected();
      }
    } finally {
      window.clearTimeout(timer);
      lightweightStatusInFlight.current = false;
    }
  };

  const fetchStatus = async () => {
    if (document.hidden) {
      return;
    }
    if (statusFetchInFlight.current) {
      return;
    }
    statusFetchInFlight.current = true;
    const controller = new AbortController();
    const timer = window.setTimeout(() => controller.abort(), 5000);
    try {
      const res = await fetch(`${apiBase}/api/status`, {
        signal: controller.signal,
      });
      if (res.ok) {
        const data = await res.json();
        statusFailStreakRef.current = 0;
        lastStatusSuccessTs.current = Date.now();
        markBackendAlive();
        setStatus((prev: any) => {
          if (!prev) {
            return data;
          }
          const sigPrev = `${prev.isRunning}_${prev.mt5Online}_${prev.bridgeOk}_${prev.light}_${prev.bid}_${prev.ask}_${prev.current_regime}_${prev.risk_block?.exists}_${prev.risk_block?.time}_${prev.risk_block?.summary}_${prev.final_reject?.ts}_${prev.final_reject?.reason}`;
          const sigNext = `${data.isRunning}_${data.mt5Online}_${data.bridgeOk}_${data.light}_${data.bid}_${data.ask}_${data.current_regime}_${data.risk_block?.exists}_${data.risk_block?.time}_${data.risk_block?.summary}_${data.final_reject?.ts}_${data.final_reject?.reason}`;
          return sigPrev === sigNext ? prev : data;
        });

        // 如果后端传回了黑板状态，更新它用于雷达展示
        if (data.blackboard) {
          const preview = normalizeBlackboardPreview(data.blackboard);
          setBlackboardState((prev: any) => {
            const getSig = (obj: any) => {
              if (!obj) {
                return "";
              }
              return `${obj.Macro_Commander?.bias}_${obj.Macro_Commander?.confidence}_${obj.Micro_Sniper?.is_defensive_env}_${obj.Micro_Sniper?.current_regime}_${obj.Micro_Sniper?.override_counter}_${obj.Risk_Commissar?.position_multiplier}`;
            };
            const prevSig = getSig(prev);
            const nextSig = getSig(preview);
            return prevSig === nextSig ? prev : preview;
          });
        }

        // 更新价格历史数据用于图表显示
        const now = new Date();
        const timeStr = `${now.getHours().toString().padStart(2, "0")}:${now.getMinutes().toString().padStart(2, "0")}:${now.getSeconds().toString().padStart(2, "0")}`;
        setPriceHistory((prev) => {
          const newHistory = [...prev, { time: timeStr, price: data.bid }];
          return newHistory.slice(-20); // 只保留最近20个数据点
        });
      } else {
        statusFailStreakRef.current += 1;
        if (statusFailStreakRef.current >= 3) {
          maybeMarkBackendDisconnected();
        }
      }

      const now = Date.now();
      if (now - lastSetupStatusFetchTs.current > 60000) {
        lastSetupStatusFetchTs.current = now;
        const setupController = new AbortController();
        const setupTimer = window.setTimeout(
          () => setupController.abort(),
          3000,
        );
        try {
          await fetch(`${apiBase}/api/setup_status`, {
            signal: setupController.signal,
          });
        } catch {
          // setup status is best-effort; do not block dashboard updates
        } finally {
          window.clearTimeout(setupTimer);
        }
      }
    } catch (e) {
      statusFailStreakRef.current += 1;
      if (statusFailStreakRef.current >= 3) {
        maybeMarkBackendDisconnected();
      }
      if (
        statusFailStreakRef.current === 1 &&
        !(e instanceof DOMException && e.name === "AbortError")
      ) {
        console.warn("API not ready yet, using mock data");
      }
    } finally {
      window.clearTimeout(timer);
      statusFetchInFlight.current = false;
    }
  };

  useEffect(() => {
    if (!backendProbeReady) {
      return;
    }
    fetchLightweightStatus();
    const heartbeatTimer = setInterval(fetchLightweightStatus, 5000);
    return () => clearInterval(heartbeatTimer);
  }, [backendProbeReady, apiBase]);

  useEffect(() => {
    if (!backendProbeReady) {
      return;
    }
    fetchStatus();
    const timer = setInterval(fetchStatus, 12000);
    return () => clearInterval(timer);
  }, [backendProbeReady, apiBase]);

  useEffect(() => {
    if (!backendProbeReady || !backendConnected) {
      return;
    }
    const currentView = drawerPanel || activeMenu;
    const timers: number[] = [];

    if (currentView === "logs") {
      fetchLogs();
      timers.push(window.setInterval(fetchLogs, 2000));
    } else if (currentView === "positions") {
      fetchStrategyWorkbench();
      timers.push(window.setInterval(fetchStrategyWorkbench, 5000));
    } else if (currentView === "settings") {
      if (currentView === "settings") {
        fetchStrategyWorkbench();
        fetchUpdateStatus();
        timers.push(window.setInterval(fetchUpdateStatus, 15000));
        fetchRiskParams();
        fetchUpdateConfig();
        timers.push(window.setInterval(fetchStrategyWorkbench, 6000));
      }
    } else if (currentView === "models" || currentView === "training") {
      fetchAgentModels();
      fetchTrainingStatus();
      fetchTrainingDatasets();
      fetchGovernanceReport();
      fetchApprovalChain();
      fetchGovernanceLifecycle();
      fetchRuntimeObservability();
      timers.push(window.setInterval(fetchTrainingStatus, 5000));
      timers.push(window.setInterval(fetchGovernanceReport, 15000));
      timers.push(window.setInterval(fetchApprovalChain, 15000));
      timers.push(window.setInterval(fetchGovernanceLifecycle, 10000));
      timers.push(window.setInterval(fetchRuntimeObservability, 10000));
    } else if (currentView === "timeline") {
      fetchTimeline();
      timers.push(window.setInterval(fetchTimeline, 5000));
    } else if (
      currentView === "strategyMarketplace" ||
      currentView === "strategyCustom"
    ) {
      fetchStrategyWorkbench();
      timers.push(window.setInterval(fetchStrategyWorkbench, 6000));
      if (currentView === "strategyCustom") {
        fetchStrategyCustomState();
      }
    } else if (currentView === "robotDashboard") {
      fetchRuntimeOperations();
      fetchRuntimeAiEvaluation();
      timers.push(window.setInterval(fetchRuntimeOperations, 6000));
    } else if (currentView === "dashboard") {
      fetchTrainingStatus();
      fetchApprovalChain();
      fetchPendingSignals();
      fetchMailbox();
      timers.push(window.setInterval(fetchTrainingStatus, 15000));
      timers.push(window.setInterval(fetchApprovalChain, 15000));
      timers.push(window.setInterval(fetchPendingSignals, 10000));
      timers.push(window.setInterval(fetchMailbox, 10000));
    } else if (currentView === "webchat") {
      fetchApprovalChain();
      fetchRuntimeObservability();
      fetchPendingSignals();
      fetchMailbox();
      fetchSystemMessages();
      timers.push(window.setInterval(fetchApprovalChain, 15000));
      timers.push(window.setInterval(fetchRuntimeObservability, 10000));
      timers.push(window.setInterval(fetchPendingSignals, 5000));
      timers.push(window.setInterval(fetchMailbox, 5000));
      timers.push(window.setInterval(fetchSystemMessages, 10000));
    }

    return () => {
      timers.forEach((timer) => window.clearInterval(timer));
    };
  }, [
    backendProbeReady,
    backendConnected,
    activeMenu,
    drawerPanel,
    activeLogTab,
    apiBase,
  ]);

  useEffect(() => {
    const currentView = drawerPanel || activeMenu;
    if (currentView !== "strategyCustom") {
      return;
    }
    setCustomDraftStatus("unsaved");
    const timer = window.setTimeout(() => {
      void saveStrategyCustomDraft();
    }, 800);
    return () => window.clearTimeout(timer);
  }, [customStrategyName, customStrategyDocument]);

  useEffect(() => {
    if (Object.keys(workbenchDecisionPolicy).length === 0) {
      return;
    }
    syncDecisionPolicyForm(workbenchDecisionPolicy);
  }, [workbenchDecisionPolicy]);

  useEffect(() => {
    if (!backendProbeReady || !backendConnected) {
      return;
    }
    const refreshMailboxOnFocus = () => {
      if (document.visibilityState === "visible") {
        fetchMailbox();
      }
    };
    document.addEventListener("visibilitychange", refreshMailboxOnFocus);
    window.addEventListener("focus", refreshMailboxOnFocus);
    return () => {
      document.removeEventListener("visibilitychange", refreshMailboxOnFocus);
      window.removeEventListener("focus", refreshMailboxOnFocus);
    };
  }, [backendProbeReady, backendConnected, activeMenu, drawerPanel, apiBase]);

  useEffect(() => {
    const currentView = drawerPanel || activeMenu;
    if (currentView !== "webchat") {
      return;
    }
    const container = mailboxScrollRef.current;
    if (!container) {
      return;
    }
    container.scrollTop = 0;
  }, [decisionHallMessages, activeMenu, drawerPanel]);

  const handleToggleGateway = async () => {
    setConfirmModal({
      title: status.isRunning ? "停止网关" : "启动网关",
      message: status.isRunning
        ? "确定要停止自动交易网关吗？这将暂停所有策略监控和自动下单。"
        : "确定要启动自动交易网关吗？系统将开始监控行情并执行策略。",
      onConfirm: async () => {
        try {
          const endpoint = status.isRunning ? "/api/stop" : "/api/start";
          await fetch(`${apiBase}${endpoint}`, { method: "POST" });
          setStatus((s) => ({ ...s, isRunning: !s.isRunning }));
          showToast(status.isRunning ? "网关已停止" : "网关已启动", "success");
        } catch (e) {
          console.error("Failed to toggle gateway", e);
          setStatus((s) => ({ ...s, isRunning: !s.isRunning }));
        }
        setConfirmModal(null);
      },
    });
  };

  const handleForceMacroRefresh = async () => {
    setActionLoading("macro_refresh");
    try {
      const res = await fetch(`${apiBase}/api/macro/refresh`, {
        method: "POST",
      });
      const data = await res.json();
      if (res.ok && data.success) {
        showToast("已强制唤醒 M2 刷新宏观方向", "success");
      } else {
        showToast(String(data.message || "宏观方向刷新失败"), "error");
      }
      fetchStatus();
    } catch {
      showToast("宏观方向刷新请求失败", "error");
    } finally {
      setActionLoading(null);
    }
  };

  const showWorkspaceInDashboard = false;
  const enableWorkspaceExperience = false;
  const menuTitles: Record<string, string> = {
    dashboard: "总控面板",
    updates: "更新中心",
    positions: "持仓与信号",
    settings: "风控与参数",
    logs: "日志与告警",
    timeline: "复盘时间轴",
    strategyMarketplace: "策略集市",
    robotDashboard: "机器人看板",
    strategyCustom: "策略定制",
    webchat: "WebChat",
    models: "大模型配置",
    training: "训练与进化",
    notify: "系统消息中心",
  };
  const getMenuTitle = (menu: string) =>
    menuTitles[menu] || menu.replace("-", " ");

  const renderView = (menu: string) => {
    if (menu === "notify") {
      return (
        <div className="max-w-6xl w-full mx-auto p-8 space-y-6">
          <div className="flex justify-between items-center mb-6">
            <h2 className="text-2xl font-bold flex items-center gap-3">
              <Bell className="w-6 h-6 text-primary" />
              系统消息中心
            </h2>
            <div className="text-sm text-slate-400">
              统一收口发布、回滚、模板热更新与自动修复消息
            </div>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
            <div className="bg-card border border-slate-800 rounded-xl p-4">
              <div className="text-xs uppercase tracking-wide text-slate-500">
                总消息数
              </div>
              <div className="mt-2 text-2xl font-bold text-white">
                {Number(systemMessageSummary.total || 0)}
              </div>
            </div>
            <div className="bg-card border border-slate-800 rounded-xl p-4">
              <div className="text-xs uppercase tracking-wide text-slate-500">
                发布 / 回滚
              </div>
              <div className="mt-2 text-sm text-slate-300">
                发布 {Number(systemMessageSummary.publishCount || 0)} 次
              </div>
              <div className="text-sm text-slate-300">
                回滚 {Number(systemMessageSummary.rollbackCount || 0)} 次
              </div>
            </div>
            <div className="bg-card border border-slate-800 rounded-xl p-4">
              <div className="text-xs uppercase tracking-wide text-slate-500">
                模板热更新
              </div>
              <div className="mt-2 text-2xl font-bold text-primary">
                {Number(systemMessageSummary.templateCount || 0)}
              </div>
            </div>
            <div className="bg-card border border-slate-800 rounded-xl p-4">
              <div className="text-xs uppercase tracking-wide text-slate-500">
                自动修复
              </div>
              <div className="mt-2 text-2xl font-bold text-warning">
                {Number(systemMessageSummary.repairCount || 0)}
              </div>
            </div>
          </div>

          <div className="bg-card border border-slate-800 rounded-xl overflow-hidden min-h-[420px]">
            <div className="px-5 py-4 border-b border-slate-800 flex items-center justify-between">
              <div className="flex items-center gap-2 text-sm font-medium">
                <Bell className="w-4 h-4 text-primary" />
                最近系统消息
              </div>
              <div className="text-xs text-slate-500">
                轮询同步，统一展示策略与系统事件
              </div>
            </div>
            <div className="p-4 space-y-3 max-h-[560px] overflow-y-auto">
              {systemMessages.map((message) => (
                <div
                  key={message.id}
                  className={`rounded-xl border p-4 bg-${message.color}/10 border-${message.color}/20`}
                >
                  <div className="flex items-start justify-between gap-3">
                    <div>
                      <div className="flex items-center gap-2">
                        <span
                          className={`text-xs font-bold uppercase text-${message.color}`}
                        >
                          {String(message.kind || "system").replaceAll(
                            "_",
                            " ",
                          )}
                        </span>
                        <span className="text-xs text-slate-500">
                          {String(message.source || "system")}
                        </span>
                      </div>
                      <div className="mt-1 text-base font-semibold text-white">
                        {String(message.title || "系统消息")}
                      </div>
                    </div>
                    <div className="text-xs text-slate-500 whitespace-nowrap">
                      {formatDisplayTimestamp(message.ts || message.time) ||
                        "--:--:--"}
                    </div>
                  </div>
                  <div className="mt-2 text-sm text-slate-300">
                    {String(message.desc || "")}
                  </div>
                  {message.metadata &&
                    typeof message.metadata === "object" &&
                    Object.keys(message.metadata).length > 0 && (
                      <div className="mt-3 flex flex-wrap gap-2 text-xs text-slate-400">
                        {Object.entries(message.metadata)
                          .slice(0, 4)
                          .map(([key, value]) => (
                            <span
                              key={`${message.id}-${key}`}
                              className="px-2 py-1 rounded-full bg-slate-900/60 border border-slate-800"
                            >
                              {key}: {String(value)}
                            </span>
                          ))}
                      </div>
                    )}
                </div>
              ))}
              {systemMessages.length === 0 && (
                <div className="p-8 text-center flex flex-col items-center justify-center min-h-[320px]">
                  <Bell className="w-16 h-16 text-slate-600 mb-4" />
                  <h3 className="text-xl font-bold text-slate-300 mb-2">
                    暂无系统消息
                  </h3>
                  <p className="text-slate-500 max-w-md">
                    当系统发生发布、回滚、模板热更新或自动修复时，这里会自动汇总展示。
                  </p>
                </div>
              )}
            </div>
          </div>
        </div>
      );
    }

    if (menu === "dashboard") {
      return (
        <div className="flex flex-col h-full w-full">
          {/* Phase 1: Virtual Workspace (Top 35%) */}
          {showWorkspaceInDashboard && (
            <div className="relative h-[35vh] min-h-[250px] w-full shrink-0 border-b border-slate-800 bg-black flex justify-center overflow-hidden">
              <div className="relative h-full aspect-[16/9] max-w-full">
                <img
                  src="/office_bg.png"
                  alt="Workspace"
                  className="absolute inset-0 w-full h-full object-cover opacity-80"
                />

                {/* 机柜指示灯 Hotzone (现在映射到右侧的机房区域) */}
                <div
                  className="absolute left-[70%] top-[25%] w-[20%] h-[55%] cursor-pointer hover:bg-white/10 border-2 border-transparent hover:border-white/30 rounded-lg transition-all flex items-start justify-end p-3"
                  onClick={() => setDrawerPanel("logs")}
                  title="点击查看系统日志 (System Logs)"
                >
                  {(status.isRunning || status.mt5Online) && (
                    <div className="flex gap-1.5 bg-black/60 p-1.5 rounded border border-white/20">
                      <div className="w-2.5 h-2.5 rounded-full bg-green-500 animate-pulse shadow-[0_0_8px_#22c55e]"></div>
                      <div className="w-2.5 h-2.5 rounded-full bg-green-400 animate-pulse delay-75"></div>
                    </div>
                  )}
                </div>

                {/* 墙上白板 Hotzone */}
                <div
                  className="absolute left-[36%] top-[12%] w-[25%] h-[35%] cursor-pointer hover:bg-white/10 border-2 border-transparent hover:border-white/30 rounded-lg transition-all flex items-center justify-center group"
                  onClick={() => setDrawerPanel("models")}
                  title="点击配置大模型 (Agent Models)"
                >
                  <div className="bg-black/60 backdrop-blur-md px-4 py-2 rounded border border-white/20 text-center shadow-lg transform group-hover:scale-105 transition-transform">
                    <div className="text-[10px] text-slate-300 mb-1">
                      当前倾向
                    </div>
                    <div className="text-sm font-bold text-primary">
                      {status.positionOpen
                        ? status.positionSide === "BUY"
                          ? "看涨 (做多)"
                          : "看跌 (做空)"
                        : status.riskLevel || "观望中"}
                    </div>
                  </div>
                </div>

                {/* 桌面报警器/电话 Hotzone (现在映射到桌上的茶几区域) */}
                <div
                  className="absolute left-[44%] top-[60%] w-[10%] h-[18%] cursor-pointer hover:bg-white/10 border-2 border-transparent hover:border-white/30 rounded-lg transition-all flex items-center justify-center group"
                  onClick={() => setDrawerPanel("timeline")}
                  title="点击查看复盘时间轴 (Timeline)"
                >
                  <div className="relative transform group-hover:scale-110 transition-transform">
                    <Bell
                      className={`w-8 h-8 drop-shadow-2xl transition-colors ${status.light === "RED" ? "text-red-500 animate-bounce" : "text-amber-500/80"}`}
                    />
                    {status.light === "RED" && (
                      <span className="absolute -top-1 -right-1 flex h-3 w-3">
                        <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-red-400 opacity-75"></span>
                        <span className="relative inline-flex rounded-full h-3 w-3 bg-red-500"></span>
                      </span>
                    )}
                  </div>
                </div>

                {/* 左侧工作站电脑区 Hotzone (新增映射到左侧多屏电脑) */}
                <div
                  className="absolute left-[5%] top-[25%] w-[20%] h-[45%] cursor-pointer hover:bg-white/10 border-2 border-transparent hover:border-white/30 rounded-lg transition-all flex items-center justify-center group"
                  onClick={() => setDrawerPanel("settings")}
                  title="点击配置风控参数 (Risk Settings)"
                >
                  <div className="bg-black/60 p-3 rounded-full opacity-0 group-hover:opacity-100 transition-opacity border border-white/20">
                    <Settings className="w-6 h-6 text-white" />
                  </div>
                </div>
              </div>
            </div>
          )}

          {/* Bottom 65% Professional Dashboard */}
          <div className="flex-1 overflow-y-auto p-8 space-y-6">
            {/* 顶部大字报与一键平仓 */}
            <div className="flex flex-col items-center justify-center py-6 space-y-6 border-b border-slate-800 relative">
              <div className="flex items-center space-x-4">
                <div
                  className={`w-4 h-4 rounded-full ${status.isRunning ? "bg-success shadow-[0_0_15px_rgba(16,185,129,0.5)]" : "bg-danger animate-pulse shadow-[0_0_15px_rgba(239,68,68,0.5)]"}`}
                ></div>
                <h2 className="text-5xl font-bold tracking-tight">
                  {status.isRunning ? "运行中" : "已停止"}
                </h2>
              </div>
              <p className="text-slate-400 text-lg">
                AI 自治交易网关 v{GUI_VERSION}
              </p>

              <div className="flex gap-4">
                <button
                  onClick={handleToggleGateway}
                  className={`${status.isRunning ? "bg-slate-700 hover:bg-slate-600" : "bg-success hover:bg-emerald-400 shadow-[0_0_20px_rgba(16,185,129,0.3)]"} text-white font-bold py-4 px-12 rounded-2xl text-xl transition-all transform hover:scale-105 active:scale-95 flex items-center space-x-2`}
                >
                  {status.isRunning ? (
                    <Square className="w-6 h-6 fill-current" />
                  ) : (
                    <Play className="w-6 h-6 fill-current" />
                  )}
                  <span>{status.isRunning ? "停止网关" : "启动网关"}</span>
                </button>

                {status.isRunning && (
                  <button
                    onClick={() => setShowPanicModal(true)}
                    className="bg-danger hover:bg-red-500 text-white font-bold py-4 px-8 rounded-2xl text-xl shadow-[0_0_20px_rgba(239,68,68,0.4)] transition-all transform hover:scale-105 active:scale-95 flex items-center space-x-2 border-2 border-red-400/50 animate-pulse"
                  >
                    <ShieldAlert className="w-6 h-6" />
                    <span>一键平仓并阻断</span>
                  </button>
                )}
                <button
                  onClick={handleForceMacroRefresh}
                  disabled={actionLoading === "macro_refresh"}
                  className="bg-primary hover:bg-blue-500 disabled:opacity-60 text-white font-bold py-4 px-8 rounded-2xl text-xl transition-all transform hover:scale-105 active:scale-95 flex items-center space-x-2 border border-blue-300/40"
                >
                  <RotateCcw
                    className={`w-6 h-6 ${actionLoading === "macro_refresh" ? "animate-spin" : ""}`}
                  />
                  <span>
                    {actionLoading === "macro_refresh"
                      ? "刷新中..."
                      : "强制刷新宏观方向"}
                  </span>
                </button>
              </div>
            </div>

            {/* 核心指标卡片组 */}
            <div className="grid grid-cols-1 md:grid-cols-6 gap-4">
              <div className="bg-card border border-slate-800 rounded-xl p-5">
                <p className="text-xs text-slate-400 font-medium mb-1">
                  MT5 连接状态
                </p>
                <div className="flex items-baseline space-x-2">
                  <span className="text-2xl font-bold">
                    {backendConnected
                      ? status.mt5Online
                        ? "在线"
                        : "离线"
                      : "未连接"}
                  </span>
                </div>
                <div
                  className={`mt-3 inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium border ${
                    !backendConnected
                      ? "bg-amber-500/20 text-amber-300 border-amber-500/30"
                      : status.mt5Online
                        ? "bg-success/20 text-success border-success/30"
                        : "bg-danger/20 text-danger border-danger/30"
                  }`}
                >
                  {backendConnected
                    ? status.mt5Online
                      ? "心跳正常"
                      : "连接断开"
                    : "后端未启动"}
                </div>
              </div>

              <div className="bg-card border border-slate-800 rounded-xl p-5">
                <div className="flex justify-between items-start mb-1">
                  <p className="text-xs text-slate-400 font-medium">
                    当前行情 (XAUUSD)
                  </p>
                  <div className="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium bg-primary/20 text-primary border border-primary/30">
                    点差 {((status.ask - status.bid) * 100).toFixed(1)}
                  </div>
                </div>
                <div className="flex items-baseline space-x-2 mb-2 relative">
                  <span
                    className={`text-2xl font-bold font-mono transition-colors duration-300 ${status.isRunning ? "text-primary" : ""}`}
                  >
                    {status.bid.toFixed(2)}
                  </span>
                  <span className="text-sm text-slate-500 font-mono">
                    / {status.ask.toFixed(2)}
                  </span>
                  {status.isRunning && (
                    <span className="absolute -right-2 top-1 flex h-2 w-2">
                      <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
                      <span className="relative inline-flex rounded-full h-2 w-2 bg-primary"></span>
                    </span>
                  )}
                </div>
                <div className="h-12 w-full mt-2">
                  {priceHistory.length > 0 ? (
                    <ResponsiveContainer width="100%" height="100%">
                      <LineChart data={priceHistory}>
                        <Line
                          type="monotone"
                          dataKey="price"
                          stroke="#3b82f6"
                          strokeWidth={2}
                          dot={false}
                          isAnimationActive={false}
                        />
                      </LineChart>
                    </ResponsiveContainer>
                  ) : (
                    <div className="w-full h-full flex items-center justify-center text-[10px] text-slate-600 border border-dashed border-slate-800 rounded">
                      等待行情数据...
                    </div>
                  )}
                </div>
              </div>

              <div className="bg-card border border-slate-800 rounded-xl p-5">
                <p className="text-xs text-slate-400 font-medium mb-1">
                  持仓状态
                </p>
                <div className="flex items-baseline space-x-2">
                  <span className="text-2xl font-bold">
                    {visibleOpenPositions.length > 0
                      ? `${visibleOpenPositions.length} 个仓位`
                      : "空仓"}
                  </span>
                </div>
                {visibleOpenPositions.length > 0 ? (
                  <div className="mt-3 flex flex-col gap-1">
                    {visibleOpenPositions.map((p: any, i: number) => (
                      <div
                        key={i}
                        className={`inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium ${p.side === "BUY" ? "bg-success/20 text-success border border-success/30" : "bg-danger/20 text-danger border border-danger/30"}`}
                      >
                        {p.side} {p.volume}手 @ {p.entry} (PnL:{" "}
                        {p.pnl > 0 ? "+" : ""}
                        {p.pnl})
                      </div>
                    ))}
                  </div>
                ) : (
                  <div className="mt-3 inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium bg-slate-800 text-slate-400 border border-slate-700">
                    无活跃持仓
                  </div>
                )}
              </div>

              <div className="bg-card border border-slate-800 rounded-xl p-5">
                <p className="text-xs text-slate-400 font-medium mb-1">
                  Agent 宏观定调
                </p>
                <div className="flex items-baseline space-x-2">
                  <span
                    className={`text-2xl font-bold ${
                      status.agent_dir === "LONG"
                        ? "text-success"
                        : status.agent_dir === "SHORT"
                          ? "text-danger"
                          : "text-warning"
                    }`}
                  >
                    {status.agent_dir === "LONG"
                      ? "只做多 (LONG)"
                      : status.agent_dir === "SHORT"
                        ? "只做空 (SHORT)"
                        : "震荡双向 (NEUTRAL)"}
                  </span>
                </div>
                <div
                  className={`mt-3 inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium border ${
                    status.agent_dir === "LONG"
                      ? "bg-success/20 text-success border-success/30"
                      : status.agent_dir === "SHORT"
                        ? "bg-danger/20 text-danger border-danger/30"
                        : "bg-warning/20 text-warning border-warning/30"
                  }`}
                >
                  agent_dir={status.agent_dir || "NEUTRAL"}
                </div>
              </div>

              <div className="bg-card border border-slate-800 rounded-xl p-5">
                <div className="flex items-center justify-between mb-1">
                  <p className="text-xs text-slate-400 font-medium">
                    Session Risk Lens
                  </p>
                  <Crosshair className="w-3 h-3 text-primary" />
                </div>
                <div className="mt-2 space-y-2">
                  <div className="rounded-lg border border-slate-800 bg-slate-950/50 p-2">
                    <div className="flex items-center justify-between gap-2">
                      <span className="text-[10px] text-slate-500 uppercase tracking-[0.08em]">
                        亚欧重叠
                      </span>
                      <span
                        className={`inline-flex items-center gap-1 rounded-full border border-slate-700 px-2 py-0.5 text-[10px] ${asiaLondonTone.text}`}
                      >
                        <span
                          className={`h-1.5 w-1.5 rounded-full ${asiaLondonTone.dot}`}
                        />
                        {asiaLondonTone.label}
                      </span>
                    </div>
                    <div className="mt-1 text-[11px] text-slate-300">
                      {String(runtimeAsiaLondonRule.action || "neutral")} ·
                      limit_only{" "}
                      {String(Boolean(runtimeAsiaLondonRule.limit_only))}
                    </div>
                  </div>
                  <div className="rounded-lg border border-slate-800 bg-slate-950/50 p-2">
                    <div className="flex items-center justify-between gap-2">
                      <span className="text-[10px] text-slate-500 uppercase tracking-[0.08em]">
                        欧美重叠
                      </span>
                      <span
                        className={`inline-flex items-center gap-1 rounded-full border border-slate-700 px-2 py-0.5 text-[10px] ${londonNyTone.text}`}
                      >
                        <span
                          className={`h-1.5 w-1.5 rounded-full ${londonNyTone.dot}`}
                        />
                        {londonNyTone.label}
                      </span>
                    </div>
                    <div className="mt-1 text-[11px] text-slate-300">
                      {String(runtimeLondonNyRule.action || "neutral")} ·
                      limit_only{" "}
                      {String(Boolean(runtimeLondonNyRule.limit_only))}
                    </div>
                  </div>
                </div>
              </div>

              {/* 智能风控雷达模块 (替代了原来的今日交易统计) */}
              <div className="bg-card border border-slate-800 rounded-xl p-5 relative overflow-hidden">
                <div
                  className={`absolute top-0 left-0 w-full h-1 ${status.is_defensive ? "bg-amber-500/50" : "bg-primary/50"}`}
                ></div>
                <div className="flex justify-between items-center mb-2">
                  <p className="text-xs text-slate-400 font-medium flex items-center gap-1">
                    <Activity className="w-3 h-3 text-primary" />
                    智能风控雷达
                  </p>
                  {status.is_defensive ? (
                    <span className="text-[10px] bg-amber-500/10 text-amber-500 border border-amber-500/20 px-2 py-0.5 rounded flex items-center gap-1">
                      <Shield className="w-3 h-3" />
                      严密防守中
                    </span>
                  ) : (
                    <span className="text-[10px] bg-green-500/10 text-green-500 border border-green-500/20 px-2 py-0.5 rounded flex items-center gap-1">
                      <Crosshair className="w-3 h-3" />
                      全速进攻中
                    </span>
                  )}
                </div>

                <div className="mt-3 space-y-2">
                  <div className="flex justify-between items-center text-xs">
                    <span className="text-slate-500">当前市场结构:</span>
                    <span className="text-slate-300 font-mono bg-slate-800 px-1.5 py-0.5 rounded">
                      {status.regime || "UNKNOWN"}
                    </span>
                  </div>
                  {status.risk_block?.exists && (
                    <div className="flex justify-between items-start text-xs gap-2">
                      <span className="text-slate-500">最新阻断:</span>
                      <div className="text-right">
                        <div className="text-amber-400 font-medium">
                          {String(status.risk_block.categoryLabel || "未分类")}
                        </div>
                        <div className="text-[10px] text-slate-500 font-mono">
                          {String(status.risk_block.rawReason || "")}
                        </div>
                      </div>
                    </div>
                  )}
                  {status.final_reject?.reason && (
                    <div className="flex justify-between items-start text-xs gap-2">
                      <span className="text-slate-500">最终拒绝:</span>
                      <div className="text-right">
                        <div className="text-orange-300 font-medium">
                          {String(status.final_reject.stage || "unknown")}
                        </div>
                        <div className="text-[10px] text-slate-500 font-mono">
                          {String(status.final_reject.reason || "")}
                        </div>
                      </div>
                    </div>
                  )}
                  <div className="flex justify-between items-center text-xs">
                    <span className="text-slate-500">重叠预算:</span>
                    <span className="text-slate-300 font-mono bg-slate-800 px-1.5 py-0.5 rounded">
                      {Number(
                        (status.overlap_budget as any)?.effective_attempts || 0,
                      )}
                      /{Number((status as any)?.overlap_budget_target || 2)}
                    </span>
                  </div>

                  <div className="pt-2 border-t border-slate-800/50">
                    <p className="text-[10px] text-slate-500 mb-1.5">
                      隐形挂单 (Soft Limits)
                    </p>
                    {status.soft_limits && status.soft_limits.length > 0 ? (
                      <div className="space-y-1.5 max-h-[120px] overflow-y-auto custom-scrollbar pr-1">
                        {status.soft_limits.map((order: any, idx: number) => (
                          <div
                            key={idx}
                            className="text-[10px] bg-slate-800/50 p-1.5 rounded border border-slate-700/50"
                          >
                            <div className="flex justify-between items-center">
                              <span
                                className={
                                  order.side === "BUY"
                                    ? "text-green-400 font-mono"
                                    : "text-red-400 font-mono"
                                }
                              >
                                {order.side} LMT @{order.limit_price}
                              </span>
                              <span className="text-slate-500 flex items-center gap-1">
                                <Clock className="w-2.5 h-2.5" />
                                {order.remain_mins}m
                              </span>
                            </div>
                            {order.final_offset_usd != null && (
                              <div className="mt-1 text-[9px] text-slate-400">
                                距离=$
                                {Number(order.final_offset_usd).toFixed(2)}{" "}
                                (ATR=
                                {Number(order.atr_offset_usd || 0).toFixed(2)},
                                spread底=
                                {Number(order.spread_floor_usd || 0).toFixed(2)}
                                , 护栏=
                                {Number(order.min_offset_usd || 0).toFixed(1)}~
                                {Number(order.max_offset_usd || 0).toFixed(1)})
                              </div>
                            )}
                          </div>
                        ))}
                      </div>
                    ) : (
                      <div className="text-[10px] text-slate-500 flex items-center gap-1.5 bg-slate-800/30 p-1.5 rounded border border-slate-800/50 border-dashed">
                        <Search className="w-3 h-3 text-slate-600" />
                        内存队列为空，正在扫描绝佳入场点...
                      </div>
                    )}
                  </div>
                </div>
              </div>
            </div>

            {/* [Phase 5] 决策大厅：审批链 + 运行阻断 + 运行画像 */}
            <div className="bg-card border border-slate-800 rounded-2xl p-6 relative overflow-hidden group mt-6">
              <div className="absolute top-0 left-0 w-1 h-full bg-primary animate-pulse"></div>
              <div className="flex justify-between items-center mb-6">
                <h3 className="text-lg font-bold flex items-center gap-2">
                  <Activity className="w-5 h-5 text-primary" />
                  决策大厅
                </h3>
                <span className="flex items-center gap-1 text-xs font-medium px-2 py-1 bg-primary/10 text-primary rounded-md border border-primary/20">
                  <div className="w-1.5 h-1.5 rounded-full bg-primary animate-pulse"></div>
                  审批链与运行阻断实时同步
                </span>
              </div>

              <div className="grid grid-cols-1 xl:grid-cols-12 gap-4">
                <div className="xl:col-span-7 rounded-xl border border-slate-800 bg-slate-950/50 p-4">
                  <div className="flex items-center justify-between gap-3">
                    <div>
                      <div className="text-sm font-semibold text-slate-100">
                        审批消息 + 运行阻断消息
                      </div>
                      <div className="mt-1 text-xs text-slate-500">
                        来自真实
                        `approval_chain`、`review_pending`、`risk_block`、`blackboard`、`mailbox`
                        与 `system_messages`
                      </div>
                    </div>
                    <span className="rounded-full border border-slate-700 bg-slate-900/80 px-2 py-1 text-[10px] text-slate-300">
                      {decisionHallMessages.length} 条有效消息
                    </span>
                  </div>
                  <div className="mt-4 space-y-3 max-h-[360px] overflow-y-auto pr-1 custom-scrollbar">
                    {decisionHallMessages.length > 0 ? (
                      decisionHallMessages.slice(0, 8).map((message) => (
                        <div
                          key={message.id}
                          className={`rounded-xl border px-4 py-3 ${decisionToneClass(message.tone)}`}
                        >
                          <div className="flex items-start justify-between gap-3">
                            <div className="min-w-0 flex-1">
                              <div className="flex flex-wrap items-center gap-2">
                                <div
                                  className={`text-sm font-semibold ${decisionLabelClass(message.tone)}`}
                                >
                                  {message.title}
                                </div>
                                <span className="rounded-full border border-slate-700/80 bg-slate-950/60 px-2 py-0.5 text-[10px] uppercase tracking-[0.08em] text-slate-400">
                                  {message.source}
                                </span>
                              </div>
                              <div className="mt-2 text-sm leading-6 text-slate-200">
                                {message.body}
                              </div>
                              {message.chips.length > 0 && (
                                <div className="mt-3 flex flex-wrap gap-2">
                                  {message.chips.map((chip) => (
                                    <span
                                      key={`${message.id}_${chip}`}
                                      className="rounded-full border border-slate-700 bg-slate-950/70 px-2 py-0.5 text-[10px] text-slate-300"
                                    >
                                      {chip}
                                    </span>
                                  ))}
                                </div>
                              )}
                            </div>
                            <div className="shrink-0 text-[10px] text-slate-500">
                              {formatDisplayTimestamp(message.timestamp) ||
                                message.timestamp ||
                                "实时"}
                            </div>
                          </div>
                        </div>
                      ))
                    ) : (
                      <div className="rounded-xl border border-dashed border-slate-700 bg-slate-950/40 px-4 py-6 text-sm text-slate-500">
                        当前没有新的审批或运行阻断消息，系统将继续监听真实运行链。
                      </div>
                    )}
                  </div>
                </div>

                <div className="xl:col-span-5 space-y-4">
                  <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                    <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-4">
                      <div className="text-[11px] uppercase tracking-[0.14em] text-slate-500">
                        审批状态
                      </div>
                      <div
                        className={`mt-2 text-lg font-bold ${decisionLabelClass(decisionHallApprovalTone)}`}
                      >
                        {approvalDecisionStatus}
                      </div>
                      <div className="mt-1 text-xs text-slate-500">
                        {approvalStage}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-4">
                      <div className="text-[11px] uppercase tracking-[0.14em] text-slate-500">
                        运行阻断
                      </div>
                      <div className="mt-2 text-lg font-bold text-slate-100">
                        {runtimeGovernorBlockers.length}
                      </div>
                      <div className="mt-1 text-xs text-slate-500">
                        {String(
                          blackboardRiskProtocol.global_state || "normal",
                        )}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-4">
                      <div className="text-[11px] uppercase tracking-[0.14em] text-slate-500">
                        待人工审批
                      </div>
                      <div className="mt-2 text-lg font-bold text-warning">
                        {signalReviewPendingCount}
                      </div>
                      <div className="mt-1 text-xs text-slate-500">
                        review_pending 队列
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-4">
                      <div className="text-[11px] uppercase tracking-[0.14em] text-slate-500">
                        当前仲裁
                      </div>
                      <div className="mt-2 text-lg font-bold text-slate-100">
                        {String(blackboardExecution.final_action || "HOLD")}
                      </div>
                      <div className="mt-1 text-xs text-slate-500">
                        {String(
                          blackboardExecution.hold_mode || "selected_action",
                        )}
                      </div>
                    </div>
                  </div>
                  <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-4">
                    <div className="text-[11px] uppercase tracking-[0.14em] text-slate-500">
                      当前运行实例
                    </div>
                    <div className="mt-2 text-sm text-slate-200 break-all">
                      {String(
                        blackboardScheduler.selected_strategy_id ||
                          blackboardExecution.selected_strategy_id ||
                          "未选中策略",
                      )}
                    </div>
                    <div className="mt-1 text-xs text-slate-500 break-all">
                      {String(
                        blackboardScheduler.selected_instance_id ||
                          blackboardExecution.selected_instance_id ||
                          "未选中实例",
                      )}
                    </div>
                    <div className="mt-2 text-[11px] text-slate-500 break-all">
                      {String(blackboardScheduler.route_family || "unknown")} ·
                      side {String(blackboardScheduler.allowed_side || "BOTH")}
                    </div>
                    <div className="mt-1 text-[11px] text-slate-500 break-all">
                      {Array.isArray(
                        blackboardScheduler.candidate_strategy_ids,
                      ) && blackboardScheduler.candidate_strategy_ids.length > 0
                        ? blackboardScheduler.candidate_strategy_ids.join(", ")
                        : "暂无候选策略"}
                    </div>
                    <div className="mt-3 flex flex-wrap gap-2">
                      {Object.entries(
                        (blackboardScheduler.router_weights as Record<
                          string,
                          unknown
                        >) || {},
                      )
                        .slice(0, 3)
                        .map(([strategyId, weight]) => (
                          <span
                            key={`route-${strategyId}`}
                            className="rounded-full border border-primary/20 bg-primary/10 px-2 py-0.5 text-[10px] text-primary"
                          >
                            {strategyId}:{Number(weight || 0).toFixed(2)}
                          </span>
                        ))}
                      {String(
                        (
                          blackboardScheduler.direction_guard as Record<
                            string,
                            unknown
                          >
                        )?.state || "",
                      ) && (
                        <span className="rounded-full border border-warning/20 bg-warning/10 px-2 py-0.5 text-[10px] text-warning">
                          方向守门{" "}
                          {String(
                            (
                              blackboardScheduler.direction_guard as Record<
                                string,
                                unknown
                              >
                            )?.state || "inactive",
                          )}
                        </span>
                      )}
                      {runtimeGovernorBlockers.slice(0, 4).map((reason) => (
                        <span
                          key={reason}
                          className="rounded-full border border-danger/20 bg-danger/10 px-2 py-0.5 text-[10px] text-danger"
                        >
                          {reason}
                        </span>
                      ))}
                      {runtimeGovernorBlockers.length === 0 && (
                        <span className="rounded-full border border-success/20 bg-success/10 px-2 py-0.5 text-[10px] text-success">
                          当前无显式运行阻断
                        </span>
                      )}
                    </div>
                  </div>
                </div>
              </div>

              <div className="mt-6 border-t border-slate-800 pt-4">
                <div className="mb-3 text-[11px] uppercase tracking-[0.14em] text-slate-500">
                  运行画像
                </div>
                <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
                  {/* 宏观指挥官 */}
                  <div className="bg-slate-900/50 border border-slate-800 rounded-xl p-4 flex flex-col">
                    <div className="flex justify-between items-center mb-3">
                      <span className="text-sm text-slate-400 font-medium">
                        宏观指挥官
                      </span>
                      <Globe className="w-4 h-4 text-blue-400" />
                    </div>
                    <div className="flex-1 flex flex-col justify-center">
                      <div className="text-2xl font-bold text-white tracking-wider">
                        {blackboardState?.Macro_Commander?.bias || "UNKNOWN"}
                      </div>
                      <div className="text-xs text-slate-500 mt-1 flex items-center gap-2">
                        <span>置信度</span>
                        <div className="w-full bg-slate-800 rounded-full h-1.5 max-w-[80px]">
                          <div
                            className="bg-blue-500 h-1.5 rounded-full transition-all duration-500"
                            style={{
                              width: `${(blackboardState?.Macro_Commander?.confidence || 0) * 100}%`,
                            }}
                          ></div>
                        </div>
                      </div>
                      {/* M2 调用统计 & 触发原因 */}
                      <div className="flex items-center gap-2 mt-1.5">
                        <span className="text-xs text-slate-600">今日M2:</span>
                        <span className="text-xs font-mono text-blue-400">
                          #{blackboardState?.Macro_Commander?.daily_calls ?? 0}
                        </span>
                        {blackboardState?.Macro_Commander?.trigger_reason && (
                          <span
                            className={`text-xs px-1.5 py-0.5 rounded font-medium ${
                              blackboardState.Macro_Commander.trigger_reason ===
                              "score_jump"
                                ? "bg-amber-500/20 text-amber-400 border border-amber-500/30"
                                : blackboardState.Macro_Commander
                                      .trigger_reason === "ny_session"
                                  ? "bg-purple-500/20 text-purple-400 border border-purple-500/30"
                                  : "bg-slate-800 text-slate-400"
                            }`}
                          >
                            {blackboardState.Macro_Commander.trigger_reason ===
                              "score_jump" && "🔥 剧变"}
                            {blackboardState.Macro_Commander.trigger_reason ===
                              "cold_start" && "⚡ 冷启动"}
                            {blackboardState.Macro_Commander.trigger_reason ===
                              "hourly" && "⏰ 整点"}
                            {blackboardState.Macro_Commander.trigger_reason ===
                              "ny_session" && "🌙 NY时段"}
                            {blackboardState.Macro_Commander.trigger_reason ===
                              "override" && "🚨 逼宫"}
                          </span>
                        )}
                      </div>
                    </div>
                  </div>

                  {/* 微观狙击手 */}
                  <div
                    className={`bg-slate-900/50 border rounded-xl p-4 flex flex-col transition-colors duration-500 ${blackboardState?.Micro_Sniper?.is_defensive_env ? "border-warning/30 bg-warning/5" : "border-slate-800"}`}
                  >
                    <div className="flex justify-between items-center mb-3">
                      <span className="text-sm text-slate-400 font-medium">
                        微观狙击手
                      </span>
                      <Crosshair
                        className={`w-4 h-4 ${blackboardState?.Micro_Sniper?.is_defensive_env ? "text-warning" : "text-slate-400"}`}
                      />
                    </div>
                    <div className="flex-1 flex flex-col justify-center">
                      <div className="flex flex-wrap gap-2">
                        <span
                          className={`text-xs px-2 py-1 rounded font-medium ${blackboardState?.Micro_Sniper?.is_defensive_env ? "bg-warning text-warning-900" : "bg-slate-800 text-slate-400"}`}
                        >
                          {blackboardState?.Micro_Sniper?.is_defensive_env
                            ? "防守环境激活"
                            : "常态环境"}
                        </span>
                        {blackboardState?.Micro_Sniper?.knife_catching_risk && (
                          <span className="text-xs px-2 py-1 rounded font-medium bg-danger/20 text-danger border border-danger/30 animate-pulse">
                            ⚠️ 飞刀风险
                          </span>
                        )}
                        {blackboardState?.Micro_Sniper?.ny_session_active && (
                          <span className="text-xs px-2 py-1 rounded font-medium bg-purple-500/20 text-purple-400 border border-purple-500/30">
                            🌙 NY时段
                          </span>
                        )}
                      </div>
                      <div className="text-xs text-slate-500 mt-2">
                        市场状态:{" "}
                        <span className="text-slate-300">
                          {blackboardState?.Micro_Sniper?.current_regime ||
                            "探测中"}
                        </span>
                      </div>
                      {/* 逼宫计数器 */}
                      {(blackboardState?.Micro_Sniper?.override_counter ?? 0) >
                        0 && (
                        <div className="text-xs mt-1.5 flex items-center gap-1">
                          <span className="text-slate-600">逼宫:</span>
                          <div className="flex gap-1">
                            {[1, 2].map((i) => (
                              <div
                                key={i}
                                className={`w-2 h-2 rounded-full ${
                                  i <=
                                  (blackboardState?.Micro_Sniper
                                    ?.override_counter ?? 0)
                                    ? "bg-danger animate-pulse"
                                    : "bg-slate-700"
                                }`}
                              />
                            ))}
                            <span className="text-slate-500 ml-0.5">
                              /
                              {blackboardState?.Micro_Sniper
                                ?.override_threshold ?? 2}
                            </span>
                          </div>
                        </div>
                      )}
                    </div>
                  </div>

                  {/* 风控政委 */}
                  <div
                    className={`bg-slate-900/50 border rounded-xl p-4 flex flex-col transition-colors duration-500 ${(blackboardState?.Risk_Commissar?.position_multiplier ?? 1.0) < 1.0 ? "border-danger/30 bg-danger/5" : "border-slate-800"}`}
                  >
                    <div className="flex justify-between items-center mb-3">
                      <span className="text-sm text-slate-400 font-medium">
                        风控政委
                      </span>
                      <ShieldAlert
                        className={`w-4 h-4 ${(blackboardState?.Risk_Commissar?.position_multiplier ?? 1.0) < 1.0 ? "text-danger" : "text-success"}`}
                      />
                    </div>
                    <div className="flex-1 flex flex-col justify-center">
                      <div className="flex items-end gap-2">
                        <span className="text-2xl font-bold text-white">
                          {(
                            blackboardState?.Risk_Commissar
                              ?.position_multiplier ?? 1.0
                          ).toFixed(1)}
                          x
                        </span>
                        <span className="text-xs text-slate-500 mb-1">
                          仓位缩放
                        </span>
                      </div>
                      {(blackboardState?.Risk_Commissar?.position_multiplier ??
                        1.0) < 1.0 && (
                        <div className="text-xs text-danger mt-1 flex items-center gap-1">
                          <AlertCircle className="w-3 h-3" /> 已触发风控缩仓
                        </div>
                      )}
                    </div>
                  </div>
                </div>
              </div>
            </div>

            {/* AI 模型进化状态 */}
            <div className="bg-card border border-slate-800 rounded-2xl p-6 mt-6 relative overflow-hidden group">
              <div
                className={`absolute top-0 left-0 w-1 h-full ${trainingStatus.isTraining ? "bg-primary animate-pulse" : "bg-success"}`}
              ></div>
              <div className="flex justify-between items-center mb-4">
                <h3 className="text-lg font-bold flex items-center gap-2">
                  <DatabaseZap className="w-5 h-5 text-primary" />
                  离线数据训练与进化
                </h3>
                <button
                  onClick={() => setActiveMenu("training")}
                  className="text-sm text-primary hover:text-blue-400 transition-colors flex items-center gap-1"
                >
                  查看训练详情 <TrendingUp className="w-3 h-3 rotate-90" />
                </button>
              </div>

              <div className="flex items-center gap-6">
                <div className="flex-1">
                  <div className="flex justify-between text-xs text-slate-400 mb-2">
                    <span>
                      进度:{" "}
                      {trainingStatus.currentEpoch
                        ? `Epoch ${trainingStatus.currentEpoch} / ${trainingStatus.totalEpochs}`
                        : `${trainingStatus.currentBar} / ${trainingStatus.totalBars}`}
                    </span>
                    <span>{trainingStatus.progress.toFixed(1)}%</span>
                  </div>
                  <div className="w-full bg-slate-800 rounded-full h-2">
                    <div
                      className="bg-primary h-2 rounded-full transition-all duration-500 relative"
                      style={{ width: `${trainingStatus.progress}%` }}
                    >
                      <div className="absolute right-0 top-0 bottom-0 w-4 bg-white/20 blur-sm rounded-full animate-[pulse_1s_ease-in-out_infinite]"></div>
                    </div>
                  </div>
                </div>
                <div className="flex items-center gap-4 border-l border-slate-800 pl-6">
                  <div>
                    <p className="text-[10px] text-slate-500 uppercase tracking-wider">
                      实时胜率 (Win Rate)
                    </p>
                    <p
                      className={`text-xl font-mono font-bold ${trainingStatus.winRate > 50 ? "text-success" : "text-warning"}`}
                    >
                      {trainingStatus.winRate.toFixed(1)}%
                    </p>
                  </div>
                  <div>
                    <p className="text-[10px] text-slate-500 uppercase tracking-wider">
                      模拟盈亏 (PnL)
                    </p>
                    <p
                      className={`text-lg font-mono font-bold ${trainingStatus.pnl > 0 ? "text-success" : trainingStatus.pnl < 0 ? "text-danger" : "text-slate-400"}`}
                    >
                      {trainingStatus.pnl > 0 ? "+" : ""}$
                      {trainingStatus.pnl.toFixed(2)}
                    </p>
                  </div>
                </div>
              </div>
            </div>

            <div className="h-12"></div>
          </div>
        </div>
      );
    }

    if (menu === "timeline") {
      return (
        <div className="max-w-5xl w-full mx-auto p-8 space-y-6">
          <div className="flex justify-between items-center mb-6 border-b border-slate-800 pb-4">
            <div>
              <h2 className="text-2xl font-bold flex items-center gap-3">
                <Clock className="w-6 h-6 text-primary" />
                大模型交易复盘时间轴
              </h2>
              <p className="text-sm text-slate-400 mt-1">
                将底层冰冷的系统日志，转化为 AI 角色间的对话决策流
              </p>
            </div>
          </div>

          <div className="bg-card border border-slate-800 rounded-2xl p-5">
            <div className="flex items-center justify-between gap-4 mb-4">
              <div>
                <div className="text-sm font-bold text-slate-100">
                  真实事件源接入概览
                </div>
                <div className="text-xs text-slate-500 mt-1">
                  direction / execution_state / risk_events / trading_ledger /
                  closures / strategy runtime
                </div>
              </div>
              <div className="text-xs text-slate-400">
                共 {timelineEvents.length} 条可视事件
              </div>
            </div>
            <div className="flex flex-wrap gap-2">
              {timelineSources.length > 0 ? (
                timelineSources.map((source: any) => (
                  <span
                    key={String(source.id)}
                    className="px-2.5 py-1 rounded-full border border-slate-700 bg-[#0A0E17] text-xs text-slate-300"
                  >
                    {String(source.id)} · {Number(source.count || 0)}
                  </span>
                ))
              ) : (
                <span className="text-sm text-slate-500">
                  等待事件源返回...
                </span>
              )}
            </div>
          </div>

          <div className="relative border-l-2 border-slate-800 ml-4 pl-8 space-y-8 pb-12">
            {timelineEvents.length > 0 ? (
              timelineEvents.map((evt, idx) => (
                <div key={idx} className="relative">
                  {/* 节点图标 */}
                  <div
                    className={`absolute -left-[41px] top-1 w-6 h-6 rounded-full border-4 border-background flex items-center justify-center ${
                      evt.type === "analyze"
                        ? "bg-blue-500"
                        : evt.type === "trade"
                          ? "bg-emerald-500"
                          : evt.type === "warning"
                            ? "bg-amber-500"
                            : "bg-slate-500"
                    }`}
                  >
                    <div className="w-2 h-2 rounded-full bg-white"></div>
                  </div>

                  {/* 时间戳 */}
                  <div className="text-xs text-slate-500 font-mono mb-2 flex items-center gap-2">
                    <span>{evt.time}</span>
                    <span
                      className={`px-2 py-0.5 rounded text-[10px] ${
                        evt.role === "Data_Analyst"
                          ? "bg-blue-500/20 text-blue-400"
                          : evt.role === "Trend_Strategy_v2"
                            ? "bg-emerald-500/20 text-emerald-400"
                            : evt.role === "Risk_Manager"
                              ? "bg-amber-500/20 text-amber-400"
                              : "bg-slate-700 text-slate-300"
                      }`}
                    >
                      {evt.role}
                    </span>
                    {evt.source && (
                      <span className="px-2 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 border border-slate-700">
                        {evt.source}
                      </span>
                    )}
                  </div>

                  {/* 内容卡片 */}
                  <div className="bg-card border border-slate-800 rounded-xl p-4 shadow-lg">
                    <h4 className="text-sm font-bold text-slate-200 mb-2">
                      {evt.title}
                    </h4>
                    <p className="text-sm text-slate-400 whitespace-pre-wrap leading-relaxed">
                      {evt.content}
                    </p>

                    {/* 附加数据展示 */}
                    {evt.data && (
                      <div className="mt-3 bg-[#0A0E17] border border-slate-800 rounded-lg p-3 text-xs font-mono text-slate-500 overflow-x-auto">
                        {JSON.stringify(evt.data, null, 2)}
                      </div>
                    )}
                  </div>
                </div>
              ))
            ) : (
              <div className="py-12 text-center text-slate-500">
                暂无决策流记录，请等待系统运行产生数据...
              </div>
            )}
          </div>
        </div>
      );
    }

    if (menu === "models") {
      return (
        <div className="max-w-5xl w-full mx-auto p-8 space-y-6">
          <div className="flex justify-between items-center mb-6">
            <h2 className="text-2xl font-bold">大模型与密钥配置</h2>
            <div className="flex gap-2">
              <button className="px-4 py-2 bg-primary hover:bg-blue-500 text-white text-sm font-medium rounded-lg transition-colors flex items-center gap-2 shadow-[0_0_10px_rgba(59,130,246,0.3)]">
                <Save className="w-4 h-4" /> 保存所有配置
              </button>
            </div>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
            {agentModels.length > 0 ? (
              agentModels.map((agent, idx) => (
                <div
                  key={idx}
                  className="bg-card border border-slate-800 rounded-2xl p-6 relative overflow-hidden group hover:border-slate-600 transition-colors"
                >
                  <div
                    className={`absolute top-0 left-0 w-1 h-full ${agent.status === "ready" ? "bg-success" : "bg-warning"}`}
                  ></div>

                  <div className="flex justify-between items-start mb-4">
                    <div>
                      <h3 className="text-lg font-bold flex items-center gap-2">
                        <Cpu className="w-5 h-5 text-primary" /> {agent.role}
                      </h3>
                      <p className="text-sm text-slate-400 mt-1">
                        {agent.type}
                      </p>
                    </div>
                    <div
                      className={`px-2 py-1 rounded text-xs font-bold border ${
                        agent.status === "ready"
                          ? "bg-success/10 text-success border-success/30"
                          : "bg-warning/10 text-warning border-warning/30"
                      }`}
                    >
                      {agent.status === "ready" ? "就绪" : "未配置"}
                    </div>
                  </div>

                  <div className="space-y-4">
                    <div>
                      <label className="block text-xs font-medium text-slate-400 mb-1">
                        选择绑定模型
                      </label>
                      <select
                        value={agent.model}
                        onChange={async (e) => {
                          const newAgents = [...agentModels];
                          newAgents[idx].model = e.target.value;
                          setAgentModels(newAgents);
                          try {
                            const res = await fetch(
                              `${apiBase}/api/agent_models`,
                              {
                                method: "POST",
                                headers: { "Content-Type": "application/json" },
                                body: JSON.stringify(newAgents),
                              },
                            );
                            const data = await res.json();
                            if (!res.ok || !data.success) {
                              setAgentModels(agentModels);
                              showToast(data.error || "模型切换失败", "error");
                              return;
                            }
                            showToast(
                              `已将 ${agent.role} 切换为 ${formatModelLabel(e.target.value)}`,
                              "success",
                            );
                          } catch {
                            setAgentModels(agentModels);
                            showToast("模型切换失败", "error");
                          }
                        }}
                        className="w-full bg-[#0A0E17] border border-slate-700 rounded-lg px-3 py-2 text-slate-200 focus:outline-none focus:border-primary text-sm appearance-none"
                      >
                        <option value={agent.model}>
                          {formatModelLabel(agent.model)} (当前生效)
                        </option>
                        {availableModels
                          .filter((m) => m !== agent.model)
                          .map((m) => (
                            <option key={m} value={m}>
                              {formatModelLabel(m)}
                            </option>
                          ))}
                      </select>
                    </div>

                    <div>
                      <label className="block text-xs font-medium text-slate-400 mb-1">
                        API Key
                      </label>
                      <div className="relative">
                        <Key className="w-4 h-4 absolute left-3 top-1/2 transform -translate-y-1/2 text-slate-500" />
                        <input
                          type="password"
                          defaultValue={
                            agent.api_key_configured
                              ? "********-****-****-********"
                              : ""
                          }
                          placeholder="sk-..."
                          className="w-full bg-[#0A0E17] border border-slate-700 rounded-lg pl-9 pr-4 py-2 text-slate-200 focus:outline-none focus:border-primary text-sm font-mono"
                        />
                      </div>
                    </div>

                    {agent.status === "ready" && (
                      <div className="flex items-center gap-4 text-xs text-slate-400 pt-3 border-t border-slate-800/50">
                        <span className="flex items-center gap-1">
                          <Activity className="w-3 h-3 text-success" /> 延迟:{" "}
                          {agent.latency}
                        </span>
                        <span className="flex items-center gap-1 text-success">
                          验证通过
                        </span>
                      </div>
                    )}
                  </div>
                </div>
              ))
            ) : (
              <div className="col-span-2 py-12 text-center text-slate-500">
                加载模型配置中...
              </div>
            )}
          </div>
        </div>
      );
    }

    if (menu === "webchat") {
      return (
        <div className="h-full flex flex-col bg-background p-6">
          <div className="flex justify-between items-center mb-6 pb-4 border-b border-slate-800">
            <div className="flex items-center space-x-3">
              <div className="w-10 h-10 rounded-xl bg-blue-900/30 flex items-center justify-center border border-blue-500/30">
                <Globe className="w-5 h-5 text-blue-400" />
              </div>
              <div>
                <h2 className="text-xl font-bold text-white flex items-center gap-2">
                  蜂群决策大厅{" "}
                  <span className="text-[10px] bg-blue-500/20 text-blue-400 px-2 py-0.5 rounded border border-blue-500/30">
                    Approval + Blockers
                  </span>
                </h2>
                <p className="text-xs text-slate-400">
                  真实组合审批链结论、运行阻断、待人工审批与黑板消息，不再只显示探明报价
                </p>
              </div>
            </div>
            <div className="flex items-center gap-3">
              <div className="flex items-center gap-2 text-xs text-slate-400 bg-slate-800/50 px-3 py-1.5 rounded-lg border border-slate-700/50">
                <div className="w-2 h-2 rounded-full bg-success animate-pulse"></div>
                黑板状态同步中
              </div>
            </div>
          </div>

          <div className="mb-4 rounded-2xl border border-cyan-900/40 bg-cyan-950/20 px-4 py-3">
            <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
              <div>
                <div className="flex flex-wrap items-center gap-2">
                  <span className="text-sm font-semibold text-cyan-100">
                    统一决策合同
                  </span>
                  <span
                    className={`rounded-full border px-2 py-0.5 text-[10px] uppercase tracking-[0.08em] ${decisionContractHealth.badge}`}
                  >
                    {decisionContractHealth.label}
                  </span>
                </div>
                <div className="mt-1 text-xs text-cyan-100/70">
                  更新时间 {runtimeDecisionContractUpdatedAtLabel || "未知"}
                  ，当前由同一份合同向宏观层、解释层和多策略仲裁下发约束。
                </div>
                {runtimeDecisionContractMissingLineage.length > 0 ? (
                  <div className="mt-1 text-[11px] text-warning">
                    待修复来源字段:{" "}
                    {runtimeDecisionContractMissingLineage.join(", ")}
                  </div>
                ) : null}
              </div>
              <div className="grid grid-cols-1 gap-2 text-xs text-slate-300 sm:grid-cols-3">
                <div className="rounded-xl border border-slate-700/80 bg-slate-950/60 px-3 py-2">
                  <div className="text-[10px] uppercase tracking-[0.08em] text-slate-500">
                    绑定方向
                  </div>
                  <div className="mt-1 font-mono text-slate-100">
                    {activeMacroDirection}
                  </div>
                </div>
                <div className="rounded-xl border border-slate-700/80 bg-slate-950/60 px-3 py-2">
                  <div className="text-[10px] uppercase tracking-[0.08em] text-slate-500">
                    执行建议
                  </div>
                  <div className="mt-1 font-mono text-slate-100">
                    {activeExecutionAdvice}
                  </div>
                </div>
                <div className="rounded-xl border border-slate-700/80 bg-slate-950/60 px-3 py-2">
                  <div className="text-[10px] uppercase tracking-[0.08em] text-slate-500">
                    合同 Profile
                  </div>
                  <div className="mt-1 font-mono text-slate-100">
                    {activeDecisionProfile}
                  </div>
                </div>
              </div>
            </div>
            <div className="mt-3 flex flex-wrap gap-2">
              <span className="rounded-full border border-slate-700 bg-slate-950/70 px-2.5 py-1 text-[10px] text-slate-300">
                Effective:{" "}
                {String(
                  runtimeDecisionContract.effectiveDirection || "NEUTRAL",
                )}
              </span>
              <span className="rounded-full border border-slate-700 bg-slate-950/70 px-2.5 py-1 text-[10px] text-slate-300">
                Allowed: {String(runtimeDecisionContract.allowedSide || "BOTH")}
              </span>
              {decisionContractSources.map((item) => (
                <span
                  key={item.key}
                  className="rounded-full border border-slate-700 bg-slate-950/70 px-2.5 py-1 text-[10px] text-slate-300"
                >
                  {item.label}: {item.value}
                </span>
              ))}
            </div>
          </div>

          <div
            ref={mailboxScrollRef}
            className="flex-1 overflow-y-auto pr-4 custom-scrollbar bg-[#0A0E17]/50 rounded-2xl p-6 border border-slate-800/50 shadow-inner flex flex-col"
          >
            <div className="space-y-4">
              {sortedDecisionHallMessages.length > 0 ? (
                sortedDecisionHallMessages.map((message) => {
                  const isMicroSniper = message.actor === "Micro_Sniper";
                  return (
                    <div
                      key={message.id}
                      className={`flex ${isMicroSniper ? "justify-end" : "justify-start"}`}
                    >
                      <div className="max-w-[88%] min-w-[280px]">
                        <div
                          className={`mb-1 flex items-center gap-2 text-sm font-semibold ${
                            isMicroSniper ? "justify-end" : "justify-start"
                          } ${message.actorTone}`}
                        >
                          <span>{message.actor}</span>
                          <span className="text-[11px] font-mono text-slate-500">
                            {message.timestamp || "实时"}
                          </span>
                        </div>
                        <div
                          className={`rounded-2xl border px-4 py-3 shadow-md ${decisionToneClass(message.tone)}`}
                        >
                          <div className="flex flex-wrap items-center gap-2">
                            <span
                              className={`text-sm font-semibold ${decisionLabelClass(message.tone)}`}
                            >
                              {message.title}
                            </span>
                            <span className="rounded-full border border-slate-700/80 bg-slate-950/60 px-2 py-0.5 text-[10px] uppercase tracking-[0.08em] text-slate-400">
                              {message.source}
                            </span>
                          </div>
                          <div className="mt-2 text-sm leading-6 text-slate-200">
                            {message.body}
                          </div>
                          {message.chips.length > 0 && (
                            <div className="mt-3 flex flex-wrap gap-2">
                              {message.chips.map((chip) => (
                                <span
                                  key={`${message.id}_${chip}`}
                                  className="rounded-full border border-slate-700 bg-slate-950/70 px-2 py-0.5 text-[10px] text-slate-300"
                                >
                                  {chip}
                                </span>
                              ))}
                            </div>
                          )}
                        </div>
                      </div>
                    </div>
                  );
                })
              ) : (
                <div className="rounded-xl border border-dashed border-slate-700 bg-slate-950/40 px-4 py-6 text-sm text-slate-500">
                  当前没有新的审批或运行阻断消息，系统将继续监听真实运行链。
                </div>
              )}
            </div>
          </div>

          <div className="mt-4 pt-4 border-t border-slate-800">
            <div className="bg-blue-900/10 border border-blue-900/30 rounded-xl p-3 flex items-center justify-between">
              <p className="text-xs text-blue-300/70">
                <MessageSquare className="w-3 h-3 inline mr-1 mb-0.5" />
                提示：当前为上帝视角的"只读监听"模式。若需与大模型进行交互式量化分析，请前往
              </p>
              <a
                href="http://127.0.0.1:18789"
                target="_blank"
                rel="noopener noreferrer"
                className="px-4 py-1.5 bg-blue-600/20 hover:bg-blue-600/40 text-blue-400 text-xs font-medium rounded-lg transition-colors border border-blue-500/30"
              >
                打开原生 WebUI 交互
              </a>
            </div>
          </div>
        </div>
      );
    }

    if (menu === "training") {
      return (
        <div className="mx-auto w-full max-w-[1480px] space-y-6 px-4 py-6 sm:px-6 xl:px-8">
          <div className="flex justify-between items-center mb-6">
            <div>
              <h2 className="text-2xl font-bold flex items-center gap-3">
                离线数据训练与模型进化
                {trainingStatus.isTraining && (
                  <span className="text-xs bg-primary/20 text-primary px-2 py-1 rounded border border-primary/30 flex items-center gap-1">
                    <span className="w-1.5 h-1.5 rounded-full bg-primary animate-pulse"></span>
                    训练中
                  </span>
                )}
              </h2>
              <p className="text-sm text-slate-400 mt-1">
                将训练门槛、审批链、生命周期和进化动作收敛到一个真实联动面板里
              </p>
            </div>
            {/* 隐藏离线网格训练按钮，防止过度拟合
            <div className="flex gap-3">
              <button className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-slate-200 text-sm font-medium rounded-lg transition-colors border border-slate-700">
                导入新数据集
              </button>
              <button
                onClick={handleToggleTraining}
                className={`px-4 py-2 ${trainingStatus.isTraining ? "bg-danger/20 text-danger hover:bg-danger/30" : "bg-primary text-white hover:bg-blue-500"} text-sm font-medium rounded-lg transition-colors flex items-center gap-2 shadow-[0_0_10px_rgba(59,130,246,0.3)]`}
              >
                {trainingStatus.isTraining ? (
                  <Square className="w-4 h-4 fill-current" />
                ) : (
                  <Play className="w-4 h-4 fill-current" />
                )}
                {trainingStatus.isTraining ? "中止训练" : "开始微调"}
              </button>
              <button
                onClick={handleApplyBestParams}
                className="px-4 py-2 bg-amber-900 hover:bg-amber-800 text-amber-200 text-sm font-medium rounded-lg transition-colors flex items-center gap-2 border border-amber-700"
              >
                <TrendingUp className="w-4 h-4" /> 应用训练最优
              </button>
            </div>
            */}
          </div>

          <div className="flex flex-col gap-6">
            <div className="space-y-4">
              <div className="grid grid-cols-2 gap-3 lg:grid-cols-4">
                <div className="bg-card border border-slate-800 rounded-2xl p-4">
                  <div className="text-[11px] text-slate-500 mb-1">
                    训练资格
                  </div>
                  <div
                    className={`text-lg font-bold ${trainingStatus.readyForTraining ? "text-success" : "text-danger"}`}
                  >
                    {trainingStatus.readyForTraining ? "READY" : "BLOCKED"}
                  </div>
                  <div className="text-xs text-slate-400 mt-1">
                    closure {trainingStatus.closureCoveragePct.toFixed(1)}%
                  </div>
                </div>
                <div className="bg-card border border-slate-800 rounded-2xl p-4">
                  <div className="text-[11px] text-slate-500 mb-1">
                    关键异常
                  </div>
                  <div
                    className={`text-lg font-bold ${trainingStatus.criticalAnomalies > 0 ? "text-warning" : "text-success"}`}
                  >
                    {trainingStatus.criticalAnomalies}
                  </div>
                  <div className="text-xs text-slate-400 mt-1">
                    待修复 {Number(closureLifecycle.pendingRepairCount || 0)}
                  </div>
                </div>
                <div className="bg-card border border-slate-800 rounded-2xl p-4">
                  <div className="text-[11px] text-slate-500 mb-1">
                    闭环质量
                  </div>
                  <div className="text-lg font-bold text-slate-100">
                    {trainingStatus.naturalClosedTransitions}/
                    {trainingStatus.recoveredClosedTransitions}
                  </div>
                  <div className="text-xs text-slate-400 mt-1">自然 / 补回</div>
                </div>
                <div className="bg-card border border-slate-800 rounded-2xl p-4">
                  <div className="text-[11px] text-slate-500 mb-1">
                    训练收益
                  </div>
                  <div
                    className={`text-lg font-bold ${trainingStatus.pnl > 0 ? "text-success" : trainingStatus.pnl < 0 ? "text-danger" : "text-slate-100"}`}
                  >
                    {trainingStatus.pnl > 0 ? "+" : ""}$
                    {trainingStatus.pnl.toFixed(2)}
                  </div>
                  <div className="text-xs text-slate-400 mt-1">
                    recovered{" "}
                    {trainingStatus.recoveredClosedRatioPct.toFixed(1)}%
                  </div>
                </div>
              </div>

              {showTrainingAdvanced && (
                <div className="rounded-[28px] border border-slate-800 bg-[linear-gradient(135deg,rgba(8,15,30,0.96),rgba(5,9,19,0.98))] p-4 shadow-[0_14px_40px_rgba(2,6,23,0.28)] sm:p-5">
                  <div className="flex flex-col gap-2 md:flex-row md:items-end md:justify-between">
                    <div>
                      <div className="inline-flex items-center gap-2 rounded-full border border-slate-700/80 bg-slate-900/70 px-3 py-1 text-[11px] uppercase tracking-[0.18em] text-slate-400">
                        Runtime Smoke
                      </div>
                      <div className="mt-3 text-lg font-semibold text-slate-100">
                        实盘运行态总线
                      </div>
                      <div className="mt-1 text-sm text-slate-500">
                        不再靠猜模块是否运行，直接看解释器、performance
                        gate、训练门禁和自动治理的真实心跳
                      </div>
                    </div>
                    <div className="rounded-full border border-slate-700 bg-slate-950/80 px-3 py-1 text-[11px] text-slate-300">
                      gateway{" "}
                      {String(runtimeGateway.light || status.light || "RED")} ·
                      price age{" "}
                      {formatAgeLabel(
                        runtimeGateway.priceAgeSec ?? status.priceAge,
                      )}
                    </div>
                  </div>

                  <div className="mt-5 grid grid-cols-1 gap-4 xl:grid-cols-6">
                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <Terminal className="h-3.5 w-3.5" />
                        Gateway
                      </div>
                      <div className="mt-3 flex items-center justify-between gap-3">
                        <div
                          className={`text-base font-semibold ${
                            runtimeGateway.daemonRunning &&
                            runtimeGateway.mt5Online &&
                            runtimeGateway.bridgeOk
                              ? "text-success"
                              : "text-warning"
                          }`}
                        >
                          {runtimeGateway.daemonRunning ? "RUNNING" : "STOPPED"}
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-950/80 px-2.5 py-1 text-[10px] text-slate-300">
                          {String(runtimeGateway.light || "RED")}
                        </span>
                      </div>
                      <div className="mt-3 space-y-1 text-xs text-slate-400">
                        <div>
                          MT5: {String(Boolean(runtimeGateway.mt5Online))}
                        </div>
                        <div>
                          Bridge: {String(Boolean(runtimeGateway.bridgeOk))}
                        </div>
                        <div>
                          Regime: {String(runtimeGateway.regime || "UNKNOWN")}
                        </div>
                        <div>
                          Macro Bias:{" "}
                          {String(runtimeGateway.agentDirection || "NEUTRAL")}
                        </div>
                        <div>Tech Bias: {technicalTrendBias}</div>
                      </div>
                    </div>

                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <Cpu className="h-3.5 w-3.5" />
                        Interpreter
                      </div>
                      <div className="mt-3 flex items-center justify-between gap-3">
                        <div
                          className={`text-base font-semibold ${
                            String(runtimeInterpreter.status || "") === "ACTIVE"
                              ? "text-success"
                              : String(runtimeInterpreter.status || "") ===
                                  "STALE"
                                ? "text-warning"
                                : "text-slate-300"
                          }`}
                        >
                          {String(runtimeInterpreter.status || "MISSING")}
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-950/80 px-2.5 py-1 text-[10px] text-slate-300">
                          age {formatAgeLabel(runtimeInterpreter.ageSec)}
                        </span>
                      </div>
                      <div className="mt-3 space-y-1 text-xs text-slate-400">
                        <div>
                          View: {String(runtimeInterpreter.view || "UNKNOWN")}
                        </div>
                        <div>
                          Structure:{" "}
                          {String(
                            runtimeInterpreter.marketStructure || "UNKNOWN",
                          )}
                        </div>
                        <div>
                          Subtype:{" "}
                          {String(
                            runtimeInterpreter.regimeSubtype ||
                              "STRUCTURE_UNCLEAR",
                          )}
                        </div>
                        <div>
                          Vol/Liq:{" "}
                          {String(
                            runtimeInterpreter.volatilityState || "NORMAL",
                          )}{" "}
                          /{" "}
                          {String(
                            runtimeInterpreter.liquidityState || "NORMAL",
                          )}
                        </div>
                        <div>
                          Bias/Timing:{" "}
                          {String(
                            runtimeInterpreter.continuationBias || "NEUTRAL",
                          )}{" "}
                          /{" "}
                          {String(
                            runtimeInterpreter.entryTimingHint ||
                              "WAIT_CLEAR_SIGNAL",
                          )}
                        </div>
                        <div>
                          Session:{" "}
                          {String(runtimeInterpreter.sessionName || "UNKNOWN")}
                        </div>
                        <div>
                          Advice:{" "}
                          {String(
                            runtimeInterpreter.executionAdvice || "UNKNOWN",
                          )}
                        </div>
                      </div>
                    </div>

                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <TrendingUp className="h-3.5 w-3.5" />
                        Performance Gate
                      </div>
                      <div className="mt-3 flex items-center justify-between gap-3">
                        <div
                          className={`text-base font-semibold ${
                            runtimePerformance.ready
                              ? "text-success"
                              : "text-warning"
                          }`}
                        >
                          {String(runtimePerformance.status || "MISSING")}
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-950/80 px-2.5 py-1 text-[10px] text-slate-300">
                          usable{" "}
                          {String(runtimePerformance.usableTradeCount ?? 0)}
                        </span>
                      </div>
                      <div className="mt-3 space-y-1 text-xs text-slate-400">
                        <div>
                          更新: {String(runtimePerformance.updatedAt || "-")}
                        </div>
                        <div>
                          排除 incomplete:{" "}
                          {String(
                            runtimePerformance.excludedIncompleteCount ?? 0,
                          )}
                        </div>
                        <div>
                          排除 recovered:{" "}
                          {String(
                            runtimePerformance.excludedRecoveredCount ?? 0,
                          )}
                        </div>
                        <div>
                          最小样本:{" "}
                          {String(runtimePerformance.minBucketTrades ?? 0)}
                        </div>
                      </div>
                    </div>

                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <Shield className="h-3.5 w-3.5" />
                        Auto Governance
                      </div>
                      <div className="mt-3 flex items-center justify-between gap-3">
                        <div
                          className={`text-base font-semibold ${
                            runtimeTrainingGate.readyForTraining
                              ? "text-success"
                              : "text-warning"
                          }`}
                        >
                          {String(
                            runtimeAutoGovernance.lastAction ||
                              runtimeAutoGovernance.status ||
                              "NOOP",
                          )}
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-950/80 px-2.5 py-1 text-[10px] text-slate-300">
                          {String(
                            runtimeAutoGovernance.currentMode || "shadow",
                          )}{" "}
                          → {String(runtimeAutoGovernance.nextMode || "next")}
                        </span>
                      </div>
                      <div className="mt-3 space-y-1 text-xs text-slate-400">
                        <div>
                          Decision:{" "}
                          {String(
                            runtimeAutoGovernance.decisionStatus || "UNKNOWN",
                          )}
                        </div>
                        <div>
                          Can promote:{" "}
                          {String(Boolean(runtimeAutoGovernance.canPromote))}
                        </div>
                        <div>
                          Last reason:{" "}
                          {String(
                            runtimeAutoGovernance.lastReason || "steady_state",
                          )}
                        </div>
                        <div>
                          Age: {formatAgeLabel(runtimeAutoGovernance.ageSec)}
                        </div>
                      </div>
                    </div>

                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <AlertTriangle className="h-3.5 w-3.5" />
                        Freeze Reason
                      </div>
                      <div className="mt-3 flex items-center justify-between gap-3">
                        <div
                          className={`text-base font-semibold ${
                            String(
                              runtimeAutoGovernance.lastAction || "NOOP",
                            ).includes("FREEZE") ||
                            String(
                              runtimeAutoGovernance.lastAction || "NOOP",
                            ).includes("BLOCK")
                              ? "text-warning"
                              : "text-success"
                          }`}
                        >
                          {String(runtimeAutoGovernance.lastAction || "NOOP")}
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-950/80 px-2.5 py-1 text-[10px] text-slate-300">
                          {runtimeLatestGoalActionAt
                            ? runtimeLatestGoalActionAt
                            : "no recent freeze"}
                        </span>
                      </div>
                      <div className="mt-3 space-y-1 text-xs text-slate-400">
                        <div className="break-words">
                          {String(
                            runtimeAutoGovernance.lastReason || "steady_state",
                          )}
                        </div>
                        <div className="break-words">
                          {String(
                            runtimeAutoGovernance.goalRecoveryHint ||
                              "月回撤<=10% 且 月自治率>=85% 后自动解除冻结",
                          )}
                        </div>
                      </div>
                    </div>

                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <CheckCircle2 className="h-3.5 w-3.5" />
                        Goal Gates
                      </div>
                      <div className="mt-3 flex items-center justify-between gap-3">
                        <div
                          className={`text-base font-semibold ${
                            runtimeGoalGates.all_passed
                              ? "text-success"
                              : "text-warning"
                          }`}
                        >
                          {runtimeGoalGates.all_passed ? "PASS" : "WATCH"}
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-950/80 px-2.5 py-1 text-[10px] text-slate-300">
                          月闭合单{" "}
                          {String(runtimeGoalMonth.closed_trade_count ?? 0)}
                        </span>
                      </div>
                      <div className="mt-3 space-y-1 text-xs text-slate-400">
                        <div>
                          月回撤:{" "}
                          {Number(
                            runtimeGoalMonth.max_drawdown_pct ?? 0,
                          ).toFixed(2)}
                          %{" / <= "}
                          {Number(runtimeDrawdownGate.threshold ?? 10).toFixed(
                            2,
                          )}
                          %
                        </div>
                        <div>
                          月自治:{" "}
                          {Number(
                            runtimeGoalMonth.autonomy_rate_pct ?? 0,
                          ).toFixed(2)}
                          %{" / >= "}
                          {Number(runtimeAutonomyGate.threshold ?? 85).toFixed(
                            2,
                          )}
                          %
                        </div>
                        <div>
                          快照回撤:{" "}
                          {Number(
                            (
                              runtimeGoalSnapshot.max_drawdown_pct as Record<
                                string,
                                unknown
                              >
                            )?.current ??
                              runtimeGoalMonth.max_drawdown_pct ??
                              0,
                          ).toFixed(2)}
                          %
                        </div>
                        <div>
                          快照自治:{" "}
                          {Number(
                            (
                              runtimeGoalSnapshot.autonomy_rate_pct as Record<
                                string,
                                unknown
                              >
                            )?.current ??
                              runtimeGoalMonth.autonomy_rate_pct ??
                              0,
                          ).toFixed(2)}
                          %
                        </div>
                        <div>
                          人工干预交易日:{" "}
                          {String(
                            runtimeGoalMonth.manual_trade_days_count ?? 0,
                          )}
                        </div>
                        <div>
                          自主交易日:{" "}
                          {String(
                            runtimeGoalMonth.autonomous_trade_days_count ?? 0,
                          )}
                        </div>
                      </div>
                    </div>
                  </div>

                  <div className="mt-4 grid grid-cols-1 gap-4 xl:grid-cols-4">
                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <DatabaseZap className="h-3.5 w-3.5" />
                        Evolution Evidence
                      </div>
                      <div className="mt-3 flex items-center justify-between gap-3">
                        <div
                          className={`text-base font-semibold ${
                            String(
                              runtimeEvidenceVerdict.status ||
                                "INSUFFICIENT_EVIDENCE",
                            ) === "SIGNIFICANT_OUTPERFORM"
                              ? "text-success"
                              : String(
                                    runtimeEvidenceVerdict.status || "",
                                  ).includes("UNDERPERFORM")
                                ? "text-danger"
                                : "text-warning"
                          }`}
                        >
                          {String(
                            runtimeEvidenceVerdict.status ||
                              "INSUFFICIENT_EVIDENCE",
                          )}
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-950/80 px-2.5 py-1 text-[10px] text-slate-300">
                          p-value{" "}
                          {Number(runtimeEvidencePnlTest.p_value ?? 1).toFixed(
                            4,
                          )}
                        </span>
                      </div>
                      <div className="mt-3 space-y-1 text-xs text-slate-400">
                        <div className="break-words">
                          reason:{" "}
                          {String(
                            runtimeEvidenceVerdict.reason ||
                              "sample_not_enough",
                          )}
                        </div>
                        <div>
                          learner avgPnL:{" "}
                          {Number(runtimeEvidenceLearner.avg_pnl ?? 0).toFixed(
                            4,
                          )}{" "}
                          ( n={String(runtimeEvidenceLearner.count ?? 0)})
                        </div>
                        <div>
                          baseline avgPnL:{" "}
                          {Number(runtimeEvidenceBaseline.avg_pnl ?? 0).toFixed(
                            4,
                          )}{" "}
                          (n={String(runtimeEvidenceBaseline.count ?? 0)})
                        </div>
                        <div>
                          z-score:{" "}
                          {Number(runtimeEvidencePnlTest.z_score ?? 0).toFixed(
                            4,
                          )}
                        </div>
                      </div>
                    </div>

                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <Activity className="h-3.5 w-3.5" />
                        Autonomy Loop
                      </div>
                      <div className="mt-3 flex items-center justify-between gap-3">
                        <div
                          className={`text-base font-semibold ${
                            String(
                              runtimeAutonomyLoop.next_action || "",
                            ).includes("PROMOTION")
                              ? "text-success"
                              : String(
                                    runtimeAutonomyLoop.next_action || "",
                                  ).includes("FREEZE")
                                ? "text-warning"
                                : "text-slate-200"
                          }`}
                        >
                          {String(
                            runtimeAutonomyLoop.next_action ||
                              "CONTINUE_COLLECT_EVIDENCE",
                          )}
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-950/80 px-2.5 py-1 text-[10px] text-slate-300">
                          {String(runtimeAutonomyLoop.ts || "-")}
                        </span>
                      </div>
                      <div className="mt-3 space-y-1 text-xs text-slate-400">
                        <div>
                          governance:{" "}
                          {String(
                            runtimeAutonomyLoop.governance_action || "NOOP",
                          )}
                        </div>
                        <div className="break-words">
                          notice:{" "}
                          {String(
                            runtimeAutonomyLoop.notice ||
                              "not_significant_keep_collecting",
                          )}
                        </div>
                        <div>
                          evidence:{" "}
                          {String(
                            (
                              runtimeAutonomyLoop.evolution_verdict as Record<
                                string,
                                unknown
                              >
                            )?.status || "INSUFFICIENT_EVIDENCE",
                          )}
                        </div>
                        <div>
                          goal gates:{" "}
                          {String(
                            (
                              (runtimeAutonomyLoop.goal_gates as Record<
                                string,
                                unknown
                              >) || {}
                            ).all_passed
                              ? "PASS"
                              : "WATCH",
                          )}
                        </div>
                      </div>
                    </div>

                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <Crosshair className="h-3.5 w-3.5" />
                        Session Risk Lens
                      </div>
                      <div className="mt-3 space-y-3 text-xs text-slate-400">
                        <div className="rounded-xl border border-slate-800 bg-slate-950/60 p-3">
                          <div className="flex items-center justify-between gap-2">
                            <div className="text-[11px] uppercase tracking-[0.08em] text-slate-500">
                              ASIA_LONDON_OVERLAP
                            </div>
                            <span
                              className={`inline-flex items-center gap-1 rounded-full border border-slate-700 px-2 py-0.5 text-[10px] ${asiaLondonTone.text}`}
                            >
                              <span
                                className={`h-1.5 w-1.5 rounded-full ${asiaLondonTone.dot}`}
                              />
                              {asiaLondonTone.label}
                            </span>
                          </div>
                          <div className="mt-1">
                            action{" "}
                            {String(runtimeAsiaLondonRule.action || "neutral")}{" "}
                            · limit_only{" "}
                            {String(Boolean(runtimeAsiaLondonRule.limit_only))}
                          </div>
                          <div>
                            size{" "}
                            {Number(
                              runtimeAsiaLondonRule.size_multiplier ?? 1,
                            ).toFixed(2)}{" "}
                            · conf{" "}
                            {Number(
                              runtimeAsiaLondonRule.confidence_delta ?? 0,
                            ).toFixed(2)}
                          </div>
                          <div className="break-words">
                            reason:{" "}
                            {String(runtimeAsiaLondonRule.reason || "-")}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-slate-950/60 p-3">
                          <div className="flex items-center justify-between gap-2">
                            <div className="text-[11px] uppercase tracking-[0.08em] text-slate-500">
                              LONDON_NY_OVERLAP
                            </div>
                            <span
                              className={`inline-flex items-center gap-1 rounded-full border border-slate-700 px-2 py-0.5 text-[10px] ${londonNyTone.text}`}
                            >
                              <span
                                className={`h-1.5 w-1.5 rounded-full ${londonNyTone.dot}`}
                              />
                              {londonNyTone.label}
                            </span>
                          </div>
                          <div className="mt-1">
                            action{" "}
                            {String(runtimeLondonNyRule.action || "neutral")} ·
                            limit_only{" "}
                            {String(Boolean(runtimeLondonNyRule.limit_only))}
                          </div>
                          <div>
                            size{" "}
                            {Number(
                              runtimeLondonNyRule.size_multiplier ?? 1,
                            ).toFixed(2)}{" "}
                            · conf{" "}
                            {Number(
                              runtimeLondonNyRule.confidence_delta ?? 0,
                            ).toFixed(2)}
                          </div>
                          <div className="break-words">
                            reason: {String(runtimeLondonNyRule.reason || "-")}
                          </div>
                        </div>
                      </div>
                    </div>

                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <TrendingUp className="h-3.5 w-3.5" />
                        Direction Quality
                      </div>
                      <div className="mt-3 flex items-center justify-between gap-3">
                        <div className="text-base font-semibold text-slate-100">
                          {Number(
                            runtimeDirectionQuality.alignedHitRatePct ?? 0,
                          ).toFixed(1)}
                          %
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-950/80 px-2.5 py-1 text-[10px] text-slate-300">
                          sample{" "}
                          {String(runtimeDirectionQuality.sampleCount ?? 0)}
                        </span>
                      </div>
                      <div className="mt-3 space-y-1 text-xs text-slate-400">
                        <div>
                          同向命中:{" "}
                          {Number(
                            runtimeDirectionQuality.alignedHitRatePct ?? 0,
                          ).toFixed(1)}
                          %
                        </div>
                        <div>
                          逆向命中:{" "}
                          {Number(
                            runtimeDirectionQuality.counterHitRatePct ?? 0,
                          ).toFixed(1)}
                          %
                        </div>
                        <div>
                          方向收益差:{" "}
                          {Number(
                            runtimeDirectionQuality.directionEdgePnl ?? 0,
                          ).toFixed(3)}
                        </div>
                        <div>
                          逆向在震荡占比:{" "}
                          {Number(
                            runtimeDirectionQuality.counterInRangePct ?? 0,
                          ).toFixed(1)}
                          %
                        </div>
                        <div>
                          连亏计数:{" "}
                          {String(
                            runtimeDirectionQuality.consecutiveLosses ?? 0,
                          )}
                        </div>
                        <div className="flex items-center gap-2">
                          <span>Macro Bias:</span>
                          <span className="rounded-full border border-slate-700 px-2 py-0.5 text-[10px] text-slate-200">
                            {String(runtimeGateway.agentDirection || "NEUTRAL")}
                          </span>
                          <span className="text-slate-500">
                            {String(
                              runtimeMacroDirectionData.phase || "UNKNOWN",
                            )}{" "}
                            · p=
                            {Number(
                              runtimeMacroDirectionData.probability ?? 0.5,
                            ).toFixed(2)}
                          </span>
                        </div>
                        <div className="flex items-center gap-2">
                          <span>Technical Trend Bias:</span>
                          <span
                            className={`rounded-full border px-2 py-0.5 text-[10px] ${technicalTrendTone.badge}`}
                          >
                            {technicalTrendTone.label}
                          </span>
                          <span className="text-slate-500">
                            {String(
                              runtimeTechnicalTrendData.phase || "UNKNOWN",
                            )}{" "}
                            · raw=
                            {Number(
                              runtimeTechnicalTrendData.raw_score ?? 0,
                            ).toFixed(2)}{" "}
                            · ADX=
                            {Number(runtimeTechnicalTrendData.adx ?? 0).toFixed(
                              1,
                            )}
                          </span>
                        </div>
                        <div>
                          Session Risk Lens:
                          下方重叠时段卡片展示的是历史会话偏好，不等于当前技术趋势
                        </div>
                        <div>
                          HOLD streak:{" "}
                          {String(runtimeMacroPolling.holdStreak ?? 0)} · 持续{" "}
                          {String(runtimeMacroPolling.holdDurationSec ?? 0)}s
                        </div>
                        <div>
                          宏观轮询:{" "}
                          {Number(
                            runtimeMacroPolling.lastMacroPollAgoSec ?? -1,
                          ) >= 0
                            ? `${String(runtimeMacroPolling.lastMacroPollAgoSec)}s ago`
                            : "not yet"}
                        </div>
                        <div>
                          置信校准:{" "}
                          {runtimeConfidenceCalibration.ready
                            ? `${Number(runtimeConfidenceCalibration.raw ?? 0).toFixed(3)} -> ${Number(runtimeConfidenceCalibration.calibrated ?? 0).toFixed(3)}`
                            : "warming_up"}{" "}
                          (n=
                          {String(
                            runtimeConfidenceCalibration.sample_count ?? 0,
                          )}
                          )
                        </div>
                        <div>
                          Trailing basis/ATR:{" "}
                          {Number(
                            runtimeTrailingTelemetry.trail_basis ?? 0,
                          ).toFixed(2)}{" "}
                          /{" "}
                          {Number(
                            runtimeTrailingTelemetry.trail_dist_atr ?? 0,
                          ).toFixed(2)}
                        </div>
                        <div className="flex items-center gap-2">
                          <span>机会状态:</span>
                          <span
                            className={`rounded-full border px-2 py-0.5 text-[10px] ${trailingStateTone.badge}`}
                          >
                            {trailingStateTone.label}
                          </span>
                        </div>
                        <div>
                          峰值利润保留:{" "}
                          {Number(
                            runtimeTrailingTelemetry.profit_capture_ratio ?? 0,
                          ).toFixed(2)}{" "}
                          · 回吐{" "}
                          {Number(
                            runtimeTrailingTelemetry.profit_giveback_atr ?? 0,
                          ).toFixed(2)}
                          ATR
                        </div>
                        <div>
                          波段完成度:{" "}
                          {Number(
                            runtimeTrailingTelemetry.wave_completion ?? 0,
                          ).toFixed(2)}{" "}
                          · 峰值 完成{" "}
                          {Number(
                            runtimeTrailingTelemetry.peak_completion ?? 0,
                          ).toFixed(2)}
                        </div>
                        <div>
                          预期波段/峰值后:{" "}
                          {Number(
                            runtimeTrailingTelemetry.expected_wave_atr ?? 0,
                          ).toFixed(2)}
                          ATR ·{" "}
                          {String(
                            runtimeTrailingTelemetry.bars_since_peak ?? 0,
                          )}{" "}
                          bars
                        </div>
                        <div>
                          动能衰减分数:{" "}
                          {Number(
                            runtimeTrailingTelemetry.momentum_decay_score ?? 0,
                          ).toFixed(2)}
                        </div>
                        <div>
                          SL步长拦截累计:{" "}
                          {String(
                            runtimeTrailingTelemetry.sl_move_step_blocked_count ??
                              0,
                          )}
                        </div>
                      </div>
                    </div>
                  </div>

                  <div className="mt-4 grid grid-cols-1 gap-4 xl:grid-cols-3">
                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4 xl:col-span-2">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <Activity className="h-3.5 w-3.5" />
                        训练门禁与阻断
                      </div>
                      <div className="mt-3 grid grid-cols-2 gap-3 md:grid-cols-4">
                        <div className="rounded-xl border border-slate-800 bg-slate-950/60 p-3">
                          <div className="text-[11px] text-slate-500">
                            训练资格
                          </div>
                          <div
                            className={`mt-1 text-sm font-semibold ${
                              runtimeTrainingGate.readyForTraining
                                ? "text-success"
                                : "text-warning"
                            }`}
                          >
                            {String(runtimeTrainingGate.status || "BLOCKED")}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-slate-950/60 p-3">
                          <div className="text-[11px] text-slate-500">
                            闭环覆盖率
                          </div>
                          <div className="mt-1 text-sm font-semibold text-slate-100">
                            {Number(
                              runtimeTrainingGate.closureCoveragePct || 0,
                            ).toFixed(1)}
                            %
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-slate-950/60 p-3">
                          <div className="text-[11px] text-slate-500">
                            关键异常
                          </div>
                          <div className="mt-1 text-sm font-semibold text-warning">
                            {String(runtimeTrainingGate.criticalAnomalies ?? 0)}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-slate-950/60 p-3">
                          <div className="text-[11px] text-slate-500">
                            待修复闭环
                          </div>
                          <div className="mt-1 text-sm font-semibold text-slate-100">
                            {String(
                              runtimeTrainingGate.pendingRepairCount ?? 0,
                            )}
                          </div>
                        </div>
                      </div>
                      <div className="mt-3 rounded-xl border border-slate-800 bg-slate-950/60 p-3 text-sm text-slate-300">
                        {Array.isArray(runtimeTrainingGate.blockedReasons) &&
                        runtimeTrainingGate.blockedReasons.length > 0
                          ? runtimeTrainingGate.blockedReasons.join("，")
                          : "当前没有训练阻断项"}
                      </div>
                    </div>

                    <div className="rounded-[22px] border border-slate-800 bg-[#0A0E17] p-4">
                      <div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.14em] text-slate-400">
                        <Search className="h-3.5 w-3.5" />
                        Performance Top Buckets
                      </div>
                      <div className="mt-3 space-y-2 text-xs">
                        {[
                          { label: "Session", rows: runtimeTopSessions },
                          { label: "Regime", rows: runtimeTopRegimes },
                          { label: "Strategy", rows: runtimeTopStrategies },
                          {
                            label: "Interpreter",
                            rows: runtimeTopInterpreters,
                          },
                        ].map((bucket) => (
                          <div
                            key={bucket.label}
                            className="rounded-xl border border-slate-800 bg-slate-950/60 p-3"
                          >
                            <div className="text-slate-500">{bucket.label}</div>
                            <div className="mt-1 text-slate-300 break-words">
                              {bucket.rows.length > 0
                                ? `${String(bucket.rows[0]?.name || "-")} · ${String(bucket.rows[0]?.trades || 0)} trades · WR ${Number(bucket.rows[0]?.winRatePct || 0).toFixed(1)}%`
                                : "暂无有效样本"}
                            </div>
                          </div>
                        ))}
                      </div>
                    </div>
                  </div>
                </div>
              )}

              <div className="rounded-[28px] border border-slate-800 bg-[linear-gradient(135deg,rgba(15,23,42,0.92),rgba(9,14,31,0.96))] p-4 shadow-[0_14px_40px_rgba(2,6,23,0.32)] sm:p-5">
                <div className="flex flex-wrap items-center justify-between gap-3">
                  <div>
                    <div className="inline-flex items-center gap-2 rounded-full border border-slate-700/80 bg-slate-900/70 px-3 py-1 text-[11px] uppercase tracking-[0.18em] text-slate-400">
                      Review Center
                    </div>
                    <div className="mt-3 text-lg font-semibold text-slate-100">
                      进化审核中心
                    </div>
                    <div className="mt-1 text-sm text-slate-500">
                      报告、审批、回滚放在同一块，默认显示，不再让你自己一步步找。
                    </div>
                    <div className="mt-2 text-[11px] text-slate-500">
                      数据源: {trainingMetricsSource}
                      {trainingMetricsUpdatedAt
                        ? ` · 更新于 ${trainingMetricsUpdatedAt}`
                        : ""}
                    </div>
                  </div>
                  <button
                    onClick={() => setShowTrainingAdvanced((prev) => !prev)}
                    className="rounded-lg border border-slate-700 bg-slate-900/70 px-3 py-1.5 text-xs text-slate-300 transition-colors hover:border-slate-500"
                  >
                    {showTrainingAdvanced ? "收起技术细节" : "展开技术细节"}
                  </button>
                </div>

                <div className="mt-4 grid grid-cols-1 gap-4 xl:grid-cols-12 xl:items-start">
                  <div className="xl:col-span-7">
                    <div className="rounded-[24px] border border-slate-800/90 bg-[linear-gradient(180deg,rgba(11,17,32,0.98),rgba(7,12,24,0.96))] p-5 shadow-[0_10px_30px_rgba(2,6,23,0.22)]">
                      <div className="flex flex-wrap items-center justify-between gap-2">
                        <div>
                          <div className="text-[11px] uppercase tracking-[0.14em] text-slate-500">
                            分析报告
                          </div>
                          <div className="mt-1 text-sm leading-6 text-slate-400">
                            Agent
                            自动筛选训练证据，只把真正值得上实盘的候选推到你面前。
                          </div>
                        </div>
                        <button
                          onClick={handleRegenerateGovernanceAnalysis}
                          disabled={trainingActionBusy}
                          className="rounded-xl border border-primary/25 bg-primary/10 px-3 py-2 text-xs font-medium text-primary transition-colors hover:bg-primary/20 disabled:opacity-50"
                        >
                          重新生成分析报告
                        </button>
                      </div>
                      <div className="mt-4 rounded-[20px] border border-slate-800/90 bg-slate-950/70 p-4">
                        <div className="mb-3 flex items-center justify-between gap-3">
                          <div className="text-[11px] uppercase tracking-[0.12em] text-slate-500">
                            报告正文
                          </div>
                          <button
                            onClick={() =>
                              setShowAuditSummaryExpanded((prev) => !prev)
                            }
                            className="rounded-full border border-slate-700 bg-slate-900/80 px-2.5 py-1 text-[10px] text-slate-300 transition-colors hover:border-slate-500"
                          >
                            {showAuditSummaryExpanded ? "收起全文" : "展开全文"}
                          </button>
                        </div>
                        <div
                          className={`overflow-y-auto pr-1 whitespace-pre-wrap text-sm leading-7 text-slate-200 ${
                            showAuditSummaryExpanded
                              ? "max-h-[360px]"
                              : "max-h-[168px]"
                          }`}
                        >
                          {auditSummaryText}
                        </div>
                        {!showAuditSummaryExpanded && (
                          <div className="mt-3 text-[11px] text-slate-500">
                            默认折叠显示，滚动可预览更多内容；需要时再展开全文。
                          </div>
                        )}
                      </div>
                      <div className="mt-4 grid grid-cols-2 gap-3 lg:grid-cols-4">
                        <div className="rounded-[18px] border border-slate-800/90 bg-slate-950/60 p-3">
                          <div className="text-[11px] uppercase tracking-[0.12em] text-slate-500">
                            样本
                          </div>
                          <div className="mt-2 text-lg font-semibold text-slate-100">
                            {quickSampleCount}
                          </div>
                          {quickSampleThreshold > 0 && (
                            <div className="mt-1 text-[10px] text-slate-500">
                              门槛 {quickSampleThreshold}
                            </div>
                          )}
                        </div>
                        <div className="rounded-[18px] border border-slate-800/90 bg-slate-950/60 p-3">
                          <div className="text-[11px] uppercase tracking-[0.12em] text-slate-500">
                            胜率
                          </div>
                          <div className="mt-2 text-lg font-semibold text-slate-100">
                            {quickWinRate.toFixed(1)}%
                          </div>
                        </div>
                        <div className="rounded-[18px] border border-slate-800/90 bg-slate-950/60 p-3">
                          <div className="text-[11px] uppercase tracking-[0.12em] text-slate-500">
                            回撤
                          </div>
                          <div className="mt-2 text-lg font-semibold text-slate-100">
                            {quickDrawdown.toFixed(1)}
                          </div>
                        </div>
                        <div className="rounded-[18px] border border-slate-800/90 bg-slate-950/60 p-3">
                          <div className="text-[11px] uppercase tracking-[0.12em] text-slate-500">
                            当前阶段
                          </div>
                          <div className="mt-2 text-sm font-semibold text-slate-100">
                            {String(approvalChain.stage || "NO_SUGGESTION")}
                          </div>
                        </div>
                      </div>
                      <div className="mt-4 rounded-[18px] border border-slate-800/90 bg-slate-950/50 p-3">
                        <div className="mb-2 flex items-center justify-between gap-2">
                          <div className="text-[11px] uppercase tracking-[0.12em] text-slate-500">
                            训练结果数据流
                          </div>
                          <div className="text-[10px] text-slate-500">
                            训练 / 影子 / 复核 / 推进
                          </div>
                        </div>
                        <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
                          {flowItems.map((item) => (
                            <div
                              key={item.id}
                              className={`rounded-xl border px-3 py-2 ${
                                item.status === "done"
                                  ? "border-success/25 bg-success/10 text-success"
                                  : item.status === "active"
                                    ? "border-primary/25 bg-primary/10 text-primary"
                                    : "border-slate-800 bg-slate-950/60 text-slate-400"
                              }`}
                            >
                              <div className="text-[11px]">{item.label}</div>
                              <div className="mt-1 text-xs font-semibold">
                                {item.hint}
                              </div>
                            </div>
                          ))}
                        </div>
                      </div>
                      {hasTrainingErrorDispatch && (
                        <div className="mt-4 rounded-[18px] border border-slate-800/90 bg-slate-950/50 p-3">
                          <div className="flex flex-wrap items-center justify-between gap-2">
                            <div className="text-[11px] uppercase tracking-[0.12em] text-slate-500">
                              OpenClaw 错误派发
                            </div>
                            <span
                              className={`rounded-full border px-2.5 py-1 text-[10px] font-medium ${trainingErrorToneClass}`}
                            >
                              {trainingErrorStatus || "waiting"}
                            </span>
                          </div>
                          <div className="mt-3 text-sm leading-6 text-slate-200">
                            {trainingErrorMessage ||
                              "训练错误已进入 OpenClaw 处理链。"}
                          </div>
                          <div className="mt-3 grid grid-cols-1 gap-2 text-xs text-slate-400 sm:grid-cols-2">
                            <div className="rounded-xl border border-slate-800 bg-slate-950/60 px-3 py-2">
                              <div className="text-[10px] uppercase tracking-[0.12em] text-slate-500">
                                continue mode
                              </div>
                              <div className="mt-1 font-mono text-slate-200">
                                {trainingErrorContinueMode || "-"}
                              </div>
                            </div>
                            <div className="rounded-xl border border-slate-800 bg-slate-950/60 px-3 py-2">
                              <div className="text-[10px] uppercase tracking-[0.12em] text-slate-500">
                                fingerprint
                              </div>
                              <div className="mt-1 font-mono text-slate-200">
                                {trainingErrorFingerprint || "-"}
                              </div>
                            </div>
                            <div className="rounded-xl border border-slate-800 bg-slate-950/60 px-3 py-2">
                              <div className="text-[10px] uppercase tracking-[0.12em] text-slate-500">
                                has value
                              </div>
                              <div className="mt-1 font-semibold text-slate-200">
                                {trainingErrorHasValue ? "YES" : "NO"}
                              </div>
                            </div>
                            <div className="rounded-xl border border-slate-800 bg-slate-950/60 px-3 py-2">
                              <div className="text-[10px] uppercase tracking-[0.12em] text-slate-500">
                                ready for review
                              </div>
                              <div className="mt-1 font-semibold text-slate-200">
                                {trainingErrorReadyForReview ? "YES" : "NO"}
                              </div>
                            </div>
                          </div>
                          {trainingErrorBlockedReasons.length > 0 && (
                            <div className="mt-3 flex flex-wrap gap-2">
                              {trainingErrorBlockedReasons.map((reason) => (
                                <span
                                  key={reason}
                                  className="rounded-full border border-danger/30 bg-danger/10 px-2.5 py-1 text-[11px] text-danger"
                                >
                                  {reason}
                                </span>
                              ))}
                            </div>
                          )}
                          {(trainingErrorActions.length > 0 ||
                            trainingErrorExecutedActions.length > 0) && (
                            <div className="mt-3 grid grid-cols-1 gap-2 text-xs text-slate-400 sm:grid-cols-2">
                              <div className="rounded-xl border border-slate-800 bg-slate-950/60 px-3 py-2">
                                <div className="text-[10px] uppercase tracking-[0.12em] text-slate-500">
                                  OpenClaw 动作
                                </div>
                                <div className="mt-2 flex flex-wrap gap-1.5">
                                  {trainingErrorActions.length > 0 ? (
                                    trainingErrorActions.map((action) => (
                                      <span
                                        key={action}
                                        className="rounded-full border border-primary/25 bg-primary/10 px-2 py-0.5 text-[11px] text-primary"
                                      >
                                        {humanizeDispatchAction(action)}
                                      </span>
                                    ))
                                  ) : (
                                    <span className="text-slate-500">-</span>
                                  )}
                                </div>
                              </div>
                              <div className="rounded-xl border border-slate-800 bg-slate-950/60 px-3 py-2">
                                <div className="text-[10px] uppercase tracking-[0.12em] text-slate-500">
                                  已执行动作
                                </div>
                                <div className="mt-2 flex flex-wrap gap-1.5">
                                  {trainingErrorExecutedActions.length > 0 ? (
                                    trainingErrorExecutedActions.map(
                                      (action) => (
                                        <span
                                          key={action}
                                          className="rounded-full border border-success/25 bg-success/10 px-2 py-0.5 text-[11px] text-success"
                                        >
                                          {humanizeDispatchAction(action)}
                                        </span>
                                      ),
                                    )
                                  ) : (
                                    <span className="text-slate-500">-</span>
                                  )}
                                </div>
                              </div>
                            </div>
                          )}
                          <div
                            className={`mt-3 rounded-xl border px-3 py-2 text-xs ${
                              trainingErrorDeliveryOk
                                ? "border-success/25 bg-success/10 text-success"
                                : "border-warning/25 bg-warning/10 text-warning"
                            }`}
                          >
                            {trainingErrorDeliveryOk
                              ? `已写入 OpenClaw 会话 ${trainingErrorSessionKey || "-"} · 消息ID ${trainingErrorMessageId || "-"}`
                              : "尚未确认写入 OpenClaw 可见会话"}
                          </div>
                          {trainingErrorReplyRecommendedJson && (
                            <div className="mt-3 rounded-xl border border-slate-800 bg-slate-950/60 px-3 py-3">
                              <div className="flex flex-wrap items-center justify-between gap-2">
                                <div className="text-[10px] uppercase tracking-[0.12em] text-slate-500">
                                  OpenClaw 标准回复模板
                                </div>
                                <button
                                  type="button"
                                  onClick={handleCopyTrainingErrorReplyTemplate}
                                  className="rounded-full border border-primary/25 bg-primary/10 px-3 py-1 text-[11px] font-medium text-primary transition hover:border-primary/40 hover:bg-primary/15"
                                >
                                  复制 JSON
                                </button>
                              </div>
                              <div className="mt-2 flex flex-wrap gap-1.5 text-[11px]">
                                {trainingErrorReplyStatusOptions.map(
                                  (option) => (
                                    <span
                                      key={`status-${option}`}
                                      className="rounded-full border border-slate-700 bg-slate-900/70 px-2 py-0.5 text-slate-300"
                                    >
                                      status: {option}
                                    </span>
                                  ),
                                )}
                                {trainingErrorReplyContinueModeOptions.map(
                                  (option) => (
                                    <span
                                      key={`mode-${option}`}
                                      className="rounded-full border border-slate-700 bg-slate-900/70 px-2 py-0.5 text-slate-300"
                                    >
                                      mode: {option}
                                    </span>
                                  ),
                                )}
                              </div>
                              <pre className="mt-3 overflow-x-auto rounded-xl border border-slate-800 bg-slate-950/90 px-3 py-3 text-[11px] leading-5 text-slate-200">
                                <code>{trainingErrorReplyRecommendedJson}</code>
                              </pre>
                            </div>
                          )}
                          {(trainingErrorTicketId ||
                            trainingErrorUpdatedAt) && (
                            <div className="mt-2 text-[11px] text-slate-500">
                              {trainingErrorTicketId
                                ? `ticket ${trainingErrorTicketId}`
                                : ""}
                              {trainingErrorTicketId && trainingErrorUpdatedAt
                                ? " · "
                                : ""}
                              {trainingErrorUpdatedAt
                                ? `updated ${trainingErrorUpdatedAt}`
                                : ""}
                            </div>
                          )}
                        </div>
                      )}
                    </div>
                  </div>

                  <div className="xl:col-span-5">
                    <div className="rounded-[24px] border border-slate-800/90 bg-[linear-gradient(180deg,rgba(11,17,32,0.98),rgba(7,12,24,0.96))] p-5 shadow-[0_10px_30px_rgba(2,6,23,0.22)]">
                      <div className="flex items-center justify-between gap-3">
                        <div className="text-[11px] uppercase tracking-[0.14em] text-slate-500">
                          审批结论与回滚
                        </div>
                        <span className="rounded-full border border-slate-700 bg-slate-900/80 px-2.5 py-1 text-[10px] text-slate-300">
                          系统建议
                        </span>
                      </div>
                      <div className="mt-3 text-base font-semibold text-slate-100">
                        {approvalVerdict}
                      </div>
                      <div className="mt-2 text-sm leading-6 text-slate-400">
                        {String(
                          approvalDecision.nextStep ||
                            "系统建议会根据训练门槛和审批链自动刷新。",
                        )}
                      </div>
                      <div
                        className={`mt-3 rounded-lg border px-3 py-2 text-xs ${
                          trainingStatus.readyForTraining
                            ? "border-success/25 bg-success/10 text-success"
                            : "border-warning/25 bg-warning/10 text-warning"
                        }`}
                      >
                        {readinessLabel} · {readinessReason}
                      </div>
                      <div className="mt-3 flex flex-wrap gap-2">
                        {approvalRecommendedActions.length > 0 ? (
                          approvalRecommendedActions
                            .slice(0, 3)
                            .map((action) => (
                              <span
                                key={action}
                                className="rounded-full border border-success/25 bg-success/10 px-2.5 py-1 text-[11px] text-success"
                              >
                                {humanizeTrainingAction(action)}
                              </span>
                            ))
                        ) : (
                          <span className="rounded-full border border-slate-700 bg-slate-900/70 px-2 py-1 text-[11px] text-slate-400">
                            继续训练并观察
                          </span>
                        )}
                      </div>
                      <div className="mt-4 border-t border-slate-800/80 pt-4">
                        <div className="flex items-center justify-between gap-2">
                          <div className="text-[11px] uppercase tracking-[0.14em] text-slate-500">
                            风险与回滚
                          </div>
                          <span
                            className={`rounded-full border px-2 py-1 text-[10px] ${
                              rollbackAvailable
                                ? "border-red-500/30 bg-red-500/10 text-red-100"
                                : "border-slate-700 bg-slate-900/70 text-slate-400"
                            }`}
                          >
                            {rollbackAvailable ? "可回滚" : "暂无回滚点"}
                          </span>
                        </div>
                        <div className="mt-3 rounded-[18px] border border-slate-800/90 bg-slate-950/60 p-3 text-sm leading-6 text-slate-300">
                          {rollbackHintText}
                        </div>
                        <div className="mt-3 text-xs leading-5 text-slate-500">
                          {trainingRefreshHint}
                        </div>
                      </div>
                    </div>
                  </div>

                  <div className="xl:col-span-12">
                    <div className="rounded-[24px] border border-slate-800/90 bg-[linear-gradient(180deg,rgba(11,17,32,0.98),rgba(7,12,24,0.96))] p-5 shadow-[0_10px_30px_rgba(2,6,23,0.22)]">
                      <div className="flex flex-wrap items-center justify-between gap-3">
                        <div>
                          <div className="text-[11px] uppercase tracking-[0.14em] text-slate-500">
                            审批动作
                          </div>
                          <div className="mt-1 text-sm leading-6 text-slate-400">
                            下面按固定顺序执行人工审批，系统自动生成的分析与维护动作已移到技术细节区。
                          </div>
                        </div>
                        <span className="rounded-full border border-amber-500/20 bg-amber-500/10 px-2.5 py-1 text-[10px] text-amber-100">
                          人工闸门
                        </span>
                      </div>
                      <div className="mt-3 rounded-[18px] border border-amber-500/20 bg-amber-500/5 px-3 py-2 text-[11px] leading-5 text-amber-100">
                        {trainingActionHint}
                      </div>
                      {hasVisibleManualReviewAction ? (
                        <div className="mt-4 grid grid-cols-1 gap-3 xl:grid-cols-4">
                          <div className="h-full min-h-[116px] rounded-[18px] border border-primary/20 bg-primary/8 px-4 py-3 text-left text-sm text-primary">
                            <div className="flex h-full items-start gap-3">
                              <div className="mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full border border-current/20 bg-black/20 text-[11px] font-semibold">
                                01
                              </div>
                              <div className="min-w-0 flex-1">
                                <div className="flex flex-wrap items-center gap-2">
                                  <div className="font-semibold">
                                    自动修复阻断并补跑建议
                                  </div>
                                  <span className="rounded-full border border-current/20 bg-black/15 px-2 py-0.5 text-[10px]">
                                    自动执行
                                  </span>
                                </div>
                                <div className="mt-2 text-[11px] opacity-80">
                                  {autoRepairStatusText}
                                </div>
                              </div>
                            </div>
                          </div>

                          <div className="h-full min-h-[116px] rounded-[18px] border border-sky-500/20 bg-sky-900/8 px-4 py-3 text-left text-sm text-sky-300">
                            <div className="flex h-full items-start gap-3">
                              <div className="mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full border border-sky-400/20 bg-sky-950/50 text-[11px] font-semibold text-sky-200">
                                02
                              </div>
                              <div className="min-w-0 flex-1">
                                <div className="flex flex-wrap items-center gap-2">
                                  <div className="font-semibold">
                                    自动进入观察态
                                  </div>
                                  <span className="rounded-full border border-sky-400/20 bg-sky-950/30 px-2 py-0.5 text-[10px]">
                                    自动执行
                                  </span>
                                </div>
                                <div className="mt-2 text-[11px] text-sky-300/70">
                                  {autoApproveStatusText}
                                </div>
                              </div>
                            </div>
                          </div>

                          <button
                            onClick={handleCompleteTrainingReview}
                            disabled={
                              trainingActionBusy ||
                              !(hasSuggestion || trainingReviewPending) ||
                              !canCompleteTrainingReview
                            }
                            className="h-full min-h-[116px] rounded-[18px] border border-emerald-600/25 bg-emerald-900/10 px-4 py-3 text-left text-sm text-emerald-300 transition-colors hover:bg-emerald-800/20 disabled:cursor-not-allowed disabled:opacity-45"
                          >
                            <div className="flex h-full items-start gap-3">
                              <div className="mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full border border-emerald-400/20 bg-emerald-950/50 text-[11px] font-semibold text-emerald-200">
                                03
                              </div>
                              <div className="min-w-0 flex-1">
                                <div className="font-semibold">
                                  {actionLoading === "training:review"
                                    ? "复核中..."
                                    : "完成人工复核"}
                                </div>
                                <div className="mt-2 text-[11px] text-emerald-300/70">
                                  {!(hasSuggestion || trainingReviewPending)
                                    ? "当前还没有进入人工复核链路"
                                    : canCompleteTrainingReview
                                      ? "结束本轮人工审核并推进到下一状态"
                                      : "当前未进入待复核阶段，按钮保留但暂不可执行"}
                                </div>
                              </div>
                            </div>
                          </button>

                          <button
                            onClick={handleRollbackTrainingReview}
                            disabled={
                              trainingActionBusy ||
                              !(hasSuggestion || rollbackAvailable) ||
                              !canRollbackTraining
                            }
                            className="h-full min-h-[116px] rounded-[18px] border border-red-500/30 bg-red-500/10 px-4 py-3 text-left text-sm text-red-100 transition-colors hover:bg-red-500/15 disabled:cursor-not-allowed disabled:opacity-45"
                          >
                            <div className="flex h-full items-start gap-3">
                              <div className="mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full border border-red-300/20 bg-red-950/40 text-[11px] font-semibold text-red-100">
                                04
                              </div>
                              <div className="min-w-0 flex-1">
                                <div className="font-semibold">
                                  {actionLoading === "training:rollback"
                                    ? "回滚中..."
                                    : "回滚到上一稳定参数"}
                                </div>
                                <div className="mt-2 text-[11px] text-red-100/70">
                                  {!(hasSuggestion || rollbackAvailable)
                                    ? "当前还没有进入可回滚的应用阶段"
                                    : canRollbackTraining
                                      ? "触发撤回时，恢复上一版稳定 effective 参数"
                                      : "当前还没有稳定快照，暂时无法执行回滚"}
                                </div>
                              </div>
                            </div>
                          </button>
                        </div>
                      ) : (
                        <div className="mt-4 rounded-[18px] border border-slate-800/90 bg-slate-950/60 px-4 py-3 text-sm text-slate-400">
                          当前无需人工操作，系统会继续自动观察训练结果和审批状态。
                        </div>
                      )}
                    </div>
                  </div>
                </div>

                {showTrainingAdvanced && (
                  <div className="mt-4 rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                    <div className="mb-3 text-xs uppercase tracking-[0.14em] text-slate-500">
                      高级维护动作
                    </div>
                    <div className="grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3">
                      <button
                        onClick={handlePromotionPrecheck}
                        className="rounded-xl border border-emerald-600/25 bg-emerald-900/10 px-3 py-2 text-left text-sm text-emerald-300 transition-colors hover:bg-emerald-800/20"
                      >
                        推进前校验
                      </button>
                      <button
                        onClick={handleRunTrainingEvolution}
                        disabled={trainingStatus.isTraining}
                        className="rounded-xl border border-fuchsia-600/25 bg-fuchsia-900/10 px-3 py-2 text-left text-sm text-fuchsia-200 transition-colors hover:bg-fuchsia-800/20 disabled:opacity-50"
                      >
                        生成进化建议
                      </button>
                      <button
                        onClick={handleApplyBestParams}
                        className="rounded-xl border border-amber-600/25 bg-amber-900/10 px-3 py-2 text-left text-sm text-amber-200 transition-colors hover:bg-amber-800/20"
                      >
                        应用训练最优
                      </button>
                      <button
                        onClick={handleAutoGovernanceTick}
                        className="rounded-xl border border-cyan-600/25 bg-cyan-900/10 px-3 py-2 text-left text-sm text-cyan-200 transition-colors hover:bg-cyan-800/20"
                      >
                        自动治理编排
                      </button>
                    </div>
                  </div>
                )}
              </div>
            </div>

            {showTrainingAdvanced && (
              <div className="grid grid-cols-1 gap-6 2xl:grid-cols-12">
                <div className="space-y-6 2xl:col-span-4">
                  <div className="bg-card border border-slate-800 rounded-2xl p-6">
                    <div className="flex items-start justify-between gap-4 mb-5">
                      <div>
                        <h3 className="text-sm font-bold text-slate-200">
                          训练控制台
                        </h3>
                        <p className="text-xs text-slate-500 mt-1">
                          模型、数据集与训练进度集中在这里
                        </p>
                      </div>
                      {trainingStatus.isTraining && (
                        <span className="text-[10px] bg-primary/15 text-primary px-2 py-1 rounded border border-primary/20 flex items-center gap-1">
                          <span className="w-1.5 h-1.5 rounded-full bg-primary animate-pulse"></span>
                          训练中
                        </span>
                      )}
                    </div>

                    <div className="space-y-5">
                      <div>
                        <div className="mb-2 text-xs text-slate-500 block">
                          训练数据集
                        </div>
                        <select
                          value={selectedTrainingDataset}
                          onChange={(event) =>
                            setSelectedTrainingDataset(event.target.value)
                          }
                          className="w-full bg-[#0A0E17] border border-slate-800 rounded-xl px-3 py-2 text-sm text-slate-200 focus:outline-none focus:border-primary appearance-none cursor-pointer"
                        >
                          {availableTrainingDatasets.length > 0 ? (
                            availableTrainingDatasets.map((dataset) => (
                              <option key={dataset.id} value={dataset.label}>
                                {dataset.label}
                              </option>
                            ))
                          ) : (
                            <option value={trainingStatus.activeDataset}>
                              {trainingStatus.activeDataset}
                            </option>
                          )}
                        </select>
                        <p className="mt-2 text-[11px] text-slate-500">
                          启动训练时会把该数据集真实传入后端训练脚本，而不是只做展示。
                        </p>
                      </div>

                      <div>
                        <div className="flex justify-between items-center mb-2">
                          <label className="text-xs text-slate-500 block">
                            治理分析模型
                          </label>
                          {trainingStatus.isTraining && (
                            <span className="text-[10px] text-warning bg-warning/10 px-1.5 py-0.5 rounded border border-warning/20">
                              分析模型可保留，下次分析生效
                            </span>
                          )}
                        </div>
                        <select
                          value={selectedTrainingModel}
                          onChange={(event) =>
                            setSelectedTrainingModel(event.target.value)
                          }
                          className="w-full bg-[#0A0E17] border border-slate-800 rounded-xl px-3 py-2 text-sm font-mono text-slate-200 focus:outline-none focus:border-primary appearance-none disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"
                        >
                          {analysisModelOptions.length > 0 ? (
                            analysisModelOptions.map((model, idx) => (
                              <option key={idx} value={model}>
                                {formatModelLabel(model)}
                              </option>
                            ))
                          ) : (
                            <option value="deepseek/deepseek-reasoner">
                              deepseek-reasoner (deepseek)
                            </option>
                          )}
                        </select>
                        <p className="mt-2 text-[11px] text-slate-500">
                          该模型用于生成治理分析与审批报告，不影响底层网格搜索训练引擎。
                        </p>
                      </div>

                      <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-[11px] text-slate-500 mb-1">
                            训练数据源
                          </div>
                          <div className="font-mono text-sm text-primary flex items-center gap-2">
                            <DatabaseZap className="w-3 h-3" />{" "}
                            {selectedTrainingDataset ||
                              trainingStatus.activeDataset}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-[11px] text-slate-500 mb-1">
                            分析执行模型
                          </div>
                          <div className="text-sm text-slate-200 break-words">
                            {trainingStatus.analysisModel ||
                              trainingStatus.activeModel ||
                              selectedTrainingModel ||
                              "未指定"}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-[11px] text-slate-500 mb-1">
                            训练引擎
                          </div>
                          <div className="text-sm text-slate-200">
                            {String(trainingEngine.engine || "Grid Search")}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-[11px] text-slate-500 mb-1">
                            行情采样
                          </div>
                          <div className="text-sm text-slate-200">
                            {String(trainingEngine.symbol || "GC=F")} ·{" "}
                            {String(trainingEngine.lookbackDays || 10)}d ·{" "}
                            {String(trainingEngine.interval || "5m")}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3 sm:col-span-2">
                          <div className="text-[11px] text-slate-500 mb-1">
                            训练阶段
                          </div>
                          <div className="text-sm text-slate-200">
                            {trainingStatus.currentEpoch
                              ? `Epoch ${trainingStatus.currentEpoch}/${trainingStatus.totalEpochs}`
                              : `Bar ${trainingStatus.currentBar}/${trainingStatus.totalBars}`}
                          </div>
                        </div>
                      </div>

                      <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                        <div className="flex justify-between items-center mb-2">
                          <span className="text-xs text-slate-500">
                            训练进度
                          </span>
                          <span className="text-xs font-mono text-slate-300">
                            {trainingStatus.progress.toFixed(1)}%
                          </span>
                        </div>
                        <div className="bg-slate-800 rounded-full h-2">
                          <div
                            className="bg-primary h-2 rounded-full transition-all"
                            style={{ width: `${trainingStatus.progress}%` }}
                          ></div>
                        </div>
                      </div>

                      <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                        <div className="text-[11px] text-slate-500 mb-2">
                          当前阻断原因
                        </div>
                        <div className="text-sm text-slate-300 break-words">
                          {trainingStatus.blockedReasons.length > 0
                            ? trainingStatus.blockedReasons.join("，")
                            : "当前没有阻断项"}
                        </div>
                      </div>
                    </div>
                  </div>

                  <div className="bg-card border border-slate-800 rounded-2xl p-6">
                    <div className="flex items-center justify-between mb-4">
                      <div>
                        <h3 className="text-sm font-bold text-slate-200">
                          模型连接概况
                        </h3>
                        <p className="text-xs text-slate-500 mt-1">
                          当前参与训练与进化的模型角色
                        </p>
                      </div>
                      <span className="text-xs px-2 py-1 rounded bg-slate-800 text-slate-300">
                        {agentModels.length} 个
                      </span>
                    </div>
                    <div className="space-y-3">
                      {agentModels.length > 0 ? (
                        agentModels.map((agent: any, idx: number) => (
                          <div
                            key={idx}
                            className={`rounded-xl border p-3 ${agent.status === "ready" ? "bg-success/5 border-success/20" : "bg-warning/5 border-warning/20"}`}
                          >
                            <div className="flex items-start justify-between gap-3">
                              <div>
                                <p
                                  className={`text-sm font-medium ${agent.status === "ready" ? "text-success" : "text-warning"}`}
                                >
                                  {agent.role} ({agent.model})
                                </p>
                                <p className="text-[11px] text-slate-400 mt-1">
                                  延迟: {agent.latency || "N/A"} · 状态:{" "}
                                  {agent.status === "ready" ? "就绪" : "未配置"}
                                </p>
                              </div>
                              <span
                                className={`text-[11px] px-2 py-1 rounded ${agent.status === "ready" ? "bg-success/20 text-success" : "bg-warning/20 text-warning"}`}
                              >
                                {agent.status === "ready"
                                  ? "Active"
                                  : "Pending"}
                              </span>
                            </div>
                          </div>
                        ))
                      ) : (
                        <div className="text-center py-4 text-slate-500 text-xs">
                          暂无模型数据
                        </div>
                      )}
                    </div>
                  </div>
                </div>

                <div className="space-y-6 2xl:col-span-8">
                  <div className="bg-card border border-slate-800 rounded-2xl p-6">
                    <div className="flex flex-col gap-2 mb-5 md:flex-row md:items-end md:justify-between">
                      <div>
                        <h3 className="text-sm font-bold text-slate-200">
                          训练治理总览
                        </h3>
                        <p className="text-xs text-slate-500 mt-1">
                          先看是否可训练，再看异常、闭环质量与补回情况
                        </p>
                      </div>
                      <div className="text-xs text-slate-500">
                        repair cycle:{" "}
                        {Number(lifecycleTransitionCounts.before || 0)} →{" "}
                        {Number(lifecycleTransitionCounts.after || 0)}
                      </div>
                    </div>

                    <div className="grid grid-cols-2 gap-3 md:grid-cols-3 2xl:grid-cols-5">
                      <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                        <div className="text-[11px] text-slate-500 mb-1">
                          训练资格
                        </div>
                        <div
                          className={`text-base font-bold ${trainingLifecycle.readyForTraining ? "text-success" : "text-warning"}`}
                        >
                          {trainingLifecycle.readyForTraining
                            ? "READY"
                            : "BLOCKED"}
                        </div>
                      </div>
                      <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                        <div className="text-[11px] text-slate-500 mb-1">
                          闭环覆盖率
                        </div>
                        <div className="text-base font-bold text-slate-100">
                          {trainingStatus.closureCoveragePct.toFixed(1)}%
                        </div>
                      </div>
                      <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                        <div className="text-[11px] text-slate-500 mb-1">
                          关键异常
                        </div>
                        <div
                          className={`text-base font-bold ${trainingStatus.criticalAnomalies > 0 ? "text-warning" : "text-success"}`}
                        >
                          {trainingStatus.criticalAnomalies}
                        </div>
                      </div>
                      <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                        <div className="text-[11px] text-slate-500 mb-1">
                          自然闭环
                        </div>
                        <div className="text-base font-bold text-success">
                          {trainingStatus.naturalClosedTransitions}
                        </div>
                        <div className="text-xs text-slate-400 mt-1">
                          {trainingStatus.naturalClosedRatioPct.toFixed(1)}%
                        </div>
                      </div>
                      <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                        <div className="text-[11px] text-slate-500 mb-1">
                          补回闭环
                        </div>
                        <div className="text-base font-bold text-warning">
                          {trainingStatus.recoveredClosedTransitions}
                        </div>
                        <div className="text-xs text-slate-400 mt-1">
                          {trainingStatus.recoveredClosedRatioPct.toFixed(1)}%
                        </div>
                      </div>
                    </div>

                    <div className="mt-4 grid grid-cols-1 gap-4 2xl:grid-cols-3">
                      <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4 2xl:col-span-2">
                        <div className="text-[11px] text-slate-500 mb-2">
                          训练门槛阻断原因
                        </div>
                        <div className="text-sm text-slate-300 break-words">
                          {trainingStatus.blockedReasons.length > 0
                            ? trainingStatus.blockedReasons.join("，")
                            : "当前没有阻断项"}
                        </div>
                      </div>
                      <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                        <div className="text-[11px] text-slate-500 mb-2">
                          主要异常类型
                        </div>
                        <div className="text-sm text-slate-300 break-words">
                          {Array.isArray(
                            governanceReport.governanceContext?.top_anomalies,
                          ) &&
                          governanceReport.governanceContext.top_anomalies
                            .length > 0
                            ? governanceReport.governanceContext.top_anomalies
                                .map((item) =>
                                  String(item?.anomaly_type || "unknown"),
                                )
                                .join("，")
                            : "无"}
                        </div>
                      </div>
                    </div>
                  </div>

                  <div className="space-y-6">
                    <div className="bg-card border border-slate-800 rounded-2xl p-6">
                      <div className="flex items-center justify-between mb-4">
                        <div>
                          <h3 className="text-sm font-bold text-slate-200">
                            决策生命周期
                          </h3>
                          <p className="text-xs text-slate-500 mt-1">
                            观察活跃 decision、最近转移和闭环修复状态
                          </p>
                        </div>
                        <div className="text-right text-xs text-slate-500">
                          <div>
                            活跃 {governanceLifecycle.activeSignals.length}
                          </div>
                          <div>
                            最近 {governanceLifecycle.recentSignals.length}
                          </div>
                        </div>
                      </div>

                      <div className="mb-4 grid grid-cols-1 gap-3 text-xs sm:grid-cols-2 2xl:grid-cols-8">
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-1">repair</div>
                          <div className="text-slate-100">
                            恢复 {Number(lifecycleRecovery.recovered || 0)}
                          </div>
                          <div className="text-slate-400 mt-1">
                            {Number(lifecycleTransitionCounts.before || 0)} →{" "}
                            {Number(lifecycleTransitionCounts.after || 0)}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-1">audit</div>
                          <div className="text-slate-100">
                            {Number(
                              lifecycleCoverage.closure_coverage_pct || 0,
                            ).toFixed(1)}
                            %
                          </div>
                          <div className="text-slate-400 mt-1">
                            critical={Number(lifecycleAnomalies.critical || 0)}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-1">closure</div>
                          <div className="text-slate-100">
                            N {Number(closureLifecycle.normalClosedCount || 0)}{" "}
                            / R{" "}
                            {Number(closureLifecycle.recoveredClosedCount || 0)}
                          </div>
                          <div className="text-slate-400 mt-1">
                            pending=
                            {Number(closureLifecycle.pendingRepairCount || 0)}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-1">training</div>
                          <div
                            className={`font-bold ${trainingLifecycle.readyForTraining ? "text-success" : "text-warning"}`}
                          >
                            {trainingLifecycle.readyForTraining
                              ? "READY"
                              : "BLOCKED"}
                          </div>
                          <div className="text-slate-400 mt-1">
                            repair=
                            {Number(trainingLifecycle.repairRecovered || 0)}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-1">
                            shadow learner
                          </div>
                          <div className="text-slate-100">
                            {String(shadowLearnerLifecycle.status || "EMPTY")}
                          </div>
                          <div className="text-slate-400 mt-1">
                            divergence=
                            {Number(
                              shadowLearnerLifecycle.divergenceCount || 0,
                            )}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-1">
                            live learner
                          </div>
                          <div className="text-slate-100">
                            {String(
                              liveLearnerLifecycle.currentMode || "shadow",
                            )}
                          </div>
                          <div className="text-slate-400 mt-1">
                            rate=
                            {String(liveLearnerLifecycle.learnerLiveRate ?? 0)}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-1">
                            auto governance
                          </div>
                          <div className="text-slate-100">
                            {String(
                              autoGovernanceLifecycle.lastAction ||
                                autoGovernanceLifecycle.status ||
                                "NOOP",
                            )}
                          </div>
                          <div className="text-slate-400 mt-1">
                            {String(
                              autoGovernanceLifecycle.lastReason ||
                                "steady_state",
                            )}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-1">
                            phase readiness
                          </div>
                          <div className="text-slate-100">
                            {String(phaseReadiness.status || "BLOCKED")}
                          </div>
                          <div className="text-slate-400 mt-1">
                            {String(phaseReadiness.nextClosure || "待收口")}
                          </div>
                        </div>
                      </div>

                      <div className="grid grid-cols-1 gap-3 text-xs 2xl:grid-cols-6">
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-2">活跃决策</div>
                          <div className="space-y-2 max-h-64 overflow-auto">
                            {governanceLifecycle.activeSignals.length > 0 ? (
                              governanceLifecycle.activeSignals.map(
                                (item, idx) => (
                                  <div
                                    key={`active-${String(item.signalId || idx)}`}
                                    className="rounded-lg border border-slate-800 bg-slate-950/60 p-2"
                                  >
                                    <div className="flex items-center justify-between gap-2">
                                      <span className="text-slate-100 font-medium">
                                        {String(item.signalId || "-")}
                                      </span>
                                      <span className="px-2 py-0.5 rounded bg-cyan-500/10 text-cyan-300 border border-cyan-500/20">
                                        {String(item.state || "-")}
                                      </span>
                                    </div>
                                    <div className="text-slate-400 mt-1 break-words">
                                      {String(item.reason || "无原因")}
                                    </div>
                                    <div className="text-slate-500 mt-1">
                                      {String(item.latestTs || "-")}
                                    </div>
                                  </div>
                                ),
                              )
                            ) : (
                              <div className="text-slate-500">
                                当前没有活跃 decision
                              </div>
                            )}
                          </div>
                        </div>

                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-2">最近转移</div>
                          <div className="space-y-2 max-h-64 overflow-auto">
                            {governanceLifecycle.recentSignals.length > 0 ? (
                              governanceLifecycle.recentSignals.map(
                                (item, idx) => (
                                  <div
                                    key={`recent-${String(item.signalId || idx)}`}
                                    className="rounded-lg border border-slate-800 bg-slate-950/60 p-2"
                                  >
                                    <div className="flex items-center justify-between gap-2">
                                      <span className="text-slate-100 font-medium">
                                        {String(item.signalId || "-")}
                                      </span>
                                      <span className="px-2 py-0.5 rounded bg-slate-800 text-slate-200 border border-slate-700">
                                        {String(item.state || "-")}
                                      </span>
                                    </div>
                                    <div className="text-slate-400 mt-1 break-words">
                                      {String(item.reason || "无原因")}
                                    </div>
                                    <div className="text-slate-500 mt-1">
                                      {String(item.latestTs || "-")}
                                    </div>
                                  </div>
                                ),
                              )
                            ) : (
                              <div className="text-slate-500">暂无最近转移</div>
                            )}
                          </div>
                        </div>

                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-2">闭环与修复</div>
                          <div className="space-y-2 max-h-40 overflow-auto">
                            {recentClosures.length > 0 ? (
                              recentClosures.map((item, idx) => (
                                <div
                                  key={`closure-${String(item.decisionId || idx)}`}
                                  className="rounded-lg border border-slate-800 bg-slate-950/60 p-2"
                                >
                                  <div className="flex items-center justify-between gap-2">
                                    <span className="text-slate-100 font-medium">
                                      {String(item.decisionId || "-")}
                                    </span>
                                    <span
                                      className={`px-2 py-0.5 rounded border ${item.recovered ? "bg-amber-500/10 text-amber-300 border-amber-500/20" : "bg-emerald-500/10 text-emerald-300 border-emerald-500/20"}`}
                                    >
                                      {item.recovered ? "RECOVERED" : "CLOSED"}
                                    </span>
                                  </div>
                                  <div className="text-slate-400 mt-1 break-words">
                                    {String(item.doneReason || "closed")} · pnl=
                                    {String(item.realizedPnl || 0)}
                                  </div>
                                  <div className="text-slate-500 mt-1">
                                    {String(item.eventTime || "-")}
                                  </div>
                                </div>
                              ))
                            ) : (
                              <div className="text-slate-500">
                                暂无 closure 记录
                              </div>
                            )}
                          </div>
                          <div className="mt-3 pt-3 border-t border-slate-800">
                            <div className="text-slate-500 mb-2">
                              待修复列表
                            </div>
                            <div className="space-y-2 max-h-24 overflow-auto">
                              {pendingRepairDecisions.length > 0 ? (
                                pendingRepairDecisions.map((item, idx) => (
                                  <div
                                    key={`repair-${String(item.decisionId || idx)}`}
                                    className="text-slate-400"
                                  >
                                    {String(item.decisionId || "-")} · ticket=
                                    {String(item.ticket || 0)} ·{" "}
                                    {String(item.severity || "unknown")}
                                  </div>
                                ))
                              ) : (
                                <div className="text-slate-500">
                                  暂无待修复 closure
                                </div>
                              )}
                            </div>
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-2">
                            Shadow Learner 对照
                          </div>
                          <div className="mb-3 grid grid-cols-2 gap-2">
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">action match</div>
                              <div className="text-slate-100">
                                {String(
                                  shadowLearnerLifecycle.actionMatchRate ?? "-",
                                )}
                              </div>
                            </div>
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">
                                direction match
                              </div>
                              <div className="text-slate-100">
                                {String(
                                  shadowLearnerLifecycle.directionMatchRate ??
                                    "-",
                                )}
                              </div>
                            </div>
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">
                                baseline approved
                              </div>
                              <div className="text-slate-100">
                                {String(
                                  shadowLearnerLifecycle.baselineApprovedRate ??
                                    "-",
                                )}
                              </div>
                            </div>
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">
                                learner approved
                              </div>
                              <div className="text-slate-100">
                                {String(
                                  shadowLearnerLifecycle.learnerApprovedRate ??
                                    "-",
                                )}
                              </div>
                            </div>
                          </div>
                          <div className="space-y-2 max-h-64 overflow-auto">
                            {recentShadowDecisions.length > 0 ? (
                              recentShadowDecisions.map((item, idx) => (
                                <div
                                  key={`shadow-${String(item.decisionId || idx)}`}
                                  className="rounded-lg border border-slate-800 bg-slate-950/60 p-2"
                                >
                                  <div className="flex items-center justify-between gap-2">
                                    <span className="text-slate-100 font-medium">
                                      {String(item.decisionId || "-")}
                                    </span>
                                    <span className="px-2 py-0.5 rounded bg-purple-500/10 text-purple-300 border border-purple-500/20">
                                      {String(item.learnerAction || "HOLD")}
                                    </span>
                                  </div>
                                  <div className="text-slate-400 mt-1 break-words">
                                    B:{String(item.baselineAction || "-")} / L:
                                    {String(item.learnerAction || "-")}
                                  </div>
                                  <div className="text-slate-500 mt-1 break-words">
                                    risk B:{String(item.baselineRisk || "-")} /
                                    L:
                                    {String(item.learnerRisk || "-")}
                                  </div>
                                </div>
                              ))
                            ) : (
                              <div className="text-slate-500">
                                暂无 learner shadow 对照
                              </div>
                            )}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-2">
                            Live Learner 选择
                          </div>
                          <div className="mb-3 grid grid-cols-2 gap-2">
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">live rate</div>
                              <div className="text-slate-100">
                                {String(
                                  liveLearnerLifecycle.learnerLiveRate ?? "-",
                                )}
                              </div>
                            </div>
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">selected</div>
                              <div className="text-slate-100">
                                {String(
                                  liveLearnerLifecycle.learnerLiveSelections ??
                                    "-",
                                )}
                              </div>
                            </div>
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">
                                baseline fallback
                              </div>
                              <div className="text-slate-100">
                                {String(
                                  liveLearnerLifecycle.baselineSelections ??
                                    "-",
                                )}
                              </div>
                            </div>
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">rollback</div>
                              <div className="text-slate-100">
                                {String(
                                  Array.isArray(rollbackEvidence.triggered)
                                    ? rollbackEvidence.triggered.length
                                    : 0,
                                )}
                              </div>
                            </div>
                          </div>
                          <div className="space-y-2 max-h-64 overflow-auto">
                            {recentLiveSelections.length > 0 ? (
                              recentLiveSelections.map((item, idx) => (
                                <div
                                  key={`live-${String(item.decision_id || idx)}`}
                                  className="rounded-lg border border-slate-800 bg-slate-950/60 p-2"
                                >
                                  <div className="flex items-center justify-between gap-2">
                                    <span className="text-slate-100 font-medium">
                                      {String(item.decision_id || "-")}
                                    </span>
                                    <span className="px-2 py-0.5 rounded bg-emerald-500/10 text-emerald-300 border border-emerald-500/20">
                                      {String(
                                        item.selected_source || "baseline",
                                      )}
                                    </span>
                                  </div>
                                  <div className="text-slate-400 mt-1 break-words">
                                    {String(item.selection_reason || "-")}
                                  </div>
                                  <div className="text-slate-500 mt-1 break-words">
                                    mode={String(item.promotion_mode || "-")} ·
                                    canary=
                                    {String(item.canary_bucket ?? "-")}
                                  </div>
                                </div>
                              ))
                            ) : (
                              <div className="text-slate-500">
                                暂无 live learner 选择记录
                              </div>
                            )}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-2">
                            自动编排历史
                          </div>
                          <div className="mb-3 grid grid-cols-2 gap-2">
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">enabled</div>
                              <div className="text-slate-100">
                                {String(
                                  Boolean(autoGovernanceLifecycle.enabled),
                                )}
                              </div>
                            </div>
                            <div className="rounded-lg border border-slate-800 bg-slate-950/60 p-2">
                              <div className="text-slate-500">current mode</div>
                              <div className="text-slate-100">
                                {String(
                                  autoGovernanceLifecycle.currentMode || "-",
                                )}
                              </div>
                            </div>
                          </div>
                          <div className="space-y-2 max-h-64 overflow-auto">
                            {Array.isArray(
                              autoGovernanceLifecycle.recentActions,
                            ) &&
                            autoGovernanceLifecycle.recentActions.length > 0 ? (
                              autoGovernanceLifecycle.recentActions.map(
                                (item, idx) => (
                                  <div
                                    key={`auto-${String(item.timestamp || idx)}`}
                                    className="rounded-lg border border-slate-800 bg-slate-950/60 p-2"
                                  >
                                    <div className="flex items-center justify-between gap-2">
                                      <span className="text-slate-100 font-medium">
                                        {String(item.action || "NOOP")}
                                      </span>
                                      <span className="px-2 py-0.5 rounded bg-cyan-500/10 text-cyan-300 border border-cyan-500/20">
                                        {String(item.promotion_mode || "-")}
                                      </span>
                                    </div>
                                    <div className="text-slate-400 mt-1 break-words">
                                      {String(item.reason || "-")}
                                    </div>
                                    <div className="text-slate-500 mt-1">
                                      {String(item.timestamp || "-")}
                                    </div>
                                  </div>
                                ),
                              )
                            ) : (
                              <div className="text-slate-500">
                                暂无自动编排动作
                              </div>
                            )}
                          </div>
                        </div>
                        <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                          <div className="text-slate-500 mb-2">
                            阶段收口判定
                          </div>
                          <div className="mb-3 grid grid-cols-2 gap-2">
                            {Object.entries(
                              (phaseReadiness.phases as Record<
                                string,
                                unknown
                              >) || {},
                            ).map(([name, payload]) => (
                              <div
                                key={`phase-${name}`}
                                className="rounded-lg border border-slate-800 bg-slate-950/60 p-2"
                              >
                                <div className="text-slate-500">{name}</div>
                                <div className="text-slate-100">
                                  {String(
                                    (payload as Record<string, unknown>)
                                      .status || "BLOCKED",
                                  )}
                                </div>
                              </div>
                            ))}
                          </div>
                          <div className="text-slate-300 text-sm break-words">
                            {String(
                              phaseReadiness.nextClosure || "当前仍不建议收口",
                            )}
                          </div>
                          <pre className="mt-3 max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-xl bg-slate-950/60 p-3 text-[11px] leading-5 text-slate-300">
                            {JSON.stringify(phaseReadiness, null, 2)}
                          </pre>
                        </div>
                      </div>
                    </div>

                    <div>
                      <div className="grid grid-cols-1 gap-6 xl:grid-cols-2">
                        <div className="bg-card border border-slate-800 rounded-2xl p-6 xl:col-span-2">
                          <div className="flex items-center justify-between mb-4">
                            <div>
                              <h3 className="text-sm font-bold text-slate-200">
                                进化审批链
                              </h3>
                              <p className="text-xs text-slate-500 mt-1">
                                整理建议、审批条件与下一步动作
                              </p>
                            </div>
                            <span className="text-xs px-2 py-1 rounded bg-slate-800 text-slate-300">
                              {approvalChain.stage}
                            </span>
                          </div>

                          <div className="grid grid-cols-1 gap-4 text-xs">
                            <div className="rounded-2xl border border-slate-800 bg-[linear-gradient(180deg,rgba(10,14,24,0.96),rgba(6,10,18,0.98))] p-4">
                              <div className="flex flex-wrap items-center justify-between gap-2">
                                <div className="text-slate-500">建议原因</div>
                                <span className="rounded-full border border-slate-700 bg-slate-900 px-2.5 py-1 text-[10px] text-slate-400">
                                  next:{" "}
                                  {String(
                                    approvalDecision.promotionTarget ||
                                      "未生成",
                                  )}
                                </span>
                              </div>
                              <div className="mt-3 max-h-40 overflow-auto whitespace-pre-wrap break-words text-[13px] leading-6 text-slate-200">
                                {String(
                                  approvalChain.suggestion?.evolution_reason ||
                                    approvalChain.appliedSuggestion
                                      ?.evolution_reason ||
                                    "NONE",
                                )}
                              </div>
                            </div>
                            <div className="grid grid-cols-1 gap-3 md:grid-cols-2 2xl:grid-cols-4">
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="text-slate-500 mb-1">
                                  审批状态
                                </div>
                                <div className="text-base font-semibold text-slate-100">
                                  {String(approvalDecision.status || "UNKNOWN")}
                                </div>
                                <div
                                  className={`mt-2 text-sm font-bold ${approvalDecision.canPromote ? "text-success" : "text-warning"}`}
                                >
                                  canPromote=
                                  {String(Boolean(approvalDecision.canPromote))}
                                </div>
                              </div>
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="text-slate-500 mb-1">
                                  推进模式
                                </div>
                                <div className="text-base font-semibold text-slate-100">
                                  {String(
                                    approvalDecision.promotionMode || "shadow",
                                  )}
                                </div>
                                <div className="mt-2 break-words text-xs leading-5 text-slate-400">
                                  {String(
                                    approvalDecision.nextStep ||
                                      "暂无下一步建议",
                                  )}
                                </div>
                              </div>
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="text-slate-500 mb-1">
                                  缺失条件
                                </div>
                                <div className="text-base font-semibold text-slate-100">
                                  {approvalMissingConditions.length}
                                </div>
                                <div className="mt-2 break-words text-xs leading-5 text-slate-400">
                                  {approvalMissingConditions.length > 0
                                    ? approvalMissingConditions.join("，")
                                    : "已满足当前审批条件"}
                                </div>
                              </div>
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="text-slate-500 mb-1">
                                  Live Learner
                                </div>
                                <div className="text-base font-semibold text-slate-100">
                                  {String(
                                    approvalDecision.liveLearnerStatus ||
                                      approvalLiveLearner.status ||
                                      "EMPTY",
                                  )}
                                </div>
                                <div className="mt-2 break-words text-xs leading-5 text-slate-400">
                                  liveRate=
                                  {String(
                                    approvalDecision.liveLearnerRate ??
                                      approvalLiveLearner.learnerLiveRate ??
                                      0,
                                  )}
                                </div>
                              </div>
                            </div>
                            <div className="grid grid-cols-1 gap-3 2xl:grid-cols-2">
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="text-slate-500 mb-2">
                                  建议参数
                                </div>
                                <pre className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-xl bg-slate-950/60 p-3 text-[11px] leading-5 text-slate-300">
                                  {JSON.stringify(
                                    approvalChain.suggestion
                                      ?.suggested_params ||
                                      approvalChain.appliedSuggestion
                                        ?.suggested_params ||
                                      {},
                                    null,
                                    2,
                                  )}
                                </pre>
                              </div>
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="text-slate-500 mb-2">
                                  当前生效参数
                                </div>
                                <pre className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-xl bg-slate-950/60 p-3 text-[11px] leading-5 text-slate-300">
                                  {JSON.stringify(
                                    effectiveOfflineParams,
                                    null,
                                    2,
                                  )}
                                </pre>
                              </div>
                            </div>
                            <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                              <div className="flex items-center justify-between gap-3">
                                <div className="text-slate-500">
                                  阶段收口状态
                                </div>
                                <span className="rounded-full border border-slate-700 bg-slate-900 px-2.5 py-1 text-[10px] text-slate-400">
                                  {String(
                                    approvalDecision.phaseReadiness ||
                                      approvalPhaseReadiness.status ||
                                      "BLOCKED",
                                  )}
                                </span>
                              </div>
                              <div className="mt-3 text-sm text-slate-200 break-words">
                                {String(
                                  approvalPhaseReadiness.nextClosure ||
                                    "当前还不能阶段收口",
                                )}
                              </div>
                              <div className="mt-3 grid grid-cols-2 gap-3 text-xs">
                                {Object.entries(
                                  (approvalPhaseReadiness.phases as Record<
                                    string,
                                    unknown
                                  >) || {},
                                ).map(([name, payload]) => (
                                  <div
                                    key={`approval-phase-${name}`}
                                    className="rounded-xl border border-slate-800 bg-slate-950/50 p-3"
                                  >
                                    <div className="text-slate-500">{name}</div>
                                    <div className="mt-1 text-sm font-semibold text-slate-100">
                                      {String(
                                        (payload as Record<string, unknown>)
                                          .status || "BLOCKED",
                                      )}
                                    </div>
                                    <div className="mt-1 text-slate-400 break-words">
                                      {Array.isArray(
                                        (payload as Record<string, unknown>)
                                          .blockers,
                                      )
                                        ? String(
                                            (
                                              (
                                                payload as Record<
                                                  string,
                                                  unknown
                                                >
                                              ).blockers as Array<unknown>
                                            ).join("，") || "无",
                                          )
                                        : "无"}
                                    </div>
                                  </div>
                                ))}
                              </div>
                            </div>
                            <div className="grid grid-cols-1 gap-3 min-[1800px]:grid-cols-[minmax(0,0.9fr)_minmax(320px,1.1fr)]">
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="flex items-center justify-between gap-3">
                                  <div className="text-slate-500">
                                    参数 Learner 对照
                                  </div>
                                  <span className="rounded-full border border-slate-700 bg-slate-900 px-2.5 py-1 text-[10px] text-slate-400">
                                    {String(
                                      paramLearnerComparison.status ||
                                        paramLearnerReport.status ||
                                        "NONE",
                                    )}
                                  </span>
                                </div>
                                <div className="mt-3 grid grid-cols-2 gap-3 text-xs">
                                  <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-3">
                                    <div className="text-slate-500">Δ PnL</div>
                                    <div className="mt-1 text-sm font-semibold text-slate-100">
                                      {String(paramLearnerDelta.pnl ?? "-")}
                                    </div>
                                  </div>
                                  <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-3">
                                    <div className="text-slate-500">
                                      Δ Score
                                    </div>
                                    <div className="mt-1 text-sm font-semibold text-slate-100">
                                      {String(paramLearnerDelta.score ?? "-")}
                                    </div>
                                  </div>
                                  <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-3">
                                    <div className="text-slate-500">Δ 胜率</div>
                                    <div className="mt-1 text-sm font-semibold text-slate-100">
                                      {String(
                                        paramLearnerDelta.win_rate ?? "-",
                                      )}
                                    </div>
                                  </div>
                                  <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-3">
                                    <div className="text-slate-500">下一步</div>
                                    <div className="mt-1 text-sm font-semibold text-slate-100">
                                      {String(
                                        paramLearnerComparison.next_step || "-",
                                      )}
                                    </div>
                                  </div>
                                </div>
                              </div>
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="text-slate-500 mb-2">
                                  Learner 候选策略
                                </div>
                                <pre className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-xl bg-slate-950/60 p-3 text-[11px] leading-5 text-slate-300">
                                  {JSON.stringify(
                                    paramLearnerCandidate,
                                    null,
                                    2,
                                  )}
                                </pre>
                              </div>
                            </div>
                            <div className="grid grid-cols-1 gap-3 2xl:grid-cols-[0.9fr_1.1fr]">
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="flex items-center justify-between gap-3">
                                  <div className="text-slate-500">
                                    Shadow Promotion 证据
                                  </div>
                                  <span className="rounded-full border border-slate-700 bg-slate-900 px-2.5 py-1 text-[10px] text-slate-400">
                                    {String(
                                      approvalDecision.shadowLearnerStatus ||
                                        approvalShadowLearner.status ||
                                        "EMPTY",
                                    )}
                                  </span>
                                </div>
                                <div className="mt-3 grid grid-cols-2 gap-3 text-xs">
                                  <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-3">
                                    <div className="text-slate-500">
                                      shadow pnl
                                    </div>
                                    <div className="mt-1 text-sm font-semibold text-slate-100">
                                      {String(
                                        approvalShadowLearner.min_shadow_total_pnl ??
                                          approvalShadowLearner.shadowTotalPnl ??
                                          "-",
                                      )}
                                    </div>
                                  </div>
                                  <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-3">
                                    <div className="text-slate-500">
                                      closed trades
                                    </div>
                                    <div className="mt-1 text-sm font-semibold text-slate-100">
                                      {String(
                                        approvalShadowLearner.min_shadow_closed_trades ??
                                          approvalShadowLearner.shadowClosedTrades ??
                                          "-",
                                      )}
                                    </div>
                                  </div>
                                  <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-3">
                                    <div className="text-slate-500">
                                      win rate
                                    </div>
                                    <div className="mt-1 text-sm font-semibold text-slate-100">
                                      {String(
                                        approvalShadowLearner.min_shadow_win_rate_pct ??
                                          approvalShadowLearner.shadowWinRatePct ??
                                          "-",
                                      )}
                                    </div>
                                  </div>
                                  <div className="rounded-xl border border-slate-800 bg-slate-950/50 p-3">
                                    <div className="text-slate-500">
                                      drawdown
                                    </div>
                                    <div className="mt-1 text-sm font-semibold text-slate-100">
                                      {String(
                                        approvalShadowLearner.max_shadow_max_drawdown_abs ??
                                          approvalShadowLearner.shadowMaxDrawdownAbs ??
                                          "-",
                                      )}
                                    </div>
                                  </div>
                                </div>
                              </div>
                              <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                                <div className="text-slate-500 mb-2">
                                  Shadow Learner 汇总
                                </div>
                                <pre className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-xl bg-slate-950/60 p-3 text-[11px] leading-5 text-slate-300">
                                  {JSON.stringify(
                                    approvalShadowLearner,
                                    null,
                                    2,
                                  )}
                                </pre>
                              </div>
                            </div>
                            <div className="grid grid-cols-1 gap-3 min-[1800px]:grid-cols-[minmax(0,1.15fr)_minmax(300px,0.85fr)]">
                              <div className="min-w-0 rounded-2xl border border-slate-800 bg-[#0A0E17] p-4 overflow-hidden">
                                <div className="text-slate-500 mb-2">
                                  质量快照
                                </div>
                                <pre className="max-h-48 overflow-auto whitespace-pre-wrap break-words rounded-xl bg-slate-950/60 p-3 text-[11px] leading-5 text-slate-300">
                                  {JSON.stringify(
                                    effectiveQualityContext,
                                    null,
                                    2,
                                  )}
                                </pre>
                              </div>
                              <div className="min-w-0 grid grid-cols-1 gap-3">
                                <div className="min-w-0 rounded-2xl border border-slate-800 bg-[#0A0E17] p-4 overflow-hidden">
                                  <div className="text-slate-500 mb-1 whitespace-nowrap">
                                    推荐动作
                                  </div>
                                  <div className="max-h-24 overflow-auto flex flex-wrap gap-2">
                                    {approvalRecommendedActions.length > 0 ? (
                                      approvalRecommendedActions.map(
                                        (action) => (
                                          <span
                                            key={String(action)}
                                            className="max-w-full px-2 py-1 rounded bg-success/10 text-success border border-success/20 whitespace-normal break-all leading-4"
                                          >
                                            {String(action)}
                                          </span>
                                        ),
                                      )
                                    ) : (
                                      <span className="text-slate-400">
                                        NONE
                                      </span>
                                    )}
                                  </div>
                                </div>
                                <div className="min-w-0 rounded-2xl border border-slate-800 bg-[#0A0E17] p-4 overflow-hidden">
                                  <div className="text-slate-500 mb-1 whitespace-nowrap">
                                    禁止动作
                                  </div>
                                  <div className="max-h-24 overflow-auto flex flex-wrap gap-2">
                                    {approvalForbiddenActions.length > 0 ? (
                                      approvalForbiddenActions.map((action) => (
                                        <span
                                          key={String(action)}
                                          className="max-w-full px-2 py-1 rounded bg-danger/10 text-danger border border-danger/20 whitespace-normal break-all leading-4"
                                        >
                                          {String(action)}
                                        </span>
                                      ))
                                    ) : (
                                      <span className="text-slate-400">
                                        NONE
                                      </span>
                                    )}
                                  </div>
                                </div>
                              </div>
                            </div>
                          </div>
                        </div>

                        <div className="mt-4 rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                          <div className="flex flex-wrap items-center justify-between gap-3">
                            <div>
                              <div className="text-xs font-medium text-slate-400">
                                动作已收敛到顶部控制带
                              </div>
                              <div className="mt-1 text-sm text-slate-300">
                                这里仅保留审批上下文，避免同一动作在多个位置重复出现
                              </div>
                            </div>
                            <div className="flex flex-wrap gap-2 text-[11px]">
                              <span
                                className={`rounded-full border px-3 py-1 ${
                                  canCompleteTrainingReview
                                    ? "border-warning/25 bg-warning/10 text-warning"
                                    : "border-slate-700 bg-slate-900 text-slate-500"
                                }`}
                              >
                                人工复核{" "}
                                {canCompleteTrainingReview ? "READY" : "LOCKED"}
                              </span>
                              <span
                                className={`rounded-full border px-3 py-1 ${
                                  canRepairTraining
                                    ? "border-danger/25 bg-danger/10 text-danger"
                                    : "border-slate-700 bg-slate-900 text-slate-500"
                                }`}
                              >
                                修复阻断{" "}
                                {canRepairTraining ? "READY" : "LOCKED"}
                              </span>
                              <span
                                className={`rounded-full border px-3 py-1 ${
                                  canPromoteTraining
                                    ? "border-success/25 bg-success/10 text-success"
                                    : "border-slate-700 bg-slate-900 text-slate-500"
                                }`}
                              >
                                推进 {canPromoteTraining ? "READY" : "LOCKED"}
                              </span>
                            </div>
                          </div>
                        </div>
                      </div>

                      <div className="bg-card border border-slate-800 rounded-2xl p-6 flex min-h-[340px] flex-col">
                        <div className="flex flex-wrap items-start justify-between gap-3 mb-4">
                          <div>
                            <h3 className="text-sm font-bold text-slate-200">
                              PnL 累计盈亏曲线
                            </h3>
                            <p className="mt-1 text-xs text-slate-500">
                              结合胜率、交易数与最新收益观察训练结果质量
                            </p>
                          </div>
                          <span
                            className={`text-xs font-mono font-bold px-2 py-1 rounded ${trainingStatus.pnl > 0 ? "bg-success/20 text-success" : trainingStatus.pnl < 0 ? "bg-danger/20 text-danger" : "bg-slate-800 text-slate-400"}`}
                          >
                            当前盈亏: {trainingStatus.pnl > 0 ? "+" : ""}
                            {"$"}
                            {trainingStatus.pnl.toFixed(2)}
                          </span>
                        </div>
                        <div className="mb-4 grid grid-cols-1 gap-3 text-xs sm:grid-cols-3">
                          <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                            <div className="text-slate-500">胜率</div>
                            <div className="mt-1 text-sm font-semibold text-slate-100">
                              {trainingStatus.winRate.toFixed(1)}%
                            </div>
                          </div>
                          <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                            <div className="text-slate-500">交易数</div>
                            <div className="mt-1 text-sm font-semibold text-slate-100">
                              {trainingStatus.totalTrades}
                            </div>
                          </div>
                          <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-3">
                            <div className="text-slate-500">Epoch</div>
                            <div className="mt-1 text-sm font-semibold text-slate-100">
                              {trainingStatus.currentEpoch}/
                              {trainingStatus.totalEpochs || 0}
                            </div>
                          </div>
                        </div>
                        <div className="h-[240px] w-full rounded-2xl border border-slate-800 bg-[#0A0E17] p-3 sm:h-[280px]">
                          <ResponsiveContainer width="100%" height="100%">
                            <LineChart data={pnlHistory}>
                              <CartesianGrid
                                strokeDasharray="3 3"
                                stroke="#1e293b"
                                vertical={false}
                              />
                              <XAxis
                                dataKey="epoch"
                                stroke="#64748b"
                                fontSize={10}
                                tickMargin={10}
                              />
                              <YAxis
                                stroke="#64748b"
                                fontSize={10}
                                domain={["auto", "auto"]}
                              />
                              <Tooltip
                                contentStyle={{
                                  backgroundColor: "#0f172a",
                                  borderColor: "#1e293b",
                                  fontSize: "12px",
                                }}
                                itemStyle={{ color: "#10b981" }}
                              />
                              <Line
                                type="monotone"
                                dataKey="loss"
                                stroke="#10b981"
                                strokeWidth={2}
                                dot={false}
                                activeDot={{
                                  r: 5,
                                  fill: "#10b981",
                                  stroke: "#fff",
                                }}
                                isAnimationActive={false}
                              />
                            </LineChart>
                          </ResponsiveContainer>
                        </div>
                      </div>

                      <div className="bg-card border border-slate-800 rounded-2xl p-5 flex min-h-[340px] flex-col">
                        <div className="flex flex-wrap items-center justify-between gap-3 mb-4 border-b border-slate-800/50 pb-4">
                          <div>
                            <h3 className="text-sm font-bold text-slate-200">
                              Evolution Agent 报告
                            </h3>
                            <p className="text-[11px] text-slate-500 mt-1">
                              训练门槛、进化状态与治理建议统一查看
                            </p>
                          </div>
                          <button
                            onClick={handleRegenerateGovernanceAnalysis}
                            className="rounded-lg bg-primary/20 px-3 py-1.5 text-[11px] text-primary hover:bg-primary/30 transition-colors flex items-center gap-1 cursor-pointer"
                          >
                            <MessageSquare className="w-3 h-3" /> 刷新分析
                          </button>
                        </div>
                        <div className="mb-4 flex flex-wrap gap-2 text-[11px]">
                          <span className="rounded-full border border-slate-700 bg-slate-900 px-3 py-1 text-slate-300">
                            ENGINE{" "}
                            {String(trainingEngine.engine || "Grid Search")}
                          </span>
                          <span className="rounded-full border border-slate-700 bg-slate-900 px-3 py-1 text-slate-300">
                            MODEL{" "}
                            {trainingStatus.analysisModel ||
                              trainingStatus.activeModel ||
                              "deepseek/deepseek-reasoner"}
                          </span>
                          <span
                            className={`rounded-full border px-3 py-1 ${
                              trainingStatus.readyForTraining
                                ? "border-success/25 bg-success/10 text-success"
                                : "border-warning/25 bg-warning/10 text-warning"
                            }`}
                          >
                            GATE{" "}
                            {trainingStatus.readyForTraining
                              ? "READY"
                              : "BLOCKED"}
                          </span>
                          <span className="rounded-full border border-slate-700 bg-slate-900 px-3 py-1 text-slate-300">
                            REPAIR{" "}
                            {Number(closureLifecycle.pendingRepairCount || 0)}
                          </span>
                        </div>
                        <div className="grid flex-1 min-h-0 grid-cols-1 gap-4 2xl:grid-cols-[0.9fr_1.1fr]">
                          <div className="space-y-3">
                            <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4 text-xs">
                              <div className="text-slate-500">运行摘要</div>
                              <div className="mt-3 space-y-2 text-slate-300">
                                <div>
                                  数据源：
                                  {String(
                                    trainingEngine.source || "Yahoo Finance",
                                  )}{" "}
                                  · {String(trainingEngine.symbol || "GC=F")} ·{" "}
                                  {String(trainingEngine.interval || "5m")}
                                </div>
                                <div>
                                  阻断项：
                                  {trainingStatus.blockedReasons.join(" | ") ||
                                    "NONE"}
                                </div>
                                <div>
                                  闭环覆盖{" "}
                                  {trainingStatus.closureCoveragePct.toFixed(1)}
                                  % · critical{" "}
                                  {trainingStatus.criticalAnomalies} · recovered{" "}
                                  {trainingStatus.recoveredClosedRatioPct.toFixed(
                                    1,
                                  )}
                                  %
                                </div>
                                <div>
                                  审批：{approvalChain.stage} /{" "}
                                  {String(approvalDecision.status || "UNKNOWN")}{" "}
                                  / canPromote=
                                  {String(Boolean(approvalDecision.canPromote))}
                                </div>
                                <div>
                                  {trainingStatus.isTraining
                                    ? `训练中：${trainingStatus.currentEpoch}/${trainingStatus.totalEpochs || 81}，progress=${trainingStatus.progress.toFixed(1)}%`
                                    : `当前空闲，最近收益 $${trainingStatus.pnl.toFixed(2)}`}
                                </div>
                              </div>
                            </div>
                          </div>
                          <div className="min-h-0 rounded-2xl border border-slate-800 bg-[#0A0E17] p-4">
                            <div className="mb-2 text-xs text-slate-500">
                              治理建议正文
                            </div>
                            <div className="max-h-[360px] overflow-y-auto pr-1">
                              {governanceReport.governanceAdvice ? (
                                <pre className="whitespace-pre-wrap text-[12px] leading-6 text-slate-200">
                                  {governanceReport.governanceAdvice}
                                </pre>
                              ) : (
                                <p className="text-sm text-slate-500">
                                  暂无治理建议文本，请点击 Agent 分析 生成。
                                </p>
                              )}
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            )}
          </div>
        </div>
      );
    }
    if (menu === "logs") {
      return (
        <div className="h-full flex flex-col p-6 space-y-4">
          <div className="flex items-center justify-between">
            <div>
              <h2 className="text-2xl font-bold">日志与告警</h2>
              <p className="mt-1 text-sm text-slate-400">
                同时展示两条真相源：`pipeline.py`
                决定这笔单能不能下，`gold_trader.py` 告诉你单子是否真的到 MT5
                并拿到回报。
              </p>
            </div>
            <div className="flex space-x-2">
              <button
                onClick={handleExportLogs}
                className="px-3 py-1.5 bg-slate-800 text-sm rounded-lg hover:bg-slate-700 transition-colors"
              >
                导出日志
              </button>
              <button
                onClick={handleClearLogScreen}
                className="px-3 py-1.5 bg-danger/20 text-danger text-sm rounded-lg hover:bg-danger/30 transition-colors"
              >
                清空屏幕
              </button>
            </div>
          </div>

          <div className="flex flex-1 gap-4 min-h-0">
            {/* 左侧：风控与告警事件流 */}
            <div className="w-1/3 flex flex-col bg-card border border-slate-800 rounded-xl overflow-hidden">
              <div className="p-4 border-b border-slate-800 bg-slate-800/30 flex justify-between items-center">
                <h3 className="font-medium text-sm flex items-center gap-2">
                  <AlertCircle className="w-4 h-4 text-warning" /> 关键告警
                </h3>
                <span className="text-xs text-slate-400 bg-slate-800 px-2 py-0.5 rounded-full">
                  今日 {alerts.length} 条
                </span>
              </div>
              <div className="flex-1 overflow-y-auto p-4 space-y-3">
                {alerts.map((alert) => (
                  <div
                    key={alert.id}
                    className={`bg-${alert.color}/10 border border-${alert.color}/20 p-3 rounded-lg`}
                  >
                    <div className="flex justify-between items-start mb-1">
                      <span className={`text-${alert.color} text-xs font-bold`}>
                        {alert.type}
                      </span>
                      <span className="text-slate-500 text-[10px]">
                        {alert.time}
                      </span>
                    </div>
                    <p className="text-sm text-slate-300">{alert.desc}</p>
                  </div>
                ))}
                {alerts.length === 0 && (
                  <div className="text-slate-500 italic text-center text-sm py-8">
                    暂无告警事件
                  </div>
                )}
              </div>
            </div>

            {/* 右侧：实时系统终端日志 */}
            <div className="flex-1 flex flex-col bg-[#0A0E17] border border-slate-800 rounded-xl overflow-hidden font-mono">
              <div className="p-3 border-b border-slate-800 bg-slate-800/50 flex space-x-4 text-xs">
                <button
                  onClick={() => setActiveLogTab("system")}
                  className={`${activeLogTab === "system" ? "text-primary border-b border-primary" : "text-slate-500 hover:text-slate-300"} pb-1`}
                >
                  {logTabMeta.system.label}
                </button>
                <button
                  onClick={() => setActiveLogTab("daemon")}
                  className={`${activeLogTab === "daemon" ? "text-primary border-b border-primary" : "text-slate-500 hover:text-slate-300"} pb-1`}
                >
                  {logTabMeta.daemon.label}
                </button>
              </div>
              <div className="px-3 py-2 border-b border-slate-800 bg-slate-900/60">
                <div className="text-[11px] font-semibold text-slate-200">
                  {activeLogMeta.title}
                </div>
                <div className="mt-1 text-[11px] text-slate-500 leading-5">
                  {activeLogMeta.description}
                </div>
              </div>
              {activeLogSource && (
                <div className="px-3 py-2 border-b border-slate-800 bg-[#0F172A] text-[11px] text-slate-500 truncate">
                  {activeLogSource}
                </div>
              )}
              <div className="flex-1 overflow-y-auto p-4 text-[13px] leading-relaxed space-y-1">
                {activeLogs.map((line, i) => (
                  <div
                    key={i}
                    className={`whitespace-pre-wrap break-words ${getLogLineToneClass(line)}`}
                  >
                    {line.trim()}
                  </div>
                ))}
                {activeLogs.length === 0 && (
                  <div className="text-slate-500 italic">
                    {activeLogMeta.empty}
                  </div>
                )}
                <div className="animate-pulse text-primary mt-2">_</div>
              </div>
            </div>
          </div>
        </div>
      );
    }

    if (menu === "positions") {
      return (
        <div className="h-full flex flex-col p-6 space-y-6">
          <div className="grid grid-cols-1 xl:grid-cols-4 gap-4">
            <div className="bg-card border border-slate-800 rounded-2xl p-5">
              <div className="text-xs text-slate-400 mb-2">执行链活跃信号</div>
              <div className="text-3xl font-bold text-slate-100">
                {Number(workbenchExecutionSummary.activeExecutions || 0)}
              </div>
              <div className="text-xs text-slate-500 mt-2">
                来自真实 `execution_state.json`
              </div>
            </div>
            <div className="bg-card border border-slate-800 rounded-2xl p-5">
              <div className="text-xs text-slate-400 mb-2">待人工复核</div>
              <div className="text-3xl font-bold text-warning">
                {signalReviewPendingCount}
              </div>
              <div className="text-xs text-slate-500 mt-2">
                review_pending 队列
              </div>
            </div>
            <div className="bg-card border border-slate-800 rounded-2xl p-5">
              <div className="text-xs text-slate-400 mb-2">当前策略</div>
              <div className="text-lg font-bold text-slate-100 break-all">
                {currentRuntimeStrategyName}
              </div>
              <div className="text-xs text-slate-500 mt-2">
                {currentRuntimeStrategyId}
                {currentRuntimeStrategyIds.length > 1
                  ? ` | active: ${currentRuntimeStrategyIds.join(", ")}`
                  : ""}
                {` | ${currentRuntimeMode} / ${currentRuntimeArbiter}`}
              </div>
            </div>
            <div className="bg-card border border-slate-800 rounded-2xl p-5">
              <div className="text-xs text-slate-400 mb-2">运行时装载</div>
              <div
                className={`text-lg font-bold ${workbenchExecutionSummary.runtimeLoaded ? "text-success" : "text-warning"}`}
              >
                {workbenchExecutionSummary.runtimeLoaded ? "已装载" : "未装载"}
              </div>
              <div className="text-xs text-slate-500 mt-2">
                策略 runtime 健康快照
              </div>
            </div>
          </div>

          <div className="grid grid-cols-1 xl:grid-cols-12 gap-6 flex-1 min-h-0">
            <div className="xl:col-span-4 bg-card border border-slate-800 rounded-2xl p-6 flex flex-col min-h-[520px]">
              <h3 className="text-lg font-bold mb-4">当前持仓</h3>
              {visibleOpenPositions.length > 0 ? (
                <div className="space-y-4 flex-1 overflow-y-auto pr-2 custom-scrollbar">
                  {visibleOpenPositions.map((pos: any, idx: number) => (
                    <div
                      key={idx}
                      className="bg-[#0A0E17] border border-slate-800 rounded-xl p-4"
                    >
                      <div className="flex justify-between items-center mb-2">
                        <div className="flex items-center gap-2">
                          <span
                            className={`text-xs font-bold px-2 py-1 rounded ${pos.side === "BUY" ? "bg-success/20 text-success" : "bg-danger/20 text-danger"}`}
                          >
                            {pos.side}
                          </span>
                          <span className="font-mono font-bold">XAUUSD</span>
                        </div>
                        <span
                          className={`font-mono font-bold ${pos.pnl > 0 ? "text-success" : pos.pnl < 0 ? "text-danger" : "text-slate-400"}`}
                        >
                          {pos.pnl > 0 ? "+" : ""}
                          {pos.pnl}
                        </span>
                      </div>
                      <div className="grid grid-cols-2 gap-2 text-xs text-slate-400 mt-3">
                        <div>
                          <span className="block text-[10px] uppercase text-slate-500">
                            Ticket
                          </span>
                          <span className="font-mono">{pos.ticket}</span>
                        </div>
                        <div>
                          <span className="block text-[10px] uppercase text-slate-500">
                            Volume
                          </span>
                          <span className="font-mono">{pos.volume}</span>
                        </div>
                        <div>
                          <span className="block text-[10px] uppercase text-slate-500">
                            Entry
                          </span>
                          <span className="font-mono">{pos.entry}</span>
                        </div>
                        <div>
                          <span className="block text-[10px] uppercase text-slate-500">
                            SL / TP
                          </span>
                          <span className="font-mono text-warning">
                            {pos.sl} / {pos.tp}
                          </span>
                        </div>
                      </div>
                      <div className="mt-3 space-y-2 text-xs text-slate-300">
                        <div>
                          开仓归因:{" "}
                          <span className="font-mono text-slate-100">
                            {String(pos.entry_owner_strategy_id || "-")}
                          </span>
                          {" @ "}
                          <span className="font-mono text-primary">
                            {String(pos.entry_owner_instance_id || "-")}
                          </span>
                        </div>
                        <div>
                          出场 Owner:{" "}
                          <span className="font-mono text-slate-100">
                            {String(pos.exit_owner_strategy_id || "-")}
                          </span>
                          {" @ "}
                          <span className="font-mono text-warning">
                            {String(pos.exit_owner_instance_id || "-")}
                          </span>
                        </div>
                        {Array.isArray(pos.contributors) &&
                        pos.contributors.length > 0 ? (
                          <div className="flex flex-wrap gap-2 pt-1">
                            {pos.contributors
                              .slice(0, 4)
                              .map((item: any, contributorIdx: number) => (
                                <span
                                  key={`${String(pos.ticket || idx)}::${contributorIdx}`}
                                  className="px-2 py-1 rounded-lg border border-slate-700 bg-slate-900/80 text-[11px] font-mono text-slate-200"
                                >
                                  {String(item.strategy_id || "-")}@
                                  {String(item.instance_id || "-")} ·{" "}
                                  {Number(item.signed_score || 0) >= 0
                                    ? "+"
                                    : ""}
                                  {Number(item.signed_score || 0).toFixed(2)}
                                </span>
                              ))}
                          </div>
                        ) : (
                          <div className="text-slate-500">
                            暂无 contributors
                          </div>
                        )}
                      </div>
                    </div>
                  ))}
                </div>
              ) : (
                <div className="flex-1 flex items-center justify-center text-slate-500 italic">
                  暂无持仓
                </div>
              )}
            </div>

            <div className="xl:col-span-4 bg-card border border-slate-800 rounded-2xl p-6 flex flex-col min-h-[520px]">
              <div className="flex items-center justify-between mb-4">
                <h3 className="text-lg font-bold flex items-center gap-2">
                  <Activity className="w-5 h-5 text-primary" /> 执行链状态
                </h3>
                <span className="text-xs text-slate-500">execution_state</span>
              </div>
              <div className="space-y-3 flex-1 overflow-y-auto pr-2 custom-scrollbar">
                {(workbenchExecution.activeSignals || []).length > 0 ? (
                  workbenchExecution.activeSignals.map((signal: any) => (
                    <div
                      key={signal.traceId || signal.signalId}
                      className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4"
                    >
                      <div className="flex items-center justify-between gap-3">
                        <div>
                          <div className="text-sm font-bold text-slate-100">
                            {String(signal.signalId || "-")}
                          </div>
                          <div className="text-xs text-slate-500 mt-1">
                            {String(signal.strategyId || "unknown")} ·{" "}
                            {String(signal.side || "UNKNOWN")}
                          </div>
                        </div>
                        <span className="px-2.5 py-1 rounded-full text-[11px] bg-primary/10 text-primary border border-primary/20">
                          {String(signal.state || "CREATED")}
                        </span>
                      </div>
                      <div className="mt-3 text-xs text-slate-400 leading-5">
                        {String(signal.reason || "暂无额外说明")}
                      </div>
                      <div className="mt-3 grid grid-cols-2 gap-2 text-[11px] text-slate-500 font-mono">
                        <div>Action: {String(signal.action || "-")}</div>
                        <div>Entry: {String(signal.entry || "-")}</div>
                        <div className="col-span-2">
                          Trace: {String(signal.traceId || "-")}
                        </div>
                      </div>
                    </div>
                  ))
                ) : (
                  <div className="h-full flex items-center justify-center text-slate-500 italic py-12">
                    当前没有活跃执行链状态
                  </div>
                )}
              </div>
            </div>

            <div className="xl:col-span-4 bg-card border border-slate-800 rounded-2xl p-6 flex flex-col min-h-[520px]">
              <div className="flex justify-between items-center mb-6">
                <h3 className="text-lg font-bold flex items-center gap-2">
                  <Bell className="w-5 h-5 text-warning" /> 待复核信号
                  {signalReviewPendingCount > 0 && (
                    <span className="bg-warning/20 text-warning text-xs px-2 py-0.5 rounded-full ml-2">
                      {signalReviewPendingCount} 条待处理
                    </span>
                  )}
                </h3>
              </div>

              <div className="flex-1 space-y-4 overflow-y-auto pr-2 custom-scrollbar">
                {signalReviewPendingCount > 0 ? (
                  signalReviewQueue.map((signal) => (
                    <div
                      key={signal.id}
                      className="border border-warning/30 bg-warning/5 rounded-xl p-5 relative overflow-hidden"
                    >
                      <div className="absolute top-0 left-0 w-1 h-full bg-warning"></div>
                      <div className="flex justify-between items-start mb-4">
                        <div>
                          <div className="flex items-center gap-3 mb-1">
                            <span
                              className={`${signal.side === "BUY" ? "bg-success" : "bg-danger"} text-white text-xs font-bold px-2 py-1 rounded`}
                            >
                              {signal.side}
                            </span>
                            <span className="font-mono font-bold text-lg">
                              XAUUSD
                            </span>
                            <span className="text-slate-400 text-sm">
                              @ {signal.entry}
                            </span>
                          </div>
                          <p className="text-sm text-slate-400">
                            信号 ID: {signal.id}
                          </p>
                        </div>
                        <div className="text-right">
                          <div className="text-2xl font-bold text-warning">
                            {(signal.confidence * 100).toFixed(0)}%
                          </div>
                          <div className="text-[10px] text-slate-400 uppercase tracking-wider">
                            AI 置信度
                          </div>
                        </div>
                      </div>

                      <div className="bg-[#0A0E17] rounded-lg p-3 text-sm font-mono text-slate-300 mb-4 border border-slate-800">
                        <span className="text-danger">[拦截原因]</span>{" "}
                        {signal.reason}
                      </div>

                      <div className="flex gap-3">
                        <button
                          onClick={() =>
                            handleSignalAction(signal.id, "approve")
                          }
                          className="flex-1 py-2.5 bg-success hover:bg-emerald-500 text-white font-bold rounded-lg transition-colors flex justify-center items-center gap-2"
                        >
                          <CheckCircle2 className="w-4 h-4" /> 批准执行
                        </button>
                        <button
                          onClick={() =>
                            handleSignalAction(signal.id, "reject")
                          }
                          className="flex-1 py-2.5 bg-slate-800 hover:bg-slate-700 text-slate-300 font-bold rounded-lg transition-colors flex justify-center items-center gap-2 border border-slate-700"
                        >
                          <AlertCircle className="w-4 h-4" /> 否决信号
                        </button>
                      </div>
                    </div>
                  ))
                ) : (
                  <div className="h-full flex items-center justify-center text-slate-500 italic py-12">
                    暂无需要人工复核的信号
                  </div>
                )}
              </div>
            </div>
          </div>
        </div>
      );
    }

    const renderUpdateCenter = () => (
      <div className="bg-card border border-slate-800 rounded-2xl p-6">
        <div className="flex flex-col xl:flex-row xl:items-start xl:justify-between gap-4">
          <div className="min-w-0">
            <h3 className="text-lg font-bold flex items-center gap-2">
              <DatabaseZap className="w-5 h-5 text-primary" /> 无感更新中心
            </h3>
            <div className="mt-3 flex flex-wrap gap-2 text-xs">
              <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-[#0A0E17] text-slate-300">
                程序版本 {updateStatus.version?.version || "0.0.0"}
              </span>
              <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-[#0A0E17] text-slate-300">
                生效版本 {updateStatus.currentRelease?.version || "未注册"}
              </span>
              <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-[#0A0E17] text-slate-300">
                候选版本 {updateStatus.candidateRelease?.version || "无"}
              </span>
            </div>
          </div>
          <div className="flex flex-wrap gap-2 xl:justify-end">
            <button
              onClick={handleCheckUpdates}
              disabled={updateLoading}
              className="px-4 py-2 bg-slate-800 hover:bg-slate-700 disabled:opacity-50 text-slate-200 text-sm font-medium rounded-lg transition-colors flex items-center gap-2 border border-slate-700"
            >
              <Activity className="w-4 h-4" /> 检查更新
            </button>
            <button
              onClick={handleApplyUpdate}
              disabled={updateLoading}
              className="px-4 py-2 bg-primary hover:bg-blue-500 disabled:opacity-50 text-white text-sm font-medium rounded-lg transition-colors flex items-center gap-2"
            >
              <Save className="w-4 h-4" /> 安装候选版本
            </button>
            <button
              onClick={handlePromoteUpdate}
              disabled={
                updateLoading || !updateStatus.candidateRelease?.version
              }
              className="px-4 py-2 bg-success hover:bg-emerald-500 disabled:opacity-50 text-white text-sm font-medium rounded-lg transition-colors flex items-center gap-2"
            >
              <CheckCircle2 className="w-4 h-4" /> 晋升候选版本
            </button>
            <button
              onClick={handleRollbackUpdate}
              disabled={updateLoading}
              className="px-4 py-2 bg-danger hover:bg-red-500 disabled:opacity-50 text-white text-sm font-medium rounded-lg transition-colors flex items-center gap-2"
            >
              <RotateCcw className="w-4 h-4" /> 回滚版本
            </button>
          </div>
        </div>

        <div className="grid grid-cols-1 xl:grid-cols-3 gap-4 mt-6">
          <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4 min-w-0">
            <div className="text-xs text-slate-400 mb-2">更新状态</div>
            <div className="text-lg font-bold text-slate-100 break-all">
              {updateStatus.updateState?.status || "idle"}
            </div>
            <div className="text-xs text-slate-500 mt-2 break-all">
              目标版本 {updateStatus.updateState?.target_version || "-"}
            </div>
          </div>
          <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4 min-w-0">
            <div className="text-xs text-slate-400 mb-2">切换门禁</div>
            <div
              className={`text-lg font-bold ${updateStatus.quality?.safe_to_switch ? "text-success" : "text-warning"}`}
            >
              {updateStatus.quality?.safe_to_switch ? "允许切换" : "暂缓切换"}
            </div>
            <div className="text-xs text-slate-500 mt-2">
              阻塞项 {(updateStatus.quality?.blockers || []).length}
            </div>
          </div>
          <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4 min-w-0">
            <div className="text-xs text-slate-400 mb-2">学习质量</div>
            <div className="text-base font-bold text-slate-100 break-words leading-6">
              {updateStatus.quality?.learning?.training_gate || "UNKNOWN"}
            </div>
            <div className="mt-2 text-xs text-slate-500 break-words leading-5">
              {updateStatus.quality?.learning?.learning_state || "UNKNOWN"}
            </div>
          </div>
        </div>

        <div className="mt-4 rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
          <div className="text-xs text-slate-400 mb-2">更新源地址</div>
          <div className="flex flex-col xl:flex-row gap-3 mb-4">
            <input
              value={updateConfig.update_manifest_url}
              onChange={(e) =>
                setUpdateConfig((prev) => ({
                  ...prev,
                  update_manifest_url: e.target.value,
                }))
              }
              placeholder="填写 update_manifest.json 的本地路径或 URL"
              className="flex-1 min-w-0 bg-[#05080F] border border-slate-700 rounded-lg px-3 py-2 text-sm text-slate-200 focus:outline-none focus:border-primary"
            />
            <button
              onClick={handleSaveUpdateConfig}
              disabled={updateLoading}
              className="px-4 py-2 bg-slate-800 hover:bg-slate-700 disabled:opacity-50 text-slate-200 text-sm font-medium rounded-lg transition-colors border border-slate-700 whitespace-nowrap"
            >
              保存更新源
            </button>
          </div>
          <div className="text-xs text-slate-400 mb-2">当前运行态阻塞项</div>
          <div className="flex flex-wrap gap-2">
            {(updateStatus.quality?.blockers || []).length > 0 ? (
              (updateStatus.quality?.blockers || []).map((item: string) => (
                <span
                  key={item}
                  className="px-2 py-1 rounded-full text-xs bg-warning/10 text-warning border border-warning/20 break-all"
                >
                  {item}
                </span>
              ))
            ) : (
              <span className="text-sm text-success">
                当前无阻塞项，可执行候选版本晋升
              </span>
            )}
          </div>
        </div>
      </div>
    );

    if (menu === "updates") {
      return (
        <div className="max-w-5xl w-full mx-auto p-8 space-y-6">
          <div className="flex justify-between items-center mb-6">
            <h2 className="text-2xl font-bold">更新中心</h2>
          </div>
          {renderUpdateCenter()}
        </div>
      );
    }

    if (menu === "settings") {
      return (
        <div className="max-w-6xl w-full mx-auto p-8 space-y-6">
          <div className="flex justify-between items-center mb-6">
            <h2 className="text-2xl font-bold">风控与参数</h2>
            <div className="flex gap-2">
              {/* 隐藏离线网格训练按钮，防止过度拟合
              <button
                onClick={handleApplyBestParams}
                className="px-4 py-2 bg-amber-900 hover:bg-amber-800 text-amber-200 text-sm font-medium rounded-lg transition-colors flex items-center gap-2 border border-amber-700"
              >
                <TrendingUp className="w-4 h-4" /> 应用训练最优
              </button>
              */}
              <button
                onClick={handleResetParams}
                className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-slate-200 text-sm font-medium rounded-lg transition-colors flex items-center gap-2 border border-slate-700"
              >
                <RotateCcw className="w-4 h-4" /> 恢复默认
              </button>
              <button
                onClick={handleSaveParams}
                className="px-4 py-2 bg-primary hover:bg-blue-500 text-white text-sm font-medium rounded-lg transition-colors flex items-center gap-2 shadow-[0_0_10px_rgba(59,130,246,0.3)]"
              >
                <Save className="w-4 h-4" /> 保存配置
              </button>
            </div>
          </div>

          <div className="grid grid-cols-1 gap-6">
            <div className="bg-card border border-slate-800 rounded-2xl p-6">
              <div className="flex items-center justify-between gap-4 mb-6">
                <div>
                  <h3 className="text-lg font-bold flex items-center gap-2">
                    <Shield className="w-5 h-5 text-primary" /> Governor
                    实时快照
                  </h3>
                  <p className="text-xs text-slate-500 mt-1">
                    直接读取 Governor / 风控快照 / Blackboard / 治理状态
                  </p>
                </div>
                <div
                  className={`px-3 py-1.5 rounded-full text-xs font-medium border ${workbenchRiskSummary.blocked ? "border-danger/30 bg-danger/10 text-danger" : "border-success/30 bg-success/10 text-success"}`}
                >
                  {workbenchRiskSummary.blocked
                    ? "Governor Blocked"
                    : "Governor Pass"}
                </div>
              </div>

              <div className="grid grid-cols-1 xl:grid-cols-4 gap-4 mb-6">
                <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                  <div className="text-xs text-slate-400 mb-2">风险档位</div>
                  <div className="text-lg font-bold text-slate-100">
                    {String(
                      workbenchGovernor.riskLevel ||
                        riskParams.risk_level ||
                        "balanced",
                    )}
                  </div>
                </div>
                <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                  <div className="text-xs text-slate-400 mb-2">仓位缩放</div>
                  <div className="text-lg font-bold text-slate-100">
                    {Number(
                      workbenchRiskSummary.positionMultiplier || 1,
                    ).toFixed(2)}
                    x
                  </div>
                </div>
                <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                  <div className="text-xs text-slate-400 mb-2">账户总亏</div>
                  <div className="text-lg font-bold text-slate-100">
                    {Number(
                      workbenchRiskSummary.accountLossCurrentPct ||
                        status.account_total_loss_current_pct ||
                        0,
                    ).toFixed(2)}
                    %
                  </div>
                </div>
                <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                  <div className="text-xs text-slate-400 mb-2">阻断项数量</div>
                  <div className="text-lg font-bold text-warning">
                    {Number(workbenchRiskSummary.blockerCount || 0)}
                  </div>
                </div>
              </div>

              <div className="grid grid-cols-1 xl:grid-cols-3 gap-4">
                <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                  <div className="text-xs text-slate-400 mb-3">
                    Governor 阈值
                  </div>
                  <div className="space-y-2 text-sm text-slate-300">
                    <div className="flex justify-between">
                      <span>最小置信度</span>
                      <span className="font-mono">
                        {Number(
                          workbenchGovernor.minConfidencePct ||
                            riskParams.min_confidence ||
                            0,
                        ).toFixed(1)}
                        %
                      </span>
                    </div>
                    <div className="flex justify-between">
                      <span>最大仓位</span>
                      <span className="font-mono">
                        {Number(
                          workbenchGovernor.maxPositionSize ||
                            riskParams.max_position_size ||
                            0,
                        ).toFixed(2)}
                      </span>
                    </div>
                    <div className="flex justify-between">
                      <span>最大持仓数</span>
                      <span className="font-mono">
                        {Number(
                          workbenchGovernor.maxOpenPositions ||
                            riskParams.max_open_positions ||
                            0,
                        )}
                      </span>
                    </div>
                    <div className="flex justify-between">
                      <span>SL / TP</span>
                      <span className="font-mono">
                        {Number(
                          workbenchGovernor.slPips || riskParams.sl_pips || 0,
                        )}{" "}
                        /{" "}
                        {Number(
                          workbenchGovernor.tpPips || riskParams.tp_pips || 0,
                        )}
                      </span>
                    </div>
                  </div>
                </div>
                <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                  <div className="text-xs text-slate-400 mb-3">阻断与拒绝</div>
                  <div className="space-y-3 text-sm">
                    <div className="rounded-lg border border-slate-800 px-3 py-2">
                      <div className="text-slate-500 text-[11px] mb-1">
                        risk_block
                      </div>
                      <div className="text-slate-200 leading-5 break-words">
                        {String(
                          workbenchGovernor.riskBlock?.summary ||
                            workbenchGovernor.riskBlock?.rawReason ||
                            "无",
                        )}
                      </div>
                    </div>
                    <div className="rounded-lg border border-slate-800 px-3 py-2">
                      <div className="text-slate-500 text-[11px] mb-1">
                        final_reject
                      </div>
                      <div className="text-slate-200 leading-5 break-words">
                        {String(workbenchGovernor.finalReject?.reason || "无")}
                      </div>
                    </div>
                  </div>
                </div>
                <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                  <div className="text-xs text-slate-400 mb-3">
                    Blackboard 风控
                  </div>
                  <div className="space-y-2 text-sm text-slate-300">
                    <div className="flex justify-between">
                      <span>Macro Bias</span>
                      <span className="font-mono">
                        {String(
                          workbenchRiskBlackboard.Macro_Commander?.bias || "-",
                        )}
                      </span>
                    </div>
                    <div className="flex justify-between">
                      <span>Session Regime</span>
                      <span className="font-mono">
                        {String(
                          workbenchRiskBlackboard.Micro_Sniper
                            ?.current_regime || "-",
                        )}
                      </span>
                    </div>
                    <div className="flex justify-between">
                      <span>Defensive</span>
                      <span className="font-mono">
                        {String(
                          workbenchRiskBlackboard.Micro_Sniper?.is_defensive_env
                            ? "true"
                            : "false",
                        )}
                      </span>
                    </div>
                    <div className="flex justify-between">
                      <span>Governor Multiplier</span>
                      <span className="font-mono">
                        {Number(
                          workbenchRiskBlackboard.Risk_Commissar
                            ?.position_multiplier || 1,
                        ).toFixed(2)}
                        x
                      </span>
                    </div>
                  </div>
                </div>
              </div>

              {(workbenchGovernor.blockers || []).length > 0 && (
                <div className="mt-4 flex flex-wrap gap-2">
                  {(workbenchGovernor.blockers || []).map((item: string) => (
                    <span
                      key={item}
                      className="px-2 py-1 rounded-full text-xs bg-danger/10 text-danger border border-danger/20"
                    >
                      {item}
                    </span>
                  ))}
                </div>
              )}
            </div>

            {/* 风险档位快速切换 */}
            <div className="bg-card border border-slate-800 rounded-2xl p-6">
              <h3 className="text-lg font-bold mb-4 flex items-center gap-2">
                <ShieldAlert className="w-5 h-5 text-primary" /> 全局风险档位
              </h3>
              <div className="grid grid-cols-3 gap-4">
                <div
                  onClick={() => handleRiskLevelChange("conservative")}
                  className={`border ${riskParams.risk_level === "conservative" ? "border-success bg-success/5" : "border-slate-700 opacity-50 hover:border-success"} rounded-xl p-4 cursor-pointer transition-colors relative overflow-hidden`}
                >
                  {riskParams.risk_level === "conservative" && (
                    <div className="absolute top-0 right-0 bg-success text-white text-[10px] font-bold px-2 py-0.5 rounded-bl-lg">
                      当前
                    </div>
                  )}
                  <div className="font-bold text-lg mb-1 text-success">
                    保守 (Conservative)
                  </div>
                  <div className="text-xs text-slate-400">
                    仓位极小，严格止损，只做高确定性趋势
                  </div>
                </div>
                <div
                  onClick={() => handleRiskLevelChange("balanced")}
                  className={`border ${riskParams.risk_level === "balanced" ? "border-primary bg-primary/5" : "border-slate-700 opacity-50 hover:border-primary"} rounded-xl p-4 cursor-pointer transition-colors relative overflow-hidden`}
                >
                  {riskParams.risk_level === "balanced" && (
                    <div className="absolute top-0 right-0 bg-primary text-white text-[10px] font-bold px-2 py-0.5 rounded-bl-lg">
                      当前
                    </div>
                  )}
                  <div className="font-bold text-lg mb-1 text-primary">
                    平衡 (Balanced)
                  </div>
                  <div className="text-xs text-slate-400">
                    标准仓位，动态止盈止损，允许日内震荡刮单
                  </div>
                </div>
                <div
                  onClick={() => handleRiskLevelChange("aggressive")}
                  className={`border ${riskParams.risk_level === "aggressive" ? "border-danger bg-danger/5" : "border-slate-700 opacity-50 hover:border-danger"} rounded-xl p-4 cursor-pointer transition-colors relative overflow-hidden`}
                >
                  {riskParams.risk_level === "aggressive" && (
                    <div className="absolute top-0 right-0 bg-danger text-white text-[10px] font-bold px-2 py-0.5 rounded-bl-lg">
                      当前
                    </div>
                  )}
                  <div className="font-bold text-lg mb-1 text-danger">
                    激进 (Aggressive)
                  </div>
                  <div className="text-xs text-slate-400">
                    仓位放大，容忍较大回撤，博取趋势最大利润
                  </div>
                </div>
              </div>
            </div>

            {/* 核心参数表单 */}
            <div className="bg-card border border-slate-800 rounded-2xl p-6">
              <h3 className="text-lg font-bold mb-6 border-b border-slate-800 pb-4">
                交易执行参数
              </h3>

              <div className="space-y-6">
                <div className="grid grid-cols-2 gap-8">
                  <div>
                    <label className="flex justify-between text-sm font-medium text-slate-300 mb-2">
                      <span>单笔最大仓位 (Lots)</span>
                      <span className="text-primary font-mono">
                        {riskParams.max_position_size.toFixed(2)}
                      </span>
                    </label>
                    <div className="flex items-center gap-4">
                      <input
                        type="range"
                        min="0.01"
                        max="1.00"
                        step="0.01"
                        value={riskParams.max_position_size}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            max_position_size: parseFloat(e.target.value),
                          })
                        }
                        className="w-full accent-primary h-2 bg-slate-800 rounded-lg appearance-none cursor-pointer"
                      />
                      <input
                        type="number"
                        value={riskParams.max_position_size}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            max_position_size: parseFloat(e.target.value),
                          })
                        }
                        className="w-20 bg-[#0A0E17] border border-slate-700 rounded-lg px-2 py-1.5 text-slate-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 font-mono text-center"
                      />
                    </div>
                    <div className="flex justify-between text-[10px] text-slate-500 mt-1">
                      <span>保守: 0.05</span>
                      <span>激进: 0.20</span>
                    </div>
                  </div>
                  <div>
                    <label className="flex justify-between text-sm font-medium text-slate-300 mb-2">
                      <span>最大同时持仓数</span>
                      <span className="text-primary font-mono">
                        {riskParams.max_open_positions}
                      </span>
                    </label>
                    <div className="flex items-center gap-4">
                      <input
                        type="range"
                        min="1"
                        max="10"
                        step="1"
                        value={riskParams.max_open_positions}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            max_open_positions: parseInt(e.target.value),
                          })
                        }
                        className="w-full accent-primary h-2 bg-slate-800 rounded-lg appearance-none cursor-pointer"
                      />
                      <input
                        type="number"
                        value={riskParams.max_open_positions}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            max_open_positions: parseInt(e.target.value),
                          })
                        }
                        className="w-20 bg-[#0A0E17] border border-slate-700 rounded-lg px-2 py-1.5 text-slate-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 font-mono text-center"
                      />
                    </div>
                  </div>
                </div>

                <div className="grid grid-cols-2 gap-8">
                  <div>
                    <label className="flex justify-between text-sm font-medium text-slate-300 mb-2">
                      <span>默认止损点数 (SL Pips)</span>
                      <span className="text-primary font-mono">
                        {riskParams.sl_pips}
                      </span>
                    </label>
                    <div className="flex items-center gap-4">
                      <input
                        type="range"
                        min="10"
                        max="200"
                        step="5"
                        value={riskParams.sl_pips}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            sl_pips: parseInt(e.target.value),
                          })
                        }
                        className="w-full accent-primary h-2 bg-slate-800 rounded-lg appearance-none cursor-pointer"
                      />
                      <input
                        type="number"
                        value={riskParams.sl_pips}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            sl_pips: parseInt(e.target.value),
                          })
                        }
                        className="w-20 bg-[#0A0E17] border border-slate-700 rounded-lg px-2 py-1.5 text-slate-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 font-mono text-center"
                      />
                    </div>
                  </div>
                  <div>
                    <label className="flex justify-between text-sm font-medium text-slate-300 mb-2">
                      <span>默认止盈点数 (TP Pips)</span>
                      <span className="text-primary font-mono">
                        {riskParams.tp_pips}
                      </span>
                    </label>
                    <div className="flex items-center gap-4">
                      <input
                        type="range"
                        min="20"
                        max="500"
                        step="10"
                        value={riskParams.tp_pips}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            tp_pips: parseInt(e.target.value),
                          })
                        }
                        className="w-full accent-primary h-2 bg-slate-800 rounded-lg appearance-none cursor-pointer"
                      />
                      <input
                        type="number"
                        value={riskParams.tp_pips}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            tp_pips: parseInt(e.target.value),
                          })
                        }
                        className="w-20 bg-[#0A0E17] border border-slate-700 rounded-lg px-2 py-1.5 text-slate-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 font-mono text-center"
                      />
                    </div>
                  </div>
                </div>

                <div className="grid grid-cols-2 gap-8">
                  <div>
                    <label className="flex justify-between text-sm font-medium text-slate-300 mb-2">
                      <span>账户总亏止损 (%)</span>
                      <span className="text-danger font-mono">
                        {Number(
                          riskParams.account_total_loss_stop_pct || 0,
                        ).toFixed(1)}
                        %
                      </span>
                    </label>
                    <div className="flex items-center gap-4">
                      <input
                        type="range"
                        min="0"
                        max="100"
                        step="1"
                        value={riskParams.account_total_loss_stop_pct}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            account_total_loss_stop_pct: parseFloat(
                              e.target.value,
                            ),
                          })
                        }
                        className="w-full accent-danger h-2 bg-slate-800 rounded-lg appearance-none cursor-pointer"
                      />
                      <input
                        type="number"
                        min="0"
                        max="100"
                        step="1"
                        value={riskParams.account_total_loss_stop_pct}
                        onChange={(e) =>
                          setRiskParams({
                            ...riskParams,
                            account_total_loss_stop_pct: parseFloat(
                              e.target.value || "0",
                            ),
                          })
                        }
                        className="w-24 bg-[#0A0E17] border border-slate-700 rounded-lg px-2 py-1.5 text-slate-200 focus:outline-none focus:border-danger focus:ring-1 focus:ring-danger/50 font-mono text-center"
                      />
                    </div>
                    <div className="mt-2 text-[11px] text-slate-500">
                      账户总亏损达到该阈值后，系统自动停止新开仓；填 `0`
                      表示关闭此风控。
                    </div>
                  </div>
                  <div className="rounded-xl border border-slate-800 bg-[#0A0E17] p-4">
                    <div className="mb-2 text-sm font-medium text-slate-300">
                      总亏止损实时状态
                    </div>
                    <div className="space-y-2 text-sm text-slate-400">
                      <div className="flex items-center justify-between">
                        <span>当前总亏</span>
                        <span className="font-mono text-slate-200">
                          {Number(
                            status.account_total_loss_current_pct || 0,
                          ).toFixed(2)}
                          %
                        </span>
                      </div>
                      <div className="flex items-center justify-between">
                        <span>触发阈值</span>
                        <span className="font-mono text-slate-200">
                          {Number(
                            status.account_total_loss_stop_pct ||
                              riskParams.account_total_loss_stop_pct ||
                              0,
                          ).toFixed(2)}
                          %
                        </span>
                      </div>
                      <div className="flex items-center justify-between">
                        <span>取值来源</span>
                        <span className="font-mono text-slate-200">
                          {String(
                            status.account_total_loss_stop_source || "NONE",
                          )}
                        </span>
                      </div>
                      <div
                        className={`rounded-lg border px-3 py-2 text-xs font-medium ${
                          status.account_total_loss_stop_active
                            ? "border-danger/40 bg-danger/10 text-danger"
                            : "border-success/30 bg-success/10 text-success"
                        }`}
                      >
                        {status.account_total_loss_stop_active
                          ? "总亏止损已触发，系统严禁新开仓"
                          : "总亏止损未触发，系统仍可继续交易"}
                      </div>
                    </div>
                  </div>
                </div>

                <div className="pt-6 border-t border-slate-800">
                  <label className="flex items-center space-x-3 cursor-pointer">
                    <input
                      type="checkbox"
                      checked={riskParams.human_in_the_loop}
                      onChange={(e) =>
                        setRiskParams({
                          ...riskParams,
                          human_in_the_loop: e.target.checked,
                        })
                      }
                      className="w-5 h-5 rounded border-slate-700 text-primary focus:ring-primary/50 bg-[#0A0E17]"
                    />
                    <div>
                      <span className="block text-sm font-medium text-slate-300">
                        启用 Agent 二次复核 (Human-in-the-loop)
                      </span>
                      <span className="block text-[10px] text-slate-500 mt-0.5">
                        当信号置信度低于阈值时，不自动下单，而是推送到「待复核」队列
                      </span>
                    </div>
                  </label>
                </div>

                {riskParams.human_in_the_loop && (
                  <div className="pl-8 transition-all">
                    <label className="block text-sm font-medium text-slate-300 mb-2">
                      自动执行最小置信度阈值 (%)
                    </label>
                    <input
                      type="number"
                      value={riskParams.min_confidence}
                      onChange={(e) =>
                        setRiskParams({
                          ...riskParams,
                          min_confidence: parseFloat(e.target.value),
                        })
                      }
                      className="w-1/2 bg-[#0A0E17] border border-slate-700 rounded-lg px-4 py-2.5 text-slate-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 font-mono"
                    />
                  </div>
                )}
              </div>
            </div>
          </div>
        </div>
      );
    }

    if (menu === "strategyMarketplace") {
      return (
        <div className="max-w-6xl w-full mx-auto p-8 space-y-6">
          <div className="flex items-center gap-2">
            <button
              onClick={() => setActiveMenu("strategyMarketplace")}
              className="px-4 py-2 rounded-lg bg-primary text-white text-sm font-medium"
            >
              策略集市
            </button>
            <button
              onClick={() => setActiveMenu("robotDashboard")}
              className="px-4 py-2 rounded-lg bg-slate-800 text-slate-300 text-sm font-medium hover:bg-slate-700 transition-colors"
            >
              机器人看板
            </button>
          </div>

          <div className="flex items-center justify-between gap-3 rounded-2xl border border-slate-800 bg-card p-4">
            <div>
              <div className="text-sm font-semibold text-slate-100">
                策略集市视图切换
              </div>
              <div className="mt-1 text-xs text-slate-400">
                简化版面向普通用户；专业版保留运维侧的组合、发布和协同配置。
              </div>
            </div>
            <div className="inline-flex rounded-xl border border-slate-700 bg-slate-950/70 p-1">
              <button
                onClick={() => setStrategyMarketplaceView("simple")}
                className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
                  strategyMarketplaceView === "simple"
                    ? "bg-primary text-white"
                    : "text-slate-300 hover:text-slate-100"
                }`}
              >
                简化版
              </button>
              <button
                onClick={() => setStrategyMarketplaceView("pro")}
                className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
                  strategyMarketplaceView === "pro"
                    ? "bg-primary text-white"
                    : "text-slate-300 hover:text-slate-100"
                }`}
              >
                专业版
              </button>
            </div>
          </div>

          {strategyMarketplaceView === "pro" ? (
            <>
              <div className="bg-card border border-slate-800 rounded-2xl p-6">
                <h3 className="text-xl font-bold text-slate-100">组合策略</h3>
                <div className="text-sm text-slate-400 mt-1">
                  输入组合名，并选择至少 2 个策略组件。
                </div>
                <div className="mt-4 space-y-4">
                  <input
                    value={compositeName}
                    onChange={(e) => setCompositeName(e.target.value)}
                    placeholder="组合策略名称（如：黄金多因子）"
                    className="w-full md:w-[420px] bg-[#0A0E17] border border-slate-700 rounded-xl px-4 py-3 text-slate-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50"
                  />
                  <div className="flex flex-wrap gap-2">
                    {(workbenchMarketplace.strategies || []).map(
                      (strategy: any) => {
                        const sid = String(strategy.id || "");
                        const selected = compositeComponents.includes(sid);
                        return (
                          <button
                            key={`component-${sid}`}
                            type="button"
                            onClick={() =>
                              setCompositeComponents((prev) =>
                                prev.includes(sid)
                                  ? prev.filter((item) => item !== sid)
                                  : [...prev, sid],
                              )
                            }
                            className={`px-3 py-1.5 rounded-lg border text-sm font-medium transition-colors ${selected ? "border-primary/60 bg-primary/15 text-primary" : "border-slate-700 bg-slate-900/40 text-slate-200 hover:bg-slate-800"}`}
                          >
                            {sid}
                          </button>
                        );
                      },
                    )}
                  </div>
                  <button
                    onClick={handleCreateComposite}
                    className="px-4 py-2 rounded-lg bg-primary hover:bg-blue-500 text-white text-sm font-medium transition-colors"
                  >
                    创建组合
                  </button>
                </div>
              </div>

              <div className="bg-card border border-slate-800 rounded-2xl p-6">
                <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500 mb-3">
                  产品层
                </div>
                <h3 className="text-lg font-bold text-slate-100">
                  策略资产生命周期管理
                </h3>
                <p className="text-sm text-slate-400 mt-2">
                  严格按流程执行：选择策略 → 部署/停用 → 发布/回滚。
                </p>
              </div>

              <div className="bg-card border border-primary/30 rounded-2xl p-6 space-y-5">
                <div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
                  <div>
                    <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500">
                      协同协议
                    </div>
                    <h3 className="text-lg font-bold text-slate-100">
                      多 Agent 与多策略决策合同
                    </h3>
                    <p className="text-sm text-slate-400 mt-1">
                      Agent
                      只做门控与限权，策略只产出信号，最终由多策略仲裁器统一落单。
                    </p>
                  </div>
                  <button
                    onClick={handleSaveDecisionPolicy}
                    disabled={decisionPolicySaving}
                    className="px-4 py-2 rounded-lg bg-primary hover:bg-blue-500 disabled:opacity-40 text-white text-sm font-medium transition-colors"
                  >
                    {decisionPolicySaving ? "保存中..." : "保存协同协议"}
                  </button>
                </div>

                <div className="rounded-2xl border border-cyan-900/40 bg-cyan-950/15 p-4">
                  <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
                    <div>
                      <div className="text-sm font-semibold text-cyan-100">
                        运行时统一合同来源
                      </div>
                      <div className="mt-1 text-xs text-cyan-100/70">
                        当前工作台显示的协议、宏观方向和执行建议，均应来自同一份运行时合同，而不是各模块单独猜测。
                      </div>
                    </div>
                    <div className="rounded-full border border-slate-700 bg-slate-950/70 px-3 py-1 text-[11px] text-slate-300">
                      updated {runtimeDecisionContractUpdatedAt || "unknown"}
                    </div>
                  </div>
                  <div className="mt-3 grid grid-cols-1 gap-3 md:grid-cols-3">
                    <div className="rounded-xl border border-slate-700/80 bg-slate-950/60 px-3 py-3">
                      <div className="text-[10px] uppercase tracking-[0.08em] text-slate-500">
                        Macro Source
                      </div>
                      <div className="mt-1 font-mono text-sm text-slate-100">
                        {String(
                          runtimeDecisionContractLineage.macro || "unknown",
                        )}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-700/80 bg-slate-950/60 px-3 py-3">
                      <div className="text-[10px] uppercase tracking-[0.08em] text-slate-500">
                        Interpreter Source
                      </div>
                      <div className="mt-1 font-mono text-sm text-slate-100">
                        {String(
                          runtimeDecisionContractLineage.interpreter ||
                            "unknown",
                        )}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-700/80 bg-slate-950/60 px-3 py-3">
                      <div className="text-[10px] uppercase tracking-[0.08em] text-slate-500">
                        Policy Source
                      </div>
                      <div className="mt-1 font-mono text-sm text-slate-100">
                        {String(
                          runtimeDecisionContractLineage.decision_policy ||
                            "unknown",
                        )}
                      </div>
                    </div>
                  </div>
                </div>

                <div className="grid grid-cols-1 xl:grid-cols-2 gap-4">
                  <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4 space-y-3">
                    <div className="text-sm font-semibold text-slate-100">
                      Macro Agent
                    </div>
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
                      <label className="space-y-1">
                        <span className="text-slate-400">角色</span>
                        <select
                          value={decisionPolicyForm.macroRole}
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              macroRole: e.target.value,
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200"
                        >
                          <option value="directional_gate">
                            directional_gate
                          </option>
                          <option value="directional_hard_block">
                            directional_hard_block
                          </option>
                        </select>
                      </label>
                      <label className="space-y-1">
                        <span className="text-slate-400">降级策略</span>
                        <select
                          value={decisionPolicyForm.macroDegradedPolicy}
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              macroDegradedPolicy: e.target.value,
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200"
                        >
                          <option value="soften_to_neutral">
                            soften_to_neutral
                          </option>
                          <option value="keep_last_bias">keep_last_bias</option>
                        </select>
                      </label>
                      <label className="space-y-1">
                        <span className="text-slate-400">顺势放大</span>
                        <input
                          type="number"
                          min="0"
                          max="2"
                          step="0.05"
                          value={decisionPolicyForm.macroAlignedScale}
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              macroAlignedScale: Number(e.target.value || 0),
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200 font-mono"
                        />
                      </label>
                      <label className="space-y-1">
                        <span className="text-slate-400">逆势降权</span>
                        <input
                          type="number"
                          min="0"
                          max="2"
                          step="0.05"
                          value={decisionPolicyForm.macroCountertrendScale}
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              macroCountertrendScale: Number(
                                e.target.value || 0,
                              ),
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200 font-mono"
                        />
                      </label>
                    </div>
                  </div>

                  <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-4 space-y-3">
                    <div className="text-sm font-semibold text-slate-100">
                      Interpreter + Execution
                    </div>
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
                      <label className="space-y-1">
                        <span className="text-slate-400">解释层角色</span>
                        <select
                          value={decisionPolicyForm.interpreterRole}
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              interpreterRole: e.target.value,
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200"
                        >
                          <option value="execution_bias_only">
                            execution_bias_only
                          </option>
                        </select>
                      </label>
                      <label className="space-y-1">
                        <span className="text-slate-400">最小聚合置信度</span>
                        <input
                          type="number"
                          min="0"
                          max="1"
                          step="0.01"
                          value={decisionPolicyForm.executionMinConfidence}
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              executionMinConfidence: Number(
                                e.target.value || 0,
                              ),
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200 font-mono"
                        />
                      </label>
                      <label className="space-y-1">
                        <span className="text-slate-400">BUY 放大</span>
                        <input
                          type="number"
                          min="0"
                          max="2"
                          step="0.05"
                          value={decisionPolicyForm.interpreterBuyScale}
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              interpreterBuyScale: Number(e.target.value || 0),
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200 font-mono"
                        />
                      </label>
                      <label className="space-y-1">
                        <span className="text-slate-400">SELL 放大</span>
                        <input
                          type="number"
                          min="0"
                          max="2"
                          step="0.05"
                          value={decisionPolicyForm.interpreterSellScale}
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              interpreterSellScale: Number(e.target.value || 0),
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200 font-mono"
                        />
                      </label>
                      <label className="space-y-1">
                        <span className="text-slate-400">逆势限权</span>
                        <input
                          type="number"
                          min="0"
                          max="2"
                          step="0.05"
                          value={
                            decisionPolicyForm.interpreterLimitCountertrendScale
                          }
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              interpreterLimitCountertrendScale: Number(
                                e.target.value || 0,
                              ),
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200 font-mono"
                        />
                      </label>
                      <label className="space-y-1">
                        <span className="text-slate-400">逆势阻断</span>
                        <input
                          type="number"
                          min="0"
                          max="2"
                          step="0.05"
                          value={
                            decisionPolicyForm.interpreterBlockCountertrendScale
                          }
                          onChange={(e) =>
                            setDecisionPolicyForm((prev) => ({
                              ...prev,
                              interpreterBlockCountertrendScale: Number(
                                e.target.value || 0,
                              ),
                            }))
                          }
                          className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-slate-200 font-mono"
                        />
                      </label>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-950/60 p-3 text-sm text-slate-300">
                      <div className="flex justify-between">
                        <span>当前 Profile</span>
                        <span className="font-mono text-slate-100">
                          {String(
                            workbenchDecisionPolicy.profile ||
                              decisionPolicyForm.profile,
                          )}
                        </span>
                      </div>
                      <div className="flex justify-between mt-2">
                        <span>Risk 角色</span>
                        <span className="font-mono text-slate-100">
                          {String(
                            workbenchDecisionPolicy.risk?.role ||
                              decisionPolicyForm.riskRole,
                          )}
                        </span>
                      </div>
                      <div className="flex justify-between mt-2">
                        <span>聚合模式</span>
                        <span className="font-mono text-slate-100">
                          {String(
                            workbenchDecisionPolicy.execution?.aggregation ||
                              decisionPolicyForm.executionAggregation,
                          )}
                        </span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </>
          ) : (
            <div className="rounded-2xl border border-primary/25 bg-card p-5">
              <div className="text-sm font-semibold text-slate-100">
                简化切换说明
              </div>
              <div className="mt-2 text-sm leading-6 text-slate-400">
                这里默认只保留“切换到该策略”与“启用 /
                停用”。发布、回滚、参数模板、组合创建和协同协议配置统一收进专业版，避免日常切换时误操作。
              </div>
            </div>
          )}
          <div className="space-y-4">
            {(workbenchMarketplace.strategies || []).map((strategy: any) => (
              <div
                key={strategy.id}
                className={`rounded-2xl border p-5 ${strategy.active ? "border-primary/40 bg-primary/5" : "border-slate-800 bg-[#0A0E17]"}`}
              >
                <div className="flex flex-col gap-4">
                  <div className="flex flex-wrap items-center justify-between gap-3">
                    <div>
                      <div className="text-lg font-bold text-slate-100">
                        {String(strategy.name || strategy.id)}
                      </div>
                      <div className="mt-1 text-sm text-slate-400">
                        ID: {String(strategy.id || "-")} · 引擎:{" "}
                        {String(strategy.id || "-")} · 发布版本:{" "}
                        {String(strategy.version || "legacy")}
                      </div>
                    </div>
                    <div
                      className={`px-3 py-1 rounded-full text-sm font-medium ${strategy.active ? "bg-success/15 text-success border border-success/30" : "bg-slate-800 text-slate-300 border border-slate-700"}`}
                    >
                      {strategy.active
                        ? "已启用"
                        : strategy.enabled
                          ? "未启用"
                          : "已停用"}
                    </div>
                  </div>

                  {strategyMarketplaceView === "pro" ? (
                    <>
                      <div className="grid grid-cols-1 md:grid-cols-3 gap-3 text-sm">
                        <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                          当前版本:{" "}
                          <span className="font-mono text-slate-200">
                            {String(strategy.version || "-")}
                          </span>
                        </div>
                        <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                          版本数:{" "}
                          <span className="font-mono text-slate-200">
                            {Number(strategy.versionsCount || 0)}
                          </span>
                        </div>
                        <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                          组件:{" "}
                          <span className="font-mono text-slate-200">
                            {Number(strategy.componentsCount || 0)}
                          </span>
                        </div>
                      </div>

                      <div className="flex flex-wrap gap-2">
                        <button
                          disabled={strategy.active || !strategy.enabled}
                          onClick={() =>
                            handleMarketplaceAction("deploy", strategy)
                          }
                          className="px-4 py-2 rounded-lg bg-primary hover:bg-blue-500 disabled:opacity-40 text-white text-sm font-medium transition-colors"
                        >
                          部署
                        </button>
                        <button
                          onClick={() =>
                            handleMarketplaceAction("disable", strategy)
                          }
                          className="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 text-sm font-medium transition-colors"
                        >
                          {strategy.enabled ? "停用" : "启用"}
                        </button>
                        <button
                          onClick={() =>
                            handleMarketplaceAction("publish", strategy)
                          }
                          className="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 text-sm font-medium transition-colors"
                        >
                          发布
                        </button>
                        <button
                          onClick={() =>
                            handleMarketplaceAction("rollback", strategy)
                          }
                          className="px-4 py-2 rounded-lg bg-danger hover:bg-red-500 text-white text-sm font-medium transition-colors"
                        >
                          回滚
                        </button>
                        <button
                          onClick={() =>
                            handleMarketplaceAction("template", strategy)
                          }
                          className="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 text-sm font-medium transition-colors"
                        >
                          参数模板
                        </button>
                      </div>
                    </>
                  ) : (
                    <>
                      <div className="grid grid-cols-1 md:grid-cols-3 gap-3 text-sm">
                        <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                          当前版本:{" "}
                          <span className="font-mono text-slate-200">
                            {String(strategy.version || "-")}
                          </span>
                        </div>
                        <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                          状态:{" "}
                          <span className="font-mono text-slate-200">
                            {strategy.active
                              ? "当前运行中"
                              : strategy.enabled
                                ? "可切换"
                                : "已停用"}
                          </span>
                        </div>
                        <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                          简化动作:{" "}
                          <span className="font-mono text-slate-200">
                            {strategy.active
                              ? "保持当前"
                              : strategy.enabled
                                ? "一键切换"
                                : "先启用"}
                          </span>
                        </div>
                      </div>

                      <div className="flex flex-wrap gap-2">
                        <button
                          disabled={Boolean(strategy.active)}
                          onClick={() =>
                            strategy.enabled
                              ? handleMarketplaceAction("deploy", strategy)
                              : handleMarketplaceAction("disable", strategy)
                          }
                          className="px-4 py-2 rounded-lg bg-primary hover:bg-blue-500 disabled:opacity-40 text-white text-sm font-medium transition-colors"
                        >
                          {strategy.active
                            ? "当前运行中"
                            : strategy.enabled
                              ? "切换到这里"
                              : "启用策略"}
                        </button>
                        <button
                          onClick={() =>
                            handleMarketplaceAction("disable", strategy)
                          }
                          className="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 text-sm font-medium transition-colors"
                        >
                          {strategy.enabled ? "停用" : "启用"}
                        </button>
                        <button
                          onClick={() =>
                            setMarketplaceExpandedStrategyId((prev) =>
                              prev === String(strategy.id || "")
                                ? null
                                : String(strategy.id || ""),
                            )
                          }
                          className="px-4 py-2 rounded-lg bg-slate-900 hover:bg-slate-800 text-slate-200 text-sm font-medium transition-colors"
                        >
                          {marketplaceExpandedStrategyId ===
                          String(strategy.id || "")
                            ? "收起更多操作"
                            : "更多操作"}
                        </button>
                      </div>

                      {marketplaceExpandedStrategyId ===
                      String(strategy.id || "") ? (
                        <div className="flex flex-wrap gap-2 rounded-xl border border-slate-800 bg-slate-950/50 p-3">
                          <button
                            onClick={() =>
                              handleMarketplaceAction("publish", strategy)
                            }
                            className="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 text-sm font-medium transition-colors"
                          >
                            发布
                          </button>
                          <button
                            onClick={() =>
                              handleMarketplaceAction("rollback", strategy)
                            }
                            className="px-4 py-2 rounded-lg bg-danger hover:bg-red-500 text-white text-sm font-medium transition-colors"
                          >
                            回滚
                          </button>
                          <button
                            onClick={() =>
                              handleMarketplaceAction("template", strategy)
                            }
                            className="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 text-sm font-medium transition-colors"
                          >
                            参数模板
                          </button>
                        </div>
                      ) : null}
                    </>
                  )}
                </div>
              </div>
            ))}
          </div>

          {strategyMarketplaceView === "pro" ? (
            <div className="grid grid-cols-1 xl:grid-cols-2 gap-6">
              <div className="bg-card border border-slate-800 rounded-2xl p-6">
                <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500 mb-3">
                  系统层
                </div>
                <div className="space-y-2 text-sm text-slate-300">
                  <div className="flex justify-between">
                    <span>当前策略</span>
                    <span className="font-mono">
                      {String(workbenchMarketplaceCurrent.strategyId || "-")}
                    </span>
                  </div>
                  <div className="flex justify-between">
                    <span>配置版本</span>
                    <span className="font-mono">
                      {String(
                        workbenchMarketplaceCurrent.configRevision || "-",
                      )}
                    </span>
                  </div>
                  <div className="flex justify-between">
                    <span>运行状态</span>
                    <span
                      className={`${workbenchMarketplaceCurrent.runtimeLoaded ? "text-success" : "text-warning"}`}
                    >
                      {workbenchMarketplaceCurrent.runtimeLoaded
                        ? "已装载"
                        : "未装载"}
                    </span>
                  </div>
                  <div className="flex justify-between">
                    <span>生效时间</span>
                    <span className="font-mono">
                      {String(
                        workbenchMarketplaceCurrent.effectiveUpdatedAt || "-",
                      )}
                    </span>
                  </div>
                </div>
              </div>

              <div className="bg-card border border-slate-800 rounded-2xl p-6">
                <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500 mb-3">
                  执行层
                </div>
                <div className="grid grid-cols-2 gap-3 text-sm">
                  <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                    活跃执行链:{" "}
                    <span className="font-mono text-slate-200">
                      {Number(workbenchExecutionSummary.activeExecutions || 0)}
                    </span>
                  </div>
                  <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                    待复核:{" "}
                    <span className="font-mono text-warning">
                      {signalReviewPendingCount}
                    </span>
                  </div>
                  <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                    风控阻断数:{" "}
                    <span className="font-mono">
                      {Number(workbenchRiskSummary.blockerCount || 0)}
                    </span>
                  </div>
                  <div className="rounded-lg border border-slate-800 bg-slate-900/50 p-3">
                    账户总亏:{" "}
                    <span className="font-mono">
                      {Number(
                        workbenchRiskSummary.accountLossCurrentPct || 0,
                      ).toFixed(2)}
                      %
                    </span>
                  </div>
                </div>
              </div>
            </div>
          ) : null}
        </div>
      );
    }

    if (menu === "robotDashboard") {
      return (
        <div className="max-w-7xl w-full mx-auto p-8 space-y-6">
          <div className="flex items-center gap-2">
            <button
              onClick={() => setActiveMenu("strategyMarketplace")}
              className="px-4 py-2 rounded-lg bg-slate-800 text-slate-300 text-sm font-medium hover:bg-slate-700 transition-colors"
            >
              策略集市
            </button>
            <button
              onClick={() => setActiveMenu("robotDashboard")}
              className="px-4 py-2 rounded-lg bg-primary text-white text-sm font-medium"
            >
              机器人看板
            </button>
          </div>

          <div className="flex items-center justify-between gap-3 rounded-2xl border border-slate-800 bg-card p-4">
            <div>
              <div className="text-sm font-semibold text-slate-100">
                看板视图切换
              </div>
              <div className="mt-1 text-xs text-slate-400">
                简化版面向普通用户，专业版保留完整运行中枢。
              </div>
            </div>
            <div className="inline-flex rounded-xl border border-slate-700 bg-slate-950/70 p-1">
              <button
                onClick={() => setRobotDashboardView("simple")}
                className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
                  robotDashboardView === "simple"
                    ? "bg-primary text-white"
                    : "text-slate-300 hover:text-slate-100"
                }`}
              >
                简化版
              </button>
              <button
                onClick={() => setRobotDashboardView("pro")}
                className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
                  robotDashboardView === "pro"
                    ? "bg-primary text-white"
                    : "text-slate-300 hover:text-slate-100"
                }`}
              >
                专业版
              </button>
            </div>
          </div>

          {robotDashboardView === "pro" ? (
            <div className="rounded-2xl border border-slate-800 bg-card p-5">
              <div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
                <div>
                  <div className="text-xl font-bold text-slate-100">
                    AI组合评估
                  </div>
                  <div className="mt-2 text-sm leading-6 text-slate-400">
                    默认隐藏详细评估，只保留结论摘要；需要时再展开看完整建议、风险提示和历史。
                  </div>
                </div>
                <div className="flex flex-wrap gap-2">
                  <button
                    onClick={() => void handleEvaluateRuntimeAi()}
                    disabled={runtimeAiLoading}
                    className="px-4 py-2 rounded-xl bg-primary hover:bg-blue-500 disabled:opacity-50 text-white text-sm font-semibold transition-colors"
                  >
                    {runtimeAiLoading ? "评估中..." : "刷新评估"}
                  </button>
                  <button
                    onClick={() => setRuntimeAiSimpleExpanded((prev) => !prev)}
                    className="px-4 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-100 text-sm font-semibold transition-colors"
                  >
                    {runtimeAiSimpleExpanded ? "收起详情" : "展开详情"}
                  </button>
                </div>
              </div>

              <div className="mt-4 grid grid-cols-1 gap-3 xl:grid-cols-3 text-sm">
                <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-4 py-3">
                  <div className="text-xs text-slate-500">当前结论</div>
                  <div className="mt-1 font-semibold text-slate-100">
                    {runtimeAiSummaryVerdict}
                  </div>
                </div>
                <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-4 py-3">
                  <div className="text-xs text-slate-500">建议组合</div>
                  <div className="mt-1 font-semibold text-slate-100">
                    {runtimeAiSummaryCombo}
                  </div>
                </div>
                <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-4 py-3">
                  <div className="text-xs text-slate-500">摘要说明</div>
                  <div className="mt-1 text-slate-300">
                    {runtimeAiSummaryHint}
                  </div>
                </div>
              </div>

              {runtimeAiSimpleExpanded ? (
                <>
                  <div className="mt-4 flex flex-col gap-3 xl:flex-row">
                    <input
                      value={runtimeAiGoal}
                      onChange={(e) => setRuntimeAiGoal(e.target.value)}
                      placeholder="评估目标（如：提高胜率并减少互搏）"
                      className="flex-1 bg-[#0A0E17] border border-slate-700 rounded-xl px-4 py-3 text-slate-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50"
                    />
                    <button
                      disabled={!runtimeAiApplyAvailable}
                      title={String(
                        runtimeAiEvaluation.applySuggestionReason ||
                          "当前没有可直接应用的建议",
                      )}
                      className="px-5 py-3 rounded-xl bg-slate-800 hover:bg-slate-700 disabled:opacity-50 text-slate-100 font-semibold transition-colors"
                    >
                      应用建议
                    </button>
                  </div>

                  <div className="mt-4 space-y-2 text-sm text-slate-300">
                    {runtimeAiRecommendations.length > 0 ? (
                      runtimeAiRecommendations.map(
                        (item: unknown, index: number) => (
                          <div
                            key={`runtime-ai-rec-${index}`}
                            className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3"
                          >
                            • {String(item || "")}
                          </div>
                        ),
                      )
                    ) : (
                      <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3">
                        • 评估后会在这里展示逐实例重编排建议
                      </div>
                    )}
                    {runtimeAiRiskWarnings.length > 0 ? (
                      runtimeAiRiskWarnings.map(
                        (item: unknown, index: number) => (
                          <div
                            key={`runtime-ai-risk-${index}`}
                            className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3"
                          >
                            • {String(item || "")}
                          </div>
                        ),
                      )
                    ) : (
                      <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3">
                        • 当前没有额外风险提示
                      </div>
                    )}
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3">
                      •{" "}
                      {String(
                        runtimeAiEvaluation.rationale ||
                          "当前暂无元评估场景说明",
                      )}
                    </div>
                  </div>

                  <div className="mt-5">
                    <div className="text-sm font-semibold text-slate-100">
                      最近评估历史：
                    </div>
                    <div className="mt-2 space-y-2 text-sm text-slate-300">
                      {runtimeAiHistory.length > 0 ? (
                        runtimeAiHistory
                          .slice(0, 4)
                          .map(
                            (item: Record<string, unknown>, index: number) => (
                              <div
                                key={`runtime-ai-history-${index}`}
                                className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3"
                              >
                                • {String(item.ts || "-")} ·{" "}
                                {String(item.verdictLabel || "未命名评估")} ·{" "}
                                {String(item.recommendedComboLabel || "待评估")}
                              </div>
                            ),
                          )
                      ) : (
                        <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3">
                          • 暂无 AI 评估历史
                        </div>
                      )}
                    </div>
                  </div>
                </>
              ) : null}
            </div>
          ) : null}

          {robotDashboardView === "simple" ? (
            <div className="space-y-6">
              <div className="grid grid-cols-1 xl:grid-cols-3 gap-4">
                <div className="xl:col-span-2 rounded-2xl border border-primary/30 bg-card p-6">
                  <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500">
                    普通用户总览
                  </div>
                  <div className="mt-3 text-3xl font-bold text-slate-100">
                    {runtimeOpsGateway.light === "GREEN"
                      ? "现在可以正常交易"
                      : runtimeOpsGateway.light === "YELLOW"
                        ? "现在可以看，但要留意风险"
                        : "现在不适合继续交易"}
                  </div>
                  <div className="mt-3 text-sm leading-7 text-slate-300">
                    当前系统最终动作：
                    <span className="font-mono text-slate-100">
                      {" "}
                      {String(
                        runtimeOpsArbitrationSummary.finalAction || "UNKNOWN",
                      )}{" "}
                      /{" "}
                      {String(runtimeOpsArbitrationSummary.finalSide || "NONE")}
                    </span>
                    {" · "}
                    原因：
                    <span className="text-slate-100">
                      {String(
                        runtimeOpsArbitrationSummary.reason ||
                          runtimeOpsScheduler.reason ||
                          "暂无运行解释",
                      )}
                    </span>
                  </div>
                  <div className="mt-4 flex flex-wrap gap-2 text-xs">
                    <span
                      className={`px-2.5 py-1 rounded-full border ${runtimePillTone(runtimeOpsGateway.daemonRunning ? "ok" : "danger")}`}
                    >
                      网关 {runtimeOpsGateway.daemonRunning ? "在线" : "离线"}
                    </span>
                    <span
                      className={`px-2.5 py-1 rounded-full border ${runtimePillTone(runtimeOpsGateway.mt5Online ? "ok" : "warn")}`}
                    >
                      MT5 {runtimeOpsGateway.mt5Online ? "在线" : "掉线"}
                    </span>
                    <span
                      className={`px-2.5 py-1 rounded-full border ${runtimePillTone(runtimeOpsBridgeHealth.bridgeOk ? "ok" : "danger")}`}
                    >
                      执行桥 {runtimeOpsBridgeHealth.bridgeOk ? "正常" : "异常"}
                    </span>
                    <span
                      className={`px-2.5 py-1 rounded-full border ${runtimePillTone(runtimeOpsRiskSummary.blocked ? "danger" : "ok")}`}
                    >
                      风险总闸{" "}
                      {runtimeOpsRiskSummary.blocked ? "阻断中" : "正常"}
                    </span>
                  </div>
                </div>

                <div className="rounded-2xl border border-slate-800 bg-card p-6">
                  <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500">
                    今日表现
                  </div>
                  <div className="mt-3 grid grid-cols-1 gap-3 text-sm">
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      今日成交
                      <div className="mt-1 text-2xl font-bold font-mono text-slate-100">
                        {Number(
                          runtimeOpsPerformance.todayTrades ||
                            status.todayTrades ||
                            0,
                        )}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      今日盈亏
                      <div className="mt-1 text-2xl font-bold font-mono text-slate-100">
                        {formatSignedNumber(
                          runtimeOpsPerformance.todayPnl ||
                            status.todayPnl ||
                            0,
                          2,
                        )}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      当前点差
                      <div className="mt-1 text-2xl font-bold font-mono text-slate-100">
                        {formatNumberValue(runtimeOpsMarket.spread || 0, 2)}
                      </div>
                    </div>
                  </div>
                </div>
              </div>

              <div className="grid grid-cols-1 xl:grid-cols-3 gap-4">
                <div className="rounded-2xl border border-slate-800 bg-card p-5">
                  <h3 className="text-lg font-bold text-slate-100">
                    系统现在在跑什么
                  </h3>
                  <div className="mt-4 space-y-3 text-sm text-slate-300">
                    <div>
                      运行模式：
                      <span className="font-mono text-slate-100">
                        {" "}
                        {String(runtimeOpsScheduler.mode || "idle")}
                      </span>
                    </div>
                    <div>
                      活跃策略：
                      <span className="font-mono text-slate-100">
                        {" "}
                        {Array.isArray(runtimeOpsScheduler.activeStrategyIds) &&
                        runtimeOpsScheduler.activeStrategyIds.length > 0
                          ? runtimeOpsScheduler.activeStrategyIds.join(", ")
                          : "无"}
                      </span>
                    </div>
                    <div>
                      活跃实例：
                      <span className="font-mono text-slate-100">
                        {" "}
                        {Number(
                          runtimeOpsSchedulerSummary.activeInstanceCount || 0,
                        )}
                      </span>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3 text-xs leading-6 text-slate-400">
                      {String(
                        runtimeOpsScheduler.reason ||
                          (runtimeOpsCurrent.runtimeLoaded
                            ? "系统已装载运行配置"
                            : "当前没有运行实例"),
                      )}
                    </div>
                  </div>
                </div>

                <div className="rounded-2xl border border-slate-800 bg-card p-5">
                  <h3 className="text-lg font-bold text-slate-100">
                    现在能不能开仓
                  </h3>
                  <div className="mt-4 space-y-3 text-sm text-slate-300">
                    <div>
                      结论：
                      <span className="font-semibold text-slate-100">
                        {" "}
                        {runtimeOpsRiskSummary.blocked
                          ? "当前被全局风控阻断"
                          : String(
                                runtimeOpsArbitrationSummary.finalAction ||
                                  "HOLD",
                              ) === "HOLD"
                            ? "当前处于信号观望，不是全局风控阻断"
                            : "当前允许执行信号"}
                      </span>
                    </div>
                    <div>
                      风险状态：
                      <span className="font-mono text-slate-100">
                        {" "}
                        {runtimeOpsRiskSummary.blocked ? "blocked" : "normal"}
                      </span>
                    </div>
                    <div>
                      最终信号：
                      <span className="font-mono text-slate-100">
                        {" "}
                        {String(
                          runtimeOpsArbitrationSummary.finalAction || "UNKNOWN",
                        )}{" "}
                        /{" "}
                        {String(
                          runtimeOpsArbitrationSummary.finalSide || "NONE",
                        )}
                      </span>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3 text-xs leading-6 text-slate-400">
                      {String(
                        runtimeOpsRiskSummary.blocked
                          ? runtimeOpsRiskSummary.blockedReason ||
                              runtimeOpsArbitrationSummary.reason ||
                              "当前没有额外阻断说明"
                          : runtimeOpsArbitrationSummary.reason ||
                              runtimeSignalHoldReasons.join("，") ||
                              "当前没有额外阻断说明",
                      )}
                    </div>
                  </div>
                </div>

                <div className="rounded-2xl border border-slate-800 bg-card p-5">
                  <h3 className="text-lg font-bold text-slate-100">
                    普通用户建议
                  </h3>
                  <div className="mt-4 space-y-2 text-sm text-slate-300">
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3">
                      {runtimeOpsGateway.light === "RED"
                        ? "建议先暂停观察，不要继续推进实例动作。"
                        : runtimeOpsRiskSummary.blocked
                          ? "风控已阻断，先处理风险再考虑继续。"
                          : String(
                                runtimeOpsArbitrationSummary.finalAction ||
                                  "HOLD",
                              ) === "HOLD"
                            ? "当前属于信号观望，先看主实例理由，不要把它当成风控故障。"
                            : runtimeOpsBridgeHealth.bridgeOk
                              ? "系统链路正常，可继续让系统自动运行。"
                              : "策略没坏，但执行桥异常，先恢复桥接链路。"}
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3">
                      当前运行实例 {Number(runtimeOpsInstances.length || 0)}{" "}
                      个，候选策略{" "}
                      {Number(
                        runtimeOpsSchedulerSummary.candidateStrategyCount || 0,
                      )}{" "}
                      个。
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3">
                      如果你只关心“为什么没下单”，看上面的“现在能不能开仓”即可。
                    </div>
                  </div>
                </div>
              </div>

              <div className="rounded-2xl border border-slate-800 bg-card p-6">
                <div className="flex items-center justify-between gap-3">
                  <div>
                    <h3 className="text-xl font-bold text-slate-100">
                      当前运行实例
                    </h3>
                    <div className="mt-1 text-sm text-slate-400">
                      简化版只保留普通用户最关心的实例状态和常用动作。
                    </div>
                  </div>
                  <div className="text-sm text-slate-400">
                    共 {Number(runtimeOpsInstances.length || 0)} 个实例
                  </div>
                </div>
                <div className="mt-5 grid grid-cols-1 xl:grid-cols-2 gap-4">
                  {runtimeOpsInstances.map((instance: any) => {
                    const risk = (instance.risk as Record<string, any>) || {};
                    const signal =
                      (instance.signal as Record<string, any>) || {};
                    const orders =
                      (instance.orders as Record<string, any>) || {};
                    const positionState =
                      (instance.positionState as Record<string, any>) || {};
                    const instanceId = String(instance.instanceId || "-");
                    const strategyId = String(instance.strategyId || "-");
                    return (
                      <div
                        key={`${strategyId}::${instanceId}::simple`}
                        className={`rounded-2xl border p-5 ${runtimeCardTone(instance)}`}
                      >
                        <div className="flex items-center justify-between gap-3">
                          <div>
                            <div className="text-lg font-bold text-slate-100">
                              {String(instance.strategyName || strategyId)}
                            </div>
                            <div className="mt-1 text-xs text-slate-400">
                              实例 {instanceId} ·{" "}
                              {String(instance.role || "live_support")}
                            </div>
                          </div>
                          <span
                            className={`px-2.5 py-1 rounded-full border text-xs font-semibold ${runtimePillTone(instance.active ? "ok" : "warn")}`}
                          >
                            {instance.active ? "运行中" : "已暂停"}
                          </span>
                        </div>
                        <div className="mt-4 grid grid-cols-2 gap-3 text-sm text-slate-300">
                          <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                            当前动作
                            <div className="mt-1 font-semibold text-slate-100">
                              {String(signal.action || "HOLD")} /{" "}
                              {String(signal.side || "NONE")}
                            </div>
                          </div>
                          <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                            风险状态
                            <div className="mt-1 font-semibold text-slate-100">
                              {String(risk.status || "normal")}
                            </div>
                          </div>
                          <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                            持仓状态
                            <div className="mt-1 font-semibold text-slate-100">
                              {String(positionState.stateLabel || "未知")}
                            </div>
                          </div>
                          <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                            最近成交
                            <div className="mt-1 font-semibold text-slate-100">
                              {formatValueOrFallback(
                                orders.latestFilledAt,
                                "暂无",
                              )}
                            </div>
                          </div>
                        </div>
                        <div className="mt-3 text-xs leading-6 text-slate-400">
                          {String(
                            signal.reason ||
                              risk.blockedReason ||
                              "当前没有额外实例说明",
                          )}
                        </div>
                        <div className="mt-4 flex flex-wrap gap-2">
                          <button
                            onClick={() =>
                              void handleRuntimeInstanceAction(
                                instanceId,
                                instance.active ? "pause" : "resume",
                              )
                            }
                            className="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-100 text-sm font-medium transition-colors"
                          >
                            {instance.active ? "暂停实例" : "继续实例"}
                          </button>
                          <button
                            onClick={() =>
                              void handleMarketplaceAction("rollback", {
                                id: strategyId,
                                name: instance.strategyName,
                              })
                            }
                            className="px-4 py-2 rounded-lg bg-warning/15 hover:bg-warning/25 text-warning text-sm font-medium transition-colors border border-warning/30"
                          >
                            回滚版本
                          </button>
                          {Number(
                            instance.templateDiff?.summary?.overrideCount || 0,
                          ) > 0 ? (
                            <button
                              onClick={() => {
                                if (
                                  !window.confirm("确认清空该实例覆写参数吗？")
                                ) {
                                  return;
                                }
                                void handleRuntimeInstanceAction(
                                  instanceId,
                                  "clear_overrides",
                                );
                              }}
                              className="px-4 py-2 rounded-lg bg-slate-900 hover:bg-slate-800 text-slate-200 text-sm font-medium transition-colors border border-slate-700"
                            >
                              清空覆写
                            </button>
                          ) : null}
                        </div>
                      </div>
                    );
                  })}
                  {runtimeOpsInstances.length === 0 ? (
                    <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-8 text-center text-sm text-slate-500 xl:col-span-2">
                      当前没有运行实例，可先去策略集市部署后再回来查看。
                    </div>
                  ) : null}
                </div>
              </div>
            </div>
          ) : (
            <div className="space-y-6">
              <div className="grid grid-cols-1 xl:grid-cols-4 gap-4">
                <div className="bg-card border border-primary/30 rounded-2xl p-5">
                  <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500">
                    系统总览
                  </div>
                  <div className="mt-3 text-2xl font-bold text-slate-100">
                    {runtimeOpsGateway.light === "GREEN"
                      ? "系统可交易"
                      : runtimeOpsGateway.light === "YELLOW"
                        ? "系统需关注"
                        : "系统阻断中"}
                  </div>
                  <div className="mt-2 text-sm text-slate-400">
                    daemon={runtimeOpsGateway.daemonRunning ? "up" : "down"} ·
                    mt5=
                    {runtimeOpsGateway.mt5Online ? "online" : "offline"} ·
                    bridge=
                    {runtimeOpsGateway.bridgeOk ? "ok" : "degraded"}
                  </div>
                </div>

                <div className="bg-card border border-slate-800 rounded-2xl p-5">
                  <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500">
                    调度器状态
                  </div>
                  <div className="mt-3 text-2xl font-bold text-slate-100">
                    {String(runtimeOpsScheduler.mode || "idle")}
                  </div>
                  <div className="mt-2 text-sm text-slate-400">
                    活跃实例{" "}
                    {Number(
                      runtimeOpsSchedulerSummary.activeInstanceCount || 0,
                    )}{" "}
                    / 活跃策略{" "}
                    {Number(
                      runtimeOpsSchedulerSummary.activeStrategyCount || 0,
                    )}
                  </div>
                  <div className="mt-4 grid grid-cols-2 gap-3 text-sm text-slate-300">
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      候选策略
                      <div className="mt-1 font-mono text-slate-100">
                        {Number(
                          runtimeOpsSchedulerSummary.candidateStrategyCount ||
                            0,
                        )}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      被压制
                      <div className="mt-1 font-mono text-slate-100">
                        {Number(
                          runtimeOpsSchedulerSummary.suppressedCount || 0,
                        )}
                      </div>
                    </div>
                  </div>
                </div>

                <div className="bg-card border border-slate-800 rounded-2xl p-5">
                  <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500">
                    风险总闸
                  </div>
                  <div className="mt-3 text-2xl font-bold text-slate-100">
                    {runtimeOpsRiskSummary.blocked ? "硬熔断 / 阻断" : "正常"}
                  </div>
                  <div className="mt-2 text-sm text-slate-400">
                    回撤{" "}
                    {formatPercentPoints(
                      runtimeOpsRiskSummary.accountLossCurrentPct || 0,
                      2,
                    )}{" "}
                    / 阈值{" "}
                    {formatPercentPoints(
                      runtimeOpsRiskSummary.accountLossStopPct || 0,
                      2,
                    )}
                  </div>
                  <div className="mt-4 flex flex-wrap gap-2 text-xs">
                    <span
                      className={`px-2.5 py-1 rounded-full border ${runtimePillTone(runtimeOpsRiskSummary.blocked ? "danger" : "ok")}`}
                    >
                      KillSwitch{" "}
                      {runtimeOpsRiskSummary.blocked ? "触发" : "正常"}
                    </span>
                    <span
                      className={`px-2.5 py-1 rounded-full border ${runtimePillTone(Number(runtimeOpsMarket.spread || 0) > 80 ? "warn" : "neutral")}`}
                    >
                      点差 {formatNumberValue(runtimeOpsMarket.spread || 0, 2)}
                    </span>
                    <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-slate-800/70 text-slate-200">
                      隔离数{" "}
                      {Array.isArray(
                        runtimeOpsRiskGovernorState.isolatedStrategyIds,
                      )
                        ? runtimeOpsRiskGovernorState.isolatedStrategyIds.length
                        : 0}
                    </span>
                  </div>
                </div>

                <div className="bg-card border border-slate-800 rounded-2xl p-5">
                  <div className="text-[11px] uppercase tracking-[0.16em] text-slate-500">
                    执行异常聚焦
                  </div>
                  <div className="mt-3 text-2xl font-bold text-slate-100">
                    {Number(runtimeOpsExecutionFocus.length || 0)} 类
                  </div>
                  <div className="mt-2 text-sm text-slate-400">
                    今日{" "}
                    {Number(
                      runtimeOpsPerformance.todayTrades ||
                        status.todayTrades ||
                        0,
                    )}{" "}
                    笔 · PnL{" "}
                    {formatSignedNumber(
                      runtimeOpsPerformance.todayPnl || status.todayPnl || 0,
                      2,
                    )}
                  </div>
                  <div className="mt-4 space-y-2 text-xs text-slate-300">
                    {runtimeOpsExecutionFocus
                      .slice(0, 3)
                      .map((item: any, index: number) => (
                        <div
                          key={`${String(item.kind || "focus")}::${index}`}
                          className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2"
                        >
                          {String(item.kind || "unknown")} ·{" "}
                          {Number(item.count || 0)}
                        </div>
                      ))}
                    {runtimeOpsExecutionFocus.length === 0 ? (
                      <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-slate-500">
                        当前没有聚焦异常
                      </div>
                    ) : null}
                  </div>
                </div>
              </div>

              <div className="grid grid-cols-1 xl:grid-cols-3 gap-4">
                <div className="bg-card border border-slate-800 rounded-2xl p-5">
                  <div className="flex items-center justify-between gap-3">
                    <h3 className="text-lg font-bold text-slate-100">
                      执行桥健康
                    </h3>
                    <span
                      className={`px-2.5 py-1 rounded-full border text-xs font-semibold ${runtimePillTone(runtimeOpsBridgeHealth.bridgeOk ? "ok" : "danger")}`}
                    >
                      {runtimeOpsBridgeHealth.bridgeOk
                        ? "bridge ok"
                        : "bridge degraded"}
                    </span>
                  </div>
                  <div className="mt-4 grid grid-cols-2 gap-3 text-sm text-slate-300">
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      to_ea
                      <div className="mt-1 font-mono text-slate-100">
                        {Number(runtimeOpsBridgeQueue.toEaDepth || 0)}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      from_ea
                      <div className="mt-1 font-mono text-slate-100">
                        {Number(runtimeOpsBridgeQueue.fromEaDepth || 0)}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      心跳年龄
                      <div className="mt-1 font-mono text-slate-100">
                        {formatValueOrFallback(
                          runtimeOpsBridgeHealth.heartbeatAgeSec,
                          "未知",
                        )}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      pending exit
                      <div className="mt-1 font-mono text-slate-100">
                        {Number(runtimeOpsBridgeQueue.pendingExit || 0)}
                      </div>
                    </div>
                  </div>
                  <div className="mt-4 space-y-2 text-xs text-slate-300">
                    {runtimeOpsBridgeRequests
                      .slice(0, 5)
                      .map((item: any, index: number) => (
                        <div
                          key={`${String(item.traceId || item.signalId || item.instanceId || "req")}::${index}`}
                          className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2"
                        >
                          {String(item.action || "")} {String(item.side || "")}{" "}
                          · {String(item.status || "")} ·{" "}
                          {String(item.instanceId || item.strategyId || "-")}
                        </div>
                      ))}
                    {runtimeOpsBridgeRequests.length === 0 ? (
                      <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-slate-500">
                        当前没有桥接请求流水
                      </div>
                    ) : null}
                  </div>
                </div>

                <div className="bg-card border border-slate-800 rounded-2xl p-5">
                  <div className="flex items-center justify-between gap-3">
                    <h3 className="text-lg font-bold text-slate-100">
                      最近一次仲裁解释
                    </h3>
                    <span
                      className={`px-2.5 py-1 rounded-full border text-xs font-semibold ${
                        String(
                          runtimeOpsArbitrationSummary.finalAction || "HOLD",
                        ).toUpperCase() === "HOLD"
                          ? runtimePillTone("warn")
                          : runtimePillTone("ok")
                      }`}
                    >
                      {String(
                        runtimeOpsArbitrationSummary.finalAction || "UNKNOWN",
                      )}
                    </span>
                  </div>
                  <div className="mt-4 space-y-3 text-sm text-slate-300">
                    <div>
                      最终方向:{" "}
                      <span className="font-mono text-slate-100">
                        {String(
                          runtimeOpsArbitrationSummary.finalSide || "NONE",
                        )}
                      </span>
                    </div>
                    <div>
                      置信度:{" "}
                      <span className="font-mono text-slate-100">
                        {formatRatioPercent(
                          runtimeOpsArbitrationSummary.confidence || 0,
                          1,
                        )}
                      </span>
                    </div>
                    <div>
                      加权净分:{" "}
                      <span
                        className={`font-mono ${contributorScoreTone(
                          Number(runtimeOpsArbitrationSummary.netScore || 0),
                        )}`}
                      >
                        {formatNumberValue(
                          runtimeOpsArbitrationSummary.netScore || 0,
                          4,
                        )}
                      </span>
                    </div>
                    <div>
                      hold_type:{" "}
                      <span className="font-mono text-slate-100">
                        {String(
                          runtimeOpsArbitrationSummary.holdMode || "unknown",
                        )}
                      </span>
                    </div>
                    <div className="rounded-2xl border border-slate-800 bg-slate-900/50 px-4 py-3 text-xs leading-6 text-slate-400">
                      {String(
                        runtimeOpsArbitrationSummary.reason || "暂无仲裁解释",
                      )}
                    </div>
                    <div className="space-y-2">
                      {runtimeOpsContributors
                        .slice(0, 4)
                        .map((item: any, index: number) => (
                          <div
                            key={`${String(item.instanceId || "-")}::${String(item.strategyId || "-")}::${index}`}
                            className={`rounded-xl border px-3 py-2 text-xs ${contributorTone(item)}`}
                          >
                            {String(item.instanceId || "-")} ·{" "}
                            {String(item.action || "HOLD")}{" "}
                            {String(item.side || "NONE")} · score=
                            {formatNumberValue(item.signedScore || 0, 4)}
                          </div>
                        ))}
                      {runtimeOpsContributors.length === 0 ? (
                        <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-500">
                          暂无 contributors
                        </div>
                      ) : null}
                    </div>
                  </div>
                </div>

                <div className="bg-card border border-slate-800 rounded-2xl p-5">
                  <div className="flex items-center justify-between gap-3">
                    <h3 className="text-lg font-bold text-slate-100">
                      编排快照
                    </h3>
                    <span
                      className={`px-2.5 py-1 rounded-full border text-xs font-semibold ${runtimePillTone(runtimeOpsOrchestration.supportsRollback ? "ok" : "warn")}`}
                    >
                      {runtimeOpsOrchestration.supportsRollback
                        ? "支持回退"
                        : "只读"}
                    </span>
                  </div>
                  <div className="mt-4 space-y-3 text-sm text-slate-300">
                    <div>
                      配置修订:{" "}
                      <span className="font-mono text-slate-100">
                        {formatValueOrFallback(
                          runtimeOpsOrchestration.configRevision,
                          "manual",
                        )}
                      </span>
                    </div>
                    <div>
                      快照更新时间:{" "}
                      <span className="font-mono text-slate-100">
                        {formatValueOrFallback(
                          runtimeOpsOrchestration.updatedAt,
                          "未知",
                        )}
                      </span>
                    </div>
                    <div>
                      实例数:{" "}
                      <span className="font-mono text-slate-100">
                        {Number(
                          runtimeOpsOrchestration.runtimeInstanceCount || 0,
                        )}
                      </span>
                    </div>
                    <div className="rounded-2xl border border-slate-800 bg-slate-900/50 px-4 py-3 text-xs leading-6 text-slate-400">
                      当前快照用于支撑部署、调权、模板热改和 agent
                      覆写后的回滚判责。
                    </div>
                  </div>
                </div>
              </div>

              <div className="grid grid-cols-1 xl:grid-cols-2 gap-4">
                <div className="bg-card border border-slate-800 rounded-2xl p-5">
                  <h3 className="text-lg font-bold text-slate-100">
                    为什么是这些策略在跑
                  </h3>
                  <div className="mt-4 grid grid-cols-2 gap-3 text-sm text-slate-300">
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      当前模式
                      <div className="mt-1 font-semibold text-slate-100">
                        {String(runtimeOpsScheduler.mode || "idle")}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      当前仲裁器
                      <div className="mt-1 font-semibold text-slate-100">
                        {String(runtimeOpsScheduler.arbiter || "unknown")}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      活跃实例
                      <div className="mt-1 font-semibold text-slate-100">
                        {Array.isArray(runtimeOpsScheduler.activeInstanceIds) &&
                        runtimeOpsScheduler.activeInstanceIds.length > 0
                          ? runtimeOpsScheduler.activeInstanceIds.join(", ")
                          : "无"}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      活跃策略
                      <div className="mt-1 font-semibold text-slate-100">
                        {Array.isArray(runtimeOpsScheduler.activeStrategyIds) &&
                        runtimeOpsScheduler.activeStrategyIds.length > 0
                          ? runtimeOpsScheduler.activeStrategyIds.join(", ")
                          : "无"}
                      </div>
                    </div>
                  </div>
                  <div className="mt-4 rounded-2xl border border-slate-800 bg-slate-900/50 px-4 py-3 text-xs leading-6 text-slate-400">
                    {String(
                      runtimeOpsScheduler.reason ||
                        (runtimeOpsCurrent.runtimeLoaded
                          ? "runtime loaded"
                          : "no running instances"),
                    )}
                  </div>
                  <div className="mt-4 flex flex-wrap gap-2 text-xs">
                    <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-slate-800/70 text-slate-200">
                      Profile{" "}
                      {String(runtimeOpsDecisionPolicy.profile || "unknown")}
                    </span>
                    <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-slate-800/70 text-slate-200">
                      Macro{" "}
                      {String(
                        runtimeOpsDecisionPolicy.macro?.role || "unknown",
                      )}
                    </span>
                    <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-slate-800/70 text-slate-200">
                      Interpreter{" "}
                      {String(
                        runtimeOpsDecisionPolicy.interpreter?.role || "unknown",
                      )}
                    </span>
                    <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-slate-800/70 text-slate-200">
                      Risk{" "}
                      {String(runtimeOpsDecisionPolicy.risk?.role || "unknown")}
                    </span>
                  </div>
                </div>

                <div className="bg-card border border-slate-800 rounded-2xl p-5">
                  <h3 className="text-lg font-bold text-slate-100">
                    Agent 配置诊断
                  </h3>
                  <div className="mt-4 grid grid-cols-3 gap-3 text-sm">
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      suppressions
                      <div className="mt-1 text-xl font-bold font-mono text-slate-100">
                        {Number(
                          runtimeOpsDiagnosticsSummary.suppressionCount || 0,
                        )}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      warnings
                      <div className="mt-1 text-xl font-bold font-mono text-slate-100">
                        {Number(
                          runtimeOpsDiagnosticsSummary.profileWarningCount || 0,
                        )}
                      </div>
                    </div>
                    <div className="rounded-xl border border-slate-800 bg-slate-900/50 p-3">
                      overrides
                      <div className="mt-1 text-xl font-bold font-mono text-slate-100">
                        {Number(
                          runtimeOpsDiagnosticsSummary.overrideWarningCount ||
                            0,
                        )}
                      </div>
                    </div>
                  </div>
                  <div className="mt-4 space-y-3">
                    <div>
                      <div className="mb-2 text-xs uppercase tracking-[0.08em] text-slate-500">
                        suppressions
                      </div>
                      <div className="space-y-2">
                        {runtimeOpsSuppressions
                          .slice(0, 4)
                          .map((item: any, index: number) => (
                            <div
                              key={`${String(item.instanceId || "-")}::${index}`}
                              className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-300"
                            >
                              {String(item.instanceId || "-")} ·{" "}
                              {String(item.reason || "")} ·{" "}
                              {String(item.rawReason || "")}
                            </div>
                          ))}
                        {runtimeOpsSuppressions.length === 0 ? (
                          <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-500">
                            当前没有 suppression 记录
                          </div>
                        ) : null}
                      </div>
                    </div>
                    <div>
                      <div className="mb-2 text-xs uppercase tracking-[0.08em] text-slate-500">
                        profile warnings
                      </div>
                      <div className="space-y-2">
                        {runtimeOpsProfileWarnings
                          .slice(0, 4)
                          .map((item: any, index: number) => (
                            <div
                              key={`${String(item.message || "profile")}::${index}`}
                              className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-300"
                            >
                              {String(item.message || "")}
                            </div>
                          ))}
                        {runtimeOpsProfileWarnings.length === 0 ? (
                          <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-500">
                            当前没有 profile warning
                          </div>
                        ) : null}
                      </div>
                    </div>
                    <div>
                      <div className="mb-2 text-xs uppercase tracking-[0.08em] text-slate-500">
                        override warnings
                      </div>
                      <div className="space-y-2">
                        {runtimeOpsOverrideWarnings
                          .slice(0, 4)
                          .map((item: any, index: number) => (
                            <div
                              key={`${String(item.instanceId || "-")}::${index}`}
                              className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-300"
                            >
                              {String(item.instanceId || "-")} · overrides=
                              {Number(item.overrideCount || 0)} · drift=
                              {Number(item.changedKeys || 0)}
                            </div>
                          ))}
                        {runtimeOpsOverrideWarnings.length === 0 ? (
                          <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-500">
                            当前没有 override warning
                          </div>
                        ) : null}
                      </div>
                    </div>
                  </div>
                </div>
              </div>

              <div className="bg-card border border-slate-800 rounded-2xl p-6">
                <div className="flex items-center justify-between gap-3">
                  <div>
                    <h3 className="text-2xl font-bold text-slate-100">
                      实例卡片层
                    </h3>
                    <div className="mt-1 text-sm text-slate-400">
                      按“调度 → 风险 → 执行 → 模板差异 →
                      时间轴”下钻每个运行实例。
                    </div>
                  </div>
                  <div className="text-sm text-slate-400">
                    共 {Number(runtimeOpsInstances.length || 0)} 个实例
                  </div>
                </div>

                <div className="mt-5 space-y-5">
                  {runtimeOpsInstances.map((instance: any) => {
                    const risk = (instance.risk as Record<string, any>) || {};
                    const signal =
                      (instance.signal as Record<string, any>) || {};
                    const orders =
                      (instance.orders as Record<string, any>) || {};
                    const positionState =
                      (instance.positionState as Record<string, any>) || {};
                    const templateDiff =
                      (instance.templateDiff as Record<string, any>) || {};
                    const templateDiffEntries = Array.isArray(
                      templateDiff.entries,
                    )
                      ? templateDiff.entries
                      : [];
                    const bridge =
                      (instance.bridge as Record<string, any>) || {};
                    const activeSignals = Array.isArray(bridge.activeSignals)
                      ? bridge.activeSignals
                      : [];
                    const recentRequests = Array.isArray(bridge.recentRequests)
                      ? bridge.recentRequests
                      : [];
                    const timeline = Array.isArray(instance.timeline)
                      ? instance.timeline
                      : [];
                    const instanceId = String(instance.instanceId || "-");
                    const strategyId = String(instance.strategyId || "-");
                    return (
                      <article
                        key={`${strategyId}::${instanceId}`}
                        className={`rounded-2xl border p-5 ${runtimeCardTone(instance)}`}
                      >
                        <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
                          <div>
                            <div className="flex flex-wrap items-center gap-2">
                              <h4 className="text-xl font-bold text-slate-50">
                                {String(instance.strategyName || strategyId)}
                              </h4>
                              <span
                                className={`px-2.5 py-1 rounded-full border text-xs font-semibold ${runtimePillTone(instance.active ? "ok" : "warn")}`}
                              >
                                {instance.active ? "运行中" : "已暂停"}
                              </span>
                              {instance.selected ? (
                                <span
                                  className={`px-2.5 py-1 rounded-full border text-xs font-semibold ${runtimePillTone("ok")}`}
                                >
                                  当前选中实例
                                </span>
                              ) : null}
                              {String(risk.status || "") === "blocked" ? (
                                <span
                                  className={`px-2.5 py-1 rounded-full border text-xs font-semibold ${runtimePillTone("danger")}`}
                                >
                                  受风险约束
                                </span>
                              ) : null}
                            </div>
                            <div className="mt-2 text-sm text-slate-400">
                              实例 {instanceId} · role=
                              {String(instance.role || "live_support")} ·
                              version=
                              {String(instance.strategyVersion || "legacy")}
                            </div>
                          </div>
                          <div className="flex flex-wrap gap-2 text-xs text-slate-300">
                            <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-slate-800/70">
                              allocation{" "}
                              {formatPercentPoints(
                                instance.allocationPct || 0,
                                1,
                              )}
                            </span>
                            <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-slate-800/70">
                              health{" "}
                              {formatNumberValue(
                                instance.health?.runtimeScore ||
                                  instance.health?.score ||
                                  0,
                                1,
                              )}
                            </span>
                            <span className="px-2.5 py-1 rounded-full border border-slate-700 bg-slate-800/70">
                              signal {String(signal.action || "HOLD")} /{" "}
                              {String(signal.side || "NONE")}
                            </span>
                          </div>
                        </div>

                        <div className="mt-5 grid grid-cols-1 gap-4 xl:grid-cols-2">
                          <div className="rounded-2xl border border-slate-800 bg-slate-950/40 p-4">
                            <div className="text-sm font-semibold text-slate-100">
                              调度 / 健康 / 风险 / 订单
                            </div>
                            <div className="mt-3 grid grid-cols-2 gap-3 text-sm text-slate-300">
                              <div>
                                <span className="text-slate-500">调度状态</span>
                                <div className="mt-1 font-semibold">
                                  {String(
                                    instance.scheduler?.state || "unknown",
                                  )}
                                </div>
                              </div>
                              <div>
                                <span className="text-slate-500">风险状态</span>
                                <div className="mt-1 font-semibold">
                                  {String(risk.status || "normal")}
                                </div>
                              </div>
                              <div>
                                <span className="text-slate-500">今日订单</span>
                                <div className="mt-1 font-semibold">
                                  {Number(orders.today || 0)}
                                </div>
                              </div>
                              <div>
                                <span className="text-slate-500">今日拒单</span>
                                <div className="mt-1 font-semibold">
                                  {Number(orders.reject || 0)}
                                </div>
                              </div>
                            </div>
                            <div className="mt-3 text-xs text-slate-400">
                              {risk.blockedReason
                                ? `blocked_reason: ${String(risk.blockedReason)}`
                                : "当前没有实例级 blocked_reason"}
                            </div>
                            <div className="mt-2 text-xs text-slate-400">
                              global_blocked=
                              {risk.globalBlocked ? "true" : "false"} ·
                              governor_blockers=
                              {Array.isArray(risk.governorBlockers)
                                ? risk.governorBlockers.length
                                : 0}
                            </div>
                          </div>

                          <div className="rounded-2xl border border-slate-800 bg-slate-950/40 p-4">
                            <div className="text-sm font-semibold text-slate-100">
                              持仓态 / 最近执行
                            </div>
                            <div className="mt-3 grid grid-cols-2 gap-3 text-sm text-slate-300">
                              <div>
                                <span className="text-slate-500">持仓态</span>
                                <div className="mt-1 font-semibold">
                                  {String(positionState.stateLabel || "未知")}
                                </div>
                              </div>
                              <div>
                                <span className="text-slate-500">当前方向</span>
                                <div className="mt-1 font-semibold">
                                  {String(positionState.currentSide || "NONE")}
                                </div>
                              </div>
                              <div>
                                <span className="text-slate-500">当前手数</span>
                                <div className="mt-1 font-semibold">
                                  {formatNumberValue(
                                    positionState.currentLots || 0,
                                    2,
                                  )}
                                </div>
                              </div>
                              <div>
                                <span className="text-slate-500">最近成交</span>
                                <div className="mt-1 font-semibold">
                                  {formatValueOrFallback(
                                    orders.latestFilledAt,
                                    "暂无",
                                  )}
                                </div>
                              </div>
                            </div>
                          </div>

                          <div className="rounded-2xl border border-slate-800 bg-slate-950/40 p-4">
                            <div className="text-sm font-semibold text-slate-100">
                              实例信号 / 贡献分 / 原因
                            </div>
                            <div className="mt-3 space-y-1 text-sm text-slate-300">
                              <div>
                                动作:{" "}
                                <span className="font-semibold">
                                  {String(signal.action || "HOLD")}
                                </span>
                              </div>
                              <div>
                                方向:{" "}
                                <span className="font-semibold">
                                  {String(signal.side || "NONE")}
                                </span>
                              </div>
                              <div>
                                贡献分:{" "}
                                <span
                                  className={`font-semibold ${contributorScoreTone(
                                    Number(signal.contributionScore || 0),
                                  )}`}
                                >
                                  {formatNumberValue(
                                    signal.contributionScore || 0,
                                    4,
                                  )}
                                </span>
                              </div>
                              <div>
                                置信度:{" "}
                                <span className="font-semibold">
                                  {formatRatioPercent(
                                    signal.confidence || 0,
                                    2,
                                  )}
                                </span>
                              </div>
                            </div>
                            <div className="mt-3 text-xs leading-6 text-slate-400">
                              {String(
                                signal.reason ||
                                  signal.suppressionReason ||
                                  "暂无信号解释",
                              )}
                            </div>
                          </div>

                          <div className="rounded-2xl border border-slate-800 bg-slate-950/40 p-4">
                            <div className="text-sm font-semibold text-slate-100">
                              Agent 画像 / 模板差异
                            </div>
                            <div className="mt-3 grid grid-cols-1 gap-2 text-sm text-slate-300">
                              <div>
                                Profile:{" "}
                                <span className="font-mono">
                                  {String(
                                    instance.agentProfile?.decisionProfile ||
                                      "unknown",
                                  )}
                                </span>
                              </div>
                              <div>
                                Macro:{" "}
                                <span className="font-mono">
                                  {String(
                                    instance.agentProfile?.macroRole ||
                                      "unknown",
                                  )}
                                </span>
                              </div>
                              <div>
                                Interpreter:{" "}
                                <span className="font-mono">
                                  {String(
                                    instance.agentProfile?.interpreterRole ||
                                      "unknown",
                                  )}
                                </span>
                              </div>
                              <div>
                                Risk:{" "}
                                <span className="font-mono">
                                  {String(
                                    instance.agentProfile?.riskRole ||
                                      "unknown",
                                  )}
                                </span>
                              </div>
                            </div>
                            <div className="mt-4 space-y-2">
                              {templateDiffEntries
                                .slice(0, 6)
                                .map((entry: any, index: number) => (
                                  <div
                                    key={`${String(entry.key || "entry")}::${index}`}
                                    className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3 text-xs text-slate-300"
                                  >
                                    <div className="font-semibold text-slate-100">
                                      {String(entry.key || "-")}
                                    </div>
                                    <div className="mt-1">
                                      市场默认:{" "}
                                      <span className="font-mono">
                                        {JSON.stringify(entry.marketDefault)}
                                      </span>
                                    </div>
                                    <div className="mt-1">
                                      实例生效:{" "}
                                      <span className="font-mono">
                                        {JSON.stringify(entry.effectiveValue)}
                                      </span>
                                    </div>
                                  </div>
                                ))}
                              {templateDiffEntries.length === 0 ? (
                                <div className="text-xs text-slate-500">
                                  当前实例未偏离市场默认模板。
                                </div>
                              ) : null}
                            </div>
                          </div>

                          <div className="rounded-2xl border border-slate-800 bg-slate-950/40 p-4">
                            <div className="text-sm font-semibold text-slate-100">
                              执行桥 / 请求账本
                            </div>
                            <div className="mt-3 space-y-2">
                              {activeSignals.map((row: any, index: number) => (
                                <div
                                  key={`${String(row.signalId || "active")}::${index}`}
                                  className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-300"
                                >
                                  {String(row.signalId || "-")} ·{" "}
                                  {String(row.action || "")}{" "}
                                  {String(row.side || "")} ·{" "}
                                  {String(row.state || "")}
                                </div>
                              ))}
                              {activeSignals.length === 0 ? (
                                <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-500">
                                  当前没有活跃执行信号
                                </div>
                              ) : null}
                            </div>
                            <div className="mt-4 space-y-2">
                              {recentRequests.map((row: any, index: number) => (
                                <div
                                  key={`${String(row.traceId || row.signalId || "recent")}::${index}`}
                                  className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-300"
                                >
                                  {String(row.action || "")}{" "}
                                  {String(row.side || "")} ·{" "}
                                  {String(row.status || "")} ·{" "}
                                  {String(row.ts || "")}
                                </div>
                              ))}
                              {recentRequests.length === 0 ? (
                                <div className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-2 text-xs text-slate-500">
                                  当前没有实例级请求流水
                                </div>
                              ) : null}
                            </div>
                          </div>

                          <div className="rounded-2xl border border-slate-800 bg-slate-950/40 p-4">
                            <div className="text-sm font-semibold text-slate-100">
                              事件时间轴
                            </div>
                            <div className="mt-3 space-y-2">
                              {timeline.map((item: any, index: number) => (
                                <div
                                  key={`${String(item.label || "timeline")}::${index}`}
                                  className="rounded-xl border border-slate-800 bg-slate-900/50 px-3 py-3 text-xs text-slate-300"
                                >
                                  <span className="font-semibold text-slate-100">
                                    {String(item.label || "-")}
                                  </span>
                                  <span className="ml-2">
                                    {String(item.value || "")}
                                  </span>
                                </div>
                              ))}
                              {timeline.length === 0 ? (
                                <div className="text-sm text-slate-500">
                                  当前还没有实例时间轴。
                                </div>
                              ) : null}
                            </div>
                          </div>
                        </div>

                        <div className="mt-4 flex flex-wrap gap-2">
                          <button
                            onClick={() =>
                              void handleRuntimeInstanceAction(
                                instanceId,
                                instance.active ? "pause" : "resume",
                              )
                            }
                            className="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-100 text-sm font-medium transition-colors"
                          >
                            {instance.active ? "暂停实例" : "继续实例"}
                          </button>
                          <button
                            onClick={() =>
                              void handleMarketplaceAction("rollback", {
                                id: strategyId,
                                name: instance.strategyName,
                              })
                            }
                            className="px-4 py-2 rounded-lg bg-warning/15 hover:bg-warning/25 text-warning text-sm font-medium transition-colors border border-warning/30"
                          >
                            回滚策略版本
                          </button>
                          <button
                            onClick={() =>
                              void handleRuntimeInstanceAction(
                                instanceId,
                                "remove",
                              )
                            }
                            className="px-4 py-2 rounded-lg bg-danger hover:bg-red-500 text-white text-sm font-medium transition-colors"
                          >
                            移除实例
                          </button>
                          <button
                            onClick={() => {
                              if (
                                !window.confirm(
                                  "确认恢复该实例到市场默认模板吗？这会清空实例覆写。",
                                )
                              ) {
                                return;
                              }
                              void handleRuntimeInstanceAction(
                                instanceId,
                                "restore_defaults",
                              );
                            }}
                            className="px-4 py-2 rounded-lg bg-slate-900 hover:bg-slate-800 text-slate-200 text-sm font-medium transition-colors border border-slate-700"
                          >
                            恢复实例默认
                          </button>
                          {Number(
                            instance.templateDiff?.summary?.overrideCount || 0,
                          ) > 0 ? (
                            <button
                              onClick={() => {
                                if (
                                  !window.confirm(
                                    "确认仅清空该实例覆写参数吗？",
                                  )
                                ) {
                                  return;
                                }
                                void handleRuntimeInstanceAction(
                                  instanceId,
                                  "clear_overrides",
                                );
                              }}
                              className="px-4 py-2 rounded-lg bg-slate-900 hover:bg-slate-800 text-slate-200 text-sm font-medium transition-colors border border-slate-700"
                            >
                              清空覆写
                            </button>
                          ) : null}
                        </div>
                      </article>
                    );
                  })}
                  {runtimeOpsInstances.length === 0 ? (
                    <div className="rounded-2xl border border-slate-800 bg-[#0A0E17] p-8 text-center text-sm text-slate-500">
                      当前没有运行实例，可先在策略集市部署实例后再回到看板。
                    </div>
                  ) : null}
                </div>
              </div>
            </div>
          )}
        </div>
      );
    }

    if (menu === "strategyCustom") {
      return (
        <div className="max-w-5xl w-full mx-auto p-6 space-y-4">
          <div className="bg-card border border-slate-800 rounded-2xl p-4">
            <div className="flex items-center justify-between">
              <h3 className="text-2xl font-bold text-slate-100">策略定制</h3>
              <div className="text-sm">
                {customDraftStatus === "saved" ? (
                  <span className="text-success">已保存</span>
                ) : customDraftStatus === "syncing" ? (
                  <span className="text-warning">同步中</span>
                ) : (
                  <span className="text-slate-400">未保存</span>
                )}
              </div>
            </div>
            <div className="mt-3 flex gap-2">
              <input
                value={customStrategyName}
                onChange={(e) => setCustomStrategyName(e.target.value)}
                placeholder="策略名称（如：黄金突破增强版）"
                className="flex-1 bg-[#0A0E17] border border-slate-700 rounded-xl px-4 py-3 text-slate-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50"
              />
              <button
                onClick={() => void handleOptimizeCustomStrategy()}
                disabled={customActionLoading !== null}
                className="px-5 py-3 rounded-xl bg-primary hover:bg-blue-500 disabled:opacity-50 text-white font-semibold transition-colors"
              >
                {customActionLoading === "optimize" ? "优化中" : "AI优化"}
              </button>
            </div>
            <textarea
              value={customStrategyDocument}
              onChange={(e) => setCustomStrategyDocument(e.target.value)}
              placeholder="请粘贴或编写策略文档：市场假设、入场规则、出场规则、风控约束..."
              className="mt-3 w-full min-h-[220px] bg-[#0A0E17] border border-slate-700 rounded-xl px-4 py-3 text-slate-200 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 resize-y"
            />
            <div className="mt-2 text-xs text-slate-500">
              {customDraftSavedAt
                ? `最后保存：${customDraftSavedAt}`
                : "等待输入策略文档..."}
            </div>
          </div>

          <div className="bg-card border border-slate-800 rounded-2xl p-4">
            <div className="text-base font-semibold mb-2">
              优化结果预览（策略标准 JSON）
            </div>
            <pre className="text-xs text-slate-300 whitespace-pre-wrap break-words rounded-xl border border-slate-800 bg-[#0A0E17] p-4 min-h-[88px]">
              {Object.keys(customOptimized).length > 0
                ? JSON.stringify(customOptimized, null, 2)
                : "尚未生成优化结果。"}
            </pre>
          </div>

          <div className="bg-card border border-slate-800 rounded-2xl p-4">
            <div className="text-base font-semibold mb-2">AI评估结果</div>
            <pre className="text-xs text-slate-300 whitespace-pre-wrap break-words rounded-xl border border-slate-800 bg-[#0A0E17] p-4 min-h-[88px]">
              {Object.keys(customEvaluation).length > 0
                ? JSON.stringify(customEvaluation, null, 2)
                : "尚未进行评估。"}
            </pre>
          </div>

          <div className="flex items-center gap-2">
            <button
              onClick={() => void handleGenerateCustomStrategy()}
              disabled={customActionLoading !== null}
              className="flex-1 px-4 py-3 rounded-xl bg-primary hover:bg-blue-500 disabled:opacity-50 text-white font-semibold transition-colors"
            >
              {customActionLoading === "generate" ? "生成中..." : "生成策略"}
            </button>
            <button
              onClick={() => void handleEvaluateCustomStrategy()}
              disabled={customActionLoading !== null}
              className="flex-1 px-4 py-3 rounded-xl bg-slate-800 hover:bg-slate-700 disabled:opacity-50 text-slate-100 font-semibold transition-colors"
            >
              {customActionLoading === "evaluate" ? "评估中..." : "AI评估"}
            </button>
          </div>
        </div>
      );
    }

    return (
      <div className="flex items-center justify-center h-full text-slate-500">
        该模块正在建设中...
      </div>
    );
  };

  return (
    <div className="h-screen w-screen flex bg-background text-slate-200 relative overflow-hidden">
      <CommercialGate />
      {templateEditorOpen && (
        <div className="absolute inset-0 z-[120] flex items-center justify-center bg-black/80 backdrop-blur-sm">
          <div className="w-full max-w-4xl mx-4 bg-card border border-slate-700 rounded-2xl shadow-2xl">
            <div className="flex items-center justify-between px-6 py-4 border-b border-slate-800">
              <h3 className="text-xl font-bold text-slate-100">
                参数模板配置 -{" "}
                {String(
                  templateStrategy?.name || templateStrategy?.id || "策略",
                )}
              </h3>
              <button
                onClick={() => {
                  setTemplateEditorOpen(false);
                  setTemplateSaveMessage(null);
                }}
                className="w-8 h-8 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300"
              >
                ×
              </button>
            </div>
            <div className="p-6 space-y-5 max-h-[75vh] overflow-y-auto">
              <div className="rounded-2xl border border-primary/20 bg-primary/5 p-4">
                <div className="text-lg font-semibold text-slate-100">
                  机器人运行合同
                </div>
                <div className="mt-2 text-sm leading-6 text-slate-400">
                  这不是普通参数表，而是把策略从“名字”翻译成“可运行实例”的正式合同。它一次性定义：
                  这条策略怎么交易、在什么环境下交易、以及和其他策略如何共存。
                </div>
              </div>

              <div className="rounded-2xl border border-slate-800 p-4 space-y-4">
                <div>
                  <div className="text-base font-semibold text-slate-100">
                    1. 交易执行基线
                  </div>
                  <div className="mt-1 text-sm text-slate-400">
                    定义这条策略单独运行时的执行人格、风控预算和持仓边界。
                  </div>
                </div>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">timeframe</div>
                    <select
                      value={templateBaseFields.timeframe}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          timeframe: e.target.value,
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    >
                      <option value="M1">M1</option>
                      <option value="M5">M5</option>
                      <option value="M15">M15</option>
                      <option value="H1">H1</option>
                    </select>
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">risk_per_trade</div>
                    <input
                      type="number"
                      min={0.001}
                      max={0.05}
                      step={0.001}
                      value={templateBaseFields.risk_per_trade}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          risk_per_trade: Number(e.target.value || 0),
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">atr_sl_mult</div>
                    <input
                      type="number"
                      min={0.8}
                      max={4}
                      step={0.1}
                      value={templateBaseFields.atr_sl_mult}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          atr_sl_mult: Number(e.target.value || 0),
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">tp_rr</div>
                    <input
                      type="number"
                      min={0.5}
                      max={5}
                      step={0.1}
                      value={templateBaseFields.tp_rr}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          tp_rr: Number(e.target.value || 0),
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">max_positions</div>
                    <input
                      type="number"
                      min={1}
                      max={10}
                      step={1}
                      value={templateBaseFields.max_positions}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          max_positions: Math.round(
                            Number(e.target.value || 1),
                          ),
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">reduce_only</div>
                    <select
                      value={templateBaseFields.reduce_only ? "true" : "false"}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          reduce_only: e.target.value === "true",
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    >
                      <option value="false">关闭</option>
                      <option value="true">开启</option>
                    </select>
                  </label>
                </div>
              </div>

              <div className="rounded-2xl border border-slate-800 p-4 space-y-4">
                <div>
                  <div className="text-base font-semibold text-slate-100">
                    2. Agent 协同配置
                  </div>
                  <div className="mt-1 text-sm text-slate-400">
                    定义策略在组合里的职责、适用环境和与其他策略的共存规则，避免多策略互搏。
                  </div>
                </div>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">策略风格</div>
                    <select
                      value={templateBaseFields.strategy_style}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          strategy_style: e.target.value,
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    >
                      <option value="trend">趋势</option>
                      <option value="breakout">突破</option>
                      <option value="mean_reversion">均值回归</option>
                      <option value="momentum">动量</option>
                    </select>
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">执行角色</div>
                    <select
                      value={templateBaseFields.execution_role}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          execution_role: e.target.value,
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    >
                      <option value="primary">主攻</option>
                      <option value="support">辅助</option>
                      <option value="confirm">确认</option>
                      <option value="auto_infer">自动推断</option>
                    </select>
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">适用市场</div>
                    <input
                      value={templateBaseFields.applicable_markets.join(", ")}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          applicable_markets: e.target.value
                            .split(",")
                            .map((item) => item.trim().toUpperCase())
                            .filter(Boolean),
                        }))
                      }
                      placeholder="TRENDING, BREAKOUT"
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">适用时段</div>
                    <input
                      value={templateBaseFields.applicable_sessions.join(", ")}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          applicable_sessions: e.target.value
                            .split(",")
                            .map((item) => item.trim().toUpperCase())
                            .filter(Boolean),
                        }))
                      }
                      placeholder="LONDON, NEW_YORK, NY_OVERLAP"
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">冲突组</div>
                    <input
                      value={templateBaseFields.conflict_groups.join(", ")}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          conflict_groups: e.target.value
                            .split(",")
                            .map((item) => item.trim())
                            .filter(Boolean),
                        }))
                      }
                      placeholder="trend, breakout_core"
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">协同标签</div>
                    <input
                      value={templateBaseFields.coordination_tags.join(", ")}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          coordination_tags: e.target.value
                            .split(",")
                            .map((item) => item.trim().toUpperCase())
                            .filter(Boolean),
                        }))
                      }
                      placeholder="TREND, MOMENTUM"
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">最大并发策略数</div>
                    <input
                      type="number"
                      min={1}
                      max={10}
                      step={1}
                      value={templateBaseFields.max_active_strategies}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          max_active_strategies: Math.round(
                            Number(e.target.value || 1),
                          ),
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">冲突 HOLD 阈值</div>
                    <input
                      type="number"
                      min={0}
                      max={1}
                      step={0.01}
                      value={templateBaseFields.conflict_hold_threshold}
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          conflict_hold_threshold: Number(e.target.value || 0),
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    />
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">同组可叠加</div>
                    <select
                      value={
                        templateBaseFields.allow_same_group_stack
                          ? "true"
                          : "false"
                      }
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          allow_same_group_stack: e.target.value === "true",
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    >
                      <option value="false">关闭</option>
                      <option value="true">开启</option>
                    </select>
                  </label>
                  <label className="space-y-2 text-sm">
                    <div className="text-slate-300">允许反风格混跑</div>
                    <select
                      value={
                        templateBaseFields.allow_counter_style_mix
                          ? "true"
                          : "false"
                      }
                      onChange={(e) =>
                        setTemplateBaseFields((prev) => ({
                          ...prev,
                          allow_counter_style_mix: e.target.value === "true",
                        }))
                      }
                      className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2"
                    >
                      <option value="false">关闭</option>
                      <option value="true">开启</option>
                    </select>
                  </label>
                </div>
              </div>

              <div className="rounded-2xl border border-slate-800 p-4 space-y-4">
                <div>
                  <div className="text-base font-semibold text-slate-100">
                    3. 高级参数扩展
                  </div>
                  <div className="mt-1 text-sm text-slate-400">
                    通用能力走结构化合同，策略特有参数继续通过 JSON
                    扩展，避免模板面板膨胀。
                  </div>
                </div>
                <textarea
                  value={templateAdvancedRaw}
                  onChange={(e) => {
                    setTemplateAdvancedRaw(e.target.value);
                    setTemplateAdvancedError("");
                  }}
                  className="w-full min-h-[120px] bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2 text-sm font-mono"
                  placeholder='例如: {"ema_fast":9,"ema_slow":21}'
                />
                {(templateAdvancedError || !parsedAdvancedParams.ok) && (
                  <div className="text-xs text-danger">
                    {templateAdvancedError || parsedAdvancedParams.error}
                  </div>
                )}
              </div>

              <div className="rounded-2xl border border-slate-800 p-4 space-y-4">
                <div>
                  <div className="text-base font-semibold text-slate-100">
                    4. 最终模板预览
                  </div>
                  <div className="mt-1 text-sm text-slate-400">
                    这里展示最终会传给后端的运行合同，用于提前暴露字段冲突和结构错误。
                  </div>
                </div>
                <pre className="w-full min-h-[220px] bg-[#0A0E17] border border-slate-700 rounded-xl px-3 py-2 text-xs whitespace-pre-wrap break-words">
                  {JSON.stringify(mergedTemplatePreview, null, 2)}
                </pre>
              </div>
            </div>
            <div className="flex justify-end gap-2 px-6 py-4 border-t border-slate-800">
              {templateSaveMessage && (
                <div
                  className={`mr-auto rounded-lg border px-3 py-2 text-sm ${
                    templateSaveMessage.type === "success"
                      ? "border-emerald-500/40 bg-emerald-500/10 text-emerald-200"
                      : "border-red-500/40 bg-red-500/10 text-red-200"
                  }`}
                >
                  {templateSaveMessage.text}
                </div>
              )}
              <button
                onClick={() => {
                  setTemplateEditorOpen(false);
                  setTemplateSaveMessage(null);
                }}
                className="px-4 py-2 rounded-lg bg-slate-700 hover:bg-slate-600 text-slate-100"
              >
                取消
              </button>
              <button
                onClick={() => void saveTemplateFromEditor()}
                disabled={templateSaveBusy}
                className="px-4 py-2 rounded-lg bg-primary hover:bg-blue-500 disabled:opacity-50 text-white font-medium"
              >
                {templateSaveBusy ? "保存中..." : "保存模板"}
              </button>
            </div>
          </div>
        </div>
      )}
      {/* 全局 Panic 模态框 */}
      {showPanicModal && (
        <div className="absolute inset-0 z-[100] flex items-center justify-center bg-black/80 backdrop-blur-sm animate-in fade-in">
          <div className="bg-card border border-danger/50 rounded-2xl p-8 max-w-md w-full mx-4 shadow-[0_0_50px_rgba(239,68,68,0.2)] scale-in-95 duration-200">
            <div className="flex flex-col items-center text-center space-y-4">
              <div className="w-16 h-16 bg-danger/20 rounded-full flex items-center justify-center">
                <ShieldAlert className="w-8 h-8 text-danger animate-pulse" />
              </div>
              <h3 className="text-2xl font-bold text-white">确认紧急阻断？</h3>
              <p className="text-slate-400 text-sm">
                此操作将立即发送强平指令清空所有持仓，并停止交易网关。请仅在极端行情或系统异常时使用。
              </p>
              <div className="flex gap-4 w-full mt-6">
                <button
                  onClick={() => setShowPanicModal(false)}
                  disabled={actionLoading === "panic"}
                  className="flex-1 py-3 bg-slate-800 hover:bg-slate-700 text-white rounded-xl font-medium transition-colors disabled:opacity-50"
                >
                  取消
                </button>
                <button
                  onClick={handlePanicAction}
                  disabled={actionLoading === "panic"}
                  className="flex-1 py-3 bg-danger hover:bg-red-500 text-white rounded-xl font-bold transition-all shadow-[0_0_15px_rgba(239,68,68,0.4)] disabled:opacity-50 flex items-center justify-center"
                >
                  {actionLoading === "panic" ? (
                    <div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
                  ) : (
                    "确认阻断"
                  )}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* 首次启动向导 */}
      {showSetupWizard && (
        <div className="absolute inset-0 z-[110] flex items-center justify-center bg-black/90 backdrop-blur-sm animate-in fade-in">
          <div className="bg-card border border-primary/50 rounded-2xl p-8 max-w-xl w-full mx-4 shadow-[0_0_50px_rgba(59,130,246,0.15)] scale-in-95 duration-300">
            <div className="flex items-center gap-3 mb-6 border-b border-slate-800 pb-4">
              <div className="w-10 h-10 rounded-xl bg-primary/20 flex items-center justify-center">
                <Settings className="w-5 h-5 text-primary" />
              </div>
              <div>
                <h3 className="text-xl font-bold text-white">
                  欢迎使用 OpenClaw 交易系统
                </h3>
                <p className="text-xs text-slate-400 mt-1">
                  请完成基础配置以启动您的量化引擎
                </p>
              </div>
            </div>

            <div className="space-y-6">
              <div>
                <label className="flex items-center gap-2 text-sm font-medium text-slate-300 mb-2">
                  <Key className="w-4 h-4 text-slate-500" />
                  配置主模型 API Key
                </label>
                <input
                  type="password"
                  value={setupForm.apiKey}
                  onChange={(e) =>
                    setSetupForm({ ...setupForm, apiKey: e.target.value })
                  }
                  placeholder="sk-..."
                  className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-4 py-3 text-slate-200 focus:outline-none focus:border-primary text-sm font-mono transition-colors"
                />
                <p className="text-[10px] text-slate-500 mt-2">
                  推荐使用 DeepSeek 或 Claude 模型。此 Key
                  仅保存在本地，绝不上传。
                </p>
              </div>

              <div>
                <label className="flex items-center gap-2 text-sm font-medium text-slate-300 mb-2">
                  <FolderOpen className="w-4 h-4 text-slate-500" />
                  指定 MT5 数据目录 (可选)
                </label>
                <input
                  type="text"
                  value={setupForm.mt5Path}
                  onChange={(e) =>
                    setSetupForm({ ...setupForm, mt5Path: e.target.value })
                  }
                  placeholder="留空则由系统自动探测..."
                  className="w-full bg-[#0A0E17] border border-slate-700 rounded-xl px-4 py-3 text-slate-200 focus:outline-none focus:border-primary text-sm font-mono transition-colors"
                />
              </div>

              <div className="pt-4 flex justify-end gap-3">
                <button
                  onClick={handleFinishWizard}
                  className="px-6 py-3 bg-slate-800 hover:bg-slate-700 text-white rounded-xl font-medium transition-colors text-sm"
                >
                  跳过，稍后配置
                </button>
                <button
                  onClick={handleFinishWizard}
                  className="px-6 py-3 bg-primary hover:bg-blue-500 text-white rounded-xl font-medium transition-all shadow-[0_0_15px_rgba(59,130,246,0.3)] text-sm flex items-center gap-2"
                >
                  保存并进入系统 <Play className="w-4 h-4" />
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* 全局 Toast 提示 */}
      {toast && (
        <div
          className={`absolute top-4 left-1/2 transform -translate-x-1/2 px-6 py-3 rounded-xl shadow-lg z-[160] flex items-center space-x-2 text-white font-medium animate-in fade-in slide-in-from-top-4 ${
            toast.type === "success"
              ? "bg-success"
              : toast.type === "warning"
                ? "bg-warning text-slate-950"
                : "bg-danger"
          }`}
        >
          {toast.type === "success" ? (
            <CheckCircle2 className="w-5 h-5" />
          ) : toast.type === "warning" ? (
            <AlertTriangle className="w-5 h-5" />
          ) : (
            <AlertCircle className="w-5 h-5" />
          )}
          <span>{toast.msg}</span>
        </div>
      )}

      {/* 二次确认模态框 */}
      {confirmModal && (
        <div className="absolute inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm animate-in fade-in">
          <div className="bg-card border border-slate-800 rounded-2xl p-6 w-full max-w-md shadow-2xl scale-in-95">
            <h3 className="text-xl font-bold mb-2 text-slate-100">
              {confirmModal.title}
            </h3>
            <p className="text-slate-400 mb-6">{confirmModal.message}</p>
            <div className="flex justify-end gap-3">
              <button
                onClick={() => setConfirmModal(null)}
                className="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300 transition-colors font-medium"
              >
                取消
              </button>
              <button
                onClick={confirmModal.onConfirm}
                className="px-4 py-2 rounded-lg bg-primary hover:bg-blue-500 text-white transition-colors font-medium"
              >
                确认执行
              </button>
            </div>
          </div>
        </div>
      )}

      {/* 侧边栏 */}
      <aside className="w-64 border-r border-slate-800 flex flex-col h-full bg-card/30 backdrop-blur-sm shrink-0">
        <div className="p-6 border-b border-slate-800">
          <div className="flex items-center space-x-3 mb-1">
            <div className="w-8 h-8 rounded-lg bg-danger/20 flex items-center justify-center text-danger font-bold text-xs">
              OC
            </div>
            <div>
              <h1 className="font-bold text-sm tracking-wide">
                OpenClaw 交易系统
              </h1>
              <p className="text-xs text-slate-400">
                一键版 <span className="text-[10px]">v{GUI_VERSION}</span>
              </p>
            </div>
          </div>
        </div>

        <nav className="flex-1 p-4 space-y-2 overflow-y-auto">
          <button
            onClick={() => setActiveMenu("dashboard")}
            className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "dashboard" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
          >
            <LayoutDashboard className="w-5 h-5" />
            <span>总控面板</span>
          </button>
          <button
            onClick={() => setActiveMenu("updates")}
            className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "updates" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
          >
            <DatabaseZap className="w-5 h-5" />
            <span>更新中心</span>
          </button>
          <button
            onClick={() => setActiveMenu("positions")}
            className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "positions" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
          >
            <LineChartIcon className="w-5 h-5" />
            <span>持仓与信号</span>
          </button>
          <button
            onClick={() => setActiveMenu("settings")}
            className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "settings" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
          >
            <Settings className="w-5 h-5" />
            <span>风控与参数</span>
          </button>
          <button
            onClick={() => setActiveMenu("logs")}
            className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "logs" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
          >
            <Terminal className="w-5 h-5" />
            <span>日志与告警</span>
          </button>
          <button
            onClick={() => setActiveMenu("timeline")}
            className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "timeline" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
          >
            <Clock className="w-5 h-5" />
            <span>复盘时间轴</span>
          </button>
          <button
            onClick={() => setActiveMenu("strategyMarketplace")}
            className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "strategyMarketplace" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
          >
            <Search className="w-5 h-5" />
            <span>策略集市</span>
          </button>
          <button
            onClick={() => setActiveMenu("robotDashboard")}
            className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "robotDashboard" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
          >
            <Cpu className="w-5 h-5" />
            <span>机器人看板</span>
          </button>
          <button
            onClick={() => setActiveMenu("strategyCustom")}
            className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "strategyCustom" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
          >
            <Crosshair className="w-5 h-5" />
            <span>策略定制</span>
          </button>

          <div className="pt-4 mt-4 border-t border-slate-800/50 space-y-2">
            <button
              onClick={() => setActiveMenu("webchat")}
              className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "webchat" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
            >
              <MessageSquare className="w-5 h-5" />
              <span>WebChat</span>
            </button>
            <button
              onClick={() => setActiveMenu("models")}
              className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "models" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
            >
              <Cpu className="w-5 h-5" />
              <span>大模型配置</span>
            </button>
            <button
              onClick={() => setActiveMenu("training")}
              className={`w-full flex items-center space-x-3 px-4 py-3 rounded-xl font-medium transition-colors ${activeMenu === "training" ? "bg-primary/20 text-primary" : "text-slate-400 hover:text-slate-200 hover:bg-slate-800/50"}`}
            >
              <DatabaseZap className="w-5 h-5" />
              <div className="flex-1 flex justify-between items-center">
                <span>训练与进化</span>
                {trainingStatus.isTraining && (
                  <span className="w-2 h-2 rounded-full bg-primary animate-pulse shadow-[0_0_8px_rgba(59,130,246,0.8)]"></span>
                )}
              </div>
            </button>
          </div>
        </nav>

        <div className="p-4 mt-auto border-t border-slate-800 text-center">
          <p className="text-[10px] text-slate-500 leading-tight">
            风险提示：本系统只供交流学习，不构成任何投资建议。
          </p>
        </div>
      </aside>

      <div className="flex-1 flex flex-col min-w-0 relative">
        {/* 顶部导航 */}
        <header className="h-16 bg-card border-b border-slate-800 flex items-center justify-between px-6 z-10">
          <div className="flex items-center space-x-4">
            <h2 className="text-xl font-bold text-white capitalize">
              {getMenuTitle(activeMenu)}
            </h2>
            {status.isRunning && (
              <span className="px-3 py-1 bg-success/20 text-success text-xs font-medium rounded-full animate-pulse">
                System Active
              </span>
            )}
          </div>
          <div className="flex items-center space-x-4">
            {enableWorkspaceExperience && (
              <button
                onClick={() => setIsZenMode(true)}
                className="flex items-center gap-2 px-4 py-2 bg-indigo-500/20 hover:bg-indigo-500/30 text-indigo-400 rounded-lg text-sm font-bold transition-all border border-indigo-500/30 shadow-[0_0_15px_rgba(99,102,241,0.2)]"
                title="进入沉浸式可视化工作站"
              >
                <Gamepad2 className="w-4 h-4" />
                Zen Mode
              </button>
            )}
            <button
              className="relative p-2 text-slate-400 hover:text-white transition-colors"
              onClick={() => setActiveMenu("notify")}
              title="点击查看通知与待复核信号"
            >
              <Bell className="w-5 h-5" />
              {/* 待复核提示小红点 */}
              {signalReviewPendingCount > 0 && (
                <span className="absolute top-1 right-1 w-2 h-2 bg-danger rounded-full animate-ping"></span>
              )}
            </button>
            <div className="w-8 h-8 rounded-full bg-slate-800 border border-slate-700 flex items-center justify-center">
              <span className="text-sm font-medium">M2</span>
            </div>
          </div>
        </header>

        {/* 主内容区 */}
        <main className="flex-1 flex flex-col h-full overflow-y-auto pb-12 relative">
          {renderView(activeMenu)}
        </main>
      </div>

      {/* 右侧抽屉面板 */}
      <div
        className={`fixed top-0 right-0 h-full w-[800px] max-w-[90vw] bg-background border-l border-slate-800 shadow-2xl transform transition-transform duration-300 z-[60] flex flex-col ${drawerPanel ? "translate-x-0" : "translate-x-full"}`}
      >
        {drawerPanel && (
          <>
            <div className="flex justify-between items-center p-4 border-b border-slate-800 bg-card">
              <h3 className="font-bold text-lg capitalize">
                {getMenuTitle(drawerPanel)}
              </h3>
              <button
                onClick={() => setDrawerPanel(null)}
                className="p-2 hover:bg-slate-800 rounded-lg text-slate-400 hover:text-white transition-colors"
              >
                <Square className="w-5 h-5 opacity-0" />
                <span className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-xl">
                  &times;
                </span>
              </button>
            </div>
            <div className="flex-1 overflow-y-auto relative">
              {renderView(drawerPanel)}
            </div>
          </>
        )}
      </div>

      {/* Drawer Overlay */}
      {drawerPanel && (
        <div
          className="fixed inset-0 bg-black/50 backdrop-blur-sm z-[50] transition-opacity"
          onClick={() => setDrawerPanel(null)}
        ></div>
      )}

      {/* 底部常驻状态栏 */}
      <div className="absolute bottom-0 left-64 right-0 h-8 bg-card/80 backdrop-blur-md border-t border-slate-800 flex items-center justify-between px-4 text-[10px] text-slate-400 z-40">
        <div className="flex items-center gap-4">
          <span className="flex items-center gap-1.5">
            <div
              className={`w-1.5 h-1.5 rounded-full ${status.isRunning ? "bg-success" : "bg-danger"}`}
            ></div>
            {status.isRunning ? "引擎运行中" : "引擎已停止"}
          </span>
          <span className="flex items-center gap-1.5 border-l border-slate-800 pl-4">
            <Activity className="w-3 h-3" />
            MT5 延迟:{" "}
            <span
              className={
                status.mt5Online
                  ? "text-success font-mono"
                  : "text-danger font-mono"
              }
            >
              {status.mt5Online &&
              (status as any).system_stats?.mt5_latency >= 0
                ? `${(status as any).system_stats.mt5_latency}ms`
                : "离线"}
            </span>
          </span>
          <span className="flex items-center gap-1.5 border-l border-slate-800 pl-4">
            <DatabaseZap className="w-3 h-3" />
            CPU:{" "}
            <span className="font-mono text-slate-300">
              {(status as any).system_stats?.cpu_percent || 0}%
            </span>{" "}
            | RAM:{" "}
            <span className="font-mono text-slate-300">
              {(status as any).system_stats?.ram_used_mb || 0}MB (
              {(status as any).system_stats?.ram_percent || 0}%)
            </span>
          </span>
        </div>
        <div className="flex items-center gap-4">
          <span>策略版本: v1.2.0</span>
          <span>最后同步: {new Date().toLocaleTimeString()}</span>
        </div>
      </div>

      {/* Zen Mode 沉浸工作站渲染 (全屏覆盖) */}
      {enableWorkspaceExperience && isZenMode && (
        <ZenWorkspace
          status={status}
          state={{
            riskLevel: status.riskLevel,
            positionOpen: status.positionOpen,
            positionSide: status.positionSide,
          }}
          onExit={() => setIsZenMode(false)}
        />
      )}
    </div>
  );
}

export default App;
