// automations.jsx — automations list + recipe editor

const AUTO_CSS = `
.auto { flex: 1; overflow-y: auto; padding: 28px 36px 60px; background: var(--bg-app); }
.auto-h { display: flex; align-items: flex-end; gap: 16px; margin-bottom: 22px; }
.auto-h h1 { font-size: 28px; font-weight: 800; color: var(--ink-strong); letter-spacing: -0.025em; margin: 0; }
.auto-h p { font-size: 13px; color: var(--ink-muted); margin: 4px 0 0; }
.auto-h .actions { margin-left: auto; display: flex; gap: 8px; }

.auto-tabs { display: flex; gap: 22px; border-bottom: 1px solid var(--border); margin-bottom: 16px; }
.auto-tabs .t {
  padding: 10px 0; font-size: 13.5px; color: var(--ink-muted); font-weight: 500;
  border-bottom: 2px solid transparent; cursor: pointer;
}
.auto-tabs .t.is-on { color: var(--ink-strong); border-color: var(--brand); font-weight: 600; }
.auto-tabs .t .ct {
  display: inline-block; margin-left: 6px; padding: 1px 7px;
  border-radius: 999px; background: var(--bg-subtle);
  font-size: 10.5px; color: var(--ink-muted); font-weight: 600;
}
.auto-tabs .t.is-on .ct { background: rgba(162,93,220,.14); color: var(--brand); }

.auto-search-row { display: flex; gap: 8px; margin-bottom: 14px; }
.auto-search-row input {
  flex: 1; max-width: 360px; font-family: inherit; font-size: 13px;
  padding: 8px 12px; border: 1px solid var(--border); border-radius: 6px;
  outline: none;
}
.auto-search-row input:focus { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(162,93,220,.10); }
.auto-search-row select { font-family: inherit; font-size: 13px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px; }

.auto-list {
  background: white; border: 1px solid var(--border); border-radius: 10px;
  overflow: hidden;
}
.auto-row {
  display: grid;
  grid-template-columns: 36px 1fr 130px 90px 90px 36px;
  align-items: center;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-row);
  cursor: pointer;
  font-size: 13px;
  gap: 12px;
}
.auto-row:last-child { border-bottom: none; }
.auto-row:hover { background: var(--bg-subtle); }
.auto-row .ic {
  width: 32px; height: 32px; border-radius: 6px;
  background: rgba(162,93,220,.12); color: var(--brand);
  display: grid; place-items: center; font-size: 14px;
}
.auto-row .nm { font-weight: 600; color: var(--ink-strong); }
.auto-row .desc { font-size: 12px; color: var(--ink-muted); margin-top: 2px; line-height: 1.4; }
.auto-row .scope { font-size: 12px; color: var(--ink-muted); }
.auto-row .runs { font-size: 12px; color: var(--ink-muted); font-variant-numeric: tabular-nums; text-align: right; }

.auto-toggle {
  position: relative; width: 34px; height: 20px; border-radius: 999px;
  background: var(--border-strong); transition: background .15s; cursor: pointer;
}
.auto-toggle.on { background: #14b76a; }
.auto-toggle::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px; border-radius: 50%; background: white;
  transition: left .15s; box-shadow: 0 1px 3px rgba(0,0,0,.15);
}
.auto-toggle.on::after { left: 16px; }

.auto-empty { padding: 60px 20px; text-align: center; color: var(--ink-muted); }
.auto-empty .big { font-size: 28px; margin-bottom: 10px; }

/* Recipe gallery */
.recipe-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px;
}
.recipe-card {
  background: white; border: 1px solid var(--border); border-radius: 10px;
  padding: 18px; cursor: pointer; transition: border-color .12s, transform .12s;
  display: flex; flex-direction: column; gap: 10px;
}
.recipe-card:hover { border-color: var(--brand); transform: translateY(-1px); box-shadow: 0 4px 14px rgba(162,93,220,.10); }
.recipe-card .badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 10.5px; font-weight: 700; color: var(--brand);
  background: rgba(162,93,220,.12); padding: 3px 8px; border-radius: 4px;
  letter-spacing: 0.06em; text-transform: uppercase; align-self: flex-start;
}
.recipe-card .nm { font-size: 14px; font-weight: 600; color: var(--ink-strong); }
.recipe-card .recipe-sentence {
  font-size: 13px; color: var(--ink-body); line-height: 1.55;
}
.recipe-card .recipe-sentence b { color: var(--brand); font-weight: 600; }

/* Editor */
.auto-editor { display: grid; grid-template-columns: 1fr 320px; gap: 20px; }
.editor-canvas {
  background: white; border: 1px solid var(--border); border-radius: 12px;
  padding: 28px 28px 32px;
}
.editor-title-row { display: flex; align-items: center; gap: 12px; margin-bottom: 4px; }
.editor-title {
  font-size: 22px; font-weight: 700; color: var(--ink-strong);
  letter-spacing: -0.02em; border: 1.5px solid transparent; border-radius: 6px;
  padding: 4px 8px; margin-left: -8px;
}
.editor-title:hover { background: var(--bg-subtle); }
.editor-title:focus { background: white; border-color: var(--brand); outline: none; }
.editor-meta { font-size: 12.5px; color: var(--ink-muted); margin-bottom: 22px; }

/* The block tree */
.block {
  border: 1.5px solid var(--border); border-radius: 10px;
  padding: 14px 16px; background: white;
  display: flex; align-items: flex-start; gap: 12px;
  position: relative;
}
.block:hover { border-color: var(--border-strong); }
.block.trigger { border-color: #d97f1f; background: linear-gradient(180deg, #fef9f0, white); }
.block.condition { border-color: #579bfc; background: linear-gradient(180deg, #f0f6ff, white); }
.block.action { border-color: var(--brand); background: linear-gradient(180deg, #f9f3fc, white); }
.block-ic {
  width: 36px; height: 36px; border-radius: 8px;
  display: grid; place-items: center; font-size: 16px; flex-shrink: 0;
  font-weight: 600;
}
.block.trigger .block-ic { background: #fef4e6; color: #b8651b; }
.block.condition .block-ic { background: #e6f0fe; color: #1660c8; }
.block.action .block-ic { background: rgba(162,93,220,.15); color: var(--brand); }
.block-body { flex: 1; min-width: 0; }
.block-kind {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase;
}
.block.trigger .block-kind   { color: #b8651b; }
.block.condition .block-kind { color: #1660c8; }
.block.action .block-kind    { color: var(--brand); }
.block-sentence {
  font-size: 14px; color: var(--ink-strong); line-height: 1.5;
  margin-top: 4px;
}
.block-sentence .slot {
  display: inline-block;
  padding: 2px 8px; margin: 0 2px;
  background: var(--bg-subtle); border: 1.5px dashed var(--border-strong);
  border-radius: 4px; font-weight: 600; color: var(--ink-strong);
  cursor: pointer; font-size: 13px;
}
.block-sentence .slot:hover { border-color: var(--brand); border-style: solid; background: rgba(162,93,220,.06); }
.block-sentence .slot.is-set { border-style: solid; border-color: var(--brand); background: rgba(162,93,220,.10); color: var(--brand); }
.block-actions { display: flex; gap: 4px; align-items: flex-start; flex-shrink: 0; }
.block-actions button {
  width: 26px; height: 26px; border-radius: 4px;
  border: none; background: transparent; cursor: pointer;
  display: grid; place-items: center; color: var(--ink-faint);
}
.block-actions button:hover { background: var(--bg-subtle); color: var(--ink-body); }

.block-conn {
  display: flex; flex-direction: column; align-items: center;
  margin: 4px 0;
  position: relative;
}
.block-conn .line { width: 2px; height: 20px; background: var(--border-strong); }
.block-conn .word {
  font-size: 10.5px; font-weight: 700; color: var(--ink-muted);
  letter-spacing: 0.1em; text-transform: uppercase;
  background: var(--bg-app); padding: 0 8px;
  position: absolute; top: 50%; transform: translateY(-50%);
}

.add-block-row {
  display: flex; justify-content: center; padding: 8px 0;
}
.add-block-btn {
  font-family: inherit; font-size: 12.5px; font-weight: 500;
  padding: 8px 14px; border: 1.5px dashed var(--border-strong);
  background: var(--bg-subtle); color: var(--ink-muted);
  border-radius: 6px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
}
.add-block-btn:hover { border-color: var(--brand); color: var(--brand); border-style: solid; }

.editor-side {
  background: white; border: 1px solid var(--border); border-radius: 10px;
  padding: 18px 20px; align-self: flex-start;
}
.editor-side h4 {
  font-size: 11px; color: var(--ink-muted); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em; margin: 0 0 10px;
}
.editor-side .ts-row {
  display: grid; grid-template-columns: 24px 1fr; gap: 8px;
  align-items: flex-start; padding: 8px 0;
  font-size: 12.5px; border-bottom: 1px solid var(--border-row);
}
.editor-side .ts-row:last-child { border-bottom: none; }
.editor-side .ts-row .dt { color: var(--ink-faint); font-size: 10px; }
.editor-side .ts-row .ic { font-size: 12px; }
.editor-side .ts-row b { color: var(--ink-strong); font-weight: 600; }

.editor-test-bar {
  display: flex; gap: 8px; padding: 12px 14px;
  background: #f9f3fc; border: 1px solid #e7d3f5;
  border-radius: 8px; margin-bottom: 18px;
  align-items: center; font-size: 12.5px; color: var(--brand);
}
.editor-test-bar b { color: var(--ink-strong); }
.editor-test-bar .btn { margin-left: auto; }
`;

