// Canvas Directions — stream part vocabulary + shared atoms.
// Receipts are the workhorse: actor · action · scope · time · restore/open/record.
// Loads after canvas-data.js. Exports to window at the end.

const DS = window.StimulusDesignSystem_bb8fa3 || {};
const ConsentChip = (props) => { const C = (window.StimulusDesignSystem_bb8fa3 || {}).ConsentChip; return C ? React.createElement(C, props) : null; };
const WorkStateChip = (props) => { const C = (window.StimulusDesignSystem_bb8fa3 || {}).WorkStateChip; return C ? React.createElement(C, props) : null; };

// ── Icons — Lucide path data, 2px stroke, currentColor ──────────────────
const ICON_PATHS = {
  search: <g><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.35-4.35"></path></g>,
  lock: <g><rect x="3" y="11" width="18" height="11" rx="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></g>,
  check: <path d="M20 6 9 17l-5-5"></path>,
  x: <g><path d="M18 6 6 18"></path><path d="m6 6 12 12"></path></g>,
  clock: <g><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></g>,
  history: <g><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><path d="M3 3v5h5"></path><path d="M12 7v5l4 2"></path></g>,
  open: <g><path d="M7 17 17 7"></path><path d="M7 7h10v10"></path></g>,
  chevD: <path d="m6 9 6 6 6-6"></path>,
  chevR: <path d="m9 18 6-6-6-6"></path>,
  chevL: <path d="m15 18-6-6 6-6"></path>,
  home: <g><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></g>,
  building: <g><path d="M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z"></path><path d="M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2"></path><path d="M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2"></path><path d="M10 6h4"></path><path d="M10 10h4"></path><path d="M10 14h4"></path><path d="M10 18h4"></path></g>,
  briefcase: <g><rect x="2" y="7" width="20" height="14" rx="2"></rect><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path></g>,
  share: <g><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><path d="m8.59 13.51 6.83 3.98"></path><path d="m15.41 6.51-6.82 3.98"></path></g>,
  chart: <g><path d="M3 3v16a2 2 0 0 0 2 2h16"></path><path d="M18 17V9"></path><path d="M13 17V5"></path><path d="M8 17v-3"></path></g>,
  user: <g><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></g>,
  users: <g><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M22 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></g>,
  filter: <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46"></polygon>,
  list: <g><path d="M8 6h13"></path><path d="M8 12h13"></path><path d="M8 18h13"></path><path d="M3 6h.01"></path><path d="M3 12h.01"></path><path d="M3 18h.01"></path></g>,
  pause: <g><rect x="14" y="4" width="4" height="16" rx="1"></rect><rect x="6" y="4" width="4" height="16" rx="1"></rect></g>,
  alert: <g><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 20h16a2 2 0 0 0 1.73-2Z"></path><path d="M12 9v4"></path><path d="M12 17h.01"></path></g>,
  send: <g><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"></path><path d="m21.854 2.147-10.94 10.939"></path></g>,
  eye: <g><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"></path><circle cx="12" cy="12" r="3"></circle></g>,
  settings: <g><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"></path><circle cx="12" cy="12" r="3"></circle></g>,
  panelL: <g><rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="M9 3v18"></path></g>,
  logout: <g><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" x2="9" y1="12" y2="12"></line></g>,
  penSquare: <g><path d="M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.375 2.625a2.121 2.121 0 1 1 3 3L12 15l-4 1 1-4Z"></path></g>,
  clipboard: <g><rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path></g>,
  pieChart: <g><path d="M21.21 15.89A10 10 0 1 1 8 2.83"></path><path d="M22 12A10 10 0 0 0 12 2v10z"></path></g>,
  sparkles: <g><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"></path></g>,
  calendar: <g><path d="M8 2v4"></path><path d="M16 2v4"></path><rect width="18" height="18" x="3" y="4" rx="2"></rect><path d="M3 10h18"></path></g>,
  clock: <g><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></g>,
  star: <path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.12 2.12 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.12 2.12 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.12 2.12 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.12 2.12 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.12 2.12 0 0 0 1.597-1.16z"></path>,
  flame: <path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z"></path>,
  search: <g><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.3-4.3"></path></g>,
  exchange: <g><path d="m16 3 4 4-4 4"></path><path d="M20 7H4"></path><path d="m8 21-4-4 4-4"></path><path d="M4 17h16"></path></g>,
  plus: <g><path d="M5 12h14"></path><path d="M12 5v14"></path></g>,
  download: <g><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" x2="12" y1="15" y2="3"></line></g>,
  upload: <g><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" x2="12" y1="3" y2="15"></line></g>,
  globe: <g><circle cx="12" cy="12" r="10"></circle><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"></path><path d="M2 12h20"></path></g>,
  grid: <g><rect width="7" height="7" x="3" y="3" rx="1"></rect><rect width="7" height="7" x="14" y="3" rx="1"></rect><rect width="7" height="7" x="14" y="14" rx="1"></rect><rect width="7" height="7" x="3" y="14" rx="1"></rect></g>,
  mail: <g><rect width="20" height="16" x="2" y="4" rx="2"></rect><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"></path></g>,
  linkedin: <g><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect width="4" height="12" x="2" y="9"></rect><circle cx="4" cy="4" r="2"></circle></g>,
  bolt: <path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"></path>,
  copy: <g><rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path></g>,
  maximize: <g><path d="M8 3H5a2 2 0 0 0-2 2v3"></path><path d="M21 8V5a2 2 0 0 0-2-2h-3"></path><path d="M3 16v3a2 2 0 0 0 2 2h3"></path><path d="M16 21h3a2 2 0 0 0 2-2v-3"></path></g>,
  minimize: <g><path d="M8 3v3a2 2 0 0 1-2 2H3"></path><path d="M21 8h-3a2 2 0 0 1-2-2V3"></path><path d="M3 16h3a2 2 0 0 1 2 2v3"></path><path d="M16 21v-3a2 2 0 0 1 2-2h3"></path></g>,
  shield: <path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"></path>,
  arrowUp: <g><path d="m5 12 7-7 7 7"></path><path d="M12 19V5"></path></g>,
};
function Icon({ name, size = 14, style }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
      style={Object.assign({ flex: "none" }, style)} aria-hidden="true">{ICON_PATHS[name]}</svg>
  );
}

