<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <title>Genesis Dashboard</title>
  <link rel="icon" type="image/svg+xml" href="/public/favicon.svg">
  <link rel="manifest" href="/manifest.json">
  <meta name="theme-color" content="#0f1117">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
  <link rel="stylesheet" href="/index.css">
  <link rel="stylesheet" href="/css/modals.css">
  <link rel="stylesheet" href="/css/buttons.css">
  <link rel="stylesheet" href="/vendor/google/google-icons.css">
  <link href="/vendor/ace-min/ace.min.css" rel="stylesheet">
  <script src="/vendor/ace-min/ace.js"></script>
  <script type="module" src="/js/initFw.js"></script>

  <script type="module">
    import { fetchApi } from "/js/api.js";

    document.addEventListener("alpine:init", () => {
      Alpine.store("genesisDashboard", {
        // Tab state
        activeTab: "overview",
        _tabInitialized: { overview: false, chat: false, internals: false, config: false, files: false, work: false, observations: false, memory: false, knowledge: false, backup: false },

        // State
        health: {},
        activity: [],
        sessions: [],

        configFiles: [],
        // providerActivity moved to operationalVitals
        errorSummary: { groups: [], active_alerts: [], totals: { events: 0, dead_letters: 0, deferred_failures: 0 } },
        budgets: [],
        routingConfig: null,
        approvals: [],
        queueReview: {
          clearingIds: {},
          clearingAll: false,
          message: null,
          error: null,
        },
        budgetEditor: {
          budget_type: "daily",
          limit_usd: "",
          warning_pct: "0.8",
          saving: false,
          message: null,
          error: null,
        },
        routingEditor: {
          siteId: null,
          chainText: "",
          default_paid: false,
          never_pays: false,
          saving: false,
          reloading: false,
          message: null,
          error: null,
          reloadMessage: null,
          reloadError: null,
        },
        filters: { subsystem: "", minSeverity: "info" },
        sessionFilters: { status: "", sessionType: "", channel: "" },
        pauseState: { paused: false, reason: null, since: null, toggling: false },
        activityTimeRange: "24h",
        expandedSession: null,
        sessionEvents: [],
        selectedModule: null,
        loading: true,
        lastHealthUpdate: null,
        configExpanded: false,
        configCategoryFilter: null,
        configModal: {
          open: false,
          name: "",
          content: "",
          loadedName: "",
          syntax: "markdown",
          editable: true,
          deletable: false,
          dirty: false,
          saving: false,
          saveMessage: null,
          saveError: null,
          fetch: { state: "idle", lastSuccess: null, error: null },
        },
        surplusModal: {
          open: false,
          data: null,
          filter: null,
          fetch: { state: "idle", lastSuccess: null, error: null },
        },
        outreachModal: {
          open: false,
          messages: [],
          pendingApprovals: [],
          categoryFilter: null,
          fetch: { state: "idle", lastSuccess: null, error: null },
        },
        mcpModal: {
          open: false,
          data: null,
          fetch: { state: "idle", lastSuccess: null, error: null },
        },
        egoModal: {
          open: false,
          tab: "overview",
          proposalFilter: null,
          cycles: [],
          proposals: [],
          cadence: null,
          followUps: [],
          expandedCycle: null,
          rejectingId: null,
          rejectReason: "",
          fetch: { state: "idle", lastSuccess: null, error: null },
        },
        egoStatus: null,
        apiKeysModal: { open: false },
        modules: [],
        providersDetail: [],
        operationalVitals: null,
        autonomousCliPolicy: null,
        cognitiveState: null,
        essentialKnowledge: null,
        awarenessSignals: null,
        jobHealth: null,
        evalMetrics: null,
        autonomyConfig: null,
        approvalActions: {},
        _restartingBridge: false,
        _restartingHF: false,
        error: null,

        // ── Chat terminal state ───────────────────────────────────
        _terminalWindow: null,

        // ── Files tab state ────────────────────────────────────────
        fileBrowser: {
          path: null,
          parent: null,
          entries: [],
          loading: false,
          selectedFile: null,
          fileContent: null,
          fileMode: "text",
          fileWritable: false,
          fileDirty: false,
          saving: false,
          sidebarCollapsed: false,
          _resizing: false,
        },
        fileUpload: { dragging: false, uploading: false, error: null },

        // ── Work tab state (tasks + sessions + follow-ups) ──────
        taskList: [],
        taskActive: {},
        taskExpanded: null,
        taskDetail: null,
        taskDetailSteps: [],
        taskTimeline: [],
        taskLinkedFollowUps: [],
        tasksView: 'active',       // 'active' or 'completed'
        sessionsList: [],
        sessionsView: 'active',    // 'active' or 'history'
        sessionsExpanded: null,
        followUpsList: [],
        followUpsView: 'active',   // 'active' or 'all'
        followUpsCounts: {},
        followUpsExpanded: null,

        // ── Comms state (on Chat tab) ────────────────────────────
        commsOutreach: [],
        commsProposals: [],
        commsPendingApprovals: [],
        commsCounts: {},
        commsView: 'pending',
        commsTab: 'outreach',
        commsProposalFilter: null,
        commsCategoryFilter: null,
        commsRejectingId: null,
        commsRejectReason: '',

        // ── Memory tab state ──────────────────────────────────────
        memorySearch: { query: "", results: [], loading: false },
        memoryRecent: { items: [], total: 0, loading: false },
        memoryStats: {},
        memoryDetail: null,
        knowledgeQuery: "",
        knowledgeSearchResults: [],
        knowledgeRecent: [],
        knowledgeStats: null,
        knowledgeDetail: null,
        // Upload state
        knowledgeUpload: {
          dragging: false,
          file: null,
          uploading: false,
          confirm: false,
          uploadId: null,
          projectType: "",
          domain: "",
          purpose: "",
          context: "",
          mode: "extract",
          error: null,
        },
        knowledgeUploads: [],
        knowledgeTaxonomy: { project_types: [], domains: [] },
        _uploadPollInterval: null,

        // ── Confirm modal state ──────────────────────────────────
        confirmModal: { show: false, title: '', message: '', _resolve: null },

        // ── Backup tab state ──────────────────────────────────────
        backupStatus: null,

        // ── Update state ─────────────────────────────────────────
        updateStatus: null,
        updateProgress: null,
        _updating: false,
        _updateReconnecting: false,
        _checkingForUpdates: false,
        _checkUpToDate: false,
        _resolvingConflicts: false,

        // ── Settings hub state ────────────────────────────────────
        settingsDomains: null,
        settingsData: {},         // domain_name → config object
        settingsEditing: null,    // domain being edited
        settingsViewing: null,    // readonly domain being viewed
        systemTimezone: null,     // from /api/genesis/settings/timezone
        settingsSaving: false,
        settingsRestartMessage: null,

        // ── Auth state ────────────────────────────────────────────
        authEnabled: false,

        // ── Provider Keys state ──────────────────────────────────
        secretsGroups: null,
        secretsEditing: {},       // key_name → true when input open
        secretsSaving: false,
        secretsValues: {},        // key_name → input value during edit
        secretsMessage: null,     // {type, text}

        fetchState: {
          health: { state: "idle", lastSuccess: null, error: null },
          activity: { state: "idle", lastSuccess: null, error: null },
          sessions: { state: "idle", lastSuccess: null, error: null },

          // providerActivity removed — data now in operationalVitals
          attention: { state: "idle", lastSuccess: null, error: null },
          budgets: { state: "idle", lastSuccess: null, error: null },
          routing: { state: "idle", lastSuccess: null, error: null },
          approvals: { state: "idle", lastSuccess: null, error: null },
          modules: { state: "idle", lastSuccess: null, error: null },
          providersDetail: { state: "idle", lastSuccess: null, error: null },
          cognitive: { state: "idle", lastSuccess: null, error: null },
          awarenessSignals: { state: "idle", lastSuccess: null, error: null },
          jobHealth: { state: "idle", lastSuccess: null, error: null },
          autonomyConfig: { state: "idle", lastSuccess: null, error: null },
          autonomousCliPolicy: { state: "idle", lastSuccess: null, error: null },
        },

        // Polling interval IDs
        _healthInterval: null,
        _activityInterval: null,

        _sessionsInterval: null,
        _modulesInterval: null,
        _routingInterval: null,
        _approvalsInterval: null,
        _cognitiveInterval: null,
        _ekInterval: null,
        _awarenessInterval: null,
        _jobHealthInterval: null,
        _tasksInterval: null,
        _workSessionsInterval: null,
        _followUpsInterval: null,
        _observationsInterval: null,
        _commsInterval: null,

        // Observations tab state
        observationsList: [],
        observationsHasMore: false,
        observationsExpanded: null,
        observationsView: 'unresolved',
        observationsFilters: { priority: '', type: '', source: '' },
        observationsAvailableFilters: { types: [], sources: [] },
        observationsCounts: { counts: {}, total_unsurfaced: 0, total_unresolved: 0 },
        observationsResolving: {},
        observationsMarkingRead: {},
        observationsBatchIds: {},

        // Tab management
        _TAB_INTERVALS: {
          overview:  ["_cognitiveInterval", "_ekInterval", "_modulesInterval"],
          chat:      ["_commsInterval", "_approvalsInterval"],
          internals: ["_awarenessInterval", "_routingInterval", "_jobHealthInterval", "_activityInterval", "_sessionsInterval"],
          config:    [],
          files:     [],
          work:      ["_tasksInterval", "_workSessionsInterval", "_followUpsInterval"],
          observations: ["_observationsInterval"],
          memory:    [],
          knowledge: [],
          backup:    [],
        },

        initTab() {
          const hash = location.hash.replace("#", "") || "overview";
          const valid = ["overview", "chat", "internals", "config", "files", "work", "observations", "memory", "knowledge", "backup"];
          this.activeTab = valid.includes(hash) ? hash : "overview";
          window.addEventListener("hashchange", () => {
            const h = location.hash.replace("#", "");
            if (valid.includes(h) && h !== this.activeTab) {
              this._onTabChange(this.activeTab, h);
              this.activeTab = h;
            }
          });
        },

        _onTabChange(oldTab, newTab) {
          this._stopTabIntervals(oldTab);
          this._startTabIntervals(newTab);
        },

        _stopTabIntervals(tab) {
          for (const key of (this._TAB_INTERVALS[tab] || [])) {
            if (this[key]) { clearInterval(this[key]); this[key] = null; }
          }
        },

        _startTabIntervals(tab) {
          const first = !this._tabInitialized[tab];
          this._tabInitialized[tab] = true;
          switch (tab) {
            case "overview":
              if (first) { this.fetchCognitive(); this.fetchEssentialKnowledge(); this.fetchModules(); this.fetchProvidersDetail(); }
              this._cognitiveInterval = setInterval(() => this.fetchCognitive(), 60000);
              this._ekInterval = setInterval(() => this.fetchEssentialKnowledge(), 120000);
              this._modulesInterval = setInterval(() => { this.fetchModules(); this.fetchProvidersDetail(); }, 30000);
              break;
            case "internals":
              if (first) { this.fetchAwarenessSignals(); this.fetchOperationalVitals(); this.fetchAutonomyConfig(); this.fetchAutonomousCliPolicy(); this.fetchRoutingConfig(); this.fetchJobHealth(); this.fetchEvalMetrics(); this.fetchApprovals(); this.fetchActivity(); this.fetchSessions(); }
              this._awarenessInterval = setInterval(() => this.fetchAwarenessSignals(), 30000);
              this._routingInterval = setInterval(() => this.fetchRoutingConfig(), 15000);
              this._jobHealthInterval = setInterval(() => this.fetchJobHealth(), 60000);
              this._activityInterval = setInterval(() => this.fetchActivity(), 10000);
              this._sessionsInterval = setInterval(() => this.fetchSessions(), 30000);
              break;
            case "config":
              if (first) { this.fetchConfigFiles(); this.fetchBudgets(); this.fetchSettingsDomains(); this.fetchAutonomousCliPolicy(); this.fetchSecrets(); }
              break;
            case "chat":
              // Re-fit terminal on tab re-entry
              if (!first && this._xterm && this._fitAddon) { this._fitAddon.fit(); }
              if (first) { this.fetchComms(); this.fetchApprovals(); }
              this._commsInterval = setInterval(() => this.fetchComms(), 15000);
              this._approvalsInterval = setInterval(() => this.fetchApprovals(), 15000);
              break;
            case "files":
              if (first) { this.fetchFiles(); }
              break;
            case "work":
              if (first) { this.fetchTasks(); this.fetchWorkSessions(); this.fetchFollowUps(); }
              this._tasksInterval = setInterval(() => this.fetchTasks(), 5000);
              this._workSessionsInterval = setInterval(() => this.fetchWorkSessions(), 10000);
              this._followUpsInterval = setInterval(() => this.fetchFollowUps(), 15000);
              break;
            case "observations":
              if (first) { this.fetchObservations(); this.fetchObservationsSummary(); this.fetchObservationsFilters(); }
              this._observationsInterval = setInterval(() => { this.fetchObservations(); this.fetchObservationsSummary(); }, 30000);
              break;
            case "memory":
              if (first) { this.fetchMemoryRecent(); this.fetchMemoryStats(); }
              break;
            case "knowledge":
              if (first) { this.fetchKnowledgeRecent(); this.fetchKnowledgeStats(); this.fetchKnowledgeUploads(); this.fetchKnowledgeTaxonomy(); }
              // Resume polling if any uploads are processing
              if (this.knowledgeUploads.some(u => u.status === "processing")) { this._startUploadPolling(); }
              break;
            case "backup":
              if (first) { this.fetchBackupStatus(); this.fetchUpdateStatus(); this.fetchUpdateProgress(); }
              break;
          }
        },

        navigateTo(tab, anchor) {
          if (this.activeTab !== tab) {
            location.hash = tab;
            if (anchor) {
              setTimeout(() => {
                const el = document.getElementById(anchor);
                if (el) el.scrollIntoView({ behavior: "smooth" });
              }, 50);
            }
          } else if (anchor) {
            const el = document.getElementById(anchor);
            if (el) el.scrollIntoView({ behavior: "smooth" });
          }
        },

        // Lifecycle
        async onOpen() {
          // Check auth status (non-blocking, best-effort)
          this.checkAuth();

          // Always fetch: health, errors, pause, update status, approvals (needed on all tabs)
          await Promise.all([
            this.fetchHealth(),
            this.fetchErrorSummary(),
            this.fetchPauseState(),
            this.fetchUpdateStatus(),
            this.fetchEgoStatus(),
            this.fetchApprovals(),
          ]);

          // Initialize tab from URL hash and fetch tab-specific data
          this.initTab();
          this._startTabIntervals(this.activeTab);

          this.loading = false;

          // Always-on polling: health snapshot drives the attention strip on all tabs
          this._healthInterval = setInterval(() => {
            this.fetchHealth();
            this.fetchErrorSummary();
            this.fetchPauseState();
            this.fetchEgoStatus();
          }, 15000);
        },

        cleanup() {
          if (this._healthInterval) clearInterval(this._healthInterval);
          for (const tab of ["overview", "chat", "internals", "config", "work"]) {
            this._stopTabIntervals(tab);
          }
          // Terminal runs in its own window — no cleanup needed here
        },

        // Fetch methods
        async fetchHealth() {
          this.startFetch("health");
          try {
            const resp = await fetchApi("/api/genesis/health");
            if (resp && resp.ok) {
              this.health = await resp.json();
              this.lastHealthUpdate = Date.now();
              this.error = null;
              this.finishFetch("health");
            } else {
              this.failFetch("health", "Health endpoint returned an error");
            }
          } catch (e) {
            console.warn("Health fetch failed:", e);
            this.error = "Failed to fetch health data";
            this.failFetch("health", "Failed to fetch health data");
          }
        },

        get healthStale() {
          if (!this.lastHealthUpdate) return false;
          return (Date.now() - this.lastHealthUpdate) > 60000;
        },

        async fetchActivity() {
          this.startFetch("activity");
          try {
            let url = "/api/genesis/activity?limit=100";
            if (this.filters.minSeverity) url += `&min_severity=${this.filters.minSeverity}`;
            if (this.filters.subsystem) url += `&subsystem=${this.filters.subsystem}`;
            // Time range filter
            const ranges = { "1h": 1, "6h": 6, "24h": 24, "7d": 168 };
            const hours = ranges[this.activityTimeRange] || 1;
            const since = new Date(Date.now() - hours * 3600000).toISOString();
            url += `&since=${since}`;
            const resp = await fetchApi(url);
            if (resp && resp.ok) {
              this.activity = await resp.json();
              this.finishFetch("activity");
            } else {
              this.failFetch("activity", "Activity feed unavailable");
            }
          } catch (e) {
            console.warn("Activity fetch failed:", e);
            this.failFetch("activity", "Activity feed unavailable");
          }
        },

        async fetchSessions() {
          this.startFetch("sessions");
          try {
            let url = "/api/genesis/sessions?limit=50";
            if (this.sessionFilters.status) url += `&status=${this.sessionFilters.status}`;
            if (this.sessionFilters.sessionType) url += `&session_type=${this.sessionFilters.sessionType}`;
            if (this.sessionFilters.channel) url += `&channel=${this.sessionFilters.channel}`;
            const resp = await fetchApi(url);
            if (resp && resp.ok) {
              this.sessions = await resp.json();
              this.finishFetch("sessions");
            } else {
              this.failFetch("sessions", "Session history unavailable");
            }
          } catch (e) {
            console.warn("Sessions fetch failed:", e);
            this.failFetch("sessions", "Session history unavailable");
          }
        },

        async toggleSession(sessionId) {
          if (this.expandedSession === sessionId) {
            this.expandedSession = null;
            this.sessionEvents = [];
            return;
          }
          this.expandedSession = sessionId;
          try {
            const resp = await fetchApi(`/api/genesis/sessions/${sessionId}/events`);
            if (resp && resp.ok) this.sessionEvents = await resp.json();
          } catch (e) { this.sessionEvents = []; }
        },


        async fetchConfigFiles() {
          try {
            const resp = await fetchApi("/api/genesis/config-files");
            if (resp && resp.ok) this.configFiles = await resp.json();
          } catch (e) { console.warn("Config files fetch failed:", e); }
        },

        async fetchModules() {
          this.startFetch("modules");
          try {
            const resp = await fetchApi("/api/genesis/modules");
            if (resp && resp.ok) {
              this.modules = await resp.json();
              this.finishFetch("modules");
            } else {
              this.failFetch("modules", "Modules endpoint unavailable");
            }
          } catch (e) {
            console.error("Modules fetch failed:", e);
            this.failFetch("modules", "Modules endpoint unavailable");
          }
        },

        async fetchProvidersDetail() {
          this.startFetch("providersDetail");
          try {
            const resp = await fetchApi("/api/genesis/providers-detail");
            if (resp && resp.ok) {
              this.providersDetail = await resp.json();
              this.finishFetch("providersDetail");
            } else {
              this.failFetch("providersDetail", "Providers endpoint unavailable");
            }
          } catch (e) {
            console.error("Providers detail fetch failed:", e);
            this.failFetch("providersDetail", "Providers endpoint unavailable");
          }
        },

        async fetchOperationalVitals() {
          try {
            const resp = await fetchApi("/api/genesis/operational-vitals");
            if (resp?.ok) this.operationalVitals = await resp.json();
          } catch (e) {
            console.warn("Operational vitals fetch failed:", e);
          }
        },

        async fetchErrorSummary() {
          this.startFetch("attention");
          try {
            const resp = await fetchApi("/api/genesis/unified-errors?grouped=true&limit=6");
            if (resp && resp.ok) {
              this.errorSummary = await resp.json();
              this.finishFetch("attention");
            } else {
              this.failFetch("attention", "Error summary unavailable");
            }
          } catch (e) {
            console.warn("Unified errors fetch failed:", e);
            this.failFetch("attention", "Error summary unavailable");
          }
        },

        async fetchBudgets() {
          this.startFetch("budgets");
          try {
            const resp = await fetchApi("/api/genesis/budgets");
            if (resp && resp.ok) {
              this.budgets = await resp.json();
              this.syncBudgetEditor();
              this.finishFetch("budgets");
            } else {
              this.failFetch("budgets", "Budget config unavailable");
            }
          } catch (e) {
            console.warn("Budget fetch failed:", e);
            this.failFetch("budgets", "Budget config unavailable");
          }
        },

        // ── Chat terminal (opens in new window) ─────────────────
        openTerminal() {
          if (this._terminalWindow && !this._terminalWindow.closed) {
            this._terminalWindow.focus();
            return;
          }
          this._terminalWindow = window.open("/genesis/terminal", "genesis-terminal");
        },

        // ── Files tab fetches ─────────────────────────────────────
        async fetchFiles(path) {
          this.fileBrowser.loading = true;
          try {
            const url = path ? `/api/genesis/files?path=${encodeURIComponent(path)}` : "/api/genesis/files";
            const resp = await fetchApi(url);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.fileBrowser.path = data.path;
              this.fileBrowser.parent = data.parent;
              this.fileBrowser.entries = data.entries;
              this.fileBrowser.selectedFile = null;
              this.fileBrowser.fileContent = null;
            }
          } catch (e) { console.warn("Files fetch failed:", e); }
          this.fileBrowser.loading = false;
        },
        async openFile(filePath) {
          try {
            const resp = await fetchApi(`/api/genesis/files/read?path=${encodeURIComponent(filePath)}`);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.fileBrowser.selectedFile = data.path;
              this.fileBrowser.fileContent = data.content;
              this.fileBrowser.fileMode = data.mode;
              this.fileBrowser.fileWritable = data.writable;
              this.fileBrowser.fileDirty = false;
            }
          } catch (e) { console.warn("File read failed:", e); }
        },
        async saveFile() {
          if (!this.fileBrowser.selectedFile) return;
          this.fileBrowser.saving = true;
          try {
            const resp = await fetchApi("/api/genesis/files/write", {
              method: "PUT",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ path: this.fileBrowser.selectedFile, content: this.fileBrowser.fileContent }),
            });
            if (resp && resp.ok) { this.fileBrowser.fileDirty = false; }
            else { const d = await resp.json(); alert(d.error || "Save failed"); }
          } catch (e) { alert("Save failed: " + e.message); }
          this.fileBrowser.saving = false;
        },
        async uploadFile(event) {
          event.preventDefault();
          this.fileUpload.dragging = false;
          this.fileUpload.error = null;
          const files = event.dataTransfer?.files || event.target?.files;
          if (!files || files.length === 0) return;
          this.fileUpload.uploading = true;
          try {
            const form = new FormData();
            form.append("file", files[0]);
            const resp = await fetchApi("/api/genesis/files/upload", { method: "POST", body: form });
            if (resp && resp.ok) {
              const data = await resp.json();
              this.fetchFiles(data.path.substring(0, data.path.lastIndexOf("/")));
            } else {
              const err = resp ? await resp.json() : {};
              this.fileUpload.error = err.error || "Upload failed";
            }
          } catch (e) { this.fileUpload.error = "Upload failed: " + e.message; }
          this.fileUpload.uploading = false;
        },
        _startFileBrowserResize(e, sidebar) {
          this.fileBrowser._resizing = true;
          const startX = e.clientX;
          const startW = sidebar.offsetWidth;
          const container = sidebar.parentElement;
          const maxW = container.offsetWidth * 0.6;
          const onMove = (ev) => {
            const newW = Math.max(150, Math.min(maxW, startW + ev.clientX - startX));
            sidebar.style.flex = '0 0 ' + newW + 'px';
          };
          const onUp = () => {
            this.fileBrowser._resizing = false;
            document.removeEventListener('mousemove', onMove);
            document.removeEventListener('mouseup', onUp);
          };
          document.addEventListener('mousemove', onMove);
          document.addEventListener('mouseup', onUp);
        },

        // ── Tasks tab fetches ─────────────────────────────────────
        async fetchTasks() {
          try {
            const resp = await fetchApi("/api/genesis/tasks?include_completed=true&limit=50");
            if (resp && resp.ok) {
              const data = await resp.json();
              this.taskList = data.tasks || [];
              this.taskActive = data.active || {};
            }
          } catch (e) { console.warn("Tasks fetch failed:", e); }
        },
        async fetchTaskDetail(taskId) {
          if (this.taskExpanded === taskId) { this.taskExpanded = null; this.taskDetail = null; this.taskDetailSteps = []; this.taskTimeline = []; this.taskLinkedFollowUps = []; return; }
          this.taskExpanded = taskId;
          try {
            const resp = await fetchApi(`/api/genesis/tasks/${taskId}`);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.taskDetail = data.task;
              this.taskDetailSteps = data.steps || [];
              this.taskTimeline = data.timeline || [];
              this.taskLinkedFollowUps = data.linked_follow_ups || [];
            }
          } catch (e) { console.warn("Task detail fetch failed:", e); }
        },
        phaseColor(phase) {
          const colors = {
            pending: '#616161', observing: '#78909c', reviewing: '#7e57c2',
            planning: '#9e9e9e', executing: '#2196F3', verifying: '#ab47bc',
            synthesizing: '#26a69a', delivering: '#66bb6a', completed: '#66bb6a',
            failed: '#ef9a9a', cancelled: '#9e9e9e', blocked: '#ffa726', paused: '#ffa726',
          };
          return colors[phase?.toLowerCase()] || '#9e9e9e';
        },
        async taskAction(taskId, action) {
          try {
            await fetchApi(`/api/genesis/tasks/${taskId}/${action}`, { method: "POST" });
            await this.fetchTasks();
            if (this.taskExpanded === taskId) await this.fetchTaskDetail(taskId);
          } catch (e) { console.warn(`Task ${action} failed:`, e); }
        },

        // ── Work tab fetches ──────────────────────────────────────
        async fetchWorkSessions() {
          try {
            const resp = await fetchApi(`/api/genesis/work?type=session&view=${this.sessionsView}&limit=50`);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.sessionsList = data.items || [];
            }
          } catch (e) { console.warn("Work sessions fetch failed:", e); }
        },
        async fetchFollowUps() {
          try {
            const resp = await fetchApi("/api/genesis/follow-ups?limit=50");
            if (resp && resp.ok) {
              const data = await resp.json();
              this.followUpsList = data.follow_ups || [];
              this.followUpsCounts = data.counts || {};
            }
          } catch (e) { console.warn("Follow-ups fetch failed:", e); }
        },

        // ── Observations tab fetches ─────────────────────────────
        async fetchObservations() {
          try {
            const f = this.observationsFilters;
            const params = new URLSearchParams();
            params.set("limit", "50");
            if (this.observationsView === 'unresolved') params.set("resolved", "false");
            if (f.priority) params.set("priority", f.priority);
            if (f.type) params.set("type", f.type);
            if (f.source) params.set("source", f.source);
            const resp = await fetchApi(`/api/genesis/observations?${params}`);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.observationsList = data.observations || [];
              this.observationsHasMore = data.has_more || false;
            }
          } catch (e) { console.warn("Observations fetch failed:", e); }
        },
        async fetchObservationsSummary() {
          try {
            const resp = await fetchApi("/api/genesis/observations/summary");
            if (resp && resp.ok) {
              this.observationsCounts = await resp.json();
            }
          } catch (e) { console.warn("Observations summary fetch failed:", e); }
        },
        async fetchObservationsFilters() {
          try {
            const resp = await fetchApi("/api/genesis/observations/filters");
            if (resp && resp.ok) {
              this.observationsAvailableFilters = await resp.json();
            }
          } catch (e) { console.warn("Observations filters fetch failed:", e); }
        },
        async resolveObservation(id, notes) {
          this.observationsResolving = { ...this.observationsResolving, [id]: true };
          try {
            const resp = await fetchApi(`/api/genesis/observations/${id}/resolve`, {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ notes: notes || "" }),
            });
            if (resp && resp.ok) {
              await this.fetchObservations();
              await this.fetchObservationsSummary();
            }
          } catch (e) { console.warn("Resolve failed:", e); }
          finally { const { [id]: _, ...rest } = this.observationsResolving; this.observationsResolving = rest; }
        },
        async markObservationRead(id) {
          this.observationsMarkingRead = { ...this.observationsMarkingRead, [id]: true };
          try {
            const resp = await fetchApi(`/api/genesis/observations/${id}/mark-read`, {
              method: "POST",
            });
            if (resp && resp.ok) {
              const obs = this.observationsList.find(o => o.id === id);
              if (obs) obs.surfaced_at = new Date().toISOString();
              await this.fetchObservationsSummary();
            }
          } catch (e) { console.warn("Mark read failed:", e); }
          finally { const { [id]: _, ...rest } = this.observationsMarkingRead; this.observationsMarkingRead = rest; }
        },
        async batchObservationsAction(action) {
          const ids = Object.keys(this.observationsBatchIds).filter(k => this.observationsBatchIds[k]);
          if (!ids.length) return;
          try {
            const resp = await fetchApi("/api/genesis/observations/batch", {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ action, ids }),
            });
            if (resp && resp.ok) {
              this.observationsBatchIds = {};
              await this.fetchObservations();
              await this.fetchObservationsSummary();
            }
          } catch (e) { console.warn("Batch action failed:", e); }
        },
        toggleObservationBatch(id) {
          if (this.observationsBatchIds[id]) {
            const { [id]: _, ...rest } = this.observationsBatchIds;
            this.observationsBatchIds = rest;
          } else {
            this.observationsBatchIds = { ...this.observationsBatchIds, [id]: true };
          }
        },
        get observationsBatchCount() {
          return Object.keys(this.observationsBatchIds).filter(k => this.observationsBatchIds[k]).length;
        },

        // ── Comms fetches (on Chat tab) ──────────────────────────
        async fetchComms() {
          try {
            const resp = await fetchApi(`/api/genesis/comms?view=${this.commsView}&limit=30`);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.commsOutreach = data.outreach || [];
              this.commsProposals = data.proposals || [];
              this.commsPendingApprovals = data.pending_approvals || [];
              this.commsCounts = data.counts || {};
            }
          } catch (e) { console.warn("Comms fetch failed:", e); }
        },
        async resolveCommsProposal(proposalId, status, userResponse) {
          try {
            await fetchApi(`/api/genesis/comms/proposals/${proposalId}/resolve`, {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ status, user_response: userResponse || "" }),
            });
            this.commsRejectingId = null;
            this.commsRejectReason = '';
            await this.fetchComms();
          } catch (e) { console.warn("Proposal resolve failed:", e); }
        },

        // ── Memory tab fetches ────────────────────────────────────
        async fetchMemoryRecent() {
          this.memoryRecent.loading = true;
          try {
            const resp = await fetchApi("/api/genesis/memory/recent?limit=50");
            if (resp && resp.ok) {
              const data = await resp.json();
              this.memoryRecent.items = data.memories || [];
              this.memoryRecent.total = data.total || 0;
            }
          } catch (e) { console.warn("Memory recent failed:", e); }
          this.memoryRecent.loading = false;
        },
        async fetchMemoryStats() {
          try {
            const resp = await fetchApi("/api/genesis/memory/stats");
            if (resp && resp.ok) { this.memoryStats = await resp.json(); }
          } catch (e) { console.warn("Memory stats failed:", e); }
        },
        async searchMemory() {
          if (!this.memorySearch.query.trim()) return;
          this.memorySearch.loading = true;
          try {
            const resp = await fetchApi(`/api/genesis/memory/search?q=${encodeURIComponent(this.memorySearch.query)}&limit=30`);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.memorySearch.results = data.results || [];
            }
          } catch (e) { console.warn("Memory search failed:", e); }
          this.memorySearch.loading = false;
        },
        async viewMemoryDetail(memId) {
          try {
            const resp = await fetchApi(`/api/genesis/memory/${memId}`);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.memoryDetail = data.memory;
            }
          } catch (e) { console.warn("Memory detail failed:", e); }
        },
        async deleteMemory(memId) {
          try {
            await fetchApi(`/api/genesis/memory/${memId}`, { method: "DELETE" });
            this.memoryDetail = null;
            await this.fetchMemoryRecent();
            await this.fetchMemoryStats();
          } catch (e) { console.warn("Memory delete failed:", e); }
        },

        // ── Knowledge tab fetches ──────────────────────────────────
        async fetchKnowledgeRecent() {
          try {
            const resp = await fetchApi("/api/genesis/knowledge/recent?limit=50");
            if (resp && resp.ok) {
              const data = await resp.json();
              this.knowledgeRecent = data.units || [];
            }
          } catch (e) { console.warn("Knowledge recent failed:", e); }
        },
        async fetchKnowledgeStats() {
          try {
            const resp = await fetchApi("/api/genesis/knowledge/stats");
            if (resp && resp.ok) { this.knowledgeStats = await resp.json(); }
          } catch (e) { console.warn("Knowledge stats failed:", e); }
        },
        async searchKnowledge() {
          if (!this.knowledgeQuery.trim()) return;
          try {
            const resp = await fetchApi(`/api/genesis/knowledge/search?q=${encodeURIComponent(this.knowledgeQuery)}&limit=30`);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.knowledgeSearchResults = data.results || [];
            }
          } catch (e) { console.warn("Knowledge search failed:", e); }
        },
        async viewKnowledgeDetail(unitId) {
          try {
            const resp = await fetchApi(`/api/genesis/knowledge/${unitId}`);
            if (resp && resp.ok) {
              const data = await resp.json();
              this.knowledgeDetail = data.unit;
            }
          } catch (e) { console.warn("Knowledge detail failed:", e); }
        },
        async deleteKnowledge(unitId) {
          try {
            await fetchApi(`/api/genesis/knowledge/${unitId}`, { method: "DELETE" });
            this.knowledgeDetail = null;
            await this.fetchKnowledgeRecent();
            await this.fetchKnowledgeStats();
          } catch (e) { console.warn("Knowledge delete failed:", e); }
        },

        // ── Knowledge upload methods ────────────────────────────
        async handleKnowledgeFileDrop(event) {
          event.preventDefault();
          this.knowledgeUpload.dragging = false;
          const files = event.dataTransfer?.files || event.target?.files;
          if (!files || files.length === 0) return;
          await this._uploadKnowledgeFile(files[0]);
        },
        async _uploadKnowledgeFile(file) {
          this.knowledgeUpload.error = null;
          this.knowledgeUpload.uploading = true;
          try {
            const form = new FormData();
            form.append("file", file);
            const resp = await fetch("/api/genesis/knowledge/upload", { method: "POST", body: form });
            if (!resp.ok) {
              const err = await resp.json().catch(() => ({}));
              throw new Error(err.error || `Upload failed (${resp.status})`);
            }
            const data = await resp.json();
            this.knowledgeUpload.file = { name: data.filename, size: data.file_size, mime: data.mime_type };
            this.knowledgeUpload.uploadId = data.upload_id;
            this.knowledgeUpload.confirm = true;
            this.knowledgeUpload.uploading = false;
            // Fetch taxonomy for autocomplete
            await this.fetchKnowledgeTaxonomy();
          } catch (e) {
            this.knowledgeUpload.uploading = false;
            this.knowledgeUpload.error = e.message;
          }
        },
        async fetchKnowledgeTaxonomy() {
          try {
            const resp = await fetchApi("/api/genesis/knowledge/taxonomy");
            if (resp && resp.ok) { this.knowledgeTaxonomy = await resp.json(); }
          } catch (e) { console.warn("Taxonomy fetch failed:", e); }
        },
        async confirmKnowledgeIngest() {
          const u = this.knowledgeUpload;
          if (!u.projectType.trim()) { u.error = "Project type is required"; return; }
          u.error = null;
          try {
            const resp = await fetchApi("/api/genesis/knowledge/ingest", {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({
                upload_id: u.uploadId,
                project_type: u.projectType.trim(),
                domain: u.domain.trim() || "auto",
                purpose: u.purpose.trim() || null,
                context: u.context.trim() || "",
                mode: u.mode || "extract",
              }),
            });
            if (!resp.ok) {
              const err = await resp.json().catch(() => ({}));
              throw new Error(err.error || "Ingest failed");
            }
            this.cancelKnowledgeUpload();
            await this.fetchKnowledgeUploads();
            this._startUploadPolling();
          } catch (e) {
            u.error = e.message;
          }
        },
        async cancelKnowledgeUpload() {
          const uploadId = this.knowledgeUpload.uploadId;
          this.knowledgeUpload = {
            dragging: false, file: null, uploading: false, confirm: false,
            uploadId: null, projectType: "", domain: "", purpose: "", context: "", mode: "extract", error: null,
          };
          // Clean up server-side file + DB record
          if (uploadId) {
            try { await fetchApi(`/api/genesis/knowledge/upload/${uploadId}`, { method: "DELETE" }); }
            catch (e) { console.warn("Upload cleanup failed:", e); }
          }
        },
        async fetchKnowledgeUploads() {
          try {
            const resp = await fetchApi("/api/genesis/knowledge/uploads");
            if (resp && resp.ok) {
              const data = await resp.json();
              this.knowledgeUploads = data.uploads || [];
            }
          } catch (e) { console.warn("Uploads list failed:", e); }
        },
        _startUploadPolling() {
          if (this._uploadPollInterval) return;
          this._uploadPollInterval = setInterval(async () => {
            await this.fetchKnowledgeUploads();
            const hasActive = this.knowledgeUploads.some(u => u.status === "processing");
            if (!hasActive) {
              clearInterval(this._uploadPollInterval);
              this._uploadPollInterval = null;
              // Refresh knowledge data since new units may have been created
              await this.fetchKnowledgeRecent();
              await this.fetchKnowledgeStats();
            }
          }, 3000);
        },
        _formatFileSize(bytes) {
          if (!bytes) return "—";
          if (bytes < 1024) return bytes + " B";
          if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
          return (bytes / (1024 * 1024)).toFixed(1) + " MB";
        },

        // ── Confirm modal ─────────────────────────────────────
        showConfirm(title, message) {
          return new Promise(resolve => {
            this.confirmModal = { show: true, title, message, _resolve: resolve };
          });
        },
        _confirmModalResolve(result) {
          if (this.confirmModal._resolve) this.confirmModal._resolve(result);
          this.confirmModal = { show: false, title: '', message: '', _resolve: null };
        },

        // ── Backup tab fetches ───────────────────────────────────
        async fetchBackupStatus() {
          try {
            const resp = await fetchApi("/api/genesis/backup/status");
            if (resp && resp.ok) { this.backupStatus = await resp.json(); }
          } catch (e) { console.warn("Backup status failed:", e); }
        },
        async triggerBackup() {
          try {
            const resp = await fetchApi("/api/genesis/backup/trigger", { method: "POST" });
            if (resp && resp.ok) { alert("Backup triggered"); setTimeout(() => this.fetchBackupStatus(), 5000); }
            else { alert("Trigger failed"); }
          } catch (e) { alert("Trigger failed: " + e.message); }
        },

        // ── Update methods ──────────────────────────────────────
        async fetchUpdateStatus() {
          try {
            const resp = await fetchApi("/api/genesis/updates/status");
            if (resp && resp.ok) { this.updateStatus = await resp.json(); }
          } catch (e) { console.warn("Update status failed:", e); }
        },
        async checkForUpdates() {
          this._checkingForUpdates = true;
          this._checkUpToDate = false;
          try {
            const resp = await fetchApi("/api/genesis/updates/check", { method: "POST" });
            if (resp && resp.ok) {
              const check = await resp.json();
              if (!this.updateStatus) await this.fetchUpdateStatus();
              if (check.commits_behind > 0) {
                this.updateStatus.update_available = {
                  commits_behind: check.commits_behind,
                  target_tag: check.target_tag,
                  summary: check.summary,
                  detected_at: new Date().toISOString(),
                };
              } else {
                this.updateStatus.update_available = null;
                this._checkUpToDate = true;
                setTimeout(() => { this._checkUpToDate = false; }, 4000);
              }
            } else {
              let msg = "Could not reach upstream";
              try { const body = await resp.json(); if (body.error) msg = body.error; } catch {}
              alert("Check failed: " + msg);
            }
          } catch (e) { alert("Server unreachable — is Genesis running?"); }
          this._checkingForUpdates = false;
        },
        async fetchUpdateProgress() {
          try {
            const resp = await fetchApi("/api/genesis/updates/progress");
            if (resp && resp.ok) { this.updateProgress = await resp.json(); }
          } catch (e) { /* server may be down during update */ }
        },
        _updatePhaseLabel(phase) {
          const labels = {
            fetching: "Fetching latest code...",
            merging: "Merging updates...",
            bootstrap: "Running bootstrap...",
            migrations: "Running migrations...",
            health_check: "Verifying system health...",
            done: "Update complete",
          };
          return labels[phase] || "Starting update...";
        },
        async applyUpdate() {
          const msg = "Apply Genesis update?\n\nA background session will:\n\u2022 Back up data\n\u2022 Merge latest code\n\u2022 Resolve trivial conflicts automatically\n\u2022 Run migrations & restart services\n\u2022 Verify health\n\nContinue?";
          if (!(await this.showConfirm("Apply Update", msg))) return;
          this._updating = true;
          try {
            await fetchApi("/api/genesis/updates/apply", {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ supervised: true }),
            });
          } catch (e) { /* expected — server may restart */ }
          const start = Date.now();
          let seenInProgress = false;
          const poll = setInterval(async () => {
            try {
              await this.fetchUpdateProgress();
              const prog = this.updateProgress;
              if (!prog) return;
              if (prog.in_progress) seenInProgress = true;
              // Conflicts detected — stop polling, show resolve UI
              if (prog.escalation && (prog.escalation.includes("tier3_needed") || prog.escalation.includes("tier2_needed"))
                  && !prog.in_progress) {
                clearInterval(poll);
                this._updating = false;
                await this.fetchUpdateStatus();
                return;
              }
              // Failed state (not success, not in progress)
              if (prog.failed && !prog.in_progress) {
                clearInterval(poll);
                this._updating = false;
                await this.fetchUpdateStatus();
                return;
              }
              // Success
              if (!prog.in_progress && prog.summary && prog.summary.startsWith("success")) {
                clearInterval(poll);
                this._updating = false;
                await this.fetchUpdateStatus();
                await this.fetchHealth();
                return;
              }
              // Fallback: health ok + not in progress
              if (!prog.in_progress) {
                const resp = await fetchApi("/api/genesis/health");
                if (resp && resp.ok) {
                  clearInterval(poll);
                  this._updating = false;
                  await this.fetchUpdateStatus();
                  await this.fetchHealth();
                  return;
                }
              }
              // Silent-death detection: process ended without leaving any state
              if (!prog.in_progress && !prog.summary && !prog.escalation && !(prog.conflicts && prog.conflicts.length)) {
                if (seenInProgress || Date.now() - start > 30000) {
                  clearInterval(poll);
                  this._updating = false;
                  alert("Update process ended without completing.\nCheck server logs for status.");
                  await this.fetchUpdateStatus();
                  return;
                }
              }
            } catch (e) { /* server may be restarting, keep polling */ }
            // Backstop: if server is completely dead, stop after 30 min
            if (Date.now() - start > 1800000) {
              clearInterval(poll);
              this._updating = false;
              alert("Update polling timed out after 30 minutes.\nCheck server status manually.");
              return;
            }
          }, 5000);
        },
        async resolveConflicts() {
          if (!(await this.showConfirm("Resolve Conflicts", "Spawn an Opus session to resolve deep merge conflicts?\n\nThis may take a few minutes."))) return;
          this._resolvingConflicts = true;
          try {
            const resp = await fetchApi("/api/genesis/updates/resolve", { method: "POST" });
            if (resp && !resp.ok) {
              const data = await resp.json();
              alert("Failed: " + (data.error || "unknown error"));
              this._resolvingConflicts = false;
              return;
            }
          } catch (e) { /* server may restart */ }
          // Poll for completion
          const poll = setInterval(async () => {
            try {
              await this.fetchUpdateProgress();
              if (this.updateProgress && !this.updateProgress.in_progress) {
                clearInterval(poll);
                this._resolvingConflicts = false;
                await this.fetchUpdateStatus();
                await this.fetchHealth();
              }
            } catch (e) { /* keep polling */ }
          }, 5000);
          // Safety timeout — alert and refresh status so user isn't left with a blank UI
          setTimeout(async () => {
            clearInterval(poll);
            this._resolvingConflicts = false;
            alert("Conflict resolution did not complete after 15 minutes.\nCheck server logs for status.");
            await this.fetchUpdateStatus();
          }, 900000);
        },

        async dismissUpdate() {
          try {
            await fetchApi("/api/genesis/updates/dismiss", { method: "POST" });
            this.updateProgress = {};
            await this.fetchUpdateStatus();
          } catch (e) { console.warn("Dismiss failed:", e); }
        },

        // ── Settings hub fetches ─────────────────────────────────
        async fetchSettingsDomains() {
          try {
            const resp = await fetchApi("/api/genesis/settings");
            if (resp && resp.ok) { this.settingsDomains = await resp.json(); }
          } catch (e) { console.warn("Settings index failed:", e); }
          // Also fetch the system timezone
          try {
            const tzResp = await fetchApi("/api/genesis/settings/timezone");
            if (tzResp && tzResp.ok) { this.systemTimezone = (await tzResp.json()).timezone; }
          } catch (e) { /* ignore */ }
        },
        async fetchSettingsData(domain) {
          try {
            const resp = await fetchApi(`/api/genesis/settings/${domain}`);
            if (resp && resp.ok) {
              const d = await resp.json();
              this.settingsData[domain] = d.config;
            }
          } catch (e) { console.warn(`Settings fetch ${domain} failed:`, e); }
        },
        async saveSettings(domain) {
          this.settingsSaving = true;
          try {
            const resp = await fetchApi(`/api/genesis/settings/${domain}`, {
              method: "PUT",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify(this.settingsData[domain]),
            });
            if (resp && resp.ok) {
              const d = await resp.json();
              this.settingsData[domain] = d.config;
              this.settingsEditing = null;
              if (domain === "autonomous_cli_policy") {
                this.fetchAutonomousCliPolicy();
              }
              if (d.needs_restart) { this.settingsRestartMessage = "Settings saved. Restart Genesis server to apply."; }
            } else {
              const err = await resp.json().catch(() => ({}));
              alert("Save failed: " + (err.details ? err.details.join(", ") : err.error || "Unknown error"));
            }
          } catch (e) { alert("Save failed: " + e.message); }
          this.settingsSaving = false;
        },
        startEditSettings(domain) {
          if (!this.settingsData[domain]) { this.fetchSettingsData(domain); }
          this.settingsEditing = domain;
        },
        viewSettings(domain) {
          if (this.settingsViewing === domain) { this.settingsViewing = null; return; }
          if (!this.settingsData[domain]) { this.fetchSettingsData(domain); }
          this.settingsViewing = domain;
        },

        // ── Provider Keys methods ────────────────────────────────
        async fetchSecrets() {
          try {
            const resp = await fetchApi("/api/genesis/secrets");
            if (resp && resp.ok) { this.secretsGroups = (await resp.json()).groups; }
          } catch (e) { console.warn("Secrets fetch failed:", e); }
        },
        toggleSecretEdit(keyName) {
          this.secretsEditing = {...this.secretsEditing, [keyName]: !this.secretsEditing[keyName]};
          if (!this.secretsEditing[keyName]) { delete this.secretsValues[keyName]; }
        },
        async saveSecret(keyName) {
          const val = (this.secretsValues[keyName] || '').trim();
          if (!val) { this.secretsMessage = {type: 'error', text: 'Value cannot be empty'}; return; }
          this.secretsSaving = true;
          try {
            const resp = await fetchApi("/api/genesis/secrets", {
              method: "PUT", headers: {"Content-Type": "application/json"},
              body: JSON.stringify({keys: {[keyName]: val}}),
            });
            const d = await resp.json();
            if (resp.ok) {
              this.secretsEditing = {...this.secretsEditing, [keyName]: false};
              delete this.secretsValues[keyName];
              this.secretsMessage = {type: 'restart', text: `${keyName} saved. Changes take effect after server restart.`};
              this.fetchSecrets();
            } else {
              this.secretsMessage = {type: 'error', text: d.error || 'Save failed'};
            }
          } catch (e) { this.secretsMessage = {type: 'error', text: e.message}; }
          this.secretsSaving = false;
        },
        // Map env var names → provider_type values from model_routing.yaml.
        // MAINTENANCE: update when adding new providers to config/model_routing.yaml.
        _KEY_TO_PROVIDER_TYPES: {
          API_KEY_GROQ: ['groq'],
          API_KEY_MISTRAL: ['mistral'],
          GOOGLE_API_KEY: ['google'],
          API_KEY_OPENROUTER: ['openrouter'],
          ANTHROPIC_API_KEY: ['anthropic'],
          API_KEY_DEEPSEEK: ['deepseek'],
          API_KEY_QWEN: ['qwen'],
          API_KEY_ZENMUX: ['zenmux'],
          API_KEY_MINIMAX: ['minimax'],
          OPENAI_API_KEY: ['openai'],
          API_KEY_XAI: ['xai'],
          API_KEY_DEEPINFRA: ['deepinfra'],
          API_KEY_CEREBRAS: ['cerebras'],
          API_KEY_GITHUB: ['github'],
          API_KEY_SAMBANOVA: ['sambanova'],
        },
        secretHealthStatus(keyEntry) {
          if (keyEntry.status === 'not_set') return 'not_set';
          const provTypes = this._KEY_TO_PROVIDER_TYPES[keyEntry.key];
          if (!provTypes || !this.routingConfig) return keyEntry.status;
          const cbStates = this.routingConfig.cb_states || {};
          const providers = this.routingConfig.providers || {};
          // Find all routing providers that match this key's provider types
          const matchedProviders = Object.keys(providers).filter(pname => {
            const prov = providers[pname];
            return provTypes.includes(prov.type);
          });
          if (matchedProviders.length === 0) return keyEntry.status;
          const openCount = matchedProviders.filter(p => cbStates[p] === 'OPEN').length;
          if (openCount === matchedProviders.length) return 'error';
          if (openCount > 0) return 'degraded';
          return 'healthy';
        },
        secretStatusColor(status) {
          if (status === 'validated' || status === 'healthy') return '#4caf50';
          if (status === 'configured') return '#4caf50';
          if (status === 'degraded') return '#f0ad4e';
          if (status === 'error') return '#d9534f';
          return 'var(--color-text-secondary)';
        },

        // ── Auth methods ─────────────────────────────────────────
        async checkAuth() {
          try {
            const resp = await fetchApi("/api/genesis/auth/status");
            if (resp && resp.ok) {
              const d = await resp.json();
              this.authEnabled = d.enabled;
            }
          } catch (e) { /* auth check is best-effort */ }
        },
        async logout() {
          try {
            await fetchApi("/api/genesis/auth/logout", {
              method: "POST", credentials: "same-origin",
            });
          } catch (e) { /* ignore */ }
          window.location.href = "/genesis/login";
        },

        _SETTING_LABELS: {
          // Autonomous CLI Policy
          autonomous_cli_fallback_enabled: 'CLI Fallback Enabled',
          manual_approval_required: 'Manual Approval Required',
          approval_channel: 'Approval Channel',
          reask_interval_hours: 'Re-ask Interval (hours)',
          shared_export_enabled: 'Shared Export',
          // TTS
          provider: 'TTS Provider', voice_id: 'Voice ID', model: 'Model',
          stability: 'Stability', similarity_boost: 'Similarity Boost',
          style: 'Style Expressiveness', speed: 'Speed',
          use_speaker_boost: 'Speaker Boost', strip_markdown: 'Strip Markdown',
          max_chars: 'Max Characters', block_background_sessions: 'Block Background TTS',
          // Ego
          enabled: 'Enabled', cadence_minutes: 'Cadence (minutes)',
          activity_threshold_minutes: 'Activity Threshold (min)',
          max_interval_minutes: 'Max Interval (min)', backoff_multiplier: 'Backoff Multiplier',
          board_size: 'Board Size', batch_digest: 'Batch Digest',
          ego_thinking_budget_usd: 'Thinking Budget ($)',
          ego_dispatch_budget_usd: 'Dispatch Budget ($)',
          morning_report_hour: 'Morning Report Hour', morning_report_minute: 'Morning Report Minute',
          shadow_morning_report: 'Shadow Morning Report',
          consecutive_failure_limit: 'Failure Limit', failure_backoff_minutes: 'Failure Backoff (min)',
          // Inbox Monitor
          watch_path: 'Watch Path', response_dir: 'Response Dir Pattern',
          check_interval_seconds: 'Check Interval (sec)', batch_size: 'Batch Size',
          effort: 'Effort Level', timeout_s: 'Timeout (sec)',
          // Outreach
          start: 'Start Time', end: 'End Time',
          default: 'Default Channel', blocker: 'Blocker Channel',
          alert: 'Alert Channel', surplus: 'Surplus Channel', digest: 'Digest Channel',
          max_daily: 'Max Daily Messages', surplus_daily: 'Surplus Daily Limit',
          trigger_time: 'Trigger Time', timeout_hours: 'Timeout (hours)',
          poll_interval_minutes: 'Poll Interval (min)',
          // Surplus
          interval_minutes: 'Dispatch Interval (min)', task_expiry_hours: 'Task Expiry (hours)',
          max_iterations_per_cycle: 'Max Iterations/Cycle',
          brainstorm_check_hours: 'Brainstorm Check (hours)',
          code_audit_hours: 'Code Audit (hours)', code_index_hours: 'Code Index (hours)',
          recon_gather_hours: 'Recon Gather (hours)', maintenance_hours: 'Maintenance (hours)',
          analytical_hours: 'Analytical (hours)', follow_up_dispatch_minutes: 'Follow-up Dispatch (min)',
          memory_extraction_hours: 'Memory Extraction (hours)',
          // Resilience
          transition_count: 'Transition Count', window_seconds: 'Window (sec)',
          stabilization_seconds: 'Stabilization (sec)',
          confirmation_probes: 'Confirmation Probes', confirmation_interval_s: 'Confirmation Interval (sec)',
          drain_pace_s: 'Drain Pace (sec)', embedding_pace_per_min: 'Embedding Pace/min',
          queue_overflow_threshold: 'Queue Overflow Threshold',
          max_sessions_per_hour: 'Max Sessions/Hour', throttle_threshold_pct: 'Throttle Threshold (%)',
          // Confidence Gates
          min_confidence: 'Min Confidence', min_separability: 'Min Separability',
          shadow_mode: 'Shadow Mode',
          // Updates
          interval_hours: 'Check Interval (hours)',
          auto_apply: 'Auto Apply', allowed_impacts: 'Allowed Impacts',
          backup_before_update: 'Backup Before Update',
          // Channels
          telegram: 'Telegram',
          default_model: 'Default Model', default_effort: 'Default Effort',
        },
        _SETTING_DESCS: {
          // Autonomous CLI Policy
          autonomous_cli_fallback_enabled: 'Allow background sessions to use Claude Code CLI when API routing fails',
          manual_approval_required: 'Require Telegram approval before dispatching background CC sessions',
          approval_channel: 'Channel for approval requests (must be configured and reachable)',
          reask_interval_hours: 'Hours between re-asking for approval on the same task',
          shared_export_enabled: 'Export policy to Guardian shared mount for host-side enforcement',
          // TTS
          provider: 'Active TTS provider. Requires restart to switch.',
          voice_id: 'Voice ID string from the TTS provider (e.g., ElevenLabs voice ID)',
          model: 'LLM model for processing (opus = highest quality, haiku = fastest)',
          stability: '0.0\u20131.0: higher = more consistent voice',
          similarity_boost: '0.0\u20131.0: higher = closer to original voice',
          style: '0.0\u20131.0: higher = more expressive delivery',
          speed: '0.7\u20131.2: playback speed multiplier',
          use_speaker_boost: 'Apply TTS provider speaker boost enhancement',
          strip_markdown: 'Remove markdown formatting before synthesis',
          max_chars: 'Maximum text length sent to TTS',
          block_background_sessions: 'Prevent background sessions from triggering voice',
          // Ego
          enabled: 'Enable autonomous ego sessions (proposal pipeline)',
          cadence_minutes: 'Base interval between autonomous cycles',
          activity_threshold_minutes: 'Min time since last user activity before running',
          max_interval_minutes: 'Maximum backoff cap (prevents indefinite delays)',
          backoff_multiplier: 'How much to increase interval on idle cycles',
          board_size: 'Max active proposals on the bulletin board (ego tables excess)',
          batch_digest: 'Bundle ego proposals into periodic digests instead of individual messages',
          ego_thinking_budget_usd: 'Daily cap for ego cycle (thinking) costs',
          ego_dispatch_budget_usd: 'Daily cap for dispatched background sessions',
          morning_report_hour: 'Hour (0\u201323) to send the daily morning report',
          morning_report_minute: 'Minute (0\u201359) for morning report delivery',
          shadow_morning_report: 'Send reports to a test topic for validation before going live',
          consecutive_failure_limit: 'Consecutive failures before circuit breaker trips',
          failure_backoff_minutes: 'Cooldown period after consecutive failures before retrying',
          // Inbox Monitor
          watch_path: 'Directory path monitored for incoming files',
          response_dir: 'Subdirectory pattern where responses are written (excluded from scanning)',
          check_interval_seconds: 'How often (in seconds) to scan the inbox directory for new files',
          batch_size: 'Maximum files to process per scan cycle (1\u201310)',
          effort: 'Processing depth: low (fast), medium (balanced), high (thorough), xhigh (Opus 4.7 only), or max',
          timeout_s: 'Max seconds per inbox item processing before timeout',
          // Outreach
          start: 'Quiet hours start \u2014 no outreach before this time (e.g., 22:00)',
          end: 'Quiet hours end \u2014 outreach resumes after this time (e.g., 07:00)',
          default: 'Channel for general outreach (morning reports, digests)',
          blocker: 'Channel for blocking/critical alerts that need immediate attention',
          alert: 'Channel for non-blocking alerts and notifications',
          surplus: 'Channel for surplus compute outputs (brainstorms, enrichment)',
          digest: 'Channel for periodic summary digests',
          max_daily: 'Maximum outreach messages per day across all categories',
          surplus_daily: 'Maximum surplus compute messages per day',
          trigger_time: 'Daily time when digest/report delivery fires (e.g., 08:00)',
          timeout_hours: 'Max hours to wait for outreach delivery confirmation',
          poll_interval_minutes: 'How often (in minutes) to check for pending outreach items',
          // Surplus
          interval_minutes: 'How often the surplus dispatch loop runs',
          task_expiry_hours: 'Pending tasks older than this are discarded',
          max_iterations_per_cycle: 'Maximum tasks dispatched per surplus cycle',
          brainstorm_check_hours: 'Hours between brainstorm surplus runs',
          code_audit_hours: 'Hours between code audit runs',
          code_index_hours: 'Hours between code indexing runs',
          recon_gather_hours: 'Hours between recon gathering runs',
          maintenance_hours: 'Hours between maintenance task runs',
          analytical_hours: 'Hours between analytical runs (0 = disabled)',
          follow_up_dispatch_minutes: 'Minutes between follow-up dispatch checks',
          memory_extraction_hours: 'Hours between memory extraction runs',
          // Resilience
          transition_count: 'State transitions in window before flagging as flapping',
          window_seconds: 'Time window for flapping detection',
          stabilization_seconds: 'Seconds a service must stay stable after recovery',
          confirmation_probes: 'Health probes required to confirm recovery',
          confirmation_interval_s: 'Seconds between confirmation probes',
          drain_pace_s: 'Seconds between draining queued items',
          embedding_pace_per_min: 'Max embedding operations per minute during recovery',
          queue_overflow_threshold: 'Queue size that triggers overflow alert',
          max_sessions_per_hour: 'Max CC sessions per hour before throttling',
          throttle_threshold_pct: 'API usage percentage that triggers rate throttling',
          // Confidence Gates
          min_confidence: 'Minimum confidence score to accept (0.0\u20131.0)',
          min_separability: 'Minimum separability score for deep reflection (0.0\u20131.0)',
          shadow_mode: 'Log what would be filtered but do not enforce',
          // Updates
          interval_hours: 'Hours between checking for upstream updates',
          auto_apply: 'Automatically apply safe updates without approval',
          allowed_impacts: 'Impact levels eligible for auto-apply',
          backup_before_update: 'Run backup before applying any update',
          // Channels
          default_model: 'Model for new Telegram sessions (opus = highest quality, haiku = fastest)',
          default_effort: 'Effort level for new Telegram sessions (higher = more thorough)',
        },
        _SETTING_CHOICES: {
          provider: ['elevenlabs', 'fish_audio', 'cartesia'],
          model: ['opus', 'sonnet', 'haiku'],
          effort: ['low', 'medium', 'high', 'xhigh', 'max'],
          approval_channel: ['telegram', 'email', 'dashboard'],
          default: ['telegram', 'email', 'dashboard'],
          blocker: ['telegram', 'email', 'dashboard'],
          alert: ['telegram', 'email', 'dashboard'],
          surplus: ['telegram', 'email', 'dashboard'],
          digest: ['telegram', 'email', 'dashboard'],
          default_model: ['opus', 'sonnet', 'haiku'],
          default_effort: ['low', 'medium', 'high', 'xhigh', 'max'],
        },
        // Display order for settings domains — most important first
        _DOMAIN_ORDER: [
          'channels', 'autonomous_cli_policy', 'ego', 'outreach', 'tts',
          'inbox_monitor', 'surplus', 'resilience', 'confidence_gates',
          'updates', 'recon_schedules', 'recon_watchlist', 'recon_sources',
          'autonomy', 'autonomy_rules', 'guardian',
          'model_profiles', 'model_routing', 'content_sanitization',
        ],
        _DOMAIN_LABELS: {
          autonomous_cli_policy: 'Autonomous CLI Policy',
          ego: 'Autonomous Ego', outreach: 'Outreach Pipeline',
          tts: 'Text-to-Speech', inbox_monitor: 'Inbox Monitor',
          surplus: 'Surplus Compute', resilience: 'Resilience',
          confidence_gates: 'Confidence Gates', updates: 'Updates',
          recon_schedules: 'Recon Schedules', recon_watchlist: 'Recon Watchlist',
          recon_sources: 'Recon Sources',
          autonomy: 'Autonomy Levels', autonomy_rules: 'Autonomy Rules',
          guardian: 'Guardian', model_profiles: 'Model Profiles',
          model_routing: 'Model Routing',
          content_sanitization: 'Content Sanitization',
          channels: 'Channels',
        },
        _sortedDomains(domains) {
          const order = this._DOMAIN_ORDER;
          return [...domains].sort((a, b) => {
            const ai = order.indexOf(a.name), bi = order.indexOf(b.name);
            return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
          });
        },
        _settingLabel(key) {
          return this._SETTING_LABELS[key] || key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
        },
        _settingDesc(key) {
          return this._SETTING_DESCS[key] || '';
        },

        // ── Color helpers for Knowledge & Memory tabs ──────────────
        _domainColor(d) {
          const m = {ai_research:'#60a5fa', professional:'#4ade80', genesis:'#a78bfa',
                     security:'#f87171', finance:'#fbbf24', general:'#94a3b8',
                     career:'#34d399', technology:'#38bdf8', science:'#c084fc'};
          return m[d] || '#6b7280';
        },
        _tierColor(t) {
          return {curated:'#fbbf24', validated:'#4ade80', raw:'#6b7280', promoted:'#60a5fa',
                  extraction_job:'#38bdf8', recon:'#f59e0b', manual:'#a78bfa',
                  ingestion:'#34d399', conversation:'#f472b6', unknown:'#6b7280'}[t] || '#6b7280';
        },
        _memoryTypeColor(t) {
          const m = {episodic_memory:'#60a5fa', semantic_memory:'#4ade80', procedural:'#f59e0b',
                     core_fact:'#a78bfa', episodic:'#60a5fa', semantic:'#4ade80'};
          return m[t] || '#6b7280';
        },

        async fetchRoutingConfig() {
          this.startFetch("routing");
          try {
            const resp = await fetchApi("/api/genesis/routing/config");
            if (resp && resp.ok) {
              this.routingConfig = await resp.json();
              this.finishFetch("routing");
            } else {
              this.failFetch("routing", "Routing config unavailable");
            }
          } catch (e) {
            console.warn("Routing config fetch failed:", e);
            this.failFetch("routing", "Routing config unavailable");
          }
        },

        async fetchApprovals() {
          this.startFetch("approvals");
          try {
            const resp = await fetchApi("/api/genesis/approvals");
            if (resp && resp.ok) {
              this.approvals = await resp.json();
              this.finishFetch("approvals");
            } else {
              this.failFetch("approvals", "Approval queue unavailable");
            }
          } catch (e) {
            console.warn("Approval fetch failed:", e);
            this.failFetch("approvals", "Approval queue unavailable");
          }
        },

        // New panel fetch methods
        async fetchCognitive() {
          this.startFetch("cognitive");
          try {
            const resp = await fetchApi("/api/genesis/cognitive");
            if (resp && resp.ok) {
              this.cognitiveState = await resp.json();
              this.finishFetch("cognitive");
            } else {
              this.failFetch("cognitive", "Cognitive state unavailable");
            }
          } catch (e) {
            console.warn("Cognitive fetch failed:", e);
            this.failFetch("cognitive", "Cognitive state unavailable");
          }
        },

        async fetchEssentialKnowledge() {
          try {
            const resp = await fetchApi("/api/genesis/essential-knowledge");
            if (resp && resp.ok) {
              this.essentialKnowledge = await resp.json();
            }
          } catch (e) {
            console.warn("Essential knowledge fetch failed:", e);
          }
        },

        async fetchAwarenessSignals() {
          this.startFetch("awarenessSignals");
          try {
            const resp = await fetchApi("/api/genesis/awareness/signals");
            if (resp && resp.ok) {
              this.awarenessSignals = await resp.json();
              this.finishFetch("awarenessSignals");
            } else {
              this.failFetch("awarenessSignals", "Awareness signals unavailable");
            }
          } catch (e) {
            console.warn("Awareness signals fetch failed:", e);
            this.failFetch("awarenessSignals", "Awareness signals unavailable");
          }
        },

        async fetchJobHealth() {
          this.startFetch("jobHealth");
          try {
            const resp = await fetchApi("/api/genesis/jobs");
            if (resp && resp.ok) {
              this.jobHealth = await resp.json();
              this.finishFetch("jobHealth");
            } else {
              this.failFetch("jobHealth", "Job health unavailable");
            }
          } catch (e) {
            console.warn("Job health fetch failed:", e);
            this.failFetch("jobHealth", "Job health unavailable");
          }
        },

        async fetchEvalMetrics() {
          try {
            const resp = await fetchApi("/api/genesis/metrics/compounding");
            if (resp && resp.ok) {
              this.evalMetrics = await resp.json();
            }
          } catch (e) {
            console.warn("Eval metrics fetch failed:", e);
          }
        },

        async fetchAutonomyConfig() {
          this.startFetch("autonomyConfig");
          try {
            const resp = await fetchApi("/api/genesis/autonomy/config");
            if (resp && resp.ok) {
              this.autonomyConfig = await resp.json();
              this.finishFetch("autonomyConfig");
            } else {
              this.failFetch("autonomyConfig", "Autonomy config unavailable");
            }
          } catch (e) {
            console.warn("Autonomy config fetch failed:", e);
            this.failFetch("autonomyConfig", "Autonomy config unavailable");
          }
        },

        async fetchAutonomousCliPolicy() {
          this.startFetch("autonomousCliPolicy");
          try {
            const resp = await fetchApi("/api/genesis/autonomous-cli-policy");
            if (resp && resp.ok) {
              this.autonomousCliPolicy = await resp.json();
              this.finishFetch("autonomousCliPolicy");
            } else {
              this.failFetch("autonomousCliPolicy", "Autonomous CLI policy unavailable");
            }
          } catch (e) {
            console.warn("Autonomous CLI policy fetch failed:", e);
            this.failFetch("autonomousCliPolicy", "Autonomous CLI policy unavailable");
          }
        },

        // Pause / kill switch
        async fetchPauseState() {
          try {
            const resp = await fetchApi("/api/genesis/pause");
            if (resp && resp.ok) {
              const data = await resp.json();
              this.pauseState.paused = data.paused;
              this.pauseState.reason = data.reason;
              this.pauseState.since = data.since;
            }
          } catch (e) { console.warn("Pause state fetch failed:", e); }
        },

        async togglePause() {
          const newState = !this.pauseState.paused;
          const action = newState ? "Pause" : "Resume";
          const pauseMsg = "Pause Genesis?\n\nThis will stop ALL background activity:\n• Reflections\n• Surplus tasks\n• Outreach\n• Inbox monitoring\n\nConversations still work but without background enrichment.\nYou must manually resume via this button or /pause off in Telegram.";
          const resumeMsg = "Resume Genesis?\n\nAll background activity will restart\n(reflections, surplus tasks, outreach, inbox monitoring).";
          if (!(await this.showConfirm(action + " Genesis", newState ? pauseMsg : resumeMsg))) return;
          this.pauseState.toggling = true;
          try {
            const resp = await fetchApi("/api/genesis/pause", {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ paused: newState, reason: "Dashboard toggle" }),
            });
            if (resp && resp.ok) {
              await this.fetchPauseState();
            }
          } catch (e) { console.warn("Pause toggle failed:", e); }
          this.pauseState.toggling = false;
        },

        // Service restarts
        async restartBridge() {
          const label = this.health.services?.bridge?.service_label || "Genesis";
          if (!(await this.showConfirm("Restart", `Restart Genesis ${label}?`))) return;
          this._restartingBridge = true;
          try {
            const resp = await fetchApi("/api/genesis/restart/bridge", { method: "POST" });
            if (resp && resp.ok) {
              setTimeout(() => { this._restartingBridge = false; this.fetchHealth(); }, 5000);
            } else {
              // Restarting ourselves kills the connection — a network error
              // or 500 with empty message is expected, not a failure.
              const err = await resp?.json().catch(() => ({}));
              if (!err.message) {
                setTimeout(() => { this._restartingBridge = false; this.fetchHealth(); }, 5000);
              } else {
                alert(`${label} restart failed: ` + err.message);
                this._restartingBridge = false;
              }
            }
          } catch (e) {
            // Network error from the server restarting itself — expected.
            setTimeout(() => { this._restartingBridge = false; this.fetchHealth(); }, 5000);
          }
        },

        async restartHostFramework() {
          const name = this.health.services?.host_framework?.name || "host framework";
          if (!(await this.showConfirm("Restart", `Restart ${name}? The dashboard will reload.`))) return;
          this._restartingHF = true;
          try {
            fetchApi("/api/genesis/restart/host-framework", { method: "POST" });
          } catch (e) { /* server will die — expected */ }
          setTimeout(() => window.location.reload(), 8000);
        },

        // Module & Provider toggles
        async toggleModule(name) {
          try {
            const resp = await fetchApi(`/api/genesis/modules/${name}/toggle`, { method: "POST" });
            if (resp?.ok) {
              await this.fetchModules();
            } else {
              const err = await resp?.json().catch(() => ({}));
              alert("Toggle failed: " + (err.message || "unknown error"));
            }
          } catch (e) { alert("Toggle failed: " + e.message); }
        },

        async toggleProvider(name) {
          try {
            const resp = await fetchApi(`/api/genesis/providers/${name}/toggle`, { method: "POST" });
            if (resp?.ok) {
              await Promise.all([this.fetchProvidersDetail(), this.fetchRoutingConfig()]);
            } else {
              const err = await resp?.json().catch(() => ({}));
              alert("Toggle failed: " + (err.message || "unknown error"));
            }
          } catch (e) { alert("Toggle failed: " + e.message); }
        },

        // Actions

        syncBudgetEditor() {
          const current = this.budgets.find(b => b.budget_type === this.budgetEditor.budget_type);
          this.budgetEditor.limit_usd = current ? Number(current.limit_usd).toFixed(2) : "";
          this.budgetEditor.warning_pct = current ? String(Number(current.warning_pct)) : "0.8";
        },

        selectBudgetType(type) {
          this.budgetEditor.budget_type = type;
          this.budgetEditor.message = null;
          this.budgetEditor.error = null;
          this.syncBudgetEditor();
        },

        async saveBudget() {
          this.budgetEditor.saving = true;
          this.budgetEditor.message = null;
          this.budgetEditor.error = null;
          try {
            const resp = await fetchApi("/api/genesis/budgets", {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({
                budget_type: this.budgetEditor.budget_type,
                limit_usd: Number(this.budgetEditor.limit_usd),
                warning_pct: Number(this.budgetEditor.warning_pct),
              }),
            });
            if (resp?.ok) {
              await this.fetchBudgets();
              this.budgetEditor.message = `Saved ${this.budgetEditor.budget_type} budget`;
            } else {
              this.budgetEditor.error = await this.readApiError(resp, "Budget save failed");
            }
          } catch (e) {
            console.error("Budget save failed:", e);
            this.budgetEditor.error = "Budget save failed";
          } finally {
            this.budgetEditor.saving = false;
          }
        },

        openRoutingEditor(siteId) {
          const config = this.routingConfig?.call_sites?.[siteId];
          if (!config) return;
          this.routingEditor.siteId = siteId;
          this.routingEditor.chainText = (config.chain || []).join(", ");
          this.routingEditor.default_paid = !!config.default_paid;
          this.routingEditor.never_pays = !!config.never_pays;
          this.routingEditor.message = null;
          this.routingEditor.error = null;
        },

        closeRoutingEditor() {
          this.routingEditor.siteId = null;
          this.routingEditor.chainText = "";
          this.routingEditor.default_paid = false;
          this.routingEditor.never_pays = false;
          this.routingEditor.message = null;
          this.routingEditor.error = null;
        },

        async saveRoutingEditor() {
          if (!this.routingEditor.siteId) return;
          this.routingEditor.saving = true;
          this.routingEditor.message = null;
          this.routingEditor.error = null;
          try {
            const chain = this.routingEditor.chainText
              .split(",")
              .map(value => value.trim())
              .filter(Boolean);
            const resp = await fetchApi(`/api/genesis/routing/config/${encodeURIComponent(this.routingEditor.siteId)}`, {
              method: "PUT",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({
                chain,
                default_paid: !!this.routingEditor.default_paid,
                never_pays: !!this.routingEditor.never_pays,
              }),
            });
            if (resp?.ok) {
              await Promise.all([this.fetchRoutingConfig(), this.fetchHealth(), this.fetchErrorSummary()]);
              this.routingEditor.message = `Saved routing for ${this.routingEditor.siteId}`;
            } else {
              this.routingEditor.error = await this.readApiError(resp, "Routing update failed");
            }
          } catch (e) {
            console.error("Routing update failed:", e);
            this.routingEditor.error = "Routing update failed";
          } finally {
            this.routingEditor.saving = false;
          }
        },

        async reloadRoutingConfig() {
          this.routingEditor.reloading = true;
          this.routingEditor.reloadMessage = null;
          this.routingEditor.reloadError = null;
          try {
            const resp = await fetchApi("/api/genesis/routing/reload", { method: "POST" });
            if (resp?.ok) {
              await Promise.all([this.fetchRoutingConfig(), this.fetchHealth(), this.fetchErrorSummary()]);
              this.routingEditor.reloadMessage = "Routing config reloaded";
            } else {
              this.routingEditor.reloadError = await this.readApiError(resp, "Routing reload failed");
            }
          } catch (e) {
            console.error("Routing reload failed:", e);
            this.routingEditor.reloadError = "Routing reload failed";
          } finally {
            this.routingEditor.reloading = false;
          }
        },

        async resolveApproval(requestId, decision) {
          const current = this.approvalActions[requestId] || {};
          this.approvalActions = {
            ...this.approvalActions,
            [requestId]: { ...current, saving: true, error: null },
          };
          try {
            const resp = await fetchApi(`/api/genesis/approvals/${encodeURIComponent(requestId)}/resolve`, {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ decision }),
            });
            if (resp?.ok) {
              this.approvals = this.approvals.filter(req => req.id !== requestId);
              this.approvalActions = {
                ...this.approvalActions,
                [requestId]: { saving: false, error: null },
              };
              this.finishFetch("approvals");
            } else {
              const error = await this.readApiError(resp, "Approval update failed");
              this.approvalActions = {
                ...this.approvalActions,
                [requestId]: { saving: false, error },
              };
            }
          } catch (e) {
            this.approvalActions = {
              ...this.approvalActions,
              [requestId]: { saving: false, error: "Approval update failed" },
            };
          }
        },

        async clearDeferredItem(itemId) {
          this.queueReview.clearingIds = { ...this.queueReview.clearingIds, [itemId]: true };
          this.queueReview.message = null;
          this.queueReview.error = null;
          try {
            const resp = await fetchApi(`/api/genesis/deferred/${encodeURIComponent(itemId)}/clear`, { method: "DELETE" });
            if (resp?.ok) {
              // Brief delay to ensure DB commit propagates before re-fetch
              await new Promise(r => setTimeout(r, 200));
              await Promise.all([this.fetchHealth(), this.fetchErrorSummary()]);
              this.queueReview.message = "Discarded item cleared";
              setTimeout(() => { this.queueReview.message = null; }, 5000);
            } else {
              this.queueReview.error = await this.readApiError(resp, "Unable to clear discarded item");
            }
          } catch (e) {
            console.error("Clear discarded item failed:", e);
            this.queueReview.error = "Unable to clear discarded item";
          } finally {
            const { [itemId]: _, ...rest } = this.queueReview.clearingIds;
            this.queueReview.clearingIds = rest;
          }
        },

        async clearAllDiscardedItems() {
          this.queueReview.clearingAll = true;
          this.queueReview.message = null;
          this.queueReview.error = null;
          try {
            const resp = await fetchApi("/api/genesis/deferred/all/clear", { method: "DELETE" });
            if (resp?.ok) {
              const data = await resp.json();
              await Promise.all([this.fetchHealth(), this.fetchErrorSummary()]);
              this.queueReview.message = `Cleared ${data?.cleared ?? 0} discarded item${data?.cleared === 1 ? "" : "s"}`;
            } else {
              this.queueReview.error = await this.readApiError(resp, "Unable to clear discarded items");
            }
          } catch (e) {
            console.error("Clear all discarded items failed:", e);
            this.queueReview.error = "Unable to clear discarded items";
          } finally {
            this.queueReview.clearingAll = false;
          }
        },

        async openConfigFile(file) {
          const sameFile = this.configModal.loadedName === file.name;
          this.configModal.open = true;
          this.configModal.name = file.name;
          this.configModal.editable = file.editable !== false;
          this.configModal.deletable = !!file.deletable;
          this.configModal.dirty = false;
          this.configModal.saveMessage = null;
          this.configModal.saveError = null;
          if (!sameFile) {
            this.configModal.content = "";
            this.configModal.loadedName = "";
            this.resetModalFetch("configModal");
          }
          this.startModalFetch("configModal");
          try {
            const resp = await fetchApi(`/api/genesis/config-files/${file.name.split('/').map(encodeURIComponent).join('/')}`);
            if (resp?.ok) {
              const data = await resp.json();
              this.configModal.content = data.content || "(empty file)";
              this.configModal.loadedName = file.name;
              this.configModal.syntax = data.syntax || "markdown";
              this.finishModalFetch("configModal");
              requestAnimationFrame(() => this._initConfigEditor());
            } else {
              this.failModalFetch("configModal", "Config file unavailable");
            }
          } catch (e) {
            this.failModalFetch("configModal", "Config file unavailable");
          }
        },

        _initConfigEditor() {
          const el = document.getElementById("config-ace-editor");
          if (!el || !window.ace) return;
          if (this._configEditor) { this._configEditor.destroy(); this._configEditor = null; }
          const editor = window.ace.edit(el);
          editor.setTheme("ace/theme/twilight");
          const mode = this.configModal.syntax === "yaml" ? "ace/mode/yaml" : "ace/mode/markdown";
          editor.session.setMode(mode);
          editor.setValue(this.configModal.content, -1);
          editor.setReadOnly(!this.configModal.editable);
          editor.setOptions({ fontSize: "13px", showPrintMargin: false, wrap: true, tabSize: 2 });
          editor.on("change", () => {
            this.configModal.dirty = true;
            this.configModal.saveMessage = null;
            this.configModal.saveError = null;
          });
          this._configEditor = editor;
        },

        async saveConfigFile() {
          if (!this._configEditor || this.configModal.saving) return;
          this.configModal.saving = true;
          this.configModal.saveMessage = null;
          this.configModal.saveError = null;
          const content = this._configEditor.getValue();
          try {
            const resp = await fetchApi(
              `/api/genesis/config-files/${this.configModal.name.split('/').map(encodeURIComponent).join('/')}`,
              { method: "PUT", headers: {"Content-Type": "application/json"}, body: JSON.stringify({content}) }
            );
            if (resp?.ok) {
              this.configModal.dirty = false;
              this.configModal.content = content;
              this.configModal.saveMessage = "Saved";
            } else {
              const data = await resp.json().catch(() => ({}));
              this.configModal.saveError = data.error || "Save failed";
            }
          } catch (e) {
            this.configModal.saveError = "Save failed";
          } finally {
            this.configModal.saving = false;
          }
        },

        async deleteConfigFile() {
          if (!this.configModal.deletable) return;
          if (!(await this.showConfirm("Delete File", `Delete ${this.configModal.name}? This cannot be undone.`))) return;
          try {
            const resp = await fetchApi(
              `/api/genesis/config-files/${this.configModal.name.split('/').map(encodeURIComponent).join('/')}`,
              { method: "DELETE" }
            );
            if (resp?.ok) {
              this.configFiles = this.configFiles.filter(f => f.name !== this.configModal.name);
              this.closeConfigModal();
            } else {
              const data = await resp.json().catch(() => ({}));
              this.configModal.saveError = data.error || "Delete failed";
            }
          } catch (e) {
            this.configModal.saveError = "Delete failed";
          }
        },

        async closeConfigModal() {
          if (this.configModal.dirty && !(await this.showConfirm("Discard Changes", "You have unsaved changes. Discard?"))) return;
          if (this._configEditor) { this._configEditor.destroy(); this._configEditor = null; }
          this.configModal.open = false;
          this.configModal.dirty = false;
        },

        // Helpers
        severityColor(severity) {
          const map = { debug: "#666", info: "#ccc", warning: "#f0ad4e", error: "#d9534f", critical: "#ff2d2d" };
          return map[severity] || "#ccc";
        },

        async readApiError(resp, fallback) {
          if (!resp) return fallback;
          try {
            const data = await resp.json();
            return data?.error || data?.message || fallback;
          } catch {
            return fallback;
          }
        },

        startFetch(name) {
          const state = this.fetchState[name];
          if (!state) return;
          state.state = state.lastSuccess ? "refreshing" : "loading";
          state.error = null;
        },

        finishFetch(name) {
          const state = this.fetchState[name];
          if (!state) return;
          state.state = "healthy";
          state.lastSuccess = Date.now();
          state.error = null;
        },

        failFetch(name, message) {
          const state = this.fetchState[name];
          if (!state) return;
          state.state = state.lastSuccess ? "stale" : "error";
          state.error = message;
        },

        panelState(name) {
          const state = this.fetchState[name];
          return state ? state.state : "unknown";
        },

        panelStateColor(name) {
          return this.fetchStateColor(this.panelState(name));
        },

        panelStateLabel(name) {
          const state = this.fetchState[name];
          if (!state) return "unknown";
          return state.state;
        },

        panelStatusDetail(name) {
          return this.fetchStatusDetail(this.fetchState[name]);
        },

        resetModalFetch(name) {
          const state = this[name]?.fetch;
          if (!state) return;
          state.state = "idle";
          state.lastSuccess = null;
          state.error = null;
        },

        startModalFetch(name) {
          const state = this[name]?.fetch;
          if (!state) return;
          state.state = state.lastSuccess ? "refreshing" : "loading";
          state.error = null;
        },

        finishModalFetch(name) {
          const state = this[name]?.fetch;
          if (!state) return;
          state.state = "healthy";
          state.lastSuccess = Date.now();
          state.error = null;
        },

        failModalFetch(name, message) {
          const state = this[name]?.fetch;
          if (!state) return;
          state.state = state.lastSuccess ? "stale" : "error";
          state.error = message;
        },

        fetchStateColor(stateName) {
          const map = {
            healthy: "#4caf50",
            loading: "#2196F3",
            refreshing: "#2196F3",
            stale: "#f0ad4e",
            error: "#d9534f",
            idle: "#666",
            unknown: "#666",
          };
          return map[stateName] || "#666";
        },

        fetchStatusDetail(state) {
          if (!state) return "";
          if (state.state === "stale") {
            const parts = [];
            if (state.error) parts.push(state.error);
            if (state.lastSuccess) parts.push(`last ok ${this.relativeTime(state.lastSuccess)}`);
            return parts.join(" — ");
          }
          if (state.state === "healthy" && state.lastSuccess) {
            return `updated ${this.relativeTime(state.lastSuccess)}`;
          }
          if (state.state === "refreshing" && state.lastSuccess) {
            return `refreshing — last ok ${this.relativeTime(state.lastSuccess)}`;
          }
          return state.error || "";
        },

        modalStateColor(modal) {
          return this.fetchStateColor(modal?.fetch?.state || "unknown");
        },

        modalStateLabel(modal) {
          return modal?.fetch?.state || "unknown";
        },

        modalStatusDetail(modal) {
          return this.fetchStatusDetail(modal?.fetch);
        },

        semanticStateColor(state) {
          const map = {
            healthy: "#4caf50",
            degraded: "#f0ad4e",
            fallback: "#f0ad4e",
            warning: "#f0ad4e",
            unknown: "#888",
            error: "#d9534f",
          };
          return map[state] || "#888";
        },

        statusReason(fetchName, semantic) {
          const fetchDetail = fetchName ? this.panelStatusDetail(fetchName) : "";
          if (fetchDetail && semantic?.reason) return `${semantic.reason} — ${fetchDetail}`;
          return semantic?.reason || fetchDetail || "";
        },

        infrastructureSemantic() {
          const infra = this.health.infrastructure;
          if (!infra) return { state: "unknown", reason: "infrastructure data unavailable" };
          const probes = Object.values(infra);
          if (!probes.length) return { state: "unknown", reason: "no infrastructure probes reported" };
          if (probes.some(probe => ["error", "down"].includes(probe?.status))) {
            return { state: "error", reason: "one or more infrastructure probes failed" };
          }
          if ((infra.ollama?.missing_models?.length || 0) > 0) {
            return { state: "degraded", reason: "configured Ollama models are missing" };
          }
          if (infra.cc_tmp?.cc_tier === "red" || infra.cc_tmp?.sys_tier === "red") {
            return { state: "error", reason: "temp directory critically full" };
          }
          if (infra.cc_tmp?.cc_tier === "orange" || infra.cc_tmp?.sys_tier === "orange") {
            return { state: "degraded", reason: "temp directory pressure detected" };
          }
          if (probes.some(probe => ["degraded", "fallback", "overdue"].includes(probe?.status))) {
            return { state: "degraded", reason: "one or more infrastructure probes are degraded" };
          }
          if (probes.some(probe => ["unknown", "unavailable"].includes(probe?.status))) {
            return { state: "unknown", reason: "some infrastructure probes have no current data" };
          }
          return { state: "healthy", reason: "infrastructure probes are healthy" };
        },

        ccSemantic() {
          const cc = this.health.cc_sessions;
          if (!cc) return { state: "unknown", reason: "CC session data unavailable" };
          const rt = cc.realtime_status;
          if (rt === "UNAVAILABLE") {
            return { state: "error", reason: "CC is unavailable — contingency mode active" };
          }
          if (rt === "RATE_LIMITED" || rt === "THROTTLED") {
            return { state: "degraded", reason: `CC is ${rt.toLowerCase().replace('_', '-')}` };
          }
          if (cc.background?.status === "error") {
            return { state: "error", reason: "background CC session health check failed" };
          }
          if ((cc.failed_24h || 0) > 0 || ["warning", "limited"].includes(cc.background?.status)) {
            return { state: "degraded", reason: "recent failed CC sessions detected" };
          }
          if (cc.background?.status === "unknown") {
            return { state: "unknown", reason: "background CC capacity is unknown" };
          }
          return { state: "healthy", reason: "CC sessions are operating normally" };
        },

        costSemantic() {
          const cost = this.health.cost;
          if (!cost) return { state: "unknown", reason: "cost data unavailable" };
          if (cost.budget_status === "ERROR") {
            return { state: "error", reason: "cost tracker returned an error" };
          }
          const cc = this.health.cc_sessions;
          if (cc && (cc.rate_limited_24h || 0) > 0) {
            return { state: "degraded", reason: cc.rate_limited_24h + " rate limit(s) in 24h" };
          }
          if (cost.monthly_usd == null) return { state: "unknown", reason: "cost tracking is unavailable" };
          if (cost.budget_monthly_limit && cost.forecast_monthly_usd > cost.budget_monthly_limit) {
            return { state: "degraded", reason: "forecast exceeds monthly budget" };
          }
          if (cost.budget_monthly_limit && cost.forecast_monthly_usd > cost.budget_monthly_limit * 0.8) {
            return { state: "degraded", reason: "forecast is approaching the monthly budget" };
          }
          return { state: "healthy", reason: "cost usage is within current limits" };
        },

        queuesSemantic() {
          const queues = this.health.queues;
          if (!queues) return { state: "unknown", reason: "queue data unavailable" };
          if ((queues.dead_letters || 0) > 0 || (queues.discarded_items?.length || 0) > 0
              || (queues.deferred_stuck || 0) > 0 || (queues.failed_embeddings || 0) > 0) {
            return { state: "error", reason: "stuck/failed items or dead letters require attention" };
          }
          if ((queues.deferred_work || 0) > 0 || (queues.deferred_processing || 0) > 0) {
            return { state: "degraded", reason: "work is backing up in deferred queues" };
          }
          const pe = queues.pending_embeddings || 0;
          if (pe > 2000) {
            return { state: "error", reason: `embedding queue critically backed up (${pe} pending)` };
          }
          if (pe > 500) {
            return { state: "degraded", reason: `embedding queue backed up (${pe} pending)` };
          }
          if (Array.isArray(queues.errors) && queues.errors.length > 0) {
            return { state: "unknown", reason: "some queue counters could not be collected" };
          }
          return { state: "healthy", reason: "queues are clear" };
        },

        surplusSemantic() {
          const surplus = this.health.surplus;
          if (!surplus || surplus.status === "unknown") return { state: "unknown", reason: "surplus scheduler data unavailable" };
          const failed = surplus.tasks_failed_24h || 0;
          const completed = surplus.tasks_completed_24h || 0;
          if (failed > 0 && completed > 0 && failed / (completed + failed) > 0.2) {
            return { state: "degraded", reason: `surplus failure rate ${Math.round(failed / (completed + failed) * 100)}% (${failed}/${completed + failed})` };
          }
          if (failed > 0 && completed === 0) {
            return { state: "degraded", reason: `${failed} surplus failures, no completions` };
          }
          return { state: "healthy", reason: `surplus scheduler is ${surplus.status}` };
        },

        egoSemantic() {
          const ego = this.egoStatus;
          if (!ego || ego.status === "not_bootstrapped") return { state: "unknown", reason: "ego data unavailable" };
          if (!ego.enabled) return { state: "unknown", reason: "ego disabled by config" };
          // Circuit breaker / cadence check
          const cadence = this.egoModal.cadence;
          if (cadence && cadence.available) {
            if (cadence.consecutive_failures >= 3) {
              return { state: "error", reason: `circuit open (${cadence.consecutive_failures} consecutive failures)` };
            }
            if (cadence.is_paused) {
              return { state: "degraded", reason: "ego paused" };
            }
          }
          // Budget exhausted
          if (ego.daily_budget_cap_usd > 0 && ego.budget_remaining_usd <= 0) {
            return { state: "error", reason: "daily budget exhausted" };
          }
          // Budget >80%
          if (ego.daily_budget_cap_usd > 0 && ego.daily_cost_usd / ego.daily_budget_cap_usd > 0.8) {
            return { state: "degraded", reason: `budget ${Math.round(ego.daily_cost_usd / ego.daily_budget_cap_usd * 100)}% used` };
          }
          // Proposals piling up
          if (ego.pending_proposals > 5) {
            return { state: "degraded", reason: `${ego.pending_proposals} proposals awaiting review` };
          }
          return { state: "healthy", reason: ego.focus_summary || "ego active" };
        },

        servicesSemantic() {
          const services = this.health.services;
          if (!services || services.status === "unknown") return { state: "unknown", reason: "service status unavailable" };
          const svcLabel = (services?.bridge?.service_label || "Genesis").toLowerCase();
          // Host framework health
          const hf = services?.host_framework;
          if (hf?.detected && (hf.status === "down" || hf.status === "error")) {
            return { state: "error", reason: `${hf.name} is ${hf.status}` };
          }
          if (services?.bridge?.active_state && services.bridge.active_state !== "active") {
            if (services.bridge.active_state === "unknown") {
              return { state: "unknown", reason: `${svcLabel} service state is unknown` };
            }
            return { state: "error", reason: `${svcLabel} service is not active` };
          }
          if (services?.watchdog_timer?.active_state && services.watchdog_timer.active_state !== "active") {
            if (services.watchdog_timer.active_state === "unknown") {
              return { state: "unknown", reason: "watchdog timer state is unknown" };
            }
            return { state: "error", reason: "watchdog timer is not active" };
          }
          if (hf?.detected && hf.status === "degraded") {
            return { state: "degraded", reason: `${hf.name} is degraded` };
          }
          if ((services?.watchdog?.consecutive_failures || 0) > 0) {
            return { state: "degraded", reason: "watchdog has recent consecutive failures" };
          }
          // Sentinel — container-side guardian. Below liveness checks above so a
          // dead bridge/timer/host_framework still wins; an escalated Sentinel
          // paints the card red, an in-flight investigation paints it degraded.
          const sentinel = services?.sentinel;
          if (sentinel?.enabled) {
            if (sentinel.is_stale) {
              return { state: "degraded", reason: `sentinel stale — last heartbeat ${Math.round((sentinel.staleness_s || 0) / 60)}m ago` };
            }
            if (sentinel.current_state === "escalated") {
              return { state: "error", reason: "sentinel escalated — CC diagnosis failed" };
            }
            if (["investigating", "remediating", "awaiting_dispatch_approval", "awaiting_action_approval"].includes(sentinel.current_state)) {
              const label = sentinel.current_state.startsWith("awaiting") ? "awaiting approval" : sentinel.current_state;
              return { state: "degraded", reason: `sentinel ${label}` };
            }
          }
          return { state: "healthy", reason: `${svcLabel} and watchdog services are active` };
        },

        containerSemantic() {
          const mem = this.health.infrastructure?.container_memory;
          const disk = this.health.infrastructure?.disk;
          const stateRank = { error: 3, degraded: 2, unknown: 1, healthy: 0 };

          // Memory assessment (primary — OOM kills)
          let memState = "healthy", memReason = "container resources within safe limits";
          if (!mem || ["unknown", "unavailable"].includes(mem.status)) {
            memState = "unknown"; memReason = "container memory data unavailable";
          } else if ((mem.anon_pct ?? mem.used_pct) > 85 || mem.status === "down") {
            memState = "error"; memReason = "memory in danger zone (" + (mem.anon_pct ?? mem.used_pct).toFixed(0) + "%)";
          } else if ((mem.anon_pct ?? mem.used_pct) > 75 || mem.status === "degraded") {
            memState = "degraded"; memReason = "memory usage elevated (" + (mem.anon_pct ?? mem.used_pct).toFixed(0) + "%)";
          }

          // Disk assessment (secondary — write failures)
          let diskState = "healthy", diskReason = "";
          if (disk && disk.free_pct != null) {
            const usedPct = 100 - disk.free_pct;
            if (usedPct > 90) {
              diskState = "error"; diskReason = "disk critically full (" + usedPct.toFixed(0) + "%)";
            } else if (usedPct > 85) {
              diskState = "degraded"; diskReason = "disk usage high (" + usedPct.toFixed(0) + "%)";
            }
          }

          // Worst-of-two — disk or memory, whichever is worse
          if ((stateRank[diskState] || 0) > (stateRank[memState] || 0)) {
            return { state: diskState, reason: diskReason };
          }
          return { state: memState, reason: memReason };
        },

        awarenessSemantic() {
          const awareness = this.health.awareness;
          if (!awareness) return { state: "unknown", reason: "awareness data unavailable" };
          if (awareness.status === "overdue") {
            return { state: "error", reason: "awareness loop is overdue (>6 min)" };
          }
          if (awareness.status === "no_ticks") {
            return { state: "error", reason: "awareness loop has never ticked — system may not be running" };
          }
          if (awareness.status === "unknown") {
            return { state: "unknown", reason: "awareness loop has no current tick data" };
          }
          if ((awareness.critical_bypasses_24h || 0) > 0) {
            return { state: "degraded", reason: "critical bypasses were recorded recently" };
          }
          return { state: "healthy", reason: "awareness loop is ticking normally" };
        },

        outreachSemantic() {
          const outreach = this.health.outreach_stats;
          if (!outreach || outreach.status === "unknown") {
            return { state: "unknown", reason: "outreach metrics unavailable" };
          }
          return { state: "healthy", reason: outreach.total > 0 ? "recent outreach activity recorded" : "no outreach sent in the last 7 days" };
        },

        conversationSemantic() {
          const conversation = this.health.conversation;
          if (!conversation || conversation.status === "unknown" || conversation.last_user_message_age_s == null) {
            return { state: "unknown", reason: "conversation activity is unavailable" };
          }
          return { state: "healthy", reason: "conversation activity is available" };
        },

        mcpSemantic() {
          const servers = this.health.mcp_servers;
          if (!servers) return { state: "unknown", reason: "MCP server data unavailable" };
          const values = Object.values(servers);
          if (!values.length) return { state: "unknown", reason: "no MCP servers reported" };
          if (values.some(info => info.status === "error")) {
            return { state: "error", reason: "one or more MCP servers are failing" };
          }
          if (values.some(info => info.status !== "up")) {
            return { state: "degraded", reason: "one or more MCP servers are only partially available" };
          }
          return { state: "healthy", reason: "MCP servers are available" };
        },

        apiKeysSemantic() {
          const keys = this.health.api_keys;
          if (!keys) return { state: "unknown", reason: "API key data unavailable" };
          const bad = Object.entries(keys).filter(([, info]) => info.status === "missing" || info.status === "failed");
          if (!bad.length) return { state: "healthy", reason: "required provider keys are available" };
          const blocking = bad.filter(([name]) => !this.providerFallbackActive(name));
          if (blocking.length > 0) {
            return { state: "error", reason: "one or more required provider keys are missing or failing" };
          }
          return { state: "degraded", reason: "provider key issues exist but fallback capacity remains" };
        },

        overallHealthSemantic() {
          // Aggregate all semantic health signals into one overall status
          const checks = [
            this.infrastructureSemantic(),
            this.servicesSemantic(),
            this.awarenessSemantic(),
            this.surplusSemantic(),
            this.queuesSemantic(),
            ...(this.egoStatus?.enabled ? [this.egoSemantic()] : []),
          ];
          const hasError = checks.some(c => c.state === "error");
          const hasDegraded = checks.some(c => c.state === "degraded" || c.state === "fallback");
          const hasUnknown = checks.some(c => c.state === "unknown");
          if (hasError) {
            const reasons = checks.filter(c => c.state === "error").map(c => c.reason);
            return { state: "error", reason: reasons.join("; ") };
          }
          if (hasDegraded) {
            const reasons = checks.filter(c => c.state === "degraded" || c.state === "fallback").map(c => c.reason);
            return { state: "degraded", reason: reasons.join("; ") };
          }
          if (hasUnknown) {
            return { state: "unknown", reason: "some subsystems have unknown status" };
          }
          return { state: "healthy", reason: "all core subsystems operational" };
        },

        routingSemantic() {
          const sites = this.health.call_sites || {};
          const routing = Object.values(sites).filter(s => s.routing !== false);
          if (!routing.length) return { state: "unknown", reason: "routing data unavailable" };
          if (routing.some(site => site.status === "down")) {
            return { state: "error", reason: "one or more call sites are down" };
          }
          if (this.fallbackCallSiteCount > 0) {
            return { state: "fallback", reason: "one or more call sites are running on fallback providers" };
          }
          if (routing.some(site => site.status === "degraded")) {
            return { state: "degraded", reason: "one or more call sites are degraded" };
          }
          if (routing.some(site => site.status === "warning")) {
            return { state: "degraded", reason: "recent routing failures detected on one or more call sites" };
          }
          return { state: "healthy", reason: "call sites are using their primary routes" };
        },

        probeStatusColor(probe) {
          // Color Rule: GREEN = primary/healthy, YELLOW = fallback/degraded, RED = error/down, GRAY = unknown
          const map = {
            healthy: "#4caf50", active: "#4caf50",     // GREEN: confirmed working
            degraded: "#f0ad4e", fallback: "#f0ad4e", warning: "#f0ad4e",  // YELLOW: working but not ideal
            idle: "#888", unknown: "#666",              // GRAY: no data or inactive
            down: "#d9534f", error: "#d9534f",         // RED: broken
            up: "#4caf50",                              // GREEN: MCP server up
            unavailable: "#666",                        // GRAY: not applicable
            local: "#2196F3", configured: "#4caf50",   // API key states
            missing: "#d9534f",                         // API key missing
          };
          if (typeof probe === "string") return map[probe] || "#666";
          if (probe?.status) return map[probe.status] || "#666";
          // Disk: derive status from free_pct
          if (probe?.free_pct != null) {
            if (probe.free_pct >= 20) return "#4caf50";
            if (probe.free_pct > 10) return "#f0ad4e";
            return "#d9534f";
          }
          // CC tmp: derive from cc_tier/sys_tier
          if (probe?.cc_tier != null || probe?.sys_tier != null) {
            const worst = [probe.cc_tier, probe.sys_tier].includes("red") ? "red"
              : [probe.cc_tier, probe.sys_tier].includes("orange") ? "orange" : "green";
            if (worst === "red") return "#d9534f";
            if (worst === "orange") return "#f0ad4e";
            return "#4caf50";
          }
          return "#666";
        },

        get groupedConfigFiles() {
          const groups = {};
          for (const f of this.configFiles) {
            if (!groups[f.category]) groups[f.category] = [];
            groups[f.category].push(f);
          }
          return groups;
        },

        sessionStatusColor(status) {
          const map = { active: "#2196F3", completed: "#4caf50", failed: "#d9534f", expired: "#999" };
          return map[status] || "#666";
        },

        sessionTypeLabel(type) {
          const map = { foreground: "FG", background_reflection: "Refl", background_task: "Task" };
          return map[type] || type;
        },

        formatDuration(ms) {
          if (!ms) return "-";
          const s = Math.round(ms / 1000);
          if (s < 60) return `${s}s`;
          return `${Math.floor(s / 60)}m ${s % 60}s`;
        },

        formatAgeSeconds(seconds) {
          if (seconds == null) 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`;
        },

        formatTime(isoStr) {
          if (!isoStr) return "-";
          try { return new Date(isoStr).toLocaleTimeString("en-US", { hour12: false }); } catch { return isoStr; }
        },

        formatDateTime(isoStr) {
          if (!isoStr) return "-";
          try {
            const d = new Date(isoStr);
            return d.toLocaleDateString("en-US", { month: "short", day: "numeric" })
              + " " + d.toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit" });
          } catch { return isoStr; }
        },

        relativeTime(value) {
          if (!value) return "-";
          const ts = typeof value === "number" ? value : Date.parse(value);
          if (!ts) return "-";
          const diff = Math.max(0, Date.now() - ts);
          const s = Math.round(diff / 1000);
          if (s < 10) return "just now";
          if (s < 60) return `${s}s ago`;
          const m = Math.round(s / 60);
          if (m < 60) return `${m}m ago`;
          const h = Math.round(m / 60);
          if (h < 48) return `${h}h ago`;
          return `${Math.round(h / 24)}d ago`;
        },

        approvalActionState(requestId) {
          return this.approvalActions[requestId] || { saving: false, error: null };
        },

        approvalActionLabel(req) {
          return req?.context_data?.action_label || req?.description || req?.action_type || "Approval request";
        },

        approvalFallbackLabel(req) {
          const context = req?.context_data || {};
          const model = context.model || "claude -p";
          const effort = context.effort ? ` (${context.effort})` : "";
          return `${model}${effort}`;
        },

        approvalReasonLabel(req) {
          const context = req?.context_data || {};
          if (context.api_error) return context.api_error;
          if (context.api_call_site_id) return `API route ${context.api_call_site_id} exhausted`;
          return "CLI fallback requires manual approval";
        },

        groupQueueItems(items) {
          const groups = new Map();
          for (const item of (items || [])) {
            const key = [item.site || "unknown", item.reason || "unknown", item.type || "unknown"].join("::");
            if (!groups.has(key)) {
              groups.set(key, {
                key,
                site: item.site || "unknown",
                reason: item.reason || "unknown",
                type: item.type || "unknown",
                count: 0,
                maxAgeSeconds: 0,
                items: [],
              });
            }
            const group = groups.get(key);
            group.count += 1;
            group.maxAgeSeconds = Math.max(group.maxAgeSeconds, item.age_s || 0);
            group.items.push(item);
          }
          return Array.from(groups.values()).sort((a, b) => {
            if (b.count !== a.count) return b.count - a.count;
            if (b.maxAgeSeconds !== a.maxAgeSeconds) return b.maxAgeSeconds - a.maxAgeSeconds;
            return a.site.localeCompare(b.site);
          });
        },

        get deferredQueueGroups() {
          return this.groupQueueItems(this.health.queues?.deferred_items || []);
        },

        get discardedQueueGroups() {
          return this.groupQueueItems(this.health.queues?.discarded_items || []);
        },

        get routingProviderList() {
          return Object.keys(this.routingConfig?.providers || {});
        },

        providerCbState(providerName) {
          const sites = this.health.call_sites || {};
          for (const [, site] of Object.entries(sites)) {
            for (const p of (site.chain_health || [])) {
              if (p.provider === providerName) return p.state;
            }
          }
          return null;
        },

        providerCallSites(providerName) {
          const sites = this.health.call_sites || {};
          const result = [];
          for (const [siteId, site] of Object.entries(sites)) {
            if ((site.chain_health || []).some(p => p.provider === providerName)) {
              result.push(siteId);
            }
          }
          return result;
        },

        providerFallbackActive(providerName) {
          const sites = this.health.call_sites || {};
          const usingSites = [];
          for (const [siteId, site] of Object.entries(sites)) {
            if ((site.chain_health || []).some(p => p.provider === providerName)) {
              usingSites.push(site);
            }
          }
          if (usingSites.length === 0) return false;
          return usingSites.every(site =>
            (site.chain_health || []).some(p => p.provider !== providerName && p.state === 'closed')
          );
        },

        get subsystems() {
          return ["", "routing", "awareness", "surplus", "memory", "health",
                  "perception", "learning", "inbox", "reflection", "providers", "web", "outreach", "dashboard"];
        },

        get fallbackCallSites() {
          const sites = this.health.call_sites || {};
          return Object.entries(sites).filter(([, site]) => {
            const chain = site.chain_health || [];
            return site.active_provider && chain.length > 0 && site.active_provider !== chain[0].provider;
          }).map(([id]) => id);
        },
        get fallbackCallSiteCount() {
          return this.fallbackCallSites.length;
        },

        get pendingApprovalCount() {
          return this.approvals.length;
        },

        get badApiKeyCount() {
          const keys = this.health.api_keys || {};
          const sites = this.health.call_sites || {};
          // "failed" keys always count. "missing" keys only count if they
          // are causing a specific call site to be degraded/down/on-fallback.
          const missingProviders = new Set(
            Object.entries(keys)
              .filter(([, info]) => info.status === "missing")
              .map(([name]) => name)
          );
          const missingCausingPain = new Set();
          if (missingProviders.size > 0) {
            for (const site of Object.values(sites)) {
              const chain = site.chain_health || [];
              const onFallback = site.active_provider && chain.length > 0 && site.active_provider !== chain[0].provider;
              const degraded = site.status === "degraded" || site.status === "down";
              if (onFallback || degraded) {
                for (const link of chain) {
                  if (missingProviders.has(link.provider)) {
                    missingCausingPain.add(link.provider);
                  }
                }
              }
            }
          }
          const failedCount = Object.values(keys).filter(info => info.status === "failed").length;
          return failedCount + missingCausingPain.size;
        },

        get attentionItems() {
          const items = [];
          const activeAlerts = (this.errorSummary.active_alerts || []).length;
          const activeGroups = (this.errorSummary.groups || []).filter(g => g.still_active).length;
          if (activeAlerts > 0) {
            items.push({ level: "critical", title: `${activeAlerts} active alert${activeAlerts === 1 ? "" : "s"}`, detail: "health alerts need operator review", href: "/genesis/errors" });
          }
          if (activeGroups > 0) {
            items.push({ level: "warning", title: `${activeGroups} active error group${activeGroups === 1 ? "" : "s"}`, detail: "grouped warnings/errors across events, dead letters, or deferred work", href: "/genesis/errors" });
          }
          if ((this.health.queues?.dead_letters || 0) > 0) {
            items.push({ level: "critical", title: `${this.health.queues.dead_letters} dead letters`, detail: "requests exhausted all fallback providers; open the errors view to inspect", href: "/genesis/errors" });
          }
          if ((this.health.queues?.discarded_items?.length || 0) > 0) {
            items.push({ level: "warning", title: `${this.health.queues.discarded_items.length} discarded item${this.health.queues.discarded_items.length === 1 ? "" : "s"}`, detail: "work was dropped and can be reviewed or cleared below", href: "#queue-review", tab: "overview", anchor: "queue-review" });
          }
          if (this.fallbackCallSiteCount > 0) {
            const names = this.fallbackCallSites.join(", ");
            items.push({ level: "warning", title: `${this.fallbackCallSiteCount} call site${this.fallbackCallSiteCount === 1 ? "" : "s"} on fallback`, detail: names, href: "#routing-health", tab: "internals", anchor: "routing-health" });
          }
          if (this.pendingApprovalCount > 0) {
            items.push({ level: "warning", title: `${this.pendingApprovalCount} pending approval${this.pendingApprovalCount === 1 ? "" : "s"}`, detail: "autonomous CLI fallbacks are waiting for operator action", href: "#chat", tab: "chat", onClick: () => { this.commsTab = 'approvals'; this.fetchApprovals(); } });
          }
          if (this.badApiKeyCount > 0) {
            items.push({ level: "critical", title: `${this.badApiKeyCount} provider key issue${this.badApiKeyCount === 1 ? "" : "s"}`, detail: "missing or failed provider credentials detected", href: null });
          }
          if (this.costSemantic().state === "degraded") {
            items.push({ level: "warning", title: "Budget pressure rising", detail: this.costSemantic().reason, href: "#budget-controls", tab: "config", anchor: "budget-controls" });
          }
          // Update availability
          if (this.updateStatus?.update_available) {
            const u = this.updateStatus.update_available;
            const label = u.target_tag || (u.commits_behind + " commit" + (u.commits_behind === 1 ? "" : "s") + " behind");
            items.push({ level: "info", title: `Update available (${label})`, detail: "go to Backup & Updates to apply", href: "#update-section", tab: "backup", anchor: "update-section" });
          }
          if (this.updateStatus?.last_update?.status === "rolled_back" || this.updateStatus?.last_update?.status === "failed") {
            items.push({ level: "warning", title: "Last update failed", detail: this.updateStatus.last_update.failure_reason || "check Backup & Updates tab", href: "#update-section", tab: "backup", anchor: "update-section" });
          }
          for (const [name, state] of Object.entries(this.fetchState)) {
            if (state.state === "stale" || state.state === "error") {
              items.push({
                level: state.state === "error" ? "critical" : "warning",
                title: `${name} panel ${state.state}`,
                detail: state.error || (state.lastSuccess ? `last ok ${this.relativeTime(state.lastSuccess)}` : "no successful fetch yet"),
                href: null,
              });
            }
          }
          return items.slice(0, 8);
        },

        attentionLevelColor(level) {
          const map = { critical: "#d9534f", warning: "#f0ad4e", info: "#2196F3" };
          return map[level] || "#666";
        },

        async fetchSurplusDetail() {
          this.startModalFetch("surplusModal");
          try {
            const resp = await fetchApi("/api/genesis/surplus/detail");
            if (resp?.ok) {
              this.surplusModal.data = await resp.json();
              this.finishModalFetch("surplusModal");
            } else {
              this.failModalFetch("surplusModal", "Surplus detail unavailable");
            }
          } catch {
            this.failModalFetch("surplusModal", "Surplus detail unavailable");
          }
        },

        async fetchEgoStatus() {
          try {
            const resp = await fetchApi("/api/genesis/ego/status");
            if (resp?.ok) { this.egoStatus = await resp.json(); }
          } catch { /* silent — card shows unknown */ }
        },

        async fetchEgoDetail() {
          this.startModalFetch("egoModal");
          try {
            const [statusR, cadenceR, cyclesR, proposalsR, followUpsR] = await Promise.all([
              fetchApi("/api/genesis/ego/status"),
              fetchApi("/api/genesis/ego/cadence"),
              fetchApi("/api/genesis/ego/cycles"),
              fetchApi("/api/genesis/ego/proposals/all"),
              fetchApi("/api/genesis/ego/follow-ups"),
            ]);
            if (statusR?.ok) this.egoStatus = await statusR.json();
            if (cadenceR?.ok) this.egoModal.cadence = await cadenceR.json();
            if (cyclesR?.ok) this.egoModal.cycles = await cyclesR.json();
            if (proposalsR?.ok) this.egoModal.proposals = await proposalsR.json();
            if (followUpsR?.ok) this.egoModal.followUps = await followUpsR.json();
            this.finishModalFetch("egoModal");
          } catch {
            this.failModalFetch("egoModal", "Ego detail unavailable");
          }
        },

        async resolveEgoProposal(id, status, response) {
          try {
            const resp = await fetchApi("/api/genesis/ego/proposals/" + id + "/resolve", {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ status, response: response || "" }),
            });
            if (resp?.ok) {
              this.egoModal.rejectingId = null;
              this.egoModal.rejectReason = "";
              await this.fetchEgoDetail();
            }
          } catch (e) { console.warn("Proposal resolve failed:", e); }
        },

        async fetchOutreachMessages() {
          this.startModalFetch("outreachModal");
          try {
            const [msgResp, approvalResp] = await Promise.all([
              fetchApi("/api/genesis/outreach/messages?limit=20"),
              fetchApi("/api/genesis/approvals").catch(() => null),
            ]);
            if (msgResp?.ok) {
              this.outreachModal.messages = await msgResp.json();
              this.outreachModal.pendingApprovals = approvalResp?.ok ? await approvalResp.json() : [];
              this.finishModalFetch("outreachModal");
            } else {
              this.failModalFetch("outreachModal", "Outreach history unavailable");
            }
          } catch {
            this.failModalFetch("outreachModal", "Outreach history unavailable");
          }
        },

        // Find a pending approval that matches a blocker outreach message
        findMatchingApproval(msg) {
          if (msg.category !== 'blocker') return null;
          const approvals = this.outreachModal.pendingApprovals || [];
          // Match by signal_type → action_type mapping
          for (const a of approvals) {
            // CLI fallback approvals: signal_type contains 'cli_approval' or 'approval'
            if (msg.signal_type === 'cli_approval' && a.action_type === 'autonomous_cli_fallback') return a;
            // Generic: match topic substring
            if (a.description && msg.topic && a.description.includes(msg.topic.slice(0, 30))) return a;
          }
          return null;
        },

        async resolveApproval(approvalId, decision, outreachMsgId) {
          try {
            await fetchApi("/api/genesis/approvals/" + approvalId + "/resolve", {
              method: "POST", headers: {"Content-Type": "application/json"},
              body: JSON.stringify({decision})
            });
            if (outreachMsgId) {
              const outcome = decision === 'approved' ? 'useful' : 'not_useful';
              await fetchApi("/api/genesis/outreach/" + outreachMsgId + "/engage", {
                method: "POST", headers: {"Content-Type": "application/json"},
                body: JSON.stringify({outcome, response: decision === 'approved' ? 'approve' : 'deny'})
              });
            }
            // Refresh all approval-related stores for immediate UI update
            await Promise.all([
              this.fetchOutreachMessages(),
              this.fetchApprovals(),
              this.fetchComms(),
            ]);
          } catch (e) { console.error("resolve failed", e); }
        },

        async approveAllPending() {
          try {
            const resp = await fetchApi("/api/genesis/approvals/approve-all", {
              method: "POST", headers: {"Content-Type": "application/json"},
            });
            if (resp?.ok) {
              // Optimistic clear for instant visual feedback
              this.approvals = [];
              this.commsPendingApprovals = [];
              this.outreachModal.pendingApprovals = [];
              // Confirm from server
              await Promise.all([
                this.fetchOutreachMessages(),
                this.fetchApprovals(),
                this.fetchComms(),
              ]);
            }
          } catch (e) { console.error("approve-all failed", e); }
        },

        async engageOutreach(id, outcome, response) {
          try {
            const body = {outcome};
            if (response) body.response = response;
            await fetchApi("/api/genesis/outreach/" + id + "/engage", {
              method: "POST", headers: {"Content-Type": "application/json"},
              body: JSON.stringify(body)
            });
            await this.fetchOutreachMessages();
          } catch (e) { console.error("engage failed", e); }
        },

        async fetchMcpTools() {
          this.startModalFetch("mcpModal");
          try {
            const resp = await fetchApi("/api/genesis/mcp/tools");
            if (resp?.ok) {
              this.mcpModal.data = await resp.json();
              this.finishModalFetch("mcpModal");
            } else {
              this.failModalFetch("mcpModal", "MCP tool inventory unavailable");
            }
          } catch {
            this.failModalFetch("mcpModal", "MCP tool inventory unavailable");
          }
        },
      });
    });
  </script>

  <style>
    :root { --color-text-secondary: var(--color-text-muted, #d4d4d4e4); }

    /* Override AZ's body overflow:hidden + position:fixed so dashboard can scroll.
       overscroll-behavior:auto counters index.css body{overscroll-behavior:none}
       which blocks wheel-event scroll chaining from body→html viewport. */
    html, body { overflow: auto !important; position: static !important; height: auto !important; }
    body { overscroll-behavior: auto !important; }

    /* Error banner */
    .error-banner {
      background: rgba(217,83,79,0.1);
      border: 1px solid rgba(217,83,79,0.3);
      border-radius: 6px;
      padding: 0.5rem 0.75rem;
      margin-bottom: 0.75rem;
      font-size: 0.8rem;
      color: #d9534f;
      display: flex;
      align-items: center;
      gap: 0.4rem;
    }
    .error-banner .material-symbols-outlined { font-size: 1rem; }

    .attention-strip {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
      gap: 0.75rem;
      margin-bottom: 1rem;
    }

    .attention-card {
      background: rgba(255,255,255,0.03);
      border: 1px solid var(--color-border);
      border-radius: 8px;
      padding: 0.75rem 0.9rem;
      min-height: 5rem;
    }

    .attention-card-title {
      font-size: 0.84rem;
      font-weight: 600;
      margin-bottom: 0.25rem;
      display: flex;
      align-items: center;
      gap: 0.45rem;
    }

    .attention-card-detail {
      font-size: 0.74rem;
      color: var(--color-text-secondary);
      line-height: 1.35;
    }

    .panel-status {
      margin-left: auto;
      display: flex;
      align-items: center;
      gap: 0.4rem;
      font-size: 0.72rem;
      font-weight: 500;
      opacity: 0.9;
    }

    .panel-status-detail {
      font-size: 0.68rem;
      color: var(--color-text-secondary);
      margin-bottom: 0.6rem;
    }

    .status-chip {
      display: inline-flex;
      align-items: center;
      gap: 0.35rem;
      padding: 0.14rem 0.42rem;
      border-radius: 999px;
      font-size: 0.64rem;
      font-weight: 600;
      letter-spacing: 0.03em;
      text-transform: uppercase;
      border: 1px solid currentColor;
      margin-left: auto;
      white-space: nowrap;
    }

    .health-card-header {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      margin-bottom: 0.35rem;
    }

    .health-card-reason {
      font-size: 0.68rem;
      color: var(--color-text-secondary);
      line-height: 1.35;
      margin-top: 0.35rem;
    }

    .inline-warning {
      background: rgba(240,173,78,0.08);
      border: 1px solid rgba(240,173,78,0.25);
      border-radius: 6px;
      color: #f0ad4e;
      padding: 0.5rem 0.7rem;
      font-size: 0.78rem;
      margin-bottom: 0.75rem;
    }

    /* Config file modal */
    .config-modal-overlay {
      position: fixed; inset: 0; background: rgba(0,0,0,0.6);
      z-index: 1000; display: flex; align-items: center; justify-content: center;
    }
    .config-modal {
      background: var(--color-panel); border: 1px solid var(--color-border);
      border-radius: 8px; width: 90%; max-width: 700px; max-height: 80vh;
      display: flex; flex-direction: column;
    }
    .config-modal-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.75rem 1rem; border-bottom: 1px solid var(--color-border);
      font-weight: 600; font-size: 0.9rem;
    }
    .config-modal-header button {
      background: none; border: none; color: var(--color-text-secondary);
      cursor: pointer; font-size: 1.2rem; padding: 0.2rem;
    }
    .config-modal-header button:hover { color: var(--color-text); }
    .config-modal-body {
      padding: 1rem; overflow-y: auto; flex: 1;
    }
    .config-modal-body pre {
      font-family: monospace; font-size: 0.8rem; white-space: pre-wrap;
      word-break: break-word; line-height: 1.5;
    }

    /* Dashboard layout */
    .genesis-dashboard {
      max-width: 1400px;
      width: 100%;
      margin: 0 auto;
      padding: 1.5rem;
      color: var(--color-text);
      font-family: var(--font-family);
    }

    .genesis-dashboard h1 {
      font-size: 1.3rem;
      font-weight: 600;
      margin-bottom: 1.5rem;
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }

    .genesis-dashboard h1 .material-symbols-outlined {
      font-size: 1.5rem;
      color: #27875e;
    }

    .back-link {
      color: var(--color-text-secondary);
      text-decoration: none;
      font-size: 0.85rem;
      margin-left: auto;
      display: flex;
      align-items: center;
      gap: 0.3rem;
    }

    .back-link:hover { color: var(--color-text); }

    /* Panels */
    .panel {
      background: var(--color-panel);
      border: 1px solid var(--color-border);
      border-radius: 8px;
      margin-bottom: 1rem;
      overflow: hidden;
    }

    .panel-header {
      padding: 0.75rem 1rem;
      font-weight: 600;
      font-size: 0.9rem;
      border-bottom: 1px solid var(--color-border);
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }

    .panel-header .material-symbols-outlined { font-size: 1.1rem; opacity: 0.7; }

    .panel-body { padding: 1rem; }

    /* Health bar */
    .health-grid {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 0.75rem;
    }
    @media (max-width: 1000px) { .health-grid { grid-template-columns: repeat(3, 1fr); } }
    @media (max-width: 700px) { .health-grid { grid-template-columns: repeat(2, 1fr); } }

    .health-card {
      background: var(--color-background);
      border: 1px solid var(--color-border);
      border-radius: 6px;
      padding: 0.75rem;
    }

    .health-card-title {
      font-size: 0.75rem;
      color: var(--color-text-secondary);
      margin-bottom: 0.4rem;
      text-transform: uppercase;
      letter-spacing: 0.05em;
    }

    .health-card-value {
      font-size: 1.1rem;
      font-weight: 600;
    }

    .health-card-detail {
      font-size: 0.78rem;
      color: var(--color-text-secondary);
      margin-top: 0.2rem;
    }

    .status-dot {
      display: inline-block;
      width: 8px;
      height: 8px;
      border-radius: 50%;
      margin-right: 0.4rem;
      vertical-align: middle;
    }

    /* Cost progress bar */
    .cost-bar {
      height: 4px;
      background: var(--color-border);
      border-radius: 2px;
      margin-top: 0.4rem;
      overflow: hidden;
    }

    .cost-bar-fill {
      height: 100%;
      border-radius: 2px;
      transition: width 0.3s;
    }

    /* Provider activity cards */
    .provider-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
      gap: 0.75rem;
      margin-top: 0.75rem;
    }

    .provider-card {
      background: var(--color-background);
      border: 1px solid var(--color-border);
      border-radius: 6px;
      padding: 0.75rem;
    }

    .provider-name {
      font-weight: 600;
      font-size: 0.85rem;
      margin-bottom: 0.5rem;
    }

    .provider-stat {
      display: flex;
      justify-content: space-between;
      font-size: 0.78rem;
      padding: 0.15rem 0;
    }

    .provider-stat-label { color: var(--color-text-secondary); }

    /* Pending actions */
    .action-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0.85rem 0.5rem;
      border-bottom: 1px solid var(--color-border);
      min-height: 3rem;
    }

    .action-item:last-child { border-bottom: none; }

    .action-info { flex: 1; min-width: 0; }

    .action-category {
      font-size: 0.72rem;
      text-transform: uppercase;
      color: var(--color-text-secondary);
      letter-spacing: 0.05em;
    }

    .action-topic { font-size: 0.9rem; margin-top: 0.2rem; }

    .action-buttons { display: flex; gap: 0.5rem; }

    .btn-approve, .btn-reject {
      border: none;
      border-radius: 4px;
      padding: 0.3rem 0.6rem;
      cursor: pointer;
      font-size: 0.78rem;
      transition: opacity 0.15s;
    }

    .btn-approve { background: #4caf50; color: white; }
    .btn-reject { background: #666; color: white; }
    .btn-approve:hover, .btn-reject:hover { opacity: 0.85; }

    .empty-state {
      color: var(--color-text-secondary);
      font-size: 0.85rem;
      padding: 1rem 0;
      text-align: center;
    }

    /* Nav bar */
    .genesis-nav {
      display: flex;
      gap: 1.5rem;
      margin-bottom: 1rem;
      padding-bottom: 0.5rem;
      border-bottom: 1px solid var(--color-border);
    }
    .genesis-nav a {
      color: var(--color-text-secondary);
      text-decoration: none;
      font-size: 0.85rem;
      padding: 0.3rem 0;
    }
    .genesis-nav a:hover { color: var(--color-text); }
    .genesis-nav a.active {
      color: #27875e;
      border-bottom: 2px solid #27875e;
    }
    .genesis-tabs {
      display: flex;
      gap: 0;
      margin-bottom: 1.25rem;
      border-bottom: 1px solid var(--color-border);
    }
    .genesis-tabs button {
      color: var(--color-text-secondary);
      background: none;
      border: none;
      font-size: 0.82rem;
      padding: 0.5rem 1rem;
      border-bottom: 2px solid transparent;
      cursor: pointer;
      transition: color 0.15s, border-color 0.15s;
      font-family: inherit;
    }
    .genesis-tabs button:hover { color: var(--color-text); }
    .genesis-tabs button.active-tab {
      color: #27875e;
      border-bottom-color: #27875e;
    }

    /* Activity feed */
    .activity-filters {
      display: flex;
      gap: 0.75rem;
      margin-bottom: 0.75rem;
    }

    .activity-filters select {
      background: var(--color-background);
      color: var(--color-text);
      border: 1px solid var(--color-border);
      border-radius: 4px;
      padding: 0.3rem 0.5rem;
      font-size: 0.78rem;
    }

    .activity-feed {
      max-height: 400px;
      overflow-y: auto;
    }

    .activity-row {
      display: flex;
      align-items: baseline;
      gap: 0.5rem;
      padding: 0.3rem 0;
      font-size: 0.78rem;
      border-bottom: 1px solid rgba(255, 255, 255, 0.04);
    }

    .activity-time {
      color: var(--color-text-secondary);
      white-space: nowrap;
      font-family: monospace;
      font-size: 0.72rem;
    }

    .activity-subsystem {
      font-size: 0.65rem;
      padding: 0.1rem 0.4rem;
      border-radius: 3px;
      background: rgba(255, 255, 255, 0.08);
      white-space: nowrap;
    }

    .activity-type {
      color: var(--color-text-secondary);
      white-space: nowrap;
    }

    .activity-msg { flex: 1; word-break: break-word; }

    /* Config files */
    .config-toggle {
      cursor: pointer;
      user-select: none;
    }

    .config-toggle .material-symbols-outlined {
      transition: transform 0.2s;
    }

    .config-category {
      margin-bottom: 0.75rem;
    }

    .config-category-title {
      font-size: 0.75rem;
      text-transform: uppercase;
      color: #66bb6a;
      letter-spacing: 0.05em;
      margin-bottom: 0.3rem;
      font-weight: 600;
    }

    .config-file {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0.25rem 0;
    }

    .config-file-name {
      font-size: 0.82rem;
      font-family: monospace;
    }

    .config-edit-btn {
      font-size: 0.72rem;
      color: #27875e;
      cursor: pointer;
      background: none;
      border: none;
      padding: 0.15rem 0.4rem;
    }

    .config-edit-btn:hover { text-decoration: underline; }

    /* Loading state */
    .loading-overlay {
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 3rem;
      color: var(--color-text-secondary);
    }

    /* Scrollbar */
    .activity-feed::-webkit-scrollbar { width: 6px; }
    .activity-feed::-webkit-scrollbar-track { background: transparent; }
    .activity-feed::-webkit-scrollbar-thumb {
      background-color: rgba(155, 155, 155, 0.4);
      border-radius: 3px;
    }
  </style>
</head>

<body class="dark-mode" x-data x-init="$store.genesisDashboard.onOpen()"
      @beforeunload.window="$store.genesisDashboard.cleanup()">

  <div class="genesis-dashboard" x-show="!$store.genesisDashboard.loading"
       :style="$store.genesisDashboard.activeTab === 'files' ? 'max-width:100%' : ''">

    <!-- Nav -->
    <nav class="genesis-nav">
      <a href="/genesis" class="active">Dashboard</a>
      <a href="/genesis/logs">Event Log</a>
      <a href="/genesis/errors">Error Log</a>
      <a href="/genesis/monitor">Neural Monitor</a>
    </nav>

    <!-- Error banner -->
    <div class="error-banner" x-show="$store.genesisDashboard.error" x-transition>
      <span class="material-symbols-outlined">warning</span>
      <span x-text="$store.genesisDashboard.error"></span>
    </div>

    <template x-if="$store.genesisDashboard.attentionItems.length > 0">
      <div class="attention-strip">
        <template x-for="(item, idx) in $store.genesisDashboard.attentionItems" :key="idx">
          <a class="attention-card"
             :href="item.tab ? '#' : (item.href || '#')"
             :style="`text-decoration:none; color:inherit; border-color:${$store.genesisDashboard.attentionLevelColor(item.level)}55; background:${item.level === 'critical' ? 'rgba(217,83,79,0.09)' : item.level === 'warning' ? 'rgba(240,173,78,0.08)' : 'rgba(33,150,243,0.08)'}`"
             @click="if (item.tab) { $event.preventDefault(); $store.genesisDashboard.navigateTo(item.tab, item.anchor); } else if (!item.href) { $event.preventDefault(); }">
            <div class="attention-card-title" :style="`color:${$store.genesisDashboard.attentionLevelColor(item.level)}`">
              <span class="status-dot" :style="`background:${$store.genesisDashboard.attentionLevelColor(item.level)}`"></span>
              <span x-text="item.title"></span>
            </div>
            <div class="attention-card-detail" x-text="item.detail"></div>
          </a>
        </template>
      </div>
    </template>

    <!-- Header -->
    <h1>
      <span class="material-symbols-outlined">neurology</span>
      Genesis Dashboard
      <span style="margin-left: auto; display: flex; gap: 0.5rem; align-items: center;">
        <button @click="$store.genesisDashboard.restartBridge()"
                :disabled="$store.genesisDashboard._restartingBridge"
                style="font-size: 0.7rem; padding: 3px 8px; background: #1a237e; color: #90caf9; border: 1px solid #283593; border-radius: 4px; cursor: pointer;"
                x-text="$store.genesisDashboard._restartingBridge ? 'Restarting...' : ('Restart ' + ($store.genesisDashboard.health.services?.bridge?.service_label || 'Genesis'))"></button>
        <template x-if="$store.genesisDashboard.health.services?.host_framework?.detected">
          <button @click="$store.genesisDashboard.restartHostFramework()"
                  :disabled="$store.genesisDashboard._restartingHF"
                  style="font-size: 0.7rem; padding: 3px 8px; background: #4a1400; color: #ef9a9a; border: 1px solid #5d1a00; border-radius: 4px; cursor: pointer;"
                  x-text="$store.genesisDashboard._restartingHF ? 'Restarting...' : 'Restart ' + ($store.genesisDashboard.health.services.host_framework.name || 'Host')"></button>
        </template>
        <a href="#" @click.prevent="$store.genesisDashboard.navigateTo('chat')" class="back-link">
          <span class="material-symbols-outlined" style="font-size:1rem">terminal</span>
          Terminal
        </a>
        <template x-if="$store.genesisDashboard.authEnabled">
          <button @click="$store.genesisDashboard.logout()"
                  title="Logout"
                  style="font-size: 0.7rem; padding: 3px 8px; background: transparent; color: var(--color-text-secondary); border: 1px solid var(--color-border); border-radius: 4px; cursor: pointer;">
            <span class="material-symbols-outlined" style="font-size:0.9rem; vertical-align:middle;">logout</span>
          </button>
        </template>
      </span>
    </h1>

    <!-- Tab navigation -->
    <nav class="genesis-tabs">
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'overview' }"
              @click="location.hash = 'overview'">Overview</button>
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'chat' }"
              @click="location.hash = 'chat'">Chat</button>
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'work' }"
              @click="location.hash = 'work'">Work</button>
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'observations' }"
              @click="location.hash = 'observations'">Observations
        <span x-show="$store.genesisDashboard.observationsCounts.total_unsurfaced > 0"
              style="background:#ffa726; color:#000; border-radius:8px; padding:0 5px; font-size:0.6rem; margin-left:4px; font-weight:700;"
              x-text="$store.genesisDashboard.observationsCounts.total_unsurfaced"></span>
      </button>
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'memory' }"
              @click="location.hash = 'memory'">Memory</button>
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'knowledge' }"
              @click="location.hash = 'knowledge'">Knowledge</button>
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'files' }"
              @click="location.hash = 'files'">Files</button>
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'config' }"
              @click="location.hash = 'config'">Configuration</button>
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'internals' }"
              @click="location.hash = 'internals'">Internals</button>
      <button :class="{ 'active-tab': $store.genesisDashboard.activeTab === 'backup' }"
              @click="location.hash = 'backup'">Backup & Updates</button>
    </nav>

    <!-- Panel 1: System Health [Tab: overview] -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'overview'">
      <div class="panel-header">
        <span class="material-symbols-outlined">monitor_heart</span>
        System Health
        <span class="panel-status">
          <span class="status-dot"
                :style="`background:${$store.genesisDashboard.healthStale
                  ? '#d9534f'
                  : $store.genesisDashboard.semanticStateColor($store.genesisDashboard.overallHealthSemantic().state)}`"></span>
          <span x-text="$store.genesisDashboard.healthStale
            ? 'stale'
            : $store.genesisDashboard.overallHealthSemantic().state"></span>
        </span>
      </div>
      <!-- Stale data warning -->
      <template x-if="$store.genesisDashboard.healthStale">
        <div style="background: #d9534f; color: white; padding: 0.5rem 1rem; font-size: 0.85rem; font-weight: 600; text-align: center;">
          Health data stale — API unreachable. Data shown may be outdated.
        </div>
      </template>
      <!-- Genesis paused banner -->
      <template x-if="$store.genesisDashboard.pauseState.paused">
        <div style="background: #f0ad4e; color: white; padding: 0.5rem 1rem; font-size: 0.85rem; font-weight: 600; text-align: center;">
          Genesis is paused — background processing suspended. Use the pause button or /pause off in Telegram to resume.
        </div>
      </template>
      <!-- Resilience degradation banner -->
      <template x-if="$store.genesisDashboard.health.resilience?.level && $store.genesisDashboard.health.resilience.level !== 'L0' && $store.genesisDashboard.health.resilience.level !== 'not configured'">
        <div :style="`background: ${['L3', 'L4', 'L5', 'error'].includes($store.genesisDashboard.health.resilience.level) ? '#d9534f' : '#f0ad4e'}; color: white; padding: 0.5rem 1rem; font-size: 0.85rem; font-weight: 600; text-align: center;`"
             x-text="'Resilience: ' + $store.genesisDashboard.health.resilience.level + ' — ' + ($store.genesisDashboard.health.resilience.summary || 'system is operating in degraded mode')">
        </div>
      </template>
      <div class="panel-body">
        <template x-if="$store.genesisDashboard.panelStatusDetail('health')">
          <div class="panel-status-detail" x-text="$store.genesisDashboard.panelStatusDetail('health')"></div>
        </template>
        <div class="health-grid">

          <!-- Infrastructure probes -->
          <div class="health-card">
            <div class="health-card-header">
              <div class="health-card-title">Infrastructure</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.infrastructureSemantic().state)}`"
                    x-text="$store.genesisDashboard.infrastructureSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.infrastructure">
                <template x-for="(probe, name) in $store.genesisDashboard.health.infrastructure" :key="name">
                  <div x-show="!['container_memory', 'disk', 'cpu'].includes(name)"
                       style="margin-bottom: 0.2rem; cursor: default;"
                       :title="probe.error
                         ? name + ': ERROR — ' + probe.error
                         : probe.latency_ms != null
                           ? name + ': ' + (probe.status || 'healthy') + ' (' + Math.round(probe.latency_ms) + 'ms)'
                           : probe.free_pct != null
                             ? name + ': ' + probe.free_gb?.toFixed(1) + ' GB free (' + probe.free_pct?.toFixed(0) + '% of ' + probe.total_gb?.toFixed(0) + ' GB)'
                             : probe.total_points != null
                               ? name + ': ' + probe.total_points + ' total points across ' + (probe.collections?.length || 0) + ' collections'
                             : probe.cc_tier != null
                               ? name + ': CC ' + probe.cc_tier + ' (' + probe.cc_used_mb + '/' + probe.cc_budget_mb + 'MB)' + (probe.sys_tier ? ', /tmp ' + probe.sys_tier + ' (' + probe.sys_used_pct + '%)' : '')
                             : name + ': ' + (probe.status || 'unknown')">
                    <span class="status-dot"
                          :style="`background: ${$store.genesisDashboard.probeStatusColor(probe)}`"></span>
                    <span x-text="name" style="font-size: 0.82rem"></span>
                    <template x-if="probe.total_points != null">
                      <span style="opacity: 0.6; font-size: 0.72rem;" x-text="'(' + probe.total_points + ' pts)'"></span>
                    </template>
                    <template x-if="probe.collections?.length > 0">
                      <div style="margin-left: 1.1rem; margin-top: 0.1rem;">
                        <template x-for="coll in probe.collections" :key="coll.name">
                          <div style="font-size: 0.7rem; opacity: 0.6; padding: 0.05rem 0;">
                            <span x-text="coll.name"></span>
                            <span style="opacity: 0.7;" x-text="'(' + (coll.points || 0).toLocaleString() + ' pts)'"></span>
                          </div>
                        </template>
                      </div>
                    </template>
                  </div>
                </template>
              </template>
              <!-- Ollama missing models warning -->
              <template x-if="$store.genesisDashboard.health.infrastructure?.ollama?.missing_models?.length > 0">
                <div style="margin-top: 0.3rem; font-size: 0.72rem; color: #d9534f;">
                  Missing Ollama models:
                  <template x-for="m in $store.genesisDashboard.health.infrastructure.ollama.missing_models" :key="m.model">
                    <span x-text="m.model + ' '" style="font-weight: 600;"></span>
                  </template>
                </div>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.infrastructureSemantic().reason"></div>
          </div>

          <!-- CC Sessions -->
          <div class="health-card" title="Active Claude Code sessions. Foreground = user conversation, Background = reflections/tasks.">
            <div class="health-card-header">
              <div class="health-card-title">CC Sessions</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.ccSemantic().state)}`"
                    x-text="$store.genesisDashboard.ccSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.cc_sessions">
                <div>
                  <span x-text="$store.genesisDashboard.health.cc_sessions.foreground?.active ?? '—'"
                        :style="`color: ${($store.genesisDashboard.health.cc_sessions.foreground?.active || 0) > 0 ? '#4caf50' : '#888'}`"></span> fg
                  /
                  <span x-text="$store.genesisDashboard.health.cc_sessions.background?.active ?? '—'"
                        :style="`color: ${($store.genesisDashboard.health.cc_sessions.background?.active || 0) > 0 ? '#4caf50' : '#888'}`"></span> bg
                </div>
              </template>
            </div>
            <div class="health-card-detail"
                 x-text="$store.genesisDashboard.health.cc_sessions?.background?.hourly_budget || ''"></div>
            <template x-if="$store.genesisDashboard.health.cc_sessions?.hourly_burn_rate != null">
              <div class="health-card-detail" style="font-size: 0.72rem;"
                   x-text="$store.genesisDashboard.health.cc_sessions.hourly_burn_rate + ' sess/hr (max ' + ($store.genesisDashboard.health.cc_sessions.max_per_hour || 20) + ')'"></div>
            </template>
            <template x-if="($store.genesisDashboard.health.cc_sessions?.failed_24h || 0) > 0">
              <div class="health-card-detail" style="color: #d9534f; font-weight: 600;"
                   x-text="$store.genesisDashboard.health.cc_sessions.failed_24h + ' failed (24h)'"></div>
            </template>
            <div class="health-card-reason" x-text="$store.genesisDashboard.ccSemantic().reason"></div>
          </div>

          <!-- Cost -->
          <div class="health-card" title="API cost + CC subscription shadow cost.">
            <div class="health-card-header">
              <div class="health-card-title">Cost</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.costSemantic().state)}`"
                    x-text="$store.genesisDashboard.costSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.cost">
                <div>
                  <span x-text="'API: $' + ($store.genesisDashboard.health.cost.monthly_usd?.toFixed(2) ?? '—')" style="font-size: 0.85rem"></span>
                  <template x-if="$store.genesisDashboard.health.cost.budget_monthly_limit">
                    <span style="opacity: 0.6; font-size: 0.72rem"
                          x-text="' / $' + $store.genesisDashboard.health.cost.budget_monthly_limit.toFixed(2) + ' (' + ($store.genesisDashboard.health.cost.budget_pct_used?.toFixed(0) || 0) + '%)'"></span>
                  </template>
                  <div class="health-card-detail"
                       x-text="'Today: $' + ($store.genesisDashboard.health.cost.daily_usd?.toFixed(3) ?? '—') + ' | Week: $' + ($store.genesisDashboard.health.cost.weekly_usd?.toFixed(3) ?? '—')"></div>
                  <template x-if="$store.genesisDashboard.health.cost.forecast_monthly_usd">
                    <div class="health-card-detail"
                         :style="(() => { const f = $store.genesisDashboard.health.cost.forecast_monthly_usd; const l = $store.genesisDashboard.health.cost.budget_monthly_limit; if (!l) return ''; return f > l ? 'color: #d9534f; font-weight: 600' : f > l * 0.8 ? 'color: #f0ad4e' : 'color: #4caf50'; })()"
                         x-text="'Pacing: ~$' + $store.genesisDashboard.health.cost.forecast_monthly_usd.toFixed(2) + '/mo'"></div>
                  </template>
                  <template x-if="$store.genesisDashboard.health.cc_sessions?.shadow_cost_month > 0">
                    <div class="health-card-detail" style="margin-top: 0.2rem; border-top: 1px solid var(--color-border); padding-top: 0.2rem;"
                         x-text="'CC shadow: $' + $store.genesisDashboard.health.cc_sessions.shadow_cost_today.toFixed(2) + ' today ($' + $store.genesisDashboard.health.cc_sessions.shadow_cost_month.toFixed(2) + '/mo)'"></div>
                  </template>
                  <template x-if="($store.genesisDashboard.health.cc_sessions?.rate_limited_24h || 0) > 0">
                    <div class="health-card-detail" style="color: #d9534f; font-weight: 600;"
                         x-text="$store.genesisDashboard.health.cc_sessions.rate_limited_24h + ' rate limits (24h)'"></div>
                  </template>
                </div>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.costSemantic().reason"></div>
          </div>

          <!-- Queues -->
          <div class="health-card" id="queue-review">
            <div class="health-card-header">
              <div class="health-card-title">Queues</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.queuesSemantic().state)}`"
                    x-text="$store.genesisDashboard.queuesSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.queues">
                <div>
                  <div style="font-size: 0.82rem; cursor: default;"
                       title="Failed operations that exhausted all retry providers">
                    Dead Letters:
                    <span x-text="$store.genesisDashboard.health.queues.dead_letters ?? 0"
                          :style="($store.genesisDashboard.health.queues.dead_letters || 0) > 0 ? 'color: #d9534f; font-weight: 700' : 'color: #4caf50'"></span>
                  </div>
                  <div style="font-size: 0.82rem; cursor: default;"
                       title="Tasks postponed due to service degradation">
                    Deferred Pending:
                    <span x-text="$store.genesisDashboard.health.queues.deferred_work ?? 0"
                          :style="($store.genesisDashboard.health.queues.deferred_work || 0) > 0 ? 'color: #f0ad4e; font-weight: 700' : 'color: #4caf50'"></span>
                    <template x-if="$store.genesisDashboard.health.queues.deferred_oldest_age_seconds > 0">
                      <span style="font-size: 0.68rem; color: var(--color-text-secondary);"
                            x-text="'(oldest: ' + (() => { const s = $store.genesisDashboard.health.queues.deferred_oldest_age_seconds; return s > 3600 ? Math.round(s/3600) + 'h' : Math.round(s/60) + 'm'; })() + ')'"></span>
                    </template>
                  </div>
                  <template x-if="($store.genesisDashboard.health.queues.deferred_processing || 0) > 0">
                    <div style="font-size: 0.82rem; cursor: default;"
                         title="Items currently being processed (may be stuck if old)">
                      Deferred Processing:
                      <span x-text="$store.genesisDashboard.health.queues.deferred_processing"
                            style="color: #f0ad4e; font-weight: 700"></span>
                      <template x-if="($store.genesisDashboard.health.queues.deferred_stuck || 0) > 0">
                        <span style="font-size: 0.72rem; color: #d9534f; font-weight: 600;"
                              x-text="'(' + $store.genesisDashboard.health.queues.deferred_stuck + ' stuck >2h)'"></span>
                      </template>
                    </div>
                  </template>
                  <template x-if="$store.genesisDashboard.health.queues.deferred_items?.length > 0">
                    <div style="margin-top: 0.3rem; font-size: 0.68rem;">
                      <template x-for="item in $store.genesisDashboard.health.queues.deferred_items" :key="item.type + item.site">
                        <div style="color: var(--color-text-secondary); margin: 0.1rem 0;"
                             :title="item.reason">
                          <span x-text="item.type"></span> &rarr;
                          <span x-text="item.site"></span>
                          (<span x-text="Math.round(item.age_s / 60) + 'm'" :style="item.age_s > 3600 ? 'color: #d9534f' : ''"></span>,
                          <span x-text="item.attempts + ' tries'"></span>)
                        </div>
                      </template>
                    </div>
                  </template>
                  <template x-if="($store.genesisDashboard.health.queues.discarded_items?.length || 0) > 0">
                    <div style="margin-top: 0.3rem; font-size: 0.72rem; color: #d9534f; font-weight: 600;">
                      <span x-text="$store.genesisDashboard.health.queues.discarded_items.length"></span> discarded — needs review
                    </div>
                  </template>
                  <div style="font-size: 0.82rem; cursor: default;"
                       title="Memory items waiting to be embedded in vector DB">
                    Embeddings Pending:
                    <span x-text="$store.genesisDashboard.health.queues.pending_embeddings ?? 0"
                          :style="($store.genesisDashboard.health.queues.pending_embeddings || 0) > 0 ? 'color: #f0ad4e; font-weight: 700' : ''"></span>
                  </div>
                  <template x-if="($store.genesisDashboard.health.queues.failed_embeddings || 0) > 0">
                    <div style="font-size: 0.82rem; cursor: default;"
                         :title="$store.genesisDashboard.health.queues.embedding_last_error || 'embedding failure'">
                      Embeddings Failed:
                      <span x-text="$store.genesisDashboard.health.queues.failed_embeddings"
                            style="color: #d9534f; font-weight: 700"></span>
                    </div>
                  </template>
                  <div style="font-size: 0.82rem; cursor: default;"
                       title="Items that failed inline embedding but were later successfully embedded via retry queue">
                    Embedding Retries OK:
                    <span x-text="$store.genesisDashboard.health.queues.embedded_total ?? 0"
                          style="color: #4caf50"></span>
                  </div>
                  <template x-if="$store.genesisDashboard.queueReview.message">
                    <div class="health-card-detail" style="margin-top:0.45rem; color:#4caf50;" x-text="$store.genesisDashboard.queueReview.message"></div>
                  </template>
                  <template x-if="$store.genesisDashboard.queueReview.error">
                    <div class="health-card-detail" style="margin-top:0.45rem; color:#d9534f;" x-text="$store.genesisDashboard.queueReview.error"></div>
                  </template>
                  <template x-if="$store.genesisDashboard.deferredQueueGroups.length > 0">
                    <div style="margin-top:0.55rem; border-top:1px solid rgba(255,255,255,0.06); padding-top:0.55rem;">
                      <div style="font-size:0.7rem; font-weight:600; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-text-secondary); margin-bottom:0.35rem;">Deferred review</div>
                      <template x-for="group in $store.genesisDashboard.deferredQueueGroups" :key="group.key">
                        <div style="margin-bottom:0.45rem; padding:0.4rem 0.5rem; border-radius:6px; background:rgba(240,173,78,0.07); border:1px solid rgba(240,173,78,0.18);">
                          <div style="display:flex; justify-content:space-between; gap:0.5rem; align-items:flex-start;">
                            <div>
                              <div style="font-size:0.74rem; font-weight:600;">
                                <span x-text="group.site"></span>
                                <span style="opacity:0.6;"> • </span>
                                <span x-text="group.type"></span>
                              </div>
                              <div style="font-size:0.68rem; color:var(--color-text-secondary);" x-text="group.reason"></div>
                            </div>
                            <div style="font-size:0.68rem; color:var(--color-text-secondary); text-align:right;">
                              <div x-text="group.count + ' item' + (group.count === 1 ? '' : 's')"></div>
                              <div x-text="'oldest ' + $store.genesisDashboard.formatAgeSeconds(group.maxAgeSeconds)"></div>
                            </div>
                          </div>
                          <template x-for="item in group.items" :key="item.type + ':' + item.site + ':' + item.age_s + ':' + item.attempts">
                            <div style="margin-top:0.3rem; font-size:0.68rem; color:var(--color-text-secondary); display:flex; justify-content:space-between; gap:0.5rem;">
                              <span x-text="$store.genesisDashboard.formatAgeSeconds(item.age_s) + ' old'"></span>
                              <span x-text="item.attempts + ' tries'"></span>
                            </div>
                          </template>
                        </div>
                      </template>
                    </div>
                  </template>
                  <div style="margin-top:0.55rem; border-top:1px solid rgba(255,255,255,0.06); padding-top:0.55rem;">
                    <div style="display:flex; justify-content:space-between; gap:0.5rem; align-items:center; margin-bottom:0.35rem;">
                      <div style="font-size:0.7rem; font-weight:600; text-transform:uppercase; letter-spacing:0.04em; color:var(--color-text-secondary);">Discarded review</div>
                      <button type="button"
                              style="font-size:0.68rem; padding:0.22rem 0.45rem; border-radius:4px; border:1px solid rgba(217,83,79,0.3); color:#d9534f; background:transparent; cursor:pointer;"
                              :disabled="$store.genesisDashboard.queueReview.clearingAll || ($store.genesisDashboard.health.queues.discarded_items?.length || 0) === 0"
                              @click="$store.genesisDashboard.clearAllDiscardedItems()"
                              x-text="$store.genesisDashboard.queueReview.clearingAll ? 'Clearing...' : 'Clear all reviewed'"></button>
                    </div>
                    <template x-if="$store.genesisDashboard.discardedQueueGroups.length === 0">
                      <div class="health-card-detail" style="margin-top:0;">No discarded or expired items awaiting review.</div>
                    </template>
                    <template x-for="group in $store.genesisDashboard.discardedQueueGroups" :key="group.key">
                      <div style="margin-bottom:0.5rem; padding:0.45rem 0.55rem; border-radius:6px; background:rgba(217,83,79,0.08); border:1px solid rgba(217,83,79,0.18);">
                        <div style="display:flex; justify-content:space-between; gap:0.5rem; align-items:flex-start;">
                          <div>
                            <div style="font-size:0.74rem; font-weight:600;">
                              <span x-text="group.site"></span>
                              <span style="opacity:0.6;"> • </span>
                              <span x-text="group.type"></span>
                            </div>
                            <div style="font-size:0.68rem; color:var(--color-text-secondary);" x-text="group.reason"></div>
                          </div>
                          <div style="font-size:0.68rem; color:var(--color-text-secondary); text-align:right;">
                            <div x-text="group.count + ' item' + (group.count === 1 ? '' : 's')"></div>
                            <div x-text="'oldest ' + $store.genesisDashboard.formatAgeSeconds(group.maxAgeSeconds)"></div>
                          </div>
                        </div>
                        <template x-for="item in group.items" :key="item.id">
                          <div style="margin-top:0.35rem; padding-top:0.35rem; border-top:1px solid rgba(255,255,255,0.05);">
                            <div style="display:flex; justify-content:space-between; gap:0.5rem; align-items:flex-start;">
                              <div style="font-size:0.68rem; color:var(--color-text-secondary);">
                                <div>
                                  <span x-text="item.status"></span>
                                  <span style="opacity:0.6;"> • </span>
                                  <span x-text="$store.genesisDashboard.formatAgeSeconds(item.age_s) + ' old'"></span>
                                  <span style="opacity:0.6;"> • </span>
                                  <span x-text="item.attempts + ' tries'"></span>
                                </div>
                                <template x-if="item.error">
                                  <div style="margin-top:0.15rem; color:#f5c2c0;" x-text="item.error"></div>
                                </template>
                                <template x-if="item.discarded_at">
                                  <div style="margin-top:0.15rem;" x-text="'discarded ' + $store.genesisDashboard.relativeTime(item.discarded_at)"></div>
                                </template>
                              </div>
                              <button type="button"
                                      style="font-size:0.68rem; padding:0.22rem 0.45rem; border-radius:4px; border:1px solid rgba(217,83,79,0.3); color:#d9534f; background:transparent; cursor:pointer;"
                                      :disabled="$store.genesisDashboard.queueReview.clearingIds[item.id]"
                                      @click="$store.genesisDashboard.clearDeferredItem(item.id)"
                                      x-text="$store.genesisDashboard.queueReview.clearingIds[item.id] ? 'Clearing...' : 'Clear'"></button>
                            </div>
                          </div>
                        </template>
                      </div>
                    </template>
                  </div>
                </div>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.queuesSemantic().reason"></div>
          </div>

          <!-- Surplus -->
          <div class="health-card" title="Surplus compute: opportunistic background tasks during idle time."
               style="cursor: pointer;" @click="$store.genesisDashboard.surplusModal.open = true; $store.genesisDashboard.fetchSurplusDetail()">
            <div class="health-card-header">
              <div class="health-card-title">Surplus <span style="font-size: 0.6rem; opacity: 0.5;">click for details</span></div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.surplusSemantic().state)}`"
                    x-text="$store.genesisDashboard.surplusSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.surplus">
                <div>
                  <span class="status-dot"
                        :style="`background: ${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.surplusSemantic().state)}`"></span>
                  <span style="font-size: 0.82rem"
                        x-text="$store.genesisDashboard.health.surplus.status || 'unknown'"></span>
                  <div class="health-card-detail"
                       x-text="'Queue: ' + ($store.genesisDashboard.health.surplus.queue_depth ?? 0)"></div>
                  <template x-if="$store.genesisDashboard.health.surplus.tasks_completed_24h > 0 || $store.genesisDashboard.health.surplus.tasks_failed_24h > 0">
                    <div class="health-card-detail" style="font-size: 0.72rem;"
                         x-text="($store.genesisDashboard.health.surplus.tasks_completed_24h || 0) + ' done / ' + ($store.genesisDashboard.health.surplus.tasks_failed_24h || 0) + ' failed (24h)'"></div>
                  </template>
                </div>
              </template>
              <template x-if="!$store.genesisDashboard.health.surplus">
                <span style="color: #666; font-size: 0.82rem">No surplus data</span>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.surplusSemantic().reason"></div>
          </div>

          <!-- Ego -->
          <template x-if="$store.genesisDashboard.egoStatus?.enabled">
            <div class="health-card" title="Ego: autonomous decision-making cycle with adaptive cadence and budget controls."
                 style="cursor: pointer;" @click="$store.genesisDashboard.egoModal.open = true; $store.genesisDashboard.fetchEgoDetail()">
              <div class="health-card-header">
                <div class="health-card-title">Ego <span style="font-size: 0.6rem; opacity: 0.5;">click for details</span></div>
                <span class="status-chip"
                      :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.egoSemantic().state)}`"
                      x-text="$store.genesisDashboard.egoSemantic().state"></span>
              </div>
              <div class="health-card-value">
                <div>
                  <span class="status-dot"
                        :style="`background: ${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.egoSemantic().state)}`"></span>
                  <span style="font-size: 0.82rem"
                        x-text="$store.genesisDashboard.egoStatus?.focus_summary || 'no focus'"></span>
                  <!-- Budget gauge -->
                  <div style="margin-top: 0.3rem; display: flex; align-items: center; gap: 0.4rem;">
                    <div style="flex: 1; height: 4px; background: rgba(255,255,255,0.1); border-radius: 2px; overflow: hidden;">
                      <div :style="`width: ${Math.min(100, ($store.genesisDashboard.egoStatus?.daily_cost_usd || 0) / ($store.genesisDashboard.egoStatus?.daily_budget_cap_usd || 1) * 100)}%; height: 100%; border-radius: 2px; background: ${($store.genesisDashboard.egoStatus?.daily_cost_usd || 0) / ($store.genesisDashboard.egoStatus?.daily_budget_cap_usd || 1) > 0.8 ? '#d9534f' : ($store.genesisDashboard.egoStatus?.daily_cost_usd || 0) / ($store.genesisDashboard.egoStatus?.daily_budget_cap_usd || 1) > 0.5 ? '#f0ad4e' : '#4caf50'}`"></div>
                    </div>
                    <span style="font-size: 0.68rem; color: var(--color-text-secondary);"
                          x-text="'$' + ($store.genesisDashboard.egoStatus?.daily_cost_usd || 0).toFixed(2) + ' / $' + ($store.genesisDashboard.egoStatus?.daily_budget_cap_usd || 0).toFixed(2)"></span>
                  </div>
                  <div class="health-card-detail" style="font-size: 0.72rem;"
                       x-text="($store.genesisDashboard.egoStatus?.pending_proposals || 0) + ' pending proposals'"></div>
                </div>
              </div>
              <div class="health-card-reason" x-text="$store.genesisDashboard.egoSemantic().reason"></div>
            </div>
          </template>

          <!-- Services -->
          <div class="health-card" title="Host framework, bridge, and watchdog service status">
            <div class="health-card-header">
              <div class="health-card-title">Services</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.servicesSemantic().state)}`"
                    x-text="$store.genesisDashboard.servicesSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.services">
                <div>
                  <!-- Host Framework (auto-detected) -->
                  <template x-if="$store.genesisDashboard.health.services?.host_framework?.detected">
                    <div style="font-size: 0.82rem; margin-bottom: 0.2rem; cursor: default;"
                         :title="(() => {
                           const hf = $store.genesisDashboard.health.services.host_framework;
                           let tip = hf.name + ': ' + hf.status;
                           if (hf.details?.restart_count != null) tip += ' (restarts: ' + hf.details.restart_count + ')';
                           return tip;
                         })()">
                      <span class="status-dot"
                            :style="`background: ${$store.genesisDashboard.health.services.host_framework.status === 'healthy' ? '#4caf50' : $store.genesisDashboard.health.services.host_framework.status === 'degraded' ? '#f0ad4e' : '#d9534f'}`"></span>
                      <span x-text="$store.genesisDashboard.health.services.host_framework.name" style="font-weight: 600"></span>
                      <span style="opacity: 0.6; font-size: 0.75rem"
                            x-text="$store.genesisDashboard.health.services.host_framework.uptime_seconds != null ? Math.round($store.genesisDashboard.health.services.host_framework.uptime_seconds / 60) + 'm' : ''"></span>
                    </div>
                  </template>
                  <!-- Genesis service (server or bridge) -->
                  <div style="font-size: 0.82rem; margin-bottom: 0.2rem; cursor: default;"
                       :title="($store.genesisDashboard.health.services?.bridge?.service_label || 'Genesis') + ': ' + ($store.genesisDashboard.health.services?.bridge?.active_state || 'unknown') + ' (PID ' + ($store.genesisDashboard.health.services?.bridge?.pid || '?') + ')'">
                    <span class="status-dot"
                          :style="`background: ${$store.genesisDashboard.health.services?.bridge?.active_state === 'active' ? '#4caf50' : ['failed', 'inactive'].includes($store.genesisDashboard.health.services?.bridge?.active_state) ? '#d9534f' : '#666'}`"></span>
                    <span x-text="$store.genesisDashboard.health.services?.bridge?.service_label || 'Genesis'"></span>
                    <span style="opacity: 0.6; font-size: 0.75rem"
                          x-text="$store.genesisDashboard.health.services?.bridge?.uptime_seconds != null ? Math.round($store.genesisDashboard.health.services.bridge.uptime_seconds / 60) + 'm' : ''"></span>
                  </div>
                  <!-- Watchdog -->
                  <div style="font-size: 0.82rem; margin-bottom: 0.2rem; cursor: default;"
                       :title="'Watchdog timer: ' + ($store.genesisDashboard.health.services?.watchdog_timer?.active_state || 'unknown')">
                    <span class="status-dot"
                          :style="`background: ${$store.genesisDashboard.health.services?.watchdog_timer?.active_state === 'active' ? '#4caf50' : ['failed', 'inactive'].includes($store.genesisDashboard.health.services?.watchdog_timer?.active_state) ? '#d9534f' : '#666'}`"></span>
                    Watchdog
                    <span style="opacity: 0.6; font-size: 0.75rem"
                          x-text="($store.genesisDashboard.health.services?.watchdog?.consecutive_failures || 0) > 0 ? '(' + $store.genesisDashboard.health.services.watchdog.consecutive_failures + ' fails)' : ''"></span>
                  </div>
                  <!-- Sentinel (container-side guardian) -->
                  <div style="font-size: 0.82rem; margin-bottom: 0.2rem; cursor: default;"
                       :title="(() => {
                         const s = $store.genesisDashboard.health.services?.sentinel;
                         if (!s || !s.enabled) return 'Sentinel: unavailable';
                         let tip = 'Sentinel: ' + s.current_state;
                         if (s.is_stale) tip += ` (stale ${Math.round((s.staleness_s || 0) / 60)}m)`;
                         else if (s.is_active) tip += ' (running)';
                         if (s.last_trigger_reason) tip += ' — last: ' + s.last_trigger_reason;
                         return tip;
                       })()">
                    <span class="status-dot"
                          :style="`background: ${(() => {
                            const s = $store.genesisDashboard.health.services?.sentinel;
                            if (!s || !s.enabled) return '#666';
                            if (s.is_stale || s.current_state === 'stale') return '#ff9800';
                            if (s.current_state === 'healthy') return '#4caf50';
                            if (s.current_state === 'escalated') return '#d9534f';
                            if (['investigating', 'remediating', 'awaiting_dispatch_approval', 'awaiting_action_approval'].includes(s.current_state)) return '#f0ad4e';
                            return '#666';  // unknown/future state — gray, not yellow
                          })()}`"></span>
                    Sentinel
                    <span style="opacity: 0.6; font-size: 0.75rem"
                          x-text="(() => {
                            const s = $store.genesisDashboard.health.services?.sentinel;
                            if (!s || !s.enabled) return '';
                            if (s.is_stale) return '(stale)';
                            if (s.is_active) return '(running)';
                            if (s.current_state.startsWith('awaiting')) return '(awaiting approval)';
                            if (s.current_state !== 'healthy') return '(' + s.current_state + ')';
                            return '';
                          })()"></span>
                  </div>
                  <!-- /tmp is shown in Infrastructure card, not here -->
                </div>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.servicesSemantic().reason"></div>
          </div>

          <!-- Container Resources (memory + CPU + disk) -->
          <div class="health-card" title="Container resource usage. Memory >85% = OOM danger zone. Disk >90% = write failures.">
            <div class="health-card-header">
              <div class="health-card-title">Container</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.containerSemantic().state)}`"
                    x-text="$store.genesisDashboard.containerSemantic().state"></span>
            </div>
            <div class="health-card-value" style="display:flex; flex-direction:column; gap:0.35rem;">
              <!-- Memory row -->
              <template x-if="($store.genesisDashboard.health.infrastructure?.container_memory?.anon_pct ?? $store.genesisDashboard.health.infrastructure?.container_memory?.used_pct) != null">
                <div style="display:flex; align-items:center; gap:0.5rem; font-size:0.8rem;">
                  <span style="width:3.2rem; color:var(--color-text-secondary);">Memory</span>
                  <span style="width:3rem; text-align:right; font-weight:600;"
                        :style="(() => { const p = $store.genesisDashboard.health.infrastructure.container_memory.anon_pct ?? $store.genesisDashboard.health.infrastructure.container_memory.used_pct; return `color: ${p > 85 ? '#d9534f' : p > 75 ? '#f0ad4e' : '#4caf50'}`; })()"
                        x-text="(($store.genesisDashboard.health.infrastructure.container_memory.anon_pct ?? $store.genesisDashboard.health.infrastructure.container_memory.used_pct) || 0).toFixed(0) + '%'"></span>
                  <div style="flex:1; height:6px; background:var(--color-background); border-radius:3px; min-width:40px;">
                    <div style="height:100%; border-radius:3px; transition:width 0.3s;"
                         :style="(() => { const p = $store.genesisDashboard.health.infrastructure.container_memory.anon_pct ?? $store.genesisDashboard.health.infrastructure.container_memory.used_pct ?? 0; return 'width:' + p + '%; background:' + (p > 85 ? '#d9534f' : p > 75 ? '#f0ad4e' : '#4caf50'); })()"></div>
                  </div>
                  <span style="font-size:0.7rem; color:var(--color-text-secondary); white-space:nowrap;"
                        x-text="$store.genesisDashboard.health.infrastructure.container_memory.current_gb?.toFixed(0) + '/' + $store.genesisDashboard.health.infrastructure.container_memory.limit_gb?.toFixed(0) + ' GB'"></span>
                </div>
              </template>
              <!-- CPU row -->
              <template x-if="$store.genesisDashboard.health.infrastructure?.cpu">
                <div style="display:flex; align-items:center; gap:0.5rem; font-size:0.8rem;">
                  <span style="width:3.2rem; color:var(--color-text-secondary);">CPU</span>
                  <template x-if="$store.genesisDashboard.health.infrastructure.cpu.used_pct != null">
                    <span style="width:3rem; text-align:right; font-weight:600;"
                          :style="`color: ${$store.genesisDashboard.health.infrastructure.cpu.used_pct > 85 ? '#d9534f' : $store.genesisDashboard.health.infrastructure.cpu.used_pct > 60 ? '#f0ad4e' : '#4caf50'}`"
                          x-text="$store.genesisDashboard.health.infrastructure.cpu.used_pct.toFixed(0) + '%'"></span>
                  </template>
                  <template x-if="$store.genesisDashboard.health.infrastructure.cpu.used_pct == null">
                    <span style="width:3rem; text-align:right; font-size:0.7rem; color:var(--color-text-secondary);">—</span>
                  </template>
                  <template x-if="$store.genesisDashboard.health.infrastructure.cpu.used_pct != null">
                    <div style="flex:1; height:6px; background:var(--color-background); border-radius:3px; min-width:40px;">
                      <div style="height:100%; border-radius:3px; transition:width 0.3s;"
                           :style="'width:' + $store.genesisDashboard.health.infrastructure.cpu.used_pct + '%; background:' + ($store.genesisDashboard.health.infrastructure.cpu.used_pct > 85 ? '#d9534f' : $store.genesisDashboard.health.infrastructure.cpu.used_pct > 60 ? '#f0ad4e' : '#4caf50')"></div>
                    </div>
                  </template>
                  <template x-if="$store.genesisDashboard.health.infrastructure.cpu.used_pct == null">
                    <div style="flex:1;"></div>
                  </template>
                  <span style="font-size:0.7rem; color:var(--color-text-secondary); white-space:nowrap;"
                        x-text="($store.genesisDashboard.health.infrastructure.cpu.count || '?') + ' vCPUs'"></span>
                </div>
              </template>
              <!-- Disk row -->
              <template x-if="$store.genesisDashboard.health.infrastructure?.disk?.free_pct != null">
                <div style="display:flex; align-items:center; gap:0.5rem; font-size:0.8rem;">
                  <span style="width:3.2rem; color:var(--color-text-secondary);">Disk</span>
                  <span style="width:3rem; text-align:right; font-weight:600;"
                        :style="`color: ${(100 - $store.genesisDashboard.health.infrastructure.disk.free_pct) > 90 ? '#d9534f' : (100 - $store.genesisDashboard.health.infrastructure.disk.free_pct) > 85 ? '#f0ad4e' : '#4caf50'}`"
                        x-text="(100 - $store.genesisDashboard.health.infrastructure.disk.free_pct).toFixed(0) + '%'"></span>
                  <div style="flex:1; height:6px; background:var(--color-background); border-radius:3px; min-width:40px;">
                    <div style="height:100%; border-radius:3px; transition:width 0.3s;"
                         :style="'width:' + (100 - $store.genesisDashboard.health.infrastructure.disk.free_pct) + '%; background:' + ((100 - $store.genesisDashboard.health.infrastructure.disk.free_pct) > 90 ? '#d9534f' : (100 - $store.genesisDashboard.health.infrastructure.disk.free_pct) > 85 ? '#f0ad4e' : '#4caf50')"></div>
                  </div>
                  <span style="font-size:0.7rem; color:var(--color-text-secondary); white-space:nowrap;"
                        x-text="($store.genesisDashboard.health.infrastructure.disk.total_gb - $store.genesisDashboard.health.infrastructure.disk.free_gb).toFixed(0) + '/' + $store.genesisDashboard.health.infrastructure.disk.total_gb.toFixed(0) + ' GB'"></span>
                </div>
              </template>
              <!-- Fallback when no data -->
              <template x-if="!$store.genesisDashboard.health.infrastructure?.container_memory?.used_pct && !$store.genesisDashboard.health.infrastructure?.cpu && !$store.genesisDashboard.health.infrastructure?.disk">
                <span style="color: #666; font-size: 0.82rem;">no data</span>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.containerSemantic().reason"></div>
          </div>

          <!-- Awareness Loop -->
          <div class="health-card" title="Awareness loop health: 5-min ticks, signal collection, reflection triggers.">
            <div class="health-card-header">
              <div class="health-card-title">Awareness Loop</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.awarenessSemantic().state)}`"
                    x-text="$store.genesisDashboard.awarenessSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.awareness">
                <div>
                  <span class="status-dot"
                        :style="`background: ${$store.genesisDashboard.probeStatusColor($store.genesisDashboard.health.awareness)}`"></span>
                  <span x-text="$store.genesisDashboard.health.awareness.time_since_last_tick_seconds != null
                    ? ($store.genesisDashboard.health.awareness.time_since_last_tick_seconds < 60
                      ? Math.round($store.genesisDashboard.health.awareness.time_since_last_tick_seconds) + 's ago'
                      : Math.round($store.genesisDashboard.health.awareness.time_since_last_tick_seconds / 60) + 'm ago')
                    : $store.genesisDashboard.health.awareness.status || 'unknown'"
                        style="font-size: 0.82rem"></span>
                  <div class="health-card-detail"
                       x-text="$store.genesisDashboard.health.awareness.ticks_24h != null ? $store.genesisDashboard.health.awareness.ticks_24h + ' ticks/24h' : ''"></div>
                  <template x-if="$store.genesisDashboard.health.awareness.depth_distribution_24h">
                    <div style="font-size: 0.68rem; color: var(--color-text-secondary); margin-top: 0.15rem; cursor: help;"
                         title="Ticks = awareness loop cycles (~2 min). Reflections (micro/light/deep/strategic) trigger when signal scores exceed thresholds. 'No reflections' = all ticks were signal-only."
                         x-text="(() => {
                           const d = $store.genesisDashboard.health.awareness.depth_distribution_24h;
                           const keys = Object.keys(d);
                           if (keys.length === 1 && keys[0] === 'none') return d.none + ' ticks (no reflections)';
                           return Object.entries(d).map(([k,v]) => (k === 'none' ? 'micro' : k) + ':' + v).join(' ');
                         })()"></div>
                  </template>
                  <template x-if="$store.genesisDashboard.health.awareness.last_reflection">
                    <div style="font-size: 0.68rem; color: var(--color-text-secondary); margin-top: 0.1rem;"
                         x-text="'Last reflection: ' + $store.genesisDashboard.formatTime($store.genesisDashboard.health.awareness.last_reflection.at)"></div>
                  </template>
                  <template x-if="($store.genesisDashboard.health.awareness.critical_bypasses_24h || 0) > 0">
                    <div style="font-size: 0.68rem; color: #d9534f; font-weight: 600; margin-top: 0.1rem;"
                         x-text="$store.genesisDashboard.health.awareness.critical_bypasses_24h + ' critical bypasses (24h)'"></div>
                  </template>
                </div>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.awarenessSemantic().reason"></div>
          </div>

          <!-- Outreach Stats -->
          <div class="health-card" title="7-day outreach metrics. Click to view messages."
               style="cursor: pointer;" @click="location.hash = 'chat'; $store.genesisDashboard.commsTab = 'outreach'">
            <div class="health-card-header">
              <div class="health-card-title">Outreach (7d) <span style="font-size: 0.6rem; opacity: 0.5;">click for details</span></div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.outreachSemantic().state)}`"
                    x-text="$store.genesisDashboard.outreachSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.outreach_stats?.total != null">
                <div>
                  <span x-text="$store.genesisDashboard.health.outreach_stats.total + ' sent'" style="font-size: 0.82rem"></span>
                  <div class="health-card-detail"
                       x-text="$store.genesisDashboard.health.outreach_stats.engagement_rate != null ? 'Engagement: ' + ($store.genesisDashboard.health.outreach_stats.engagement_rate * 100).toFixed(0) + '%' : 'No engagement data'"></div>
                </div>
              </template>
              <template x-if="$store.genesisDashboard.health.outreach_stats?.total == null">
                <span style="color: #666; font-size: 0.82rem">No outreach data</span>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.outreachSemantic().reason"></div>
          </div>

          <!-- Conversation Activity -->
          <div class="health-card" title="Current conversation session activity from CC CLI.">
            <div class="health-card-header">
              <div class="health-card-title">Conversation</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.conversationSemantic().state)}`"
                    x-text="$store.genesisDashboard.conversationSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.conversation?.last_user_message_age_s != null">
                <div>
                  <span style="font-size: 0.82rem"
                        :style="`color: ${(() => {
                          const s = $store.genesisDashboard.health.conversation.last_user_message_age_s;
                          if (s < 300) return '#4caf50';
                          if (s < 1800) return '#f0ad4e';
                          return '#888';
                        })()}`"
                        x-text="(() => {
                          const s = $store.genesisDashboard.health.conversation.last_user_message_age_s;
                          if (s < 60) return 'Last msg: ' + Math.round(s) + 's ago';
                          if (s < 3600) return 'Last msg: ' + Math.round(s/60) + 'm ago';
                          return 'Last msg: ' + Math.round(s/3600) + 'h ago';
                        })()"></span>
                  <div class="health-card-detail"
                       x-text="($store.genesisDashboard.health.conversation.recent_user_turns || 0) + ' user / ' + ($store.genesisDashboard.health.conversation.recent_assistant_turns || 0) + ' assistant turns'"></div>
                </div>
              </template>
              <template x-if="$store.genesisDashboard.health.conversation?.last_user_message_age_s == null">
                <span style="color: #666; font-size: 0.82rem"
                      x-text="$store.genesisDashboard.health.conversation?.status || 'no data'"></span>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.conversationSemantic().reason"></div>
          </div>

          <!-- MCP Servers -->
          <div class="health-card" title="Genesis MCP server status. Click for tool details."
               style="cursor: pointer;" @click="$store.genesisDashboard.mcpModal.open = true; $store.genesisDashboard.fetchMcpTools()">
            <div class="health-card-header">
              <div class="health-card-title">MCP Servers</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.mcpSemantic().state)}`"
                    x-text="$store.genesisDashboard.mcpSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.mcp_servers">
                <div>
                  <template x-for="(info, name) in $store.genesisDashboard.health.mcp_servers" :key="name">
                    <div style="font-size: 0.78rem; margin-bottom: 0.15rem;"
                         :title="info.error ? name + ': ' + info.error : name + ': ' + info.tool_count + ' tools'">
                      <span class="status-dot" :style="`background: ${$store.genesisDashboard.probeStatusColor(info)}`"></span>
                      <span x-text="name"></span>
                      <span style="opacity: 0.6; font-size: 0.7rem"
                            x-text="info.tool_count != null ? '(' + info.tool_count + ' tools)' : info.error ? '(error)' : ''"></span>
                    </div>
                  </template>
                </div>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.mcpSemantic().reason"></div>
          </div>

          <!-- API Keys -->
          <div class="health-card" title="API key status. Click for details."
               style="cursor: pointer;" @click="$store.genesisDashboard.apiKeysModal.open = true">
            <div class="health-card-header">
              <div class="health-card-title">API Keys</div>
              <span class="status-chip"
                    :style="`color:${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.apiKeysSemantic().state)}`"
                    x-text="$store.genesisDashboard.apiKeysSemantic().state"></span>
            </div>
            <div class="health-card-value">
              <template x-if="$store.genesisDashboard.health.api_keys">
                <div>
                  <span style="font-size: 0.82rem"
                        x-text="(() => {
                          const keys = $store.genesisDashboard.health.api_keys;
                          const total = Object.keys(keys).length;
                          const missing = Object.values(keys).filter(k => k.status === 'missing').length;
                          const failed = Object.values(keys).filter(k => k.status === 'failed').length;
                          const local = Object.values(keys).filter(k => k.status === 'local').length;
                          const validated = Object.values(keys).filter(k => k.status === 'validated').length;
                          if (missing > 0 || failed > 0) return validated + ' ok, ' + (missing + failed) + ' bad / ' + (total - local);
                          return validated + '/' + (total - local) + ' validated';
                        })()"></span>
                  <template x-for="(info, name) in $store.genesisDashboard.health.api_keys" :key="name">
                    <template x-if="info.status === 'missing' || info.status === 'failed'">
                      <div style="font-size: 0.72rem; margin-top: 0.1rem;"
                           :style="`color: ${info.status === 'missing' ? '#d9534f' : '#f0ad4e'}`"
                           :title="info.error || ''">
                        <span class="status-dot" :style="`background: ${info.status === 'missing' ? '#d9534f' : '#f0ad4e'}`"></span>
                        <span x-text="name + ' (' + (info.error ? info.error.substring(0, 40) : info.status) + ')'"></span>
                      </div>
                    </template>
                  </template>
                </div>
              </template>
            </div>
            <div class="health-card-reason" x-text="$store.genesisDashboard.apiKeysSemantic().reason"></div>
          </div>

        </div>

        <!-- Provider Activity moved to Operational Vitals -->
      </div>
    </div>

    <!-- Panel: Cognitive State (Collapsible) [Tab: overview] -->
    <div class="panel" x-data="{ cogOpen: false }" x-show="$store.genesisDashboard.activeTab === 'overview'">
      <div class="panel-header" style="cursor: pointer;" @click="cogOpen = !cogOpen">
        <span class="material-symbols-outlined" :style="cogOpen ? 'transform: rotate(90deg)' : ''" style="transition: transform 0.2s">chevron_right</span>
        <span class="material-symbols-outlined">psychology</span>
        Cognitive State
        <span class="panel-status">
          <template x-if="$store.genesisDashboard.cognitiveState?.freshness_level">
            <span style="font-size: 0.68rem;"
                  :style="({'fresh':'color:#4caf50','aging':'color:#f0ad4e','stale':'color:#d9534f','unknown':'opacity:0.5'})[
                    $store.genesisDashboard.cognitiveState.freshness_level] || 'opacity:0.5'"
                  x-text="(() => {
                    const s = $store.genesisDashboard.cognitiveState.freshness_seconds;
                    if (!s) return '';
                    if (s < 3600) return Math.round(s/60) + 'm ago';
                    if (s < 86400) return Math.round(s/3600) + 'h ago';
                    return Math.round(s/86400) + 'd ago';
                  })()"></span>
          </template>
          <template x-if="$store.genesisDashboard.cognitiveState?.health_flags">
            <span style="color: #f0ad4e; font-size: 0.68rem;" x-text="$store.genesisDashboard.cognitiveState.health_flags.split('\n').filter(l => l.trim()).length + ' flag(s)'"></span>
          </template>
          <span class="status-dot" :style="`background:${$store.genesisDashboard.panelStateColor('cognitive')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('cognitive')"></span>
        </span>
      </div>
      <div class="panel-body" x-show="cogOpen" x-transition>
        <template x-if="$store.genesisDashboard.panelStatusDetail('cognitive')">
          <div class="panel-status-detail" x-text="$store.genesisDashboard.panelStatusDetail('cognitive')"></div>
        </template>
        <template x-if="!$store.genesisDashboard.cognitiveState">
          <div class="empty-state">No cognitive state generated yet.</div>
        </template>
        <template x-if="$store.genesisDashboard.cognitiveState">
          <div>
            <!-- Health flags (computed, auto-clearing) -->
            <template x-if="$store.genesisDashboard.cognitiveState.health_flags">
              <div style="margin-bottom: 0.75rem; padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px; background: rgba(240,173,78,0.06);">
                <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.3rem; color: #f0ad4e;">Computed Health Flags</div>
                <template x-for="line in $store.genesisDashboard.cognitiveState.health_flags.split('\n').filter(l => l.trim())" :key="line">
                  <div style="font-size: 0.76rem; margin: 0.15rem 0; color: var(--color-text);"
                       :style="line.includes('[CRITICAL]') ? 'color: #d9534f; font-weight: 600' : line.includes('[WARNING]') ? 'color: #f0ad4e' : ''"
                       x-text="line.replace(/^- /, '')"></div>
                </template>
              </div>
            </template>
            <!-- State flags / focus directive -->
            <template x-if="$store.genesisDashboard.cognitiveState.state_flags?.content">
              <div style="margin-bottom: 0.75rem; padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px;">
                <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.3rem;">Reflection Focus</div>
                <div style="font-size: 0.76rem; white-space: pre-wrap; color: var(--color-text-secondary);" x-text="$store.genesisDashboard.cognitiveState.state_flags.content.replace(/^## .+\n/, '')"></div>
              </div>
            </template>
            <!-- Active context -->
            <template x-if="$store.genesisDashboard.cognitiveState.active_context?.content">
              <div style="padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px;">
                <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.3rem;">
                  Active Context
                  <span :style="(() => {
                          const hrs = (Date.now() - new Date($store.genesisDashboard.cognitiveState.active_context.created_at).getTime()) / 3600000;
                          return hrs > 24 ? 'color:#d9534f; font-weight:600; text-transform:none'
                               : hrs > 4  ? 'color:#f0ad4e; font-weight:600; text-transform:none'
                               : 'font-weight:400; opacity:0.6; text-transform:none';
                        })()"
                        x-text="(() => {
                          const hrs = (Date.now() - new Date($store.genesisDashboard.cognitiveState.active_context.created_at).getTime()) / 3600000;
                          const ts = new Date($store.genesisDashboard.cognitiveState.active_context.created_at).toLocaleString();
                          return hrs > 24 ? 'generated ' + ts + ' (stale — ' + Math.round(hrs) + 'h ago)'
                               : hrs > 4  ? 'generated ' + ts + ' (' + Math.round(hrs) + 'h ago)'
                               : 'generated ' + ts;
                        })()"></span>
                </div>
                <div style="font-size: 0.74rem; white-space: pre-wrap; max-height: 400px; overflow-y: auto; line-height: 1.5; color: var(--color-text-secondary);"
                     x-text="$store.genesisDashboard.cognitiveState.active_context.content"></div>
              </div>
            </template>
            <!-- Session Patches (since last reflection) -->
            <template x-if="($store.genesisDashboard.cognitiveState?.session_patches || []).length > 0">
              <div style="margin-top: 0.75rem; padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px;">
                <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.3rem;">
                  Recent Sessions
                  <span style="font-weight: 400; opacity: 0.6; text-transform: none;"
                        x-text="'(' + $store.genesisDashboard.cognitiveState.session_patches.length + ' since last reflection)'"></span>
                </div>
                <template x-for="p in $store.genesisDashboard.cognitiveState.session_patches.slice().reverse()" :key="p.session_id">
                  <div style="font-size: 0.74rem; padding: 0.2rem 0; border-bottom: 1px solid rgba(255,255,255,0.04); display: flex; justify-content: space-between; gap: 0.5rem;">
                    <span style="color: var(--color-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" x-text="p.topic || 'no topic'"></span>
                    <span style="opacity: 0.6; white-space: nowrap; font-size: 0.68rem;"
                          x-text="(p.message_count || 0) + ' msgs · ' + new Date(p.ended_at).toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'})"></span>
                  </div>
                </template>
              </div>
            </template>
          </div>
        </template>
      </div>
    </div>

    <!-- Panel: Essential Knowledge (Collapsible) [Tab: overview] -->
    <div class="panel" x-data="{ ekOpen: false }" x-show="$store.genesisDashboard.activeTab === 'overview'">
      <div class="panel-header" style="cursor: pointer;" @click="ekOpen = !ekOpen">
        <span class="material-symbols-outlined" :style="ekOpen ? 'transform: rotate(90deg)' : ''" style="transition: transform 0.2s">chevron_right</span>
        <span class="material-symbols-outlined">auto_stories</span>
        Essential Knowledge
        <span class="panel-status">
          <template x-if="$store.genesisDashboard.essentialKnowledge?.updated_at">
            <span style="font-size: 0.68rem; opacity: 0.7;"
                  x-text="(() => {
                    const s = Math.round((Date.now() - new Date($store.genesisDashboard.essentialKnowledge.updated_at).getTime()) / 60000);
                    if (s < 60) return s + 'm ago';
                    if (s < 1440) return Math.round(s/60) + 'h ago';
                    return Math.round(s/1440) + 'd ago';
                  })()"></span>
          </template>
        </span>
      </div>
      <div class="panel-body" x-show="ekOpen" x-transition>
        <template x-if="!$store.genesisDashboard.essentialKnowledge?.content">
          <div class="empty-state" x-text="$store.genesisDashboard.essentialKnowledge?.error || 'Essential knowledge not loaded yet.'"></div>
        </template>
        <template x-if="$store.genesisDashboard.essentialKnowledge?.content">
          <div style="font-size: 0.76rem; white-space: pre-wrap; color: var(--color-text-secondary); max-height: 400px; overflow-y: auto;"
               x-text="$store.genesisDashboard.essentialKnowledge.content"></div>
        </template>
      </div>
    </div>

    <!-- Approval Queue moved to Chat tab → Approvals sub-tab -->

    <!-- Panel: Awareness Signals (Collapsible) [Tab: internals] -->
    <div class="panel" x-data="{ sigOpen: true }" x-show="$store.genesisDashboard.activeTab === 'internals'">
      <div class="panel-header" style="cursor: pointer;" @click="sigOpen = !sigOpen">
        <span class="material-symbols-outlined" :style="sigOpen ? 'transform: rotate(90deg)' : ''" style="transition: transform 0.2s">chevron_right</span>
        <span class="material-symbols-outlined">sensors</span>
        Awareness Signals
        <span class="panel-status">
          <template x-if="$store.genesisDashboard.awarenessSignals?.latest">
            <span style="font-size: 0.68rem; opacity: 0.7;"
                  x-text="(() => { const t = $store.genesisDashboard.awarenessSignals.latest; const d = t.classified_depth; const ago = Math.round((Date.now() - new Date(t.created_at).getTime()) / 60000); return (d ? d : 'idle') + ' · ' + ago + 'm ago'; })()"></span>
          </template>
          <span class="status-dot" :style="`background:${$store.genesisDashboard.panelStateColor('awarenessSignals')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('awarenessSignals')"></span>
        </span>
      </div>
      <div class="panel-body" x-show="sigOpen" x-transition>
        <template x-if="$store.genesisDashboard.panelStatusDetail('awarenessSignals')">
          <div class="panel-status-detail" x-text="$store.genesisDashboard.panelStatusDetail('awarenessSignals')"></div>
        </template>
        <template x-if="!$store.genesisDashboard.awarenessSignals?.latest">
          <div class="empty-state">No awareness ticks recorded.</div>
        </template>
        <template x-if="$store.genesisDashboard.awarenessSignals?.latest">
          <div>
            <!-- Depth Scores -->
            <div style="margin-bottom: 0.75rem; padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px;">
              <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.4rem;">Depth Scores</div>
              <template x-for="score in $store.genesisDashboard.awarenessSignals.latest.scores" :key="score.depth">
                <div style="display: flex; align-items: center; gap: 0.5rem; margin: 0.2rem 0; font-size: 0.76rem;">
                  <span style="width: 60px; font-weight: 600;" x-text="score.depth"></span>
                  <div style="flex: 1; height: 8px; background: rgba(255,255,255,0.08); border-radius: 4px; overflow: hidden;">
                    <div :style="`width: ${Math.min(score.final_score * 100 / Math.max(score.threshold, 0.01), 100)}%; height: 100%; border-radius: 4px; background: ${score.triggered ? '#4caf50' : score.final_score > score.threshold * 0.7 ? '#f0ad4e' : '#888'};`"></div>
                  </div>
                  <span style="width: 70px; font-size: 0.68rem; text-align: right;"
                        x-text="score.final_score.toFixed(2) + '/' + score.threshold.toFixed(2)"></span>
                  <template x-if="score.triggered">
                    <span style="font-size: 0.62rem; color: #4caf50; font-weight: 600;">TRIGGERED</span>
                  </template>
                </div>
              </template>
            </div>
            <!-- Signal Values -->
            <div style="padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px; margin-bottom: 0.75rem;">
              <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.4rem;">Signal Values</div>
              <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 0.2rem;">
                <template x-for="sig in $store.genesisDashboard.awarenessSignals.latest.signals" :key="sig.name">
                  <div style="display: flex; align-items: center; gap: 0.4rem; font-size: 0.72rem;">
                    <span style="width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" :title="sig.name" x-text="sig.name.replace(/_/g, ' ')"></span>
                    <div style="flex: 1; height: 6px; background: rgba(255,255,255,0.08); border-radius: 3px; overflow: hidden; min-width: 40px;">
                      <div :style="`width: ${Math.min(sig.value * 100, 100)}%; height: 100%; border-radius: 3px; background: ${sig.value > 0.7 ? '#d9534f' : sig.value > 0.3 ? '#f0ad4e' : '#4caf50'};`"></div>
                    </div>
                    <span style="width: 32px; text-align: right; font-family: monospace; font-size: 0.68rem;" x-text="sig.value.toFixed(2)"></span>
                  </div>
                </template>
              </div>
            </div>
            <!-- Tick History -->
            <div style="padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px;">
              <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.3rem;">Recent Ticks</div>
              <div style="display: flex; gap: 0.3rem; flex-wrap: wrap;">
                <template x-for="tick in $store.genesisDashboard.awarenessSignals.history" :key="tick.id">
                  <div :style="`padding: 0.15rem 0.4rem; border-radius: 3px; font-size: 0.62rem; font-family: monospace; background: ${tick.classified_depth ? (tick.classified_depth === 'Deep' ? 'rgba(217,83,79,0.2)' : tick.classified_depth === 'Light' ? 'rgba(240,173,78,0.2)' : tick.classified_depth === 'Micro' ? 'rgba(76,175,80,0.2)' : 'rgba(156,39,176,0.2)') : 'rgba(255,255,255,0.05)'};`"
                       :title="tick.created_at + (tick.trigger_reason ? ' — ' + tick.trigger_reason : '')"
                       x-text="new Date(tick.created_at).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'}) + (tick.classified_depth ? ' ' + tick.classified_depth.charAt(0) : '')"></div>
                </template>
              </div>
            </div>
          </div>
        </template>
      </div>
    </div>

    <!-- Panel: Routing Health (Collapsible) [Tab: internals] -->
    <div class="panel" id="routing-health" x-data="{ routingOpen: true }" x-show="$store.genesisDashboard.activeTab === 'internals'">
      <div class="panel-header" style="cursor: pointer;" @click="routingOpen = !routingOpen">
        <span class="material-symbols-outlined" :style="routingOpen ? 'transform: rotate(90deg)' : ''" style="transition: transform 0.2s">chevron_right</span>
        <span class="material-symbols-outlined">route</span>
        Routing Health
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.panelStateColor('routing')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('routing')"></span>
        </span>
        <template x-if="$store.genesisDashboard.health.call_sites">
          <span style="margin-left: auto; font-size: 0.75rem; font-weight: 400; opacity: 0.7"
                x-text="(() => {
                  const sites = $store.genesisDashboard.health.call_sites;
                  const routing = Object.entries(sites).filter(([, s]) => s.routing !== false);
                  const total = routing.length;
                  const healthy = routing.filter(([, s]) => s.status === 'healthy' || s.status === 'active').length;
                  const down = routing.filter(([, s]) => s.status === 'down').length;
                  const warning = routing.filter(([, s]) => s.status === 'warning').length;
                  const degraded = routing.filter(([, s]) => s.status === 'degraded').length;
                  const parts = [];
                  if (down > 0) parts.push(down + ' down');
                  if (warning > 0) parts.push(warning + ' warning');
                  if (degraded > 0) parts.push(degraded + ' degraded');
                  if (parts.length) return parts.join(', ') + ' / ' + total + ' configured';
                  return healthy + '/' + total + ' call sites healthy';
                })()"></span>
        </template>
      </div>
      <div class="panel-body" x-show="routingOpen" x-transition>
        <template x-if="$store.genesisDashboard.statusReason('routing', $store.genesisDashboard.routingSemantic())">
          <div class="inline-warning" x-text="$store.genesisDashboard.statusReason('routing', $store.genesisDashboard.routingSemantic())"></div>
        </template>
        <div style="display:flex; gap:0.5rem; flex-wrap:wrap; align-items:center; margin-bottom:0.75rem;">
          <button type="button"
                  style="font-size:0.74rem; padding:0.3rem 0.55rem; border-radius:4px; border:1px solid rgba(33,150,243,0.28); color:#2196F3; background:transparent; cursor:pointer;"
                  :disabled="$store.genesisDashboard.routingEditor.reloading"
                  @click="$store.genesisDashboard.reloadRoutingConfig()"
                  x-text="$store.genesisDashboard.routingEditor.reloading ? 'Reloading...' : 'Reload routing config'"></button>
          <template x-if="$store.genesisDashboard.routingEditor.reloadMessage">
            <span style="font-size:0.72rem; color:#4caf50;" x-text="$store.genesisDashboard.routingEditor.reloadMessage"></span>
          </template>
          <template x-if="$store.genesisDashboard.routingEditor.reloadError">
            <span style="font-size:0.72rem; color:#d9534f;" x-text="$store.genesisDashboard.routingEditor.reloadError"></span>
          </template>
        </div>
        <template x-if="$store.genesisDashboard.routingConfig?.call_sites">
          <div style="display:flex; gap:0.75rem; flex-wrap:wrap; margin-bottom:0.8rem; font-size:0.76rem;">
            <div style="padding:0.35rem 0.6rem; border-radius:6px; background:rgba(255,255,255,0.04); border:1px solid var(--color-border);">
              <span style="font-weight:600;" x-text="Object.keys($store.genesisDashboard.routingConfig.call_sites || {}).length"></span> configured call sites
            </div>
            <div style="padding:0.35rem 0.6rem; border-radius:6px; background:rgba(240,173,78,0.08); border:1px solid rgba(240,173,78,0.18); color:#f0ad4e;">
              <span style="font-weight:600;" x-text="$store.genesisDashboard.fallbackCallSiteCount"></span> on fallback
            </div>
            <div style="padding:0.35rem 0.6rem; border-radius:6px; background:rgba(76,175,80,0.08); border:1px solid rgba(76,175,80,0.18); color:#4caf50;">
              <span style="font-weight:600;" x-text="Object.values($store.genesisDashboard.routingConfig.providers || {}).filter(p => p.free).length"></span> free providers
            </div>
          </div>
          <!-- Model provider toggles -->
          <div style="display:flex; gap:0.4rem; flex-wrap:wrap; margin-bottom:0.8rem;">
            <template x-for="(prov, provName) in ($store.genesisDashboard.routingConfig.providers || {})" :key="provName">
              <div style="display:flex; align-items:center; gap:0.35rem; padding:0.25rem 0.5rem; border-radius:5px; background:rgba(255,255,255,0.04); border:1px solid var(--color-border); font-size:0.72rem;">
                <span class="status-dot"
                      :style="`background: ${($store.genesisDashboard.routingConfig.cb_states || {})[provName] === 'OPEN' ? '#d9534f' : '#4caf50'}`"></span>
                <span style="font-weight:500; color:#e0e0e0;" x-text="provName"></span>
                <span style="color:#666; font-size:0.65rem;" x-text="prov.model"></span>
                <button @click.stop="$store.genesisDashboard.toggleProvider(provName)"
                        style="font-size:0.62rem; padding:1px 6px; border-radius:3px; cursor:pointer; border:1px solid; font-weight:500; margin-left:0.25rem;"
                        :style="($store.genesisDashboard.routingConfig.cb_states || {})[provName] !== 'OPEN'
                          ? 'background:transparent; color:#ef9a9a; border-color:#ef9a9a;'
                          : 'background:transparent; color:#81c784; border-color:#81c784;'"
                        x-text="($store.genesisDashboard.routingConfig.cb_states || {})[provName] !== 'OPEN' ? 'disable' : 'enable'"></button>
              </div>
            </template>
          </div>
        </template>
        <template x-if="$store.genesisDashboard.health.call_sites">
          <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.5rem;">
            <template x-for="(site, siteId) in $store.genesisDashboard.health.call_sites" :key="siteId">
              <div style="background: var(--color-background); border: 1px solid var(--color-border); border-radius: 6px; padding: 0.5rem 0.75rem; font-size: 0.78rem;">
                <div style="display: flex; align-items: center; justify-content:space-between; gap: 0.4rem; margin-bottom: 0.25rem;">
                  <div style="display:flex; align-items:center; gap:0.4rem;">
                    <span class="status-dot" :style="`background: ${$store.genesisDashboard.probeStatusColor(site)}`"></span>
                    <span style="font-weight: 600" x-text="siteId"></span>
                  </div>
                  <button type="button"
                          style="font-size:0.68rem; padding:0.2rem 0.42rem; border-radius:4px; border:1px solid rgba(33,150,243,0.24); color:#2196F3; background:transparent; cursor:pointer;"
                          @click="$store.genesisDashboard.openRoutingEditor(siteId)"
                          x-text="$store.genesisDashboard.routingEditor.siteId === siteId ? 'Editing' : 'Edit'"></button>
                </div>
                <div style="color: var(--color-text-secondary); font-size: 0.72rem; margin-bottom: 0.2rem;"
                     x-text="site.description || ''"></div>
                <div style="font-size: 0.72rem;">
                  Active: <span x-text="site.active_provider || '—'" :style="`color: ${site.active_provider === site.chain_health?.[0]?.provider ? '#4caf50' : '#f0ad4e'}`"></span>
                </div>
                <template x-if="site.recent_failures">
                  <div style="font-size:0.68rem; margin-top:0.15rem; color:#f0ad4e;"
                       :title="site.last_failure_at ? 'Last failure: ' + new Date(site.last_failure_at).toLocaleString() : ''"
                       x-text="site.recent_failures + ' failures in last 30m'"></div>
                </template>
                <template x-if="site.recent_exhaustions && !site.recent_failures">
                  <div style="font-size:0.68rem; margin-top:0.15rem; color:#f0ad4e;"
                       x-text="site.recent_exhaustions + ' recent exhaustions'"></div>
                </template>
                <template x-if="$store.genesisDashboard.routingConfig?.call_sites?.[siteId]">
                  <div style="display:flex; gap:0.25rem; flex-wrap:wrap; margin-top:0.25rem;">
                    <template x-if="$store.genesisDashboard.routingConfig.call_sites[siteId].default_paid">
                      <span style="font-size:0.65rem; padding:0.08rem 0.32rem; border-radius:3px; background:rgba(240,173,78,0.16); color:#f0ad4e;">default paid</span>
                    </template>
                    <template x-if="$store.genesisDashboard.routingConfig.call_sites[siteId].never_pays">
                      <span style="font-size:0.65rem; padding:0.08rem 0.32rem; border-radius:3px; background:rgba(76,175,80,0.16); color:#4caf50;">never pays</span>
                    </template>
                    <template x-if="$store.genesisDashboard.routingConfig.call_sites[siteId].retry_profile">
                      <span style="font-size:0.65rem; padding:0.08rem 0.32rem; border-radius:3px; background:rgba(255,255,255,0.07); color:var(--color-text-secondary);" x-text="$store.genesisDashboard.routingConfig.call_sites[siteId].retry_profile"></span>
                    </template>
                    <template x-if="site.parallelized">
                      <span style="font-size:0.65rem; padding:0.08rem 0.32rem; border-radius:3px; background:rgba(156,39,176,0.16); color:#9c27ac;">parallelized</span>
                    </template>
                  </div>
                </template>
                <template x-if="site.chain_health">
                  <div style="font-size: 0.68rem; margin-top: 0.2rem; color: var(--color-text-secondary);">
                    Chain:
                    <template x-for="(ch, ci) in site.chain_health" :key="ci">
                      <span>
                        <span :style="`color: ${ch.state === 'open' ? '#d9534f' : ch.failures > 0 ? '#f0ad4e' : '#4caf50'}`"
                              x-text="ch.provider"></span>
                        <span style="opacity:0.55;" x-text="' (' + ch.state + (ch.failures > 0 ? ', ' + ch.failures + ' fail' + (ch.failures === 1 ? '' : 's') : '') + ')'"></span><span x-show="ci < site.chain_health.length - 1"> → </span>
                      </span>
                    </template>
                  </div>
                </template>
                <template x-if="$store.genesisDashboard.routingEditor.siteId === siteId">
                  <div style="margin-top:0.5rem; padding-top:0.5rem; border-top:1px solid rgba(255,255,255,0.06);">
                    <div style="font-size:0.68rem; color:var(--color-text-secondary); margin-bottom:0.25rem;">Edit provider chain as a comma-separated list.</div>
                    <label style="display:block; font-size:0.68rem; color:var(--color-text-secondary); margin-bottom:0.15rem;">Chain</label>
                    <input type="text"
                           x-model="$store.genesisDashboard.routingEditor.chainText"
                           style="width:100%; box-sizing:border-box; font-size:0.72rem; padding:0.36rem 0.45rem; border-radius:4px; border:1px solid var(--color-border); background:rgba(255,255,255,0.03); color:var(--color-text-primary);">
                    <div style="font-size:0.64rem; color:var(--color-text-secondary); margin-top:0.2rem;"
                         x-text="'Available providers: ' + $store.genesisDashboard.routingProviderList.join(', ')"></div>
                    <label style="display:flex; gap:0.35rem; align-items:center; font-size:0.68rem; margin-top:0.4rem;">
                      <input type="checkbox" x-model="$store.genesisDashboard.routingEditor.default_paid">
                      <span>Default paid</span>
                    </label>
                    <label style="display:flex; gap:0.35rem; align-items:center; font-size:0.68rem; margin-top:0.2rem;">
                      <input type="checkbox" x-model="$store.genesisDashboard.routingEditor.never_pays">
                      <span>Never pays</span>
                    </label>
                    <div style="display:flex; gap:0.4rem; flex-wrap:wrap; margin-top:0.5rem;">
                      <button type="button"
                              style="font-size:0.68rem; padding:0.24rem 0.48rem; border-radius:4px; border:1px solid rgba(33,150,243,0.24); color:#2196F3; background:transparent; cursor:pointer;"
                              :disabled="$store.genesisDashboard.routingEditor.saving"
                              @click="$store.genesisDashboard.saveRoutingEditor()"
                              x-text="$store.genesisDashboard.routingEditor.saving ? 'Saving...' : 'Save route'"></button>
                      <button type="button"
                              style="font-size:0.68rem; padding:0.24rem 0.48rem; border-radius:4px; border:1px solid var(--color-border); color:var(--color-text-secondary); background:transparent; cursor:pointer;"
                              @click="$store.genesisDashboard.closeRoutingEditor()">Close</button>
                    </div>
                    <template x-if="$store.genesisDashboard.routingEditor.message">
                      <div style="font-size:0.68rem; color:#4caf50; margin-top:0.35rem;" x-text="$store.genesisDashboard.routingEditor.message"></div>
                    </template>
                    <template x-if="$store.genesisDashboard.routingEditor.error">
                      <div style="font-size:0.68rem; color:#d9534f; margin-top:0.35rem;" x-text="$store.genesisDashboard.routingEditor.error"></div>
                    </template>
                  </div>
                </template>
              </div>
            </template>
          </div>
        </template>
        <template x-if="!$store.genesisDashboard.health.call_sites || Object.keys($store.genesisDashboard.health.call_sites).length === 0">
          <div class="empty-state">No call site data available.</div>
        </template>
      </div>
    </div>

    <!-- Panel: Job Health (Collapsible) [Tab: internals] -->
    <div class="panel" x-data="{ jobsOpen: true }" x-show="$store.genesisDashboard.activeTab === 'internals'">
      <div class="panel-header" style="cursor: pointer;" @click="jobsOpen = !jobsOpen">
        <span class="material-symbols-outlined" :style="jobsOpen ? 'transform: rotate(90deg)' : ''" style="transition: transform 0.2s">chevron_right</span>
        <span class="material-symbols-outlined">schedule</span>
        Job Health
        <span class="panel-status">
          <template x-if="$store.genesisDashboard.jobHealth?.jobs">
            <span style="font-size: 0.68rem; opacity: 0.7;"
                  x-text="(() => { const j = $store.genesisDashboard.jobHealth.jobs; const f = j.filter(x => x.consecutive_failures > 0).length; return f > 0 ? f + ' failing' : j.length + ' jobs healthy'; })()"></span>
          </template>
          <template x-if="$store.genesisDashboard.jobHealth?.observations">
            <span style="font-size: 0.68rem; opacity: 0.5; margin-left: 0.3rem;"
                  x-text="'obs: ' + $store.genesisDashboard.jobHealth.observations.total"></span>
          </template>
          <span class="status-dot" :style="`background:${$store.genesisDashboard.panelStateColor('jobHealth')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('jobHealth')"></span>
        </span>
      </div>
      <div class="panel-body" x-show="jobsOpen" x-transition>
        <template x-if="$store.genesisDashboard.panelStatusDetail('jobHealth')">
          <div class="panel-status-detail" x-text="$store.genesisDashboard.panelStatusDetail('jobHealth')"></div>
        </template>
        <template x-if="!$store.genesisDashboard.jobHealth?.jobs?.length">
          <div class="empty-state">No scheduled jobs.</div>
        </template>
        <template x-if="$store.genesisDashboard.jobHealth?.jobs?.length > 0">
          <div>
            <!-- Observation Stats -->
            <template x-if="$store.genesisDashboard.jobHealth?.observations">
              <div style="margin-bottom: 0.75rem; padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px; background: rgba(76,175,80,0.04);">
                <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.3rem;">Observation Pipeline</div>
                <div style="display: flex; gap: 1rem; font-size: 0.76rem; flex-wrap: wrap;">
                  <span>Total: <strong x-text="$store.genesisDashboard.jobHealth.observations.total"></strong></span>
                  <span>24h: <strong x-text="$store.genesisDashboard.jobHealth.observations.created_24h"></strong></span>
                  <span>Retrieved: <strong x-text="$store.genesisDashboard.jobHealth.observations.total_retrieved"
                        :style="$store.genesisDashboard.jobHealth.observations.total_retrieved === 0 && $store.genesisDashboard.jobHealth.observations.total > 0 ? 'color: #d9534f' : 'color: #4caf50'"></strong></span>
                  <span>Influenced: <strong x-text="$store.genesisDashboard.jobHealth.observations.total_influenced"></strong></span>
                </div>
              </div>
            </template>
            <!-- Job Table -->
            <div style="overflow-x: auto;">
              <table style="width: 100%; border-collapse: collapse; font-size: 0.72rem;">
                <thead>
                  <tr style="border-bottom: 1px solid var(--color-border); text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.65rem;">
                    <th style="text-align: left; padding: 0.3rem 0.4rem;">Job</th>
                    <th style="text-align: right; padding: 0.3rem 0.4rem;">Runs</th>
                    <th style="text-align: right; padding: 0.3rem 0.4rem;">Fails</th>
                    <th style="text-align: right; padding: 0.3rem 0.4rem;">Streak</th>
                    <th style="text-align: right; padding: 0.3rem 0.4rem;">Last Run</th>
                  </tr>
                </thead>
                <tbody>
                  <template x-for="job in $store.genesisDashboard.jobHealth.jobs" :key="job.job_name">
                    <tr :style="job.consecutive_failures > 0 ? 'background: rgba(217,83,79,0.08)' : ''"
                        style="border-bottom: 1px solid rgba(255,255,255,0.04);">
                      <td style="padding: 0.25rem 0.4rem;">
                        <span class="status-dot" :style="`background: ${job.consecutive_failures > 0 ? '#d9534f' : '#4caf50'}`"></span>
                        <span x-text="job.job_name" style="margin-left: 0.3rem;"></span>
                      </td>
                      <td style="text-align: right; padding: 0.25rem 0.4rem;" x-text="job.total_runs"></td>
                      <td style="text-align: right; padding: 0.25rem 0.4rem;"
                          :style="job.total_failures > 0 ? 'color: #f0ad4e' : ''"
                          x-text="job.total_failures"></td>
                      <td style="text-align: right; padding: 0.25rem 0.4rem;"
                          :style="job.consecutive_failures > 0 ? 'color: #d9534f; font-weight: 700' : ''"
                          x-text="job.consecutive_failures"></td>
                      <td style="text-align: right; padding: 0.25rem 0.4rem; font-family: monospace; font-size: 0.65rem;"
                          x-text="job.last_run ? new Date(job.last_run).toLocaleString([], {month:'short',day:'numeric',hour:'2-digit',minute:'2-digit'}) : '—'"></td>
                    </tr>
                  </template>
                </tbody>
              </table>
            </div>
          </div>
        </template>
      </div>
    </div>

    <!-- Panel: Eval Metrics (Compounding Intelligence) [Tab: internals] -->
    <div class="panel" x-data="{ evalOpen: true }" x-show="$store.genesisDashboard.activeTab === 'internals'">
      <div class="panel-header" style="cursor: pointer;" @click="evalOpen = !evalOpen">
        <span class="material-symbols-outlined" :style="evalOpen ? 'transform: rotate(90deg)' : ''" style="transition: transform 0.2s">chevron_right</span>
        <span class="material-symbols-outlined">insights</span>
        Eval Metrics (J-9)
        <span class="panel-status">
          <template x-if="$store.genesisDashboard.evalMetrics?.dimensions">
            <span style="font-size: 0.68rem; opacity: 0.7;"
                  x-text="(() => { const d = $store.genesisDashboard.evalMetrics.dimensions; const vals = Object.values(d).map(x => x.weeks_of_data || 0); const weeks = vals.length ? Math.max(...vals) : 0; return weeks + ' weeks of data'; })()"></span>
          </template>
        </span>
      </div>
      <div class="panel-body" x-show="evalOpen" x-transition>
        <template x-if="!$store.genesisDashboard.evalMetrics?.dimensions">
          <div class="empty-state">No eval data yet. Aggregation runs Sundays 05:00 UTC.</div>
        </template>
        <template x-if="$store.genesisDashboard.evalMetrics?.dimensions">
          <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.6rem;">
            <template x-for="[dim, data] in Object.entries($store.genesisDashboard.evalMetrics.dimensions)" :key="dim">
              <div style="border: 1px solid var(--color-border); border-radius: 6px; padding: 0.5rem 0.6rem;">
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.3rem;">
                  <span style="font-size: 0.72rem; font-weight: 600; text-transform: capitalize;" x-text="dim"></span>
                  <span style="font-size: 0.65rem; opacity: 0.6;" x-text="data.headline_metric"></span>
                </div>
                <div style="display: flex; align-items: baseline; gap: 0.4rem;">
                  <span style="font-size: 1.1rem; font-weight: 700;"
                        x-text="data.current_value !== null ? (data.headline_metric === 'delta' ? (data.current_value >= 0 ? '+' : '') : '') + (data.current_value * 100).toFixed(1) + '%' : '—'"></span>
                  <span style="font-size: 0.7rem;"
                        :style="data.trend === 'up' ? 'color: #4caf50' : data.trend === 'down' ? 'color: #d9534f' : 'color: #888'"
                        x-text="data.trend === 'up' ? '\u2191' : data.trend === 'down' ? '\u2193' : data.trend === 'flat' ? '\u2192' : '\u2026'"></span>
                </div>
                <!-- Sparkline: CSS bar chart (min-max normalized per series) -->
                <div style="display: flex; align-items: flex-end; gap: 1px; height: 24px; margin-top: 0.3rem;">
                  <template x-for="(pt, i) in data.series" :key="i">
                    <div :style="(() => {
                      const color = data.trend === 'up' ? 'rgba(76,175,80,0.5)' : data.trend === 'down' ? 'rgba(217,83,79,0.5)' : 'rgba(136,136,136,0.4)';
                      if (pt.value === null) return `flex:1; background:${color}; border-radius:1px; height:2px;`;
                      const vals = data.series.filter(p => p.value !== null).map(p => p.value);
                      const mn = Math.min(...vals), mx = Math.max(...vals);
                      const pct = mx > mn ? ((pt.value - mn) / (mx - mn)) * 90 + 10 : 50;
                      return `flex:1; background:${color}; border-radius:1px; height:${pct}%;`;
                    })()"></div>
                  </template>
                </div>
                <div style="font-size: 0.62rem; opacity: 0.5; margin-top: 0.2rem;" x-text="data.weeks_of_data + ' weeks'"></div>
              </div>
            </template>
          </div>
        </template>
      </div>
    </div>

    <!-- Panel: Drives & Thresholds (Collapsible) [Tab: internals] -->
    <div class="panel" x-data="{ drivesOpen: true }" x-show="$store.genesisDashboard.activeTab === 'internals'">
      <div class="panel-header" style="cursor: pointer;" @click="drivesOpen = !drivesOpen">
        <span class="material-symbols-outlined" :style="drivesOpen ? 'transform: rotate(90deg)' : ''" style="transition: transform 0.2s">chevron_right</span>
        <span class="material-symbols-outlined">tune</span>
        Drives & Thresholds
        <span class="panel-status">
          <template x-if="$store.genesisDashboard.autonomyConfig?.drives?.length">
            <span style="font-size: 0.68rem; opacity: 0.7;"
                  x-text="$store.genesisDashboard.autonomyConfig.drives.length + ' drives · ' + ($store.genesisDashboard.autonomyConfig.thresholds?.length || 0) + ' thresholds'"></span>
          </template>
          <span class="status-dot" :style="`background:${$store.genesisDashboard.panelStateColor('autonomyConfig')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('autonomyConfig')"></span>
        </span>
      </div>
      <div class="panel-body" x-show="drivesOpen" x-transition>
        <template x-if="$store.genesisDashboard.panelStatusDetail('autonomyConfig')">
          <div class="panel-status-detail" x-text="$store.genesisDashboard.panelStatusDetail('autonomyConfig')"></div>
        </template>
        <template x-if="!$store.genesisDashboard.autonomyConfig?.drives?.length">
          <div class="empty-state">No drives configured.</div>
        </template>
        <template x-if="$store.genesisDashboard.autonomyConfig?.drives?.length > 0">
          <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem;">
            <!-- Drive Weights -->
            <div style="padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px;">
              <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.4rem;">Drive Weights</div>
              <template x-for="d in $store.genesisDashboard.autonomyConfig.drives" :key="d.drive_name">
                <div style="display: flex; align-items: center; gap: 0.4rem; margin: 0.3rem 0; font-size: 0.76rem;">
                  <span style="width: 90px; text-transform: capitalize;" x-text="d.drive_name"></span>
                  <div style="flex: 1; height: 8px; background: rgba(255,255,255,0.08); border-radius: 4px; overflow: hidden;">
                    <div :style="`width: ${d.current_weight * 100}%; height: 100%; border-radius: 4px; background: ${d.drive_name === 'preservation' ? '#2196F3' : d.drive_name === 'curiosity' ? '#9c27b0' : d.drive_name === 'cooperation' ? '#4caf50' : '#ff9800'};`"></div>
                  </div>
                  <span style="width: 32px; text-align: right; font-family: monospace; font-size: 0.68rem;" x-text="d.current_weight.toFixed(2)"></span>
                </div>
              </template>
            </div>
            <!-- Depth Thresholds -->
            <div style="padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 6px;">
              <div style="font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.4rem;">Depth Thresholds</div>
              <template x-for="t in $store.genesisDashboard.autonomyConfig.thresholds" :key="t.depth_name">
                <div style="display: flex; align-items: center; gap: 0.4rem; margin: 0.3rem 0; font-size: 0.76rem;">
                  <span style="width: 65px; font-weight: 600;" x-text="t.depth_name"></span>
                  <span style="font-family: monospace; font-size: 0.72rem;" x-text="'≥ ' + t.threshold.toFixed(2)"></span>
                  <span style="opacity: 0.5; font-size: 0.65rem; margin-left: auto;"
                        x-text="(() => { const s = t.floor_seconds; return s >= 86400 ? Math.round(s/86400) + 'd' : s >= 3600 ? Math.round(s/3600) + 'h' : Math.round(s/60) + 'm'; })() + ' floor'"></span>
                </div>
              </template>
            </div>
          </div>
        </template>
      </div>
    </div>


    <!-- Panel: CC Sessions [Tab: sessions] -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'internals'">
      <div class="panel-header">
        <span class="material-symbols-outlined">terminal</span>
        CC Sessions
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.panelStateColor('sessions')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('sessions')"></span>
        </span>
      </div>
      <div class="panel-body">
        <template x-if="$store.genesisDashboard.panelStatusDetail('sessions')">
          <div class="panel-status-detail" x-text="$store.genesisDashboard.panelStatusDetail('sessions')"></div>
        </template>
        <div class="activity-filters">
          <select x-model="$store.genesisDashboard.sessionFilters.status"
                  @change="$store.genesisDashboard.fetchSessions()">
            <option value="">All statuses</option>
            <option value="active">Active</option>
            <option value="completed">Completed</option>
            <option value="failed">Failed</option>
            <option value="expired">Expired</option>
          </select>
          <select x-model="$store.genesisDashboard.sessionFilters.sessionType"
                  @change="$store.genesisDashboard.fetchSessions()">
            <option value="">All types</option>
            <option value="foreground">Foreground</option>
            <option value="background_reflection">Reflection</option>
            <option value="background_task">Task</option>
          </select>
        </div>
        <div class="activity-feed" style="max-height: 300px;">
          <template x-if="$store.genesisDashboard.sessions.length === 0">
            <div class="empty-state">No sessions found.</div>
          </template>
          <template x-for="sess in $store.genesisDashboard.sessions" :key="sess.id">
            <div>
              <div class="activity-row" style="cursor:pointer;"
                   @click="$store.genesisDashboard.toggleSession(sess.id)">
                <span class="activity-time"
                      x-text="$store.genesisDashboard.formatTime(sess.started_at)"></span>
                <span class="activity-subsystem"
                      :style="`color: ${$store.genesisDashboard.sessionStatusColor(sess.status)}`"
                      x-text="$store.genesisDashboard.sessionTypeLabel(sess.session_type)"></span>
                <span class="activity-type" x-text="sess.model"></span>
                <span class="activity-msg" style="color: #aaa;"
                      x-text="(sess.source_tag || sess.channel || '-') + ' | ' + sess.status"></span>
                <template x-if="sess.status === 'active' && sess.session_type === 'foreground' && sess.last_activity_at && (Date.now() - Date.parse(sess.last_activity_at)) > 7200000">
                  <span style="font-size: 0.62rem; padding: 0.08rem 0.3rem; border-radius: 3px; background: rgba(240,173,78,0.15); color: #f0ad4e; margin-left: 0.3rem;">stale</span>
                </template>
              </div>
              <template x-if="$store.genesisDashboard.expandedSession === sess.id">
                <div style="padding: 0.4rem 0.8rem; background: rgba(255,255,255,0.03); border-left: 2px solid #27875e; margin: 0.2rem 0 0.4rem 1rem; font-size: 0.75rem;">
                  <template x-if="$store.genesisDashboard.sessionEvents.length === 0">
                    <div style="color: #666;">No events recorded for this session.</div>
                  </template>
                  <template x-for="(evt, i) in $store.genesisDashboard.sessionEvents" :key="i">
                    <div class="activity-row">
                      <span class="activity-time"
                            x-text="$store.genesisDashboard.formatTime(evt.timestamp)"></span>
                      <span class="activity-type" x-text="evt.event_type"></span>
                      <span class="activity-msg"
                            :style="`color: ${$store.genesisDashboard.severityColor(evt.severity)}`"
                            x-text="evt.message"></span>
                    </div>
                  </template>
                </div>
              </template>
            </div>
          </template>
        </div>
      </div>
    </div>

    <!-- Panel: Activity Feed [Tab: sessions] -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'internals'">
      <div class="panel-header">
        <span class="material-symbols-outlined">timeline</span>
        Activity Feed
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.panelStateColor('activity')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('activity')"></span>
        </span>
      </div>
      <div class="panel-body">
        <template x-if="$store.genesisDashboard.panelStatusDetail('activity')">
          <div class="panel-status-detail" x-text="$store.genesisDashboard.panelStatusDetail('activity')"></div>
        </template>
        <div class="activity-filters">
          <select x-model="$store.genesisDashboard.activityTimeRange"
                  @change="$store.genesisDashboard.fetchActivity()">
            <option value="1h">Last 1h</option>
            <option value="6h">Last 6h</option>
            <option value="24h">Last 24h</option>
            <option value="7d">Last 7d</option>
          </select>
          <select x-model="$store.genesisDashboard.filters.subsystem"
                  @change="$store.genesisDashboard.fetchActivity()">
            <option value="">All subsystems</option>
            <template x-for="s in $store.genesisDashboard.subsystems.filter(x => x)" :key="s">
              <option :value="s" x-text="s"></option>
            </template>
          </select>
          <select x-model="$store.genesisDashboard.filters.minSeverity"
                  @change="$store.genesisDashboard.fetchActivity()">
            <option value="debug">Debug+</option>
            <option value="info">Info+</option>
            <option value="warning">Warning+</option>
            <option value="error">Error+</option>
          </select>
        </div>
        <div class="activity-feed">
          <template x-if="$store.genesisDashboard.activity.length === 0">
            <div class="empty-state">No events yet.</div>
          </template>
          <template x-for="(evt, i) in $store.genesisDashboard.activity" :key="i">
            <div class="activity-row">
              <span class="activity-time"
                    x-text="evt.timestamp ? new Date(evt.timestamp).toLocaleTimeString() : ''"></span>
              <span class="activity-subsystem" x-text="evt.subsystem"></span>
              <span class="activity-type" x-text="evt.event_type"></span>
              <span class="activity-msg"
                    :style="`color: ${$store.genesisDashboard.severityColor(evt.severity)}`"
                    x-text="evt.message"></span>
            </div>
          </template>
        </div>
      </div>
    </div>

    <!-- Panel: Operational Vitals (Collapsible) [Tab: internals] -->
    <div class="panel" x-data="{ vitalsOpen: true, llmOpen: true, embedOpen: true, qdOpen: false, sqlOpen: false, mcpOpen: false, onpremOpen: false }" x-show="$store.genesisDashboard.activeTab === 'internals'">
      <div class="panel-header" style="cursor: pointer;" @click="vitalsOpen = !vitalsOpen">
        <span class="material-symbols-outlined" :style="vitalsOpen ? 'transform: rotate(90deg)' : ''" style="transition: transform 0.2s">chevron_right</span>
        <span class="material-symbols-outlined">monitoring</span>
        Operational Vitals
        <span class="panel-status">
          <template x-if="$store.genesisDashboard.operationalVitals">
            <span style="font-size: 0.72rem; opacity: 0.7;"
                  x-text="(() => {
                    const v = $store.genesisDashboard.operationalVitals;
                    const llm = v?.llm?.totals || {};
                    const emb = v?.embedding || {};
                    const qd = v?.qdrant || {};
                    return (llm.calls_24h || 0) + ' LLM calls · ' + (emb.total_embeddings_24h || 0) + ' embed ops · ' + (qd.total_points || 0) + ' vectors · $' + (llm.cost_24h || 0).toFixed(2) + '/24h';
                  })()"></span>
          </template>
          <template x-if="!$store.genesisDashboard.operationalVitals">
            <span style="font-size: 0.72rem; opacity: 0.5;">loading...</span>
          </template>
        </span>
      </div>
      <div class="panel-body" x-show="vitalsOpen" x-transition>
        <template x-if="!$store.genesisDashboard.operationalVitals">
          <div style="font-size: 0.78rem; color: var(--color-text-secondary); padding: 0.5rem 0;">Loading operational vitals...</div>
        </template>
        <template x-if="$store.genesisDashboard.operationalVitals">
          <div x-data="{ v: $store.genesisDashboard.operationalVitals }">

            <!-- ── LLM Routing ── -->
            <div style="margin-bottom: 0.75rem; border: 1px solid var(--color-border); border-radius: 6px; overflow: hidden;">
              <div @click="llmOpen = !llmOpen" style="cursor: pointer; padding: 0.4rem 0.6rem; background: rgba(255,152,0,0.06); display: flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; font-weight: 600;">
                <span class="material-symbols-outlined" style="font-size: 14px;" :style="llmOpen ? 'transform:rotate(90deg)' : ''">chevron_right</span>
                LLM Routing
                <span style="margin-left: auto; font-weight: 400; opacity: 0.7; font-size: 0.7rem;"
                      x-text="(v.llm?.providers?.length || 0) + ' providers · ' + (v.llm?.totals?.calls_1h || 0) + ' calls/1h · $' + (v.llm?.totals?.cost_24h || 0).toFixed(2) + '/24h'"></span>
              </div>
              <div x-show="llmOpen" x-transition style="padding: 0.5rem 0.6rem; font-size: 0.74rem;">
                <template x-if="v.llm?.error">
                  <div style="color: #d9534f;" x-text="'LLM: ' + v.llm.error"></div>
                </template>
                <template x-if="!v.llm?.error">
                  <div>
                    <!-- Totals -->
                    <div style="display: flex; gap: 1rem; margin-bottom: 0.5rem; font-size: 0.72rem; flex-wrap: wrap;">
                      <span>1h: <b x-text="v.llm?.totals?.calls_1h || 0"></b> calls · $<b x-text="(v.llm?.totals?.cost_1h || 0).toFixed(4)"></b></span>
                      <span>24h: <b x-text="v.llm?.totals?.calls_24h || 0"></b> calls · $<b x-text="(v.llm?.totals?.cost_24h || 0).toFixed(4)"></b></span>
                    </div>
                    <!-- Per-provider full cards -->
                    <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 0.4rem;">
                      <template x-for="p in (v.llm?.providers || [])" :key="p.name">
                        <div style="padding: 0.4rem 0.55rem; border-radius: 5px; border: 1px solid var(--color-border);"
                             :style="p.calls_24h > 0 ? 'background: rgba(255,255,255,0.03)' : 'background: rgba(255,255,255,0.01); opacity: 0.5'">
                          <div style="display: flex; align-items: center; gap: 0.35rem; margin-bottom: 0.2rem;">
                            <span style="font-weight: 600; font-size: 0.74rem;" x-text="p.display_name"></span>
                            <span style="padding: 0.05rem 0.25rem; border-radius: 3px; font-size: 0.58rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.03em;"
                                  :style="({'openrouter':'background:rgba(139,92,246,0.15);color:#a78bfa','google':'background:rgba(66,133,244,0.15);color:#8ab4f8','mistral':'background:rgba(255,152,0,0.15);color:#ffb74d','anthropic':'background:rgba(217,119,87,0.15);color:#d9a98a','ollama':'background:rgba(76,175,80,0.15);color:#81c784','groq':'background:rgba(0,188,212,0.15);color:#4dd0e1','deepseek':'background:rgba(33,150,243,0.15);color:#64b5f6','xai':'background:rgba(255,255,255,0.1);color:#aaa','qwen':'background:rgba(255,193,7,0.15);color:#ffd54f','zenmux':'background:rgba(156,39,176,0.15);color:#ce93d8','minimax':'background:rgba(244,67,54,0.15);color:#ef9a9a'})[p.provider_type] || 'background:rgba(255,255,255,0.08);color:#888'"
                                  x-text="p.provider_type"></span>
                            <template x-if="p.intelligence_tier">
                              <span style="padding: 0.05rem 0.25rem; border-radius: 3px; font-size: 0.58rem; font-weight: 700; letter-spacing: 0.03em;"
                                    :style="({'S':'background:rgba(255,215,0,0.2);color:#ffd700','A':'background:rgba(139,92,246,0.15);color:#a78bfa','B':'background:rgba(33,150,243,0.12);color:#64b5f6','C':'background:rgba(255,255,255,0.08);color:#888'})[p.intelligence_tier] || 'background:rgba(255,255,255,0.08);color:#888'"
                                    x-text="p.intelligence_tier"></span>
                            </template>
                            <template x-if="p.free">
                              <span style="padding: 0.05rem 0.2rem; border-radius: 3px; font-size: 0.56rem; background: rgba(76,175,80,0.15); color: #81c784;">FREE</span>
                            </template>
                          </div>
                          <div style="font-size: 0.64rem; opacity: 0.6; font-family: monospace; margin-bottom: 0.2rem;" x-text="p.model_id"></div>
                          <template x-if="p.calls_24h > 0">
                            <div style="display: flex; gap: 0.6rem; font-size: 0.66rem; flex-wrap: wrap;">
                              <span><b x-text="p.calls_24h"></b> calls</span>
                              <span x-text="p.avg_latency_ms.toFixed(0) + 'ms'"></span>
                              <span :style="p.error_rate > 0.1 ? 'color: #d9534f' : ''" x-text="(p.error_rate * 100).toFixed(1) + '% err'"></span>
                              <template x-if="p.cost_24h > 0">
                                <span x-text="'$' + p.cost_24h.toFixed(4)"></span>
                              </template>
                            </div>
                          </template>
                          <div style="font-size: 0.6rem; opacity: 0.5; margin-top: 0.15rem;"
                               x-text="p.call_site_count > 0 ? p.call_site_count + ' call site(s): ' + p.call_sites.slice(0, 3).join(', ') + (p.call_sites.length > 3 ? '...' : '') : 'available (not assigned)'"></div>
                        </div>
                      </template>
                    </div>
                    <!-- Sessions -->
                    <template x-if="v.llm?.sessions">
                      <div style="margin-top: 0.5rem; font-size: 0.7rem; opacity: 0.8;">
                        CC Sessions: <b x-text="v.llm.sessions.fg_active"></b> fg · <b x-text="v.llm.sessions.bg_active"></b> bg active · <b x-text="v.llm.sessions.created_24h"></b> created 24h · $<b x-text="(v.llm.sessions.session_cost_24h || 0).toFixed(4)"></b> cost
                      </div>
                    </template>
                  </div>
                </template>
              </div>
            </div>

            <!-- ── Embedding Pipeline ── -->
            <div style="margin-bottom: 0.75rem; border: 1px solid var(--color-border); border-radius: 6px; overflow: hidden;">
              <div @click="embedOpen = !embedOpen" style="cursor: pointer; padding: 0.4rem 0.6rem; background: rgba(76,175,80,0.06); display: flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; font-weight: 600;">
                <span class="material-symbols-outlined" style="font-size: 14px;" :style="embedOpen ? 'transform:rotate(90deg)' : ''">chevron_right</span>
                Embedding Pipeline
                <span style="margin-left: auto; font-weight: 400; opacity: 0.7; font-size: 0.7rem;"
                      x-text="(v.embedding?.total_embeddings_24h || 0) + ' ops/24h · ' + (v.embedding?.backends?.length || 0) + ' backends'"></span>
              </div>
              <div x-show="embedOpen" x-transition style="padding: 0.5rem 0.6rem; font-size: 0.74rem;">
                <template x-if="v.embedding?.error">
                  <div style="color: #d9534f;" x-text="'Embedding: ' + v.embedding.error"></div>
                </template>
                <template x-if="!v.embedding?.error">
                  <div>
                    <!-- Model & dual chain info -->
                    <div style="display: flex; gap: 1rem; margin-bottom: 0.5rem; font-size: 0.7rem; flex-wrap: wrap;">
                      <span>Model: <b x-text="v.embedding?.active_model || '—'"></b></span>
                    </div>
                    <div style="display: flex; gap: 0.5rem; margin-bottom: 0.5rem; font-size: 0.68rem; flex-wrap: wrap;">
                      <span style="background: rgba(76,175,80,0.12); padding: 0.15rem 0.4rem; border-radius: 3px;">
                        Storage: <b x-text="(v.embedding?.storage_chain || []).join(' → ') || '—'"></b>
                      </span>
                      <span style="background: rgba(33,150,243,0.12); padding: 0.15rem 0.4rem; border-radius: 3px;">
                        Recall: <b x-text="(v.embedding?.recall_chain || []).join(' → ') || '—'"></b>
                      </span>
                    </div>
                    <!-- Per-backend stats -->
                    <template x-for="b in (v.embedding?.backends || [])" :key="b.name">
                      <div style="display: flex; justify-content: space-between; padding: 0.25rem 0; border-bottom: 1px solid rgba(255,255,255,0.04);">
                        <span style="font-weight: 600; font-size: 0.72rem;" x-text="b.name"></span>
                        <span style="opacity: 0.7; font-size: 0.68rem;">
                          <span x-text="b.calls_24h"></span> calls
                          · <span :style="b.avg_latency_ms > 5000 ? 'color:#d9534f; font-weight:600' : b.avg_latency_ms > 2000 ? 'color:#f0ad4e; font-weight:600' : ''" x-text="b.avg_latency_ms.toFixed(0) + 'ms'"></span>
                          · <span :style="b.error_rate > 0.1 ? 'color: #d9534f' : ''" x-text="(b.error_rate * 100).toFixed(1) + '% err'"></span>
                        </span>
                      </div>
                    </template>
                    <template x-if="(v.embedding?.backends || []).length === 0">
                      <div style="font-size: 0.7rem; opacity: 0.5;">No embedding activity in last 24h</div>
                    </template>
                  </div>
                </template>
              </div>
            </div>

            <!-- ── Vector Store (Qdrant) ── -->
            <div style="margin-bottom: 0.75rem; border: 1px solid var(--color-border); border-radius: 6px; overflow: hidden;">
              <div @click="qdOpen = !qdOpen" style="cursor: pointer; padding: 0.4rem 0.6rem; background: rgba(156,39,176,0.06); display: flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; font-weight: 600;">
                <span class="material-symbols-outlined" style="font-size: 14px;" :style="qdOpen ? 'transform:rotate(90deg)' : ''">chevron_right</span>
                Vector Store — Qdrant
                <span style="margin-left: auto; font-weight: 400; opacity: 0.7; font-size: 0.7rem;" x-text="(v.qdrant?.total_points || 0) + ' points · ' + (v.qdrant?.collections?.length || 0) + ' collections'"></span>
              </div>
              <div x-show="qdOpen" x-transition style="padding: 0.5rem 0.6rem; font-size: 0.74rem;">
                <template x-if="v.qdrant?.error">
                  <div style="color: #d9534f;" x-text="'Qdrant: ' + v.qdrant.error"></div>
                </template>
                <template x-if="!v.qdrant?.error">
                  <div>
                    <template x-for="c in (v.qdrant?.collections || [])" :key="c.name">
                      <div style="display: flex; justify-content: space-between; padding: 0.2rem 0; border-bottom: 1px solid rgba(255,255,255,0.04);">
                        <span style="font-weight: 600;" x-text="c.name"></span>
                        <span style="opacity: 0.7;">
                          <span x-text="(c.points || 0).toLocaleString()"></span> points
                          · dim <span x-text="c.dimension || '?'"></span>
                          · <span x-text="(c.indexed_vectors || 0) + ' indexed (threshold: ' + (c.full_scan_threshold || '?') + ')'"></span>
                        </span>
                      </div>
                    </template>
                    <div style="display: flex; gap: 1rem; margin-top: 0.4rem; opacity: 0.8; font-size: 0.7rem;">
                      <span x-text="'Points written/24h: ' + (v.qdrant?.embedded_24h ?? '—')"></span>
                      <span x-text="'Pending queue: ' + (v.qdrant?.pending_queue ?? '—')"></span>
                    </div>
                    <template x-if="(v.qdrant?.warnings || []).length > 0">
                      <div style="margin-top: 0.4rem;">
                        <template x-for="w in v.qdrant.warnings" :key="w">
                          <div style="font-size: 0.7rem; color: #f0ad4e; padding: 0.2rem 0.4rem; margin-top: 0.2rem; background: rgba(240,173,78,0.08); border-radius: 3px;"
                               x-text="w"></div>
                        </template>
                      </div>
                    </template>
                  </div>
                </template>
              </div>
            </div>

            <!-- ── Database (SQLite) ── -->
            <div style="margin-bottom: 0.75rem; border: 1px solid var(--color-border); border-radius: 6px; overflow: hidden;">
              <div @click="sqlOpen = !sqlOpen" style="cursor: pointer; padding: 0.4rem 0.6rem; background: rgba(33,150,243,0.06); display: flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; font-weight: 600;">
                <span class="material-symbols-outlined" style="font-size: 14px;" :style="sqlOpen ? 'transform:rotate(90deg)' : ''">chevron_right</span>
                Database — SQLite
                <span style="margin-left: auto; font-weight: 400; opacity: 0.7; font-size: 0.7rem;"
                      x-text="(v.sqlite?.tables?.length || 0) + ' tables · ' + (v.sqlite?.db_size_mb || 0) + ' MB'"></span>
              </div>
              <div x-show="sqlOpen" x-transition style="padding: 0.5rem 0.6rem; font-size: 0.74rem;">
                <div style="display: flex; gap: 1rem; margin-bottom: 0.5rem; font-size: 0.72rem; flex-wrap: wrap;">
                  <template x-if="v.sqlite?.events">
                    <span>Events: <b x-text="v.sqlite.events.events_1h"></b>/1h · <b x-text="v.sqlite.events.events_24h"></b>/24h</span>
                  </template>
                  <template x-if="v.sqlite?.observations">
                    <span>Observations: <b x-text="v.sqlite.observations.created_24h"></b> new · <b x-text="v.sqlite.observations.resolved_24h"></b> resolved · <b x-text="v.sqlite.observations.open_total"></b> open</span>
                  </template>
                </div>
                <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.25rem;">
                  <template x-for="t in (v.sqlite?.tables || []).filter(t => t.rows > 0).sort((a,b) => b.rows - a.rows)" :key="t.name">
                    <div style="display: flex; justify-content: space-between; padding: 0.15rem 0.3rem; border-radius: 3px; background: rgba(255,255,255,0.02);">
                      <span style="font-family: monospace; font-size: 0.68rem;" x-text="t.name"></span>
                      <span style="opacity: 0.7; font-size: 0.68rem;">
                        <span x-text="t.rows.toLocaleString()"></span>
                        <template x-if="t.rows_24h !== undefined">
                          <span style="color: #4caf50;" x-text="' (+' + t.rows_24h + ')'"></span>
                        </template>
                      </span>
                    </div>
                  </template>
                </div>
              </div>
            </div>

            <!-- ── MCP Servers ── -->
            <div style="margin-bottom: 0.75rem; border: 1px solid var(--color-border); border-radius: 6px; overflow: hidden;">
              <div @click="mcpOpen = !mcpOpen" style="cursor: pointer; padding: 0.4rem 0.6rem; background: rgba(0,188,212,0.06); display: flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; font-weight: 600;">
                <span class="material-symbols-outlined" style="font-size: 14px;" :style="mcpOpen ? 'transform:rotate(90deg)' : ''">chevron_right</span>
                MCP Servers
                <span style="margin-left: auto; font-weight: 400; opacity: 0.7; font-size: 0.7rem;"
                      x-text="(v.mcp?.servers?.length || 0) + ' servers · ' + (v.mcp?.servers || []).reduce((s, srv) => s + srv.total_calls_24h, 0) + ' calls/24h'"></span>
              </div>
              <div x-show="mcpOpen" x-transition style="padding: 0.5rem 0.6rem; font-size: 0.74rem;">
                <template x-if="v.mcp?.error">
                  <div style="color: #d9534f;" x-text="'MCP: ' + v.mcp.error"></div>
                </template>
                <template x-if="!v.mcp?.error">
                  <div>
                    <template x-for="s in (v.mcp?.servers || [])" :key="s.name">
                      <div style="margin-bottom: 0.4rem; padding: 0.3rem 0; border-bottom: 1px solid rgba(255,255,255,0.04);">
                        <div style="display: flex; justify-content: space-between; align-items: center;">
                          <span style="font-weight: 600; font-size: 0.72rem;" x-text="s.name"></span>
                          <span style="opacity: 0.6; font-size: 0.66rem;" x-text="s.total_calls_24h + ' calls/24h'"></span>
                        </div>
                        <template x-if="s.tools_invoked.length > 0">
                          <div style="display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.2rem;">
                            <template x-for="t in s.tools_invoked" :key="t.tool">
                              <span style="padding: 0.1rem 0.35rem; border-radius: 3px; background: rgba(0,188,212,0.08); border: 1px solid rgba(0,188,212,0.15); font-size: 0.62rem; font-family: monospace;"
                                    x-text="t.tool + ' (' + t.calls + (t.errors > 0 ? ', ' + t.errors + ' err' : '') + ')'"></span>
                            </template>
                          </div>
                        </template>
                        <template x-if="s.tools_invoked.length === 0">
                          <div style="font-size: 0.64rem; opacity: 0.4; margin-top: 0.1rem;">no activity</div>
                        </template>
                      </div>
                    </template>
                  </div>
                </template>
              </div>
            </div>

            <!-- ── On-Prem Inference (conditional) ── -->
            <template x-if="v.onprem?.ollama?.enabled || v.onprem?.lmstudio?.enabled">
              <div style="margin-bottom: 0; border: 1px solid var(--color-border); border-radius: 6px; overflow: hidden;">
                <div @click="onpremOpen = !onpremOpen" style="cursor: pointer; padding: 0.4rem 0.6rem; background: rgba(121,85,72,0.06); display: flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; font-weight: 600;">
                  <span class="material-symbols-outlined" style="font-size: 14px;" :style="onpremOpen ? 'transform:rotate(90deg)' : ''">chevron_right</span>
                  On-Prem Inference
                  <span style="margin-left: auto; font-weight: 400; opacity: 0.7; font-size: 0.7rem;"
                        x-text="[v.onprem?.ollama?.enabled ? 'Ollama ' + (v.onprem.ollama.status || '') : '', v.onprem?.lmstudio?.enabled ? 'LM Studio ' + (v.onprem.lmstudio.status || '') : ''].filter(Boolean).join(' · ')"></span>
                </div>
                <div x-show="onpremOpen" x-transition style="padding: 0.5rem 0.6rem; font-size: 0.74rem;">
                  <!-- Ollama -->
                  <template x-if="v.onprem?.ollama?.enabled">
                    <div style="margin-bottom: 0.4rem;">
                      <div style="display: flex; align-items: center; gap: 0.3rem; margin-bottom: 0.2rem;">
                        <span style="font-weight: 600; font-size: 0.72rem;">Ollama</span>
                        <span style="font-size: 0.64rem; opacity: 0.6;" x-text="v.onprem.ollama.url || ''"></span>
                        <span style="padding: 0.05rem 0.2rem; border-radius: 3px; font-size: 0.56rem;"
                              :style="v.onprem.ollama.status === 'online' ? 'background: rgba(76,175,80,0.15); color: #81c784' : 'background: rgba(217,83,79,0.15); color: #d9534f'"
                              x-text="v.onprem.ollama.status || 'unknown'"></span>
                      </div>
                      <template x-for="m in (v.onprem?.ollama?.models || [])" :key="m.name">
                        <div style="display: flex; justify-content: space-between; padding: 0.15rem 0; font-size: 0.7rem;">
                          <span style="font-weight: 500;" x-text="m.name"></span>
                          <span style="opacity: 0.6;" x-text="[m.parameter_size, m.quantization, m.size_gb + 'GB'].filter(Boolean).join(' · ')"></span>
                        </div>
                      </template>
                    </div>
                  </template>
                  <!-- LM Studio -->
                  <template x-if="v.onprem?.lmstudio?.enabled">
                    <div>
                      <div style="display: flex; align-items: center; gap: 0.3rem;">
                        <span style="font-weight: 600; font-size: 0.72rem;">LM Studio</span>
                        <span style="padding: 0.05rem 0.2rem; border-radius: 3px; font-size: 0.56rem;"
                              :style="v.onprem.lmstudio.status === 'online' ? 'background: rgba(76,175,80,0.15); color: #81c784' : 'background: rgba(217,83,79,0.15); color: #d9534f'"
                              x-text="v.onprem.lmstudio.status || 'unknown'"></span>
                      </div>
                    </div>
                  </template>
                </div>
              </div>
            </template>

          </div>
        </template>
      </div>
    </div>

    <!-- Panel: Modules & Providers [Tab: overview] -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'overview'">
      <div class="panel-header">
        <span class="material-symbols-outlined">extension</span>
        Modules & Providers
        <span class="panel-status">
          <span class="status-dot"
                :style="`background:${$store.genesisDashboard.panelStateColor('modules')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('modules')"></span>
        </span>
      </div>
      <div class="panel-body">
        <template x-if="$store.genesisDashboard.panelStatusDetail('modules')">
          <div class="panel-status-detail"
               x-text="$store.genesisDashboard.panelStatusDetail('modules')"></div>
        </template>

        <!-- Capability Modules -->
        <h4 style="margin: 0 0 0.5rem 0; color: #ccc; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em;">Capability Modules</h4>
        <template x-if="$store.genesisDashboard.modules.length === 0">
          <div class="empty-state">No modules loaded.</div>
        </template>
        <template x-for="mod in $store.genesisDashboard.modules" :key="mod.name">
          <div style="background: #1a1a2e; border-radius: 8px; padding: 0.75rem; margin-bottom: 0.5rem; border-left: 3px solid; cursor: pointer;"
               :style="`border-left-color: ${mod.type === 'external' ? (mod.ipc_healthy ? '#2196F3' : '#d9534f') : (mod.enabled ? '#4caf50' : '#666')}`"
               @click="$store.genesisDashboard.selectedModule = mod">
            <div style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.4rem;">
              <span style="font-weight: 600; color: #e0e0e0;" x-text="mod.name.replace(/_/g, ' ')"></span>
              <template x-if="mod.type === 'external'">
                <span style="font-size: 0.65rem; padding: 1px 5px; border-radius: 3px; font-weight: 600; background: #1a237e; color: #90caf9; letter-spacing: 0.03em;">EXTERNAL</span>
              </template>
              <span style="font-size: 0.7rem; padding: 2px 6px; border-radius: 4px; font-weight: 500;"
                    :style="`background: ${mod.enabled ? '#1b5e20' : '#424242'}; color: ${mod.enabled ? '#81c784' : '#999'}`"
                    x-text="mod.enabled ? 'active' : 'disabled'"></span>
              <template x-if="mod.type === 'external'">
                <span class="status-dot" :style="`background: ${mod.ipc_healthy ? '#4caf50' : '#d9534f'}`" title="IPC connection status"></span>
              </template>
              <button @click.stop="$store.genesisDashboard.toggleModule(mod.name)"
                      style="margin-left: auto; font-size: 0.68rem; padding: 2px 8px; border-radius: 4px; cursor: pointer; border: 1px solid; font-weight: 500;"
                      :style="mod.enabled
                        ? 'background: transparent; color: #ef9a9a; border-color: #ef9a9a;'
                        : 'background: transparent; color: #81c784; border-color: #81c784;'"
                      x-text="mod.enabled ? 'disable' : 'enable'"></button>
            </div>
            <div style="font-size: 0.8rem; color: #999; margin-bottom: 0.3rem; line-height: 1.4;" x-text="mod.description"></div>
            <div style="font-size: 0.75rem; color: #666; display: flex; gap: 1rem; flex-wrap: wrap;">
              <span x-show="mod.research_profile">Pipeline: <em style="color: #888;" x-text="mod.research_profile"></em></span>
              <template x-if="mod.type === 'external' && mod.ipc_url">
                <span style="color: #7986cb;"><em x-text="mod.ipc_method.toUpperCase()"></em> <span style="opacity: 0.7;" x-text="mod.ipc_url"></span></span>
              </template>
              <template x-if="mod.type === 'external' && mod.ipc_error">
                <span style="color: #ef9a9a;" x-text="mod.ipc_error"></span>
              </template>
              <template x-if="mod.stats && mod.stats.total_records !== undefined">
                <span>Bets: <em style="color: #888;" x-text="mod.stats.total_records"></em></span>
              </template>
              <template x-if="mod.stats && mod.stats.total_launches !== undefined">
                <span>Launches: <em style="color: #888;" x-text="mod.stats.total_launches"></em></span>
              </template>
              <template x-if="mod.stats && mod.stats.brier_score !== null && mod.stats.brier_score !== undefined">
                <span>Brier: <em style="color: #888;" x-text="mod.stats.brier_score.toFixed(3)"></em></span>
              </template>
            </div>
          </div>
        </template>

        <!-- Tool Providers -->
        <h4 style="margin: 1rem 0 0.5rem 0; color: #ccc; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em;">Tool Providers</h4>
        <template x-if="$store.genesisDashboard.providersDetail.length === 0">
          <div class="empty-state">No providers registered.</div>
        </template>
        <div style="display: grid; gap: 0.3rem;">
          <template x-for="p in $store.genesisDashboard.providersDetail" :key="p.name">
            <div style="display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.6rem; background: #1a1a2e; border-radius: 6px; font-size: 0.8rem;">
              <span class="status-dot" :style="`background: ${p.status === 'available' ? '#4caf50' : p.status === 'degraded' ? '#f0ad4e' : '#d9534f'}`"></span>
              <span style="font-weight: 500; color: #e0e0e0; min-width: 140px;" x-text="p.name"></span>
              <span style="color: #888; min-width: 80px;" x-text="p.categories.join(', ')"></span>
              <span style="font-size: 0.7rem; padding: 1px 5px; border-radius: 3px;"
                    :style="`background: ${p.cost_tier === 'free' ? '#1b5e20' : p.cost_tier === 'cheap' ? '#1a237e' : p.cost_tier === 'moderate' ? '#4a3800' : '#4a0000'}; color: ${p.cost_tier === 'free' ? '#81c784' : p.cost_tier === 'cheap' ? '#90caf9' : p.cost_tier === 'moderate' ? '#ffd54f' : '#ef9a9a'}`"
                    x-text="p.cost_tier"></span>
              <span style="color: #666;" x-text="p.invocation_count > 0 ? p.invocation_count + ' calls' : ''"></span>
              <button @click.stop="$store.genesisDashboard.toggleProvider(p.name)"
                      style="margin-left: auto; font-size: 0.68rem; padding: 2px 8px; border-radius: 4px; cursor: pointer; border: 1px solid; font-weight: 500;"
                      :style="p.status !== 'disabled'
                        ? 'background: transparent; color: #ef9a9a; border-color: #ef9a9a;'
                        : 'background: transparent; color: #81c784; border-color: #81c784;'"
                      x-text="p.status !== 'disabled' ? 'disable' : 'enable'"></button>
            </div>
          </template>
        </div>
      </div>
    </div>

    <!-- Panel: Budgets & Operator Controls [Tab: config] -->
    <div class="panel" id="budget-controls" x-show="$store.genesisDashboard.activeTab === 'config'">
      <div class="panel-header">
        <span class="material-symbols-outlined">account_balance_wallet</span>
        Budgets & Operator Controls
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.panelStateColor('budgets')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('budgets')"></span>
        </span>
      </div>
      <div class="panel-body">
        <template x-if="$store.genesisDashboard.panelStatusDetail('budgets')">
          <div class="panel-status-detail" x-text="$store.genesisDashboard.panelStatusDetail('budgets')"></div>
        </template>
        <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0.75rem;">
          <div style="background:var(--color-background); border:1px solid var(--color-border); border-radius:6px; padding:0.75rem;">
            <div class="health-card-title">Active budgets</div>
            <template x-if="$store.genesisDashboard.budgets.length === 0">
              <div class="empty-state" style="padding:0.5rem 0;">No active budgets configured.</div>
            </template>
            <template x-for="b in $store.genesisDashboard.budgets" :key="b.budget_type">
              <div style="font-size:0.8rem; padding:0.2rem 0;">
                <div style="display:flex; justify-content:space-between; margin-bottom:0.15rem;">
                  <span style="text-transform:capitalize;" x-text="b.budget_type"></span>
                  <span x-text="(() => {
                    const cost = $store.genesisDashboard.health.cost || {};
                    const spent = b.budget_type === 'daily' ? cost.daily_usd
                                : b.budget_type === 'weekly' ? cost.weekly_usd
                                : cost.monthly_usd;
                    return '$' + (spent || 0).toFixed(2) + ' / $' + Number(b.limit_usd).toFixed(2);
                  })()"></span>
                </div>
                <div style="height:4px; background:rgba(255,255,255,0.08); border-radius:2px; overflow:hidden;">
                  <div :style="(() => {
                    const cost = $store.genesisDashboard.health.cost || {};
                    const spent = b.budget_type === 'daily' ? cost.daily_usd
                                : b.budget_type === 'weekly' ? cost.weekly_usd
                                : cost.monthly_usd;
                    const pct = Math.min(100, ((spent || 0) / Number(b.limit_usd)) * 100);
                    const color = pct >= 100 ? '#d9534f' : pct >= Number(b.warning_pct) * 100 ? '#f0ad4e' : '#4caf50';
                    return 'width:' + pct + '%; height:100%; background:' + color + '; border-radius:2px; transition:width 0.3s';
                  })()"></div>
                </div>
              </div>
            </template>
          </div>
          <div style="background:var(--color-background); border:1px solid var(--color-border); border-radius:6px; padding:0.75rem;">
            <div class="health-card-title">Edit budget</div>
            <div style="display:grid; gap:0.45rem; margin-top:0.3rem;">
              <label style="font-size:0.72rem; color:var(--color-text-secondary);">
                Budget type
                <select x-model="$store.genesisDashboard.budgetEditor.budget_type"
                        @change="$store.genesisDashboard.selectBudgetType($event.target.value)"
                        style="display:block; width:100%; margin-top:0.15rem; font-size:0.76rem; padding:0.36rem 0.4rem; border-radius:4px; border:1px solid var(--color-border); background:rgba(255,255,255,0.03); color:var(--color-text-primary);">
                  <option value="daily">daily</option>
                  <option value="weekly">weekly</option>
                  <option value="monthly">monthly</option>
                </select>
              </label>
              <label style="font-size:0.72rem; color:var(--color-text-secondary);">
                Limit (USD)
                <input type="number" min="0.01" step="0.01"
                       x-model="$store.genesisDashboard.budgetEditor.limit_usd"
                       style="display:block; width:100%; box-sizing:border-box; margin-top:0.15rem; font-size:0.76rem; padding:0.36rem 0.4rem; border-radius:4px; border:1px solid var(--color-border); background:rgba(255,255,255,0.03); color:var(--color-text-primary);">
              </label>
              <label style="font-size:0.72rem; color:var(--color-text-secondary);">
                Warning threshold
                <input type="number" min="0.01" max="1" step="0.01"
                       x-model="$store.genesisDashboard.budgetEditor.warning_pct"
                       style="display:block; width:100%; box-sizing:border-box; margin-top:0.15rem; font-size:0.76rem; padding:0.36rem 0.4rem; border-radius:4px; border:1px solid var(--color-border); background:rgba(255,255,255,0.03); color:var(--color-text-primary);">
              </label>
              <div style="display:flex; gap:0.45rem; align-items:center; flex-wrap:wrap;">
                <button type="button"
                        style="font-size:0.74rem; padding:0.3rem 0.55rem; border-radius:4px; border:1px solid rgba(33,150,243,0.28); color:#2196F3; background:transparent; cursor:pointer;"
                        :disabled="$store.genesisDashboard.budgetEditor.saving"
                        @click="$store.genesisDashboard.saveBudget()"
                        x-text="$store.genesisDashboard.budgetEditor.saving ? 'Saving...' : 'Save budget'"></button>
                <span style="font-size:0.68rem; color:var(--color-text-secondary);">Threshold is stored as 0.01-1.00.</span>
              </div>
              <template x-if="$store.genesisDashboard.budgetEditor.message">
                <div style="font-size:0.68rem; color:#4caf50;" x-text="$store.genesisDashboard.budgetEditor.message"></div>
              </template>
              <template x-if="$store.genesisDashboard.budgetEditor.error">
                <div style="font-size:0.68rem; color:#d9534f;" x-text="$store.genesisDashboard.budgetEditor.error"></div>
              </template>
            </div>
          </div>
          <!-- Total Cost Picture: provider + CC shadow -->
          <div style="background:var(--color-background); border:1px solid var(--color-border); border-radius:6px; padding:0.75rem;">
            <div class="health-card-title">Total Cost</div>
            <div style="font-size:0.78rem; line-height:1.7;">
              <div style="display:flex; justify-content:space-between;">
                <span>Provider (today)</span>
                <span x-text="'$' + ($store.genesisDashboard.health.cost?.daily_usd?.toFixed(3) ?? '—')"></span>
              </div>
              <div style="display:flex; justify-content:space-between;">
                <span>CC shadow (today)</span>
                <span x-text="'$' + ($store.genesisDashboard.health.cc_sessions?.shadow_cost_today?.toFixed(3) ?? '—')"></span>
              </div>
              <div style="display:flex; justify-content:space-between; border-top:1px solid var(--color-border); padding-top:0.15rem; font-weight:600;">
                <span>Combined (today)</span>
                <span x-text="$store.genesisDashboard.health.cost?.daily_usd != null ? '$' + ($store.genesisDashboard.health.cost.daily_usd + ($store.genesisDashboard.health.cc_sessions?.shadow_cost_today || 0)).toFixed(3) : 'unavailable'"></span>
              </div>
              <div style="display:flex; justify-content:space-between; margin-top:0.3rem;">
                <span>Provider (month)</span>
                <span x-text="$store.genesisDashboard.health.cost?.monthly_usd != null ? '$' + $store.genesisDashboard.health.cost.monthly_usd.toFixed(2) : '—'"></span>
              </div>
              <div style="display:flex; justify-content:space-between;">
                <span>CC shadow (month)</span>
                <span x-text="$store.genesisDashboard.health.cc_sessions?.shadow_cost_month != null ? '$' + $store.genesisDashboard.health.cc_sessions.shadow_cost_month.toFixed(2) : '—'"></span>
              </div>
              <div style="display:flex; justify-content:space-between; border-top:1px solid var(--color-border); padding-top:0.15rem; font-weight:600;">
                <span>Combined (month)</span>
                <span x-text="$store.genesisDashboard.health.cost?.monthly_usd != null ? '$' + ($store.genesisDashboard.health.cost.monthly_usd + ($store.genesisDashboard.health.cc_sessions?.shadow_cost_month || 0)).toFixed(2) : 'unavailable'"></span>
              </div>
            </div>
            <div class="health-card-detail" style="margin-top:0.35rem;">Provider cost is checked against budget limits. CC shadow cost is the Anthropic subscription usage from reflections and tasks — not gated by budget.</div>
          </div>
          <!-- Cost Attribution -->
          <div style="background:var(--color-background); border:1px solid var(--color-border); border-radius:6px; padding:0.75rem;">
            <div class="health-card-title">Cost Attribution (month)</div>
            <template x-if="!($store.genesisDashboard.health.cost?.cost_by_provider || []).length">
              <div class="empty-state" style="padding:0.3rem 0;">No cost events this month.</div>
            </template>
            <template x-for="p in ($store.genesisDashboard.health.cost?.cost_by_provider || [])" :key="p.provider">
              <div style="font-size:0.76rem; display:flex; justify-content:space-between; padding:0.12rem 0;">
                <span x-text="p.provider"></span>
                <span x-text="'$' + p.month_usd.toFixed(3) + ' (' + p.calls + ')'"></span>
              </div>
            </template>
            <template x-if="($store.genesisDashboard.health.cost?.cost_by_call_site || []).length > 0">
              <div style="margin-top:0.35rem; border-top:1px solid var(--color-border); padding-top:0.25rem;">
                <div style="font-size:0.68rem; font-weight:600; margin-bottom:0.15rem;">By call site</div>
                <template x-for="cs in $store.genesisDashboard.health.cost.cost_by_call_site" :key="cs.call_site">
                  <div style="font-size:0.72rem; display:flex; justify-content:space-between; padding:0.08rem 0;">
                    <span style="opacity:0.7" x-text="cs.call_site"></span>
                    <span x-text="'$' + cs.month_usd.toFixed(3)"></span>
                  </div>
                </template>
              </div>
            </template>
          </div>
          <!-- Pressure & Enforcement -->
          <div style="background:var(--color-background); border:1px solid var(--color-border); border-radius:6px; padding:0.75rem;">
            <div class="health-card-title">Pressure & Enforcement</div>
            <div style="font-size:0.78rem; line-height:1.6;">
              <div>
                Monthly pacing:
                <span x-text="$store.genesisDashboard.health.cost?.forecast_monthly_usd != null ? '$' + $store.genesisDashboard.health.cost.forecast_monthly_usd.toFixed(2) + '/mo' : 'unknown'"
                      :style="$store.genesisDashboard.health.cost?.budget_monthly_limit && $store.genesisDashboard.health.cost?.forecast_monthly_usd > $store.genesisDashboard.health.cost?.budget_monthly_limit ? 'color:#d9534f; font-weight:600' : ''"></span>
              </div>
              <div>
                CC rate limits (24h):
                <span x-text="$store.genesisDashboard.health.cc_sessions?.rate_limited_24h ?? 0"
                      :style="($store.genesisDashboard.health.cc_sessions?.rate_limited_24h || 0) > 0 ? 'color:#d9534f; font-weight:600' : ''"></span>
              </div>
              <div>
                Failed sessions (24h):
                <span x-text="$store.genesisDashboard.health.cc_sessions?.failed_24h ?? 0"
                      :style="($store.genesisDashboard.health.cc_sessions?.failed_24h || 0) > 0 ? 'color:#d9534f; font-weight:600' : ''"></span>
              </div>
            </div>
            <div style="margin-top:0.4rem; padding:0.35rem 0.45rem; background:rgba(33,150,243,0.05); border-radius:4px; font-size:0.66rem; color:var(--color-text-secondary); line-height:1.5;">
              <strong>Budget enforcement:</strong> When a budget is exceeded, paid LLM providers are skipped in genesis.routing — calls fall back to free providers. CC session costs are tracked separately and not gated by budget limits.
            </div>
          </div>
          <!-- Operator Shortcuts -->
          <div style="background:var(--color-background); border:1px solid var(--color-border); border-radius:6px; padding:0.75rem;">
            <div class="health-card-title">Operator shortcuts</div>
            <div style="display:flex; gap:0.45rem; flex-wrap:wrap; margin-top:0.25rem;">
              <a href="/genesis/errors" style="font-size:0.76rem; padding:0.28rem 0.55rem; border-radius:4px; border:1px solid rgba(217,83,79,0.35); color:#d9534f; text-decoration:none;">Open errors</a>
              <button style="font-size:0.76rem; padding:0.28rem 0.55rem; border-radius:4px; border:1px solid rgba(33,150,243,0.22); color:#2196F3; background:transparent; cursor:pointer;"
                      @click="$store.genesisDashboard.navigateTo('internals', 'routing-health')">Review routing</button>
              <a href="/genesis/logs" style="font-size:0.76rem; padding:0.28rem 0.55rem; border-radius:4px; border:1px solid var(--color-border); color:var(--color-text-secondary); text-decoration:none;">Open logs</a>
              <button style="font-size:0.76rem; padding:0.28rem 0.55rem; border-radius:4px; border:1px solid rgba(240,173,78,0.35); color:#f0ad4e; background:transparent; cursor:pointer;"
                      @click="$store.genesisDashboard.apiKeysModal.open = true">Review provider keys</button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Panel: Autonomous CLI Policy [Tab: config] -->
    <div class="panel" id="autonomous-cli-policy" x-show="$store.genesisDashboard.activeTab === 'config'">
      <div class="panel-header">
        <span class="material-symbols-outlined">policy</span>
        Autonomous CLI Policy
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.panelStateColor('autonomousCliPolicy')}`"></span>
          <span x-text="$store.genesisDashboard.panelStateLabel('autonomousCliPolicy')"></span>
        </span>
      </div>
      <div class="panel-body">
        <template x-if="$store.genesisDashboard.panelStatusDetail('autonomousCliPolicy')">
          <div class="panel-status-detail" x-text="$store.genesisDashboard.panelStatusDetail('autonomousCliPolicy')"></div>
        </template>
        <template x-if="!$store.genesisDashboard.autonomousCliPolicy">
          <div class="empty-state">Policy status not loaded yet.</div>
        </template>
        <template x-if="$store.genesisDashboard.autonomousCliPolicy">
          <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0.75rem;">
            <div style="background:var(--color-background); border:1px solid var(--color-border); border-radius:6px; padding:0.75rem;">
              <div class="health-card-title">Effective policy</div>
              <div style="font-size:0.78rem; line-height:1.7;">
                <div style="display:flex; justify-content:space-between;"><span>CLI fallback</span><span x-text="$store.genesisDashboard.autonomousCliPolicy.effective_policy?.autonomous_cli_fallback_enabled ? 'enabled' : 'disabled'"></span></div>
                <div style="display:flex; justify-content:space-between;"><span>Manual approval</span><span x-text="$store.genesisDashboard.autonomousCliPolicy.effective_policy?.manual_approval_required ? 'required' : 'not required'"></span></div>
                <div style="display:flex; justify-content:space-between;"><span>Channel</span><span x-text="$store.genesisDashboard.autonomousCliPolicy.effective_policy?.approval_channel || 'telegram'"></span></div>
                <div style="display:flex; justify-content:space-between;"><span>Re-ask</span><span x-text="(($store.genesisDashboard.autonomousCliPolicy.effective_policy?.reask_interval_hours || 24) + 'h')"></span></div>
                <div style="display:flex; justify-content:space-between;"><span>Source</span><span x-text="$store.genesisDashboard.autonomousCliPolicy.effective_policy?.source || 'unknown'"></span></div>
              </div>
            </div>
            <div style="background:var(--color-background); border:1px solid var(--color-border); border-radius:6px; padding:0.75rem;">
              <div class="health-card-title">Guardian export</div>
              <div style="font-size:0.78rem; line-height:1.7;">
                <div style="display:flex; justify-content:space-between;"><span>Shared export</span><span x-text="$store.genesisDashboard.autonomousCliPolicy.effective_policy?.shared_export_enabled ? 'enabled' : 'disabled'"></span></div>
                <div style="display:flex; justify-content:space-between;"><span>Last export</span><span x-text="$store.genesisDashboard.autonomousCliPolicy.last_export_at ? $store.genesisDashboard.relativeTime($store.genesisDashboard.autonomousCliPolicy.last_export_at) : 'not exported'"></span></div>
                <div style="display:flex; justify-content:space-between; gap:0.5rem;"><span>Path</span><span style="text-align:right; word-break:break-all;" x-text="$store.genesisDashboard.autonomousCliPolicy.last_export_path || 'pending'"></span></div>
              </div>
              <template x-if="$store.genesisDashboard.autonomousCliPolicy.last_export_error">
                <div style="margin-top:0.45rem; font-size:0.7rem; color:#d9534f;" x-text="$store.genesisDashboard.autonomousCliPolicy.last_export_error"></div>
              </template>
            </div>
            <div style="background:var(--color-background); border:1px solid var(--color-border); border-radius:6px; padding:0.75rem;">
              <div class="health-card-title">Operator actions</div>
              <div style="font-size:0.74rem; color:var(--color-text-secondary); line-height:1.6;">
                Edit the <code>autonomous_cli_policy</code> settings domain below to change the global fallback gate. Changes hot-reload for Genesis-side routing and are exported to the shared Guardian mount.
              </div>
              <div style="display:flex; gap:0.45rem; flex-wrap:wrap; margin-top:0.55rem;">
                <button style="font-size:0.76rem; padding:0.28rem 0.55rem; border-radius:4px; border:1px solid rgba(33,150,243,0.28); color:#2196F3; background:transparent; cursor:pointer;"
                        @click="$store.genesisDashboard.fetchSettingsData('autonomous_cli_policy'); $store.genesisDashboard.settingsEditing = 'autonomous_cli_policy'; $nextTick(() => { const el = document.querySelector('[data-settings-domain=autonomous_cli_policy]'); if (el) el.scrollIntoView({behavior:'smooth', block:'center'}); })">Edit policy</button>
                <button style="font-size:0.76rem; padding:0.28rem 0.55rem; border-radius:4px; border:1px solid var(--color-border); color:var(--color-text-secondary); background:transparent; cursor:pointer;"
                        @click="$store.genesisDashboard.fetchAutonomousCliPolicy()">Refresh status</button>
              </div>
            </div>
          </div>
        </template>
      </div>
    </div>

    <!-- Panel: Settings Hub [Tab: config] -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'config'">
      <div class="panel-header">
        <span class="material-symbols-outlined">tune</span>
        Settings
      </div>
      <div class="panel-body">
        <!-- Restart banner (shown after saving a setting that needs restart) -->
        <template x-if="$store.genesisDashboard.settingsRestartMessage">
          <div style="padding:0.5rem 0.75rem; border-radius:4px; margin-bottom:0.75rem; font-size:0.74rem; background:rgba(255,193,7,0.12); color:#856404; border:1px solid rgba(255,193,7,0.25); display:flex; align-items:center; gap:0.5rem;">
            <span x-text="$store.genesisDashboard.settingsRestartMessage"></span>
            <button style="font-size:0.7rem; padding:2px 8px; border-radius:3px; border:1px solid rgba(33,150,243,0.3); color:#2196F3; background:transparent; cursor:pointer;"
                    @click="$store.genesisDashboard.restartBridge(); $store.genesisDashboard.settingsRestartMessage = null;">Restart Genesis</button>
            <button class="btn-secondary" style="font-size:0.7rem; padding:2px 8px;"
                    @click="$store.genesisDashboard.settingsRestartMessage = null">Dismiss</button>
          </div>
        </template>
        <!-- System timezone display -->
        <div style="font-size:0.72rem; color:var(--color-text-secondary); margin-bottom:0.75rem; display:flex; align-items:center; gap:0.4rem;">
          <span class="material-symbols-outlined" style="font-size:0.9rem;">schedule</span>
          System timezone: <strong x-text="$store.genesisDashboard.systemTimezone || 'loading...'" style="color:var(--color-text);"></strong>
          <span style="font-size:0.65rem;">(all schedules use this timezone)</span>
        </div>
        <template x-if="!$store.genesisDashboard.settingsDomains">
          <div style="padding:1rem; text-align:center; color:var(--color-text-secondary);">Loading...</div>
        </template>
        <template x-if="$store.genesisDashboard.settingsDomains">
          <div>
            <!-- Form domains (TTS, Ego, Inbox, Outreach) -->
            <template x-for="domain in $store.genesisDashboard._sortedDomains($store.genesisDashboard.settingsDomains.filter(d => d.has_form))" :key="domain.name">
              <div class="card" :data-settings-domain="domain.name" style="padding:1rem; margin-bottom:0.75rem;">
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.5rem;">
                  <div>
                    <strong x-text="$store.genesisDashboard._DOMAIN_LABELS[domain.name] || domain.name"></strong>
                    <span style="font-size:0.75rem; color:var(--color-text-secondary); margin-left:0.5rem;" x-text="domain.description"></span>
                  </div>
                  <div style="display:flex; gap:0.5rem; align-items:center;">
                    <template x-if="domain.needs_restart">
                      <span style="font-size:0.65rem; background:#fff3cd; color:#856404; padding:2px 6px; border-radius:3px;" title="Changes to this setting require a genesis-server restart to take effect">Changing these settings requires a restart to apply</span>
                    </template>
                    <template x-if="$store.genesisDashboard.settingsEditing !== domain.name">
                      <button style="font-size:0.75rem; padding:2px 10px;" @click="$store.genesisDashboard.startEditSettings(domain.name)">Edit</button>
                    </template>
                  </div>
                </div>
                <template x-if="domain.name === 'ego' && $store.genesisDashboard.egoStatus">
                  <div style="font-size:0.72rem; background:rgba(192,132,252,0.06); border:1px solid rgba(192,132,252,0.15); border-radius:4px; padding:0.4rem 0.6rem; margin-bottom:0.5rem; display:flex; align-items:center; gap:0.4rem;">
                    <span class="status-dot" :style="`background: ${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.egoSemantic().state)}`"></span>
                    <span :style="`color: ${$store.genesisDashboard.semanticStateColor($store.genesisDashboard.egoSemantic().state)}`"
                          x-text="$store.genesisDashboard.egoStatus.enabled ? 'Ego active' : 'Ego disabled'"></span>
                    <span style="color:var(--color-text-secondary);" x-text="' — ' + ($store.genesisDashboard.egoStatus.focus_summary || 'no focus')"></span>
                  </div>
                </template>
                <!-- Collapsed view: show key values -->
                <template x-if="$store.genesisDashboard.settingsEditing !== domain.name">
                  <div style="font-size:0.78rem; color:var(--color-text-secondary);">
                    <template x-if="$store.genesisDashboard.settingsData[domain.name]">
                      <div style="display:flex; flex-wrap:wrap; gap:0.5rem 1.5rem;">
                        <template x-for="[k, v] in Object.entries($store.genesisDashboard.settingsData[domain.name]).filter(([k]) => !k.startsWith('_')).slice(0, 8)" :key="k">
                          <span><span style="color:var(--color-text-secondary);" x-text="($store.genesisDashboard._settingLabel(k)) + ': '"></span><span x-text="typeof v === 'object' ? '...' : v"></span></span>
                        </template>
                      </div>
                    </template>
                    <template x-if="!$store.genesisDashboard.settingsData[domain.name]">
                      <span style="cursor:pointer; text-decoration:underline;" @click="$store.genesisDashboard.fetchSettingsData(domain.name)">Load settings</span>
                    </template>
                  </div>
                </template>
                <!-- Expanded edit view -->
                <template x-if="$store.genesisDashboard.settingsEditing === domain.name && $store.genesisDashboard.settingsData[domain.name]">
                  <div>
                    <div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr)); gap:0.5rem; margin-top:0.5rem;">
                      <template x-for="[key, val] in Object.entries($store.genesisDashboard.settingsData[domain.name]).filter(([k, v]) => typeof v !== 'object')" :key="key">
                        <div style="display:flex; flex-direction:column; gap:2px;">
                          <label style="font-size:0.7rem; color:var(--color-text-secondary);"
                                 x-text="$store.genesisDashboard._settingLabel(key)"
                                 :title="$store.genesisDashboard._settingDesc(key)"></label>
                          <template x-if="typeof val === 'boolean'">
                            <select style="font-size:0.78rem; padding:3px 6px;"
                                    @change="$store.genesisDashboard.settingsData[domain.name][key] = $event.target.value === 'true'"
                                    :value="val">
                              <option value="true" :selected="val === true">true</option>
                              <option value="false" :selected="val === false">false</option>
                            </select>
                          </template>
                          <template x-if="typeof val === 'number'">
                            <input type="number" style="font-size:0.78rem; padding:3px 6px; width:100%;"
                                   :value="val" step="any"
                                   @change="$store.genesisDashboard.settingsData[domain.name][key] = parseFloat($event.target.value)">
                          </template>
                          <template x-if="typeof val === 'string' && $store.genesisDashboard._SETTING_CHOICES[key]">
                            <select style="font-size:0.78rem; padding:3px 6px; width:100%;"
                                    @change="$store.genesisDashboard.settingsData[domain.name][key] = $event.target.value"
                                    :value="val">
                              <template x-for="opt in $store.genesisDashboard._SETTING_CHOICES[key]" :key="opt">
                                <option :value="opt" :selected="val === opt" x-text="opt"></option>
                              </template>
                            </select>
                          </template>
                          <template x-if="typeof val === 'string' && !$store.genesisDashboard._SETTING_CHOICES[key]">
                            <input type="text" style="font-size:0.78rem; padding:3px 6px; width:100%;"
                                   :value="val"
                                   @change="$store.genesisDashboard.settingsData[domain.name][key] = $event.target.value">
                          </template>
                        </div>
                      </template>
                    </div>
                    <!-- Nested objects -->
                    <template x-for="[key, val] in Object.entries($store.genesisDashboard.settingsData[domain.name]).filter(([k, v]) => typeof v === 'object' && v !== null)" :key="key">
                      <div style="margin-top:0.5rem;">
                        <div style="font-size:0.7rem; color:var(--color-text-secondary); margin-bottom:2px;" x-text="$store.genesisDashboard._settingLabel(key)"></div>
                        <div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr)); gap:0.5rem;">
                          <template x-for="[sk, sv] in Object.entries(val)" :key="sk">
                            <div style="display:flex; flex-direction:column; gap:2px;">
                              <label style="font-size:0.7rem; color:var(--color-text-secondary);"
                                     x-text="$store.genesisDashboard._settingLabel(sk)"
                                     :title="$store.genesisDashboard._settingDesc(sk)"></label>
                              <template x-if="typeof sv === 'boolean'">
                                <select style="font-size:0.78rem; padding:3px 6px;"
                                        @change="$store.genesisDashboard.settingsData[domain.name][key][sk] = $event.target.value === 'true'"
                                        :value="sv">
                                  <option value="true" :selected="sv === true">true</option>
                                  <option value="false" :selected="sv === false">false</option>
                                </select>
                              </template>
                              <template x-if="typeof sv === 'number'">
                                <input type="number" style="font-size:0.78rem; padding:3px 6px; width:100%;"
                                       :value="sv" step="any"
                                       @change="$store.genesisDashboard.settingsData[domain.name][key][sk] = parseFloat($event.target.value)">
                              </template>
                              <template x-if="typeof sv === 'string' && $store.genesisDashboard._SETTING_CHOICES[sk]">
                                <select style="font-size:0.78rem; padding:3px 6px; width:100%;"
                                        @change="$store.genesisDashboard.settingsData[domain.name][key][sk] = $event.target.value"
                                        :value="sv">
                                  <template x-for="opt in $store.genesisDashboard._SETTING_CHOICES[sk]" :key="opt">
                                    <option :value="opt" :selected="sv === opt" x-text="opt"></option>
                                  </template>
                                </select>
                              </template>
                              <template x-if="typeof sv === 'string' && !$store.genesisDashboard._SETTING_CHOICES[sk]">
                                <input type="text" style="font-size:0.78rem; padding:3px 6px; width:100%;"
                                       :value="sv"
                                       @change="$store.genesisDashboard.settingsData[domain.name][key][sk] = $event.target.value">
                              </template>
                            </div>
                          </template>
                        </div>
                      </div>
                    </template>
                    <div style="display:flex; gap:0.5rem; margin-top:0.75rem;">
                      <button @click="$store.genesisDashboard.saveSettings(domain.name)"
                              :disabled="$store.genesisDashboard.settingsSaving"
                              x-text="$store.genesisDashboard.settingsSaving ? 'Saving...' : 'Save'"></button>
                      <button class="btn-secondary"
                              @click="$store.genesisDashboard.settingsEditing = null; $store.genesisDashboard.fetchSettingsData(domain.name)">Cancel</button>
                    </div>
                  </div>
                </template>
              </div>
            </template>

            <!-- Settings Index: non-form domains -->
            <div style="margin-top:1rem;">
              <h3 style="font-size:0.85rem; margin:0 0 0.5rem 0; color:var(--color-text-secondary);">Other Settings</h3>
              <table style="width:100%; font-size:0.78rem; border-collapse:collapse;">
                <thead>
                  <tr style="border-bottom:1px solid var(--color-border); text-align:left;">
                    <th style="padding:4px 8px;">Setting</th>
                    <th style="padding:4px 8px;">How to Change</th>
                    <th style="padding:4px 8px;">Status</th>
                  </tr>
                </thead>
                <tbody>
                  <template x-for="domain in $store.genesisDashboard._sortedDomains($store.genesisDashboard.settingsDomains.filter(d => !d.has_form))" :key="domain.name">
                    <tr style="border-bottom:1px solid var(--color-border);"
                        :style="domain.readonly ? 'cursor:pointer;' : ''"
                        @click="domain.readonly && $store.genesisDashboard.viewSettings(domain.name)">
                      <td style="padding:4px 8px;">
                        <strong x-text="$store.genesisDashboard._DOMAIN_LABELS[domain.name] || domain.name"></strong>
                        <div style="font-size:0.7rem; color:var(--color-text-secondary);" x-text="domain.description"></div>
                        <!-- Expandable readonly config viewer -->
                        <template x-if="domain.readonly && $store.genesisDashboard.settingsViewing === domain.name">
                          <div style="margin-top:0.4rem; padding:0.5rem; background:var(--color-bg-secondary); border:1px solid var(--color-border); border-radius:4px;" @click.stop>
                            <template x-if="!$store.genesisDashboard.settingsData[domain.name]">
                              <span style="font-size:0.72rem; color:var(--color-text-secondary);">Loading...</span>
                            </template>
                            <template x-if="domain.dedicated_tool && $store.genesisDashboard.settingsData[domain.name]">
                              <div style="font-size:0.72rem; color:var(--color-text-secondary);">
                                Managed by a dedicated tool. Ask Genesis: <em x-text="'&quot;show my ' + domain.name.replace(/_/g, ' ') + '&quot;'"></em>
                              </div>
                            </template>
                            <template x-if="!domain.dedicated_tool && $store.genesisDashboard.settingsData[domain.name]">
                              <div>
                                <div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr)); gap:0.3rem 1rem; font-size:0.72rem;">
                                  <template x-for="[key, val] in Object.entries($store.genesisDashboard.settingsData[domain.name]).filter(([k, v]) => typeof v !== 'object' && !k.startsWith('_'))" :key="key">
                                    <div>
                                      <span style="color:var(--color-text-secondary);" x-text="$store.genesisDashboard._settingLabel(key) + ':'"></span>
                                      <span style="margin-left:0.25rem;" x-text="String(val)"></span>
                                    </div>
                                  </template>
                                </div>
                                <template x-for="[key, val] in Object.entries($store.genesisDashboard.settingsData[domain.name]).filter(([k, v]) => typeof v === 'object' && v !== null && !k.startsWith('_'))" :key="key">
                                  <div style="margin-top:0.35rem;">
                                    <div style="font-size:0.68rem; color:var(--color-text-secondary); font-weight:600; margin-bottom:2px;" x-text="$store.genesisDashboard._settingLabel(key)"></div>
                                    <div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr)); gap:0.2rem 1rem; font-size:0.72rem; padding-left:0.5rem;">
                                      <template x-for="[sk, sv] in Object.entries(val)" :key="sk">
                                        <div>
                                          <span style="color:var(--color-text-secondary);" x-text="$store.genesisDashboard._settingLabel(sk) + ':'"></span>
                                          <span style="margin-left:0.25rem;" x-text="typeof sv === 'object' ? JSON.stringify(sv) : String(sv)"></span>
                                        </div>
                                      </template>
                                    </div>
                                  </div>
                                </template>
                                <div x-show="domain.readonly_reason" style="font-size:0.65rem; color:var(--color-text-secondary); margin-top:0.4rem; padding-top:0.3rem; border-top:1px solid var(--color-border);"
                                     x-text="domain.readonly_reason"></div>
                              </div>
                            </template>
                          </div>
                        </template>
                      </td>
                      <td style="padding:4px 8px;">
                        <template x-if="!domain.readonly && domain.dedicated_tool">
                          <span title="Say this to Genesis in conversation to change these settings" style="cursor:help;">Chat: <em x-text="'&quot;update my ' + domain.name.replace(/_/g, ' ') + '&quot;'"></em></span>
                        </template>
                        <template x-if="!domain.readonly && !domain.dedicated_tool">
                          <span title="Say this to Genesis in conversation to change these settings" style="cursor:help;">Chat: <em x-text="'&quot;update ' + domain.name.replace(/_/g, ' ') + ' settings&quot;'"></em></span>
                        </template>
                        <template x-if="domain.readonly">
                          <span style="color:var(--color-text-secondary); cursor:help;"
                                :title="domain.readonly_reason || 'This setting cannot be edited from the dashboard'"
                                x-text="domain.readonly_reason || 'Read-only'"></span>
                        </template>
                      </td>
                      <td style="padding:4px 8px;">
                        <template x-if="domain.readonly">
                          <span style="font-size:0.65rem; background:var(--color-background); padding:2px 6px; border-radius:3px; cursor:pointer;"
                                @click.stop="$store.genesisDashboard.viewSettings(domain.name)"
                                x-text="$store.genesisDashboard.settingsViewing === domain.name ? '\u25BC viewing' : '\u25B6 view'"></span>
                        </template>
                        <template x-if="domain.needs_restart && !domain.readonly">
                          <span style="font-size:0.65rem; background:#fff3cd; color:#856404; padding:2px 6px; border-radius:3px;" title="Changes require a genesis-server restart to take effect">Changing these settings requires a restart to apply</span>
                        </template>
                        <template x-if="!domain.readonly && !domain.needs_restart">
                          <span style="font-size:0.65rem; background:#d4edda; color:#155724; padding:2px 6px; border-radius:3px;">hot-reload</span>
                        </template>
                      </td>
                    </tr>
                  </template>
                  <!-- Non-MCP settings -->
                  <tr style="border-bottom:1px solid var(--color-border);">
                    <td style="padding:4px 8px;"><strong>Budgets</strong><div style="font-size:0.7rem; color:var(--color-text-secondary);">Daily/weekly/monthly cost limits</div></td>
                    <td style="padding:4px 8px;"><span style="color:#4caf50;">Budget panel above</span></td>
                    <td style="padding:4px 8px;"><span style="font-size:0.65rem; background:#d4edda; color:#155724; padding:2px 6px; border-radius:3px;">hot-reload</span></td>
                  </tr>
                  <tr style="border-bottom:1px solid var(--color-border);">
                    <td style="padding:4px 8px;"><strong>Model Routing</strong><div style="font-size:0.7rem; color:var(--color-text-secondary);">Provider chains per call site</div></td>
                    <td style="padding:4px 8px;">Routing panel on <a href="#internals" style="color:var(--color-primary);">Internals tab</a></td>
                    <td style="padding:4px 8px;"><span style="font-size:0.65rem; background:#d4edda; color:#155724; padding:2px 6px; border-radius:3px;">hot-reload</span></td>
                  </tr>
                  <tr style="border-bottom:1px solid var(--color-border);">
                    <td style="padding:4px 8px;"><strong>Modules</strong><div style="font-size:0.7rem; color:var(--color-text-secondary);">Enable/disable capability modules</div></td>
                    <td style="padding:4px 8px;">Module cards on <a href="#internals" style="color:var(--color-primary);">Internals tab</a></td>
                    <td style="padding:4px 8px;"><span style="font-size:0.65rem; background:#d4edda; color:#155724; padding:2px 6px; border-radius:3px;">hot-reload</span></td>
                  </tr>
                  <tr>
                    <td style="padding:4px 8px;"><strong>Identity & Skills</strong><div style="font-size:0.7rem; color:var(--color-text-secondary);">SOUL.md, CONVERSATION.md, skill files</div></td>
                    <td style="padding:4px 8px;"><span style="color:#4caf50;">Config Files panel below</span></td>
                    <td style="padding:4px 8px;"><span style="font-size:0.65rem; background:#d4edda; color:#155724; padding:2px 6px; border-radius:3px;">hot-reload</span></td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
        </template>
      </div>
    </div>

    <!-- Panel: Provider Keys [Tab: config] -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'config'">
      <div class="panel-header">
        <span class="material-symbols-outlined">key</span>
        Provider Keys
      </div>
      <div class="panel-body">
        <div style="font-size:0.74rem; color:var(--color-text-secondary); margin-bottom:0.75rem;">
          Manage API keys and credentials for external providers.
        </div>
        <!-- Message banner -->
        <template x-if="$store.genesisDashboard.secretsMessage">
          <div style="padding:0.5rem 0.75rem; border-radius:4px; margin-bottom:0.75rem; font-size:0.74rem;"
               :style="{
                 'background': $store.genesisDashboard.secretsMessage.type === 'error' ? 'rgba(217,83,79,0.12)' : 'rgba(255,193,7,0.12)',
                 'color': $store.genesisDashboard.secretsMessage.type === 'error' ? '#d9534f' : '#856404',
                 'border': $store.genesisDashboard.secretsMessage.type === 'error' ? '1px solid rgba(217,83,79,0.25)' : '1px solid rgba(255,193,7,0.25)'
               }">
            <span x-text="$store.genesisDashboard.secretsMessage.text"></span>
            <template x-if="$store.genesisDashboard.secretsMessage.type === 'restart'">
              <button style="margin-left:0.5rem; font-size:0.7rem; padding:2px 8px; border-radius:3px; border:1px solid rgba(33,150,243,0.3); color:#2196F3; background:transparent; cursor:pointer;"
                      @click="$store.genesisDashboard.restartBridge()">Restart Genesis</button>
            </template>
          </div>
        </template>
        <!-- Loading state -->
        <template x-if="!$store.genesisDashboard.secretsGroups">
          <div style="padding:1rem; text-align:center; color:var(--color-text-secondary);">Loading...</div>
        </template>
        <!-- Key groups -->
        <template x-if="$store.genesisDashboard.secretsGroups">
          <div>
            <template x-for="group in $store.genesisDashboard.secretsGroups" :key="group.name">
              <div style="margin-bottom:0.75rem;">
                <div style="font-size:0.72rem; font-weight:600; color:var(--color-text-secondary); margin-bottom:0.35rem; text-transform:uppercase; letter-spacing:0.03em;" x-text="group.name"></div>
                <template x-for="k in group.keys" :key="k.key">
                  <div style="display:flex; align-items:center; gap:0.5rem; padding:0.35rem 0; border-bottom:1px solid var(--color-border); font-size:0.78rem; flex-wrap:wrap;">
                    <!-- Status dot (health-aware) -->
                    <span class="status-dot" :style="`background:${$store.genesisDashboard.secretStatusColor($store.genesisDashboard.secretHealthStatus(k))}`"></span>
                    <!-- Label + env var -->
                    <span style="font-weight:600; min-width:90px;" x-text="k.label"></span>
                    <code style="font-size:0.65rem; color:var(--color-text-secondary);" x-text="k.key"></code>
                    <!-- Status text (health-aware) -->
                    <span style="margin-left:auto; min-width:70px; text-align:right;"
                          :style="`color:${$store.genesisDashboard.secretStatusColor($store.genesisDashboard.secretHealthStatus(k))}`"
                          :title="$store.genesisDashboard.secretHealthStatus(k) === 'error' ? 'Circuit breaker OPEN — provider unreachable or failing' : $store.genesisDashboard.secretHealthStatus(k) === 'degraded' ? 'Some providers using this key have circuit breakers open' : ''"
                          x-text="({healthy:'healthy', configured:'configured', validated:'validated', degraded:'degraded', error:'unreachable', not_set:'not set'})[$store.genesisDashboard.secretHealthStatus(k)] || 'not set'"></span>
                    <!-- Signup link -->
                    <template x-if="k.signup_url && k.status === 'not_set'">
                      <a :href="'https://' + k.signup_url" target="_blank" rel="noopener"
                         style="font-size:0.65rem; color:var(--color-primary); text-decoration:none;"
                         x-text="k.signup_url"></a>
                    </template>
                    <!-- Edit/Set button -->
                    <button class="btn-secondary" style="font-size:0.68rem;"
                            @click="$store.genesisDashboard.toggleSecretEdit(k.key)"
                            x-text="$store.genesisDashboard.secretsEditing[k.key] ? 'Cancel' : (k.status === 'not_set' ? 'Set' : 'Edit')"></button>
                    <!-- Inline edit row -->
                    <template x-if="$store.genesisDashboard.secretsEditing[k.key]">
                      <div style="width:100%; display:flex; gap:0.4rem; align-items:center; margin-top:0.25rem;">
                        <input type="text" placeholder="Enter value..."
                               style="flex:1; font-size:0.76rem; padding:4px 8px; border:1px solid var(--color-border); border-radius:4px; background:var(--color-background); color:var(--color-text);"
                               :value="$store.genesisDashboard.secretsValues[k.key] ?? k.value ?? ''"
                               @input="$store.genesisDashboard.secretsValues = {...$store.genesisDashboard.secretsValues, [k.key]: $event.target.value}">
                        <button style="font-size:0.7rem; padding:3px 10px; border-radius:4px; border:1px solid rgba(33,150,243,0.3); color:#2196F3; background:transparent; cursor:pointer;"
                                :disabled="$store.genesisDashboard.secretsSaving"
                                @click="$store.genesisDashboard.saveSecret(k.key)"
                                x-text="$store.genesisDashboard.secretsSaving ? 'Saving...' : 'Save'"></button>
                      </div>
                    </template>
                  </div>
                </template>
              </div>
            </template>
          </div>
        </template>
      </div>
    </div>

    <!-- Panel: Config Files (Collapsible) [Tab: config] -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'config'">
      <div class="panel-header config-toggle"
           @click="$store.genesisDashboard.configExpanded = !$store.genesisDashboard.configExpanded">
        <span class="material-symbols-outlined"
              :style="$store.genesisDashboard.configExpanded ? 'transform: rotate(90deg)' : ''">
          chevron_right
        </span>
        <span class="material-symbols-outlined">description</span>
        Config Files
      </div>
      <div class="panel-body" x-show="$store.genesisDashboard.configExpanded" x-transition>
        <div style="display:flex;gap:0.3rem;flex-wrap:wrap;margin-bottom:0.75rem;">
          <button style="font-size:0.68rem;padding:0.2rem 0.5rem;border-radius:3px;cursor:pointer;border:1px solid var(--color-border);background:transparent;color:var(--color-text-secondary);"
                  :style="!$store.genesisDashboard.configCategoryFilter ? 'background:rgba(33,150,243,0.15);color:#2196F3;border-color:rgba(33,150,243,0.3)' : ''"
                  @click="$store.genesisDashboard.configCategoryFilter = null">All</button>
          <template x-for="cat in [...new Set($store.genesisDashboard.configFiles.map(f => f.category))].sort()" :key="cat">
            <button style="font-size:0.68rem;padding:0.2rem 0.5rem;border-radius:3px;cursor:pointer;border:1px solid var(--color-border);background:transparent;color:var(--color-text-secondary);"
                    :style="$store.genesisDashboard.configCategoryFilter === cat ? 'background:rgba(33,150,243,0.15);color:#2196F3;border-color:rgba(33,150,243,0.3)' : ''"
                    @click="$store.genesisDashboard.configCategoryFilter = cat"
                    x-text="cat"></button>
          </template>
        </div>
        <template x-for="(files, category) in (() => {
          const grouped = $store.genesisDashboard.groupedConfigFiles;
          const filter = $store.genesisDashboard.configCategoryFilter;
          if (!filter) return grouped;
          const r = {}; if (grouped[filter]) r[filter] = grouped[filter]; return r;
        })()" :key="category">
          <div class="config-category">
            <div class="config-category-title" x-text="category"></div>
            <template x-for="file in files" :key="file.path || file.name">
              <div class="config-file">
                <span class="config-file-name" x-text="file.name"></span>
                <button class="config-edit-btn"
                        @click="$store.genesisDashboard.openConfigFile(file)"
                        x-text="file.editable !== false ? 'Edit' : 'View'">
                </button>
              </div>
            </template>
          </div>
        </template>
      </div>
    </div>

    <!-- Config file viewer modal -->
    <div class="config-modal-overlay" x-show="$store.genesisDashboard.configModal.open"
         @click.self="$store.genesisDashboard.closeConfigModal()" x-transition>
    <div class="config-modal">
      <div class="config-modal-header">
        <span x-text="$store.genesisDashboard.configModal.name"></span>
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.modalStateColor($store.genesisDashboard.configModal)}`"></span>
          <span x-text="$store.genesisDashboard.modalStateLabel($store.genesisDashboard.configModal)"></span>
        </span>
        <button @click="$store.genesisDashboard.closeConfigModal()">&times;</button>
      </div>
      <div class="config-modal-body" style="padding:0;">
          <template x-if="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.configModal)">
            <div class="panel-status-detail" style="margin:0.75rem 1rem;"
                 x-text="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.configModal)"></div>
          </template>
          <div x-show="$store.genesisDashboard.configModal.fetch.state === 'loading' && !$store.genesisDashboard.configModal.content"
               style="color: var(--color-text-secondary); text-align: center; padding: 2rem;">
            Loading...
          </div>
          <div x-show="$store.genesisDashboard.configModal.fetch.state === 'error' && !$store.genesisDashboard.configModal.content"
               class="empty-state">
            Config file unavailable.
          </div>
          <div x-show="$store.genesisDashboard.configModal.content"
               id="config-ace-editor"
               style="width:100%;height:60vh;font-size:13px;"></div>
        </div>
        <div x-show="$store.genesisDashboard.configModal.content"
             style="display:flex;align-items:center;gap:0.5rem;padding:0.5rem 1rem;border-top:1px solid var(--color-border);">
          <button style="font-size:0.74rem;padding:0.3rem 0.7rem;border-radius:4px;border:1px solid rgba(33,150,243,0.28);color:#2196F3;background:transparent;cursor:pointer;"
                  x-show="$store.genesisDashboard.configModal.editable"
                  :disabled="!$store.genesisDashboard.configModal.dirty || $store.genesisDashboard.configModal.saving"
                  @click="$store.genesisDashboard.saveConfigFile()"
                  x-text="$store.genesisDashboard.configModal.saving ? 'Saving...' : 'Save'"></button>
          <button style="font-size:0.74rem;padding:0.3rem 0.7rem;border-radius:4px;border:1px solid rgba(217,83,79,0.28);color:#d9534f;background:transparent;cursor:pointer;"
                  x-show="$store.genesisDashboard.configModal.deletable"
                  @click="$store.genesisDashboard.deleteConfigFile()">Delete</button>
          <span x-show="$store.genesisDashboard.configModal.saveMessage"
                style="color:#4caf50;font-size:0.72rem;"
                x-text="$store.genesisDashboard.configModal.saveMessage"></span>
          <span x-show="$store.genesisDashboard.configModal.saveError"
                style="color:#d9534f;font-size:0.72rem;"
                x-text="$store.genesisDashboard.configModal.saveError"></span>
          <span x-show="!$store.genesisDashboard.configModal.editable"
                style="color:var(--color-text-secondary);font-size:0.72rem;">Read-only</span>
        </div>
      </div>
    </div>

  </div>

  <!-- Surplus Detail Modal -->
  <div class="config-modal-overlay" x-show="$store.genesisDashboard.surplusModal.open"
       @click.self="$store.genesisDashboard.surplusModal.open = false" x-transition>
    <div class="config-modal" style="max-width: 800px;">
      <div class="config-modal-header">
        <span>Surplus Compute Detail</span>
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.modalStateColor($store.genesisDashboard.surplusModal)}`"></span>
          <span x-text="$store.genesisDashboard.modalStateLabel($store.genesisDashboard.surplusModal)"></span>
        </span>
        <button @click="$store.genesisDashboard.surplusModal.open = false">&times;</button>
      </div>
      <div class="config-modal-body">
        <template x-if="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.surplusModal)">
          <div class="panel-status-detail" style="margin-bottom: 0.75rem;"
               x-text="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.surplusModal)"></div>
        </template>
        <div x-show="$store.genesisDashboard.surplusModal.fetch.state === 'loading' && !$store.genesisDashboard.surplusModal.data"
             style="text-align: center; padding: 2rem; color: var(--color-text-secondary);">Loading...</div>
        <div x-show="$store.genesisDashboard.surplusModal.fetch.state === 'error' && !$store.genesisDashboard.surplusModal.data"
             class="empty-state">Surplus detail unavailable.</div>
        <template x-if="$store.genesisDashboard.surplusModal.data">
          <div>
            <!-- Summary stats (clickable filters) -->
            <div style="display: flex; gap: 0.5rem; margin-bottom: 1rem; flex-wrap: wrap;">
              <div style="font-size: 0.82rem; padding: 0.4rem 0.8rem; border-radius: 6px; cursor: pointer; transition: opacity 0.15s;"
                   :style="`background: rgba(76,175,80,${$store.genesisDashboard.surplusModal.filter === 'completed' ? '0.3' : '0.12'}); color: #4caf50; opacity: ${!$store.genesisDashboard.surplusModal.filter || $store.genesisDashboard.surplusModal.filter === 'completed' ? '1' : '0.5'}`"
                   @click="$store.genesisDashboard.surplusModal.filter = $store.genesisDashboard.surplusModal.filter === 'completed' ? null : 'completed'">
                <span x-text="($store.genesisDashboard.surplusModal.data.stats?.completed || 0)"></span> completed
              </div>
              <div style="font-size: 0.82rem; padding: 0.4rem 0.8rem; border-radius: 6px; cursor: pointer; transition: opacity 0.15s;"
                   :style="`background: rgba(217,83,79,${$store.genesisDashboard.surplusModal.filter === 'failed' ? '0.3' : '0.12'}); color: #d9534f; opacity: ${!$store.genesisDashboard.surplusModal.filter || $store.genesisDashboard.surplusModal.filter === 'failed' ? '1' : '0.5'}`"
                   @click="$store.genesisDashboard.surplusModal.filter = $store.genesisDashboard.surplusModal.filter === 'failed' ? null : 'failed'">
                <span x-text="($store.genesisDashboard.surplusModal.data.stats?.failed || 0)"></span> failed
              </div>
              <div style="font-size: 0.82rem; padding: 0.4rem 0.8rem; border-radius: 6px; cursor: pointer; transition: opacity 0.15s;"
                   :style="`background: rgba(240,173,78,${$store.genesisDashboard.surplusModal.filter === 'pending' ? '0.3' : '0.12'}); color: #f0ad4e; opacity: ${!$store.genesisDashboard.surplusModal.filter || $store.genesisDashboard.surplusModal.filter === 'pending' ? '1' : '0.5'}`"
                   @click="$store.genesisDashboard.surplusModal.filter = $store.genesisDashboard.surplusModal.filter === 'pending' ? null : 'pending'">
                <span x-text="($store.genesisDashboard.surplusModal.data.stats?.pending || 0)"></span> pending
              </div>
              <template x-if="($store.genesisDashboard.surplusModal.data.stats?.stub_completions || 0) > 0">
                <div style="font-size: 0.82rem; padding: 0.4rem 0.8rem; border-radius: 6px; cursor: pointer; transition: opacity 0.15s;"
                     :style="`background: rgba(100,116,139,${$store.genesisDashboard.surplusModal.filter === 'stub' ? '0.3' : '0.12'}); color: #94a3b8; opacity: ${!$store.genesisDashboard.surplusModal.filter || $store.genesisDashboard.surplusModal.filter === 'stub' ? '1' : '0.5'}`"
                     title="Heuristic: tasks that completed in under 1 second and may be stub outputs"
                     @click="$store.genesisDashboard.surplusModal.filter = $store.genesisDashboard.surplusModal.filter === 'stub' ? null : 'stub'">
                  <span x-text="$store.genesisDashboard.surplusModal.data.stats.stub_completions"></span> stubs
                </div>
              </template>
            </div>

            <!-- Failure reasons -->
            <template x-if="Object.keys($store.genesisDashboard.surplusModal.data.failure_reasons || {}).length > 0">
              <div style="margin-bottom: 1rem; padding: 0.5rem 0.8rem; background: rgba(217,83,79,0.08); border-radius: 6px; border: 1px solid rgba(217,83,79,0.2);">
                <div style="font-size: 0.78rem; font-weight: 600; color: #d9534f; margin-bottom: 0.3rem;">Failure Reasons</div>
                <template x-for="[reason, count] in Object.entries($store.genesisDashboard.surplusModal.data.failure_reasons)" :key="reason">
                  <div style="font-size: 0.75rem; color: #f87171;">
                    <span x-text="reason"></span>
                    <span style="opacity: 0.6;" x-text="'(' + count + 'x)'"></span>
                  </div>
                </template>
              </div>
            </template>

            <!-- Task history table -->
            <h4 style="margin: 0 0 0.5rem; font-size: 0.85rem;">Task History</h4>
            <template x-if="($store.genesisDashboard.surplusModal.data.tasks || []).length === 0">
              <div style="font-size: 0.78rem; color: var(--color-text-secondary); padding: 1rem; text-align: center;">
                No surplus tasks have been created yet. The system schedules brainstorm tasks daily when idle compute is available.
              </div>
            </template>
            <div style="max-height: 400px; overflow-y: auto;">
              <template x-for="t in ($store.genesisDashboard.surplusModal.data.tasks || []).filter(t => {
                const f = $store.genesisDashboard.surplusModal.filter;
                if (!f) return true;
                if (f === 'stub') return t.stub;
                return t.status === f;
              })" :key="t.id">
                <div style="font-size: 0.78rem; padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--color-border); display: flex; align-items: center; gap: 0.5rem;">
                  <span class="status-dot" :style="`background: ${t.status === 'completed' ? (t.stub ? '#64748b' : '#4caf50') : t.status === 'failed' ? '#d9534f' : '#f0ad4e'}`"></span>
                  <span x-text="t.task_type" style="font-weight: 600; min-width: 130px;"></span>
                  <span style="color: var(--color-text-secondary); min-width: 130px;" x-text="t.created_at ? $store.genesisDashboard.formatDateTime(t.created_at) : '-'"></span>
                  <span :style="`min-width: 80px; color: ${t.status === 'completed' ? (t.stub ? '#64748b' : '#4caf50') : t.status === 'failed' ? '#d9534f' : '#f0ad4e'}`"
                        x-text="t.status + (t.stub ? ' (stub heuristic)' : '')"></span>
                  <span style="color: var(--color-text-secondary); min-width: 70px;"
                        x-text="t.duration_s != null ? (t.duration_s < 1 ? t.duration_s + 's' : Math.round(t.duration_s) + 's') : '-'"></span>
                  <span style="color: #f87171; font-size: 0.72rem; flex: 1; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;"
                        x-text="t.failure_reason || ''"
                        :title="t.failure_reason || ''"></span>
                </div>
              </template>
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>

  <!-- Ego Detail Modal -->
  <div class="config-modal-overlay" x-show="$store.genesisDashboard.egoModal.open"
       @click.self="$store.genesisDashboard.egoModal.open = false" x-transition>
    <div class="config-modal" style="max-width: 900px;">
      <div class="config-modal-header">
        <span>Ego — Autonomous Decision Cycle</span>
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.modalStateColor($store.genesisDashboard.egoModal)}`"></span>
          <span x-text="$store.genesisDashboard.modalStateLabel($store.genesisDashboard.egoModal)"></span>
        </span>
        <button @click="$store.genesisDashboard.egoModal.open = false">&times;</button>
      </div>
      <div class="config-modal-body">
        <!-- Status detail -->
        <template x-if="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.egoModal)">
          <div class="panel-status-detail" style="margin-bottom: 0.75rem;"
               x-text="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.egoModal)"></div>
        </template>
        <!-- Loading -->
        <div x-show="$store.genesisDashboard.egoModal.fetch.state === 'loading' && !$store.genesisDashboard.egoStatus"
             style="text-align: center; padding: 2rem; color: var(--color-text-secondary);">Loading...</div>
        <!-- Error -->
        <div x-show="$store.genesisDashboard.egoModal.fetch.state === 'error' && !$store.genesisDashboard.egoStatus"
             class="empty-state">Ego detail unavailable.</div>

        <template x-if="$store.genesisDashboard.egoStatus">
          <div>
            <!-- Tab bar -->
            <div style="display: flex; gap: 0; border-bottom: 1px solid var(--color-border); margin-bottom: 1rem;">
              <template x-for="t in [{id:'overview',label:'Overview'},{id:'cycles',label:'Cycles'}]" :key="t.id">
                <button style="padding: 0.4rem 1rem; font-size: 0.78rem; border: none; background: none; cursor: pointer; border-bottom: 2px solid transparent; color: var(--color-text-secondary);"
                        :style="$store.genesisDashboard.egoModal.tab === t.id ? 'border-bottom-color: #c084fc; color: #c084fc; font-weight: 600;' : ''"
                        @click="$store.genesisDashboard.egoModal.tab = t.id"
                        x-text="t.label + (t.id === 'proposals' ? ' (' + ($store.genesisDashboard.egoStatus?.pending_proposals || 0) + ')' : '')"></button>
              </template>
            </div>

            <!-- ═══ Tab: Overview ═══ -->
            <div x-show="$store.genesisDashboard.egoModal.tab === 'overview'">
              <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;">
                <!-- Focus -->
                <div style="background: rgba(192,132,252,0.06); border: 1px solid rgba(192,132,252,0.15); border-radius: 6px; padding: 0.8rem;">
                  <div style="font-size: 0.72rem; color: #c084fc; font-weight: 600; margin-bottom: 0.3rem;">Current Focus</div>
                  <div style="font-size: 0.82rem;" x-text="$store.genesisDashboard.egoStatus?.focus_summary || 'No focus set'"></div>
                </div>
                <!-- Cadence -->
                <div style="background: rgba(255,255,255,0.03); border: 1px solid var(--color-border); border-radius: 6px; padding: 0.8rem;">
                  <div style="font-size: 0.72rem; color: var(--color-text-secondary); font-weight: 600; margin-bottom: 0.3rem;">Cadence</div>
                  <template x-if="$store.genesisDashboard.egoModal.cadence?.available">
                    <div style="font-size: 0.82rem;">
                      <span x-text="$store.genesisDashboard.egoModal.cadence.is_paused ? 'Paused' : ($store.genesisDashboard.egoModal.cadence.is_running ? 'Running' : 'Stopped')"></span>
                      <span style="color: var(--color-text-secondary);" x-text="' — every ' + $store.genesisDashboard.egoModal.cadence.current_interval_minutes + 'min'"></span>
                      <template x-if="$store.genesisDashboard.egoModal.cadence.is_running && !$store.genesisDashboard.egoModal.cadence.is_paused">
                        <span class="status-dot" style="width: 6px; height: 6px; margin-left: 0.3rem; animation: pulse 2s infinite;" :style="`background: #4caf50`"></span>
                      </template>
                      <template x-if="$store.genesisDashboard.egoModal.cadence.consecutive_failures > 0">
                        <div style="font-size: 0.72rem; color: #f0ad4e; margin-top: 0.2rem;"
                             x-text="$store.genesisDashboard.egoModal.cadence.consecutive_failures + ' consecutive failures'"></div>
                      </template>
                    </div>
                  </template>
                  <template x-if="!$store.genesisDashboard.egoModal.cadence?.available">
                    <span style="font-size: 0.82rem; color: var(--color-text-secondary);">Cadence manager not available</span>
                  </template>
                </div>
                <!-- Budget -->
                <div style="background: rgba(255,255,255,0.03); border: 1px solid var(--color-border); border-radius: 6px; padding: 0.8rem;">
                  <div style="font-size: 0.72rem; color: var(--color-text-secondary); font-weight: 600; margin-bottom: 0.3rem;">Daily Budget</div>
                  <div style="display: flex; align-items: center; gap: 0.5rem;">
                    <span style="font-size: 1.1rem; font-weight: 600;"
                          x-text="'$' + ($store.genesisDashboard.egoStatus?.daily_cost_usd || 0).toFixed(2)"></span>
                    <span style="font-size: 0.78rem; color: var(--color-text-secondary);"
                          x-text="'/ $' + ($store.genesisDashboard.egoStatus?.daily_budget_cap_usd || 0).toFixed(2)"></span>
                  </div>
                  <div style="margin-top: 0.4rem; height: 6px; background: rgba(255,255,255,0.1); border-radius: 3px; overflow: hidden;">
                    <div :style="`width: ${Math.min(100, ($store.genesisDashboard.egoStatus?.daily_cost_usd || 0) / ($store.genesisDashboard.egoStatus?.daily_budget_cap_usd || 1) * 100)}%; height: 100%; border-radius: 3px; transition: width 0.3s; background: ${($store.genesisDashboard.egoStatus?.daily_cost_usd || 0) / ($store.genesisDashboard.egoStatus?.daily_budget_cap_usd || 1) > 0.8 ? '#d9534f' : ($store.genesisDashboard.egoStatus?.daily_cost_usd || 0) / ($store.genesisDashboard.egoStatus?.daily_budget_cap_usd || 1) > 0.5 ? '#f0ad4e' : '#4caf50'}`"></div>
                  </div>
                </div>
                <!-- Quick stats -->
                <div style="background: rgba(255,255,255,0.03); border: 1px solid var(--color-border); border-radius: 6px; padding: 0.8rem;">
                  <div style="font-size: 0.72rem; color: var(--color-text-secondary); font-weight: 600; margin-bottom: 0.3rem;">Quick Stats</div>
                  <div style="font-size: 0.82rem; display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem;">
                    <span x-text="($store.genesisDashboard.egoModal.cycles?.length || 0) + ' recent cycles'"></span>
                    <span x-text="($store.genesisDashboard.egoStatus?.pending_proposals || 0) + ' pending'"></span>
                    <span x-text="$store.genesisDashboard.egoStatus?.model || 'unknown'"></span>
                    <span x-text="($store.genesisDashboard.egoStatus?.uncompacted_cycles || 0) + ' uncompacted'"></span>
                  </div>
                </div>
              </div>
              <!-- Effort selector -->
              <div style="margin-top: 1rem; padding: 0.6rem 0.8rem; background: rgba(192,132,252,0.04); border: 1px solid rgba(192,132,252,0.12); border-radius: 6px;">
                <div style="display: flex; align-items: center; gap: 1rem;">
                  <div>
                    <div style="font-size: 0.72rem; color: #c084fc; font-weight: 600; margin-bottom: 0.2rem;">Default Effort</div>
                    <div style="font-size: 0.72rem; color: var(--color-text-secondary);">Takes effect on restart</div>
                  </div>
                  <select style="margin-left: auto; background: var(--color-bg-secondary); color: var(--color-text-primary); border: 1px solid var(--color-border); border-radius: 4px; padding: 0.3rem 0.5rem; font-size: 0.82rem;"
                          @change="fetchApi('/api/genesis/settings/ego', { method: 'PUT', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({default_effort: $event.target.value}) })">
                    <!-- MAX and XHIGH intentionally excluded per user decision (defaults stay at high; xhigh is Opus 4.7 only and reachable via session_set_effort) -->
                    <template x-for="e in ['low', 'medium', 'high']" :key="e">
                      <option :value="e" x-text="e.charAt(0).toUpperCase() + e.slice(1)"
                              :selected="e === ($store.genesisDashboard.egoStatus?.default_effort || 'high')"></option>
                    </template>
                  </select>
                </div>
              </div>
              <!-- Model / Cadence / Budget controls -->
              <div style="margin-top: 0.6rem; padding: 0.6rem 0.8rem; background: rgba(192,132,252,0.04); border: 1px solid rgba(192,132,252,0.12); border-radius: 6px; display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem;">
                <!-- Model -->
                <div>
                  <div style="font-size: 0.72rem; color: #c084fc; font-weight: 600; margin-bottom: 0.2rem;">Model</div>
                  <select style="width: 100%; background: var(--color-bg-secondary); color: var(--color-text-primary); border: 1px solid var(--color-border); border-radius: 4px; padding: 0.3rem 0.5rem; font-size: 0.82rem;"
                          @change="fetchApi('/api/genesis/settings/ego', { method: 'PUT', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({model: $event.target.value}) })">
                    <template x-for="m in ['opus', 'sonnet', 'haiku']" :key="m">
                      <option :value="m" x-text="m.charAt(0).toUpperCase() + m.slice(1)"
                              :selected="m === ($store.genesisDashboard.egoStatus?.model || 'opus')"></option>
                    </template>
                  </select>
                </div>
                <!-- Cadence -->
                <div>
                  <div style="font-size: 0.72rem; color: #c084fc; font-weight: 600; margin-bottom: 0.2rem;">Cadence (min)</div>
                  <select style="width: 100%; background: var(--color-bg-secondary); color: var(--color-text-primary); border: 1px solid var(--color-border); border-radius: 4px; padding: 0.3rem 0.5rem; font-size: 0.82rem;"
                          @change="fetchApi('/api/genesis/settings/ego', { method: 'PUT', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({cadence_minutes: parseInt($event.target.value)}) })">
                    <template x-for="c in [30, 60, 120, 240]" :key="c">
                      <option :value="c" x-text="c + 'min'"
                              :selected="c === ($store.genesisDashboard.egoStatus?.cadence_minutes || 60)"></option>
                    </template>
                  </select>
                </div>
                <!-- Thinking Budget -->
                <div>
                  <div style="font-size: 0.72rem; color: #c084fc; font-weight: 600; margin-bottom: 0.2rem;">Think Budget</div>
                  <select style="width: 100%; background: var(--color-bg-secondary); color: var(--color-text-primary); border: 1px solid var(--color-border); border-radius: 4px; padding: 0.3rem 0.5rem; font-size: 0.82rem;"
                          @change="fetchApi('/api/genesis/settings/ego', { method: 'PUT', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ego_thinking_budget_usd: parseFloat($event.target.value)}) })">
                    <template x-for="b in [2, 5, 10, 15, 20]" :key="b">
                      <option :value="b" x-text="'$' + b + '/day'"
                              :selected="b === ($store.genesisDashboard.egoStatus?.ego_thinking_budget_usd || 10)"></option>
                    </template>
                  </select>
                </div>
                <!-- Dispatch Budget -->
                <div>
                  <div style="font-size: 0.72rem; color: #c084fc; font-weight: 600; margin-bottom: 0.2rem;">Dispatch Budget</div>
                  <select style="width: 100%; background: var(--color-bg-secondary); color: var(--color-text-primary); border: 1px solid var(--color-border); border-radius: 4px; padding: 0.3rem 0.5rem; font-size: 0.82rem;"
                          @change="fetchApi('/api/genesis/settings/ego', { method: 'PUT', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ego_dispatch_budget_usd: parseFloat($event.target.value)}) })">
                    <template x-for="b in [1, 2.5, 5, 10]" :key="b">
                      <option :value="b" x-text="'$' + b + '/day'"
                              :selected="b === ($store.genesisDashboard.egoStatus?.ego_dispatch_budget_usd || 2.5)"></option>
                    </template>
                  </select>
                </div>
              </div>
              <div style="font-size: 0.65rem; color: var(--color-text-secondary); margin-top: 0.3rem; padding: 0 0.8rem;">
                Changes saved to local overlay. Restart server to apply.
              </div>
              <!-- Last cycle -->
              <template x-if="$store.genesisDashboard.egoStatus?.last_cycle">
                <div style="margin-top: 1rem; padding: 0.6rem 0.8rem; background: rgba(255,255,255,0.03); border: 1px solid var(--color-border); border-radius: 6px;">
                  <div style="font-size: 0.72rem; color: var(--color-text-secondary); font-weight: 600; margin-bottom: 0.2rem;">Last Cycle</div>
                  <div style="font-size: 0.82rem;">
                    <span x-text="$store.genesisDashboard.egoStatus.last_cycle.focus_summary || 'No summary'"></span>
                    <span style="color: var(--color-text-secondary); font-size: 0.72rem; margin-left: 0.5rem;"
                          x-text="$store.genesisDashboard.formatDateTime($store.genesisDashboard.egoStatus.last_cycle.created_at)"></span>
                    <span style="color: var(--color-text-secondary); font-size: 0.72rem; margin-left: 0.5rem;"
                          x-text="'$' + ($store.genesisDashboard.egoStatus.last_cycle.cost_usd || 0).toFixed(4)"></span>
                  </div>
                </div>
              </template>
              <!-- Quick navigation links -->
              <div style="margin-top:1rem; display:flex; gap:0.5rem;">
                <button style="font-size:0.72rem; padding:0.3rem 0.8rem; border-radius:4px; cursor:pointer; background:rgba(192,132,252,0.1); color:#c084fc; border:1px solid rgba(192,132,252,0.2);"
                        @click="$store.genesisDashboard.egoModal.open = false; location.hash = 'chat'; $store.genesisDashboard.commsTab = 'proposals'">View Proposals</button>
                <button style="font-size:0.72rem; padding:0.3rem 0.8rem; border-radius:4px; cursor:pointer; background:rgba(156,39,176,0.1); color:#ce93d8; border:1px solid rgba(156,39,176,0.2);"
                        @click="$store.genesisDashboard.egoModal.open = false; location.hash = 'work';">View Follow-ups</button>
              </div>
            </div>

            <!-- ═══ Tab: Proposals (deprecated — now in Chat tab) ═══ -->
            <div x-show="$store.genesisDashboard.egoModal.tab === 'proposals'">
              <!-- Filter pills -->
              <div style="display: flex; gap: 0.4rem; margin-bottom: 0.8rem; flex-wrap: wrap;">
                <template x-for="s in [null, 'pending', 'approved', 'rejected', 'expired']" :key="s || 'all'">
                  <button style="font-size: 0.75rem; padding: 0.25rem 0.7rem; border-radius: 12px; border: 1px solid var(--color-border); cursor: pointer; transition: all 0.15s;"
                          :style="$store.genesisDashboard.egoModal.proposalFilter === s ? 'background: rgba(192,132,252,0.2); border-color: #c084fc; color: #c084fc;' : 'background: transparent; color: var(--color-text-secondary);'"
                          @click="$store.genesisDashboard.egoModal.proposalFilter = s"
                          x-text="s || 'all'"></button>
                </template>
              </div>
              <!-- Proposal list -->
              <div style="max-height: 450px; overflow-y: auto;">
                <template x-if="$store.genesisDashboard.egoModal.proposals.filter(p => !$store.genesisDashboard.egoModal.proposalFilter || p.status === $store.genesisDashboard.egoModal.proposalFilter).length === 0">
                  <div class="empty-state" style="font-size: 0.78rem;">No proposals match this filter.</div>
                </template>
                <template x-for="p in $store.genesisDashboard.egoModal.proposals.filter(p => !$store.genesisDashboard.egoModal.proposalFilter || p.status === $store.genesisDashboard.egoModal.proposalFilter)" :key="p.id">
                  <div style="padding: 0.6rem 0.8rem; border: 1px solid var(--color-border); border-radius: 6px; margin-bottom: 0.5rem;">
                    <!-- Header: type badge + urgency + status + confidence -->
                    <div style="display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.3rem; flex-wrap: wrap;">
                      <span style="font-size: 0.68rem; padding: 1px 6px; border-radius: 3px; font-weight: 600;"
                            :style="`background: rgba(192,132,252,0.15); color: #c084fc;`"
                            x-text="p.action_type"></span>
                      <span style="font-size: 0.68rem; padding: 1px 6px; border-radius: 3px;"
                            :style="`background: ${p.urgency === 'critical' ? 'rgba(217,83,79,0.15)' : p.urgency === 'high' ? 'rgba(240,173,78,0.15)' : p.urgency === 'normal' ? 'rgba(33,150,243,0.15)' : 'rgba(136,136,136,0.15)'}; color: ${p.urgency === 'critical' ? '#d9534f' : p.urgency === 'high' ? '#f0ad4e' : p.urgency === 'normal' ? '#2196F3' : '#888'}`"
                            x-text="p.urgency"></span>
                      <span style="font-size: 0.68rem; padding: 1px 6px; border-radius: 3px;"
                            :style="`background: ${p.status === 'approved' ? 'rgba(76,175,80,0.15)' : p.status === 'rejected' ? 'rgba(217,83,79,0.15)' : p.status === 'expired' ? 'rgba(136,136,136,0.15)' : 'rgba(240,173,78,0.15)'}; color: ${p.status === 'approved' ? '#4caf50' : p.status === 'rejected' ? '#d9534f' : p.status === 'expired' ? '#888' : '#f0ad4e'}`"
                            x-text="p.status"></span>
                      <!-- Confidence bar -->
                      <div style="display: flex; align-items: center; gap: 0.3rem; margin-left: auto;">
                        <div style="width: 40px; height: 4px; background: rgba(255,255,255,0.1); border-radius: 2px; overflow: hidden;">
                          <div :style="`width: ${(p.confidence || 0) * 100}%; height: 100%; background: #c084fc; border-radius: 2px;`"></div>
                        </div>
                        <span style="font-size: 0.65rem; color: var(--color-text-secondary);" x-text="Math.round((p.confidence || 0) * 100) + '%'"></span>
                      </div>
                    </div>
                    <!-- Content -->
                    <div style="font-size: 0.82rem; margin-bottom: 0.3rem;" x-text="p.content"></div>
                    <!-- Rationale (if present) -->
                    <template x-if="p.rationale">
                      <div style="font-size: 0.72rem; color: var(--color-text-secondary); margin-bottom: 0.3rem;">
                        <span style="font-weight: 600;">Rationale:</span> <span x-text="p.rationale"></span>
                      </div>
                    </template>
                    <!-- Timestamps -->
                    <div style="font-size: 0.68rem; color: var(--color-text-secondary); display: flex; gap: 1rem;">
                      <span x-text="'Created: ' + $store.genesisDashboard.formatDateTime(p.created_at)"></span>
                      <template x-if="p.expires_at">
                        <span x-text="'Expires: ' + $store.genesisDashboard.formatDateTime(p.expires_at)"></span>
                      </template>
                      <template x-if="p.resolved_at">
                        <span x-text="'Resolved: ' + $store.genesisDashboard.formatDateTime(p.resolved_at)"></span>
                      </template>
                    </div>
                    <!-- User response (if resolved) -->
                    <template x-if="p.user_response">
                      <div style="font-size: 0.72rem; color: var(--color-text-secondary); margin-top: 0.2rem;">
                        <span style="font-weight: 600;">Response:</span> <span x-text="p.user_response"></span>
                      </div>
                    </template>
                    <!-- Approve/Reject buttons (pending only) -->
                    <template x-if="p.status === 'pending'">
                      <div style="margin-top: 0.5rem; display: flex; gap: 0.4rem; align-items: center;">
                        <button style="font-size: 0.72rem; padding: 0.25rem 0.8rem; border-radius: 4px; border: 1px solid #4caf50; background: rgba(76,175,80,0.1); color: #4caf50; cursor: pointer;"
                                @click="$store.genesisDashboard.resolveEgoProposal(p.id, 'approved', '')">Approve</button>
                        <template x-if="$store.genesisDashboard.egoModal.rejectingId !== p.id">
                          <button style="font-size: 0.72rem; padding: 0.25rem 0.8rem; border-radius: 4px; border: 1px solid #d9534f; background: rgba(217,83,79,0.1); color: #d9534f; cursor: pointer;"
                                  @click="$store.genesisDashboard.egoModal.rejectingId = p.id; $store.genesisDashboard.egoModal.rejectReason = ''">Reject</button>
                        </template>
                        <template x-if="$store.genesisDashboard.egoModal.rejectingId === p.id">
                          <div style="display: flex; gap: 0.3rem; align-items: center; flex: 1;">
                            <input type="text" placeholder="Reason (optional)"
                                   style="font-size: 0.72rem; padding: 0.2rem 0.5rem; border: 1px solid var(--color-border); border-radius: 4px; background: var(--color-bg); color: var(--color-text); flex: 1;"
                                   x-model="$store.genesisDashboard.egoModal.rejectReason"
                                   @keyup.enter="$store.genesisDashboard.resolveEgoProposal(p.id, 'rejected', $store.genesisDashboard.egoModal.rejectReason)">
                            <button style="font-size: 0.72rem; padding: 0.2rem 0.6rem; border-radius: 4px; border: 1px solid #d9534f; background: #d9534f; color: white; cursor: pointer;"
                                    @click="$store.genesisDashboard.resolveEgoProposal(p.id, 'rejected', $store.genesisDashboard.egoModal.rejectReason)">Reject</button>
                            <button style="font-size: 0.72rem; padding: 0.2rem 0.5rem; border: none; background: none; color: var(--color-text-secondary); cursor: pointer;"
                                    @click="$store.genesisDashboard.egoModal.rejectingId = null">&times;</button>
                          </div>
                        </template>
                      </div>
                    </template>
                  </div>
                </template>
              </div>
            </div>

            <!-- ═══ Tab: Cycles ═══ -->
            <div x-show="$store.genesisDashboard.egoModal.tab === 'cycles'">
              <template x-if="$store.genesisDashboard.egoModal.cycles.length === 0">
                <div class="empty-state" style="font-size: 0.78rem;">No ego cycles recorded yet.</div>
              </template>
              <div style="max-height: 450px; overflow-y: auto;">
                <template x-for="c in $store.genesisDashboard.egoModal.cycles" :key="c.id">
                  <div style="padding: 0.5rem 0.8rem; border-bottom: 1px solid var(--color-border);">
                    <div style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;"
                         @click="$store.genesisDashboard.egoModal.expandedCycle = $store.genesisDashboard.egoModal.expandedCycle === c.id ? null : c.id">
                      <span style="font-size: 0.72rem; color: var(--color-text-secondary); min-width: 120px;"
                            x-text="$store.genesisDashboard.formatDateTime(c.created_at)"></span>
                      <span style="font-size: 0.82rem; flex: 1;" x-text="c.focus_summary || 'No summary'"></span>
                      <span style="font-size: 0.72rem; color: var(--color-text-secondary);"
                            x-text="'$' + (c.cost_usd || 0).toFixed(4)"></span>
                      <span style="font-size: 0.68rem; color: var(--color-text-secondary);"
                            x-text="c.model_used || ''"></span>
                      <template x-if="c.compacted_into">
                        <span style="font-size: 0.62rem; padding: 1px 4px; border-radius: 2px; background: rgba(136,136,136,0.15); color: #888;">compacted</span>
                      </template>
                      <span style="font-size: 0.72rem; color: var(--color-text-secondary);" x-text="$store.genesisDashboard.egoModal.expandedCycle === c.id ? '▾' : '▸'"></span>
                    </div>
                    <!-- Expanded detail -->
                    <template x-if="$store.genesisDashboard.egoModal.expandedCycle === c.id">
                      <div style="margin-top: 0.5rem; padding: 0.5rem; background: rgba(255,255,255,0.03); border-radius: 4px; font-size: 0.75rem;">
                        <div style="display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.4rem; color: var(--color-text-secondary);">
                          <span x-text="'Tokens: ' + (c.input_tokens || 0) + ' in / ' + (c.output_tokens || 0) + ' out'"></span>
                          <span x-text="'Duration: ' + ((c.duration_ms || 0) / 1000).toFixed(1) + 's'"></span>
                          <span x-text="'ID: ' + c.id.slice(0, 8)"></span>
                        </div>
                      </div>
                    </template>
                  </div>
                </template>
              </div>
            </div>

            <!-- ═══ Tab: Follow-ups ═══ -->
            <div x-show="$store.genesisDashboard.egoModal.tab === 'followups'">
              <template x-if="$store.genesisDashboard.egoModal.followUps.length === 0">
                <div class="empty-state" style="font-size: 0.78rem;">No ego-originated follow-ups pending.</div>
              </template>
              <div style="max-height: 450px; overflow-y: auto;">
                <template x-for="f in $store.genesisDashboard.egoModal.followUps" :key="f.id">
                  <div style="padding: 0.5rem 0.8rem; border-bottom: 1px solid var(--color-border); font-size: 0.82rem;">
                    <div style="display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.2rem;">
                      <span style="font-size: 0.68rem; padding: 1px 6px; border-radius: 3px;"
                            :style="`background: ${f.priority === 'critical' ? 'rgba(217,83,79,0.15)' : f.priority === 'high' ? 'rgba(240,173,78,0.15)' : 'rgba(136,136,136,0.15)'}; color: ${f.priority === 'critical' ? '#d9534f' : f.priority === 'high' ? '#f0ad4e' : '#888'}`"
                            x-text="f.priority"></span>
                      <span style="font-size: 0.68rem; padding: 1px 6px; border-radius: 3px; background: rgba(33,150,243,0.15); color: #2196F3;"
                            x-text="f.strategy"></span>
                      <span style="font-size: 0.68rem; color: var(--color-text-secondary); margin-left: auto;"
                            x-text="$store.genesisDashboard.formatDateTime(f.created_at)"></span>
                    </div>
                    <div x-text="f.content"></div>
                    <template x-if="f.reason">
                      <div style="font-size: 0.72rem; color: var(--color-text-secondary); margin-top: 0.2rem;" x-text="f.reason"></div>
                    </template>
                  </div>
                </template>
              </div>
            </div>

          </div>
        </template>
      </div>
    </div>
  </div>

  <!-- Outreach Messages Modal (deprecated — moved to Chat tab Communication panel) -->
  <div class="config-modal-overlay" x-show="false"
       x-transition>
    <div class="config-modal" style="max-width: 800px; max-height: 85vh;">
      <div class="config-modal-header">
        <span>Outreach Messages</span>
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.modalStateColor($store.genesisDashboard.outreachModal)}`"></span>
          <span x-text="$store.genesisDashboard.modalStateLabel($store.genesisDashboard.outreachModal)"></span>
        </span>
        <button @click="$store.genesisDashboard.outreachModal.open = false">&times;</button>
      </div>
      <div class="config-modal-body">
        <template x-if="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.outreachModal)">
          <div class="panel-status-detail" style="margin-bottom: 0.75rem;"
               x-text="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.outreachModal)"></div>
        </template>
        <div x-show="$store.genesisDashboard.outreachModal.fetch.state === 'loading' && $store.genesisDashboard.outreachModal.messages.length === 0"
             style="text-align: center; padding: 2rem; color: var(--color-text-secondary);">Loading...</div>
        <div x-show="$store.genesisDashboard.outreachModal.fetch.state === 'error' && $store.genesisDashboard.outreachModal.messages.length === 0"
             class="empty-state">Outreach history unavailable.</div>
        <template x-if="$store.genesisDashboard.outreachModal.messages.length > 0 || $store.genesisDashboard.outreachModal.fetch.state !== 'loading'">
          <div>
            <!-- Pending approvals banner -->
            <template x-if="$store.genesisDashboard.outreachModal.pendingApprovals.length > 0">
              <div style="background: #d9534f1a; border: 1px solid #d9534f44; border-radius: 6px; padding: 0.6rem 0.75rem; margin-bottom: 0.75rem;">
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.3rem;">
                  <span style="font-weight: 600; font-size: 0.82rem; color: #d9534f;">
                    Action Required
                    <span style="background: #d9534f; color: white; font-size: 0.65rem; padding: 0.1rem 0.35rem; border-radius: 10px; margin-left: 0.3rem;"
                          x-text="$store.genesisDashboard.outreachModal.pendingApprovals.length"></span>
                  </span>
                  <button style="font-size: 0.68rem; padding: 0.2rem 0.5rem; border: 1px solid #4caf50; color: #4caf50; border-radius: 3px; cursor: pointer; background: transparent;"
                          @click="$store.genesisDashboard.approveAllPending()">Approve All</button>
                </div>
                <template x-for="a in $store.genesisDashboard.outreachModal.pendingApprovals" :key="a.id">
                  <div style="display: flex; justify-content: space-between; align-items: center; padding: 0.25rem 0; border-top: 1px solid #d9534f22;">
                    <div>
                      <span style="font-size: 0.75rem;" x-text="a.description || a.action_type"></span>
                      <span style="font-size: 0.62rem; color: #888; margin-left: 0.3rem;" x-text="$store.genesisDashboard.formatDateTime(a.created_at)"></span>
                    </div>
                    <div style="display: flex; gap: 0.25rem;">
                      <button style="font-size: 0.65rem; padding: 0.15rem 0.4rem; border: 1px solid #4caf50; color: #4caf50; border-radius: 3px; cursor: pointer; background: transparent;"
                              @click="$store.genesisDashboard.resolveApproval(a.id, 'approved')">Approve</button>
                      <button style="font-size: 0.65rem; padding: 0.15rem 0.4rem; border: 1px solid #d9534f; color: #d9534f; border-radius: 3px; cursor: pointer; background: transparent;"
                              @click="$store.genesisDashboard.resolveApproval(a.id, 'rejected')">Deny</button>
                    </div>
                  </div>
                </template>
              </div>
            </template>
            <!-- Category filters -->
            <div style="display: flex; gap: 0.4rem; margin-bottom: 0.75rem; flex-wrap: wrap;">
              <template x-for="cat in [null, 'alert', 'digest', 'surplus', 'blocker']" :key="cat || 'all'">
                <button style="font-size: 0.72rem; padding: 0.2rem 0.6rem; border-radius: 3px; cursor: pointer; transition: opacity 0.15s;"
                        :style="`border: 1px solid ${cat ? '#888' : '#4caf50'}; background: ${$store.genesisDashboard.outreachModal.categoryFilter === cat ? (cat ? '#88888833' : '#4caf5033') : 'transparent'}; color: ${$store.genesisDashboard.outreachModal.categoryFilter === cat ? '#fff' : '#aaa'}; opacity: ${$store.genesisDashboard.outreachModal.categoryFilter === cat || $store.genesisDashboard.outreachModal.categoryFilter === null && cat === null ? '1' : '0.6'}`"
                        @click="$store.genesisDashboard.outreachModal.categoryFilter = cat"
                        x-text="cat ? cat.charAt(0).toUpperCase() + cat.slice(1) : 'All'"></button>
              </template>
            </div>
            <template x-if="$store.genesisDashboard.outreachModal.messages.length === 0 && $store.genesisDashboard.outreachModal.fetch.state !== 'error'">
              <div style="color: var(--color-text-secondary); text-align: center; padding: 2rem;">No outreach messages found.</div>
            </template>
            <template x-for="msg in $store.genesisDashboard.outreachModal.messages.filter(m => !$store.genesisDashboard.outreachModal.categoryFilter || m.category === $store.genesisDashboard.outreachModal.categoryFilter)" :key="msg.id">
              <div style="border: 1px solid var(--color-border); border-radius: 6px; padding: 0.75rem; margin-bottom: 0.5rem;">
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.3rem;">
                  <div>
                    <span style="font-weight: 600; font-size: 0.85rem;" x-text="msg.topic || msg.signal_type || 'Untitled'"></span>
                    <span style="font-size: 0.68rem; padding: 0.1rem 0.3rem; border-radius: 3px; margin-left: 0.3rem;"
                          :style="`background: ${(msg.category === 'blocker' || msg.category === 'approval') ? '#d9534f33' : msg.category === 'alert' ? '#f0ad4e33' : msg.category === 'digest' ? '#2196F333' : '#4caf5033'}; color: ${(msg.category === 'blocker' || msg.category === 'approval') ? '#d9534f' : msg.category === 'alert' ? '#f0ad4e' : msg.category === 'digest' ? '#2196F3' : '#4caf50'}`"
                          x-text="msg.category"></span>
                  </div>
                  <span style="font-size: 0.68rem; color: var(--color-text-secondary);"
                        x-text="msg.channel + ' · ' + $store.genesisDashboard.formatDateTime(msg.created_at)"></span>
                </div>
                <div style="font-size: 0.8rem; white-space: pre-wrap; max-height: 150px; overflow-y: auto; padding: 0.4rem; background: var(--color-background); border-radius: 4px; margin-bottom: 0.3rem;"
                     x-text="msg.message_content || '(no content)'"></div>
                <!-- Engagement buttons — category-aware -->
                <div style="display: flex; gap: 0.3rem; align-items: center;">
                  <template x-if="msg.engagement_outcome && !['useful','not_useful','ambivalent'].includes(msg.engagement_outcome)">
                    <span style="font-size: 0.68rem; color: #888; margin-right: 0.3rem;"
                          x-text="'Currently: ' + (msg.engagement_outcome === 'ignored' ? 'ignored (auto)' : msg.user_response || msg.engagement_outcome)"></span>
                  </template>
                  <!-- Blocker: Approve/Deny — wire to approval API when matching -->
                  <template x-if="msg.category === 'blocker' || msg.category === 'approval'">
                    <div style="display: flex; gap: 0.3rem; align-items: center;">
                      <template x-for="btn in [{value: 'approved', label: 'Approve', color: '#4caf50'}, {value: 'rejected', label: 'Deny', color: '#d9534f'}]" :key="btn.value">
                        <button style="font-size: 0.68rem; padding: 0.2rem 0.5rem; border-radius: 3px; cursor: pointer; transition: all 0.15s;"
                                :style="`border: 1px solid ${btn.color}; color: ${btn.color}; background: ${msg.user_response === (btn.value === 'approved' ? 'approve' : 'deny') ? btn.color + '33' : 'transparent'}; font-weight: ${msg.user_response === (btn.value === 'approved' ? 'approve' : 'deny') ? '700' : '400'}; opacity: ${!msg.user_response || msg.user_response === (btn.value === 'approved' ? 'approve' : 'deny') ? '1' : '0.4'}`"
                                @click="(() => { const a = $store.genesisDashboard.findMatchingApproval(msg); if (a) { $store.genesisDashboard.resolveApproval(a.id, btn.value, msg.id); } else { $store.genesisDashboard.engageOutreach(msg.id, btn.value === 'approved' ? 'useful' : 'not_useful', btn.value === 'approved' ? 'approve' : 'deny'); } })()"
                                x-text="btn.label"></button>
                      </template>
                      <template x-if="$store.genesisDashboard.findMatchingApproval(msg)">
                        <span style="font-size: 0.6rem; color: #4caf50; margin-left: 0.3rem;">linked</span>
                      </template>
                    </div>
                  </template>
                  <!-- Alert: Acknowledge -->
                  <template x-if="msg.category === 'alert'">
                    <button style="font-size: 0.68rem; padding: 0.2rem 0.5rem; border-radius: 3px; cursor: pointer; transition: all 0.15s;"
                            :style="`border: 1px solid #f0ad4e; color: #f0ad4e; background: ${msg.engagement_outcome === 'useful' ? '#f0ad4e33' : 'transparent'}; font-weight: ${msg.engagement_outcome === 'useful' ? '700' : '400'}`"
                            @click="$store.genesisDashboard.engageOutreach(msg.id, 'useful')"
                            x-text="msg.engagement_outcome === 'useful' ? 'Acknowledged' : 'Acknowledge'"></button>
                  </template>
                  <!-- Digest/Surplus: Useful/Not Useful/Ambivalent -->
                  <template x-if="msg.category !== 'blocker' && msg.category !== 'alert' && msg.category !== 'approval'">
                    <div style="display: flex; gap: 0.3rem;">
                      <template x-for="btn in [{value: 'useful', label: 'Useful', color: '#4caf50'}, {value: 'not_useful', label: 'Not Useful', color: '#d9534f'}, {value: 'ambivalent', label: 'Ambivalent', color: '#888'}]" :key="btn.value">
                        <button style="font-size: 0.68rem; padding: 0.2rem 0.5rem; border-radius: 3px; cursor: pointer; transition: all 0.15s;"
                                :style="`border: 1px solid ${btn.color}; color: ${btn.color}; background: ${msg.engagement_outcome === btn.value ? btn.color + '33' : 'transparent'}; font-weight: ${msg.engagement_outcome === btn.value ? '700' : '400'}; opacity: ${!msg.engagement_outcome || msg.engagement_outcome === btn.value ? '1' : '0.4'}`"
                                @click="$store.genesisDashboard.engageOutreach(msg.id, btn.value)"
                                x-text="btn.label"></button>
                      </template>
                    </div>
                  </template>
                </div>
                <div style="font-size: 0.62rem; color: var(--color-text-secondary); margin-top: 0.15rem; opacity: 0.7;"
                     x-text="(msg.category === 'blocker' || msg.category === 'approval') ? 'Approve or deny this request' : msg.category === 'alert' ? 'Acknowledge to dismiss' : msg.category === 'digest' ? 'Feedback shapes report content over time' : 'Feedback guides task prioritization'"></div>
              </div>
            </template>
          </div>
        </template>
      </div>
    </div>
  </div>

  <!-- MCP Tools Modal -->
  <div class="config-modal-overlay" x-show="$store.genesisDashboard.mcpModal.open"
       @click.self="$store.genesisDashboard.mcpModal.open = false" x-transition>
    <div class="config-modal" style="max-width: 600px;">
      <div class="config-modal-header">
        <span>MCP Server Tools</span>
        <span class="panel-status">
          <span class="status-dot" :style="`background:${$store.genesisDashboard.modalStateColor($store.genesisDashboard.mcpModal)}`"></span>
          <span x-text="$store.genesisDashboard.modalStateLabel($store.genesisDashboard.mcpModal)"></span>
        </span>
        <button @click="$store.genesisDashboard.mcpModal.open = false">&times;</button>
      </div>
      <div class="config-modal-body">
        <template x-if="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.mcpModal)">
          <div class="panel-status-detail" style="margin-bottom: 0.75rem;"
               x-text="$store.genesisDashboard.modalStatusDetail($store.genesisDashboard.mcpModal)"></div>
        </template>
        <div x-show="$store.genesisDashboard.mcpModal.fetch.state === 'loading' && !$store.genesisDashboard.mcpModal.data"
             style="text-align: center; padding: 2rem; color: var(--color-text-secondary);">Loading...</div>
        <div x-show="$store.genesisDashboard.mcpModal.fetch.state === 'error' && !$store.genesisDashboard.mcpModal.data"
             class="empty-state">MCP tool inventory unavailable.</div>
        <template x-if="$store.genesisDashboard.mcpModal.data">
          <div>
            <template x-for="(info, name) in $store.genesisDashboard.mcpModal.data" :key="name">
              <div style="margin-bottom: 1rem;">
                <div style="font-weight: 600; font-size: 0.85rem; margin-bottom: 0.3rem;">
                  <span class="status-dot" :style="`background: ${info.status === 'up' ? '#4caf50' : '#d9534f'}`"></span>
                  <span x-text="name"></span>
                  <span style="opacity: 0.5; font-size: 0.72rem;" x-text="'(' + (info.tools?.length || 0) + ' tools)'"></span>
                </div>
                <template x-if="info.tools && info.tools.length > 0">
                  <div style="display: flex; flex-wrap: wrap; gap: 0.25rem; padding-left: 1rem;">
                    <template x-for="tool in info.tools" :key="tool">
                      <span style="font-size: 0.68rem; padding: 0.1rem 0.4rem; background: rgba(255,255,255,0.06); border-radius: 3px; color: var(--color-text-secondary);"
                            x-text="tool"></span>
                    </template>
                  </div>
                </template>
                <template x-if="info.error">
                  <div style="font-size: 0.72rem; color: #d9534f; padding-left: 1rem;" x-text="info.error"></div>
                </template>
              </div>
            </template>
          </div>
        </template>
      </div>
    </div>
  </div>

  <!-- API Keys Modal -->
  <div class="config-modal-overlay" x-show="$store.genesisDashboard.apiKeysModal.open"
       @click.self="$store.genesisDashboard.apiKeysModal.open = false" x-transition>
    <div class="config-modal" style="max-width: 700px;">
      <div class="config-modal-header">
        <span>API Key Status</span>
        <button @click="$store.genesisDashboard.apiKeysModal.open = false">&times;</button>
      </div>
      <div class="config-modal-body">
        <template x-if="$store.genesisDashboard.health.api_keys">
          <div>
            <div style="font-size: 0.72rem; color: var(--color-text-secondary); margin-bottom: 0.75rem;">
              Keys are read from environment variables. Configure in <a href="#" @click.prevent="$store.genesisDashboard.activeTab = 'config'; $store.genesisDashboard.fetchSecrets()" style="color:var(--color-primary);">Settings &rarr; Provider Keys</a>.
            </div>
            <template x-for="(info, name) in $store.genesisDashboard.health.api_keys" :key="name">
              <div style="display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0; border-bottom: 1px solid var(--color-border); font-size: 0.78rem; flex-wrap: wrap;">
                <span class="status-dot" :style="`background: ${$store.genesisDashboard.probeStatusColor(info)}`"></span>
                <span style="font-weight: 600; min-width: 100px;" x-text="name"></span>
                <template x-if="info.status === 'validated'">
                  <span style="min-width: 80px; color: #4caf50;" title="API key accepted by provider. Does not verify inference works.">key ok</span>
                </template>
                <template x-if="info.status === 'missing'">
                  <span :style="`min-width: 80px; color: ${$store.genesisDashboard.providerFallbackActive(name) ? '#f0ad4e' : '#d9534f'}`"
                        x-text="$store.genesisDashboard.providerFallbackActive(name) ? 'missing (fallback active)' : 'missing (needed!)'"></span>
                </template>
                <template x-if="info.status !== 'validated' && info.status !== 'missing'">
                  <span :style="`min-width: 80px; color: ${info.status === 'local' ? '#2196F3' : '#f0ad4e'}`"
                        x-text="info.status"></span>
                </template>
                <span style="color: var(--color-text-secondary); font-size: 0.72rem;"
                      x-text="info.provider_type || ''"></span>
                <template x-if="info.status === 'missing'">
                  <code style="font-size: 0.68rem; color: #f0ad4e; margin-left: auto;"
                        x-text="'export API_KEY_' + name.toUpperCase() + '=...'"></code>
                </template>
                <template x-if="info.error">
                  <span style="font-size: 0.68rem; color: #d9534f; margin-left: auto;" x-text="info.error.substring(0, 60)"></span>
                </template>
                <template x-if="$store.genesisDashboard.providerCbState(name)">
                  <span style="font-size: 0.68rem; margin-left: 0.3rem;"
                        :style="`color: ${$store.genesisDashboard.providerCbState(name) === 'closed' ? '#4caf50' : $store.genesisDashboard.providerCbState(name) === 'open' ? '#d9534f' : '#f0ad4e'}`"
                        x-text="'CB: ' + $store.genesisDashboard.providerCbState(name)"></span>
                </template>
              </div>
            </template>
            <!-- Provider → Call Site Usage -->
            <template x-if="$store.genesisDashboard.health.api_keys">
              <div style="margin-top: 1rem;">
                <div style="font-size: 0.78rem; font-weight: 600; margin-bottom: 0.3rem;">Provider → Call Site Usage</div>
                <div style="font-size: 0.72rem; color: var(--color-text-secondary);">
                  <template x-for="(info, name) in $store.genesisDashboard.health.api_keys" :key="'usage-' + name">
                    <div style="margin-bottom: 0.15rem;">
                      <span style="font-weight: 600;" x-text="name"></span>:
                      <span x-text="(() => { const sites = $store.genesisDashboard.providerCallSites(name); return sites.length ? sites.join(', ') : '(no call sites)'; })()"></span>
                    </div>
                  </template>
                </div>
              </div>
            </template>
          </div>
        </template>
      </div>
    </div>
  </div>

  <!-- Loading state -->
  <div class="loading-overlay" x-show="$store.genesisDashboard.loading">
    <span class="material-symbols-outlined" style="animation: spin 1s linear infinite; font-size: 2rem">progress_activity</span>
  </div>

  <!-- Module Detail Modal -->
  <div class="config-modal-overlay" x-show="$store.genesisDashboard.selectedModule"
       @click.self="$store.genesisDashboard.selectedModule = null" x-transition>
    <div class="config-modal" style="max-width: 600px;">
      <template x-if="$store.genesisDashboard.selectedModule">
        <div>
          <div class="config-modal-header">
            <span x-text="$store.genesisDashboard.selectedModule.name.replace('_', ' ')" style="text-transform: capitalize;"></span>
            <span style="font-size: 0.7rem; padding: 2px 8px; border-radius: 4px; font-weight: 500; margin-left: 0.5rem;"
                  :style="`background: ${$store.genesisDashboard.selectedModule.enabled ? '#1b5e20' : '#424242'}; color: ${$store.genesisDashboard.selectedModule.enabled ? '#81c784' : '#999'}`"
                  x-text="$store.genesisDashboard.selectedModule.enabled ? 'active' : 'disabled'"></span>
            <button @click="$store.genesisDashboard.selectedModule = null">&times;</button>
          </div>
          <div class="config-modal-body">
            <!-- Description -->
            <div style="margin-bottom: 1rem; line-height: 1.5; color: #ccc; font-size: 0.85rem;"
                 x-text="$store.genesisDashboard.selectedModule.description || 'No description available.'"></div>

            <!-- External Module Info -->
            <template x-if="$store.genesisDashboard.selectedModule.type === 'external'">
              <div style="margin-bottom: 0.75rem; padding: 0.6rem; background: rgba(33,150,243,0.06); border-radius: 6px; border: 1px solid rgba(33,150,243,0.15);">
                <div style="font-weight: 600; font-size: 0.78rem; color: #90caf9; margin-bottom: 0.4rem;">
                  <span class="material-symbols-outlined" style="font-size: 0.85rem; vertical-align: text-bottom;">lan</span>
                  External Program
                </div>
                <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.4rem;">
                  <div style="padding: 0.3rem 0.4rem; background: rgba(255,255,255,0.04); border-radius: 4px;">
                    <div style="font-size: 0.65rem; color: #888;">IPC Method</div>
                    <div style="font-size: 0.8rem; color: #e0e0e0; font-weight: 600;" x-text="$store.genesisDashboard.selectedModule.ipc_method?.toUpperCase()"></div>
                  </div>
                  <div style="padding: 0.3rem 0.4rem; background: rgba(255,255,255,0.04); border-radius: 4px;">
                    <div style="font-size: 0.65rem; color: #888;">Connection</div>
                    <div style="font-size: 0.8rem; font-weight: 600;"
                         :style="$store.genesisDashboard.selectedModule.ipc_healthy ? 'color:#4caf50' : 'color:#d9534f'"
                         x-text="$store.genesisDashboard.selectedModule.ipc_healthy ? 'Connected' : 'Disconnected'"></div>
                  </div>
                  <template x-if="$store.genesisDashboard.selectedModule.has_lifecycle">
                    <div style="padding: 0.3rem 0.4rem; background: rgba(255,255,255,0.04); border-radius: 4px;">
                      <div style="font-size: 0.65rem; color: #888;">Lifecycle</div>
                      <div style="font-size: 0.8rem; color: #81c784; font-weight: 600;">SSH managed</div>
                    </div>
                  </template>
                  <template x-if="$store.genesisDashboard.selectedModule.health_endpoint">
                    <div style="padding: 0.3rem 0.4rem; background: rgba(255,255,255,0.04); border-radius: 4px;">
                      <div style="font-size: 0.65rem; color: #888;">Health Endpoint</div>
                      <div style="font-size: 0.75rem; color: #e0e0e0; font-family: monospace;" x-text="$store.genesisDashboard.selectedModule.health_endpoint"></div>
                    </div>
                  </template>
                </div>
                <template x-if="$store.genesisDashboard.selectedModule.ipc_url">
                  <div style="margin-top: 0.4rem; font-size: 0.72rem; color: #7986cb; font-family: monospace;" x-text="$store.genesisDashboard.selectedModule.ipc_url"></div>
                </template>
                <template x-if="$store.genesisDashboard.selectedModule.ipc_error">
                  <div style="margin-top: 0.3rem; font-size: 0.72rem; color: #ef9a9a;" x-text="$store.genesisDashboard.selectedModule.ipc_error"></div>
                </template>
              </div>
            </template>

            <!-- Research Profile -->
            <template x-if="$store.genesisDashboard.selectedModule.research_profile">
              <div style="margin-bottom: 0.75rem;">
                <span style="font-weight: 600; font-size: 0.78rem; color: #aaa;">Research Profile:</span>
                <span style="font-size: 0.78rem; color: #e0e0e0;" x-text="$store.genesisDashboard.selectedModule.research_profile"></span>
              </div>
            </template>

            <!-- Health (universal — assembled from existing data) -->
            <template x-if="$store.genesisDashboard.selectedModule.health">
              <div style="margin-bottom: 0.75rem;">
                <div style="font-weight: 600; font-size: 0.78rem; color: #aaa; margin-bottom: 0.4rem;">Health</div>
                <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 0.4rem;">
                  <div style="padding: 0.4rem 0.5rem; background: rgba(255,255,255,0.04); border-radius: 5px; border: 1px solid var(--color-border);">
                    <div style="font-size: 0.68rem; color: #888;">Status</div>
                    <div style="font-size: 0.82rem; font-weight: 600;"
                         :style="({'healthy':'color:#4caf50','error':'color:#d9534f','disabled':'color:#888','idle':'color:#f0ad4e','no_pipeline':'color:#f0ad4e','unknown':'color:#888'})[$store.genesisDashboard.selectedModule.health.status] || 'color:#888'"
                         x-text="$store.genesisDashboard.selectedModule.health.status"></div>
                  </div>
                  <template x-if="$store.genesisDashboard.selectedModule.health.last_run">
                    <div style="padding: 0.4rem 0.5rem; background: rgba(255,255,255,0.04); border-radius: 5px; border: 1px solid var(--color-border);">
                      <div style="font-size: 0.68rem; color: #888;">Last Run</div>
                      <div style="font-size: 0.78rem; color: #e0e0e0;"
                           x-text="$store.genesisDashboard.relativeTime($store.genesisDashboard.selectedModule.health.last_run)"></div>
                    </div>
                  </template>
                  <template x-if="$store.genesisDashboard.selectedModule.health.success_rate != null">
                    <div style="padding: 0.4rem 0.5rem; background: rgba(255,255,255,0.04); border-radius: 5px; border: 1px solid var(--color-border);">
                      <div style="font-size: 0.68rem; color: #888;">Success Rate</div>
                      <div style="font-size: 0.82rem; font-weight: 600;"
                           :style="$store.genesisDashboard.selectedModule.health.success_rate >= 90 ? 'color:#4caf50' : $store.genesisDashboard.selectedModule.health.success_rate >= 70 ? 'color:#f0ad4e' : 'color:#d9534f'"
                           x-text="$store.genesisDashboard.selectedModule.health.success_rate + '%'"></div>
                    </div>
                  </template>
                  <template x-if="$store.genesisDashboard.selectedModule.health.total_runs">
                    <div style="padding: 0.4rem 0.5rem; background: rgba(255,255,255,0.04); border-radius: 5px; border: 1px solid var(--color-border);">
                      <div style="font-size: 0.68rem; color: #888;">Total Runs</div>
                      <div style="font-size: 0.82rem; color: #e0e0e0;"
                           x-text="$store.genesisDashboard.selectedModule.health.total_runs"></div>
                    </div>
                  </template>
                  <template x-if="$store.genesisDashboard.selectedModule.health.cost?.today_usd != null">
                    <div style="padding: 0.4rem 0.5rem; background: rgba(255,255,255,0.04); border-radius: 5px; border: 1px solid var(--color-border);">
                      <div style="font-size: 0.68rem; color: #888;">Cost (today)</div>
                      <div style="font-size: 0.78rem; color: #e0e0e0;"
                           x-text="'$' + $store.genesisDashboard.selectedModule.health.cost.today_usd.toFixed(3) + ' (' + $store.genesisDashboard.selectedModule.health.cost.today_calls + ')'"></div>
                    </div>
                  </template>
                  <template x-if="$store.genesisDashboard.selectedModule.health.cost?.month_usd != null">
                    <div style="padding: 0.4rem 0.5rem; background: rgba(255,255,255,0.04); border-radius: 5px; border: 1px solid var(--color-border);">
                      <div style="font-size: 0.68rem; color: #888;">Cost (month)</div>
                      <div style="font-size: 0.78rem; color: #e0e0e0;"
                           x-text="'$' + $store.genesisDashboard.selectedModule.health.cost.month_usd.toFixed(3)"></div>
                    </div>
                  </template>
                  <template x-if="$store.genesisDashboard.selectedModule.health.config_updated_at">
                    <div style="padding: 0.4rem 0.5rem; background: rgba(255,255,255,0.04); border-radius: 5px; border: 1px solid var(--color-border);">
                      <div style="font-size: 0.68rem; color: #888;">Config Updated</div>
                      <div style="font-size: 0.78rem; color: #e0e0e0;"
                           x-text="$store.genesisDashboard.relativeTime($store.genesisDashboard.selectedModule.health.config_updated_at)"></div>
                    </div>
                  </template>
                </div>
                <template x-if="$store.genesisDashboard.selectedModule.health.last_error">
                  <div style="margin-top: 0.4rem; padding: 0.3rem 0.5rem; background: rgba(217,83,79,0.08); border-radius: 4px; border: 1px solid rgba(217,83,79,0.2);">
                    <div style="font-size: 0.68rem; color: #d9534f; font-weight: 600;">Last Error</div>
                    <div style="font-size: 0.72rem; color: #ef9a9a; font-family: monospace; word-break: break-all;"
                         x-text="$store.genesisDashboard.selectedModule.health.last_error"></div>
                  </div>
                </template>
              </div>
            </template>

            <!-- Stats -->
            <template x-if="$store.genesisDashboard.selectedModule.stats">
              <div style="margin-bottom: 0.75rem;">
                <div style="font-weight: 600; font-size: 0.78rem; color: #aaa; margin-bottom: 0.4rem;">Statistics</div>
                <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 0.4rem;">
                  <template x-for="(val, key) in $store.genesisDashboard.selectedModule.stats" :key="key">
                    <div style="padding: 0.4rem 0.5rem; background: rgba(255,255,255,0.04); border-radius: 5px; border: 1px solid var(--color-border);">
                      <div style="font-size: 0.68rem; color: #888; text-transform: capitalize;" x-text="key.replace('_', ' ')"></div>
                      <div style="font-size: 0.9rem; font-weight: 600; color: #e0e0e0;"
                           x-text="typeof val === 'number' && !Number.isInteger(val) ? val.toFixed(3) : val"></div>
                    </div>
                  </template>
                </div>
              </div>
            </template>

            <!-- Configurable Fields -->
            <template x-if="($store.genesisDashboard.selectedModule.config_fields || []).length > 0">
              <div style="margin-bottom: 0.75rem;">
                <div style="font-weight: 600; font-size: 0.78rem; color: #aaa; margin-bottom: 0.4rem;">Configuration</div>
                <div style="display: grid; gap: 0.4rem;" x-data="{ saving: false, saved: false, saveError: '' }">
                  <template x-for="field in $store.genesisDashboard.selectedModule.config_fields" :key="field.name">
                    <div style="display: flex; align-items: center; gap: 0.5rem; font-size: 0.78rem;">
                      <!-- Label — asterisk for required fields -->
                      <label style="min-width: 140px; color: #ccc;" :title="field.description">
                        <span x-text="field.label"></span>
                        <template x-if="field.required"><span style="color: #ef9a9a; margin-left: 2px;">*</span></template>
                      </label>
                      <!-- Bool: toggle switch -->
                      <template x-if="field.type === 'bool'">
                        <label style="position: relative; display: inline-block; width: 36px; height: 20px; cursor: pointer;">
                          <input type="checkbox" :checked="field.value" @change="field.value = $el.checked"
                                 style="opacity: 0; width: 0; height: 0;">
                          <span :style="'position: absolute; inset: 0; border-radius: 10px; transition: 0.2s; ' +
                            (field.value ? 'background: #66bb6a;' : 'background: rgba(255,255,255,0.15);')"></span>
                          <span :style="'position: absolute; top: 2px; width: 16px; height: 16px; border-radius: 50%; transition: 0.2s; background: #fff; ' +
                            (field.value ? 'left: 18px;' : 'left: 2px;')"></span>
                        </label>
                      </template>
                      <!-- List: comma-separated text input -->
                      <template x-if="field.type === 'list'">
                        <input type="text"
                               :value="Array.isArray(field.value) ? field.value.join(', ') : field.value"
                               @change="field.value = $el.value.split(',').map(s => s.trim()).filter(s => s)"
                               style="width: 200px; padding: 0.25rem 0.4rem; border-radius: 4px; border: 1px solid var(--color-border); background: rgba(255,255,255,0.06); color: #e0e0e0; font-size: 0.78rem;"
                               placeholder="comma-separated values">
                      </template>
                      <!-- Str: plain text input -->
                      <template x-if="field.type === 'str'">
                        <input type="text"
                               :value="field.value"
                               @change="field.value = $el.value"
                               :placeholder="field.default !== undefined && field.default !== null ? String(field.default) : ''"
                               style="width: 200px; padding: 0.25rem 0.4rem; border-radius: 4px; border: 1px solid var(--color-border); background: rgba(255,255,255,0.06); color: #e0e0e0; font-size: 0.78rem;">
                      </template>
                      <!-- Secret: masked input, never pre-populated -->
                      <template x-if="field.type === 'secret'">
                        <input type="password"
                               placeholder="••••••••"
                               @change="field.value = $el.value"
                               autocomplete="new-password"
                               style="width: 200px; padding: 0.25rem 0.4rem; border-radius: 4px; border: 1px solid var(--color-border); background: rgba(255,255,255,0.06); color: #e0e0e0; font-size: 0.78rem;">
                      </template>
                      <!-- Enum: select dropdown -->
                      <template x-if="field.type === 'enum'">
                        <select :value="field.value" @change="field.value = $el.value"
                                style="width: 200px; padding: 0.25rem 0.4rem; border-radius: 4px; border: 1px solid var(--color-border); background: rgba(30,30,30,0.9); color: #e0e0e0; font-size: 0.78rem;">
                          <template x-for="opt in (field.options || [])" :key="opt.value">
                            <option :value="opt.value" :selected="opt.value == field.value" x-text="opt.label"></option>
                          </template>
                        </select>
                      </template>
                      <!-- Int: integer number input -->
                      <template x-if="field.type === 'int'">
                        <input type="number" step="1"
                               :value="field.value"
                               :min="field.min !== undefined && field.min !== null ? field.min : undefined"
                               :max="field.max !== undefined && field.max !== null ? field.max : undefined"
                               :placeholder="field.default !== undefined && field.default !== null ? String(field.default) : ''"
                               @change="field.value = parseInt($el.value, 10)"
                               style="width: 100px; padding: 0.25rem 0.4rem; border-radius: 4px; border: 1px solid var(--color-border); background: rgba(255,255,255,0.06); color: #e0e0e0; font-size: 0.78rem;">
                      </template>
                      <!-- Float: decimal number input -->
                      <template x-if="field.type === 'float'">
                        <input type="number" step="any"
                               :value="field.value"
                               :min="field.min !== undefined && field.min !== null ? field.min : undefined"
                               :max="field.max !== undefined && field.max !== null ? field.max : undefined"
                               :placeholder="field.default !== undefined && field.default !== null ? String(field.default) : ''"
                               @change="field.value = parseFloat($el.value)"
                               style="width: 100px; padding: 0.25rem 0.4rem; border-radius: 4px; border: 1px solid var(--color-border); background: rgba(255,255,255,0.06); color: #e0e0e0; font-size: 0.78rem;">
                      </template>
                      <span style="font-size: 0.64rem; opacity: 0.5;" x-text="field.description"></span>
                    </div>
                  </template>
                  <!-- Save error message -->
                  <template x-if="saveError">
                    <div style="font-size: 0.72rem; color: #ef9a9a; padding: 0.2rem 0;" x-text="saveError"></div>
                  </template>
                  <button @click="
                    saveError = '';
                    // Frontend pre-validation
                    const fields = $store.genesisDashboard.selectedModule.config_fields;
                    const errs = [];
                    fields.forEach(f => {
                      if (f.required && (f.value === null || f.value === undefined || f.value === '')) {
                        errs.push(f.label + ' is required');
                      }
                      if ((f.type === 'int' || f.type === 'float') && f.value !== null && f.value !== undefined && f.value !== '') {
                        const v = parseFloat(f.value);
                        if (f.min !== undefined && f.min !== null && v < f.min) errs.push(f.label + ' must be >= ' + f.min);
                        if (f.max !== undefined && f.max !== null && v > f.max) errs.push(f.label + ' must be <= ' + f.max);
                      }
                    });
                    if (errs.length > 0) { saveError = errs.join('; '); return; }
                    saving = true; saved = false;
                    const updates = {};
                    fields.forEach(f => {
                      // Secret fields: only include if user typed a value
                      if (f.type === 'secret') { if (f.value) updates[f.name] = f.value; }
                      else updates[f.name] = f.value;
                    });
                    fetch('/api/genesis/modules/' + $store.genesisDashboard.selectedModule.name + '/config', {
                      method: 'PATCH', headers: {'Content-Type': 'application/json'},
                      body: JSON.stringify(updates)
                    }).then(r => r.json()).then(d => {
                      saving = false;
                      if (d.status === 'ok') { saved = true; setTimeout(() => saved = false, 2000); }
                      else { saveError = d.message || 'Save failed'; }
                    }).catch(() => { saving = false; saveError = 'Network error'; });
                  " style="width: fit-content; font-size: 0.74rem; padding: 0.3rem 0.7rem; border-radius: 4px; cursor: pointer; background: rgba(33,150,243,0.15); color: #90caf9; border: 1px solid rgba(33,150,243,0.3);"
                  x-text="saving ? 'Saving...' : saved ? 'Saved!' : 'Save Config'"></button>
                </div>
              </div>
            </template>

            <!-- Controls -->
            <div style="border-top: 1px solid var(--color-border); padding-top: 0.75rem; display: flex; gap: 0.5rem;">
              <button @click="$store.genesisDashboard.toggleModule($store.genesisDashboard.selectedModule.name); $store.genesisDashboard.selectedModule.enabled = !$store.genesisDashboard.selectedModule.enabled;"
                      style="font-size: 0.78rem; padding: 0.4rem 0.8rem; border-radius: 5px; cursor: pointer; border: 1px solid; font-weight: 500;"
                      :style="$store.genesisDashboard.selectedModule.enabled
                        ? 'background: transparent; color: #ef9a9a; border-color: #ef9a9a;'
                        : 'background: transparent; color: #81c784; border-color: #81c784;'"
                      x-text="$store.genesisDashboard.selectedModule.enabled ? 'Disable Module' : 'Enable Module'"></button>
            </div>
          </div>
        </div>
      </template>
    </div>
  </div>

  <!-- Kill Switch Footer -->
  <div style="position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000;
              background: var(--color-bg); border-top: 1px solid var(--color-border);
              padding: 0.5rem 1.5rem; display: flex; align-items: center; justify-content: space-between;"
       x-data>
    <div style="display: flex; align-items: center; gap: 0.75rem; font-size: 0.78rem;">
      <template x-if="$store.genesisDashboard.pauseState.paused">
        <div style="display: flex; align-items: center; gap: 0.5rem;">
          <span style="display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #ffa726;"></span>
          <span style="color: #ffa726; font-weight: 600;">PAUSED</span>
          <span style="color: var(--color-text-secondary);"
                x-text="$store.genesisDashboard.pauseState.since
                  ? 'since ' + new Date($store.genesisDashboard.pauseState.since).toLocaleTimeString()
                  : ''"></span>
        </div>
      </template>
      <template x-if="!$store.genesisDashboard.pauseState.paused">
        <div style="display: flex; align-items: center; gap: 0.5rem;">
          <span style="display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #66bb6a;"></span>
          <span style="color: #66bb6a; font-weight: 600;">RUNNING</span>
        </div>
      </template>
    </div>
    <button @click="$store.genesisDashboard.togglePause()"
            :disabled="$store.genesisDashboard.pauseState.toggling"
            style="font-size: 0.74rem; padding: 0.35rem 0.9rem; border-radius: 4px; cursor: pointer;
                   font-weight: 500; transition: all 0.15s;"
            :style="$store.genesisDashboard.pauseState.paused
              ? 'background: rgba(102,187,106,0.12); color: #66bb6a; border: 1px solid rgba(102,187,106,0.3);'
              : 'background: rgba(255,167,38,0.12); color: #ffa726; border: 1px solid rgba(255,167,38,0.3);'"
            x-text="$store.genesisDashboard.pauseState.toggling ? '...'
              : $store.genesisDashboard.pauseState.paused ? 'Resume Genesis' : 'Pause Genesis'">
    </button>
  </div>
  <!-- ═══════════════════════════════════════════════════════════════
       Panel: Chat [Tab: chat]
       ═══════════════════════════════════════════════════════════════ -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'chat'">
      <div class="panel-header">
        <span class="material-symbols-outlined">terminal</span>
        Genesis / Claude Code Terminal
      </div>
      <div class="panel-body">
        <div style="padding:2rem; text-align:center;">
          <span class="material-symbols-outlined" style="font-size:2.5rem; color:#555; display:block; margin-bottom:0.75rem;">terminal</span>
          <div style="margin-bottom:0.5rem; color:var(--color-text-secondary); font-size:0.85rem;">
            Open a shell in the Genesis project directory.
          </div>
          <button @click="$store.genesisDashboard.openTerminal()"
                  style="font-size:0.8rem; padding:0.5rem 1.5rem; border-radius:4px; cursor:pointer;
                         background:rgba(33,150,243,0.15); color:#2196F3; border:1px solid rgba(33,150,243,0.3);
                         font-weight:500;">Open Terminal</button>
        </div>
      </div>
    </div>

    <!-- ── Communication: Outreach + Proposals [Tab: chat] ─── -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'chat'">
      <div class="panel-header">
        <span class="material-symbols-outlined">forum</span>
        Communication
        <span class="panel-status">
          <span style="font-size:0.72rem; opacity:0.7;"
                x-text="(() => {
                  const c = $store.genesisDashboard.commsCounts;
                  const parts = [];
                  if (c.proposals_pending) parts.push(c.proposals_pending + ' proposal' + (c.proposals_pending > 1 ? 's' : ''));
                  if (c.pending_approvals) parts.push(c.pending_approvals + ' approval' + (c.pending_approvals > 1 ? 's' : ''));
                  return parts.length ? parts.join(' · ') : '';
                })()"></span>
        </span>
      </div>
      <div class="panel-body">
        <!-- Sub-tabs -->
        <div style="display:flex; gap:0.25rem; margin-bottom:0.75rem;">
          <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer;"
                  :style="$store.genesisDashboard.commsTab === 'outreach' ? 'background:#2196F333; border:1px solid #2196F3; color:#2196F3; font-weight:600;' : 'background:transparent; border:1px solid #666; color:#aaa;'"
                  @click="$store.genesisDashboard.commsTab = 'outreach'">Outreach</button>
          <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer;"
                  :style="$store.genesisDashboard.commsTab === 'proposals' ? 'background:#ce93d833; border:1px solid #ce93d8; color:#ce93d8; font-weight:600;' : 'background:transparent; border:1px solid #666; color:#aaa;'"
                  @click="$store.genesisDashboard.commsTab = 'proposals'">
            Proposals
            <template x-if="$store.genesisDashboard.commsCounts.proposals_pending > 0">
              <span style="background:#ce93d8; color:#000; font-size:0.6rem; padding:0.05rem 0.25rem; border-radius:8px; margin-left:0.25rem;"
                    x-text="$store.genesisDashboard.commsCounts.proposals_pending"></span>
            </template>
          </button>
          <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer;"
                  :style="$store.genesisDashboard.commsTab === 'approvals' ? 'background:#4caf5033; border:1px solid #4caf50; color:#4caf50; font-weight:600;' : 'background:transparent; border:1px solid #666; color:#aaa;'"
                  @click="$store.genesisDashboard.commsTab = 'approvals'; $store.genesisDashboard.fetchApprovals()">
            Approvals
            <template x-if="$store.genesisDashboard.pendingApprovalCount > 0">
              <span style="background:#4caf50; color:#000; font-size:0.6rem; padding:0.05rem 0.25rem; border-radius:8px; margin-left:0.25rem;"
                    x-text="$store.genesisDashboard.pendingApprovalCount"></span>
            </template>
          </button>
        </div>

        <!-- View toggle -->
        <div style="display:flex; gap:0.25rem; margin-bottom:0.75rem;">
          <button style="font-size:0.68rem; padding:0.15rem 0.5rem; border-radius:3px; cursor:pointer;"
                  :style="$store.genesisDashboard.commsView === 'pending' ? 'background:#ffffff15; border:1px solid #888; color:#fff;' : 'background:transparent; border:1px solid #555; color:#888;'"
                  @click="$store.genesisDashboard.commsView = 'pending'; $store.genesisDashboard.fetchComms()">Pending</button>
          <button style="font-size:0.68rem; padding:0.15rem 0.5rem; border-radius:3px; cursor:pointer;"
                  :style="$store.genesisDashboard.commsView === 'all' ? 'background:#ffffff15; border:1px solid #888; color:#fff;' : 'background:transparent; border:1px solid #555; color:#888;'"
                  @click="$store.genesisDashboard.commsView = 'all'; $store.genesisDashboard.fetchComms()">All</button>
        </div>

        <!-- Pending approvals banner -->
        <template x-if="$store.genesisDashboard.commsPendingApprovals.length > 0">
          <div style="background:#d9534f1a; border:1px solid #d9534f44; border-radius:6px; padding:0.6rem 0.75rem; margin-bottom:0.75rem;">
            <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.3rem;">
              <span style="font-weight:600; font-size:0.82rem; color:#d9534f;">
                Action Required
                <span style="background:#d9534f; color:white; font-size:0.65rem; padding:0.1rem 0.35rem; border-radius:10px; margin-left:0.3rem;"
                      x-text="$store.genesisDashboard.commsPendingApprovals.length"></span>
              </span>
              <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border:1px solid #4caf50; color:#4caf50; border-radius:3px; cursor:pointer; background:transparent;"
                      @click="$store.genesisDashboard.approveAllPending()">Approve All</button>
            </div>
            <template x-for="a in $store.genesisDashboard.commsPendingApprovals" :key="a.id">
              <div style="display:flex; justify-content:space-between; align-items:center; padding:0.25rem 0; border-top:1px solid #d9534f22;">
                <div>
                  <span style="font-size:0.75rem;" x-text="a.description || a.action_type"></span>
                  <span style="font-size:0.62rem; color:#888; margin-left:0.3rem;" x-text="$store.genesisDashboard.formatDateTime(a.created_at)"></span>
                </div>
                <div style="display:flex; gap:0.25rem;">
                  <button style="font-size:0.65rem; padding:0.15rem 0.4rem; border:1px solid #4caf50; color:#4caf50; border-radius:3px; cursor:pointer; background:transparent;"
                          @click="$store.genesisDashboard.resolveApproval(a.id, 'approved')">Approve</button>
                  <button style="font-size:0.65rem; padding:0.15rem 0.4rem; border:1px solid #d9534f; color:#d9534f; border-radius:3px; cursor:pointer; background:transparent;"
                          @click="$store.genesisDashboard.resolveApproval(a.id, 'rejected')">Deny</button>
                </div>
              </div>
            </template>
          </div>
        </template>

        <!-- ── Outreach messages ──────────────────────────── -->
        <div x-show="$store.genesisDashboard.commsTab === 'outreach'">
          <!-- Category filters -->
          <div style="display:flex; gap:0.4rem; margin-bottom:0.75rem; flex-wrap:wrap;">
            <template x-for="cat in [null, 'alert', 'digest', 'surplus', 'blocker']" :key="cat || 'all'">
              <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer; transition:opacity 0.15s;"
                      :style="`border:1px solid ${cat ? '#888' : '#4caf50'}; background:${$store.genesisDashboard.commsCategoryFilter === cat ? (cat ? '#88888833' : '#4caf5033') : 'transparent'}; color:${$store.genesisDashboard.commsCategoryFilter === cat ? '#fff' : '#aaa'}; opacity:${$store.genesisDashboard.commsCategoryFilter === cat || $store.genesisDashboard.commsCategoryFilter === null && cat === null ? '1' : '0.6'}`"
                      @click="$store.genesisDashboard.commsCategoryFilter = cat"
                      x-text="cat ? cat.charAt(0).toUpperCase() + cat.slice(1) : 'All'"></button>
            </template>
          </div>
          <template x-if="$store.genesisDashboard.commsOutreach.filter(m => m.signal_type !== 'cli_approval').length === 0">
            <div style="color:var(--color-text-secondary); text-align:center; padding:2rem; font-size:0.75rem;">No outreach messages found.</div>
          </template>
          <template x-for="msg in $store.genesisDashboard.commsOutreach.filter(m => m.signal_type !== 'cli_approval').filter(m => !$store.genesisDashboard.commsCategoryFilter || m.category === $store.genesisDashboard.commsCategoryFilter)" :key="msg.id">
            <div style="border:1px solid var(--color-border); border-radius:6px; padding:0.75rem; margin-bottom:0.5rem;">
              <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.3rem;">
                <div>
                  <span style="font-weight:600; font-size:0.85rem;" x-text="msg.topic || msg.signal_type || 'Untitled'"></span>
                  <span style="font-size:0.68rem; padding:0.1rem 0.3rem; border-radius:3px; margin-left:0.3rem;"
                        :style="`background:${(msg.category === 'blocker' || msg.category === 'approval') ? '#d9534f33' : msg.category === 'alert' ? '#f0ad4e33' : msg.category === 'digest' ? '#2196F333' : '#4caf5033'}; color:${(msg.category === 'blocker' || msg.category === 'approval') ? '#d9534f' : msg.category === 'alert' ? '#f0ad4e' : msg.category === 'digest' ? '#2196F3' : '#4caf50'}`"
                        x-text="msg.category"></span>
                </div>
                <span style="font-size:0.68rem; color:var(--color-text-secondary);"
                      x-text="msg.channel + ' · ' + $store.genesisDashboard.formatDateTime(msg.created_at)"></span>
              </div>
              <div style="font-size:0.8rem; white-space:pre-wrap; max-height:150px; overflow-y:auto; padding:0.4rem; background:var(--color-background); border-radius:4px; margin-bottom:0.3rem;"
                   x-text="msg.message_content || '(no content)'"></div>
              <!-- Engagement buttons -->
              <div style="display:flex; gap:0.3rem; align-items:center;">
                <template x-if="msg.category === 'blocker' || msg.category === 'approval'">
                  <div style="display:flex; gap:0.3rem;">
                    <template x-for="btn in [{value:'approved',label:'Approve',color:'#4caf50'},{value:'rejected',label:'Deny',color:'#d9534f'}]" :key="btn.value">
                      <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border-radius:3px; cursor:pointer;"
                              :style="`border:1px solid ${btn.color}; color:${btn.color}; background:${msg.user_response === (btn.value === 'approved' ? 'approve' : 'deny') ? btn.color + '33' : 'transparent'};`"
                              @click="$store.genesisDashboard.engageOutreach(msg.id, btn.value === 'approved' ? 'useful' : 'not_useful', btn.value === 'approved' ? 'approve' : 'deny')"
                              x-text="btn.label"></button>
                    </template>
                  </div>
                </template>
                <template x-if="msg.category === 'alert'">
                  <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border-radius:3px; cursor:pointer;"
                          :style="`border:1px solid #f0ad4e; color:#f0ad4e; background:${msg.engagement_outcome === 'useful' ? '#f0ad4e33' : 'transparent'};`"
                          @click="$store.genesisDashboard.engageOutreach(msg.id, 'useful')"
                          x-text="msg.engagement_outcome === 'useful' ? 'Acknowledged' : 'Acknowledge'"></button>
                </template>
                <template x-if="msg.category !== 'blocker' && msg.category !== 'alert' && msg.category !== 'approval'">
                  <div style="display:flex; gap:0.3rem;">
                    <template x-for="btn in [{value:'useful',label:'Useful',color:'#4caf50'},{value:'not_useful',label:'Not Useful',color:'#d9534f'},{value:'ambivalent',label:'Ambivalent',color:'#888'}]" :key="btn.value">
                      <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border-radius:3px; cursor:pointer;"
                              :style="`border:1px solid ${btn.color}; color:${btn.color}; background:${msg.engagement_outcome === btn.value ? btn.color + '33' : 'transparent'}; opacity:${!msg.engagement_outcome || msg.engagement_outcome === btn.value ? '1' : '0.4'};`"
                              @click="$store.genesisDashboard.engageOutreach(msg.id, btn.value)"
                              x-text="btn.label"></button>
                    </template>
                  </div>
                </template>
              </div>
            </div>
          </template>
        </div>

        <!-- ── Ego Proposals ──────────────────────────────── -->
        <div x-show="$store.genesisDashboard.commsTab === 'proposals'">
          <!-- Status filter pills -->
          <div style="display:flex; gap:0.4rem; margin-bottom:0.75rem; flex-wrap:wrap;">
            <template x-for="[val, label] in [[null, 'All'], ['pending', 'Pending'], ['approved', 'Approved'], ['executed', 'Executed'], ['rejected', 'Rejected'], ['expired', 'Expired']]" :key="val || 'all'">
              <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer;"
                      :style="$store.genesisDashboard.commsProposalFilter === val ? 'background:#ffffff15; border:1px solid #888; color:#fff;' : 'background:transparent; border:1px solid #555; color:#888;'"
                      @click="$store.genesisDashboard.commsProposalFilter = val"
                      x-text="label"></button>
            </template>
          </div>
          <template x-if="$store.genesisDashboard.commsProposals.length === 0">
            <div style="color:var(--color-text-secondary); text-align:center; padding:2rem; font-size:0.75rem;">No proposals. The ego hasn't produced any proposals yet.</div>
          </template>
          <template x-for="p in $store.genesisDashboard.commsProposals.filter(p => !$store.genesisDashboard.commsProposalFilter || p.status === $store.genesisDashboard.commsProposalFilter)" :key="p.id">
            <div style="border:1px solid var(--color-border); border-radius:6px; padding:0.75rem; margin-bottom:0.5rem;">
              <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.3rem;">
                <div style="display:flex; gap:0.3rem; align-items:center;">
                  <span style="font-size:0.65rem; padding:0.08rem 0.35rem; border-radius:3px; font-weight:600; text-transform:uppercase;"
                        :style="{
                          'pending':  'background:rgba(255,167,38,0.15); color:#ffa726;',
                          'approved': 'background:rgba(102,187,106,0.15); color:#66bb6a;',
                          'rejected': 'background:rgba(239,154,154,0.15); color:#ef9a9a;',
                          'expired':  'background:rgba(158,158,158,0.15); color:#9e9e9e;',
                          'executed': 'background:rgba(33,150,243,0.15); color:#2196F3;',
                        }[p.status] || 'background:rgba(158,158,158,0.15); color:#9e9e9e;'"
                        x-text="p.status"></span>
                  <span x-show="p.ego_source" style="font-size:0.65rem; padding:0.1rem 0.4rem; border-radius:3px; font-weight:600; text-transform:uppercase;"
                        :style="p.ego_source === 'genesis_ego_cycle' ? 'background:rgba(156,39,176,0.25); color:#e1bee7;' : 'background:rgba(33,150,243,0.25); color:#90caf9;'"
                        x-text="p.ego_source === 'genesis_ego_cycle' ? 'Genesis' : p.ego_source === 'user_ego_cycle' ? 'User' : 'Ego'"></span>
                  <span x-show="p.action_type" style="font-size:0.65rem; padding:0.08rem 0.35rem; border-radius:3px; background:rgba(33,150,243,0.1); color:#64b5f6;"
                        x-text="p.action_type"></span>
                  <span x-show="p.urgency && p.urgency !== 'normal'" style="font-size:0.65rem; padding:0.08rem 0.35rem; border-radius:3px;"
                        :style="p.urgency === 'high' || p.urgency === 'critical' ? 'background:rgba(239,154,154,0.15); color:#ef9a9a;' : ''"
                        x-text="p.urgency"></span>
                </div>
                <span style="font-size:0.65rem; color:var(--color-text-secondary);"
                      x-text="$store.genesisDashboard.formatDateTime(p.created_at)"></span>
              </div>
              <!-- Confidence bar -->
              <template x-if="p.confidence != null">
                <div style="margin-bottom:0.3rem;">
                  <div style="display:flex; align-items:center; gap:0.3rem;">
                    <div style="flex:1; height:4px; background:rgba(255,255,255,0.1); border-radius:2px; overflow:hidden;">
                      <div style="height:100%; border-radius:2px; transition:width 0.3s;"
                           :style="`width:${(p.confidence * 100)}%; background:${p.confidence > 0.7 ? '#66bb6a' : p.confidence > 0.4 ? '#ffa726' : '#ef9a9a'};`"></div>
                    </div>
                    <span style="font-size:0.6rem; color:var(--color-text-secondary);" x-text="(p.confidence * 100).toFixed(0) + '%'"></span>
                  </div>
                </div>
              </template>
              <div style="font-size:0.8rem; margin-bottom:0.3rem; line-height:1.4;" x-text="p.content"></div>
              <template x-if="p.rationale">
                <div style="font-size:0.7rem; color:var(--color-text-secondary); margin-bottom:0.3rem;" x-text="'Rationale: ' + p.rationale"></div>
              </template>
              <!-- Execution outcome for executed proposals -->
              <template x-if="p.session_outcome">
                <div style="margin-top:0.4rem; padding:0.5rem; border-radius:4px; font-size:0.72rem;"
                     :style="p.session_outcome.status === 'completed' ? 'background:rgba(102,187,106,0.08); border:1px solid rgba(102,187,106,0.2);' : 'background:rgba(239,154,154,0.08); border:1px solid rgba(239,154,154,0.2);'">
                  <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.25rem;">
                    <div style="display:flex; gap:0.4rem; align-items:center;">
                      <span style="font-weight:600;"
                            :style="p.session_outcome.status === 'completed' ? 'color:#66bb6a;' : 'color:#ef9a9a;'"
                            x-text="p.session_outcome.status === 'completed' ? 'Completed' : p.session_outcome.status === 'failed' ? 'Failed' : p.session_outcome.status"></span>
                      <span x-show="p.session_outcome.profile" style="font-size:0.65rem; padding:0.08rem 0.3rem; border-radius:3px; background:rgba(33,150,243,0.1); color:#64b5f6;"
                            x-text="p.session_outcome.profile"></span>
                    </div>
                    <div style="display:flex; gap:0.5rem; align-items:center; color:var(--color-text-secondary); font-size:0.65rem;">
                      <span x-show="p.session_outcome.cost_usd != null" x-text="'$' + Number(p.session_outcome.cost_usd || 0).toFixed(2)"></span>
                      <span x-show="p.session_outcome.completed_at" x-text="$store.genesisDashboard.formatDateTime(p.session_outcome.completed_at)"></span>
                    </div>
                  </div>
                  <template x-if="p.session_outcome.error">
                    <div style="font-size:0.7rem; color:#ef9a9a; white-space:pre-wrap; max-height:80px; overflow-y:auto;" x-text="p.session_outcome.error"></div>
                  </template>
                  <template x-if="p.session_outcome.output_summary && !p.session_outcome.error">
                    <div style="font-size:0.7rem; color:var(--color-text-secondary); white-space:pre-wrap; max-height:80px; overflow-y:auto;" x-text="p.session_outcome.output_summary"></div>
                  </template>
                  <template x-if="!p.session_outcome.output_summary && !p.session_outcome.error">
                    <div style="font-size:0.68rem; color:var(--color-text-secondary); font-style:italic;">No output captured</div>
                  </template>
                </div>
              </template>
              <!-- Response for non-executed proposals -->
              <template x-if="p.user_response && !p.session_outcome">
                <div style="font-size:0.7rem; color:var(--color-text-secondary); margin-top:0.2rem;">
                  <strong>Response:</strong> <span x-text="p.user_response"></span>
                </div>
              </template>
              <!-- Approve/Reject for pending -->
              <template x-if="p.status === 'pending'">
                <div style="display:flex; gap:0.3rem; margin-top:0.4rem;">
                  <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border-radius:3px; cursor:pointer; border:1px solid #4caf50; color:#4caf50; background:transparent;"
                          @click="$store.genesisDashboard.resolveCommsProposal(p.id, 'approved')">Approve</button>
                  <template x-if="$store.genesisDashboard.commsRejectingId !== p.id">
                    <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border-radius:3px; cursor:pointer; border:1px solid #d9534f; color:#d9534f; background:transparent;"
                            @click="$store.genesisDashboard.commsRejectingId = p.id">Reject</button>
                  </template>
                  <template x-if="$store.genesisDashboard.commsRejectingId === p.id">
                    <div style="display:flex; gap:0.25rem; flex:1;">
                      <input type="text" x-model="$store.genesisDashboard.commsRejectReason" placeholder="Reason (optional)"
                             style="flex:1; font-size:0.68rem; padding:0.2rem 0.4rem; background:var(--color-background); border:1px solid var(--color-border); color:var(--color-text); border-radius:3px;">
                      <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border-radius:3px; cursor:pointer; border:1px solid #d9534f; color:#d9534f; background:#d9534f22;"
                              @click="$store.genesisDashboard.resolveCommsProposal(p.id, 'rejected', $store.genesisDashboard.commsRejectReason)">Confirm</button>
                      <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border-radius:3px; cursor:pointer; border:1px solid #666; color:#888; background:transparent;"
                              @click="$store.genesisDashboard.commsRejectingId = null; $store.genesisDashboard.commsRejectReason = ''">Cancel</button>
                    </div>
                  </template>
                </div>
              </template>
            </div>
          </template>
        </div>

        <!-- ── Approvals ────────────────────────────────── -->
        <div x-show="$store.genesisDashboard.commsTab === 'approvals'">
          <template x-if="$store.genesisDashboard.approvals.length === 0">
            <div style="color:var(--color-text-secondary); text-align:center; padding:2rem; font-size:0.75rem;">No pending approvals.</div>
          </template>
          <template x-if="$store.genesisDashboard.approvals.length > 0">
            <div style="display:grid; gap:0.6rem;">
              <template x-for="req in $store.genesisDashboard.approvals" :key="req.id">
                <div style="padding:0.65rem 0.75rem; border-radius:6px; border:1px solid var(--color-border); background:rgba(255,255,255,0.03);">
                  <div style="display:flex; align-items:flex-start; justify-content:space-between; gap:0.6rem; margin-bottom:0.35rem;">
                    <div>
                      <div style="font-size:0.8rem; font-weight:600;" x-text="$store.genesisDashboard.approvalActionLabel(req)"></div>
                      <div style="font-size:0.68rem; color:var(--color-text-secondary); margin-top:0.15rem;"
                           x-text="(req.context_data?.subsystem || 'unknown subsystem') + ' · ' + $store.genesisDashboard.relativeTime(req.created_at)"></div>
                    </div>
                    <div style="font-size:0.66rem; font-family:monospace; color:var(--color-text-secondary);" x-text="req.id"></div>
                  </div>
                  <div style="display:grid; grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:0.45rem; font-size:0.72rem;">
                    <div>
                      <div style="opacity:0.6; text-transform:uppercase; letter-spacing:0.04em; font-size:0.62rem;">Fallback</div>
                      <div x-text="$store.genesisDashboard.approvalFallbackLabel(req)"></div>
                    </div>
                    <div>
                      <div style="opacity:0.6; text-transform:uppercase; letter-spacing:0.04em; font-size:0.62rem;">Reason</div>
                      <div x-text="$store.genesisDashboard.approvalReasonLabel(req)"></div>
                    </div>
                    <div>
                      <div style="opacity:0.6; text-transform:uppercase; letter-spacing:0.04em; font-size:0.62rem;">API Route</div>
                      <div x-text="req.context_data?.api_call_site_id || 'none'"></div>
                    </div>
                    <div>
                      <div style="opacity:0.6; text-transform:uppercase; letter-spacing:0.04em; font-size:0.62rem;">Channel</div>
                      <div x-text="req.context_data?.channel || 'dashboard-only'"></div>
                    </div>
                  </div>
                  <div style="display:flex; gap:0.45rem; flex-wrap:wrap; margin-top:0.6rem;">
                    <button type="button"
                            style="font-size:0.68rem; padding:0.24rem 0.5rem; border-radius:4px; border:1px solid rgba(76,175,80,0.28); color:#4caf50; background:transparent; cursor:pointer;"
                            :disabled="$store.genesisDashboard.approvalActionState(req.id).saving"
                            @click="$store.genesisDashboard.resolveApproval(req.id, 'approved')"
                            x-text="$store.genesisDashboard.approvalActionState(req.id).saving ? 'Saving...' : 'Approve'"></button>
                    <button type="button"
                            style="font-size:0.68rem; padding:0.24rem 0.5rem; border-radius:4px; border:1px solid rgba(217,83,79,0.28); color:#d9534f; background:transparent; cursor:pointer;"
                            :disabled="$store.genesisDashboard.approvalActionState(req.id).saving"
                            @click="$store.genesisDashboard.resolveApproval(req.id, 'rejected')">Reject</button>
                  </div>
                  <template x-if="$store.genesisDashboard.approvalActionState(req.id).error">
                    <div style="font-size:0.68rem; color:#d9534f; margin-top:0.35rem;"
                         x-text="$store.genesisDashboard.approvalActionState(req.id).error"></div>
                  </template>
                </div>
              </template>
            </div>
          </template>
        </div>
      </div>
    </div>

    <!-- ═══════════════════════════════════════════════════════════════
         Panel: File Browser [Tab: files]
         ═══════════════════════════════════════════════════════════════ -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'files'">
      <div class="panel-header">
        <span class="material-symbols-outlined">folder_open</span>
        File Browser
      </div>
      <div class="panel-body">
        <!-- File upload drop zone -->
        <div @dragover.prevent="$store.genesisDashboard.fileUpload.dragging = true"
             @dragleave.prevent="$store.genesisDashboard.fileUpload.dragging = false"
             @drop.prevent="$store.genesisDashboard.uploadFile($event)"
             @click="$refs.fileUploadInput.click()"
             :style="`border: 1px dashed ${$store.genesisDashboard.fileUpload.dragging ? 'var(--color-accent)' : 'var(--color-border)'}; border-radius: 6px; padding: 0.6rem 1rem; text-align: center; cursor: pointer; margin-bottom: 0.75rem; transition: border-color .2s; background: ${$store.genesisDashboard.fileUpload.dragging ? 'rgba(99,102,241,.06)' : 'transparent'};`">
          <span style="font-size: .8rem; color: var(--color-text-secondary);"
                x-text="$store.genesisDashboard.fileUpload.uploading ? 'Uploading...' : 'Drop files here to upload — no processing, just storage'"></span>
          <input type="file" x-ref="fileUploadInput" style="display:none" @change="$store.genesisDashboard.uploadFile($event)">
        </div>
        <template x-if="$store.genesisDashboard.fileUpload.error">
          <div style="color: var(--color-error-text); font-size: .8rem; margin-bottom: .5rem;" x-text="$store.genesisDashboard.fileUpload.error"></div>
        </template>
        <!-- Breadcrumb / path bar -->
        <div style="display:flex; gap:0.3rem; align-items:center; margin-bottom:0.75rem; font-size:0.75rem; flex-wrap:wrap;">
          <template x-if="$store.genesisDashboard.fileBrowser.parent">
            <button @click="$store.genesisDashboard.fetchFiles($store.genesisDashboard.fileBrowser.parent)"
                    style="cursor:pointer; background:rgba(33,150,243,0.1); color:#2196F3; border:1px solid rgba(33,150,243,0.2);
                           padding:0.15rem 0.5rem; border-radius:3px; font-size:0.72rem;">
              <span class="material-symbols-outlined" style="font-size:0.85rem;vertical-align:middle;">arrow_upward</span> Up
            </button>
          </template>
          <span style="color:var(--color-text-secondary); font-family:monospace; word-break:break-all;"
                x-text="$store.genesisDashboard.fileBrowser.path || 'Loading...'"></span>
          <button @click="$store.genesisDashboard.fileBrowser.sidebarCollapsed = !$store.genesisDashboard.fileBrowser.sidebarCollapsed"
                  style="cursor:pointer; background:rgba(255,255,255,0.05); color:var(--color-text-secondary); border:1px solid var(--color-border);
                         padding:0.15rem 0.5rem; border-radius:3px; font-size:0.65rem; margin-left:auto;"
                  x-text="$store.genesisDashboard.fileBrowser.sidebarCollapsed ? 'Show Files' : 'Hide Files'"></button>
        </div>

        <div style="display:flex;">
          <!-- Directory listing -->
          <div x-show="!$store.genesisDashboard.fileBrowser.sidebarCollapsed"
               x-ref="fileBrowserSidebar"
               style="flex:0 0 28%; max-height:calc(100vh - 280px); overflow-y:auto; padding-right:0.5rem;">
            <template x-if="$store.genesisDashboard.fileBrowser.loading">
              <div style="color:var(--color-text-secondary); font-size:0.75rem; padding:1rem;">Loading...</div>
            </template>
            <template x-for="entry in $store.genesisDashboard.fileBrowser.entries" :key="entry.path">
              <div @click="entry.is_dir ? $store.genesisDashboard.fetchFiles(entry.path) : $store.genesisDashboard.openFile(entry.path)"
                   style="display:flex; align-items:center; gap:0.4rem; padding:0.25rem 0.35rem; cursor:pointer;
                          border-radius:3px; font-size:0.73rem; transition:background 0.1s;"
                   :style="$store.genesisDashboard.fileBrowser.selectedFile === entry.path ? 'background:rgba(33,150,243,0.15)' : ''"
                   onmouseover="this.style.background=this.style.background||'rgba(255,255,255,0.04)'"
                   onmouseout="if(!this.style.background.includes('33,150,243'))this.style.background=''">
                <span class="material-symbols-outlined" style="font-size:1rem;"
                      :style="entry.is_dir ? 'color:#ffa726' : 'color:#90caf9'"
                      x-text="entry.is_dir ? 'folder' : 'description'"></span>
                <span x-text="entry.name" style="flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;"></span>
                <span x-show="!entry.is_dir && entry.size != null"
                      style="color:var(--color-text-secondary); font-size:0.65rem; flex-shrink:0;"
                      x-text="entry.size > 1024*1024 ? (entry.size/1024/1024).toFixed(1)+'MB' : entry.size > 1024 ? (entry.size/1024).toFixed(1)+'KB' : entry.size+'B'"></span>
              </div>
            </template>
          </div>

          <!-- Resize handle -->
          <div x-show="!$store.genesisDashboard.fileBrowser.sidebarCollapsed"
               style="flex:0 0 8px; cursor:col-resize; background:var(--color-bg-tertiary);
                      display:flex; align-items:center; justify-content:center;
                      border-left:1px solid var(--color-border); border-right:1px solid var(--color-border);
                      transition:background .15s; position:relative; z-index:5;"
               @mouseenter="$el.style.background='rgba(99,102,241,0.25)'"
               @mouseleave="if(!$store.genesisDashboard.fileBrowser._resizing) $el.style.background='var(--color-bg-tertiary)'"
               @mousedown.prevent="$store.genesisDashboard._startFileBrowserResize($event, $refs.fileBrowserSidebar)">
            <span style="color:var(--color-text-secondary); font-size:0.55rem; pointer-events:none; opacity:0.6;">&#x22EE;</span>
          </div>

          <!-- File viewer -->
          <div style="flex:1; min-width:0;">
            <template x-if="$store.genesisDashboard.fileBrowser.selectedFile">
              <div>
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.5rem;">
                  <span style="font-size:0.72rem; font-family:monospace; color:var(--color-text-secondary); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:70%;"
                        x-text="$store.genesisDashboard.fileBrowser.selectedFile"></span>
                  <div style="display:flex; gap:0.3rem;">
                    <button @click="window.open('/api/genesis/files/download?path=' + encodeURIComponent($store.genesisDashboard.fileBrowser.selectedFile), '_blank')"
                            style="font-size:0.75rem; padding:0.3rem 0.7rem; border-radius:3px; cursor:pointer;
                                   background:rgba(33,150,243,0.15); color:#2196F3; border:1px solid rgba(33,150,243,0.3);
                                   display:flex; align-items:center; gap:0.3rem;"
                            title="Download file">
                      <span class="material-symbols-outlined" style="font-size:0.9rem;">download</span>
                      Download
                    </button>
                    <template x-if="$store.genesisDashboard.fileBrowser.fileWritable && $store.genesisDashboard.fileBrowser.fileDirty">
                      <button @click="$store.genesisDashboard.saveFile()"
                              :disabled="$store.genesisDashboard.fileBrowser.saving"
                              style="font-size:0.7rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer;
                                     background:rgba(102,187,106,0.15); color:#66bb6a; border:1px solid rgba(102,187,106,0.3);"
                              x-text="$store.genesisDashboard.fileBrowser.saving ? 'Saving...' : 'Save'"></button>
                    </template>
                  </div>
                </div>
                <textarea x-model="$store.genesisDashboard.fileBrowser.fileContent"
                          @input="$store.genesisDashboard.fileBrowser.fileDirty = true"
                          :readonly="!$store.genesisDashboard.fileBrowser.fileWritable"
                          style="width:100%; height:calc(100vh - 320px); min-height:300px; font-family:monospace;
                                 font-size:0.75rem; line-height:1.5; background:rgba(0,0,0,0.3); color:var(--color-text);
                                 border:1px solid var(--color-border); border-radius:4px; padding:0.5rem;
                                 resize:both; tab-size:4;"></textarea>
              </div>
            </template>
            <template x-if="!$store.genesisDashboard.fileBrowser.selectedFile">
              <div style="padding:2rem; text-align:center; color:var(--color-text-secondary); font-size:0.75rem;">
                Select a file to view its contents.
              </div>
            </template>
          </div>
        </div>
      </div>
    </div>

    <!-- ═══════════════════════════════════════════════════════════════
         Panel: Work [Tab: work] — Tasks + Sessions + Follow-ups
         ═══════════════════════════════════════════════════════════════ -->

    <!-- Work: Tasks -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'work'">
      <div class="panel-header">
        <span class="material-symbols-outlined">task_alt</span>
        Tasks
        <span class="panel-status" x-show="Object.keys($store.genesisDashboard.taskActive).length > 0">
          <span class="status-dot" style="background:#66bb6a;"></span>
          <span x-text="Object.keys($store.genesisDashboard.taskActive).length + ' active'"></span>
        </span>
      </div>
      <div class="panel-body">
        <!-- Active / Completed toggle -->
        <div style="display:flex; gap:0.25rem; margin-bottom:0.75rem;">
          <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer; transition:all 0.15s;"
                  :style="$store.genesisDashboard.tasksView === 'active' ? 'background:#4caf5033; border:1px solid #4caf50; color:#4caf50; font-weight:600;' : 'background:transparent; border:1px solid #666; color:#aaa;'"
                  @click="$store.genesisDashboard.tasksView = 'active'">Active</button>
          <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer; transition:all 0.15s;"
                  :style="$store.genesisDashboard.tasksView === 'completed' ? 'background:#2196F333; border:1px solid #2196F3; color:#2196F3; font-weight:600;' : 'background:transparent; border:1px solid #666; color:#aaa;'"
                  @click="$store.genesisDashboard.tasksView = 'completed'">Completed</button>
        </div>
        <!-- Task list -->
        <template x-if="$store.genesisDashboard.taskList.filter(t => {
          const phase = (t.current_phase || '').toLowerCase();
          const active = ['executing','paused','blocked','pending'].includes(phase);
          return $store.genesisDashboard.tasksView === 'active' ? active : !active;
        }).length === 0">
          <div style="padding:1.5rem; text-align:center; color:var(--color-text-secondary); font-size:0.75rem;"
               x-text="$store.genesisDashboard.tasksView === 'active' ? 'No active tasks.' : 'No completed tasks.'">
          </div>
        </template>
        <div class="activity-feed">
          <template x-for="task in $store.genesisDashboard.taskList.filter(t => {
            const phase = (t.current_phase || '').toLowerCase();
            const active = ['executing','paused','blocked','pending'].includes(phase);
            return $store.genesisDashboard.tasksView === 'active' ? active : !active;
          })" :key="task.task_id">
            <div>
              <div class="activity-row"
                   @click="$store.genesisDashboard.fetchTaskDetail(task.task_id)"
                   style="cursor:pointer; display:flex; align-items:center; gap:0.5rem;">
                <!-- Phase badge -->
                <span style="font-size:0.65rem; padding:0.1rem 0.4rem; border-radius:3px; font-weight:600; text-transform:uppercase; flex-shrink:0;"
                      :style="{
                        'executing': 'background:rgba(33,150,243,0.15); color:#2196F3;',
                        'completed': 'background:rgba(102,187,106,0.15); color:#66bb6a;',
                        'failed':    'background:rgba(239,154,154,0.15); color:#ef9a9a;',
                        'cancelled': 'background:rgba(158,158,158,0.15); color:#9e9e9e;',
                        'paused':    'background:rgba(255,167,38,0.15); color:#ffa726;',
                        'blocked':   'background:rgba(255,167,38,0.15); color:#ffa726;',
                        'pending':   'background:rgba(158,158,158,0.15); color:#9e9e9e;',
                      }[task.current_phase?.toLowerCase()] || 'background:rgba(33,150,243,0.15); color:#2196F3;'"
                      x-text="task.current_phase || 'unknown'"></span>
                <!-- Description -->
                <span style="flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:0.73rem;"
                      x-text="task.description || task.task_id"></span>
                <!-- Task ID -->
                <span style="color:var(--color-text-secondary); font-size:0.65rem; font-family:monospace; flex-shrink:0;"
                      x-text="task.task_id?.substring(0,10)"></span>
                <!-- Timestamp -->
                <span style="color:var(--color-text-secondary); font-size:0.65rem; flex-shrink:0;"
                      x-text="$store.genesisDashboard.formatTime(task.created_at)"></span>
                <!-- Expand arrow -->
                <span class="material-symbols-outlined" style="font-size:0.9rem; color:var(--color-text-secondary); transition:transform 0.15s;"
                      :style="$store.genesisDashboard.taskExpanded === task.task_id ? 'transform:rotate(90deg)' : ''">chevron_right</span>
              </div>

              <!-- Expanded detail -->
              <template x-if="$store.genesisDashboard.taskExpanded === task.task_id && $store.genesisDashboard.taskDetail">
                <div style="padding:0.5rem 0.75rem; background:rgba(0,0,0,0.15); border-radius:4px; margin:0.25rem 0 0.5rem 0; font-size:0.72rem;">
                  <!-- Actions bar -->
                  <div style="display:flex; gap:0.3rem; margin-bottom:0.5rem;">
                    <template x-if="$store.genesisDashboard.taskActive[task.task_id]">
                      <button @click.stop="$store.genesisDashboard.taskAction(task.task_id, 'pause')"
                              style="font-size:0.68rem; padding:0.15rem 0.5rem; border-radius:3px; cursor:pointer;
                                     background:rgba(255,167,38,0.1); color:#ffa726; border:1px solid rgba(255,167,38,0.2);">Pause</button>
                    </template>
                    <template x-if="task.current_phase?.toLowerCase() === 'paused'">
                      <button @click.stop="$store.genesisDashboard.taskAction(task.task_id, 'resume')"
                              style="font-size:0.68rem; padding:0.15rem 0.5rem; border-radius:3px; cursor:pointer;
                                     background:rgba(102,187,106,0.1); color:#66bb6a; border:1px solid rgba(102,187,106,0.2);">Resume</button>
                    </template>
                    <template x-if="$store.genesisDashboard.taskActive[task.task_id]">
                      <button @click.stop="$store.genesisDashboard.taskAction(task.task_id, 'cancel')"
                              style="font-size:0.68rem; padding:0.15rem 0.5rem; border-radius:3px; cursor:pointer;
                                     background:rgba(239,154,154,0.1); color:#ef9a9a; border:1px solid rgba(239,154,154,0.2);">Cancel</button>
                    </template>
                  </div>
                  <!-- Phase Timeline -->
                  <template x-if="$store.genesisDashboard.taskTimeline.length > 0">
                    <div style="margin-bottom:0.5rem;">
                      <div style="font-weight:600; margin-bottom:0.2rem; color:var(--color-text-secondary); font-size:0.65rem;">Phase Timeline</div>
                      <div style="display:flex; height:6px; border-radius:3px; overflow:hidden; background:rgba(255,255,255,0.05);">
                        <template x-for="(phase, idx) in $store.genesisDashboard.taskTimeline" :key="idx">
                          <div :style="`flex:${phase.duration_s || 1}; background:${$store.genesisDashboard.phaseColor(phase.phase)};`"
                               :title="`${phase.phase}: ${phase.duration_s ? Math.round(phase.duration_s) + 's' : 'active'}`"></div>
                        </template>
                      </div>
                      <div style="display:flex; gap:0.4rem; margin-top:0.15rem; flex-wrap:wrap;">
                        <template x-for="(phase, idx) in $store.genesisDashboard.taskTimeline" :key="'lbl'+idx">
                          <span style="font-size:0.6rem; display:inline-flex; align-items:center; gap:0.15rem;">
                            <span :style="`width:6px; height:6px; border-radius:50%; background:${$store.genesisDashboard.phaseColor(phase.phase)};`"></span>
                            <span style="color:var(--color-text-secondary);"
                                  x-text="`${phase.phase} ${phase.duration_s ? '(' + (phase.duration_s > 60 ? Math.round(phase.duration_s/60) + 'm' : Math.round(phase.duration_s) + 's') + ')' : '(active)'}`"></span>
                          </span>
                        </template>
                      </div>
                    </div>
                  </template>
                  <!-- Steps -->
                  <div style="margin-top:0.3rem;">
                    <div style="font-weight:600; margin-bottom:0.3rem; color:var(--color-text-secondary);">Steps</div>
                    <template x-for="step in $store.genesisDashboard.taskDetailSteps" :key="step.step_idx">
                      <div style="display:flex; align-items:flex-start; gap:0.4rem; padding:0.2rem 0; border-bottom:1px solid rgba(255,255,255,0.05); transition:all 0.15s;"
                           :style="step.status === 'executing' ? 'background:rgba(33,150,243,0.06); border-left:2px solid #2196F3; padding-left:0.3rem; margin-left:-0.3rem;' : ''">
                        <span class="material-symbols-outlined" style="font-size:0.85rem; flex-shrink:0; margin-top:0.05rem;"
                              :style="{
                                'completed': 'color:#66bb6a',
                                'executing': 'color:#2196F3',
                                'failed':    'color:#ef9a9a',
                                'pending':   'color:#9e9e9e',
                                'blocked':   'color:#ffa726',
                              }[step.status] || 'color:#9e9e9e'"
                              x-text="{
                                'completed': 'check_circle',
                                'executing': 'sync',
                                'failed':    'error',
                                'pending':   'radio_button_unchecked',
                                'blocked':   'block',
                              }[step.status] || 'radio_button_unchecked'"></span>
                        <div style="flex:1; min-width:0;">
                          <div style="display:flex; justify-content:space-between; gap:0.5rem;">
                            <span x-text="step.description || `Step ${step.step_idx}`" style="overflow:hidden; text-overflow:ellipsis; white-space:nowrap;"></span>
                            <span style="color:var(--color-text-secondary); font-size:0.65rem; flex-shrink:0;"
                                  x-text="step.step_type"></span>
                          </div>
                          <div style="display:flex; gap:0.5rem; color:var(--color-text-secondary); font-size:0.65rem; margin-top:0.1rem;">
                            <span x-show="step.model_used" x-text="step.model_used"></span>
                            <span x-show="step.cost_usd" x-text="'$' + step.cost_usd?.toFixed(4)"></span>
                            <span x-show="step.started_at && step.completed_at" style="display:inline-flex; align-items:center; gap:0.2rem;">
                              <span x-text="((new Date(step.completed_at) - new Date(step.started_at)) / 1000).toFixed(0) + 's'"></span>
                              <span style="display:inline-block; height:3px; border-radius:2px; background:#2196F3;"
                                    :style="`width:${Math.min(50, Math.max(4, ((new Date(step.completed_at) - new Date(step.started_at)) / 1000) * 0.5))}px;`"></span>
                            </span>
                          </div>
                          <template x-if="step.result_json && step.result_json.result">
                            <div style="margin-top:0.2rem; padding:0.2rem 0.4rem; background:rgba(0,0,0,0.2); border-radius:3px;
                                        font-family:monospace; font-size:0.65rem; max-height:80px; overflow:hidden; color:var(--color-text-secondary);"
                                 x-text="(typeof step.result_json.result === 'string' ? step.result_json.result : JSON.stringify(step.result_json.result)).substring(0, 500)">
                            </div>
                          </template>
                        </div>
                      </div>
                    </template>
                    <template x-if="$store.genesisDashboard.taskDetailSteps.length === 0">
                      <div style="color:var(--color-text-secondary); font-size:0.7rem; padding:0.3rem 0;">No steps recorded yet.</div>
                    </template>
                  </div>
                  <template x-if="$store.genesisDashboard.taskDetail.blockers">
                    <div style="margin-top:0.5rem; padding:0.3rem 0.5rem; background:rgba(255,167,38,0.08); border-radius:3px; border:1px solid rgba(255,167,38,0.15);">
                      <div style="font-weight:600; color:#ffa726; font-size:0.68rem; margin-bottom:0.15rem;">Blockers</div>
                      <div style="font-size:0.7rem; color:var(--color-text-secondary);"
                           x-text="JSON.stringify($store.genesisDashboard.taskDetail.blockers)"></div>
                    </div>
                  </template>
                  <!-- Linked Follow-ups -->
                  <template x-if="$store.genesisDashboard.taskLinkedFollowUps.length > 0">
                    <div style="margin-top:0.5rem; padding:0.3rem 0.5rem; background:rgba(33,150,243,0.05); border-radius:3px; border:1px solid rgba(33,150,243,0.1);">
                      <div style="font-weight:600; color:#64b5f6; font-size:0.68rem; margin-bottom:0.15rem;">
                        Linked Follow-ups <span style="font-weight:400; opacity:0.7;" x-text="'(' + $store.genesisDashboard.taskLinkedFollowUps.length + ')'"></span>
                      </div>
                      <template x-for="fu in $store.genesisDashboard.taskLinkedFollowUps" :key="fu.id">
                        <div style="display:flex; gap:0.3rem; align-items:flex-start; font-size:0.68rem; padding:0.15rem 0; border-bottom:1px solid rgba(255,255,255,0.03);">
                          <span style="font-size:0.6rem; padding:0.05rem 0.25rem; border-radius:2px; flex-shrink:0; text-transform:uppercase; font-weight:600;"
                                :style="{
                                  'completed': 'background:rgba(102,187,106,0.15); color:#66bb6a;',
                                  'pending':   'background:rgba(158,158,158,0.15); color:#9e9e9e;',
                                  'in_progress': 'background:rgba(33,150,243,0.15); color:#2196F3;',
                                  'blocked':   'background:rgba(255,167,38,0.15); color:#ffa726;',
                                  'failed':    'background:rgba(239,154,154,0.15); color:#ef9a9a;',
                                }[fu.status] || 'background:rgba(158,158,158,0.15); color:#9e9e9e;'"
                                x-text="fu.status"></span>
                          <span style="color:var(--color-text-secondary); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;"
                                x-text="fu.content"></span>
                        </div>
                      </template>
                    </div>
                  </template>
                </div>
              </template>
            </div>
          </template>
        </div>
      </div>
    </div>

    <!-- Work: Background Sessions -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'work'">
      <div class="panel-header">
        <span class="material-symbols-outlined">terminal</span>
        Background Sessions
        <span class="panel-status" x-show="$store.genesisDashboard.sessionsList.filter(s => ['active','running','executing'].includes(s.status?.toLowerCase())).length > 0">
          <span class="status-dot" style="background:#80cbc4;"></span>
          <span x-text="$store.genesisDashboard.sessionsList.filter(s => ['active','running','executing'].includes(s.status?.toLowerCase())).length + ' active'"></span>
        </span>
      </div>
      <div class="panel-body">
        <!-- Active / History toggle -->
        <div style="display:flex; gap:0.25rem; margin-bottom:0.75rem;">
          <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer; transition:all 0.15s;"
                  :style="$store.genesisDashboard.sessionsView === 'active' ? 'background:#4caf5033; border:1px solid #4caf50; color:#4caf50; font-weight:600;' : 'background:transparent; border:1px solid #666; color:#aaa;'"
                  @click="$store.genesisDashboard.sessionsView = 'active'; $store.genesisDashboard.fetchWorkSessions()">Active</button>
          <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer; transition:all 0.15s;"
                  :style="$store.genesisDashboard.sessionsView === 'history' ? 'background:#2196F333; border:1px solid #2196F3; color:#2196F3; font-weight:600;' : 'background:transparent; border:1px solid #666; color:#aaa;'"
                  @click="$store.genesisDashboard.sessionsView = 'history'; $store.genesisDashboard.fetchWorkSessions()">History</button>
        </div>
        <template x-if="$store.genesisDashboard.sessionsList.length === 0">
          <div style="padding:1.5rem; text-align:center; color:var(--color-text-secondary); font-size:0.75rem;">
            No background sessions found.
          </div>
        </template>
        <div class="activity-feed">
          <template x-for="item in $store.genesisDashboard.sessionsList" :key="item.id">
            <div>
              <div class="activity-row" style="cursor:pointer; display:flex; align-items:center; gap:0.5rem;"
                   @click="$store.genesisDashboard.sessionsExpanded = $store.genesisDashboard.sessionsExpanded === item.id ? null : item.id">
                <!-- Status badge -->
                <span style="font-size:0.65rem; padding:0.1rem 0.4rem; border-radius:3px; font-weight:600; text-transform:uppercase; flex-shrink:0;"
                      :style="{
                        'active':    'background:rgba(102,187,106,0.15); color:#66bb6a;',
                        'running':   'background:rgba(33,150,243,0.15); color:#2196F3;',
                        'executing': 'background:rgba(33,150,243,0.15); color:#2196F3;',
                        'completed': 'background:rgba(102,187,106,0.15); color:#66bb6a;',
                        'failed':    'background:rgba(239,154,154,0.15); color:#ef9a9a;',
                        'cancelled': 'background:rgba(158,158,158,0.15); color:#9e9e9e;',
                      }[item.status?.toLowerCase()] || 'background:rgba(158,158,158,0.15); color:#9e9e9e;'"
                      x-text="item.status"></span>
                <!-- Description -->
                <span style="flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:0.73rem;"
                      x-text="item.description || item.id"></span>
                <!-- Model -->
                <span style="color:var(--color-text-secondary); font-size:0.65rem; flex-shrink:0;"
                      x-text="item.model || ''"></span>
                <!-- Timestamp -->
                <span style="color:var(--color-text-secondary); font-size:0.65rem; flex-shrink:0;"
                      x-text="$store.genesisDashboard.formatTime(item.created_at)"></span>
                <!-- Expand arrow -->
                <span class="material-symbols-outlined" style="font-size:0.9rem; color:var(--color-text-secondary); transition:transform 0.15s;"
                      :style="$store.genesisDashboard.sessionsExpanded === item.id ? 'transform:rotate(90deg)' : ''">chevron_right</span>
              </div>
              <!-- Expanded detail -->
              <template x-if="$store.genesisDashboard.sessionsExpanded === item.id">
                <div style="padding:0.5rem 0.75rem; background:rgba(0,0,0,0.15); border-radius:4px; margin:0.25rem 0 0.5rem 0; font-size:0.72rem;">
                  <div style="display:flex; gap:1rem; flex-wrap:wrap; color:var(--color-text-secondary); font-size:0.7rem;">
                    <span x-text="'Type: ' + (item.session_type || 'unknown')"></span>
                    <span x-text="'Model: ' + (item.model || 'unknown')"></span>
                    <span x-show="item.cost_usd != null" x-text="'Cost: $' + (item.cost_usd || 0).toFixed(4)"></span>
                    <span x-text="'Started: ' + $store.genesisDashboard.formatTime(item.created_at)"></span>
                  </div>
                </div>
              </template>
            </div>
          </template>
        </div>
      </div>
    </div>

    <!-- Work: Follow-ups -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'work'">
      <div class="panel-header">
        <span class="material-symbols-outlined">follow_the_signs</span>
        Follow-ups
        <span class="panel-status" x-show="$store.genesisDashboard.followUpsCounts.pending > 0">
          <span style="background:#ce93d8; width:6px; height:6px; border-radius:50%; display:inline-block;"></span>
          <span x-text="$store.genesisDashboard.followUpsCounts.pending + ' pending'"></span>
        </span>
      </div>
      <div class="panel-body">
        <!-- Active / All toggle -->
        <div style="display:flex; gap:0.25rem; margin-bottom:0.75rem;">
          <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer; transition:all 0.15s;"
                  :style="$store.genesisDashboard.followUpsView === 'active' ? 'background:#4caf5033; border:1px solid #4caf50; color:#4caf50; font-weight:600;' : 'background:transparent; border:1px solid #666; color:#aaa;'"
                  @click="$store.genesisDashboard.followUpsView = 'active'">Active</button>
          <button style="font-size:0.72rem; padding:0.2rem 0.6rem; border-radius:3px; cursor:pointer; transition:all 0.15s;"
                  :style="$store.genesisDashboard.followUpsView === 'all' ? 'background:#2196F333; border:1px solid #2196F3; color:#2196F3; font-weight:600;' : 'background:transparent; border:1px solid #666; color:#aaa;'"
                  @click="$store.genesisDashboard.followUpsView = 'all'">All</button>
        </div>
        <template x-if="$store.genesisDashboard.followUpsList.filter(f => {
          if ($store.genesisDashboard.followUpsView === 'active') return ['pending','in_progress','blocked'].includes(f.status);
          return true;
        }).length === 0">
          <div style="padding:1.5rem; text-align:center; color:var(--color-text-secondary); font-size:0.75rem;">
            No follow-ups found.
          </div>
        </template>
        <div class="activity-feed">
          <template x-for="item in $store.genesisDashboard.followUpsList.filter(f => {
            if ($store.genesisDashboard.followUpsView === 'active') return ['pending','in_progress','blocked'].includes(f.status);
            return true;
          })" :key="item.id">
            <div>
              <div class="activity-row" style="cursor:pointer; display:flex; align-items:center; gap:0.5rem;"
                   @click="$store.genesisDashboard.followUpsExpanded = $store.genesisDashboard.followUpsExpanded === item.id ? null : item.id">
                <!-- Status badge -->
                <span style="font-size:0.65rem; padding:0.1rem 0.4rem; border-radius:3px; font-weight:600; text-transform:uppercase; flex-shrink:0;"
                      :style="{
                        'pending':     'background:rgba(158,158,158,0.15); color:#9e9e9e;',
                        'in_progress': 'background:rgba(33,150,243,0.15); color:#2196F3;',
                        'blocked':     'background:rgba(255,167,38,0.15); color:#ffa726;',
                        'completed':   'background:rgba(102,187,106,0.15); color:#66bb6a;',
                        'cancelled':   'background:rgba(158,158,158,0.15); color:#9e9e9e;',
                      }[item.status] || 'background:rgba(158,158,158,0.15); color:#9e9e9e;'"
                      x-text="item.status"></span>
                <!-- Priority badge -->
                <template x-if="item.priority && item.priority !== 'medium'">
                  <span style="font-size:0.6rem; padding:0.08rem 0.3rem; border-radius:3px; flex-shrink:0;"
                        :style="item.priority === 'high' || item.priority === 'critical' ? 'background:rgba(239,154,154,0.15); color:#ef9a9a;' : 'background:rgba(158,158,158,0.1); color:#9e9e9e;'"
                        x-text="item.priority"></span>
                </template>
                <!-- Description -->
                <span style="flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:0.73rem;"
                      x-text="item.content || item.id"></span>
                <!-- Timestamp -->
                <span style="color:var(--color-text-secondary); font-size:0.65rem; flex-shrink:0;"
                      x-text="$store.genesisDashboard.formatTime(item.created_at)"></span>
                <!-- Expand arrow -->
                <span class="material-symbols-outlined" style="font-size:0.9rem; color:var(--color-text-secondary); transition:transform 0.15s;"
                      :style="$store.genesisDashboard.followUpsExpanded === item.id ? 'transform:rotate(90deg)' : ''">chevron_right</span>
              </div>
              <!-- Expanded detail -->
              <template x-if="$store.genesisDashboard.followUpsExpanded === item.id">
                <div style="padding:0.5rem 0.75rem; background:rgba(0,0,0,0.15); border-radius:4px; margin:0.25rem 0 0.5rem 0; font-size:0.72rem;">
                  <div style="margin-bottom:0.4rem; line-height:1.5;" x-text="item.content"></div>
                  <template x-if="item.reason">
                    <div style="margin-bottom:0.3rem; color:var(--color-text-secondary); font-size:0.7rem;">
                      <strong>Reason:</strong> <span x-text="item.reason"></span>
                    </div>
                  </template>
                  <div style="display:flex; gap:0.5rem; font-size:0.65rem; color:var(--color-text-secondary);">
                    <span x-text="'Strategy: ' + (item.strategy || 'unknown')"></span>
                    <span x-text="'Source: ' + (item.source || 'unknown')"></span>
                  </div>
                  <template x-if="item.resolution_notes">
                    <div style="margin-top:0.3rem; padding:0.2rem 0.4rem; background:rgba(0,0,0,0.2); border-radius:3px; font-size:0.65rem; color:var(--color-text-secondary);">
                      <strong>Resolution:</strong> <span x-text="item.resolution_notes"></span>
                    </div>
                  </template>
                  <template x-if="item.blocked_reason">
                    <div style="margin-top:0.3rem; padding:0.2rem 0.4rem; background:rgba(255,167,38,0.08); border-radius:3px; border:1px solid rgba(255,167,38,0.15); font-size:0.65rem;">
                      <strong style="color:#ffa726;">Blocked:</strong> <span x-text="item.blocked_reason"></span>
                    </div>
                  </template>
                </div>
              </template>
            </div>
          </template>
        </div>
      </div>
    </div>

    <!-- ═══════════════════════════════════════════════════════════
         Panel: Observations [Tab: observations]
         ═══════════════════════════════════════════════════════════ -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'observations'">
      <div class="panel-header">
        <span class="material-symbols-outlined">visibility</span>
        Observations
        <span class="panel-status" x-show="$store.genesisDashboard.observationsCounts.total_unsurfaced > 0">
          <span class="status-dot" style="background:#ffa726;"></span>
          <span x-text="$store.genesisDashboard.observationsCounts.total_unsurfaced + ' unsurfaced'"></span>
        </span>
      </div>
      <div class="panel-body">
        <!-- Summary badges -->
        <div style="display:flex; gap:0.5rem; margin-bottom:0.75rem; flex-wrap:wrap; align-items:center;">
          <template x-for="[prio, count] in Object.entries($store.genesisDashboard.observationsCounts.counts || {})" :key="prio">
            <span style="font-size:0.65rem; padding:0.15rem 0.5rem; border-radius:3px; font-weight:600; text-transform:uppercase;"
                  :style="{
                    critical: 'background:rgba(244,67,54,0.15); color:#f44336; border:1px solid rgba(244,67,54,0.3)',
                    high: 'background:rgba(255,152,0,0.15); color:#ff9800; border:1px solid rgba(255,152,0,0.3)',
                    medium: 'background:rgba(255,193,7,0.15); color:#ffc107; border:1px solid rgba(255,193,7,0.3)',
                    low: 'background:rgba(158,158,158,0.15); color:#9e9e9e; border:1px solid rgba(158,158,158,0.3)'
                  }[prio] || ''"
                  x-text="prio + ': ' + count"></span>
          </template>
          <span style="font-size:0.65rem; color:var(--color-text-secondary); margin-left:auto;"
                x-text="$store.genesisDashboard.observationsCounts.total_unresolved + ' total unresolved'"></span>
        </div>

        <!-- Filter bar -->
        <div style="display:flex; gap:0.25rem; margin-bottom:0.75rem; flex-wrap:wrap; align-items:center;">
          <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border-radius:3px; cursor:pointer; border:1px solid #555;"
                  :style="$store.genesisDashboard.observationsView === 'unresolved' ? 'background:rgba(33,150,243,0.15); color:#2196F3; border-color:rgba(33,150,243,0.4)' : 'background:transparent; color:var(--color-text-secondary)'"
                  @click="$store.genesisDashboard.observationsView = 'unresolved'; $store.genesisDashboard.fetchObservations()">Unresolved</button>
          <button style="font-size:0.68rem; padding:0.2rem 0.5rem; border-radius:3px; cursor:pointer; border:1px solid #555;"
                  :style="$store.genesisDashboard.observationsView === 'all' ? 'background:rgba(33,150,243,0.15); color:#2196F3; border-color:rgba(33,150,243,0.4)' : 'background:transparent; color:var(--color-text-secondary)'"
                  @click="$store.genesisDashboard.observationsView = 'all'; $store.genesisDashboard.fetchObservations()">All</button>

          <select style="font-size:0.68rem; padding:0.2rem 0.3rem; border-radius:3px; background:rgba(0,0,0,0.2); border:1px solid #555; color:var(--color-text-primary); margin-left:0.5rem;"
                  @change="$store.genesisDashboard.observationsFilters.priority = $event.target.value; $store.genesisDashboard.fetchObservations()">
            <option value="">All priorities</option>
            <option value="critical">Critical</option>
            <option value="high">High</option>
            <option value="medium">Medium</option>
            <option value="low">Low</option>
          </select>

          <select style="font-size:0.68rem; padding:0.2rem 0.3rem; border-radius:3px; background:rgba(0,0,0,0.2); border:1px solid #555; color:var(--color-text-primary);"
                  @change="$store.genesisDashboard.observationsFilters.type = $event.target.value; $store.genesisDashboard.fetchObservations()">
            <option value="">All types</option>
            <template x-for="t in $store.genesisDashboard.observationsAvailableFilters.types" :key="t">
              <option :value="t" x-text="t"></option>
            </template>
          </select>

          <select style="font-size:0.68rem; padding:0.2rem 0.3rem; border-radius:3px; background:rgba(0,0,0,0.2); border:1px solid #555; color:var(--color-text-primary);"
                  @change="$store.genesisDashboard.observationsFilters.source = $event.target.value; $store.genesisDashboard.fetchObservations()">
            <option value="">All sources</option>
            <template x-for="s in $store.genesisDashboard.observationsAvailableFilters.sources" :key="s">
              <option :value="s" x-text="s"></option>
            </template>
          </select>

          <!-- Batch actions -->
          <template x-if="$store.genesisDashboard.observationsBatchCount > 0">
            <div style="margin-left:auto; display:flex; gap:0.25rem;">
              <button style="font-size:0.65rem; padding:0.15rem 0.5rem; border-radius:3px; cursor:pointer; background:rgba(33,150,243,0.1); color:#2196F3; border:1px solid rgba(33,150,243,0.2);"
                      @click="$store.genesisDashboard.batchObservationsAction('mark_read')">
                Mark Read (<span x-text="$store.genesisDashboard.observationsBatchCount"></span>)
              </button>
              <button style="font-size:0.65rem; padding:0.15rem 0.5rem; border-radius:3px; cursor:pointer; background:rgba(102,187,106,0.1); color:#66bb6a; border:1px solid rgba(102,187,106,0.2);"
                      @click="$store.genesisDashboard.batchObservationsAction('resolve')">
                Resolve (<span x-text="$store.genesisDashboard.observationsBatchCount"></span>)
              </button>
            </div>
          </template>
        </div>

        <!-- Empty state -->
        <template x-if="$store.genesisDashboard.observationsList.length === 0">
          <div style="padding:1.5rem; text-align:center; color:var(--color-text-secondary); font-size:0.75rem;">
            No observations found.
          </div>
        </template>

        <!-- Observation list -->
        <div class="activity-feed">
          <template x-for="obs in $store.genesisDashboard.observationsList" :key="obs.id">
            <div>
              <div class="activity-row" style="cursor:pointer; display:flex; align-items:center; gap:0.5rem;"
                   @click="$store.genesisDashboard.observationsExpanded = $store.genesisDashboard.observationsExpanded === obs.id ? null : obs.id">
                <!-- Batch checkbox -->
                <input type="checkbox" @click.stop
                       :checked="!!$store.genesisDashboard.observationsBatchIds[obs.id]"
                       @change="$store.genesisDashboard.toggleObservationBatch(obs.id)"
                       style="width:12px; height:12px; cursor:pointer; flex-shrink:0;">
                <!-- Priority badge -->
                <span style="font-size:0.6rem; padding:0.1rem 0.35rem; border-radius:3px; font-weight:600; text-transform:uppercase; flex-shrink:0; min-width:3rem; text-align:center;"
                      :style="{
                        critical: 'background:rgba(244,67,54,0.15); color:#f44336',
                        high: 'background:rgba(255,152,0,0.15); color:#ff9800',
                        medium: 'background:rgba(255,193,7,0.15); color:#ffc107',
                        low: 'background:rgba(158,158,158,0.15); color:#9e9e9e'
                      }[obs.priority] || ''"
                      x-text="obs.priority"></span>
                <!-- Unsurfaced indicator -->
                <span x-show="!obs.surfaced_at && !obs.resolved" style="width:6px; height:6px; border-radius:50%; background:#ffa726; flex-shrink:0;" title="Unsurfaced"></span>
                <!-- Content preview -->
                <span style="flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:0.72rem;"
                      x-text="(obs.content || '').substring(0, 120)"></span>
                <!-- Type -->
                <span style="color:var(--color-text-secondary); font-size:0.58rem; font-family:monospace; flex-shrink:0; max-width:8rem; overflow:hidden; text-overflow:ellipsis;"
                      x-text="obs.type"></span>
                <!-- Timestamp -->
                <span style="color:var(--color-text-secondary); font-size:0.63rem; flex-shrink:0;"
                      x-text="$store.genesisDashboard.formatTime ? $store.genesisDashboard.formatTime(obs.created_at) : (obs.created_at || '').substring(0, 16)"></span>
                <!-- Expand arrow -->
                <span class="material-symbols-outlined" style="font-size:0.9rem; color:var(--color-text-secondary); transition:transform 0.15s;"
                      :style="$store.genesisDashboard.observationsExpanded === obs.id ? 'transform:rotate(90deg)' : ''">chevron_right</span>
              </div>

              <!-- Expanded detail -->
              <template x-if="$store.genesisDashboard.observationsExpanded === obs.id">
                <div style="padding:0.5rem 0.75rem; background:rgba(0,0,0,0.15); border-radius:4px; margin:0.25rem 0 0.5rem 1.5rem; font-size:0.72rem;">
                  <!-- Full content -->
                  <div style="margin-bottom:0.4rem; line-height:1.5; white-space:pre-wrap; word-break:break-word;" x-text="obs.content"></div>
                  <!-- Metadata -->
                  <div style="display:flex; gap:0.5rem; font-size:0.63rem; color:var(--color-text-secondary); flex-wrap:wrap; margin-bottom:0.4rem;">
                    <span x-text="'Source: ' + (obs.source || 'unknown')"></span>
                    <span x-text="'Type: ' + obs.type"></span>
                    <span x-show="obs.category" x-text="'Category: ' + obs.category"></span>
                    <span x-text="'Retrieved: ' + (obs.retrieved_count || 0) + 'x'"></span>
                    <span x-show="obs.influenced_action" style="color:#66bb6a;">Influenced action</span>
                    <span x-show="obs.surfaced_at" style="color:#90caf9;">Surfaced</span>
                  </div>
                  <!-- Resolution info (if resolved) -->
                  <template x-if="obs.resolved">
                    <div style="margin-top:0.3rem; padding:0.25rem 0.5rem; background:rgba(102,187,106,0.08); border-radius:3px; font-size:0.65rem;">
                      <strong style="color:#66bb6a;">Resolved:</strong>
                      <span x-text="obs.resolution_notes || 'No notes'"></span>
                      <span style="margin-left:0.5rem; color:var(--color-text-secondary);"
                            x-text="(obs.resolved_at || '').substring(0, 16)"></span>
                    </div>
                  </template>
                  <!-- Actions (unresolved only) -->
                  <template x-if="!obs.resolved">
                    <div style="display:flex; gap:0.3rem; margin-top:0.5rem; align-items:center;">
                      <button @click.stop="$store.genesisDashboard.markObservationRead(obs.id)"
                              :disabled="$store.genesisDashboard.observationsMarkingRead[obs.id]"
                              x-show="!obs.surfaced_at"
                              style="font-size:0.65rem; padding:0.15rem 0.5rem; border-radius:3px; cursor:pointer; background:rgba(33,150,243,0.1); color:#2196F3; border:1px solid rgba(33,150,243,0.2);">
                        <span x-text="$store.genesisDashboard.observationsMarkingRead[obs.id] ? 'Marking...' : 'Mark Read'"></span>
                      </button>
                      <button @click.stop="$store.genesisDashboard.resolveObservation(obs.id, '')"
                              :disabled="$store.genesisDashboard.observationsResolving[obs.id]"
                              style="font-size:0.65rem; padding:0.15rem 0.5rem; border-radius:3px; cursor:pointer; background:rgba(102,187,106,0.1); color:#66bb6a; border:1px solid rgba(102,187,106,0.2);">
                        <span x-text="$store.genesisDashboard.observationsResolving[obs.id] ? 'Resolving...' : 'Resolve'"></span>
                      </button>
                      <input type="text" placeholder="Resolution notes... (Enter to resolve)"
                             @click.stop
                             @keydown.enter.stop="$store.genesisDashboard.resolveObservation(obs.id, $el.value); $el.value = ''"
                             style="font-size:0.65rem; padding:0.15rem 0.4rem; border-radius:3px; flex:1; min-width:120px; background:rgba(0,0,0,0.2); border:1px solid #555; color:var(--color-text-primary);">
                    </div>
                  </template>
                </div>
              </template>
            </div>
          </template>
        </div>

        <!-- Load more indicator -->
        <div x-show="$store.genesisDashboard.observationsHasMore"
             style="text-align:center; padding:0.5rem; font-size:0.65rem; color:var(--color-text-secondary);">
          Showing first 50 results. Use filters to narrow down.
        </div>
      </div>
    </div>

    <!-- ═══════════════════════════════════════════════════════════
         Panel: Memory Browser [Tab: memory]
         ═══════════════════════════════════════════════════════════ -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'memory'">
      <div class="panel-header">
        <span class="material-symbols-outlined">psychology</span>
        Memory Browser
      </div>
      <div class="panel-body">
        <!-- Stats row -->
        <div style="display:flex; gap:1rem; margin-bottom:1rem; flex-wrap:wrap;" x-data>
          <template x-if="$store.genesisDashboard.memoryStats.total != null">
            <div class="card" style="flex:1; min-width:120px; padding:0.75rem;">
              <div style="font-size:0.7rem; color:var(--color-text-secondary);">Total Memories</div>
              <div style="font-size:1.5rem; font-weight:600;" x-text="$store.genesisDashboard.memoryStats.total"></div>
            </div>
          </template>
          <template x-if="$store.genesisDashboard.memoryStats.pending_embeddings != null">
            <div class="card" style="flex:1; min-width:120px; padding:0.75rem;">
              <div style="font-size:0.7rem; color:var(--color-text-secondary);">Pending Embeddings</div>
              <div style="font-size:1.5rem; font-weight:600;" x-text="$store.genesisDashboard.memoryStats.pending_embeddings"></div>
            </div>
          </template>
          <template x-if="$store.genesisDashboard.memoryStats.qdrant_episodic_memory != null">
            <div class="card" style="flex:1; min-width:120px; padding:0.75rem;">
              <div style="font-size:0.7rem; color:var(--color-text-secondary);">Qdrant Episodic</div>
              <div style="font-size:1.5rem; font-weight:600;" x-text="$store.genesisDashboard.memoryStats.qdrant_episodic_memory"></div>
            </div>
          </template>
        </div>

        <!-- Memory Growth Sparkline -->
        <template x-if="$store.genesisDashboard.memoryStats.daily_growth && $store.genesisDashboard.memoryStats.daily_growth.length > 1">
          <div class="card" style="margin-bottom:1rem; padding:0.75rem;">
            <div style="font-size:0.75rem; color:var(--color-text-secondary); margin-bottom:0.5rem;">Memory Growth (30 days)</div>
            <svg width="100%" height="48" viewBox="0 0 600 48" preserveAspectRatio="none" style="display:block;" x-data="{
              get points() {
                const data = $store.genesisDashboard.memoryStats.daily_growth;
                if (!data || data.length < 2) return '';
                const max = Math.max(...data.map(d => d.count));
                const min = Math.min(...data.map(d => d.count));
                const range = max - min || 1;
                const w = 600;
                const h = 44;
                return data.map((d, i) => {
                  const x = (i / (data.length - 1)) * w;
                  const y = h - ((d.count - min) / range) * (h - 4) - 2;
                  return `${x},${y}`;
                }).join(' ');
              }
            }">
              <polyline :points="points" fill="none" stroke="var(--color-accent, #60a5fa)" stroke-width="2" vector-effect="non-scaling-stroke" />
            </svg>
            <div style="display:flex; justify-content:space-between; font-size:0.65rem; color:var(--color-text-secondary);">
              <span x-text="$store.genesisDashboard.memoryStats.daily_growth[0]?.day || ''"></span>
              <span x-text="'Total: +' + $store.genesisDashboard.memoryStats.daily_growth.reduce((s,d) => s + d.count, 0) + ' memories'"></span>
              <span x-text="$store.genesisDashboard.memoryStats.daily_growth[$store.genesisDashboard.memoryStats.daily_growth.length - 1]?.day || ''"></span>
            </div>
          </div>
        </template>

        <!-- Wing Distribution -->
        <template x-if="$store.genesisDashboard.memoryStats.wings && $store.genesisDashboard.memoryStats.wings.length > 0">
          <div class="card" style="margin-bottom:1rem; padding:0.75rem;">
            <div style="font-size:0.75rem; color:var(--color-text-secondary); margin-bottom:0.5rem;">Memory by Wing</div>
            <div style="display:flex; flex-wrap:wrap; gap:0.4rem;">
              <template x-for="w in $store.genesisDashboard.memoryStats.wings" :key="w.wing">
                <span class="badge" style="font-size:0.7rem; padding:0.2rem 0.5rem;"
                      x-text="w.wing + ': ' + w.count.toLocaleString()"></span>
              </template>
            </div>
          </div>
        </template>

        <!-- Search -->
        <div style="display:flex; gap:0.5rem; margin-bottom:1rem;">
          <input type="text" x-model="$store.genesisDashboard.memorySearch.query"
                 @keydown.enter="$store.genesisDashboard.searchMemory()"
                 placeholder="Semantic search..."
                 style="flex:1; background:var(--color-bg-primary); border:1px solid var(--color-border); color:var(--color-text-primary); padding:0.5rem; border-radius:4px; font-family:inherit;">
          <button @click="$store.genesisDashboard.searchMemory()"
                  style="background:var(--color-accent); color:#000; border:none; padding:0.5rem 1rem; border-radius:4px; cursor:pointer;"
                  x-text="$store.genesisDashboard.memorySearch.loading ? 'Searching...' : 'Search'"></button>
        </div>

        <!-- Search results -->
        <template x-if="$store.genesisDashboard.memorySearch.results.length > 0">
          <div class="card" style="margin-bottom:1rem;">
            <div style="padding:0.5rem; font-size:0.8rem; color:var(--color-text-secondary);">
              Search Results (<span x-text="$store.genesisDashboard.memorySearch.results.length"></span>)
            </div>
            <template x-for="r in $store.genesisDashboard.memorySearch.results" :key="r.memory_id">
              <div :style="`padding:0.5rem; border-top:1px solid var(--color-border); border-left:3px solid ${$store.genesisDashboard._memoryTypeColor(r.memory_type || r.collection)}; cursor:pointer; transition:background .15s;`"
                   @mouseenter="$el.style.background='rgba(255,255,255,0.04)'"
                   @mouseleave="$el.style.background=''"
                   @click="$store.genesisDashboard.viewMemoryDetail(r.memory_id)">
                <div style="display:flex; justify-content:space-between; align-items:center; font-size:0.75rem;">
                  <span :style="`padding:1px 5px; border-radius:3px; background:${$store.genesisDashboard._memoryTypeColor(r.memory_type || r.collection)}22; color:${$store.genesisDashboard._memoryTypeColor(r.memory_type || r.collection)};`"
                        x-text="r.memory_type || r.collection"></span>
                  <span style="color:var(--color-text-secondary);" x-text="'score: ' + (r.score || '?')"></span>
                </div>
                <div style="font-size:0.85rem; white-space:pre-wrap; max-height:3rem; overflow:hidden; margin-top:.25rem;" x-text="r.content"></div>
              </div>
            </template>
          </div>
        </template>

        <!-- Memory detail modal -->
        <template x-if="$store.genesisDashboard.memoryDetail">
          <div class="card" style="margin-bottom:1rem; border:1px solid var(--color-accent);">
            <div style="padding:0.75rem; display:flex; justify-content:space-between; align-items:center;">
              <span style="font-size:0.8rem; color:var(--color-accent);" x-text="'ID: ' + $store.genesisDashboard.memoryDetail.memory_id"></span>
              <div style="display:flex; gap:0.5rem; justify-content:space-between;">
                <button @click="$store.genesisDashboard.deleteMemory($store.genesisDashboard.memoryDetail.memory_id)"
                        style="background:rgba(239,154,154,0.2); color:#ef9a9a; border:1px solid rgba(239,154,154,0.3); padding:0.25rem 0.5rem; border-radius:4px; cursor:pointer; font-size:0.75rem;">Delete</button>
                <button @click="$store.genesisDashboard.memoryDetail = null"
                        style="background:var(--color-background); color:var(--color-text-secondary); border:1px solid var(--color-border); padding:0.25rem 0.5rem; border-radius:4px; cursor:pointer; font-size:0.75rem;">Close</button>
              </div>
            </div>
            <div style="padding:0.75rem; border-top:1px solid var(--color-border);">
              <div style="font-size:0.7rem; color:var(--color-text-secondary); margin-bottom:0.25rem;">
                <span x-text="'Collection: ' + ($store.genesisDashboard.memoryDetail.collection || '?')"></span> ·
                <span x-text="'Links: ' + ($store.genesisDashboard.memoryDetail.link_count || 0)"></span> ·
                <span x-text="'Created: ' + ($store.genesisDashboard.memoryDetail.created_at || 'unknown')"></span>
              </div>
              <pre style="white-space:pre-wrap; font-size:0.85rem; max-height:400px; overflow-y:auto; margin:0;" x-text="$store.genesisDashboard.memoryDetail.content"></pre>
            </div>
          </div>
        </template>

        <!-- Recent memories -->
        <div class="card">
          <div style="padding:0.5rem; font-size:0.8rem; color:var(--color-text-secondary);">
            Recent Memories (<span x-text="$store.genesisDashboard.memoryRecent.total"></span> total)
          </div>
          <template x-if="$store.genesisDashboard.memoryRecent.loading">
            <div style="padding:1rem; text-align:center; color:var(--color-text-secondary);">Loading...</div>
          </template>
          <template x-for="m in $store.genesisDashboard.memoryRecent.items" :key="m.memory_id">
            <div :style="`padding:0.5rem; border-top:1px solid var(--color-border); border-left:3px solid ${$store.genesisDashboard._memoryTypeColor(m.collection)}; cursor:pointer; transition:background .15s;`"
                 @mouseenter="$el.style.background='rgba(255,255,255,0.04)'"
                 @mouseleave="$el.style.background=''"
                 @click="$store.genesisDashboard.viewMemoryDetail(m.memory_id)">
              <div style="display:flex; justify-content:space-between; align-items:center; font-size:0.7rem;">
                <span :style="`padding:1px 5px; border-radius:3px; background:${$store.genesisDashboard._memoryTypeColor(m.collection)}22; color:${$store.genesisDashboard._memoryTypeColor(m.collection)};`"
                      x-text="m.collection"></span>
                <span style="color:var(--color-text-secondary);" x-text="m.created_at ? new Date(m.created_at).toLocaleString() : ''"></span>
              </div>
              <div style="font-size:0.85rem; white-space:pre-wrap; max-height:2.5rem; overflow:hidden; margin-top:.25rem; line-height:1.4;" x-text="m.content"></div>
            </div>
          </template>
        </div>
      </div>
    </div>

    <!-- ═══════════════════════════════════════════════════════════
         Panel: Knowledge Base [Tab: knowledge]
         ═══════════════════════════════════════════════════════════ -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'knowledge'" style="overflow-y: auto; max-height: calc(100vh - 180px);">
      <div class="panel-header">
        <span class="material-symbols-outlined">school</span>
        Knowledge Base
      </div>
      <div style="padding: 1rem;">

      <!-- ── Upload Zone ─────────────────────────────────────── -->
      <div style="margin-bottom: 1.5rem;">
        <!-- Drop Zone -->
        <div x-show="!$store.genesisDashboard.knowledgeUpload.confirm"
             @dragover.prevent="$store.genesisDashboard.knowledgeUpload.dragging = true"
             @dragleave.prevent="$store.genesisDashboard.knowledgeUpload.dragging = false"
             @drop.prevent="$store.genesisDashboard.handleKnowledgeFileDrop($event)"
             @click="$refs.knowledgeFileInput.click()"
             :style="`border: 2px dashed ${$store.genesisDashboard.knowledgeUpload.dragging ? 'var(--color-accent)' : 'var(--color-border)'}; border-radius: 8px; padding: 2rem; text-align: center; cursor: pointer; transition: border-color .2s; background: ${$store.genesisDashboard.knowledgeUpload.dragging ? 'rgba(99,102,241,.08)' : 'transparent'};`">
          <span class="material-symbols-outlined" style="font-size: 2rem; color: var(--color-text-secondary);">upload_file</span>
          <div style="margin-top: .5rem; color: var(--color-text-secondary);" x-text="$store.genesisDashboard.knowledgeUpload.uploading ? 'Uploading...' : 'Drop files here or click to browse'"></div>
          <div style="font-size: .8em; color: var(--color-text-secondary); margin-top: .25rem;">PDF, text, audio, video — up to 500 MB</div>
          <div style="font-size: .7em; color: var(--color-text-secondary); margin-top: .15rem; opacity: .7;">Stores to knowledge base for long-term recall. For simple file sharing, use the Files tab.</div>
          <input type="file" x-ref="knowledgeFileInput" style="display:none"
                 @change="$store.genesisDashboard.handleKnowledgeFileDrop($event)">
        </div>

        <!-- Confirmation Card -->
        <template x-if="$store.genesisDashboard.knowledgeUpload.confirm">
          <div class="card" style="border: 1px solid var(--color-accent); padding: 1.25rem;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
              <strong>Store to Knowledge Base</strong>
              <span class="badge" x-text="$store.genesisDashboard.knowledgeUpload.file?.mime || 'unknown'"></span>
            </div>
            <div style="margin-bottom: .75rem; color: var(--color-text-secondary);">
              <span x-text="$store.genesisDashboard.knowledgeUpload.file?.name"></span>
              (<span x-text="$store.genesisDashboard._formatFileSize($store.genesisDashboard.knowledgeUpload.file?.size)"></span>)
            </div>
            <!-- Context message -->
            <div style="margin-bottom: .75rem;">
              <label style="font-size: .8em; color: var(--color-text-secondary);">Context</label>
              <textarea x-model="$store.genesisDashboard.knowledgeUpload.context" rows="3"
                        placeholder="Tell Genesis about this document — what is it, how should it be understood? (optional)"
                        style="width: 100%; padding: .4rem; background: var(--color-background); border: 1px solid var(--color-border); color: var(--color-text); border-radius: 4px; font-size: .85rem; resize: vertical;"></textarea>
            </div>
            <!-- Processing mode -->
            <div style="margin-bottom: .75rem; display: flex; gap: 1rem;">
              <label style="font-size: .8em; cursor: pointer; display: flex; align-items: center; gap: .3rem;">
                <input type="radio" value="extract" x-model="$store.genesisDashboard.knowledgeUpload.mode">
                <span style="color: var(--color-text-secondary);">Extract &amp; distill</span>
                <span style="font-size: .7em; color: var(--color-text-secondary); opacity: .7;">— AI breaks into searchable concepts</span>
              </label>
              <label style="font-size: .8em; cursor: pointer; display: flex; align-items: center; gap: .3rem;">
                <input type="radio" value="store" x-model="$store.genesisDashboard.knowledgeUpload.mode">
                <span style="color: var(--color-text-secondary);">Store as-is</span>
                <span style="font-size: .7em; color: var(--color-text-secondary); opacity: .7;">— full document, one unit, instant</span>
              </label>
            </div>
            <div style="display: flex; gap: .5rem; margin-bottom: .75rem;">
              <div style="flex: 1;">
                <label style="font-size: .8em; color: var(--color-text-secondary);">Project Type *</label>
                <input type="text" list="kb-project-types" x-model="$store.genesisDashboard.knowledgeUpload.projectType"
                       placeholder="e.g. professional" style="width: 100%; padding: .4rem; background: var(--color-background); border: 1px solid var(--color-border); color: var(--color-text); border-radius: 4px;">
                <datalist id="kb-project-types">
                  <template x-for="pt in $store.genesisDashboard.knowledgeTaxonomy.project_types" :key="pt">
                    <option :value="pt"></option>
                  </template>
                </datalist>
                <div style="font-size: .65em; color: var(--color-text-secondary); margin-top: 2px; opacity: .7;">Workspace scope (e.g., 'genesis', 'career')</div>
              </div>
              <div style="flex: 1;">
                <label style="font-size: .8em; color: var(--color-text-secondary);">Domain</label>
                <input type="text" list="kb-domains" x-model="$store.genesisDashboard.knowledgeUpload.domain"
                       placeholder="auto" style="width: 100%; padding: .4rem; background: var(--color-background); border: 1px solid var(--color-border); color: var(--color-text); border-radius: 4px;">
                <datalist id="kb-domains">
                  <template x-for="d in $store.genesisDashboard.knowledgeTaxonomy.domains" :key="d">
                    <option :value="d"></option>
                  </template>
                </datalist>
                <div style="font-size: .65em; color: var(--color-text-secondary); margin-top: 2px; opacity: .7;">Topic filter. Leave 'auto' for AI detection.</div>
              </div>
            </div>
            <div style="margin-bottom: .75rem;">
              <label style="font-size: .8em; color: var(--color-text-secondary);">Purpose (optional, comma-separated)</label>
              <input type="text" x-model="$store.genesisDashboard.knowledgeUpload.purpose"
                     placeholder="e.g. resume-prep, cloud-eng" style="width: 100%; padding: .4rem; background: var(--color-background); border: 1px solid var(--color-border); color: var(--color-text); border-radius: 4px;">
              <div style="font-size: .65em; color: var(--color-text-secondary); margin-top: 2px; opacity: .7;">Usage tags (e.g., 'planning', 'reference')</div>
            </div>
            <template x-if="$store.genesisDashboard.knowledgeUpload.error">
              <div style="color: var(--color-error-text); margin-bottom: .5rem; font-size: .9em;" x-text="$store.genesisDashboard.knowledgeUpload.error"></div>
            </template>
            <div style="display: flex; gap: .5rem; justify-content: flex-end;">
              <button class="btn-sm" style="opacity: .7;" @click="$store.genesisDashboard.cancelKnowledgeUpload()">Cancel</button>
              <button class="btn-sm" style="background: var(--color-accent); color: #fff;" @click="$store.genesisDashboard.confirmKnowledgeIngest()">Store</button>
            </div>
          </div>
        </template>

        <!-- Upload error outside confirmation -->
        <template x-if="$store.genesisDashboard.knowledgeUpload.error && !$store.genesisDashboard.knowledgeUpload.confirm">
          <div style="color: var(--color-error-text); margin-top: .5rem; font-size: .9em;" x-text="$store.genesisDashboard.knowledgeUpload.error"></div>
        </template>
      </div>

      <!-- ── Recent Uploads Status ────────────────────────────── -->
      <template x-if="$store.genesisDashboard.knowledgeUploads.length > 0">
        <div style="margin-bottom: 1.5rem;">
          <h4 style="margin-bottom: .5rem;">Recent Uploads</h4>
          <template x-for="upload in $store.genesisDashboard.knowledgeUploads.slice(0, 10)" :key="upload.id">
            <div class="card" style="margin-bottom: .4rem; padding: .6rem .8rem; display: flex; justify-content: space-between; align-items: center;">
              <div>
                <span x-text="upload.filename" style="font-weight: 500;"></span>
                <span style="font-size: .8em; color: var(--color-text-secondary); margin-left: .5rem;"
                      x-text="$store.genesisDashboard._formatFileSize(upload.file_size)"></span>
              </div>
              <div style="display: flex; align-items: center; gap: .5rem;">
                <template x-if="upload.status === 'processing'">
                  <span class="badge" style="background: var(--color-warning-text); color: #000;"
                        x-text="upload.chunks_total ? 'processing ' + (upload.chunks_done || 0) + '/' + upload.chunks_total : 'processing'"></span>
                </template>
                <template x-if="upload.status === 'completed'">
                  <span class="badge" style="background: var(--color-primary); color: #fff;" x-text="'completed (' + (JSON.parse(upload.unit_ids || '[]')).length + ' units)'"></span>
                </template>
                <template x-if="upload.status === 'failed'">
                  <span class="badge" style="background: var(--color-error-text); color: #fff;" :title="upload.error_message">failed</span>
                </template>
                <template x-if="upload.status === 'uploaded'">
                  <span class="badge">uploaded</span>
                </template>
              </div>
            </div>
          </template>
        </div>
      </template>

      <!-- Stats Cards -->
      <div style="display: flex; gap: 1rem; margin-bottom: 1.5rem; flex-wrap: wrap;">
        <div style="flex: 1; min-width: 100px; background: var(--color-background); border-radius: 6px; padding: .75rem; text-align: center;">
          <div style="font-size: 1.4rem; font-weight: 700;" x-text="$store.genesisDashboard.knowledgeStats?.total ?? '—'"></div>
          <div style="font-size: .75rem; color: var(--color-text-secondary);">Total Units</div>
        </div>
        <div style="flex: 1; min-width: 100px; background: var(--color-background); border-radius: 6px; padding: .75rem; text-align: center;">
          <div style="font-size: 1.4rem; font-weight: 700;" x-text="$store.genesisDashboard.knowledgeStats?.qdrant_vectors ?? '—'"></div>
          <div style="font-size: .75rem; color: var(--color-text-secondary);">Qdrant Vectors</div>
        </div>
        <div style="flex: 1; min-width: 100px; background: var(--color-background); border-radius: 6px; padding: .75rem; text-align: center;">
          <div style="font-size: 1.4rem; font-weight: 700;" x-text="Object.keys($store.genesisDashboard.knowledgeStats?.by_domain ?? {}).length"></div>
          <div style="font-size: .75rem; color: var(--color-text-secondary);">Domains</div>
        </div>
        <div style="flex: 1; min-width: 100px; background: var(--color-background); border-radius: 6px; padding: .75rem; text-align: center;">
          <div style="font-size: 1.4rem; font-weight: 700;" x-text="$store.genesisDashboard.knowledgeStats?.by_tier?.curated ?? 0"></div>
          <div style="font-size: .75rem; color: var(--color-text-secondary);">Curated</div>
        </div>
      </div>

      <!-- Tier Breakdown -->
      <template x-if="$store.genesisDashboard.knowledgeStats?.by_tier">
        <div style="margin-bottom: 1rem;">
          <strong>By Tier:</strong>
          <template x-for="[tier, count] in Object.entries($store.genesisDashboard.knowledgeStats.by_tier)" :key="tier">
            <span class="badge" style="margin: 0 .25rem;" x-text="tier + ': ' + count"></span>
          </template>
        </div>
      </template>

      <!-- Domain Breakdown -->
      <template x-if="$store.genesisDashboard.knowledgeStats?.by_domain">
        <div style="margin-bottom: 1.5rem;">
          <strong>By Domain:</strong>
          <template x-for="[domain, count] in Object.entries($store.genesisDashboard.knowledgeStats.by_domain)" :key="domain">
            <span class="badge" style="margin: 0 .25rem;" x-text="domain + ': ' + count"></span>
          </template>
        </div>
      </template>

      <!-- Search -->
      <div style="margin-bottom: 1rem; display: flex; gap: .5rem;">
        <input type="text" x-model="$store.genesisDashboard.knowledgeQuery" placeholder="Search knowledge base..."
               @keyup.enter="$store.genesisDashboard.searchKnowledge()"
               style="flex: 1; padding: .5rem; background: var(--color-background); border: 1px solid var(--color-border); color: var(--color-text); border-radius: 4px;">
        <button @click="$store.genesisDashboard.searchKnowledge()" class="btn-sm">Search</button>
      </div>

      <!-- Search Results -->
      <template x-if="$store.genesisDashboard.knowledgeSearchResults.length > 0">
        <div style="margin-bottom: 1.5rem;">
          <h4 style="margin-bottom: .5rem;">Search Results</h4>
          <div style="display: flex; flex-direction: column; gap: .5rem;">
            <template x-for="item in $store.genesisDashboard.knowledgeSearchResults" :key="item.unit_id">
              <div :style="`background: var(--color-background); border: 1px solid var(--color-border); border-left: 3px solid ${$store.genesisDashboard._domainColor(item.domain)}; border-radius: 6px; padding: .75rem; cursor: pointer; transition: background .15s;`"
                   @mouseenter="$el.style.background='rgba(255,255,255,0.06)'"
                   @mouseleave="$el.style.background=''"
                   @click="$store.genesisDashboard.viewKnowledgeDetail(item.unit_id)">
                <div style="display: flex; justify-content: space-between; align-items: center;">
                  <strong x-text="item.concept || item.unit_id" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 55%;"></strong>
                  <div style="display:flex; gap:.35rem; align-items:center;">
                    <span :style="`font-size:.65rem; padding:1px 6px; border-radius:3px; background:${$store.genesisDashboard._domainColor(item.domain)}22; color:${$store.genesisDashboard._domainColor(item.domain)};`"
                          x-text="item.domain"></span>
                    <span class="badge" x-text="item.source_pipeline || 'unknown'"></span>
                  </div>
                </div>
                <div style="font-size: .85em; margin-top: .25rem; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;"
                     x-text="(item.body || item.content || '').substring(0, 200)"></div>
              </div>
            </template>
          </div>
        </div>
      </template>

      <!-- Recent Units -->
      <h4 style="margin-bottom: .5rem;">Recent Knowledge Units</h4>
      <template x-if="$store.genesisDashboard.knowledgeRecent.length === 0">
        <p style="color: var(--color-text-secondary);">No knowledge units ingested yet.</p>
      </template>
      <div style="display: flex; flex-direction: column; gap: .5rem;">
        <template x-for="unit in $store.genesisDashboard.knowledgeRecent" :key="unit.id">
          <div :style="`background: var(--color-background); border: 1px solid var(--color-border); border-left: 3px solid ${$store.genesisDashboard._domainColor(unit.domain)}; border-radius: 6px; padding: .75rem; cursor: pointer; transition: background .15s;`"
               @mouseenter="$el.style.background='rgba(255,255,255,0.06)'"
               @mouseleave="$el.style.background=''"
               @click="$store.genesisDashboard.viewKnowledgeDetail(unit.id)">
            <div style="display: flex; justify-content: space-between; align-items: center;">
              <strong x-text="unit.concept || unit.id" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 55%;"></strong>
              <div style="display:flex; gap:.35rem; align-items:center;">
                <span :style="`font-size:.65rem; padding:1px 6px; border-radius:3px; background:${$store.genesisDashboard._tierColor(unit.source_pipeline)}22; color:${$store.genesisDashboard._tierColor(unit.source_pipeline)};`"
                      x-text="unit.source_pipeline || 'unknown'"></span>
                <span :style="`font-size:.65rem; padding:1px 6px; border-radius:3px; background:${$store.genesisDashboard._domainColor(unit.domain)}22; color:${$store.genesisDashboard._domainColor(unit.domain)};`"
                      x-text="unit.domain"></span>
              </div>
            </div>
            <div style="display:flex; justify-content:space-between; font-size: .8em; color: var(--color-text-secondary); margin-top:.25rem;">
              <span>
                <span x-text="unit.source_pipeline || 'unknown'" style="opacity:.7;"></span>
                <span x-show="unit.project_type"> | <span x-text="unit.project_type"></span></span>
              </span>
              <span x-text="unit.ingested_at?.substring(0, 10)" style="opacity:.6;"></span>
            </div>
            <div style="font-size: .85em; margin-top: .35rem; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height:1.4;"
                 x-text="(unit.body || '').substring(0, 200)"></div>
          </div>
        </template>
      </div>

      <!-- Detail Modal -->
      <template x-if="$store.genesisDashboard.knowledgeDetail">
        <div style="position: fixed; inset: 0; background: rgba(0,0,0,.6); z-index: 100; display: flex; align-items: center; justify-content: center;"
             @click.self="$store.genesisDashboard.knowledgeDetail = null">
          <div style="background: var(--color-panel); border: 1px solid var(--color-border); border-radius: 8px; padding: 1.5rem; max-width: 700px; width: 90%; max-height: 80vh; overflow-y: auto;">
            <h3 x-text="$store.genesisDashboard.knowledgeDetail.concept"></h3>
            <div style="margin: .75rem 0; font-size: .9em; color: var(--color-text-secondary);">
              <span x-text="'Domain: ' + $store.genesisDashboard.knowledgeDetail.domain"></span> |
              <span x-text="'Project: ' + $store.genesisDashboard.knowledgeDetail.project_type"></span> |
              <span x-text="'Pipeline: ' + ($store.genesisDashboard.knowledgeDetail.source_pipeline || 'unknown')"></span> |
              <span x-text="'Confidence: ' + $store.genesisDashboard.knowledgeDetail.confidence"></span>
            </div>
            <template x-if="$store.genesisDashboard.knowledgeDetail.purpose">
              <div style="margin-bottom: .5rem;"><strong>Purpose:</strong> <span x-text="$store.genesisDashboard.knowledgeDetail.purpose"></span></div>
            </template>
            <template x-if="$store.genesisDashboard.knowledgeDetail.ingestion_source">
              <div style="margin-bottom: .5rem;"><strong>Source:</strong> <span x-text="$store.genesisDashboard.knowledgeDetail.ingestion_source"></span></div>
            </template>
            <div style="white-space: pre-wrap; font-family: monospace; font-size: .85em; background: var(--color-background); padding: 1rem; border-radius: 4px; margin: .75rem 0;"
                 x-text="$store.genesisDashboard.knowledgeDetail.body"></div>
            <div style="display: flex; gap: .5rem; justify-content: space-between; margin-top: 1rem;">
              <button class="btn-sm btn-danger" @click="$store.genesisDashboard.deleteKnowledge($store.genesisDashboard.knowledgeDetail.id)">Delete</button>
              <button class="btn-sm" @click="$store.genesisDashboard.knowledgeDetail = null">Close</button>
            </div>
          </div>
        </div>
      </template>
      </div><!-- /panel-body padding -->
    </div>

    <!-- ═══════════════════════════════════════════════════════════
         Panel: Backup & Updates [Tab: backup]
         ═══════════════════════════════════════════════════════════ -->
    <div class="panel" x-show="$store.genesisDashboard.activeTab === 'backup'">
      <div class="panel-header">
        <span class="material-symbols-outlined">system_update</span>
        Backup & Updates
      </div>
      <div class="panel-body">

        <!-- ── Update Section ─────────────────────────────────── -->
        <div id="update-section" style="margin-bottom:1.5rem;">

          <!-- Updating overlay -->
          <template x-if="$store.genesisDashboard._updating">
            <div class="card" style="padding:1.5rem; text-align:center;">
              <div style="font-size:1.5rem; margin-bottom:0.5rem;">&#8987;</div>
              <div style="font-size:1rem; font-weight:500;"
                   x-text="$store.genesisDashboard._updatePhaseLabel($store.genesisDashboard.updateProgress?.phase)"></div>
              <div style="font-size:0.8rem; color:var(--color-text-secondary); margin-top:0.5rem;">A background session is managing the update. This may take a few minutes.</div>
              <div style="font-size:0.75rem; color:var(--color-text-secondary); margin-top:0.25rem;">Progress continues in the background. You can safely close or refresh this page.</div>
              <template x-if="$store.genesisDashboard.updateProgress?.summary">
                <div style="font-size:0.8rem; color:var(--color-text-secondary); margin-top:0.5rem; font-family:monospace;"
                     x-text="$store.genesisDashboard.updateProgress.summary"></div>
              </template>
            </div>
          </template>

          <!-- Resolving conflicts overlay -->
          <template x-if="$store.genesisDashboard._resolvingConflicts">
            <div class="card" style="padding:1.5rem; text-align:center;">
              <div style="font-size:1.5rem; margin-bottom:0.5rem;">&#128295;</div>
              <div style="font-size:1rem; font-weight:500;">Opus is resolving merge conflicts...</div>
              <div style="font-size:0.8rem; color:var(--color-text-secondary); margin-top:0.5rem;">This may take several minutes. The page will update when complete.</div>
            </div>
          </template>

          <!-- Normal update UI -->
          <template x-if="!$store.genesisDashboard._updating && !$store.genesisDashboard._resolvingConflicts">
            <div>
              <!-- Version + check/apply -->
              <div class="card" style="padding:1rem; margin-bottom:1rem;">
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.75rem;">
                  <h3 style="margin:0; font-size:1rem;">Genesis Version</h3>
                  <div style="display:flex; gap:0.5rem;">
                    <template x-if="$store.genesisDashboard.updateStatus?.update_available">
                      <button @click="$store.genesisDashboard.applyUpdate()"
                              style="background:#2196F3; color:#fff; border:none; padding:0.4rem 0.8rem; border-radius:4px; cursor:pointer; font-size:0.8rem;">
                        Install Update</button>
                    </template>
                    <button @click="$store.genesisDashboard.checkForUpdates()"
                            :disabled="$store.genesisDashboard._checkingForUpdates"
                            style="background:var(--color-surface-elevated); color:var(--color-text); border:1px solid var(--color-border); padding:0.4rem 0.8rem; border-radius:4px; cursor:pointer; font-size:0.8rem;">
                      <span x-text="$store.genesisDashboard._checkingForUpdates ? 'Checking...' : $store.genesisDashboard._checkUpToDate ? 'Up to date \u2714' : 'Check for Updates'"></span>
                    </button>
                  </div>
                </div>

                <!-- Current version -->
                <div style="display:flex; gap:1.5rem; flex-wrap:wrap; margin-bottom:0.5rem;">
                  <div>
                    <span style="font-size:0.7rem; color:var(--color-text-secondary);">Current</span><br>
                    <span style="font-size:0.9rem;" x-text="($store.genesisDashboard.updateStatus?.current_version || '...') + ' (' + ($store.genesisDashboard.updateStatus?.current_commit || '...') + ')'"></span>
                  </div>
                </div>

                <!-- Update available banner -->
                <template x-if="$store.genesisDashboard.updateStatus?.update_available">
                  <div style="margin-top:0.75rem; padding:0.75rem; border-radius:4px; background:rgba(33,150,243,0.1); border:1px solid rgba(33,150,243,0.3);">
                    <div style="font-size:0.85rem; font-weight:500; color:#2196F3;">
                      Update available
                      <span x-text="$store.genesisDashboard.updateStatus.update_available.target_tag ? '  ' + $store.genesisDashboard.updateStatus.update_available.target_tag : ''"></span>
                    </div>
                    <div style="font-size:0.8rem; color:var(--color-text-secondary); margin-top:0.25rem;"
                         x-text="($store.genesisDashboard.updateStatus.update_available.commits_behind || '?') + ' commit(s) behind'"></div>
                    <template x-if="$store.genesisDashboard.updateStatus.update_available.summary">
                      <pre style="font-size:0.75rem; color:var(--color-text-secondary); margin-top:0.5rem; max-height:6rem; overflow-y:auto; white-space:pre-wrap; background:transparent; border:none; padding:0;"
                           x-text="$store.genesisDashboard.updateStatus.update_available.summary"></pre>
                    </template>
                  </div>
                </template>

                <!-- Up to date -->
                <template x-if="$store.genesisDashboard.updateStatus && !$store.genesisDashboard.updateStatus.update_available">
                  <div style="margin-top:0.5rem; font-size:0.8rem; color:#81c784;">Up to date</div>
                </template>
              </div>

              <!-- Conflicts / failed update needing resolution -->
              <template x-if="$store.genesisDashboard.updateProgress?.conflicts || $store.genesisDashboard.updateProgress?.failed || $store.genesisDashboard.updateProgress?.stale">
                <div class="card" style="padding:1rem; margin-bottom:1rem; border:1px solid rgba(255,152,0,0.4);">
                  <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.75rem;">
                    <h3 style="margin:0; font-size:1rem; color:#ffb74d;"
                        x-text="$store.genesisDashboard.updateProgress?.conflicts ? 'Merge Conflicts' : 'Update Failed'"></h3>
                    <div style="display:flex; gap:0.5rem;">
                      <template x-if="$store.genesisDashboard.updateProgress?.conflicts">
                        <button @click="$store.genesisDashboard.resolveConflicts()"
                                style="background:#ff9800; color:#fff; border:none; padding:0.4rem 0.8rem; border-radius:4px; cursor:pointer; font-size:0.8rem;">
                          Resolve with Opus</button>
                      </template>
                      <button @click="$store.genesisDashboard.applyUpdate()"
                              style="background:var(--color-surface-elevated); color:var(--color-text); border:1px solid var(--color-border); padding:0.4rem 0.8rem; border-radius:4px; cursor:pointer; font-size:0.8rem;">
                        Retry</button>
                      <button @click="$store.genesisDashboard.dismissUpdate()"
                              style="background:transparent; color:var(--color-text-secondary); border:1px solid var(--color-border); padding:0.4rem 0.8rem; border-radius:4px; cursor:pointer; font-size:0.8rem;">
                        Dismiss</button>
                    </div>
                  </div>
                  <div style="font-size:0.8rem; color:var(--color-text-secondary);"
                       x-text="$store.genesisDashboard.updateProgress?.conflicts
                         ? 'The update has merge conflicts that could not be resolved automatically. Opus can analyze both sides and find the best resolution.'
                         : 'The last update attempt did not complete successfully. You can retry or dismiss this notice.'"></div>
                  <template x-if="$store.genesisDashboard.updateProgress?.summary">
                    <div style="margin-top:0.5rem; padding:0.5rem; border-radius:4px; background:rgba(255,152,0,0.05); font-size:0.8rem; font-family:monospace; color:var(--color-text-secondary);"
                         x-text="$store.genesisDashboard.updateProgress.summary"></div>
                  </template>
                  <template x-if="$store.genesisDashboard.updateProgress?.conflicts?.conflicted_files">
                    <div style="margin-top:0.5rem;">
                      <span style="font-size:0.7rem; color:var(--color-text-secondary);">Conflicted files:</span>
                      <pre style="font-size:0.75rem; color:#ffb74d; margin-top:0.25rem; white-space:pre-wrap; background:transparent; border:none; padding:0;"
                           x-text="$store.genesisDashboard.updateProgress.conflicts.conflicted_files.join('\n')"></pre>
                    </div>
                  </template>
                </div>
              </template>

              <!-- Last update result -->
              <template x-if="$store.genesisDashboard.updateStatus?.last_update">
                <div class="card" style="padding:1rem; margin-bottom:1rem;">
                  <h3 style="margin:0 0 0.75rem 0; font-size:1rem;">Last Update</h3>
                  <div style="display:flex; gap:1.5rem; flex-wrap:wrap;">
                    <div>
                      <span style="font-size:0.7rem; color:var(--color-text-secondary);">Status</span><br>
                      <span style="font-size:0.9rem;"
                            :style="$store.genesisDashboard.updateStatus.last_update.status === 'success' ? 'color:#81c784' : 'color:#ef9a9a'"
                            x-text="$store.genesisDashboard.updateStatus.last_update.status"></span>
                    </div>
                    <div>
                      <span style="font-size:0.7rem; color:var(--color-text-secondary);">Version</span><br>
                      <span style="font-size:0.9rem;" x-text="($store.genesisDashboard.updateStatus.last_update.old_tag || '?') + ' → ' + ($store.genesisDashboard.updateStatus.last_update.new_tag || '?')"></span>
                    </div>
                    <div>
                      <span style="font-size:0.7rem; color:var(--color-text-secondary);">When</span><br>
                      <span style="font-size:0.9rem;" x-text="$store.genesisDashboard.updateStatus.last_update.completed_at ? new Date($store.genesisDashboard.updateStatus.last_update.completed_at).toLocaleString() : 'in progress'"></span>
                    </div>
                  </div>
                  <template x-if="$store.genesisDashboard.updateStatus.last_update.failure_reason">
                    <div style="margin-top:0.75rem; padding:0.5rem; border-radius:4px; background:rgba(239,154,154,0.1); border:1px solid rgba(239,154,154,0.3); font-size:0.8rem; color:#ef9a9a;"
                         x-text="$store.genesisDashboard.updateStatus.last_update.failure_reason"></div>
                  </template>
                </div>
              </template>
            </div>
          </template>
        </div>

        <hr style="border:none; border-top:1px solid var(--color-border); margin-bottom:1.5rem;">

        <!-- ── Backup Section (original) ──────────────────────── -->
        <template x-if="!$store.genesisDashboard.backupStatus">
          <div style="padding:1rem; text-align:center; color:var(--color-text-secondary);">Loading...</div>
        </template>
        <template x-if="$store.genesisDashboard.backupStatus">
          <div>
            <!-- Status card -->
            <div class="card" style="padding:1rem; margin-bottom:1rem;">
              <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.75rem;">
                <h3 style="margin:0; font-size:1rem;">Backup Status</h3>
                <button @click="$store.genesisDashboard.triggerBackup()"
                        style="background:var(--color-accent); color:#000; border:none; padding:0.4rem 0.8rem; border-radius:4px; cursor:pointer; font-size:0.8rem;">
                  Run Now</button>
              </div>
              <template x-if="$store.genesisDashboard.backupStatus.last_backup">
                <div>
                  <div style="display:flex; gap:1.5rem; flex-wrap:wrap; margin-bottom:0.5rem;">
                    <div>
                      <span style="font-size:0.7rem; color:var(--color-text-secondary);">Last Run</span><br>
                      <span style="font-size:0.9rem;" x-text="new Date($store.genesisDashboard.backupStatus.last_backup.timestamp).toLocaleString()"></span>
                    </div>
                    <div>
                      <span style="font-size:0.7rem; color:var(--color-text-secondary);">Status</span><br>
                      <span style="font-size:0.9rem;"
                            :style="$store.genesisDashboard.backupStatus.last_backup.success ? 'color:#81c784' : 'color:#ef9a9a'"
                            x-text="$store.genesisDashboard.backupStatus.last_backup.success ? 'Success' : 'Failed'"></span>
                    </div>
                    <div>
                      <span style="font-size:0.7rem; color:var(--color-text-secondary);">Duration</span><br>
                      <span style="font-size:0.9rem;" x-text="$store.genesisDashboard.backupStatus.last_backup.duration_s + 's'"></span>
                    </div>
                  </div>
                  <template x-if="$store.genesisDashboard.backupStatus.last_backup.success">
                    <div style="display:flex; gap:1.5rem; flex-wrap:wrap; font-size:0.8rem; color:var(--color-text-secondary);">
                      <span x-text="'SQLite: ' + $store.genesisDashboard.backupStatus.last_backup.sqlite_lines + ' lines'"></span>
                      <span x-text="'Qdrant: ' + $store.genesisDashboard.backupStatus.last_backup.qdrant_collections + ' collections'"></span>
                      <span x-text="'Transcripts: ' + $store.genesisDashboard.backupStatus.last_backup.transcript_files + ' files'"></span>
                      <span x-text="'Memory: ' + $store.genesisDashboard.backupStatus.last_backup.memory_files + ' files'"></span>
                      <span :style="$store.genesisDashboard.backupStatus.last_backup.secrets_encrypted ? 'color:#81c784' : 'color:#ef9a9a'"
                            x-text="$store.genesisDashboard.backupStatus.last_backup.secrets_encrypted ? 'Secrets: encrypted' : 'Secrets: NOT encrypted'"></span>
                    </div>
                  </template>
                  <template x-if="!$store.genesisDashboard.backupStatus.last_backup.success">
                    <div>
                      <div style="margin-top:0.5rem; padding:0.5rem; border-radius:4px; background:rgba(239,154,154,0.1); border:1px solid rgba(239,154,154,0.3); font-size:0.8rem; color:#ef9a9a;"
                           x-text="$store.genesisDashboard.backupStatus.last_backup.failure_reason || 'Backup failed — check logs'"></div>
                      <template x-if="!$store.genesisDashboard.backupStatus?.repo_configured">
                        <div style="margin-top:0.4rem; padding:0.5rem; border-radius:4px; background:rgba(255,183,77,0.1); border:1px solid rgba(255,183,77,0.3); font-size:0.8rem; color:#ffb74d;">
                          Backup repo not configured. Set GENESIS_BACKUP_REPO in secrets.env and run a backup to clone it.</div>
                      </template>
                    </div>
                  </template>
                </div>
              </template>
              <template x-if="!$store.genesisDashboard.backupStatus.last_backup">
                <div style="color:var(--color-text-secondary);">No backup status file found. Run a backup to generate status.</div>
              </template>
            </div>
            <!-- Config card -->
            <div class="card" style="padding:1rem;">
              <h3 style="margin:0 0 0.5rem 0; font-size:1rem;">Configuration</h3>
              <div style="font-size:0.85rem;">
                <div style="margin-bottom:0.25rem;">
                  <span style="color:var(--color-text-secondary);">Repo:</span>
                  <span x-text="$store.genesisDashboard.backupStatus.repo || 'Not configured'"></span>
                </div>
                <div style="margin-bottom:0.25rem;">
                  <span style="color:var(--color-text-secondary);">Cron:</span>
                  <code style="font-size:0.8rem;" x-text="$store.genesisDashboard.backupStatus.cron_schedule || 'Not scheduled'"></code>
                </div>
                <div>
                  <span style="color:var(--color-text-secondary);">Script:</span>
                  <span x-text="$store.genesisDashboard.backupStatus.configured ? 'Installed' : 'Not found'"
                        :style="$store.genesisDashboard.backupStatus.configured ? 'color:#81c784' : 'color:#ef9a9a'"></span>
                </div>
              </div>
            </div>
          </div>
        </template>
      </div>
    </div>

    <!-- ═══════════════════════════════════════════════════════════════
         Confirm Modal (replaces window.confirm)
         ═══════════════════════════════════════════════════════════════ -->
    <template x-if="$store.genesisDashboard.confirmModal.show">
      <div style="position:fixed; inset:0; z-index:9999; display:flex; align-items:center; justify-content:center; background:rgba(0,0,0,0.6);"
           @click.self="$store.genesisDashboard._confirmModalResolve(false)">
        <div style="background:var(--color-bg-secondary); border:1px solid var(--color-border); border-radius:8px; padding:1.5rem; max-width:420px; width:90%; box-shadow:0 8px 32px rgba(0,0,0,0.4);">
          <h3 style="margin:0 0 0.75rem 0; font-size:1rem;" x-text="$store.genesisDashboard.confirmModal.title"></h3>
          <p style="color:var(--color-text-secondary); font-size:0.85rem; white-space:pre-line; margin:0 0 1.25rem 0; line-height:1.5;"
             x-text="$store.genesisDashboard.confirmModal.message"></p>
          <div style="display:flex; gap:0.5rem; justify-content:flex-end;">
            <button class="btn-sm" style="opacity:.7;" @click="$store.genesisDashboard._confirmModalResolve(false)">Cancel</button>
            <button class="btn-sm" style="background:var(--color-accent); color:#fff;" @click="$store.genesisDashboard._confirmModalResolve(true)">Confirm</button>
          </div>
        </div>
      </div>
    </template>

  <!-- Extra bottom padding so content isn't hidden behind the fixed footer -->
  <div style="height: 50px;"></div>

  <style>
    @keyframes spin {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }
  </style>

  <script>
  if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js').catch(e => console.warn('SW:', e)); }
  </script>

</body>

</html>
