grooph 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +33 -31
  2. package/THIRD-PARTY-NOTICES.md +5 -1
  3. package/dist/app/assets/App-CT9KxzfQ.css +1 -0
  4. package/dist/app/assets/App-D1pDFbEY.js +5 -0
  5. package/dist/app/assets/EmbedApp-CTausQWY.js +1 -0
  6. package/dist/app/assets/ExportPanel-CbRH4C69.js +8 -0
  7. package/dist/app/assets/Import-DF0XLxRI.js +1 -0
  8. package/dist/app/assets/SketchView-BjeUHG4X.js +143 -0
  9. package/dist/app/assets/brakes-B9b3hDX8.js +1 -0
  10. package/dist/app/assets/{builtins-Cbs5iQtH.js → builtins-DzyPaYdd.js} +1 -1
  11. package/dist/app/assets/{compile-BAvi-rd0.js → compile-DL2budwP.js} +8 -8
  12. package/dist/app/assets/{front-BRl7rl-u.js → front-OxfL-OaD.js} +1 -1
  13. package/dist/app/assets/full-C0asYORc.js +1 -0
  14. package/dist/app/assets/graph-more-Dn_hNa20.js +2 -0
  15. package/dist/app/assets/graph-stage-CwNePnN4.js +4 -0
  16. package/dist/app/assets/graph-views-CmkQ41zC.js +2 -0
  17. package/dist/app/assets/{index-BoSi6XYh.js → index-B5ZkSF4L.js} +2 -2
  18. package/dist/app/assets/mermaid-read-cyqJ32v-.js +17 -0
  19. package/dist/app/assets/{plan-templates-BQu8G2sX.js → plan-templates-u2fF3GnS.js} +1 -1
  20. package/dist/app/assets/runs-BA5HKtsx.js +1 -0
  21. package/dist/app/assets/screens-CMMuexid.js +16 -0
  22. package/dist/app/assets/share-DV3wsAsJ.js +8 -0
  23. package/dist/app/assets/site-looks.v1.css +223 -0
  24. package/dist/app/assets/space-Cuy4YqyZ.js +1 -0
  25. package/dist/app/assets/styles-Dlp-yYlE.css +1 -0
  26. package/dist/app/assets/templates-DbAhWvP6.js +2 -0
  27. package/dist/app/assets/{themes-DtOBrLk0.js → themes-C34TrvOJ.js} +1 -1
  28. package/dist/app/assets/{units-DRaa5U2m.js → units-DlniUjfH.js} +1 -1
  29. package/dist/app/assets/{views-DCEDX6Qx.js → views-CFqRShXD.js} +2 -1
  30. package/dist/app/grooph-app.json +1 -1
  31. package/dist/app/index.html +14 -11
  32. package/dist/app/llms.txt +6 -7
  33. package/dist/app/manifest.webmanifest +1 -1
  34. package/dist/app/og.png +0 -0
  35. package/dist/app/routes.json +42 -33
  36. package/dist/app/sw.js +7 -2
  37. package/dist/browser/grooph.d.ts +44 -0
  38. package/dist/browser/grooph.global.js +7 -0
  39. package/dist/browser/grooph.js +7 -0
  40. package/dist/bundle/grooph.js +7082 -2606
  41. package/hooks/grooph-event.mjs +163 -14
  42. package/package.json +14 -6
  43. package/dist/app/assets/App-CFO6bPna.js +0 -5
  44. package/dist/app/assets/App-Cv1auMeh.css +0 -1
  45. package/dist/app/assets/EmbedApp-B5LWao3x.js +0 -1
  46. package/dist/app/assets/ExportPanel-VWus7GM3.js +0 -8
  47. package/dist/app/assets/Import-YEKofx4_.js +0 -1
  48. package/dist/app/assets/brakes-9E9PsV_Z.js +0 -1
  49. package/dist/app/assets/graph-more-BKW9C4-h.js +0 -2
  50. package/dist/app/assets/graph-stage-CWh3OWga.js +0 -4
  51. package/dist/app/assets/graph-views-tFUJK-be.js +0 -2
  52. package/dist/app/assets/runs-DcjRi7S6.js +0 -1
  53. package/dist/app/assets/screens-YUd2HaLm.js +0 -16
  54. package/dist/app/assets/share-BzIzB4EY.js +0 -8
  55. package/dist/app/assets/space-DWgrlnfB.js +0 -1
  56. package/dist/app/assets/styles-BA1aVO9R.css +0 -1
  57. package/dist/app/assets/templates-DvzLa5sE.js +0 -2
  58. package/dist/app/demo/run.txt +0 -1