// Actor glyph: you = neutral initials · agent = brand arrowhead (the workspace, alive)
function ActorGlyph({ actor }) {
  if (actor === "you") return <span className="cvActor cvActorYou">PN</span>;
  return (
    <span className="cvActor cvActorAgent">
      <svg width="8" height="8" viewBox="0 0 8 8" aria-hidden="true"><path d="M1 7 7 4 1 1v2.4L4.4 4 1 4.6Z" fill="currentColor"></path></svg>
    </span>
  );
}

// ── User utterance — plain, right-weighted, no heavy bubble ─────────────
function Utterance({ text }) {
  return (
    <div className="cvUtter" data-part="utterance">
      <span className="cvUtterText">{text}</span>
      <ActorGlyph actor="you" />
    </div>
  );
}

// ── Agent prose — judgment, never data; may end with suggested intents ──
function AgentProse({ text, suggestions, onSuggest }) {
  return (
    <div className="cvProse" data-part="prose">
      <div className="cvProseBody">
        <p>{text}</p>
        {suggestions && suggestions.length > 0 && (
          <div className="cvSugg">
            {suggestions.map((s) => (
              <button key={s} type="button" onClick={() => onSuggest && onSuggest(s)}>{s}</button>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ── Receipt — the compact grammar. One line that chains well. ────────────
function ReceiptRow({ r, onRestore, onOpen, isPast }) {
  return (
    <div className={"cvReceipt" + (isPast ? " isPast" : "")} data-part="receipt">
      <ActorGlyph actor={r.actor} />
      <div className="cvReceiptMain">
        <div className="cvReceiptLine">
          <span className="cvReceiptVerb">{r.verb}</span>
          {r.scope && <span className="cvReceiptScope tabular">{r.scope}</span>}
          <span className="cvReceiptTime">{r.time}</span>
        </div>
        {r.moved && <div className="cvReceiptMoved">Moved: {r.moved}</div>}
      </div>
      <div className="cvReceiptActs">
        {r.snapshot && (
          <button type="button" title="Restore the stage as it was after this action"
            onClick={() => onRestore && onRestore(r)}><Icon name="history" size={12} /> Restore</button>
        )}
        {r.reopenId && (
          <button type="button" title="Reopen this matter — its transcript and artifacts were kept"
            onClick={() => onRestore && onRestore(r)}><Icon name="history" size={12} /> Reopen</button>
        )}
        {r.open && (
          <button type="button" onClick={() => onOpen && onOpen(r)}><Icon name="open" size={12} /> Open</button>
        )}
        <a className="cvReceiptRecord" href="#record" onClick={(e) => e.preventDefault()}
          title="Open this decision in the record">record</a>
      </div>
    </div>
  );
}

// A chain of receipts from one agent run — scans as one story, collapsible.
function ReceiptGroup({ title, count, children, defaultOpen }) {
  const [open, setOpen] = React.useState(!!defaultOpen);
  return (
    <div className="cvGroup" data-part="receipt-group">
      <button type="button" className="cvGroupHead" onClick={() => setOpen(!open)}>
        <Icon name={open ? "chevD" : "chevR"} size={12} />
        <span>{title}</span>
        <span className="cvGroupCount tabular">{count}</span>
      </button>
      {open && <div className="cvGroupBody">{children}</div>}
    </div>
  );
}

function DaySep({ label }) {
  return <div className="cvDaySep" data-part="day"><span>{label}</span></div>;
}

// ── Job card — one card per job, updates in place. No fake percent. ─────
function JobCard({ job, onCancel, mini }) {
  const stateMap = { queued: "queued", running: "running", "needs-you": "needs-you", done: "done", failed: "queued" };
  const frac = job.total ? job.doneCount / job.total : 0;
  if (mini) {
    return (
      <span className="cvJobMini">
        <WorkStateChip state={stateMap[job.state]} size="inline"
          progress={job.state === "running" ? job.doneCount + "/" + job.total : undefined} />
        <span className="cvJobMiniTitle">{job.title}</span>
      </span>
    );
  }
  return (
    <div className="cvJob" data-part="job" data-state={job.state}>
      <div className="cvJobTop">
        <span className="cvJobTitle">{job.title}</span>
        <WorkStateChip state={stateMap[job.state]}
          progress={job.state === "running" ? job.doneCount + "/" + job.total : job.state === "queued" ? job.queueNote : undefined} />
      </div>
      {job.state === "running" && (
        <div className="cvJobBar" role="progressbar" aria-valuenow={job.doneCount} aria-valuemax={job.total}>
          <div className="cvJobFill" style={{ width: (frac * 100).toFixed(1) + "%" }}></div>
        </div>
      )}
      <div className="cvJobDetail">
        {job.state === "queued" && <span>Waiting to start · {job.queueNote}</span>}
        {job.state === "running" && <span className="tabular">{job.detail}</span>}
        {job.state === "needs-you" && <span>Paused — {job.pauseNote}</span>}
        {job.state === "done" && <span>{job.doneNote}</span>}
        {job.state === "failed" && <span className="cvJobFail"><Icon name="alert" size={12} /> {job.failNote}</span>}
        {(job.state === "queued" || job.state === "running") && (
          <button type="button" className="cvJobCancel" onClick={() => onCancel && onCancel(job)}>Cancel</button>
        )}
        {job.state === "failed" && <button type="button" className="cvJobCancel">Retry</button>}
      </div>
    </div>
  );
}

// ── Approval request — governance as UI. Consent-colored moment. ────────
function ApprovalCard({ req, onApprove, onDeny, onEdit, resolved }) {
  return (
    <div className={"cvApproval" + (resolved ? " isResolved" : "")} data-part="approval">
      <div className="cvApprovalHead">
        <Icon name="pause" size={13} />
        <span>Needs you — {req.title}</span>
      </div>
      <div className="cvApprovalScope">
        <ConsentChip level={req.fromLevel} label={req.fromLabel} />
        <span className="cvApprovalArrow" aria-hidden="true">→</span>
        <ConsentChip level={req.toLevel} label={req.toLabel} />
      </div>
      <p className="cvApprovalBody">{req.body}</p>
      <div className="cvApprovalEvidence">
        {req.evidence.map((ev) => (
          <a key={ev} href="#evidence" onClick={(e) => e.preventDefault()}>{ev}</a>
        ))}
      </div>
      {!resolved ? (
        <div className="cvApprovalActs">
          <button type="button" className="cvBtnPrimary" onClick={onApprove}><Icon name="check" size={13} /> Approve</button>
          <button type="button" className="cvBtnQuiet" onClick={onEdit}>Suggest a change</button>
          <button type="button" className="cvBtnQuiet" onClick={onDeny}>Deny</button>
        </div>
      ) : (
        <div className="cvApprovalDone"><Icon name="check" size={12} /> {resolved}</div>
      )}
    </div>
  );
}

// ── Inline glanceable — read it here; work on it up on the stage ────────
function Glanceable({ metrics, caption }) {
  return (
    <div className="cvGlance" data-part="glanceable">
      {metrics.map((m) => (
        <div key={m.label} className="cvGlanceCell">
          <span className="cvGlanceN tabular">{m.n}</span>
          <span className="cvGlanceL">{m.label}</span>
        </div>
      ))}
      {caption && <div className="cvGlanceCap">{caption}</div>}
    </div>
  );
}

// ── Ticker — the stream at rest: one line, the most recent receipt ──────
function Ticker({ receipt, job, onExpand }) {
  return (
    <button type="button" className="cvTicker" onClick={onExpand}
      title="Open the activity below this page">
      <span className="cvTickerPulse" aria-hidden="true"></span>
      {receipt ? (
        <span className="cvTickerText">
          <span className="cvTickerVerb">{receipt.verb}</span>
          {receipt.scope && <span className="cvTickerScope tabular">{receipt.scope}</span>}
          <span className="cvTickerTime">{receipt.time}</span>
        </span>
      ) : (
        <span className="cvTickerText"><span className="cvTickerTime">Nothing yet today — activity will appear here.</span></span>
      )}
      {job && job.state !== "done" && <JobCard job={job} mini />}
      <Icon name="chevD" size={12} style={{ transform: "rotate(180deg)", opacity: 0.5 }} />
    </button>
  );
}

// ── Frame chip — what the agent currently sees ───────────────────────────
function FrameChip({ feature, selection, subject, acting }) {
  return (
    <span className={"cvFrame" + (acting ? " isActing" : "")}
      title="What the agent sees right now: the active feature, your selection, and what's on the stage">
      <Icon name="eye" size={11} />
      <span>{feature}</span>
      {subject && <span className="cvFrameSep">·</span>}
      {subject && <span>{subject}</span>}
      {selection > 0 && <span className="cvFrameSep">·</span>}
      {selection > 0 && <span className="cvFrameSel tabular">{acting ? "acting on " : ""}{selection} selected</span>}
    </span>
  );
}

// ── Warm path — list-first, never a graph hero ───────────────────────────
function WarmPath({ path, defaultOpen }) {
  const [open, setOpen] = React.useState(!!defaultOpen);
  return (
    <div className="cvWarm" data-part="warm-path">
      <button type="button" className="cvWarmChip" onClick={() => setOpen(!open)}>
        <span className="cvWarmDot" aria-hidden="true"></span>
        {path.label}
        <Icon name={open ? "chevD" : "chevR"} size={11} />
      </button>
      {open && (
        <div className="cvWarmHops">
          {path.hops.map((h, i) => (
            <React.Fragment key={h.name}>
              <div className="cvWarmHop">
                <span className="cvWarmName">{h.name}</span>
                <span className="cvWarmRole">{h.role}</span>
              </div>
              {h.strength != null && (
                <div className="cvWarmLink" title={"Relationship strength " + h.strength + " of 100"}>
                  <span className="tabular">{h.strength}</span>
                </div>
              )}
              {i === path.hops.length - 1 && null}
            </React.Fragment>
          ))}
          <div className="cvWarmHop"><span className="cvWarmName">Meridian Catering Co.</span><span className="cvWarmRole">the business</span></div>
          <button type="button" className="cvWarmAsk">Ask Sam for the intro</button>
        </div>
      )}
    </div>
  );
}

// ── Strength cell — score + read, "why" one hover away ──────────────────
function StrengthCell({ score, trend, why }) {
  return (
    <span className="cvStrength" data-trend={trend}>
      <span className="tabular cvStrengthN">{score}</span>
      <span className="cvStrengthT">{trend}</span>
      <span className="cvStrengthWhy" role="tooltip">{why}</span>
    </span>
  );
}

Object.assign(window, {
  Icon, ActorGlyph, Utterance, AgentProse, ReceiptRow, ReceiptGroup, DaySep,
  JobCard, ApprovalCard, Glanceable, Ticker, FrameChip, WarmPath, StrengthCell,
});
