﻿// ════════════════════════════════════════════════════════════════════════════
// app-config-view.jsx — v1.4.457
// ────────────────────────────────────────────────────────────────────────────
// Extracted from app.jsx in Session 71. Contains the Config screen and its
// sub-components: ConfigView, CredentialsTab, MachineManagementSection, and
// the MONITOR_DEFAULT_* constants used for system-wide defaults.
//
// Loading order: MUST load AFTER app.jsx. Depends on shared primitives
// (Btn, Card, Badge, ErrBox, OkBox, Spinner, SectionHead, API, c, etc.)
// via Babel's shared top-level lexical scope. No window.OP1 boilerplate.
// ════════════════════════════════════════════════════════════════════════════
// ═══ CONFIG ═══
const MONITOR_DEFAULT_SECTIONS = [
  { label:"General", keys:["default_check_frequency_seconds","default_failure_threshold","default_timeout_ms","default_response_time_warning_ms","default_response_time_critical_ms","default_ssl_expiry_warning_days","default_anomaly_baseline_days"] },
  { label:"Thresholds — Infrastructure", keys:["default_cpu_warning_percent","default_cpu_critical_percent","default_memory_warning_percent","default_memory_critical_percent","default_disk_warning_percent","default_disk_critical_percent"] },
  { label:"Thresholds — Database", keys:["default_db_query_latency_warning_ms","default_db_query_latency_critical_ms","default_db_connection_pool_warning_pct"] },
  { label:"Thresholds — Website", keys:["default_page_load_warning_ms","default_page_load_critical_ms"] },
  { label:"Scheduler & Retention", keys:["default_escalation_repeat_minutes","default_retention_hot_days","default_scheduler_refresh_seconds","default_max_concurrent_checks"] },
];
const MONITOR_DEFAULT_LABELS = {
  default_check_frequency_seconds:"Check Frequency (seconds)", default_failure_threshold:"Failure Threshold",
  default_timeout_ms:"Timeout (ms)", default_response_time_warning_ms:"Response Time Warning (ms)",
  default_response_time_critical_ms:"Response Time Critical (ms)", default_ssl_expiry_warning_days:"SSL Expiry Warning (days)",
  default_anomaly_baseline_days:"Anomaly Baseline Days", default_cpu_warning_percent:"CPU Warning (%)",
  default_cpu_critical_percent:"CPU Critical (%)", default_memory_warning_percent:"Memory Warning (%)",
  default_memory_critical_percent:"Memory Critical (%)", default_disk_warning_percent:"Disk Warning (%)",
  default_disk_critical_percent:"Disk Critical (%)", default_db_query_latency_warning_ms:"DB Query Latency Warning (ms)",
  default_db_query_latency_critical_ms:"DB Query Latency Critical (ms)", default_db_connection_pool_warning_pct:"DB Pool Warning (%)",
  default_page_load_warning_ms:"Page Load Warning (ms)", default_page_load_critical_ms:"Page Load Critical (ms)",
  default_escalation_repeat_minutes:"Escalation Repeat (minutes)", default_retention_hot_days:"Hot Retention (days)",
  default_scheduler_refresh_seconds:"Scheduler Refresh (seconds)", default_max_concurrent_checks:"Max Concurrent Checks",
};
const MONITOR_DEFAULT_DESC = {
  default_check_frequency_seconds:"Default check frequency (seconds)",
  default_failure_threshold:"Consecutive failures before alert",
  default_timeout_ms:"Check timeout (ms)",
  default_response_time_warning_ms:"Response time warning threshold (ms)",
  default_response_time_critical_ms:"Response time critical threshold (ms)",
  default_ssl_expiry_warning_days:"SSL cert expiry warning (days)",
  default_anomaly_baseline_days:"Anomaly detection baseline window (days)",
  default_cpu_warning_percent:"CPU warning threshold (%)",
  default_cpu_critical_percent:"CPU critical threshold (%)",
  default_memory_warning_percent:"Memory warning threshold (%)",
  default_memory_critical_percent:"Memory critical threshold (%)",
  default_disk_warning_percent:"Disk warning threshold (%)",
  default_disk_critical_percent:"Disk critical threshold (%)",
  default_db_query_latency_warning_ms:"DB query latency warning (ms)",
  default_db_query_latency_critical_ms:"DB query latency critical (ms)",
  default_db_connection_pool_warning_pct:"DB connection pool warning (%)",
  default_page_load_warning_ms:"Page load warning (ms)",
  default_page_load_critical_ms:"Page load critical (ms)",
  default_escalation_repeat_minutes:"Escalation repeat interval (minutes)",
  default_retention_hot_days:"Hot tier retention (days)",
  default_scheduler_refresh_seconds:"Scheduler monitor refresh interval (seconds)",
  default_max_concurrent_checks:"Max concurrent monitor checks",
};

