      toast(`Campaign finished — status: ${(JSON.parse(ev.data) || {}).status || "?"}`, "info", 6000);
      drawControls();
    });
    MON.es.onerror = () => { $("#liveInd").classList.add("hidden"); };
  }
  async function drawProgress() {
    try { const p = await GET(`/campaigns/${MON.id}/progress`); paintProgress(p); }
    catch (e) { $("#monBody").innerHTML = `<div class="notice err"><span class="n-ico">✕</span><div>${esc(e.message)}</div></div>`; }
  }
  function paintProgress(p) {
    let box = $("#progBox");
    if (!box) {
      box = el("div", { id: "progBox" });
      $("#monBody").prepend(box);
    }
    const meterSegs = Math.min(p.total || 0, 400);
    const seg = (cls, n) => `<span class="${cls}" style="flex:${Math.max(n, 0)}"></span>`;
    const sum = p.sent + p.perm_failed + p.suppressed + p.skipped;
    box.innerHTML = `
      <div class="card mb-2"><div class="card-bd">
        <div class="flex-between mb-1">
          <div class="flex">
            <strong id="monName">#${p.campaign_id}</strong>
            ${stBadge(p.status)}
            <span class="small muted">${p.started_at ? "started " + fmtDT(p.started_at) : "not started"}</span>
            ${p.finished_at ? `<span class="small muted">· finished ${fmtDT(p.finished_at)}</span>` : ""}
          </div>
          <span class="small muted">${p.progress_pct}% complete</span>
        </div>
        <div class="pbar ${p.status === "completed" ? "ok" : ""}"><div style="width:${Math.min(p.progress_pct, 100)}%"></div></div>
        <div class="meter mt-2" title="sent / permanent fail / suppressed / skipped / in-flight">${meterSegs("sent", p.sent)}${meterSegs("fail", p.perm_failed)}${meterSegs("supp", p.suppressed)}${meterSegs("skip", p.skipped)}${meterSegs("proc", (p.total || 0) - sum)}</div>
        <div class="stat-grid mt-2">
          <div class="cell"><div class="v">${p.sent}</div><div class="l">Accepted & sent</div></div>
          <div class="cell"><div class="v">${p.temp_failed}</div><div class="l">Temp failed</div></div>
          <div class="cype cell"><div class="v">${p.perm_failed}</div><div class="l">Perm failed</div></div>
          <div class="cell"><div class="v">${p.suppressed}</div><div class="l">Suppressed</div></div>
          <div class="cell"><div class="v">${p.skipped}</div><div class="l">Skipped</div></div>
          <div class="cell"><div class="v">${p.pending}</div><div class="l">Pending</div></div>
          <div class="cell"><div class="v">${p.queued}</div><div class="l">Queued</div></div>
          <div class="cell"><div class="v">${p.total}</div><div class="l">Total</div></div>
        </div>
        <div class="small muted mt-1">${p.jobs_total} send jobs · delivery attempts are retried with backoff; temporary failures never masquerade as success.</div>
      </div></div>`;
    drawControls();
  }
  function drawControls() {
    const ctl = $("#monCtl");
    if (!ctl) return;
    fetch(`/campaigns/${MON.id}`).then(r => r.json()).then(c => {
      ctl.innerHTML = "";
      const mk = (label, cls, fn, confirmMsg) => {
