// ui.jsx — shared primitives for the command center
(function () {
  const { useState } = React;
  const h = React.createElement;

  const toneColor = { blue: "var(--blue)", green: "var(--green)", amber: "var(--amber)", violet: "var(--violet)", red: "var(--red)" };
  const toneBg = { blue: "var(--blue-soft)", green: "var(--green-soft)", amber: "var(--amber-soft)", violet: "var(--violet-soft)", red: "var(--red-soft)" };

  // a11y for modal dialogs: Escape closes, focus moves in + is trapped, and is restored on unmount.
  const FOCUSABLE = '[href],button:not([disabled]),input:not([disabled]),textarea:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex="-1"])';
  function useDialogA11y(onClose) {
    const ref = React.useRef(null);
    const closeRef = React.useRef(onClose);
    closeRef.current = onClose;
    React.useEffect(() => {
      const node = ref.current;
      const prev = document.activeElement;
      const focusables = () => Array.prototype.slice.call(node ? node.querySelectorAll(FOCUSABLE) : []);
      (focusables()[0] || node).focus();
      function onKey(e) {
        if (e.key === "Escape") { e.stopPropagation(); closeRef.current && closeRef.current(); return; }
        if (e.key !== "Tab" || !node) return;
        const items = focusables();
        if (!items.length) { e.preventDefault(); node.focus(); return; }
        const first = items[0], last = items[items.length - 1];
        if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
        else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
      }
      document.addEventListener("keydown", onKey, true);
      return () => {
        document.removeEventListener("keydown", onKey, true);
        if (prev && prev.focus) prev.focus();
      };
    }, []);
    return ref;
  }
  // derive a string aria-label from a title that may be a React element
  function dialogLabel(title) {
    if (typeof title === "string") return title;
    if (title == null) return undefined;
    // element title (e.g. BriefReveal "Drafting · <role>"): pull the concatenated text so the dialog still has an accessible name
    const pull = (n) => n == null || typeof n === "boolean" ? "" : (typeof n === "string" || typeof n === "number") ? String(n) : Array.isArray(n) ? n.map(pull).join("") : (n.props && n.props.children != null) ? pull(n.props.children) : "";
    return pull(title).trim() || undefined;
  }

  function Card({ children, style, className = "", interactive, onClick, innerRef, ...props }) {
    const domProps = Object.assign({}, props);
    delete domProps.interactive;
    delete domProps.hover;
    delete domProps.innerRef;
    if (typeof onClick === "function") {
      const existingKeyDown = domProps.onKeyDown;
      const disabled = domProps["aria-disabled"] === true || domProps["aria-disabled"] === "true";
      if (domProps.role == null) domProps.role = "button";
      if (domProps.tabIndex == null) domProps.tabIndex = 0;
      if (domProps["data-card-keyboard"] == null) domProps["data-card-keyboard"] = "true";
      domProps.onKeyDown = (e) => {
        if (typeof existingKeyDown === "function") existingKeyDown(e);
        if (disabled || e.defaultPrevented) return;
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault();
          onClick(e);
        }
      };
    }
    return h("div", Object.assign({}, domProps, { ref: innerRef, className: `glass ${interactive ? "glass-hover" : ""} ${className}`, style: { ...style, cursor: onClick ? "pointer" : undefined }, onClick }), children);
  }

  function CardHead({ title, sub, right, icon, headingLevel = 3, headingId }) {
    const Heading = headingLevel === 2 ? "h2" : headingLevel === 4 ? "h4" : "h3";
    return h("div", { className: "card-head" },
      h("div", { className: "row gap10" },
        icon && h("div", { style: { width: 30, height: 30, borderRadius: 9, display: "grid", placeItems: "center", background: "var(--blue-soft)", color: "var(--blue)" } }, h(window.Icon, { name: icon, size: 16 })),
        h("div", null,
          h(Heading, { id: headingId }, title),
          sub && h("div", { style: { fontSize: 12, color: "var(--text-faint)", marginTop: 2 } }, sub))),
      right);
  }

  // status badge mapping
  const STATUS = {
    Active: "green", Pilot: "amber", "Needs Review": "amber", Paused: "neutral",
    Connected: "green", "Read-only": "blue", "Approval Required": "amber", Disabled: "neutral",
    Running: "blue", "Awaiting Approval": "amber", Completed: "green",
    Allowed: "green", Denied: "red", "Pending Approval": "amber",
    Passing: "green", Watch: "amber",
    Low: "green", Medium: "amber", High: "red",
  };
  function Badge({ children, tone, dot, status }) {
    const t = tone || STATUS[status || children] || "neutral";
    return h("span", { className: `badge badge-${t}` }, dot && h("span", { className: "dot" }), children);
  }

  function RiskBadge({ level }) {
    return h(Badge, { status: level }, h("span", { className: "dot" }), level);
  }

  function Button({ children, variant = "", icon, iconRight, sm, onClick, style, title, ariaLabel, disabled, ...rest }) {
    const cls = ["btn", variant && `btn-${variant}`, sm && "btn-sm"].filter(Boolean).join(" ");
    return h("button", Object.assign({ type: "button", className: cls, onClick, style, title, "aria-label": ariaLabel, disabled }, rest),
      icon && h(window.Icon, { name: icon, size: sm ? 14 : 15 }),
      children,
      iconRight && h(window.Icon, { name: iconRight, size: sm ? 14 : 15 }));
  }

  // KPI stat card
  function KPI({ data, onClick, ...rest }) {
    const c = toneColor[data.tone] || toneColor.blue;
    return h(Card, Object.assign({}, rest, { interactive: true, onClick, style: { padding: 16, display: "flex", flexDirection: "column", gap: 10, minHeight: 118, position: "relative" } }),
      onClick && h(window.Icon, { name: "chevRight", size: 14, color: "var(--text-faint)", style: { position: "absolute", top: 14, right: 14, opacity: 0.5 } }),
      h("div", { className: "row between", style: { alignItems: "flex-start" } },
        h("div", { style: { width: 34, height: 34, borderRadius: 10, display: "grid", placeItems: "center", background: toneBg[data.tone], color: c } },
          h(window.Icon, { name: data.icon, size: 17 })),
        data.spark && h(window.Spark, { data: data.spark, color: c, width: 72, height: 26 })),
      h("div", null,
        h("div", { className: "mono", style: { fontSize: 26, fontWeight: 700, letterSpacing: "-0.02em" } }, data.v),
        h("div", { style: { fontSize: 12.5, color: "var(--text-dim)", marginTop: 2, fontWeight: 500 } }, data.l),
        data.sub && h("div", { style: { fontSize: 11.5, color: "var(--text-faint)", marginTop: 3 } }, data.sub)));
  }

  // employee avatar
  function Avatar({ emp, size = 34 }) {
    return h("div", { style: { width: size, height: size, borderRadius: size * 0.3, flex: "none", display: "grid", placeItems: "center",
      background: `linear-gradient(135deg, ${emp.color}, ${emp.color}cc)`, color: "#fff", fontWeight: 700, fontSize: size * 0.34, fontFamily: "var(--mono)" } }, emp.initials);
  }

  function PageHeader({ eyebrow, title, sub, right, icon }) {
    return h("div", { className: "page-header" },
      h("div", { className: "page-header-main" },
        icon && h("div", { className: "page-header-icon" }, h(window.Icon, { name: icon, size: 20 })),
        h("div", { className: "page-header-copy" },
          eyebrow && h("div", { className: "eyebrow", style: { marginBottom: 8 } }, eyebrow),
          h("h1", { className: "page-header-title" }, title),
          sub && h("p", { className: "page-header-sub" }, sub))),
      right && h("div", { className: "page-header-actions" }, right));
  }

  // segmented control — options accepts plain strings ["A","B"] OR {value,label,attrs} objects, or a mix.
  function Segmented({ options, value, onChange, blue, disabled, title, ariaLabel, className = "" }) {
    const groupProps = ariaLabel ? { role: "group", "aria-label": ariaLabel } : {};
    return h("div", Object.assign({}, groupProps, { className: ["segmented", className].filter(Boolean).join(" "), style: { display: "inline-flex", flexWrap: "wrap", gap: 3, padding: 3, background: "var(--bg-3)", border: "1px solid var(--border)", borderRadius: 10, maxWidth: "100%", minWidth: 0 } }),
      options.map((o) => {
        const v = typeof o === "string" ? o : o.value;
        const label = typeof o === "string" ? o : o.label;
        const attrs = typeof o === "string" ? {} : (o.attrs || {});
        const active = v === value;
        return h("button", Object.assign({}, attrs, { key: v, type: "button", className: "segmented-option", "aria-pressed": active, onClick: disabled ? undefined : () => onChange(v), disabled, title,
          style: { fontFamily: "var(--font)", fontSize: 12.5, fontWeight: 600, padding: "5px 12px", borderRadius: 7, border: "none", cursor: disabled ? "not-allowed" : "pointer", whiteSpace: "nowrap", opacity: disabled && !active ? .55 : 1,
            background: active ? "var(--bg-2)" : "transparent", color: active ? "var(--text)" : "var(--text-dim)",
            boxShadow: active ? "var(--shadow-sm)" : "none", transition: "all .15s" } }), label);
      }));
  }

  function Toggle({ on, onChange, blue, disabled, title, ...rest }) {
    const act = () => { if (!disabled) onChange(!on); };
    return h("div", Object.assign({
      className: `switch ${blue ? "blue" : ""} ${on ? "on" : ""} ${disabled ? "disabled" : ""}`,
      role: "switch",
      "aria-checked": !!on,
      "aria-disabled": !!disabled,
      tabIndex: disabled ? -1 : 0,
      title: title || "",
      onClick: act,
      onKeyDown: (e) => { if ((e.key === "Enter" || e.key === " ") && !disabled) { e.preventDefault(); act(); } },
    }, rest), h("i"));
  }

  function ProgressBar({ value, tone = "", height = 6, ariaLabel, className = "", style, ...rest }) {
    const bounded = Math.max(0, Math.min(100, Number(value) || 0));
    const semantics = ariaLabel
      ? { role: "progressbar", "aria-label": ariaLabel, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": bounded }
      : { "aria-hidden": "true" };
    return h("div", Object.assign({}, rest, semantics, { className: ["bar", tone, className].filter(Boolean).join(" "), style: { ...style, height } }), h("i", { style: { width: `${bounded}%` } }));
  }

  function EmptyHint({ icon, text, children }) {
    return h("div", { style: { padding: 30, textAlign: "center", color: "var(--text-faint)" } },
      icon && h(window.Icon, { name: icon, size: 22, style: { opacity: 0.5 } }),
      h("div", { style: { marginTop: 8, fontSize: 13 } }, text != null ? text : children));
  }

  function FutureStep({ text, children, tone = "blue", compact = false, label = "Next step" }) {
    const raw = text || children;
    const body = typeof raw === "string" ? raw.replace(/^Next:\s*/, "") : raw;
    if (!body) return null;
    return h("div", { className: `future-step future-${tone} ${compact ? "compact" : ""}` },
      h("span", { className: "future-ico" }, h(window.Icon, { name: "arrowRight", size: compact ? 12 : 14 })),
      h("span", null, h("b", null, label), body));
  }

  // centered modal dialog
  function Modal({ title, sub, icon, onClose, children, footer, width = 520, ...rest }) {
    const dialogRef = useDialogA11y(onClose);
    return h("div", { onClick: onClose, style: { position: "fixed", inset: 0, zIndex: 70, display: "grid", placeItems: "center", padding: 20,
      background: "rgba(20,28,45,0.4)", backdropFilter: "blur(3px)", animation: "fadeUp .2s" } },
      h("div", Object.assign({ ref: dialogRef, role: "dialog", "aria-modal": "true", "aria-label": dialogLabel(title), tabIndex: -1, onClick: (e) => e.stopPropagation(), className: "glass", style: { width, maxWidth: "94vw", maxHeight: "88vh", display: "flex", flexDirection: "column", boxShadow: "var(--shadow-lg)", padding: 0, animation: "fadeUp .24s", outline: "none" } }, rest),
        h("div", { className: "row between", style: { padding: "16px 20px", borderBottom: "1px solid var(--border)" } },
          h("div", { className: "row gap10" },
            icon && h("div", { style: { width: 32, height: 32, borderRadius: 9, background: "var(--blue-soft)", color: "var(--blue)", display: "grid", placeItems: "center", flex: "none" } }, h(window.Icon, { name: icon, size: 17 })),
            h("div", null, h("div", { style: { fontWeight: 600, fontSize: 15.5, letterSpacing: "-0.01em" } }, title), sub && h("div", { style: { fontSize: 12.5, color: "var(--text-faint)", marginTop: 2 } }, sub))),
          h(Button, { variant: "ghost", icon: "x", ariaLabel: "Close", onClick: onClose })),
        h("div", { style: { padding: 20, overflowY: "auto" } }, children),
        footer && h("div", { className: "row gap8", style: { padding: "14px 20px", borderTop: "1px solid var(--border)", justifyContent: "flex-end" } }, footer)));
  }

  // labelled section for modal/page detail content
  function Section({ title, children, style }) {
    return h("div", { style: { marginBottom: 22, ...style } },
      title && h("div", { style: { fontSize: 11, fontWeight: 700, letterSpacing: ".08em", color: "var(--text-faint)", marginBottom: 10 } }, title.toUpperCase()), children);
  }

  // ---- RunTrace: the single primitive that renders one office.runs[] entry as a visible timeline ----
  // trigger -> read named source -> draft -> check -> gate (the human pause) -> sent/filed. Exported on
  // window so every screen block can use it. English-source step labels localize via dict; run title +
  // source snippets are data-derived 繁中 (mirror inbox/auditLog). No emoji — glyphs come from window.Icon.
  const STEP_META = {
    trigger:  { icon: "clock",  label: "Started" },
    read:     { icon: "search", label: "Read the file" },
    draft:    { icon: "edit",   label: "Drafted from file" },
    check:    { icon: "shield", label: "Checked against file" },
    gate:     { icon: "stamp",  label: "Waiting for your approval" },
    buffer:   { icon: "zap",    label: "Repeat work · 10-minute undo" },
    send:     { icon: "send",   label: "Sent" },
    file:     { icon: "folder", label: "Saved" },
    nosource: { icon: "ban",    label: "Stopped — file missing" },
  };
  const TRIGGER_ICON = { schedule: "clock", event: "mail", manual: "user", demo: "play" };
  function runStatusLabel(run) {
    return ({
      "awaiting-approval": "Waiting for approval", buffering: "Waiting to send · can undo",
      sent: "Sent", filed: "Saved", recalled: "Undone", rejected: "Returned",
      nosource: "Stopped — file missing", running: "Working",
    })[run.status] || run.status;
  }
  function scenarioStateLabel(state) {
    return ({
      done: "Step saved", current: "Current step", pending: "Next",
      blocked: "File missing", rejected: "Returned", recalled: "Undone",
    })[state] || (state || "Next");
  }
  function RunTrace({ run, compact, onOpenSource, onOpenInbox }) {
    const [openStep, setOpenStep] = useState(null);
    const [openScenarioStep, setOpenScenarioStep] = useState(null);
    if (!run) return null;
    const runDomId = String(run.id || "run").replace(/[^a-zA-Z0-9_-]/g, "-");
    const steps = run.steps || [];
    const scenarioSteps = run.scenarioSteps || [];
    const trigger = run.trigger || {};
    const displayTrigger = window.runTriggerDisplay ? window.runTriggerDisplay(trigger, run, window.OFFICE || {}) : (trigger.label || "Work");
    const displayTriggerTime = window.officeTimeDisplay ? window.officeTimeDisplay(trigger.at) : (trigger.at || "");
    const displayCaveat = window.runCaveatDisplay ? window.runCaveatDisplay(run.caveat) : run.caveat;
    const displaySource = (value) => window.runSourceDisplay ? window.runSourceDisplay(value) : value;
    const localDisplay = (value) => window.I18N ? window.I18N.t(value) : value;
    const formatDisplay = (key, values) => window.I18N
      ? window.I18N.format(key, Object.fromEntries(Object.entries(values).map(([name, value]) => [name, localDisplay(value)])))
      : key.replace(/\{([A-Za-z0-9_]+)\}/g, (token, name) => Object.prototype.hasOwnProperty.call(values, name) ? values[name] : token);
    const tIcon = TRIGGER_ICON[trigger.type] || "clock";
    const muted = run.status === "rejected" || run.status === "nosource" || run.status === "recalled";
    const stateLabel = (state) => ({
      done: "Done", current: "Current", pending: "Pending", rejected: "Returned", recalled: "Undone",
    })[state] || (state || "Pending");
    const stepSource = (s) => {
      if (s && s.source) return s.source;
      if (s && s.file) return { file: s.file, snippet: s.snippet || "", fileId: s.fileId || null };
      return (run.sources || [])[0] || null;
    };
    const stepApprovalId = (s) => {
      if (s && s.inboxId) return s.inboxId;
      if (s && s.originalInboxId) return s.originalInboxId;
      if (s && (s.kind === "draft" || s.kind === "gate" || s.kind === "send" || s.kind === "file")) return run.inboxId || run.originalInboxId || null;
      return null;
    };
    const stepDetail = (s, src, approvalId) => {
      const file = src && displaySource(src.file || src.name);
      if (s.kind === "trigger") return formatDisplay("Work started by {trigger} at {when}.", { trigger: displayTrigger || "this task", when: displayTriggerTime || "this session" });
      if (s.kind === "read") return file ? "File checked: " + file + "." : "An approved file is required.";
      if (s.kind === "draft") return approvalId ? "Draft is in My Desk as " + approvalId + "." : "Draft is ready but still needs approval.";
      if (s.kind === "check") return "The file, rules and result are checked before review.";
      if (s.kind === "gate") return approvalId ? "Review " + approvalId + " in My Desk: approve, edit, return or start again." : "Approval is required before anything is sent.";
      if (s.kind === "buffer") return "You can still undo during the 10-minute wait.";
      if (s.kind === "send") return s.state === "done" ? "Sent and saved in History." : "Sending stays locked until approval.";
      if (s.kind === "file") return s.state === "done" ? "Saved in Files and History." : "The file waits for owner approval.";
      if (s.kind === "nosource") return "No matching file was found, so no draft was made.";
      return "This step is saved in work history.";
    };
    const metaCard = (key, value) => value ? h("div", { className: "rt-meta" }, h("b", null, key), h("span", null, value)) : null;
    const scenarioInspector = (s, i, detailId) => {
      const ev = s.evidence || {};
      const source = displaySource(ev.source || s.source || "");
      const note = ev.note || s.note || "";
      const state = ev.state || s.state;
      return h("div", { id: detailId, className: "rt-inspector", "data-run-trace-scenario-detail": String(i), "data-run-id": run.id || "", "data-run-workorder-id": run.workOrderId || "" },
        h("div", { className: "rt-inspector-head" },
          h("div", null,
            h("b", null, "Step " + (i + 1) + " · " + (s.title || "Work step")),
            h("span", null, ev.outcome || s.outcome || "Saved work step.")),
          h(Badge, { tone: state === "done" ? "green" : state === "blocked" ? "amber" : state === "current" ? "blue" : "neutral" }, scenarioStateLabel(state))),
        h("div", { className: "rt-meta-grid" },
          metaCard("App", ev.tool || s.tool),
          metaCard("File", source),
          metaCard("Checks", ev.summary || ev.gate),
          metaCard("User note", note),
          metaCard("Work", run.id),
          metaCard("Task", run.workOrderId)));
    };
    function inspector(s, i, m, src, approvalId, detailId) {
      const sourceName = src && displaySource(src.file || src.name);
      const sourceLabel = src && ((src.fileId ? "《" + sourceName + "》" : sourceName) + (src.snippet ? " — " + src.snippet : ""));
      const actionButtons = [
        src && src.fileId && onOpenSource ? h("button", { key: "src", type: "button", className: "ac-chip", "data-run-trace-action": "open-source", "data-run-id": run.id || "", "data-run-source-file-id": src.fileId || "", onClick: () => onOpenSource(src) }, "Open file") : null,
        approvalId && onOpenInbox ? h("button", { key: "ap", type: "button", className: "ac-chip", "data-run-trace-action": "open-approval", "data-run-id": run.id || "", "data-approval-id": approvalId || "", onClick: () => onOpenInbox(approvalId) }, "Open My Desk") : null,
      ].filter(Boolean);
      return h("div", { id: detailId, className: "rt-inspector", "data-run-trace-step-detail": String(i), "data-run-step-kind": s.kind || "", "data-run-id": run.id || "", "data-run-workorder-id": run.workOrderId || "" },
        h("div", { className: "rt-inspector-head" },
          h("div", null,
            h("b", null, "Step " + (i + 1) + " · " + m.label),
            h("span", null, stepDetail(s, src, approvalId))),
          h(Badge, { tone: s.state === "done" ? "green" : s.state === "current" ? "blue" : s.state === "rejected" ? "red" : "neutral" }, stateLabel(s.state))),
        h("div", { className: "rt-meta-grid" },
          metaCard("Work", run.id),
          metaCard("Task", run.workOrderId),
          metaCard("File", sourceLabel),
          metaCard("My Desk item", approvalId),
          metaCard("Ready", run.conf),
          metaCard("Note", displayCaveat)),
        actionButtons.length ? h("div", { className: "rt-actions" }, actionButtons) : null);
    }
    const header = h("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginBottom: compact ? 6 : 10 } },
      h("span", { style: { display: "inline-flex", alignItems: "center", gap: 5, fontSize: 12, fontWeight: 600, padding: "2px 8px", borderRadius: 999, background: "var(--blue-soft)", color: "var(--blue)" } },
        h(window.Icon, { name: tIcon, size: 13 }), displayTrigger),
      h("span", { style: { fontSize: 12, color: "var(--text-faint)" } }, displayTriggerTime),
      run.conf && h("span", { style: { display: "inline-flex", alignItems: "center", gap: 4, fontSize: 11, color: "var(--text-faint)" } },
        h("span", null, "Ready"), h("span", { style: { fontWeight: 600, color: "var(--text-dim)" } }, run.conf)),
      displayCaveat && h("span", { style: { fontSize: 11, color: "var(--text-faint)", marginLeft: "auto" } }, displayCaveat));
    if (compact) {
      const out = steps[steps.length - 1] || { kind: "draft", state: run.status || "running" };
      const m = STEP_META[out.kind] || STEP_META.draft;
      const clickable = onOpenInbox && run.inboxId;
      const currentScenario = scenarioSteps.find((s) => s.state === "current" || s.state === "blocked") || scenarioSteps.find((s) => s.state === "pending") || scenarioSteps[scenarioSteps.length - 1];
      const openInbox = () => clickable && onOpenInbox(run.inboxId);
      const keyOpen = (ev) => {
        if (!clickable || (ev.key !== "Enter" && ev.key !== " ")) return;
        ev.preventDefault();
        openInbox();
      };
      return h("div", { className: clickable ? "glass-hover" : "", role: clickable ? "button" : undefined, tabIndex: clickable ? 0 : undefined, "aria-label": clickable ? "Open My Desk item " + run.inboxId + " for " + (run.title || "work history") : undefined, "data-run-trace": run.id || "", "data-run-trace-compact": "true", "data-run-workorder-id": run.workOrderId || "", "data-approval-id": run.inboxId || "", onClick: clickable ? openInbox : undefined, onKeyDown: clickable ? keyOpen : undefined,
          style: { padding: 12, borderRadius: 12, border: "1px solid var(--border)", background: "var(--bg-2)", cursor: clickable ? "pointer" : "default" } },
        header,
        h("div", { style: { display: "flex", alignItems: "center", gap: 8, fontSize: 13 } },
          h(window.Icon, { name: m.icon, size: 14, color: "var(--blue)" }),
          h("span", { style: { fontWeight: 600 } }, run.title),
          h("span", { style: { marginLeft: "auto", fontSize: 11, fontWeight: 600, color: muted ? "var(--text-faint)" : "var(--green)" } }, runStatusLabel(run))),
        currentScenario && h("div", { className: "rt-step-sub", style: { marginTop: 6 } },
          "Current step: " + (currentScenario.title || "Work step") + " · " + scenarioStateLabel(currentScenario.state)));
    }
    return h("div", { "data-run-trace": run.id || "", "data-run-trace-compact": "false", "data-run-workorder-id": run.workOrderId || "", style: { padding: 14, borderRadius: 14, border: "1px solid var(--border)", background: "var(--bg-2)" } },
      header,
      h("div", { style: { fontWeight: 700, marginBottom: 10 } }, run.title),
      scenarioSteps.length ? h("div", { className: "rt-scenario-list", "aria-label": "Work steps" },
        scenarioSteps.map((s, i) => {
          const cur = s.state === "current";
          const done = s.state === "done";
          const blocked = s.state === "blocked";
          const col = blocked ? "var(--amber)" : cur ? "var(--blue)" : done ? "var(--green)" : "var(--text-faint)";
          const open = openScenarioStep === i;
          const detailId = "rt-scenario-detail-" + runDomId + "-" + i;
          return h("div", { key: i, className: "rt-scenario-item" },
            h("button", { type: "button", className: "rt-step-row", "data-run-trace-scenario-step": String(i), "data-run-scenario-state": s.state || "", onClick: () => setOpenScenarioStep(open ? null : i), "aria-expanded": open ? "true" : "false", "aria-controls": open ? detailId : undefined },
              h("span", { className: "rt-step-mark" + (done ? " done" : (cur || blocked) ? " current" : ""), style: { "--rt-color": col } },
                h(window.Icon, { name: blocked ? "alert" : cur ? "dot" : "check", size: 13, color: done || cur || blocked ? "#fff" : "var(--text-faint)" })),
              h("span", { style: { minWidth: 0 } },
                h("span", { className: "rt-step-title", style: { fontWeight: cur || blocked ? 800 : 600 } }, "Step " + (i + 1) + " · " + (s.title || "Work step")),
                h("span", { className: "rt-step-sub" }, (s.evidence && (s.evidence.summary || s.evidence.source)) || s.outcome || "This step will update when it is complete.")),
              h("span", { className: "rt-step-state" }, scenarioStateLabel(s.state))),
            open && scenarioInspector(s, i, detailId));
        })) : null,
      h("ol", { style: { listStyle: "none", margin: 0, padding: 0 } },
        steps.map((s, i) => {
          const m = STEP_META[s.kind] || STEP_META.draft;
          const cur = s.state === "current";
          const done = s.state === "done";
          const bad = s.state === "rejected" || s.state === "recalled";
          const col = bad ? "var(--red)" : cur ? "var(--blue)" : done ? "var(--green)" : "var(--text-faint)";
          const src = stepSource(s);
          const approvalId = stepApprovalId(s);
          const sourceName = src && displaySource(src.file || src.name);
          const sourceText = src && ((src.fileId ? "《" + sourceName + "》" : sourceName) + (src.snippet ? " — " + src.snippet : ""));
          const open = openStep === i;
          const detailId = "rt-step-detail-" + runDomId + "-" + i;
          return h("li", { key: i, style: { opacity: s.state === "pending" ? 0.58 : 1 } },
            h("button", { type: "button", className: "rt-step-row", "data-run-trace-step": String(i), "data-run-step-kind": s.kind || "", "data-run-step-state": s.state || "", onClick: () => setOpenStep(open ? null : i), "aria-expanded": open ? "true" : "false", "aria-controls": open ? detailId : undefined },
              h("span", { className: "rt-step-mark" + (done ? " done" : (cur || bad) ? " current" : ""), style: { "--rt-color": col } },
                h(window.Icon, { name: cur ? "dot" : ((s.kind === "gate" || s.kind === "buffer" || s.kind === "nosource") ? m.icon : "check"),
                  size: 13, color: done || cur || bad ? "#fff" : "var(--text-faint)" })),
              h("span", { style: { minWidth: 0 } },
                h("span", { className: "rt-step-title", style: { fontWeight: cur ? 800 : 600 } }, m.label),
                sourceText && h("span", { className: "rt-step-sub" }, sourceText),
                s.kind === "gate" && cur && h("span", { className: "rt-step-sub" }, "Approve / Edit / Return")),
              h("span", { className: "rt-step-state" }, stateLabel(s.state))),
            open && inspector(s, i, m, src, approvalId, detailId));
        })));
  }
  window.RunTrace = RunTrace;

  Object.assign(window, { Card, CardHead, Badge, RiskBadge, Button, KPI, Avatar, PageHeader, Segmented, Toggle, ProgressBar, EmptyHint, FutureStep, Modal, Section, STATUS, RunTrace });
})();
