// dashboard-workflow-composer.js — extracted verbatim from dashboard.js (classic script,
// shared global scope). Loaded before dashboard.js. Pure move, no logic change.

// ── Workflow Composer (WHO × WHERE × WHAT) ───────────────────────
//
// Phase 1: list page + 4-step wizard (WHO + REVIEW are functional;
// WHERE + WHAT collapsed to sane defaults). Manual trigger only.
//
// State for the in-flight wizard lives on dashboardState.composerDraft
// so it survives accidental route bumps (and Step navigation).

function _composerEmptyDraft() {
  return {
    id: null,
    name: "Untitled workflow",
    description: "",
    audience: { resolvers: [], combine: "union", exclude_already_contacted_within_days: 30 },
    channels: [],
    plays: [],
    trigger: { type: "manual" },
    status: "draft",
  };
}

/**
 * Phase ZD — Proposals list page.
 *
 * Lists every proposal owned by the user, newest first. Click a row → open
 * the detail page. Top filter pills for status. Headline counters: total
 * sent / viewed / never-viewed.
 */
async function renderProposalsList() {
  const resp = await api("proposals-list", { queryString: "?limit=200" }).catch((e) => ({
    error: e?.message,
  }));
  if (resp?.error || resp?.unauthorized) {
    setContentNode(emptyState("⚠️", "Could not load proposals", esc(resp.error || "")));
    return;
  }
  const proposals = resp?.proposals || [];
  const totalSent = proposals.length;
  const viewed = proposals.filter((p) => (p.view_count || 0) > 0).length;
  const neverViewed = totalSent - viewed;
  const totalViews = proposals.reduce((s, p) => s + (p.view_count || 0), 0);

  const headerCard = el(
    "div",
    {
      style:
        "padding: 18px 22px; background: var(--bg-0); border: 1px solid var(--border); border-radius: 8px; margin-bottom: 16px; display: flex; gap: 32px; flex-wrap: wrap;",
    },
    [
      el("div", {}, [
        el(
          "div",
          {
            class: "muted",
            style: "font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;",
          },
          "Sent",
        ),
        el(
          "div",
          { style: "font-size: 22px; font-weight: 600; color: var(--text-2); margin-top: 4px;" },
          String(totalSent),
        ),
      ]),
      el("div", {}, [
        el(
          "div",
          {
            class: "muted",
            style: "font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;",
          },
          "Viewed",
        ),
        el(
          "div",
          {
            style: `font-size: 22px; font-weight: 600; color: ${viewed > 0 ? "#5ada5a" : "#666"}; margin-top: 4px;`,
          },
          `${viewed}${totalSent > 0 ? ` (${Math.round((viewed / totalSent) * 100)}%)` : ""}`,
        ),
      ]),
      el("div", {}, [
        el(
          "div",
          {
            class: "muted",
            style: "font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;",
          },
          "Never viewed",
        ),
        el(
          "div",
          {
            style: `font-size: 22px; font-weight: 600; color: ${neverViewed > 0 ? "#daaa5a" : "#666"}; margin-top: 4px;`,
          },
          String(neverViewed),
        ),
      ]),
      el("div", {}, [
        el(
          "div",
          {
            class: "muted",
            style: "font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;",
          },
          "Total views",
        ),
        el(
          "div",
          { style: "font-size: 22px; font-weight: 600; color: #5a8aff; margin-top: 4px;" },
          String(totalViews),
        ),
      ]),
    ],
  );

  let body;
  if (proposals.length === 0) {
    body = el("div", { class: "empty-state", style: "padding: 40px 20px;" }, [
      el("div", { class: "empty-state-icon" }, icon("note")),
      el("div", { class: "empty-state-title" }, "No proposals yet"),
      el(
        "div",
        { class: "empty-state-hint" },
        "Build a workflow that uses the generate_proposal play, then run it. Each contact gets a personalized proposal with a public share URL.",
      ),
      el("div", { class: "row", style: "gap: 8px; margin-top: 16px; justify-content: center;" }, [
        el(
          "button",
          {
            class: "btn btn-primary",
            type: "button",
            onclick: () => navigate("workflows"),
          },
          "Build a workflow",
        ),
      ]),
    ]);
  } else {
    body = el(
      "div",
      { class: "card" },
      proposals.map((p) => {
        const statusColors = {
          published: { bg: "rgba(16,185,129,0.18)", color: "#a7f3d0", label: "PUBLISHED" },
          draft: { bg: "rgba(168,85,247,0.18)", color: "#ede9fe", label: "DRAFT" },
          revoked: { bg: "rgba(239,68,68,0.18)", color: "#fca5a5", label: "REVOKED" },
          expired: { bg: "rgba(234,179,8,0.18)", color: "#fde68a", label: "EXPIRED" },
        };
        const st = statusColors[p.status] || statusColors.draft;
        const viewBadge =
          (p.view_count || 0) > 0
            ? el(
                "span",
                {
                  class: "pill",
                  style:
                    "background: rgba(90,218,90,0.12); color: #a7e8a7; padding: 2px 6px; font-size: 10px;",
                },
                `${p.view_count} view${p.view_count === 1 ? "" : "s"}`,
              )
            : el(
                "span",
                {
                  class: "pill",
                  style:
                    "background: rgba(218,170,90,0.10); color: #daaa5a; padding: 2px 6px; font-size: 10px;",
                },
                "not viewed yet",
              );
        return el(
          "div",
          {
            class: "row",
            style:
              "padding: 14px 4px; border-bottom: 1px solid var(--border); gap: 12px; align-items: center; cursor: pointer;",
            onclick: () => {
              dashboardState.currentParams = { id: p.id };
              navigate(`proposals/detail/${p.id}`);
            },
          },
          [
            el("div", { style: "flex: 1; min-width: 0;" }, [
              el("div", { class: "row", style: "gap: 8px; align-items: center;" }, [
                el("strong", { style: "font-size: 13px; color: var(--text-1);" }, p.title),
                el(
                  "span",
                  {
                    class: "pill",
                    style: `background: ${st.bg}; color: ${st.color}; font-size: 10px; padding: 2px 6px; font-family: ui-monospace, monospace;`,
                  },
                  st.label,
                ),
                viewBadge,
              ]),
              el(
                "div",
                { class: "muted", style: "font-size: 11px; margin-top: 4px;" },
                `Template: ${p.template_id || "?"} · created ${p.created_at ? new Date(p.created_at).toLocaleDateString() : "?"}` +
                  (p.last_viewed_at
                    ? ` · last viewed ${new Date(p.last_viewed_at).toLocaleDateString()}`
                    : ""),
              ),
            ]),
            el(
              "a",
              {
                href: `/p/${p.public_slug}`,
                target: "_blank",
                rel: "noopener",
                onclick: (e) => e.stopPropagation(),
                style:
                  "padding: 4px 10px; background: rgba(90,138,255,0.15); border: 1px solid rgba(90,138,255,0.4); color: #93c5fd; border-radius: 5px; text-decoration: none; font-size: 11px;",
                title: "Open the public share URL",
              },
              "View →",
            ),
          ],
        );
      }),
    );
  }

  setContentNode(
    el("div", { style: "max-width: 1100px; margin: 0 auto; padding: 24px;" }, [
      el("div", { class: "page-header" }, [
        el("div", {}, [
          el("div", { class: "page-title" }, "Proposals"),
          el(
            "div",
            { class: "page-subtitle" },
            "AI-generated sales proposals from your composer workflows. Each composition that uses generate_proposal creates one of these per contact.",
          ),
        ]),
      ]),
      headerCard,
      body,
    ]),
  );
}