@@ -0,0 +1,143 @@
1
+ import{a as e,c as t,t as n}from"./index-B5ZkSF4L.js";import{Gt as r,Ht as i,Wt as a,b as o,en as s,nn as c,pn as l}from"./share-DV3wsAsJ.js";import{v as u}from"./App-D1pDFbEY.js";import{n as d}from"./mermaid-read-cyqJ32v-.js";import{a as f,i as p,n as m,o as h,r as g}from"./screens-CMMuexid.js";var _=t(e(),1),v=`:root{--draw-ink:var(--ink);--draw-green:#1f7a5a;--draw-blue:#2563eb;--draw-red:#c0392b;--draw-amber:#b26b00}@media (prefers-color-scheme:dark){:root{--draw-green:#5dbb94;--draw-blue:#7aa2ff;--draw-red:#ff8f80;--draw-amber:#f0b35a}}.graph-sketch{z-index:1;overscroll-behavior:contain;background:var(--bg);pointer-events:auto;position:absolute;inset:52px 0 0;overflow-y:auto;container:sk/size}.sk{--sk-radius-lg:10px;--sk-gutter:12px;min-height:100%;padding:6px var(--sk-gutter) 32px;box-sizing:border-box;gap:20px;display:grid}.sk-draw{align-content:start;gap:10px;min-width:0;display:grid}@container sk (width>=1024px){.sk{grid-template-columns:minmax(0,1.7fr) minmax(340px,1fr);align-items:start;padding-inline:20px}.sk-draw{position:sticky;top:12px}}.sk-bar{flex-wrap:wrap;align-items:center;gap:4px 14px;display:flex;position:relative}.sk-tools-row{align-items:center;gap:2px;min-width:0;display:flex}.sk-tools-row:last-child{flex:auto}.sk-spacer{flex:1 1 0}.sk-rule{background:var(--line-strong);flex:none;width:1px;height:20px;margin-inline:7px}.sk-bar svg{fill:none;stroke:currentColor;stroke-width:1.6px;stroke-linecap:round;stroke-linejoin:round}.sk-bar svg circle{fill:currentColor;stroke:none}.sk-seg{flex:none;gap:2px;display:inline-flex}.sk-seg button,.sk-icon{border-radius:var(--radius);min-width:40px;height:40px;min-height:40px;color:var(--ink-2);font:600 .9rem/1 var(--font);cursor:pointer;touch-action:manipulation;background:0 0;border:0;justify-content:center;align-items:center;gap:7px;padding:0 11px 0 10px;display:inline-flex}.sk-icon{width:40px;padding:0}.sk-seg button svg,.sk-icon svg{flex:none;width:20px;height:20px}.sk-seg button[aria-checked=true]{background:var(--ink);color:var(--bg)}.sk-seg button[data-options]{position:relative}.sk-seg button[data-options]:after{content:"";opacity:.55;border:3px solid;border-color:#0000 currentColor currentColor #0000;position:absolute;bottom:4px;right:4px}@media (hover:hover){.sk-seg button[aria-checked=false]:hover,.sk-icon:not(:disabled):hover{background:var(--surface-2);color:var(--ink)}}.sk-icon[aria-expanded=true]{background:var(--surface-2);color:var(--ink)}.sk-icon:disabled{opacity:.35;cursor:default}@media (prefers-reduced-motion:no-preference){.sk-seg button{transition:background-color .12s ease-out,color .12s ease-out}}.sk-seg button{padding:0}.sk-seg button span{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.sk-inks{border:0;flex:none;gap:0;margin:0;padding:0;display:inline-flex}.sk-inks input{opacity:0;width:1px;height:1px;position:absolute}.sk-inks label{border-radius:var(--radius);cursor:pointer;place-items:center;width:31px;height:40px;display:grid}.sk-swatch{border-radius:50%;width:18px;height:18px;box-shadow:inset 0 0 0 1px #0000002e;box-shadow:inset 0 0 0 1px lab(0% 0 0/.18)}.sk-inks input:checked+label .sk-swatch{box-shadow:inset 0 0 0 1px #0000002e, 0 0 0 2.5px var(--bg), 0 0 0 4px var(--ink)}@supports (color:lab(0% 0 0)){.sk-inks input:checked+label .sk-swatch{box-shadow:inset 0 0 0 1px lab(0% 0 0/.18), 0 0 0 2.5px var(--bg), 0 0 0 4px var(--ink)}}@media (hover:hover){.sk-inks input:not(:checked)+label:hover{background:var(--surface-2)}}.sk-inks input:focus-visible+label{outline:2px solid var(--focus);outline-offset:-2px}@media (forced-colors:active){.sk-seg button[aria-checked=true],.sk-inks input:checked+label{outline-offset:-2px;outline:2px solid canvastext}}.sk-go{border:1px solid var(--accent);border-radius:var(--radius);background:var(--accent);height:40px;min-height:40px;color:var(--accent-ink);font:650 .95rem/1 var(--font);white-space:nowrap;cursor:pointer;touch-action:manipulation;justify-content:center;align-items:center;gap:7px;padding:0 15px 0 13px;display:inline-flex;position:relative}.sk-go svg{stroke-width:1.8px;flex:none;width:18px;height:18px}@media (hover:hover){.sk-go:hover{filter:brightness(1.08)}}.sk-go:active{transform:translateY(1px)}.sk-go[data-stale=true]:after{content:"";background:var(--accent-ink);opacity:.7;border-radius:50%;width:6px;height:6px;position:absolute;top:5px;right:5px}@container sk (width<=719px){.sk-tools-row{flex:100%}.sk-bar .sk-more,.sk-bar .sk-tools{position:static}.sk-bar .sk-menu,.sk-bar .sk-add .sk-menu{width:auto;min-width:0;left:0;right:0}}@container sk (width<=419px){.sk-rule{margin-inline:4px}.sk-go{padding-inline:11px 12px}}@container sk (width<=399px){.sk-inks label{width:30px}.sk-icon,.sk-seg button{width:36px;min-width:36px}.sk-rule{margin-inline:4px}.sk-go svg{display:none}.sk-go{padding-inline:12px}}@container sk (width<=349px){.sk-inks label{width:27px}.sk-icon,.sk-seg button{width:30px;min-width:30px}.sk-tools-row:last-child .sk-rule{display:none}.sk-go{padding-inline:10px;font-size:.9rem}}.sk-more,.sk-tools{position:relative}.sk-menu{z-index:20;border:1px solid var(--line-strong);border-radius:var(--sk-radius-lg);background:var(--surface);min-width:260px;box-shadow:var(--shadow-card);gap:2px;margin:0;padding:6px;list-style:none;display:grid;position:absolute;top:calc(100% + 6px);left:0}.sk-menu[hidden]{display:none}.sk-menu button{width:100%;min-height:44px;color:var(--ink);font:450 .95rem/1.2 var(--font);text-align:left;cursor:pointer;background:0 0;border:0;border-radius:6px;padding:0 12px}.sk-menu [role=menuitemcheckbox]{padding-left:40px;position:relative}.sk-menu [role=menuitemcheckbox]:before{content:"";border:1.5px solid var(--line-strong);border-radius:4px;width:16px;height:16px;margin-top:-8px;position:absolute;top:50%;left:12px}.sk-menu [role=menuitemcheckbox][aria-checked=true]:before{border-color:var(--accent);background:var(--accent)}.sk-menu [role=menuitemcheckbox][aria-checked=true]:after{content:"";border:solid var(--accent-ink);border-width:0 2px 2px 0;width:5px;height:9px;margin-top:-6.5px;position:absolute;top:50%;left:17.5px;transform:rotate(45deg)}.sk-menu [role=menuitemradio]{padding-left:40px;position:relative}.sk-menu [role=menuitemradio][aria-checked=true]:before{content:"";background:var(--accent);border-radius:50%;width:8px;height:8px;margin-top:-4px;position:absolute;top:50%;left:16px}.sk-menu button small{color:var(--ink-3);margin-top:2px;font-size:.8rem;display:block}.sk-tool-menu{width:290px}.sk-tool-menu button{padding-block:8px}.sk-menu [role=separator]{background:var(--line);height:1px;margin:4px 6px}@media (hover:hover){.sk-menu button:hover{background:var(--surface-2)}}.sk-menu button:focus-visible{outline-offset:-2px}.sk-add .sk-menu{overscroll-behavior:contain;width:340px;max-height:min(60cqh,560px);overflow-y:auto}.sk-menu-head{color:var(--ink-3);font:600 .8rem/1.2 var(--font);margin:8px 12px 4px}.sk-menu-head:first-child{margin-top:4px}.sk-add-shapes{grid-template-columns:repeat(2,minmax(0,1fr));gap:2px;display:grid}.sk-add-shapes button{align-items:center;gap:10px;min-height:42px;padding:0 8px;font-size:.9rem;display:flex}.sk-add-shapes svg{stroke-width:1.4px;flex:none;width:28px;height:20px}.sk-add-shapes svg circle{fill:none;stroke:currentColor}.sk-add-shapes svg .sk-fill{fill:currentColor;stroke:none}.sk-add-arrows{grid-template-columns:minmax(0,1fr)}.sk-add-templates{gap:2px;display:grid}.sk-add-templates button{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.sk-pad{border:1px solid var(--line);border-radius:var(--sk-radius-lg);background:var(--surface);position:relative;overflow:hidden}@container sk (width<=719px){.sk-pad{margin-inline:calc(-1 * var(--sk-gutter));border-inline:0;border-radius:0}}.sk-pad canvas{width:100%;height:clamp(260px, calc(100cqh - 6px - var(--sk-toolbar,92px) - 70px), 1100px);touch-action:none;cursor:crosshair;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;display:block}.sk-pad canvas[data-tool=erase],.sk-pad canvas[data-tool=cut]{cursor:cell}.sk-pad canvas[data-tool=select]{cursor:default}.sk-pad canvas[data-tool=select][data-over]{cursor:move}.sk-pad canvas[data-tool=hand],.sk-pad canvas[data-space]{cursor:grab}.sk-pad canvas[data-panning]{cursor:grabbing}@container sk (height<=540px){.sk-pad canvas{height:max(150px, calc(100cqh - var(--sk-toolbar,52px) - 54px))}.sk-read-row{flex-wrap:nowrap;align-items:center}.sk-read{align-items:center;gap:10px;min-width:0;font-size:.86rem;line-height:1.35;display:flex}.sk-read>span:first-child{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;min-width:0;display:-webkit-box;overflow:hidden}.sk-read .sk-ms{display:none}.sk-read .sk-to-result,.sk-read-row .sk-check{flex:none}}@container sk (height<=540px) and (width<=699px){.sk-read-row .sk-check{display:none}}.sk-hint{color:var(--ink-2);text-align:center;pointer-events:none;place-content:center;justify-items:center;gap:14px;padding:24px;display:grid;position:absolute;inset:0}.sk-hint[hidden]{display:none}.sk-hint p{max-width:30ch;margin:0;font-size:1rem;line-height:1.5}.sk-hint strong{color:var(--ink);margin-bottom:4px;font-size:1.06rem;font-weight:600;display:block}.sk-hint .btn{pointer-events:auto}.sk-chip{border:1px solid var(--line);background:color-mix(in oklch, var(--surface) 90%, transparent);max-width:calc(100% - 16px);color:var(--ink-2);border-radius:8px;flex-wrap:wrap;align-items:center;gap:4px 10px;margin:0;padding:3px 3px 3px 10px;font-size:.82rem;line-height:1.3;display:flex;position:absolute;bottom:8px;left:8px}.sk-chip[hidden]{display:none}.sk-chip button,.sk-zoom{border:1px solid var(--line);background:var(--surface);min-height:30px;color:var(--ink);font:600 .8rem/1 var(--font);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:0 9px;display:inline-flex}.sk-corner{gap:6px;display:flex;position:absolute;top:8px;right:8px}.sk-full{border:1px solid var(--line);background:color-mix(in oklch, var(--surface) 90%, transparent);width:32px;height:32px;color:var(--ink-2);cursor:pointer;border-radius:6px;place-items:center;padding:0;display:grid}.sk-full svg{fill:none;stroke:currentColor;stroke-width:1.6px;stroke-linecap:round;stroke-linejoin:round;width:18px;height:18px}.sk-zoom{background:color-mix(in oklch, var(--surface) 90%, transparent);min-height:32px;color:var(--ink-2);font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:500}.sk-zoom:after{content:"Fit";color:var(--ink);font-family:var(--font);font-weight:600}.sk-zoom[hidden]{display:none}.sk-sel-bar{z-index:6;border:1px solid var(--line-strong);background:var(--surface);border-radius:9px;flex-wrap:wrap;gap:1px;max-width:calc(100% - 8px);padding:3px;display:flex;position:absolute;box-shadow:0 1px 2px #0000001f,0 8px 20px -6px #00000052;box-shadow:0 1px 2px lab(0% 0 0/.12),0 8px 20px -6px lab(0% 0 0/.32)}.sk-sel-bar[hidden],.sk-sel-bar button[hidden]{display:none}.sk-sel-bar button{height:32px;color:var(--ink);font:600 .82rem/1 var(--font);white-space:nowrap;cursor:pointer;touch-action:manipulation;background:0 0;border:0;border-radius:6px;padding:0 9px}.sk-sel-bar button[data-sel=delete]{color:var(--error)}@container sk (width<=399px){.sk-sel-bar button{padding:0 7px}}.sk-full[aria-pressed=false] .sk-leave,.sk-full[aria-pressed=true] .sk-enter{display:none}@media (hover:hover){.sk-full:hover{background:var(--surface-2);color:var(--ink)}.sk-sel-bar button:hover,.sk-zoom:hover,.sk-chip button:hover{background:var(--surface-2)}}.sk-name-edit{z-index:5;margin:0;position:absolute}.sk-name-edit[hidden]{display:none}.sk-name-edit input{box-sizing:border-box;border:2px solid var(--accent);border-radius:var(--radius);background:var(--surface);width:100%;min-height:44px;color:var(--ink);font:600 1rem/1.2 var(--font);text-align:center;box-shadow:var(--shadow-card);padding:0 12px}.sk-read-row{flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:6px 16px;display:flex}.sk-read{min-width:0;color:var(--ink-2);margin:0;font-size:.94rem;line-height:1.5}.sk-read strong{color:var(--ink)}.sk-read .sk-ms{color:var(--ink-3);font:.8rem var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}.sk-read .sk-to-result{color:var(--accent);white-space:nowrap;margin-left:4px;font-weight:560}@container sk (width>=1024px){.sk-read .sk-to-result{display:none}}.sk-check{min-height:36px;color:var(--ink-2);cursor:pointer;align-items:center;gap:8px;font-size:.94rem;display:inline-flex}.sk-check input{width:18px;height:18px;accent-color:var(--accent);margin:0}.sk-result{align-content:start;gap:14px;min-width:0;scroll-margin-top:8px;display:grid}.sk-back{color:var(--accent);justify-self:start;font-size:.92rem;font-weight:560}@container sk (width>=1024px){.sk-back{display:none}}.sk-panel{border:1px solid var(--line);border-radius:var(--sk-radius-lg);background:var(--surface);gap:12px;min-width:0;padding:16px;display:grid}.sk-panel-head{flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:4px 12px;display:flex}.sk-panel h2{margin:0;font-size:1rem;font-weight:650}.sk-panel h2 label{cursor:inherit}.sk-panel-head span{color:var(--ink-3);font-size:.86rem}.sk-diagram{border-radius:var(--radius);place-items:center;min-height:220px;display:grid;overflow-x:auto}.sk-diagram svg{max-width:100%;height:auto}.sk-diagram [data-node]{cursor:pointer}.sk-empty{max-width:32ch;color:var(--ink-3);text-align:center;margin:0;font-size:.94rem}.sk-guesses{border-radius:var(--radius);background:var(--surface-2);color:var(--ink-2);gap:4px;margin:0;padding:10px 12px 10px 28px;font-size:.88rem;line-height:1.45;display:grid}.sk-guesses[hidden]{display:none}.sk-row{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.sk-row .btn[hidden]{display:none}.sk-status{color:var(--ink-3);margin:0;font-size:.88rem}.sk-note{color:var(--ink-3);margin:0;font-size:.86rem;line-height:1.45}.sk-note strong{color:var(--ink-2);font-weight:600}.sk-names{grid-template-columns:repeat(auto-fill,minmax(min(100%,270px),1fr));gap:8px 14px;display:grid}.sk-names>.sk-status{grid-column:1/-1}.sk-name-row{align-items:center;gap:6px;min-width:0;display:flex}.sk-names label{flex:auto;align-items:center;gap:8px;min-width:0;display:flex}.sk-names select,.sk-shape-note{flex:none;width:11em}.sk-names select{border:1px solid var(--line);background:linear-gradient(45deg, transparent 50%, var(--ink-2) 50%) right 14px center / 5px 5px no-repeat, linear-gradient(135deg, var(--ink-2) 50%, transparent 50%) right 9px center / 5px 5px no-repeat, var(--surface-2);min-height:40px;color:var(--ink);font:400 .9rem/1.2 var(--font);appearance:none;cursor:pointer;border-radius:6px;padding:0 26px 0 9px}.sk-shape-note{color:var(--ink-3);padding-left:10px;font-size:.86rem}.sk-names input{border:1px solid var(--line);background:var(--surface-2);min-width:0;min-height:40px;color:var(--ink);font:400 .95rem/1.3 var(--font);border-radius:6px;flex:auto;padding:0 10px}.sk-names input::placeholder{color:var(--ink-3)}.sk-tag{background:var(--accent);min-width:28px;color:var(--accent-ink);font:600 .78rem/1 var(--mono);text-align:center;border-radius:4px;flex:none;padding:5px 6px}.sk-line-tag{border:1px solid var(--accent);background:var(--accent-soft);color:var(--ink);padding:4px 5px}.sk-code{box-sizing:border-box;resize:vertical;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2);width:100%;min-height:240px;color:var(--ink);font:.86rem/1.55 var(--mono);tab-size:2;white-space:pre;padding:12px;overflow:auto}.sk-full-page,.sk-full-page body{overflow:hidden}.sk-full-page .stage,.sk-full-page .graph-views{z-index:100}.sk-full-page .graph-switch,.sk-full-page .graph-views-note{display:none}.sk.is-full .sk-draw{z-index:100;padding:max(6px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right)) max(4px, env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-left));background:var(--bg);grid-template-rows:auto minmax(0,1fr) auto;gap:6px;position:fixed;inset:0}.sk.is-full .sk-pad{border:1px solid var(--line);border-radius:var(--radius);min-height:0;margin-inline:0;display:grid}.sk.is-full .sk-pad canvas{height:100%;min-height:0}.sk.is-full .sk-read-row{flex-wrap:nowrap;align-items:center;min-height:30px;padding-inline:4px}.sk.is-full .sk-read{align-items:center;gap:2px 10px;font-size:.86rem;line-height:1.35;display:flex}.sk.is-full .sk-read>span:first-child{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;min-width:0;display:-webkit-box;overflow:hidden}.sk.is-full .sk-read .sk-ms{display:none}.sk.is-full .sk-read .sk-to-result{flex:none;margin-left:0;display:inline}.sk.is-full .sk-read-row .sk-check{flex:none;min-height:30px;font-size:.86rem}@media (max-width:559px){.sk.is-full .sk-read-row .sk-check{display:none}}@media (max-width:719px){.sk.is-full .sk-tools-row{flex:100%}}.graph-views.is-sketch{background:var(--bg);pointer-events:auto}.graph-views.is-sketch .graph-switch{top:8px}:is(.stage:has(>.graph-views.is-sketch)>.toolbar,.stage:has(>.graph-views.is-sketch)>.loop-legend,.stage:has(>.graph-views.is-sketch)>.empty-canvas,.stage:has(>.graph-views.is-sketch)>.look-dot){display:none}`,y=(e,t)=>Math.hypot(e[0]-t[0],e[1]-t[1]);function b(e){let t=0;for(let n=1;n<e.length;n++)t+=y(e[n-1],e[n]);return t}function x(e){let t=1/0,n=1/0,r=-1/0,i=-1/0;for(let[a,o]of e)a<t&&(t=a),o<n&&(n=o),a>r&&(r=a),o>i&&(i=o);return{x0:t,y0:n,x1:r,y1:i,w:r-t,h:i-n,cx:(t+r)/2,cy:(n+i)/2}}function S(e,t){let n=e.map(e=>[e[0],e[1]]),r=b(n)/(t-1);if(!(r>0))return Array.from({length:t},()=>[n[0][0],n[0][1]]);let i=[[n[0][0],n[0][1]]],a=0;for(let e=1;e<n.length;e++){let t=y(n[e-1],n[e]);if(a+t>=r&&t>0){let o=(r-a)/t,s=[n[e-1][0]+o*(n[e][0]-n[e-1][0]),n[e-1][1]+o*(n[e][1]-n[e-1][1])];i.push(s),n.splice(e,0,s),a=0}else a+=t}let o=n[n.length-1];for(;i.length<t;)i.push([o[0],o[1]]);return i.slice(0,t)}function ee(e){let t=b(e)/2;for(let n=1;n<e.length;n++){let r=y(e[n-1],e[n]);if(r>=t&&r>0)return[e[n-1][0]+(e[n][0]-e[n-1][0])*t/r,e[n-1][1]+(e[n][1]-e[n-1][1])*t/r];t-=r}return[e[e.length-1][0],e[e.length-1][1]]}function C(e,t,n){let r=n[0]-t[0],i=n[1]-t[1],a=r*r+i*i,o=a?Math.max(0,Math.min(1,((e[0]-t[0])*r+(e[1]-t[1])*i)/a)):0;return Math.hypot(e[0]-t[0]-o*r,e[1]-t[1]-o*i)}function w(e,t){let n=1/0;for(let r=0;r<t.length;r++)n=Math.min(n,C(e,t[r],t[(r+1)%t.length]));return n}function te(e,t){let n=t.length?y(e,t[0]):1/0;for(let r=1;r<t.length;r++)n=Math.min(n,C(e,t[r-1],t[r]));return n}function ne(e,t){let n=!1;for(let r=0,i=t.length-1;r<t.length;i=r++){let[a,o]=t[r],[s,c]=t[i];o>e[1]!=c>e[1]&&e[0]<(s-a)*(e[1]-o)/(c-o)+a&&(n=!n)}return n}function T(e,t){let n=[];for(let r=0;r<e.length-1;r++){let i=e[r],a=e[r+1],o=Math.max(1,Math.ceil(y(i,a)/t));for(let e=0;e<o;e++)n.push([i[0]+(a[0]-i[0])*e/o,i[1]+(a[1]-i[1])*e/o])}let r=e[e.length-1];return n.push([r[0],r[1]]),n}function E(e,t,n,r){let i=0,a=t;for(;a+r>=0&&a+r<e.length&&i<n;)i+=y(e[a],e[a+r]),a+=r;return e[a]}function re(e){let t=0;for(let n=0,r=e.length-1;n<e.length;r=n++)t+=(e[r][0]+e[n][0])*(e[r][1]-e[n][1]);return Math.abs(t)/2}function ie(e){let t=e.slice().sort((e,t)=>e[0]-t[0]||e[1]-t[1]),n=(e,t,n)=>(t[0]-e[0])*(n[1]-e[1])-(t[1]-e[1])*(n[0]-e[0]),r=e=>{let t=[];for(let r of e){for(;t.length>=2&&n(t[t.length-2],t[t.length-1],r)<=0;)t.pop();t.push(r)}return t.pop(),t};return[...r(t),...r(t.slice().reverse())]}var ae=64,oe={rect:[[0,0],[1,0],[1,1],[0,1]],diamond:[[.5,0],[1,.5],[.5,1],[0,.5]],hexagon:[[.22,0],[.78,0],[1,.5],[.78,1],[.22,1],[0,.5]],trapezoid:[[.22,0],[.78,0],[1,1],[0,1]],"inv-trapezoid":[[0,0],[1,0],[.78,1],[.22,1]],"lean-right":[[.22,0],[1,0],[.78,1],[0,1]],"lean-left":[[0,0],[.78,0],[1,1],[.22,1]],triangle:[[.5,0],[1,1],[0,1]],"flip-triangle":[[0,0],[1,0],[.5,1]],ellipse:Array.from({length:48},(e,t)=>[.5+.5*Math.cos(t*Math.PI/24),.5+.5*Math.sin(t*Math.PI/24)])},se=Object.fromEntries(Object.entries(oe).map(([e,t])=>[e,S([...t,t[0]],ae)])),D=new Set([`triangle`,`flip-triangle`,`lean-right`,`lean-left`,`inv-trapezoid`]),O=60,k={rect:`rect`,subroutine:`rect`,diamond:`diamond`,hexagon:`hexagon`,trapezoid:`trapezoid`,"inv-trapezoid":`inv-trapezoid`,"lean-right":`lean-right`,"lean-left":`lean-left`,triangle:`triangle`,"flip-triangle":`flip-triangle`,circle:`ellipse`,stadium:`ellipse`,double:`ellipse`,dot:`ellipse`,bullseye:`ellipse`},A=new Set([`circle`,`stadium`,`double`]);function j(e){let t=e.length,n=[];for(let r=0;r<t;r++){let i=e[(r-2+t)%t],a=e[r],o=e[(r+2)%t],s=Math.abs(Math.atan2(o[1]-a[1],o[0]-a[0])-Math.atan2(a[1]-i[1],a[0]-i[0]));s>Math.PI&&(s=2*Math.PI-s),n.push(s)}let r=n.slice().sort((e,t)=>e-t),i=Math.max(.6,2.2*r[t>>1]),a=n.map((e,t)=>[e,t]).filter(([e])=>e>i).sort((e,t)=>t[0]-e[0]),o=[];for(let[,e]of a)o.every(n=>Math.min(Math.abs(e-n),t-Math.abs(e-n))>3)&&o.push(e);return o.length}function M(e){let t=t=>{let n=t*Math.PI/180,r=Math.cos(n),i=Math.sin(n),a=1/0,o=1/0,s=-1/0,c=-1/0;for(let[t,n]of e){let e=t*r+n*i,l=n*r-t*i;a=Math.min(a,e),s=Math.max(s,e),o=Math.min(o,l),c=Math.max(c,l)}return(s-a)*(c-o)},n=0,r=t(0);for(let e=-25;e<=25;e++){let i=t(e);i<r&&([n,r]=[e,i])}return Math.abs(n)<3||Math.abs(n)>=25?0:n*Math.PI/180}function ce(e){let t=x(e);if(t.w<12||t.h<12)return null;let n=S(e,ae),r=j(S(e,40)),i=Math.max(t.w,t.h)<O,a=N(n,t,r,i),o=M(n);if(!o)return{...a,bb:t,poly:n};let s=Math.cos(o),c=Math.sin(o),l=n.map(([e,t])=>[e*s+t*c,t*s-e*c]),u=x(l),d=N(l,u,r,i);return d.kind===`rect`&&d.score<a.score?{...d,bb:t,poly:n,upright:{w:u.w,h:u.h}}:{...a,bb:t,poly:n}}function N(e,t,n,r){let i=e.map(([e,n])=>[(e-t.x0)/t.w,(n-t.y0)/t.h]),a=Object.keys(oe).filter(e=>r===!1||!D.has(e)).map(e=>{let t=0;for(let n of i)t+=w(n,oe[e]);return{kind:e,a:t}}).sort((e,t)=>e.a-t.a).filter((e,t)=>t<4||e.kind===`ellipse`).map(({kind:e,a:t})=>{let n=0;for(let t of se[e])n+=w(t,i);return{kind:e,score:(t+n)/128}}).sort((e,t)=>e.score-t.score),o=a[0],s=a[1];if(o.kind===`ellipse`&&n>=4&&s.score<o.score+.03)o=s;else if(o.kind!==`ellipse`&&n<=2){let e=a.find(e=>e.kind===`ellipse`);e.score<o.score+.03&&(o=e)}let c=t.w/t.h;return{kind:o.kind===`ellipse`?c>.77&&c<1.3?`circle`:`stadium`:o.kind,score:o.score,unsure:o.score>.1}}function P(e){let t=e.length,n=b(e),r=(r,i)=>{let a=[];for(let o=r,s=0;o>=0&&o<t&&s<=.2*n;s+=o+i>=0&&o+i<t?y(e[o],e[o+i]):0,o+=i)a.push(o);let o=Math.ceil(a.length/80);return a.filter((e,t)=>t%o===0)},i=r(0,1),a=r(t-1,-1),o=0,s=t-1,c=y(e[0],e[t-1]);for(let t of i)for(let n of a){if(n<=t+2)continue;let r=y(e[t],e[n]);r<c-1e-9&&([c,o,s]=[r,t,n])}return e.slice(o,s+1)}function le(e,t){let n=e.length,r=e[0],i=e[n-1],a=y(r,i),o=0;for(let r=1;r<n&&o<.2*t;r++)o+=y(e[r-1],e[r]),a=Math.min(a,y(e[r],i));o=0;for(let i=n-2;i>=0&&o<.2*t;i--)o+=y(e[i+1],e[i]),a=Math.min(a,y(e[i],r));return a}var F=6,I=.12,L=.82;function R(e,t){let n=t.w,r=t.h;(e===`circle`||(e===`rect`||e===`diamond`)&&n/r>.88&&n/r<1.14)&&(n=r=(n+r)/2);let i=t.cx-n/2,a=t.cy-r/2,o=k[e];if(o===`ellipse`){let e=4*Math.max(8,Math.min(24,Math.round(Math.PI*(n+r)/8/F))),i=Array.from({length:e},(i,a)=>{let o=-Math.PI/2+a*2*Math.PI/e;return[t.cx+n/2*Math.cos(o),t.cy+r/2*Math.sin(o)]});return[...i,[i[0][0],i[0][1]]]}let s=oe[o].map(([e,t])=>[i+e*n,a+t*r]),c=T([...s,s[0]],F),l=[];for(let e of c)l.push(e),s.some(t=>y(t,e)<1e-6)&&l.push([e[0],e[1]]);return l}function ue(e,t=0,n=1){let r=e.length;if(r<3)return null;let i=n>=.01&&n<=100?n:1,a=(e,t)=>e.map(([e,n])=>[e*t,n*t]),o=de(a(e,i))??pe(a(e,i),Math.max(0,Math.min(t,r-2)));return o&&i!==1?{...o,pts:a(o.pts,1/i),box:x(a(o.pts,1/i))}:o}function de(e){let t=e.length,n=e[t-1],r=new Float64Array(t),i=Array(t),a=1/0,o=1/0,s=-1/0,c=-1/0;for(let n=t-1;n>=0;n--){n<t-1&&(r[n]=r[n+1]+y(e[n],e[n+1]));let[l,u]=e[n];a=Math.min(a,l),o=Math.min(o,u),s=Math.max(s,l),c=Math.max(c,u),i[n]={x0:a,y0:o,x1:s,y1:c,w:s-a,h:c-o,cx:(a+s)/2,cy:(o+c)/2}}let l=t=>{let a=i[t];return Math.max(a.w,a.h)>=28&&Math.min(a.w,a.h)>=18&&r[t]>1.3*(a.w+a.h)&&y(e[t],n)<Math.max(14,.18*Math.hypot(a.w,a.h))},u=0;for(;u<t&&!l(u);)u++;if(u>=t)return null;let d=u;for(let r=u+1;r<t&&l(r);r++)y(e[r],n)<y(e[d],n)&&(d=r);let f=ce(e.slice(d));if(!f||f.score>I||re(f.poly)<L*re(ie(f.poly)))return null;let p=f.upright?{...f.bb,x0:f.bb.cx-f.upright.w/2,x1:f.bb.cx+f.upright.w/2,y0:f.bb.cy-f.upright.h/2,y1:f.bb.cy+f.upright.h/2,w:f.upright.w,h:f.upright.h}:f.bb,m=fe(R(f.kind,p),e[d]);return{kind:f.kind,pts:m,from:d,box:x(m)}}function fe(e,t){let n=e.slice(0,-1),r=0;for(let e=1;e<n.length;e++)y(n[e],t)<y(n[r],t)&&(r=e);let i=[...n.slice(r),...n.slice(0,r)];return[...i,[i[0][0],i[0][1]]]}function pe(e,t){let n=e[t],r=e[e.length-1],i=y(n,r);if(i<24)return null;let a=e.slice(t);if(b(a)>1.12*i)return null;for(let e of a)if(C(e,n,r)>.07*i+3)return null;let o=[[n[0],n[1]],[r[0],r[1]]];return{kind:`line`,pts:o,from:t,box:x(o)}}function z(e,t,n,r=!1){let i=y(e,t),a=Math.atan2(t[1]-e[1],t[0]-e[0]),o=Math.min(14/n,i/(r?4:3)),s=3/n,c=[],l=(e,t)=>{let n=Math.max(1,Math.ceil(y(e,t)/s));for(let r=1;r<=n;r++)c.push([e[0]+(t[0]-e[0])*r/n,e[1]+(t[1]-e[1])*r/n])},u=(e,t,n)=>[e[0]-t*o*Math.cos(a+n),e[1]-t*o*Math.sin(a+n)];if(r){let t=u(e,-1,-.5),n=u(e,-1,.5);c.push(t),l(t,e),l(e,n),l(n,e)}else c.push([e[0],e[1]]);return l(e,t),l(t,u(t,1,.5)),l(u(t,1,.5),t),l(t,u(t,1,-.5)),c}var me=(e,t,n,r)=>({x0:e-n/2,y0:t-r/2,x1:e+n/2,y1:t+r/2,w:n,h:r,cx:e,cy:t});function he(e,t,n){let r=[];for(let i=0;i<=32;i++)r.push([e+n*Math.cos(-Math.PI/2+i/32*2*Math.PI),t+n*Math.sin(-Math.PI/2+i/32*2*Math.PI)]);let i=Math.max(2,Math.round(n/2.5));for(let a=0;a<=i*24;a++){let o=a/(i*24),s=n*(1-o),c=-Math.PI/2+o*i*2*Math.PI;r.push([e+s*Math.cos(c),t+s*Math.sin(c)])}return T([...r,[e,t-n]],2)}function B(e,t,n,r,i,a){return e===`dot`?[{pts:he(t,n,r/2)}]:e===`bullseye`?[{pts:R(`circle`,me(t,n,r,i))},{pts:he(t,n,r*.22)}]:[{pts:R(e,me(t,n,r,i)),name:a}]}function V(e,t){let n=T(e,3),r=n[n.length-1],i=e[e.length-2],a=Math.atan2(r[1]-i[1],r[0]-i[0]),o=e=>[r[0]-14*Math.cos(a+e),r[1]-14*Math.sin(a+e)];return{pts:[...n,...T([r,o(.5),r,o(-.5)],2).slice(1)],name:t,line:!0}}function ge(e,t,n=7){let r=t[0]-e.cx,i=t[1]-e.cy,a=Math.min(r?e.w/2/Math.abs(r):1/0,i?e.h/2/Math.abs(i):1/0),o=Math.hypot(r,i)||1;return[e.cx+r*a+r/o*n,e.cy+i*a+i/o*n]}function H(e,t,n,r=0){let i=x(e.flatMap(e=>e.pts)),a=x(t.flatMap(e=>e.pts)),o=a.cx-i.cx,s=a.cy-i.cy,c=Math.hypot(o,s),l=-s/c*r,u=o/c*r,d={...i,cx:i.cx+l,cy:i.cy+u},f={...a,cx:a.cx+l,cy:a.cy+u};return V([ge(d,[f.cx,f.cy]),ge(f,[d.cx,d.cy])],n)}function _e(e,t,n,r){return[...B(`circle`,e,t,n,n,r),...B(`circle`,e,t,n*.72,n*.72)]}var U=[{id:`steps`,label:`Steps in order`,group:`Flowcharts`,diagram:`flowchart`,parts(){let e=B(`stadium`,0,0,140,56,`Start`),t=B(`rect`,0,120,150,64,`First step`),n=B(`rect`,0,240,150,64,`Second step`),r=B(`stadium`,0,360,140,56,`Done`);return[...e,...t,...n,...r,H(e,t),H(t,n),H(n,r)]}},{id:`decision`,label:`A yes-or-no choice`,group:`Flowcharts`,diagram:`flowchart`,parts(){let e=B(`stadium`,0,0,140,56,`Start`),t=B(`diamond`,0,140,140,104,`Ready?`),n=B(`rect`,-120,300,140,64,`Go ahead`),r=B(`rect`,120,300,140,64,`Wait`);return[...e,...t,...n,...r,H(e,t),V([[-70,140],[-120,140],[-120,261]],`Yes`),V([[70,140],[120,140],[120,261]],`No`)]}},{id:`loop`,label:`Try until done`,group:`Flowcharts`,diagram:`flowchart`,parts(){let e=B(`stadium`,0,0,140,56,`Start`),t=B(`rect`,0,120,150,64,`Try`),n=B(`diamond`,0,260,140,104,`Done?`),r=B(`stadium`,0,400,140,56,`Finish`);return[...e,...t,...n,...r,H(e,t),H(t,n),H(n,r,`Yes`),V([[70,260],[150,260],[150,120],[82,120]],`No`)]}},{id:`sign-in`,label:`Sign in, with retries`,group:`Flowcharts`,diagram:`flowchart`,parts(){let e=B(`stadium`,0,0,140,56,`Start`),t=B(`lean-right`,0,120,170,64,`Enter password`),n=B(`diamond`,0,260,140,104,`Correct?`),r=B(`diamond`,210,260,140,104,`Tries left?`),i=B(`stadium`,0,400,140,56,`Signed in`),a=B(`stadium`,210,400,140,56,`Locked out`);return[...e,...t,...n,...r,...i,...a,H(e,t),H(t,n),H(n,i,`Yes`),H(n,r,`No`),V([[210,208],[210,120],[74,120]],`Yes`),H(r,a,`No`)]}},{id:`retry`,label:`A request, retried`,group:`Flowcharts`,diagram:`flowchart`,parts(){let e=B(`stadium`,0,0,140,56,`Start`),t=B(`rect`,0,120,150,64,`Send request`),n=B(`diamond`,0,260,140,104,`Worked?`),r=B(`rect`,210,260,120,64,`Wait`),i=B(`stadium`,0,400,140,56,`Done`);return[...e,...t,...n,...r,...i,H(e,t),H(t,n),H(n,i,`Yes`),H(n,r,`No`),V([[210,224],[210,120],[82,120]])]}},{id:`door`,label:`A door: closed, open, locked`,group:`State diagrams`,diagram:`state`,parts(){let e=B(`dot`,-150,0,30,30),t=B(`rect`,0,0,130,60,`Closed`),n=B(`rect`,230,0,130,60,`Open`),r=B(`rect`,0,160,130,60,`Locked`);return[...e,...t,...n,...r,H(e,t),H(t,n,`open`,-14),H(n,t,`close`,-14),H(t,r,`lock`,24),H(r,t,`unlock`,24)]}},{id:`light`,label:`A traffic light`,group:`State diagrams`,diagram:`state`,parts(){let e=B(`dot`,-170,0,30,30),t=B(`rect`,0,0,120,60,`Red`),n=B(`rect`,210,150,120,60,`Green`),r=B(`rect`,-90,150,120,60,`Yellow`);return[...e,...t,...n,...r,H(e,t),H(t,n,`go`),H(n,r,`slow`),H(r,t,`stop`)]}},{id:`order`,label:`An order, start to end`,group:`State diagrams`,diagram:`state`,parts(){let e=B(`dot`,0,0,30,30),t=B(`rect`,0,110,140,60,`Placed`),n=B(`rect`,0,230,140,60,`Paid`),r=B(`rect`,0,350,140,60,`Shipped`),i=B(`rect`,220,230,140,60,`Canceled`),a=B(`bullseye`,0,460,42,42);return[...e,...t,...n,...r,...i,...a,H(e,t),H(t,n,`pay`),H(n,r,`ship`),H(r,a),H(t,i,`cancel`),V([[220,264],[220,460],[29,460]])]}},{id:`player`,label:`A media player`,group:`State diagrams`,diagram:`state`,parts(){let e=B(`dot`,0,-110,30,30),t=B(`rect`,0,0,130,60,`Stopped`),n=B(`rect`,230,0,130,60,`Playing`),r=B(`rect`,230,160,130,60,`Paused`),i=B(`bullseye`,0,160,42,42);return[...e,...t,...n,...r,...i,H(e,t),H(t,n,`play`,-14),H(n,t,`stop`,-14),H(n,r,`pause`,30),H(r,n,`play`,30),H(r,t,`stop`),H(t,i,`close`)]}},{id:`vending`,label:`A vending machine`,group:`State diagrams`,diagram:`state`,parts(){let e=B(`dot`,-160,0,30,30),t=B(`rect`,0,0,130,60,`Idle`),n=B(`rect`,0,160,130,60,`Paid`),r=B(`rect`,230,160,130,60,`Vending`);return[...e,...t,...n,...r,H(e,t),H(t,n,`coin`,30),H(n,t,`refund`,30),H(n,r,`choose`),V([[230,126],[230,0],[72,0]],`done`)]}},{id:`grind-loop`,label:`Grind loop`,group:`Agent workflows`,diagram:`flowchart`,parts(){let e=B(`rect`,0,0,150,64,`Builder`),t=B(`hexagon`,0,130,150,64,`Tests`),n=_e(0,260,84,`Done`);return[...e,...t,...n,H(e,t),H(t,n,`pass`),V([[75,130],[150,130],[150,0],[82,0]],`fail`)]}},{id:`ralph-loop`,label:`Ralph loop`,group:`Agent workflows`,diagram:`flowchart`,parts(){let e=B(`rect`,0,0,150,64,`Builder`),t=B(`hexagon`,0,130,150,64,`Tests`),n=B(`hexagon`,0,260,150,64,`Plan empty?`),r=_e(0,410,84,`Done`);return[...e,...t,...n,...r,H(e,t),V([[75,130],[150,130],[150,0],[82,0]],`fail`),H(t,n,`pass`),V([[-75,260],[-150,260],[-150,0],[-82,0]],`fail`),H(n,r,`pass`)]}},{id:`red-team-loop`,label:`Red-team loop`,group:`Agent workflows`,diagram:`flowchart`,parts(){let e=B(`rect`,0,0,150,64,`Builder`),t=B(`diamond`,0,140,140,104,`Red team`),n=_e(0,290,84,`Done`);return[...e,...t,...n,H(e,t),H(t,n,`pass`),V([[70,140],[150,140],[150,0],[82,0]],`fail`)]}},{id:`review-gate`,label:`Review gate`,group:`Agent workflows`,diagram:`flowchart`,parts(){let e=B(`rect`,0,0,150,64,`Builder`),t=B(`diamond`,0,140,140,104,`Critic`),n=B(`trapezoid`,0,290,170,64,`Merge approval`),r=_e(0,450,84,`Done`);return[...e,...t,...n,...r,H(e,t),V([[70,140],[150,140],[150,0],[82,0]],`fail`),H(t,n,`pass`),H(n,r,`pass`),V([[-70,290],[-150,290],[-150,0],[-82,0]],`fail`)]}},{id:`spec-then-loop`,label:`Spec then loop`,group:`Agent workflows`,diagram:`flowchart`,parts(){let e=B(`rect`,0,0,150,64,`Planner`),t=B(`trapezoid`,0,130,170,64,`Spec approval`),n=B(`rect`,0,260,150,64,`Builder`),r=B(`diamond`,0,400,140,104,`Critic`),i=_e(0,550,84,`Done`);return[...e,...t,...n,...r,...i,H(e,t),H(t,n,`pass`),H(n,r),V([[70,400],[150,400],[150,260],[82,260]],`fail`),H(r,i,`pass`)]}},{id:`human-gated-irreversible`,label:`Human gate, then act`,group:`Agent workflows`,diagram:`flowchart`,parts(){let e=B(`trapezoid`,0,0,160,64,`Step approval`),t=B(`rect`,0,120,180,64,`Irreversible step`),n=_e(0,240,84,`Done`);return[...e,...t,...n,H(e,t,`pass`),H(t,n)]}},{id:`debate-then-build`,label:`Debate then build`,group:`Agent workflows`,diagram:`flowchart`,parts(){let e=B(`rect`,-110,0,150,64,`Planner A`),t=B(`rect`,110,0,150,64,`Planner B`),n=B(`diamond`,110,140,140,104,`Judge`),r=B(`trapezoid`,110,290,170,64,`Plan approval`),i=B(`rect`,-110,290,150,64,`Builder`),a=B(`hexagon`,-110,420,150,64,`Tests`),o=_e(-110,550,84,`Done`);return[...e,...t,...n,...r,...i,...a,...o,H(e,t),H(t,n),V([[40,140],[-110,140],[-110,39]],`verdict: rebut`),H(n,r,`pass`),V([[40,290],[-28,290]],`pass`),H(i,a),V([[-185,420],[-240,420],[-240,290],[-192,290]],`fail`),H(a,o,`pass`)]}},{id:`tournament-then-judge`,label:`Tournament then judge`,group:`Agent workflows`,diagram:`flowchart`,parts(){let e=B(`rect`,-150,0,124,64,`Candidate A`),t=B(`rect`,0,0,124,64,`Candidate B`),n=B(`rect`,150,0,124,64,`Candidate C`),r=B(`hexagon`,0,150,170,64,`Finalist filter`),i=B(`diamond`,0,290,140,104,`Judge`),a=B(`rect`,0,430,150,64,`Finisher`),o=_e(0,560,84,`Done`);return[...e,...t,...n,...r,...i,...a,...o,H(e,r),H(t,r),H(n,r),H(r,i,`pass`),H(i,a,`pass`),H(a,o)]}}],W={rect:[`[`,`]`],subroutine:[`[[`,`]]`],stadium:[`([`,`])`],circle:[`((`,`))`],double:[`(((`,`)))`],diamond:[`{`,`}`],hexagon:[`{{`,`}}`],trapezoid:[`[/`,`\\]`],"inv-trapezoid":[`[\\`,`/]`],"lean-right":[`[/`,`/]`],"lean-left":[`[\\`,`\\]`],triangle:`tri`,"flip-triangle":`flip-tri`,dot:`sm-circ`,bullseye:`fr-circ`};function G(e,t,n){let r=W[t];return typeof r==`string`?`${e}@{ shape: ${r}, label: "${n.replace(/\\/g,`#92;`)}" }`:`${e}${r[0]}"${n}"${r[1]}`}var K=e=>String(e).replace(/[\x00-\x1f\x7f]+/g,` `).replace(/[#&<>"]/g,e=>`#`+e.charCodeAt(0)+`;`);function q(e){switch(e.kind){case`agent`:return s(e)?`diamond`:c(e)?`rect`:`stadium`;case`check`:return`hexagon`;case`human-gate`:return`trapezoid`;case`merge`:return`circle`;case`stop`:return`double`}}var ve={rect:`agent`,subroutine:`agent`,"lean-right":`agent`,"lean-left":`agent`,"inv-trapezoid":`agent`,triangle:`agent`,"flip-triangle":`agent`,stadium:`other agent`,diamond:`critic`,hexagon:`check`,trapezoid:`human-gate`,circle:`merge`,double:`stop`,bullseye:`stop`,dot:`start`},J=e=>ve[q(e)];function ye(e){let t=e.when??`always`;return[t===`always`?``:typeof t==`string`?t:`verdict: ${t.verdict}`,e.approval?`approval`:``].filter(e=>e!==``).join(`, `)||e.label||``}var be={rect:[150,64],stadium:[150,60],diamond:[140,104],hexagon:[150,64],trapezoid:[170,64],circle:[84,84],double:[84,84]},xe=[.85,.9],Se=[1,1.2];function Y(e,t){let n=T(e,3),r=n[n.length-1],i=e[e.length-2],a=Math.atan2(r[1]-i[1],r[0]-i[0]),o=e=>[r[0]-14*Math.cos(a+e),r[1]-14*Math.sin(a+e)];return{pts:[...n,...T([r,o(.5),r,o(-.5)],2).slice(1)],...t?{name:t}:{},line:!0}}function Ce(e,t,n=7){let r=t[0]-e.cx,i=t[1]-e.cy,a=Math.min(r?e.w/2/Math.abs(r):1/0,i?e.h/2/Math.abs(i):1/0),o=Math.hypot(r,i)||1;return[e.cx+r*a+r/o*n,e.cy+i*a+i/o*n]}function we(e,t,n,r=8){let i=n.x0-r,a=n.x1+r,o=n.y0-r,s=n.y1+r,c=0,l=1,u=t[0]-e[0],d=t[1]-e[1];for(let[t,n]of[[-u,e[0]-i],[u,a-e[0]],[-d,e[1]-o],[d,s-e[1]]])if(t===0){if(n<0)return!1}else{let e=n/t;if(t<0?c=Math.max(c,e):l=Math.min(l,e),c>l)return!1}return!0}function Te(e,t){let n=[],r=new Map;for(let i of e.nodes){let a=t[i.id]??{x:0,y:0},o=q(i),[s,c]=be[o],l=e.groups?.length?Se:xe,u=(a.x+100)*l[0],d=(a.y+42)*l[1],f=i.name||i.id,p=o===`double`?[...B(`circle`,u,d,s,c,f),...B(`circle`,u,d,s*.72,c*.72)]:B(o,u,d,s,c,f);for(let e of p)n.push({...e,mark:{node:i.id}});r.set(i.id,x(p.flatMap(e=>e.pts)))}let i=e.groups??[],a=new Map,o=(t,n)=>{if(a.has(t.id))return a.get(t.id);if(n.has(t.id))return;n.add(t.id);let s=t.members.flatMap(e=>{let t=r.get(e)??(i.find(t=>t.id===e)?o(i.find(t=>t.id===e),n):void 0);return t?[t]:[]});if(s.length===0)return;let c=s.length===1&&t.members.length===1?e.nodes.find(e=>e.id===t.members[0]):void 0,l=c&&[`stadium`,`circle`,`double`].includes(q(c))?s[0].w*.55:30,u=Math.min(...s.map(e=>e.x0))-l,d=Math.max(...s.map(e=>e.x1))+l,f=Math.min(...s.map(e=>e.y0))-30-22,p=Math.max(...s.map(e=>e.y1))+30,m={x0:u,x1:d,y0:f,y1:p,w:d-u,h:p-f,cx:(u+d)/2,cy:(f+p)/2};return a.set(t.id,m),m},s=new Map(i.map(e=>[e.id,e])),c=(e,t=new Set)=>(t.add(e.id),new Set(e.members.flatMap(e=>s.has(e)?t.has(e)?[]:[...c(s.get(e),t)]:[e]))),l=(e,t)=>e.x0<t.x1&&t.x0<e.x1&&e.y0<t.y1&&t.y0<e.y1,u=new Map,d=new Map,f=(e,t=new Set)=>{if(d.has(e.id))return d.get(e.id);if(t.has(e.id))return!1;t.add(e.id);let n=e.members.filter(e=>s.has(e)),i=n.map(e=>f(s.get(e),t)).every(Boolean),a=o(e,new Set),m=i&&a!==void 0;if(m){let t={...a,x0:a.x0-8,x1:a.x1+8,y0:a.y0-8,y1:a.y1+8},i=c(e),o=new Set(n.flatMap(e=>[e,...p(e)]));m=[...r].every(([e,n])=>i.has(e)||!l(n,t))&&[...u].every(([e,n])=>o.has(e)||!l(n,t))}return d.set(e.id,m),m&&u.set(e.id,a),m};function p(e,t=new Set){let n=s.get(e);if(!n||t.has(e))return t;t.add(e);for(let e of n.members)s.has(e)&&p(e,t);return t}let m=[];for(let e of i)f(e)||m.push(e.id);for(let e of i){let t=u.get(e.id);if(t)for(let r of B(`rect`,t.cx,t.cy,t.w,t.h,e.name||e.id))n.push({...r,mark:{group:e.id}})}let h=[...r.values()],g=new Map;for(let t of e.edges){if(!r.has(t.from)||!r.has(t.to))continue;let e=[t.from,t.to].sort().join(`\0`);(g.get(e)??g.set(e,[]).get(e)).push(t)}let _={right:0,left:0},v=(e,t)=>h.some(n=>n!==e&&n.y1>e.y0&&n.y0<e.y1&&(t===`right`?n.x0>=e.x1-1:n.x1<=e.x0+1));for(let t of e.edges){let e=r.get(t.from),n=r.get(t.to);if(!e||!n)continue;let i=ye(t);if(t.from===t.to){let n=e.x1+7,r=e.x1+44;y(t,Y([[n,e.cy-16],[r,e.cy-16],[r,e.cy+16],[n,e.cy+16]],i));continue}let a=g.get([t.from,t.to].sort().join(`\0`)),o=a.length>1?(a.indexOf(t)-(a.length-1)/2)*30*(t.from<t.to?1:-1):0,s=n.cx-e.cx,c=n.cy-e.cy,l=Math.hypot(s,c)||1,u=-c/l*o,d=s/l*o,f={...e,cx:e.cx+u,cy:e.cy+d},p={...n,cx:n.cx+u,cy:n.cy+d},m=Ce(f,[p.cx,p.cy]),b=Ce(p,[f.cx,f.cy]);if(!h.some(t=>t!==e&&t!==n&&we(m,b,t))){y(t,Y([m,b],i));continue}let x=n.cy<=e.cy,S=t=>!v(e,t)&&!v(n,t),ee=S(x?`right`:`left`)?x?`right`:`left`:S(x?`left`:`right`)?x?`left`:`right`:void 0;if(!ee){y(t,Y([m,b],i));continue}let C=Math.min(e.y0,n.y0),w=Math.max(e.y1,n.y1),te=h.filter(e=>e.y1>C&&e.y0<w),ne=_[ee]++,T=ee===`right`?Math.max(...te.map(e=>e.x1))+34+24*ne:Math.min(...te.map(e=>e.x0))-34-24*ne,E=ee===`right`?e.x1+7:e.x0-7,re=ee===`right`?n.x1+7:n.x0-7;y(t,Y([[E,e.cy],[T,e.cy],[T,n.cy],[re,n.cy]],i))}return{parts:n,unboxed:m};function y(e,t){n.push({...t,mark:{edge:e.id}})}}function Ee(e,t,n){let r=new Set(e),i=new Map;for(let e of t)(i.get(e.from)??i.set(e.from,[]).get(e.from)).push(e);let a=n.find(e=>!r.has(e.from)&&r.has(e.to))?.to??e[0],o=new Map,s=[],c=e=>{o.set(e,`on`);for(let t of i.get(e)??[]){let e=o.get(t.to);e===`on`?s.push(t.id):e||c(t.to)}o.set(e,`done`)};for(let t of[a,...e])o.has(t)||c(t);return s}function De(e,t){let n=e=>Array.isArray(e)?e.map(n):e&&typeof e==`object`?Object.fromEntries(Object.keys(e).sort().map(t=>[t,n(e[t])])):e;return JSON.stringify(n(e))===JSON.stringify(n(t))}function Oe(e,t,n,o,s=[]){let c=new Set(e.nodes.filter(e=>e.kind===`dot`).map(e=>e.id)),u=e.nodes.filter(e=>!c.has(e.id)).map(e=>e.kind===`bullseye`?{...e,kind:`double`}:e);if(u.length===0)return{error:c.size?`Only a start dot was read. Draw the steps, like a box or a diamond, and the arrows between them.`:`No shapes were read. Draw a closed shape, like a box or a circle.`};let f=new Map(e.groups.map(e=>[e.id,e])),p=new Map([...u,...e.groups].map(e=>[e.id,e.poly])),m=(e,t)=>{for(let n=t.parent;n!==null;n=f.get(n)?.parent??null)if(n===e)return!0;return!1},h=(e,t,n)=>{let r=[e.pts[0],e.pts[e.pts.length-1]];if(t===n)return t===e.from?r[0]:r[1];let i=e=>w(e,p.get(t)??[])-w(e,p.get(n)??[]);return i(r[0])<=i(r[1])?r[0]:r[1]},g=(e,t,n)=>u.filter(t=>m(e,t)&&t.id!==n).sort((e,n)=>w(t,e.poly)-w(t,n.poly))[0]?.id,_=0,v=e.edges.filter(e=>!c.has(e.from)&&!c.has(e.to)).flatMap(e=>{let t=f.has(e.from)?g(e.from,h(e,e.from,e.to),e.to):e.from,n=f.has(e.to)?g(e.to,h(e,e.to,e.from),e.from):e.to;return t&&n?[{...e,from:t,to:n}]:(_++,[])}),y=e=>t[e]?.replace(/\s+/g,` `).trim()??``,b=new Map(o.nodes.map(e=>[e.id,e])),x=new Map,S=new Set;for(let e of u){let t=n.nodes[e.id],r=t===void 0?void 0:b.get(t);r&&!S.has(r.id)&&(x.set(e.id,r),S.add(r.id))}for(let e of u){if(x.has(e.id)||!y(e.id))continue;let t=o.nodes.filter(t=>!S.has(t.id)&&(t.name||t.id)===y(e.id));t.length===1&&(x.set(e.id,t[0]),S.add(t[0].id))}let ee=e=>y(e.id)||(x.get(e.id)?.name??``)||e.label,C=new Map((o.groups??[]).map(e=>[e.id,e])),te=e=>y(e.id)||C.get(n.groups[e.id]??``)?.name||e.label,ne=[`flowchart TD`,...u.map(e=>` ${G(e.id,e.kind,K(ee(e)))}`)],T=[];for(let e of v)for(let[t,n]of e.both?[[e.from,e.to],[e.to,e.from]]:[[e.from,e.to]]){let r=y(e.id);ne.push(` ${t} -->${r?`|"${K(r)}"|`:``} ${n}`),T.push({line:e,from:t.toLowerCase(),to:n.toLowerCase()})}let E=ne.join(`
2
+ `),re=d(E,{name:`sketch read`});if(!re.ok)return{error:`grooph could not read the drawing: ${re.error}`};let ie=re.doc,ae=i(o),oe=e=>{let t=r(e,ae);return ae.add(t),t},se={nodes:{},edges:{},groups:{}},D=new Map,O=[],k=new Set,A=0;for(let e of u){let t=ie.nodes.find(t=>t.id===e.id.toLowerCase());if(!t)continue;let n=x.get(e.id),r=ee(e),i;n&&J(n)===ve[e.kind]?(i={...n,name:r},k.add(r)):n&&n.kind===`agent`&&t.kind===`agent`?i={...n,name:r,role:t.role}:n?i={...t,id:n.id,name:r}:(i={...t,id:oe(a(r,`step`)),name:r},A++),D.set(t.id,i.id),se.nodes[e.id]=i.id,O.push(i)}let j=(e,t)=>{let n=new Map(t.map((e,t)=>[e.id,t]));return e.map((e,r)=>[e,n.get(e.id)??t.length+r]).sort((e,t)=>e[1]-t[1]).map(([e])=>e)},M=o.edges.filter(e=>S.has(e.from)&&S.has(e.to)),ce=new Set,N=new Set,P=new Map,le=[];for(let e of ie.edges){let t=D.get(e.from),r=D.get(e.to);if(!t||!r)continue;let i=T.findIndex((t,n)=>!N.has(n)&&t.from===e.from&&t.to===e.to);i>=0&&N.add(i);let a=i>=0?T[i].line:void 0,o=e.label!==void 0&&a&&y(a.id)?{...e,label:y(a.id)}:e,s=a?n.edges[a.id]:void 0,c=M.filter(e=>!ce.has(e.id)&&e.from===t&&e.to===r),l=c.find(e=>e.id===s)??c[0],u;if(l){if(ce.add(l.id),a===void 0||s!==l.id&&y(a.id)===``||y(a.id)===ye(l))u=l;else{let{when:e,approval:t,label:n,...r}=l;u={...r,...o.when===void 0?{}:{when:o.when},...o.approval?{approval:!0}:{},...o.label===void 0?{}:{label:o.label}}}}else u={...o,id:oe(`${t}-to-${r}`),from:t,to:r};P.set(e.id,u.id),a&&se.edges[a.id]===void 0&&(se.edges[a.id]=u.id),le.push(u)}let F=new Set(le.map(e=>e.id)),I=new Set(O.map(e=>e.id)),L=o.loops.filter(e=>e.back.every(e=>F.has(e))&&e.members.every(e=>I.has(e))),R=o.loops.filter(e=>!L.includes(e));for(let e of L)k.add(e.name);for(let e of ie.loops){let t=e.members.map(e=>D.get(e)).filter(e=>e!==void 0),n=e.back.map(e=>P.get(e)).filter(e=>e!==void 0);if(t.length===0||n.length===0)continue;let r=new Set(L.filter(e=>e.members.some(e=>t.includes(e))).flatMap(e=>e.members));if(t.every(e=>r.has(e))){k.add(e.name);continue}let i=new Set(t),a=new Set(L.flatMap(e=>e.back)),o=Ee(t,le.filter(e=>i.has(e.from)&&i.has(e.to)&&!a.has(e.id)),le);if(o.length===0){let n=e=>le.some(t=>t.id===e&&i.has(t.from)&&i.has(t.to)),r=L.filter(e=>e.back.some(n)).sort((e,t)=>t.members.length-e.members.length)[0];r&&(L[L.indexOf(r)]={...r,members:[...r.members,...t.filter(e=>!r.members.includes(e))]}),k.add(e.name);continue}let s=e=>e.members.filter(e=>t.includes(e)).length/new Set([...e.members,...t]).size,c=R.filter(e=>s(e)>=.5).sort((e,t)=>s(t)-s(e))[0];c?(R.splice(R.indexOf(c),1),k.add(e.name),L.push({...c,members:t,back:o})):L.push({...e,id:oe(`${t[0]}-loop`),members:t,back:o})}let ue=new Set,de=[],fe=new Map;for(let t of e.groups){let e=n.groups[t.id],r=e!==void 0&&!ue.has(e)?C.get(e):void 0;r&&ue.add(r.id),fe.set(t.id,r?r.id:oe(a(te(t),`box`)))}let pe=new Map(u.map(e=>[e.id,se.nodes[e.id]])),z=e.groups.flatMap(t=>{let n=fe.get(t.id),r=[...u.filter(e=>e.parent===t.id).map(e=>pe.get(e.id)),...e.groups.filter(e=>e.parent===t.id).map(e=>fe.get(e.id))],i=C.get(n),a=new Map((i?.members??[]).map((e,t)=>[e,t])),o=r.filter(e=>e!==void 0).map((e,t)=>[e,a.get(e)??1e6+t]).sort((e,t)=>e[1]-t[1]).map(([e])=>e);if(o.length===0)return[];se.groups[t.id]=n;let s=te(t);return i||de.push(`${s}: a box drawn round steps, so a group`),[i?{...i,name:s,members:o}:{id:n,name:s,members:o}]}),me=new Set((o.groups??[]).filter(e=>s.includes(e.id)&&!ue.has(e.id)).map(e=>e.id)),he=new Set(O.map(e=>e.id));for(let e of o.groups??[]){if(!me.has(e.id))continue;let t=e.members.filter(e=>he.has(e)||me.has(e)||ue.has(e));t.length&&z.push(t.length===e.members.length?e:{...e,members:t})}let B=new Set([o.id,...O.map(e=>e.id),...le.map(e=>e.id),...L.map(e=>e.id),...z.map(e=>e.id)]),V=(o.policies??[]).filter(e=>e.scope===`graph`||B.has(e.scope.slice(e.scope.indexOf(`:`)+1))),ge=e=>e.bar?.answerKeyFrom!==void 0&&!B.has(e.bar.answerKeyFrom)?{...e,bar:(({answerKeyFrom:e,...t})=>t)(e.bar)}:e,H=e=>e.stops.map(e=>e.then!==void 0&&!B.has(e.then)?(({then:e,...t})=>t)(e):e),_e=o.layout?Object.fromEntries(Object.entries(o.layout).filter(([e])=>B.has(e))):void 0,U={...o,nodes:j(O,o.nodes),edges:j(le,o.edges),loops:j(L,o.loops).map(e=>({...ge(e),stops:H(e)}))};V.length?U.policies=V:delete U.policies,z.length?U.groups=j(z,o.groups??[]):delete U.groups,_e&&Object.keys(_e).length?U.layout=_e:delete U.layout;let W=l(U);if(!W.doc)return{error:`The drawing made a graph grooph cannot keep: ${W.issues[0]?.message??`it does not match the schema`}`};let q=[...re.guesses.filter(e=>!k.has(e.slice(0,e.indexOf(`: `)))).map(e=>e.replace(`: a stadium, so `,`: an oval, so `)),...de],be=[c.size?`${c.size===1?`The start dot is`:`${c.size} start dots are`} not a step: a run starts at the steps nothing leads to.`:``,_?`${_===1?`A line that ends`:`${_} lines that end`} on a box with no other step in it ${_===1?`was`:`were`} left out.`:``].filter(Boolean).join(` `)||void 0;return{doc:U,guesses:q,became:se,counts:{added:A,kept:S.size,removed:o.nodes.length-S.size},mermaid:E,...be?{left:be}:{}}}var ke=`
3
+ <section class="sk-draw" aria-label="Drawing">
4
+ <div class="sk-bar" role="toolbar" aria-label="Drawing tools">
5
+ <div class="sk-tools-row">
6
+ <div class="sk-tools">
7
+ <div class="sk-seg" role="radiogroup" aria-label="Tool">
8
+ <button type="button" role="radio" aria-checked="true" data-tool="draw" title="Pen (D)">
9
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M3.5 16.5 4.4 13 13 4.4a1.8 1.8 0 0 1 2.6 2.6L7 15.6Z" /><path d="m11.6 5.8 2.6 2.6" /></svg><span>Pen</span>
10
+ </button>
11
+ <button type="button" role="radio" aria-checked="false" data-tool="erase" data-options="eraser" title="Eraser (E). Tap it again to erase whole strokes or only what it passes over" aria-describedby="sk-tool-kinds">
12
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M8.2 16.5h8.3M3.9 12.2l7.5-7.5a1.6 1.6 0 0 1 2.3 0l2.6 2.6a1.6 1.6 0 0 1 0 2.3l-6.3 6.3a2 2 0 0 1-1.4.6H6.8a2 2 0 0 1-1.4-.6l-1.5-1.5a1.6 1.6 0 0 1 0-2.2Z" /><path d="m7.3 8.8 4.8 4.8" /></svg><span>Eraser</span>
13
+ </button>
14
+ <button type="button" role="radio" aria-checked="false" data-tool="select" data-options="select" title="Select (V): press a stroke to move it, or drag a box around strokes. Tap it again for a lasso" aria-describedby="sk-tool-kinds">
15
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4.5 3.2 15.3 9l-4.7 1.3-2.2 4.4Z" /><path d="m10.6 10.3 3.6 4.9" /></svg><span>Select</span>
16
+ </button>
17
+ <button type="button" role="radio" aria-checked="false" data-tool="hand" title="Hand (H): drag to move around the drawing. Space and a drag does the same">
18
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M7 10.5V5.2a1.2 1.2 0 0 1 2.4 0v4.3M9.4 9.5V4a1.2 1.2 0 0 1 2.4 0v5.5M11.8 9.5V5a1.2 1.2 0 0 1 2.4 0v6.2c0 3.2-2 5.3-4.8 5.3-2 0-3.2-.9-4.3-2.6L3.5 11.2a1.2 1.2 0 0 1 2-1.3L7 12" /></svg><span>Hand</span>
19
+ </button>
20
+ </div>
21
+ <ul class="sk-menu sk-tool-menu" id="sk-tool-menu" role="menu" hidden></ul>
22
+ <span class="sr-only" id="sk-tool-kinds">Once chosen, press again for its kinds.</span>
23
+ </div>
24
+ <span class="sk-rule" aria-hidden="true"></span>
25
+ <fieldset class="sk-inks" id="sk-inks">
26
+ <legend class="sr-only">Ink</legend>
27
+ </fieldset>
28
+ </div>
29
+ <div class="sk-tools-row">
30
+ <button class="sk-icon" type="button" id="sk-undo" aria-label="Undo" title="Undo (Ctrl+Z)" disabled>
31
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M7.5 5 4 8.5 7.5 12" /><path d="M4.5 8.5h7.2a4.3 4.3 0 0 1 0 8.6H9" /></svg>
32
+ </button>
33
+ <button class="sk-icon" type="button" id="sk-redo" aria-label="Redo" title="Redo (Ctrl+Shift+Z)" disabled>
34
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M12.5 5 16 8.5 12.5 12" /><path d="M15.5 8.5H8.3a4.3 4.3 0 0 0 0 8.6H11" /></svg>
35
+ </button>
36
+ <button class="sk-icon" type="button" id="sk-clear" aria-label="Clear the drawing" title="Clear the drawing (Undo brings it back)" disabled>
37
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M3.8 5.8h12.4M8 5.8V4.2h4v1.6M5.4 5.8l.8 10a1.4 1.4 0 0 0 1.4 1.3h4.8a1.4 1.4 0 0 0 1.4-1.3l.8-10M8.6 9v4.8M11.4 9v4.8" /></svg>
38
+ </button>
39
+ <span class="sk-rule" aria-hidden="true"></span>
40
+ <div class="sk-more sk-add">
41
+ <button class="sk-icon" type="button" id="sk-add" aria-haspopup="menu" aria-expanded="false" aria-controls="sk-add-list" aria-label="Add a step, an arrow, or a template" title="Add a step, an arrow, or a template">
42
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 4.2v11.6M4.2 10h11.6" /></svg>
43
+ </button>
44
+ <div class="sk-menu sk-add-menu" id="sk-add-list" role="menu" aria-label="Add" hidden></div>
45
+ </div>
46
+ <div class="sk-more">
47
+ <button class="sk-icon" type="button" id="sk-more" aria-haspopup="menu" aria-expanded="false" aria-controls="sk-more-list" aria-label="More" title="More">
48
+ <svg viewBox="0 0 20 20" aria-hidden="true"><circle cx="4.5" cy="10" r="1.4" /><circle cx="10" cy="10" r="1.4" /><circle cx="15.5" cy="10" r="1.4" /></svg>
49
+ </button>
50
+ <ul class="sk-menu" id="sk-more-list" role="menu" aria-label="More" hidden>
51
+ <li role="none"><button type="button" role="menuitem" data-act="example">Load the example</button></li>
52
+ <li role="none"><button type="button" role="menuitem" data-act="redraw">Draw the graph again</button></li>
53
+ <li role="none"><button type="button" role="menuitem" data-act="fit">Fit the drawing to the screen</button></li>
54
+ <li role="none"><button type="button" role="menuitemcheckbox" aria-checked="true" data-act="snap">Snap shapes and arrows when you hold</button></li>
55
+ <li role="none"><button type="button" role="menuitemcheckbox" aria-checked="true" data-act="names">Show names on the drawing</button></li>
56
+ <li role="none"><button type="button" role="menuitemcheckbox" aria-checked="true" data-act="outlines">Show what it read</button></li>
57
+ <li role="separator"></li>
58
+ <li role="none"><button type="button" role="menuitem" data-act="save-drawing">Save the drawing (.json)</button></li>
59
+ <li role="none"><button type="button" role="menuitem" data-act="open-drawing">Open a drawing…</button></li>
60
+ </ul>
61
+ <input type="file" id="sk-open-file" accept=".json,application/json" hidden />
62
+ </div>
63
+ <span class="sk-spacer"></span>
64
+ <button class="sk-go" type="button" id="sk-go" data-stale="false" title="Make it a graph (Ctrl+Enter)">
65
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M3 10.2c1.6-3.4 3.4-3.4 5 0s3.4 3.4 5 0" /><path d="m13.5 6.5 3.5 3.7-3.5 3.7" /></svg>Make it a graph
66
+ </button>
67
+ </div>
68
+ </div>
69
+ <div class="sk-pad" id="sk-pad-wrap">
70
+ <canvas id="sk-pad" role="img" aria-label="Drawing area. Draw the steps and the arrows that join them, then press Make it a graph."></canvas>
71
+ <div class="sk-hint" id="sk-hint">
72
+ <p><strong>Draw a graph here.</strong> Boxes, ovals, diamonds, and the other shapes, joined by arrows, in any order. Hold still at the end of a shape to tidy it, then press Make it a graph. The plus adds steps, arrows, and templates.</p>
73
+ <button class="btn" type="button" id="sk-hint-example">Load the example</button>
74
+ </div>
75
+ <p class="sk-chip" id="sk-pen-chip" hidden>
76
+ <span>Pen draws; fingers move the drawing.</span>
77
+ <button type="button" id="sk-fingers-draw">Let fingers draw</button>
78
+ </p>
79
+ <div class="sk-corner">
80
+ <button class="sk-zoom" type="button" id="sk-zoom" title="Fit the drawing to the screen" hidden></button>
81
+ <button class="sk-full" type="button" id="sk-full" aria-pressed="false" aria-label="Full screen" title="Full screen (F)">
82
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path class="sk-enter" d="M3.5 7.5v-4h4M12.5 3.5h4v4M16.5 12.5v4h-4M7.5 16.5h-4v-4" /><path class="sk-leave" d="M7.5 3.5v4h-4M16.5 7.5h-4v-4M12.5 16.5v-4h4M3.5 12.5h4v4" /></svg>
83
+ </button>
84
+ </div>
85
+ <div class="sk-sel-bar" id="sk-sel-bar" role="toolbar" aria-label="Chosen strokes" hidden>
86
+ <button type="button" data-sel="cut">Cut</button>
87
+ <button type="button" data-sel="copy">Copy</button>
88
+ <button type="button" data-sel="paste">Paste</button>
89
+ <button type="button" data-sel="duplicate">Duplicate</button>
90
+ <button type="button" data-sel="group">Group</button>
91
+ <button type="button" data-sel="snap" title="Make the chosen shapes and arrows clean">Snap</button>
92
+ <button type="button" data-sel="delete">Delete</button>
93
+ </div>
94
+ <form class="sk-name-edit" id="sk-name-edit" hidden>
95
+ <label class="sr-only" for="sk-name-input" id="sk-name-label">Name</label>
96
+ <input id="sk-name-input" type="text" autocomplete="off" enterkeyhint="done" maxlength="120" data-own-undo />
97
+ </form>
98
+ </div>
99
+ <div class="sk-read-row">
100
+ <p class="sk-read" id="sk-read" aria-live="polite">Nothing read yet.</p>
101
+ <label class="sk-check"><input type="checkbox" id="sk-show-read" checked /> Show what it read</label>
102
+ </div>
103
+ </section>
104
+
105
+ <section class="sk-result" id="sk-result" aria-label="The graph">
106
+ <a class="sk-back" href="#sk-pad-wrap" id="sk-back">Back to the drawing</a>
107
+ <div class="sk-panel">
108
+ <div class="sk-panel-head">
109
+ <h2>Graph</h2>
110
+ <span id="sk-graph-hint">Tap a step to open it</span>
111
+ </div>
112
+ <div class="sk-diagram" id="sk-diagram"><p class="sk-empty">The graph appears here after Make it a graph.</p></div>
113
+ <ul class="sk-guesses" id="sk-guesses" aria-label="What was guessed" hidden></ul>
114
+ <div class="sk-row">
115
+ <button class="btn" type="button" id="sk-undo-make" hidden>Undo Make it a graph</button>
116
+ <button class="btn" type="button" id="sk-save-svg" disabled>Save SVG</button>
117
+ <button class="btn" type="button" id="sk-save-png" disabled>Save PNG</button>
118
+ <button class="btn" type="button" id="sk-export" title="Share a link, embed it, or download the package">Export…</button>
119
+ <span class="sk-status" id="sk-save-status" role="status"></span>
120
+ </div>
121
+ </div>
122
+ <div class="sk-panel">
123
+ <div class="sk-panel-head">
124
+ <h2>Names</h2>
125
+ <span id="sk-names-note">Each step's and line's name, and what each shape makes</span>
126
+ </div>
127
+ <div class="sk-names" id="sk-names"><p class="sk-status">Shapes appear here after Make it a graph.</p></div>
128
+ <p class="sk-note">Name a line <strong>pass</strong> or <strong>fail</strong> and it is followed only on that result; <strong>approval</strong> asks a person first.</p>
129
+ </div>
130
+ <div class="sk-panel">
131
+ <div class="sk-panel-head">
132
+ <h2><label for="sk-code">Mermaid code</label></h2>
133
+ <span>The graph as Mermaid, as grooph writes it</span>
134
+ </div>
135
+ <textarea class="sk-code" id="sk-code" readonly spellcheck="false" autocapitalize="off" autocomplete="off" autocorrect="off" rows="12"></textarea>
136
+ <div class="sk-row">
137
+ <button class="btn" type="button" id="sk-copy">Copy code</button>
138
+ <button class="btn" type="button" id="sk-save-mmd">Save .mmd</button>
139
+ <span class="sk-status" id="sk-copy-status" role="status"></span>
140
+ </div>
141
+ </div>
142
+ </section>`;function Ae(e,t=1){if(e.length<3)return!1;let n=t>=.01&&t<=100?t:1,r=e.map(([e,t])=>[e*n,t*n]),i=b(r),a=x(r);return Math.max(a.w,a.h)>=28&&Math.min(a.w,a.h)>=18&&i>1.3*(a.w+a.h)&&le(r,i)<Math.max(14,.22*Math.hypot(a.w,a.h))}function je(e,t,n,r,i=3){let a=new Map,o=[];if(!t.length||!(n>0))return{strokes:e.slice(),pieces:a};let s=x(t),c=e=>{if(e[0]<s.x0-n||e[0]>s.x1+n||e[1]<s.y0-n||e[1]>s.y1+n)return!1;if(t.length===1)return y(e,t[0])<=n;for(let r=0;r<t.length-1;r++)if(C(e,t[r],t[r+1])<=n)return!0;return!1};for(let t of e){let e=x(t.pts);if(!t.pts.length||e.x1<s.x0-n||e.x0>s.x1+n||e.y1<s.y0-n||e.y0>s.y1+n){o.push(t);continue}let l=[],u=[];for(let e=0;e<t.pts.length;e++){let r=t.pts[e],i=t.pts[e+1];if(l.push(r),u.push(!0),!i)break;let a=Math.ceil(y(r,i)/(n/4));for(let e=1;e<a;e++)l.push([r[0]+(i[0]-r[0])*e/a,r[1]+(i[1]-r[1])*e/a]),u.push(!1)}let d=l.map(c);if(!d.some(Boolean)){o.push(t);continue}let f=[],p=[];l.forEach((e,t)=>{d[t]?(p.length&&f.push(p),p=[]):(u[t]||d[t-1]||d[t+1])&&p.push(e)}),p.length&&f.push(p),f.length>=2&&!t.open&&!d[0]&&!d[l.length-1]&&Ae(t.pts,t.zoom)&&f.unshift([...f.pop(),...f.shift()]);let m=[];for(let e of f)if(e.length>=2&&b(e)>=i){let n={...t,id:r(),pts:e,open:!0};m.push(n.id),o.push(n)}a.set(t.id,m)}return{strokes:o,pieces:a}}var Me=`mermaidify-drawing`,Ne=new Set([`ink`,`green`,`blue`,`red`,`amber`]),Pe=new Set([`pen`,`touch`,`mouse`]),Fe=new Set([`rect`,`subroutine`,`stadium`,`circle`,`double`,`diamond`,`hexagon`,`trapezoid`,`inv-trapezoid`,`lean-right`,`lean-left`,`triangle`,`flip-triangle`,`dot`,`bullseye`]),Ie=new Set([`plain`,`dotted`,`thick`]),Le=new Set([`state`,`choice`,`dot`]),Re=e=>Math.round(e*10)/10,ze=e=>typeof e==`number`&&Number.isInteger(e)&&e>=1&&e<=1e9?e:void 0,Be=e=>typeof e==`number`&&e>=.01&&e<=100&&Math.abs(e-1)>.001?Math.round(e*1e3)/1e3:void 0,Ve=1e5;function He(e,t,n,r,i={},a={},o=`flowchart`,s={}){return{format:Me,version:1,saved:new Date().toISOString(),strokes:e.map(e=>({color:e.color,by:e.by,pts:e.pts.map(([e,t])=>[Re(e),Re(t)]),...e.open?{open:!0}:{},...Be(e.zoom)?{zoom:Be(e.zoom)}:{},...ze(e.group)?{group:ze(e.group)}:{}})),labels:t,...Object.keys(i).length?{shapes:i}:{},...Object.keys(a).length?{lines:a}:{},...o===`state`?{diagram:o}:{},...Object.keys(s).length?{roles:s}:{},mermaid:n,...r?{edited:!0}:{}}}function Ue(e){let t=e=>({ok:!1,error:e});if(!e||typeof e!=`object`)return t(`This file is not a drawing.`);let n=e;if(n.format!==`mermaidify-drawing`)return t(`This file is not a mermaidify drawing.`);if(n.version!==1)return t(`This drawing was saved by a newer version of mermaidify.`);if(!Array.isArray(n.strokes)||n.strokes.length>1e3)return t(`This drawing's strokes cannot be read.`);let r=[],i=0;for(let e of n.strokes){let n=e;if(!n||!Array.isArray(n.pts)||n.pts.length>1e4)return t(`This drawing's strokes cannot be read.`);if(i+=n.pts.length,i>15e4)return t(`This drawing is too large to open here.`);let a=[];for(let e of n.pts){if(!Array.isArray(e)||e.length<2||!Number.isFinite(e[0])||!Number.isFinite(e[1])||Math.abs(e[0])>1e6||Math.abs(e[1])>1e6)return t(`This drawing's strokes cannot be read.`);a.push([e[0],e[1]])}a.length&&r.push({color:Ne.has(n.color)?n.color:`ink`,by:Pe.has(n.by)?n.by:`mouse`,pts:a,...n.open===!0?{open:!0}:{},...Be(n.zoom)?{zoom:Be(n.zoom)}:{},...ze(n.group)?{group:ze(n.group)}:{}})}let a={};if(n.labels&&typeof n.labels==`object`)for(let[e,t]of Object.entries(n.labels))/^[A-Za-z0-9_]{1,12}$/.test(e)&&typeof t==`string`&&(a[e]=t.slice(0,200));let o={};if(n.shapes&&typeof n.shapes==`object`)for(let[e,t]of Object.entries(n.shapes))/^[A-Za-z0-9_]{1,12}$/.test(e)&&Fe.has(t)&&(o[e]=t);let s={};if(n.lines&&typeof n.lines==`object`)for(let[e,t]of Object.entries(n.lines))/^[A-Za-z0-9_]{1,12}$/.test(e)&&Ie.has(t)&&(s[e]=t);let c={};if(n.roles&&typeof n.roles==`object`)for(let[e,t]of Object.entries(n.roles))/^[A-Za-z0-9_]{1,12}$/.test(e)&&Le.has(t)&&(c[e]=t);let l=n.diagram===`state`?`state`:`flowchart`,u=typeof n.mermaid==`string`?n.mermaid.slice(0,Ve):``;return{ok:!0,file:{format:Me,version:1,saved:typeof n.saved==`string`?n.saved:``,strokes:r,labels:a,shapes:o,lines:s,diagram:l,roles:c,mermaid:u,edited:n.edited===!0}}}function We(e,t){let n=E(e,t,7,-1),r=E(e,t,6,1),i=[e[t][0]-n[0],e[t][1]-n[1]],a=[r[0]-e[t][0],r[1]-e[t][1]],o=Math.hypot(i[0],i[1]),s=Math.hypot(a[0],a[1]);return o<3||s<3?Ge:(i[0]*a[0]+i[1]*a[1])/(o*s)}var Ge=2;function Ke(e,t,n=0,r){let i=0,a=e.length-1;for(;a>n&&i<t;)i+=y(e[a],e[a-1]),a--;let o=-1,s=-.3;for(let t=Math.max(1,a);t<e.length-1;t++){let n=r?r[t]:NaN;if(Number.isNaN(n)&&(n=We(e,t),r&&(r[t]=n)),n!==Ge){if(n<s)o=t,s=n;else if(o>=0)break}}return o}function qe(e){let t=b(e),n=new Float64Array(e.length).fill(NaN),r=Ke(e,Math.min(.7*t,Math.max(60,.4*t)),0,n);if(r>=0){let n=e.slice(r),i=b(n),a=Math.max(...n.map(t=>y(t,e[r])));i>=6&&i<=90&&i>=1.5*a&&a<=Math.max(28,.5*(t-i))||(r=-1)}let i=r;for(let r of[Ze(e,t,n),Je(e,t,n)])r>=0&&(i<0||r<i)&&(i=r);return i}function Je(e,t,n){if(t>Xe)return-1;let r=Ke(e,.85*t,0,n);if(r<0)return-1;let i=e.slice(r),a=e[r],o=b(i),s=t-o,c=i.reduce((e,t)=>y(t,a)>y(e,a)?t:e),l=y(c,a);if(s<10||l>1.25*s||o<2.2*l||o>3.6*l||y(e[0],a)<.9*s||!Ye(i,a,l))return-1;let u=(a[0]-e[0][0])/y(e[0],a),d=(a[1]-e[0][1])/y(e[0],a),f=e=>(e[0]-a[0])*u+(e[1]-a[1])*d<-.2*l;return f(c)&&f(i[i.length-1])?r:-1}function Ye(e,t,n){let r=0;for(;r<e.length&&y(e[r],t)<.6*n;)r++;for(;r<e.length&&y(e[r],t)>Math.max(10,.25*n);)r++;let i=r;for(;r<e.length&&y(e[r],t)<.5*n;)r++;if(i>=e.length||r>=e.length)return!1;let a=0;for(let t=0,n=0;t<4;t++){let t=Ke(e,b(e.slice(n)),n);if(t<0||t<=n)break;a++,n=t+1}return a<=3}var Xe=480;function Ze(e,t,n){let r=Ke(e,Math.min(.7*t,Math.max(60,.6*t)),0,n);if(r<0)return-1;let i=e.slice(r),a=e[r],o=b(i),s=Math.max(...i.map(e=>y(e,a)));return o<=90||o>3.5*s||s>.5*(t-o)?-1:Ye(i,a,s)?r:-1}var Qe=40,$e=120,et=20;function tt(e,t=Qe,n=$e){let r=1/0,i=1/0,a=-1/0,o=-1/0,s=-1;for(let n=0;n<e.length&&(r=Math.min(r,e[n][0]),i=Math.min(i,e[n][1]),a=Math.max(a,e[n][0]),o=Math.max(o,e[n][1]),!(Math.max(a-r,o-i)>t));n++)s=n;if(s<2||s===e.length-1)return null;let c=e.slice(0,s+1),l=b(c),u=b(e)-l;if(l<n||u<et)return null;let d=e[e.length-1];return{at:s,tip:c.reduce((e,t)=>y(t,d)>y(e,d)?t:e)}}function nt(e){let t=e.slice(),n=!1,r=!1,i=tt(t);i&&(t=[i.tip,...t.slice(i.at)],r=!0);let a=tt(t.slice().reverse());a&&(t=[...t.slice(0,t.length-a.at),a.tip],n=!0);let o=n?-1:qe(t);o>=0&&(t=t.slice(0,o+1),n=!0);let s=t.slice().reverse(),c=r?-1:qe(s);return c>=0&&(t=s.slice(0,c+1).reverse(),r=!0),{pts:t,headEnd:n,headStart:r}}function rt(e){let t=e.length,n=e[t-1],r=0,i=-1;for(let a=t-2;a>0;a--){if(r+=y(e[a],e[a+1]),r<24)continue;let t=y(e[a],n);if(t<=Math.max(8,.12*r))(i<0||t<y(e[i],n))&&(i=a);else if(i>=0)break}if(i<0)return null;let a=e.slice(i),o=x(a),s=Math.max(o.w,o.h),c=b(a),l=b(e.slice(0,i+1));if(s<8||l<Math.max(20,s/.55)||c<2.4*s||c>4.2*s)return null;let u=ie(a),d=re(u);if(!(d>0)||re(a)<.75*d||it(u)<.75*d)return null;let f=E(e,i,Math.min(40,.5*l),-1),p=y(f,e[i]);if(p<1)return null;let m=(e[i][0]-f[0])/p,h=(e[i][1]-f[1])/p,g=a[0],_=-1/0,v=0,S=0;for(let t of a){let n=(t[0]-e[i][0])*m+(t[1]-e[i][1])*h,r=(t[0]-e[i][0])*h-(t[1]-e[i][1])*m;n>_&&(_=n,g=t),v=Math.max(v,r),S=Math.max(S,-r)}return Math.min(v,S)<.25*s?null:Math.abs((g[0]-e[i][0])*h-(g[1]-e[i][1])*m)<=.6*s?{at:i,tip:g}:null}function it(e){let t=e.length>48?e.filter((t,n)=>n%Math.ceil(e.length/48)===0):e,n=0;for(let e=0;e<t.length;e++)for(let r=e+1;r<t.length;r++)for(let i=r+1;i<t.length;i++){let a=Math.abs((t[r][0]-t[e][0])*(t[i][1]-t[e][1])-(t[i][0]-t[e][0])*(t[r][1]-t[e][1]))/2;a>n&&(n=a)}return n}function at(e){let t=e=>{let t=b(e),n=e[0],r=e[e.length-1];return t>=30&&y(n,r)>=.85*t?{tail:n,tip:r}:null},n=rt(e),r=n&&t([...e.slice(0,n.at+1),n.tip]);if(r)return r;let i=nt(e);return i.headEnd&&!i.headStart?t(i.pts):null}var ot=(e=0,t=0)=>({dx:0,dy:0,angle:0,scale:1,cx:e,cy:t});function st(e,t){let n=(e[0]-t.cx)*t.scale,r=(e[1]-t.cy)*t.scale,i=Math.cos(t.angle),a=Math.sin(t.angle);return[t.cx+n*i-r*a+t.dx,t.cy+n*a+r*i+t.dy]}function ct(e){if(e.pts.length<8)return!1;let t=x(e.pts);return Math.min(t.w,t.h)>8&&y(e.pts[0],e.pts[e.pts.length-1])<Math.max(14,.25*Math.hypot(t.w,t.h))}function lt(e,t){let n=new Set(t);for(let t=!0;t;){t=!1;let r=new Set(e.filter(e=>n.has(e.id)&&e.group!==void 0).map(e=>e.group)),i=e.filter(e=>n.has(e.id)&&ct(e));for(let a of e){if(n.has(a.id))continue;let e=x(a.pts),o=i.some(t=>{let n=x(t.pts);return e.x0>=n.x0&&e.x1<=n.x1&&e.y0>=n.y0&&e.y1<=n.y1&&a.pts.every((e,n)=>n%4!=0||ne(e,t.pts))});(a.group!==void 0&&r.has(a.group)||o)&&(n.add(a.id),t=!0)}}return n}function ut(e,t){if(t.length<3)return new Set;let n=x(t),r=[],i=Math.max(2,Math.min(n.w,n.h)/4);for(let a of e){let e=x(a.pts);e.x1<n.x0||e.x0>n.x1||e.y1<n.y0||e.y0>n.y1||(a.pts.length>1?T(a.pts,i):a.pts).some(e=>ne(e,t))&&r.push(a.id)}return lt(e,r)}function dt(e,t,n){let r=null;for(let i of e){let e=i.pts;for(let a=0;a<e.length;a++){let o=e.length===1?y(t,e[0]):C(t,e[a],e[Math.min(a+1,e.length-1)]);o<=n&&(!r||o<r.d)&&(r={id:i.id,d:o})}}return r?.id??null}function ft(e,t){let n=null,r=e.filter(ct);for(let e of r){let r=x(e.pts);t[0]<r.x0||t[0]>r.x1||t[1]<r.y0||t[1]>r.y1||!ne(t,e.pts)||(!n||r.w*r.h<n.b.w*n.b.h)&&(n={s:e,b:r})}if(!n)return null;let{s:i,b:a}=n;return r.some(e=>{if(e===i)return!1;let t=x(e.pts);return t.x0>=a.x0&&t.x1<=a.x1&&t.y0>=a.y0&&t.y1<=a.y1})?null:i.id}var pt=(e,t)=>[e,[t[0],e[1]],t,[e[0],t[1]],e];function mt(e,t){let n=e.filter(e=>t.has(e.id)).flatMap(e=>e.pts);return n.length?x(n):null}function ht(e,t,n){return e.map(e=>t.has(e.id)?{...e,pts:e.pts.map(e=>st(e,n)),open:e.open}:e)}function gt(e,t,n,r,i,a=e){let o=new Map,s=new Map,c=[],l=Math.max(0,...a.map(e=>e.group??0));for(let a of e){if(!t.has(a.id))continue;let e=i(),u=a.group;u!==void 0&&(o.has(u)||o.set(u,++l),u=o.get(u)),c.push({...a,id:e,pts:a.pts.map(([e,t])=>[e+n,t+r]),...u===void 0?{}:{group:u}}),s.set(e,a.id)}return{copies:c,from:s}}var _t=e=>Math.round(e/(Math.PI/12))*(Math.PI/12),vt=.1,yt=4,X=e=>getComputedStyle(document.documentElement).getPropertyValue(e).trim();function bt(e,t){let n=e.getContext(`2d`),r=0,i=0,a=!1,o=[],s=null,c=!0,l=[],u=!0,d=`draw`,f=`ink`,p={scale:1,x:0,y:0},m=1,h=!1,g=-1e9,_=(e,t)=>[(e-p.x)/p.scale,(t-p.y)/p.scale],v=t=>{let n=e.getBoundingClientRect();return[t.clientX-n.left,t.clientY-n.top]};function x(){a||(a=!0,requestAnimationFrame(()=>{a=!1,re()}))}function S(){let t=e.getBoundingClientRect(),a=Math.min(window.devicePixelRatio||1,3),s=t.width!==r||t.height!==i;r=t.width,i=t.height,e.width=Math.max(1,Math.round(r*a)),e.height=Math.max(1,Math.round(i*a)),n.setTransform(a,0,0,a,0,0),s&&o.length&&!w()&&ne(),re()}function w(){let e=te();if(!e)return!0;let[t,n]=[e[0]*p.scale+p.x,e[1]*p.scale+p.y],[a,o]=[e[2]*p.scale+p.x,e[3]*p.scale+p.y];return t>=-2&&n>=-2&&a<=r+2&&o<=i+2}function te(){let e=1/0,t=1/0,n=-1/0,r=-1/0;for(let i of o)for(let[a,o]of i.pts)a<e&&(e=a),o<t&&(t=o),a>n&&(n=a),o>r&&(r=o);return e===1/0?null:[e,t,n,r]}function ne(){let e=te();if(!e||!r||!i){T({scale:1,x:0,y:0});return}let t=e[2]-e[0],n=e[3]-e[1],a=Math.max(vt,Math.min(1,(r-32)/Math.max(t,1),(i-32)/Math.max(n,1)));a===1&&e[0]>=14&&e[1]>=14&&e[2]<=r-16+2&&e[3]<=i-16+2?T({scale:1,x:0,y:0}):T({scale:a,x:(r-t*a)/2-e[0]*a,y:(i-n*a)/2-e[1]*a})}function T(e){p=e,t.view(p),x()}function E(e){n.beginPath(),n.moveTo(e[0][0],e[0][1]),e.length===1&&n.lineTo(e[0][0]+.01,e[0][1]);for(let t=1;t<e.length-1;t++)n.quadraticCurveTo(e[t][0],e[t][1],(e[t][0]+e[t+1][0])/2,(e[t][1]+e[t+1][1])/2);e.length>1&&n.lineTo(e[e.length-1][0],e[e.length-1][1])}function re(){n.save(),n.clearRect(0,0,r,i);let e=24;for(;e*p.scale<10;)e*=2;let t=e*p.scale;n.fillStyle=X(`--dots`);let a=(p.x%t+t)%t,l=(p.y%t+t)%t,f=Math.max(.6,Math.min(1,p.scale));for(let e=a;e<r;e+=t)for(let r=l;r<i;r+=t)n.fillRect(e-f,r-f,2*f,2*f);n.translate(p.x,p.y),n.scale(p.scale,p.scale),n.lineCap=`round`,n.lineJoin=`round`;let m=Math.max(3/Math.sqrt(p.scale),1.3/p.scale),h=s&&c?s.reading:null;if(h){n.save(),n.lineWidth=m+8/p.scale,n.globalAlpha=.42,n.strokeStyle=X(`--accent`);for(let e of h.edges)for(let t of e.strokes)o[t]&&(E(o[t].pts),n.stroke());n.globalAlpha=.5,n.strokeStyle=X(`--warning`);for(let e of h.unused)o[e]&&(E(o[e].pts),n.stroke());n.restore()}let g=e=>q&&U.has(e.id)?e.pts.map(e=>st(e,q.m)):e.pts;if(U.size&&d===`select`){n.save(),n.lineWidth=m+6/p.scale,n.globalAlpha=.28,n.strokeStyle=X(`--accent`);for(let e of o)U.has(e.id)&&(E(g(e)),n.stroke());n.restore()}n.lineWidth=m;for(let e of o)n.globalAlpha=j.has(e.id)?.2:1,n.strokeStyle=X(`--draw-`+e.color)||X(`--draw-ink`),E(g(e)),n.stroke();if(n.globalAlpha=1,G&&(W===`lasso`||G.length>1)){if(n.save(),n.lineWidth=1.5/p.scale,n.setLineDash([5/p.scale,4/p.scale]),n.strokeStyle=n.fillStyle=X(`--accent`),n.beginPath(),W===`box`){let[e,t]=[G[0],G[G.length-1]];n.rect(Math.min(e[0],t[0]),Math.min(e[1],t[1]),Math.abs(t[0]-e[0]),Math.abs(t[1]-e[1]))}else E(G),n.closePath();n.stroke(),n.globalAlpha=.06,n.fill(),n.restore()}N&&(n.save(),n.globalAlpha=.22,n.strokeStyle=X(`--error`),n.lineWidth=2*D/p.scale,E(N),n.stroke(),n.restore());for(let e of[...A?.done??[],...O?[O]:[]])n.strokeStyle=X(`--draw-`+e.color),E(e.pts),n.stroke();h&&s&&!q?se(h,s.labels):!h&&u&&ie(),n.restore(),be(),ce&&(d===`erase`||d===`cut`)&&(n.save(),n.strokeStyle=X(`--ink-3`),n.setLineDash([3,3]),n.beginPath(),n.arc(ce[0],ce[1],D,0,Math.PI*2),n.stroke(),n.restore())}function ie(){if(!l.length||14*p.scale<7)return;let e=new Map(o.map(e=>[e.id,e]));n.save(),n.font=`600 14px ${X(`--font`)}`,n.textAlign=`center`,n.textBaseline=`middle`;for(let t of l){let r=t.strokes.flatMap(t=>e.get(t)??[]);if(!r.length)continue;let i=q&&r.some(e=>U.has(e.id))?st(t.at,q.m):t.at,a=Math.max(40,t.w-12),o=t.text;for(;o.length>1&&n.measureText(o).width>a;)o=o.slice(0,-2)+`…`;if(t.line){let e=n.measureText(o).width+10;n.fillStyle=X(`--surface`),n.beginPath(),n.roundRect(i[0]-e/2,i[1]-10,e,20,6),n.fill()}n.fillStyle=X(`--draw-`+r[0].color)||X(`--draw-ink`),n.fillText(o,i[0],i[1]+.5)}n.restore()}function ae(e,t,r=1){let i=t.w*r,a=t.h*r,o=t.cx-i/2,s=t.cy-a/2,c=k[e];n.beginPath(),c===`ellipse`?n.ellipse(t.cx,t.cy,i/2,a/2,0,0,Math.PI*2):(oe[c].forEach(([e,t],r)=>r?n.lineTo(o+e*i,s+t*a):n.moveTo(o+e*i,s+t*a)),n.closePath()),n.stroke()}function se(e,t){let r=1/p.scale,i=X(`--accent`);n.lineWidth=1.5*r,n.setLineDash([5*r,5*r]),n.strokeStyle=i;for(let t of[...e.groups,...e.nodes])ae(t.kind,t.bb),t.kind===`double`&&ae(`circle`,t.bb,.64),t.kind===`subroutine`&&ae(`rect`,t.bb,.8);n.setLineDash([]),n.lineWidth=2*r;for(let t of e.edges){if(!t.assumed||t.pts.length<2)continue;let e=t.pts[t.pts.length-1],i=t.pts.length-2;for(;i>0&&y(t.pts[i],e)<10*r;)i--;let a=Math.atan2(e[1]-t.pts[i][1],e[0]-t.pts[i][0]),o=9*r;n.beginPath(),n.moveTo(e[0]-o*Math.cos(a-.5),e[1]-o*Math.sin(a-.5)),n.lineTo(e[0],e[1]),n.lineTo(e[0]-o*Math.cos(a+.5),e[1]-o*Math.sin(a+.5)),n.stroke()}n.textBaseline=`middle`;for(let a of e.edges){let e=t[a.id]?.trim();if(!e||a.pts.length<2)continue;n.font=`600 ${12*r}px ${X(`--font`)}`;let o=e;for(;o.length>1&&n.measureText(o).width>160*r;)o=o.slice(0,-2)+`…`;let[s,c]=ee(a.pts),l=n.measureText(o).width+12*r;n.fillStyle=X(`--surface`),n.strokeStyle=i,n.lineWidth=1.5*r,n.beginPath(),n.roundRect(s-l/2,c-10*r,l,20*r,6*r),n.fill(),n.stroke(),n.fillStyle=X(`--ink`),n.textAlign=`center`,n.fillText(o,s,c+.5*r),n.textAlign=`start`}for(let a of[...e.groups,...e.nodes]){if(a.role===`dot`)continue;n.font=`600 ${11*r}px ${X(`--mono`)}`;let o=n.measureText(a.id).width+10*r,s=a.bb.x0-4*r,c=a.bb.y0-9*r;n.fillStyle=i,n.beginPath(),n.roundRect(s,c,o,18*r,5*r),n.fill(),n.fillStyle=X(`--accent-ink`),n.fillText(a.id,s+5*r,c+9.5*r);let l=a.role===`choice`?void 0:t[a.id]?.trim();if(l){n.font=`600 ${13*r}px ${X(`--font`)}`,n.fillStyle=X(`--ink`),n.textAlign=`center`;let t=Math.max(40*r,a.bb.w-12*r),i=l;for(;i.length>1&&n.measureText(i).width>t;)i=i.slice(0,-2)+`…`;let o=e.groups.includes(a)?a.bb.y0+14*r:a.bb.cy;n.fillText(i,a.bb.cx,o),n.textAlign=`start`}}}let D=14,O=null,A=null,j=new Set,M=null,ce=null,N=null,P=``,le=[0,0],F=new Map,I=null,L=null,R=!1,de=e=>e.pointerType===`pen`&&!!(e.buttons&34),fe=e=>d===`erase`||d===`cut`||de(e);function pe(e){let t=_(e[0],e[1]),n=14/p.scale;for(let e of o){if(j.has(e.id))continue;let r=e.pts;for(let i=0;i<r.length;i++)if((r.length===1?y(t,r[0]):C(t,r[i],r[Math.min(i+1,r.length-1)]))<=n){j.add(e.id);break}}}function me(){let e=[...F.values()];if(e.length>=2){let[t,n]=e;I={d:Math.max(1,y(t,n)),c:[(t[0]+n[0])/2,(t[1]+n[1])/2],view:{...p}}}else I=e.length===1?{d:0,c:e[0],view:{...p}}:null}function he(){if(!I)return;let e=[...F.values()];if(I.d&&e.length>=2){let[t,n]=e,r=[(t[0]+n[0])/2,(t[1]+n[1])/2],i=Math.max(vt,Math.min(yt,I.view.scale*y(t,n)/I.d)),a=(I.c[0]-I.view.x)/I.view.scale,o=(I.c[1]-I.view.y)/I.view.scale;T({scale:i,x:r[0]-a*i,y:r[1]-o*i})}else!I.d&&e.length===1&&T({scale:I.view.scale,x:I.view.x+e[0][0]-I.c[0],y:I.view.y+e[0][1]-I.c[1]})}function B(){clearTimeout(ge),O=null,A=null}let V=!0,ge;function H(){clearTimeout(ge),V&&d===`draw`&&(ge=setTimeout(_e,500))}function _e(){let e=A,t=O;if(!e||!t||e.aim)return;let n=t.zoom??1,r=at(t.pts.slice(e.anchor).map(e=>[e[0]*n,e[1]*n]));if(r){let i=[r.tail[0]/n,r.tail[1]/n],a=[r.tip[0]/n,r.tip[1]/n];e.aim={before:t.pts.slice(0,e.anchor),tail:i,tip:a,from:t.pts[t.pts.length-1]},t.pts=[...e.aim.before,...z(i,a,p.scale)];try{navigator.vibrate?.(12)}catch{}x();return}let i=ue(t.pts,e.anchor,t.zoom);if(i){if(i.kind===`line`)t.pts=[...t.pts.slice(0,i.from),...i.pts],e.anchor=t.pts.length-1;else{let n=t.pts.slice(0,i.from+1),r=4/p.scale;b(n)*p.scale>=12&&!n.every(t=>[e.snapped,i.box].some(e=>e&&t[0]>=e.x0-r&&t[0]<=e.x1+r&&t[1]>=e.y0-r&&t[1]<=e.y1+r))&&e.done.push({id:m++,color:t.color,pts:n,by:t.by,zoom:t.zoom}),e.done.push({id:m++,color:t.color,pts:i.pts,by:t.by,zoom:t.zoom}),O={id:0,color:t.color,pts:[t.pts[t.pts.length-1]],by:t.by,zoom:t.zoom},e.anchor=0,e.snapped=i.box}try{navigator.vibrate?.(12)}catch{}x()}}let U=new Set,W=`box`,G=null,K=null,q=null,ve=/Mac|iPhone|iPad/.test(navigator.userAgent),J=e=>[e[0]*p.scale+p.x,e[1]*p.scale+p.y];function ye(){let e=mt(o,U);if(!e)return null;let[t,n]=J([e.x0,e.y0]),[r,i]=J([e.x1,e.y1]);return{x0:t-8,y0:n-8,x1:r+8,y1:i+8,turn:[(t+r)/2,n-8-26],grow:[r+8,i+8]}}function be(){let e=ye();if(!e||d!==`select`)return;let t=e=>q?J(st(_(e[0],e[1]),q.m)):e,r=[[e.x0,e.y0],[e.x1,e.y0],[e.x1,e.y1],[e.x0,e.y1]].map(t);n.save(),n.strokeStyle=X(`--accent`),n.fillStyle=X(`--surface`),n.lineWidth=1.25,n.setLineDash([4,4]),n.beginPath(),r.forEach((e,t)=>t?n.lineTo(e[0],e[1]):n.moveTo(e[0],e[1])),n.closePath(),n.stroke(),n.setLineDash([]);let i=t([(e.x0+e.x1)/2,e.y0]),a=t(e.turn),o=t(e.grow);n.beginPath(),n.moveTo(i[0],i[1]),n.lineTo(a[0],a[1]),n.stroke(),n.lineWidth=1.5,n.beginPath(),n.arc(a[0],a[1],7,0,2*Math.PI),n.fill(),n.stroke(),n.beginPath(),n.rect(o[0]-6,o[1]-6,12,12),n.fill(),n.stroke(),n.restore()}function xe(e,n){let r=e.shiftKey||(ve?e.metaKey:e.ctrlKey),i=K={id:e.pointerId,by:e.pointerType,at:n,last:n,moved:0,adding:r},a=ye(),s=mt(o,U),c=_(n[0],n[1]),l=e.pointerType===`touch`?22:14,u=e=>q={mode:`move`,box:e,from:c,m:ot((e.x0+e.x1)/2,(e.y0+e.y1)/2)},d=!!a&&n[0]>=a.x0&&n[0]<=a.x1&&n[1]>=a.y0&&n[1]<=a.y1;if(a&&s&&!r&&(y(n,a.turn)<=l?q={mode:`turn`,box:s,from:c,m:ot((s.x0+s.x1)/2,(s.y0+s.y1)/2)}:y(n,a.grow)<=l&&(q={mode:`grow`,box:s,from:c,m:ot(s.x0,s.y0)})),!q){let n=(e.pointerType===`touch`?14:8)/p.scale,a=dt(o,c,n)??(d||r?null:ft(o,c));if(a!==null){let e=lt(o,[a]),n=[...e].every(e=>U.has(e));i.took={ids:e,was:n},n||(U=r?new Set([...U,...e]):e,t.select([...U])),u(mt(o,U))}else d&&s&&!r&&u(s)}q||(G=[c]),x()}function Se(e){let t=K,n=_(e[0],e[1]);if(t.moved=Math.max(t.moved,y(e,t.at)),t.last=e,G&&W===`box`)G=[G[0],n];else if(G&&y(n,G[G.length-1])*p.scale>=2)G.push(n);else if(q){let e=q,t=e.box;if(e.mode===`move`)e.m={...e.m,dx:n[0]-e.from[0],dy:n[1]-e.from[1]};else if(e.mode===`turn`){let t=Math.atan2(n[1]-e.m.cy,n[0]-e.m.cx)-Math.atan2(e.from[1]-e.m.cy,e.from[0]-e.m.cx);e.m={...e.m,angle:_t(t)}}else{let r=y(e.from,[t.x0,t.y0]);r>0&&(e.m={...e.m,scale:Math.max(.2,Math.min(5,y(n,[t.x0,t.y0])/r))})}}x()}function Y(e){let n=K,r=G,i=q;K=null,G=null,q=null;let a=n.moved<4;if(e&&r){let e=a?new Set:ut(o,W===`box`?pt(r[0],r[r.length-1]):r),i=a&&n.adding?ft(o,r[0]):null;i!==null&&(e=lt(o,[i]),[...e].every(e=>U.has(e))&&(U=new Set([...U].filter(t=>!e.has(t))),e=new Set)),a&&!n.adding&&t.empty(),U=n.adding?new Set([...U,...e]):e,t.select([...U])}else if(e&&i&&!a&&(i.m.dx||i.m.dy||i.m.angle||i.m.scale!==1))l=l.map(e=>e.strokes.some(e=>U.has(e))?{...e,at:st(e.at,i.m)}:e),t.edit(ht(o,U,i.m));else if(e&&a&&n.took?.was){let e=n.took.ids;U=n.adding?new Set([...U].filter(t=>!e.has(t))):e,t.select([...U])}x()}e.addEventListener(`pointerdown`,n=>{let r=v(n);if(we=n.pointerType,n.pointerType===`pen`&&(g=n.timeStamp,h||(h=!0,t.penMode(!0)),F.size&&(F.clear(),I=null),A&&A.by===`touch`&&(B(),x()),K&&K.by===`touch`&&(K=G=q=null,x())),n.pointerType===`touch`){if(n.timeStamp-g<600)return;let t=()=>{F.set(n.pointerId,r);try{e.setPointerCapture(n.pointerId)}catch{}me(),n.preventDefault()};if(h||F.size||d===`hand`)return t();if(M!==null&&P===`touch`){let e=ce??le;return y(e,le)>14?void 0:(F.set(M,e),M=null,ce=null,j.clear(),N=null,x(),t())}if(A&&A.by===`touch`)return A.moved>14?void 0:(F.set(A.id,A.last),B(),x(),t());if(K&&K.by===`touch`)return K.moved>14?void 0:(F.set(K.id,K.last),K=G=q=null,x(),t())}if(n.pointerType===`mouse`&&n.button===1||n.button===0&&(d===`hand`||R)&&!A&&M===null&&!K){L={id:n.pointerId,at:r,view:{...p}},e.dataset.panning=``,e.setPointerCapture(n.pointerId),n.preventDefault();return}if(!(n.pointerType===`mouse`&&n.button!==0||A||M!==null||K)){Te=n.pointerType===`mouse`&&n.ctrlKey;try{e.setPointerCapture(n.pointerId)}catch{}if(n.preventDefault(),fe(n)){M=n.pointerId,P=n.pointerType,le=r,ce=r,d===`cut`&&!de(n)?N=[_(r[0],r[1])]:pe(r),x();return}if(d===`select`){xe(n,r);return}A={id:n.pointerId,by:n.pointerType,start:n.timeStamp,moved:0,at:r,last:r,still:r,anchor:0,snapped:null,done:[]},O={id:0,color:f,pts:[_(r[0],r[1])],by:n.pointerType,zoom:p.scale},t.begin(),H(),x()}}),e.addEventListener(`pointermove`,n=>{let r=v(n);if(n.pointerType===`pen`&&(g=n.timeStamp),n.pointerType===`pen`&&!h&&n.buttons===0&&(h=!0,t.penMode(!0)),F.has(n.pointerId)){F.set(n.pointerId,r),n.timeStamp-g>=600&&he();return}if(L&&L.id===n.pointerId){if(n.buttons===0){L=null,delete e.dataset.panning;return}T({scale:L.view.scale,x:L.view.x+r[0]-L.at[0],y:L.view.y+r[1]-L.at[1]});return}if(n.pointerType===`mouse`&&n.buttons===0&&(M===n.pointerId||A?.id===n.pointerId||K?.id===n.pointerId)&&Ce(n,!0),(d===`erase`||d===`cut`)&&n.pointerType===`mouse`&&(ce=r,x()),d===`select`&&n.pointerType===`mouse`&&!K){let t=_(r[0],r[1]),n=dt(o,t,8/p.scale)!==null;n!==`over`in e.dataset&&(n?e.dataset.over=``:delete e.dataset.over)}if(M===n.pointerId){let e=n.getCoalescedEvents?.()??[];for(let t of e.length?e:[n]){let e=v(t);N?y(_(e[0],e[1]),N[N.length-1])*p.scale>=1&&N.push(_(e[0],e[1])):pe(e)}ce=r,x();return}if(K&&K.id===n.pointerId){Se(r);return}if(!A||A.id!==n.pointerId||!O)return;if(A.aim){let e=A.aim,t=_(r[0],r[1]),n=[e.tip[0]+t[0]-e.from[0],e.tip[1]+t[1]-e.from[1]];y(e.tail,n)*p.scale>=12&&(O.pts=[...e.before,...z(e.tail,n,p.scale)]),A.moved=Math.max(A.moved,y(r,A.at)),x();return}let i=n.getCoalescedEvents?.()??[];for(let e of i.length?i:[n]){let t=v(e),n=_(t[0],t[1]),r=O.pts[O.pts.length-1];A.moved=Math.max(A.moved,y(t,A.at)),A.last=t,y(n,r)*p.scale>=1.5&&O.pts.push(n)}y(r,A.still)>(A.by===`touch`?6:4)&&(A.still=r,H()),x()});function Ce(n,r){if(F.has(n.pointerId)){F.delete(n.pointerId),me();return}if(L&&L.id===n.pointerId){r&&y(v(n),L.at)<4&&t.empty(),L=null,delete e.dataset.panning;return}if(M===n.pointerId){M=null,n.pointerType!==`mouse`&&(ce=null),r&&j.size?t.erase([...j]):r&&!N&&y(v(n),le)<4&&t.empty(),r&&N&&t.cut(N,14/p.scale),j.clear(),N=null,x();return}if(K&&K.id===n.pointerId){Y(r);return}if(!A||A.id!==n.pointerId)return;let i=O,a=A;if(B(),r&&i){let e=v(n);a.moved=Math.max(a.moved,y(e,a.at)),a.snapped?(b(i.pts)*p.scale>=10&&a.done.push({...i,id:m++}),t.stroke(...a.done)):a.moved<6&&n.timeStamp-a.start<500&&b(i.pts)*p.scale<8?t.tap(i.pts[0]):(i.id=m++,t.stroke(i))}x()}e.addEventListener(`pointerup`,e=>Ce(e,!0));let we=`mouse`,Te=!1;return e.addEventListener(`contextmenu`,e=>{if(we===`mouse`&&Te&&(A||M!==null||K)){B(),M=null,j.clear(),N=null,K=G=q=null,x();return}(we!==`mouse`||A||M!==null||K)&&e.preventDefault()}),e.addEventListener(`pointercancel`,e=>Ce(e,!1)),e.addEventListener(`lostpointercapture`,e=>{K?.id===e.pointerId&&(K=G=q=null,x())}),e.addEventListener(`pointerleave`,e=>{e.pointerType===`mouse`&&M===null&&(ce=null,x())}),e.addEventListener(`wheel`,e=>{e.preventDefault();let t=e.deltaMode===1?16:e.deltaMode===2?i:1,n=e.deltaX*t,r=e.deltaY*t;if(!e.ctrlKey&&Math.abs(n)>Math.abs(r)){T({...p,x:p.x-n});return}let[a,o]=v(e),s=Math.max(vt,Math.min(yt,p.scale*Math.exp(-r*(e.ctrlKey?.01:.002)))),c=(a-p.x)/p.scale,l=(o-p.y)/p.scale;T({scale:s,x:a-c*s,y:o-l*s})},{passive:!1}),new ResizeObserver(()=>S()).observe(e),{setStrokes(e){o=e;let t=new Set(e.map(e=>e.id));U=new Set([...U].filter(e=>t.has(e)));for(let t of e)t.id>=m&&(m=t.id+1);x()},setOverlay(t){s=t,t?e.dataset.read=``:delete e.dataset.read,x()},setShowOverlay(e){c=e,x()},get overlaid(){return!!s&&c},setNames(e){l=e,x()},setShowNames(e){u=e,x()},setTool(n){d=n,n!==`erase`&&n!==`cut`&&(ce=null),delete e.dataset.over,n!==`select`&&U.size&&(U=new Set,t.select([])),e.dataset.tool=n,x()},setColor(e){f=e},setChooseBy(e){W=e},setSpace(t){R=t,t?e.dataset.space=``:delete e.dataset.space},setPenMode(e){h=e},setSnap(e){V=e,e||clearTimeout(ge)},fitContent:ne,resetView:()=>T({scale:1,x:0,y:0}),get pressing(){return!!A||M!==null||F.size>0||!!L||!!K},get chosen(){return[...U]},choose(e){U=new Set(e),t.select([...U]),x()},chosenBox:ye,get view(){return p},get size(){return{w:r/p.scale,h:i/p.scale}},toScreen:e=>[e[0]*p.scale+p.x,e[1]*p.scale+p.y],nextId:()=>m++,repaint:x}}var xt=new Set([`rect`,`stadium`,`circle`,`diamond`,`hexagon`,`trapezoid`,`inv-trapezoid`,`lean-right`,`lean-left`,`triangle`,`flip-triangle`]),St=(e,t)=>e.map(([e,n])=>[e*t,n*t]);function Ct(e,t,n,r){let i=new Map,a=(e,t)=>i.set(e,[...i.get(e)??[],t]),o=n=>n.length>0&&n.every(n=>e[n]&&t.has(e[n].id)),s=0,c=0,l=new Map;for(let t of[...n.nodes,...n.groups])for(let n of t.strokes)e[n]&&l.set(e[n],t);let u=e.filter(e=>t.has(e.id)),d=u.length>1?Et(u):null,f=(e,t)=>{let n=l.get(e);return!n||(n.kind===`triangle`||n.kind===`flip-triangle`)&&n.strokes.length===1&&Math.max(n.bb.w,n.bb.h)<=.55*t},p=d&&!l.has(d.shaft)&&u.every(e=>e===d.shaft||f(e,y(d.tail,d.tip)))?d:null;if(p){a(p.shaft.id,z(p.tail,p.tip,p.shaft.zoom??1));for(let e of u)e!==p.shaft&&i.set(e.id,[]);c++}let m=e=>n.edges.filter(t=>t.strokes.includes(e));for(let t of p?[]:n.nodes){if(!o(t.strokes)||t.strokes.length!==1||!xt.has(t.kind)||t.role===`dot`)continue;let n=e[t.strokes[0]],r=m(t.strokes[0]).length>0;if(r&&!m(t.strokes[0]).every(e=>o(e.strokes)))continue;let i=r?null:ue(n.pts,0,n.zoom);a(n.id,i&&i.kind!==`line`&&i.from<=2?i.pts:R(t.kind,t.bb)),s++}for(let t of p?[]:n.edges){if(!o(t.strokes)||t.pts.length<2||t.style!==`plain`)continue;let[n,...r]=t.strokes.map(t=>e[t]),s=t.pts[0],l=t.assumed?t.pts[t.pts.length-1]:wt(t.pts,t.strokes.map(t=>e[t].pts)),u=y(s,l)>=.9*b(t.pts),d=n.zoom??1;if(!u&&t.assumed){i.has(n.id)&&a(n.id,t.pts.slice());continue}a(n.id,u?t.assumed?[s,l]:z(s,l,d,t.both):Tt([...t.pts.slice(0,-1),l],d,t.both));for(let e of r)i.has(e.id)||i.set(e.id,[]);c++}let h=new Set([...n.nodes,...n.groups,...n.edges].flatMap(t=>t.strokes.map(t=>e[t]))),g=e.filter(e=>t.has(e.id)&&!i.has(e.id)&&!h.has(e)),_=g.length>1?Et(g):null;if(_&&!l.has(_.shaft)&&g.every(e=>e===_.shaft||f(e,y(_.tail,_.tip)))){a(_.shaft.id,z(_.tail,_.tip,_.shaft.zoom??1));for(let e of g)e!==_.shaft&&i.set(e.id,[]);c++}else for(let e of g){let t=e.zoom??1,n=at(St(e.pts,t));if(n){a(e.id,z(St([n.tail],1/t)[0],St([n.tip],1/t)[0],t)),c++;continue}let r=ue(e.pts,0,t);r&&(r.kind!==`line`&&r.from>2&&a(e.id,e.pts.slice(0,r.from+1)),a(e.id,r.pts),r.kind===`line`?c++:s++)}let v=[],x=new Map;for(let t of e){let e=i.get(t.id);if(!e){v.push(t);continue}e.forEach((e,n)=>{let i=n?r():t.id;n&&x.set(i,t.id),v.push({...t,id:i,pts:e,open:void 0})})}return{strokes:v,from:x,shapes:s,arrows:c}}function wt(e,t){let n=e[e.length-1],r=e.length-2;for(;r>0&&y(e[r],n)<12;)r--;let i=y(e[r],n);if(i<1)return n;let a=(n[0]-e[r][0])/i,o=(n[1]-e[r][1])/i,s=n,c=0;for(let e of t)for(let t of e){let e=(t[0]-n[0])*a+(t[1]-n[1])*o,r=Math.abs((t[0]-n[0])*o-(t[1]-n[1])*a);e>c&&e<=40&&r<=Math.max(6,.5*e)&&(c=e,s=t)}return s}function Tt(e,t,n){let r=e=>{let n=e[e.length-1],r=e.length-2;for(;r>0&&y(e[r],n)<14/t;)r--;let i=z(e[r],n,t);return i.slice(i.findIndex((e,t)=>t>0&&y(e,n)<1e-6)+1)},i=[...e,...r(e)];return n?[...r([...e].reverse()).reverse(),...i]:i}function Et(e){let{s:t,t:n}=e.map(e=>({s:e,t:nt(e.pts).pts})).sort((e,t)=>y(t.t[0],t.t[t.t.length-1])-y(e.t[0],e.t[e.t.length-1]))[0],r=b(n);if(r<20||y(n[0],n[n.length-1])<.85*r)return null;let i=e.filter(e=>e!==t),a=Math.max(40,.4*r);for(let[e,o]of[[n[0],n[n.length-1]],[n[n.length-1],n[0]]]){if(!i.every(e=>e.pts.every(e=>y(e,o)<=a)))continue;let n=x(i.flatMap(e=>e.pts));if(Math.max(n.w,n.h)>r)return null;let s=(o[0]-e[0])/y(e,o),c=(o[1]-e[1])/y(e,o),l=o,u=0;for(let e of i)for(let t of e.pts){let e=(t[0]-o[0])*s+(t[1]-o[1])*c;e>u&&(u=e,l=t)}return{shaft:t,tail:e,tip:l}}return null}function Dt(e){let t=7,n=()=>(t=t*1664525+1013904223>>>0)/4294967296,r=Math.round(e/2),i=[],a=(e,t,r=1.6)=>{let a=n()*6,o=n()*6;i.push({color:t,pts:e.map(([e,t],i)=>[e+Math.sin(i*.13+a)*r+(n()-.5)*.8,t+Math.cos(i*.11+o)*r+(n()-.5)*.8])})},o=(e,t,r,i)=>{let a=n()*6.28,o=[];for(let n=0;n<=68;n++){let s=a+n/64*Math.PI*2;o.push([e+r*Math.cos(s),t+i*Math.sin(s)])}return o},s=(e,t,n,r)=>T([[e,t],[e+n,t],[e+n,t+r],[e,t+r],[e,t+3]],4),c=(e,t,n,r)=>T([[e,t-r/2],[e+n/2,t],[e,t+r/2],[e-n/2,t],[e+2,t-r/2+2]],4),l=e=>{let[t,n]=e[e.length-1],[r,i]=e[e.length-2],a=Math.atan2(n-i,t-r),o=e=>[t-11*Math.cos(a+e),n-11*Math.sin(a+e)];return T(e,4).concat(T([[t,n],o(.5),[t,n],o(-.5)],2))};return a(o(r,46,58,22),`ink`),a(s(r-65,104,130,50),`ink`),a(c(r,234,136,86),`amber`),a(o(r,352,25,25),`red`,1),a(o(r,352,16,16),`red`,.6),a(l([[r,72],[r,101]]),`ink`,.8),a(l([[r,158],[r,188]]),`ink`,.8),a(l([[r,280],[r,324]]),`ink`,.8),a(l([[r+70,234],[r+112,234],[r+112,129],[r+69,129]]),`green`,1),i}var Z=e=>e.bb.w*e.bb.h,Ot=(e,t)=>e!==t&&Z(e)>Z(t)&&t.bb.x0>=e.bb.x0-6&&t.bb.x1<=e.bb.x1+6&&t.bb.y0>=e.bb.y0-6&&t.bb.y1<=e.bb.y1+6,kt=(e,t,n)=>e[0]>=t.x0-n&&e[0]<=t.x1+n&&e[1]>=t.y0-n&&e[1]<=t.y1+n,Q=(e,t)=>ne(e,t.poly)?0:w(e,t.poly),At=(e,t,n)=>kt(e,t.bb,n)&&Q(e,t)<n,jt=e=>Math.max(18,Math.min(44,.3*Math.max(e.bb.w,e.bb.h))),Mt=(e,t)=>{let n=Math.max(...e.map(e=>Q(e,t))),r=Math.max(Q(e[0],t),Q(e[e.length-1],t));return n>22&&n>r+15},Nt=(e,t,n,r)=>({kind:t.kind,unsure:t.unsure,bb:t.bb,poly:t.poly,pts:e,color:n,diag:Math.hypot(t.bb.w,t.bb.h),strokes:r}),Pt=()=>typeof performance<`u`?performance.now():Date.now();function Ft(e){let t=e.filter(e=>e&&Array.isArray(e.pts)).map(e=>typeof e.zoom==`number`&&e.zoom>=.01&&e.zoom<=100?e.zoom:1).sort((e,t)=>e-t);return t.length?t[t.length>>1]:1}function It(e,t={}){let n=Ft(e);if(n===1)return Lt(e,t);let r=(e,t)=>e.map(e=>Array.isArray(e)?[e[0]*t,e[1]*t]:[NaN,NaN]),i=Lt(e.map(e=>e&&Array.isArray(e.pts)?{...e,pts:r(e.pts,n)}:e),t),a=e=>({x0:e.x0/n,y0:e.y0/n,x1:e.x1/n,y1:e.y1/n,w:e.w/n,h:e.h/n,cx:e.cx/n,cy:e.cy/n}),o=e=>({...e,bb:a(e.bb),poly:r(e.poly,1/n)});return{...i,nodes:i.nodes.map(o),groups:i.groups.map(o),edges:i.edges.map(e=>({...e,pts:r(e.pts,1/n)}))}}function Lt(e,t){let n=Pt(),r=t.diagram===`state`?`state`:`flowchart`,i=[];e.forEach((e,t)=>{if(!e||!Array.isArray(e.pts)||e.pts.length<2)return;let n=b(e.pts);if(!(n>=8))return;let r=x(e.pts);i.push({index:t,color:e.color??`ink`,pts:e.pts,len:n,bb:r,diag:Math.hypot(r.w,r.h)})});let a=[],o=[];for(let e of i){let t=e.pts,n=[!1,!1],r=[];for(let i=0;i<2;i++){let i=mn(t);if(!i||n[i.end])break;let o=Nt(i.loop,i.fit,e.color,[e.index]);o.line={it:e,end:i.end},a.push(o),r.push(o),n=i.end?[n[0],!0]:[!0,n[1]],t=i.line}if(r.length){let i=x(t),a=b(t),s={index:e.index,color:e.color,pts:t,len:a,bb:i,diag:Math.hypot(i.w,i.h),joints:n};for(let e of r)e.line.it=s;o.push(s);continue}let i=un(e.pts);i?a.push(Nt(e.pts,i,e.color,[e.index])):o.push(e)}let s=[],c=new Set,l=()=>{for(let e of a.slice()){let t=Math.max(e.bb.w,e.bb.h),n=[e.bb.cx,e.bb.cy];if(t>(e.line?cn:sn))continue;let r=a.find(r=>r!==e&&Z(r)>=(e.line?4:6)*Z(e)&&w(n,r.poly)<.5*t+10&&e.pts.some(t=>Q(t,r)<=(e.line?jt(r):10))&&!a.some(t=>t!==r&&t!==e&&Ot(r,t)));if(!r)continue;let i=t=>kt(t,e.bb,10)&&Q(t,e)<=10,l=t=>ne(t,e.poly)||Q(t,r)>Q(n,r),u,d=0,f=1/0;if(e.line)[u,d]=[e.line.it,e.line.end];else for(let n of o){if(c.has(n)||n.len<=t)continue;let r=i(n.pts[0]),a=i(n.pts[n.pts.length-1]),o=r?n.pts[0]:n.pts[n.pts.length-1];r!==a&&l(o)&&Q(o,e)<f&&([u,d,f]=[n,+!r,Q(o,e)])}if(!u)continue;let p=e.pts.reduce((e,t)=>Q(t,r)<Q(e,r)?t:e);u.pts=d?[...u.pts,p]:[p,...u.pts],u.len=b(u.pts),a=a.filter(t=>t!==e),s.push({pts:e.pts,color:e.color,len:b(e.pts),strokes:e.strokes})}};l();let u=[];for(let e of a.slice()){let t=e.pts[0],n=e.pts[e.pts.length-1],r=a.find(r=>r!==e&&At(t,r,8)&&At(n,r,8)&&!Ot(e,r)&&!Ot(r,e));r&&(a=a.filter(t=>t!==e),u.push({pts:e.pts,color:e.color,len:b(e.pts),strokes:e.strokes,host:r}))}let d=e=>a.some(t=>At(e,t,jt(t))),f=o.filter(e=>e.len>=20&&!a.some(t=>At(e.pts[0],t,10)||At(e.pts[e.pts.length-1],t,10))&&!(d(e.pts[0])&&d(e.pts[e.pts.length-1])));for(let e of f){if(c.has(e))continue;let t=[e],n=e.pts.slice();for(let r=0;r<3;r++){let r=n[0],i=n[n.length-1],o=x(n),s=Math.max(14,.18*Math.hypot(o.w,o.h)),l=null;for(let e of f){if(c.has(e)||t.includes(e))continue;let n=e.pts[0],a=e.pts[e.pts.length-1],o=[[y(i,n),`tail`,!1],[y(i,a),`tail`,!0],[y(r,a),`head`,!1],[y(r,n),`head`,!0]];for(let[t,n,r]of o)t<s&&(!l||t<l.d)&&(l={b:e,d:t,end:n,rev:r})}if(!l)break;let u=l.rev?l.b.pts.slice().reverse():l.b.pts;n=l.end===`tail`?n.concat(u):u.concat(n),t.push(l.b);let d=x(n);if(y(n[0],n[n.length-1])<Math.max(14,.18*Math.hypot(d.w,d.h))&&Math.min(d.w,d.h)>=14){let r=ce(n);r&&(a.push(Nt(n,r,e.color,t.map(e=>e.index))),t.forEach(e=>c.add(e)));break}}}l(),a.sort((e,t)=>Z(t)-Z(e));let p=new Set,m=new Set(a.filter(e=>{let t=a.filter(t=>Ot(e,t));return t.filter(e=>!t.some(t=>Ot(t,e))).length>=2}));for(let e of a)for(let t of a){if(p.has(e)||p.has(t)||!Ot(e,t)||m.has(e)||r===`state`&&Math.max(e.bb.w,e.bb.h)>Kt)continue;let n=Z(e)/Z(t),i=y([e.bb.cx,e.bb.cy],[t.bb.cx,t.bb.cy])<.2*e.diag,a=Math.max(e.bb.w,e.bb.h)/Math.max(t.bb.w,t.bb.h);i&&(n<3.2||a<1.9)&&(A.has(e.kind)||A.has(t.kind))?(e.kind=Math.max(t.bb.w,t.bb.h)<=Bt&&Qt(t.pts)?`bullseye`:`double`,e.strokes.push(...t.strokes),p.add(t)):i&&n<2&&e.kind===`rect`&&t.kind===`rect`&&r===`flowchart`&&(e.kind=`subroutine`,e.strokes.push(...t.strokes),p.add(t))}let h=a.filter(e=>!p.has(e));for(let e of h)e.isGroup=h.some(t=>Ot(e,t));let g=h.filter(e=>!e.isGroup),_=h.filter(e=>e.isGroup);for(let e of h)e.parent=_.filter(t=>Ot(t,e)).sort((e,t)=>Z(e)-Z(t))[0];let v=e=>_.filter(t=>Ot(t,e)).sort((e,t)=>Z(e)-Z(t))[0],S=r===`state`,C=new Set,te=(e,t,n)=>{let r=Nt(e,$t(e),t,n);return r.kind=`dot`,r.parent=v(r),g.push(r),C.add(r),r},T=(e,t)=>zt.has(e.kind)&&Math.max(e.bb.w,e.bb.h)<=t&&e.bb.w<1.6*e.bb.h&&e.bb.h<1.6*e.bb.w,re=e=>h.some(t=>t.isGroup?kt(e,t.bb,Jt)&&w(e,t.poly)<Jt:At(e,t,qt)),ie=(e,t)=>g.some(n=>!C.has(n)&&e.some(e=>At(e,n,jt(n)))&&!t.some(e=>At(e,n,jt(n))));for(let e of g)C.has(e)||(Math.max(e.bb.w,e.bb.h)<=Bt&&Qt(e.pts)?(e.kind=`dot`,C.add(e)):S&&(e.kind===`double`||T(e,Gt))&&C.add(e));for(let e of o){let t=Math.max(e.bb.w,e.bb.h),n=[e.bb.cx,e.bb.cy];if(c.has(e)||t>Bt||e.len<Vt*t||!(Qt(e.pts)||S&&le(e.pts,e.len)<.3*t))continue;let r=g.find(r=>ne(n,r.poly)&&T(r,Kt)&&(S||y(n,[r.bb.cx,r.bb.cy])<.2*Math.max(r.bb.w,r.bb.h)&&e.len>=Ht*t));if(r){r.kind=`bullseye`,C.add(r),r.strokes.push(e.index),c.add(e);continue}if(!S)continue;let i=e=>h.some(t=>t.isGroup?kt(e,t.bb,jt(t))&&w(e,t.poly)<=jt(t):At(e,t,jt(t))),a=e=>{let t=nt(e.pts).pts;return y(t[0],t[t.length-1])>=.7*b(t)},s=o.filter(t=>t!==e&&!c.has(t)&&t.len>=Zt).flatMap(e=>[[e.pts[0],e.pts[e.pts.length-1],e],[e.pts[e.pts.length-1],e.pts[0],e]]).filter(([e,r,o])=>y(e,n)<=Xt+t/2&&i(r)&&a(o)).map(([,e])=>e);s.length&&!e.pts.some(re)&&!ie(e.pts,s)&&(te(e.pts,e.color,[e.index]),c.add(e))}let ae=e=>C.has(e)?Math.max(Xt,jt(e)):jt(e),oe=e=>{let t=null;for(let n of g){if(!kt(e,n.bb,ae(n)))continue;let r=Q(e,n);r<=ae(n)&&(!t||r<t.d||r===t.d&&Z(n)<Z(t.s))&&(t={s:n,d:r})}if(t)return _.find(n=>Ot(n,t.s)&&!ne(e,n.poly)&&w(e,n.poly)<t.d)??t.s;for(let n of _){if(!kt(e,n.bb,jt(n)))continue;let r=w(e,n.poly);r<=jt(n)&&(!t||r<t.d)&&(t={s:n,d:r})}return t?.s},se=(e,t)=>{if(b(e)<nn)return;let n=t?e.length-1:0,r=e[n],i=E(e,n,20,t?-1:1),a=r[0]-i[0],o=r[1]-i[1],s=Math.hypot(a,o);if(s<10)return;let c=Math.min(tn,en*b(e));for(let e=3;e<=c;e+=3){let t=[r[0]+a/s*e,r[1]+o/s*e],n=g.find(e=>At(t,e,2));if(n)return n}},D=e=>({pts:e.pts,color:e.color,len:e.len,strokes:[e.index],joints:e.joints}),O=o.filter(e=>!c.has(e)),k=_n(O,(e,t)=>g.some(n=>At(e,n,t))),j=new Map(k.map(e=>[e.reduce((e,t)=>t.it.index<e.it.index?t:e).it,e])),M=new Set(k.flat().map(e=>e.it)),N=[];for(let e of O){let t=j.get(e);if(t){let e=t.flatMap(e=>e.flip?e.it.pts.slice().reverse():e.it.pts);N.push({pts:e,color:t[0].it.color,len:b(e),strokes:t.map(e=>e.it.index),dashes:t.map(e=>e.it)})}else M.has(e)||N.push(D(e))}N.push(...u);for(let e of N)if(!(!S||e.host||e.dashes))for(let t of[0,1]){let n=t?e.pts.slice().reverse():e.pts,r=tt(n,$,Yt);if(!r)continue;let i=n.slice(0,r.at+1),a=x(i),o=[a.cx,a.cy];if(i.some(re)||ie(i,[n[n.length-1]]))continue;te(i,e.color,e.strokes.slice(0,1));let s=[o,...n.slice(r.at)];e.pts=t?s.reverse():s,e.len=b(e.pts),e.joints=t?[e.joints?.[0]??!1,!0]:[!0,e.joints?.[1]??!1]}let P=[],F=[],I=[],L=new Set,R=[],ue=new Map,de=e=>{let t=e.pts,n={...ue.get(t)??ue.set(t,nt(t)).get(t)};return e.joints?.[0]&&n.headStart&&([n.pts,n.headStart]=[[t[0],...n.pts],!1]),e.joints?.[1]&&n.headEnd&&([n.pts,n.headEnd]=[[...n.pts,t[t.length-1]],!1]),n};for(let e of N){let t=de(e),n=e.host||oe(t.pts[0]),r=e.host||oe(t.pts[t.pts.length-1]),i={from:n,to:r,pts:t.pts,headEnd:t.headEnd,headStart:t.headStart,color:e.color,line:e};n&&r&&n!==r||n&&r&&(e.host||e.len>50&&Mt(t.pts,n)&&!(an(t.pts)>=0&&Q(t.pts[0],n)>10&&Q(t.pts[t.pts.length-1],n)>10))?P.push(i):e.dashes?N.push(...e.dashes.map(D)):e.len<70?F.push(e):Math.max(x(e.pts).w,x(e.pts).h)<=sn?(F.push(e),L.add(e)):R.push(e)}for(let e of s)F.push(e),L.add(e);let fe=e=>y(e.pts[0],e.pts[e.pts.length-1])<.8*e.len;for(let e of P.slice()){let t=e.line,n=fe(t),r=x(t.pts),i=e.from===e.to&&(Math.max(r.w,r.h)<.5*Math.max(e.from.bb.w,e.from.bb.h)||an(t.pts)>=0);if(t.host||t.dashes||e.from===e.to&&!i||t.len>=(i?160:n?70:45))continue;let a=i?22:n?10:8,o=i?8:a;P.some(i=>i!==e&&(kt(i.pts[0],r,o)||kt(i.pts[i.pts.length-1],r,o))&&(n===fe(i.line)?i.line.len>t.len:n)&&t.pts.some(e=>y(e,i.pts[0])<a||y(e,i.pts[i.pts.length-1])<a)&&!(y(e.pts[0],e.pts[e.pts.length-1])>=.8*b(e.pts)&&bn(e.pts,i.pts)))&&(P.splice(P.indexOf(e),1),F.push(t))}let pe=(e,t)=>{let n=null,r=x(e.pts);for(let i of t)for(let[t,a]of[[`start`,i.pts[0]],[`end`,i.pts[i.pts.length-1]]]){if(!kt(a,r,L.has(e)?8:22))continue;let o=1/0;for(let t of e.pts)o=Math.min(o,y(a,t));o<22&&(!n||o<n.d)&&(n={e:i,end:t,d:o})}return n?(n.end===`end`?n.e.headEnd=!0:n.e.headStart=!0,n.e.line.strokes.push(...e.strokes.filter(e=>!n.e.line.strokes.includes(e))),!0):!1};for(let e of F)pe(e,P)||R.push(e);let z=new Set,me=new Map,he=new Map,B=e=>me.get(e)??me.set(e,an(e.pts)).get(e),V=e=>he.get(e)??he.set(e,x(e.pts)).get(e),ge=(e,t,n,r)=>{let i=r?t.length-1:0,a=t[i];if(!kt(a,V(e),Math.max(40,.5*n)+12))return null;let o=B(e);if(o>=0&&on(e.pts,o,t,n,r))return e.pts[o];if(!F.includes(e)||!(L.has(e)||y(e.pts[0],e.pts[e.pts.length-1])<.8*e.len))return null;let s=E(t,i,20,r?-1:1),c=Math.hypot(a[0]-s[0],a[1]-s[1]);if(c<10||!kt(a,V(e),12)||!e.pts.some(e=>y(e,a)<12))return null;let l=(a[0]-s[0])/c,u=(a[1]-s[1])/c,d=e.pts.reduce((e,t)=>(t[0]-a[0])*l+(t[1]-a[1])*u>(e[0]-a[0])*l+(e[1]-a[1])*u?t:e),f=(d[0]-a[0])*l+(d[1]-a[1])*u,p=Math.abs((d[1]-a[1])*l-(d[0]-a[0])*u);return f>=8&&p<=.5*f+6?d:null},H=P.filter(e=>e.from===e.to&&!e.line.host&&!e.line.dashes&&B(e.line)>=0);for(let e of R){if(z.has(e)||e.dashes||e.host||e.len<rn||e.len<nn&&!g.some(t=>kt(e.pts[0],t.bb,jt(t)+40)||kt(e.pts[e.pts.length-1],t.bb,jt(t)+40)))continue;let t=de(e),n=[oe(t.pts[0]),oe(t.pts[t.pts.length-1])],r=b(t.pts);if(e.len<nn&&!n[0]==!n[1])continue;let i=[];for(let a of[0,1]){if(n[a])continue;let o=null,s=n=>n!==e&&!z.has(n)&&!i.includes(n)&&!!(o=ge(n,t.pts,r,a)),c=R.find(s)??H.find(e=>P.includes(e)&&s(e.line))?.line;c&&o&&(t.pts=a?[...t.pts,o]:[o,...t.pts],a?t.headEnd=!0:t.headStart=!0,i.push(c),n[a]=oe(o))}let a=n[0]||se(t.pts,0),o=n[1]||se(t.pts,1);if(a&&o&&a!==o){for(let t of i){z.add(t),e.strokes.push(...t.strokes);let n=P.findIndex(e=>e.line===t);n>=0&&P.splice(n,1)}P.push({from:a,to:o,pts:t.pts,headEnd:t.headEnd,headStart:t.headStart,color:e.color,line:e}),z.add(e)}}let _e=e=>{let t=B(e);if(t<0)return!1;let n=e.pts[t],r=V(e),i=(e.pts[0][0]+e.pts[e.pts.length-1][0])/2,a=(e.pts[0][1]+e.pts[e.pts.length-1][1])/2;for(let t of P)for(let o of[0,1]){let s=o?t.pts.length-1:0,c=t.pts[s];if(!kt(c,r,22)||y(n,c)>=22)continue;let l=E(t.pts,s,20,o?-1:1);if(!(Math.hypot(c[0]-l[0],c[1]-l[1])<10||(i-n[0])*(c[0]-l[0])+(a-n[1])*(c[1]-l[1])>=0))return o?t.headEnd=!0:t.headStart=!0,t.line.strokes.push(...e.strokes.filter(e=>!t.line.strokes.includes(e))),!0}return!1};for(let e of R)!z.has(e)&&(F.includes(e)?pe(e,P):_e(e))&&z.add(e);for(let e of R)z.has(e)||I.push(...e.strokes);let U=new Map(P.map(e=>[e,{at:ee(e.pts),len:b(e.pts)}]));for(let e=0;e<P.length;e++)for(let t=e+1;t<P.length;t++){let n=P[e],r=P[t],i=U.get(n),a=U.get(r);if(n.line.dashes||r.line.dashes||y(i.at,a.at)>2*yn+Math.abs(i.len-a.len)/2)continue;let o;if(n.from===r.from&&n.to===r.to)o=n.from!==n.to||y(n.pts[0],r.pts[0])<=y(n.pts[0],r.pts[r.pts.length-1]);else if(n.from===r.to&&n.to===r.from)o=!1;else continue;let s=o?r.headEnd:r.headStart,c=o?r.headStart:r.headEnd;n.headEnd&&!n.headStart&&c&&!s||n.headStart&&!n.headEnd&&s&&!c||!bn(n.pts,r.pts)||(n.headEnd||=s,n.headStart||=c,n.thick=!0,n.line.strokes.push(...r.line.strokes),P.splice(t--,1))}for(let e of P)e.headStart&&!e.headEnd&&([e.from,e.to]=[e.to,e.from]),e.both=e.headStart&&e.headEnd,e.assumed=!e.headStart&&!e.headEnd;let W=0,G=0,K=0,q=0;for(let e of P)if(e.from!==e.to){let t=e.to.bb.cx-e.from.bb.cx,n=e.to.bb.cy-e.from.bb.cy;W+=Math.abs(t),G+=Math.abs(n),K+=t,q+=n}let ve;if(W+G===0){let e=x(g.flatMap(e=>[[e.bb.x0,e.bb.y0],[e.bb.x1,e.bb.y1]]).concat([[0,0]]));ve=e.w>e.h*1.2?`LR`:`TD`}else ve=G>=W?q>=0?`TD`:`BT`:K>=0?`LR`:`RL`;let J=ve===`TD`||ve===`BT`,ye=ve===`BT`||ve===`RL`?-1:1,be=g.map(e=>J?e.bb.h:e.bb.w).sort((e,t)=>e-t),xe=be[be.length>>1]||40,Se=e=>J?[Math.round(ye*e.bb.cy/xe),e.bb.cx]:[Math.round(ye*e.bb.cx/xe),e.bb.cy];if(g.sort((e,t)=>{let n=Se(e),r=Se(t);return n[0]-r[0]||n[1]-r[1]}),g.forEach((e,t)=>{e.id=t<26?String.fromCharCode(65+t):`N`+(t+1),e.label=`Node `+(t+1)}),r===`state`){let e=0,t=0;for(let n of g)n.role=C.has(n)?`dot`:n.kind===`diamond`?`choice`:`state`,n.id=n.role===`dot`?`dot`+ ++t:e<26?String.fromCharCode(65+e++):`N`+ ++e;for(let e of _)e.role=`state`}_.sort((e,t)=>Z(t)-Z(e)).forEach((e,t)=>{e.id=`G`+(t+1),e.label=`Group `+(t+1)});let Y=e=>({id:e.id,kind:e.kind,label:e.label,color:e.color,bb:e.bb,poly:e.poly,unsure:e.unsure,strokes:e.strokes.slice().sort((e,t)=>e-t),parent:e.parent?.id??null,...e.role?{role:e.role}:{}}),Ce=g.map(Y);return r===`state`&&Rt(Ce),{diagram:r,direction:ve,nodes:Ce,groups:_.map(Y),edges:P.map((e,t)=>({id:`L`+(t+1),from:e.from.id,to:e.to.id,both:e.both,assumed:e.assumed,style:e.line.dashes?`dotted`:e.thick?`thick`:`plain`,color:e.color,pts:e.pts,strokes:e.line.strokes.slice().sort((e,t)=>e-t)})),unused:I.sort((e,t)=>e-t),loops:xn(g,P),ms:Pt()-n}}function Rt(e){let t=0;for(let n of e)n.label=n.role===`state`?`State `+ ++t:``}var zt=new Set([`circle`,`double`,`hexagon`,`stadium`,`dot`,`bullseye`]),Bt=44,Vt=2.5,Ht=5,Ut=3,Wt=.25,Gt=50,Kt=70,qt=16,Jt=8,$=24,Yt=96,Xt=26,Zt=16;function Qt(e){let t=x(e),n=Math.max(t.w,t.h),r=b(e),i=[t.cx,t.cy];if(!e.some((t,r)=>r>0&&C(i,e[r-1],t)<Wt*n))return!1;if(r>=Ht*n)return!0;if(r<Vt*n)return!1;let a=Math.max(6,.3*n),o=0,s=1/0;for(let t=1,n=0;t<e.length-1;t++){if(n+=y(e[t-1],e[t]),s+=y(e[t-1],e[t]),n<a||r-n<a)continue;let i=E(e,t,a,-1),c=E(e,t,a,1),l=e[t][0]-i[0],u=e[t][1]-i[1],d=c[0]-e[t][0],f=c[1]-e[t][1],p=Math.hypot(l,u)*Math.hypot(d,f);p>0&&(l*d+u*f)/p<-.4&&s>a&&(o++,s=0)}return o>=Ut}function $t(e){let t=x(e),n=Math.max(t.w,t.h)/2+2,r=[];for(let e=0;e<24;e++)r.push([t.cx+n*Math.cos(e/24*2*Math.PI),t.cy+n*Math.sin(e/24*2*Math.PI)]);return{kind:`circle`,score:0,unsure:!1,bb:x(r),poly:r}}var en=.4,tn=90,nn=60,rn=20;function an(e){if(e.length<5)return-1;let t=e[0],n=e[e.length-1],r=-1,i=0;for(let a=1;a<e.length-1;a++){let o=C(e[a],t,n);o>i&&([r,i]=[a,o])}if(r<0)return-1;let a=y(t,e[r]),o=y(e[r],n);if(a<8||o<8||Math.max(a,o)>3*Math.min(a,o)||b(e.slice(0,r+1))>1.25*a||b(e.slice(r))>1.25*o)return-1;let s=((t[0]-e[r][0])*(n[0]-e[r][0])+(t[1]-e[r][1])*(n[1]-e[r][1]))/(a*o);return s<.94&&s>-.5?r:-1}function on(e,t,n,r,i){let a=i?n.length-1:0,o=n[a],s=E(n,a,20,i?-1:1),c=Math.hypot(o[0]-s[0],o[1]-s[1]);if(c<10)return!1;let l=(o[0]-s[0])/c,u=(o[1]-s[1])/c,d=e[t],f=(d[0]-o[0])*l+(d[1]-o[1])*u,p=Math.abs((d[1]-o[1])*l-(d[0]-o[0])*u);if(f<-8||f>Math.max(40,.5*r)||p>12+.5*Math.max(0,f))return!1;let m=(e[0][0]+e[e.length-1][0])/2,h=(e[0][1]+e[e.length-1][1])/2;return(m-d[0])*l+(h-d[1])*u<0}var sn=50,cn=80,ln=160;function un(e){if(!dn(e))return null;let t=tt(e),n=tt(e.slice().reverse());if((t||n)&&!dn(e.slice(t?t.at:0,n?e.length-n.at:e.length)))return null;let r=x(e);if(Math.max(r.w,r.h)<=ln){let t=nt(e),n=b(t.pts);if(t.headEnd!==t.headStart&&n>=10&&y(t.pts[0],t.pts[t.pts.length-1])>=.9*n)return null}let i=P(e),a=ce(dn(i)?i:e);return a&&!(a.unsure&&Math.max(a.bb.w,a.bb.h)<50)?a:null}function dn(e){if(e.length<3)return!1;let t=b(e),n=x(e);return Math.max(n.w,n.h)>=28&&Math.min(n.w,n.h)>=18&&t>1.3*(n.w+n.h)&&le(e,t)<Math.max(14,.22*Math.hypot(n.w,n.h))}var fn=45,pn=60;function mn(e){for(let t of[e,e.slice().reverse()]){let n=t.length,r=t[n-1],i=b(t),a=-1,o=1/0,s=0;for(let e=1;e<n-1&&(s+=y(t[e-1],t[e]),!(i-s<pn));e++)s>=fn&&y(t[e],r)<o&&(o=y(t[e],r),a=e);if(a<0)continue;let c=t.slice(a),l=x(c),u=t.slice(0,a+1);if(o>=Math.max(14,.22*Math.hypot(l.w,l.h))||Math.max(l.w,l.h)<=sn)continue;let d=x(u);if(Math.max(l.x0-t[0][0],t[0][0]-l.x1,l.y0-t[0][1],t[0][1]-l.y1)<Math.max(20,.2*Math.hypot(l.w,l.h))||y(t[0],t[a])<Math.max(14,.22*Math.hypot(d.w,d.h)))continue;let f=un(c);if(!(!f||ne(t[0],f.poly)||w(t[0],f.poly)<20))return t===e?{loop:c,line:u,end:1,fit:f}:{loop:c.reverse(),line:u.reverse(),end:0,fit:f}}return null}var hn=44,gn=.65;function _n(e,t){let n=(e,t)=>{let n=y(e,t)||1;return[(t[0]-e[0])/n,(t[1]-e[1])/n]},r=[];for(let i of e){if(i.len>132)continue;let e=nt(i.pts),a=e.pts;if(e.headEnd!==e.headStart){let t=e.headEnd?i.pts:i.pts.slice().reverse(),n=Math.max(...t.map(e=>y(e,t[0]))),r=t.findIndex(e=>y(e,t[0])>=n-3);a=e.headEnd?t.slice(0,r+1):t.slice(0,r+1).reverse()}let o=b(a),s=a[0],c=a[a.length-1];if(a.length<2||o<6||o>hn||y(s,c)<gn*o||e.headStart&&e.headEnd)continue;let l=[n(E(a,0,6,1),s),n(E(a,a.length-1,6,-1),c)];r.push({it:i,end:[s,c],out:l,hook:[e.headStart,e.headEnd],atShape:[t(s,6),t(c,6)],len:o})}if(r.length<2)return[];let i=(e,t)=>e[0]*t[0]+e[1]*t[1],a=[];for(let e=0;e<r.length;e++)for(let o=e+1;o<r.length;o++)for(let s of[0,1])for(let c of[0,1]){let l=r[e],u=r[o];if(l.hook[s]||u.hook[c]||l.atShape[s]||u.atShape[c])continue;let d=l.end[s],f=u.end[c],p=y(d,f);if(p<3||p>Math.min(48,Math.max(16,1.8*Math.max(l.len,u.len))))continue;let m=l.out[s],h=n(d,f),g=[-u.out[c][0],-u.out[c][1]],_=i(m,h)>=-.1&&i(h,g)>=-.1&&i(m,h)+i(h,g)>=.9&&i(m,g)>=-.4,v=e=>[d[0]+e*(f[0]-d[0]),d[1]+e*(f[1]-d[1])];_&&![.25,.5,.75].some(e=>t(v(e),3))&&a.push([p,e,s,o,c])}a.sort((e,t)=>e[0]-t[0]);let o=r.map(()=>[null,null]),s=r.map((e,t)=>t),c=e=>s[e]===e?e:s[e]=c(s[e]);for(let[,e,t,n,r]of a)o[e][t]||o[n][r]||c(e)===c(n)||(o[e][t]=[n,r],o[n][r]=[e,t],s[c(e)]=c(n));let l=[],u=new Set;return r.forEach((e,t)=>{let n=o[t][0]?o[t][1]?-1:1:0;if(u.has(t)||n<0||!o[t][1-n])return;let i=[],a=[t,n];for(;a&&!u.has(a[0]);){let[e,t]=a;u.add(e),i.push({it:r[e].it,flip:t===1}),a=o[e][1-t]}if(i[0].it.index>i[i.length-1].it.index){i.reverse();for(let e of i)e.flip=!e.flip}l.push(i)}),l}var vn=8,yn=10;function bn(e,t){let n=e=>Math.max(20,y(e[0],e[e.length-1]));if(Math.min(n(e),n(t))<.6*Math.max(n(e),n(t)))return!1;let r=Math.min(yn,Math.max(vn,.04*Math.min(b(e),b(t)))),i=(e,t)=>S(e,16).slice(3,13).every(e=>te(e,t)<=r);return i(e,t)&&i(t,e)}function xn(e,t){let n=new Map(e.map(e=>[e,[]])),r=new Map(e.map(e=>[e,[]]));for(let e of t)n.has(e.from)&&n.has(e.to)&&(n.get(e.from).push(e.to),r.get(e.to).push(e.from),e.both&&(n.get(e.to).push(e.from),r.get(e.from).push(e.to)));let i=[],a=new Set;for(let t of e){if(a.has(t))continue;a.add(t);let e=[[t,0]];for(;e.length;){let t=e[e.length-1],r=n.get(t[0]);if(t[1]<r.length){let n=r[t[1]++];a.has(n)||(a.add(n),e.push([n,0]))}else i.push(t[0]),e.pop()}}let o=new Set,s=0;for(let e of i.reverse()){if(o.has(e))continue;let t=[e],i=0;for(o.add(e);t.length;){let e=t.pop();i++;for(let n of r.get(e))o.has(n)||(o.add(n),t.push(n))}(i>1||n.get(e).includes(e))&&s++}return s}var Sn=[{key:`ink`,name:`Ink`},{key:`green`,name:`Green`},{key:`blue`,name:`Blue`},{key:`red`,name:`Red`},{key:`amber`,name:`Amber`}],Cn={rect:[`box`,`boxes`],subroutine:[`box in a box`,`boxes in boxes`],stadium:[`oval`,`ovals`],circle:[`circle`,`circles`],double:[`double circle`,`double circles`],diamond:[`diamond`,`diamonds`],hexagon:[`hexagon`,`hexagons`],trapezoid:[`trapezoid`,`trapezoids`],"inv-trapezoid":[`trapezoid wide at the top`,`trapezoids wide at the top`],"lean-right":[`parallelogram`,`parallelograms`],"lean-left":[`parallelogram leaning left`,`parallelograms leaning left`],triangle:[`triangle`,`triangles`],"flip-triangle":[`triangle pointing down`,`triangles pointing down`],dot:[`start dot`,`start dots`],bullseye:[`end ring`,`end rings`]},wn=[[`rect`,`Agent: box`],[`stadium`,`Researcher: oval`],[`diamond`,`Critic: diamond`],[`hexagon`,`Check: hexagon`],[`trapezoid`,`Human gate: trapezoid`],[`circle`,`Merge: circle`],[`double`,`Stop: double circle`],[`subroutine`,`Agent: box in a box`],[`lean-right`,`Agent: parallelogram`],[`lean-left`,`Agent: parallelogram, leaning left`],[`inv-trapezoid`,`Agent: trapezoid, wide at the top`],[`triangle`,`Agent: triangle`],[`flip-triangle`,`Agent: triangle, pointing down`]],Tn=[{kind:`rect`,label:`Agent`,w:150,h:64},{kind:`stadium`,label:`Researcher`,w:150,h:60},{kind:`diamond`,label:`Critic`,w:140,h:104},{kind:`hexagon`,label:`Check`,w:150,h:64},{kind:`trapezoid`,label:`Human gate`,w:170,h:64},{kind:`circle`,label:`Merge`,w:84,h:84},{kind:`double`,label:`Stop`,w:84,h:84}],En=(e,t,n)=>`${e} ${e===1?t:n}`,Dn=`groophSketch.v1`,On=16,kn=e=>({nodes:e.nodes.map(e=>({id:e.id,name:e.name||e.id,shape:q(e)})),edges:e.edges.map(e=>({id:e.id,from:e.from,to:e.to,name:ye(e)})),groups:(e.groups??[]).map(e=>({id:e.id,name:e.name||e.id,members:e.members}))}),An=e=>JSON.stringify(kn(e));function jn(e,t){let n;try{n=JSON.parse(e)}catch{return null}if(!Array.isArray(n?.nodes)||!Array.isArray(n.edges)||!Array.isArray(n.groups)||n.nodes.length!==t.nodes.length||n.edges.length!==t.edges.length||n.groups.length!==t.groups.length)return null;let r=new Map;for(let[e,i]of n.nodes.entries()){if(i.shape!==t.nodes[e].shape)return null;r.set(i.id,t.nodes[e].id)}for(let[e,i]of n.groups.entries())r.set(i.id,t.groups[e].id);for(let[e,i]of n.edges.entries()){let n=t.edges[e];if(r.get(i.from)!==n.from||r.get(i.to)!==n.to)return null;r.set(i.id,n.id)}for(let[e,i]of n.groups.entries())if(JSON.stringify(i.members.map(e=>r.get(e)))!==JSON.stringify(t.groups[e].members))return null;return r}function Mn(e){try{let t=localStorage.getItem(`${Dn}:${e}`);if(!t)return null;let n=JSON.parse(t),r=Ue(n.file);if(!r.ok)return null;let i=Array.isArray(n.marks)&&n.marks.length===r.file.strokes.length?n.marks:r.file.strokes.map(()=>null),a=Array.isArray(n.unboxed)?n.unboxed.filter(e=>typeof e==`string`):[];return{file:r.file,marks:i,synced:typeof n.synced==`string`?n.synced:``,unboxed:a}}catch{return null}}function Nn(e,t){try{let n=JSON.parse(localStorage.getItem(Dn)??`[]`).filter(t=>typeof t==`string`&&t!==e);for(t?(localStorage.setItem(`${Dn}:${e}`,JSON.stringify(t)),n.push(e)):localStorage.removeItem(`${Dn}:${e}`);n.length>On;)localStorage.removeItem(`${Dn}:${n.shift()}`);localStorage.setItem(Dn,JSON.stringify(n))}catch{}}function Pn(e,t){e.classList.add(`sk`),e.innerHTML=ke;let n=!1,r=t=>e.querySelector(`#sk-${t}`),i=[],a=(e,t,n,r)=>{e.addEventListener(t,n,r),i.push(()=>e.removeEventListener(t,n,r))},s={};function c(e,t,n){clearTimeout(s[e]),s[e]=setTimeout(t,n)}let l={strokes:[],undo:[],redo:[],reading:null,stale:!1,labels:{},tool:`draw`,color:`ink`,synced:``,made:null,unboxed:[]},d=r(`pad`),_=null,v=0,y=r(`sel-bar`),b=bt(d,{begin(){r(`hint`).hidden=!0},select(){F()},edit(e){x(e),F()},stroke(...e){x([...l.strokes,...e])},erase(e){let t=new Set(e);x(l.strokes.filter(e=>!t.has(e.id)))},cut(e,t){let n=je(l.strokes,e,t,b.nextId);if(!n.pieces.size)return;let r=[...P(),...le()];for(let[e,t]of n.pieces){V.set(e,t);for(let n of t)he.set(n,e);for(let n of r)if(n.has(e))for(let r of t)n.set(r,n.get(e))}x(n.strokes)},tap(e){if(!l.strokes.length)return;let t=t=>Me(e,`nodes`,t)??Ne(e,t)??Me(e,`groups`,t),n=!!l.reading&&!l.stale;if(!t(n?l.reading:Kt())){b.overlaid&&b.setOverlay(null);return}n?b.overlaid||b.setOverlay({reading:l.reading,labels:l.labels}):Se();let r=t(l.reading);r&&`kind`in r&&r.kind===`dot`?Y(`A start dot is not a step: a run starts at the steps nothing leads to.`):r&&Je(r)},empty(){b.overlaid&&b.setOverlay(null)},penMode(e){r(`pen-chip`).hidden=!e},view(e){if(n)return;let t=r(`zoom`);t.hidden=Math.abs(e.scale-1)<.01,t.textContent=Math.round(e.scale*100)+`%`,Ye(!0),F()}});function x(e){l.undo.push(l.strokes),l.undo.length>200&&l.undo.shift(),l.redo=[],S(e)}function S(e){l.strokes=e,b.setStrokes(e),l.stale=!0,r(`go`).dataset.stale=String(e.length>0),r(`hint`).hidden=e.length>0,r(`undo`).disabled=!l.undo.length,r(`clear`).disabled=!e.length,r(`redo`).disabled=!l.redo.length,b.setOverlay(null),Ye(!0),F(),Rt(),c(`names`,Ie,120)}function C(){let e=l.undo.pop();e&&(l.redo.push(l.strokes),S(e))}function w(){let e=l.redo.pop();e&&(l.undo.push(l.strokes),S(e))}r(`undo`).addEventListener(`click`,C),r(`redo`).addEventListener(`click`,w);let T=Array.from(e.querySelectorAll(`button[data-tool]`)),E=`groophSketch.eraser`,re=`groophSketch.select`,ie=`whole`,ae=`box`;try{localStorage.getItem(E)===`part`&&(ie=`part`),localStorage.getItem(re)===`lasso`&&(ae=`lasso`)}catch{}b.setChooseBy(ae);let se=e=>e.dataset.tool===`erase`&&ie===`part`?`cut`:e.dataset.tool;function D(e){l.tool=e,b.setTool(e);let t=e===`cut`?`erase`:e;for(let e of T)e.setAttribute(`aria-checked`,String(e.dataset.tool===t));j.open(!1),F()}let O={eraser:[[`whole`,`Erase whole strokes`,`A touch takes the whole stroke`],[`part`,`Erase only what it passes over`,`Cuts a line apart from its box`]],select:[[`box`,`Drag a box`,`Takes every stroke the box reaches into`],[`lasso`,`Draw a lasso`,`Takes every stroke the loop reaches into`]]},k=r(`tool-menu`),A=`eraser`,j={list:k,open(e,t=!0){k.hidden=!e,e&&t&&k.querySelector(`[aria-checked="true"]`)?.focus()},get isOpen(){return!k.hidden}};function M(e,t,n){A=e;let r=e===`eraser`?ie:ae;k.setAttribute(`aria-label`,e===`eraser`?`Eraser`:`Select`),k.innerHTML=O[e].map(([e,t,n])=>`<li role="none"><button type="button" role="menuitemradio" aria-checked="${e===r}" data-kind="${e}">${t}<small>${n}</small></button></li>`).join(``);let i=t.closest(`.sk-tools`).getBoundingClientRect(),a=t.getBoundingClientRect();k.style.left=ce()?``:`${Math.max(0,a.left-i.left)}px`;for(let e of rt)e.open(!1);j.open(!0,n)}let ce=()=>e.clientWidth<720;function N(e,t){e===`eraser`?(ie=t===`part`?`part`:`whole`,D(ie===`part`?`cut`:`erase`)):(ae=t===`lasso`?`lasso`:`box`,b.setChooseBy(ae),D(`select`));try{localStorage.setItem(e===`eraser`?E:re,t)}catch{}}for(let e of T)e.addEventListener(`click`,t=>{let n=se(e),r=e.dataset.options;r&&l.tool===n?j.isOpen&&A===r?j.open(!1):M(r,e,t.detail===0):D(n)});k.addEventListener(`click`,e=>{let t=e.target.closest(`[data-kind]`)?.dataset.kind;t&&(N(A,t),T.find(e=>e.dataset.options===A)?.focus())}),k.addEventListener(`keydown`,e=>{let t=Array.from(k.querySelectorAll(`button`)),n=t.indexOf(document.activeElement);e.key===`ArrowDown`||e.key===`ArrowUp`?(e.preventDefault(),t[(n+(e.key===`ArrowDown`?1:-1)+t.length)%t.length].focus()):e.key===`Escape`?(e.preventDefault(),j.open(!1),T.find(e=>e.dataset.options===A)?.focus()):e.key===`Tab`&&j.open(!1)});let P=()=>[W.shape,W.line,K],le=()=>[J.node,J.edge,J.group];function F(){let e=l.tool===`select`?b.chosenBox():null,t=e!==null;for(let e of y.querySelectorAll(`[data-sel]`))e.hidden=e.dataset.sel===`paste`?!_:!t;let n=t&&I(b.chosen)!==void 0,r=y.querySelector(`[data-sel="group"]`);if(r.textContent=n?`Ungroup`:`Group`,r.setAttribute(`aria-label`,n?`Ungroup the chosen strokes`:`Group the chosen strokes`),y.hidden=l.tool!==`select`||!t&&!_,y.hidden)return;let i=y.offsetWidth,a=y.offsetHeight,o=d.clientWidth,s=d.clientHeight,c=o/2-i/2,u=8;e&&(c=(e.x0+e.x1)/2-i/2,u=e.turn[1]-16-a>=4?e.turn[1]-16-a:e.y1+14,u+a>s-4&&(u=Math.max(4,Math.min(s-a-4,e.y0+4)))),y.style.left=d.offsetLeft+Math.max(4,Math.min(o-i-4,c))+`px`,y.style.top=d.offsetTop+u+`px`}function I(e){let t=new Set(l.strokes.filter(t=>e.includes(t.id)).map(e=>e.group));return t.size===1?[...t][0]:void 0}function L(){let e=new Set(b.chosen);if(!e.size)return!1;let t=l.strokes.filter(t=>e.has(t.id));return _={strokes:t,kept:P().map(e=>new Map(t.filter(t=>e.has(t.id)).map(t=>[t.id,e.get(t.id)])))},v=0,!0}function R(e,t,n,r){let{copies:i,from:a}=gt(e,new Set(e.map(e=>e.id)),n,r,b.nextId,[...l.strokes,...e]),o=P();for(let[e,n]of a)t.forEach((t,r)=>t.has(n)&&o[r].set(e,t.get(n)));x([...l.strokes,...i]),b.choose(i.map(e=>e.id))}function ue(){let e=new Set(b.chosen);e.size&&x(l.strokes.filter(t=>!e.has(t.id)))}function de(){if(!_)return;let e=mt(_.strokes,new Set(_.strokes.map(e=>e.id))),t=b.view,n=b.size,r=24/t.scale,i=-t.x/t.scale+n.w/2+v*r,a=-t.y/t.scale+n.h/2+v*r;v++,R(_.strokes,_.kept,i-e.cx,a-e.cy)}function fe(e){let t=b.chosen;if(e===`copy`&&L())Y(`Copied. Paste puts a copy in the middle of the screen.`);else if(e===`cut`&&L())ue(),Y(`Cut. Paste puts it back in the middle of the screen.`);else if(e===`paste`)de();else if(e===`duplicate`&&t.length){let e=l.strokes.filter(e=>t.includes(e.id)),n=24/b.view.scale;R(e,P().map(t=>new Map(e.filter(e=>t.has(e.id)).map(e=>[e.id,t.get(e.id)]))),n,n)}else if(e===`delete`)ue();else if(e===`snap`&&t.length){let e=Kt(),n=be(e).shapes,r={...e,nodes:e.nodes.map(e=>n[e.id]?{...e,kind:n[e.id]}:e)},i=Ct(l.strokes,new Set(t),r,b.nextId);if(!i.shapes&&!i.arrows)Y(`Nothing here to snap: hold a shape or an arrow still as you draw it, or draw it closer to one grooph knows.`);else{let e=[...P(),...le()];for(let[t,n]of i.from)for(let r of e)r.has(n)&&r.set(t,r.get(n));x(i.strokes);let n=new Set(i.strokes.map(e=>e.id));b.choose([...t.filter(e=>n.has(e)),...i.from.keys()]),Y(`Snapped ${[i.shapes&&En(i.shapes,`shape`,`shapes`),i.arrows&&En(i.arrows,`arrow`,`arrows`)].filter(Boolean).join(` and `)} clean. Undo brings back what was drawn.`)}}else if(e===`group`&&t.length){let e=I(t)!==void 0,n=1+Math.max(0,...l.strokes.map(e=>e.group??0));x(l.strokes.map(r=>t.includes(r.id)?e?{...r,group:void 0}:{...r,group:n}:r)),Y(e?`Ungrouped.`:`Grouped: tapping any of these strokes chooses them all.`)}F()}y.addEventListener(`click`,e=>{let t=e.target.closest(`[data-sel]`)?.dataset.sel;t&&fe(t)});let pe=r(`inks`);for(let e of Sn){let t=`sk-ink-`+e.key;pe.insertAdjacentHTML(`beforeend`,`<input type="radio" name="sk-ink" id="${t}" value="${e.key}"${e.key===`ink`?` checked`:``}><label for="${t}" title="${e.name}"><span class="sr-only">${e.name}</span><span class="sk-swatch" style="background:var(--draw-${e.key})"></span></label>`)}pe.addEventListener(`change`,e=>{l.color=e.target.value,b.setColor(l.color),D(`draw`)}),r(`fingers-draw`).addEventListener(`click`,()=>{b.setPenMode(!1),r(`pen-chip`).hidden=!0}),r(`zoom`).addEventListener(`click`,()=>b.fitContent());let me=new Map,he=new Map,V=new Map;function ge(e){let t=new Set([e]);for(let n=he.get(e);n!==void 0&&!t.has(n);n=he.get(n))t.add(n);let n=[e];for(;n.length;)for(let e of V.get(n.pop())??[])t.has(e)||(t.add(e),n.push(e));return[...t]}let H=e=>[...me.get(e)??[]].flatMap(ge),_e=new Set,W={shape:new Map,line:new Map};function G(e,t){let n=W[_e.has(e)?`line`:`shape`];for(let r of H(e))t.trim()?n.set(r,t):n.delete(r)}let K=new Map,q=new Map;function ve(e,t){for(let n of H(e))t===q.get(e)?K.delete(n):K.set(n,t)}let J={node:new Map,edge:new Map,group:new Map},ye=(e,t)=>t.bb.cx>e.bb.x0&&t.bb.cx<e.bb.x1&&t.bb.cy>e.bb.y0&&t.bb.cy<e.bb.y1;function be(e){let t=l.reading,n=l.labels,r=me,i=new Map([...e.nodes,...e.groups,...e.edges].map(e=>[e.id,new Set(e.strokes.map(e=>l.strokes[e]?.id).filter(e=>e!==void 0))])),a={},o={},s={nodes:{},edges:{},groups:{}},c=(e,t)=>e.map(e=>t.get(e)).find(e=>e!==void 0);for(let t of[...e.nodes,...e.groups,...e.edges]){let n=[...i.get(t.id)],r=e.edges.includes(t),l=W[r?`line`:`shape`],u=n.map(e=>l.get(e)).find(Boolean);if(u&&(a[t.id]=u),e.nodes.includes(t)){let e=n.map(e=>K.get(e)).find(Boolean);e&&(o[t.id]=e);let r=c(n,J.node);r&&(s.nodes[t.id]=r)}else if(r){let e=c(n,J.edge);e&&(s.edges[t.id]=e)}else{let e=c(n,J.group);e&&(s.groups[t.id]=e)}}if(t){let o=new Set(l.strokes.map(e=>e.id));for(let i of[`nodes`,`groups`]){let c=t[i].filter(e=>n[e.id]?.trim()&&![...r.get(e.id)??[]].some(e=>o.has(e)));for(let t of e[i]){if(a[t.id]||!c.length)continue;let e=c.filter(e=>ye(t,e)&&ye(e,t)).sort((e,n)=>Math.hypot(e.bb.cx-t.bb.cx,e.bb.cy-t.bb.cy)-Math.hypot(n.bb.cx-t.bb.cx,n.bb.cy-t.bb.cy))[0];if(!e)continue;a[t.id]=n[e.id],c.splice(c.indexOf(e),1);let r=i===`nodes`?xe.nodes[e.id]:xe.groups[e.id],o=i===`nodes`?s.nodes:s.groups;r&&!Object.values(o).includes(r)&&(o[t.id]=r)}}let c=t=>{let n=r.get(t)??new Set;return[...e.nodes,...e.groups].find(e=>[...i.get(e.id)].some(e=>n.has(e)))?.id},u=t.edges.filter(e=>n[e.id]?.trim()&&![...r.get(e.id)??[]].some(e=>o.has(e))),d=new Set([...r.values()].flatMap(e=>[...e]));for(let t of e.edges){if(a[t.id]||!u.length||[...i.get(t.id)].some(e=>d.has(e)))continue;let e=u.find(e=>{let n=c(e.from),r=c(e.to);return n===t.from&&r===t.to||n===t.to&&r===t.from});e&&(a[t.id]=n[e.id],u.splice(u.indexOf(e),1))}}return{drawnWith:i,labels:a,shapes:o,marks:s}}let xe={nodes:{},edges:{},groups:{}};function Se(){let e=It(l.strokes,{diagram:`flowchart`}),{labels:t,shapes:n,marks:i,drawnWith:a}=be(e);me=a,_e=new Set(e.edges.map(e=>e.id)),q=new Map(e.nodes.map(e=>[e.id,e.kind]));for(let t of e.nodes)n[t.id]&&(t.kind=n[t.id],t.unsure=!1);l.reading=e,l.labels=t,xe=i;for(let[e,n]of Object.entries(t))G(e,n);return l.stale=!1,r(`go`).dataset.stale=`false`,Ce(e),We(),b.setOverlay({reading:e,labels:t}),Ie(),i}function Y(e){let t=document.createElement(`span`);t.textContent=e,r(`read`).replaceChildren(t)}function Ce(e,t){let n={};for(let t of e.nodes)n[t.kind]=(n[t.kind]||0)+1;let i=Object.entries(n).map(([e,t])=>En(t,...Cn[e])),a=e.edges.length,o=e.edges.filter(e=>e.assumed).length,s=e.nodes.filter(e=>e.unsure).length,c=[],l=o?`, ${o} with no head, so pointed the way ${o===1?`it was`:`they were`} drawn`:``;c.push(e.nodes.length?`<strong>${En(e.nodes.length,`shape`,`shapes`)}</strong> (${i.join(`, `)})`:`<strong>no shapes</strong>`),e.groups.length&&c.push(En(e.groups.length,`box`,`boxes`)),c.push(En(a,`arrow`,`arrows`)+l),e.loops&&c.push(`<strong>${En(e.loops,`loop`,`loops`)}</strong>`),e.unused.length&&c.push(`${En(e.unused.length,`mark`,`marks`)} left out, shaded on the drawing`),s&&c.push(`${En(s,`shape`,`shapes`)} hard to read`);let u=t?` ${we(t)}`:``;r(`read`).innerHTML=`<span>Read ${c.join(` · `)}.${u}</span> <span class="sk-ms">${e.ms.toFixed(1)} ms</span> <a class="sk-to-result" href="#sk-result">See the graph</a>`}function we(e){let{added:t,kept:n,removed:r}=e.counts,i=[t&&En(t,`new step`,`new steps`),n&&`${n} kept`,r&&`${r} taken away`].filter(Boolean);return`Made the graph${i.length?`: ${i.join(`, `)}`:``}.`}function Ee(e=!1,n=!1){if(!l.strokes.length){Y(`Draw something first, or load the example from More.`);return}let r=l.reading&&!l.stale?xe:Se(),i=l.reading,a=t.doc(),o=Oe(i,l.labels,r,a,l.unboxed);if(`error`in o){Y(o.error);return}if(o.doc.nodes.length===0&&a.nodes.length>0){Y(`No step was read, so the graph is as it was.`);return}let s=(e,t,n)=>{for(let r of t){let t=e[r.id];if(t!==void 0)for(let e of r.strokes)l.strokes[e]&&n.set(l.strokes[e].id,t)}};s(o.became.nodes,i.nodes,J.node),s(o.became.edges,i.edges,J.edge),s(o.became.groups,i.groups,J.group),xe=o.became;let c=!De(o.doc,a),u=n&&l.made?l.made:null;l.made={...o,at:c?o.doc:a,before:u?u.before:a,changed:c||!!u?.changed},l.synced=An(o.doc),c&&t.apply(o.doc,e),Ce(i,o),et(o.doc,o),Rt()}r(`go`).addEventListener(`click`,()=>Ee());function Ae(t){b.setShowOverlay(t),r(`show-read`).checked=t,e.querySelector(`[data-act="outlines"]`).setAttribute(`aria-checked`,String(t))}r(`show-read`).addEventListener(`change`,e=>Ae(e.target.checked));function Me(e,t,n=l.reading){if(!n)return null;let r=e=>e.bb.w*e.bb.h;return n[t].filter(t=>ne(e,t.poly)).sort((e,t)=>r(e)-r(t))[0]??null}function Ne(e,t=l.reading){let n=16/b.view.scale;if(!t)return null;let r=null;for(let i of t.edges){let t=te(e,i.pts);t<=n&&(!r||t<r.d)&&(r={e:i,d:t})}return r?.e??null}let Pe=`groophSketch.names`,Fe=!0;try{Fe=localStorage.getItem(Pe)!==`off`}catch{}function Ie(){if(b.pressing)return c(`names`,Ie,200);if(!l.strokes.some(e=>W.shape.has(e.id)||W.line.has(e.id))||!Fe)return b.setNames([]);let e=!!l.reading&&!l.stale,t=e?l.reading:Kt(),n=e?l.labels:be(t).labels,r=[],i=e=>e.flatMap(e=>l.strokes[e]?[l.strokes[e].id]:[]);for(let e of[...t.nodes,...t.groups]){let a=n[e.id]?.trim();a&&e.kind!==`dot`&&r.push({strokes:i(e.strokes),at:[e.bb.cx,t.groups.includes(e)?e.bb.y0+16:e.bb.cy],text:a,w:e.bb.w,line:!1})}for(let e of t.edges){let t=n[e.id]?.trim();t&&e.pts.length>1&&r.push({strokes:i(e.strokes),at:ee(e.pts),text:t,w:180,line:!0})}b.setNames(r)}function Le(e){Fe=e,b.setShowNames(e),r(`more-list`).querySelector(`[data-act="names"]`).setAttribute(`aria-checked`,String(e));try{e?localStorage.removeItem(Pe):localStorage.setItem(Pe,`off`)}catch{}Ie()}function Re(e){l.made&&l.reading&&!l.stale&&c(`make`,()=>Ee(e,!0),e?250:0)}function ze(t,n){l.labels[t]=n,G(t,n),l.reading&&!l.stale&&b.setOverlay({reading:l.reading,labels:l.labels}),c(`names`,Ie,60);let r=e.querySelector(`#sk-name-${t}`);r&&r.value!==n&&(r.value=n),Re(!0),Rt()}function Be(t,n){let r=l.reading?.nodes.find(e=>e.id===t);r&&r.kind!==n&&(r.kind=n,r.unsure=!1,ve(t,n),e.querySelector(`#sk-name-${t}`)?.setAttribute(`aria-label`,`Name for ${t}, ${Cn[n][0]}`),l.stale||(b.setOverlay({reading:l.reading,labels:l.labels}),Ce(l.reading)),Re(!1),Rt())}let Ve=e=>xe.nodes[e.id];function We(){let e=r(`names`),t=l.reading;if(e.textContent=``,t){for(let n of[...t.nodes,...t.groups]){if(n.kind===`dot`)continue;let r=t.groups.includes(n),i=r?`box`:Cn[n.kind]?.[0]??`shape`,a=document.createElement(`label`),o=document.createElement(`span`),s=document.createElement(`input`);o.className=`sk-tag`,o.textContent=n.id,s.id=`sk-name-`+n.id,s.value=l.labels[n.id]??``,s.placeholder=n.label,s.autocomplete=`off`,s.dataset.ownUndo=``,s.setAttribute(`aria-label`,`Name for ${n.id}, ${i}`),s.addEventListener(`input`,()=>ze(n.id,s.value)),a.append(o,s);let c=document.createElement(`div`);if(c.className=`sk-name-row`,c.append(a),r){let e=document.createElement(`span`);e.className=`sk-shape-note`,e.textContent=`Box of steps`,c.append(e)}else{let e=document.createElement(`select`);e.id=`sk-shape-`+n.id,e.setAttribute(`aria-label`,`Shape for ${n.id}`);let t=n.kind===`bullseye`?[[`bullseye`,`Stop: end ring`],...wn]:wn;for(let[r,i]of t)e.add(new Option(i,r,!1,r===n.kind));e.addEventListener(`change`,()=>Be(n.id,e.value)),c.append(e),Ve(n)&&(c.dataset.step=Ve(n))}e.append(c)}for(let n of t.edges){let t=document.createElement(`label`),r=document.createElement(`span`),i=document.createElement(`input`);r.className=`sk-tag sk-line-tag`,r.textContent=`${n.from}${n.both?`↔`:`→`}${n.to}`,i.id=`sk-name-`+n.id,i.value=l.labels[n.id]??``,i.placeholder=`No name`,i.autocomplete=`off`,i.dataset.ownUndo=``,i.setAttribute(`aria-label`,`Name for the line from ${n.from} ${n.both?`and`:`to`} ${n.to}`),i.addEventListener(`input`,()=>ze(n.id,i.value)),t.append(r,i);let a=document.createElement(`div`);a.className=`sk-name-row`,a.append(t),e.append(a)}!t.nodes.length&&!t.groups.length&&(e.innerHTML=`<p class="sk-status">No shapes were read. Draw a closed shape, like a box or a circle.</p>`)}}let Ge=r(`name-edit`),Ke=r(`name-input`),qe=null;function Je(e){Ye(!0),qe=e;let t=`pts`in e&&`from`in e,n=t?ee(e.pts):[e.bb.cx,e.bb.cy],i=r(`pad-wrap`).getBoundingClientRect(),[a,o]=b.toScreen(n),s=Math.min(i.width-16,Math.max(200,t?0:e.bb.w*b.view.scale));Ge.style.width=s+`px`,Ge.style.left=Math.max(8,Math.min(i.width-s-8,a-s/2))+`px`,Ge.style.top=Math.max(8,Math.min(i.height-52,o-22))+`px`,r(`name-label`).textContent=t?`Name for the line from ${e.from} ${e.both?`and`:`to`} ${e.to}`:`Name for ${e.id}`,Ke.value=l.labels[e.id]??``,Ke.placeholder=t?`Name this line`:e.label,Ge.hidden=!1,Ke.focus({preventScroll:!0}),Ke.select()}function Ye(e){qe&&(e&&ze(qe.id,Ke.value),qe=null,Ge.hidden=!0)}Ge.addEventListener(`submit`,e=>{e.preventDefault(),Ye(!0)}),Ke.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.preventDefault(),Ye(!1),d.focus())}),Ke.addEventListener(`blur`,()=>Ye(!0)),d.addEventListener(`pointerdown`,()=>Ye(!0),{capture:!0});let Xe=r(`code`),Ze=r(`diagram`),Qe=``,$e=0;async function et(e,t){let i=++$e;Xe.value=e.nodes.length?o(e):``;let a=r(`guesses`),s=t?[...t.left?[t.left]:[],...t.guesses]:[];if(a.replaceChildren(...s.map(e=>Object.assign(document.createElement(`li`),{textContent:e}))),a.hidden=s.length===0,r(`undo-make`).hidden=!t||!l.made?.changed,!e.nodes.length){Ze.innerHTML=`<p class="sk-empty">The graph appears here after Make it a graph.</p>`,Qe=``,tt();return}let c=g(e,`auto`);try{if(document.querySelector(`main.stage[data-look]`)||h()){let e=(await f()).look();e&&(c=e.picture(c,matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`))}}catch{}i!==$e||n||(Ze.innerHTML=c,Qe=c,tt())}Ze.addEventListener(`click`,e=>{let n=e.target.closest(`[data-node]`)?.dataset.node;n&&t.open(n)});function tt(){r(`save-svg`).disabled=!Qe,r(`save-png`).disabled=!Qe}let nt=(e,t)=>{let n=r(e);n.textContent=t,c(`say-`+e,()=>n.textContent=``,4e3)};r(`undo-make`).addEventListener(`click`,()=>{if(!l.made)return;let e=l.made.before;l.made=null,l.synced=An(e),t.apply(e,!1),r(`go`).dataset.stale=`true`,r(`undo-make`).hidden=!0,r(`guesses`).hidden=!0,Y(`The graph is as it was before Make it a graph. The drawing is as you left it.`)}),r(`save-svg`).addEventListener(`click`,()=>{let e=t.doc();Qe&&u(m(e,`light`,`svg`).replace(`.light.`,`.`),Qe,`image/svg+xml`)}),r(`save-png`).addEventListener(`click`,async()=>{let e=t.doc();try{Qe&&u(m(e,`light`,`png`).replace(`.light.`,`.`),await p(Qe),`image/png`)}catch{nt(`save-status`,`The PNG could not be made here. Save SVG still works.`)}}),r(`export`).addEventListener(`click`,()=>t.exporting()),r(`copy`).addEventListener(`click`,async()=>{try{await navigator.clipboard.writeText(Xe.value),nt(`copy-status`,`Copied.`)}catch{Xe.focus(),Xe.select(),nt(`copy-status`,`Copy was blocked here; the code is selected, so copy it by hand.`)}}),r(`save-mmd`).addEventListener(`click`,()=>{Xe.value.trim()&&u(`${t.doc().id||`graph`}.mmd`,Xe.value.trimEnd()+`
143
+ `,`text/plain`)});let rt=[j];function it(e,t){let n=()=>Array.from(t.querySelectorAll(`[role^=menuitem]`)),r=(r,i=!0)=>{t.hidden=!r,e.setAttribute(`aria-expanded`,String(r)),r&&i&&n()[0].focus()};e.addEventListener(`click`,()=>{for(let e of rt)e.list!==t&&e.open(!1);r(e.getAttribute(`aria-expanded`)!==`true`,!1)}),e.addEventListener(`keydown`,t=>{t.key===`ArrowDown`?(t.preventDefault(),r(!0)):t.key===`Escape`&&e.getAttribute(`aria-expanded`)===`true`&&(t.preventDefault(),r(!1))}),t.addEventListener(`keydown`,t=>{let i=n(),a=i.indexOf(document.activeElement);t.key===`ArrowDown`||t.key===`ArrowUp`?(t.preventDefault(),i[(a+(t.key===`ArrowDown`?1:-1)+i.length)%i.length].focus()):t.key===`Escape`?(t.preventDefault(),r(!1),e.focus()):t.key===`Tab`&&r(!1)});let i={list:t,open:r,get isOpen(){return e.getAttribute(`aria-expanded`)===`true`}};return rt.push(i),i}let at=r(`more`),ot=r(`more-list`),st=it(at,ot);a(document,`pointerdown`,e=>{for(let t of rt)t.list.parentElement.contains(e.target)||t.open(!1)});let ct=r(`add`),lt=r(`add-list`);function ut(e){let t=e=>`<svg viewBox="0 0 28 20" aria-hidden="true">${e}</svg>`;if(e===`double`)return t(`<circle cx="14" cy="10" r="7.5" /><circle cx="14" cy="10" r="4.6" />`);if(e===`circle`)return t(`<circle cx="14" cy="10" r="7.5" />`);if(e===`stadium`)return t(`<rect x="2.5" y="3.5" width="23" height="13" rx="6.5" />`);if(e===`dot`||e===`bullseye`)return t(`<circle cx="14" cy="10" r="4.5" class="sk-fill" />`);let[n,r]=e===`diamond`||e===`triangle`?[18,15]:[23,13],i=14-n/2,a=10-r/2;return t(`<polygon points="${oe[e].map(([e,t])=>`${(i+e*n).toFixed(1)},${(a+t*r).toFixed(1)}`).join(` `)}" />`)}let dt=[{id:`arrow`,label:`Arrow`,icon:`M3 10h21M19 6l5 4-5 4`,parts:()=>[{pts:z([0,0],[140,0],1),line:!0}]},{id:`both`,label:`Two-way arrow`,icon:`M4 10h20M9 6l-5 4 5 4M19 6l5 4-5 4`,parts:()=>[{pts:z([0,0],[140,0],1,!0),line:!0}]},{id:`pair`,label:`Arrows both ways`,icon:`M3 7h21M20 4l4 3-4 3M25 13H4M8 10l-4 3 4 3`,parts:()=>[{pts:z([0,0],[140,0],1),line:!0},{pts:z([140,30],[0,30],1),line:!0}]}],ft=U.filter(e=>e.diagram===`flowchart`),pt=[...new Set(ft.map(e=>e.group))];lt.innerHTML=`<p class="sk-menu-head" id="sk-add-shapes" role="presentation">Steps</p><div class="sk-add-shapes" role="group" aria-labelledby="sk-add-shapes">`+Tn.map(e=>`<button type="button" role="menuitem" data-add="${e.kind}">${ut(e.kind)}<span>${e.label}</span></button>`).join(``)+`</div><p class="sk-menu-head" id="sk-add-arrows" role="presentation">Arrows</p><div class="sk-add-shapes sk-add-arrows" role="group" aria-labelledby="sk-add-arrows">`+dt.map(e=>`<button type="button" role="menuitem" data-arrow="${e.id}"><svg viewBox="0 0 28 20" aria-hidden="true"><path d="${e.icon}" /></svg><span>${e.label}</span></button>`).join(``)+`</div>`+pt.map((e,t)=>`<p class="sk-menu-head" id="sk-add-templates-${t}" role="presentation">${e}</p><div class="sk-add-templates" role="group" aria-labelledby="sk-add-templates-${t}">`+ft.filter(t=>t.group===e).map(e=>`<button type="button" role="menuitem" data-template="${e.id}"><span>${e.label}</span></button>`).join(``)+`</div>`).join(``);let ht=it(ct,lt);function _t(e){let t=b.view,n=e.flatMap(e=>e.pts),r=Math.min(...n.map(e=>e[0])),i=Math.max(...n.map(e=>e[0])),a=Math.min(...n.map(e=>e[1])),o=Math.max(...n.map(e=>e[1])),s=(r+i)/2,c=(a+o)/2,u=Math.max(.6,Math.min(1,.9*d.clientWidth/(i-r||1),.9*d.clientHeight/(o-a||1)))/t.scale,f=-t.x/t.scale+b.size.w/2,p=-t.y/t.scale+b.size.h/2,m=e.map(e=>{let n={id:b.nextId(),color:l.color,pts:e.pts.map(([e,t])=>[f+(e-s)*u,p+(t-c)*u]),by:`mouse`,zoom:t.scale};return e.name&&W[e.line?`line`:`shape`].set(n.id,e.name),n});x([...l.strokes,...m]),D(`select`),b.choose(m.map(e=>e.id))}lt.addEventListener(`click`,e=>{let t=e.target.closest(`[data-add], [data-arrow], [data-template]`);if(t){if(ht.open(!1),ct.focus(),t.dataset.arrow){let e=dt.find(e=>e.id===t.dataset.arrow);_t(e.parts()),Y(`Added: ${e.label.toLowerCase()}. Drag it between two steps; the plus adds those too.`)}else if(t.dataset.add){let e=Tn.find(e=>e.kind===t.dataset.add);_t(e.kind===`double`?[...B(`circle`,0,0,e.w,e.h),...B(`circle`,0,0,e.w*.72,e.h*.72)]:B(e.kind,0,0,e.w,e.h)),Y(`Added: ${e.label.toLowerCase()}. Drag it into place, or pick the pen to draw.`)}else{let e=ft.find(e=>e.id===t.dataset.template);_t(e.parts()),Y(`Added: ${e.label.toLowerCase()}, chosen so you can drag it into place. Press Make it a graph to read it.`)}}}),ot.addEventListener(`click`,e=>{let n=e.target.closest(`[data-act]`)?.dataset.act;n&&(st.open(!1),at.focus(),n===`example`&&X(),n===`redraw`&&Et(t.doc(),`Drawn from the graph as it is. Undo brings back the drawing it replaced.`),n===`fit`&&b.fitContent(),n===`snap`&&kt(!Ot),n===`outlines`&&Ae(!r(`show-read`).checked),n===`names`&&Le(!Fe),n===`save-drawing`&&wt(),n===`open-drawing`&&r(`open-file`).click())});function vt(){l.reading=null,l.labels={},l.made=null,xe={nodes:{},edges:{},groups:{}},We()}function yt(){l.strokes.length&&(x([]),vt(),Y(`Cleared. Undo brings the drawing back.`))}function X(){let e=Math.max(320,Math.min(b.size.w,520));vt(),x(Dt(e).map(e=>({id:b.nextId(),color:e.color??`ink`,pts:e.pts,by:`mouse`}))),b.resetView(),b.fitContent(),Se(),Y(`The example: a researcher, a builder, a critic that sends work back to it, and a stop. Press Make it a graph to make it the graph.`)}r(`hint-example`).addEventListener(`click`,X),r(`clear`).addEventListener(`click`,yt);function xt(){let e=new Date,t=e=>String(e).padStart(2,`0`);return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}`}function St(){l.stale&&l.strokes.length&&Se();let e={};for(let t of l.reading?.nodes??[]){let n=[...me.get(t.id)??[]].map(e=>K.get(e)).find(Boolean);n&&(e[t.id]=n)}return He(l.strokes,l.labels,Xe.value,!1,e)}function wt(){if(!l.strokes.length){Y(`There is no drawing to save yet.`);return}u(`drawing-${xt()}.json`,JSON.stringify(St()),`application/json`)}r(`open-file`).addEventListener(`change`,async e=>{let t=e.target,n=t.files?.[0];if(t.value=``,!n)return;if(n.size>5e6){Y(`That file is too large to be a drawing.`);return}let r;try{r=JSON.parse(await n.text())}catch{Y(`That file is not a drawing: it is not JSON.`);return}let i=Ue(r);if(!i.ok){Y(i.error.replace(`not a mermaidify drawing`,`not a drawing grooph or mermaidify saved`).replace(`a newer version of mermaidify`,`a newer version than this one opens`));return}Tt(i.file,i.file.strokes.map(()=>null)),Y(`Opened ${n.name}. Press Make it a graph to make it the graph.`)});function Tt(e,t){vt();let n=e.strokes.map(e=>({id:b.nextId(),color:e.color,pts:e.pts,by:e.by,...e.open?{open:e.open}:{},...e.zoom?{zoom:e.zoom}:{},...e.group?{group:e.group}:{}}));if(n.forEach((e,n)=>{let r=t[n];r&&(`node`in r?J.node.set(e.id,r.node):`edge`in r?J.edge.set(e.id,r.edge):J.group.set(e.id,r.group))}),x(n),b.fitContent(),n.length){Se();for(let[t,n]of Object.entries(e.labels))me.has(t)&&(l.labels[t]=n,G(t,n));for(let[t,n]of Object.entries(e.shapes??{})){let e=l.reading.nodes.find(e=>e.id===t);e&&(e.kind=n,e.unsure=!1,ve(t,n))}Ce(l.reading),b.setOverlay({reading:l.reading,labels:l.labels}),We(),Ie()}}function Et(e,n){let{parts:r,unboxed:i}=Te(e,t.places(e));vt(),l.unboxed=i;let a=r.map(e=>{let t={id:b.nextId(),color:`ink`,pts:e.pts,by:`mouse`};return e.name&&W[e.line?`line`:`shape`].set(t.id,e.name),`node`in e.mark?J.node.set(t.id,e.mark.node):`edge`in e.mark?J.edge.set(t.id,e.mark.edge):J.group.set(t.id,e.mark.group),t});(a.length||l.strokes.length)&&x(a),b.resetView(),b.fitContent(),l.synced=An(e),a.length&&(Se(),n&&Y(n)),et(e),Rt()}let Z=`groophSketch.snap`,Ot=!0;try{Ot=localStorage.getItem(Z)!==`off`}catch{}function kt(e){Ot=e,b.setSnap(e),ot.querySelector(`[data-act="snap"]`).setAttribute(`aria-checked`,String(e));try{e?localStorage.removeItem(Z):localStorage.setItem(Z,`off`)}catch{}}kt(Ot),Le(Fe);let Q=e.querySelector(`.sk-bar`),At=new ResizeObserver(()=>e.style.setProperty(`--sk-toolbar`,Q.offsetHeight+`px`));At.observe(Q),i.push(()=>At.disconnect());let jt=r(`full`),Mt=()=>e.classList.contains(`is-full`),Nt=[];function Pt(t){if(Mt()!==t){e.classList.toggle(`is-full`,t),document.documentElement.classList.toggle(`sk-full-page`,t),jt.setAttribute(`aria-pressed`,String(t)),jt.title=t?`Leave full screen (F or Esc)`:`Full screen (F)`;for(let e of Nt)e.inert=!1;if(Nt=[],t){let e=r(`result`).previousElementSibling;for(let t=e;t&&t!==document.body;t=t.parentElement)for(let e of t.parentElement?.children??[])e!==t&&e instanceof HTMLElement&&!e.inert&&Nt.push(e);for(let e of Nt)e.inert=!0}for(let e of rt)e.open(!1);Ye(!0),t&&!document.fullscreenElement?document.documentElement.requestFullscreen?.({navigationUI:`hide`}).catch(()=>void 0):!t&&document.fullscreenElement&&document.exitFullscreen().catch(()=>void 0)}}jt.addEventListener(`click`,()=>Pt(!Mt())),a(document,`fullscreenchange`,()=>{document.fullscreenElement?Mt()||document.exitFullscreen().catch(()=>void 0):Pt(!1)}),r(`read`).addEventListener(`click`,e=>{if(!e.target.closest(`.sk-to-result`))return;e.preventDefault();let t=()=>n||r(`result`).scrollIntoView({block:`start`,behavior:matchMedia(`(prefers-reduced-motion: reduce)`).matches?`auto`:`smooth`});if(!Mt())return t();if(!document.fullscreenElement)return Pt(!1),t();let i=!1,a=()=>{i||(i=!0,requestAnimationFrame(t))};document.addEventListener(`fullscreenchange`,a,{once:!0}),setTimeout(a,1e3),Pt(!1)}),r(`back`).addEventListener(`click`,e=>{e.preventDefault(),r(`pad-wrap`).scrollIntoView({block:`center`})});let Ft=!0,Lt=!1;function Rt(){Ft||(Lt=!0,c(`keep`,zt,500))}function zt(){if(!Lt)return;if(b.pressing&&document.visibilityState===`visible`)return c(`keep`,zt,500);if(Lt=!1,clearTimeout(s.keep),!l.strokes.length)return Nn(t.key,null);let e=l.strokes.map(e=>{let t=J.node.get(e.id),n=J.edge.get(e.id),r=J.group.get(e.id);return t===void 0?n===void 0?r===void 0?null:{group:r}:{edge:n}:{node:t}});Nn(t.key,{file:St(),marks:e,synced:l.synced,unboxed:l.unboxed})}a(window,`pagehide`,zt),a(document,`visibilitychange`,()=>{document.visibilityState===`hidden`&&zt()}),a(document,`keydown`,t=>{let n=t.target;if(!e.contains(n)&&n!==document.body)return;let r=n.closest(`input, textarea, select, [contenteditable]`),i=t.metaKey||t.ctrlKey,a=()=>{t.preventDefault(),t.stopPropagation()};if(i&&t.key===`Enter`){a(),Ee();return}if(!r&&!(t.key===`Escape`&&t.defaultPrevented)){if(t.key===`Escape`&&rt.some(e=>e.isOpen)){a();for(let e of rt)e.open(!1)}else t.key===`Escape`&&l.tool===`select`&&b.chosen.length?(a(),b.choose([])):t.key===`Escape`&&b.overlaid?(a(),b.setOverlay(null)):t.key===`Escape`&&Mt()?(a(),Pt(!1)):t.key===` `&&!i&&Bt?(a(),Vt=!0,b.setSpace(!0)):!i&&!t.altKey&&t.key.toLowerCase()===`f`?t.repeat||Pt(!Mt()):i&&t.key.toLowerCase()===`z`?(a(),t.shiftKey?w():C()):i&&t.key.toLowerCase()===`y`?(a(),w()):l.tool===`select`&&i&&([`c`,`x`,`d`].includes(t.key.toLowerCase())?b.chosen.length>0:t.key.toLowerCase()===`v`&&_)?(a(),fe({c:`copy`,x:`cut`,v:`paste`,d:`duplicate`}[t.key.toLowerCase()])):l.tool===`select`&&(t.key===`Delete`||t.key===`Backspace`)&&b.chosen.length?(a(),fe(`delete`)):!i&&!t.altKey&&t.key.toLowerCase()===`d`?D(`draw`):!i&&!t.altKey&&t.key.toLowerCase()===`e`?N(`eraser`,`whole`):!i&&!t.altKey&&(t.key.toLowerCase()===`s`||t.key.toLowerCase()===`c`)?N(`eraser`,`part`):!i&&!t.altKey&&t.key.toLowerCase()===`v`?D(`select`):!i&&!t.altKey&&t.key.toLowerCase()===`h`&&D(`hand`)}});let Bt=!1,Vt=!1;d.addEventListener(`pointermove`,()=>Bt=!0),d.addEventListener(`pointerleave`,()=>Bt=!1),a(document,`keyup`,e=>{e.key===` `&&(b.setSpace(!1),Vt&&e.preventDefault(),Vt=!1)}),a(window,`blur`,()=>{b.setSpace(!1),Vt=!1});let Ht=matchMedia(`(prefers-color-scheme: dark)`),Ut=()=>{b.repaint(),et(t.doc(),l.made&&l.made.at===t.doc()?l.made:void 0)};Ht.addEventListener(`change`,Ut),i.push(()=>Ht.removeEventListener(`change`,Ut));let Wt=new MutationObserver(Ut);Wt.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]}),i.push(()=>Wt.disconnect());let Gt=null;function Kt(){if(Gt?.strokes===l.strokes)return Gt.m;let e=It(l.strokes,{diagram:`flowchart`});return Gt={strokes:l.strokes,m:e},e}function qt(e,t){let n=kn(t),r=jn(e,n);if(!r)return!1;for(let e of[J.node,J.edge,J.group])for(let[t,n]of e)r.has(n)&&e.set(t,r.get(n));l.unboxed=l.unboxed.map(e=>r.get(e)??e);let i=new Map([...n.nodes,...n.groups].map(e=>[e.id,e.name]));for(let[e,t]of J.node)i.has(t)&&W.shape.set(e,i.get(t));for(let[e,t]of J.group)i.has(t)&&W.shape.set(e,i.get(t));let a=new Map(n.edges.map(e=>[e.id,e.name]));for(let[e,t]of J.edge)a.has(t)&&(a.get(t)?W.line.set(e,a.get(t)):W.line.delete(e));return!0}let Jt=t.doc(),$=Mn(t.key);return $&&($.synced===An(Jt)||jn($.synced,kn(Jt)))?(Tt($.file,$.marks),l.unboxed=$.unboxed,$.synced!==An(Jt)&&qt($.synced,Jt)&&Se(),l.undo=[],r(`undo`).disabled=!0,et(Jt),l.reading&&Ce(l.reading)):Jt.nodes.length?($&&$.file.strokes.length&&(Tt($.file,$.marks),l.undo=[]),Et(Jt,$&&$.file.strokes.length?`The graph has changed since you last drew it, so this is the graph as it is now. Undo brings back your drawing.`:void 0),(!$||!$.file.strokes.length)&&(l.undo=[],r(`undo`).disabled=!0)):$&&$.file.strokes.length?(Tt($.file,$.marks),l.unboxed=$.unboxed,l.undo=[],r(`undo`).disabled=!0,et(Jt)):et(Jt),l.synced=An(Jt),Ft=!1,{update(e){if(l.made?.at===e)return;l.made&&(l.made=null,r(`undo-make`).hidden=!0,r(`guesses`).hidden=!0);let t=An(e);if(t===l.synced){et(e);return}if(qt(l.synced,e)){l.synced=t,l.reading&&Se(),et(e),Rt();return}l.made=null,Et(e,`The graph changed, so this is the graph as it is now. Undo brings back the drawing before it.`)},destroy(){zt(),Pt(!1),n=!0;for(let e of Object.values(s))clearTimeout(e);for(let e of i)e();e.replaceChildren(),e.classList.remove(`sk`,`is-full`)}}}var Fn=n(),In=!1;function Ln({doc:e,host:t}){let n=(0,_.useRef)(null),r=(0,_.useRef)(void 0),i=(0,_.useRef)(t);if(i.current=t,!In){let e=document.createElement(`style`);e.textContent=v,document.head.append(e),In=!0}return(0,_.useEffect)(()=>{let e=Pn(n.current,{key:t.key,doc:()=>i.current.doc(),places:e=>i.current.places(e),apply:(e,t)=>i.current.apply(e,t),open:e=>i.current.open(e),exporting:()=>i.current.exporting()});return r.current=e,()=>{e.destroy(),r.current=void 0}},[t.key]),(0,_.useEffect)(()=>r.current?.update(e),[e]),(0,Fn.jsx)(`div`,{className:`graph-sketch`,children:(0,Fn.jsx)(`div`,{ref:n})})}export{Ln as SketchView};
@@ -0,0 +1 @@
1
+ import{t as e}from"./index-B5ZkSF4L.js";import{Jt as t,Zt as n,en as r}from"./share-DV3wsAsJ.js";var i=e=>typeof e.when==`object`?e.when.verdict:e.when??`always`;function a(e){let t=new Map(e.nodes.map(e=>[e.id,e.kind])),n=new Set(e.nodes.filter(e=>e.kind===`stop`&&e.outcome===`halt`).map(e=>e.id)),a=new Set(e.nodes.filter(r).map(e=>e.id)),o=e.edges.map(e=>({from:e.from,to:e.to,person:e.approval===!0||t.get(e.from)===`human-gate`,edge:e.id,when:i(e)}));for(let t of e.loops)for(let e of t.stops){if(e.then===void 0)continue;let r=e.kind===`max-iterations`||e.kind===`budget`||e.kind===`human`,i=r&&n.has(e.then),s=e.kind===`bar-passed`?t.members.filter(e=>a.has(e)):[];for(let n of t.members)o.push({from:n,to:e.then,person:e.kind===`human`,loop:t.id,...r?{fires:r}:{},...i?{escalates:i}:{},...s.length>0?{verdictOf:s}:{}})}return o}var o=e=>`${e.loop}\n${e.to}`;function s(e,t){if(t===`every`)return e.person;if(`approval`in t)return e.edge===t.approval;if(`critic`in t&&(e.escalates||e.fires&&t.stops?.has(o(e)))||`critic`in t&&e.verdictOf?.includes(t.critic)&&(t.when===void 0||t.when===`pass`))return!0;let n=`gate`in t?t.gate:t.critic;return e.edge!==void 0&&e.from===n&&(t.when===void 0||e.when===t.when)}function c(e){let t=new Set(e.loops.flatMap(e=>e.back));return e.nodes.filter(n=>!e.edges.some(e=>e.to===n.id&&!t.has(e.id))).map(e=>e.id)}function l(e,t,n){let r=new Set(e.nodes.map(e=>e.id)),i=new Map;for(let t of a(e))n!==void 0&&s(t,n)||!r.has(t.from)||!r.has(t.to)||(i.get(t.from)??i.set(t.from,[]).get(t.from)).push(t.to);let o=new Set(t),c=[...o];for(let e=c.pop();e!==void 0;e=c.pop())for(let t of i.get(e)??[])o.has(t)||(o.add(t),c.push(t));return o}var u=(e,t)=>l(e,c(e),t);function d(e,t){let n=new Map(t.nodes.map(e=>[e.id,e])),s=new Set(t.edges.filter(e=>e.approval===!0).map(e=>e.id)),c=t=>[...new Set(e.edges.filter(e=>e.from===t).map(i))],l=[`every`],u=new Set(a(e).filter(e=>e.fires).map(o));for(let t of e.nodes)t.kind===`human-gate`&&n.get(t.id)?.kind===`human-gate`&&l.push({gate:t.id},...c(t.id).map(e=>({gate:t.id,when:e})));for(let t of e.edges)t.approval===!0&&s.has(t.id)&&l.push({approval:t.id});for(let t of e.nodes){let e=n.get(t.id);if(r(t)&&e&&r(e)&&l.push({critic:t.id},...c(t.id).map(e=>({critic:t.id,when:e}))),t.kind===`check`&&e?.kind===`check`)for(let e of[{check:!0},{check:!0,stops:u}])l.push({critic:t.id,...e},...c(t.id).map(n=>({critic:t.id,when:n,...e})))}return l}function f(e){if(e===`every`)return`a person`;if(`approval`in e)return`the approval on "${e.approval}"`;if(`gate`in e)return e.when===void 0?`the human gate "${e.gate}"`:`"${e.when}" at the human gate "${e.gate}"`;let t=e.check?`check`:`critic`;return e.when===void 0?`the ${t} "${e.critic}"`:`"${e.when}" from the ${t} "${e.critic}"`}var p=(e,t)=>JSON.stringify(e)===JSON.stringify(t),m=(e,t)=>e!==void 0&&(e===t||e.startsWith(`${t}; `)||e.endsWith(`; ${t}`)||e.includes(`; ${t}; `)),h=e=>e.map(e=>`"${e}"`).join(`, `),g=e=>e?.kind===`agent`?e.irreversible??[]:[],_=e=>e.kind===`max-iterations`||e.kind===`budget`||e.kind===`human`,v={dispatches:`dispatch`,minutes:`minute`,turns:`turn`,tokens:`token`,rounds:`round`},y=(e,t)=>`${e} ${e===1?v[t]??t:t}`,b=(e,t)=>t===``?`${e}`:y(e,t);function x(e){let t=new Map(e.nodes.map(e=>[e.id,e]));return e=>{if(e.then===void 0)return!0;let n=t.get(e.then);return n?.kind===`human-gate`||n?.kind===`stop`&&n.outcome===`halt`}}function S(e,t){let n=x(e),r=new Map,i=(e,t)=>e===void 0?t:Math.min(e,t);for(let e of t)for(let t of e.stops){let[e,a,o,s]=t.kind===`max-iterations`?[`cap`,`the round cap`,``,t.n]:t.kind===`budget`?[`budget ${t.measure}`,`the budget`,t.measure,t.limit]:t.kind===`human`?[`human`,`the stop where a person is asked`,``,t.every??1]:[void 0,``,``,0];if(e===void 0)continue;let c=r.get(e)??r.set(e,{name:a,unit:o,leads:new Set}).get(e);c.any=i(c.any,s),n(t)?c.halt=i(c.halt,s):(c.lead=i(c.lead,s),c.leads.add(t.then))}return r}function C(e,t){let n=[],r=e=>e.lead!==void 0&&(e.halt===void 0||e.lead<=e.halt);for(let[i,a]of e){let e=t.get(i),o=i===`human`;if(e?.any===void 0)n.push(o?`removes the stop where a person is asked`:`removes ${a.name} (${b(a.any,a.unit)})`);else if(e.any>a.any)n.push(o?`a person would be asked every ${e.any} rounds, not every ${a.any}`:`raises ${a.name} from ${a.any} to ${b(e.any,a.unit)}`);else if(a.halt!==void 0&&e.halt===void 0)n.push(`${a.name} (${b(a.halt,a.unit)}) would no longer halt the run`);else if(a.halt!==void 0&&e.halt>a.halt)n.push(`${a.name} that halts the run would rise from ${a.halt} to ${b(e.halt,a.unit)}`);else if(a.halt!==void 0&&!r(a)&&r(e))n.push(`${o?`a stop that asks a person`:a.name} of ${b(e.lead,a.unit)} that leads on to ${h([...e.leads])} would fire ${e.lead<e.halt?`before`:`as soon as`} the one of ${b(e.halt,a.unit)} that halts the run`);else if(r(e)){let t=[...e.leads].filter(e=>!a.leads.has(e));t.length>0&&n.push(`${a.name} would lead on to ${h(t)}${a.leads.size>0?`, not to ${h([...a.leads])}`:``}`)}}return n}function w(e){switch(e.kind){case`max-iterations`:return`the round cap of ${e.n}`;case`budget`:return`the budget of ${y(e.limit,e.measure)}`;case`human`:return(e.every??1)===1?`the stop where a person is asked`:`the stop where a person is asked every ${y(e.every,`rounds`)}`;case`diminishing-returns`:return`the stop on diminishing returns over ${y(e.rounds,`rounds`)}`;case`evidence-invalid`:return`the stop on evidence invalid for ${y(e.rounds,`rounds`)}`;default:return`the stop on "bar passed"`}}var T=e=>e.kind===`max-iterations`?e.n:e.kind===`budget`?e.limit:e.kind===`human`?e.every??1:e.kind===`bar-passed`?void 0:e.rounds,E=e=>e.kind===`budget`?`budget ${e.measure}`:e.kind===`diminishing-returns`?`${e.kind} ${JSON.stringify([e.metric??null,e.threshold??null])}`:e.kind,D=(e,t)=>n=>n.kind===`human`?!1:n.kind===`bar-passed`?!t&&(n.then===void 0||!e(n)):n.then!==void 0&&!e(n);function O(e){let t=e=>Number.isFinite(e)?Math.max(1,Math.ceil(e)):1;switch(e.kind){case`max-iterations`:return{sort:`cap`,from:t(e.n)};case`human`:return{sort:`person`,every:t(e.every??1)};case`budget`:return{sort:`counted`,key:`budget ${e.measure}`,size:e.limit,from:1,lasting:!0};case`diminishing-returns`:return{sort:`counted`,key:`no progress ${JSON.stringify([e.metric??null,e.threshold??null])}`,size:e.rounds,from:t(e.rounds),lasting:!1};case`evidence-invalid`:return{sort:`counted`,key:`invalid evidence`,size:e.rounds,from:t(e.rounds),lasting:!1};default:return{sort:`counted`,key:`bar passed`,size:0,from:1,lasting:!1}}}function k(e){let t=e.map(O),n=[],r=[],i=new Map,[a,o,s,c]=[!1,1/0,1/0,1/0];t.forEach((e,t)=>{n.push(a),r.push(o),e.sort===`person`?(i.has(e.every)||i.set(e.every,t),a||=e.every===1,s=Math.min(s,e.every)):e.sort===`cap`&&(o=Math.min(o,e.from),s>e.from&&(c=Math.min(c,e.from)))});let l=new Map,u=e=>{let n=l.get(e);if(!n){let r=1/0;n=t.map(t=>{let n=r;return t.sort===`counted`&&t.key===e&&(r=Math.min(r,t.size)),n}),l.set(e,n)}return n},d=new Map;return{timing:t,always:n,capAhead:r,over:c,person:i,divides:e=>{let t=d.get(e);if(t===void 0){t=1/0;for(let[n,r]of i)e%n===0&&(t=Math.min(t,r));d.set(e,t)}return t},least:u}}function A(e,t,n,r){let[i,a]=[k(e),k(n)],o=i.timing.flatMap((e,t)=>e.sort===`cap`?[{from:e.from,at:t}]:[]).sort((e,t)=>e.from-t.from),s=[];return n.forEach((n,c)=>{let l=a.timing[c];if(l.sort===`person`||!r(n)||a.always[c])return;let[u,d]=[l.from,Math.min(a.over,a.capAhead[c]-1)];if(u>d||l.sort===`counted`&&!(a.least(l.key)[c]>l.size))return;let f=[],p=1/0;for(let e of i.timing)f.push(p),e.sort===`person`&&!(a.divides(e.every)<c)&&(p=Math.min(p,e.every));let m=u;if(l.sort===`counted`){let e=i.timing.findIndex(e=>e.sort===`counted`&&e.key===l.key&&e.size<=l.size);e>=0&&(m=Math.max(m,f[e]))}for(let e of o)e.from<=m&&m<f[e.at]&&(m=f[e.at]);let h;for(let[r,o]of e.entries()){let e=i.timing[r];if(!t(o)||i.always[r]||e.sort===`person`&&i.divides(e.every)<r)continue;let[f,p]=[e.sort===`person`?e.every:e.from,Math.min(i.over,i.capAhead[r]-1)];if(f>p||e.sort===`counted`&&!(i.least(e.key)[r]>e.size)||l.sort===`counted`&&l.lasting&&!(i.least(l.key)[r]>l.size))continue;let g=(t,n)=>t<=n&&(e.sort!==`person`||Math.ceil(t/e.every)*e.every<=n),_=g(Math.max(u,f),Math.min(d,p))&&!(e.sort===`person`&&a.divides(e.every)<c)&&!(l.sort===`counted`&&!(i.least(l.key)[r]>l.size))&&!(e.sort===`counted`&&!(a.least(e.key)[c]>e.size));if(Number.isFinite(m)&&m<=d&&g(Math.max(f,m+1),p)){e.sort===`person`&&_?s.push({at:c,from:r,lead:n,halt:o,before:!1}):s.push({at:c,from:r,lead:n,halt:o,before:!0,...e.sort===`person`?{again:m>=e.every}:{}});return}_&&(h??=r)}h!==void 0&&s.push({at:c,from:h,lead:n,halt:e[h],before:!1})}),s}var j=e=>e.edge??`${e.loop} → ${e.to}`;function M(e,t,n){let r=new Set(t.back),i=new Set(e.nodes.filter(e=>e.kind===`human-gate`).map(e=>e.id)),o=a(e).filter(e=>e.from!==e.to&&(e.edge===void 0||!r.has(e.edge))&&(!e.person||n.has(j(e)))),s=n=>n.edge===void 0?[j(n)]:e.loops.filter(e=>e.id!==t.id&&e.back.includes(n.edge)).map(e=>e.id),c=(e,t)=>{let n=new Set(e),r=[...n];for(let e=r.pop();e!==void 0;e=r.pop())for(let i of t(e))n.has(i)||r.push((n.add(i),i));return n},l=o.filter(e=>e.loop===t.id&&t.members.includes(e.to)&&!i.has(e.to)),u=new Map(l.map(e=>[j(e),e])),d=new Map;for(let e of t.members){let t=c([e],e=>o.filter(t=>t.from===e).map(e=>e.to)),n=c([e],e=>o.filter(t=>t.to===e).map(e=>e.from)),r=new Set(l.map(j));for(let e of o)if(t.has(e.from)&&n.has(e.to)){u.set(j(e),e);for(let t of s(e))r.add(t)}d.set(e,r)}return{ways:u,closers:d}}function N(e,t){let n=[],i=[],o=new Set(t.nodes.map(e=>e.id)),s=new Set(e.nodes.map(e=>e.id)),c=a(e),u=a(t),d=new Set(t.nodes.filter(e=>[...l(t,u.filter(t=>t.from===e.id&&t.to!==e.id).map(e=>e.to))].includes(e.id)||u.some(t=>t.edge!==void 0&&t.from===e.id&&t.to===e.id)).map(e=>e.id)),f=new Map(t.edges.map(e=>[e.id,e])),m=new Map(t.loops.map(e=>[e.id,e])),g=new Map(e.loops.map(e=>[e.id,e])),v=new Map(e.edges.map(e=>[e.id,e])),y=new Set(e.nodes.filter(e=>r(e)&&t.nodes.some(t=>t.id===e.id&&r(t))).map(e=>e.id));for(let r of e.loops){if(!(r.stops.some(_)||r.bar!==void 0))continue;let a=m.get(r.id);a||n.push({why:`removes a loop with its stops and its bar`,at:[`loop:${r.id}`]});let l=[...new Set(r.stops.flatMap(e=>e.then===void 0?[]:[`node:${e.then}.kind`,`node:${e.then}.outcome`,`node:${e.then}`]))],b=S(e,[r]);if(a){for(let e of C(b,S(t,[a])))n.push({why:e,at:[`loop:${r.id}.stops`,...l]});let[o,s]=[x(e),x(t)],c=e=>e.kind===`human`||_(e)&&o(e),u=(e,t)=>e.members.some(e=>(t?.members.includes(e)??!1)&&y.has(e)),d=e=>e.kind===`human`?w(e):`${w(e)} that halts the run`,f=e=>JSON.stringify(e),[p,m]=[new Map,new Map];r.stops.forEach((e,t)=>void(p.has(f(e))||p.set(f(e),t))),a.stops.forEach((e,t)=>void m.set(f(e),t));let h=new Map;for(let e of r.stops)m.has(f(e))||(h.get(E(e))??h.set(E(e),[]).get(E(e))).push(e);let v=a.stops.filter(e=>e.kind===`human`&&!p.has(f(e))),O=[...new Set(a.stops.flatMap(e=>e.kind===`human`?[e.every??1]:[]))],k=[`loop:${r.id}.stops`,...l];for(let{at:e,from:t,lead:n,halt:l,before:g,again:_}of A(r.stops,c,a.stops,D(s,u(a,r)))){let r=w(n),a=n.then===void 0?`${r}, which follows the loop's pass edges,`:`${r} that leads on to "${n.then}"`,s=g?l.kind===`human`?_?`between two askings of ${w(l)}, after the person has said go on`:`before ${w(l)} first asks`:`before ${d(l)}`:`on the same pass as ${d(l)}, where it would be the one obeyed`,c=p.get(f(n)),u=h.get(E(n))??[],y=u.find(e=>e.then===n.then&&T(e)!==T(n)),b=n.then===void 0?void 0:u.find(e=>T(e)===T(n)&&e.then!==n.then),x=l.kind===`human`?l.every??1:1,S=c!==void 0&&l.kind===`human`&&!m.has(f(l))&&!O.some(e=>x%e===0)?v.find(e=>e.then===l.then):void 0,C=c===void 0?y?`${a} would go from ${T(y)} to ${T(n)}, and could fire ${s}`:b?`${r} would lead on to "${n.then}"${b.then===void 0?``:`, not to "${b.then}"`}${o(b)?`, where it halted the run`:``}${b===l?``:`, and could fire ${s}`}`:`${a} would come into the loop, and could fire ${s}`:S?`a person would be asked every ${S.every??1} rounds where it was every ${x}: on pass ${x} nobody would be asked, and ${a} could fire on a pass where a person was asked`:!g&&c>t&&(m.get(f(l))??-1)>e?`${a} would be moved ahead of ${d(l)}, and could fire on the same pass`:`${a} could fire ${s}, as it could not before`;i.push({why:C,at:k})}let j=r.stops.find(c);for(let e of j?t.loops:[]){let t=e=>e?.back.some(e=>r.back.includes(e)||a.back.includes(e))??!1;if(e.id===r.id||!t(e))continue;let n=g.get(e.id),o=new Set(t(n)?n.stops.map(f):[]),c=t=>D(s,u(e,t.then===void 0?n??r:n))(t);for(let t of e.stops){if(!c(t)||o.has(f(t)))continue;let a=`${w(t)} among its stops, which ${t.then===void 0?`follows that loop's pass edges`:`leads on to "${t.then}"`},`;i.push({why:`the loop "${e.id}" would count rounds that "${r.id}" counts, and ${a} could fire before ${d(j)}`,at:n?[`loop:${e.id}.stops`,`loop:${e.id}.back`]:[`loop:${e.id}`]})}}r.bar&&a.bar?.acceptance!==r.bar.acceptance&&n.push({why:a.bar?`changes the bar's acceptance`:`removes the loop's bar`,at:[`loop:${r.id}.bar`]})}for(let e of r.back){let i=v.get(e);if(!i)continue;let o=f.has(e)?[f.get(e)]:t.edges.filter(e=>e.from===i.from&&e.to===i.to);for(let e of o){if(a?.back.includes(e.id))continue;let i=t.loops.filter(t=>t.back.includes(e.id));n.push({why:i.length===0?`the rounds that "${e.id}" starts would no longer be counted by any loop`:`the rounds that "${e.id}" starts would be counted by ${h(i.map(e=>e.id))}, not against the stops of "${r.id}"`,at:[`loop:${r.id}.back`,`loop:${r.id}`,...i.flatMap(e=>[`loop:${e.id}`,`loop:${e.id}.back`])]})}}let O=new Set(r.members);for(let i of t.loops){if(i.id===r.id)continue;let t=new Set(e.loops.find(e=>e.id===i.id)?.back??[]);for(let e of i.back){let o=f.get(e),s=v.get(e);!o||t.has(e)&&s?.from===o.from&&s.to===o.to||a?.back.includes(e)||!O.has(o.from)||!O.has(o.to)||n.push({why:`a round between "${o.from}" and "${o.to}", which the loop "${r.id}" bounds, would be counted by "${i.id}" and not against its stops`,at:[`loop:${i.id}`,`loop:${i.id}.back`,`edge:${e}`,`edge:${e}.from`,`edge:${e}.to`]})}}let k=a?r.members.filter(e=>o.has(e)&&!a.members.includes(e)):[];a&&r.members.length>0&&!r.members.some(e=>a.members.includes(e))?n.push({why:`the loop "${r.id}" would keep its stops and bound none of the nodes it did`,at:[`loop:${r.id}.members`,`loop:${r.id}.back`]}):k.length>0&&n.push({why:`the loop "${r.id}" would no longer bound ${h(k)}, which ${k.length===1?`is`:`are`} still in the graph`,at:[`loop:${r.id}.members`]});let N=a?r.members.filter(e=>!o.has(e)):[],P=N.length>0?t.nodes.filter(e=>!s.has(e.id)&&!a.members.includes(e.id)&&e.kind!==`stop`&&d.has(e.id)).map(e=>e.id):[];if(P.length>0&&n.push({why:`removes ${h(N)}, which the loop "${r.id}" bounded, while ${h(P)} would come in on a round it does not count: it may be the same step under another name`,at:[...N.map(e=>`node:${e}`),`loop:${r.id}.members`]}),a&&a.stops.some(e=>e.kind===`budget`&&e.measure===`dispatches`)){let e=new Set(t.loops.filter(e=>e.id!==r.id).flatMap(e=>e.back)),i=u.filter(t=>t.edge!==void 0&&!e.has(t.edge)),o=e=>t=>i.filter(n=>e(n)[0]===t).map(t=>e(t)[1]),c=(e,t)=>{let n=new Set(e),r=[...n];for(let e=r.pop();e!==void 0;e=r.pop())for(let i of t(e))n.has(i)||r.push((n.add(i),i));return n},l=c(a.members,o(e=>[e.from,e.to])),d=c(a.members,o(e=>[e.to,e.from])),f=t.nodes.filter(e=>!s.has(e.id)&&(e.kind===`agent`||e.kind===`check`)&&!a.members.includes(e.id)&&l.has(e.id)&&d.has(e.id)).map(e=>e.id);f.length>0&&n.push({why:`${h(f)} would work on the rounds of the loop "${r.id}" and not be among its members: its budget of dispatches would not count ${f.length===1?`it`:`them`}`,at:[...f.map(e=>`node:${e}`),`loop:${r.id}.members`]})}if(a){let i=new Set(c.filter(e=>e.person).map(j)),s=M(e,r,i),l=[...new Set([...r.members.filter(e=>o.has(e)),...a.members])],u=0,d=M(t,{id:r.id,members:l,back:a.back},i),g=r.members.some(e=>[...d.closers.get(e)??[]].some(t=>!s.closers.get(e)?.has(t))),_=e=>e.edge!==void 0&&v.has(e.edge)&&(v.get(e.edge).from!==e.from||v.get(e.edge).to!==e.to),y=g?[...d.ways].filter(([e,t])=>!s.ways.has(e)||_(t)):[];for(let[,i]of y){let a=i.edge===void 0?void 0:v.get(i.edge),o=i.edge===void 0?[]:t.loops.filter(e=>e.back.includes(i.edge)),s=i.edge===void 0?e.loops.find(e=>e.id===i.loop)?.stops:void 0,c=i.edge===void 0?p(s,m.get(i.loop)?.stops)?[]:[`loop:${i.loop}.stops`,`loop:${i.loop}`]:a===void 0?[`edge:${i.edge}`]:[`from`,`to`,`when`].filter(e=>!p(a[e],f.get(i.edge)[e])).map(e=>`edge:${i.edge}.${e}`);c.length!==0&&(u+=1,n.push({why:i.edge===void 0?`a stop of the loop "${i.loop}" would lead back to "${i.to}": a way round the nodes of "${r.id}" that its stops do not count`:`"${i.edge}" (${i.from} → ${i.to}) would make a way round the nodes of "${r.id}" that its stops do not count${o.length>0?`: ${h(o.map(e=>e.id))} would count it, and each time round "${r.id}" starts afresh`:``}`,at:[...c,...o.flatMap(e=>[`loop:${e.id}`,`loop:${e.id}.back`])]}))}g&&u===0&&n.push({why:`there would be a way round the nodes of "${r.id}" that its stops do not count`,at:[`loop:${r.id}.members`,`loop:${r.id}.back`]})}}return{losses:n,fired:i}}function P(e,n){let a=[],o=new Map(n.nodes.map(e=>[e.id,e])),s=new Map(n.edges.map(e=>[e.id,e])),c=new Map(e.edges.map(e=>[e.id,e])),l=new Map(e.nodes.map(e=>[e.id,e]));for(let i of e.nodes){let c=o.get(i.id);if(i.kind===`human-gate`){if(!c)a.push({why:`removes a human gate`,at:[`node:${i.id}`]});else if(c.kind!==`human-gate`)a.push({why:`a human gate becomes another kind of node`,at:[`node:${i.id}.kind`]});else{let e=(i.options??[]).filter(e=>!(c.options??[]).includes(e));e.length>0&&a.push({why:`the gate would no longer offer ${h(e)}`,at:[`node:${i.id}.options`],gain:!0})}}if(g(i).length>0){let e=g(i).filter(e=>!g(c).includes(e));c?e.length>0&&a.push({why:`removes the irreversible marker ${h(e)}`,at:[`node:${i.id}.irreversible`,`node:${i.id}.kind`]}):a.push({why:`removes a node marked irreversible (${g(i).join(`, `)}): what takes its place carries no such mark unless it is given one`,at:[`node:${i.id}`],gain:!0})}if(i.kind===`stop`&&i.outcome===`halt`&&c?.kind===`stop`&&F(c)&&a.push({why:`the stop "${i.id}" would end in success where it halted: what led there to stop the run would now end it well`,at:[`node:${i.id}.outcome`]}),i.kind===`check`){let e=n.nodes.filter(e=>e.kind===`check`&&l.get(e.id)?.kind!==`check`),t=e.map(e=>`"${e.id}": ${e.check.run===void 0?`of kind "${e.check.kind}"`:`runs ${JSON.stringify(e.check.run)}`}, passes on ${JSON.stringify(e.check.pass)}${e.check.threshold===void 0?``:`, threshold ${e.check.threshold}`}`).join(`, and `),r=`while ${e.length===1?`a check`:`checks`} the graph has not ${e.length===1?`comes`:`come`} in (${t}): if that is this check under another id, allowing this`;if(!c&&e.length>0)a.push({why:`removes a check, ${r} name allows every change made to it and every way round it`,at:[`node:${i.id}`],swap:`removes a check`});else if(!c)a.push({why:`removes a check`,at:[`node:${i.id}`]});else if(c.kind!==`check`&&e.length>0)a.push({why:`a check becomes another kind of node, ${r} change allows every change made to it and every way round it`,at:[`node:${i.id}.kind`,`node:${i.id}.check`],swap:`a check becomes another kind of node`});else if(c.kind!==`check`)a.push({why:`a check becomes another kind of node`,at:[`node:${i.id}.kind`,`node:${i.id}.check`]});else{let[e,t]=[i.check,c.check],n=[...new Set([...Object.keys(e),...Object.keys(t)])].filter(n=>!p(e[n],t[n]));n.length>0&&a.push({why:`changes the check's definition (${n.join(`, `)}): what it runs and what counts as a pass may be tightened and not loosened, and a program cannot tell which this is`,at:[`node:${i.id}.check`]})}}if(r(i)){c?r(c)||a.push({why:c.kind===`agent`?`a critic is given another role`:`a critic becomes another kind of node`,at:[`node:${i.id}.role`,`node:${i.id}.kind`]}):a.push({why:`removes a critic`,at:[`node:${i.id}`]});let u=e=>e.edges.filter(e=>e.to===i.id),d=new Set(e.edges.map(e=>e.id));for(let t of c?u(e):[]){let e=s.get(t.id),r=new Set(n.edges.filter(e=>e.from===t.from&&!l.has(e.to)).map(e=>e.to)),c=e&&e.from===t.from&&e.to===i.id?[e]:u(n).filter(e=>!d.has(e.id)&&(!o.has(t.from)||e.from===t.from||r.has(e.from))),f=new Set(c.flatMap(e=>e.evidence??[])),p=(t.evidence??[]).filter(e=>!f.has(e));p.length>0&&a.push({why:`the critic would no longer be handed ${h(p)} by "${t.from}"`,at:[`edge:${t.id}.evidence`,`edge:${t.id}.to`,`edge:${t.id}.from`,`edge:${t.id}`,`node:${t.from}`]})}for(let r of u(n)){let n=e.edges.find(e=>e.id===r.id);t(r)===`shared`&&!(n&&n.to===i.id&&t(n)===`shared`)&&a.push({why:`the critic would share its builder's context`,at:[`edge:${r.id}.isolation`,`edge:${r.id}.to`,`edge:${r.id}`]})}}}for(let t of e.edges){let e=s.get(t.id);if(t.approval===!0){e?e.approval!==!0&&a.push({why:`removes a person's approval from the edge`,at:[`edge:${t.id}.approval`]}):a.push({why:`removes an edge that needs a person's approval`,at:[`edge:${t.id}`,`node:${t.from}`,`node:${t.to}`]});for(let r of e?n.edges:[]){if(r.id===t.id||r.from!==e.from||r.to!==e.to||r.approval===!0)continue;let n=c.get(r.id),i=n===void 0?[`edge:${r.id}`]:[`from`,`to`,`approval`].filter(e=>!p(n[e],r[e])).map(e=>`edge:${r.id}.${e}`);i.length>0&&a.push({why:`"${r.id}" would lead from "${r.from}" to "${r.to}" beside "${t.id}", which needs a person's approval, and need none`,at:i})}}let u=l.get(t.from);u?.kind===`human-gate`&&o.get(t.from)?.kind===`human-gate`&&!n.edges.some(e=>e.from===t.from&&i(e)===i(t))&&a.push({why:`"${i(t)}" at the human gate "${t.from}" would lead nowhere`,at:[`edge:${t.id}`,`edge:${t.id}.from`,`edge:${t.id}.when`,`node:${t.to}`],gain:!0}),e&&i(e)!==i(t)&&(t.approval===!0||u?.kind===`human-gate`?a.push({why:`changes what a person's answer leads to`,at:[`edge:${t.id}.when`]}):u&&r(u)&&a.push({why:`changes what the critic's verdict leads to`,at:[`edge:${t.id}.when`]}))}let u=new Map((n.policies??[]).map(e=>[e.id,e]));for(let t of e.policies??[]){let e=t.kind===`critic-isolation`?`removes critic isolation`:t.kind===`no-self-grading`?`lets a node grade its own work`:t.kind===`no-live-graph-rewrite`?`lets a run rewrite the graph where it could only propose`:void 0,n=u.get(t.id),r=n?[`kind`,`scope`,`params`].filter(e=>!p(n[e],t[e])):[];e===void 0||n&&r.length===0||a.push({why:e,at:n?r.map(e=>`policy:${t.id}.${e}`):[`policy:${t.id}`]})}return a}var F=e=>e.kind===`stop`&&(e.outcome??`success`)===`success`;function I(e,t,n){let r=new Map;for(let e of t)s(e,n)||(r.get(e.to)??r.set(e.to,[]).get(e.to)).push(e.from);let i=new Set(e.nodes.filter(F).map(e=>e.id)),a=[...i];for(let e=a.pop();e!==void 0;e=a.pop())for(let t of r.get(e)??[])i.has(t)||(i.add(t),a.push(t));return i}function L(e,t){let n=[],r=new Set(e.nodes.map(e=>e.id)),o=new Set(t.nodes.map(e=>e.id)),m=u(t,`every`);for(let e of t.nodes)!r.has(e.id)&&g(e).length>0&&m.has(e.id)&&n.push({why:`adds an irreversible step that a run reaches without a person`,at:[`node:${e.id}`]});let _=new Map(e.edges.map(e=>[e.id,e])),v=new Map(t.edges.map(e=>[e.id,e])),y=new Map(e.loops.map(e=>[e.id,e])),b=new Map(t.loops.map(e=>[e.id,e])),x=new Set(c(t)),S=new Set(e.loops.flatMap(e=>e.back)),C=a(t),w=a(e),T=new Set,E=new Set,D=new Map,O=t=>D.get(t)??D.set(t,l(e,[t])).get(t),k=[],A=(e,t,r)=>{let i=`${e!==`every`&&`critic`in e?e.critic:``}\n${t}\n${r.at.join(` `)}`;E.has(i)||(E.add(i),n.push(r))};for(let a of d(e,t)){let c=u(e,a),d=u(t,a),m=`that does not pass ${f(a)}`,g=`${a!==`every`&&`critic`in a?a.critic:``}\n`,D=e.nodes.filter(e=>!o.has(e.id)&&!c.has(e.id)&&!T.has(g+e.id)),j=t.nodes.filter(e=>!r.has(e.id)&&d.has(e.id));if(j.length>0)for(let e of D)T.add(g+e.id),n.push({why:`removes "${e.id}", which a run reached only by passing ${f(a)}, while ${h(j.map(e=>e.id))} would come in with no such need: it may be the same step under another name`,at:[`node:${e.id}`]});let M=0,N=e=>{if(e.edge!==void 0){let t=_.get(e.edge);if(!t)return[`edge:${e.edge}`];let n=[`from`,`to`,`approval`,`when`].filter(n=>!p(t[n],v.get(e.edge)[n]));return n.length>0?n.map(t=>`edge:${e.edge}.${t}`):w.some(t=>t.edge===e.edge&&s(t,a))?[`node:${e.from}.kind`,`node:${e.from}.role`]:void 0}let t=y.get(e.loop);if(!t)return[`loop:${e.loop}`];let n=[`stops`,`members`].filter(n=>!p(t[n],b.get(e.loop)[n]));return n.length>0?n.map(t=>`loop:${e.loop}.${t}`):void 0},P=(e,t)=>{M+=1,A(a,e,t)},L=new Set(t.nodes.filter(e=>r.has(e.id)&&!c.has(e.id)&&d.has(e.id)).map(e=>e.id));for(let e of L.size>0?C:[]){if(s(e,a)||!d.has(e.from)||!L.has(e.to))continue;let t=N(e);t&&(e.edge===void 0?P(e.to,{why:`a stop of the loop would lead on to "${e.to}", a way ${m}`,at:t}):P(e.to,{why:`${_.has(e.edge)?`opens`:`adds`} a way into "${e.to}" ${m}`,at:t}))}let R=a===`every`||!(`when`in a)||a.when===void 0,z=a===`every`?void 0:`gate`in a?a.gate:`critic`in a?a.critic:void 0;for(let n of R?t.nodes:[]){if(!r.has(n.id)||n.id===z)continue;let i=l(e,[n.id],a),o=l(t,[n.id],a),c=new Set([...o].filter(e=>r.has(e)&&!i.has(e)&&O(n.id).has(e)));for(let e of c.size>0?C:[]){if(e.from===e.to||s(e,a)||!o.has(e.from)||!c.has(e.to))continue;let t=N(e);if(!t)continue;let n=e.edge===void 0?`a stop of the loop would lead on from "${e.from}" to "${e.to}", a way ${m}`:`${_.has(e.edge)?`opens`:`adds`} a way from "${e.from}" to "${e.to}" ${m}`;k.push([a,e.to,{why:n,at:t}])}}for(let n of L){if(!x.has(n))continue;let r=`nothing would lead to "${n}", so a run would start there, where every way to it passed ${f(a)}`;for(let i of e.edges){if(i.to!==n||S.has(i.id))continue;let e=v.get(i.id);e&&e.to!==n?P(`start ${n}`,{why:r,at:[`edge:${i.id}.to`]}):e?P(`start ${n}`,{why:r,at:t.loops.filter(e=>e.back.includes(i.id)).flatMap(e=>[`loop:${e.id}.back`,`loop:${e.id}`])}):P(`start ${n}`,{why:r,at:[o.has(i.from)?`edge:${i.id}`:`node:${i.from}`]})}}let B=typeof a==`object`&&`critic`in a&&a.when!==void 0?new Set(e.edges.filter(e=>e.from===a.critic).map(i)):new Set,V=B.size>1&&!B.has(`pass`),H=R||V||typeof a==`object`&&`critic`in a&&a.when===`pass`,U=H?I(e,w,a):new Set,W=H?I(t,C,a):new Set,G=new Set(t.nodes.filter(e=>e.kind!==`stop`&&r.has(e.id)&&!U.has(e.id)&&W.has(e.id)).map(e=>e.id));for(let e of G.size>0?C:[]){if(s(e,a)||!G.has(e.from)||!W.has(e.to))continue;let t=N(e),n=`${a!==`every`&&`critic`in a?a.critic:``}\n`;t&&![...E].some(e=>e.startsWith(n)&&e.endsWith(`\n${t.join(` `)}`))?P(`ends ${e.to}`,{why:`adds a way from "${e.from}" to end in success ${m}`,at:t}):t&&(M+=1)}let K=new Set(e.nodes.filter(F).map(e=>e.id));for(let e of G.size>0?t.nodes:[])F(e)&&r.has(e.id)&&!K.has(e.id)&&W.has(e.id)&&P(`ends ${e.id}`,{why:`a run could end in success at "${e.id}", a way ${m}`,at:[`node:${e.id}.outcome`,`node:${e.id}.kind`]});M===0&&(L.size>0||G.size>0)&&n.push({why:L.size>0?`a run would reach ${h([...L])} by a way ${m}`:`a run could end in success from ${h([...G])} by a way ${m}`,at:[]})}return{losses:n,later:k.map(([,,e])=>e)}}function R(e,t){let n=[],r=new Set(a(e).filter(e=>e.person).map(j)),i=new Set(a(t).filter(e=>e.person).map(j)),o=new Set(t.nodes.map(e=>e.id)),s=new Set(t.nodes.filter(e=>e.kind===`human-gate`).map(e=>e.id));for(let a of e.loops){let c=t.loops.find(e=>e.id===a.id);if(!c||!(a.stops.some(_)||a.bar!==void 0))continue;let l={id:a.id,members:[...new Set([...a.members.filter(e=>o.has(e)),...c.members])],back:c.back},u=M(e,a,r),d=[...M(t,l,i).ways].filter(([e,t])=>t.person&&!r.has(e)&&!u.ways.has(e));if(d.length===0)continue;let f=[...new Set(d.map(([,e])=>e.edge===void 0?`the stop where a person is asked, which continues at "${e.to}"`:s.has(e.from)?`"${e.when}" at the human gate "${e.from}" (${e.edge})`:`the approval asked on "${e.edge}"`))],p=[...S(t,[c])].filter(([e])=>e!==`human`).map(([,e])=>`${e.name} (${b(e.halt??e.any,e.unit)})`);n.push(`the loop "${a.id}": ${p.length>0?p.join(` and `):`its stops`} would count the rounds between two of a person's decisions, and no longer the whole run. A way round its nodes that they do not count is opened each time by ${f.join(`, and by `)}`)}return n}function z(e,t){let n=[],r=`a program cannot tell which way this goes, so it is held either way, and an honest change (a gate put behind the check's pass, more evidence handed to a builder) costs one --allow too, the price of a rule a program can apply`,a=new Set(e.nodes.filter(e=>e.kind===`check`&&t.nodes.some(t=>t.id===e.id&&t.kind===`check`)).map(e=>e.id)),o=new Set(t.nodes.map(e=>e.id)),s=new Map(e.edges.map(e=>[e.id,e])),c=new Map(t.edges.map(e=>[e.id,e]));for(let t of e.edges){if(!a.has(t.from))continue;let e=c.get(t.id);if(!e){n.push({why:`removes "${t.id}", an edge that leaves the check "${t.from}": ${r}`,at:[o.has(t.to)?`edge:${t.id}`:`node:${t.to}`],either:!0});continue}for(let a of new Set([...Object.keys(t),...Object.keys(e)])){let o=a===`when`?i(t)!==i(e):!p(t[a],e[a]);a!==`id`&&o&&n.push({why:`changes "${t.id}", an edge that leaves the check "${t.from}" (${a}): ${r}`,at:[`edge:${t.id}.${a}`],either:!0})}}for(let e of t.edges){if(!a.has(e.from))continue;let t=s.get(e.id);t?t.from!==e.from&&n.push({why:`moves "${e.id}" to leave the check "${e.from}": ${r}`,at:[`edge:${e.id}.from`],either:!0}):n.push({why:`adds "${e.id}", an edge that leaves the check "${e.from}": ${r}`,at:[`edge:${e.id}`],either:!0})}return n}function B(e,t){let n=[],i=new Map(e.nodes.map(e=>[e.id,e])),a=new Map(e.loops.map(e=>[e.id,e])),o=e=>e?.stops.some(e=>e.kind===`bar-passed`)??!1;for(let e of t.loops){let s=a.get(e.id),c=e=>i.get(e),l=e.members.filter(e=>c(e)?.kind===`check`&&t.nodes.some(t=>t.id===e&&t.kind===`check`)),u=s?.members.some(e=>c(e)!==void 0&&r(c(e))&&t.nodes.some(t=>t.id===e&&r(t)))??!1;if(l.length===0||u)continue;let d=s?`the loop "${e.id}", which the check ${h(l)} judges with no critic`:`the new loop "${e.id}", around the check ${h(l)}`;e.bar!==void 0&&s?.bar===void 0&&n.push({why:`gives ${d}, a bar of its own: the lead would stop on the bar's words, a way out that does not pass the check`,at:s?[`loop:${e.id}.bar`]:[`loop:${e.id}`]}),o(e)&&!o(s)&&n.push({why:`adds a stop on "bar passed" to ${d}: a way out that does not pass the check`,at:s?[`loop:${e.id}.stops`]:[`loop:${e.id}`]})}return n}function V(e,t){let n=new Set,i=(e,t)=>e.nodes.some(e=>e.id===t&&r(e)),a=new Map(t.edges.map(e=>[e.id,e]));for(let r of e.edges){let o=a.get(r.id);if(!o)continue;r.approval!==!0&&o.approval===!0&&n.add(`edge:${r.id}.approval`);let[s,c]=[r.evidence??[],o.evidence??[]];o.to===r.to&&i(e,r.to)&&i(t,r.to)&&s.every(e=>c.includes(e))&&n.add(`edge:${r.id}.evidence`)}return n}function H(e,t){let n=new Set,r=new Set(e.nodes.filter(e=>e.kind===`stop`&&e.outcome===`halt`).map(e=>e.id)),i=e=>e.kind===`bar-passed`||e.then!==void 0&&!r.has(e.then);for(let r of e.loops){let e=t.loops.find(e=>e.id===r.id);if(!e)continue;let a=new Map;e.stops.forEach((e,t)=>void(a.get(JSON.stringify(e))??a.set(JSON.stringify(e),[]).get(JSON.stringify(e))).push(t));let o=new Set(a.keys()),s=r.stops.map(e=>a.get(JSON.stringify(e))?.shift()),c=1/0,l=!1;for(let e=r.stops.length-1;e>=0;--e){let t=s[e];l||=i(r.stops[e])&&(t===void 0?!o.has(JSON.stringify(r.stops[e])):t>c),t!==void 0&&(c=Math.min(c,t))}l&&n.add(`loop:${r.id}.stops`)}return n}function U(e,t){let n=H(e,t);return n.size===0?W(e,t):W(e,t).map(e=>e.at.some(e=>n.has(e))?{...e,gain:!0}:e)}function W(e,t){let n=[...G(e,t),...B(e,t)],r=z(e,t);if(r.length===0)return n;let i=new Set(n.flatMap(e=>e.at)),a=V(e,t);return[...n,...r.filter(e=>!(a.has(e.at[0])&&!i.has(e.at[0])))]}function G(e,t){let n=new Set,r=L(e,t),i=N(e,t),a=P(e,t),o=[...a,...i.losses,...r.losses],s=new Set(o.flatMap(e=>e.at)),c=new Set,l=r.later.filter(e=>!e.at.some(e=>s.has(e))&&!c.has(e.at.join(` `))&&c.add(e.at.join(` `)));return[...a,...i.losses,...i.fired,...r.losses,...l].filter(e=>{let t=`${e.why}\n${e.at.join(` `)}`;return!n.has(t)&&(n.add(t),!0)})}var K=e=>JSON.stringify(e),q=[`fixed`,`propose`,`adaptive`],J=new Set([`grooph`,`id`,`name`,`version`,`lineage`,`notes`,`layout`,`nodes`,`edges`,`loops`,`policies`,`groups`]);function Y(e,t){let n=[],r=[[`node`,e.nodes,t.nodes],[`edge`,e.edges,t.edges],[`loop`,e.loops,t.loops],[`policy`,e.policies??[],t.policies??[]],[`group`,e.groups??[],t.groups??[]]];for(let[e,t,i]of r){let r=new Map(i.map(e=>[e.id,e])),a=new Set(t.map(e=>e.id));for(let i of t){let t=r.get(i.id);if(!t){n.push({name:`${e}:${i.id}`,kind:`remove`});continue}for(let r of new Set([...Object.keys(i),...Object.keys(t)]))r!==`id`&&K(i[r])!==K(t[r])&&n.push({name:`${e}:${i.id}.${r}`,kind:`change`})}for(let t of i)a.has(t.id)||n.push({name:`${e}:${t.id}`,kind:`add`})}let i=e,a=t;for(let e of new Set([...Object.keys(i),...Object.keys(a)]))!J.has(e)&&K(i[e])!==K(a[e])&&n.push({name:`graph:${e}`,kind:`change`});return n}function ee(e,t){let[r,i]=[n(e),n(t)];return q.indexOf(i)<=q.indexOf(r)?[]:[{why:`the adaptation level would go from "${r}" to "${i}": the lead may change more of the graph during a run`,at:K(e.adaptation)===K(t.adaptation)?[]:[`graph:adaptation`]}]}var X=(e,t)=>[...U(e,t),...ee(e,t)];function Z(e,t,n={}){let r=Y(e,t),i=new Set(r.map(e=>e.name)),a=(e,t,n)=>{for(let a of e){if(t!==`loosens`&&a.either)continue;let e=new Set(a.at.filter(e=>i.has(e)));(e.size!==0||n)&&(r=r.map(n=>e.size>0&&!e.has(n.name)||m(n[t],a.why)||t!==`loosens`&&(m(n.loosens,a.why)||n.kind===`add`&&n.name.startsWith(`loop:`))?n:{...n,[t]:n[t]===void 0?a.why:`${n[t]}; ${a.why}`}))}},o=X(e,t);a(o,`loosens`,!0);let s=X(t,e),c=o.some(e=>e.swap);c?a(s.map(e=>e.swap?{...e,why:e.swap}:e),`unjudged`,!1):(a(s.filter(e=>!e.gain),`tightens`,!1),a(s.filter(e=>e.gain),`unjudged`,!1)),r.sort((e,t)=>Number(t.loosens!==void 0)-Number(e.loosens!==void 0));let l=new Set(n.allow??[]);return{changes:r,refused:r.filter(e=>e.loosens!==void 0&&!l.has(e.name)),unknown:[...l].filter(e=>!i.has(e)),notices:R(e,t),swapped:c}}function te(e,t,n){let r=e=>/^[A-Za-z0-9_.:/@=+-]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`;return[`grooph`,`adopt`,r(e),...n===void 0?[]:[`--into`,r(n)],`--write`,...t.flatMap(e=>[`--allow`,r(e)])].join(` `)}var Q=e(),ne=e=>()=>void navigator.clipboard?.writeText(e).catch(()=>void 0),$=e=>e?.scrollIntoView({block:`start`});function re(e,t,n){if(!n)return(0,Q.jsx)(`p`,{className:`field-hint`,"data-brakes":`not-compared`,ref:$,children:`Its brakes were not compared with the graph's: the copy is not a valid graph. Open the copy to see why before you use it.`});let r=Z(e,t);if(r.refused.length+r.notices.length===0)return null;let i=r.notices.map(e=>(0,Q.jsxs)(`p`,{"data-brakes":`note`,children:[`Note: `,e]},e));return r.refused.length===0?(0,Q.jsx)(`div`,{className:`field-hint`,"data-brakes":`said`,ref:$,children:i}):(0,Q.jsxs)(`div`,{className:`refusal-hint`,"data-brakes":`proposed`,ref:$,children:[(0,Q.jsxs)(`p`,{children:[(0,Q.jsx)(`strong`,{children:`This copy loosens a brake the graph has.`}),` It is the run's working copy with this proposal applied; either may have done it, and it is yours to allow or not: read each line before you use the copy.`]}),(0,Q.jsx)(`ul`,{className:`brakes-list`,"data-brakes":`loosens`,children:r.refused.map(e=>(0,Q.jsxs)(`li`,{"data-change-name":e.name,children:[(0,Q.jsx)(`span`,{className:`mono`,children:e.name}),` `,e.loosens]},e.name))}),i]})}function ie(e,t,n){let r=Z(e,t),i=r.changes.filter(e=>e.tightens!==void 0&&e.loosens===void 0),a=r.changes.filter(e=>e.unjudged!==void 0&&e.loosens===void 0),o=te(`.grooph/${e.id}/runs/${n}`,r.refused.map(e=>e.name)),s=(0,Q.jsxs)(Q.Fragment,{children:[i.length>0?(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(`p`,{children:r.refused.length>0?`It also tightens a brake:`:`It tightens a brake:`}),(0,Q.jsx)(`ul`,{className:`brakes-list`,"data-brakes":`tightens`,children:i.map(e=>(0,Q.jsxs)(`li`,{"data-change-name":e.name,children:[(0,Q.jsx)(`span`,{className:`mono`,children:e.name}),` undoing it: `,e.tightens]},e.name))})]}):null,a.length>0?(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(`p`,{children:r.swapped?`With a check removed in this copy, no change is called a tightening. If the check that comes in is the same one under another id, these may be built around it:`:`An answer a gate did not give, a step marked irreversible that the graph did not have, or a stop of a loop that leads on, where it is new, changed or put ahead, lets a person or a run do what it could not before. A change that brings one is named here and not called a tightening, whatever else it does:`}),(0,Q.jsx)(`ul`,{className:`brakes-list`,"data-brakes":`unjudged`,children:a.map(e=>(0,Q.jsxs)(`li`,{"data-change-name":e.name,children:[(0,Q.jsx)(`span`,{className:`mono`,children:e.name}),` undoing it: `,e.unjudged]},e.name))})]}):null,r.notices.map(e=>(0,Q.jsxs)(`p`,{"data-brakes":`note`,children:[`Note: `,e]},e))]});return r.refused.length===0?{ok:!0,view:i.length+a.length+r.notices.length>0?(0,Q.jsx)(`div`,{className:`field-hint`,"data-brakes":`said`,children:s}):null}:{ok:!1,view:(0,Q.jsxs)(`div`,{className:`refusal`,role:`alert`,"data-brakes":`refused`,children:[(0,Q.jsxs)(`p`,{children:[(0,Q.jsx)(`strong`,{children:`Not adopted: this working copy loosens a brake.`}),` A run may tighten a brake and never loosen one. Nothing was saved.`]}),(0,Q.jsx)(`ul`,{className:`brakes-list`,"data-brakes":`loosens`,children:r.refused.map(e=>(0,Q.jsxs)(`li`,{"data-change-name":e.name,children:[(0,Q.jsx)(`span`,{className:`mono`,children:e.name}),` `,e.loosens]},e.name))}),(0,Q.jsx)(`p`,{children:`To adopt it on purpose, run this in the project's folder. It names each change above:`}),(0,Q.jsx)(`pre`,{className:`issue-lines`,"data-brakes":`command`,children:o}),(0,Q.jsx)(`button`,{type:`button`,className:`btn`,onClick:ne(o),children:`Copy the command`}),s]})}}export{ie as judge,re as loosened};