// dashboard-ai-service-match-phase-5.js — extracted verbatim from dashboard.js (pure move).

// ─── AI Service Match (Phase 5) ──────────────────────────────────

let serviceMatchStep = "profile";

async function renderServiceMatch() {
  showLoading("Loading Service Match…");
  const data = await api("service-match-profile-get").catch((err) => ({ error: err.message }));
  if (data?.error) {
    showError(data.error, renderServiceMatch);
    return;
  }

  const profile = data.profile;
  // Auto-advance: if no profile, start at "profile" step. If profile exists,
  // default to "companies".
  if (!profile && serviceMatchStep !== "profile") serviceMatchStep = "profile";
  if (profile && serviceMatchStep === "profile") serviceMatchStep = "companies";

  const header = el("div", { class: "page-header" }, [
    el("div", {}, [
      el("div", { class: "page-title" }, "AI Service Match"),
      el(
        "div",
        { class: "page-subtitle" },
        "Score companies by service-fit and generate phased outreach plans",
      ),
    ]),
    el(
      "button",
      { class: "btn btn-secondary btn-tiny", type: "button", onclick: renderServiceMatch },
      "↻ Refresh",
    ),
  ]);

  const tabs = el("div", { class: "tabs" }, [
    tabBtn("profile", "1. Service Profile", () => {
      serviceMatchStep = "profile";
      renderServiceMatch();
    }),
    tabBtn("companies", "2. Matched Companies", () => {
      serviceMatchStep = "companies";
      renderServiceMatch();
    }),
    tabBtn("plan", "3. Outreach Plan", () => {
      serviceMatchStep = "plan";
      renderServiceMatch();
    }),
  ]);

  setTimeout(() => {
    $$(".tab").forEach((t) =>
      t.classList.toggle("active", t.getAttribute("data-tab") === serviceMatchStep),
    );
  }, 0);

  let bodyNode;
  if (serviceMatchStep === "profile") bodyNode = renderServiceMatchProfile(profile);
  else if (serviceMatchStep === "companies") bodyNode = await renderServiceMatchCompanies(profile);
  else bodyNode = await renderServiceMatchPlan(profile);

  setContentNode(el("div", {}, [header, _discoverHubNav("service-match"), tabs, bodyNode]));
}

function renderServiceMatchProfile(profile) {
  let description = "";
  return el("div", {}, [
    profile
      ? el("div", { class: "card" }, [
          el("div", { class: "card-title" }, "Current profile"),
          profile.summary
            ? el(
                "div",
                { class: "muted", style: "font-size: 13px; margin-bottom: 12px;" },
                profile.summary,
              )
            : null,
          el("div", { class: "field-row" }, [
            el("span", { class: "field-label" }, "Categories"),
            el(
              "div",
              { class: "filter-pills" },
              (profile.matched_categories || []).map((c) =>
                el("div", { class: "filter-pill" }, [c]),
              ),
            ),
          ]),
          profile.search_keywords?.length
            ? el("div", { class: "field-row" }, [
                el("span", { class: "field-label" }, "Keywords"),
                el(
                  "div",
                  { class: "filter-pills" },
                  profile.search_keywords
                    .slice(0, 12)
                    .map((k) => el("div", { class: "filter-pill" }, [k])),
                ),
              ])
            : null,
          profile.target_roles?.length
            ? el("div", { class: "field-row" }, [
                el("span", { class: "field-label" }, "Target roles"),
                el(
                  "div",
                  { class: "filter-pills" },
                  profile.target_roles
                    .slice(0, 8)
                    .map((r) => el("div", { class: "filter-pill" }, [r])),
                ),
              ])
            : null,
          el("div", { style: "margin-top: 12px;" }, [
            el(
              "button",
              {
                class: "btn btn-primary btn-tiny",
                type: "button",
                onclick: () => {
                  serviceMatchStep = "companies";
                  renderServiceMatch();
                },
              },
              "View matched companies →",
            ),
          ]),
        ])
      : null,

    el("div", { class: "card" }, [
      el("div", { class: "card-title" }, profile ? "Update profile" : "Describe your service"),
      el(
        "div",
        { class: "muted", style: "font-size: 13px; margin-bottom: 12px;" },
        profile
          ? "Paste a new description to re-analyze. The AI will extract categories, keywords, and target roles."
          : "Tell the AI what your service does — what you sell, to whom. The richer the description, the better the matching. 200+ words is ideal.",
      ),
      el("textarea", {
        class: "wizard-textarea",
        style: "min-height: 140px;",
        placeholder:
          "e.g. We provide fractional CMO services to early-stage crypto projects. We help founders build their growth engine — content, community, paid acquisition. Our typical client is a Series A token issuer with 10–50 employees, post-TGE, who needs to scale past the early-adopter phase…",
        oninput: (e) => {
          description = e.target.value;
        },
      }),
      el("div", { style: "display: flex; gap: 8px; margin-top: 12px;" }, [
        el(
          "button",
          {
            class: "btn btn-primary",
            type: "button",
            onclick: async (ev) => {
              if (description.trim().length < 20) {
                toast("Need at least 20 characters", "err");
                return;
              }
              await withProgress(ev.currentTarget, async () => {
                const r = await api("service-match-analyze", { body: { description } });
                if (r?.error) toast(r.error, "err");
                else {
                  toast("Profile saved", "ok");
                  serviceMatchStep = "companies";
                  renderServiceMatch();
                }
              });
            },
          },
          "Analyze + save",
        ),
      ]),
    ]),
  ]);
}

