          res.appendChild(el("div",{class:"notice warn",style:"margin-top:10px;font-size:.82rem"}, "Parse errors: " + esc(d.parse_errors.slice(0,5).join(" | "))));
      } catch (err) {
        res.innerHTML = "";
        res.appendChild(el("div",{class:"notice err"}, "Preview failed: " + esc(err.message)));
      }
    }},
      el("label",{}, "CSV or TXT file (JSON is rejected)"), file,
      el("div",{class:"btns"}, el("button",{class:"btn secondary",type:"submit"}, "Validate (preview only)")));
    openModal("Import Recipients", el("div", {},
      el("p",{class:"mut",style:"margin-top:0;font-size:.85rem"},
        "CSV must contain an <b>email</b> column (headers: email, first_name, last_name, company_name, company_phone + custom columns). TXT format: <span class='mono'>email, first, last</span> per line."),
      form, res), {
      wide: true,
      buttons: [{ label:"Commit import", kind:"btn", onClick: async (close) => {
          if (!file.files[0]) { toast("Choose a file first", "err"); return; }
          if (parsed && ((parsed.summary.invalid_recipients ?? parsed.summary.invalid ?? 0) > 0 || (parsed.summary.duplicate_recipients ?? parsed.summary.duplicates ?? 0) > 0))
            toast("Note: only valid, non-duplicate rows will be imported", "warn");
          const fd = new FormData(); fd.append("file", file.files[0]);
          fd.append("list_id", listId);
          try {
            const d = await api("/recipients/import", { method:"POST", body: fd });
            const added = d.valid_recipients ?? d.added ?? 0;
            const dup = d.duplicate_recipients ?? d.duplicates ?? 0;
            const bad = d.invalid_recipients ?? d.invalid ?? 0;
            const sup = d.suppressed_recipients ?? d.suppressed ?? 0;
            toast(`Imported ${added} recipients (${dup} dup, ${bad} invalid, ${sup} suppressed)`, "ok");
            close(); await loadLists(); if (state.cur) await loadRecs();
          } catch (err) { toast("Import failed: " + err.message, "err"); }
        }}]
    });
  }

  function manualModal(listId){
    const em = el("input", {class:"inp", type:"email", required:"required", placeholder:"name@example.com"});
    const fn = el("input", {class:"inp", placeholder:"First name"});
    const ln = el("input", {class:"inp", placeholder:"Last name"});
    const cn = el("input", {class:"inp", placeholder:"Company name"});
    const cf = el("input", {class:"inp", placeholder:'Custom fields JSON, e.g. {"Account":"ACC-991"}'});
    openModal("Add Recipient Manually", el("div", {class:"form"},
      el("label",{}, "Email"), em,
      el("label",{}, "First name"), fn,
      el("label",{}, "Last name"), ln,
      el("label",{}, "Company name"), cn,
      el("label",{}, "Custom fields (optional)"), cf), {
      buttons: [{ label:"Add", kind:"btn", onClick: async (close) => {
        let custom = {};
        try { if (cf.value.trim()) custom = JSON.parse(cf.value); } catch { toast("Custom fields must be valid JSON","err"); return; }
        const d = await POST("/recipients/manual", { list_id: listId, recipient: {
          email: em.value, first_name: fn.value, last_name: ln.value,
          company_name: cn.value, custom_fields: custom }});
        if (d.ok) { toast("Recipient added", "ok"); close(); await loadLists(); if (state.cur) await loadRecs(); }
        else {
          const s = d.summary || {};
          const why = (d.duplicates && d.duplicates[0] && d.duplicates[0].reason) ||
                      (d.invalid && d.invalid[0] && d.invalid[0].reason) ||
                      (d.suppressed && d.suppressed[0] && d.suppressed[0].reason) ||
                      (d.errors && d.errors[0]) || "rejected";
          toast(`Rejected: ${why}`, "err");
        }
      }}]
    });