/**
 * Phase ZD — Proposal detail page.
 * Shows full proposal sections, status, view history, and a button to open
 * the public share URL.
 */
async function renderProposalDetail() {
  const id = dashboardState.currentParams?.id;
  if (!id) {
    navigate("proposals");
    return;
  }
  const [propResp, viewsResp] = await Promise.all([
    api("proposals-get", { id }).catch((e) => ({ error: e?.message })),
    api("proposals-views", { id }).catch(() => null),
  ]);
  if (propResp?.error) {
    setContentNode(
      el("div", { class: "empty-state" }, [
        el("div", {}, "Proposal not found"),
        el("div", { class: "muted", style: "font-size: 11px;" }, esc(propResp.error || "")),
        el(
          "button",
          { class: "btn btn-secondary", type: "button", onclick: () => navigate("proposals") },
          "← All proposals",
        ),
      ]),
    );
    return;
  }
  const p = propResp.proposal;
  const viewLog = viewsResp?.views || [];
  const sections = p.sections || [];

  const sectionsHtml = sections.map((s) =>
    el(
      "div",
      {
        style: "padding: 16px 0; border-bottom: 1px solid var(--border);",
      },
      [
        s.heading
          ? el(
              "h3",
              { style: "margin: 0 0 8px; font-size: 14px; color: var(--text-1);" },
              s.heading,
            )
          : null,
        el(
          "div",
          {
            style:
              "font-size: 12px; color: var(--text-2); line-height: 1.6; white-space: pre-wrap;",
          },
          s.body || "",
        ),
      ].filter(Boolean),
    ),
  );

  setContentNode(
    el(
      "div",
      { style: "max-width: 900px; margin: 0 auto; padding: 24px;" },
      [
        el(
          "div",
          {
            class: "row",
            style: "justify-content: space-between; align-items: center; margin-bottom: 16px;",
          },
          [
            el(
              "button",
              {
                class: "btn btn-tiny btn-secondary",
                type: "button",
                onclick: () => navigate("proposals"),
              },
              "← All proposals",
            ),
            el("div", { class: "row", style: "gap: 6px;" }, [
              el(
                "a",
                {
                  href: `/p/${p.public_slug}`,
                  target: "_blank",
                  rel: "noopener",
                  class: "btn btn-secondary",
                  style: "text-decoration: none; padding: 6px 12px; font-size: 12px;",
                },
                "Open public URL",
              ),
              el(
                "button",
                {
                  class: "btn btn-tiny btn-secondary",
                  type: "button",
                  onclick: async () => {
                    try {
                      await navigator.clipboard.writeText(
                        `${window.location.origin}/p/${p.public_slug}`,
                      );
                      toast("Link copied", "ok", 1500);
                    } catch {
                      toast("Copy failed", "err");
                    }
                  },
                },
                "Copy",
              ),
            ]),
          ],
        ),
        el("div", { class: "page-header" }, [
          el("div", {}, [
            el("div", { class: "page-title", style: "font-size: 22px;" }, p.title),
            el(
              "div",
              { class: "page-subtitle" },
              `Status: ${p.status} · ${p.view_count || 0} view(s)` +
                (p.last_viewed_at
                  ? ` · last seen ${new Date(p.last_viewed_at).toLocaleString()}`
                  : "") +
                (p.created_at ? ` · sent ${new Date(p.created_at).toLocaleDateString()}` : ""),
            ),
          ]),
        ]),
        el(
          "div",
          {
            style:
              "padding: 18px 22px; background: var(--bg-0); border: 1px solid var(--border); border-radius: 8px; margin-bottom: 18px;",
          },
          sectionsHtml,
        ),
        viewLog.length > 0
          ? el(
              "div",
              {
                style:
                  "padding: 14px 18px; background: var(--bg-0); border: 1px solid var(--border); border-radius: 8px;",
              },
              [
                el(
                  "h3",
                  { style: "margin: 0 0 10px; font-size: 13px; color: var(--text-1);" },
                  `View history (${viewLog.length})`,
                ),
                el(
                  "div",
                  { style: "display: flex; flex-direction: column; gap: 4px;" },
                  viewLog.slice(0, 20).map((v) =>
                    el(
                      "div",
                      {
                        class: "row",
                        style: "font-size: 11px; color: var(--text-2); gap: 12px;",
                      },
                      [
                        el(
                          "span",
                          { style: "min-width: 140px;" },
                          new Date(v.created_at).toLocaleString(),
                        ),
                        el(
                          "span",
                          { class: "muted" },
                          v.viewer_ua ? String(v.viewer_ua).slice(0, 60) + "..." : "anonymous",
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            )
          : null,
      ].filter(Boolean),
    ),
  );
}

/**
 * Phase ZC — Results page after a test-all canvas session completes (or
 * is cancelled). Reads dashboardState.testAllSession.results.
 */
async function renderTestAllResults() {
  const s = dashboardState.testAllSession;
  if (!s) {
    setContentNode(
      el("div", { class: "empty-state", style: "padding: 40px 20px;" }, [
        el("div", { class: "empty-state-icon" }, icon("flask")),
        el("div", { class: "empty-state-title" }, "No test session"),
        el(
          "div",
          { class: "empty-state-hint" },
          'Click "Test all my workflows" on the Active workflows page to start a session.',
        ),
        el(
          "button",
          {
            class: "btn btn-primary",
            type: "button",
            style: "margin-top:14px;",
            onclick: () => navigate("automations"),
          },
          "← Active workflows",
        ),
      ]),
    );
    return;
  }
  const results = s.results || [];
  const counts = results.reduce((a, r) => {
    a[r.status] = (a[r.status] || 0) + 1;
    return a;
  }, {});
  const totalMs = s.finishedAt && s.startedAt ? new Date(s.finishedAt) - new Date(s.startedAt) : 0;
  const headlineColor = counts.fail > 0 ? "#fa8a8a" : "#5ada5a";
  const headlineLabel =
    s.status === "cancelled"
      ? `Cancelled at ${results.length} of ${s.queue.length}`
      : counts.fail > 0
        ? `${counts.fail} failed`
        : `All passed`;

  // Top: summary card
  const summaryCard = el(
    "div",
    {
      style:
        "padding: 18px 22px; background: var(--bg-0); border: 1px solid var(--border); border-radius: 8px; margin-bottom: 16px; display: flex; align-items: center; gap: 18px; flex-wrap: wrap;",
    },
    [
      el(
        "div",
        { style: `font-size: 18px; font-weight: 600; color: ${headlineColor};` },
        headlineLabel,
      ),
      el(
        "div",
        { class: "muted", style: "font-size: 12px;" },
        `${results.length} workflow(s) tested · ${counts.pass || 0} pass · ${counts.fail || 0} fail · ${counts.skipped || 0} skipped${totalMs ? ` · ${msFormat(totalMs)} total` : ""}`,
      ),
      el("div", { style: "flex:1;" }),
      el(
        "button",
        {
          class: "btn btn-secondary",
          type: "button",
          onclick: () => {
            // Re-run with the same queue
            const comps = (s.queue || []).map((q) => q._raw || q);
            if (comps.length > 0) startTestAllCanvasSession(comps);
          },
        },
        "▶ Run again",
      ),
      el(
        "button",
        {
          class: "btn btn-secondary",
          type: "button",
          onclick: () => navigate("automations"),
        },
        "← Active workflows",
      ),
    ],
  );

  // Per-comp result cards
  const list = el("div", { style: "display: flex; flex-direction: column; gap: 8px;" });
  for (const r of results) {
    const cfg = {
      pass: { icon: "✅", color: "#5ada5a", border: "#5ada5a" },
      fail: { icon: "❌", color: "#fa8a8a", border: "#fa8a8a" },
      skipped: { icon: "↷", color: "#daaa5a", border: "#daaa5a" },
    }[r.status] || { icon: "?", color: "#666", border: "#444" };
    const card = el(
      "div",
      {
        style: `padding: 12px 14px; background: var(--bg-0); border: 1px solid var(--border); border-left: 3px solid ${cfg.border}; border-radius: 6px; cursor: pointer; transition: background 120ms;`,
        onmouseover: (e) => {
          e.currentTarget.style.background = "var(--bg-1)";
        },
        onmouseout: (e) => {
          e.currentTarget.style.background = "var(--bg-0)";
        },
        onclick: () => {
          const comp = (s.queue || []).find((q) => q.id === r.compositionId);
          if (comp) {
            dashboardState.composerDraft = comp._raw || comp;
            navigate("workflows/canvas");
          }
        },
      },
      [
        el("div", { class: "row", style: "gap: 12px; align-items: center;" }, [
          el("span", { style: `font-size: 18px; width: 24px;` }, cfg.icon),
          el("div", { style: "flex: 1; min-width: 0;" }, [
            el(
              "div",
              { style: "font-size: 13px; font-weight: 500; color: var(--text-2);" },
              r.name || `#${r.compositionId}`,
            ),
            el(
              "div",
              { class: "muted", style: `font-size: 11px; color: ${cfg.color}; margin-top: 2px;` },
              r.summary,
            ),
          ]),
          el(
            "div",
            { class: "muted", style: "font-size: 10px; min-width: 60px; text-align: right;" },
            r.durationMs != null ? msFormat(r.durationMs) : "",
          ),
          el("span", { class: "muted", style: "font-size: 10px;" }, "→"),
        ]),
      ],
    );
    list.appendChild(card);
  }

  setContentNode(
    el("div", { style: "max-width: 1100px; margin: 0 auto; padding: 24px;" }, [
      el("div", { class: "page-header" }, [
        el("div", {}, [
          el("div", { class: "page-title" }, "Test all results"),
          el(
            "div",
            { class: "page-subtitle" },
            `Session ran ${s.startedAt ? new Date(s.startedAt).toLocaleString() : "recently"}. Click any result to open that workflow's canvas.`,
          ),
        ]),
      ]),
      summaryCard,
      list,
    ]),
  );
}

async function renderWorkflowsHome() {
  // Legacy entry — kept so any direct call still works. The hub at
  // #workflows now wraps this body inside the "My workflows" tab via
  // _buildWorkflowsMineBody. New code should call the hub directly.
  const root = el("div", { style: "max-width: 1100px; margin: 0 auto; padding: 24px;" });
  setContentNode(root);
  await _buildWorkflowsMineBody(root);
}

// "My workflows" body — surfaces the user's saved compositions. Shared
// between the legacy #workflows standalone page (above) and the
// #workflows/mine tab inside renderWorkflowsHub.
async function _buildWorkflowsMineBody(root) {
  const [resp, summary] = await Promise.all([
    api("compositions-list").catch((e) => ({ error: e?.message })),
    api("composition-operator-summary").catch(() => null),
  ]);
  if (resp?.error || resp?.unauthorized) {
    root.appendChild(
      el("div", { class: "empty-state" }, [
        el("div", { class: "empty-state-icon" }, icon("alert")),
        el("div", { class: "empty-state-title" }, "Could not load workflows"),
        el("div", { class: "empty-state-hint" }, esc(resp.error || "")),
      ]),
    );
    return;
  }
  const items = resp?.compositions || [];

  const header = el(
    "div",
    {
      class: "row",
      style: "justify-content: space-between; align-items: center; margin-bottom: 16px;",
    },
    [
      el("div", {}, [
        el("h1", { style: "margin: 0; font-size: 22px;" }, "Build a workflow"),
        el(
          "div",
          { class: "muted", style: "font-size: 12px; margin-top: 4px;" },
          "Pick a starter template by track, or build from scratch on the canvas. See live workflows on Active workflows →",
        ),
      ]),
      el("div", { class: "row", style: "gap: 8px;" }, [
        el(
          "button",
          {
            class: "btn btn-secondary",
            type: "button",
            title: "Aggregated funnel + cost-per-reply across all your compositions",
            onclick: () => navigate("workflows/performance"),
          },
          "Performance",
        ),
        el(
          "button",
          {
            class: "btn btn-secondary",
            type: "button",
            onclick: () => _openTemplatesPickerModal(),
          },
          "Start from template",
        ),
        el(
          "button",
          {
            class: "btn btn-primary",
            type: "button",
            onclick: () => {
              // Phase A: route new workflows to the n8n canvas, not the legacy wizard.
              // The canvas now handles unsaved drafts (id=null until first save).
              dashboardState.composerDraft = _composerEmptyDraft();
              navigate("workflows/canvas");
            },
          },
          "+ New workflow",
        ),
      ]),
    ],
  );

  let body;
  if (items.length === 0) {
    body = el("div", { class: "empty-state", style: "padding: 40px 20px;" }, [
      el("div", { class: "empty-state-icon" }, icon("layers")),
      el("div", { class: "empty-state-title" }, "No workflows yet"),
      el(
        "div",
        { class: "empty-state-hint" },
        "Pick a template to see what's possible, or start from scratch.",
      ),
      el("div", { class: "row", style: "gap: 8px; margin-top: 16px; justify-content: center;" }, [
        el(
          "button",
          {
            class: "btn btn-primary",
            type: "button",
            onclick: () => _openTemplatesPickerModal(),
          },
          "Browse templates",
        ),
        el(
          "button",
          {
            class: "btn btn-secondary",
            type: "button",
            onclick: () => {
              // Phase A: route to canvas
              dashboardState.composerDraft = _composerEmptyDraft();
              navigate("workflows/canvas");
            },
          },
          "+ Start from scratch",
        ),
      ]),
    ]);
  } else {
    body = el(
      "div",
      { class: "card" },
      items.map((w) => {
        const channelSummary =
          (w.channels || []).map((c) => `${c.platform}@${c.account_id}`).join(" → ") || "—";
        const playSummary = (w.plays || []).map((p) => p.type).join(" · ") || "—";
        const audienceSummary = (() => {
          const r = (w.audience?.resolvers || [])[0];
          if (!r) return "—";
          if (r.type === "crm_query") {
            const tags = Array.isArray(r.filters?.tags)
              ? r.filters.tags.join(", ")
              : r.filters?.tags || "";
            return `CRM: ${tags || "all"}`;
          }
          if (r.type === "manual_list") return `Manual: ${(r.contact_ids || []).length} contacts`;
          return r.type;
        })();
        const statusPill = el(
          "span",
          {
            class: "pill",
            style: `background: ${w.status === "active" ? "#1e3a1e" : w.status === "paused" ? "#3a2a1e" : "#222"}; color: ${w.status === "active" ? "#5ada5a" : w.status === "paused" ? "#daaa5a" : "#aaa"};`,
          },
          w.status,
        );
        return el(
          "div",
          {
            class: "row",
            style:
              "padding: 12px 4px; border-bottom: 1px solid var(--border); gap: 12px; align-items: center; cursor: pointer;",
            onclick: () => {
              // Phase 34b: clicking a workflow row opens the canvas editor by default
              dashboardState.composerDraft = { ...w };
              navigate("workflows/canvas");
            },
          },
          [
            el("div", { style: "flex: 1;" }, [
              el("div", { style: "font-weight: 500;" }, [w.name, " ", statusPill]),
              el(
                "div",
                { class: "muted", style: "font-size: 11px; margin-top: 2px;" },
                `${audienceSummary} · ${channelSummary} · ${playSummary}`,
              ),
            ]),
            // Phase 10: mini-funnel sparkline (hydrated from listCompositionsByOwner)
            // + inline reply-rate text. Six 6px bars representing matched →
            // eligible → attempted → sent → replied → converted, height
            // proportional to the max stage (so even tiny audiences render).
            (w.total_runs || 0) > 0 && w.funnel
              ? el(
                  "div",
                  {
                    style:
                      "display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 200px;",
                  },
                  [
                    _composerFunnelMiniSparkline(w.funnel),
                    el(
                      "div",
                      { class: "muted", style: "font-size: 11px;" },
                      `${w.total_runs || 0} run${w.total_runs === 1 ? "" : "s"} · ${w.total_audience_reached || 0} reached · ${w.total_replies || 0} replied`,
                    ),
                    w.total_audience_reached > 0
                      ? el(
                          "div",
                          {
                            style: `font-size: 11px; color: ${w.total_replies / w.total_audience_reached > 0.1 ? "#5ada5a" : "#aaa"};`,
                          },
                          `${Math.round((100 * w.total_replies) / Math.max(w.total_audience_reached, 1))}% reply rate`,
                        )
                      : null,
                  ].filter(Boolean),
                )
              : el(
                  "div",
                  { class: "muted", style: "font-size: 11px;" },
                  w.last_run_at
                    ? `Last run: ${new Date(w.last_run_at).toLocaleString()}`
                    : "Never run",
                ),
            el(
              "button",
              {
                class: "btn btn-tiny btn-secondary",
                type: "button",
                onclick: async (ev) => {
                  ev.stopPropagation();
                  const r = await api("composition-run", { id: w.id, body: {} }).catch((e) => ({
                    error: e?.message,
                  }));
                  if (r?.error) toast(`Run failed: ${r.error}`, "err");
                  else
                    toast(
                      `Run complete · ${r.playsSucceeded || 0}/${r.playsExecuted || 0} plays`,
                      "ok",
                      4000,
                    );
                },
              },
              "▶ Run now",
            ),
            el(
              "button",
              {
                class: "btn btn-tiny btn-secondary",
                type: "button",
                onclick: (ev) => {
                  ev.stopPropagation();
                  dashboardState.composerDraft = { ...w };
                  navigate("workflows/canvas");
                },
                title: "Open canvas editor (n8n-style)",
              },
              "🔀",
            ),
            el(
              "button",
              {
                class: "btn btn-tiny btn-secondary",
                type: "button",
                onclick: (ev) => {
                  ev.stopPropagation();
                  dashboardState.composerDraft = { ...w };
                  navigate("workflows/detail");
                },
                title: "View runs and stats",
              },
              "📊",
            ),
            // Phase 9: killswitch (only when not already paused/archived)
            w.status === "active" || w.status === "draft"
              ? el(
                  "button",
                  {
                    class: "btn btn-tiny btn-danger",
                    type: "button",
                    title: "Killswitch — pauses + cancels in-flight runs",
                    onclick: async (ev) => {
                      ev.stopPropagation();
                      if (await _composerKillswitch(w)) renderWorkflowsHome();
                    },
                  },
                  "🛑",
                )
              : null,
          ],
        );
      }),
    );
  }

  // Phase 14: operator overview card — single-glance rollup at the top.
  const overviewCard = _composerBuildOperatorOverview(summary);

  // Phase E: templates tracks strip — primary discovery affordance for new
  // workflows. Renders the 8 persona tracks as clickable tiles above the
  // workflow list. Each tile opens the templates picker pre-filtered.
  const tracksStrip = await _buildBuildPageTracksStrip();

  // Append everything to the provided root. (Was setContentNode(root) in
  // the standalone page; now the hub passes the tab's content area as
  // root, so this just appends.)
  for (const node of [header, tracksStrip, overviewCard, body].filter(Boolean)) {
    root.appendChild(node);
  }
}