function CredentialsTab({ api }) {
  const CRED_TYPES = ["Windows","Database","SNMP","SSH","APIKey","Generic"];
  const TYPE_COLORS = {
    Windows:  { bg:"#E0F2F7", color:"#006D8C" },
    Database: { bg:"#DCF2EA", color:"#008C6F" },
    SNMP:     { bg:"#FDF3E0", color:"#E89A2E" },
    SSH:      { bg:"#F0F7FB", color:"#4A4A4A" },
    APIKey:   { bg:"#FAEAEA", color:"#D95C5C" },
    Generic:  { bg:"#F5F0E8", color:"#6B6B6B" },
  };
  const BLANK = { Name:"", CredentialType:"Windows", Username:"", Password:"", Notes:"" };

  const [creds, setCreds]       = useState([]);
  const [loading, setLoading]   = useState(true);
  const [err, setErr]           = useState("");
  const [confirmModal, setConfirmModal] = useState(null);
  const showConfirm = (msg, onOk) => setConfirmModal({ msg, onOk });
  const [ok, setOk]             = useState("");
  const [form, setForm]         = useState(BLANK);
  const [editId, setEditId]     = useState(null);
  const [showPass, setShowPass] = useState(false);
  const [busy, setBusy]         = useState(false);

  const load = useCallback(() => {
    setLoading(true);
    api("GET", "/credentials")
      .then(r => { setCreds(Array.isArray(r) ? r : []); setErr(""); })
      .catch(e => setErr(e.message))
      .finally(() => setLoading(false));
  }, [api]);

  useEffect(() => { load(); }, [load]);

  const resetForm = () => { setForm(BLANK); setEditId(null); setShowPass(false); };

  const startEdit = (c) => {
    setForm({ Name: c.Name, CredentialType: c.CredentialType, Username: c.Username, Password: "", Notes: c.Notes || "" });
    setEditId(c.CredentialID);
    setShowPass(false);
  };

  const save = async () => {
    setErr(""); setOk(""); setBusy(true);
    try {
      if (editId) {
        await api("PUT", `/credentials/${editId}`, form);
        setOk("Credential updated.");
      } else {
        await api("POST", "/credentials", form);
        setOk("Credential created.");
      }
      resetForm(); load();
    } catch(e) { setErr(e.message); }
    finally { setBusy(false); }
  };

  const del = (c) => {
    showConfirm(`Delete credential "${c.Name}"?`, async () => {
      setErr(""); setOk("");
      try {
        await api("DELETE", `/credentials/${c.CredentialID}`);
        setOk("Credential deleted.");
        load();
      } catch(e) { setErr(e.message); }
    });
  };

  const f = (k, v) => setForm(p => ({ ...p, [k]: v }));

  const THstyle = { padding:"7px 12px", textAlign:"left", fontSize:11, fontWeight:600, color:"#1A1A1A", textTransform:"uppercase", letterSpacing:"0.05em", position:"sticky", top:0, zIndex:1, background:"#D8CCBA" };
  const TDstyle = { padding:"8px 12px", fontSize:12, color:"#1A1A1A", borderBottom:"0.5px solid #f1f5f9" };

  return (
    <div>
      <ErrBox msg={err} /><OkBox msg={ok} />
      <div style={{ background:"#ffffff", border:"0.5px solid #e2e5ea", borderRadius:8, overflow:"hidden", marginBottom:16 }}>
        <div style={{ padding:"10px 14px", background:"#f8fafc", borderBottom:"0.5px solid #e2e5ea", display:"flex", alignItems:"center", gap:12 }}>
          <span style={{ fontSize:11, fontWeight:700, color:"#1A1A1A" }}>Credential Vault</span>
          <span style={{ fontSize:11, color:"#94a3b8" }}>{creds.length} stored</span>
        </div>
        {loading ? <Spinner /> : creds.length === 0 ? (
          <div style={{ padding:32, textAlign:"center", color:"#94a3b8", fontSize:12 }}>No credentials stored. Add one below.</div>
        ) : (
          <table style={{ width:"100%", borderCollapse:"collapse", fontSize:12 }}>
            <thead><tr style={{ background:"#D8CCBA", borderBottom:"1px solid #C0C0B0" }}>
              {["Name","Type","Username","Notes","Monitors","Actions"].map(h =>
                <th key={h} style={THstyle}>{h}</th>
              )}
            </tr></thead>
            <tbody>
              {creds.map(c => {
                const tc = TYPE_COLORS[c.CredentialType] || TYPE_COLORS.Generic;
                const isEditing = editId === c.CredentialID;
                return (
                  <tr key={c.CredentialID} style={{ background: isEditing ? "#F0F7FB" : "#fff" }}>
                    <td style={TDstyle}><span style={{ fontWeight:600 }}>{c.Name}</span></td>
                    <td style={TDstyle}>
                      <span style={{ fontSize:10, fontWeight:600, padding:"2px 7px", borderRadius:10, background:tc.bg, color:tc.color }}>{c.CredentialType}</span>
                    </td>
                    <td style={{ ...TDstyle, fontFamily:"monospace" }}>{c.Username}</td>
                    <td style={{ ...TDstyle, color:"#64748b" }}>{c.Notes || "—"}</td>
                    <td style={{ ...TDstyle, textAlign:"center" }}>{c.MonitorCount}</td>
                    <td style={TDstyle}>
                      <div style={{ display:"flex", gap:4 }}>
                        <button onClick={() => startEdit(c)}
                          style={{ fontSize:10, padding:"2px 8px", border:"1px solid #006D8C", borderRadius:3, background:"#E0F2F7", color:"#006D8C", cursor:"pointer" }}>Edit</button>
                        <button onClick={() => del(c)} disabled={c.MonitorCount > 0}
                          title={c.MonitorCount > 0 ? `Used by ${c.MonitorCount} monitor(s)` : "Delete"}
                          style={{ fontSize:10, padding:"2px 8px", border:"1px solid #D95C5C", borderRadius:3, background: c.MonitorCount > 0 ? "#f1f5f9" : "#FAEAEA", color: c.MonitorCount > 0 ? "#94a3b8" : "#D95C5C", cursor: c.MonitorCount > 0 ? "not-allowed" : "pointer" }}>Delete</button>
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </div>

      <div style={{ background:"#ffffff", border:"0.5px solid #e2e5ea", borderRadius:8, padding:16 }}>
        <div style={{ fontSize:11, fontWeight:700, color:"#1A1A1A", marginBottom:12, textTransform:"uppercase", letterSpacing:"0.05em" }}>
          {editId ? "Edit Credential" : "Add Credential"}
        </div>
        <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr 1fr", gap:12, marginBottom:12 }}>
          <div>
            <label style={{ fontSize:10, fontWeight:600, color:"#64748b", textTransform:"uppercase", display:"block", marginBottom:4 }}>Name *</label>
            <input value={form.Name} onChange={e=>f("Name",e.target.value)} placeholder="e.g. DC01 Admin"
              style={{ width:"100%", fontSize:12, padding:"6px 8px", border:"1px solid #e2e5ea", borderRadius:4, outline:"none" }} />
          </div>
          <div>
            <label style={{ fontSize:10, fontWeight:600, color:"#64748b", textTransform:"uppercase", display:"block", marginBottom:4 }}>Type</label>
            <select value={form.CredentialType} onChange={e=>f("CredentialType",e.target.value)}
              style={{ width:"100%", fontSize:12, padding:"6px 8px", border:"1px solid #e2e5ea", borderRadius:4, outline:"none", background:"#fff" }}>
              {CRED_TYPES.map(t=><option key={t} value={t}>{t}</option>)}
            </select>
          </div>
          <div>
            <label style={{ fontSize:10, fontWeight:600, color:"#64748b", textTransform:"uppercase", display:"block", marginBottom:4 }}>Username *</label>
            <input value={form.Username} onChange={e=>f("Username",e.target.value)} placeholder="domain\user or username"
              style={{ width:"100%", fontSize:12, padding:"6px 8px", border:"1px solid #e2e5ea", borderRadius:4, outline:"none" }} />
          </div>
          <div style={{ position:"relative" }}>
            <label style={{ fontSize:10, fontWeight:600, color:"#64748b", textTransform:"uppercase", display:"block", marginBottom:4 }}>
              {editId ? "New Password (blank = keep)" : "Password *"}
            </label>
            <div style={{ position:"relative" }}>
              <input type={showPass?"text":"password"} value={form.Password} onChange={e=>f("Password",e.target.value)}
                placeholder={editId ? "Leave blank to keep existing" : "Enter password"}
                style={{ width:"100%", fontSize:12, padding:"6px 28px 6px 8px", border:"1px solid #e2e5ea", borderRadius:4, outline:"none" }} />
              <button onClick={()=>setShowPass(p=>!p)} tabIndex={-1}
                style={{ position:"absolute", right:6, top:"50%", transform:"translateY(-50%)", background:"none", border:"none", cursor:"pointer", fontSize:12, color:"#94a3b8" }}>
                {showPass?"\uD83D\uDE48":"\uD83D\uDC41"}
              </button>
            </div>
          </div>
          <div style={{ gridColumn:"2 / span 2" }}>
            <label style={{ fontSize:10, fontWeight:600, color:"#64748b", textTransform:"uppercase", display:"block", marginBottom:4 }}>Notes</label>
            <input value={form.Notes} onChange={e=>f("Notes",e.target.value)} placeholder="Optional description"
              style={{ width:"100%", fontSize:12, padding:"6px 8px", border:"1px solid #e2e5ea", borderRadius:4, outline:"none" }} />
          </div>
        </div>
        <div style={{ display:"flex", gap:8 }}>
          <button onClick={save} disabled={busy}
            style={{ fontSize:12, padding:"6px 18px", border:"none", borderRadius:4, background:"#006D8C", color:"#fff", cursor: busy ? "not-allowed" : "pointer", fontWeight:600 }}>
            {busy ? "Saving\u2026" : editId ? "Update" : "Save"}
          </button>
          {editId && (
            <button onClick={resetForm}
              style={{ fontSize:12, padding:"6px 14px", border:"1px solid #e2e5ea", borderRadius:4, background:"#fff", color:"#475569", cursor:"pointer" }}>
              Cancel
            </button>
          )}
        </div>
      </div>

      {confirmModal && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.75)', zIndex:1300, display:'flex', alignItems:'center', justifyContent:'center' }}
          onClick={e => { if(e.target===e.currentTarget) setConfirmModal(null); }}>
          <div style={{ background:'#fff', borderRadius:8, width:380, maxWidth:'90vw', padding:'24px', boxShadow:'0 8px 32px rgba(0,0,0,0.18)' }}>
            <div style={{ fontSize:13, color:'#1A1A1A', marginBottom:20, lineHeight:1.5 }}>{confirmModal.msg}</div>
            <div style={{ display:'flex', justifyContent:'flex-end', gap:8 }}>
              <button onClick={()=>setConfirmModal(null)}
                style={{ fontSize:12, padding:'6px 16px', border:'1px solid #006D8C', borderRadius:6, background:'#fff', color:'#006D8C', cursor:'pointer' }}>Cancel</button>
              <button onClick={()=>{ confirmModal.onOk(); setConfirmModal(null); }}
                style={{ fontSize:12, padding:'6px 16px', border:'none', borderRadius:6, background:'#D95C5C', color:'#fff', cursor:'pointer', fontWeight:600 }}>{confirmModal.okLabel || 'Confirm'}</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function ConfigView({ api, machines: machinesProp, currentMachine, onMachinesChange, monitoringControl }) {
  const [configTab, setConfigTab]           = useState("notifications");
  const [notifCfg, setNotifCfg]             = useState([]);
  const [retPolicies, setRetPolicies]       = useState([]);
  const [monDefaults, setMonDefaults]       = useState({});
  const [monDefaultsDirty, setMonDefaultsDirty] = useState({});
  const [err, setErr]                       = useState("");
  const [ok, setOk]                         = useState("");
  const [confirmModal, setConfirmModal]     = useState(null);
  const showConfirm = (msg, onOk) => setConfirmModal({ msg, onOk });
  const [aiCfg, setAiCfg]                   = useState(null);
  const [aiCfgLoading, setAiCfgLoading]     = useState(false);
  const [aiCfgSaving, setAiCfgSaving]       = useState(false);
  const [aiCfgSaved, setAiCfgSaved]         = useState(false);
  const [recentAlerts, setRecentAlerts]     = useState([]);
  // ── Notifications tab state ──
  const [notifChs, setNotifChs]                       = useState([]);
  const [notifRecs, setNotifRecs]                     = useState([]);
  const [notifSettings, setNotifSettings]             = useState({});
  const [notifLoading, setNotifLoading]               = useState(false);
  const [notifChannelModal, setNotifChannelModal]     = useState(null);
  const [notifRecipientModal, setNotifRecipientModal] = useState(null);
  const [notifTestState, setNotifTestState]           = useState({});
  const [notifSaving, setNotifSaving]                 = useState(false);
  const [notifRulesDraft, setNotifRulesDraft]         = useState({});
  const [notifTestCh, setNotifTestCh]                 = useState('');
  const [notifTestRec, setNotifTestRec]               = useState('');
  const [notifTestResult, setNotifTestResult]         = useState(null);
  const [notifTestDiag,   setNotifTestDiag]            = useState({});
  const [notifTestResultDiag, setNotifTestResultDiag] = useState(null);
  const [notifChannelDraft, setNotifChannelDraft]     = useState({});
  const [notifRecipientDraft, setNotifRecipientDraft] = useState({});

  // ── Config Pack state ──
  const [configPackTab, setConfigPackTab]   = useState('export');
  const [exportGroups, setExportGroups]     = useState([]);
  const [exportGroupsLoading, setExportGroupsLoading] = useState(false);
  const [selectedExportGroups, setSelectedExportGroups] = useState(null);
  const [exportFormat, setExportFormat]     = useState('json');
  const [exportLastDate, setExportLastDate] = useState(null);
  const [importFile, setImportFile]         = useState(null);
  const [importFilterGroups, setImportFilterGroups] = useState([]);
  const [importReview, setImportReview]     = useState(null);
  const [importReviewLoading, setImportReviewLoading] = useState(false);
  const [importCommitting, setImportCommitting] = useState(false);
  const [importCommitResult, setImportCommitResult] = useState(null);
  const [conflictResolution, setConflictResolution] = useState('skip');

  // ── Ingest Feeds state ──
  const [feedsList, setFeedsList]               = useState([]);
  const [feedsLoading, setFeedsLoading]         = useState(false);
  const [feedWizardOpen, setFeedWizardOpen]     = useState(false);
  const feedWizardRef = useRef(null);
  const [feedWizardStep, setFeedWizardStep]     = useState(1);
  const [feedForm, setFeedForm]                 = useState({ feedName:'', protocol:'influxdb', notes:'', scrapeInterval:'30', scrapeTimeout:'10' });
  const [feedSampleMode, setFeedSampleMode]     = useState('file');
  const [feedSampleFile, setFeedSampleFile]     = useState(null);
  const [feedSampleJson, setFeedSampleJson]     = useState('');
  const [feedReviewLoading, setFeedReviewLoading] = useState(false);
  const [feedReview, setFeedReview]             = useState(null);
  const [feedMappings, setFeedMappings]         = useState([]);
  const [feedConfirmLoading, setFeedConfirmLoading] = useState(false);
  const [feedConfirmResult, setFeedConfirmResult] = useState(null);
  const [monitorsForMapping, setMonitorsForMapping] = useState([]);
  const [scrapeTargets, setScrapeTargets]           = useState([]);
  const [scrapeTargetUrl, setScrapeTargetUrl]       = useState('');
  const [scrapeTargetCredId, setScrapeTargetCredId] = useState('');
  const [scrapeTestResult, setScrapeTestResult]     = useState(null);
  const [scrapeTestLoading, setScrapeTestLoading]   = useState(false);
  const [rawPayloadOpen, setRawPayloadOpen]         = useState(null);
  const [rawPayload, setRawPayload]                 = useState(null);
  const [rawPayloadLoading, setRawPayloadLoading]   = useState(false);
  const [credentialsList, setCredentialsList]       = useState([]);
  const [feedCreatedId, setFeedCreatedId]           = useState(null);
  const [scrapeTargetsByFeed, setScrapeTargetsByFeed] = useState({});
  const [feedAiOpenId, setFeedAiOpenId]     = useState(null);
  const [feedAiThreads, setFeedAiThreads]   = useState({});
  const [feedAiInput, setFeedAiInput]       = useState({});
  const [feedAiLoading, setFeedAiLoading]   = useState({});
  const [feedIsNewSystem, setFeedIsNewSystem]         = useState(false);
  const [feedTargetGroupId, setFeedTargetGroupId]     = useState(null);
  const [feedNewGroupName, setFeedNewGroupName]       = useState('');
  const [feedSystemDescription, setFeedSystemDescription] = useState('');

  // ── Metric Mappings state ──
  const [mappingsList, setMappingsList]           = useState([]);
  const [mappingsLoading, setMappingsLoading]     = useState(false);
  const [unresolvedList, setUnresolvedList]       = useState([]);
  const [unresolvedLoading, setUnresolvedLoading] = useState(false);
  const [mappingAddOpen, setMappingAddOpen]       = useState(false);
  const [mappingForm, setMappingForm]             = useState({ protocol:'', pattern:'', monitorId:'' });
  const [mappingAddSaving, setMappingAddSaving]   = useState(false);
  const [mappingDeleteId, setMappingDeleteId]     = useState(null);
  const [unresolvedCreateOpen, setUnresolvedCreateOpen]   = useState(null);
  const [unresolvedCreateForm, setUnresolvedCreateForm]   = useState({ name:'', subtype:'app-http', groupId:'' });
  const [unresolvedCreateSaving, setUnresolvedCreateSaving] = useState(false);
  const [unresolvedCreateSuccess, setUnresolvedCreateSuccess] = useState(null);
  const [shProbes, setShProbes]                   = useState(null);
  const [shProbesLoading, setShProbesLoading]     = useState(false);
  const [shProbesLastRefresh, setShProbesLastRefresh] = useState(null);
  const [shIncidents, setShIncidents]             = useState(null);
  const [shIncidentsLoading, setShIncidentsLoading] = useState(false);
  const [shSources, setShSources]                 = useState([]);
  const [shFilterActive, setShFilterActive]       = useState(true);
  const [shFilterSeverity, setShFilterSeverity]   = useState("");
  const [shFilterSource, setShFilterSource]       = useState("");
  const [shFilterSearch, setShFilterSearch]       = useState("");
  const [shIncidentModal, setShIncidentModal]     = useState(null);
  const [shAnthropic, setShAnthropic]             = useState(null);
  const [shAnthropicLoading, setShAnthropicLoading] = useState(false);

  useEffect(()=>{
    const id = "op1-ticker-kf";
    if (!document.getElementById(id)) {
      const el = document.createElement("style"); el.id = id;
      el.textContent = "@keyframes op1-ticker { from { transform:translateX(0) } to { transform:translateX(-50%) } }";
      document.head.appendChild(el);
    }
    api("GET","/config/notifications").then(r=>setNotifCfg(Array.isArray(r)?r:[])).catch(()=>{});
    api("GET","/retention").then(r=>setRetPolicies(Array.isArray(r)?r:[])).catch(()=>{});
    api("GET","/config/monitor-defaults").then(r=>{ if(r && typeof r==="object") setMonDefaults(r); }).catch(()=>{});
    api("GET","/alerts/recent?top=20").then(r=>setRecentAlerts(Array.isArray(r)?r:[])).catch(()=>{});
  },[api]);

  useEffect(()=>{
    if (configTab === "ai-diagnosis" && aiCfg === null) {
      setAiCfgLoading(true);
      api("GET","/config/ai-diagnosis").then(r=>{ if(r && typeof r==="object") setAiCfg(r); }).catch(()=>{}).finally(()=>setAiCfgLoading(false));
    }
  },[configTab, aiCfg, api]);

  useEffect(()=>{
    if (configTab !== "notifications") return;
    setNotifLoading(true);
    Promise.all([
      api("GET","/notifications/channels"),
      api("GET","/notifications/recipients"),
      api("GET","/notifications/settings"),
    ]).then(([chs,recs,settings])=>{
      setNotifChs(Array.isArray(chs)?chs:[]);
      setNotifRecs(Array.isArray(recs)?recs:[]);
      setNotifSettings(settings&&typeof settings==='object'?settings:{});
    }).catch(()=>{}).finally(()=>setNotifLoading(false));
  },[configTab,api]);

  useEffect(()=>{ setNotifRulesDraft(notifSettings); },[notifSettings]);

  useEffect(()=>{
    if (configTab !== "configpack") return;
    setExportGroupsLoading(true);
    api("GET","/config-pack/groups")
      .then(d=>setExportGroups(Array.isArray(d)?d:[]))
      .catch(()=>{})
      .finally(()=>setExportGroupsLoading(false));
  },[configTab, api]);

  useEffect(()=>{
    if (configTab !== "configpack" || configPackTab !== "feeds") return;
    setFeedsLoading(true);
    api("GET","/ingest/feeds")
      .then(async d=>{
        const feeds = Array.isArray(d) ? d : [];
        setFeedsList(feeds);
        const scrapeFeeds = feeds.filter(f => f.IsScrape);
        if (scrapeFeeds.length > 0) {
          const results = await Promise.all(scrapeFeeds.map(f=>api("GET",`/ingest/feeds/${f.FeedID}/targets`).catch(()=>[])));
          const byFeed = {};
          scrapeFeeds.forEach((f,i)=>{ byFeed[f.FeedID]=Array.isArray(results[i])?results[i]:[]; });
          setScrapeTargetsByFeed(byFeed);
        }
      })
      .catch(()=>{})
      .finally(()=>setFeedsLoading(false));
  },[configTab, configPackTab, api]);

  useEffect(()=>{
    if (configTab !== "configpack" || configPackTab !== "mappings") return;
    setMappingsLoading(true);
    setUnresolvedLoading(true);
    api("GET","/ingest/mappings")
      .then(d=>setMappingsList(Array.isArray(d)?d:[]))
      .catch(()=>{})
      .finally(()=>setMappingsLoading(false));
    api("GET","/ingest/mappings/unresolved")
      .then(d=>setUnresolvedList(Array.isArray(d)?d:[]))
      .catch(()=>{})
      .finally(()=>setUnresolvedLoading(false));
  },[configTab, configPackTab, api]);

  useEffect(()=>{
    if (feedWizardOpen && feedWizardRef.current) {
      feedWizardRef.current.scrollIntoView({ behavior:'smooth', block:'start' });
    }
  },[feedWizardOpen]);

  useEffect(()=>{
    if (feedWizardStep !== 3 || feedForm.protocol !== 'prometheus-scrape' || feedCreatedId !== null) return;
    const tok = localStorage.getItem("op1_token") || "";
    const run = async () => {
      setFeedReviewLoading(true);
      try {
        const feedRes = await fetch('/api/ingest/feeds', {
          method:'POST', headers:{'Content-Type':'application/json',Authorization:'Bearer '+tok},
          body: JSON.stringify({ FeedName:feedForm.feedName, Protocol:'prometheus-scrape', Notes:feedForm.notes, IsScrape:true, ScrapeIntervalSeconds:parseInt(feedForm.scrapeInterval)||30, ScrapeTimeoutSeconds:parseInt(feedForm.scrapeTimeout)||10 })
        });
        if (!feedRes.ok) throw new Error('Feed creation failed');
        const fd = await feedRes.json();
        setFeedCreatedId(fd.feedId);
        for (const t of scrapeTargets) {
          await fetch(`/api/ingest/feeds/${fd.feedId}/targets`, {
            method:'POST', headers:{'Content-Type':'application/json',Authorization:'Bearer '+tok},
            body: JSON.stringify({ FeedID:fd.feedId, ScrapeUrl:t.url, CredentialID:t.credId?parseInt(t.credId):null })
          }).catch(()=>{});
        }
        const allMetrics = scrapeTargets.flatMap(t=>t.sampleMetrics||[]);
        if (allMetrics.length > 0) {
          const fd2 = new FormData();
          fd2.append('protocol','prometheus');
          fd2.append('rawJson', JSON.stringify(allMetrics.map(m=>({metric_name:m}))));
          const reviewRes = await fetch('/api/ingest/feeds/review',{method:'POST',headers:{Authorization:'Bearer '+tok},body:fd2});
          if (reviewRes.ok) {
            const rv = await reviewRes.json();
            setFeedReview(rv);
            setFeedMappings((rv.Suggestions||[]).map(s=>({...s,included:s.Status!=='unresolved',overrideMonitorId:null,newMonitorName:''})));
            if (monitorsForMapping.length===0) api("GET","/monitors").then(r=>{if(Array.isArray(r))setMonitorsForMapping(r);}).catch(()=>{});
          } else {
            setFeedReview({HaikuSummary:'AI review unavailable.',TotalMetrics:allMetrics.length,HighConfidenceCount:0,MediumConfidenceCount:0,UnresolvedCount:0,Suggestions:[]});
            setFeedMappings([]);
          }
        } else {
          setFeedReview({HaikuSummary:'No sample metrics available — targets are scheduled and will begin scraping shortly.',TotalMetrics:0,HighConfidenceCount:0,MediumConfidenceCount:0,UnresolvedCount:0,Suggestions:[]});
          setFeedMappings([]);
        }
        api("GET","/ingest/feeds").then(r=>{if(Array.isArray(r))setFeedsList(r);}).catch(()=>{});
        api("GET",`/ingest/feeds/${fd.feedId}/targets`).then(r=>{if(Array.isArray(r))setScrapeTargetsByFeed(prev=>({...prev,[fd.feedId]:r}));}).catch(()=>{});
        setFeedConfirmResult({created:0});
      } catch(e) {
        alert('Setup failed: '+e.message);
        setFeedWizardStep(2);
      } finally {
        setFeedReviewLoading(false);
      }
    };
    run();
  },[feedWizardStep, feedCreatedId]);

  const shRelTime = (d) => {
    if (!d) return "just now";
    const secs = Math.round((Date.now() - d.getTime()) / 1000);
    if (secs < 60) return `${secs}s ago`;
    if (secs < 3600) return `${Math.floor(secs/60)}m ago`;
    if (secs < 86400) return `${Math.floor(secs/3600)}h ago`;
    return `${Math.floor(secs/86400)}d ago`;
  };

  const doShProbesRefresh = () => {
    setShProbesLoading(true);
    api("GET","/system-health/baseline")
      .then(r=>{ setShProbes(Array.isArray(r?.Probes)?r.Probes:[]); setShProbesLastRefresh(new Date()); })
      .catch(()=>setShProbes([]))
      .finally(()=>setShProbesLoading(false));
  };

  const doShAck = (id) => {
    api("POST",`/system-health/incidents/${id}/acknowledge`,{})
      .then(()=>setShIncidents(prev=>(prev||[]).map(i=>i.IncidentID===id?{...i,AcknowledgedAt:new Date().toISOString()}:i)))
      .catch(e=>setErr(e.message));
  };

  const doShResolve = (id) => {
    api("POST",`/system-health/incidents/${id}/resolve`,{})
      .then(()=>setShIncidents(prev=>(prev||[]).map(i=>i.IncidentID===id?{...i,IsActive:false}:i)))
      .catch(e=>setErr(e.message));
  };

  const loadShAnthropic = () => {
    setShAnthropicLoading(true);
    api("GET","/system-health/anthropic-stats")
      .then(r=>setShAnthropic(r))
      .catch(()=>setShAnthropic(null))
      .finally(()=>setShAnthropicLoading(false));
  };

  useEffect(()=>{
    if (configTab !== "systemhealth") return;
    doShProbesRefresh();
    loadShAnthropic();
    api("GET","/system-health/incidents/sources")
      .then(r=>setShSources(Array.isArray(r?.sources)?r.sources:[]))
      .catch(()=>{});
  },[configTab]);

  useEffect(()=>{
    if (configTab !== "systemhealth") return;
    setShIncidentsLoading(true);
    const tid = setTimeout(()=>{
      const params = new URLSearchParams();
      params.set("activeOnly", shFilterActive ? "true" : "false");
      if (shFilterSeverity) params.set("severity", shFilterSeverity);
      if (shFilterSource)   params.set("source",   shFilterSource);
      api("GET",`/system-health/incidents?${params}`)
        .then(r=>setShIncidents(Array.isArray(r)?r:[]))
        .catch(()=>setShIncidents([]))
        .finally(()=>setShIncidentsLoading(false));
    }, 250);
    return ()=>clearTimeout(tid);
  },[configTab, shFilterActive, shFilterSeverity, shFilterSource, api]);

  const saveAiCfg = async () => {
    if (!aiCfg) return;
    setAiCfgSaving(true);
    try {
      await api("PUT","/config/ai-diagnosis", { enabled: aiCfg.enabled, minSeverity: aiCfg.minSeverity, cooldownMinutes: aiCfg.cooldownMinutes });
      setAiCfgSaved(true);
      setTimeout(()=>setAiCfgSaved(false), 2000);
    } catch(e){ setErr(e.message); }
    finally { setAiCfgSaving(false); }
  };

  const runPurge = async () => {
    setErr(""); setOk("");
    try { await api("POST","/retention/purge",{}); setOk("Purge job triggered."); } catch(e){setErr(e.message);}
  };

  const saveDefaults = async () => {
    setErr(""); setOk("");
    try {
      const payload = { ...monDefaults, ...monDefaultsDirty };
      await api("POST","/config/monitor-defaults/save", payload);
      setMonDefaults(payload); setMonDefaultsDirty({});
      setOk("Monitor defaults saved.");
    } catch(e){ setErr(e.message); }
  };

  const loadNotificationsTab = () => {
    setNotifLoading(true);
    Promise.all([
      api("GET","/notifications/channels"),
      api("GET","/notifications/recipients"),
      api("GET","/notifications/settings"),
    ]).then(([chs,recs,settings])=>{
      setNotifChs(Array.isArray(chs)?chs:[]);
      setNotifRecs(Array.isArray(recs)?recs:[]);
      setNotifSettings(settings&&typeof settings==='object'?settings:{});
    }).catch(()=>{}).finally(()=>setNotifLoading(false));
  };

  const saveNotifSetting = (key, value) => {
    api("POST","/notifications/settings",{key,value:String(value)})
      .then(()=>setNotifSettings(prev=>({...prev,[key]:String(value)})))
      .catch(()=>{});
  };

  // ── Config Pack helpers ──
  const handleExportDownload = () => {
    const selGroups = selectedExportGroups && selectedExportGroups.length < exportGroups.length ? selectedExportGroups : null;
    const groupsParam = selGroups ? '&groups=' + encodeURIComponent(selGroups.join(',')) : '';
    const url = '/api/config-pack/export?format=' + exportFormat + groupsParam;
    const tok = localStorage.getItem("op1_token") || "";
    fetch(url, { headers: { Authorization: 'Bearer ' + tok } })
      .then(r => r.blob())
      .then(blob => {
        const ext = exportFormat === 'xlsx' ? 'xlsx' : 'json';
        const fname = 'op1-config-' + new Date().toISOString().slice(0,10) + '.' + ext;
        const burl = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = burl;
        a.download = fname;
        document.body.appendChild(a);
        a.click();
        a.remove();
        URL.revokeObjectURL(burl);
        setExportLastDate(new Date().toLocaleString());
      });
  };

  const handleFileSelect = (e) => {
    const f = e.target.files[0];
    if (!f) return;
    setImportFile(f);
    setImportReview(null);
    setImportCommitResult(null);
  };

  const handleReview = async () => {
    if (!importFile) return;
    setImportReviewLoading(true);
    setImportReview(null);
    try {
      const fd = new FormData();
      fd.append('file', importFile);
      if (importFilterGroups.length > 0) {
        fd.append('groups', importFilterGroups.join(','));
      }
      const tok = localStorage.getItem("op1_token") || "";
      const res = await fetch('/api/config-pack/review', {
        method: 'POST',
        headers: { Authorization: 'Bearer ' + tok },
        body: fd
      });
      if (res.ok) { setImportReview(await res.json()); }
      else { alert('Review failed: ' + await res.text()); }
    } catch(e) { alert('Error: ' + e.message); }
    finally { setImportReviewLoading(false); }
  };

  const handleCommit = async (readyOnly) => {
    if (!importReview) return;
    setImportCommitting(true);
    try {
      const monitors = readyOnly
        ? importReview.Rows.filter(r => r.Status === 0).map(r => r.Data)
        : importReview.Rows.filter(r => r.Status !== 2 || conflictResolution === 'overwrite').map(r => r.Data);
      const body = {
        Monitors: monitors.filter(Boolean),
        GroupsToCreate: importReview.GroupsToCreate,
        ConflictResolution: conflictResolution
      };
      const tok = localStorage.getItem("op1_token") || "";
      const res = await fetch('/api/config-pack/commit', {
        method: 'POST',
        headers: { Authorization: 'Bearer ' + tok, 'Content-Type': 'application/json' },
        body: JSON.stringify(body)
      });
      if (res.ok) {
        setImportCommitResult(await res.json());
        setImportReview(null);
        setImportFile(null);
      } else { alert('Commit failed: ' + await res.text()); }
    } catch(e) { alert('Error: ' + e.message); }
    finally { setImportCommitting(false); }
  };

  const toggleAllGroups = () => {
    const allSelected = selectedExportGroups===null || selectedExportGroups.length===exportGroups.length;
    if (allSelected) { setSelectedExportGroups([]); } else { setSelectedExportGroups(null); }
  };

  const toggleGroup = (groupName) => {
    const current = selectedExportGroups===null ? exportGroups.map(g=>g.GroupName) : [...selectedExportGroups];
    const idx = current.indexOf(groupName);
    if (idx >= 0) {
      const next = current.filter(n=>n!==groupName);
      setSelectedExportGroups(next.length===exportGroups.length ? null : next);
    } else {
      const next = [...current, groupName];
      setSelectedExportGroups(next.length===exportGroups.length ? null : next);
    }
  };

  // ── Ingest Feeds wizard helpers ──
  const resetFeedWizard = () => {
    setFeedWizardOpen(false);
    setFeedWizardStep(1);
    setFeedForm({ feedName:'', protocol:'influxdb', notes:'', scrapeInterval:'30', scrapeTimeout:'10' });
    setFeedSampleMode('file');
    setFeedSampleFile(null);
    setFeedSampleJson('');
    setFeedReview(null);
    setFeedMappings([]);
    setFeedConfirmResult(null);
    setScrapeTargets([]);
    setScrapeTargetUrl('');
    setScrapeTargetCredId('');
    setScrapeTestResult(null);
    setFeedCreatedId(null);
    setRawPayloadOpen(null);
    setRawPayload(null);
    setFeedIsNewSystem(false);
    setFeedTargetGroupId(null);
    setFeedNewGroupName('');
    setFeedSystemDescription('');
  };

  const handleFeedReview = async () => {
    setFeedReviewLoading(true);
    setFeedReview(null);
    try {
      const tok = localStorage.getItem("op1_token") || "";
      const fd = new FormData();
      fd.append('protocol', feedForm.protocol);
      fd.append('isNewSystem', feedIsNewSystem ? 'true' : 'false');
      fd.append('targetGroupId', (feedTargetGroupId && feedTargetGroupId !== '__new__') ? String(feedTargetGroupId) : '');
      fd.append('newGroupName', feedNewGroupName || '');
      fd.append('systemDescription', feedSystemDescription || '');
      if (feedSampleMode === 'file' && feedSampleFile) fd.append('file', feedSampleFile);
      if (feedSampleMode === 'json' && feedSampleJson) fd.append('rawJson', feedSampleJson);
      const res = await fetch('/api/ingest/feeds/review', {
        method: 'POST',
        headers: { Authorization: 'Bearer ' + tok },
        body: fd
      });
      if (!res.ok) throw new Error('Review failed: ' + await res.text());
      const data = await res.json();
      setFeedReview(data);
      setFeedMappings((data.Suggestions || []).map(s => ({
        ...s, included: s.Status !== 'unresolved', overrideMonitorId: null,
        newMonitorName: feedIsNewSystem && !s.MonitorID ? (s.MonitorName || '') : ''
      })));
      if (monitorsForMapping.length === 0) {
        api("GET","/monitors").then(r=>{ if(Array.isArray(r)) setMonitorsForMapping(r); }).catch(()=>{});
      }
      setFeedWizardStep(3);
    } catch(e) {
      alert('Haiku review failed: ' + e.message);
    } finally {
      setFeedReviewLoading(false);
    }
  };

  const handleFeedConfirm = async () => {
    setFeedConfirmLoading(true);
    try {
      const tok = localStorage.getItem("op1_token") || "";
      const mappings = feedMappings
        .filter(m => m.included)
        .map(m => ({
          MetricNamePattern: m.MetricNamePattern,
          MonitorID: m.overrideMonitorId || m.MonitorID || null,
          NewMonitorName: m.newMonitorName || '',
          MonitorSubType: m.MonitorSubType || 'app-http'
        }));
      const protocol = feedForm.protocol === 'prometheus-scrape' ? 'prometheus' : feedForm.protocol;
      const body = {
        Protocol: protocol,
        FeedID: feedCreatedId || null,
        Mappings: mappings,
        IsNewSystem: feedIsNewSystem,
        TargetGroupId: (feedTargetGroupId && feedTargetGroupId !== '__new__') ? Number(feedTargetGroupId) : null,
        NewGroupName: feedNewGroupName || null
      };
      const res = await fetch('/api/ingest/feeds/confirm-mappings', {
        method: 'POST',
        headers: { 'Content-Type':'application/json', Authorization:'Bearer '+tok },
        body: JSON.stringify(body)
      });
      if (!res.ok) throw new Error('Confirm failed');
      const data = await res.json();
      if (!feedCreatedId && feedForm.feedName.trim()) {
        await fetch('/api/ingest/feeds', {
          method: 'POST',
          headers: { 'Content-Type':'application/json', Authorization:'Bearer '+tok },
          body: JSON.stringify({ FeedName: feedForm.feedName, Protocol: feedForm.protocol, Notes: feedForm.notes })
        });
      }
      setFeedConfirmResult(data);
      setFeedWizardStep(4);
      api("GET","/ingest/feeds").then(r=>{ if(Array.isArray(r)) setFeedsList(r); }).catch(()=>{});
      if (feedCreatedId) {
        api("GET",`/ingest/feeds/${feedCreatedId}/targets`).then(r=>{ if(Array.isArray(r)) setScrapeTargetsByFeed(prev=>({...prev,[feedCreatedId]:r})); }).catch(()=>{});
      }
    } catch(e) {
      alert('Confirm failed: ' + e.message);
    } finally {
      setFeedConfirmLoading(false);
    }
  };

  // ── Metric Mappings helpers ──
  const handleMappingAdd = async () => {
    setMappingAddSaving(true);
    try {
      const tok = localStorage.getItem("op1_token") || "";
      const res = await fetch('/api/ingest/mappings', {
        method: 'POST',
        headers: { 'Content-Type':'application/json', Authorization:'Bearer '+tok },
        body: JSON.stringify({ SourceProtocol: mappingForm.protocol, MetricNamePattern: mappingForm.pattern, MonitorID: parseInt(mappingForm.monitorId) })
      });
      if (!res.ok) throw new Error('Save failed');
      setMappingAddOpen(false);
      setMappingForm({ protocol:'', pattern:'', monitorId:'' });
      const r = await fetch('/api/ingest/mappings', { headers:{ Authorization:'Bearer '+tok }});
      if (r.ok) setMappingsList(await r.json());
    } catch(e) { alert('Failed: ' + e.message); }
    finally { setMappingAddSaving(false); }
  };

  const handleMappingDelete = async (mappingId) => {
    setMappingDeleteId(mappingId);
    try {
      const tok = localStorage.getItem("op1_token") || "";
      await fetch('/api/ingest/mappings/'+mappingId, { method:'DELETE', headers:{ Authorization:'Bearer '+tok }});
      setMappingsList(prev => prev.filter(m => m.MappingID !== mappingId));
    } catch(e) { alert('Delete failed'); }
    finally { setMappingDeleteId(null); }
  };

  const handleUnresolvedQuickAdd = (row) => {
    setMappingForm({ protocol: row.SourceProtocol || '', pattern: row.MetricName || '', monitorId:'' });
    if (monitorsForMapping.length === 0) {
      api("GET","/monitors").then(r=>{ if(Array.isArray(r)) setMonitorsForMapping(r); }).catch(()=>{});
    }
    setMappingAddOpen(true);
  };

  const handleUnresolvedCreateMonitor = async (row) => {
    setUnresolvedCreateSaving(true);
    try {
      const tok = localStorage.getItem("op1_token") || "";
      const monRes = await fetch('/api/monitors', {
        method: 'POST',
        headers: { 'Content-Type':'application/json', Authorization:'Bearer '+tok },
        body: JSON.stringify({
          MonitorName: unresolvedCreateForm.name,
          MonitorType: 'application',
          MonitorSubType: unresolvedCreateForm.subtype,
          GroupID: unresolvedCreateForm.groupId ? Number(unresolvedCreateForm.groupId) : null,
          IsEnabled: false,
          IPAddressOrUrl: ''
        })
      });
      if (!monRes.ok) throw new Error('Create monitor failed: ' + await monRes.text());
      const monData = await monRes.json();
      const newMonitorId = monData.MonitorID;
      const mapRes = await fetch('/api/ingest/mappings', {
        method: 'POST',
        headers: { 'Content-Type':'application/json', Authorization:'Bearer '+tok },
        body: JSON.stringify({ SourceProtocol: row.SourceProtocol || '', MetricNamePattern: row.MetricName, MonitorID: newMonitorId })
      });
      if (!mapRes.ok) throw new Error('Create mapping failed');
      const rowKey = (row.MetricName||'')+'|'+(row.SourceProtocol||'');
      setUnresolvedCreateSuccess(rowKey);
      setUnresolvedCreateOpen(null);
      fetch('/api/ingest/mappings/unresolved', { headers:{ Authorization:'Bearer '+tok }})
        .then(r=>r.json()).then(d=>{ if(Array.isArray(d)) setUnresolvedList(d); }).catch(()=>{});
      api("GET","/monitors").then(r=>{ if(Array.isArray(r)) setMonitorsForMapping(r); }).catch(()=>{});
    } catch(e) { alert('Failed: ' + e.message); }
    finally { setUnresolvedCreateSaving(false); }
  };

  const loadRawPayload = async (targetId) => {
    try {
      const r = await api("GET", `/ingest/feeds/targets/${targetId}/raw`);
      setRawPayload(r);
    } catch(e) {
      setRawPayload({ Payload: null, Error: e.message });
    } finally {
      setRawPayloadLoading(false);
    }
  };

  const toggleFeed = async (feedId, currentIsActive) => {
    setFeedsList(prev => prev.map(f => f.FeedID === feedId ? {...f, IsActive: !currentIsActive} : f));
    try { await api("PATCH", `/ingest/feeds/${feedId}/toggle`, {}); }
    catch(_) { setFeedsList(prev => prev.map(f => f.FeedID === feedId ? {...f, IsActive: currentIsActive} : f)); }
  };

  const handleAskFeed = async (feedId, text) => {
    if (!text || !text.trim()) return;
    const prevThread = feedAiThreads[feedId] || [];
    const userMsg = { role: 'user', content: text.trim() };
    const newThread = [...prevThread, userMsg];
    setFeedAiThreads(prev => ({ ...prev, [feedId]: newThread }));
    setFeedAiInput(prev => ({ ...prev, [feedId]: '' }));
    setFeedAiLoading(prev => ({ ...prev, [feedId]: true }));
    try {
      const r = await api("POST", "/ingest/feeds/"+feedId+"/ai-chat", {
        messages: newThread.map(m => ({ role: m.role, content: m.content }))
      });
      const reply = (r && r.reply) ? r.reply : 'No response received.';
      setFeedAiThreads(prev => ({ ...prev, [feedId]: [...(prev[feedId]||[]), { role: 'assistant', content: reply }] }));
    } catch(e) {
      setFeedAiThreads(prev => ({ ...prev, [feedId]: [...(prev[feedId]||[]), { role: 'assistant', content: 'AI assistant is unavailable. Please try again.' }] }));
    } finally {
      setFeedAiLoading(prev => ({ ...prev, [feedId]: false }));
    }
  };

  // ── Metric Mappings panel ──
  const mpc = { influxdb:'#006D8C', prometheus:'#E6522C', statsd:'#6366f1', graphite:'#374151', webhook:'#008C6F', spreadsheet:'#B45309' };
  const mpl = { influxdb:'InfluxDB LP', prometheus:'Prometheus', statsd:'StatsD', graphite:'Graphite', webhook:'Webhook', spreadsheet:'Spreadsheet' };
  const mpGrouped = {};
  mappingsList.forEach(m => { if (!mpGrouped[m.SourceProtocol]) mpGrouped[m.SourceProtocol]=[]; mpGrouped[m.SourceProtocol].push(m); });
  const mpSeen = new Set();
  const mpDedup = [];
  unresolvedList.forEach(r => { const k=(r.MetricName||'')+'|'+(r.SourceProtocol||''); if (!mpSeen.has(k)){ mpSeen.add(k); mpDedup.push(r); }});
  const mpShown = mpDedup.slice(0, 20);
  const fmtMpDate = d => { if(!d) return 'Never'; const dt=new Date(d); return dt.toLocaleDateString('en-US',{month:'short',day:'numeric',year:'numeric'})+' '+dt.toLocaleTimeString('en-US',{hour:'numeric',minute:'2-digit'}); };
  const mappingsPanel = (
    <div style={{display:"flex",flexDirection:"column",gap:16,maxWidth:860}}>
      <div style={{background:"#fff",border:"0.5px solid #e2e5ea",borderRadius:8,padding:16}}>
        <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:14}}>
          <div style={{fontSize:13,fontWeight:700,color:"#1e293b"}}>Metric Mappings</div>
          <button onClick={()=>{ setMappingAddOpen(true); if(monitorsForMapping.length===0) api("GET","/monitors").then(r=>{if(Array.isArray(r))setMonitorsForMapping(r);}).catch(()=>{}); }}
            style={{padding:"6px 14px",background:"#006D8C",color:"#fff",border:"none",borderRadius:6,fontSize:12,fontWeight:600,cursor:"pointer"}}>
            + Add Mapping
          </button>
        </div>
        {mappingAddOpen && (
          <div style={{background:"#f8fafc",border:"0.5px solid #e2e5ea",borderRadius:8,padding:14,marginBottom:14}}>
            <div style={{fontSize:11,fontWeight:700,color:"#94a3b8",textTransform:"uppercase",letterSpacing:"0.06em",marginBottom:12}}>New Mapping</div>
            <div style={{display:"flex",gap:10,flexWrap:"wrap",marginBottom:10}}>
              <div style={{display:"flex",flexDirection:"column",gap:4}}>
                <div style={{fontSize:11,fontWeight:600,color:"#4A4A4A"}}>Protocol</div>
                <select value={mappingForm.protocol} onChange={e=>setMappingForm(p=>({...p,protocol:e.target.value}))}
                  style={{padding:"6px 10px",border:"0.5px solid #cbd5e1",borderRadius:6,fontSize:12,minWidth:140}}>
                  <option value="">Select…</option>
                  {['prometheus','statsd','graphite','influxdb','webhook','spreadsheet'].map(p=>(
                    <option key={p} value={p}>{mpl[p]||p}</option>
                  ))}
                </select>
              </div>
              <div style={{display:"flex",flexDirection:"column",gap:4,flex:1,minWidth:200}}>
                <div style={{fontSize:11,fontWeight:600,color:"#4A4A4A"}}>Pattern</div>
                <input value={mappingForm.pattern} onChange={e=>setMappingForm(p=>({...p,pattern:e.target.value}))}
                  placeholder="e.g. cpu.%.usage"
                  style={{padding:"6px 10px",border:"0.5px solid #cbd5e1",borderRadius:6,fontSize:12,fontFamily:"monospace"}} />
                <div style={{fontSize:10,color:"#94a3b8"}}>Use % as wildcard. More specific patterns take priority.</div>
              </div>
              <div style={{display:"flex",flexDirection:"column",gap:4,minWidth:200}}>
                <div style={{fontSize:11,fontWeight:600,color:"#4A4A4A"}}>Monitor</div>
                <select value={mappingForm.monitorId} onChange={e=>setMappingForm(p=>({...p,monitorId:e.target.value}))}
                  style={{padding:"6px 10px",border:"0.5px solid #cbd5e1",borderRadius:6,fontSize:12,minWidth:200}}>
                  <option value="">Select monitor…</option>
                  {monitorsForMapping.map(m=>(
                    <option key={m.MonitorID} value={m.MonitorID}>{m.MonitorName}</option>
                  ))}
                </select>
              </div>
            </div>
            <div style={{display:"flex",gap:8}}>
              <button onClick={handleMappingAdd} disabled={!mappingForm.protocol||!mappingForm.pattern||!mappingForm.monitorId||mappingAddSaving}
                style={{padding:"6px 16px",background:(!mappingForm.protocol||!mappingForm.pattern||!mappingForm.monitorId||mappingAddSaving)?"#94a3b8":"#006D8C",color:"#fff",border:"none",borderRadius:6,fontSize:12,fontWeight:600,cursor:(!mappingForm.protocol||!mappingForm.pattern||!mappingForm.monitorId||mappingAddSaving)?"not-allowed":"pointer"}}>
                {mappingAddSaving?"Saving…":"Save Mapping"}
              </button>
              <button onClick={()=>{ setMappingAddOpen(false); setMappingForm({protocol:'',pattern:'',monitorId:''}); }}
                style={{padding:"6px 14px",background:"transparent",color:"#64748b",border:"0.5px solid #e2e5ea",borderRadius:6,fontSize:12,cursor:"pointer"}}>
                Cancel
              </button>
            </div>
          </div>
        )}
        {mappingsLoading ? (
          <div style={{fontSize:12,color:"#94a3b8",padding:"12px 0"}}>Loading…</div>
        ) : mappingsList.length===0 ? (
          <div style={{fontSize:12,color:"#94a3b8",padding:"12px 0"}}>No mappings configured. Use the Ingest Feeds wizard or add one manually.</div>
        ) : (
          <table style={{width:"100%",borderCollapse:"collapse",fontSize:12}}>
            <thead>
              <tr style={{background:"#f8fafc"}}>
                {['PATTERN','PROTOCOL','MONITOR','LAST MATCHED','ACTIONS'].map(h=>(
                  <th key={h} style={{padding:"6px 10px",textAlign:"left",fontSize:10,fontWeight:700,color:"#94a3b8",letterSpacing:"0.06em",borderBottom:"0.5px solid #e2e5ea"}}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {Object.entries(mpGrouped).map(([proto,rows])=>[
                <tr key={'hdr-'+proto} style={{background:"#f1f5f9"}}>
                  <td colSpan={5} style={{padding:"4px 10px",fontSize:11,fontWeight:700,color:"#64748b"}}>
                    <span style={{color:mpc[proto]||'#64748b'}}>{mpl[proto]||proto}</span>
                    <span style={{color:"#94a3b8",fontWeight:400,marginLeft:8}}>{rows.length} mapping{rows.length!==1?'s':''}</span>
                  </td>
                </tr>,
                ...rows.map(row=>(
                  <tr key={row.MappingID} style={{borderBottom:"0.5px solid #f1f5f9"}}>
                    <td style={{padding:"7px 10px",fontFamily:"monospace",color:"#1e293b"}}>{row.MetricNamePattern}</td>
                    <td style={{padding:"7px 10px"}}>
                      <span style={{background:(mpc[row.SourceProtocol]||'#64748b')+'1a',color:mpc[row.SourceProtocol]||'#64748b',fontSize:10,fontWeight:700,padding:"2px 7px",borderRadius:4}}>
                        {mpl[row.SourceProtocol]||row.SourceProtocol}
                      </span>
                    </td>
                    <td style={{padding:"7px 10px",color:"#374151"}}>{row.MonitorName||'—'}</td>
                    <td style={{padding:"7px 10px",color:"#94a3b8"}}>{fmtMpDate(row.LastMatchedAt)}</td>
                    <td style={{padding:"7px 10px"}}>
                      <button onClick={()=>handleMappingDelete(row.MappingID)} disabled={mappingDeleteId===row.MappingID}
                        style={{padding:"3px 10px",background:"transparent",color:mappingDeleteId===row.MappingID?"#94a3b8":"#D95C5C",border:`1px solid ${mappingDeleteId===row.MappingID?"#e2e5ea":"#D95C5C"}`,borderRadius:5,fontSize:11,cursor:mappingDeleteId===row.MappingID?"not-allowed":"pointer"}}>
                        {mappingDeleteId===row.MappingID?"Deleting…":"Delete"}
                      </button>
                    </td>
                  </tr>
                ))
              ])}
            </tbody>
          </table>
        )}
      </div>
      <div style={{background:"#fff",border:"0.5px solid #e2e5ea",borderRadius:8,padding:16}}>
        <div style={{marginBottom:12}}>
          <div style={{display:"flex",alignItems:"center",gap:6,marginBottom:4}}>
            <span style={{color:"#E89A2E",fontSize:14}}>⚠</span>
            <span style={{fontSize:13,fontWeight:700,color:"#1e293b"}}>Unresolved Metrics</span>
          </div>
          <div style={{fontSize:11,color:"#64748b"}}>These metrics arrived but could not be matched to a monitor. Add a mapping to resolve them.</div>
        </div>
        {unresolvedLoading ? (
          <div style={{fontSize:12,color:"#94a3b8"}}>Loading…</div>
        ) : mpShown.length===0 ? (
          <div style={{display:"inline-flex",alignItems:"center",gap:6,background:"#f0fdf4",border:"1px solid #bbf7d0",borderRadius:20,padding:"6px 14px",fontSize:12,color:"#166534",fontWeight:600}}>
            <span>✓</span> No unresolved metrics — all inbound data is mapped.
          </div>
        ) : (
          <React.Fragment>
            <table style={{width:"100%",borderCollapse:"collapse",fontSize:12}}>
              <thead>
                <tr style={{background:"#f8fafc"}}>
                  {['METRIC NAME','PROTOCOL','LAST SEEN','VALUE',''].map((h,i)=>(
                    <th key={i} style={{padding:"6px 10px",textAlign:"left",fontSize:10,fontWeight:700,color:"#94a3b8",letterSpacing:"0.06em",borderBottom:"0.5px solid #e2e5ea"}}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {mpShown.map((row,i)=>{
                  const rowKey = (row.MetricName||'')+'|'+(row.SourceProtocol||'');
                  const isCreateOpen = unresolvedCreateOpen === rowKey;
                  const isSuccess = unresolvedCreateSuccess === rowKey;
                  const defaultName = (row.MetricName||'').replace(/[._-]/g,' ').replace(/\b\w/g,c=>c.toUpperCase());
                  return (
                    <React.Fragment key={i}>
                      <tr style={{borderBottom:isCreateOpen?'none':'0.5px solid #f1f5f9'}}>
                        <td style={{padding:"7px 10px",fontFamily:"monospace",color:"#1e293b"}}>{row.MetricName}</td>
                        <td style={{padding:"7px 10px"}}>
                          <span style={{background:(mpc[row.SourceProtocol]||'#64748b')+'1a',color:mpc[row.SourceProtocol]||'#64748b',fontSize:10,fontWeight:700,padding:"2px 7px",borderRadius:4}}>
                            {mpl[row.SourceProtocol]||row.SourceProtocol||'Unknown'}
                          </span>
                        </td>
                        <td style={{padding:"7px 10px",color:"#94a3b8"}}>{fmtMpDate(row.MetricTimestamp)}</td>
                        <td style={{padding:"7px 10px",color:"#374151"}}>{row.Value!=null?row.Value:'—'}</td>
                        <td style={{padding:"7px 10px"}}>
                          {isSuccess ? (
                            <span style={{fontSize:11,color:'#008C6F',fontWeight:600}}>✓ Created</span>
                          ) : (
                            <div style={{display:'flex',flexDirection:'column',gap:3}}>
                              <button onClick={()=>handleUnresolvedQuickAdd(row)}
                                style={{padding:"3px 10px",background:"transparent",color:"#006D8C",border:"1px solid #006D8C",borderRadius:5,fontSize:11,cursor:"pointer",whiteSpace:"nowrap"}}>
                                Map to existing
                              </button>
                              <button onClick={()=>{ if(isCreateOpen){setUnresolvedCreateOpen(null);}else{setUnresolvedCreateOpen(rowKey);setUnresolvedCreateForm({name:defaultName,subtype:'app-http',groupId:''});if(exportGroups.length===0)api("GET","/monitors/groups").then(r=>{if(Array.isArray(r))setExportGroups(r);}).catch(()=>{});} }}
                                style={{padding:"3px 10px",background:isCreateOpen?"#008C6F":"transparent",color:isCreateOpen?"#fff":"#008C6F",border:"1px solid #008C6F",borderRadius:5,fontSize:11,cursor:"pointer",whiteSpace:"nowrap"}}>
                                Create new monitor
                              </button>
                            </div>
                          )}
                        </td>
                      </tr>
                      {isCreateOpen && (
                        <tr>
                          <td colSpan={5} style={{padding:'10px 12px',background:'#f0fdf4',borderBottom:'0.5px solid #f1f5f9',borderLeft:'2px solid #008C6F'}}>
                            <div style={{fontSize:11,fontWeight:700,color:'#166534',marginBottom:8}}>Create monitor for <span style={{fontFamily:'monospace'}}>{row.MetricName}</span></div>
                            <div style={{display:'flex',gap:10,flexWrap:'wrap',alignItems:'flex-end'}}>
                              <div style={{display:'flex',flexDirection:'column',gap:3,flex:'2 1 180px'}}>
                                <div style={{fontSize:10,fontWeight:600,color:'#4A4A4A'}}>Monitor name</div>
                                <input value={unresolvedCreateForm.name} onChange={e=>setUnresolvedCreateForm(f=>({...f,name:e.target.value}))}
                                  style={{padding:'5px 8px',border:'0.5px solid #cbd5e1',borderRadius:5,fontSize:12}} />
                              </div>
                              <div style={{display:'flex',flexDirection:'column',gap:3,flex:'1 1 140px'}}>
                                <div style={{fontSize:10,fontWeight:600,color:'#4A4A4A'}}>Type</div>
                                <select value={unresolvedCreateForm.subtype} onChange={e=>setUnresolvedCreateForm(f=>({...f,subtype:e.target.value}))}
                                  style={{padding:'5px 8px',border:'0.5px solid #cbd5e1',borderRadius:5,fontSize:12}}>
                                  {[['infra-cpu','CPU'],['infra-mem','Memory'],['infra-disk','Disk'],['infra-net','Network'],['infra-diskio','Disk I/O'],['app-http','HTTP App'],['app-port','Port'],['web-http','Web HTTP']].map(([v,l])=>(
                                    <option key={v} value={v}>{l}</option>
                                  ))}
                                </select>
                              </div>
                              <div style={{display:'flex',flexDirection:'column',gap:3,flex:'1 1 140px'}}>
                                <div style={{fontSize:10,fontWeight:600,color:'#4A4A4A'}}>Group</div>
                                <select value={unresolvedCreateForm.groupId} onChange={e=>setUnresolvedCreateForm(f=>({...f,groupId:e.target.value}))}
                                  style={{padding:'5px 8px',border:'0.5px solid #cbd5e1',borderRadius:5,fontSize:12}}>
                                  <option value="">No group</option>
                                  {exportGroups.map(g=>(<option key={g.GroupID} value={g.GroupID}>{g.GroupName}</option>))}
                                </select>
                              </div>
                              <button onClick={()=>handleUnresolvedCreateMonitor(row)} disabled={!unresolvedCreateForm.name.trim()||unresolvedCreateSaving}
                                style={{padding:'5px 14px',background:(!unresolvedCreateForm.name.trim()||unresolvedCreateSaving)?'#94a3b8':'#008C6F',color:'#fff',border:'none',borderRadius:5,fontSize:12,fontWeight:600,cursor:(!unresolvedCreateForm.name.trim()||unresolvedCreateSaving)?'not-allowed':'pointer',flexShrink:0}}>
                                {unresolvedCreateSaving?'Saving…':'Create & map'}
                              </button>
                              <button onClick={()=>setUnresolvedCreateOpen(null)}
                                style={{padding:'5px 10px',background:'transparent',color:'#64748b',border:'0.5px solid #e2e5ea',borderRadius:5,fontSize:12,cursor:'pointer',flexShrink:0}}>
                                Cancel
                              </button>
                            </div>
                          </td>
                        </tr>
                      )}
                    </React.Fragment>
                  );
                })}
              </tbody>
            </table>
            {mpDedup.length>20 && (
              <div style={{fontSize:10,color:"#94a3b8",marginTop:8}}>Showing top 20 most recent</div>
            )}
          </React.Fragment>
        )}
      </div>
    </div>
  );

  const { isPaused: monIsPaused, canManageConfig, pausePopover, setPausePopover, pauseReason, setPauseReason, pauseBusy, togglePause, currentCtrl } = monitoringControl || {};

  const CONFIG_TABS = [
    { key:"notifications", label:"Notifications" },
    { key:"credentials",   label:"Credentials" },
    { key:"retention",     label:"Retention" },
    { key:"monitor-defaults", label:"Monitor Defaults" },
    { key:"machines",      label:"Source Monitors" },
    { key:"ai-diagnosis",  label:"AI Diagnosis" },
    { key:"configpack",    label:"Import / Export" },
    ...(canManageConfig ? [{ key:"systemhealth", label:"System Health" }] : []),
  ];

  const notifChannels = [...new Set(notifCfg.map(n=>n.ConfigType).filter(Boolean))].length;

  return (
    <div style={{ display:"flex", flexDirection:"column", height:"calc(100vh - 20px)", overflow:"hidden", background:"#ffffff" }}>

      {/* ── Branding header ── */}
      <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", background:"#ffffff", borderBottom:"0.5px solid #f1f5f9", padding:"10px 16px", flexShrink:0 }}>
        <div style={{ display:"flex", alignItems:"center", gap:12 }}>
          <div style={{ width:36, height:36, borderRadius:8, background:"#006D8C", display:"flex", alignItems:"center", justifyContent:"center", fontSize:13, fontWeight:700, color:"#ffffff", letterSpacing:"0.02em", flexShrink:0 }}>OP1</div>
          <div>
            <div style={{ fontSize:16, fontWeight:600, color:"#1e293b" }}><span style={{ color:"#006D8C" }}>OP1</span> Operations Portal</div>
            <div style={{ fontSize:10, color:"#94a3b8" }}>Enterprise Monitoring · v1.4.457</div>
          </div>
        </div>
        <div style={{ display:"flex", alignItems:"center", gap:0 }}>
          {[
            ["Notif Configs",  String(notifCfg.length),  "#1e293b"],
            ["Ret Policies",   String(retPolicies.length), "#1e293b"],
            ["Channels",       String(notifChannels),     "#1e293b"],
          ].flatMap(([lbl, val, col], i, arr) => [
            <div key={lbl} style={{ padding:"0 16px", textAlign:"center" }}>
              <div style={{ fontSize:13, fontWeight:600, color:col }}>{val}</div>
              <div style={{ fontSize:9, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.06em" }}>{lbl}</div>
            </div>,
            i < arr.length-1 && <div key={`div-${i}`} style={{ width:"0.5px", height:28, background:"#e2e5ea", flexShrink:0 }} />,
          ].filter(Boolean))}
        </div>
      </div>

      {/* ── Tab bar ── */}
      <div style={{ display:"flex", gap:0, borderBottom:"0.5px solid #e2e5ea", background:"#ffffff", flexShrink:0 }}>
        {CONFIG_TABS.map(t => (
          <button key={t.key} onClick={()=>setConfigTab(t.key)}
            style={{ background:"transparent", border:"none", borderBottom: configTab===t.key ? "2px solid #006D8C" : "2px solid transparent", color: configTab===t.key ? "#006D8C" : "#64748b", padding:"10px 18px", fontSize:12, fontWeight: configTab===t.key ? 600 : 400, cursor:"pointer", whiteSpace:"nowrap" }}>
            {t.label}
          </button>
        ))}
      </div>

      {/* ── Scrollable content ── */}
      <div style={{ flex:1, overflowY:"auto", padding:"16px" }}>
        <ErrBox msg={err} /><OkBox msg={ok} />
        {configTab==="notifications" && (()=>{
          const notifEnabled = notifSettings['Notifications_Enabled'] === 'true';
          const tog = (on, fn) => (
            <div onClick={fn} style={{ width:36, height:20, borderRadius:10, background:on?c.blue:"#e2e5ea", position:"relative", cursor:"pointer", transition:"background 0.2s", flexShrink:0 }}>
              <div style={{ position:"absolute", top:3, left:on?17:3, width:14, height:14, borderRadius:"50%", background:"#fff", transition:"left 0.2s" }} />
            </div>
          );
          const chIcon = (t) => t==='email' ? {icon:"@",bg:c.blueLight,fg:c.blue} : t==='webhook' ? {icon:"⇒",bg:c.yellowLight,fg:c.yellow} : {icon:"?",bg:"#f1f5f9",fg:c.textMuted};
          const chSummary = (ch) => { try { const cfg=JSON.parse(ch.ConfigJson||'{}'); if(ch.ChannelType==='email') return cfg.SmtpHost?`${cfg.SmtpHost}:${cfg.SmtpPort||587}`:'—'; if(ch.ChannelType==='webhook') return cfg.Url?(cfg.Url.length>42?cfg.Url.slice(0,40)+'…':cfg.Url):'—'; } catch{} return '—'; };
          const fmtTested = (dt) => { if(!dt) return '—'; const d=parseUTC(dt); if(!d) return '—'; const now=new Date(); const today=d.getDate()===now.getDate()&&d.getMonth()===now.getMonth()&&d.getFullYear()===now.getFullYear(); return today?'Today '+d.toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'}):d.toLocaleDateString([],{day:'2-digit',month:'short'})+' '+d.toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'}); };
          const chStatus = (ch) => ch.LastTestSuccess===true ? <span style={{fontSize:11,color:c.green,fontWeight:600}}>● Connected</span> : ch.LastTestSuccess===false ? <span style={{fontSize:11,color:c.red,fontWeight:600}}>● Failed</span> : <span style={{fontSize:11,color:c.textMuted}}>● Not tested</span>;
          const inpS = { width:"100%", padding:"7px 10px", border:`1px solid ${c.border}`, borderRadius:6, fontSize:13, background:"#fff", color:c.text, outline:"none", boxSizing:"border-box" };
          const lblS = { fontSize:10, fontWeight:700, color:c.textMuted, textTransform:"uppercase", letterSpacing:"0.05em", marginBottom:4, display:"block" };
          const cardStyle = { background:"#fff", border:`1px solid ${c.border}`, borderRadius:8, overflow:"hidden" };
          const tblHdr = ["Channel","Type","Status","Last tested",""].map(h=><th key={h} style={{padding:"8px 12px",textAlign:"left",fontSize:9,fontWeight:700,color:c.textMuted,textTransform:"uppercase",letterSpacing:"0.05em"}}>{h}</th>);

          const notifGlobalBanner = (
            <div style={{ background:notifEnabled?c.greenLight:c.redLight, border:`1px solid ${notifEnabled?c.green:c.red}`, borderRadius:8, padding:"14px 16px", display:"flex", alignItems:"center", justifyContent:"space-between" }}>
              <div>
                <div style={{ fontSize:13, fontWeight:600, color:notifEnabled?c.green:c.red }}>{notifEnabled?"Notifications enabled globally":"Notifications disabled globally"}</div>
                <div style={{ fontSize:11, color:c.textMuted, marginTop:3 }}>{notifEnabled?"All channels and recipients are active. Disable to suppress all alert delivery system-wide.":"No notifications will be sent regardless of channel or recipient configuration."}</div>
              </div>
              {tog(notifEnabled,()=>saveNotifSetting('Notifications_Enabled',notifEnabled?'false':'true'))}
            </div>
          );

          const notifChannelsCard = (
            <div style={cardStyle}>
              <div style={{ padding:"12px 16px", borderBottom:`1px solid ${c.border}`, display:"flex", alignItems:"center", justifyContent:"space-between" }}>
                <div>
                  <div style={{ fontSize:13, fontWeight:600, color:c.text }}>Delivery channels</div>
                  <div style={{ fontSize:11, color:c.textMuted, marginTop:2 }}>Configure how OP1 sends notifications</div>
                </div>
                <Btn variant="primary" onClick={()=>{ setNotifChannelDraft({ChannelType:'email',DisplayName:'',IsEnabled:true,_cfg:{SmtpHost:'',SmtpPort:587,SmtpUsername:'',SmtpPassword:'',FromAddress:'',FromName:'OP1 Operations Portal',EnableSsl:true}}); setNotifChannelModal('add'); }}>+ Add channel</Btn>
              </div>
              {notifChs.length===0 ? (
                <div style={{ padding:"32px 16px", textAlign:"center", color:c.textMuted, fontSize:12 }}>No channels configured. Add an email or webhook channel to start sending notifications.</div>
              ) : (
                <table style={{ width:"100%", borderCollapse:"collapse", fontSize:12 }}>
                  <thead><tr style={{ borderBottom:`1px solid ${c.border}`, background:"#f8fafc" }}>{tblHdr}</tr></thead>
                  <tbody>
                    {notifChs.map(ch=>{
                      const {icon,bg,fg}=chIcon(ch.ChannelType);
                      const ts=notifTestState[ch.ChannelID];
                      const testDiag=notifTestDiag[ch.ChannelID];
                      const tdSucc=testDiag?.Code?.startsWith("ok");
                      return (
                        <tr key={ch.ChannelID} style={{ borderBottom:"0.5px solid #f1f5f9" }}>
                          <td style={{ padding:"10px 12px" }}>
                            <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                              <div style={{ width:32,height:32,borderRadius:6,background:bg,color:fg,display:"flex",alignItems:"center",justifyContent:"center",fontSize:14,fontWeight:700,flexShrink:0 }}>{icon}</div>
                              <div>
                                <div style={{ fontWeight:600, fontSize:13, color:c.text }}>{ch.DisplayName}</div>
                                <div style={{ fontSize:11, color:c.textMuted, fontFamily:"monospace" }}>{chSummary(ch)}</div>
                              </div>
                            </div>
                          </td>
                          <td style={{ padding:"10px 12px" }}><span style={{ fontSize:10,borderRadius:4,padding:"2px 7px",background:bg,color:fg,fontWeight:600,textTransform:"uppercase" }}>{ch.ChannelType}</span></td>
                          <td style={{ padding:"10px 12px" }}>{chStatus(ch)}</td>
                          <td style={{ padding:"10px 12px", color:c.textMuted, fontSize:11 }}>{fmtTested(ch.LastTestedAt)}</td>
                          <td style={{ padding:"10px 12px" }}>
                            <div style={{ display:"flex", gap:6, justifyContent:"flex-end" }}>
                              <div style={{ display:"flex", flexDirection:"column", alignItems:"flex-end" }}>
                                <Btn variant="secondary" style={{ fontSize:11,padding:"4px 10px" }} disabled={ts==='sending'}
                                  onClick={async()=>{ setNotifTestState(p=>({...p,[ch.ChannelID]:'sending'})); setNotifTestDiag(p=>{ const n={...p}; delete n[ch.ChannelID]; return n; }); try { const r=await api("POST",`/notifications/channels/${ch.ChannelID}/test`,{}); if(r?.ok){ setNotifTestState(p=>({...p,[ch.ChannelID]:'idle'})); setNotifTestDiag(p=>({...p,[ch.ChannelID]:r?.diagnosis})); loadNotificationsTab(); } else { setNotifTestState(p=>({...p,[ch.ChannelID]:'idle'})); setNotifTestDiag(p=>({...p,[ch.ChannelID]:r?.diagnosis})); } } catch(e){ setNotifTestState(p=>({...p,[ch.ChannelID]:'idle'})); setNotifTestDiag(p=>({...p,[ch.ChannelID]:{Code:'smtp.unknown',Headline:e?.message||'Test failed',Severity:'unknown'}})); } }}>
                                  {ts==='sending'?<><span style={{ display:"inline-block",width:10,height:10,border:"2px solid #cbd5e1",borderTopColor:"#475569",borderRadius:"50%",animation:"spin 0.7s linear infinite",marginRight:6 }} />Testing…</>:'Test'}
                                </Btn>
                                {testDiag && (
                                  <div style={{ position:"relative", marginTop:6, padding:"8px 10px", background:tdSucc?"#F0FDF4":"#FEF2F2", border:`1px solid ${tdSucc?"#BBF7D0":"#FECACA"}`, borderRadius:4, fontSize:11 }}>
                                    <button onClick={()=>{ setNotifTestDiag(p=>{ const n={...p}; delete n[ch.ChannelID]; return n; }); setNotifTestState(p=>({...p,[ch.ChannelID]:'idle'})); }} style={{ position:"absolute",top:6,right:8,background:"none",border:"none",color:"#9CA3AF",fontSize:14,cursor:"pointer",padding:0,lineHeight:1 }} title="Dismiss">&times;</button>
                                    <div style={{ fontWeight:600, color:tdSucc?"#166534":"#991B1B" }}>{tdSucc?"✓ ":""}{testDiag.Headline}</div>
                                    {testDiag.Detail && <div style={{ color:tdSucc?"#15803D":"#7F1D1D", marginTop:3 }}>{testDiag.Detail}</div>}
                                    {testDiag.Suggestion && <div style={{ color:"#525B6B", marginTop:4, fontStyle:"italic" }}>&#128161; {testDiag.Suggestion}</div>}
                                    {testDiag.RawError && (
                                      <details style={{ marginTop:6 }}>
                                        <summary style={{ cursor:"pointer", color:"#64748B", fontSize:10 }}>Show technical details</summary>
                                        <pre style={{ fontSize:10, fontFamily:"monospace", background:"#FFFFFF", padding:6, borderRadius:3, marginTop:4, whiteSpace:"pre-wrap", wordBreak:"break-all", color:"#374151" }}>{testDiag.RawError}</pre>
                                      </details>
                                    )}
                                  </div>
                                )}
                              </div>
                              <Btn variant="secondary" style={{ fontSize:11,padding:"4px 10px" }}
                                onClick={()=>{ try { const cfg=JSON.parse(ch.ConfigJson||'{}'); setNotifChannelDraft({ChannelID:ch.ChannelID,DisplayName:ch.DisplayName,ChannelType:ch.ChannelType,IsEnabled:ch.IsEnabled,_cfg:{SmtpHost:cfg.SmtpHost||'',SmtpPort:cfg.SmtpPort||587,SmtpUsername:cfg.SmtpUsername||'',SmtpPassword:cfg.SmtpPassword||'',FromAddress:cfg.FromAddress||'',FromName:cfg.FromName||'OP1 Operations Portal',EnableSsl:cfg.EnableSsl!==false,Url:cfg.Url||'',Secret:cfg.Secret||''}}); } catch { setNotifChannelDraft({ChannelID:ch.ChannelID,DisplayName:ch.DisplayName,ChannelType:ch.ChannelType,IsEnabled:ch.IsEnabled,_cfg:{}}); } setNotifChannelModal(ch); }}>Edit</Btn>
                              <Btn variant="danger" style={{ fontSize:11,padding:"4px 10px" }}
                                onClick={()=>{ showConfirm('Delete this channel? This will also remove all recipients assigned to it.', async () => { try { await api("DELETE",`/notifications/channels/${ch.ChannelID}`); loadNotificationsTab(); } catch(e) { setErr(e.message); } }); }}>Delete</Btn>
                            </div>
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              )}
            </div>
          );

          const recipInits = (name) => { const p=(name||'').trim().split(/\s+/); return p.length>=2?(p[0][0]+p[p.length-1][0]).toUpperCase():(name||'?')[0].toUpperCase(); };
          const notifRecipientsCard = (
            <div style={cardStyle}>
              <div style={{ padding:"12px 16px", borderBottom:`1px solid ${c.border}`, display:"flex", alignItems:"center", justifyContent:"space-between" }}>
                <div>
                  <div style={{ fontSize:13, fontWeight:600, color:c.text }}>Recipients</div>
                  <div style={{ fontSize:11, color:c.textMuted, marginTop:2 }}>Global list — assign to monitors or groups from the monitor form</div>
                </div>
                <Btn variant="primary" onClick={()=>{ setNotifRecipientDraft({DisplayName:'',ChannelID:notifChs[0]?.ChannelID||'',Destination:'',IsActive:true}); setNotifRecipientModal('add'); }}>+ Add recipient</Btn>
              </div>
              {notifRecs.length===0 ? (
                <div style={{ padding:"32px 16px", textAlign:"center", color:c.textMuted, fontSize:12 }}>No recipients configured. Add a recipient to begin assigning notifications.</div>
              ) : (
                <table style={{ width:"100%", borderCollapse:"collapse", fontSize:12 }}>
                  <thead><tr style={{ borderBottom:`1px solid ${c.border}`, background:"#f8fafc" }}>
                    {["Name","Channel","Destination","Assigned to","Active",""].map(h=><th key={h} style={{padding:"8px 12px",textAlign:"left",fontSize:9,fontWeight:700,color:c.textMuted,textTransform:"uppercase",letterSpacing:"0.05em"}}>{h}</th>)}
                  </tr></thead>
                  <tbody>
                    {notifRecs.map(r=>{
                      const {bg:rb,fg:rf}=chIcon(r.ChannelType);
                      return (
                        <tr key={r.RecipientID} style={{ borderBottom:"0.5px solid #f1f5f9" }}>
                          <td style={{ padding:"10px 12px" }}>
                            <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                              <div style={{ width:28,height:28,borderRadius:"50%",background:c.blueLight,color:c.blue,display:"flex",alignItems:"center",justifyContent:"center",fontSize:11,fontWeight:700,flexShrink:0 }}>{recipInits(r.DisplayName)}</div>
                              <span style={{ fontWeight:600, color:c.text }}>{r.DisplayName}</span>
                            </div>
                          </td>
                          <td style={{ padding:"10px 12px" }}><span style={{ fontSize:10,borderRadius:4,padding:"2px 7px",background:rb,color:rf,fontWeight:600,textTransform:"uppercase" }}>{r.ChannelType}</span></td>
                          <td style={{ padding:"10px 12px", fontFamily:"monospace", fontSize:11, color:c.textMuted }}>{r.Destination}</td>
                          <td style={{ padding:"10px 12px" }}>{r.AssignedCount>0?<span style={{fontSize:11,color:c.textMuted}}>{r.AssignedCount} monitor{r.AssignedCount!==1?'s':''}</span>:<span style={{fontSize:11,color:c.textMuted}}>Unassigned</span>}</td>
                          <td style={{ padding:"10px 12px" }}>
                            {tog(r.IsActive,async()=>{ await api("PUT",`/notifications/recipients/${r.RecipientID}`,{DisplayName:r.DisplayName,ChannelID:r.ChannelID,Destination:r.Destination,IsActive:!r.IsActive}); loadNotificationsTab(); })}
                          </td>
                          <td style={{ padding:"10px 12px" }}>
                            <div style={{ display:"flex", gap:6, justifyContent:"flex-end" }}>
                              <Btn variant="secondary" style={{ fontSize:11,padding:"4px 10px" }} onClick={()=>{ setNotifRecipientDraft({DisplayName:r.DisplayName,ChannelID:r.ChannelID,Destination:r.Destination,IsActive:r.IsActive}); setNotifRecipientModal(r); }}>Edit</Btn>
                              <Btn variant="danger" style={{ fontSize:11,padding:"4px 10px" }}
                                onClick={()=>{ showConfirm(r.AssignedCount>0?`This recipient is assigned to ${r.AssignedCount} monitor${r.AssignedCount!==1?'s':''}. Remove anyway?`:'Remove this recipient?', async () => { try { await api("DELETE",`/notifications/recipients/${r.RecipientID}`); loadNotificationsTab(); } catch(e) { setErr(e.message); } }); }}>Remove</Btn>
                            </div>
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              )}
            </div>
          );

          const notifRulesCard = (
            <div style={{ background:"#fff", border:`1px solid ${c.border}`, borderRadius:8, padding:16 }}>
              <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom:16 }}>
                <div>
                  <div style={{ fontSize:13, fontWeight:600, color:c.text }}>Delivery rules — global defaults</div>
                  <div style={{ fontSize:11, color:c.textMuted, marginTop:2 }}>Overridable per monitor assignment</div>
                </div>
                <Btn variant="primary" style={{ fontSize:11,padding:"6px 14px" }} loading={notifSaving}
                  onClick={async()=>{ setNotifSaving(true); try { for(const [k,v] of Object.entries(notifRulesDraft)) await api("POST","/notifications/settings",{key:k,value:String(v)}); setNotifSettings({...notifRulesDraft}); } catch{} setNotifSaving(false); }}>
                  Save rules
                </Btn>
              </div>
              <div style={{ display:"flex", gap:16, flexWrap:"wrap", marginBottom:16 }}>
                <div style={{ flex:"1 1 200px" }}>
                  <label style={lblS}>Minimum severity to notify</label>
                  <select value={notifRulesDraft['Notifications_MinSeverity']||'warning'} onChange={e=>setNotifRulesDraft(p=>({...p,'Notifications_MinSeverity':e.target.value}))} style={inpS}>
                    <option value="warning">Warning and above</option>
                    <option value="critical">Critical only</option>
                  </select>
                </div>
                <div style={{ flex:"1 1 180px" }}>
                  <label style={lblS}>Cooldown between repeat alerts</label>
                  <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                    <input type="number" min={0} max={1440} value={notifRulesDraft['Notifications_CooldownMinutes']||'30'} onChange={e=>setNotifRulesDraft(p=>({...p,'Notifications_CooldownMinutes':e.target.value}))} style={{...inpS,width:80}} />
                    <span style={{ fontSize:12, color:c.textMuted }}>minutes</span>
                  </div>
                </div>
                <div style={{ flex:"1 1 260px" }}>
                  <label style={lblS}>Suppress child if parent failing</label>
                  <div style={{ display:"flex", alignItems:"center", gap:10, marginTop:4 }}>
                    {tog(notifRulesDraft['Notifications_SuppressChildIfParentFailing']==='true',()=>setNotifRulesDraft(p=>({...p,'Notifications_SuppressChildIfParentFailing':p['Notifications_SuppressChildIfParentFailing']==='true'?'false':'true'})))}
                    <div><div style={{ fontSize:12,fontWeight:600,color:c.text }}>Enabled</div><div style={{ fontSize:11,color:c.textMuted }}>Child alerts suppressed when parent is failing</div></div>
                  </div>
                </div>
              </div>
              <div style={{ display:"flex", gap:16, flexWrap:"wrap", marginBottom:16 }}>
                <div style={{ flex:"1 1 300px" }}>
                  <label style={lblS}>Email timestamp timezone</label>
                  <select value={notifRulesDraft['Notifications_DisplayTimezone']||'America/Chicago'} onChange={e=>setNotifRulesDraft(p=>({...p,'Notifications_DisplayTimezone':e.target.value}))} style={inpS}>
                    <option value="America/New_York">Eastern (America/New_York)</option>
                    <option value="America/Chicago">Central (America/Chicago)</option>
                    <option value="America/Denver">Mountain (America/Denver)</option>
                    <option value="America/Los_Angeles">Pacific (America/Los_Angeles)</option>
                    <option value="America/Anchorage">Alaska (America/Anchorage)</option>
                    <option value="Pacific/Honolulu">Hawaii (Pacific/Honolulu)</option>
                    <option value="Europe/London">UK (Europe/London)</option>
                    <option value="Europe/Paris">Central Europe (Europe/Paris)</option>
                    <option value="Asia/Tokyo">Japan (Asia/Tokyo)</option>
                    <option value="Australia/Sydney">Eastern Australia (Australia/Sydney)</option>
                    <option value="UTC">UTC</option>
                  </select>
                  <div style={{ fontSize:11, color:c.textMuted, marginTop:3 }}>Local time shown in alert emails. UTC always shown alongside.</div>
                </div>
              </div>
              <div style={{ display:"flex", gap:16, flexWrap:"wrap" }}>
                <div style={{ flex:"1 1 240px" }}>
                  <label style={lblS}>Recovery notifications</label>
                  <div style={{ display:"flex", alignItems:"center", gap:10, marginTop:4 }}>
                    {tog(notifRulesDraft['Notifications_SendRecovery']==='true',()=>setNotifRulesDraft(p=>({...p,'Notifications_SendRecovery':p['Notifications_SendRecovery']==='true'?'false':'true'})))}
                    <div><div style={{ fontSize:12,fontWeight:600,color:c.text }}>Send recovered notification</div><div style={{ fontSize:11,color:c.textMuted }}>Fires when a monitor returns to healthy</div></div>
                  </div>
                </div>
                <div style={{ flex:"1 1 240px" }}>
                  <label style={lblS}>Include AI diagnosis</label>
                  <div style={{ display:"flex", alignItems:"center", gap:10, marginTop:4 }}>
                    {tog(notifRulesDraft['Notifications_IncludeAiDiagnosis']==='true',()=>setNotifRulesDraft(p=>({...p,'Notifications_IncludeAiDiagnosis':p['Notifications_IncludeAiDiagnosis']==='true'?'false':'true'})))}
                    <div><div style={{ fontSize:12,fontWeight:600,color:c.text }}>Attach diagnosis if available</div><div style={{ fontSize:11,color:c.textMuted }}>Includes AI diagnosis result in notification body</div></div>
                  </div>
                </div>
              </div>
            </div>
          );

          const notifTestCard = (
            <div style={{ background:"#fff", border:`1px solid ${c.border}`, borderRadius:8, padding:16 }}>
              <div style={{ marginBottom:14 }}>
                <div style={{ fontSize:13, fontWeight:600, color:c.text }}>Send test notification</div>
                <div style={{ fontSize:11, color:c.textMuted, marginTop:2 }}>Validate delivery without triggering a real alert</div>
              </div>
              <div style={{ display:"flex", gap:12, alignItems:"flex-end" }}>
                <div style={{ flex:"1 1 160px" }}>
                  <label style={lblS}>Channel</label>
                  <select value={notifTestCh} onChange={e=>setNotifTestCh(e.target.value)} style={inpS}>
                    <option value="">Select channel…</option>
                    {notifChs.map(ch=><option key={ch.ChannelID} value={String(ch.ChannelID)}>{ch.DisplayName} — {ch.ChannelType}</option>)}
                  </select>
                </div>
                <div style={{ flex:"1 1 160px" }}>
                  <label style={lblS}>Recipient</label>
                  <select value={notifTestRec} onChange={e=>setNotifTestRec(e.target.value)} style={inpS}>
                    <option value="">Select recipient…</option>
                    {notifRecs.filter(r=>r.IsActive).map(r=><option key={r.RecipientID} value={String(r.RecipientID)}>{r.DisplayName} ({r.Destination})</option>)}
                  </select>
                  <div style={{ fontSize:10, color:c.textMuted, marginTop:4, lineHeight:1.4 }}>Optional. With recipient: tests end-to-end delivery to that address. Without: validates the channel by sending to its FromAddress.</div>
                </div>
                <div style={{ display:"flex", alignItems:"center", gap:8, paddingBottom:1 }}>
                  <Btn variant="primary" disabled={!notifTestCh||notifTestResult==='sending'}
                    onClick={async()=>{ setNotifTestResult('sending'); setNotifTestResultDiag(null); try { const r=await api("POST",`/notifications/channels/${notifTestCh}/test`,notifTestRec?{recipientId:parseInt(notifTestRec)}:{}); if(r?.ok){ setNotifTestResult('idle'); setNotifTestResultDiag(r?.diagnosis); } else { setNotifTestResult('idle'); setNotifTestResultDiag(r?.diagnosis); } } catch(e){ setNotifTestResult('idle'); setNotifTestResultDiag({Code:'smtp.unknown',Headline:e?.message||'Test failed',Severity:'unknown'}); } }}>
                    {notifTestResult==='sending'?<><span style={{ display:"inline-block",width:10,height:10,border:"2px solid #cbd5e1",borderTopColor:"#475569",borderRadius:"50%",animation:"spin 0.7s linear infinite",marginRight:6 }} />Sending…</>:'Send test'}
                  </Btn>
                </div>
                {notifTestResultDiag && (()=>{ const suc=notifTestResultDiag.Code?.startsWith("ok"); return (
                  <div style={{ position:"relative", marginTop:6, padding:"8px 10px", background:suc?"#F0FDF4":"#FEF2F2", border:`1px solid ${suc?"#BBF7D0":"#FECACA"}`, borderRadius:4, fontSize:11 }}>
                    <button onClick={()=>{ setNotifTestResultDiag(null); setNotifTestResult(null); }} style={{ position:"absolute",top:6,right:8,background:"none",border:"none",color:"#9CA3AF",fontSize:14,cursor:"pointer",padding:0,lineHeight:1 }} title="Dismiss">&times;</button>
                    <div style={{ fontWeight:600, color:suc?"#166534":"#991B1B" }}>{suc?"✓ ":""}{notifTestResultDiag.Headline}</div>
                    {notifTestResultDiag.Detail && <div style={{ color:suc?"#15803D":"#7F1D1D", marginTop:3 }}>{notifTestResultDiag.Detail}</div>}
                    {notifTestResultDiag.Suggestion && <div style={{ color:"#525B6B", marginTop:4, fontStyle:"italic" }}>&#128161; {notifTestResultDiag.Suggestion}</div>}
                    {notifTestResultDiag.RawError && (
                      <details style={{ marginTop:6 }}>
                        <summary style={{ cursor:"pointer", color:"#64748B", fontSize:10 }}>Show technical details</summary>
                        <pre style={{ fontSize:10, fontFamily:"monospace", background:"#FFFFFF", padding:6, borderRadius:3, marginTop:4, whiteSpace:"pre-wrap", wordBreak:"break-all", color:"#374151" }}>{notifTestResultDiag.RawError}</pre>
                      </details>
                    )}
                  </div>
                );})()}
              </div>
            </div>
          );

          return (
            <div style={{ display:"flex", flexDirection:"column", gap:16 }}>
              {notifLoading
                ? <div style={{ textAlign:"center", padding:40, color:c.textMuted }}>Loading…</div>
                : <>{notifGlobalBanner}{notifChannelsCard}{notifRecipientsCard}{notifRulesCard}{notifTestCard}</>
              }
              {notifChannelModal !== null && (()=>{
                const isEdit = notifChannelModal !== 'add';
                const d = notifChannelDraft;
                const chType = d.ChannelType || 'email';
                const emailFields = (
                  <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
                    {[
                      {k:'SmtpHost',label:'SMTP host',ph:'smtp.example.com'},
                      {k:'SmtpPort',label:'SMTP port',ph:'587'},
                      {k:'SmtpUsername',label:'SMTP username',ph:'user@example.com'},
                      {k:'SmtpPassword',label:'SMTP password',ph:'••••••••'},
                      {k:'FromAddress',label:'From address',ph:'alerts@example.com'},
                      {k:'FromName',label:'From name',ph:'OP1 Alerts'},
                    ].map(f=>(
                      <div key={f.k}>
                        <label style={lblS}>{f.label}</label>
                        <input type={f.k==='SmtpPassword'?'password':'text'} placeholder={f.ph} value={d._cfg?.[f.k]||''} onChange={e=>setNotifChannelDraft(p=>({...p,_cfg:{...p._cfg,[f.k]:f.k==='SmtpPort'?(parseInt(e.target.value,10)||587):e.target.value}}))} style={inpS} />
                      </div>
                    ))}
                    <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                      <input type="checkbox" id="chssl" checked={!!d._cfg?.EnableSsl} onChange={e=>setNotifChannelDraft(p=>({...p,_cfg:{...p._cfg,EnableSsl:e.target.checked}}))} />
                      <label htmlFor="chssl" style={{ fontSize:12, color:c.text }}>Enable SSL/TLS</label>
                    </div>
                  </div>
                );
                const webhookFields = (
                  <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
                    <div>
                      <label style={lblS}>Webhook URL</label>
                      <input type="text" placeholder="https://hooks.example.com/..." value={d._cfg?.Url||''} onChange={e=>setNotifChannelDraft(p=>({...p,_cfg:{...p._cfg,Url:e.target.value}}))} style={inpS} />
                    </div>
                    <div>
                      <label style={lblS}>Secret (optional — for HMAC-SHA256 signing)</label>
                      <PasswordInput value={d._cfg?.Secret||''} onChange={e=>setNotifChannelDraft(p=>({...p,_cfg:{...p._cfg,Secret:e.target.value}}))} placeholder="leave blank to disable signing" />
                    </div>
                  </div>
                );
                const handleSave = async () => {
                  const configJson = JSON.stringify(d._cfg || {});
                  try {
                    if (isEdit) {
                      await api("PUT", `/notifications/channels/${d.ChannelID}`, { DisplayName: d.DisplayName, ConfigJson: configJson, IsEnabled: d.IsEnabled });
                    } else {
                      await api("POST", "/notifications/channels", { ChannelType: chType, DisplayName: d.DisplayName, ConfigJson: configJson, IsEnabled: true });
                    }
                    if (isEdit) setNotifTestDiag(p=>{ const n={...p}; delete n[d.ChannelID]; return n; });
                    loadNotificationsTab();
                    setNotifChannelModal(null);
                  } catch(e) { setErr(e.message); }
                };
                return (
                  <div style={{ position:"fixed", inset:0, background:"rgba(0,0,0,0.45)", zIndex:1200, display:"flex", alignItems:"center", justifyContent:"center" }}>
                    <div style={{ background:"#fff", borderRadius:10, width:480, maxWidth:"95vw", maxHeight:"90vh", display:"flex", flexDirection:"column", boxShadow:"0 8px 32px rgba(0,0,0,0.18)" }}>
                      <div style={{ background:"#1E2B3C", color:"#fff", padding:"14px 20px", borderRadius:"10px 10px 0 0", display:"flex", alignItems:"center", justifyContent:"space-between" }}>
                        <span style={{ fontWeight:700, fontSize:14 }}>{isEdit ? 'Edit channel' : 'Add channel'}</span>
                        <button onClick={()=>setNotifChannelModal(null)} style={{ background:"none", border:"none", color:"rgba(255,255,255,0.7)", fontSize:18, cursor:"pointer", lineHeight:1 }}>×</button>
                      </div>
                      <div style={{ overflowY:"auto", padding:20, display:"flex", flexDirection:"column", gap:14 }}>
                        <div>
                          <label style={lblS}>Display name</label>
                          <input type="text" placeholder="e.g. Primary email relay" value={d.DisplayName||''} onChange={e=>setNotifChannelDraft(p=>({...p,DisplayName:e.target.value}))} style={inpS} />
                        </div>
                        {!isEdit && (
                          <div>
                            <label style={lblS}>Channel type</label>
                            <select value={chType} onChange={e=>setNotifChannelDraft(p=>({...p,ChannelType:e.target.value,_cfg:{}}))} style={inpS}>
                              <option value="email">Email (SMTP)</option>
                              <option value="webhook">Webhook (HTTP POST)</option>
                            </select>
                          </div>
                        )}
                        {chType === 'email' ? emailFields : webhookFields}
                      </div>
                      <div style={{ padding:"12px 20px", borderTop:`1px solid ${c.border}`, display:"flex", gap:8, justifyContent:"flex-end" }}>
                        <Btn variant="secondary" onClick={()=>setNotifChannelModal(null)}>Cancel</Btn>
                        <Btn variant="primary" onClick={handleSave}>Save channel</Btn>
                      </div>
                    </div>
                  </div>
                );
              })()}
              {notifRecipientModal !== null && (()=>{
                const isEdit = notifRecipientModal !== 'add';
                const d = notifRecipientDraft;
                const selCh = notifChs.find(c=>c.ChannelID === (parseInt(d.ChannelID)||0));
                const destLabel = selCh?.ChannelType === 'webhook' ? 'Webhook URL override (leave blank to use channel URL)' : 'Email address';
                const destPlaceholder = selCh?.ChannelType === 'webhook' ? 'https://… (optional)' : 'user@example.com';
                const handleRecSave = async () => {
                  try {
                    if (isEdit) {
                      await api("PUT", `/notifications/recipients/${notifRecipientModal.RecipientID}`, { DisplayName: d.DisplayName, Destination: d.Destination, IsActive: d.IsActive });
                    } else {
                      await api("POST", "/notifications/recipients", { DisplayName: d.DisplayName, ChannelID: parseInt(d.ChannelID), Destination: d.Destination, IsActive: true });
                    }
                    loadNotificationsTab();
                    setNotifRecipientModal(null);
                  } catch(e) { setErr(e.message); }
                };
                return (
                  <div style={{ position:"fixed", inset:0, background:"rgba(0,0,0,0.45)", zIndex:1200, display:"flex", alignItems:"center", justifyContent:"center" }}>
                    <div style={{ background:"#fff", borderRadius:10, width:420, maxWidth:"95vw", display:"flex", flexDirection:"column", boxShadow:"0 8px 32px rgba(0,0,0,0.18)" }}>
                      <div style={{ background:"#1E2B3C", color:"#fff", padding:"14px 20px", borderRadius:"10px 10px 0 0", display:"flex", alignItems:"center", justifyContent:"space-between" }}>
                        <span style={{ fontWeight:700, fontSize:14 }}>{isEdit ? 'Edit recipient' : 'Add recipient'}</span>
                        <button onClick={()=>setNotifRecipientModal(null)} style={{ background:"none", border:"none", color:"rgba(255,255,255,0.7)", fontSize:18, cursor:"pointer", lineHeight:1 }}>×</button>
                      </div>
                      <div style={{ padding:20, display:"flex", flexDirection:"column", gap:14 }}>
                        <div>
                          <label style={lblS}>Display name</label>
                          <input type="text" placeholder="e.g. On-call Team" value={d.DisplayName||''} onChange={e=>setNotifRecipientDraft(p=>({...p,DisplayName:e.target.value}))} style={inpS} />
                        </div>
                        {!isEdit && (
                          <div>
                            <label style={lblS}>Channel</label>
                            <select value={d.ChannelID||''} onChange={e=>setNotifRecipientDraft(p=>({...p,ChannelID:e.target.value}))} style={inpS}>
                              <option value="">Select channel…</option>
                              {notifChs.map(ch=><option key={ch.ChannelID} value={ch.ChannelID}>{ch.DisplayName} ({ch.ChannelType})</option>)}
                            </select>
                          </div>
                        )}
                        <div>
                          <label style={lblS}>{destLabel}</label>
                          <input type="text" placeholder={destPlaceholder} value={d.Destination||''} onChange={e=>setNotifRecipientDraft(p=>({...p,Destination:e.target.value}))} style={inpS} />
                        </div>
                      </div>
                      <div style={{ padding:"12px 20px", borderTop:`1px solid ${c.border}`, display:"flex", gap:8, justifyContent:"flex-end" }}>
                        <Btn variant="secondary" onClick={()=>setNotifRecipientModal(null)}>Cancel</Btn>
                        <Btn variant="primary" onClick={handleRecSave}>Save recipient</Btn>
                      </div>
                    </div>
                  </div>
                );
              })()}
            </div>
          );
        })()}
        {configTab==="retention" && (
          <div style={{ background:"#ffffff", border:"0.5px solid #e2e5ea", borderRadius:8, overflow:"hidden" }}>
            <div style={{ padding:"12px 16px", borderBottom:"0.5px solid #e2e5ea", display:"flex", justifyContent:"space-between", alignItems:"center" }}>
              <div>
                <div style={{ fontSize:10, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.06em" }}>Data Retention Policies</div>
                <div style={{ fontSize:11, color:"#94a3b8", marginTop:2 }}>Hot / warm / cold tiers. Purge runs daily at 2:00 AM UTC.</div>
              </div>
              <Btn variant="danger" onClick={runPurge}>Run Purge Now</Btn>
            </div>
            {retPolicies.length===0 ? <div style={{ padding:32, textAlign:"center", color:"#94a3b8", fontSize:12 }}>No policies found.</div> : (
              <table style={{ width:"100%", borderCollapse:"collapse", fontSize:12 }}>
                <thead><tr style={{ borderBottom:"0.5px solid #e2e5ea", background:"#f8fafc" }}>
                  {["Table","Hot (d)","Warm (d)","Cold (d)","Active","Last Purge"].map(h=><th key={h} style={{ padding:"8px 12px", textAlign:"left", fontSize:9, fontWeight:700, color:"#94a3b8", textTransform:"uppercase" }}>{h}</th>)}
                </tr></thead>
                <tbody>
                  {retPolicies.map(p=>(
                    <tr key={p.PolicyID} style={{ borderBottom:"0.5px solid #f1f5f9" }}>
                      <td style={{ padding:"8px 12px", fontFamily:"monospace", fontSize:11 }}>{p.TableName}</td>
                      <td style={{ padding:"8px 12px", fontWeight:700 }}>{p.HotRetentionDays}</td>
                      <td style={{ padding:"8px 12px" }}>{p.WarmRetentionDays}</td>
                      <td style={{ padding:"8px 12px" }}>{p.ColdRetentionDays}</td>
                      <td style={{ padding:"8px 12px" }}>{p.IsActive?<span style={{ fontSize:10, borderRadius:4, padding:"1px 6px", background:"#dcfce7", color:"#166534" }}>ON</span>:<span style={{ fontSize:10, borderRadius:4, padding:"1px 6px", background:"#fca5a5", color:"#991b1b" }}>OFF</span>}</td>
                      <td style={{ padding:"8px 12px", color:"#94a3b8", fontSize:11 }}>{p.LastPurgeAt?parseUTC(p.LastPurgeAt)?.toLocaleDateString():"—"}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>
        )}
        {configTab==="monitor-defaults" && (
          <div style={{ background:"#ffffff", border:"0.5px solid #e2e5ea", borderRadius:8, padding:16 }}>
            <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center", marginBottom:12 }}>
              <div style={{ fontSize:10, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.06em" }}>Monitor Defaults</div>
              <Btn variant="primary" onClick={saveDefaults} style={{ fontSize:11, padding:"6px 14px" }}>Save Defaults</Btn>
            </div>
            <div style={{ fontSize:12, color:"#94a3b8", marginBottom:16 }}>These values pre-populate the Add Monitor form. Edit any field and click Save Defaults.</div>
            {MONITOR_DEFAULT_SECTIONS.map(sec=>(
              <div key={sec.label} style={{ marginBottom:20 }}>
                <div style={{ fontSize:10, fontWeight:700, color:"#006D8C", letterSpacing:"0.08em", textTransform:"uppercase", marginBottom:8, paddingBottom:4, borderBottom:"0.5px solid #f1f5f9" }}>{sec.label}</div>
                <table style={{ width:"100%", borderCollapse:"collapse", fontSize:12 }}>
                  <thead><tr>
                    {["Setting","Value","Description"].map(h=><th key={h} style={{ padding:"6px 10px", textAlign:"left", fontSize:9, fontWeight:700, color:"#94a3b8", textTransform:"uppercase" }}>{h}</th>)}
                  </tr></thead>
                  <tbody>
                    {sec.keys.map(k=>{
                      const val = monDefaultsDirty[k] ?? monDefaults[k] ?? "";
                      return (
                        <tr key={k} style={{ borderBottom:"0.5px solid #f1f5f9" }}>
                          <td style={{ padding:"7px 10px", fontWeight:600, fontSize:12 }}>{MONITOR_DEFAULT_LABELS[k]||k}</td>
                          <td style={{ padding:"4px 10px" }}>
                            <input type="number" value={val}
                              onChange={e=>setMonDefaultsDirty(p=>({...p,[k]:e.target.value}))}
                              style={{ width:100, padding:"4px 8px", border:"0.5px solid #e2e5ea", borderRadius:4, fontSize:12, fontFamily:"monospace", background:"#ffffff", color:"#1e293b" }} />
                          </td>
                          <td style={{ padding:"7px 10px", color:"#94a3b8", fontSize:11 }}>{MONITOR_DEFAULT_DESC[k]||""}</td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            ))}
          </div>
        )}
        {configTab==="credentials" && (
          <CredentialsTab api={api} />
        )}
        {configTab==="machines" && (
          <MachineManagementSection api={api} machines={machinesProp||[]} currentMachine={currentMachine} onRefresh={onMachinesChange} setErr={setErr} setOk={setOk} />
        )}
        {configTab==="ai-diagnosis" && (
          <div style={{ background:"#ffffff", border:"0.5px solid #e2e5ea", borderRadius:8, padding:16, maxWidth:520 }}>
            <div style={{ fontSize:10, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.06em", marginBottom:14 }}>AI Diagnosis Settings</div>
            {aiCfgLoading ? (
              <div style={{ color:"#94a3b8", fontSize:12, padding:"16px 0" }}>Loading…</div>
            ) : aiCfg === null ? (
              <div style={{ color:"#94a3b8", fontSize:12, padding:"16px 0" }}>Failed to load settings.</div>
            ) : (
              <div style={{ display:"flex", flexDirection:"column", gap:16 }}>
                {/* Enable toggle */}
                <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between" }}>
                  <div>
                    <div style={{ fontSize:13, fontWeight:600, color:"#1e293b" }}>Enable AI Diagnosis</div>
                    <div style={{ fontSize:11, color:"#94a3b8", marginTop:2 }}>{aiCfg.minSeverity==="critical"?"Automatically diagnose critical alerts using AI":aiCfg.minSeverity==="warning"?"Automatically diagnose warning and critical alerts using AI":aiCfg.minSeverity==="info"?"Automatically diagnose all alerts using AI":"Automatically diagnose alerts using AI"}</div>
                  </div>
                  <div onClick={()=>setAiCfg(p=>({...p, enabled:!p.enabled}))}
                    style={{ width:36, height:20, borderRadius:10, background:aiCfg.enabled?"#006D8C":"#e2e5ea", position:"relative", cursor:"pointer", transition:"background 0.2s", flexShrink:0 }}>
                    <div style={{ position:"absolute", top:3, left:aiCfg.enabled?17:3, width:14, height:14, borderRadius:"50%", background:"#fff", transition:"left 0.2s" }} />
                  </div>
                </div>
                {/* Min severity */}
                <div style={{ opacity: aiCfg.enabled ? 1 : 0.4, pointerEvents: aiCfg.enabled ? "auto" : "none" }}>
                  <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:6, textTransform:"uppercase", letterSpacing:"0.05em" }}>Minimum Severity</div>
                  <select value={aiCfg.minSeverity} onChange={e=>setAiCfg(p=>({...p, minSeverity:e.target.value}))}
                    style={{ width:"100%", padding:"8px 12px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:13, background:"#fff", color:"#1e293b", outline:"none" }}>
                    <option value="critical">Critical only</option>
                    <option value="warning">Warning and above</option>
                    <option value="info">All alerts</option>
                  </select>
                </div>
                {/* Cooldown */}
                <div style={{ opacity: aiCfg.enabled ? 1 : 0.4, pointerEvents: aiCfg.enabled ? "auto" : "none" }}>
                  <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:6, textTransform:"uppercase", letterSpacing:"0.05em" }}>Cooldown (same monitor)</div>
                  <select value={String(aiCfg.cooldownMinutes)} onChange={e=>setAiCfg(p=>({...p, cooldownMinutes:parseInt(e.target.value)}))}
                    style={{ width:"100%", padding:"8px 12px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:13, background:"#fff", color:"#1e293b", outline:"none" }}>
                    <option value="15">15 min</option>
                    <option value="30">30 min</option>
                    <option value="60">1 hour</option>
                    <option value="120">2 hours</option>
                    <option value="240">4 hours</option>
                  </select>
                </div>
                {/* Usage */}
                <div style={{ fontSize:12, color:"#4A4A4A" }}>
                  {aiCfg.firesLast24h > 0
                    ? `Fired ${aiCfg.firesLast24h} time${aiCfg.firesLast24h !== 1 ? "s" : ""} in the last 24 hours`
                    : "No diagnoses in the last 24 hours"}
                </div>
                {/* Save */}
                <div style={{ display:"flex", alignItems:"center", gap:10 }}>
                  <button onClick={saveAiCfg} disabled={aiCfgSaving}
                    style={{ padding:"8px 20px", background:"#006D8C", color:"#fff", border:"none", borderRadius:6, fontSize:13, fontWeight:600, cursor:"pointer" }}>
                    {aiCfgSaving ? "Saving…" : "Save"}
                  </button>
                  {aiCfgSaved && <span style={{ fontSize:12, color:"#008C6F", fontWeight:600 }}>Saved ✓</span>}
                </div>
              </div>
            )}
          </div>
        )}

        {/* ── Import / Export tab ── */}
        {configTab==="configpack" && (
          <div style={{ display:"flex", flexDirection:"column", gap:16 }}>
            {/* Sub-tab bar */}
            <div style={{ display:"flex", gap:0, borderBottom:"0.5px solid #e2e5ea" }}>
              {[['export','Export'],['import','Import'],['feeds','Ingest Feeds'],['mappings','Metric Mappings']].map(([k,lbl]) => (
                <button key={k} onClick={()=>setConfigPackTab(k)}
                  style={{ background:"transparent", border:"none", borderBottom: configPackTab===k ? "2px solid #006D8C" : "2px solid transparent", color: configPackTab===k ? "#006D8C" : "#64748b", padding:"8px 16px", fontSize:12, fontWeight: configPackTab===k ? 600 : 400, cursor:"pointer" }}>
                  {lbl}
                </button>
              ))}
            </div>

            {/* Export panel */}
            {configPackTab==="export" && (
              <div style={{ display:"flex", flexDirection:"column", gap:16, maxWidth:580 }}>
                <div style={{ background:"#fff", border:"0.5px solid #e2e5ea", borderRadius:8, padding:16 }}>
                  <div style={{ fontSize:10, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.06em", marginBottom:14 }}>Export configuration</div>

                  {/* Group filter */}
                  <div style={{ marginBottom:14 }}>
                    <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:8 }}>Filter by group</div>
                    {exportGroupsLoading ? (
                      <div style={{ fontSize:12, color:"#94a3b8" }}>Loading groups…</div>
                    ) : (
                      <div style={{ display:"flex", flexDirection:"column", gap:4 }}>
                        <label style={{ display:"flex", alignItems:"center", gap:6, fontSize:12, color:"#1e293b", cursor:"pointer" }}>
                          <input type="checkbox"
                            checked={selectedExportGroups===null || selectedExportGroups.length===exportGroups.length}
                            onChange={toggleAllGroups}
                          />
                          <span style={{ fontWeight:600 }}>All groups</span>
                        </label>
                        {exportGroups.map(g => (
                          <label key={g.GroupID} style={{ display:"flex", alignItems:"center", gap:6, fontSize:12, color:"#1e293b", cursor:"pointer", paddingLeft:16 }}>
                            <input type="checkbox"
                              checked={selectedExportGroups===null || (Array.isArray(selectedExportGroups) && selectedExportGroups.includes(g.GroupName))}
                              onChange={()=>toggleGroup(g.GroupName)}
                            />
                            {g.GroupName} <span style={{ color:"#94a3b8", fontSize:11 }}>({g.MonitorCount||0})</span>
                          </label>
                        ))}
                        {exportGroups.length===0 && (
                          <div style={{ fontSize:12, color:"#94a3b8", paddingLeft:4 }}>No groups defined</div>
                        )}
                      </div>
                    )}
                  </div>

                  {/* Format toggle */}
                  <div style={{ marginBottom:14 }}>
                    <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:8 }}>Format</div>
                    <div style={{ display:"flex", gap:6 }}>
                      {[['json','JSON'],['xlsx','XLSX']].map(([fmt,lbl]) => (
                        <button key={fmt} onClick={()=>setExportFormat(fmt)}
                          style={{ padding:"6px 16px", borderRadius:6, border:`1px solid ${exportFormat===fmt?c.blue:"#e2e5ea"}`, background: exportFormat===fmt?c.blue:"#fff", color: exportFormat===fmt?"#fff":"#64748b", fontSize:12, fontWeight: exportFormat===fmt?600:400, cursor:"pointer" }}>
                          {lbl}
                        </button>
                      ))}
                    </div>
                  </div>

                  {/* Summary */}
                  <div style={{ fontSize:11, color:"#64748b", marginBottom:14 }}>
                    {(()=>{
                      const sg = selectedExportGroups===null ? exportGroups : exportGroups.filter(g=>selectedExportGroups.includes(g.GroupName));
                      const tm = sg.reduce((s,g)=>s+(g.MonitorCount||0),0);
                      const tg = sg.length;
                      return `${tg} group${tg!==1?'s':''} · ${tm} monitor${tm!==1?'s':''} will be exported`;
                    })()}
                  </div>

                  {/* Download */}
                  <div style={{ display:"flex", alignItems:"center", gap:14 }}>
                    <button onClick={handleExportDownload}
                      style={{ padding:"8px 20px", background:c.blue, color:"#fff", border:"none", borderRadius:6, fontSize:13, fontWeight:600, cursor:"pointer" }}>
                      ↓ Download {exportFormat.toUpperCase()}
                    </button>
                    <span style={{ fontSize:11, color:"#94a3b8" }}>Last exported: {exportLastDate||"Never"}</span>
                  </div>
                </div>
              </div>
            )}

            {/* Metric Mappings panel */}
            {configPackTab==="mappings" && mappingsPanel}

            {/* Ingest Feeds panel */}
            {configPackTab==="feeds" && (()=>{
              const feedProtocolColors = { influxdb:'#006D8C', prometheus:'#E6522C', 'prometheus-scrape':'#E6522C', statsd:'#6366f1', graphite:'#374151', webhook:'#008C6F', spreadsheet:'#B45309' };
              const feedProtocolLabel = { influxdb:'InfluxDB LP', prometheus:'Prometheus Push', 'prometheus-scrape':'Prometheus Scrape', statsd:'StatsD', graphite:'Graphite', webhook:'Webhook', spreadsheet:'Spreadsheet' };
              const renderAiMd = (text) => {
                const html = (text||'')
                  .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
                  .replace(/\*\*(.+?)\*\*/g,'<strong>$1</strong>')
                  .replace(/^[ \t]*[-*]\s+(.+)$/gm,'<span style="display:block;padding-left:12px">\u2022 $1</span>')
                  .replace(/\n/g,'<br/>');
                return { __html: html };
              };
              const isScrape = feedForm.protocol === 'prometheus-scrape';
              const stepPct = feedWizardStep === 1 ? 25 : feedWizardStep === 2 ? 50 : feedWizardStep === 3 ? 75 : 100;
              const stepLabels = isScrape ? ['Feed details','Add targets','Review & map','Activate'] : ['Feed details','Sample data','Confirm mappings','Activate'];
              return (
                <div style={{ display:"flex", flexDirection:"column", gap:16, maxWidth:720 }}>
                  {/* Feeds list header */}
                  <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between" }}>
                    <div style={{ fontSize:13, fontWeight:700, color:"#1e293b" }}>Ingest Feeds</div>
                    <button onClick={()=>{ setFeedWizardOpen(true); setFeedWizardStep(1); if(credentialsList.length===0) api("GET","/credentials").then(r=>{if(Array.isArray(r))setCredentialsList(r);}).catch(()=>{}); }}
                      style={{ padding:"6px 14px", background:"#006D8C", color:"#fff", border:"none", borderRadius:6, fontSize:12, fontWeight:600, cursor:"pointer" }}>
                      + New Feed
                    </button>
                  </div>

                  {feedsLoading && <div style={{ fontSize:12, color:"#94a3b8" }}>Loading…</div>}

                  {!feedsLoading && feedsList.length === 0 && !feedWizardOpen && (
                    <div style={{ background:"#f8fafc", border:"1.5px dashed #cbd5e1", borderRadius:8, padding:"32px 20px", textAlign:"center" }}>
                      <div style={{ fontSize:13, color:"#64748b" }}>No feeds configured yet.</div>
                      <div style={{ fontSize:12, color:"#94a3b8", marginTop:4 }}>Click + New Feed to get started.</div>
                    </div>
                  )}

                  {feedsList.length > 0 && (
                    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
                      {feedsList.map(feed => {
                        const feedTargets = scrapeTargetsByFeed[feed.FeedID] || [];
                        const anyFail = feedTargets.some(t => t.ConsecutiveFailures > 2 || t.LastScrapeSuccess === false);
                        const totalFail = feedTargets.reduce((s,t)=>s+(t.ConsecutiveFailures||0),0);
                        const lastTarget = feedTargets[0] || null;
                        const lastAt = lastTarget && lastTarget.LastScrapedAt;
                        const lastTime = lastAt ? new Date(lastAt+'Z').toLocaleTimeString('en-US',{hour:'numeric',minute:'2-digit'}) : null;
                        const everScraped = feedTargets.some(t => t.LastScrapedAt);
                        const neverSucceeded = feed.IsScrape && feedTargets.length > 0 && !everScraped;
                        const fp = feed.Protocol || '';
                        const feedUnresolved = unresolvedList.filter(u => { const up=u.SourceProtocol||''; return up===fp||(fp==='prometheus-scrape'&&(up==='prometheus'||up==='prometheus-scrape')); }).length;
                        const isAiOpen = feedAiOpenId === feed.FeedID;
                        const isRawOpen = !!lastTarget && lastTarget.TargetID === rawPayloadOpen;
                        const statusColor = !feed.IsActive ? '#9CA3AF' : anyFail ? '#D95C5C' : '#008C6F';
                        const muted = !feed.IsActive;
                        const fid = feed.FeedID;
                        const dimBtn = neverSucceeded;
                        const tgtUrl = lastTarget ? lastTarget.ScrapeUrl || '' : '';
                        let svgHost='', svgPath='/metrics';
                        try { const pu = new URL(tgtUrl); svgHost=pu.host; svgPath=pu.pathname; } catch(_){}
                        const arcOk = feed.IsScrape && everScraped && !anyFail;
                        const targetFill = arcOk ? '#e0f2fe' : '#FAEAEA';
                        const targetStroke = arcOk ? '#006D8C' : '#D95C5C';
                        const retColor = arcOk ? '#008C6F' : '#D95C5C';
                        const interval = feed.ScrapeIntervalSeconds || 30;
                        const statusNote = neverSucceeded ? 'never succeeded' : lastTime ? 'last: '+lastTime+' \u2713' : 'pending\u2026';
                        const statusNoteColor = neverSucceeded ? '#D95C5C' : arcOk ? '#008C6F' : '#E89A2E';
                        const volRows = (()=>{
                          const rows = [{ label:'Samples received', count:everScraped?20:0, color:'#006D8C' }];
                          if (feedUnresolved > 0) rows.push({ label:'Unresolved', count:feedUnresolved, color:'#E89A2E', isUnresolved:true });
                          return rows;
                        })();
                        const volMax = Math.max(...volRows.map(r=>r.count), 1);
                        return (
                          <div key={'fc-'+fid} style={{ border:'1px solid #e2e5ea', borderRadius:8, overflow:'hidden' }}>
                            <div style={{ display:'grid', gridTemplateColumns:'44% 56%', minHeight:160 }}>
                              {/* Left column */}
                              <div style={{ background:'#f8fafc', borderRight:'1px solid #e2e5ea', display:'flex', flexDirection:'column', opacity:muted?0.75:1 }}>
                                <div style={{ display:'flex', alignItems:'center', gap:5, padding:'10px 12px', flexWrap:'wrap' }}>
                                  <span style={{ width:8, height:8, borderRadius:'50%', background:statusColor, display:'inline-block', flexShrink:0 }}/>
                                  <span style={{ fontSize:12, fontWeight:700, color:'#1e293b', flex:1, minWidth:0, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{feed.FeedName}</span>
                                  <span style={{ fontSize:10, fontWeight:700, color:feed.IsScrape?'#006D8C':'#008C6F', background:feed.IsScrape?'#e0f2fe':'#d1fae5', borderRadius:4, padding:'1px 7px', flexShrink:0 }}>{feed.IsScrape?'pull':'push'}</span>
                                  <span style={{ fontSize:10, fontWeight:600, color:'#fff', background:feedProtocolColors[feed.Protocol]||'#64748b', borderRadius:4, padding:'1px 7px', flexShrink:0 }}>{feedProtocolLabel[feed.Protocol]||feed.Protocol}</span>
                                </div>
                                <div style={{ flex:1, padding:'2px 8px 0' }}>
                                  {feed.IsScrape ? (
                                    <svg viewBox="0 0 296 112" style={{width:'100%',height:'auto',display:'block'}}>
                                      <defs>
                                        <marker id={'ah1-'+fid} markerWidth="7" markerHeight="7" refX="5" refY="3.5" orient="auto">
                                          <path d="M0,0 L7,3.5 L0,7 Z" fill={arcOk?'#006D8C':'#D95C5C'}/>
                                        </marker>
                                        <marker id={'ah2-'+fid} markerWidth="7" markerHeight="7" refX="5" refY="3.5" orient="auto">
                                          <path d="M0,0 L7,3.5 L0,7 Z" fill={retColor} fillOpacity={arcOk?1:0.4}/>
                                        </marker>
                                      </defs>
                                      <rect x="8" y="36" width="62" height="32" rx="5" fill="#006D8C"/>
                                      <text x="39" y="56" textAnchor="middle" fill="#fff" fontSize="12" fontWeight="bold" fontFamily="sans-serif">OP1</text>
                                      <rect x="222" y={arcOk?36:32} width="66" height={arcOk?32:48} rx="5" fill={targetFill} stroke={targetStroke} strokeWidth="1.5"/>
                                      {arcOk ? (
                                        <React.Fragment>
                                          <text x="255" y="50" textAnchor="middle" fill={targetStroke} fontSize="8" fontWeight="600" fontFamily="sans-serif">{svgHost.length>14?svgHost.slice(0,13)+'\u2026':svgHost||'TARGET'}</text>
                                          <text x="255" y="61" textAnchor="middle" fill={targetStroke} fontSize="7.5" fontFamily="sans-serif">{svgPath}</text>
                                        </React.Fragment>
                                      ) : (
                                        <React.Fragment>
                                          <text x="255" y="46" textAnchor="middle" fill="#D95C5C" fontSize="8" fontWeight="600" fontFamily="sans-serif">{svgHost.length>14?svgHost.slice(0,13)+'\u2026':svgHost||'target URL'}</text>
                                          <text x="255" y="58" textAnchor="middle" fill="#D95C5C" fontSize="7.5" fontFamily="sans-serif">{svgPath||'/'}</text>
                                          <text x="255" y="70" textAnchor="middle" fill="#D95C5C" fontSize="8" fontWeight="600" fontFamily="sans-serif">{neverSucceeded?'no data yet':'unreachable'}</text>
                                        </React.Fragment>
                                      )}
                                      <path d="M70,48 Q148,12 222,48" fill="none" stroke={arcOk?'#006D8C':'#D95C5C'} strokeWidth="1.5" strokeDasharray="4,3" markerEnd={'url(#ah1-'+fid+')'}/>
                                      <text x="148" y="9" textAnchor="middle" fill={arcOk?'#006D8C':'#D95C5C'} fontSize="8.5" fontFamily="sans-serif">{'GET · every '+interval+'s'}</text>
                                      <path d="M222,60 Q148,98 70,60" fill="none" stroke={retColor} strokeWidth={arcOk?2:1.5} strokeDasharray={arcOk?undefined:'4,3'} opacity={arcOk?undefined:'0.4'} markerEnd={'url(#ah2-'+fid+')'}/>
                                      <text x="148" y="110" textAnchor="middle" fill={retColor} fontSize="8.5" fontFamily="sans-serif" opacity={arcOk?undefined:'0.4'}>{arcOk?'full metrics payload':('no response \u00d7 '+totalFail)}</text>
                                      <text x="39" y="83" textAnchor="middle" fill={statusNoteColor} fontSize="8" fontFamily="sans-serif">{statusNote}</text>
                                    </svg>
                                  ) : (
                                    <svg viewBox="0 0 296 112" style={{width:'100%',height:'auto',display:'block'}}>
                                      <defs>
                                        <marker id={'ah1-'+fid} markerWidth="7" markerHeight="7" refX="5" refY="3.5" orient="auto">
                                          <path d="M0,0 L7,3.5 L0,7 Z" fill="#008C6F"/>
                                        </marker>
                                      </defs>
                                      <rect x="6" y="24" width="74" height="52" rx="5" fill="#d1fae5" stroke="#008C6F" strokeWidth="1.5"/>
                                      <text x="43" y="44" textAnchor="middle" fill="#065f46" fontSize="9" fontWeight="700" fontFamily="sans-serif">SOURCE</text>
                                      <text x="43" y="56" textAnchor="middle" fill="#065f46" fontSize="7.5" fontFamily="sans-serif">{feed.FeedName.length>13?feed.FeedName.slice(0,12)+'\u2026':feed.FeedName}</text>
                                      <text x="43" y="68" textAnchor="middle" fill="#065f46" fontSize="7" fontFamily="sans-serif">push agent</text>
                                      <rect x="222" y="36" width="66" height="32" rx="5" fill="#006D8C"/>
                                      <text x="255" y="52" textAnchor="middle" fill="#fff" fontSize="10" fontWeight="bold" fontFamily="sans-serif">OP1</text>
                                      <text x="255" y="63" textAnchor="middle" fill="#bae6fd" fontSize="6.5" fontFamily="sans-serif">{'/api/ingest/'+feed.Protocol}</text>
                                      <path d="M80,46 Q148,12 222,46" fill="none" stroke="#008C6F" strokeWidth="2" markerEnd={'url(#ah1-'+fid+')'}/>
                                      <text x="148" y="9" textAnchor="middle" fill="#008C6F" fontSize="8.5" fontFamily="sans-serif">POST metrics payload</text>
                                      <path d="M222,60 Q148,94 80,60" fill="none" stroke="#94a3b8" strokeWidth="1" opacity="0.35"/>
                                      <text x="148" y="107" textAnchor="middle" fill="#94a3b8" fontSize="7.5" fontFamily="sans-serif" opacity="0.5">204 · ack only</text>
                                      <text x="43" y="90" textAnchor="middle" fill="#94a3b8" fontSize="7" fontFamily="sans-serif">no feedback loop</text>
                                    </svg>
                                  )}
                                </div>
                                <div style={{ padding:'8px 12px', display:'flex', alignItems:'center', gap:8, borderTop:'0.5px solid #e2e5ea' }}>
                                  <button onClick={()=>toggleFeed(fid, feed.IsActive)}
                                    style={{ position:'relative', width:36, height:20, borderRadius:10, border:'none', background:feed.IsActive?'#006D8C':'#cbd5e1', cursor:'pointer', flexShrink:0 }}>
                                    <span style={{ position:'absolute', top:2, left:feed.IsActive?18:2, width:16, height:16, borderRadius:'50%', background:'#fff', display:'block' }}/>
                                  </button>
                                  <span style={{ fontSize:11, color:feed.IsActive?'#1e293b':'#94a3b8' }}>{feed.IsActive?'Enabled':'Paused'}</span>
                                </div>
                              </div>
                              {/* Right column */}
                              <div style={{ background:'#fff', display:'flex', flexDirection:'column', padding:'10px 14px' }}>
                                <div style={{ fontSize:10, fontWeight:700, color:'#94a3b8', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:8 }}>Data flow · last hour</div>
                                <div style={{ display:'flex', flexDirection:'column', gap:6, flex:1 }}>
                                  {volRows.map((row,ri) => (
                                    <div key={ri} style={{ display:'flex', alignItems:'center', gap:8 }}>
                                      <span style={{ fontSize:11, color:row.isUnresolved?'#E89A2E':'#374151', width:108, flexShrink:0, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{row.label}</span>
                                      <div style={{ flex:1, height:8, background:'#f1f5f9', borderRadius:4, overflow:'hidden' }}>
                                        <div style={{ height:'100%', width:Math.round(row.count/volMax*100)+'%', background:row.color, borderRadius:4, minWidth:row.count>0?4:0 }}/>
                                      </div>
                                      <span style={{ fontSize:10, color:'#64748b', flexShrink:0, whiteSpace:'nowrap' }}>{row.count>0?row.count+'/hr':'\u2013'}</span>
                                    </div>
                                  ))}
                                  {feed.IsScrape && !everScraped && feedUnresolved===0 && (
                                    <div style={{ fontSize:11, color:'#94a3b8', fontStyle:'italic', marginTop:4 }}>No data yet</div>
                                  )}
                                </div>
                                <div style={{ borderTop:'0.5px solid #f1f5f9', paddingTop:8, marginTop:8, display:'flex', flexWrap:'wrap', gap:10 }}>
                                  {feed.IsScrape ? (
                                    <React.Fragment>
                                      <span style={{ fontSize:10, color:'#64748b' }}>
                                        {neverSucceeded ? React.createElement('span',{style:{color:'#D95C5C'}},'Never scraped successfully') : lastTime ? React.createElement(React.Fragment,null,'Last scraped: ',React.createElement('b',null,lastTime)) : 'Pending first scrape'}
                                      </span>
                                      {totalFail>0 && <span style={{fontSize:10,color:'#D95C5C'}}>{'⚠ '+totalFail+' consecutive failure'+(totalFail!==1?'s':'')}</span>}
                                      {lastTarget&&lastTarget.LastScrapeMs&&lastTarget.LastScrapeMs>0&&<span style={{fontSize:10,color:'#64748b'}}>{'~'+lastTarget.LastScrapeMs+'ms/scrape'}</span>}
                                    </React.Fragment>
                                  ) : (
                                    <span style={{fontSize:10,color:'#64748b'}}>{'Push feed · '+(feed.IsActive?'active \u2014 awaiting data':'paused')}</span>
                                  )}
                                  {feedUnresolved>0 && <span style={{fontSize:10,color:'#E89A2E'}}>{'⚠ '+feedUnresolved+' unresolved sample'+(feedUnresolved!==1?'s':'')}</span>}
                                </div>
                              </div>
                            </div>
                            {/* Action bar */}
                            <div style={{ borderTop:'1px solid #e2e5ea', display:'flex', alignItems:'center', gap:4, padding:'6px 10px', background:'#fff' }}>
                              <button onClick={()=>setFeedAiOpenId(isAiOpen?null:fid)}
                                style={{ padding:'4px 10px', background:isAiOpen?'#006D8C':'transparent', color:isAiOpen?'#fff':'#006D8C', border:'1px solid #006D8C', borderRadius:5, fontSize:11, cursor:'pointer', fontWeight:600 }}>⚡ Ask AI</button>
                              <button onClick={()=>{ if(!feed.IsScrape||!lastTarget||neverSucceeded) return; if(rawPayloadOpen===lastTarget.TargetID){setRawPayloadOpen(null);setRawPayload(null);return;} setRawPayloadOpen(lastTarget.TargetID);setRawPayloadLoading(true);setRawPayload(null);loadRawPayload(lastTarget.TargetID); }}
                                disabled={!feed.IsScrape||!lastTarget||neverSucceeded}
                                style={{ padding:'4px 10px', background:'transparent', color:(!feed.IsScrape||!lastTarget||neverSucceeded)?'#cbd5e1':'#374151', border:'1px solid '+((!feed.IsScrape||!lastTarget||neverSucceeded)?'#e2e5ea':'#94a3b8'), borderRadius:5, fontSize:11, cursor:(!feed.IsScrape||!lastTarget||neverSucceeded)?'not-allowed':'pointer' }}>View raw</button>
                              <button onClick={()=>{ if(!dimBtn) setConfigPackTab('mappings'); }}
                                disabled={dimBtn}
                                style={{ padding:'4px 10px', background:'transparent', color:dimBtn?'#cbd5e1':'#374151', border:'1px solid '+(dimBtn?'#e2e5ea':'#94a3b8'), borderRadius:5, fontSize:11, cursor:dimBtn?'not-allowed':'pointer' }}>Mappings</button>
                              <button onClick={()=>{ if(!dimBtn&&feedUnresolved>0) setConfigPackTab('mappings'); }}
                                disabled={dimBtn||feedUnresolved===0}
                                style={{ padding:'4px 10px', background:'transparent', color:(dimBtn||feedUnresolved===0)?'#cbd5e1':'#E89A2E', border:'1px solid '+((dimBtn||feedUnresolved===0)?'#e2e5ea':'#E89A2E'), borderRadius:5, fontSize:11, cursor:(dimBtn||feedUnresolved===0)?'not-allowed':'pointer' }}>Resolve metrics</button>
                              <button onClick={()=>{}}
                                style={{ padding:'4px 10px', background:'transparent', color:'#374151', border:'1px solid #94a3b8', borderRadius:5, fontSize:11, cursor:'pointer' }}>Edit</button>
                              <span style={{ flex:1 }}/>
                              {neverSucceeded ? (
                                <button onClick={()=>showConfirm('Delete this feed?', async()=>{ try { await api("DELETE",'/ingest/feeds/'+fid); setFeedsList(prev=>prev.filter(f=>f.FeedID!==fid)); setScrapeTargetsByFeed(prev=>{const n={...prev};delete n[fid];return n;}); } catch(_){} })}
                                  style={{ padding:'4px 10px', background:'transparent', color:'#D95C5C', border:'1px solid #D95C5C', borderRadius:5, fontSize:11, cursor:'pointer' }}>Delete</button>
                              ) : (
                                <button onClick={()=>toggleFeed(fid, feed.IsActive)}
                                  style={{ padding:'4px 10px', background:'transparent', color:'#64748b', border:'1px solid #e2e5ea', borderRadius:5, fontSize:11, cursor:'pointer' }}>{feed.IsActive?'Disable':'Enable'}</button>
                              )}
                            </div>
                            {/* Raw payload panel */}
                            {isRawOpen && (
                              <div style={{ padding:'12px 14px', background:'#f8fafc', borderTop:'0.5px solid #e2e5ea' }}>
                                {rawPayloadLoading ? (
                                  <div style={{ fontSize:12, color:'#94a3b8' }}>Loading payload…</div>
                                ) : rawPayload ? (
                                  <div>
                                    <div style={{ fontSize:10, color:'#94a3b8', marginBottom:6 }}>{rawPayload.TargetUrl} · {rawPayload.LastPayloadAt?new Date(rawPayload.LastPayloadAt+'Z').toLocaleString():'Never'}</div>
                                    <pre style={{ fontSize:10, fontFamily:'monospace', background:'#1e293b', color:'#e2e8f0', borderRadius:6, padding:'10px 12px', maxHeight:200, overflow:'auto', margin:0, whiteSpace:'pre-wrap', wordBreak:'break-all' }}>{rawPayload.Payload||'(empty)'}</pre>
                                  </div>
                                ) : (
                                  <div style={{ fontSize:12, color:'#94a3b8' }}>No payload available yet.</div>
                                )}
                              </div>
                            )}
                            {/* AI panel */}
                            {isAiOpen && (
                              <div style={{ borderTop:'1px solid #e2e5ea', padding:'12px 14px', background:'#f0f9ff' }}>
                                <div style={{ fontSize:12, fontWeight:700, color:'#006D8C', marginBottom:8 }}>{'⚡ AI Assistant \u2014 '+feed.FeedName}</div>
                                <div style={{ display:'flex', flexWrap:'wrap', gap:6, marginBottom:10 }}>
                                  {(feedUnresolved > 0
                                    ? ["Why are some metrics unresolved?", "What monitors should I create?", "Show me the LIKE patterns I need"]
                                    : totalFail > 0
                                    ? ["Why is this feed failing?", "How do I fix the target URL?", "What does this error mean?"]
                                    : ["Is this data volume normal?", "How is this feed performing?", "What can I do to improve mapping coverage?"]
                                  ).map((q,qi)=>(
                                    <button key={qi} onClick={()=>handleAskFeed(fid, q)}
                                      style={{ padding:'4px 10px', background:'#e0f2fe', color:'#006D8C', border:'1px solid #bae6fd', borderRadius:20, fontSize:11, cursor:'pointer' }}>{q}</button>
                                  ))}
                                </div>
                                {(feedAiThreads[fid]||[]).length > 0 && (
                                  <div style={{ display:'flex', flexDirection:'column', gap:8, marginBottom:10, maxHeight:240, overflowY:'auto' }}>
                                    {(feedAiThreads[fid]||[]).map((msg,mi)=>(
                                      msg.role==='user'
                                        ? <div key={mi} style={{ padding:'6px 10px', borderRadius:6, background:'#e0f2fe', alignSelf:'flex-end', maxWidth:'88%', fontSize:12, color:'#1e293b', whiteSpace:'pre-wrap', lineHeight:1.5 }}>{msg.content}</div>
                                        : <div key={mi} style={{ padding:'6px 10px', borderRadius:6, background:'#fff', alignSelf:'flex-start', maxWidth:'88%', fontSize:12, color:'#1e293b', lineHeight:1.5 }} dangerouslySetInnerHTML={renderAiMd(msg.content)} />
                                    ))}
                                    {feedAiLoading[fid] && (
                                      <div style={{ padding:'6px 10px', borderRadius:6, background:'#fff', alignSelf:'flex-start', fontSize:12, color:'#94a3b8', fontStyle:'italic' }}>⚡ thinking…</div>
                                    )}
                                  </div>
                                )}
                                <div style={{ display:'flex', gap:6 }}>
                                  <input value={feedAiInput[fid]||''} onChange={e=>setFeedAiInput(prev=>({...prev,[fid]:e.target.value}))}
                                    onKeyDown={e=>{ if(e.key==='Enter'&&(feedAiInput[fid]||'').trim()&&!feedAiLoading[fid]) handleAskFeed(fid, feedAiInput[fid]||''); }}
                                    placeholder="Ask about this feed…"
                                    style={{ flex:1, padding:'6px 10px', border:'1px solid #bae6fd', borderRadius:6, fontSize:12, background:'#fff' }}/>
                                  <button disabled={!(feedAiInput[fid]||'').trim()||!!feedAiLoading[fid]}
                                    onClick={()=>handleAskFeed(fid, feedAiInput[fid]||'')}
                                    style={{ padding:'6px 14px', background:(!(feedAiInput[fid]||'').trim()||feedAiLoading[fid])?'#94a3b8':'#006D8C', color:'#fff', border:'none', borderRadius:6, fontSize:12, cursor:(!(feedAiInput[fid]||'').trim()||feedAiLoading[fid])?'not-allowed':'pointer', fontWeight:600, whiteSpace:'nowrap' }}>
                                    {feedAiLoading[fid]?'⚡ thinking…':'Ask'}
                                  </button>
                                </div>
                              </div>
                            )}
                          </div>
                        );
                      })}
                    </div>
                  )}

                  {/* Wizard */}
                  {feedWizardOpen && (
                    <div ref={feedWizardRef} style={{ background:"#fff", border:"0.5px solid #e2e5ea", borderRadius:8, overflow:"hidden" }}>
                      {/* Wizard header */}
                      <div style={{ background:"#006D8C", color:"#fff", padding:"10px 14px", display:"flex", alignItems:"center", justifyContent:"space-between" }}>
                        <span style={{ fontSize:13, fontWeight:700 }}>New Ingest Feed — Setup Wizard</span>
                        <button onClick={resetFeedWizard} style={{ background:"none", border:"none", color:"#fff", fontSize:16, cursor:"pointer", lineHeight:1 }}>×</button>
                      </div>

                      {/* Progress bar */}
                      <div style={{ height:4, background:"#e2e5ea" }}>
                        <div style={{ height:"100%", background:"#006D8C", width:stepPct+"%", transition:"width 0.3s" }} />
                      </div>

                      {/* Step indicators */}
                      <div style={{ display:"flex", borderBottom:"0.5px solid #e2e5ea" }}>
                        {stepLabels.map((lbl, i) => {
                          const sn = i+1;
                          const active = sn === feedWizardStep;
                          const done = sn < feedWizardStep;
                          return (
                            <div key={i} style={{ flex:1, padding:"8px 6px", textAlign:"center", borderRight: i < 3 ? "0.5px solid #e2e5ea" : "none", background: active ? "#f0f9ff" : "#fff" }}>
                              <div style={{ fontSize:10, fontWeight:700, color: active ? "#006D8C" : done ? "#008C6F" : "#94a3b8" }}>{done ? "✓" : sn}</div>
                              <div style={{ fontSize:10, color: active ? "#006D8C" : done ? "#008C6F" : "#94a3b8", marginTop:2 }}>{lbl}</div>
                            </div>
                          );
                        })}
                      </div>

                      <div style={{ padding:"16px" }}>

                        {/* Step 1 — Feed details */}
                        {feedWizardStep === 1 && (
                          <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
                            <div>
                              <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:4 }}>Feed name <span style={{ color:"#D95C5C" }}>*</span></div>
                              <input value={feedForm.feedName} onChange={e=>setFeedForm(f=>({...f,feedName:e.target.value}))}
                                placeholder="e.g. Production Prometheus"
                                style={{ width:"100%", padding:"7px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, boxSizing:"border-box" }} />
                            </div>
                            <div>
                              <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:4 }}>Protocol</div>
                              <select value={feedForm.protocol} onChange={e=>setFeedForm(f=>({...f,protocol:e.target.value}))}
                                style={{ width:"100%", padding:"7px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, boxSizing:"border-box" }}>
                                {[['prometheus-scrape','Prometheus Scrape'],['influxdb','InfluxDB LP'],['prometheus','Prometheus Push'],['statsd','StatsD'],['graphite','Graphite'],['webhook','Webhook'],['spreadsheet','Spreadsheet']].map(([p,lbl])=>(
                                  <option key={p} value={p}>{lbl}</option>
                                ))}
                              </select>
                            </div>
                            {isScrape && (
                              <div style={{ display:"flex", gap:12 }}>
                                <div style={{ flex:1 }}>
                                  <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:4 }}>Scrape interval</div>
                                  <select value={feedForm.scrapeInterval} onChange={e=>setFeedForm(f=>({...f,scrapeInterval:e.target.value}))}
                                    style={{ width:"100%", padding:"7px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, boxSizing:"border-box" }}>
                                    {[['15','15 seconds'],['30','30 seconds'],['60','1 minute'],['120','2 minutes'],['300','5 minutes']].map(([v,lbl])=>(
                                      <option key={v} value={v}>{lbl}</option>
                                    ))}
                                  </select>
                                </div>
                                <div style={{ flex:1 }}>
                                  <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:4 }}>Timeout</div>
                                  <select value={feedForm.scrapeTimeout} onChange={e=>setFeedForm(f=>({...f,scrapeTimeout:e.target.value}))}
                                    style={{ width:"100%", padding:"7px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, boxSizing:"border-box" }}>
                                    {[['5','5 seconds'],['10','10 seconds'],['15','15 seconds'],['30','30 seconds']].map(([v,lbl])=>(
                                      <option key={v} value={v}>{lbl}</option>
                                    ))}
                                  </select>
                                </div>
                              </div>
                            )}
                            <div>
                              <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:4 }}>Notes (optional)</div>
                              <textarea value={feedForm.notes} onChange={e=>setFeedForm(f=>({...f,notes:e.target.value}))}
                                rows={2} placeholder="e.g. Server fleet Prometheus exporter"
                                style={{ width:"100%", padding:"7px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, resize:"vertical", boxSizing:"border-box" }} />
                            </div>
                            <div style={{ background:"#f8fafc", border:"0.5px solid #e2e5ea", borderRadius:6, padding:"10px 12px" }}>
                              <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:8 }}>Is this feed for a system already monitored in OP1?</div>
                              <div style={{ display:"flex", gap:20, marginBottom: feedIsNewSystem ? 12 : 0 }}>
                                <label style={{ display:"flex", alignItems:"center", gap:6, fontSize:12, cursor:"pointer" }}>
                                  <input type="radio" name="feedSystemType" checked={!feedIsNewSystem} onChange={()=>setFeedIsNewSystem(false)} />
                                  Yes — map to existing monitors
                                </label>
                                <label style={{ display:"flex", alignItems:"center", gap:6, fontSize:12, cursor:"pointer" }}>
                                  <input type="radio" name="feedSystemType" checked={feedIsNewSystem} onChange={()=>setFeedIsNewSystem(true)} />
                                  No — this is a new system
                                </label>
                              </div>
                              {feedIsNewSystem && (
                                <div style={{ display:"flex", flexDirection:"column", gap:8 }}>
                                  <div>
                                    <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:4 }}>Group</div>
                                    <select value={feedTargetGroupId==='__new__'?'__new__':String(feedTargetGroupId||'')}
                                      onChange={e=>{ if(e.target.value==='__new__'){setFeedTargetGroupId('__new__');}else{setFeedTargetGroupId(e.target.value?Number(e.target.value):null);setFeedNewGroupName('');} }}
                                      style={{ width:"100%", padding:"6px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, boxSizing:"border-box" }}>
                                      <option value="">Select group…</option>
                                      {exportGroups.map(g=>(<option key={g.GroupID} value={g.GroupID}>{g.GroupName}</option>))}
                                      <option value="__new__">＋ Create new group</option>
                                    </select>
                                    {feedTargetGroupId==='__new__' && (
                                      <input value={feedNewGroupName} onChange={e=>setFeedNewGroupName(e.target.value)}
                                        placeholder="New group name…"
                                        style={{ marginTop:6, width:"100%", padding:"6px 10px", border:"1px solid #006D8C", borderRadius:6, fontSize:12, boxSizing:"border-box" }} />
                                    )}
                                  </div>
                                  <div>
                                    <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:4 }}>System description <span style={{ fontWeight:400, color:"#94a3b8" }}>(optional)</span></div>
                                    <input value={feedSystemDescription} onChange={e=>setFeedSystemDescription(e.target.value)}
                                      placeholder="e.g. Production Kubernetes cluster, IoT sensor array"
                                      style={{ width:"100%", padding:"6px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, boxSizing:"border-box" }} />
                                    <div style={{ fontSize:10, color:"#94a3b8", marginTop:3 }}>Helps AI suggest appropriate monitor types</div>
                                  </div>
                                </div>
                              )}
                            </div>
                            <div style={{ display:"flex", justifyContent:"flex-end" }}>
                              <button onClick={()=>{
                                setFeedWizardStep(2);
                                if (isScrape && credentialsList.length===0) api("GET","/credentials").then(r=>{if(Array.isArray(r))setCredentialsList(r);}).catch(()=>{});
                                if (monitorsForMapping.length===0) api("GET","/monitors").then(r=>{if(Array.isArray(r))setMonitorsForMapping(r);}).catch(()=>{});
                              }} disabled={!feedForm.feedName.trim()}
                                style={{ padding:"8px 20px", background:feedForm.feedName.trim()?"#006D8C":"#94a3b8", color:"#fff", border:"none", borderRadius:6, fontSize:12, fontWeight:600, cursor:feedForm.feedName.trim()?"pointer":"not-allowed" }}>
                                Next →
                              </button>
                            </div>
                          </div>
                        )}

                        {/* Step 2 — Scrape targets (prometheus-scrape) */}
                        {feedWizardStep === 2 && isScrape && (
                          <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
                            <div style={{ background:"#f8fafc", border:"0.5px solid #e2e5ea", borderRadius:6, padding:"8px 12px", display:"flex", alignItems:"center", gap:8, fontSize:12 }}>
                              <span style={{ fontWeight:600 }}>{feedForm.feedName}</span>
                              <span style={{ color:"#fff", background:feedProtocolColors['prometheus-scrape'], borderRadius:4, padding:"1px 7px", fontSize:11, fontWeight:600 }}>Prometheus Scrape</span>
                              <span style={{ color:"#94a3b8" }}>every {feedForm.scrapeInterval}s</span>
                              <button onClick={()=>setFeedWizardStep(1)} style={{ marginLeft:"auto", background:"none", border:"0.5px solid #cbd5e1", borderRadius:4, padding:"2px 8px", fontSize:11, color:"#006D8C", cursor:"pointer" }}>Edit</button>
                            </div>
                            {monitorsForMapping.filter(m=>m.Host||m.MonitorURL).length > 0 && (
                              <div>
                                <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:6 }}>Known hosts (from monitors)</div>
                                <div style={{ display:"flex", flexWrap:"wrap", gap:6 }}>
                                  {monitorsForMapping.filter(m=>m.Host||m.MonitorURL).slice(0,20).map(m=>(
                                    <button key={m.MonitorID} onClick={()=>{ const h=m.Host||m.MonitorURL||''; setScrapeTargetUrl(h.startsWith('http')?h:'http://'+h+'/metrics'); }}
                                      style={{ padding:"3px 10px", background:"#f1f5f9", color:"#374151", border:"0.5px solid #e2e5ea", borderRadius:20, fontSize:11, cursor:"pointer" }}>
                                      {m.MonitorName}
                                    </button>
                                  ))}
                                </div>
                              </div>
                            )}
                            <div style={{ background:"#f8fafc", border:"0.5px solid #e2e5ea", borderRadius:8, padding:12 }}>
                              <div style={{ fontSize:11, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.06em", marginBottom:10 }}>Add scrape target</div>
                              <div style={{ display:"flex", gap:8, flexWrap:"wrap", marginBottom:8 }}>
                                <input value={scrapeTargetUrl} onChange={e=>setScrapeTargetUrl(e.target.value)}
                                  placeholder="http://host:9090/metrics"
                                  style={{ flex:1, minWidth:200, padding:"7px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, boxSizing:"border-box" }} />
                                <select value={scrapeTargetCredId} onChange={e=>setScrapeTargetCredId(e.target.value)}
                                  style={{ padding:"7px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, minWidth:140 }}>
                                  <option value="">No auth</option>
                                  {credentialsList.map(cr=>(<option key={cr.CredentialID} value={cr.CredentialID}>{cr.CredentialName}</option>))}
                                </select>
                                <button onClick={async()=>{
                                  setScrapeTestLoading(true); setScrapeTestResult(null);
                                  try { const r=await api("POST","/ingest/feeds/targets/test",{ScrapeUrl:scrapeTargetUrl,CredentialID:scrapeTargetCredId?parseInt(scrapeTargetCredId):null,ReturnSample:true}); setScrapeTestResult(r); }
                                  catch(e){ setScrapeTestResult({Success:false,Error:e.message}); }
                                  finally { setScrapeTestLoading(false); }
                                }} disabled={!scrapeTargetUrl.trim()||scrapeTestLoading}
                                  style={{ padding:"7px 14px", background:(!scrapeTargetUrl.trim()||scrapeTestLoading)?"#94a3b8":"#374151", color:"#fff", border:"none", borderRadius:6, fontSize:12, fontWeight:600, cursor:(!scrapeTargetUrl.trim()||scrapeTestLoading)?"not-allowed":"pointer" }}>
                                  {scrapeTestLoading?"Testing…":"Test"}
                                </button>
                                <button onClick={()=>{
                                  if (!scrapeTargetUrl.trim()) return;
                                  setScrapeTargets(prev=>[...prev,{url:scrapeTargetUrl.trim(),credId:scrapeTargetCredId||null,tested:!!scrapeTestResult,testOk:!!(scrapeTestResult&&scrapeTestResult.Success),sampleMetrics:scrapeTestResult&&scrapeTestResult.SampleMetrics?scrapeTestResult.SampleMetrics:[]}]);
                                  setScrapeTargetUrl(''); setScrapeTargetCredId(''); setScrapeTestResult(null);
                                }} disabled={!scrapeTargetUrl.trim()}
                                  style={{ padding:"7px 14px", background:scrapeTargetUrl.trim()?"#006D8C":"#94a3b8", color:"#fff", border:"none", borderRadius:6, fontSize:12, fontWeight:600, cursor:scrapeTargetUrl.trim()?"pointer":"not-allowed" }}>
                                  Add
                                </button>
                              </div>
                              {scrapeTestResult && (
                                <div style={{ fontSize:11, color:scrapeTestResult.Success?"#008C6F":"#D95C5C", fontWeight:600 }}>
                                  {scrapeTestResult.Success?`✓ ${scrapeTestResult.MetricCount} metrics · ${scrapeTestResult.DurationMs}ms`:`✗ ${scrapeTestResult.Error}`}
                                </div>
                              )}
                            </div>
                            {scrapeTargets.length > 0 && (
                              <div style={{ border:"0.5px solid #e2e5ea", borderRadius:8, overflow:"hidden" }}>
                                {scrapeTargets.map((t, ti) => (
                                  <div key={ti} style={{ display:"flex", alignItems:"center", gap:8, padding:"8px 12px", borderBottom:ti<scrapeTargets.length-1?"0.5px solid #f1f5f9":"none", background:ti%2===0?"#fff":"#fafafa" }}>
                                    <span style={{ width:7, height:7, borderRadius:"50%", background:t.testOk?"#008C6F":t.tested?"#E89A2E":"#9CA3AF", flexShrink:0 }} />
                                    <span style={{ flex:1, fontSize:12, fontFamily:"monospace", color:"#1e293b" }}>{t.url}</span>
                                    {t.credId && <span style={{ fontSize:10, color:"#94a3b8" }}>auth</span>}
                                    <button onClick={()=>setScrapeTargets(prev=>prev.filter((_,i)=>i!==ti))}
                                      style={{ padding:"2px 8px", background:"transparent", color:"#D95C5C", border:"1px solid #D95C5C", borderRadius:4, fontSize:11, cursor:"pointer" }}>×</button>
                                  </div>
                                ))}
                              </div>
                            )}
                            <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center" }}>
                              <button onClick={()=>setFeedWizardStep(1)} style={{ padding:"8px 14px", background:"#fff", color:"#64748b", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, cursor:"pointer" }}>← Back</button>
                              <button onClick={()=>setFeedWizardStep(3)} disabled={scrapeTargets.length===0}
                                style={{ padding:"8px 20px", background:scrapeTargets.length>0?"#006D8C":"#94a3b8", color:"#fff", border:"none", borderRadius:6, fontSize:12, fontWeight:600, cursor:scrapeTargets.length>0?"pointer":"not-allowed" }}>
                                Review & map →
                              </button>
                            </div>
                          </div>
                        )}

                        {/* Step 2 — Sample data (non-scrape) */}
                        {feedWizardStep === 2 && !isScrape && (
                          <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
                            <div style={{ background:"#f8fafc", border:"0.5px solid #e2e5ea", borderRadius:6, padding:"8px 12px", display:"flex", alignItems:"center", gap:8, fontSize:12 }}>
                              <span style={{ fontWeight:600 }}>{feedForm.feedName}</span>
                              <span style={{ color:"#fff", background:feedProtocolColors[feedForm.protocol]||"#64748b", borderRadius:4, padding:"1px 7px", fontSize:11, fontWeight:600 }}>{feedProtocolLabel[feedForm.protocol]}</span>
                              <button onClick={()=>setFeedWizardStep(1)} style={{ marginLeft:"auto", background:"none", border:"0.5px solid #cbd5e1", borderRadius:4, padding:"2px 8px", fontSize:11, color:"#006D8C", cursor:"pointer" }}>Edit</button>
                            </div>
                            <div style={{ display:"flex", gap:6 }}>
                              {[['file','Upload file'],['json','Paste JSON']].map(([m,lbl])=>(
                                <button key={m} onClick={()=>setFeedSampleMode(m)}
                                  style={{ padding:"6px 14px", border:`1px solid ${feedSampleMode===m?"#006D8C":"#e2e5ea"}`, background:feedSampleMode===m?"#006D8C":"#fff", color:feedSampleMode===m?"#fff":"#64748b", borderRadius:6, fontSize:12, fontWeight:feedSampleMode===m?600:400, cursor:"pointer" }}>
                                  {lbl}
                                </button>
                              ))}
                            </div>
                            {feedSampleMode === 'file' && (
                              <div style={{ border:"1.5px dashed #cbd5e1", borderRadius:8, padding:"16px", textAlign:"center", background:"#f8fafc" }}>
                                <input type="file" accept=".xlsx,.json" onChange={e=>setFeedSampleFile(e.target.files[0]||null)} style={{ display:"block", margin:"0 auto", fontSize:12 }} />
                                {feedSampleFile && <div style={{ marginTop:8, fontSize:12, color:"#006D8C", fontWeight:600 }}>Selected: {feedSampleFile.name} ({(feedSampleFile.size/1024).toFixed(1)} KB)</div>}
                              </div>
                            )}
                            {feedSampleMode === 'json' && (
                              <textarea value={feedSampleJson} onChange={e=>setFeedSampleJson(e.target.value)}
                                rows={10} placeholder={'[ {"metric_name": "cpu.usage", "value": 0.72}, ... ]'}
                                style={{ width:"100%", padding:"8px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:11, fontFamily:"monospace", resize:"vertical", boxSizing:"border-box" }} />
                            )}
                            <div style={{ fontSize:11, color:"#64748b", lineHeight:1.5, background:"#f0f9ff", borderRadius:6, padding:"8px 12px" }}>
                              Upload 10–50 rows of real or representative ingest data. Haiku will review the sample alongside your existing monitors and suggest metric mapping patterns.
                            </div>
                            <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center" }}>
                              <button onClick={()=>setFeedWizardStep(1)} style={{ padding:"8px 14px", background:"#fff", color:"#64748b", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, cursor:"pointer" }}>← Back</button>
                              <button onClick={handleFeedReview}
                                disabled={feedReviewLoading||(feedSampleMode==='file'&&!feedSampleFile)||(feedSampleMode==='json'&&!feedSampleJson.trim())}
                                style={{ padding:"8px 20px", background:(feedReviewLoading||(feedSampleMode==='file'&&!feedSampleFile)||(feedSampleMode==='json'&&!feedSampleJson.trim()))?"#94a3b8":"#006D8C", color:"#fff", border:"none", borderRadius:6, fontSize:12, fontWeight:600, cursor:feedReviewLoading?"wait":"pointer" }}>
                                {feedReviewLoading?"Reviewing…":"Review with Haiku ✦"}
                              </button>
                            </div>
                          </div>
                        )}

                        {/* Step 3 — Auto setup (prometheus-scrape) */}
                        {feedWizardStep === 3 && isScrape && (
                          <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
                            {feedReviewLoading ? (
                              <div style={{ display:"flex", flexDirection:"column", alignItems:"center", gap:12, padding:"24px 0" }}>
                                <div style={{ width:32, height:32, border:"3px solid #e2e5ea", borderTopColor:"#006D8C", borderRadius:"50%", animation:"spin 0.8s linear infinite" }} />
                                <div style={{ fontSize:13, color:"#64748b" }}>Creating feed and running Haiku review…</div>
                              </div>
                            ) : feedReview ? (
                              <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
                                <div style={{ background:"#f8fafc", border:"0.5px solid #e2e5ea", borderRadius:6, padding:"8px 12px", display:"flex", alignItems:"center", gap:8, fontSize:12 }}>
                                  <span style={{ fontWeight:600 }}>{feedForm.feedName}</span>
                                  <span style={{ color:"#fff", background:feedProtocolColors['prometheus-scrape'], borderRadius:4, padding:"1px 7px", fontSize:11, fontWeight:600 }}>Prometheus Scrape</span>
                                  <span style={{ color:"#94a3b8" }}>{scrapeTargets.length} target{scrapeTargets.length!==1?'s':''} created</span>
                                </div>
                                <div style={{ background:"#f0f9ff", border:"0.5px solid #bae6fd", borderRadius:8, padding:"12px 14px" }}>
                                  <div style={{ display:"flex", alignItems:"center", gap:8, marginBottom:8 }}>
                                    <span style={{ fontSize:11, fontWeight:700, color:"#006D8C", background:"#e0f2fe", borderRadius:4, padding:"2px 8px" }}>✦ AI</span>
                                    <span style={{ fontSize:12, fontWeight:600, color:"#1e293b" }}>Haiku review — {scrapeTargets.length} target{scrapeTargets.length!==1?'s':''} scraped</span>
                                  </div>
                                  <div style={{ fontSize:12, color:"#334155", lineHeight:1.5, marginBottom:10 }}>{feedReview.HaikuSummary}</div>
                                  <div style={{ display:"flex", gap:6, flexWrap:"wrap" }}>
                                    {[[feedReview.HighConfidenceCount,'high confidence',"#008C6F","#d1fae5"],[feedReview.MediumConfidenceCount,'medium confidence',"#B45309","#fef3c7"],[feedReview.UnresolvedCount,'unresolved',"#D95C5C","#fee2e2"],[feedReview.TotalMetrics,'total metrics',"#006D8C","#e0f2fe"]].map(([n,lbl,fg,bg])=>(
                                      <span key={lbl} style={{ fontSize:11, fontWeight:600, color:fg, background:bg, borderRadius:4, padding:"2px 10px" }}>{n} {lbl}</span>
                                    ))}
                                  </div>
                                </div>
                                {feedMappings.length > 0 && (
                                  <div style={{ border:"0.5px solid #e2e5ea", borderRadius:8, overflow:"hidden" }}>
                                    <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr 90px 56px", background:"#f8fafc", padding:"6px 10px", fontSize:10, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.05em", gap:8 }}>
                                      <div>Metric pattern</div><div>Suggested monitor</div><div>Confidence</div><div>Include</div>
                                    </div>
                                    {feedMappings.map((m, mi) => {
                                      const pct = m.ConfidenceScore;
                                      const barColor = pct>=80?"#008C6F":pct>=50?"#E89A2E":"#D95C5C";
                                      return (
                                        <div key={mi} style={{ display:"flex", flexDirection:"column", borderTop:"0.5px solid #f1f5f9", padding:"8px 10px", background:mi%2===0?"#fff":"#fafafa" }}>
                                          <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr 90px 56px", gap:8, alignItems:"center" }}>
                                            <div style={{ fontSize:11, fontFamily:"monospace", color:"#1e293b", wordBreak:"break-all" }}>{m.MetricNamePattern}</div>
                                            <div style={{ fontSize:11, color:"#334155" }}>
                                              {(m.Status==='unresolved'||!m.MonitorID)?(
                                                <select value={m.overrideMonitorId||''} onChange={e=>{ const val=e.target.value; if(val==='__new__'){setFeedMappings(ms=>ms.map((x,xi)=>xi===mi?{...x,overrideMonitorId:null,newMonitorName:'new'}:x));}else{const selMon=monitorsForMapping.find(mon=>String(mon.MonitorID)===val);setFeedMappings(ms=>ms.map((x,xi)=>xi===mi?{...x,overrideMonitorId:val?Number(val):null,newMonitorName:'',MonitorName:selMon?selMon.MonitorName:''}:x));} }}
                                                  style={{ width:"100%", padding:"4px 6px", border:"1px solid #e2e5ea", borderRadius:4, fontSize:11 }}>
                                                  <option value="">Assign monitor…</option>
                                                  {monitorsForMapping.map(mon=>(<option key={mon.MonitorID} value={mon.MonitorID}>{mon.MonitorName}</option>))}
                                                  <option value="__new__">+ Create new monitor</option>
                                                </select>
                                              ):(
                                                <span style={{ fontSize:11 }}>{m.MonitorName||`Monitor #${m.MonitorID}`}</span>
                                              )}
                                            </div>
                                            <div style={{ display:"flex", alignItems:"center", gap:4 }}>
                                              <div style={{ flex:1, height:6, background:"#e2e5ea", borderRadius:3, overflow:"hidden" }}><div style={{ height:"100%", width:pct+"%", background:barColor, borderRadius:3 }} /></div>
                                              <span style={{ fontSize:10, color:barColor, fontWeight:700, minWidth:26 }}>{pct}%</span>
                                            </div>
                                            <div style={{ textAlign:"center" }}><input type="checkbox" checked={!!m.included} onChange={e=>setFeedMappings(ms=>ms.map((x,xi)=>xi===mi?{...x,included:e.target.checked}:x))} /></div>
                                          </div>
                                          {(m.newMonitorName!==''&&(m.overrideMonitorId===null||m.newMonitorName==='new'))&&(<div style={{ marginTop:6 }}><input value={m.newMonitorName==='new'?'':m.newMonitorName} onChange={e=>setFeedMappings(ms=>ms.map((x,xi)=>xi===mi?{...x,newMonitorName:e.target.value}:x))} placeholder="New monitor name…" style={{ width:"100%", padding:"5px 8px", border:"1px solid #e2e5ea", borderRadius:4, fontSize:11, boxSizing:"border-box" }} /></div>)}
                                          {m.Reasoning&&<div style={{ fontSize:10, color:"#94a3b8", marginTop:4, fontStyle:"italic" }}>{m.Reasoning}</div>}
                                        </div>
                                      );
                                    })}
                                  </div>
                                )}
                                <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center" }}>
                                  <span style={{ fontSize:11, color:"#64748b" }}>{feedMappings.length>0?`${feedMappings.filter(m=>m.included).length} of ${feedMappings.length} mappings`:'No mappings to configure'}</span>
                                  <button onClick={handleFeedConfirm} disabled={feedConfirmLoading}
                                    style={{ padding:"8px 20px", background:feedConfirmLoading?"#94a3b8":"#008C6F", color:"#fff", border:"none", borderRadius:6, fontSize:12, fontWeight:600, cursor:feedConfirmLoading?"wait":"pointer" }}>
                                    {feedConfirmLoading?"Saving…":"Activate feed →"}
                                  </button>
                                </div>
                              </div>
                            ) : (
                              <div style={{ fontSize:12, color:"#D95C5C", padding:"8px 0" }}>Setup failed. <button onClick={()=>setFeedWizardStep(2)} style={{ background:"none", border:"none", color:"#006D8C", cursor:"pointer", fontSize:12 }}>← Go back</button></div>
                            )}
                          </div>
                        )}

                        {/* Step 3 — Confirm mappings (non-scrape) */}
                        {feedWizardStep === 3 && !isScrape && feedReview && (
                          <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
                            <div style={{ background:"#f8fafc", border:"0.5px solid #e2e5ea", borderRadius:6, padding:"8px 12px", display:"flex", alignItems:"center", gap:8, fontSize:12 }}>
                              <span style={{ fontWeight:600 }}>{feedForm.feedName}</span>
                              <span style={{ color:"#fff", background:feedProtocolColors[feedForm.protocol]||"#64748b", borderRadius:4, padding:"1px 7px", fontSize:11, fontWeight:600 }}>{feedProtocolLabel[feedForm.protocol]}</span>
                            </div>
                            {feedIsNewSystem && (
                              <div style={{ background:"#f0f9ff", border:"0.5px solid #bae6fd", borderRadius:6, padding:"8px 12px", fontSize:12, color:"#334155" }}>
                                <span style={{ fontWeight:700, color:"#006D8C" }}>New system</span>
                                {(feedNewGroupName||(feedTargetGroupId&&feedTargetGroupId!=='__new__')) && (
                                  <span> · <span style={{ fontWeight:600 }}>{feedNewGroupName || (exportGroups.find(g=>g.GroupID===Number(feedTargetGroupId))?.GroupName||'Group #'+feedTargetGroupId)}</span></span>
                                )}
                                {feedSystemDescription && <span> · {feedSystemDescription}</span>}
                                <div style={{ fontSize:11, color:"#006D8C", marginTop:3 }}>
                                  {feedNewGroupName ? `New monitors will be created in group "${feedNewGroupName}" when you confirm.` : 'New monitors will be created when you confirm.'}
                                </div>
                              </div>
                            )}
                            <div style={{ background:"#f0f9ff", border:"0.5px solid #bae6fd", borderRadius:8, padding:"12px 14px" }}>
                              <div style={{ display:"flex", alignItems:"center", gap:8, marginBottom:8 }}>
                                <span style={{ fontSize:11, fontWeight:700, color:"#006D8C", background:"#e0f2fe", borderRadius:4, padding:"2px 8px" }}>✦ AI</span>
                                <span style={{ fontSize:12, fontWeight:600, color:"#1e293b" }}>Haiku review — {feedSampleFile ? feedSampleFile.name : 'JSON sample'}</span>
                              </div>
                              <div style={{ fontSize:12, color:"#334155", lineHeight:1.5, marginBottom:10 }}>{feedReview.HaikuSummary}</div>
                              <div style={{ display:"flex", gap:6, flexWrap:"wrap" }}>
                                {[[feedReview.HighConfidenceCount,'high confidence',"#008C6F","#d1fae5"],[feedReview.MediumConfidenceCount,'medium confidence',"#B45309","#fef3c7"],[feedReview.UnresolvedCount,'unresolved',"#D95C5C","#fee2e2"],[feedReview.TotalMetrics,'total metrics',"#006D8C","#e0f2fe"]].map(([n,lbl,fg,bg])=>(
                                  <span key={lbl} style={{ fontSize:11, fontWeight:600, color:fg, background:bg, borderRadius:4, padding:"2px 10px" }}>{n} {lbl}</span>
                                ))}
                              </div>
                            </div>
                            <div style={{ border:"0.5px solid #e2e5ea", borderRadius:8, overflow:"hidden" }}>
                              <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr 90px 56px", background:"#f8fafc", padding:"6px 10px", fontSize:10, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.05em", gap:8 }}>
                                <div>Metric pattern</div><div>Suggested monitor</div><div>Confidence</div><div>Include</div>
                              </div>
                              {feedMappings.map((m, mi) => {
                                const pct = m.ConfidenceScore;
                                const barColor = pct>=80?"#008C6F":pct>=50?"#E89A2E":"#D95C5C";
                                return (
                                  <div key={mi} style={{ display:"flex", flexDirection:"column", borderTop:"0.5px solid #f1f5f9", padding:"8px 10px", background:mi%2===0?"#fff":"#fafafa" }}>
                                    <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr 90px 56px", gap:8, alignItems:"center" }}>
                                      <div style={{ fontSize:11, fontFamily:"monospace", color:"#1e293b", wordBreak:"break-all" }}>{m.MetricNamePattern}</div>
                                      <div style={{ fontSize:11, color:"#334155" }}>
                                        {feedIsNewSystem && !m.MonitorID ? (
                                          <div style={{ display:"flex", alignItems:"center", gap:6 }}>
                                            <input value={m.newMonitorName} onChange={e=>setFeedMappings(ms=>ms.map((x,xi)=>xi===mi?{...x,newMonitorName:e.target.value}:x))}
                                              placeholder="Monitor name…"
                                              style={{ flex:1, padding:"3px 7px", border:"1px solid #e2e5ea", borderRadius:4, fontSize:11 }} />
                                            {m.MonitorSubType && <span style={{ fontSize:9, fontWeight:700, color:"#fff", background:"#64748b", borderRadius:3, padding:"1px 5px", flexShrink:0, whiteSpace:"nowrap" }}>{m.MonitorSubType}</span>}
                                          </div>
                                        ) : (m.Status==='unresolved'||!m.MonitorID) ? (
                                          <select value={m.overrideMonitorId||''} onChange={e=>{ const val=e.target.value; if(val==='__new__'){setFeedMappings(ms=>ms.map((x,xi)=>xi===mi?{...x,overrideMonitorId:null,newMonitorName:'new'}:x));}else{const selMon=monitorsForMapping.find(mon=>String(mon.MonitorID)===val);setFeedMappings(ms=>ms.map((x,xi)=>xi===mi?{...x,overrideMonitorId:val?Number(val):null,newMonitorName:'',MonitorName:selMon?selMon.MonitorName:''}:x));} }}
                                            style={{ width:"100%", padding:"4px 6px", border:"1px solid #e2e5ea", borderRadius:4, fontSize:11 }}>
                                            <option value="">Assign monitor…</option>
                                            {monitorsForMapping.map(mon=>(<option key={mon.MonitorID} value={mon.MonitorID}>{mon.MonitorName}</option>))}
                                            <option value="__new__">+ Create new monitor</option>
                                          </select>
                                        ) : (
                                          <span style={{ fontSize:11 }}>{m.MonitorName||`Monitor #${m.MonitorID}`}</span>
                                        )}
                                      </div>
                                      <div style={{ display:"flex", alignItems:"center", gap:4 }}>
                                        <div style={{ flex:1, height:6, background:"#e2e5ea", borderRadius:3, overflow:"hidden" }}><div style={{ height:"100%", width:pct+"%", background:barColor, borderRadius:3 }} /></div>
                                        <span style={{ fontSize:10, color:barColor, fontWeight:700, minWidth:26 }}>{pct}%</span>
                                      </div>
                                      <div style={{ textAlign:"center" }}><input type="checkbox" checked={!!m.included} onChange={e=>setFeedMappings(ms=>ms.map((x,xi)=>xi===mi?{...x,included:e.target.checked}:x))} /></div>
                                    </div>
                                    {(m.newMonitorName!==''&&(m.overrideMonitorId===null||m.newMonitorName==='new'))&&(<div style={{ marginTop:6 }}><input value={m.newMonitorName==='new'?'':m.newMonitorName} onChange={e=>setFeedMappings(ms=>ms.map((x,xi)=>xi===mi?{...x,newMonitorName:e.target.value}:x))} placeholder="New monitor name…" style={{ width:"100%", padding:"5px 8px", border:"1px solid #e2e5ea", borderRadius:4, fontSize:11, boxSizing:"border-box" }} /></div>)}
                                    {m.Reasoning&&<div style={{ fontSize:10, color:"#94a3b8", marginTop:4, fontStyle:"italic" }}>{m.Reasoning}</div>}
                                  </div>
                                );
                              })}
                            </div>
                            <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center" }}>
                              <button onClick={()=>{ setFeedWizardStep(2); setFeedReview(null); }} style={{ padding:"8px 14px", background:"#fff", color:"#64748b", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, cursor:"pointer" }}>← Back</button>
                              <div style={{ display:"flex", alignItems:"center", gap:10 }}>
                                <span style={{ fontSize:11, color:"#64748b" }}>{feedMappings.filter(m=>m.included).length} of {feedMappings.length} mappings ready</span>
                                <button onClick={handleFeedConfirm} disabled={feedConfirmLoading||feedMappings.filter(m=>m.included).length===0}
                                  style={{ padding:"8px 20px", background:(feedConfirmLoading||feedMappings.filter(m=>m.included).length===0)?"#94a3b8":"#008C6F", color:"#fff", border:"none", borderRadius:6, fontSize:12, fontWeight:600, cursor:feedConfirmLoading?"wait":"pointer" }}>
                                  {feedConfirmLoading?"Saving…":"Confirm mappings →"}
                                </button>
                              </div>
                            </div>
                          </div>
                        )}

                        {/* Step 4 — Success */}
                        {feedWizardStep === 4 && feedConfirmResult && (
                          <div style={{ display:"flex", flexDirection:"column", gap:14, alignItems:"center", padding:"8px 0" }}>
                            <div style={{ fontSize:32, color:"#008C6F" }}>✓</div>
                            <div style={{ fontSize:15, fontWeight:700, color:"#1e293b" }}>Feed configured successfully</div>
                            <div style={{ fontSize:13, color:"#334155", textAlign:"center" }}>
                              {isScrape
                                ? `${scrapeTargets.length} target${scrapeTargets.length!==1?'s':''} scheduled · scrape every ${feedForm.scrapeInterval}s${feedConfirmResult.created>0?` · ${feedConfirmResult.created} mapping${feedConfirmResult.created!==1?'s':''} configured`:''}`
                                : `${feedConfirmResult.created} mapping${feedConfirmResult.created!==1?"s":""} written to InboundMetricMappings.`}
                            </div>
                            <div style={{ background:"#f0f9ff", border:"0.5px solid #bae6fd", borderRadius:8, padding:"10px 16px", width:"100%", boxSizing:"border-box", fontSize:12, color:"#334155", lineHeight:1.6 }}>
                              {isScrape
                                ? <span>Scraped metrics will appear in <strong>Metric Mappings → Unresolved</strong> as they arrive.</span>
                                : <span>Your feed is ready. Point your <strong>{feedProtocolLabel[feedForm.protocol]}</strong> source to <code style={{ background:"#e0f2fe", borderRadius:3, padding:"1px 5px" }}>/api/ingest/{feedForm.protocol}</code> with your API key.</span>}
                            </div>
                            <button onClick={resetFeedWizard} style={{ padding:"8px 28px", background:"#006D8C", color:"#fff", border:"none", borderRadius:6, fontSize:13, fontWeight:600, cursor:"pointer" }}>Done</button>
                          </div>
                        )}

                      </div>
                    </div>
                  )}
                </div>
              );
            })()}

            {/* Import panel */}
            {configPackTab==="import" && (
              <div style={{ display:"flex", flexDirection:"column", gap:16, maxWidth:720 }}>
                {!importCommitResult ? (
                  <div style={{ display:"flex", flexDirection:"column", gap:16 }}>
                    <div style={{ background:"#fff", border:"0.5px solid #e2e5ea", borderRadius:8, padding:16 }}>
                      <div style={{ fontSize:10, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.06em", marginBottom:14 }}>Import configuration</div>

                      {/* File input */}
                      <div style={{ marginBottom:14 }}>
                        <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:6 }}>Select file</div>
                        <div style={{ border:"1.5px dashed #cbd5e1", borderRadius:8, padding:"20px 16px", textAlign:"center", background:"#f8fafc" }}>
                          <input type="file" accept=".xlsx,.json" onChange={handleFileSelect}
                            style={{ display:"block", margin:"0 auto", fontSize:12 }} />
                          {importFile && (
                            <div style={{ marginTop:8, fontSize:12, color:c.blue, fontWeight:600 }}>
                              Selected: {importFile.name} ({(importFile.size/1024).toFixed(1)} KB)
                            </div>
                          )}
                        </div>
                      </div>

                      {/* Group filter */}
                      <div style={{ marginBottom:14 }}>
                        <div style={{ fontSize:11, fontWeight:600, color:"#4A4A4A", marginBottom:4 }}>Group filter (optional)</div>
                        <input type="text" placeholder="e.g. Servers, Databases (leave blank for all)"
                          value={importFilterGroups.join(',')}
                          onChange={e=>setImportFilterGroups(e.target.value ? e.target.value.split(',').map(s=>s.trim()).filter(Boolean) : [])}
                          style={{ width:"100%", padding:"7px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, background:"#fff", color:"#1e293b", outline:"none", boxSizing:"border-box" }}
                        />
                        <div style={{ fontSize:10, color:"#94a3b8", marginTop:3 }}>
                          {importFilterGroups.length > 0 ? `Filtering to: ${importFilterGroups.join(', ')}` : 'Importing all groups'}
                        </div>
                      </div>

                      {/* Review button */}
                      <button onClick={handleReview} disabled={!importFile||importReviewLoading}
                        style={{ padding:"8px 20px", background:!importFile||importReviewLoading?"#94a3b8":c.blue, color:"#fff", border:"none", borderRadius:6, fontSize:13, fontWeight:600, cursor:!importFile||importReviewLoading?"not-allowed":"pointer" }}>
                        {importReviewLoading ? "Reviewing…" : "Review with Haiku"}
                      </button>
                    </div>

                    {/* Haiku review result */}
                    {importReview && (
                      <div style={{ background:"#fff", border:"0.5px solid #e2e5ea", borderRadius:8, overflow:"hidden" }}>
                        <div style={{ background:"#0e7490", padding:"10px 16px", display:"flex", alignItems:"center", gap:10 }}>
                          <span style={{ background:"rgba(255,255,255,0.15)", border:"1px solid rgba(255,255,255,0.3)", borderRadius:4, padding:"1px 6px", fontSize:9, fontWeight:700, color:"#fff", letterSpacing:"0.06em" }}>AI</span>
                          <span style={{ fontSize:13, fontWeight:600, color:"#fff" }}>Haiku review — {importReview.FileName}</span>
                        </div>
                        <div style={{ padding:16 }}>
                          <div style={{ fontSize:12, color:"#1e293b", marginBottom:14, lineHeight:1.5 }}>{importReview.HaikuSummary}</div>

                          {/* Stats */}
                          <div style={{ display:"flex", gap:10, marginBottom:14, flexWrap:"wrap" }}>
                            {[
                              ["Ready",    importReview.ReadyCount,    c.green,   "#f0fdf4"],
                              ["Warning",  importReview.WarningCount,  c.amber,   "#fffbeb"],
                              ["Conflict", importReview.ConflictCount, c.red,     "#fef2f2"],
                              ["Total",    importReview.TotalRows,     "#1e293b", "#f8fafc"],
                            ].map(([lbl,cnt,clr,bg]) => (
                              <div key={lbl} style={{ background:bg, border:`1px solid ${clr==="#1e293b"?"#e2e5ea":clr}`, borderRadius:6, padding:"6px 14px", textAlign:"center", minWidth:64 }}>
                                <div style={{ fontSize:16, fontWeight:700, color:clr }}>{cnt}</div>
                                <div style={{ fontSize:9, fontWeight:600, color:clr==="#1e293b"?"#94a3b8":clr, textTransform:"uppercase", letterSpacing:"0.06em" }}>{lbl}</div>
                              </div>
                            ))}
                          </div>

                          {/* Groups to create */}
                          {importReview.GroupsToCreate && importReview.GroupsToCreate.length > 0 && (
                            <div style={{ background:"#fffbeb", border:`1px solid ${c.amber}`, borderRadius:6, padding:"8px 12px", marginBottom:14, fontSize:12, color:"#92400e" }}>
                              <span style={{ fontWeight:600 }}>Groups to create: </span>
                              {importReview.GroupsToCreate.join(', ')}
                            </div>
                          )}

                          {/* Row table */}
                          <div style={{ border:"0.5px solid #e2e5ea", borderRadius:6, overflow:"hidden", marginBottom:14 }}>
                            <table style={{ width:"100%", borderCollapse:"collapse", fontSize:12 }}>
                              <thead>
                                <tr style={{ background:"#f8fafc", borderBottom:"0.5px solid #e2e5ea" }}>
                                  {["#","Monitor","Type","Group","Status","Issue"].map(h=>(
                                    <th key={h} style={{ padding:"7px 10px", textAlign:"left", fontSize:9, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.05em" }}>{h}</th>
                                  ))}
                                </tr>
                              </thead>
                              <tbody>
                                {importReview.Rows.slice(0,50).map(row => {
                                  const stColor = row.Status===0 ? c.green : row.Status===1 ? c.amber : c.red;
                                  const stBg    = row.Status===0 ? "#f0fdf4" : row.Status===1 ? "#fffbeb" : "#fef2f2";
                                  const stLbl   = row.Status===0 ? "Ready" : row.Status===1 ? "Warning" : "Conflict";
                                  return (
                                    <tr key={row.RowNumber} style={{ borderBottom:"0.5px solid #f1f5f9" }}>
                                      <td style={{ padding:"7px 10px", color:"#94a3b8" }}>{row.RowNumber}</td>
                                      <td style={{ padding:"7px 10px", fontWeight:600, color:"#1e293b", maxWidth:180, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{row.MonitorName}</td>
                                      <td style={{ padding:"7px 10px", color:"#64748b" }}>{row.MonitorType}</td>
                                      <td style={{ padding:"7px 10px", color:"#64748b" }}>{row.GroupName||'—'}</td>
                                      <td style={{ padding:"7px 10px" }}>
                                        <span style={{ background:stBg, color:stColor, border:`1px solid ${stColor}`, borderRadius:4, padding:"2px 7px", fontSize:10, fontWeight:600, whiteSpace:"nowrap" }}>{stLbl}</span>
                                      </td>
                                      <td style={{ padding:"7px 10px", fontSize:11, color:"#64748b", maxWidth:220, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{row.Issue||''}</td>
                                    </tr>
                                  );
                                })}
                              </tbody>
                            </table>
                            {importReview.Rows.length > 50 && (
                              <div style={{ padding:"8px 12px", fontSize:11, color:"#94a3b8", background:"#f8fafc", borderTop:"0.5px solid #e2e5ea" }}>
                                Showing 50 of {importReview.Rows.length} rows
                              </div>
                            )}
                          </div>

                          {/* Conflict resolution */}
                          <div style={{ display:"flex", alignItems:"center", gap:10, marginBottom:14 }}>
                            <span style={{ fontSize:12, color:"#4A4A4A" }}>On conflict:</span>
                            <select value={conflictResolution} onChange={e=>setConflictResolution(e.target.value)}
                              style={{ padding:"5px 10px", border:"1px solid #e2e5ea", borderRadius:6, fontSize:12, background:"#fff", color:"#1e293b", outline:"none" }}>
                              <option value="skip">Skip (keep existing)</option>
                              <option value="overwrite">Overwrite existing</option>
                              <option value="suffix">Add date suffix</option>
                            </select>
                          </div>

                          {/* Action buttons */}
                          <div style={{ display:"flex", gap:8, flexWrap:"wrap" }}>
                            <button onClick={()=>handleCommit(true)}
                              disabled={importCommitting||importReview.ReadyCount===0}
                              style={{ padding:"8px 18px", background:importCommitting||importReview.ReadyCount===0?"#94a3b8":c.green, color:"#fff", border:"none", borderRadius:6, fontSize:13, fontWeight:600, cursor:importCommitting||importReview.ReadyCount===0?"not-allowed":"pointer" }}>
                              {importCommitting ? "Importing…" : `Import ${importReview.ReadyCount} ready row${importReview.ReadyCount!==1?'s':''}`}
                            </button>
                            {(importReview.WarningCount > 0 || (conflictResolution === 'overwrite' && importReview.ConflictCount > 0)) && (
                              <button onClick={()=>handleCommit(false)} disabled={importCommitting}
                                style={{ padding:"8px 18px", background:importCommitting?"#94a3b8":c.amber, color:"#fff", border:"none", borderRadius:6, fontSize:13, fontWeight:600, cursor:importCommitting?"not-allowed":"pointer" }}>
                                {conflictResolution === 'overwrite' && importReview.ConflictCount > 0
                                  ? `Overwrite ${importReview.ConflictCount} conflict${importReview.ConflictCount!==1?'s':''} + import all`
                                  : "Import all non-conflict rows"}
                              </button>
                            )}
                            <button onClick={()=>{ setImportReview(null); setImportFile(null); }}
                              style={{ padding:"8px 18px", background:"#fff", color:"#64748b", border:"1px solid #e2e5ea", borderRadius:6, fontSize:13, fontWeight:500, cursor:"pointer" }}>
                              Cancel
                            </button>
                          </div>
                        </div>
                      </div>
                    )}
                  </div>
                ) : (
                  <div style={{ background:"#fff", border:"0.5px solid #e2e5ea", borderRadius:8, padding:16 }}>
                    <div style={{ background:"#f0fdf4", border:`1px solid ${c.green}`, borderRadius:6, padding:"12px 16px", marginBottom:14 }}>
                      <div style={{ fontSize:13, fontWeight:600, color:c.green, marginBottom:4 }}>Import complete</div>
                      <div style={{ fontSize:12, color:"#1e293b" }}>
                        {importCommitResult.Created} created · {importCommitResult.Skipped} skipped · {importCommitResult.Overwritten} overwritten
                      </div>
                    </div>
                    {importCommitResult.Errors && importCommitResult.Errors.length > 0 && (
                      <div style={{ background:"#fffbeb", border:`1px solid ${c.amber}`, borderRadius:6, padding:"10px 14px", marginBottom:14 }}>
                        <div style={{ fontSize:11, fontWeight:700, color:"#92400e", marginBottom:6 }}>Errors ({importCommitResult.Errors.length})</div>
                        {importCommitResult.Errors.map((e,i)=>(
                          <div key={i} style={{ fontSize:11, color:"#92400e", lineHeight:1.5 }}>{e}</div>
                        ))}
                      </div>
                    )}
                    <button onClick={()=>setImportCommitResult(null)}
                      style={{ padding:"8px 20px", background:c.blue, color:"#fff", border:"none", borderRadius:6, fontSize:13, fontWeight:600, cursor:"pointer" }}>
                      Done
                    </button>
                  </div>
                )}
              </div>
            )}
          </div>
        )}

        {/* ── System Health tab ── */}
        {configTab==="systemhealth" && (
          <div style={{ display:"flex", flexDirection:"column", gap:16 }}>

            {/* Region A — Probes */}
            <div style={{ background:"#fff", border:"0.5px solid #e2e5ea", borderRadius:8, overflow:"hidden" }}>
              <div style={{ padding:"12px 16px", borderBottom:"0.5px solid #e2e5ea", display:"flex", alignItems:"center", justifyContent:"space-between" }}>
                <div>
                  <div style={{ fontSize:13, fontWeight:600, color:"#1e293b" }}>Platform Probes</div>
                  <div style={{ fontSize:11, color:"#94a3b8", marginTop:2 }}>Diagnostic checks run every 5 minutes</div>
                </div>
                <button onClick={doShProbesRefresh} disabled={shProbesLoading}
                  style={{ fontSize:11, padding:"5px 12px", background:shProbesLoading?"#f1f5f9":"#fff", border:"1px solid #e2e5ea", borderRadius:6, cursor:shProbesLoading?"not-allowed":"pointer", color:"#64748b" }}>
                  {shProbesLoading ? "Refreshing…" : shProbesLastRefresh ? `Refreshed ${shRelTime(shProbesLastRefresh)}` : "Refresh"}
                </button>
              </div>
              {shProbesLoading && shProbes===null ? (
                <div style={{ padding:"24px 16px", textAlign:"center", color:"#94a3b8", fontSize:12 }}>Loading probes…</div>
              ) : !shProbes ? (
                <div style={{ padding:"24px 16px", textAlign:"center", color:"#94a3b8", fontSize:12 }}>No probe data available.</div>
              ) : (()=>{
                const shCats = ["Infrastructure","Database","Monitoring","Application"];
                const shByCat = shCats.reduce((acc,cat)=>{ acc[cat]=shProbes.filter(p=>p.Category===cat); return acc; },{});
                return (
                  <div style={{ padding:16, display:"flex", flexDirection:"column", gap:12 }}>
                    {shCats.map(cat => shByCat[cat].length===0 ? null : (
                      <div key={cat}>
                        <div style={{ fontSize:9, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.08em", marginBottom:6 }}>{cat}</div>
                        <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fill,minmax(200px,1fr))", gap:8 }}>
                          {shByCat[cat].map(p=>{
                            const pSt=(p.Status||"").toLowerCase();
                            const pPillBg=pSt==="healthy"?"#f0fdf4":pSt==="warning"?"#fffbeb":pSt==="critical"?"#fef2f2":"#f1f5f9";
                            const pPillFg=pSt==="healthy"?c.green:pSt==="warning"?c.amber:pSt==="critical"?c.red:"#64748b";
                            return (
                              <div key={p.Id} style={{ background:"#f8fafc", border:"0.5px solid #e2e5ea", borderRadius:6, padding:"10px 12px" }}>
                                <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom:4 }}>
                                  <div style={{ fontSize:12, fontWeight:600, color:"#1e293b" }}>{p.Label}</div>
                                  <span style={{ fontSize:10, fontWeight:700, color:pPillFg, background:pPillBg, padding:"2px 8px", borderRadius:10 }}>{p.Status||"Unknown"}</span>
                                </div>
                                <div style={{ fontSize:10, color:"#94a3b8", fontFamily:"monospace" }}>{p.Id}</div>
                                {p.Value && (
                                  <div style={{ fontSize:11, color:"#64748b", marginTop:4 }}>{p.Value}</div>
                                )}
                                {p.Detail && pSt!=="healthy" && (
                                  <div style={{ fontSize:10, color:pPillFg, marginTop:4, lineHeight:1.4 }}>{p.Detail}</div>
                                )}
                              </div>
                            );
                          })}
                        </div>
                      </div>
                    ))}
                  </div>
                );
              })()}
            </div>

            {/* Region B — Incidents */}
            <div style={{ background:"#fff", border:"0.5px solid #e2e5ea", borderRadius:8, overflow:"hidden" }}>
              <div style={{ padding:"12px 16px", borderBottom:"0.5px solid #e2e5ea", display:"flex", alignItems:"center", justifyContent:"space-between", gap:8, flexWrap:"wrap" }}>
                <div style={{ fontSize:13, fontWeight:600, color:"#1e293b" }}>System Incidents</div>
                <div style={{ display:"flex", gap:8, alignItems:"center", flexWrap:"wrap" }}>
                  <div style={{ display:"flex", border:"0.5px solid #e2e5ea", borderRadius:6, overflow:"hidden" }}>
                    {[{v:true,l:"Active"},{v:false,l:"All"}].map(o=>(
                      <button key={String(o.v)} onClick={()=>setShFilterActive(o.v)}
                        style={{ padding:"4px 10px", fontSize:11, border:"none", cursor:"pointer", background:shFilterActive===o.v?c.blue:"#fff", color:shFilterActive===o.v?"#fff":"#64748b", fontWeight:shFilterActive===o.v?600:400 }}>
                        {o.l}
                      </button>
                    ))}
                  </div>
                  <select value={shFilterSeverity} onChange={e=>setShFilterSeverity(e.target.value)}
                    style={{ fontSize:11, padding:"4px 8px", border:"0.5px solid #e2e5ea", borderRadius:6, background:"#fff", color:"#1e293b", outline:"none" }}>
                    <option value="">All severities</option>
                    <option value="critical">Critical</option>
                    <option value="warning">Warning</option>
                    <option value="info">Info</option>
                  </select>
                  {shSources.length > 0 && (
                    <select value={shFilterSource} onChange={e=>setShFilterSource(e.target.value)}
                      style={{ fontSize:11, padding:"4px 8px", border:"0.5px solid #e2e5ea", borderRadius:6, background:"#fff", color:"#1e293b", outline:"none" }}>
                      <option value="">All sources</option>
                      {shSources.map(s=><option key={s} value={s}>{s}</option>)}
                    </select>
                  )}
                  <input value={shFilterSearch} onChange={e=>setShFilterSearch(e.target.value)}
                    placeholder="Search…"
                    style={{ fontSize:11, padding:"4px 10px", border:"0.5px solid #e2e5ea", borderRadius:6, background:"#fff", color:"#1e293b", outline:"none", width:140 }} />
                </div>
              </div>
              {(()=>{
                const shDsp = shFilterSearch
                  ? (shIncidents||[]).filter(i=>{
                      const q=shFilterSearch.toLowerCase();
                      return (i.Message||"").toLowerCase().includes(q)||(i.Source||"").toLowerCase().includes(q)||(i.IncidentType||"").toLowerCase().includes(q);
                    })
                  : (shIncidents||[]);
                return shIncidentsLoading && shIncidents===null ? (
                  <div style={{ padding:"24px 16px", textAlign:"center", color:"#94a3b8", fontSize:12 }}>Loading incidents…</div>
                ) : !shIncidents || shDsp.length===0 ? (
                  <div style={{ padding:"24px 16px", textAlign:"center", color:"#94a3b8", fontSize:12 }}>
                    {shIncidents===null ? "No incidents loaded." : `No${shFilterActive?" active":""} incidents${shFilterSeverity?" ("+shFilterSeverity+")":""}${shFilterSearch?" matching \""+shFilterSearch+"\"":""}.`}
                  </div>
                ) : (
                  <div>
                    <div style={{ padding:"6px 16px", fontSize:10, color:"#94a3b8", borderBottom:"0.5px solid #e2e5ea" }}>{shDsp.length} incident{shDsp.length!==1?"s":""}</div>
                    <table style={{ width:"100%", borderCollapse:"collapse", fontSize:12 }}>
                      <thead>
                        <tr style={{ background:"#f8fafc", borderBottom:"0.5px solid #e2e5ea" }}>
                          {["Severity","Source","Type","First Seen","Count","Status","Message",""].map(h=>(
                            <th key={h} style={{ padding:"7px 10px", textAlign:"left", fontSize:9, fontWeight:700, color:"#94a3b8", textTransform:"uppercase", letterSpacing:"0.05em" }}>{h}</th>
                          ))}
                        </tr>
                      </thead>
                      <tbody>
                        {shDsp.map(inc=>{
                          const iSev=(inc.Severity||"").toLowerCase();
                          const iSevBg=iSev==="critical"?"#fef2f2":iSev==="warning"?"#fffbeb":"#f0fdf4";
                          const iSevFg=iSev==="critical"?c.red:iSev==="warning"?c.amber:c.green;
                          const iSt=inc.IsActive?(inc.AcknowledgedAt?"acked":"open"):"resolved";
                          const iStColor=iSt==="open"?c.red:iSt==="acked"?c.amber:"#64748b";
                          return (
                            <tr key={inc.IncidentID} onClick={()=>setShIncidentModal(inc)}
                              style={{ borderBottom:"0.5px solid #f1f5f9", cursor:"pointer" }}
                              onMouseEnter={e=>e.currentTarget.style.background="#f8fafc"}
                              onMouseLeave={e=>e.currentTarget.style.background=""}>
                              <td style={{ padding:"7px 10px" }}>
                                <span style={{ fontSize:10, fontWeight:700, color:iSevFg, background:iSevBg, padding:"2px 7px", borderRadius:10 }}>{inc.Severity||"—"}</span>
                              </td>
                              <td style={{ padding:"7px 10px", color:"#1e293b", fontSize:11 }}>{inc.Source||"—"}</td>
                              <td style={{ padding:"7px 10px", color:"#64748b", fontSize:10, fontFamily:"monospace" }}>{inc.IncidentType||"—"}</td>
                              <td style={{ padding:"7px 10px", color:"#64748b", fontSize:11, whiteSpace:"nowrap" }}>{inc.FirstOccurredAt?shRelTime(parseUTC(inc.FirstOccurredAt)):"—"}</td>
                              <td style={{ padding:"7px 10px", color:"#1e293b", fontSize:12, fontWeight:600 }}>{inc.OccurrenceCount||1}</td>
                              <td style={{ padding:"7px 10px" }}><span style={{ fontSize:10, color:iStColor, fontWeight:600 }}>{iSt}</span></td>
                              <td style={{ padding:"7px 10px", color:"#64748b", fontSize:11, maxWidth:260, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{inc.Message||"—"}</td>
                              <td style={{ padding:"7px 10px", textAlign:"right", whiteSpace:"nowrap" }}>
                                {inc.IsActive && !inc.AcknowledgedAt && (
                                  <button onClick={e=>{ e.stopPropagation(); doShAck(inc.IncidentID); }}
                                    style={{ fontSize:10, padding:"3px 9px", border:"1px solid #e2e5ea", borderRadius:5, background:"#fff", cursor:"pointer", color:"#64748b", marginRight:4 }}>Ack</button>
                                )}
                                {inc.IsActive && (
                                  <button onClick={e=>{ e.stopPropagation(); doShResolve(inc.IncidentID); }}
                                    style={{ fontSize:10, padding:"3px 9px", border:"none", borderRadius:5, background:c.green, color:"#fff", cursor:"pointer", fontWeight:600 }}>Resolve</button>
                                )}
                              </td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                );
              })()}
            </div>

            {/* Region C — Anthropic API telemetry */}
            <div style={{ background:"#fff", border:"0.5px solid #e2e5ea", borderRadius:8, padding:"16px" }}>
              <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom:4 }}>
                <div style={{ fontSize:13, fontWeight:600, color:"#1e293b" }}>Anthropic API integration</div>
                <button onClick={loadShAnthropic} disabled={shAnthropicLoading} style={{ fontSize:10, color:"#64748b", background:"none", border:"none", cursor:"pointer", padding:"2px 6px" }}>
                  {shAnthropicLoading ? "Loading…" : "↻ Refresh"}
                </button>
              </div>
              <div style={{ fontSize:11, color:"#64748b", marginBottom:12 }}>Health of the Claude/Haiku integration used by investigation and analyze flows.</div>
              <div style={{ display:"grid", gridTemplateColumns:"repeat(4,1fr)", gap:10 }}>
                {(()=>{
                  const fmt = (n) => n == null ? "—" : n.toLocaleString();
                  const lastCall = shAnthropic?.lastSuccessfulCall
                    ? new Date(shAnthropic.lastSuccessfulCall).toLocaleString()
                    : (shAnthropicLoading ? "…" : "—");
                  const errCount = shAnthropic?.errors24h ?? null;
                  const cards = [
                    ["Last successful call", lastCall, "#1e293b", false],
                    ["Calls (24h)",          fmt(shAnthropic?.calls24h),  "#1e293b", false],
                    ["Tokens (24h)",         fmt(shAnthropic?.tokens24h), "#1e293b", false],
                    ["Errors (24h)",         fmt(errCount), errCount > 0 ? "#D95C5C" : "#008C6F", errCount > 0],
                  ];
                  return cards.map(([lbl, val, color, bold])=>(
                    <div key={lbl} style={{ background:"#f8fafc", border:"0.5px solid #e2e5ea", borderRadius:6, padding:"10px 12px" }}>
                      <div style={{ fontSize:10, color:"#94a3b8", marginBottom:4 }}>{lbl}</div>
                      <div style={{ fontSize:lbl==="Last successful call"?11:18, fontWeight:bold?700:600, color:shAnthropicLoading?"#cbd5e1":color }}>{val}</div>
                    </div>
                  ));
                })()}
              </div>
            </div>

          </div>
        )}
      </div>

      {/* ── News ticker ── */}
      <div style={{ height:28, background:"#1e2b3c", borderTop:"0.5px solid rgba(255,255,255,0.07)", overflow:"hidden", display:"flex", alignItems:"center", flexShrink:0 }}>
        <div style={{ paddingLeft:10, paddingRight:10, borderRight:"0.5px solid rgba(255,255,255,0.15)", flexShrink:0, height:"100%", display:"flex", alignItems:"center" }}>
          <span style={{ fontSize:9, color:"rgba(255,255,255,0.4)", textTransform:"uppercase", letterSpacing:"0.08em" }}>&#9679; LIVE</span>
        </div>
        {recentAlerts.length > 0 ? (
          <div style={{ display:"inline-flex", animation:`op1-ticker ${TICKER_DURATION_SEC}s linear infinite`, whiteSpace:"nowrap" }}>
            {[...recentAlerts, ...recentAlerts].map((item, i) => (
              <span key={i} style={{ padding:"0 24px", fontSize:11, color:"rgba(255,255,255,0.85)", borderRight:"1px solid rgba(255,255,255,0.1)", display:"inline-flex", alignItems:"center", gap:5 }}>
                <span style={{ color:(item.Status||"").toLowerCase()==="critical"?"#ef4444":(item.Status||"").toLowerCase()==="warning"?"#f59e0b":"#22c55e", fontSize:8 }}>&#9679;</span>
                {(item.Status||"").toUpperCase()} &middot; {item.MonitorName}{item.Message?` \u00b7 ${item.Message}`:""}
                {item.CreatedAt && <span style={{ color:"rgba(255,255,255,0.4)", fontSize:10, marginLeft:4 }}>{parseUTC(item.CreatedAt)?.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}</span>}
              </span>
            ))}
          </div>
        ) : (
          <span style={{ fontSize:11, color:"rgba(255,255,255,0.35)", paddingLeft:16, letterSpacing:"0.04em" }}>No recent alerts</span>
        )}
      </div>

      {shIncidentModal && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.75)', zIndex:1300, display:'flex', alignItems:'center', justifyContent:'center' }}
          onClick={e=>{ if(e.target===e.currentTarget) setShIncidentModal(null); }}>
          <div style={{ background:'#fff', borderRadius:8, width:540, maxWidth:'90vw', maxHeight:'80vh', overflowY:'auto', boxShadow:'0 8px 32px rgba(0,0,0,0.18)' }}>
            <div style={{ padding:'16px 20px', borderBottom:'0.5px solid #e2e5ea', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
              <div style={{ fontSize:14, fontWeight:700, color:'#1e293b' }}>Incident #{shIncidentModal.IncidentID}</div>
              <button onClick={()=>setShIncidentModal(null)}
                style={{ background:'none', border:'none', cursor:'pointer', fontSize:18, color:'#94a3b8', lineHeight:1 }}>&times;</button>
            </div>
            <div style={{ padding:'16px 20px', display:'flex', flexDirection:'column', gap:10 }}>
              {[
                ["Source",     shIncidentModal.Source||"—"],
                ["Type",       shIncidentModal.IncidentType||"—"],
                ["Severity",   shIncidentModal.Severity||"—"],
                ["First Seen", shIncidentModal.FirstOccurredAt ? parseUTC(shIncidentModal.FirstOccurredAt)?.toLocaleString() : "—"],
                ["Last Seen",  shIncidentModal.LastOccurredAt  ? parseUTC(shIncidentModal.LastOccurredAt)?.toLocaleString()  : "—"],
                ["Count",      shIncidentModal.OccurrenceCount||1],
                ["Status",     shIncidentModal.IsActive?(shIncidentModal.AcknowledgedAt?"Acknowledged":"Open"):"Resolved"],
              ].map(([label,val])=>(
                <div key={label} style={{ display:'flex', gap:8 }}>
                  <div style={{ width:110, flexShrink:0, fontSize:11, fontWeight:700, color:'#94a3b8', textTransform:'uppercase', letterSpacing:'0.05em', paddingTop:1 }}>{label}</div>
                  <div style={{ fontSize:12, color:'#1e293b', flex:1 }}>{val}</div>
                </div>
              ))}
              {shIncidentModal.Message && (
                <div style={{ display:'flex', gap:8 }}>
                  <div style={{ width:110, flexShrink:0, fontSize:11, fontWeight:700, color:'#94a3b8', textTransform:'uppercase', letterSpacing:'0.05em', paddingTop:1 }}>Message</div>
                  <div style={{ fontSize:12, color:'#1e293b', flex:1, lineHeight:1.5 }}>{shIncidentModal.Message}</div>
                </div>
              )}
              {shIncidentModal.ResolutionNote && (
                <div style={{ display:'flex', gap:8 }}>
                  <div style={{ width:110, flexShrink:0, fontSize:11, fontWeight:700, color:'#94a3b8', textTransform:'uppercase', letterSpacing:'0.05em', paddingTop:1 }}>Resolution</div>
                  <div style={{ fontSize:12, color:'#64748b', flex:1, lineHeight:1.5, fontStyle:'italic' }}>{shIncidentModal.ResolutionNote}</div>
                </div>
              )}
            </div>
            {shIncidentModal.IsActive && (
              <div style={{ padding:'12px 20px', borderTop:'0.5px solid #e2e5ea', display:'flex', justifyContent:'flex-end', gap:8 }}>
                {!shIncidentModal.AcknowledgedAt && (
                  <button onClick={()=>{ doShAck(shIncidentModal.IncidentID); setShIncidentModal(null); }}
                    style={{ fontSize:12, padding:'6px 16px', border:'1px solid #e2e5ea', borderRadius:6, background:'#fff', color:'#64748b', cursor:'pointer' }}>Acknowledge</button>
                )}
                <button onClick={()=>{ doShResolve(shIncidentModal.IncidentID); setShIncidentModal(null); }}
                  style={{ fontSize:12, padding:'6px 16px', border:'none', borderRadius:6, background:c.green, color:'#fff', cursor:'pointer', fontWeight:600 }}>Resolve</button>
              </div>
            )}
          </div>
        </div>
      )}

      {confirmModal && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.75)', zIndex:1300, display:'flex', alignItems:'center', justifyContent:'center' }}
          onClick={e => { if(e.target===e.currentTarget) setConfirmModal(null); }}>
          <div style={{ background:'#fff', borderRadius:8, width:380, maxWidth:'90vw', padding:'24px', boxShadow:'0 8px 32px rgba(0,0,0,0.18)' }}>
            <div style={{ fontSize:13, color:'#1A1A1A', marginBottom:20, lineHeight:1.5 }}>{confirmModal.msg}</div>
            <div style={{ display:'flex', justifyContent:'flex-end', gap:8 }}>
              <button onClick={()=>setConfirmModal(null)}
                style={{ fontSize:12, padding:'6px 16px', border:'1px solid #006D8C', borderRadius:6, background:'#fff', color:'#006D8C', cursor:'pointer' }}>Cancel</button>
              <button onClick={()=>{ confirmModal.onOk(); setConfirmModal(null); }}
                style={{ fontSize:12, padding:'6px 16px', border:'none', borderRadius:6, background:'#D95C5C', color:'#fff', cursor:'pointer', fontWeight:600 }}>{confirmModal.okLabel || 'Confirm'}</button>
            </div>
          </div>
        </div>
      )}

    </div>
  );
}

// ─── Machine Management Section ─────────────────────────────────────────────
function MachineManagementSection({ api, machines, currentMachine, onRefresh, setErr, setOk }) {
  const [summaries, setSummaries] = useState([]);
  const [loading, setLoading]     = useState(true);
  const [aliases, setAliases]     = useState({});
  const [deleteConfirm, setDeleteConfirm] = useState(null); // machineName
  const [deleteInput, setDeleteInput]     = useState("");
  const [busy, setBusy]           = useState({});
  const [pauseReasons, setPauseReasons]   = useState({});

  const load = useCallback(()=>{
    setLoading(true);
    api("GET","/config/machine-summary")
      .then(r=>{ setSummaries(Array.isArray(r)?r:[]); setLoading(false); })
      .catch(()=>setLoading(false));
  },[api]);

  useEffect(()=>{ load(); },[load]);

  const saveAlias = async (machineName) => {
    setBusy(b=>({...b,[machineName+"_alias"]:true}));
    try {
      await api("POST","/config/monitoring-control/alias",{ MachineName:machineName, Alias: aliases[machineName]||"" });
      setOk("Alias saved."); load(); onRefresh && onRefresh();
    } catch(e){ setErr(e.message); }
    finally { setBusy(b=>({...b,[machineName+"_alias"]:false})); }
  };

  const toggleMachine = async (machineName, isActive) => {
    setBusy(b=>({...b,[machineName+"_toggle"]:true}));
    try {
      await api("POST","/config/monitoring-control/toggle",{
        MachineName: machineName, IsActive: !isActive,
        Reason: isActive ? (pauseReasons[machineName]||"Admin pause") : null,
      });
      setOk(isActive?"Monitoring paused.":"Monitoring resumed."); load(); onRefresh && onRefresh();
    } catch(e){ setErr(e.message); }
    finally { setBusy(b=>({...b,[machineName+"_toggle"]:false})); }
  };

  const deleteMachine = async () => {
    if (!deleteConfirm || deleteInput !== "DELETE") return;
    setBusy(b=>({...b,[deleteConfirm+"_del"]:true}));
    try {
      await api("DELETE",`/config/machine/${encodeURIComponent(deleteConfirm)}`);
      setOk(`Machine '${deleteConfirm}' deleted.`); setDeleteConfirm(null); setDeleteInput(""); load(); onRefresh && onRefresh();
    } catch(e){ setErr(e.message); }
    finally { setBusy(b=>({...b,[deleteConfirm+"_del"]:false})); }
  };

  return (
    <Card>
      <SectionHead>Source Monitor Registry</SectionHead>
      <p style={{ fontSize:12, color:c.textDim, marginBottom:16 }}>
        Each OP1 instance registers itself here. Machines can be paused to stop monitoring without stopping the service.
      </p>
      {loading ? <Spinner /> : summaries.length===0 ? <div style={{ color:c.textDimmer, fontSize:12 }}>No machines registered.</div> : (
        <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
          {summaries.map(s => {
            const isCurrent = s.MachineName === currentMachine;
            const aliasVal = aliases[s.MachineName] ?? s.MachineAlias ?? "";
            return (
              <div key={s.MachineName} style={{ border:`1px solid ${c.border}`, borderRadius:8, padding:16, background: isCurrent ? "rgba(0,109,140,0.04)" : c.surface, borderLeft: isCurrent ? `3px solid ${c.blue}` : `3px solid ${c.border}` }}>
                <div style={{ display:"flex", alignItems:"flex-start", gap:12, flexWrap:"wrap" }}>
                  <div style={{ flex:1, minWidth:200 }}>
                    <div style={{ display:"flex", alignItems:"center", gap:8, marginBottom:4 }}>
                      <span style={{ fontFamily:"mono", fontSize:13, fontWeight:700, color:c.text }}>{s.MachineName}</span>
                      {isCurrent && <Badge color={c.blue}>this machine</Badge>}
                      {s.IsActive ? <Badge color={c.green}>Active</Badge> : <Badge color={c.yellow}>Paused</Badge>}
                    </div>
                    {s.MachineAlias && <div style={{ fontSize:11, color:c.textDim, marginBottom:6 }}>Alias: {s.MachineAlias}</div>}
                    <div style={{ display:"flex", gap:16, flexWrap:"wrap", fontSize:11, color:c.textDimmer }}>
                      <span>{s.MonitorCount} monitor{s.MonitorCount!==1?"s":""}</span>
                      <span>{s.ChecksLast24h} checks last 24h</span>
                      {s.LastCheckAt && <span>Last check: {parseUTC(s.LastCheckAt)?.toLocaleString()}</span>}
                    </div>
                    {!s.IsActive && s.PauseReason && <div style={{ fontSize:11, color:c.amber, marginTop:4 }}>Pause reason: {s.PauseReason}</div>}
                    {!s.IsActive && s.PausedAt && <div style={{ fontSize:10, color:c.textDimmer }}>Paused: {parseUTC(s.PausedAt)?.toLocaleString()}</div>}
                  </div>
                  <div style={{ display:"flex", gap:8, alignItems:"center", flexWrap:"wrap" }}>
                    <div style={{ display:"flex", gap:4, alignItems:"center" }}>
                      <input value={aliasVal} onChange={e=>setAliases(a=>({...a,[s.MachineName]:e.target.value}))}
                        placeholder="Set alias…"
                        style={{ width:130, padding:"4px 8px", border:`1px solid ${c.border}`, borderRadius:4, fontSize:11, fontFamily:"mono", background:c.surface, color:c.text }} />
                      <Btn variant="secondary" loading={busy[s.MachineName+"_alias"]} onClick={()=>saveAlias(s.MachineName)} style={{ fontSize:11, padding:"4px 10px" }}>Save</Btn>
                    </div>
                    {s.IsActive ? (
                      <div style={{ display:"flex", gap:4, alignItems:"center" }}>
                        <input value={pauseReasons[s.MachineName]||""} onChange={e=>setPauseReasons(r=>({...r,[s.MachineName]:e.target.value}))}
                          placeholder="Pause reason…"
                          style={{ width:130, padding:"4px 8px", border:`1px solid ${c.border}`, borderRadius:4, fontSize:11, background:c.surface, color:c.text }} />
                        <Btn variant="warning" loading={busy[s.MachineName+"_toggle"]} onClick={()=>toggleMachine(s.MachineName, true)} style={{ fontSize:11, padding:"4px 10px" }}>Pause</Btn>
                      </div>
                    ) : (
                      <Btn variant="success" loading={busy[s.MachineName+"_toggle"]} onClick={()=>toggleMachine(s.MachineName, false)} style={{ fontSize:11, padding:"4px 10px" }}>Resume</Btn>
                    )}
                    {!isCurrent && (
                      deleteConfirm === s.MachineName ? (
                        <div style={{ display:"flex", gap:4, alignItems:"center" }}>
                          <input value={deleteInput} onChange={e=>setDeleteInput(e.target.value)}
                            placeholder='Type "DELETE"'
                            style={{ width:110, padding:"4px 8px", border:`1px solid ${c.red}`, borderRadius:4, fontSize:11, background:c.surface, color:c.red }} />
                          <Btn variant="danger" loading={busy[s.MachineName+"_del"]} onClick={deleteMachine} style={{ fontSize:11, padding:"4px 10px" }} disabled={deleteInput!=="DELETE"}>Confirm</Btn>
                          <Btn variant="ghost" onClick={()=>{ setDeleteConfirm(null); setDeleteInput(""); }} style={{ fontSize:11 }}>Cancel</Btn>
                        </div>
                      ) : (
                        <Btn variant="danger" onClick={()=>{ setDeleteConfirm(s.MachineName); setDeleteInput(""); }} style={{ fontSize:11, padding:"4px 10px" }}>Delete</Btn>
                      )
                    )}
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </Card>
  );
}