if (typeof document !== "undefined" && !document.getElementById("auto-css")) {
  const s = document.createElement("style");
  s.id = "auto-css"; s.textContent = AUTO_CSS; document.head.appendChild(s);
}

// ── Seed automations ──────────────────────────────────────────────
const AUTOMATIONS = [
  {
    id: "a1", on: true, name: "Notify owner when blocked",
    desc: "Pings the assignee in Slack the moment status flips to Blocked.",
    scope: "Checkout v2", runs7d: 12, lastRun: "2h ago",
    blocks: [
      { kind: "trigger",   id: "t",  type: "status_change",  to: "blocked" },
      { kind: "action",    id: "a1", type: "slack_notify",   who: "assignee", channel: "#checkout-eng" },
    ],
  },
  {
    id: "a2", on: true, name: "Move to In Review on PR open",
    desc: "When a linked GitHub PR opens, status moves to Review.",
    scope: "All projects", runs7d: 28, lastRun: "12m ago",
    blocks: [
      { kind: "trigger",  id: "t",  type: "github_pr_open" },
      { kind: "action",   id: "a1", type: "set_status",   value: "review" },
      { kind: "action",   id: "a2", type: "comment",      text: "PR opened — entering review." },
    ],
  },
  {
    id: "a3", on: false, name: "Auto-archive done tasks after 30 days",
    desc: "Cleans up the Done column on a recurring schedule.",
    scope: "All projects", runs7d: 0, lastRun: "Disabled",
    blocks: [
      { kind: "trigger",   id: "t",  type: "schedule",         every: "weekly", day: "Mon" },
      { kind: "condition", id: "c1", type: "field_equals",     field: "status",  value: "done" },
      { kind: "condition", id: "c2", type: "field_older_than", field: "completedAt", days: 30 },
      { kind: "action",    id: "a1", type: "archive" },
    ],
  },
  {
    id: "a4", on: true, name: "Escalate overdue P0/P1",
    desc: "Daily: re-assign overdue P0/P1 tasks to the team lead.",
    scope: "Mobile App", runs7d: 3, lastRun: "Yesterday",
    blocks: [
      { kind: "trigger",   id: "t",  type: "schedule",       every: "daily",  time: "09:00" },
      { kind: "condition", id: "c1", type: "field_equals",   field: "prio",   value: "p0" },
      { kind: "condition", id: "c2", type: "is_overdue" },
      { kind: "action",    id: "a1", type: "set_assignee",   value: "ay" },
      { kind: "action",    id: "a2", type: "slack_notify",   who: "owner",    channel: "#mobile-leads" },
    ],
  },
  {
    id: "a5", on: true, name: "Roll up sprint health to Slack",
    desc: "Posts a weekly summary card to #standups every Friday.",
    scope: "All projects", runs7d: 1, lastRun: "Fri",
    blocks: [
      { kind: "trigger", id: "t",  type: "schedule",     every: "weekly", day: "Fri", time: "16:00" },
      { kind: "action",  id: "a1", type: "slack_digest", channel: "#standups" },
    ],
  },
  {
    id: "a6", on: true, name: "Tag late tasks for retro",
    desc: "When a task is marked completed-late, add the 'retro' label.",
    scope: "Checkout v2", runs7d: 5, lastRun: "3h ago",
    blocks: [
      { kind: "trigger",   id: "t",  type: "outcome_set",  value: "late" },
      { kind: "action",    id: "a1", type: "add_label",    value: "retro" },
    ],
  },
];