async function renderServiceMatchCompanies(profile) {
  if (!profile) {
    return el("div", { class: "empty-state", style: "padding: 32px;" }, [
      el("div", { class: "empty-state-icon" }, icon("search")),
      el("div", { class: "empty-state-title" }, "Set up your service profile first"),
      el(
        "div",
        { class: "empty-state-hint" },
        "Step 1: tell the AI what you sell. Then it can find companies that need it.",
      ),
      el(
        "button",
        {
          class: "btn btn-primary",
          style: "margin-top: 12px;",
          type: "button",
          onclick: () => {
            serviceMatchStep = "profile";
            renderServiceMatch();
          },
        },
        "← Back to profile",
      ),
    ]);
  }

  const data = await api("service-match-companies", { queryString: "?limit=100" }).catch((err) => ({
    error: err.message,
  }));
  if (data?.error) return el("div", { class: "muted" }, `Error: ${data.error}`);
  const companies = data.companies || [];

  if (companies.length === 0) {
    return el("div", { class: "empty-state", style: "padding: 32px;" }, [
      el("div", { class: "empty-state-icon" }, icon("search")),
      el("div", { class: "empty-state-title" }, "No matches yet"),
      el(
        "div",
        { class: "empty-state-hint" },
        "The matcher needs companies with inferred service-needs. Run /api/icp/rescore-all from Telegram or wait for the enrichment cycle.",
      ),
    ]);
  }

  return el("div", {}, [
    el(
      "div",
      { class: "muted", style: "font-size: 12px; margin-bottom: 12px;" },
      `${companies.length} matches · ranked by service-fit confidence × funding stage × recency`,
    ),
    ...companies.slice(0, 50).map((c) => {
      const score = Math.round((c.top_confidence || 0) * 100);
      return el(
        "div",
        {
          class: "card",
          style:
            "padding: 12px; margin-bottom: 6px; cursor: pointer; display: flex; align-items: center; gap: 12px;",
          onclick: () => openServiceMatchDetail(c.id),
        },
        [
          el("div", { style: "flex: 1; min-width: 0;" }, [
            el("div", { class: "primary-cell" }, c.name || "—"),
            el(
              "div",
              { class: "muted small" },
              [c.sector, c.stage, c.total_raised ? `$${fmtNum(c.total_raised)} raised` : null]
                .filter(Boolean)
                .join(" · "),
            ),
            c.matching_needs
              ? el(
                  "div",
                  { class: "muted small", style: "margin-top: 4px;" },
                  `Needs: ${c.matching_needs}`,
                )
              : null,
          ]),
          el(
            "div",
            {
              class: "mono",
              style: `font-weight: 600; color: ${score >= 80 ? "var(--green)" : score >= 60 ? "var(--accent)" : "var(--text-3)"};`,
            },
            `${score}%`,
          ),
          el(
            "button",
            {
              class: "btn btn-tiny btn-primary",
              type: "button",
              onclick: (ev) => {
                ev.stopPropagation();
                openServiceMatchDetail(c.id);
              },
            },
            "Plan →",
          ),
        ],
      );
    }),
  ]);
}

