        errors.append(f"Max {cfg.MAX_GMAIL_ACCOUNTS_PER_CAMPAIGN} accounts per campaign")
    else:
        for aid in data.account_ids:
            acc = await db.get(GmailAccount, aid)
            if not acc or acc.user_id != user.id:
                errors.append(f"Gmail account {aid} not found")
            elif acc.status != "authorized" or not acc.is_active:
                errors.append(f"Account {acc.email} is not authorized/active")

    if data.attach_mode == "pdf":
        if not (data.attach_pdf or data.attach_pdf_template_id or data.attachment_id):
            errors.append("PDF attachment mode requires a template or attachment to convert")
    if data.attach_mode in ("file", "image") and not data.attachment_id:
        errors.append("File/image attachment mode requires selecting an attachment")

    if len(data.rotation_weights or {}) > 0 and data.rotation_strategy != "weighted":
        errors.append("rotation_weights only applies when rotation_strategy is weighted")

    # variable config sanity
    vc = data.variable_config or {}
    try:
---STEP5-UI---
           ${["repeat", "stop", "random"].map(m => `
             <label class="chk"><input type="radio" name="tplMode" value="${m}" ${C.template_sequence_mode === m ? "checked" : ""}>
             ${m === "repeat" ? "Repeat from start" : m === "stop" ? "Stop after last" : "Random"}</label>`).join("")}
         </div>`;
    } else if (step === 5) {
      const am = C.attach_mode;
      b.innerHTML = H("Step 5 — Attachments") + hint("Choose what to attach. PDF mode renders a template to a unique Invoice PDF per recipient.") +
        `<div class="radio-row">
           ${[["none", "No attachment"], ["pdf", "Generated PDF invoice"], ["file", "Stored file attachment"], ["image", "Image attachment"]].map(([m, t]) => `
             <label class="chk"><input type="radio" name="attMode" value="${m}" ${am === m ? "checked" : ""}> ${t}</label>`).join("")}
         </div>
         <div id="attExtra"></div>`;
      bindAttExtra();
    } else if (step === 6) {
      const vc = C.variable_config;
      b.innerHTML = H("Step 6 — Variables & random amounts") + hint("Configure the invoice number format and random amount ranges used by %RandomInvoiceNumber%, %RandomTotal% and %RandomShippingCharge%.") +