const RECIPES = [
  { id: "r1", tag: "Most popular", nm: "Notify on blocked",       parts: ["When", "status changes to Blocked", "notify the assignee in Slack"] },
  { id: "r2", tag: "New",          nm: "PR → Review",              parts: ["When a", "GitHub PR opens", "set status to In Review"] },
  { id: "r3", tag: "Hygiene",      nm: "Archive old done",         parts: ["Every Monday, archive tasks", "Done > 30 days"] },
  { id: "r4", tag: "Reporting",    nm: "Weekly Slack digest",      parts: ["Every Friday at 4pm,", "post sprint summary", "to #standups"] },
  { id: "r5", tag: "Quality",      nm: "Tag late tasks for retro", parts: ["When outcome is", "late", "add the retro label"] },
  { id: "r6", tag: "Escalation",   nm: "Escalate overdue P0",      parts: ["Daily, if a P0 task is overdue", "reassign to the lead"] },
];

// ── Block sentence rendering ─────────────────────────────────────
function blockMeta(b) {
  switch (b.type) {
    case "status_change":     return { ic: "↻",  kind: "Trigger",   sentence: <>When <span className={`slot ${b.to ? "is-set" : ""}`}>status changes to {b.to ? STATUSES.find(s => s.id === b.to)?.label : "…"}</span></> };
    case "github_pr_open":    return { ic: "⌥",  kind: "Trigger",   sentence: <>When a <span className="slot is-set">GitHub PR is opened</span> linked to a task</> };
    case "schedule":          return { ic: "⏰", kind: "Trigger",   sentence: <>{b.every === "daily" ? <>Every <span className="slot is-set">day at {b.time}</span></> : b.every === "weekly" ? <>Every <span className="slot is-set">{b.day}{b.time ? ` at ${b.time}` : ""}</span></> : "On schedule"}</> };
    case "outcome_set":       return { ic: "⏱",  kind: "Trigger",   sentence: <>When <span className="slot is-set">outcome is set to {b.value}</span></> };
    case "field_equals":      return { ic: "=",  kind: "If",        sentence: <>and <span className="slot is-set">{b.field} = {b.value}</span></> };
    case "field_older_than":  return { ic: "≥",  kind: "If",        sentence: <>and <span className="slot is-set">{b.field} is older than {b.days} days</span></> };
    case "is_overdue":        return { ic: "⏱",  kind: "If",        sentence: <>and the task <span className="slot is-set">is overdue</span></> };
    case "slack_notify":      return { ic: "💬", kind: "Then",      sentence: <>send <span className="slot is-set">Slack DM</span> to <span className="slot is-set">{b.who}</span> in <span className="slot is-set">{b.channel}</span></> };
    case "set_status":        return { ic: "↻",  kind: "Then",      sentence: <>set status to <span className="slot is-set">{STATUSES.find(s => s.id === b.value)?.label}</span></> };
    case "set_assignee":      return { ic: "@",  kind: "Then",      sentence: <>reassign to <span className="slot is-set">{(PEOPLE.find(p => p.id === b.value) || {}).name}</span></> };
    case "comment":           return { ic: "✎",  kind: "Then",      sentence: <>post comment <span className="slot is-set">"{b.text}"</span></> };
    case "add_label":         return { ic: "🏷",  kind: "Then",      sentence: <>add label <span className="slot is-set">{b.value}</span></> };
    case "archive":           return { ic: "📦", kind: "Then",      sentence: <>archive the task</> };
    case "slack_digest":      return { ic: "📊", kind: "Then",      sentence: <>post <span className="slot is-set">sprint digest</span> to <span className="slot is-set">{b.channel}</span></> };
    default:                  return { ic: "•",  kind: "—",         sentence: b.type };
  }
}