async function openServiceMatchDetail(companyId) {
  openDrawer("Company plan", el("div", { class: "loading" }, "Building network map and plan…"));
  const [networkRes, planRes] = await Promise.all([
    api("service-match-network", { companyId }).catch(() => ({})),
    api("service-match-plan-create", { body: { companyId } }).catch(() => ({})),
  ]);

  const network = networkRes?.network || {};
  const suggestion = planRes?.suggestion || {};

  const body = el("div", { class: "drawer-body" }, [
    network.company
      ? el("div", { style: "margin-bottom: 16px;" }, [
          el("div", { style: "font-size: 16px; font-weight: 600;" }, network.company.name),
          el(
            "div",
            { class: "muted small" },
            [network.company.sector, network.company.stage].filter(Boolean).join(" · "),
          ),
        ])
      : null,

    // Network
    network.decision_makers?.length
      ? el("div", { class: "card" }, [
          el("div", { class: "card-title" }, `Decision makers (${network.decision_makers.length})`),
          ...network.decision_makers.slice(0, 8).map((p) =>
            el(
              "div",
              {
                class: "channel-row",
                style: "padding: 6px 8px; border-bottom: 1px solid var(--border);",
              },
              [
                el("div", { style: "flex: 1;" }, [
                  el(
                    "div",
                    { class: "primary-cell", style: "font-size: 12px;" },
                    p.display_name || "—",
                  ),
                  el(
                    "div",
                    { class: "muted small" },
                    [p.role, p.company].filter(Boolean).join(" @ "),
                  ),
                ]),
                p.linkedin_url
                  ? el(
                      "a",
                      {
                        href: p.linkedin_url,
                        target: "_blank",
                        class: "btn btn-tiny btn-secondary",
                      },
                      "LI",
                    )
                  : null,
              ],
            ),
          ),
        ])
      : null,

    network.engaged_audience?.length
      ? el("div", { class: "card" }, [
          el(
            "div",
            { class: "card-title" },
            `Engaged audience (${network.engaged_audience.length})`,
          ),
          el(
            "div",
            { class: "muted small" },
            "People in your network already engaging with this company.",
          ),
        ])
      : null,

    // Suggestion
    suggestion.phases?.length
      ? el("div", { class: "card" }, [
          el("div", { class: "card-title" }, "Phased outreach plan"),
          ...suggestion.phases.map((ph, i) =>
            el(
              "div",
              {
                style:
                  "padding: 10px; margin-bottom: 8px; background: var(--bg-1); border-radius: var(--radius-sm); border-left: 3px solid var(--accent);",
              },
              [
                el(
                  "div",
                  { class: "primary-cell", style: "font-size: 13px;" },
                  `Phase ${i + 1}: ${ph.name || ph.phase || "—"}`,
                ),
                ph.duration_days
                  ? el("div", { class: "muted small" }, `${ph.duration_days} days`)
                  : null,
                ph.actions?.length
                  ? el(
                      "ul",
                      { style: "margin: 6px 0 0 16px; font-size: 12px; line-height: 1.6;" },
                      ph.actions.map((a) =>
                        el(
                          "li",
                          {},
                          typeof a === "string" ? a : a.description || JSON.stringify(a),
                        ),
                      ),
                    )
                  : null,
              ],
            ),
          ),
        ])
      : el(
          "div",
          { class: "muted", style: "padding: 16px;" },
          planRes?.error || "No suggestion available.",
        ),

    // Strategy picker + Execute — defaults driven by AI's strategy field
    renderServiceMatchExecutePanel({
      companyId,
      companyName: network.company?.name,
      aiStrategy: suggestion.strategy || null,
      pitchAngle: suggestion.pitch_angle || null,
    }),

    el("div", { style: "display: flex; gap: 8px; margin-top: 12px;" }, [
      el(
        "button",
        { class: "btn btn-tiny btn-secondary", type: "button", onclick: closeDrawer },
        "Close",
      ),
    ]),
  ]);
  openDrawer(network.company?.name || "Plan", body);
}