function AutomationBlock({ b }) {
  const m = blockMeta(b);
  return (
    <div className={`block ${b.kind}`}>
      <div className="block-ic">{m.ic}</div>
      <div className="block-body">
        <div className="block-kind">{m.kind}</div>
        <div className="block-sentence">{m.sentence}</div>
      </div>
      <div className="block-actions">
        <button title="Move up"><Icons.ChevronRt size={12} style={{ transform: "rotate(-90deg)" }}/></button>
        <button title="Move down"><Icons.ChevronRt size={12} style={{ transform: "rotate(90deg)" }}/></button>
        <button title="Delete"><Icons.More size={14}/></button>
      </div>
    </div>
  );
}

// ── List view ────────────────────────────────────────────────────
function AutomationsListPage({ onOpen }) {
  const [tab, setTab] = React.useState("active");
  const [q, setQ] = React.useState("");
  const [scope, setScope] = React.useState("all");
  const [autos, setAutos] = React.useState(AUTOMATIONS);

  const filtered = autos.filter(a => {
    if (tab === "active" && !a.on) return false;
    if (tab === "off" && a.on) return false;
    if (q && !a.name.toLowerCase().includes(q.toLowerCase())) return false;
    if (scope !== "all" && a.scope !== scope) return false;
    return true;
  });

  function toggle(id) { setAutos(list => list.map(a => a.id === id ? { ...a, on: !a.on } : a)); }

  return (
    <div className="auto">
      <div className="auto-h">
        <div>
          <h1>Automations</h1>
          <p>Recipes that run when something happens — no engineering required.</p>
        </div>
        <div className="actions">
          <button className="btn"><Icons.Activity size={12}/> Run history</button>
          <button className="btn btn-primary" onClick={() => onOpen("new")}><Icons.Plus size={12}/> New automation</button>
        </div>
      </div>

      <div className="auto-tabs">
        {[
          { id: "active",  label: "Active",   ct: autos.filter(a => a.on).length },
          { id: "off",     label: "Disabled", ct: autos.filter(a => !a.on).length },
          { id: "library", label: "Recipe library" },
        ].map(t => (
          <span key={t.id} className={`t ${tab === t.id ? "is-on" : ""}`} onClick={() => setTab(t.id)}>
            {t.label}{t.ct != null && <span className="ct">{t.ct}</span>}
          </span>
        ))}
      </div>

      {tab !== "library" ? (
        <>
          <div className="auto-search-row">
            <input placeholder="Search automations…" value={q} onChange={(e) => setQ(e.target.value)}/>
            <select value={scope} onChange={(e) => setScope(e.target.value)}>
              <option value="all">All scopes</option>
              <option value="All projects">All projects</option>
              {PROJECTS.map(p => <option key={p.id} value={p.name}>{p.name}</option>)}
            </select>
          </div>
          <div className="auto-list">
            {filtered.length === 0 ? (
              <div className="auto-empty">
                <div className="big">🪄</div>
                <div>No automations match.</div>
              </div>
            ) : filtered.map(a => (
              <div key={a.id} className="auto-row" onClick={() => onOpen(a.id)}>
                <div className="ic">⚡</div>
                <div>
                  <div className="nm">{a.name}</div>
                  <div className="desc">{a.desc}</div>
                </div>
                <div className="scope">{a.scope}</div>
                <div className="runs">{a.runs7d} runs<br/><span style={{ color: "var(--ink-faint)", fontSize: 10.5 }}>7 days</span></div>
                <div onClick={(e) => { e.stopPropagation(); toggle(a.id); }}>
                  <span className={`auto-toggle ${a.on ? "on" : ""}`}/>
                </div>
                <Icons.ChevronRt size={14} style={{ color: "var(--ink-faint)" }}/>
              </div>
            ))}
          </div>
        </>
      ) : (
        <div>
          <div style={{ marginBottom: 16, fontSize: 13, color: "var(--ink-muted)" }}>
            Browse pre-built recipes. Click one to customize it for your team.
          </div>
          <div className="recipe-grid">
            {RECIPES.map(r => (
              <div key={r.id} className="recipe-card" onClick={() => onOpen("new")}>
                <span className="badge">{r.tag}</span>
                <div className="nm">{r.nm}</div>
                <div className="recipe-sentence">
                  {r.parts.map((p, i) => i % 2 === 1 ? <b key={i}>{p}{i < r.parts.length - 1 ? " " : ""}</b> : <span key={i}>{p}{i < r.parts.length - 1 ? " " : ""}</span>)}
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// ── Editor view ──────────────────────────────────────────────────
function AutomationEditorPage({ automationId, onBack }) {
  const initial = AUTOMATIONS.find(a => a.id === automationId) || {
    id: "new", name: "Untitled automation", desc: "", on: false, scope: "All projects", runs7d: 0,
    blocks: [{ kind: "trigger", id: "t", type: "status_change", to: "blocked" }],
  };
  const [name, setName] = React.useState(initial.name);
  const [enabled, setEnabled] = React.useState(initial.on);
  const blocks = initial.blocks;

  const HISTORY = [
    { ic: "✓", color: "#14b76a", t: "Ran successfully · status_change → slack_notify",   when: "2h ago",  by: "auto" },
    { ic: "✓", color: "#14b76a", t: "Ran successfully · status_change → slack_notify",   when: "5h ago",  by: "auto" },
    { ic: "✎", color: "#a25ddc", t: "Marcus edited the channel slot",                    when: "Yesterday", by: "mj"   },
    { ic: "⚠", color: "#d97f1f", t: "Skipped — Slack channel not found",                  when: "2d ago",  by: "auto" },
    { ic: "✓", color: "#14b76a", t: "Ran successfully",                                   when: "3d ago",  by: "auto" },
  ];

  return (
    <div className="auto">
      <div className="auto-h">
        <div>
          <button className="btn" onClick={onBack} style={{ marginBottom: 8 }}>
            <Icons.ChevronRt size={12} style={{ transform: "rotate(180deg)" }}/> All automations
          </button>
          <h1 style={{ fontSize: 22 }}>Edit automation</h1>
        </div>
        <div className="actions">
          <span style={{ fontSize: 12, color: "var(--ink-muted)", marginRight: 6, alignSelf: "center" }}>
            {enabled ? "Enabled" : "Disabled"}
          </span>
          <span className={`auto-toggle ${enabled ? "on" : ""}`} onClick={() => setEnabled(e => !e)}/>
          <button className="btn">Discard</button>
          <button className="btn btn-primary">Save changes</button>
        </div>
      </div>

      <div className="auto-editor">
        <div className="editor-canvas">
          <div className="editor-title-row">
            <h2 className="editor-title" contentEditable suppressContentEditableWarning
                onBlur={(e) => setName(e.currentTarget.textContent.trim())}>
              {name}
            </h2>
          </div>
          <div className="editor-meta">Scope · {initial.scope} · Last run {initial.lastRun || "—"} · {initial.runs7d || 0} runs in 7d</div>

          <div className="editor-test-bar">
            <span>🧪</span>
            <span><b>Test mode:</b> use a sample task to dry-run this automation without firing actions.</span>
            <button className="btn">Pick task</button>
            <button className="btn btn-primary">Run test</button>
          </div>

          {blocks.map((b, i) => (
            <React.Fragment key={b.id}>
              <AutomationBlock b={b}/>
              {i < blocks.length - 1 && (
                <div className="block-conn">
                  <div className="line"/>
                  <div className="word">
                    {blocks[i + 1].kind === "condition" ? "AND" : blocks[i + 1].kind === "action" ? "THEN" : ""}
                  </div>
                  <div className="line"/>
                </div>
              )}
            </React.Fragment>
          ))}

          <div className="add-block-row">
            <button className="add-block-btn"><Icons.Plus size={12}/> Add condition or action</button>
          </div>
        </div>

        <aside className="editor-side">
          <h4>Run history</h4>
          {HISTORY.map((h, i) => (
            <div key={i} className="ts-row">
              <span className="ic" style={{ color: h.color }}>{h.ic}</span>
              <div>
                <div style={{ color: "var(--ink-strong)", fontSize: 12.5 }}>{h.t}</div>
                <div className="dt">{h.when} · {h.by === "auto" ? "system" : (PEOPLE.find(p => p.id === h.by) || {}).name}</div>
              </div>
            </div>
          ))}
          <h4 style={{ marginTop: 22 }}>Settings</h4>
          <div className="ts-row" style={{ gridTemplateColumns: "1fr" }}>
            <div>
              <div style={{ color: "var(--ink-muted)", fontSize: 11 }}>Stop after errors</div>
              <div style={{ color: "var(--ink-strong)" }}><b>3 failures</b> in a row</div>
            </div>
          </div>
          <div className="ts-row" style={{ gridTemplateColumns: "1fr" }}>
            <div>
              <div style={{ color: "var(--ink-muted)", fontSize: 11 }}>Owner</div>
              <div style={{ color: "var(--ink-strong)", display: "flex", alignItems: "center", gap: 6 }}>
                <Avatar person={PEOPLE[0]} size="sm"/> Aya Okafor
              </div>
            </div>
          </div>
        </aside>
      </div>
    </div>
  );
}

function AutomationsApp({ startInEditor = null }) {
  const [view, setView] = React.useState(startInEditor ? { kind: "editor", id: startInEditor } : { kind: "list" });
  return (
    <div className="app" style={{ position: "relative", overflow: "hidden" }}>
      <Sidebar activeProject={null} currentUserId="ay" access={PROJECT_ACCESS}/>
      <div className="main">
        <Topbar
          crumbs={view.kind === "list" ? ["Acme Labs", "Automations"] : ["Acme Labs", "Automations", "Edit"]}
          searchValue="" onSearch={() => {}} onOpenPalette={() => {}}
          currentUserId="ay" people={PEOPLE}/>
        {view.kind === "list"
          ? <AutomationsListPage onOpen={(id) => setView({ kind: "editor", id })}/>
          : <AutomationEditorPage automationId={view.id} onBack={() => setView({ kind: "list" })}/>}
      </div>
    </div>
  );
}

Object.assign(window, {
  AutomationsListPage, AutomationEditorPage, AutomationsApp,
});