// Renders the strategy-picker + Execute card inside the per-company drawer.
// Kept as a separate function because it has its own form state.
function renderServiceMatchExecutePanel({ companyId, companyName, aiStrategy, pitchAngle }) {
  const STRATEGY_OPTIONS = [
    {
      id: "siphon_engage",
      label: "Siphon & Engage",
      desc: "Add the company as a competitor and engage their audience (LinkedIn / X)",
    },
    {
      id: "direct_outreach",
      label: "Direct Outreach",
      desc: "DM/message the company's contacts in your CRM (multi-channel)",
    },
    {
      id: "warm_intro",
      label: "Warm Intro",
      desc: "Use existing relationships to ask for an intro",
    },
    {
      id: "community_infiltration",
      label: "Community Infiltration",
      desc: "Join their Telegram group and engage members (advanced)",
    },
  ];

  // Default selections from the AI's strategy field
  const defaultStrategies =
    {
      cold: new Set(["siphon_engage", "direct_outreach"]),
      warm_intro: new Set(["warm_intro", "direct_outreach"]),
      community_first: new Set(["community_infiltration", "direct_outreach"]),
    }[aiStrategy] || new Set(["direct_outreach"]);

  const state = {
    selected: defaultStrategies,
    customMessage: "",
  };

  const card = el("div", { class: "card" }, [
    el("div", { class: "card-title" }, "Execute now"),
    el(
      "div",
      { class: "muted small", style: "margin-bottom: 12px;" },
      "Pick which strategies to run. Each one creates real DB records (competitor entries, outreach campaigns) — the bot's background schedulers actually fire the DMs/comments.",
    ),

    // Strategy checkboxes
    ...STRATEGY_OPTIONS.map((opt) => {
      const checked = state.selected.has(opt.id);
      return el(
        "label",
        {
          style:
            "display: flex; gap: 10px; padding: 8px 6px; cursor: pointer; border-radius: var(--radius-sm); align-items: flex-start;",
        },
        [
          el("input", {
            type: "checkbox",
            checked: checked ? "checked" : null,
            style: "margin-top: 3px;",
            onchange: (e) => {
              if (e.currentTarget.checked) state.selected.add(opt.id);
              else state.selected.delete(opt.id);
            },
          }),
          el("div", { style: "flex: 1;" }, [
            el("div", { class: "primary-cell", style: "font-size: 12px;" }, opt.label),
            el("div", { class: "muted small" }, opt.desc),
          ]),
        ],
      );
    }),

    // Custom message override
    pitchAngle
      ? el(
          "div",
          {
            class: "muted small",
            style:
              "margin-top: 12px; padding: 8px; background: var(--bg-1); border-radius: var(--radius-sm);",
          },
          [el("b", {}, "AI pitch angle: "), pitchAngle],
        )
      : null,

    el("div", { style: "margin-top: 8px;" }, [
      el("div", { class: "wizard-label" }, "Override message template (optional)"),
      el("textarea", {
        class: "wizard-textarea",
        style: "min-height: 60px;",
        placeholder: pitchAngle || "Use the AI pitch angle by default, or write your own…",
        oninput: (e) => {
          state.customMessage = e.target.value;
        },
      }),
    ]),

    // Execute buttons
    el("div", { style: "display: flex; gap: 8px; margin-top: 12px;" }, [
      el(
        "button",
        {
          class: "btn btn-primary",
          type: "button",
          onclick: async (ev) => {
            const strategies = [...state.selected];
            if (strategies.length === 0) {
              toast("Pick at least one strategy", "err");
              return;
            }
            const msg =
              `Execute ${strategies.length} strategy${strategies.length === 1 ? "" : "ies"} against ${companyName || "this company"}?\n\n` +
              strategies
                .map((s) => `• ${STRATEGY_OPTIONS.find((o) => o.id === s)?.label || s}`)
                .join("\n") +
              `\n\nThis creates real outreach campaigns. The bot's background schedulers will start firing DMs/comments shortly after.`;
            if (!confirm(msg)) return;

            await withProgress(ev.currentTarget, async () => {
              const r = await api("service-match-company-execute", {
                companyId,
                body: {
                  strategies,
                  messageTemplate: state.customMessage.trim() || undefined,
                },
              });
              if (r?.error) {
                toast(r.error, "err");
              } else {
                const created = r.outreachCreated || 0;
                // Clickable toast jumps the user to the live campaigns view —
                // the spawned outreach_campaigns rows surface on the Outreach
                // tab with start/pause/resume controls. Without this, users
                // saw "created N" with no way to find what they ran.
                // Helper: clear the top-bar account picker BEFORE navigating so
                // the user's existing filter doesn't hide freshly-spawned rows
                // (the orchestrator hasn't picked an account yet, channel
                // statuses are 'not_started', so any active picker filter
                // would render them as 'no campaigns').
                const jumpToCampaigns = () => {
                  dashboardState.contextAccount = null;
                  campaignTab = "outreach";
                  navigate("campaigns");
                };
                toast(
                  `Created ${created} campaigns + ${r.competitorsCreated || 0} competitor entries — click to view`,
                  "ok",
                  8000,
                  jumpToCampaigns,
                );
                closeDrawer();
                // Auto-jump to the Campaigns page when the user actually got
                // outreach rows; if only competitors were created (no contacts
                // had reachable channels), stay on Service Match.
                if (created > 0) jumpToCampaigns();
                else {
                  serviceMatchStep = "plan";
                  renderServiceMatch();
                }
              }
            });
          },
        },
        "▶ Execute now",
      ),
      el(
        "button",
        {
          class: "btn btn-secondary",
          type: "button",
          onclick: () => openTgCommand("/growth"),
        },
        "Open in Telegram instead",
      ),
    ]),
  ]);

  return card;
}

async function renderServiceMatchPlan() {
  const [planRes, perfRes] = await Promise.all([
    api("service-match-plan-pending").catch(() => ({})),
    api("service-match-performance").catch(() => ({})),
  ]);

  const plan = planRes?.plan;
  const items = planRes?.items || [];
  const perf = perfRes || {};

  // Counts for the header summary
  const counts = items.reduce((acc, it) => {
    const s = it.status || "pending";
    acc[s] = (acc[s] || 0) + 1;
    return acc;
  }, {});
  const approvedCount = counts.approved || 0;
  const skippedCount = counts.skipped || 0;
  const pendingCount = counts.pending || 0;

  function renderPlanItem(item) {
    const statusBadge =
      item.status === "approved"
        ? el("span", { class: "badge badge-green" }, "Approved")
        : item.status === "skipped"
          ? el("span", { class: "badge badge-gray" }, "Skipped")
          : el("span", { class: "badge badge-yellow" }, "Pending");

    const isPending = (item.status || "pending") === "pending";
    const isApproved = item.status === "approved";

    return el(
      "div",
      {
        class: "channel-row",
        style:
          "padding: 8px 10px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 8px;",
      },
      [
        el("div", { style: "flex: 1; min-width: 0;" }, [
          el(
            "div",
            { class: "primary-cell", style: "font-size: 12px;" },
            item.title || item.action_type || "—",
          ),
          item.description
            ? el("div", { class: "muted small", style: "margin-top: 2px;" }, item.description)
            : null,
          item.service_fit != null
            ? el(
                "div",
                { class: "muted small mono", style: "margin-top: 2px;" },
                `fit ${(item.service_fit * 100).toFixed(0)}%`,
              )
            : null,
        ]),
        statusBadge,
        el("div", { style: "display: flex; gap: 4px;" }, [
          // Approve button: shown for pending items
          isPending
            ? el(
                "button",
                {
                  class: "btn btn-tiny btn-primary",
                  type: "button",
                  title:
                    "Mark this item as approved — won't run until you execute the plan in Telegram.",
                  onclick: async (ev) => {
                    await withProgress(ev.currentTarget, async () => {
                      const r = await api("service-match-plan-item-approve", { itemId: item.id });
                      if (r?.error) toast(r.error, "err");
                      else {
                        toast("Approved", "ok");
                        renderServiceMatch();
                      }
                    });
                  },
                },
                "Approve",
              )
            : null,
          // Skip button: shown for pending or approved items
          isPending || isApproved
            ? el(
                "button",
                {
                  class: "btn btn-tiny btn-secondary",
                  type: "button",
                  title: "Mark this item as skipped — won't run.",
                  onclick: async (ev) => {
                    await withProgress(ev.currentTarget, async () => {
                      const r = await api("service-match-plan-item-skip", { itemId: item.id });
                      if (r?.error) toast(r.error, "err");
                      else {
                        toast("Skipped", "ok");
                        renderServiceMatch();
                      }
                    });
                  },
                },
                "Skip",
              )
            : null,
        ]),
      ],
    );
  }

  return el("div", {}, [
    plan
      ? el("div", { class: "card" }, [
          el("div", { class: "card-title" }, `Pending plan: ${plan.title || `#${plan.id}`}`),
          el(
            "div",
            { class: "muted small", style: "margin-bottom: 8px;" },
            [
              `${items.length} items · ${plan.status}`,
              pendingCount > 0 ? `  ·  ${pendingCount} pending` : "",
              approvedCount > 0 ? `  ·  ${approvedCount} approved` : "",
              skippedCount > 0 ? `  ·  ${skippedCount} skipped` : "",
            ].join(""),
          ),
          ...items.slice(0, 30).map(renderPlanItem),
          items.length > 30
            ? el(
                "div",
                { class: "muted small", style: "padding: 8px;" },
                `+ ${items.length - 30} more not shown — open in Telegram to see the full list.`,
              )
            : null,
          el(
            "div",
            {
              style:
                "display: flex; gap: 8px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); align-items: center;",
            },
            [
              el(
                "button",
                {
                  class: "btn btn-primary btn-tiny",
                  type: "button",
                  title:
                    "Approve any pending items and execute them now — creates outreach campaigns and competitor entries.",
                  onclick: async (ev) => {
                    const willApprove = pendingCount > 0;
                    const totalToRun = approvedCount + (willApprove ? pendingCount : 0);
                    const msg = willApprove
                      ? `Execute this plan?\n\n${pendingCount} pending item${pendingCount === 1 ? "" : "s"} will be auto-approved, then ${totalToRun} total item${totalToRun === 1 ? "" : "s"} will run. This creates outreach campaigns and competitor entries.`
                      : `Execute ${approvedCount} approved item${approvedCount === 1 ? "" : "s"}?\n\nThis creates outreach campaigns and competitor entries.`;
                    if (!confirm(msg)) return;
                    await withProgress(ev.currentTarget, async () => {
                      const r = await api("service-match-plan-execute", { planId: plan.id });
                      if (r?.error) toast(r.error, "err");
                      else {
                        const created = r.outreachCreated || 0;
                        // Same as the single-strategy path: clear the account picker
                        // before navigating so freshly-spawned campaigns are visible.
                        const jumpToCampaigns = () => {
                          dashboardState.contextAccount = null;
                          campaignTab = "outreach";
                          navigate("campaigns");
                        };
                        toast(
                          `Created ${created} campaigns + ${r.competitorsCreated || 0} competitor entries — click to view`,
                          "ok",
                          8000,
                          jumpToCampaigns,
                        );
                        if (created > 0) jumpToCampaigns();
                        else renderServiceMatch();
                      }
                    });
                  },
                },
                approvedCount > 0
                  ? `▶ Execute ${approvedCount + pendingCount} item${approvedCount + pendingCount === 1 ? "" : "s"}`
                  : `▶ Execute ${pendingCount} pending`,
              ),
              el(
                "button",
                {
                  class: "btn btn-secondary btn-tiny",
                  type: "button",
                  onclick: () => openTgCommand("/growth"),
                  title: "Open the same plan in the Telegram bot",
                },
                "Open in Telegram",
              ),
              el(
                "div",
                { class: "muted small", style: "margin-left: auto;" },
                approvedCount > 0
                  ? `${approvedCount} approved · ${pendingCount} pending`
                  : `${pendingCount} pending`,
              ),
            ],
          ),
        ])
      : el("div", { class: "empty-state", style: "padding: 24px;" }, [
          el("div", { class: "empty-state-icon" }, icon("clipboard")),
          el("div", { class: "empty-state-title" }, "No pending plan"),
          el(
            "div",
            { class: "empty-state-hint" },
            "Create a plan from the Matched Companies tab — pick a company and click Plan.",
          ),
        ]),

    perf.categories?.length
      ? el("div", { class: "card" }, [
          el("div", { class: "card-title" }, "Historical performance (last 30d)"),
          ...perf.categories.map((c) =>
            el(
              "div",
              {
                class: "channel-row",
                style: "padding: 6px 8px; border-bottom: 1px solid var(--border);",
              },
              [
                el(
                  "div",
                  { class: "primary-cell", style: "font-size: 12px; flex: 1;" },
                  c.category,
                ),
                el("div", { class: "muted small" }, `${c.sent} sent · ${c.replied} replied`),
                el(
                  "div",
                  { class: "mono small", style: "min-width: 60px; text-align: right;" },
                  c.reply_rate ? `${(c.reply_rate * 100).toFixed(1)}%` : "—",
                ),
              ],
            ),
          ),
        ])
      : null,
  ]);
}
